1.1 --- a/AUTHORS Mon Jul 16 16:21:40 2018 +0200
1.2 +++ b/AUTHORS Wed Oct 17 19:14:07 2018 +0200
1.3 @@ -1,15 +1,15 @@
1.4 -The authors of the 1.x series are
1.5 +The main developers of release series 1.x are
1.6
1.7 * Balazs Dezso <deba@inf.elte.hu>
1.8 * Alpar Juttner <alpar@cs.elte.hu>
1.9 * Peter Kovacs <kpeter@inf.elte.hu>
1.10 * Akos Ladanyi <ladanyi@tmit.bme.hu>
1.11
1.12 -For more details on the actual contribution, please visit the history
1.13 -of the main LEMON source repository: http://lemon.cs.elte.hu/hg/lemon
1.14 +For more complete list of contributors, please visit the history of
1.15 +the LEMON source code repository: http://lemon.cs.elte.hu/hg/lemon
1.16
1.17 -Moreover, this version is heavily based on the 0.x series of
1.18 -LEMON. Here is the list of people who contributed to those versions.
1.19 +Moreover, this version is heavily based on version 0.x of LEMON. Here
1.20 +is the list of people who contributed to those versions.
1.21
1.22 * Mihaly Barasz <klao@cs.elte.hu>
1.23 * Johanna Becker <beckerjc@cs.elte.hu>
2.1 --- a/CMakeLists.txt Mon Jul 16 16:21:40 2018 +0200
2.2 +++ b/CMakeLists.txt Wed Oct 17 19:14:07 2018 +0200
2.3 @@ -1,4 +1,13 @@
2.4 -CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
2.5 +CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
2.6 +
2.7 +IF(POLICY CMP0048)
2.8 + CMAKE_POLICY(SET CMP0048 OLD)
2.9 +ENDIF(POLICY CMP0048)
2.10 +
2.11 +IF(POLICY CMP0026)
2.12 + #This is for copying the dll's needed by glpk (in lp_test and mip_test)
2.13 + CMAKE_POLICY(SET CMP0026 OLD)
2.14 +ENDIF(POLICY CMP0026)
2.15
2.16 SET(PROJECT_NAME "LEMON")
2.17 PROJECT(${PROJECT_NAME})
2.18 @@ -12,29 +21,47 @@
2.19 SET(LEMON_VERSION $ENV{LEMON_VERSION} CACHE STRING "LEMON version string.")
2.20 ELSE()
2.21 EXECUTE_PROCESS(
2.22 - COMMAND ${PYTHON_EXECUTABLE} ./scripts/chg-len.py
2.23 + COMMAND
2.24 + hg log -r. --template "{latesttag}"
2.25 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
2.26 - OUTPUT_VARIABLE HG_REVISION_PATH
2.27 + OUTPUT_VARIABLE HG_REVISION_TAG
2.28 ERROR_QUIET
2.29 OUTPUT_STRIP_TRAILING_WHITESPACE
2.30 )
2.31 EXECUTE_PROCESS(
2.32 - COMMAND hg id -i
2.33 + COMMAND
2.34 + hg log -r. --template "{latesttagdistance}"
2.35 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
2.36 - OUTPUT_VARIABLE HG_REVISION
2.37 + OUTPUT_VARIABLE HG_REVISION_DIST
2.38 ERROR_QUIET
2.39 OUTPUT_STRIP_TRAILING_WHITESPACE
2.40 )
2.41 - IF(HG_REVISION STREQUAL "")
2.42 + EXECUTE_PROCESS(
2.43 + COMMAND
2.44 + hg log -r. --template "{node|short}"
2.45 + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
2.46 + OUTPUT_VARIABLE HG_REVISION_ID
2.47 + ERROR_QUIET
2.48 + OUTPUT_STRIP_TRAILING_WHITESPACE
2.49 + )
2.50 +
2.51 + IF(HG_REVISION_TAG STREQUAL "")
2.52 SET(HG_REVISION_ID "hg-tip")
2.53 ELSE()
2.54 - IF(HG_REVISION_PATH STREQUAL "")
2.55 - SET(HG_REVISION_ID ${HG_REVISION})
2.56 + IF(HG_REVISION_TAG STREQUAL "null")
2.57 + SET(HG_REVISION_TAG "trunk")
2.58 + ELSEIF(HG_REVISION_TAG MATCHES "^r")
2.59 + STRING(SUBSTRING ${HG_REVISION_TAG} 1 -1 HG_REVISION_TAG)
2.60 + ENDIF()
2.61 + IF(HG_REVISION_DIST STREQUAL "0")
2.62 + SET(HG_REVISION ${HG_REVISION_TAG})
2.63 ELSE()
2.64 - SET(HG_REVISION_ID ${HG_REVISION_PATH}.${HG_REVISION})
2.65 + SET(HG_REVISION
2.66 + "${HG_REVISION_TAG}+${HG_REVISION_DIST}-${HG_REVISION_ID}")
2.67 ENDIF()
2.68 ENDIF()
2.69 - SET(LEMON_VERSION ${HG_REVISION_ID} CACHE STRING "LEMON version string.")
2.70 +
2.71 + SET(LEMON_VERSION ${HG_REVISION} CACHE STRING "LEMON version string.")
2.72 ENDIF()
2.73
2.74 SET(PROJECT_VERSION ${LEMON_VERSION})
2.75 @@ -43,9 +70,84 @@
2.76
2.77 FIND_PACKAGE(Doxygen)
2.78 FIND_PACKAGE(Ghostscript)
2.79 -FIND_PACKAGE(GLPK 4.33)
2.80 -FIND_PACKAGE(CPLEX)
2.81 -FIND_PACKAGE(COIN)
2.82 +
2.83 +IF(WIN32)
2.84 + SET(LEMON_WIN32 TRUE)
2.85 +ENDIF(WIN32)
2.86 +
2.87 +SET(LEMON_ENABLE_GLPK YES CACHE STRING "Enable GLPK solver backend.")
2.88 +SET(LEMON_ENABLE_ILOG YES CACHE STRING "Enable ILOG (CPLEX) solver backend.")
2.89 +SET(LEMON_ENABLE_COIN YES CACHE STRING "Enable COIN solver backend.")
2.90 +SET(LEMON_ENABLE_SOPLEX YES CACHE STRING "Enable SoPlex solver backend.")
2.91 +
2.92 +IF(LEMON_ENABLE_GLPK)
2.93 + FIND_PACKAGE(GLPK 4.33)
2.94 + IF(GLPK_FOUND)
2.95 + SET(LEMON_HAVE_LP TRUE)
2.96 + SET(LEMON_HAVE_MIP TRUE)
2.97 + SET(LEMON_HAVE_GLPK TRUE)
2.98 + ENDIF(GLPK_FOUND)
2.99 +ENDIF(LEMON_ENABLE_GLPK)
2.100 +IF(LEMON_ENABLE_ILOG)
2.101 + FIND_PACKAGE(ILOG)
2.102 + IF(ILOG_FOUND)
2.103 + SET(LEMON_HAVE_LP TRUE)
2.104 + SET(LEMON_HAVE_MIP TRUE)
2.105 + SET(LEMON_HAVE_CPLEX TRUE)
2.106 + ENDIF(ILOG_FOUND)
2.107 +ENDIF(LEMON_ENABLE_ILOG)
2.108 +IF(LEMON_ENABLE_COIN)
2.109 + FIND_PACKAGE(COIN)
2.110 + IF(COIN_FOUND)
2.111 + SET(LEMON_HAVE_LP TRUE)
2.112 + SET(LEMON_HAVE_MIP TRUE)
2.113 + SET(LEMON_HAVE_CLP TRUE)
2.114 + SET(LEMON_HAVE_CBC TRUE)
2.115 + ENDIF(COIN_FOUND)
2.116 +ENDIF(LEMON_ENABLE_COIN)
2.117 +IF(LEMON_ENABLE_SOPLEX)
2.118 + FIND_PACKAGE(SOPLEX)
2.119 + IF(SOPLEX_FOUND)
2.120 + SET(LEMON_HAVE_LP TRUE)
2.121 + SET(LEMON_HAVE_SOPLEX TRUE)
2.122 + ENDIF(SOPLEX_FOUND)
2.123 +ENDIF(LEMON_ENABLE_SOPLEX)
2.124 +
2.125 +IF(ILOG_FOUND)
2.126 + SET(DEFAULT_LP "CPLEX")
2.127 + SET(DEFAULT_MIP "CPLEX")
2.128 +ELSEIF(COIN_FOUND)
2.129 + SET(DEFAULT_LP "CLP")
2.130 + SET(DEFAULT_MIP "CBC")
2.131 +ELSEIF(GLPK_FOUND)
2.132 + SET(DEFAULT_LP "GLPK")
2.133 + SET(DEFAULT_MIP "GLPK")
2.134 +ELSEIF(SOPLEX_FOUND)
2.135 + SET(DEFAULT_LP "SOPLEX")
2.136 +ENDIF()
2.137 +
2.138 +IF(NOT LEMON_DEFAULT_LP OR
2.139 + (NOT ILOG_FOUND AND (LEMON_DEFAULT_LP STREQUAL "CPLEX")) OR
2.140 + (NOT COIN_FOUND AND (LEMON_DEFAULT_LP STREQUAL "CLP")) OR
2.141 + (NOT GLPK_FOUND AND (LEMON_DEFAULT_LP STREQUAL "GLPK")) OR
2.142 + (NOT SOPLEX_FOUND AND (LEMON_DEFAULT_LP STREQUAL "SOPLEX")))
2.143 + SET(LEMON_DEFAULT_LP ${DEFAULT_LP} CACHE STRING
2.144 + "Default LP solver backend (GLPK, CPLEX, CLP or SOPLEX)" FORCE)
2.145 +ELSE()
2.146 + SET(LEMON_DEFAULT_LP ${DEFAULT_LP} CACHE STRING
2.147 + "Default LP solver backend (GLPK, CPLEX, CLP or SOPLEX)")
2.148 +ENDIF()
2.149 +IF(NOT LEMON_DEFAULT_MIP OR
2.150 + (NOT ILOG_FOUND AND (LEMON_DEFAULT_MIP STREQUAL "CPLEX")) OR
2.151 + (NOT COIN_FOUND AND (LEMON_DEFAULT_MIP STREQUAL "CBC")) OR
2.152 + (NOT GLPK_FOUND AND (LEMON_DEFAULT_MIP STREQUAL "GLPK")))
2.153 + SET(LEMON_DEFAULT_MIP ${DEFAULT_MIP} CACHE STRING
2.154 + "Default MIP solver backend (GLPK, CPLEX or CBC)" FORCE)
2.155 +ELSE()
2.156 + SET(LEMON_DEFAULT_MIP ${DEFAULT_MIP} CACHE STRING
2.157 + "Default MIP solver backend (GLPK, CPLEX or CBC)")
2.158 +ENDIF()
2.159 +
2.160
2.161 IF(DEFINED ENV{LEMON_CXX_WARNING})
2.162 SET(CXX_WARNING $ENV{LEMON_CXX_WARNING})
2.163 @@ -56,10 +158,13 @@
2.164 SET(CMAKE_C_FLAGS_DEBUG CACHE STRING "-ggdb")
2.165 ELSEIF(MSVC)
2.166 # This part is unnecessary 'casue the same is set by the lemon/core.h.
2.167 - # Still keep it as an example.
2.168 - SET(CXX_WARNING "/wd4250 /wd4355 /wd4503 /wd4800 /wd4996")
2.169 + # Still kept as an example.
2.170 +
2.171 + # SET(CXX_WARNING "/wd4250 /wd4267 /wd4355 /wd4503 /wd4800 /wd4996")
2.172 +
2.173 # Suppressed warnings:
2.174 # C4250: 'class1' : inherits 'class2::member' via dominance
2.175 + # C4267: conversion from 'size_t' to 'type', possible loss of data
2.176 # C4355: 'this' : used in base member initializer list
2.177 # C4503: 'function' : decorated name length exceeded, name was truncated
2.178 # C4800: 'type' : forcing value to bool 'true' or 'false'
2.179 @@ -73,20 +178,39 @@
2.180
2.181 SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${LEMON_CXX_WARNING_FLAGS}")
2.182
2.183 -SET( CMAKE_CXX_FLAGS_MAINTAINER "-Werror -ggdb -O0" CACHE STRING
2.184 +IF(MSVC)
2.185 + SET(CMAKE_CXX_FLAGS "/bigobj ${CMAKE_CXX_FLAGS}")
2.186 + SET( CMAKE_CXX_FLAGS_MAINTAINER "/WX ${CMAKE_CXX_FLAGS_DEBUG}" CACHE STRING
2.187 "Flags used by the C++ compiler during maintainer builds."
2.188 - FORCE )
2.189 -SET( CMAKE_C_FLAGS_MAINTAINER "-Werror -O0" CACHE STRING
2.190 + )
2.191 + SET( CMAKE_C_FLAGS_MAINTAINER "/WX ${CMAKE_CXX_FLAGS_DEBUG}" CACHE STRING
2.192 "Flags used by the C compiler during maintainer builds."
2.193 - FORCE )
2.194 -SET( CMAKE_EXE_LINKER_FLAGS_MAINTAINER
2.195 - "-Wl,--warn-unresolved-symbols,--warn-once" CACHE STRING
2.196 + )
2.197 + SET( CMAKE_EXE_LINKER_FLAGS_MAINTAINER
2.198 + "${CMAKE_EXE_LINKER_FLAGS_DEBUG}" CACHE STRING
2.199 "Flags used for linking binaries during maintainer builds."
2.200 - FORCE )
2.201 -SET( CMAKE_SHARED_LINKER_FLAGS_MAINTAINER
2.202 - "-Wl,--warn-unresolved-symbols,--warn-once" CACHE STRING
2.203 + )
2.204 + SET( CMAKE_SHARED_LINKER_FLAGS_MAINTAINER
2.205 + "${CMAKE_SHARED_LINKER_FLAGS_DEBUG}" CACHE STRING
2.206 "Flags used by the shared libraries linker during maintainer builds."
2.207 - FORCE )
2.208 + )
2.209 +ELSE()
2.210 + SET( CMAKE_CXX_FLAGS_MAINTAINER "-Werror -ggdb -O0" CACHE STRING
2.211 + "Flags used by the C++ compiler during maintainer builds."
2.212 + )
2.213 + SET( CMAKE_C_FLAGS_MAINTAINER "-Werror -O0" CACHE STRING
2.214 + "Flags used by the C compiler during maintainer builds."
2.215 + )
2.216 + SET( CMAKE_EXE_LINKER_FLAGS_MAINTAINER
2.217 + "${CMAKE_EXE_LINKER_FLAGS_DEBUG}" CACHE STRING
2.218 + "Flags used for linking binaries during maintainer builds."
2.219 + )
2.220 + SET( CMAKE_SHARED_LINKER_FLAGS_MAINTAINER
2.221 + "${CMAKE_SHARED_LINKER_FLAGS_DEBUG}" CACHE STRING
2.222 + "Flags used by the shared libraries linker during maintainer builds."
2.223 + )
2.224 +ENDIF()
2.225 +
2.226 MARK_AS_ADVANCED(
2.227 CMAKE_CXX_FLAGS_MAINTAINER
2.228 CMAKE_C_FLAGS_MAINTAINER
2.229 @@ -114,7 +238,27 @@
2.230 CHECK_TYPE_SIZE("long long" LONG_LONG)
2.231 SET(LEMON_HAVE_LONG_LONG ${HAVE_LONG_LONG})
2.232
2.233 -INCLUDE(FindPythonInterp)
2.234 +INCLUDE(FindThreads)
2.235 +
2.236 +IF(NOT LEMON_THREADING)
2.237 + IF(CMAKE_USE_PTHREADS_INIT)
2.238 + SET(LEMON_THREADING "Pthread")
2.239 + ELSEIF(CMAKE_USE_WIN32_THREADS_INIT)
2.240 + SET(LEMON_THREADING "Win32")
2.241 + ELSE()
2.242 + SET(LEMON_THREADING "None")
2.243 + ENDIF()
2.244 +ENDIF()
2.245 +
2.246 +SET( LEMON_THREADING "${LEMON_THREADING}" CACHE STRING
2.247 + "Choose the threading library, options are: Pthread Win32 None."
2.248 + FORCE )
2.249 +
2.250 +IF(LEMON_THREADING STREQUAL "Pthread")
2.251 + SET(LEMON_USE_PTHREAD TRUE)
2.252 +ELSEIF(LEMON_THREADING STREQUAL "Win32")
2.253 + SET(LEMON_USE_WIN32_THREADS TRUE)
2.254 +ENDIF()
2.255
2.256 ENABLE_TESTING()
2.257
2.258 @@ -126,6 +270,7 @@
2.259
2.260 ADD_SUBDIRECTORY(lemon)
2.261 IF(${CMAKE_SOURCE_DIR} STREQUAL ${PROJECT_SOURCE_DIR})
2.262 + ADD_SUBDIRECTORY(contrib)
2.263 ADD_SUBDIRECTORY(demo)
2.264 ADD_SUBDIRECTORY(tools)
2.265 ADD_SUBDIRECTORY(doc)
2.266 @@ -149,6 +294,33 @@
2.267 )
2.268 ENDIF()
2.269
2.270 +CONFIGURE_FILE(
2.271 + ${PROJECT_SOURCE_DIR}/cmake/version.cmake.in
2.272 + ${PROJECT_BINARY_DIR}/cmake/version.cmake
2.273 + @ONLY
2.274 +)
2.275 +
2.276 +SET(ARCHIVE_BASE_NAME ${CMAKE_PROJECT_NAME})
2.277 +STRING(TOLOWER ${ARCHIVE_BASE_NAME} ARCHIVE_BASE_NAME)
2.278 +SET(ARCHIVE_NAME ${ARCHIVE_BASE_NAME}-${PROJECT_VERSION})
2.279 +ADD_CUSTOM_TARGET(dist
2.280 + COMMAND cmake -E remove_directory ${ARCHIVE_NAME}
2.281 + COMMAND hg archive ${ARCHIVE_NAME}
2.282 + COMMAND cmake -E copy cmake/version.cmake ${ARCHIVE_NAME}/cmake/version.cmake
2.283 + COMMAND tar -czf ${ARCHIVE_BASE_NAME}-nodoc-${PROJECT_VERSION}.tar.gz ${ARCHIVE_NAME}
2.284 + COMMAND zip -r ${ARCHIVE_BASE_NAME}-nodoc-${PROJECT_VERSION}.zip ${ARCHIVE_NAME}
2.285 + COMMAND cmake -E copy_directory doc/html ${ARCHIVE_NAME}/doc/html
2.286 + COMMAND tar -czf ${ARCHIVE_NAME}.tar.gz ${ARCHIVE_NAME}
2.287 + COMMAND zip -r ${ARCHIVE_NAME}.zip ${ARCHIVE_NAME}
2.288 + COMMAND cmake -E copy_directory doc/html ${ARCHIVE_BASE_NAME}-doc-${PROJECT_VERSION}
2.289 + COMMAND tar -czf ${ARCHIVE_BASE_NAME}-doc-${PROJECT_VERSION}.tar.gz ${ARCHIVE_BASE_NAME}-doc-${PROJECT_VERSION}
2.290 + COMMAND zip -r ${ARCHIVE_BASE_NAME}-doc-${PROJECT_VERSION}.zip ${ARCHIVE_BASE_NAME}-doc-${PROJECT_VERSION}
2.291 + COMMAND cmake -E remove_directory ${ARCHIVE_NAME}
2.292 + COMMAND cmake -E remove_directory ${ARCHIVE_BASE_NAME}-doc-${PROJECT_VERSION}
2.293 + DEPENDS html
2.294 + WORKING_DIRECTORY ${PROJECT_BINARY_DIR})
2.295 +
2.296 +# CPACK config (Basically for NSIS)
2.297 IF(${CMAKE_SOURCE_DIR} STREQUAL ${PROJECT_SOURCE_DIR})
2.298 SET(CPACK_PACKAGE_NAME ${PROJECT_NAME})
2.299 SET(CPACK_PACKAGE_VENDOR "EGRES")
3.1 --- a/INSTALL Mon Jul 16 16:21:40 2018 +0200
3.2 +++ b/INSTALL Wed Oct 17 19:14:07 2018 +0200
3.3 @@ -1,197 +1,167 @@
3.4 Installation Instructions
3.5 =========================
3.6
3.7 -Since you are reading this I assume you already obtained one of the release
3.8 -tarballs and successfully extracted it. The latest version of LEMON is
3.9 -available at our web page (http://lemon.cs.elte.hu/).
3.10 +This file contains instructions for building and installing LEMON from
3.11 +source on Linux. The process on Windows is similar.
3.12
3.13 -LEMON provides two different build environments, one is based on "autotool",
3.14 -while the other is based on "cmake". This file contains instructions only for
3.15 -the former one, which is the recommended build environment on Linux, Mac OSX
3.16 -and other unices or if you use Cygwin on Windows. For cmake installation
3.17 -instructions visit http://lemon.cs.elte.hu.
3.18 +Note that it is not necessary to install LEMON in order to use
3.19 +it. Instead, you can easily integrate it with your own code
3.20 +directly. For instructions, see
3.21 +https://lemon.cs.elte.hu/trac/lemon/wiki/HowToCompile
3.22 +
3.23
3.24 In order to install LEMON from the extracted source tarball you have to
3.25 issue the following commands:
3.26
3.27 - 1. `cd lemon-x.y.z'
3.28 + 1. Step into the root of the source directory.
3.29
3.30 - This command changes to the directory which was created when you
3.31 - extracted the sources. The x.y.z part is a version number.
3.32 + $ cd lemon-x.y.z
3.33
3.34 - 2. `./configure'
3.35 + 2. Create a build subdirectory and step into it.
3.36
3.37 - This command runs the configure shell script, which does some checks and
3.38 - creates the makefiles.
3.39 + $ mkdir build
3.40 + $ cd build
3.41
3.42 - 3. `make'
3.43 + 3. Perform system checks and create the makefiles.
3.44
3.45 - This command compiles the non-template part of LEMON into libemon.a
3.46 - file. It also compiles the programs in the tools subdirectory by
3.47 - default.
3.48 + $ cmake ..
3.49
3.50 - 4. `make check'
3.51 + 4. Build LEMON.
3.52
3.53 - This step is optional, but recommended. It runs the test programs that
3.54 - we developed for LEMON to check whether the library works properly on
3.55 - your platform.
3.56 + $ make
3.57
3.58 - 5. `make install'
3.59 + This command compiles the non-template part of LEMON into
3.60 + libemon.a file. It also compiles the programs in the 'tools' and
3.61 + 'demo' subdirectories.
3.62 +
3.63 + 5. [Optional] Compile and run the self-tests.
3.64 +
3.65 + $ make check
3.66 +
3.67 + 5. [Optional] Generate the user documentation.
3.68 +
3.69 + $ make html
3.70 +
3.71 + The release tarballs already include the documentation.
3.72 +
3.73 + Note that for this step you need to have the following tools
3.74 + installed: Python, Doxygen, Graphviz, Ghostscript, LaTeX.
3.75 +
3.76 + 6. [Optional] Install LEMON
3.77 +
3.78 + $ make install
3.79
3.80 This command installs LEMON under /usr/local (you will need root
3.81 - privileges to be able to do that). If you want to install it to some
3.82 - other location, then pass the --prefix=DIRECTORY flag to configure in
3.83 - step 2. For example: `./configure --prefix=/home/username/lemon'.
3.84 -
3.85 - 6. `make install-html'
3.86 -
3.87 - This command installs the documentation under share/doc/lemon/docs. The
3.88 - generated documentation is included in the tarball. If you want to
3.89 - generate it yourself, then run `make html'. Note that for this you need
3.90 - to have the following programs installed: Doxygen, Graphviz, Ghostscript,
3.91 - Latex.
3.92 -
3.93 + privileges to be able to do that). If you want to install it to
3.94 + some other location, then pass the
3.95 + -DCMAKE_INSTALL_PREFIX=DIRECTORY flag to cmake in Step 3.
3.96 + For example:
3.97 +
3.98 + $ cmake -DCMAKE_INSTALL_PREFIX=/home/username/lemon'
3.99
3.100 Configure Options and Variables
3.101 ===============================
3.102
3.103 -In step 2 you can customize the actions of configure by setting variables
3.104 -and passing options to it. This can be done like this:
3.105 -`./configure [OPTION]... [VARIABLE=VALUE]...'
3.106 +In Step 3, you can customize the build process by passing options to CMAKE.
3.107
3.108 -Below you will find some useful variables and options (see `./configure --help'
3.109 -for more):
3.110 +$ cmake [OPTIONS] ..
3.111
3.112 -CXX='comp'
3.113 +You find a list of the most useful options below.
3.114
3.115 - Change the C++ compiler to 'comp'.
3.116 -
3.117 -CXXFLAGS='flags'
3.118 -
3.119 - Pass the 'flags' to the compiler. For example CXXFLAGS='-O3 -march=pentium-m'
3.120 - turns on generation of aggressively optimized Pentium-M specific code.
3.121 -
3.122 ---prefix=PREFIX
3.123 +-DCMAKE_INSTALL_PREFIX=PREFIX
3.124
3.125 Set the installation prefix to PREFIX. By default it is /usr/local.
3.126
3.127 ---enable-tools
3.128 +-DCMAKE_BUILD_TYPE=[Release|Debug|Maintainer|...]
3.129
3.130 - Build the programs in the tools subdirectory (default).
3.131 + This sets the compiler options. The choices are the following
3.132
3.133 ---disable-tools
3.134 + 'Release': A strong optimization is turned on (-O3 with gcc). This
3.135 + is the default setting and we strongly recommend using this for
3.136 + the final compilation.
3.137
3.138 - Do not build the programs in the tools subdirectory.
3.139 + 'Debug': Optimization is turned off and debug info is added (-O0
3.140 + -ggdb with gcc). If is recommended during the development.
3.141
3.142 ---with-glpk[=PREFIX]
3.143 + 'Maintainer': The same as 'Debug' but the compiler warnings are
3.144 + converted to errors (-Werror with gcc). In addition, 'make' will
3.145 + also automatically compile and execute the test codes. It is the
3.146 + best way of ensuring that LEMON codebase is clean and safe.
3.147
3.148 - Enable GLPK support (default). You should specify the prefix too if
3.149 - you installed GLPK to some non-standard location (e.g. your home
3.150 - directory). If it is not found, GLPK support will be disabled.
3.151 + 'RelWithDebInfo': Optimized build with debug info.
3.152
3.153 ---with-glpk-includedir=DIR
3.154 + 'MinSizeRel': Size optimized build (-Os with gcc)
3.155
3.156 - The directory where the GLPK header files are located. This is only
3.157 - useful when the GLPK headers and libraries are not under the same
3.158 - prefix (which is unlikely).
3.159 +-DTEST_WITH_VALGRIND=YES
3.160
3.161 ---with-glpk-libdir=DIR
3.162 + Using this, the test codes will be executed using valgrind. It is a
3.163 + very effective way of identifying indexing problems and memory leaks.
3.164
3.165 - The directory where the GLPK libraries are located. This is only
3.166 - useful when the GLPK headers and libraries are not under the same
3.167 - prefix (which is unlikely).
3.168 +-DCMAKE_CXX_COMPILER=path-to-compiler
3.169
3.170 ---without-glpk
3.171 + Change the compiler to be used.
3.172
3.173 - Disable GLPK support.
3.174 +-DBUILD_SHARED_LIBS=TRUE
3.175
3.176 ---with-cplex[=PREFIX]
3.177 + Build shared library instead of static one. Think twice if you
3.178 + really want to use this option.
3.179
3.180 - Enable CPLEX support (default). You should specify the prefix too
3.181 - if you installed CPLEX to some non-standard location
3.182 - (e.g. /opt/ilog/cplex75). If it is not found, CPLEX support will be
3.183 - disabled.
3.184 +-DLEMON_DOC_SOURCE_BROWSER=YES
3.185
3.186 ---with-cplex-includedir=DIR
3.187 + Include the browsable cross referenced LEMON source code into the
3.188 + doc. It makes the doc quite bloated, but may be useful for
3.189 + developing LEMON itself.
3.190
3.191 - The directory where the CPLEX header files are located. This is
3.192 - only useful when the CPLEX headers and libraries are not under the
3.193 - same prefix (e.g. /usr/local/cplex/cplex75/include).
3.194 +-DLEMON_DOC_USE_MATHJAX=YES
3.195
3.196 ---with-cplex-libdir=DIR
3.197 + Use MathJax (http://mathjax.org) for rendering the math formulae in
3.198 + the doc. It of much higher quality compared to the default LaTeX
3.199 + generated static images and it allows copy&paste of the formulae to
3.200 + LaTeX, Open Office, MS Word etc. documents.
3.201
3.202 - The directory where the CPLEX libraries are located. This is only
3.203 - useful when the CPLEX headers and libraries are not under the same
3.204 - prefix (e.g.
3.205 - /usr/local/cplex/cplex75/lib/i86_linux2_glibc2.2_gcc3.0/static_pic_mt).
3.206 + On the other hand, it needs either Internet access or a locally
3.207 + installed version of MathJax to properly render the doc.
3.208
3.209 ---without-cplex
3.210 +-DLEMON_DOC_MATHJAX_RELPATH=DIRECTORY
3.211 +
3.212 + The location of the MathJax library. It defaults to
3.213 + http://www.mathjax.org/mathjax, which necessitates Internet access
3.214 + for proper rendering. The easiest way to make it usable offline is
3.215 + to set this parameter to 'mathjax' and copy all files of the MathJax
3.216 + library into the 'doc/html/mathjax' subdirectory of the build
3.217 + location.
3.218
3.219 - Disable CPLEX support.
3.220 + See http://docs.mathjax.org/en/latest/installation.html for more details.
3.221
3.222 ---with-soplex[=PREFIX]
3.223 +
3.224 +-DLEMON_ENABLE_GLPK=NO
3.225 +-DLEMON_ENABLE_COIN=NO
3.226 +-DLEMON_ENABLE_ILOG=NO
3.227
3.228 - Enable SoPlex support (default). You should specify the prefix too if
3.229 - you installed SoPlex to some non-standard location (e.g. your home
3.230 - directory). If it is not found, SoPlex support will be disabled.
3.231 + Enable optional third party libraries. They are all enabled by default.
3.232
3.233 ---with-soplex-includedir=DIR
3.234 +-DLEMON_DEFAULT_LP=GLPK
3.235
3.236 - The directory where the SoPlex header files are located. This is only
3.237 - useful when the SoPlex headers and libraries are not under the same
3.238 - prefix (which is unlikely).
3.239 + Sets the default LP solver backend. The supported values are
3.240 + CPLEX, CLP and GLPK. By default, it is set to the first one which
3.241 + is enabled and succesfully discovered.
3.242
3.243 ---with-soplex-libdir=DIR
3.244 +-DLEMON_DEFAULT_MIP=GLPK
3.245
3.246 - The directory where the SoPlex libraries are located. This is only
3.247 - useful when the SoPlex headers and libraries are not under the same
3.248 - prefix (which is unlikely).
3.249 + Sets the default MIP solver backend. The supported values are
3.250 + CPLEX, CBC and GLPK. By default, it is set to the first one which
3.251 + is enabled and succesfully discovered.
3.252
3.253 ---without-soplex
3.254 +-DGLPK_ROOT_DIR=DIRECTORY
3.255 +-DCOIN_ROOT_DIR=DIRECTORY
3.256 +-DILOG_ROOT_DIR=DIRECTORY
3.257
3.258 - Disable SoPlex support.
3.259 -
3.260 ---with-coin[=PREFIX]
3.261 -
3.262 - Enable support for COIN-OR solvers (CLP and CBC). You should
3.263 - specify the prefix too. (by default, COIN-OR tools install
3.264 - themselves to the source code directory). This command enables the
3.265 - solvers that are actually found.
3.266 -
3.267 ---with-coin-includedir=DIR
3.268 -
3.269 - The directory where the COIN-OR header files are located. This is
3.270 - only useful when the COIN-OR headers and libraries are not under
3.271 - the same prefix (which is unlikely).
3.272 -
3.273 ---with-coin-libdir=DIR
3.274 -
3.275 - The directory where the COIN-OR libraries are located. This is only
3.276 - useful when the COIN-OR headers and libraries are not under the
3.277 - same prefix (which is unlikely).
3.278 -
3.279 ---without-coin
3.280 -
3.281 - Disable COIN-OR support.
3.282 -
3.283 + Root directory prefixes of optional third party libraries.
3.284
3.285 Makefile Variables
3.286 ==================
3.287
3.288 -Some Makefile variables are reserved by the GNU Coding Standards for
3.289 -the use of the "user" - the person building the package. For instance,
3.290 -CXX and CXXFLAGS are such variables, and have the same meaning as
3.291 -explained in the previous section. These variables can be set on the
3.292 -command line when invoking `make' like this:
3.293 -`make [VARIABLE=VALUE]...'
3.294 +make VERBOSE=1
3.295
3.296 -WARNINGCXXFLAGS is a non-standard Makefile variable introduced by us
3.297 -to hold several compiler flags related to warnings. Its default value
3.298 -can be overridden when invoking `make'. For example to disable all
3.299 -warning flags use `make WARNINGCXXFLAGS='.
3.300 -
3.301 -In order to turn off a single flag from the default set of warning
3.302 -flags, you can use the CXXFLAGS variable, since this is passed after
3.303 -WARNINGCXXFLAGS. For example to turn off `-Wold-style-cast' (which is
3.304 -used by default when g++ is detected) you can use
3.305 -`make CXXFLAGS="-g -O2 -Wno-old-style-cast"'.
3.306 + This results in a more verbose output by showing the full
3.307 + compiler and linker commands.
3.308 \ No newline at end of file
4.1 --- a/LICENSE Mon Jul 16 16:21:40 2018 +0200
4.2 +++ b/LICENSE Wed Oct 17 19:14:07 2018 +0200
4.3 @@ -1,7 +1,7 @@
4.4 LEMON code without an explicit copyright notice is covered by the following
4.5 copyright/license.
4.6
4.7 -Copyright (C) 2003-2010 Egervary Jeno Kombinatorikus Optimalizalasi
4.8 +Copyright (C) 2003-2012 Egervary Jeno Kombinatorikus Optimalizalasi
4.9 Kutatocsoport (Egervary Combinatorial Optimization Research Group,
4.10 EGRES).
4.11
5.1 --- a/Makefile.am Mon Jul 16 16:21:40 2018 +0200
5.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
5.3 @@ -1,80 +0,0 @@
5.4 -ACLOCAL_AMFLAGS = -I m4
5.5 -
5.6 -AM_CXXFLAGS = $(WARNINGCXXFLAGS)
5.7 -
5.8 -AM_CPPFLAGS = -I$(top_srcdir) -I$(top_builddir)
5.9 -LDADD = $(top_builddir)/lemon/libemon.la
5.10 -
5.11 -EXTRA_DIST = \
5.12 - AUTHORS \
5.13 - LICENSE \
5.14 - m4/lx_check_cplex.m4 \
5.15 - m4/lx_check_glpk.m4 \
5.16 - m4/lx_check_soplex.m4 \
5.17 - m4/lx_check_coin.m4 \
5.18 - CMakeLists.txt \
5.19 - cmake/FindGhostscript.cmake \
5.20 - cmake/FindCPLEX.cmake \
5.21 - cmake/FindGLPK.cmake \
5.22 - cmake/FindCOIN.cmake \
5.23 - cmake/LEMONConfig.cmake.in \
5.24 - cmake/version.cmake.in \
5.25 - cmake/version.cmake \
5.26 - cmake/nsis/lemon.ico \
5.27 - cmake/nsis/uninstall.ico
5.28 -
5.29 -pkgconfigdir = $(libdir)/pkgconfig
5.30 -lemondir = $(pkgincludedir)
5.31 -bitsdir = $(lemondir)/bits
5.32 -conceptdir = $(lemondir)/concepts
5.33 -pkgconfig_DATA =
5.34 -lib_LTLIBRARIES =
5.35 -lemon_HEADERS =
5.36 -bits_HEADERS =
5.37 -concept_HEADERS =
5.38 -noinst_HEADERS =
5.39 -noinst_PROGRAMS =
5.40 -bin_PROGRAMS =
5.41 -check_PROGRAMS =
5.42 -dist_bin_SCRIPTS =
5.43 -TESTS =
5.44 -XFAIL_TESTS =
5.45 -
5.46 -include lemon/Makefile.am
5.47 -include test/Makefile.am
5.48 -include doc/Makefile.am
5.49 -include tools/Makefile.am
5.50 -include scripts/Makefile.am
5.51 -
5.52 -DIST_SUBDIRS = demo
5.53 -
5.54 -demo:
5.55 - $(MAKE) $(AM_MAKEFLAGS) -C demo
5.56 -
5.57 -MRPROPERFILES = \
5.58 - aclocal.m4 \
5.59 - config.h.in \
5.60 - config.h.in~ \
5.61 - configure \
5.62 - Makefile.in \
5.63 - build-aux/config.guess \
5.64 - build-aux/config.sub \
5.65 - build-aux/depcomp \
5.66 - build-aux/install-sh \
5.67 - build-aux/ltmain.sh \
5.68 - build-aux/missing \
5.69 - doc/doxygen.log
5.70 -
5.71 -mrproper:
5.72 - $(MAKE) $(AM_MAKEFLAGS) maintainer-clean
5.73 - -rm -f $(MRPROPERFILES)
5.74 -
5.75 -dist-bz2: dist
5.76 - zcat $(PACKAGE)-$(VERSION).tar.gz | \
5.77 - bzip2 --best -c > $(PACKAGE)-$(VERSION).tar.bz2
5.78 -
5.79 -distcheck-bz2: distcheck
5.80 - zcat $(PACKAGE)-$(VERSION).tar.gz | \
5.81 - bzip2 --best -c > $(PACKAGE)-$(VERSION).tar.bz2
5.82 -
5.83 -.PHONY: demo mrproper dist-bz2 distcheck-bz2
6.1 --- a/NEWS Mon Jul 16 16:21:40 2018 +0200
6.2 +++ b/NEWS Wed Oct 17 19:14:07 2018 +0200
6.3 @@ -1,3 +1,101 @@
6.4 +2013-08-10 Version 1.3 released
6.5 +
6.6 + This is major feature release
6.7 +
6.8 + * New data structures
6.9 +
6.10 + #69 : Bipartite graph concepts and implementations
6.11 +
6.12 + * New algorithms
6.13 +
6.14 + #177: Port Edmonds-Karp algorithm
6.15 + #380, #405: Heuristic algorithm for the max clique problem
6.16 + #386: Heuristic algorithms for symmetric TSP
6.17 + ----: Nagamochi-Ibaraki algorithm [5087694945e4]
6.18 + #397, #56: Max. cardinality search
6.19 +
6.20 + * Other new features
6.21 +
6.22 + #223: Thread safe graph and graph map implementations
6.23 + #442: Different TimeStamp print formats
6.24 + #457: File export functionality to LpBase
6.25 + #362: Bidirectional iterator support for radixSort()
6.26 +
6.27 + * Implementation improvements
6.28 +
6.29 + ----: Network Simplex
6.30 + #391: Better update process, pivot rule and arc mixing
6.31 + #435: Improved Altering List pivot rule
6.32 + #417: Various fine tunings in CostScaling
6.33 + #438: Optional iteration limit in HowardMmc
6.34 + #436: Ensure strongly polynomial running time for CycleCanceling
6.35 + while keeping the same performance
6.36 + ----: Make the CBC interface be compatible with latest CBC releases
6.37 + [ee581a0ecfbf]
6.38 +
6.39 + * CMAKE has become the default build environment (#434)
6.40 +
6.41 + ----: Autotool support has been dropped
6.42 + ----: Improved LP/MIP configuration
6.43 + #465: Enable/disable options for LP/MIP backends
6.44 + #446: Better CPLEX discovery
6.45 + #460: Add cmake config to find SoPlex
6.46 + ----: Allow CPACK configuration on all platforms
6.47 + #390: Add 'Maintainer' CMAKE build type
6.48 + #388: Add 'check' target.
6.49 + #401: Add contrib dir
6.50 + #389: Better version string setting in CMAKE
6.51 + #433: Support shared library build
6.52 + #416: Support testing with valgrind
6.53 +
6.54 + * Doc improvements
6.55 +
6.56 + #395: SOURCE_BROWSER Doxygen switch is configurable from CMAKE
6.57 + update-external-tags CMAKE target
6.58 + #455: Optionally use MathJax for rendering the math formulae
6.59 + #402, #437, #459, #456, #463: Various doc improvements
6.60 +
6.61 + * Bugfixes (compared to release 1.2):
6.62 +
6.63 + #432: Add missing doc/template.h and doc/references.bib to release
6.64 + tarball
6.65 + ----: Intel C++ compatibility fixes
6.66 + #441: Fix buggy reinitialization in _solver_bits::VarIndex::clear()
6.67 + #444: Bugfix in path copy constructors and assignment operators
6.68 + #447: Bugfix in AllArcLookUp<>
6.69 + #448: Bugfix in adaptor_test.cc
6.70 + #449: Fix clang compilation warnings and errors
6.71 + #440: Fix a bug + remove redundant typedefs in dimacs-solver
6.72 + #453: Avoid GCC 4.7 compiler warnings
6.73 + #445: Fix missing initialization in CplexEnv::CplexEnv()
6.74 + #428: Add missing lemon/lemon.pc.cmake to the release tarball
6.75 + #393: Create and install lemon.pc
6.76 + #429: Fix VS warnings
6.77 + #430: Fix LpBase::Constr two-side limit bug
6.78 + #392: Bug fix in Dfs::start(s,t)
6.79 + #414: Fix wrong initialization in Preflow
6.80 + #418: Better Win CodeBlock/MinGW support
6.81 + #419: Build environment improvements
6.82 + - Build of mip_test and lp_test precede the running of the tests
6.83 + - Also search for coin libs under ${COIN_ROOT_DIR}/lib/coin
6.84 + - Do not look for COIN_VOL libraries
6.85 + #382: Allow lgf file without Arc maps
6.86 + #417: Bug fix in CostScaling
6.87 + #366: Fix Pred[Matrix]MapPath::empty()
6.88 + #371: Bug fix in (di)graphCopy()
6.89 + The target graph is cleared before adding nodes and arcs/edges.
6.90 + #364: Add missing UndirectedTags
6.91 + #368: Fix the usage of std::numeric_limits<>::min() in Network Simplex
6.92 + #372: Fix a critical bug in preflow
6.93 + #461: Bugfix in assert.h
6.94 + #470: Fix compilation issues related to various gcc versions
6.95 + #446: Fix #define indicating CPLEX availability
6.96 + #294: Add explicit namespace to
6.97 + ignore_unused_variable_warning() usages
6.98 + #420: Bugfix in IterableValueMap
6.99 + #439: Bugfix in biNodeConnected()
6.100 +
6.101 +
6.102 2010-03-19 Version 1.2 released
6.103
6.104 This is major feature release
7.1 --- a/cmake/FindCOIN.cmake Mon Jul 16 16:21:40 2018 +0200
7.2 +++ b/cmake/FindCOIN.cmake Wed Oct 17 19:14:07 2018 +0200
7.3 @@ -65,6 +65,12 @@
7.4 HINTS ${COIN_ROOT_DIR}/lib
7.5 )
7.6
7.7 +FIND_LIBRARY(COIN_PTHREADS_LIBRARY
7.8 + NAMES pthreads libpthreads
7.9 + HINTS ${COIN_ROOT_DIR}/lib/coin
7.10 + HINTS ${COIN_ROOT_DIR}/lib
7.11 +)
7.12 +
7.13 INCLUDE(FindPackageHandleStandardArgs)
7.14 FIND_PACKAGE_HANDLE_STANDARD_ARGS(COIN DEFAULT_MSG
7.15 COIN_INCLUDE_DIR
7.16 @@ -82,14 +88,17 @@
7.17
7.18 IF(COIN_FOUND)
7.19 SET(COIN_INCLUDE_DIRS ${COIN_INCLUDE_DIR})
7.20 - SET(COIN_CLP_LIBRARIES "${COIN_CLP_LIBRARY};${COIN_COIN_UTILS_LIBRARY};${COIN_ZLIB_LIBRARY};${COIN_BZ2_LIBRARY}")
7.21 + SET(COIN_CLP_LIBRARIES "${COIN_CLP_LIBRARY};${COIN_COIN_UTILS_LIBRARY}")
7.22 IF(COIN_ZLIB_LIBRARY)
7.23 SET(COIN_CLP_LIBRARIES "${COIN_CLP_LIBRARIES};${COIN_ZLIB_LIBRARY}")
7.24 ENDIF(COIN_ZLIB_LIBRARY)
7.25 IF(COIN_BZ2_LIBRARY)
7.26 SET(COIN_CLP_LIBRARIES "${COIN_CLP_LIBRARIES};${COIN_BZ2_LIBRARY}")
7.27 ENDIF(COIN_BZ2_LIBRARY)
7.28 - SET(COIN_CBC_LIBRARIES "${COIN_CBC_LIBRARY};${COIN_CBC_SOLVER_LIBRARY};${COIN_CGL_LIBRARY};${COIN_OSI_LIBRARY};${COIN_OSI_CBC_LIBRARY};${COIN_OSI_CLP_LIBRARY};${COIN_ZLIB_LIBRARY};${COIN_BZ2_LIBRARY};${COIN_CLP_LIBRARIES}")
7.29 + IF(COIN_PTHREADS_LIBRARY)
7.30 + SET(COIN_CLP_LIBRARIES "${COIN_CLP_LIBRARIES};${COIN_PTHREADS_LIBRARY}")
7.31 + ENDIF(COIN_PTHREADS_LIBRARY)
7.32 + SET(COIN_CBC_LIBRARIES "${COIN_CBC_LIBRARY};${COIN_CBC_SOLVER_LIBRARY};${COIN_CGL_LIBRARY};${COIN_OSI_LIBRARY};${COIN_OSI_CBC_LIBRARY};${COIN_OSI_CLP_LIBRARY};${COIN_CLP_LIBRARIES}")
7.33 SET(COIN_LIBRARIES ${COIN_CBC_LIBRARIES})
7.34 ENDIF(COIN_FOUND)
7.35
7.36 @@ -108,10 +117,3 @@
7.37 COIN_ZLIB_LIBRARY
7.38 COIN_BZ2_LIBRARY
7.39 )
7.40 -
7.41 -IF(COIN_FOUND)
7.42 - SET(LEMON_HAVE_LP TRUE)
7.43 - SET(LEMON_HAVE_MIP TRUE)
7.44 - SET(LEMON_HAVE_CLP TRUE)
7.45 - SET(LEMON_HAVE_CBC TRUE)
7.46 -ENDIF(COIN_FOUND)
8.1 --- a/cmake/FindCPLEX.cmake Mon Jul 16 16:21:40 2018 +0200
8.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
8.3 @@ -1,40 +0,0 @@
8.4 -SET(CPLEX_ROOT_DIR "" CACHE PATH "CPLEX root directory")
8.5 -
8.6 -FIND_PATH(CPLEX_INCLUDE_DIR
8.7 - ilcplex/cplex.h
8.8 - PATHS "C:/ILOG/CPLEX/include"
8.9 - PATHS "/opt/ilog/cplex/include"
8.10 - HINTS ${CPLEX_ROOT_DIR}/include
8.11 -)
8.12 -FIND_LIBRARY(CPLEX_LIBRARY
8.13 - cplex
8.14 - PATHS "C:/ILOG/CPLEX/lib/msvc7/stat_mda"
8.15 - PATHS "/opt/ilog/cplex/bin"
8.16 - HINTS ${CPLEX_ROOT_DIR}/bin
8.17 - HINTS ${CPLEX_ROOT_DIR}/lib
8.18 -)
8.19 -
8.20 -INCLUDE(FindPackageHandleStandardArgs)
8.21 -FIND_PACKAGE_HANDLE_STANDARD_ARGS(CPLEX DEFAULT_MSG CPLEX_LIBRARY CPLEX_INCLUDE_DIR)
8.22 -
8.23 -FIND_PATH(CPLEX_BIN_DIR
8.24 - cplex.dll
8.25 - PATHS "C:/ILOG/CPLEX/bin/x86_win32"
8.26 - HINTS ${CPLEX_ROOT_DIR}/bin
8.27 -)
8.28 -
8.29 -IF(CPLEX_FOUND)
8.30 - SET(CPLEX_INCLUDE_DIRS ${CPLEX_INCLUDE_DIR})
8.31 - SET(CPLEX_LIBRARIES ${CPLEX_LIBRARY})
8.32 - IF(CMAKE_SYSTEM_NAME STREQUAL "Linux")
8.33 - SET(CPLEX_LIBRARIES "${CPLEX_LIBRARIES};m;pthread")
8.34 - ENDIF(CMAKE_SYSTEM_NAME STREQUAL "Linux")
8.35 -ENDIF(CPLEX_FOUND)
8.36 -
8.37 -MARK_AS_ADVANCED(CPLEX_LIBRARY CPLEX_INCLUDE_DIR CPLEX_BIN_DIR)
8.38 -
8.39 -IF(CPLEX_FOUND)
8.40 - SET(LEMON_HAVE_LP TRUE)
8.41 - SET(LEMON_HAVE_MIP TRUE)
8.42 - SET(LEMON_HAVE_CPLEX TRUE)
8.43 -ENDIF(CPLEX_FOUND)
9.1 --- a/cmake/FindGLPK.cmake Mon Jul 16 16:21:40 2018 +0200
9.2 +++ b/cmake/FindGLPK.cmake Wed Oct 17 19:14:07 2018 +0200
9.3 @@ -53,9 +53,3 @@
9.4 ENDIF(GLPK_FOUND)
9.5
9.6 MARK_AS_ADVANCED(GLPK_LIBRARY GLPK_INCLUDE_DIR GLPK_BIN_DIR)
9.7 -
9.8 -IF(GLPK_FOUND)
9.9 - SET(LEMON_HAVE_LP TRUE)
9.10 - SET(LEMON_HAVE_MIP TRUE)
9.11 - SET(LEMON_HAVE_GLPK TRUE)
9.12 -ENDIF(GLPK_FOUND)
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
10.2 +++ b/cmake/FindILOG.cmake Wed Oct 17 19:14:07 2018 +0200
10.3 @@ -0,0 +1,106 @@
10.4 +FIND_PATH(ILOG_ROOT_DIR
10.5 + NAMES cplex
10.6 + DOC "CPLEX STUDIO root directory"
10.7 + PATHS /opt/ibm/ILOG /usr/local/ibm/ILOG /usr/local/ILOG /usr/local/ilog
10.8 + PATHS "$ENV{HOME}/ILOG" "$ENV{HOME}/.local/ILOG"
10.9 + PATHS "$ENV{HOME}/ibm/ILOG" "$ENV{HOME}/.local/ibm/ILOG"
10.10 + PATHS "C:/Program Files/IBM/ILOG"
10.11 + PATH_SUFFIXES "CPLEX_Studio126" "CPLEX_Studio125"
10.12 + "CPLEX_Studio124" "CPLEX_Studio123" "CPLEX_Studio122"
10.13 + NO_DEFAULT_PATH
10.14 +)
10.15 +
10.16 +IF(WIN32)
10.17 + IF(MSVC_VERSION STREQUAL "1400")
10.18 + SET(ILOG_WIN_COMPILER "windows_vs2005")
10.19 + ELSEIF(MSVC_VERSION STREQUAL "1500")
10.20 + SET(ILOG_WIN_COMPILER "windows_vs2008")
10.21 + ELSEIF(MSVC_VERSION STREQUAL "1600")
10.22 + SET(ILOG_WIN_COMPILER "windows_vs2010")
10.23 + ELSE()
10.24 + SET(ILOG_WIN_COMPILER "windows_vs2008")
10.25 + ENDIF()
10.26 + IF(CMAKE_CL_64)
10.27 + SET(ILOG_WIN_COMPILER "x64_${ILOG_WIN_COMPILER}")
10.28 + SET(ILOG_WIN_PLATFORM "x64_win32")
10.29 + ELSE()
10.30 + SET(ILOG_WIN_COMPILER "x86_${ILOG_WIN_COMPILER}")
10.31 + SET(ILOG_WIN_PLATFORM "x86_win32")
10.32 + ENDIF()
10.33 +ENDIF()
10.34 +
10.35 +FIND_PATH(ILOG_CPLEX_ROOT_DIR
10.36 + NAMES include/ilcplex
10.37 + HINTS ${ILOG_ROOT_DIR}/cplex ${ILOG_ROOT_DIR}/cplex121
10.38 + ${ILOG_ROOT_DIR}/cplex122 ${ILOG_ROOT_DIR}/cplex123
10.39 + DOC "CPLEX root directory"
10.40 + NO_DEFAULT_PATH
10.41 +)
10.42 +
10.43 +FIND_PATH(ILOG_CONCERT_ROOT_DIR
10.44 + NAMES include/ilconcert
10.45 + HINTS ${ILOG_ROOT_DIR}/concert ${ILOG_ROOT_DIR}/concert29
10.46 + DOC "CONCERT root directory"
10.47 + NO_DEFAULT_PATH
10.48 +)
10.49 +
10.50 +FIND_PATH(ILOG_CPLEX_INCLUDE_DIR
10.51 + ilcplex/cplex.h
10.52 + HINTS ${ILOG_CPLEX_ROOT_DIR}/include
10.53 + NO_DEFAULT_PATH
10.54 +)
10.55 +
10.56 +FIND_PATH(ILOG_CONCERT_INCLUDE_DIR
10.57 + ilconcert/ilobasic.h
10.58 + HINTS ${ILOG_CONCERT_ROOT_DIR}/include
10.59 + NO_DEFAULT_PATH
10.60 +)
10.61 +
10.62 +FIND_LIBRARY(ILOG_CPLEX_LIBRARY
10.63 + cplex cplex121 cplex122 cplex123 cplex124
10.64 + HINTS ${ILOG_CPLEX_ROOT_DIR}/lib/x86_sles10_4.1/static_pic
10.65 + ${ILOG_CPLEX_ROOT_DIR}/lib/x86-64_sles10_4.1/static_pic
10.66 + ${ILOG_CPLEX_ROOT_DIR}/lib/x86_debian4.0_4.1/static_pic
10.67 + ${ILOG_CPLEX_ROOT_DIR}/lib/x86-64_debian4.0_4.1/static_pic
10.68 + ${ILOG_CPLEX_ROOT_DIR}/lib/x86_linux/static_pic
10.69 + ${ILOG_CPLEX_ROOT_DIR}/lib/x86-64_linux/static_pic
10.70 + ${ILOG_CPLEX_ROOT_DIR}/lib/${ILOG_WIN_COMPILER}/stat_mda
10.71 + NO_DEFAULT_PATH
10.72 + )
10.73 +
10.74 +FIND_LIBRARY(ILOG_CONCERT_LIBRARY
10.75 + concert
10.76 + HINTS ${ILOG_CONCERT_ROOT_DIR}/lib/x86_sles10_4.1/static_pic
10.77 + ${ILOG_CONCERT_ROOT_DIR}/lib/x86-64_sles10_4.1/static_pic
10.78 + ${ILOG_CONCERT_ROOT_DIR}/lib/x86_debian4.0_4.1/static_pic
10.79 + ${ILOG_CONCERT_ROOT_DIR}/lib/x86-64_debian4.0_4.1/static_pic
10.80 + ${ILOG_CONCERT_ROOT_DIR}/lib/x86_linux/static_pic
10.81 + ${ILOG_CONCERT_ROOT_DIR}/lib/x86-64_linux/static_pic
10.82 + ${ILOG_CONCERT_ROOT_DIR}/lib/${ILOG_WIN_COMPILER}/stat_mda
10.83 + NO_DEFAULT_PATH
10.84 + )
10.85 +
10.86 +FIND_FILE(ILOG_CPLEX_DLL
10.87 + cplex121.dll cplex122.dll cplex123.dll cplex124.dll
10.88 + HINTS ${ILOG_CPLEX_ROOT_DIR}/bin/${ILOG_WIN_PLATFORM}
10.89 + NO_DEFAULT_PATH
10.90 + )
10.91 +
10.92 +INCLUDE(FindPackageHandleStandardArgs)
10.93 +FIND_PACKAGE_HANDLE_STANDARD_ARGS(ILOG
10.94 + DEFAULT_MSG ILOG_CPLEX_LIBRARY ILOG_CPLEX_INCLUDE_DIR
10.95 + )
10.96 +
10.97 +IF(ILOG_FOUND)
10.98 + SET(ILOG_INCLUDE_DIRS ${ILOG_CPLEX_INCLUDE_DIR} ${ILOG_CONCERT_INCLUDE_DIR})
10.99 + SET(ILOG_LIBRARIES ${ILOG_CPLEX_LIBRARY} ${ILOG_CONCERT_LIBRARY})
10.100 + IF(CMAKE_SYSTEM_NAME STREQUAL "Linux")
10.101 + # SET(CPLEX_LIBRARIES "${CPLEX_LIBRARIES};m;pthread")
10.102 + SET(ILOG_LIBRARIES ${ILOG_LIBRARIES} "m" "pthread")
10.103 + ENDIF(CMAKE_SYSTEM_NAME STREQUAL "Linux")
10.104 +ENDIF(ILOG_FOUND)
10.105 +
10.106 +MARK_AS_ADVANCED(
10.107 + ILOG_CPLEX_LIBRARY ILOG_CPLEX_INCLUDE_DIR ILOG_CPLEX_DLL
10.108 + ILOG_CONCERT_LIBRARY ILOG_CONCERT_INCLUDE_DIR ILOG_CONCERT_DLL
10.109 + )
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
11.2 +++ b/cmake/FindSOPLEX.cmake Wed Oct 17 19:14:07 2018 +0200
11.3 @@ -0,0 +1,23 @@
11.4 +SET(SOPLEX_ROOT_DIR "" CACHE PATH "SoPlex root directory")
11.5 +
11.6 +FIND_PATH(SOPLEX_INCLUDE_DIR
11.7 + soplex.h
11.8 + HINTS ${SOPLEX_ROOT_DIR}/src
11.9 +)
11.10 +FIND_LIBRARY(SOPLEX_LIBRARY
11.11 + soplex
11.12 + HINTS ${SOPLEX_ROOT_DIR}/lib
11.13 +)
11.14 +
11.15 +INCLUDE(FindPackageHandleStandardArgs)
11.16 +FIND_PACKAGE_HANDLE_STANDARD_ARGS(SOPLEX DEFAULT_MSG SOPLEX_LIBRARY SOPLEX_INCLUDE_DIR)
11.17 +
11.18 +IF(SOPLEX_FOUND)
11.19 + SET(SOPLEX_INCLUDE_DIRS ${SOPLEX_INCLUDE_DIR})
11.20 + SET(SOPLEX_LIBRARIES ${SOPLEX_LIBRARY})
11.21 + IF(CMAKE_SYSTEM_NAME STREQUAL "Linux")
11.22 + SET(SOPLEX_LIBRARIES "${SOPLEX_LIBRARIES};z")
11.23 + ENDIF(CMAKE_SYSTEM_NAME STREQUAL "Linux")
11.24 +ENDIF(SOPLEX_FOUND)
11.25 +
11.26 +MARK_AS_ADVANCED(SOPLEX_LIBRARY SOPLEX_INCLUDE_DIR)
12.1 --- a/cmake/version.cmake.in Mon Jul 16 16:21:40 2018 +0200
12.2 +++ b/cmake/version.cmake.in Wed Oct 17 19:14:07 2018 +0200
12.3 @@ -1,1 +1,1 @@
12.4 -SET(LEMON_VERSION "@PACKAGE_VERSION@" CACHE STRING "LEMON version string.")
12.5 +SET(LEMON_VERSION "@LEMON_VERSION@" CACHE STRING "LEMON version string.")
13.1 --- a/configure.ac Mon Jul 16 16:21:40 2018 +0200
13.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
13.3 @@ -1,157 +0,0 @@
13.4 -dnl Process this file with autoconf to produce a configure script.
13.5 -
13.6 -dnl Version information.
13.7 -m4_define([lemon_version_number],
13.8 - [m4_normalize(esyscmd([echo ${LEMON_VERSION}]))])
13.9 -dnl m4_define([lemon_version_number], [])
13.10 -m4_define([lemon_hg_path], [m4_normalize(esyscmd([./scripts/chg-len.py]))])
13.11 -m4_define([lemon_hg_revision], [m4_normalize(esyscmd([hg id -i 2> /dev/null]))])
13.12 -m4_define([lemon_version], [ifelse(lemon_version_number(),
13.13 - [],
13.14 - [ifelse(lemon_hg_revision(),
13.15 - [],
13.16 - [hg-tip],
13.17 - [lemon_hg_path().lemon_hg_revision()])],
13.18 - [lemon_version_number()])])
13.19 -
13.20 -AC_PREREQ([2.59])
13.21 -AC_INIT([LEMON], [lemon_version()], [lemon-user@lemon.cs.elte.hu], [lemon])
13.22 -AC_CONFIG_AUX_DIR([build-aux])
13.23 -AC_CONFIG_MACRO_DIR([m4])
13.24 -AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects nostdinc])
13.25 -AC_CONFIG_SRCDIR([lemon/list_graph.h])
13.26 -AC_CONFIG_HEADERS([config.h lemon/config.h])
13.27 -
13.28 -AC_DEFINE([LEMON_VERSION], [lemon_version()], [The version string])
13.29 -
13.30 -dnl Do compilation tests using the C++ compiler.
13.31 -AC_LANG([C++])
13.32 -
13.33 -dnl Check the existence of long long type.
13.34 -AC_CHECK_TYPE(long long, [long_long_found=yes], [long_long_found=no])
13.35 -if test x"$long_long_found" = x"yes"; then
13.36 - AC_DEFINE([LEMON_HAVE_LONG_LONG], [1], [Define to 1 if you have long long.])
13.37 -fi
13.38 -
13.39 -dnl Checks for programs.
13.40 -AC_PROG_CXX
13.41 -AC_PROG_CXXCPP
13.42 -AC_PROG_INSTALL
13.43 -AC_DISABLE_SHARED
13.44 -AC_PROG_LIBTOOL
13.45 -
13.46 -AC_CHECK_PROG([doxygen_found],[doxygen],[yes],[no])
13.47 -AC_CHECK_PROG([python_found],[python],[yes],[no])
13.48 -AC_CHECK_PROG([gs_found],[gs],[yes],[no])
13.49 -
13.50 -dnl Detect Intel compiler.
13.51 -AC_MSG_CHECKING([whether we are using the Intel C++ compiler])
13.52 -AC_COMPILE_IFELSE([#ifndef __INTEL_COMPILER
13.53 -choke me
13.54 -#endif], [ICC=[yes]], [ICC=[no]])
13.55 -if test x"$ICC" = x"yes"; then
13.56 - AC_MSG_RESULT([yes])
13.57 -else
13.58 - AC_MSG_RESULT([no])
13.59 -fi
13.60 -
13.61 -dnl Set custom compiler flags when using g++.
13.62 -if test "$GXX" = yes -a "$ICC" = no; then
13.63 - WARNINGCXXFLAGS="-Wall -W -Wall -W -Wunused -Wformat=2 -Wctor-dtor-privacy -Wnon-virtual-dtor -Wno-char-subscripts -Wwrite-strings -Wno-char-subscripts -Wreturn-type -Wcast-qual -Wcast-align -Wsign-promo -Woverloaded-virtual -ansi -fno-strict-aliasing -Wold-style-cast -Wno-unknown-pragmas"
13.64 -fi
13.65 -AC_SUBST([WARNINGCXXFLAGS])
13.66 -
13.67 -dnl Checks for libraries.
13.68 -LX_CHECK_GLPK
13.69 -LX_CHECK_CPLEX
13.70 -LX_CHECK_SOPLEX
13.71 -LX_CHECK_COIN
13.72 -
13.73 -AM_CONDITIONAL([HAVE_LP], [test x"$lx_lp_found" = x"yes"])
13.74 -AM_CONDITIONAL([HAVE_MIP], [test x"$lx_mip_found" = x"yes"])
13.75 -
13.76 -dnl Disable/enable building the binary tools.
13.77 -AC_ARG_ENABLE([tools],
13.78 -AS_HELP_STRING([--enable-tools], [build additional tools @<:@default@:>@])
13.79 -AS_HELP_STRING([--disable-tools], [do not build additional tools]),
13.80 - [], [enable_tools=yes])
13.81 -AC_MSG_CHECKING([whether to build the additional tools])
13.82 -if test x"$enable_tools" != x"no"; then
13.83 - AC_MSG_RESULT([yes])
13.84 -else
13.85 - AC_MSG_RESULT([no])
13.86 -fi
13.87 -AM_CONDITIONAL([WANT_TOOLS], [test x"$enable_tools" != x"no"])
13.88 -
13.89 -dnl Support for running test cases using valgrind.
13.90 -use_valgrind=no
13.91 -AC_ARG_ENABLE([valgrind],
13.92 -AS_HELP_STRING([--enable-valgrind], [use valgrind when running tests]),
13.93 - [use_valgrind=yes])
13.94 -
13.95 -if [[ "$use_valgrind" = "yes" ]]; then
13.96 - AC_CHECK_PROG(HAVE_VALGRIND, valgrind, yes, no)
13.97 -
13.98 - if [[ "$HAVE_VALGRIND" = "no" ]]; then
13.99 - AC_MSG_ERROR([Valgrind not found in PATH.])
13.100 - fi
13.101 -fi
13.102 -AM_CONDITIONAL(USE_VALGRIND, [test "$use_valgrind" = "yes"])
13.103 -
13.104 -dnl Checks for header files.
13.105 -AC_CHECK_HEADERS(limits.h sys/time.h sys/times.h unistd.h)
13.106 -
13.107 -dnl Checks for typedefs, structures, and compiler characteristics.
13.108 -AC_C_CONST
13.109 -AC_C_INLINE
13.110 -AC_TYPE_SIZE_T
13.111 -AC_HEADER_TIME
13.112 -AC_STRUCT_TM
13.113 -
13.114 -dnl Checks for library functions.
13.115 -AC_HEADER_STDC
13.116 -AC_CHECK_FUNCS(gettimeofday times ctime_r)
13.117 -
13.118 -dnl Add dependencies on files generated by configure.
13.119 -AC_SUBST([CONFIG_STATUS_DEPENDENCIES],
13.120 - ['$(top_srcdir)/doc/Doxyfile.in $(top_srcdir)/doc/mainpage.dox.in $(top_srcdir)/lemon/lemon.pc.in $(top_srcdir)/cmake/version.cmake.in'])
13.121 -
13.122 -AC_CONFIG_FILES([
13.123 -Makefile
13.124 -demo/Makefile
13.125 -cmake/version.cmake
13.126 -doc/Doxyfile
13.127 -doc/mainpage.dox
13.128 -lemon/lemon.pc
13.129 -])
13.130 -
13.131 -AC_OUTPUT
13.132 -
13.133 -echo
13.134 -echo '****************************** SUMMARY ******************************'
13.135 -echo
13.136 -echo Package version............... : $PACKAGE-$VERSION
13.137 -echo
13.138 -echo C++ compiler.................. : $CXX
13.139 -echo C++ compiles flags............ : $WARNINGCXXFLAGS $CXXFLAGS
13.140 -echo
13.141 -echo Compiler supports long long... : $long_long_found
13.142 -echo
13.143 -echo GLPK support.................. : $lx_glpk_found
13.144 -echo CPLEX support................. : $lx_cplex_found
13.145 -echo SOPLEX support................ : $lx_soplex_found
13.146 -echo CLP support................... : $lx_clp_found
13.147 -echo CBC support................... : $lx_cbc_found
13.148 -echo
13.149 -echo Build additional tools........ : $enable_tools
13.150 -echo Use valgrind for tests........ : $use_valgrind
13.151 -echo
13.152 -echo The packace will be installed in
13.153 -echo -n ' '
13.154 -echo $prefix.
13.155 -echo
13.156 -echo '*********************************************************************'
13.157 -
13.158 -echo
13.159 -echo Configure complete, now type \'make\' and then \'make install\'.
13.160 -echo
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
14.2 +++ b/contrib/CMakeLists.txt Wed Oct 17 19:14:07 2018 +0200
14.3 @@ -0,0 +1,19 @@
14.4 +INCLUDE_DIRECTORIES(
14.5 + ${PROJECT_SOURCE_DIR}
14.6 + ${PROJECT_BINARY_DIR}
14.7 +)
14.8 +
14.9 +LINK_DIRECTORIES(
14.10 + ${PROJECT_BINARY_DIR}/lemon
14.11 +)
14.12 +
14.13 +# Uncomment (and adjust) the following two lines. 'myprog' is the name
14.14 +# of the final executable ('.exe' will automatically be added to the
14.15 +# name on Windows) and 'myprog-main.cc' is the source code it is
14.16 +# compiled from. You can add more source files separated by
14.17 +# whitespaces. Moreover, you can add multiple similar blocks if you
14.18 +# want to build more than one executables.
14.19 +
14.20 +# ADD_EXECUTABLE(myprog myprog-main.cc)
14.21 +# TARGET_LINK_LIBRARIES(myprog lemon)
14.22 +
15.1 --- a/demo/Makefile.am Mon Jul 16 16:21:40 2018 +0200
15.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
15.3 @@ -1,17 +0,0 @@
15.4 -AM_CXXFLAGS = $(WARNINGCXXFLAGS)
15.5 -
15.6 -AM_CPPFLAGS = -I$(top_srcdir) -I$(top_builddir)
15.7 -LDADD = $(top_builddir)/lemon/libemon.la
15.8 -
15.9 -EXTRA_DIST = \
15.10 - CMakeLists.txt \
15.11 - digraph.lgf
15.12 -
15.13 -noinst_PROGRAMS = \
15.14 - arg_parser_demo \
15.15 - graph_to_eps_demo \
15.16 - lgf_demo
15.17 -
15.18 -arg_parser_demo_SOURCES = arg_parser_demo.cc
15.19 -graph_to_eps_demo_SOURCES = graph_to_eps_demo.cc
15.20 -lgf_demo_SOURCES = lgf_demo.cc
16.1 --- a/doc/CMakeLists.txt Mon Jul 16 16:21:40 2018 +0200
16.2 +++ b/doc/CMakeLists.txt Wed Oct 17 19:14:07 2018 +0200
16.3 @@ -4,6 +4,13 @@
16.4 SET(abs_top_builddir ${PROJECT_BINARY_DIR})
16.5
16.6 SET(LEMON_DOC_SOURCE_BROWSER "NO" CACHE STRING "Include source into the doc (YES/NO).")
16.7 +SET(LEMON_DOC_USE_MATHJAX "NO" CACHE STRING "Use MathJax to display math formulae (YES/NO).")
16.8 +SET(LEMON_DOC_MATHJAX_RELPATH "http://www.mathjax.org/mathjax" CACHE STRING "MathJax library location.")
16.9 +
16.10 +SET(LEMON_DOC_LIBSTDC++_URL
16.11 + "http://gcc.gnu.org/onlinedocs/gcc-4.7.3/libstdc++/api"
16.12 + CACHE STRING "GCC libstdc++ doxygen doc url.")
16.13 +
16.14
16.15 CONFIGURE_FILE(
16.16 ${PROJECT_SOURCE_DIR}/doc/Doxyfile.in
16.17 @@ -17,28 +24,38 @@
16.18 @ONLY
16.19 )
16.20
16.21 +# Copy doc from source (if exists)
16.22 +IF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/html AND
16.23 + NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}/html/index.html)
16.24 + MESSAGE(STATUS "Copy doc from source tree")
16.25 + EXECUTE_PROCESS(
16.26 + COMMAND cmake -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/html ${CMAKE_CURRENT_BINARY_DIR}/html
16.27 + )
16.28 +ENDIF()
16.29 +
16.30 IF(DOXYGEN_EXECUTABLE AND PYTHONINTERP_FOUND AND GHOSTSCRIPT_EXECUTABLE)
16.31 FILE(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html/)
16.32 SET(GHOSTSCRIPT_OPTIONS -dNOPAUSE -dBATCH -q -dEPSCrop -dTextAlphaBits=4 -dGraphicsAlphaBits=4 -sDEVICE=pngalpha)
16.33 ADD_CUSTOM_TARGET(html
16.34 COMMAND ${CMAKE_COMMAND} -E remove_directory gen-images
16.35 COMMAND ${CMAKE_COMMAND} -E make_directory gen-images
16.36 - COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r18 -sOutputFile=gen-images/bipartite_matching.png ${CMAKE_CURRENT_SOURCE_DIR}/images/bipartite_matching.eps
16.37 - COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r18 -sOutputFile=gen-images/bipartite_partitions.png ${CMAKE_CURRENT_SOURCE_DIR}/images/bipartite_partitions.eps
16.38 - COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r18 -sOutputFile=gen-images/connected_components.png ${CMAKE_CURRENT_SOURCE_DIR}/images/connected_components.eps
16.39 - COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r18 -sOutputFile=gen-images/edge_biconnected_components.png ${CMAKE_CURRENT_SOURCE_DIR}/images/edge_biconnected_components.eps
16.40 - COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r18 -sOutputFile=gen-images/grid_graph.png ${CMAKE_CURRENT_SOURCE_DIR}/images/grid_graph.eps
16.41 - COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r18 -sOutputFile=gen-images/matching.png ${CMAKE_CURRENT_SOURCE_DIR}/images/matching.eps
16.42 - COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r18 -sOutputFile=gen-images/node_biconnected_components.png ${CMAKE_CURRENT_SOURCE_DIR}/images/node_biconnected_components.eps
16.43 - COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r18 -sOutputFile=gen-images/nodeshape_0.png ${CMAKE_CURRENT_SOURCE_DIR}/images/nodeshape_0.eps
16.44 - COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r18 -sOutputFile=gen-images/nodeshape_1.png ${CMAKE_CURRENT_SOURCE_DIR}/images/nodeshape_1.eps
16.45 - COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r18 -sOutputFile=gen-images/nodeshape_2.png ${CMAKE_CURRENT_SOURCE_DIR}/images/nodeshape_2.eps
16.46 - COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r18 -sOutputFile=gen-images/nodeshape_3.png ${CMAKE_CURRENT_SOURCE_DIR}/images/nodeshape_3.eps
16.47 - COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r18 -sOutputFile=gen-images/nodeshape_4.png ${CMAKE_CURRENT_SOURCE_DIR}/images/nodeshape_4.eps
16.48 - COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r18 -sOutputFile=gen-images/planar.png ${CMAKE_CURRENT_SOURCE_DIR}/images/planar.eps
16.49 - COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r18 -sOutputFile=gen-images/strongly_connected_components.png ${CMAKE_CURRENT_SOURCE_DIR}/images/strongly_connected_components.eps
16.50 + COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r20 -sOutputFile=gen-images/grid_graph.png ${CMAKE_CURRENT_SOURCE_DIR}/images/grid_graph.eps
16.51 + COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r32 -sOutputFile=gen-images/adaptors2.png ${CMAKE_CURRENT_SOURCE_DIR}/images/adaptors2.eps
16.52 + COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r32 -sOutputFile=gen-images/connected_components.png ${CMAKE_CURRENT_SOURCE_DIR}/images/connected_components.eps
16.53 + COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r32 -sOutputFile=gen-images/strongly_connected_components.png ${CMAKE_CURRENT_SOURCE_DIR}/images/strongly_connected_components.eps
16.54 + COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r32 -sOutputFile=gen-images/node_biconnected_components.png ${CMAKE_CURRENT_SOURCE_DIR}/images/node_biconnected_components.eps
16.55 + COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r32 -sOutputFile=gen-images/edge_biconnected_components.png ${CMAKE_CURRENT_SOURCE_DIR}/images/edge_biconnected_components.eps
16.56 + COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r32 -sOutputFile=gen-images/bipartite_partitions.png ${CMAKE_CURRENT_SOURCE_DIR}/images/bipartite_partitions.eps
16.57 + COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r24 -sOutputFile=gen-images/matching.png ${CMAKE_CURRENT_SOURCE_DIR}/images/matching.eps
16.58 + COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r24 -sOutputFile=gen-images/bipartite_matching.png ${CMAKE_CURRENT_SOURCE_DIR}/images/bipartite_matching.eps
16.59 + COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r40 -sOutputFile=gen-images/planar.png ${CMAKE_CURRENT_SOURCE_DIR}/images/planar.eps
16.60 + COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r24 -sOutputFile=gen-images/tsp.png ${CMAKE_CURRENT_SOURCE_DIR}/images/tsp.eps
16.61 + COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r8 -sOutputFile=gen-images/nodeshape_0.png ${CMAKE_CURRENT_SOURCE_DIR}/images/nodeshape_0.eps
16.62 + COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r8 -sOutputFile=gen-images/nodeshape_1.png ${CMAKE_CURRENT_SOURCE_DIR}/images/nodeshape_1.eps
16.63 + COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r8 -sOutputFile=gen-images/nodeshape_2.png ${CMAKE_CURRENT_SOURCE_DIR}/images/nodeshape_2.eps
16.64 + COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r8 -sOutputFile=gen-images/nodeshape_3.png ${CMAKE_CURRENT_SOURCE_DIR}/images/nodeshape_3.eps
16.65 + COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r8 -sOutputFile=gen-images/nodeshape_4.png ${CMAKE_CURRENT_SOURCE_DIR}/images/nodeshape_4.eps
16.66 COMMAND ${CMAKE_COMMAND} -E remove_directory html
16.67 - COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/scripts/bib2dox.py ${CMAKE_CURRENT_SOURCE_DIR}/references.bib >references.dox
16.68 COMMAND ${DOXYGEN_EXECUTABLE} Doxyfile
16.69 WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
16.70 )
16.71 @@ -63,12 +80,7 @@
16.72
16.73 IF(WGET_FOUND)
16.74 ADD_CUSTOM_TARGET(update-external-tags
16.75 - COMMAND ${CMAKE_COMMAND} -E make_directory dl
16.76 - # COMMAND ${CMAKE_COMMAND} -E copy libstdc++.tag dl
16.77 - COMMAND ${WGET_EXECUTABLE} wget -P dl -N libstdc++.tag.tmp http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/libstdc++.tag
16.78 - COMMAND ${CMAKE_COMMAND} -E rename dl/libstdc++.tag libstdc++.tag
16.79 - COMMAND ${CMAKE_COMMAND} -E remove dl/libstdc++.tag
16.80 - COMMAND ${CMAKE_COMMAND} -E remove_directory dl
16.81 + COMMAND ${WGET_EXECUTABLE} -N ${LEMON_DOC_LIBSTDC++_URL}/libstdc++.tag
16.82 WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
16.83 )
16.84 ENDIF()
17.1 --- a/doc/Doxyfile.in Mon Jul 16 16:21:40 2018 +0200
17.2 +++ b/doc/Doxyfile.in Wed Oct 17 19:14:07 2018 +0200
17.3 @@ -77,6 +77,7 @@
17.4 SHOW_NAMESPACES = YES
17.5 FILE_VERSION_FILTER =
17.6 LAYOUT_FILE = "@abs_top_srcdir@/doc/DoxygenLayout.xml"
17.7 +CITE_BIB_FILES = "@abs_top_srcdir@/doc/references.bib"
17.8 #---------------------------------------------------------------------------
17.9 # configuration options related to warning and progress messages
17.10 #---------------------------------------------------------------------------
17.11 @@ -95,10 +96,10 @@
17.12 "@abs_top_srcdir@/lemon/bits" \
17.13 "@abs_top_srcdir@/lemon/concepts" \
17.14 "@abs_top_srcdir@/demo" \
17.15 + "@abs_top_srcdir@/contrib" \
17.16 "@abs_top_srcdir@/tools" \
17.17 "@abs_top_srcdir@/test/test_tools.h" \
17.18 - "@abs_top_builddir@/doc/mainpage.dox" \
17.19 - "@abs_top_builddir@/doc/references.dox"
17.20 + "@abs_top_builddir@/doc/mainpage.dox"
17.21 INPUT_ENCODING = UTF-8
17.22 FILE_PATTERNS = *.h \
17.23 *.cc \
17.24 @@ -181,8 +182,8 @@
17.25 EXT_LINKS_IN_WINDOW = NO
17.26 FORMULA_FONTSIZE = 10
17.27 FORMULA_TRANSPARENT = YES
17.28 -USE_MATHJAX = NO
17.29 -MATHJAX_RELPATH = http://www.mathjax.org/mathjax
17.30 +USE_MATHJAX = @LEMON_DOC_USE_MATHJAX@
17.31 +MATHJAX_RELPATH = @LEMON_DOC_MATHJAX_RELPATH@
17.32 SEARCHENGINE = YES
17.33 SERVER_BASED_SEARCH = NO
17.34 #---------------------------------------------------------------------------
17.35 @@ -252,7 +253,7 @@
17.36 #---------------------------------------------------------------------------
17.37 # Configuration::additions related to external references
17.38 #---------------------------------------------------------------------------
17.39 -TAGFILES = "@abs_top_builddir@/doc/libstdc++.tag = http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/ "
17.40 +TAGFILES = "@abs_top_builddir@/doc/libstdc++.tag = @LEMON_DOC_LIBSTDC++_URL@"
17.41 GENERATE_TAGFILE = html/lemon.tag
17.42 ALLEXTERNALS = NO
17.43 EXTERNAL_GROUPS = NO
18.1 --- a/doc/DoxygenLayout.xml Mon Jul 16 16:21:40 2018 +0200
18.2 +++ b/doc/DoxygenLayout.xml Wed Oct 17 19:14:07 2018 +0200
18.3 @@ -17,7 +17,6 @@
18.4 <tab type="files" visible="yes" title="" intro=""/>
18.5 <tab type="globals" visible="yes" title="" intro=""/>
18.6 </tab>
18.7 - <tab type="dirs" visible="yes" title="" intro=""/>
18.8 <tab type="examples" visible="yes" title="" intro=""/>
18.9 <tab type="pages" visible="yes" title="" intro=""/>
18.10 </navindex>
19.1 --- a/doc/Makefile.am Mon Jul 16 16:21:40 2018 +0200
19.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
19.3 @@ -1,125 +0,0 @@
19.4 -EXTRA_DIST += \
19.5 - doc/Doxyfile.in \
19.6 - doc/DoxygenLayout.xml \
19.7 - doc/coding_style.dox \
19.8 - doc/dirs.dox \
19.9 - doc/groups.dox \
19.10 - doc/lgf.dox \
19.11 - doc/license.dox \
19.12 - doc/mainpage.dox \
19.13 - doc/migration.dox \
19.14 - doc/min_cost_flow.dox \
19.15 - doc/named-param.dox \
19.16 - doc/namespaces.dox \
19.17 - doc/references.bib \
19.18 - doc/template.h \
19.19 - doc/html \
19.20 - doc/CMakeLists.txt
19.21 -
19.22 -DOC_EPS_IMAGES18 = \
19.23 - grid_graph.eps \
19.24 - nodeshape_0.eps \
19.25 - nodeshape_1.eps \
19.26 - nodeshape_2.eps \
19.27 - nodeshape_3.eps \
19.28 - nodeshape_4.eps
19.29 -
19.30 -DOC_EPS_IMAGES27 = \
19.31 - bipartite_matching.eps \
19.32 - bipartite_partitions.eps \
19.33 - connected_components.eps \
19.34 - edge_biconnected_components.eps \
19.35 - matching.eps \
19.36 - node_biconnected_components.eps \
19.37 - planar.eps \
19.38 - strongly_connected_components.eps
19.39 -
19.40 -DOC_EPS_IMAGES = \
19.41 - $(DOC_EPS_IMAGES18) \
19.42 - $(DOC_EPS_IMAGES27)
19.43 -
19.44 -DOC_PNG_IMAGES = \
19.45 - $(DOC_EPS_IMAGES:%.eps=doc/gen-images/%.png)
19.46 -
19.47 -EXTRA_DIST += $(DOC_EPS_IMAGES:%=doc/images/%)
19.48 -
19.49 -doc/html:
19.50 - $(MAKE) $(AM_MAKEFLAGS) html
19.51 -
19.52 -GS_COMMAND=gs -dNOPAUSE -dBATCH -q -dEPSCrop -dTextAlphaBits=4 -dGraphicsAlphaBits=4
19.53 -
19.54 -$(DOC_EPS_IMAGES18:%.eps=doc/gen-images/%.png): doc/gen-images/%.png: doc/images/%.eps
19.55 - -mkdir doc/gen-images
19.56 - if test ${gs_found} = yes; then \
19.57 - $(GS_COMMAND) -sDEVICE=pngalpha -r18 -sOutputFile=$@ $<; \
19.58 - else \
19.59 - echo; \
19.60 - echo "Ghostscript not found."; \
19.61 - echo; \
19.62 - exit 1; \
19.63 - fi
19.64 -
19.65 -$(DOC_EPS_IMAGES27:%.eps=doc/gen-images/%.png): doc/gen-images/%.png: doc/images/%.eps
19.66 - -mkdir doc/gen-images
19.67 - if test ${gs_found} = yes; then \
19.68 - $(GS_COMMAND) -sDEVICE=pngalpha -r27 -sOutputFile=$@ $<; \
19.69 - else \
19.70 - echo; \
19.71 - echo "Ghostscript not found."; \
19.72 - echo; \
19.73 - exit 1; \
19.74 - fi
19.75 -
19.76 -references.dox: doc/references.bib
19.77 - if test ${python_found} = yes; then \
19.78 - cd doc; \
19.79 - python @abs_top_srcdir@/scripts/bib2dox.py @abs_top_builddir@/$< >$@; \
19.80 - cd ..; \
19.81 - else \
19.82 - echo; \
19.83 - echo "Python not found."; \
19.84 - echo; \
19.85 - exit 1; \
19.86 - fi
19.87 -
19.88 -html-local: $(DOC_PNG_IMAGES) references.dox
19.89 - if test ${doxygen_found} = yes; then \
19.90 - cd doc; \
19.91 - doxygen Doxyfile; \
19.92 - cd ..; \
19.93 - else \
19.94 - echo; \
19.95 - echo "Doxygen not found."; \
19.96 - echo; \
19.97 - exit 1; \
19.98 - fi
19.99 -
19.100 -clean-local:
19.101 - -rm -rf doc/html
19.102 - -rm -f doc/doxygen.log
19.103 - -rm -f $(DOC_PNG_IMAGES)
19.104 - -rm -rf doc/gen-images
19.105 -
19.106 -update-external-tags:
19.107 - wget -O doc/libstdc++.tag.tmp http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/libstdc++.tag && \
19.108 - mv doc/libstdc++.tag.tmp doc/libstdc++.tag || \
19.109 - rm doc/libstdc++.tag.tmp
19.110 -
19.111 -install-html-local: doc/html
19.112 - @$(NORMAL_INSTALL)
19.113 - $(mkinstalldirs) $(DESTDIR)$(htmldir)/html
19.114 - for p in doc/html/*.{html,css,png,map,gif,tag} ; do \
19.115 - f="`echo $$p | sed -e 's|^.*/||'`"; \
19.116 - echo " $(INSTALL_DATA) $$p $(DESTDIR)$(htmldir)/html/$$f"; \
19.117 - $(INSTALL_DATA) $$p $(DESTDIR)$(htmldir)/html/$$f; \
19.118 - done
19.119 -
19.120 -uninstall-local:
19.121 - @$(NORMAL_UNINSTALL)
19.122 - for p in doc/html/*.{html,css,png,map,gif,tag} ; do \
19.123 - f="`echo $$p | sed -e 's|^.*/||'`"; \
19.124 - echo " rm -f $(DESTDIR)$(htmldir)/html/$$f"; \
19.125 - rm -f $(DESTDIR)$(htmldir)/html/$$f; \
19.126 - done
19.127 -
19.128 -.PHONY: update-external-tags
20.1 --- a/doc/coding_style.dox Mon Jul 16 16:21:40 2018 +0200
20.2 +++ b/doc/coding_style.dox Wed Oct 17 19:14:07 2018 +0200
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-2013
20.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
20.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
20.11 *
20.12 @@ -98,10 +98,10 @@
20.13
20.14 \subsection pri-loc-var Private member variables
20.15
20.16 -Private member variables should start with underscore
20.17 +Private member variables should start with underscore.
20.18
20.19 \code
20.20 -_start_with_underscores
20.21 +_start_with_underscore
20.22 \endcode
20.23
20.24 \subsection cs-excep Exceptions
21.1 --- a/doc/dirs.dox Mon Jul 16 16:21:40 2018 +0200
21.2 +++ b/doc/dirs.dox Wed Oct 17 19:14:07 2018 +0200
21.3 @@ -2,7 +2,7 @@
21.4 *
21.5 * This file is a part of LEMON, a generic C++ optimization library.
21.6 *
21.7 - * Copyright (C) 2003-2009
21.8 + * Copyright (C) 2003-2013
21.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
21.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
21.11 *
21.12 @@ -33,6 +33,19 @@
21.13 */
21.14
21.15 /**
21.16 +\dir contrib
21.17 +\brief Directory for user contributed source codes.
21.18 +
21.19 +You can place your own C++ code using LEMON into this directory, which
21.20 +will compile to an executable along with LEMON when you build the
21.21 +library. This is probably the easiest way of compiling short to medium
21.22 +codes, for this does require neither a LEMON installed system-wide nor
21.23 +adding several paths to the compiler.
21.24 +
21.25 +Please have a look at <tt>contrib/CMakeLists.txt</tt> for
21.26 +instruction on how to add your own files into the build process. */
21.27 +
21.28 +/**
21.29 \dir test
21.30 \brief Test programs.
21.31
22.1 --- a/doc/groups.dox Mon Jul 16 16:21:40 2018 +0200
22.2 +++ b/doc/groups.dox Wed Oct 17 19:14:07 2018 +0200
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-2010
22.8 + * Copyright (C) 2003-2013
22.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
22.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
22.11 *
22.12 @@ -112,6 +112,14 @@
22.13 obtained. For other examples, the interested user is referred to the
22.14 detailed documentation of particular adaptors.
22.15
22.16 +Since the adaptor classes conform to the \ref graph_concepts "graph concepts",
22.17 +an adaptor can even be applied to another one.
22.18 +The following image illustrates a situation when a \ref SubDigraph adaptor
22.19 +is applied on a digraph and \ref Undirector is applied on the subgraph.
22.20 +
22.21 +\image html adaptors2.png
22.22 +\image latex adaptors2.eps "Using graph adaptors" width=\textwidth
22.23 +
22.24 The behavior of graph adaptors can be very different. Some of them keep
22.25 capabilities of the original graph while in other cases this would be
22.26 meaningless. This means that the concepts that they meet depend
22.27 @@ -309,7 +317,7 @@
22.28
22.29 This group contains the common graph search algorithms, namely
22.30 \e breadth-first \e search (BFS) and \e depth-first \e search (DFS)
22.31 -\ref clrs01algorithms.
22.32 +\cite clrs01algorithms.
22.33 */
22.34
22.35 /**
22.36 @@ -318,7 +326,7 @@
22.37 \brief Algorithms for finding shortest paths.
22.38
22.39 This group contains the algorithms for finding shortest paths in digraphs
22.40 -\ref clrs01algorithms.
22.41 +\cite clrs01algorithms.
22.42
22.43 - \ref Dijkstra algorithm for finding shortest paths from a source node
22.44 when all arc lengths are non-negative.
22.45 @@ -340,7 +348,7 @@
22.46 \brief Algorithms for finding minimum cost spanning trees and arborescences.
22.47
22.48 This group contains the algorithms for finding minimum cost spanning
22.49 -trees and arborescences \ref clrs01algorithms.
22.50 +trees and arborescences \cite clrs01algorithms.
22.51 */
22.52
22.53 /**
22.54 @@ -349,7 +357,7 @@
22.55 \brief Algorithms for finding maximum flows.
22.56
22.57 This group contains the algorithms for finding maximum flows and
22.58 -feasible circulations \ref clrs01algorithms, \ref amo93networkflows.
22.59 +feasible circulations \cite clrs01algorithms, \cite amo93networkflows.
22.60
22.61 The \e maximum \e flow \e problem is to find a flow of maximum value between
22.62 a single source and a single target. Formally, there is a \f$G=(V,A)\f$
22.63 @@ -365,13 +373,13 @@
22.64
22.65 LEMON contains several algorithms for solving maximum flow problems:
22.66 - \ref EdmondsKarp Edmonds-Karp algorithm
22.67 - \ref edmondskarp72theoretical.
22.68 + \cite edmondskarp72theoretical.
22.69 - \ref Preflow Goldberg-Tarjan's preflow push-relabel algorithm
22.70 - \ref goldberg88newapproach.
22.71 + \cite goldberg88newapproach.
22.72 - \ref DinitzSleatorTarjan Dinitz's blocking flow algorithm with dynamic trees
22.73 - \ref dinic70algorithm, \ref sleator83dynamic.
22.74 + \cite dinic70algorithm, \cite sleator83dynamic.
22.75 - \ref GoldbergTarjan !Preflow push-relabel algorithm with dynamic trees
22.76 - \ref goldberg88newapproach, \ref sleator83dynamic.
22.77 + \cite goldberg88newapproach, \cite sleator83dynamic.
22.78
22.79 In most cases the \ref Preflow algorithm provides the
22.80 fastest method for computing a maximum flow. All implementations
22.81 @@ -391,25 +399,41 @@
22.82 \brief Algorithms for finding minimum cost flows and circulations.
22.83
22.84 This group contains the algorithms for finding minimum cost flows and
22.85 -circulations \ref amo93networkflows. For more information about this
22.86 -problem and its dual solution, see \ref min_cost_flow
22.87 +circulations \cite amo93networkflows. For more information about this
22.88 +problem and its dual solution, see: \ref min_cost_flow
22.89 "Minimum Cost Flow Problem".
22.90
22.91 LEMON contains several algorithms for this problem.
22.92 - \ref NetworkSimplex Primal Network Simplex algorithm with various
22.93 - pivot strategies \ref dantzig63linearprog, \ref kellyoneill91netsimplex.
22.94 + pivot strategies \cite dantzig63linearprog, \cite kellyoneill91netsimplex.
22.95 - \ref CostScaling Cost Scaling algorithm based on push/augment and
22.96 - relabel operations \ref goldberg90approximation, \ref goldberg97efficient,
22.97 - \ref bunnagel98efficient.
22.98 + relabel operations \cite goldberg90approximation, \cite goldberg97efficient,
22.99 + \cite bunnagel98efficient.
22.100 - \ref CapacityScaling Capacity Scaling algorithm based on the successive
22.101 - shortest path method \ref edmondskarp72theoretical.
22.102 + shortest path method \cite edmondskarp72theoretical.
22.103 - \ref CycleCanceling Cycle-Canceling algorithms, two of which are
22.104 - strongly polynomial \ref klein67primal, \ref goldberg89cyclecanceling.
22.105 + strongly polynomial \cite klein67primal, \cite goldberg89cyclecanceling.
22.106
22.107 -In general NetworkSimplex is the most efficient implementation,
22.108 -but in special cases other algorithms could be faster.
22.109 +In general, \ref NetworkSimplex and \ref CostScaling are the most efficient
22.110 +implementations.
22.111 +\ref NetworkSimplex is usually the fastest on relatively small graphs (up to
22.112 +several thousands of nodes) and on dense graphs, while \ref CostScaling is
22.113 +typically more efficient on large graphs (e.g. hundreds of thousands of
22.114 +nodes or above), especially if they are sparse.
22.115 +However, other algorithms could be faster in special cases.
22.116 For example, if the total supply and/or capacities are rather small,
22.117 -CapacityScaling is usually the fastest algorithm (without effective scaling).
22.118 +\ref CapacityScaling is usually the fastest algorithm
22.119 +(without effective scaling).
22.120 +
22.121 +These classes are intended to be used with integer-valued input data
22.122 +(capacities, supply values, and costs), except for \ref CapacityScaling,
22.123 +which is capable of handling real-valued arc costs (other numerical
22.124 +data are required to be integer).
22.125 +
22.126 +For more details about these implementations and for a comprehensive
22.127 +experimental study, see the paper \cite KiralyKovacs12MCF.
22.128 +It also compares these codes to other publicly available
22.129 +minimum cost flow solvers.
22.130 */
22.131
22.132 /**
22.133 @@ -448,7 +472,7 @@
22.134 \brief Algorithms for finding minimum mean cycles.
22.135
22.136 This group contains the algorithms for finding minimum mean cycles
22.137 -\ref clrs01algorithms, \ref amo93networkflows.
22.138 +\cite amo93networkflows, \cite karp78characterization.
22.139
22.140 The \e minimum \e mean \e cycle \e problem is to find a directed cycle
22.141 of minimum mean length (cost) in a digraph.
22.142 @@ -464,19 +488,17 @@
22.143 function.
22.144
22.145 LEMON contains three algorithms for solving the minimum mean cycle problem:
22.146 -- \ref KarpMmc Karp's original algorithm \ref amo93networkflows,
22.147 - \ref dasdan98minmeancycle.
22.148 +- \ref KarpMmc Karp's original algorithm \cite karp78characterization.
22.149 - \ref HartmannOrlinMmc Hartmann-Orlin's algorithm, which is an improved
22.150 - version of Karp's algorithm \ref dasdan98minmeancycle.
22.151 + version of Karp's algorithm \cite hartmann93finding.
22.152 - \ref HowardMmc Howard's policy iteration algorithm
22.153 - \ref dasdan98minmeancycle.
22.154 + \cite dasdan98minmeancycle, \cite dasdan04experimental.
22.155
22.156 -In practice, the \ref HowardMmc "Howard" algorithm proved to be by far the
22.157 +In practice, the \ref HowardMmc "Howard" algorithm turned out to be by far the
22.158 most efficient one, though the best known theoretical bound on its running
22.159 time is exponential.
22.160 Both \ref KarpMmc "Karp" and \ref HartmannOrlinMmc "Hartmann-Orlin" algorithms
22.161 -run in time O(ne) and use space O(n<sup>2</sup>+e), but the latter one is
22.162 -typically faster due to the applied early termination scheme.
22.163 +run in time O(nm) and use space O(n<sup>2</sup>+m).
22.164 */
22.165
22.166 /**
22.167 @@ -539,7 +561,7 @@
22.168 */
22.169
22.170 /**
22.171 -@defgroup planar Planarity Embedding and Drawing
22.172 +@defgroup planar Planar Embedding and Drawing
22.173 @ingroup algs
22.174 \brief Algorithms for planarity checking, embedding and drawing
22.175
22.176 @@ -551,12 +573,52 @@
22.177 */
22.178
22.179 /**
22.180 -@defgroup approx Approximation Algorithms
22.181 +@defgroup tsp Traveling Salesman Problem
22.182 +@ingroup algs
22.183 +\brief Algorithms for the symmetric traveling salesman problem
22.184 +
22.185 +This group contains basic heuristic algorithms for the the symmetric
22.186 +\e traveling \e salesman \e problem (TSP).
22.187 +Given an \ref FullGraph "undirected full graph" with a cost map on its edges,
22.188 +the problem is to find a shortest possible tour that visits each node exactly
22.189 +once (i.e. the minimum cost Hamiltonian cycle).
22.190 +
22.191 +These TSP algorithms are intended to be used with a \e metric \e cost
22.192 +\e function, i.e. the edge costs should satisfy the triangle inequality.
22.193 +Otherwise the algorithms could yield worse results.
22.194 +
22.195 +LEMON provides five well-known heuristics for solving symmetric TSP:
22.196 + - \ref NearestNeighborTsp Neareast neighbor algorithm
22.197 + - \ref GreedyTsp Greedy algorithm
22.198 + - \ref InsertionTsp Insertion heuristic (with four selection methods)
22.199 + - \ref ChristofidesTsp Christofides algorithm
22.200 + - \ref Opt2Tsp 2-opt algorithm
22.201 +
22.202 +\ref NearestNeighborTsp, \ref GreedyTsp, and \ref InsertionTsp are the fastest
22.203 +solution methods. Furthermore, \ref InsertionTsp is usually quite effective.
22.204 +
22.205 +\ref ChristofidesTsp is somewhat slower, but it has the best guaranteed
22.206 +approximation factor: 3/2.
22.207 +
22.208 +\ref Opt2Tsp usually provides the best results in practice, but
22.209 +it is the slowest method. It can also be used to improve given tours,
22.210 +for example, the results of other algorithms.
22.211 +
22.212 +\image html tsp.png
22.213 +\image latex tsp.eps "Traveling salesman problem" width=\textwidth
22.214 +*/
22.215 +
22.216 +/**
22.217 +@defgroup approx_algs Approximation Algorithms
22.218 @ingroup algs
22.219 \brief Approximation algorithms.
22.220
22.221 This group contains the approximation and heuristic algorithms
22.222 implemented in LEMON.
22.223 +
22.224 +<b>Maximum Clique Problem</b>
22.225 + - \ref GrossoLocatelliPullanMc An efficient heuristic algorithm of
22.226 + Grosso, Locatelli, and Pullan.
22.227 */
22.228
22.229 /**
22.230 @@ -586,8 +648,8 @@
22.231 Various LP solvers could be used in the same manner with this
22.232 high-level interface.
22.233
22.234 -The currently supported solvers are \ref glpk, \ref clp, \ref cbc,
22.235 -\ref cplex, \ref soplex.
22.236 +The currently supported solvers are \cite glpk, \cite clp, \cite cbc,
22.237 +\cite cplex, \cite soplex.
22.238 */
22.239
22.240 /**
22.241 @@ -674,6 +736,8 @@
22.242
22.243 This group contains general \c EPS drawing methods and special
22.244 graph exporting tools.
22.245 +
22.246 +\image html graph_to_eps.png
22.247 */
22.248
22.249 /**
23.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
23.2 +++ b/doc/images/adaptors1.eps Wed Oct 17 19:14:07 2018 +0200
23.3 @@ -0,0 +1,303 @@
23.4 +%!PS-Adobe-2.0 EPSF-2.0
23.5 +%%Title: adaptors1.fig
23.6 +%%Creator: fig2dev Version 3.2 Patchlevel 5
23.7 +%%CreationDate: Sun Feb 21 18:51:21 2010
23.8 +%%For: Peter@KOVACSPETER (Péter,U-KOVACSPETER\Peter,S-1-5-21-1774138250-1299389707-1938712334-1001)
23.9 +%%BoundingBox: 0 0 787 372
23.10 +%Magnification: 1.0000
23.11 +%%EndComments
23.12 +/$F2psDict 200 dict def
23.13 +$F2psDict begin
23.14 +$F2psDict /mtrx matrix put
23.15 +/col-1 {0 setgray} bind def
23.16 +/col0 {0.000 0.000 0.000 srgb} bind def
23.17 +/col1 {0.000 0.000 1.000 srgb} bind def
23.18 +/col2 {0.000 1.000 0.000 srgb} bind def
23.19 +/col3 {0.000 1.000 1.000 srgb} bind def
23.20 +/col4 {1.000 0.000 0.000 srgb} bind def
23.21 +/col5 {1.000 0.000 1.000 srgb} bind def
23.22 +/col6 {1.000 1.000 0.000 srgb} bind def
23.23 +/col7 {1.000 1.000 1.000 srgb} bind def
23.24 +/col8 {0.000 0.000 0.560 srgb} bind def
23.25 +/col9 {0.000 0.000 0.690 srgb} bind def
23.26 +/col10 {0.000 0.000 0.820 srgb} bind def
23.27 +/col11 {0.530 0.810 1.000 srgb} bind def
23.28 +/col12 {0.000 0.560 0.000 srgb} bind def
23.29 +/col13 {0.000 0.690 0.000 srgb} bind def
23.30 +/col14 {0.000 0.820 0.000 srgb} bind def
23.31 +/col15 {0.000 0.560 0.560 srgb} bind def
23.32 +/col16 {0.000 0.690 0.690 srgb} bind def
23.33 +/col17 {0.000 0.820 0.820 srgb} bind def
23.34 +/col18 {0.560 0.000 0.000 srgb} bind def
23.35 +/col19 {0.690 0.000 0.000 srgb} bind def
23.36 +/col20 {0.820 0.000 0.000 srgb} bind def
23.37 +/col21 {0.560 0.000 0.560 srgb} bind def
23.38 +/col22 {0.690 0.000 0.690 srgb} bind def
23.39 +/col23 {0.820 0.000 0.820 srgb} bind def
23.40 +/col24 {0.500 0.190 0.000 srgb} bind def
23.41 +/col25 {0.630 0.250 0.000 srgb} bind def
23.42 +/col26 {0.750 0.380 0.000 srgb} bind def
23.43 +/col27 {1.000 0.500 0.500 srgb} bind def
23.44 +/col28 {1.000 0.630 0.630 srgb} bind def
23.45 +/col29 {1.000 0.750 0.750 srgb} bind def
23.46 +/col30 {1.000 0.880 0.880 srgb} bind def
23.47 +/col31 {1.000 0.840 0.000 srgb} bind def
23.48 +
23.49 +end
23.50 +save
23.51 +newpath 0 372 moveto 0 0 lineto 787 0 lineto 787 372 lineto closepath clip newpath
23.52 +-14.2 385.4 translate
23.53 +1 -1 scale
23.54 +
23.55 +/cp {closepath} bind def
23.56 +/ef {eofill} bind def
23.57 +/gr {grestore} bind def
23.58 +/gs {gsave} bind def
23.59 +/sa {save} bind def
23.60 +/rs {restore} bind def
23.61 +/l {lineto} bind def
23.62 +/m {moveto} bind def
23.63 +/rm {rmoveto} bind def
23.64 +/n {newpath} bind def
23.65 +/s {stroke} bind def
23.66 +/sh {show} bind def
23.67 +/slc {setlinecap} bind def
23.68 +/slj {setlinejoin} bind def
23.69 +/slw {setlinewidth} bind def
23.70 +/srgb {setrgbcolor} bind def
23.71 +/rot {rotate} bind def
23.72 +/sc {scale} bind def
23.73 +/sd {setdash} bind def
23.74 +/ff {findfont} bind def
23.75 +/sf {setfont} bind def
23.76 +/scf {scalefont} bind def
23.77 +/sw {stringwidth} bind def
23.78 +/tr {translate} bind def
23.79 +/tnt {dup dup currentrgbcolor
23.80 + 4 -2 roll dup 1 exch sub 3 -1 roll mul add
23.81 + 4 -2 roll dup 1 exch sub 3 -1 roll mul add
23.82 + 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb}
23.83 + bind def
23.84 +/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul
23.85 + 4 -2 roll mul srgb} bind def
23.86 + /DrawEllipse {
23.87 + /endangle exch def
23.88 + /startangle exch def
23.89 + /yrad exch def
23.90 + /xrad exch def
23.91 + /y exch def
23.92 + /x exch def
23.93 + /savematrix mtrx currentmatrix def
23.94 + x y tr xrad yrad sc 0 0 1 startangle endangle arc
23.95 + closepath
23.96 + savematrix setmatrix
23.97 + } def
23.98 +
23.99 +/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def
23.100 +/$F2psEnd {$F2psEnteredState restore end} def
23.101 +
23.102 +$F2psBegin
23.103 +10 setmiterlimit
23.104 +0 slj 0 slc
23.105 + 0.06299 0.06299 sc
23.106 +%
23.107 +% Fig objects follow
23.108 +%
23.109 +%
23.110 +% here starts figure with depth 60
23.111 +% Polyline
23.112 +0 slj
23.113 +0 slc
23.114 +15.000 slw
23.115 +gs clippath
23.116 +6319 5229 m 6442 5564 l 6527 5533 l 6403 5198 l 6403 5198 l 6424 5383 l 6319 5229 l cp
23.117 +eoclip
23.118 +n 5850 3825 m
23.119 + 6480 5535 l gs col0 s gr gr
23.120 +
23.121 +% arrowhead
23.122 +75.000 slw
23.123 +n 6319 5229 m 6424 5383 l 6403 5198 l 6319 5229 l cp gs 0.00 setgray ef gr col0 s
23.124 +% Polyline
23.125 +15.000 slw
23.126 +gs clippath
23.127 +5417 4044 m 5746 3905 l 5711 3822 l 5382 3961 l 5382 3961 l 5566 3933 l 5417 4044 l cp
23.128 +eoclip
23.129 +n 1575 5625 m
23.130 + 5715 3870 l gs col0 s gr gr
23.131 +
23.132 +% arrowhead
23.133 +75.000 slw
23.134 +n 5417 4044 m 5566 3933 l 5382 3961 l 5417 4044 l cp gs 0.00 setgray ef gr col0 s
23.135 +% Polyline
23.136 +15.000 slw
23.137 +gs clippath
23.138 +3897 3780 m 3540 3780 l 3540 3870 l 3897 3870 l 3897 3870 l 3717 3825 l 3897 3780 l cp
23.139 +eoclip
23.140 +n 5625 3825 m
23.141 + 3555 3825 l gs col0 s gr gr
23.142 +
23.143 +% arrowhead
23.144 +75.000 slw
23.145 +n 3897 3780 m 3717 3825 l 3897 3870 l 3897 3780 l cp gs 0.00 setgray ef gr col0 s
23.146 +% Polyline
23.147 +15.000 slw
23.148 +gs clippath
23.149 +3075 4188 m 3327 3936 l 3263 3872 l 3011 4124 l 3011 4124 l 3171 4029 l 3075 4188 l cp
23.150 +eoclip
23.151 +n 1575 5625 m
23.152 + 3285 3915 l gs col0 s gr gr
23.153 +
23.154 +% arrowhead
23.155 +75.000 slw
23.156 +n 3075 4188 m 3171 4029 l 3011 4124 l 3075 4188 l cp gs 0.00 setgray ef gr col0 s
23.157 +% Polyline
23.158 +15.000 slw
23.159 +gs clippath
23.160 +3528 2520 m 3885 2520 l 3885 2430 l 3528 2430 l 3528 2430 l 3708 2475 l 3528 2520 l cp
23.161 +eoclip
23.162 +n 1800 2475 m
23.163 + 3870 2475 l gs col0 s gr gr
23.164 +
23.165 +% arrowhead
23.166 +75.000 slw
23.167 +n 3528 2520 m 3708 2475 l 3528 2430 l 3528 2520 l cp gs 0.00 setgray ef gr col0 s
23.168 +% Polyline
23.169 +15.000 slw
23.170 +gs clippath
23.171 +4304 2156 m 4052 2408 l 4116 2472 l 4368 2220 l 4368 2220 l 4209 2316 l 4304 2156 l cp
23.172 +eoclip
23.173 +n 5850 675 m
23.174 + 4095 2430 l gs col0 s gr gr
23.175 +
23.176 +% arrowhead
23.177 +75.000 slw
23.178 +n 4304 2156 m 4209 2316 l 4368 2220 l 4304 2156 l cp gs 0.00 setgray ef gr col0 s
23.179 +% Polyline
23.180 +15.000 slw
23.181 +gs clippath
23.182 +6319 2079 m 6442 2414 l 6527 2383 l 6403 2048 l 6403 2048 l 6424 2233 l 6319 2079 l cp
23.183 +eoclip
23.184 +n 5850 675 m
23.185 + 6480 2385 l gs col0 s gr gr
23.186 +
23.187 +% arrowhead
23.188 +75.000 slw
23.189 +n 6319 2079 m 6424 2233 l 6403 2048 l 6319 2079 l cp gs 0.00 setgray ef gr col0 s
23.190 +% Polyline
23.191 +15.000 slw
23.192 +gs clippath
23.193 +5417 894 m 5746 755 l 5711 672 l 5382 811 l 5382 811 l 5566 783 l 5417 894 l cp
23.194 +eoclip
23.195 +n 1575 2475 m
23.196 + 5715 720 l gs col0 s gr gr
23.197 +
23.198 +% arrowhead
23.199 +75.000 slw
23.200 +n 5417 894 m 5566 783 l 5382 811 l 5417 894 l cp gs 0.00 setgray ef gr col0 s
23.201 +% Polyline
23.202 +15.000 slw
23.203 +gs clippath
23.204 +3528 5670 m 3885 5670 l 3885 5580 l 3528 5580 l 3528 5580 l 3708 5625 l 3528 5670 l cp
23.205 +eoclip
23.206 +n 1800 5625 m
23.207 + 3870 5625 l gs col0 s gr gr
23.208 +
23.209 +% arrowhead
23.210 +75.000 slw
23.211 +n 3528 5670 m 3708 5625 l 3528 5580 l 3528 5670 l cp gs 0.00 setgray ef gr col0 s
23.212 +% Polyline
23.213 +15.000 slw
23.214 +gs clippath
23.215 +4572 5580 m 4215 5580 l 4215 5670 l 4572 5670 l 4572 5670 l 4392 5625 l 4572 5580 l cp
23.216 +eoclip
23.217 +n 6300 5625 m
23.218 + 4230 5625 l gs col0 s gr gr
23.219 +
23.220 +% arrowhead
23.221 +75.000 slw
23.222 +n 4572 5580 m 4392 5625 l 4572 5670 l 4572 5580 l cp gs 0.00 setgray ef gr col0 s
23.223 +% Polyline
23.224 +15.000 slw
23.225 +gs clippath
23.226 +4304 5306 m 4052 5558 l 4116 5622 l 4368 5370 l 4368 5370 l 4209 5466 l 4304 5306 l cp
23.227 +eoclip
23.228 +n 5850 3825 m
23.229 + 4095 5580 l gs col0 s gr gr
23.230 +
23.231 +% arrowhead
23.232 +75.000 slw
23.233 +n 4304 5306 m 4209 5466 l 4368 5370 l 4304 5306 l cp gs 0.00 setgray ef gr col0 s
23.234 +% here ends figure;
23.235 +%
23.236 +% here starts figure with depth 50
23.237 +% Ellipse
23.238 +15.000 slw
23.239 +n 3375 3825 225 112 0 360 DrawEllipse gs 1.00 setgray ef gr gs col0 s gr
23.240 +
23.241 +% Ellipse
23.242 +n 5850 3825 225 112 0 360 DrawEllipse gs 1.00 setgray ef gr gs col0 s gr
23.243 +
23.244 +% Polyline
23.245 +0 slj
23.246 +0 slc
23.247 +n 247 2947 m 2947 247 l 9697 247 l 6997 2947 l
23.248 + 247 2947 l cp gs col0 s gr
23.249 +% Polyline
23.250 +n 247 6097 m 2947 3397 l 9697 3397 l 6997 6097 l
23.251 + 247 6097 l cp gs col0 s gr
23.252 +% Ellipse
23.253 +n 1575 2475 225 112 0 360 DrawEllipse gs 1.00 setgray ef gr gs col0 s gr
23.254 +
23.255 +% Ellipse
23.256 +n 4050 2475 225 112 0 360 DrawEllipse gs 1.00 setgray ef gr gs col0 s gr
23.257 +
23.258 +% Ellipse
23.259 +n 6525 2475 225 112 0 360 DrawEllipse gs 1.00 setgray ef gr gs col0 s gr
23.260 +
23.261 +% Ellipse
23.262 +n 5850 675 225 112 0 360 DrawEllipse gs 1.00 setgray ef gr gs col0 s gr
23.263 +
23.264 +% Ellipse
23.265 +n 1575 5625 225 112 0 360 DrawEllipse gs 1.00 setgray ef gr gs col0 s gr
23.266 +
23.267 +% Ellipse
23.268 +n 4050 5625 225 112 0 360 DrawEllipse gs 1.00 setgray ef gr gs col0 s gr
23.269 +
23.270 +% Ellipse
23.271 +n 6525 5625 225 112 0 360 DrawEllipse gs 1.00 setgray ef gr gs col0 s gr
23.272 +
23.273 +% here ends figure;
23.274 +%
23.275 +% here starts figure with depth 40
23.276 +/Helvetica ff 480.00 scf sf
23.277 +8280 2610 m
23.278 +gs 1 -1 sc (SubDigraph adaptor) col0 sh gr
23.279 +% Polyline
23.280 +0 slj
23.281 +0 slc
23.282 +7.500 slw
23.283 + [15 45] 45 sd
23.284 +n 4050 2610 m
23.285 + 4050 5625 l gs col0 s gr [] 0 sd
23.286 +% Polyline
23.287 + [15 45] 45 sd
23.288 +n 5850 810 m
23.289 + 5850 3825 l gs col0 s gr [] 0 sd
23.290 +% Polyline
23.291 + [15 45] 45 sd
23.292 +n 6525 2610 m
23.293 + 6525 5625 l gs col0 s gr [] 0 sd
23.294 +/Helvetica ff 480.00 scf sf
23.295 +8280 5760 m
23.296 +gs 1 -1 sc (Original digraph) col0 sh gr
23.297 +% Polyline
23.298 + [15 45] 45 sd
23.299 +n 1575 2610 m
23.300 + 1575 5625 l gs col0 s gr [] 0 sd
23.301 +% here ends figure;
23.302 +$F2psEnd
23.303 +rs
23.304 +showpage
23.305 +%%Trailer
23.306 +%EOF
24.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
24.2 +++ b/doc/images/adaptors2.eps Wed Oct 17 19:14:07 2018 +0200
24.3 @@ -0,0 +1,349 @@
24.4 +%!PS-Adobe-2.0 EPSF-2.0
24.5 +%%Title: adaptors2.fig
24.6 +%%Creator: fig2dev Version 3.2 Patchlevel 5
24.7 +%%CreationDate: Sun Feb 21 18:51:31 2010
24.8 +%%For: Peter@KOVACSPETER (Péter,U-KOVACSPETER\Peter,S-1-5-21-1774138250-1299389707-1938712334-1001)
24.9 +%%BoundingBox: 0 0 787 570
24.10 +%Magnification: 1.0000
24.11 +%%EndComments
24.12 +/$F2psDict 200 dict def
24.13 +$F2psDict begin
24.14 +$F2psDict /mtrx matrix put
24.15 +/col-1 {0 setgray} bind def
24.16 +/col0 {0.000 0.000 0.000 srgb} bind def
24.17 +/col1 {0.000 0.000 1.000 srgb} bind def
24.18 +/col2 {0.000 1.000 0.000 srgb} bind def
24.19 +/col3 {0.000 1.000 1.000 srgb} bind def
24.20 +/col4 {1.000 0.000 0.000 srgb} bind def
24.21 +/col5 {1.000 0.000 1.000 srgb} bind def
24.22 +/col6 {1.000 1.000 0.000 srgb} bind def
24.23 +/col7 {1.000 1.000 1.000 srgb} bind def
24.24 +/col8 {0.000 0.000 0.560 srgb} bind def
24.25 +/col9 {0.000 0.000 0.690 srgb} bind def
24.26 +/col10 {0.000 0.000 0.820 srgb} bind def
24.27 +/col11 {0.530 0.810 1.000 srgb} bind def
24.28 +/col12 {0.000 0.560 0.000 srgb} bind def
24.29 +/col13 {0.000 0.690 0.000 srgb} bind def
24.30 +/col14 {0.000 0.820 0.000 srgb} bind def
24.31 +/col15 {0.000 0.560 0.560 srgb} bind def
24.32 +/col16 {0.000 0.690 0.690 srgb} bind def
24.33 +/col17 {0.000 0.820 0.820 srgb} bind def
24.34 +/col18 {0.560 0.000 0.000 srgb} bind def
24.35 +/col19 {0.690 0.000 0.000 srgb} bind def
24.36 +/col20 {0.820 0.000 0.000 srgb} bind def
24.37 +/col21 {0.560 0.000 0.560 srgb} bind def
24.38 +/col22 {0.690 0.000 0.690 srgb} bind def
24.39 +/col23 {0.820 0.000 0.820 srgb} bind def
24.40 +/col24 {0.500 0.190 0.000 srgb} bind def
24.41 +/col25 {0.630 0.250 0.000 srgb} bind def
24.42 +/col26 {0.750 0.380 0.000 srgb} bind def
24.43 +/col27 {1.000 0.500 0.500 srgb} bind def
24.44 +/col28 {1.000 0.630 0.630 srgb} bind def
24.45 +/col29 {1.000 0.750 0.750 srgb} bind def
24.46 +/col30 {1.000 0.880 0.880 srgb} bind def
24.47 +/col31 {1.000 0.840 0.000 srgb} bind def
24.48 +
24.49 +end
24.50 +save
24.51 +newpath 0 570 moveto 0 0 lineto 787 0 lineto 787 570 lineto closepath clip newpath
24.52 +-14.2 583.9 translate
24.53 +1 -1 scale
24.54 +
24.55 +/cp {closepath} bind def
24.56 +/ef {eofill} bind def
24.57 +/gr {grestore} bind def
24.58 +/gs {gsave} bind def
24.59 +/sa {save} bind def
24.60 +/rs {restore} bind def
24.61 +/l {lineto} bind def
24.62 +/m {moveto} bind def
24.63 +/rm {rmoveto} bind def
24.64 +/n {newpath} bind def
24.65 +/s {stroke} bind def
24.66 +/sh {show} bind def
24.67 +/slc {setlinecap} bind def
24.68 +/slj {setlinejoin} bind def
24.69 +/slw {setlinewidth} bind def
24.70 +/srgb {setrgbcolor} bind def
24.71 +/rot {rotate} bind def
24.72 +/sc {scale} bind def
24.73 +/sd {setdash} bind def
24.74 +/ff {findfont} bind def
24.75 +/sf {setfont} bind def
24.76 +/scf {scalefont} bind def
24.77 +/sw {stringwidth} bind def
24.78 +/tr {translate} bind def
24.79 +/tnt {dup dup currentrgbcolor
24.80 + 4 -2 roll dup 1 exch sub 3 -1 roll mul add
24.81 + 4 -2 roll dup 1 exch sub 3 -1 roll mul add
24.82 + 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb}
24.83 + bind def
24.84 +/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul
24.85 + 4 -2 roll mul srgb} bind def
24.86 + /DrawEllipse {
24.87 + /endangle exch def
24.88 + /startangle exch def
24.89 + /yrad exch def
24.90 + /xrad exch def
24.91 + /y exch def
24.92 + /x exch def
24.93 + /savematrix mtrx currentmatrix def
24.94 + x y tr xrad yrad sc 0 0 1 startangle endangle arc
24.95 + closepath
24.96 + savematrix setmatrix
24.97 + } def
24.98 +
24.99 +/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def
24.100 +/$F2psEnd {$F2psEnteredState restore end} def
24.101 +
24.102 +$F2psBegin
24.103 +10 setmiterlimit
24.104 +0 slj 0 slc
24.105 + 0.06299 0.06299 sc
24.106 +%
24.107 +% Fig objects follow
24.108 +%
24.109 +%
24.110 +% here starts figure with depth 60
24.111 +% Polyline
24.112 +0 slj
24.113 +0 slc
24.114 +15.000 slw
24.115 +gs clippath
24.116 +5417 4044 m 5746 3905 l 5711 3822 l 5382 3961 l 5382 3961 l 5566 3933 l 5417 4044 l cp
24.117 +eoclip
24.118 +n 1575 5625 m
24.119 + 5715 3870 l gs col0 s gr gr
24.120 +
24.121 +% arrowhead
24.122 +75.000 slw
24.123 +n 5417 4044 m 5566 3933 l 5382 3961 l 5417 4044 l cp gs 0.00 setgray ef gr col0 s
24.124 +% Polyline
24.125 +15.000 slw
24.126 +gs clippath
24.127 +5417 7194 m 5746 7055 l 5711 6972 l 5382 7111 l 5382 7111 l 5566 7083 l 5417 7194 l cp
24.128 +eoclip
24.129 +n 1575 8775 m
24.130 + 5715 7020 l gs col0 s gr gr
24.131 +
24.132 +% arrowhead
24.133 +75.000 slw
24.134 +n 5417 7194 m 5566 7083 l 5382 7111 l 5417 7194 l cp gs 0.00 setgray ef gr col0 s
24.135 +% Polyline
24.136 +15.000 slw
24.137 +gs clippath
24.138 +6319 8379 m 6442 8714 l 6527 8683 l 6403 8348 l 6403 8348 l 6424 8533 l 6319 8379 l cp
24.139 +eoclip
24.140 +n 5850 6975 m
24.141 + 6480 8685 l gs col0 s gr gr
24.142 +
24.143 +% arrowhead
24.144 +75.000 slw
24.145 +n 6319 8379 m 6424 8533 l 6403 8348 l 6319 8379 l cp gs 0.00 setgray ef gr col0 s
24.146 +% Polyline
24.147 +15.000 slw
24.148 +gs clippath
24.149 +4304 8456 m 4052 8708 l 4116 8772 l 4368 8520 l 4368 8520 l 4209 8616 l 4304 8456 l cp
24.150 +eoclip
24.151 +n 5850 6975 m
24.152 + 4095 8730 l gs col0 s gr gr
24.153 +
24.154 +% arrowhead
24.155 +75.000 slw
24.156 +n 4304 8456 m 4209 8616 l 4368 8520 l 4304 8456 l cp gs 0.00 setgray ef gr col0 s
24.157 +% Polyline
24.158 +15.000 slw
24.159 +gs clippath
24.160 +4572 8730 m 4215 8730 l 4215 8820 l 4572 8820 l 4572 8820 l 4392 8775 l 4572 8730 l cp
24.161 +eoclip
24.162 +n 6300 8775 m
24.163 + 4230 8775 l gs col0 s gr gr
24.164 +
24.165 +% arrowhead
24.166 +75.000 slw
24.167 +n 4572 8730 m 4392 8775 l 4572 8820 l 4572 8730 l cp gs 0.00 setgray ef gr col0 s
24.168 +% Polyline
24.169 +15.000 slw
24.170 +gs clippath
24.171 +3528 8820 m 3885 8820 l 3885 8730 l 3528 8730 l 3528 8730 l 3708 8775 l 3528 8820 l cp
24.172 +eoclip
24.173 +n 1800 8775 m
24.174 + 3870 8775 l gs col0 s gr gr
24.175 +
24.176 +% arrowhead
24.177 +75.000 slw
24.178 +n 3528 8820 m 3708 8775 l 3528 8730 l 3528 8820 l cp gs 0.00 setgray ef gr col0 s
24.179 +% Polyline
24.180 +15.000 slw
24.181 +n 1800 2475 m
24.182 + 3870 2475 l gs col0 s gr
24.183 +% Polyline
24.184 +n 1575 2475 m
24.185 + 5715 720 l gs col0 s gr
24.186 +% Polyline
24.187 +n 5850 675 m
24.188 + 4095 2430 l gs col0 s gr
24.189 +% Polyline
24.190 +n 5850 675 m
24.191 + 6480 2385 l gs col0 s gr
24.192 +% Polyline
24.193 +gs clippath
24.194 +3075 7338 m 3327 7086 l 3263 7022 l 3011 7274 l 3011 7274 l 3171 7179 l 3075 7338 l cp
24.195 +eoclip
24.196 +n 1575 8775 m
24.197 + 3285 7065 l gs col0 s gr gr
24.198 +
24.199 +% arrowhead
24.200 +75.000 slw
24.201 +n 3075 7338 m 3171 7179 l 3011 7274 l 3075 7338 l cp gs 0.00 setgray ef gr col0 s
24.202 +% Polyline
24.203 +15.000 slw
24.204 +gs clippath
24.205 +3528 5670 m 3885 5670 l 3885 5580 l 3528 5580 l 3528 5580 l 3708 5625 l 3528 5670 l cp
24.206 +eoclip
24.207 +n 1800 5625 m
24.208 + 3870 5625 l gs col0 s gr gr
24.209 +
24.210 +% arrowhead
24.211 +75.000 slw
24.212 +n 3528 5670 m 3708 5625 l 3528 5580 l 3528 5670 l cp gs 0.00 setgray ef gr col0 s
24.213 +% Polyline
24.214 +15.000 slw
24.215 +gs clippath
24.216 +4304 5306 m 4052 5558 l 4116 5622 l 4368 5370 l 4368 5370 l 4209 5466 l 4304 5306 l cp
24.217 +eoclip
24.218 +n 5850 3825 m
24.219 + 4095 5580 l gs col0 s gr gr
24.220 +
24.221 +% arrowhead
24.222 +75.000 slw
24.223 +n 4304 5306 m 4209 5466 l 4368 5370 l 4304 5306 l cp gs 0.00 setgray ef gr col0 s
24.224 +% Polyline
24.225 +15.000 slw
24.226 +gs clippath
24.227 +6319 5229 m 6442 5564 l 6527 5533 l 6403 5198 l 6403 5198 l 6424 5383 l 6319 5229 l cp
24.228 +eoclip
24.229 +n 5850 3825 m
24.230 + 6480 5535 l gs col0 s gr gr
24.231 +
24.232 +% arrowhead
24.233 +75.000 slw
24.234 +n 6319 5229 m 6424 5383 l 6403 5198 l 6319 5229 l cp gs 0.00 setgray ef gr col0 s
24.235 +% Polyline
24.236 +15.000 slw
24.237 +gs clippath
24.238 +3897 6930 m 3540 6930 l 3540 7020 l 3897 7020 l 3897 7020 l 3717 6975 l 3897 6930 l cp
24.239 +eoclip
24.240 +n 5625 6975 m
24.241 + 3555 6975 l gs col0 s gr gr
24.242 +
24.243 +% arrowhead
24.244 +75.000 slw
24.245 +n 3897 6930 m 3717 6975 l 3897 7020 l 3897 6930 l cp gs 0.00 setgray ef gr col0 s
24.246 +% here ends figure;
24.247 +%
24.248 +% here starts figure with depth 50
24.249 +% Polyline
24.250 +0 slj
24.251 +0 slc
24.252 +15.000 slw
24.253 +n 247 6097 m 2947 3397 l 9697 3397 l 6997 6097 l
24.254 + 247 6097 l cp gs col0 s gr
24.255 +% Polyline
24.256 +n 247 9247 m 2947 6547 l 9697 6547 l 6997 9247 l
24.257 + 247 9247 l cp gs col0 s gr
24.258 +% Ellipse
24.259 +n 4050 2475 225 112 0 360 DrawEllipse gs 1.00 setgray ef gr gs col0 s gr
24.260 +
24.261 +% Ellipse
24.262 +n 6525 2475 225 112 0 360 DrawEllipse gs 1.00 setgray ef gr gs col0 s gr
24.263 +
24.264 +% Ellipse
24.265 +n 1575 2475 225 112 0 360 DrawEllipse gs 1.00 setgray ef gr gs col0 s gr
24.266 +
24.267 +% Ellipse
24.268 +n 5850 675 225 112 0 360 DrawEllipse gs 1.00 setgray ef gr gs col0 s gr
24.269 +
24.270 +% Ellipse
24.271 +n 1575 5625 225 112 0 360 DrawEllipse gs 1.00 setgray ef gr gs col0 s gr
24.272 +
24.273 +% Ellipse
24.274 +n 4050 5625 225 112 0 360 DrawEllipse gs 1.00 setgray ef gr gs col0 s gr
24.275 +
24.276 +% Ellipse
24.277 +n 6525 5625 225 112 0 360 DrawEllipse gs 1.00 setgray ef gr gs col0 s gr
24.278 +
24.279 +% Ellipse
24.280 +n 5850 3825 225 112 0 360 DrawEllipse gs 1.00 setgray ef gr gs col0 s gr
24.281 +
24.282 +% Ellipse
24.283 +n 1575 8775 225 112 0 360 DrawEllipse gs 1.00 setgray ef gr gs col0 s gr
24.284 +
24.285 +% Ellipse
24.286 +n 4050 8775 225 112 0 360 DrawEllipse gs 1.00 setgray ef gr gs col0 s gr
24.287 +
24.288 +% Ellipse
24.289 +n 3375 6975 225 112 0 360 DrawEllipse gs 1.00 setgray ef gr gs col0 s gr
24.290 +
24.291 +% Ellipse
24.292 +n 6525 8775 225 112 0 360 DrawEllipse gs 1.00 setgray ef gr gs col0 s gr
24.293 +
24.294 +% Ellipse
24.295 +n 5850 6975 225 112 0 360 DrawEllipse gs 1.00 setgray ef gr gs col0 s gr
24.296 +
24.297 +% Polyline
24.298 +n 247 2947 m 2947 247 l 9697 247 l 6997 2947 l
24.299 + 247 2947 l cp gs col0 s gr
24.300 +% here ends figure;
24.301 +%
24.302 +% here starts figure with depth 40
24.303 +/Helvetica ff 480.00 scf sf
24.304 +8280 8910 m
24.305 +gs 1 -1 sc (Original digraph) col0 sh gr
24.306 +% Polyline
24.307 +0 slj
24.308 +0 slc
24.309 +7.500 slw
24.310 + [15 45] 45 sd
24.311 +n 5850 810 m
24.312 + 5850 3825 l gs col0 s gr [] 0 sd
24.313 +% Polyline
24.314 + [15 45] 45 sd
24.315 +n 6525 2610 m
24.316 + 6525 5625 l gs col0 s gr [] 0 sd
24.317 +% Polyline
24.318 + [15 45] 45 sd
24.319 +n 4050 2610 m
24.320 + 4050 5625 l gs col0 s gr [] 0 sd
24.321 +% Polyline
24.322 + [15 45] 45 sd
24.323 +n 1575 2610 m
24.324 + 1575 5625 l gs col0 s gr [] 0 sd
24.325 +% Polyline
24.326 + [15 45] 45 sd
24.327 +n 5850 3960 m
24.328 + 5850 6975 l gs col0 s gr [] 0 sd
24.329 +% Polyline
24.330 + [15 45] 45 sd
24.331 +n 6525 5760 m
24.332 + 6525 8775 l gs col0 s gr [] 0 sd
24.333 +% Polyline
24.334 + [15 45] 45 sd
24.335 +n 4050 5760 m
24.336 + 4050 8775 l gs col0 s gr [] 0 sd
24.337 +/Helvetica ff 480.00 scf sf
24.338 +8280 2610 m
24.339 +gs 1 -1 sc (Undirector adaptor) col0 sh gr
24.340 +/Helvetica ff 480.00 scf sf
24.341 +8280 5760 m
24.342 +gs 1 -1 sc (SubDigraph adaptor) col0 sh gr
24.343 +% Polyline
24.344 + [15 45] 45 sd
24.345 +n 1575 5760 m
24.346 + 1575 8775 l gs col0 s gr [] 0 sd
24.347 +% here ends figure;
24.348 +$F2psEnd
24.349 +rs
24.350 +showpage
24.351 +%%Trailer
24.352 +%EOF
25.1 --- a/doc/images/bipartite_partitions.eps Mon Jul 16 16:21:40 2018 +0200
25.2 +++ b/doc/images/bipartite_partitions.eps Wed Oct 17 19:14:07 2018 +0200
25.3 @@ -1,6 +1,6 @@
25.4 %!PS-Adobe-2.0 EPSF-2.0
25.5 %%Creator: LEMON, graphToEps()
25.6 -%%CreationDate: Tue Nov 15 16:51:43 2005
25.7 +%%CreationDate: Fri Mar 8 00:18:43 2013
25.8 %%BoundingBox: 0 0 842 596
25.9 %%EndComments
25.10 /lb { setlinewidth setrgbcolor newpath moveto
25.11 @@ -53,62 +53,62 @@
25.12 1197.47 -613.138 translate
25.13 %Edges:
25.14 gsave
25.15 -513.857 -446.322 296.569 -487.43 79.2808 -528.539 0 0 0 2 lb
25.16 -513.857 -446.322 575.52 -315.655 637.183 -184.989 0 0 0 2 lb
25.17 -393.468 566.711 494.771 434.577 596.074 302.442 0 0 0 2 lb
25.18 -393.468 566.711 155.625 579.925 -82.2171 593.138 0 0 0 2 lb
25.19 -393.468 566.711 251.056 450.726 108.644 334.741 0 0 0 2 lb
25.20 -869.153 52.8539 732.613 177.648 596.074 302.442 0 0 0 2 lb
25.21 -869.153 52.8539 753.168 -66.0676 637.183 -184.989 0 0 0 2 lb
25.22 --82.2171 593.138 -91.0261 346.487 -99.8351 99.8351 0 0 0 2 lb
25.23 --663.61 546.157 -753.168 394.936 -842.726 243.715 0 0 0 2 lb
25.24 --663.61 546.157 -574.052 437.513 -484.494 328.869 0 0 0 2 lb
25.25 --1077.63 161.498 -960.178 202.606 -842.726 243.715 0 0 0 2 lb
25.26 --1077.63 161.498 -968.987 66.0674 -860.344 -29.3633 0 0 0 2 lb
25.27 --1177.47 -234.906 -1029.18 -381.722 -880.898 -528.539 0 0 0 2 lb
25.28 --1177.47 -234.906 -1018.91 -132.135 -860.344 -29.3633 0 0 0 2 lb
25.29 --880.898 -528.539 -744.359 -387.595 -607.82 -246.651 0 0 0 2 lb
25.30 --499.175 -499.175 -355.295 -475.685 -211.415 -452.194 0 0 0 2 lb
25.31 --499.175 -499.175 -553.498 -372.913 -607.82 -246.651 0 0 0 2 lb
25.32 --499.175 -499.175 -386.587 -315.087 -274 -131 0 0 0 2 lb
25.33 -79.2808 -528.539 -66.0671 -490.366 -211.415 -452.194 0 0 0 2 lb
25.34 -637.183 -184.989 421.363 -253.993 205.543 -322.996 0 0 0 2 lb
25.35 -205.543 -322.996 162.966 -226.097 120.389 -129.198 0 0 0 2 lb
25.36 -399.34 88.0898 259.865 -20.5541 120.389 -129.198 0 0 0 2 lb
25.37 -399.34 88.0898 253.992 211.415 108.644 334.741 0 0 0 2 lb
25.38 --842.726 243.715 -471.281 171.775 -99.8351 99.8351 0 0 0 2 lb
25.39 --842.726 243.715 -558.363 56.3575 -274 -131 0 0 0 2 lb
25.40 --860.344 -29.3633 -734.082 -138.007 -607.82 -246.651 0 0 0 2 lb
25.41 --211.415 -452.194 -45.513 -290.696 120.389 -129.198 0 0 0 2 lb
25.42 --99.8351 99.8351 4.40445 217.288 108.644 334.741 0 0 0 2 lb
25.43 --99.8351 99.8351 -292.165 214.352 -484.494 328.869 0 0 0 2 lb
25.44 -120.389 -129.198 -76.8055 -130.099 -274 -131 0 0 0 2 lb
25.45 +513.857 -446.322 296.569 -487.43 79.2808 -528.539 0 0 0 7.00153 lb
25.46 +513.857 -446.322 575.52 -315.656 637.183 -184.989 0 0 0 7.00153 lb
25.47 +393.468 566.711 494.771 434.577 596.074 302.442 0 0 0 7.00153 lb
25.48 +393.468 566.711 155.625 579.925 -82.2171 593.138 0 0 0 7.00153 lb
25.49 +393.468 566.711 251.056 450.726 108.644 334.741 0 0 0 7.00153 lb
25.50 +869.153 52.8539 732.613 177.648 596.074 302.442 0 0 0 7.00153 lb
25.51 +869.153 52.8539 753.168 -66.0676 637.183 -184.989 0 0 0 7.00153 lb
25.52 +-82.2171 593.138 -91.0261 346.487 -99.8351 99.8351 0 0 0 7.00153 lb
25.53 +-663.61 546.157 -753.168 394.936 -842.726 243.715 0 0 0 7.00153 lb
25.54 +-663.61 546.157 -574.052 437.513 -484.494 328.869 0 0 0 7.00153 lb
25.55 +-1077.63 161.498 -960.178 202.606 -842.726 243.715 0 0 0 7.00153 lb
25.56 +-1077.63 161.498 -968.987 66.0674 -860.344 -29.3633 0 0 0 7.00153 lb
25.57 +-1177.47 -234.906 -1029.18 -381.722 -880.898 -528.539 0 0 0 7.00153 lb
25.58 +-1177.47 -234.906 -1018.91 -132.135 -860.344 -29.3633 0 0 0 7.00153 lb
25.59 +-880.898 -528.539 -744.359 -387.595 -607.82 -246.651 0 0 0 7.00153 lb
25.60 +-499.175 -499.175 -355.295 -475.685 -211.415 -452.194 0 0 0 7.00153 lb
25.61 +-499.175 -499.175 -553.498 -372.913 -607.82 -246.651 0 0 0 7.00153 lb
25.62 +-499.175 -499.175 -386.587 -315.087 -274 -131 0 0 0 7.00153 lb
25.63 +79.2808 -528.539 -66.0671 -490.366 -211.415 -452.194 0 0 0 7.00153 lb
25.64 +637.183 -184.989 421.363 -253.993 205.543 -322.996 0 0 0 7.00153 lb
25.65 +205.543 -322.996 162.966 -226.097 120.389 -129.198 0 0 0 7.00153 lb
25.66 +399.34 88.0898 259.865 -20.5541 120.389 -129.198 0 0 0 7.00153 lb
25.67 +399.34 88.0898 253.992 211.415 108.644 334.741 0 0 0 7.00153 lb
25.68 +-842.726 243.715 -471.281 171.775 -99.8351 99.8351 0 0 0 7.00153 lb
25.69 +-842.726 243.715 -558.363 56.3575 -274 -131 0 0 0 7.00153 lb
25.70 +-860.344 -29.3633 -734.082 -138.007 -607.82 -246.651 0 0 0 7.00153 lb
25.71 +-211.415 -452.194 -45.513 -290.696 120.389 -129.198 0 0 0 7.00153 lb
25.72 +-99.8351 99.8351 4.40445 217.288 108.644 334.741 0 0 0 7.00153 lb
25.73 +-99.8351 99.8351 -292.165 214.352 -484.494 328.869 0 0 0 7.00153 lb
25.74 +120.389 -129.198 -76.8055 -130.099 -274 -131 0 0 0 7.00153 lb
25.75 grestore
25.76 %Nodes:
25.77 gsave
25.78 --274 -131 20 1 0 0 nc
25.79 --607.82 -246.651 20 1 0 0 nc
25.80 --484.494 328.869 20 0 0 1 nc
25.81 -108.644 334.741 20 0 0 1 nc
25.82 -120.389 -129.198 20 0 0 1 nc
25.83 --99.8351 99.8351 20 1 0 0 nc
25.84 --211.415 -452.194 20 1 0 0 nc
25.85 --860.344 -29.3633 20 0 0 1 nc
25.86 --842.726 243.715 20 0 0 1 nc
25.87 -399.34 88.0898 20 1 0 0 nc
25.88 -205.543 -322.996 20 1 0 0 nc
25.89 -637.183 -184.989 20 0 0 1 nc
25.90 -79.2808 -528.539 20 0 0 1 nc
25.91 --499.175 -499.175 20 0 0 1 nc
25.92 --880.898 -528.539 20 0 0 1 nc
25.93 --1177.47 -234.906 20 1 0 0 nc
25.94 --1077.63 161.498 20 1 0 0 nc
25.95 --663.61 546.157 20 1 0 0 nc
25.96 --82.2171 593.138 20 0 0 1 nc
25.97 -596.074 302.442 20 0 0 1 nc
25.98 -869.153 52.8539 20 1 0 0 nc
25.99 -393.468 566.711 20 1 0 0 nc
25.100 -513.857 -446.322 20 1 0 0 nc
25.101 +-274 -131 23.3384 1 0 0 nc
25.102 +-607.82 -246.651 23.3384 1 0 0 nc
25.103 +-484.494 328.869 23.3384 0 0 1 nc
25.104 +108.644 334.741 23.3384 0 0 1 nc
25.105 +120.389 -129.198 23.3384 0 0 1 nc
25.106 +-99.8351 99.8351 23.3384 1 0 0 nc
25.107 +-211.415 -452.194 23.3384 1 0 0 nc
25.108 +-860.344 -29.3633 23.3384 0 0 1 nc
25.109 +-842.726 243.715 23.3384 0 0 1 nc
25.110 +399.34 88.0898 23.3384 1 0 0 nc
25.111 +205.543 -322.996 23.3384 1 0 0 nc
25.112 +637.183 -184.989 23.3384 0 0 1 nc
25.113 +79.2808 -528.539 23.3384 0 0 1 nc
25.114 +-499.175 -499.175 23.3384 0 0 1 nc
25.115 +-880.898 -528.539 23.3384 0 0 1 nc
25.116 +-1177.47 -234.906 23.3384 1 0 0 nc
25.117 +-1077.63 161.498 23.3384 1 0 0 nc
25.118 +-663.61 546.157 23.3384 1 0 0 nc
25.119 +-82.2171 593.138 23.3384 0 0 1 nc
25.120 +596.074 302.442 23.3384 0 0 1 nc
25.121 +869.153 52.8539 23.3384 1 0 0 nc
25.122 +393.468 566.711 23.3384 1 0 0 nc
25.123 +513.857 -446.322 23.3384 1 0 0 nc
25.124 grestore
25.125 grestore
25.126 showpage
26.1 --- a/doc/images/connected_components.eps Mon Jul 16 16:21:40 2018 +0200
26.2 +++ b/doc/images/connected_components.eps Wed Oct 17 19:14:07 2018 +0200
26.3 @@ -1,6 +1,6 @@
26.4 %!PS-Adobe-2.0 EPSF-2.0
26.5 %%Creator: LEMON, graphToEps()
26.6 -%%CreationDate: Fri Nov 4 13:47:12 2005
26.7 +%%CreationDate: Fri Mar 8 00:18:43 2013
26.8 %%BoundingBox: 0 0 842 596
26.9 %%EndComments
26.10 /lb { setlinewidth setrgbcolor newpath moveto
26.11 @@ -53,107 +53,107 @@
26.12 860.856 -588.349 translate
26.13 %Edges:
26.14 gsave
26.15 -574.035 177.301 622.149 225.748 670.264 274.195 0 0 0 2 lb
26.16 -694.579 115.483 682.421 194.839 670.264 274.195 0 0 0 2 lb
26.17 -280.402 10.3938 246.402 -6.60595 212.403 -23.6057 0 0 0 2 lb
26.18 -280.402 10.3938 283.493 -18.9695 286.584 -48.3327 0 0 0 2 lb
26.19 -212.403 -23.6057 249.493 -35.9692 286.584 -48.3327 0 0 0 2 lb
26.20 -286.584 -48.3327 326.765 -79.2414 366.947 -110.15 0 0 0 2 lb
26.21 -286.584 -48.3327 278.857 -111.695 271.13 -175.058 0 0 0 2 lb
26.22 -438.037 -88.514 417.946 -142.604 397.855 -196.694 0 0 0 2 lb
26.23 -438.037 -88.514 402.492 -99.332 366.947 -110.15 0 0 0 2 lb
26.24 -397.855 -196.694 382.401 -153.422 366.947 -110.15 0 0 0 2 lb
26.25 -366.947 -110.15 319.038 -142.604 271.13 -175.058 0 0 0 2 lb
26.26 -271.13 -175.058 274.221 -213.694 277.311 -252.33 0 0 0 2 lb
26.27 -271.13 -175.058 238.675 -190.512 206.221 -205.967 0 0 0 2 lb
26.28 -277.311 -252.33 241.766 -229.149 206.221 -205.967 0 0 0 2 lb
26.29 --840.856 -246.718 -804.351 -66.7145 -767.847 113.289 0 0 0 2 lb
26.30 --579.033 445.603 -673.44 279.446 -767.847 113.289 0 0 0 2 lb
26.31 --579.033 445.603 -524.906 302.104 -470.779 158.605 0 0 0 2 lb
26.32 --767.847 113.289 -619.313 135.947 -470.779 158.605 0 0 0 2 lb
26.33 -906.312 201.403 946.592 42.798 986.873 -115.807 0 0 0 2 lb
26.34 -906.312 201.403 834.562 91.8901 762.812 -17.6227 0 0 0 2 lb
26.35 -986.873 -115.807 874.842 -66.7148 762.812 -17.6227 0 0 0 2 lb
26.36 --470.779 158.605 -390.218 50.3508 -309.657 -57.9033 0 0 0 2 lb
26.37 -422.945 521.129 208.955 541.269 -5.03507 561.41 0 0 0 2 lb
26.38 -422.945 521.129 376.371 417.911 329.797 314.692 0 0 0 2 lb
26.39 -422.945 521.129 474.554 276.928 526.164 32.7279 0 0 0 2 lb
26.40 --5.03507 561.41 -36.5042 440.568 -67.9734 319.727 0 0 0 2 lb
26.41 -329.797 314.692 130.912 317.209 -67.9734 319.727 0 0 0 2 lb
26.42 --67.9734 319.727 229.095 176.227 526.164 32.7279 0 0 0 2 lb
26.43 -762.812 -17.6227 644.488 7.5526 526.164 32.7279 0 0 0 2 lb
26.44 -762.812 -17.6227 746.448 -162.381 730.084 -307.139 0 0 0 2 lb
26.45 -526.164 32.7279 470.779 -128.394 415.393 -289.516 0 0 0 2 lb
26.46 -730.084 -307.139 572.738 -298.327 415.393 -289.516 0 0 0 2 lb
26.47 -415.393 -289.516 173.71 -318.468 -67.9734 -347.42 0 0 0 2 lb
26.48 --67.9734 -347.42 -188.815 -202.662 -309.657 -57.9033 0 0 0 2 lb
26.49 --67.9734 -347.42 -195.758 -390.692 -323.543 -433.964 0 0 0 2 lb
26.50 --309.657 -57.9033 -424.775 -160.272 -539.894 -262.64 0 0 0 2 lb
26.51 --323.543 -433.964 -431.719 -348.302 -539.894 -262.64 0 0 0 2 lb
26.52 --26.6953 -19.9585 44.8558 -96.8093 116.407 -173.66 0 0 0 2 lb
26.53 --26.6953 -19.9585 87.2563 9.19185 201.208 38.3422 0 0 0 2 lb
26.54 --26.6953 -19.9585 -144.622 43.6422 -262.548 107.243 0 0 0 2 lb
26.55 --26.6953 -19.9585 -20.0703 56.8923 -13.4452 133.743 0 0 0 2 lb
26.56 -116.407 -173.66 158.808 -67.6589 201.208 38.3422 0 0 0 2 lb
26.57 --262.548 107.243 -137.997 120.493 -13.4452 133.743 0 0 0 2 lb
26.58 --262.548 107.243 -221.472 176.144 -180.397 245.045 0 0 0 2 lb
26.59 --13.4452 133.743 -96.9211 189.394 -180.397 245.045 0 0 0 2 lb
26.60 --180.397 245.045 -142.256 345.099 -132.697 451.748 0 0 0 2 lb
26.61 --180.397 245.045 -170.838 351.694 -132.697 451.748 0 0 0 2 lb
26.62 --416.25 345.746 -274.474 398.747 -132.697 451.748 0 0 0 2 lb
26.63 --416.25 345.746 -393.725 457.048 -371.2 568.349 0 0 0 2 lb
26.64 --132.697 451.748 -251.948 510.048 -371.2 568.349 0 0 0 2 lb
26.65 -670.264 274.195 629.188 409.347 588.113 544.499 0 0 0 2 lb
26.66 -670.264 274.195 797.466 341.771 924.667 409.347 0 0 0 2 lb
26.67 -588.113 544.499 756.39 476.923 924.667 409.347 0 0 0 2 lb
26.68 --689.204 -237.261 -614.799 -102.648 -567.302 43.6423 0 0 0 2 lb
26.69 --689.204 -237.261 -641.707 -90.9706 -567.302 43.6423 0 0 0 2 lb
26.70 +574.035 177.301 622.149 225.748 670.264 274.195 0 0 0 6.25356 lb
26.71 +694.579 115.483 682.421 194.839 670.264 274.195 0 0 0 6.25356 lb
26.72 +280.402 10.3938 246.402 -6.60595 212.403 -23.6057 0 0 0 6.25356 lb
26.73 +280.402 10.3938 283.493 -18.9695 286.584 -48.3327 0 0 0 6.25356 lb
26.74 +212.403 -23.6057 249.493 -35.9692 286.584 -48.3327 0 0 0 6.25356 lb
26.75 +286.584 -48.3327 326.765 -79.2414 366.947 -110.15 0 0 0 6.25356 lb
26.76 +286.584 -48.3327 278.857 -111.695 271.13 -175.058 0 0 0 6.25356 lb
26.77 +438.037 -88.514 417.946 -142.604 397.855 -196.694 0 0 0 6.25356 lb
26.78 +438.037 -88.514 402.492 -99.332 366.947 -110.15 0 0 0 6.25356 lb
26.79 +397.855 -196.694 382.401 -153.422 366.947 -110.15 0 0 0 6.25356 lb
26.80 +366.947 -110.15 319.038 -142.604 271.13 -175.058 0 0 0 6.25356 lb
26.81 +271.13 -175.058 274.221 -213.694 277.311 -252.33 0 0 0 6.25356 lb
26.82 +271.13 -175.058 238.675 -190.512 206.221 -205.967 0 0 0 6.25356 lb
26.83 +277.311 -252.33 241.766 -229.149 206.221 -205.967 0 0 0 6.25356 lb
26.84 +-840.856 -246.718 -804.351 -66.7145 -767.847 113.289 0 0 0 6.25356 lb
26.85 +-579.033 445.603 -673.44 279.446 -767.847 113.289 0 0 0 6.25356 lb
26.86 +-579.033 445.603 -524.906 302.104 -470.779 158.605 0 0 0 6.25356 lb
26.87 +-767.847 113.289 -619.313 135.947 -470.779 158.605 0 0 0 6.25356 lb
26.88 +906.312 201.403 946.592 42.798 986.873 -115.807 0 0 0 6.25356 lb
26.89 +906.312 201.403 834.562 91.8901 762.812 -17.6227 0 0 0 6.25356 lb
26.90 +986.873 -115.807 874.842 -66.7148 762.812 -17.6227 0 0 0 6.25356 lb
26.91 +-470.779 158.605 -390.218 50.3508 -309.657 -57.9033 0 0 0 6.25356 lb
26.92 +422.945 521.129 208.955 541.269 -5.03507 561.41 0 0 0 6.25356 lb
26.93 +422.945 521.129 376.371 417.911 329.797 314.692 0 0 0 6.25356 lb
26.94 +422.945 521.129 474.554 276.928 526.164 32.7279 0 0 0 6.25356 lb
26.95 +-5.03507 561.41 -36.5042 440.568 -67.9734 319.727 0 0 0 6.25356 lb
26.96 +329.797 314.692 130.912 317.209 -67.9734 319.727 0 0 0 6.25356 lb
26.97 +-67.9734 319.727 229.095 176.227 526.164 32.7279 0 0 0 6.25356 lb
26.98 +762.812 -17.6227 644.488 7.5526 526.164 32.7279 0 0 0 6.25356 lb
26.99 +762.812 -17.6227 746.448 -162.381 730.084 -307.139 0 0 0 6.25356 lb
26.100 +526.164 32.7279 470.779 -128.394 415.393 -289.516 0 0 0 6.25356 lb
26.101 +730.084 -307.139 572.738 -298.327 415.393 -289.516 0 0 0 6.25356 lb
26.102 +415.393 -289.516 173.71 -318.468 -67.9734 -347.42 0 0 0 6.25356 lb
26.103 +-67.9734 -347.42 -188.815 -202.662 -309.657 -57.9033 0 0 0 6.25356 lb
26.104 +-67.9734 -347.42 -195.758 -390.692 -323.543 -433.964 0 0 0 6.25356 lb
26.105 +-309.657 -57.9033 -424.775 -160.272 -539.894 -262.64 0 0 0 6.25356 lb
26.106 +-323.543 -433.964 -431.719 -348.302 -539.894 -262.64 0 0 0 6.25356 lb
26.107 +-26.6953 -19.9585 44.8558 -96.8093 116.407 -173.66 0 0 0 6.25356 lb
26.108 +-26.6953 -19.9585 87.2563 9.19185 201.208 38.3422 0 0 0 6.25356 lb
26.109 +-26.6953 -19.9585 -144.622 43.6422 -262.548 107.243 0 0 0 6.25356 lb
26.110 +-26.6953 -19.9585 -20.0703 56.8923 -13.4452 133.743 0 0 0 6.25356 lb
26.111 +116.407 -173.66 158.808 -67.6589 201.208 38.3422 0 0 0 6.25356 lb
26.112 +-262.548 107.243 -137.997 120.493 -13.4452 133.743 0 0 0 6.25356 lb
26.113 +-262.548 107.243 -221.472 176.144 -180.397 245.045 0 0 0 6.25356 lb
26.114 +-13.4452 133.743 -96.9211 189.394 -180.397 245.045 0 0 0 6.25356 lb
26.115 +-180.397 245.045 -113.509 338.465 -132.697 451.748 0 0 0 6.25356 lb
26.116 +-180.397 245.045 -199.585 358.328 -132.697 451.748 0 0 0 6.25356 lb
26.117 +-416.25 345.746 -274.474 398.747 -132.697 451.748 0 0 0 6.25356 lb
26.118 +-416.25 345.746 -393.725 457.048 -371.2 568.349 0 0 0 6.25356 lb
26.119 +-132.697 451.748 -251.948 510.048 -371.2 568.349 0 0 0 6.25356 lb
26.120 +670.264 274.195 629.188 409.347 588.113 544.499 0 0 0 6.25356 lb
26.121 +670.264 274.195 797.466 341.771 924.667 409.347 0 0 0 6.25356 lb
26.122 +588.113 544.499 756.39 476.923 924.667 409.347 0 0 0 6.25356 lb
26.123 +-689.204 -237.261 -587.735 -114.393 -567.302 43.6423 0 0 0 6.25356 lb
26.124 +-689.204 -237.261 -668.771 -79.2259 -567.302 43.6423 0 0 0 6.25356 lb
26.125 grestore
26.126 %Nodes:
26.127 gsave
26.128 --567.302 43.6423 20 0 0 0 nc
26.129 --689.204 -237.261 20 0 0 0 nc
26.130 -924.667 409.347 20 1 0 0 nc
26.131 -588.113 544.499 20 1 0 0 nc
26.132 -670.264 274.195 20 1 0 0 nc
26.133 --371.2 568.349 20 0 1 0 nc
26.134 --132.697 451.748 20 0 1 0 nc
26.135 --416.25 345.746 20 0 1 0 nc
26.136 --180.397 245.045 20 0 1 0 nc
26.137 --13.4452 133.743 20 0 1 0 nc
26.138 --262.548 107.243 20 0 1 0 nc
26.139 -201.208 38.3422 20 0 1 0 nc
26.140 -116.407 -173.66 20 0 1 0 nc
26.141 --26.6953 -19.9585 20 0 1 0 nc
26.142 --539.894 -262.64 20 0 0 1 nc
26.143 --323.543 -433.964 20 0 0 1 nc
26.144 --309.657 -57.9033 20 0 0 1 nc
26.145 --67.9734 -347.42 20 0 0 1 nc
26.146 -415.393 -289.516 20 0 0 1 nc
26.147 -730.084 -307.139 20 0 0 1 nc
26.148 -526.164 32.7279 20 0 0 1 nc
26.149 -762.812 -17.6227 20 0 0 1 nc
26.150 --67.9734 319.727 20 0 0 1 nc
26.151 -329.797 314.692 20 0 0 1 nc
26.152 --5.03507 561.41 20 0 0 1 nc
26.153 -422.945 521.129 20 0 0 1 nc
26.154 --470.779 158.605 20 0 0 1 nc
26.155 -986.873 -115.807 20 0 0 1 nc
26.156 -906.312 201.403 20 0 0 1 nc
26.157 --767.847 113.289 20 0 0 1 nc
26.158 --579.033 445.603 20 0 0 1 nc
26.159 --840.856 -246.718 20 0 0 1 nc
26.160 -206.221 -205.967 20 1 1 0 nc
26.161 -277.311 -252.33 20 1 1 0 nc
26.162 -271.13 -175.058 20 1 1 0 nc
26.163 -366.947 -110.15 20 1 1 0 nc
26.164 -397.855 -196.694 20 1 1 0 nc
26.165 -438.037 -88.514 20 1 1 0 nc
26.166 -286.584 -48.3327 20 1 1 0 nc
26.167 -212.403 -23.6057 20 1 1 0 nc
26.168 -280.402 10.3938 20 1 1 0 nc
26.169 -694.579 115.483 20 1 0 0 nc
26.170 -574.035 177.301 20 1 0 0 nc
26.171 +-567.302 43.6423 20.8452 0 0 0 nc
26.172 +-689.204 -237.261 20.8452 0 0 0 nc
26.173 +924.667 409.347 20.8452 1 0 0 nc
26.174 +588.113 544.499 20.8452 1 0 0 nc
26.175 +670.264 274.195 20.8452 1 0 0 nc
26.176 +-371.2 568.349 20.8452 0 1 0 nc
26.177 +-132.697 451.748 20.8452 0 1 0 nc
26.178 +-416.25 345.746 20.8452 0 1 0 nc
26.179 +-180.397 245.045 20.8452 0 1 0 nc
26.180 +-13.4452 133.743 20.8452 0 1 0 nc
26.181 +-262.548 107.243 20.8452 0 1 0 nc
26.182 +201.208 38.3422 20.8452 0 1 0 nc
26.183 +116.407 -173.66 20.8452 0 1 0 nc
26.184 +-26.6953 -19.9585 20.8452 0 1 0 nc
26.185 +-539.894 -262.64 20.8452 0 0 1 nc
26.186 +-323.543 -433.964 20.8452 0 0 1 nc
26.187 +-309.657 -57.9033 20.8452 0 0 1 nc
26.188 +-67.9734 -347.42 20.8452 0 0 1 nc
26.189 +415.393 -289.516 20.8452 0 0 1 nc
26.190 +730.084 -307.139 20.8452 0 0 1 nc
26.191 +526.164 32.7279 20.8452 0 0 1 nc
26.192 +762.812 -17.6227 20.8452 0 0 1 nc
26.193 +-67.9734 319.727 20.8452 0 0 1 nc
26.194 +329.797 314.692 20.8452 0 0 1 nc
26.195 +-5.03507 561.41 20.8452 0 0 1 nc
26.196 +422.945 521.129 20.8452 0 0 1 nc
26.197 +-470.779 158.605 20.8452 0 0 1 nc
26.198 +986.873 -115.807 20.8452 0 0 1 nc
26.199 +906.312 201.403 20.8452 0 0 1 nc
26.200 +-767.847 113.289 20.8452 0 0 1 nc
26.201 +-579.033 445.603 20.8452 0 0 1 nc
26.202 +-840.856 -246.718 20.8452 0 0 1 nc
26.203 +206.221 -205.967 20.8452 1 1 0 nc
26.204 +277.311 -252.33 20.8452 1 1 0 nc
26.205 +271.13 -175.058 20.8452 1 1 0 nc
26.206 +366.947 -110.15 20.8452 1 1 0 nc
26.207 +397.855 -196.694 20.8452 1 1 0 nc
26.208 +438.037 -88.514 20.8452 1 1 0 nc
26.209 +286.584 -48.3327 20.8452 1 1 0 nc
26.210 +212.403 -23.6057 20.8452 1 1 0 nc
26.211 +280.402 10.3938 20.8452 1 1 0 nc
26.212 +694.579 115.483 20.8452 1 0 0 nc
26.213 +574.035 177.301 20.8452 1 0 0 nc
26.214 grestore
26.215 grestore
26.216 showpage
27.1 --- a/doc/images/edge_biconnected_components.eps Mon Jul 16 16:21:40 2018 +0200
27.2 +++ b/doc/images/edge_biconnected_components.eps Wed Oct 17 19:14:07 2018 +0200
27.3 @@ -1,6 +1,6 @@
27.4 %!PS-Adobe-2.0 EPSF-2.0
27.5 %%Creator: LEMON, graphToEps()
27.6 -%%CreationDate: Fri Nov 4 13:47:12 2005
27.7 +%%CreationDate: Fri Mar 8 00:18:43 2013
27.8 %%BoundingBox: 0 0 842 596
27.9 %%EndComments
27.10 /lb { setlinewidth setrgbcolor newpath moveto
27.11 @@ -53,107 +53,107 @@
27.12 860.856 -588.349 translate
27.13 %Edges:
27.14 gsave
27.15 -574.035 177.301 622.149 225.748 670.264 274.195 1 0 0 2 lb
27.16 -694.579 115.483 682.421 194.839 670.264 274.195 1 0 0 2 lb
27.17 -280.402 10.3938 246.402 -6.60595 212.403 -23.6057 0 0 1 2 lb
27.18 -280.402 10.3938 283.493 -18.9695 286.584 -48.3327 0 0 1 2 lb
27.19 -212.403 -23.6057 249.493 -35.9692 286.584 -48.3327 0 0 1 2 lb
27.20 -286.584 -48.3327 326.765 -79.2414 366.947 -110.15 0 0 1 2 lb
27.21 -286.584 -48.3327 278.857 -111.695 271.13 -175.058 0 0 1 2 lb
27.22 -438.037 -88.514 417.946 -142.604 397.855 -196.694 0 0 1 2 lb
27.23 -438.037 -88.514 402.492 -99.332 366.947 -110.15 0 0 1 2 lb
27.24 -397.855 -196.694 382.401 -153.422 366.947 -110.15 0 0 1 2 lb
27.25 -366.947 -110.15 319.038 -142.604 271.13 -175.058 0 0 1 2 lb
27.26 -271.13 -175.058 274.221 -213.694 277.311 -252.33 0 0 1 2 lb
27.27 -271.13 -175.058 238.675 -190.512 206.221 -205.967 0 0 1 2 lb
27.28 -277.311 -252.33 241.766 -229.149 206.221 -205.967 0 0 1 2 lb
27.29 --840.856 -246.718 -804.351 -66.7145 -767.847 113.289 1 0 0 2 lb
27.30 --579.033 445.603 -673.44 279.446 -767.847 113.289 0 0 1 2 lb
27.31 --579.033 445.603 -524.906 302.104 -470.779 158.605 0 0 1 2 lb
27.32 --767.847 113.289 -619.313 135.947 -470.779 158.605 0 0 1 2 lb
27.33 -906.312 201.403 946.592 42.798 986.873 -115.807 0 0 1 2 lb
27.34 -906.312 201.403 834.562 91.8901 762.812 -17.6227 0 0 1 2 lb
27.35 -986.873 -115.807 874.842 -66.7148 762.812 -17.6227 0 0 1 2 lb
27.36 --470.779 158.605 -390.218 50.3508 -309.657 -57.9033 1 0 0 2 lb
27.37 -422.945 521.129 208.955 541.269 -5.03507 561.41 0 0 1 2 lb
27.38 -422.945 521.129 376.371 417.911 329.797 314.692 0 0 1 2 lb
27.39 -422.945 521.129 474.554 276.928 526.164 32.7279 0 0 1 2 lb
27.40 --5.03507 561.41 -36.5042 440.568 -67.9734 319.727 0 0 1 2 lb
27.41 -329.797 314.692 130.912 317.209 -67.9734 319.727 0 0 1 2 lb
27.42 --67.9734 319.727 229.095 176.227 526.164 32.7279 0 0 1 2 lb
27.43 -762.812 -17.6227 644.488 7.5526 526.164 32.7279 0 0 1 2 lb
27.44 -762.812 -17.6227 746.448 -162.381 730.084 -307.139 0 0 1 2 lb
27.45 -526.164 32.7279 470.779 -128.394 415.393 -289.516 0 0 1 2 lb
27.46 -730.084 -307.139 572.738 -298.327 415.393 -289.516 0 0 1 2 lb
27.47 -415.393 -289.516 173.71 -318.468 -67.9734 -347.42 1 0 0 2 lb
27.48 --67.9734 -347.42 -188.815 -202.662 -309.657 -57.9033 0 0 1 2 lb
27.49 --67.9734 -347.42 -195.758 -390.692 -323.543 -433.964 0 0 1 2 lb
27.50 --309.657 -57.9033 -424.775 -160.272 -539.894 -262.64 0 0 1 2 lb
27.51 --323.543 -433.964 -431.719 -348.302 -539.894 -262.64 0 0 1 2 lb
27.52 --26.6953 -19.9585 44.8558 -96.8093 116.407 -173.66 0 0 1 2 lb
27.53 --26.6953 -19.9585 87.2563 9.19185 201.208 38.3422 0 0 1 2 lb
27.54 --26.6953 -19.9585 -144.622 43.6422 -262.548 107.243 0 0 1 2 lb
27.55 --26.6953 -19.9585 -20.0703 56.8923 -13.4452 133.743 0 0 1 2 lb
27.56 -116.407 -173.66 158.808 -67.6589 201.208 38.3422 0 0 1 2 lb
27.57 --262.548 107.243 -137.997 120.493 -13.4452 133.743 0 0 1 2 lb
27.58 --262.548 107.243 -221.472 176.144 -180.397 245.045 0 0 1 2 lb
27.59 --13.4452 133.743 -96.9211 189.394 -180.397 245.045 0 0 1 2 lb
27.60 --180.397 245.045 -142.256 345.099 -132.697 451.748 0 0 1 2 lb
27.61 --180.397 245.045 -170.838 351.694 -132.697 451.748 0 0 1 2 lb
27.62 --416.25 345.746 -274.474 398.747 -132.697 451.748 0 0 1 2 lb
27.63 --416.25 345.746 -393.725 457.048 -371.2 568.349 0 0 1 2 lb
27.64 --132.697 451.748 -251.948 510.048 -371.2 568.349 0 0 1 2 lb
27.65 -670.264 274.195 629.188 409.347 588.113 544.499 0 0 1 2 lb
27.66 -670.264 274.195 797.466 341.771 924.667 409.347 0 0 1 2 lb
27.67 -588.113 544.499 756.39 476.923 924.667 409.347 0 0 1 2 lb
27.68 --689.204 -237.261 -614.799 -102.648 -567.302 43.6423 0 0 1 2 lb
27.69 --689.204 -237.261 -641.707 -90.9706 -567.302 43.6423 0 0 1 2 lb
27.70 +574.035 177.301 622.149 225.748 670.264 274.195 1 0 0 6.25356 lb
27.71 +694.579 115.483 682.421 194.839 670.264 274.195 1 0 0 6.25356 lb
27.72 +280.402 10.3938 246.402 -6.60595 212.403 -23.6057 0 0 1 6.25356 lb
27.73 +280.402 10.3938 283.493 -18.9695 286.584 -48.3327 0 0 1 6.25356 lb
27.74 +212.403 -23.6057 249.493 -35.9692 286.584 -48.3327 0 0 1 6.25356 lb
27.75 +286.584 -48.3327 326.765 -79.2414 366.947 -110.15 0 0 1 6.25356 lb
27.76 +286.584 -48.3327 278.857 -111.695 271.13 -175.058 0 0 1 6.25356 lb
27.77 +438.037 -88.514 417.946 -142.604 397.855 -196.694 0 0 1 6.25356 lb
27.78 +438.037 -88.514 402.492 -99.332 366.947 -110.15 0 0 1 6.25356 lb
27.79 +397.855 -196.694 382.401 -153.422 366.947 -110.15 0 0 1 6.25356 lb
27.80 +366.947 -110.15 319.038 -142.604 271.13 -175.058 0 0 1 6.25356 lb
27.81 +271.13 -175.058 274.221 -213.694 277.311 -252.33 0 0 1 6.25356 lb
27.82 +271.13 -175.058 238.675 -190.512 206.221 -205.967 0 0 1 6.25356 lb
27.83 +277.311 -252.33 241.766 -229.149 206.221 -205.967 0 0 1 6.25356 lb
27.84 +-840.856 -246.718 -804.351 -66.7145 -767.847 113.289 1 0 0 6.25356 lb
27.85 +-579.033 445.603 -673.44 279.446 -767.847 113.289 0 0 1 6.25356 lb
27.86 +-579.033 445.603 -524.906 302.104 -470.779 158.605 0 0 1 6.25356 lb
27.87 +-767.847 113.289 -619.313 135.947 -470.779 158.605 0 0 1 6.25356 lb
27.88 +906.312 201.403 946.592 42.798 986.873 -115.807 0 0 1 6.25356 lb
27.89 +906.312 201.403 834.562 91.8901 762.812 -17.6227 0 0 1 6.25356 lb
27.90 +986.873 -115.807 874.842 -66.7148 762.812 -17.6227 0 0 1 6.25356 lb
27.91 +-470.779 158.605 -390.218 50.3508 -309.657 -57.9033 1 0 0 6.25356 lb
27.92 +422.945 521.129 208.955 541.269 -5.03507 561.41 0 0 1 6.25356 lb
27.93 +422.945 521.129 376.371 417.911 329.797 314.692 0 0 1 6.25356 lb
27.94 +422.945 521.129 474.554 276.928 526.164 32.7279 0 0 1 6.25356 lb
27.95 +-5.03507 561.41 -36.5042 440.568 -67.9734 319.727 0 0 1 6.25356 lb
27.96 +329.797 314.692 130.912 317.209 -67.9734 319.727 0 0 1 6.25356 lb
27.97 +-67.9734 319.727 229.095 176.227 526.164 32.7279 0 0 1 6.25356 lb
27.98 +762.812 -17.6227 644.488 7.5526 526.164 32.7279 0 0 1 6.25356 lb
27.99 +762.812 -17.6227 746.448 -162.381 730.084 -307.139 0 0 1 6.25356 lb
27.100 +526.164 32.7279 470.779 -128.394 415.393 -289.516 0 0 1 6.25356 lb
27.101 +730.084 -307.139 572.738 -298.327 415.393 -289.516 0 0 1 6.25356 lb
27.102 +415.393 -289.516 173.71 -318.468 -67.9734 -347.42 1 0 0 6.25356 lb
27.103 +-67.9734 -347.42 -188.815 -202.662 -309.657 -57.9033 0 0 1 6.25356 lb
27.104 +-67.9734 -347.42 -195.758 -390.692 -323.543 -433.964 0 0 1 6.25356 lb
27.105 +-309.657 -57.9033 -424.775 -160.272 -539.894 -262.64 0 0 1 6.25356 lb
27.106 +-323.543 -433.964 -431.719 -348.302 -539.894 -262.64 0 0 1 6.25356 lb
27.107 +-26.6953 -19.9585 44.8558 -96.8093 116.407 -173.66 0 0 1 6.25356 lb
27.108 +-26.6953 -19.9585 87.2563 9.19185 201.208 38.3422 0 0 1 6.25356 lb
27.109 +-26.6953 -19.9585 -144.622 43.6422 -262.548 107.243 0 0 1 6.25356 lb
27.110 +-26.6953 -19.9585 -20.0703 56.8923 -13.4452 133.743 0 0 1 6.25356 lb
27.111 +116.407 -173.66 158.808 -67.6589 201.208 38.3422 0 0 1 6.25356 lb
27.112 +-262.548 107.243 -137.997 120.493 -13.4452 133.743 0 0 1 6.25356 lb
27.113 +-262.548 107.243 -221.472 176.144 -180.397 245.045 0 0 1 6.25356 lb
27.114 +-13.4452 133.743 -96.9211 189.394 -180.397 245.045 0 0 1 6.25356 lb
27.115 +-180.397 245.045 -113.509 338.465 -132.697 451.748 0 0 1 6.25356 lb
27.116 +-180.397 245.045 -199.585 358.328 -132.697 451.748 0 0 1 6.25356 lb
27.117 +-416.25 345.746 -274.474 398.747 -132.697 451.748 0 0 1 6.25356 lb
27.118 +-416.25 345.746 -393.725 457.048 -371.2 568.349 0 0 1 6.25356 lb
27.119 +-132.697 451.748 -251.948 510.048 -371.2 568.349 0 0 1 6.25356 lb
27.120 +670.264 274.195 629.188 409.347 588.113 544.499 0 0 1 6.25356 lb
27.121 +670.264 274.195 797.466 341.771 924.667 409.347 0 0 1 6.25356 lb
27.122 +588.113 544.499 756.39 476.923 924.667 409.347 0 0 1 6.25356 lb
27.123 +-689.204 -237.261 -587.735 -114.393 -567.302 43.6423 0 0 1 6.25356 lb
27.124 +-689.204 -237.261 -668.771 -79.2259 -567.302 43.6423 0 0 1 6.25356 lb
27.125 grestore
27.126 %Nodes:
27.127 gsave
27.128 --567.302 43.6423 20 0 0 0 nc
27.129 --689.204 -237.261 20 0 0 0 nc
27.130 -924.667 409.347 20 0 0 1 nc
27.131 -588.113 544.499 20 0 0 1 nc
27.132 -670.264 274.195 20 0 0 1 nc
27.133 --371.2 568.349 20 1 1 0 nc
27.134 --132.697 451.748 20 1 1 0 nc
27.135 --416.25 345.746 20 1 1 0 nc
27.136 --180.397 245.045 20 1 1 0 nc
27.137 --13.4452 133.743 20 1 1 0 nc
27.138 --262.548 107.243 20 1 1 0 nc
27.139 -201.208 38.3422 20 1 1 0 nc
27.140 -116.407 -173.66 20 1 1 0 nc
27.141 --26.6953 -19.9585 20 1 1 0 nc
27.142 --539.894 -262.64 20 0 0.5 0 nc
27.143 --323.543 -433.964 20 0 0.5 0 nc
27.144 --309.657 -57.9033 20 0 0.5 0 nc
27.145 --67.9734 -347.42 20 0 0.5 0 nc
27.146 -415.393 -289.516 20 0.5 0 0 nc
27.147 -730.084 -307.139 20 0.5 0 0 nc
27.148 -526.164 32.7279 20 0.5 0 0 nc
27.149 -762.812 -17.6227 20 0.5 0 0 nc
27.150 --67.9734 319.727 20 0.5 0 0 nc
27.151 -329.797 314.692 20 0.5 0 0 nc
27.152 --5.03507 561.41 20 0.5 0 0 nc
27.153 -422.945 521.129 20 0.5 0 0 nc
27.154 --470.779 158.605 20 0 1 1 nc
27.155 -986.873 -115.807 20 0.5 0 0 nc
27.156 -906.312 201.403 20 0.5 0 0 nc
27.157 --767.847 113.289 20 0 1 1 nc
27.158 --579.033 445.603 20 0 1 1 nc
27.159 --840.856 -246.718 20 1 0 1 nc
27.160 -206.221 -205.967 20 0 0 0.5 nc
27.161 -277.311 -252.33 20 0 0 0.5 nc
27.162 -271.13 -175.058 20 0 0 0.5 nc
27.163 -366.947 -110.15 20 0 0 0.5 nc
27.164 -397.855 -196.694 20 0 0 0.5 nc
27.165 -438.037 -88.514 20 0 0 0.5 nc
27.166 -286.584 -48.3327 20 0 0 0.5 nc
27.167 -212.403 -23.6057 20 0 0 0.5 nc
27.168 -280.402 10.3938 20 0 0 0.5 nc
27.169 -694.579 115.483 20 1 0 0 nc
27.170 -574.035 177.301 20 0 1 0 nc
27.171 +-567.302 43.6423 20.8452 0 0 0 nc
27.172 +-689.204 -237.261 20.8452 0 0 0 nc
27.173 +924.667 409.347 20.8452 0 0 1 nc
27.174 +588.113 544.499 20.8452 0 0 1 nc
27.175 +670.264 274.195 20.8452 0 0 1 nc
27.176 +-371.2 568.349 20.8452 1 1 0 nc
27.177 +-132.697 451.748 20.8452 1 1 0 nc
27.178 +-416.25 345.746 20.8452 1 1 0 nc
27.179 +-180.397 245.045 20.8452 1 1 0 nc
27.180 +-13.4452 133.743 20.8452 1 1 0 nc
27.181 +-262.548 107.243 20.8452 1 1 0 nc
27.182 +201.208 38.3422 20.8452 1 1 0 nc
27.183 +116.407 -173.66 20.8452 1 1 0 nc
27.184 +-26.6953 -19.9585 20.8452 1 1 0 nc
27.185 +-539.894 -262.64 20.8452 0 0.5 0 nc
27.186 +-323.543 -433.964 20.8452 0 0.5 0 nc
27.187 +-309.657 -57.9033 20.8452 0 0.5 0 nc
27.188 +-67.9734 -347.42 20.8452 0 0.5 0 nc
27.189 +415.393 -289.516 20.8452 0.5 0 0 nc
27.190 +730.084 -307.139 20.8452 0.5 0 0 nc
27.191 +526.164 32.7279 20.8452 0.5 0 0 nc
27.192 +762.812 -17.6227 20.8452 0.5 0 0 nc
27.193 +-67.9734 319.727 20.8452 0.5 0 0 nc
27.194 +329.797 314.692 20.8452 0.5 0 0 nc
27.195 +-5.03507 561.41 20.8452 0.5 0 0 nc
27.196 +422.945 521.129 20.8452 0.5 0 0 nc
27.197 +-470.779 158.605 20.8452 0 1 1 nc
27.198 +986.873 -115.807 20.8452 0.5 0 0 nc
27.199 +906.312 201.403 20.8452 0.5 0 0 nc
27.200 +-767.847 113.289 20.8452 0 1 1 nc
27.201 +-579.033 445.603 20.8452 0 1 1 nc
27.202 +-840.856 -246.718 20.8452 1 0 1 nc
27.203 +206.221 -205.967 20.8452 0 0 0.5 nc
27.204 +277.311 -252.33 20.8452 0 0 0.5 nc
27.205 +271.13 -175.058 20.8452 0 0 0.5 nc
27.206 +366.947 -110.15 20.8452 0 0 0.5 nc
27.207 +397.855 -196.694 20.8452 0 0 0.5 nc
27.208 +438.037 -88.514 20.8452 0 0 0.5 nc
27.209 +286.584 -48.3327 20.8452 0 0 0.5 nc
27.210 +212.403 -23.6057 20.8452 0 0 0.5 nc
27.211 +280.402 10.3938 20.8452 0 0 0.5 nc
27.212 +694.579 115.483 20.8452 1 0 0 nc
27.213 +574.035 177.301 20.8452 0 1 0 nc
27.214 grestore
27.215 grestore
27.216 showpage
28.1 Binary file doc/images/graph_to_eps.png has changed
29.1 --- a/doc/images/node_biconnected_components.eps Mon Jul 16 16:21:40 2018 +0200
29.2 +++ b/doc/images/node_biconnected_components.eps Wed Oct 17 19:14:07 2018 +0200
29.3 @@ -1,6 +1,6 @@
29.4 %!PS-Adobe-2.0 EPSF-2.0
29.5 %%Creator: LEMON, graphToEps()
29.6 -%%CreationDate: Fri Nov 4 13:47:12 2005
29.7 +%%CreationDate: Fri Mar 8 00:18:43 2013
29.8 %%BoundingBox: 0 0 842 596
29.9 %%EndComments
29.10 /lb { setlinewidth setrgbcolor newpath moveto
29.11 @@ -53,107 +53,107 @@
29.12 860.856 -588.349 translate
29.13 %Edges:
29.14 gsave
29.15 -574.035 177.301 622.149 225.748 670.264 274.195 0 1 0 5 lb
29.16 -694.579 115.483 682.421 194.839 670.264 274.195 1 0 0 5 lb
29.17 -280.402 10.3938 246.402 -6.60595 212.403 -23.6057 1 1 0.5 5 lb
29.18 -280.402 10.3938 283.493 -18.9695 286.584 -48.3327 1 1 0.5 5 lb
29.19 -212.403 -23.6057 249.493 -35.9692 286.584 -48.3327 1 1 0.5 5 lb
29.20 -286.584 -48.3327 326.765 -79.2414 366.947 -110.15 1 0.5 1 5 lb
29.21 -286.584 -48.3327 278.857 -111.695 271.13 -175.058 1 0.5 1 5 lb
29.22 -438.037 -88.514 417.946 -142.604 397.855 -196.694 0.5 0.5 1 5 lb
29.23 -438.037 -88.514 402.492 -99.332 366.947 -110.15 0.5 0.5 1 5 lb
29.24 -397.855 -196.694 382.401 -153.422 366.947 -110.15 0.5 0.5 1 5 lb
29.25 -366.947 -110.15 319.038 -142.604 271.13 -175.058 1 0.5 1 5 lb
29.26 -271.13 -175.058 274.221 -213.694 277.311 -252.33 0.5 1 1 5 lb
29.27 -271.13 -175.058 238.675 -190.512 206.221 -205.967 0.5 1 1 5 lb
29.28 -277.311 -252.33 241.766 -229.149 206.221 -205.967 0.5 1 1 5 lb
29.29 --840.856 -246.718 -804.351 -66.7145 -767.847 113.289 0 0.5 0 5 lb
29.30 --579.033 445.603 -673.44 279.446 -767.847 113.289 0 0 0.5 5 lb
29.31 --579.033 445.603 -524.906 302.104 -470.779 158.605 0 0 0.5 5 lb
29.32 --767.847 113.289 -619.313 135.947 -470.779 158.605 0 0 0.5 5 lb
29.33 -906.312 201.403 946.592 42.798 986.873 -115.807 0 0.5 0.5 5 lb
29.34 -906.312 201.403 834.562 91.8901 762.812 -17.6227 0 0.5 0.5 5 lb
29.35 -986.873 -115.807 874.842 -66.7148 762.812 -17.6227 0 0.5 0.5 5 lb
29.36 --470.779 158.605 -390.218 50.3508 -309.657 -57.9033 0.5 0.5 0 5 lb
29.37 -422.945 521.129 208.955 541.269 -5.03507 561.41 0.5 0 0.5 5 lb
29.38 -422.945 521.129 376.371 417.911 329.797 314.692 0.5 0 0.5 5 lb
29.39 -422.945 521.129 474.554 276.928 526.164 32.7279 0.5 0 0.5 5 lb
29.40 --5.03507 561.41 -36.5042 440.568 -67.9734 319.727 0.5 0 0.5 5 lb
29.41 -329.797 314.692 130.912 317.209 -67.9734 319.727 0.5 0 0.5 5 lb
29.42 --67.9734 319.727 229.095 176.227 526.164 32.7279 0.5 0 0.5 5 lb
29.43 -762.812 -17.6227 644.488 7.5526 526.164 32.7279 0.5 0.5 0.5 5 lb
29.44 -762.812 -17.6227 746.448 -162.381 730.084 -307.139 0.5 0.5 0.5 5 lb
29.45 -526.164 32.7279 470.779 -128.394 415.393 -289.516 0.5 0.5 0.5 5 lb
29.46 -730.084 -307.139 572.738 -298.327 415.393 -289.516 0.5 0.5 0.5 5 lb
29.47 -415.393 -289.516 173.71 -318.468 -67.9734 -347.42 1 0.5 0.5 5 lb
29.48 --67.9734 -347.42 -188.815 -202.662 -309.657 -57.9033 0.5 1 0.5 5 lb
29.49 --67.9734 -347.42 -195.758 -390.692 -323.543 -433.964 0.5 1 0.5 5 lb
29.50 --309.657 -57.9033 -424.775 -160.272 -539.894 -262.64 0.5 1 0.5 5 lb
29.51 --323.543 -433.964 -431.719 -348.302 -539.894 -262.64 0.5 1 0.5 5 lb
29.52 --26.6953 -19.9585 44.8558 -96.8093 116.407 -173.66 1 1 0 5 lb
29.53 --26.6953 -19.9585 87.2563 9.19185 201.208 38.3422 1 1 0 5 lb
29.54 --26.6953 -19.9585 -144.622 43.6422 -262.548 107.243 1 0 1 5 lb
29.55 --26.6953 -19.9585 -20.0703 56.8923 -13.4452 133.743 1 0 1 5 lb
29.56 -116.407 -173.66 158.808 -67.6589 201.208 38.3422 1 1 0 5 lb
29.57 --262.548 107.243 -137.997 120.493 -13.4452 133.743 1 0 1 5 lb
29.58 --262.548 107.243 -221.472 176.144 -180.397 245.045 1 0 1 5 lb
29.59 --13.4452 133.743 -96.9211 189.394 -180.397 245.045 1 0 1 5 lb
29.60 --180.397 245.045 -140.307 344.649 -132.697 451.748 0 1 1 5 lb
29.61 --180.397 245.045 -172.787 352.144 -132.697 451.748 0 1 1 5 lb
29.62 --416.25 345.746 -274.474 398.747 -132.697 451.748 0.5 0 0 5 lb
29.63 --416.25 345.746 -393.725 457.048 -371.2 568.349 0.5 0 0 5 lb
29.64 --132.697 451.748 -251.948 510.048 -371.2 568.349 0.5 0 0 5 lb
29.65 -670.264 274.195 629.188 409.347 588.113 544.499 0 0 1 5 lb
29.66 -670.264 274.195 797.466 341.771 924.667 409.347 0 0 1 5 lb
29.67 -588.113 544.499 756.39 476.923 924.667 409.347 0 0 1 5 lb
29.68 --689.204 -237.261 -612.964 -103.444 -567.302 43.6423 0 0 0 5 lb
29.69 --689.204 -237.261 -643.542 -90.1744 -567.302 43.6423 0 0 0 5 lb
29.70 +574.035 177.301 622.149 225.748 670.264 274.195 0 1 0 6.25356 lb
29.71 +694.579 115.483 682.421 194.839 670.264 274.195 1 0 0 6.25356 lb
29.72 +280.402 10.3938 246.402 -6.60595 212.403 -23.6057 1 1 0.5 6.25356 lb
29.73 +280.402 10.3938 283.493 -18.9695 286.584 -48.3327 1 1 0.5 6.25356 lb
29.74 +212.403 -23.6057 249.493 -35.9692 286.584 -48.3327 1 1 0.5 6.25356 lb
29.75 +286.584 -48.3327 326.765 -79.2414 366.947 -110.15 1 0.5 1 6.25356 lb
29.76 +286.584 -48.3327 278.857 -111.695 271.13 -175.058 1 0.5 1 6.25356 lb
29.77 +438.037 -88.514 417.946 -142.604 397.855 -196.694 0.5 0.5 1 6.25356 lb
29.78 +438.037 -88.514 402.492 -99.332 366.947 -110.15 0.5 0.5 1 6.25356 lb
29.79 +397.855 -196.694 382.401 -153.422 366.947 -110.15 0.5 0.5 1 6.25356 lb
29.80 +366.947 -110.15 319.038 -142.604 271.13 -175.058 1 0.5 1 6.25356 lb
29.81 +271.13 -175.058 274.221 -213.694 277.311 -252.33 0.5 1 1 6.25356 lb
29.82 +271.13 -175.058 238.675 -190.512 206.221 -205.967 0.5 1 1 6.25356 lb
29.83 +277.311 -252.33 241.766 -229.149 206.221 -205.967 0.5 1 1 6.25356 lb
29.84 +-840.856 -246.718 -804.351 -66.7145 -767.847 113.289 0 0.5 0 6.25356 lb
29.85 +-579.033 445.603 -673.44 279.446 -767.847 113.289 0 0 0.5 6.25356 lb
29.86 +-579.033 445.603 -524.906 302.104 -470.779 158.605 0 0 0.5 6.25356 lb
29.87 +-767.847 113.289 -619.313 135.947 -470.779 158.605 0 0 0.5 6.25356 lb
29.88 +906.312 201.403 946.592 42.798 986.873 -115.807 0 0.5 0.5 6.25356 lb
29.89 +906.312 201.403 834.562 91.8901 762.812 -17.6227 0 0.5 0.5 6.25356 lb
29.90 +986.873 -115.807 874.842 -66.7148 762.812 -17.6227 0 0.5 0.5 6.25356 lb
29.91 +-470.779 158.605 -390.218 50.3508 -309.657 -57.9033 0.5 0.5 0 6.25356 lb
29.92 +422.945 521.129 208.955 541.269 -5.03507 561.41 0.5 0 0.5 6.25356 lb
29.93 +422.945 521.129 376.371 417.911 329.797 314.692 0.5 0 0.5 6.25356 lb
29.94 +422.945 521.129 474.554 276.928 526.164 32.7279 0.5 0 0.5 6.25356 lb
29.95 +-5.03507 561.41 -36.5042 440.568 -67.9734 319.727 0.5 0 0.5 6.25356 lb
29.96 +329.797 314.692 130.912 317.209 -67.9734 319.727 0.5 0 0.5 6.25356 lb
29.97 +-67.9734 319.727 229.095 176.227 526.164 32.7279 0.5 0 0.5 6.25356 lb
29.98 +762.812 -17.6227 644.488 7.5526 526.164 32.7279 0.5 0.5 0.5 6.25356 lb
29.99 +762.812 -17.6227 746.448 -162.381 730.084 -307.139 0.5 0.5 0.5 6.25356 lb
29.100 +526.164 32.7279 470.779 -128.394 415.393 -289.516 0.5 0.5 0.5 6.25356 lb
29.101 +730.084 -307.139 572.738 -298.327 415.393 -289.516 0.5 0.5 0.5 6.25356 lb
29.102 +415.393 -289.516 173.71 -318.468 -67.9734 -347.42 1 0.5 0.5 6.25356 lb
29.103 +-67.9734 -347.42 -188.815 -202.662 -309.657 -57.9033 0.5 1 0.5 6.25356 lb
29.104 +-67.9734 -347.42 -195.758 -390.692 -323.543 -433.964 0.5 1 0.5 6.25356 lb
29.105 +-309.657 -57.9033 -424.775 -160.272 -539.894 -262.64 0.5 1 0.5 6.25356 lb
29.106 +-323.543 -433.964 -431.719 -348.302 -539.894 -262.64 0.5 1 0.5 6.25356 lb
29.107 +-26.6953 -19.9585 44.8558 -96.8093 116.407 -173.66 1 1 0 6.25356 lb
29.108 +-26.6953 -19.9585 87.2563 9.19185 201.208 38.3422 1 1 0 6.25356 lb
29.109 +-26.6953 -19.9585 -144.622 43.6422 -262.548 107.243 1 0 1 6.25356 lb
29.110 +-26.6953 -19.9585 -20.0703 56.8923 -13.4452 133.743 1 0 1 6.25356 lb
29.111 +116.407 -173.66 158.808 -67.6589 201.208 38.3422 1 1 0 6.25356 lb
29.112 +-262.548 107.243 -137.997 120.493 -13.4452 133.743 1 0 1 6.25356 lb
29.113 +-262.548 107.243 -221.472 176.144 -180.397 245.045 1 0 1 6.25356 lb
29.114 +-13.4452 133.743 -96.9211 189.394 -180.397 245.045 1 0 1 6.25356 lb
29.115 +-180.397 245.045 -113.509 338.465 -132.697 451.748 0 1 1 6.25356 lb
29.116 +-180.397 245.045 -199.585 358.328 -132.697 451.748 0 1 1 6.25356 lb
29.117 +-416.25 345.746 -274.474 398.747 -132.697 451.748 0.5 0 0 6.25356 lb
29.118 +-416.25 345.746 -393.725 457.048 -371.2 568.349 0.5 0 0 6.25356 lb
29.119 +-132.697 451.748 -251.948 510.048 -371.2 568.349 0.5 0 0 6.25356 lb
29.120 +670.264 274.195 629.188 409.347 588.113 544.499 0 0 1 6.25356 lb
29.121 +670.264 274.195 797.466 341.771 924.667 409.347 0 0 1 6.25356 lb
29.122 +588.113 544.499 756.39 476.923 924.667 409.347 0 0 1 6.25356 lb
29.123 +-689.204 -237.261 -587.735 -114.393 -567.302 43.6423 0 0 0 6.25356 lb
29.124 +-689.204 -237.261 -668.771 -79.2259 -567.302 43.6423 0 0 0 6.25356 lb
29.125 grestore
29.126 %Nodes:
29.127 gsave
29.128 --567.302 43.6423 20 0 0 1 nc
29.129 --689.204 -237.261 20 0 0 1 nc
29.130 -924.667 409.347 20 0 0 1 nc
29.131 -588.113 544.499 20 0 0 1 nc
29.132 -670.264 274.195 20 1 0 0 nc
29.133 --371.2 568.349 20 0 0 1 nc
29.134 --132.697 451.748 20 1 0 0 nc
29.135 --416.25 345.746 20 0 0 1 nc
29.136 --180.397 245.045 20 1 0 0 nc
29.137 --13.4452 133.743 20 0 0 1 nc
29.138 --262.548 107.243 20 0 0 1 nc
29.139 -201.208 38.3422 20 0 0 1 nc
29.140 -116.407 -173.66 20 0 0 1 nc
29.141 --26.6953 -19.9585 20 1 0 0 nc
29.142 --539.894 -262.64 20 0 0 1 nc
29.143 --323.543 -433.964 20 0 0 1 nc
29.144 --309.657 -57.9033 20 1 0 0 nc
29.145 --67.9734 -347.42 20 1 0 0 nc
29.146 -415.393 -289.516 20 1 0 0 nc
29.147 -730.084 -307.139 20 0 0 1 nc
29.148 -526.164 32.7279 20 1 0 0 nc
29.149 -762.812 -17.6227 20 1 0 0 nc
29.150 --67.9734 319.727 20 0 0 1 nc
29.151 -329.797 314.692 20 0 0 1 nc
29.152 --5.03507 561.41 20 0 0 1 nc
29.153 -422.945 521.129 20 0 0 1 nc
29.154 --470.779 158.605 20 1 0 0 nc
29.155 -986.873 -115.807 20 0 0 1 nc
29.156 -906.312 201.403 20 0 0 1 nc
29.157 --767.847 113.289 20 1 0 0 nc
29.158 --579.033 445.603 20 0 0 1 nc
29.159 --840.856 -246.718 20 0 0 1 nc
29.160 -206.221 -205.967 20 0 0 1 nc
29.161 -277.311 -252.33 20 0 0 1 nc
29.162 -271.13 -175.058 20 1 0 0 nc
29.163 -366.947 -110.15 20 1 0 0 nc
29.164 -397.855 -196.694 20 0 0 1 nc
29.165 -438.037 -88.514 20 0 0 1 nc
29.166 -286.584 -48.3327 20 1 0 0 nc
29.167 -212.403 -23.6057 20 0 0 1 nc
29.168 -280.402 10.3938 20 0 0 1 nc
29.169 -694.579 115.483 20 0 0 1 nc
29.170 -574.035 177.301 20 0 0 1 nc
29.171 +-567.302 43.6423 20.8452 0 0 1 nc
29.172 +-689.204 -237.261 20.8452 0 0 1 nc
29.173 +924.667 409.347 20.8452 0 0 1 nc
29.174 +588.113 544.499 20.8452 0 0 1 nc
29.175 +670.264 274.195 20.8452 1 0 0 nc
29.176 +-371.2 568.349 20.8452 0 0 1 nc
29.177 +-132.697 451.748 20.8452 1 0 0 nc
29.178 +-416.25 345.746 20.8452 0 0 1 nc
29.179 +-180.397 245.045 20.8452 1 0 0 nc
29.180 +-13.4452 133.743 20.8452 0 0 1 nc
29.181 +-262.548 107.243 20.8452 0 0 1 nc
29.182 +201.208 38.3422 20.8452 0 0 1 nc
29.183 +116.407 -173.66 20.8452 0 0 1 nc
29.184 +-26.6953 -19.9585 20.8452 1 0 0 nc
29.185 +-539.894 -262.64 20.8452 0 0 1 nc
29.186 +-323.543 -433.964 20.8452 0 0 1 nc
29.187 +-309.657 -57.9033 20.8452 1 0 0 nc
29.188 +-67.9734 -347.42 20.8452 1 0 0 nc
29.189 +415.393 -289.516 20.8452 1 0 0 nc
29.190 +730.084 -307.139 20.8452 0 0 1 nc
29.191 +526.164 32.7279 20.8452 1 0 0 nc
29.192 +762.812 -17.6227 20.8452 1 0 0 nc
29.193 +-67.9734 319.727 20.8452 0 0 1 nc
29.194 +329.797 314.692 20.8452 0 0 1 nc
29.195 +-5.03507 561.41 20.8452 0 0 1 nc
29.196 +422.945 521.129 20.8452 0 0 1 nc
29.197 +-470.779 158.605 20.8452 1 0 0 nc
29.198 +986.873 -115.807 20.8452 0 0 1 nc
29.199 +906.312 201.403 20.8452 0 0 1 nc
29.200 +-767.847 113.289 20.8452 1 0 0 nc
29.201 +-579.033 445.603 20.8452 0 0 1 nc
29.202 +-840.856 -246.718 20.8452 0 0 1 nc
29.203 +206.221 -205.967 20.8452 0 0 1 nc
29.204 +277.311 -252.33 20.8452 0 0 1 nc
29.205 +271.13 -175.058 20.8452 1 0 0 nc
29.206 +366.947 -110.15 20.8452 1 0 0 nc
29.207 +397.855 -196.694 20.8452 0 0 1 nc
29.208 +438.037 -88.514 20.8452 0 0 1 nc
29.209 +286.584 -48.3327 20.8452 1 0 0 nc
29.210 +212.403 -23.6057 20.8452 0 0 1 nc
29.211 +280.402 10.3938 20.8452 0 0 1 nc
29.212 +694.579 115.483 20.8452 0 0 1 nc
29.213 +574.035 177.301 20.8452 0 0 1 nc
29.214 grestore
29.215 grestore
29.216 showpage
30.1 --- a/doc/images/strongly_connected_components.eps Mon Jul 16 16:21:40 2018 +0200
30.2 +++ b/doc/images/strongly_connected_components.eps Wed Oct 17 19:14:07 2018 +0200
30.3 @@ -1,6 +1,6 @@
30.4 %!PS-Adobe-2.0 EPSF-2.0
30.5 %%Creator: LEMON, graphToEps()
30.6 -%%CreationDate: Fri Nov 4 13:47:12 2005
30.7 +%%CreationDate: Fri Mar 8 00:22:15 2013
30.8 %%BoundingBox: 0 0 842 596
30.9 %%EndComments
30.10 /lb { setlinewidth setrgbcolor newpath moveto
30.11 @@ -53,128 +53,128 @@
30.12 695.963 -397.916 translate
30.13 %Edges:
30.14 gsave
30.15 -2 setlinewidth 0 0 1 setrgbcolor newpath
30.16 +4.56973 setlinewidth 0 0 1 setrgbcolor newpath
30.17 218.178 27.2723 moveto
30.18 -192.373 -40.1551 188.622 -49.9556 169.228 -100.631 curveto stroke
30.19 -newpath 164.939 -111.838 moveto 165.492 -99.2013 lineto 172.964 -102.061 lineto closepath fill
30.20 -2 setlinewidth 0 0 1 setrgbcolor newpath
30.21 +195.849 -31.0725 190.033 -46.2697 176.306 -82.1369 curveto stroke
30.22 +newpath 163.235 -116.291 moveto 165.206 -77.8889 lineto 187.405 -86.3849 lineto closepath fill
30.23 +4.56973 setlinewidth 0 0 1 setrgbcolor newpath
30.24 44.8044 15.5841 moveto
30.25 -119.293 20.6059 129.775 21.3125 186.25 25.1199 curveto stroke
30.26 -newpath 198.223 25.927 moveto 186.519 21.1289 lineto 185.981 29.1108 lineto closepath fill
30.27 -2 setlinewidth 1 0 0 setrgbcolor newpath
30.28 +109.705 19.9594 126.016 21.0591 166.493 23.7879 curveto stroke
30.29 +newpath 202.98 26.2477 moveto 167.292 11.9299 lineto 165.694 35.6458 lineto closepath fill
30.30 +4.56973 setlinewidth 1 0 0 setrgbcolor newpath
30.31 218.178 27.2723 moveto
30.32 -285.395 -87.4449 290.763 -96.6058 348.102 -194.464 curveto stroke
30.33 -newpath 354.169 -204.818 moveto 344.651 -196.487 lineto 351.554 -192.442 lineto closepath fill
30.34 -2 setlinewidth 0 0 1 setrgbcolor newpath
30.35 +281.264 -80.3935 289.87 -95.0808 338.092 -177.379 curveto stroke
30.36 +newpath 356.579 -208.932 moveto 327.837 -183.388 lineto 348.346 -171.371 lineto closepath fill
30.37 +4.56973 setlinewidth 0 0 1 setrgbcolor newpath
30.38 157.79 -130.517 moveto
30.39 -108.71 -67.0521 102.27 -58.7243 64.3804 -9.72954 curveto stroke
30.40 -newpath 57.0394 -0.236898 moveto 67.5446 -7.28254 lineto 61.2162 -12.1765 lineto closepath fill
30.41 -2 setlinewidth 1 0 0 setrgbcolor newpath
30.42 +114.446 -74.4692 104.358 -61.4239 76.4943 -25.394 curveto stroke
30.43 +newpath 54.1228 3.53455 moveto 85.8959 -18.1234 lineto 67.0928 -32.6646 lineto closepath fill
30.44 +4.56973 setlinewidth 1 0 0 setrgbcolor newpath
30.45 -105.193 -261.035 moveto
30.46 --35.6576 -132.801 -30.5923 -123.459 29.5506 -12.5464 curveto stroke
30.47 -newpath 35.2708 -1.99743 moveto 33.0669 -14.4531 lineto 26.0343 -10.6397 lineto closepath fill
30.48 -2 setlinewidth 0 0 1 setrgbcolor newpath
30.49 +-39.4801 -139.85 -31.344 -124.846 20.1113 -29.9539 curveto stroke
30.50 +newpath 37.5434 2.19358 moveto 30.559 -35.6192 lineto 9.66361 -24.2886 lineto closepath fill
30.51 +4.56973 setlinewidth 0 0 1 setrgbcolor newpath
30.52 -465.576 -42.8564 moveto
30.53 --559.078 -25.5413 -569.47 -23.6169 -644.498 -9.72286 curveto stroke
30.54 -newpath -656.297 -7.5378 moveto -643.77 -5.78973 lineto -645.226 -13.656 lineto closepath fill
30.55 -2 setlinewidth 0 0 1 setrgbcolor newpath
30.56 +-550.335 -27.1603 -566.8 -24.1113 -625.027 -13.3286 curveto stroke
30.57 +newpath -660.985 -6.66971 moveto -622.863 -1.64245 lineto -627.191 -25.0148 lineto closepath fill
30.58 +4.56973 setlinewidth 0 0 1 setrgbcolor newpath
30.59 -574.666 -153.893 moveto
30.60 --528.842 -107.252 -521.515 -99.794 -488.002 -65.683 curveto stroke
30.61 -newpath -479.592 -57.123 moveto -485.149 -68.4863 lineto -490.856 -62.8797 lineto closepath fill
30.62 -2 setlinewidth 1 0 0 setrgbcolor newpath
30.63 +-535.911 -114.447 -524.692 -103.027 -501.88 -79.8085 curveto stroke
30.64 +newpath -476.251 -53.7222 moveto -493.402 -88.1377 lineto -510.358 -71.4793 lineto closepath fill
30.65 +4.56973 setlinewidth 1 0 0 setrgbcolor newpath
30.66 -490.901 120.777 moveto
30.67 --480.122 51.1328 -478.519 40.7713 -470.47 -11.2329 curveto stroke
30.68 -newpath -468.635 -23.0917 moveto -474.423 -11.8447 lineto -466.517 -10.6212 lineto closepath fill
30.69 -2 setlinewidth 0 0 1 setrgbcolor newpath
30.70 +-481.623 60.8277 -479.143 44.8049 -473.499 8.33636 curveto stroke
30.71 +newpath -467.906 -27.8032 moveto -485.244 6.51862 lineto -461.754 10.1541 lineto closepath fill
30.72 +4.56973 setlinewidth 0 0 1 setrgbcolor newpath
30.73 -675.963 -3.89604 moveto
30.74 --632.116 -68.8235 -626.228 -77.5422 -592.575 -127.374 curveto stroke
30.75 -newpath -585.859 -137.319 moveto -595.89 -129.612 lineto -589.26 -125.135 lineto closepath fill
30.76 -2 setlinewidth 0 0 1 setrgbcolor newpath
30.77 +-637.405 -60.9909 -628.201 -74.6206 -603.658 -110.963 curveto stroke
30.78 +newpath -583.191 -141.27 moveto -613.507 -117.615 lineto -593.808 -104.312 lineto closepath fill
30.79 +4.56973 setlinewidth 0 0 1 setrgbcolor newpath
30.80 -490.901 120.777 moveto
30.81 --435.445 215.844 -430.107 224.995 -384.3 303.522 curveto stroke
30.82 -newpath -378.253 313.887 moveto -380.845 301.507 lineto -387.755 305.537 lineto closepath fill
30.83 -2 setlinewidth 0 0 1 setrgbcolor newpath
30.84 +-439.75 208.465 -431.238 223.057 -394.278 286.417 curveto stroke
30.85 +newpath -375.851 318.006 moveto -384.012 280.429 lineto -404.543 292.406 lineto closepath fill
30.86 +4.56973 setlinewidth 0 0 1 setrgbcolor newpath
30.87 -266.879 114.933 moveto
30.88 --367.067 117.547 -377.642 117.822 -458.912 119.943 curveto stroke
30.89 -newpath -470.908 120.255 moveto -458.807 123.941 lineto -459.016 115.944 lineto closepath fill
30.90 -2 setlinewidth 0 0 1 setrgbcolor newpath
30.91 +-358.311 117.318 -375.109 117.756 -439.117 119.426 curveto stroke
30.92 +newpath -475.674 120.38 moveto -438.807 131.307 lineto -439.426 107.545 lineto closepath fill
30.93 +4.56973 setlinewidth 0 0 1 setrgbcolor newpath
30.94 -368.176 331.163 moveto
30.95 --322.511 233.685 -318.018 224.095 -280.454 143.911 curveto stroke
30.96 -newpath -275.364 133.044 moveto -284.076 142.214 lineto -276.832 145.608 lineto closepath fill
30.97 -2 setlinewidth 1 0 0 setrgbcolor newpath
30.98 +-326.156 241.466 -318.997 226.186 -288.855 161.843 curveto stroke
30.99 +newpath -273.341 128.727 moveto -299.617 156.801 lineto -278.092 166.885 lineto closepath fill
30.100 +4.56973 setlinewidth 1 0 0 setrgbcolor newpath
30.101 -266.879 114.933 moveto
30.102 --224.004 235.52 -220.448 245.52 -184.094 347.765 curveto stroke
30.103 -newpath -180.074 359.072 moveto -180.325 346.425 lineto -187.863 349.105 lineto closepath fill
30.104 -2 setlinewidth 0 0 1 setrgbcolor newpath
30.105 +-226.764 227.755 -221.069 243.774 -190.728 329.107 curveto stroke
30.106 +newpath -178.477 363.564 moveto -179.53 325.126 lineto -201.926 333.089 lineto closepath fill
30.107 +4.56973 setlinewidth 0 0 1 setrgbcolor newpath
30.108 -251.294 -335.059 moveto
30.109 --189.25 -303.624 -179.902 -298.887 -133.738 -275.498 curveto stroke
30.110 -newpath -123.034 -270.074 moveto -131.93 -279.066 lineto -135.546 -271.93 lineto closepath fill
30.111 -2 setlinewidth 0 0 1 setrgbcolor newpath
30.112 +-198.044 -308.079 -183.61 -300.766 -151.402 -284.448 curveto stroke
30.113 +newpath -118.781 -267.92 moveto -146.031 -295.049 lineto -156.774 -273.846 lineto closepath fill
30.114 +4.56973 setlinewidth 0 0 1 setrgbcolor newpath
30.115 -389.604 -136.361 moveto
30.116 --327.15 -226.083 -321.098 -234.777 -269.576 -308.795 curveto stroke
30.117 -newpath -262.72 -318.644 moveto -272.859 -311.081 lineto -266.293 -306.51 lineto closepath fill
30.118 -2 setlinewidth 1 0 0 setrgbcolor newpath
30.119 +-332.039 -219.059 -322.392 -232.919 -280.889 -292.543 curveto stroke
30.120 +newpath -259.996 -322.557 moveto -290.643 -299.333 lineto -271.134 -285.753 lineto closepath fill
30.121 +4.56973 setlinewidth 1 0 0 setrgbcolor newpath
30.122 5.84406 175.322 moveto
30.123 --76.0754 267.926 -83.1051 275.873 -152.172 353.948 curveto stroke
30.124 -newpath -160.122 362.936 moveto -149.176 356.598 lineto -155.168 351.298 lineto closepath fill
30.125 -2 setlinewidth 0 0 1 setrgbcolor newpath
30.126 +-70.5724 261.706 -81.8227 274.423 -139.051 339.116 curveto stroke
30.127 +newpath -163.281 366.507 moveto -130.149 346.991 lineto -147.953 331.242 lineto closepath fill
30.128 +4.56973 setlinewidth 0 0 1 setrgbcolor newpath
30.129 169.478 311.683 moveto
30.130 -96.8003 251.119 88.6819 244.353 30.4273 195.808 curveto stroke
30.131 -newpath 21.2086 188.126 moveto 27.8666 198.881 lineto 32.988 192.735 lineto closepath fill
30.132 -2 setlinewidth 0 0 1 setrgbcolor newpath
30.133 +103.641 256.819 90.7821 246.103 45.6398 208.485 curveto stroke
30.134 +newpath 17.546 185.074 moveto 38.0313 217.615 lineto 53.2483 199.355 lineto closepath fill
30.135 +4.56973 setlinewidth 0 0 1 setrgbcolor newpath
30.136 342.851 111.037 moveto
30.137 -263.766 202.563 256.831 210.589 190.4 287.47 curveto stroke
30.138 -newpath 182.554 296.55 moveto 193.427 290.085 lineto 187.373 284.855 lineto closepath fill
30.139 -2 setlinewidth 0 0 1 setrgbcolor newpath
30.140 +269.224 196.246 258.132 209.083 203.347 272.486 curveto stroke
30.141 +newpath 179.437 300.157 moveto 212.34 280.257 lineto 194.354 264.716 lineto closepath fill
30.142 +4.56973 setlinewidth 0 0 1 setrgbcolor newpath
30.143 5.84406 175.322 moveto
30.144 -163.16 145.314 173.605 143.321 311.418 117.033 curveto stroke
30.145 -newpath 323.205 114.784 moveto 310.668 113.104 lineto 312.167 120.962 lineto closepath fill
30.146 -2 setlinewidth 0 0 1 setrgbcolor newpath
30.147 +155.419 146.79 172.221 143.585 291.966 120.743 curveto stroke
30.148 +newpath 327.888 113.891 moveto 289.739 109.069 lineto 294.193 132.418 lineto closepath fill
30.149 +4.56973 setlinewidth 0 0 1 setrgbcolor newpath
30.150 342.851 111.037 moveto
30.151 -497.255 2.58683 505.964 -3.53033 643.932 -100.436 curveto stroke
30.152 -newpath 653.752 -107.334 moveto 641.633 -103.71 lineto 646.231 -97.163 lineto closepath fill
30.153 -2 setlinewidth 0 0 1 setrgbcolor newpath
30.154 +490.978 6.99574 505.015 -2.86383 627.727 -89.0547 curveto stroke
30.155 +newpath 657.653 -110.074 moveto 620.896 -98.7802 lineto 634.558 -79.3291 lineto closepath fill
30.156 +4.56973 setlinewidth 0 0 1 setrgbcolor newpath
30.157 364.28 -222.074 moveto
30.158 -354.298 -66.9063 353.616 -56.2971 344.905 79.1029 curveto stroke
30.159 -newpath 344.135 91.0781 moveto 348.897 79.3597 lineto 340.914 78.8461 lineto closepath fill
30.160 -2 setlinewidth 0 0 1 setrgbcolor newpath
30.161 +354.807 -74.8128 353.709 -57.7536 346.177 59.3416 curveto stroke
30.162 +newpath 343.829 95.836 moveto 358.037 60.1045 lineto 334.316 58.5786 lineto closepath fill
30.163 +4.56973 setlinewidth 0 0 1 setrgbcolor newpath
30.164 670.118 -118.829 moveto
30.165 -528.037 -166.793 517.967 -170.192 394.599 -211.839 curveto stroke
30.166 -newpath 383.229 -215.677 moveto 393.32 -208.049 lineto 395.878 -215.629 lineto closepath fill
30.167 -2 setlinewidth 1 0 0 setrgbcolor newpath
30.168 +535.595 -164.241 519.412 -169.704 413.361 -205.505 curveto stroke
30.169 +newpath 378.712 -217.202 moveto 409.559 -194.245 lineto 417.162 -216.766 lineto closepath fill
30.170 +4.56973 setlinewidth 1 0 0 setrgbcolor newpath
30.171 -105.193 -261.035 moveto
30.172 -118.401 -242.479 129.015 -241.598 332.39 -224.721 curveto stroke
30.173 -newpath 344.348 -223.728 moveto 332.72 -228.707 lineto 332.059 -220.734 lineto closepath fill
30.174 -2 setlinewidth 0 0 1 setrgbcolor newpath
30.175 +110.939 -243.099 128.069 -241.677 312.655 -226.358 curveto stroke
30.176 +newpath 349.1 -223.334 moveto 313.638 -238.202 lineto 311.672 -214.514 lineto closepath fill
30.177 +4.56973 setlinewidth 0 0 1 setrgbcolor newpath
30.178 -105.193 -261.035 moveto
30.179 --160.867 -161.176 -166.028 -151.918 -212.336 -68.858 curveto stroke
30.180 -newpath -218.179 -58.3769 moveto -208.842 -66.9102 lineto -215.829 -70.8058 lineto closepath fill
30.181 -2 setlinewidth 0 0 1 setrgbcolor newpath
30.182 +-156.746 -168.566 -164.987 -153.784 -202.693 -86.1539 curveto stroke
30.183 +newpath -220.5 -54.2129 moveto -192.312 -80.3665 lineto -213.073 -91.9413 lineto closepath fill
30.184 +4.56973 setlinewidth 0 0 1 setrgbcolor newpath
30.185 -227.918 -40.9084 moveto
30.186 --298.35 -82.4884 -307.42 -87.8432 -362.048 -120.093 curveto stroke
30.187 -newpath -372.381 -126.193 moveto -364.081 -116.648 lineto -360.014 -123.537 lineto closepath fill
30.188 +-290.327 -77.7521 -304.558 -86.1532 -344.995 -110.026 curveto stroke
30.189 +newpath -376.487 -128.617 moveto -351.037 -99.7914 lineto -338.953 -120.26 lineto closepath fill
30.190 grestore
30.191 %Nodes:
30.192 gsave
30.193 --389.604 -136.361 20 0 1 0 nc
30.194 --227.918 -40.9084 20 0 1 0 nc
30.195 --105.193 -261.035 20 0 1 0 nc
30.196 -364.28 -222.074 20 1 1 0 nc
30.197 -670.118 -118.829 20 1 1 0 nc
30.198 -342.851 111.037 20 1 1 0 nc
30.199 -5.84406 175.322 20 1 1 0 nc
30.200 -169.478 311.683 20 1 1 0 nc
30.201 --173.374 377.916 20 1 0 1 nc
30.202 --251.294 -335.059 20 0 1 0 nc
30.203 --266.879 114.933 20 0 0 0 nc
30.204 --368.176 331.163 20 0 0 0 nc
30.205 --490.901 120.777 20 0 0 0 nc
30.206 --574.666 -153.893 20 1 0 0 nc
30.207 --675.963 -3.89604 20 1 0 0 nc
30.208 --465.576 -42.8564 20 1 0 0 nc
30.209 -44.8044 15.5841 20 0 0 1 nc
30.210 -157.79 -130.517 20 0 0 1 nc
30.211 -218.178 27.2723 20 0 0 1 nc
30.212 +-389.604 -136.361 15.2324 0 1 0 nc
30.213 +-227.918 -40.9084 15.2324 0 1 0 nc
30.214 +-105.193 -261.035 15.2324 0 1 0 nc
30.215 +364.28 -222.074 15.2324 1 1 0 nc
30.216 +670.118 -118.829 15.2324 1 1 0 nc
30.217 +342.851 111.037 15.2324 1 1 0 nc
30.218 +5.84406 175.322 15.2324 1 1 0 nc
30.219 +169.478 311.683 15.2324 1 1 0 nc
30.220 +-173.374 377.916 15.2324 1 0 1 nc
30.221 +-251.294 -335.059 15.2324 0 1 0 nc
30.222 +-266.879 114.933 15.2324 0 0 0 nc
30.223 +-368.176 331.163 15.2324 0 0 0 nc
30.224 +-490.901 120.777 15.2324 0 0 0 nc
30.225 +-574.666 -153.893 15.2324 1 0 0 nc
30.226 +-675.963 -3.89604 15.2324 1 0 0 nc
30.227 +-465.576 -42.8564 15.2324 1 0 0 nc
30.228 +44.8044 15.5841 15.2324 0 0 1 nc
30.229 +157.79 -130.517 15.2324 0 0 1 nc
30.230 +218.178 27.2723 15.2324 0 0 1 nc
30.231 grestore
30.232 grestore
30.233 showpage
31.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
31.2 +++ b/doc/images/tsp.eps Wed Oct 17 19:14:07 2018 +0200
31.3 @@ -0,0 +1,229 @@
31.4 +%!PS-Adobe-2.0 EPSF-2.0
31.5 +%%Creator: LEMON, graphToEps()
31.6 +%%CreationDate: Tue Jun 15 00:58:57 2010
31.7 +%%BoundingBox: 31 41 649 709
31.8 +%%EndComments
31.9 +/lb { setlinewidth setrgbcolor newpath moveto
31.10 + 4 2 roll 1 index 1 index curveto stroke } bind def
31.11 +/l { setlinewidth setrgbcolor newpath moveto lineto stroke } bind def
31.12 +/c { newpath dup 3 index add 2 index moveto 0 360 arc closepath } bind def
31.13 +/sq { newpath 2 index 1 index add 2 index 2 index add moveto
31.14 + 2 index 1 index sub 2 index 2 index add lineto
31.15 + 2 index 1 index sub 2 index 2 index sub lineto
31.16 + 2 index 1 index add 2 index 2 index sub lineto
31.17 + closepath pop pop pop} bind def
31.18 +/di { newpath 2 index 1 index add 2 index moveto
31.19 + 2 index 2 index 2 index add lineto
31.20 + 2 index 1 index sub 2 index lineto
31.21 + 2 index 2 index 2 index sub lineto
31.22 + closepath pop pop pop} bind def
31.23 +/nc { 0 0 0 setrgbcolor 5 index 5 index 5 index c fill
31.24 + setrgbcolor 1.1 div c fill
31.25 + } bind def
31.26 +/nsq { 0 0 0 setrgbcolor 5 index 5 index 5 index sq fill
31.27 + setrgbcolor 1.1 div sq fill
31.28 + } bind def
31.29 +/ndi { 0 0 0 setrgbcolor 5 index 5 index 5 index di fill
31.30 + setrgbcolor 1.1 div di fill
31.31 + } bind def
31.32 +/nfemale { 0 0 0 setrgbcolor 3 index 0.0909091 1.5 mul mul setlinewidth
31.33 + newpath 5 index 5 index moveto 5 index 5 index 5 index 3.01 mul sub
31.34 + lineto 5 index 4 index .7 mul sub 5 index 5 index 2.2 mul sub moveto
31.35 + 5 index 4 index .7 mul add 5 index 5 index 2.2 mul sub lineto stroke
31.36 + 5 index 5 index 5 index c fill
31.37 + setrgbcolor 1.1 div c fill
31.38 + } bind def
31.39 +/nmale {
31.40 + 0 0 0 setrgbcolor 3 index 0.0909091 1.5 mul mul setlinewidth
31.41 + newpath 5 index 5 index moveto
31.42 + 5 index 4 index 1 mul 1.5 mul add
31.43 + 5 index 5 index 3 sqrt 1.5 mul mul add
31.44 + 1 index 1 index lineto
31.45 + 1 index 1 index 7 index sub moveto
31.46 + 1 index 1 index lineto
31.47 + exch 5 index 3 sqrt .5 mul mul sub exch 5 index .5 mul sub lineto
31.48 + stroke
31.49 + 5 index 5 index 5 index c fill
31.50 + setrgbcolor 1.1 div c fill
31.51 + } bind def
31.52 +/arrl 1 def
31.53 +/arrw 0.3 def
31.54 +/lrl { 2 index mul exch 2 index mul exch rlineto pop} bind def
31.55 +/arr { setrgbcolor /y1 exch def /x1 exch def /dy exch def /dx exch def
31.56 + /w exch def /len exch def
31.57 + newpath x1 dy w 2 div mul add y1 dx w 2 div mul sub moveto
31.58 + len w sub arrl sub dx dy lrl
31.59 + arrw dy dx neg lrl
31.60 + dx arrl w add mul dy w 2 div arrw add mul sub
31.61 + dy arrl w add mul dx w 2 div arrw add mul add rlineto
31.62 + dx arrl w add mul neg dy w 2 div arrw add mul sub
31.63 + dy arrl w add mul neg dx w 2 div arrw add mul add rlineto
31.64 + arrw dy dx neg lrl
31.65 + len w sub arrl sub neg dx dy lrl
31.66 + closepath fill } bind def
31.67 +/cshow { 2 index 2 index moveto dup stringwidth pop
31.68 + neg 2 div fosi .35 mul neg rmoveto show pop pop} def
31.69 +
31.70 +gsave
31.71 +10 dup scale
31.72 +%Arcs:
31.73 +gsave
31.74 +27 68 37 69 0 0 1 0.513798 l
31.75 +37 69 27 68 0 0 1 0.513798 l
31.76 +8 52 5 64 0 0 1 0.513798 l
31.77 +5 64 8 52 0 0 1 0.513798 l
31.78 +16 57 25 55 0 0 1 0.513798 l
31.79 +25 55 16 57 0 0 1 0.513798 l
31.80 +43 67 37 69 0 0 1 0.513798 l
31.81 +37 69 43 67 0 0 1 0.513798 l
31.82 +42 57 43 67 0 0 1 0.513798 l
31.83 +43 67 42 57 0 0 1 0.513798 l
31.84 +62 42 61 33 0 0 1 0.513798 l
31.85 +61 33 62 42 0 0 1 0.513798 l
31.86 +62 42 58 48 0 0 1 0.513798 l
31.87 +58 48 62 42 0 0 1 0.513798 l
31.88 +58 27 61 33 0 0 1 0.513798 l
31.89 +61 33 58 27 0 0 1 0.513798 l
31.90 +57 58 62 63 0 0 1 0.513798 l
31.91 +62 63 57 58 0 0 1 0.513798 l
31.92 +13 13 21 10 0 0 1 0.513798 l
31.93 +21 10 13 13 0 0 1 0.513798 l
31.94 +13 13 5 6 0 0 1 0.513798 l
31.95 +5 6 13 13 0 0 1 0.513798 l
31.96 +17 33 7 38 0 0 1 0.513798 l
31.97 +7 38 17 33 0 0 1 0.513798 l
31.98 +46 10 59 15 0 0 1 0.513798 l
31.99 +59 15 46 10 0 0 1 0.513798 l
31.100 +46 10 39 10 0 0 1 0.513798 l
31.101 +39 10 46 10 0 0 1 0.513798 l
31.102 +27 23 21 10 0 0 1 0.513798 l
31.103 +21 10 27 23 0 0 1 0.513798 l
31.104 +52 41 56 37 0 0 1 0.513798 l
31.105 +56 37 52 41 0 0 1 0.513798 l
31.106 +62 63 63 69 0 0 1 0.513798 l
31.107 +63 69 62 63 0 0 1 0.513798 l
31.108 +36 16 39 10 0 0 1 0.513798 l
31.109 +39 10 36 16 0 0 1 0.513798 l
31.110 +36 16 30 15 0 0 1 0.513798 l
31.111 +30 15 36 16 0 0 1 0.513798 l
31.112 +12 42 7 38 0 0 1 0.513798 l
31.113 +7 38 12 42 0 0 1 0.513798 l
31.114 +12 42 8 52 0 0 1 0.513798 l
31.115 +8 52 12 42 0 0 1 0.513798 l
31.116 +32 22 30 15 0 0 1 0.513798 l
31.117 +30 15 32 22 0 0 1 0.513798 l
31.118 +5 25 10 17 0 0 1 0.513798 l
31.119 +10 17 5 25 0 0 1 0.513798 l
31.120 +5 25 17 33 0 0 1 0.513798 l
31.121 +17 33 5 25 0 0 1 0.513798 l
31.122 +45 35 48 28 0 0 1 0.513798 l
31.123 +48 28 45 35 0 0 1 0.513798 l
31.124 +31 32 25 32 0 0 1 0.513798 l
31.125 +25 32 31 32 0 0 1 0.513798 l
31.126 +31 32 32 39 0 0 1 0.513798 l
31.127 +32 39 31 32 0 0 1 0.513798 l
31.128 +42 41 38 46 0 0 1 0.513798 l
31.129 +38 46 42 41 0 0 1 0.513798 l
31.130 +42 41 52 41 0 0 1 0.513798 l
31.131 +52 41 42 41 0 0 1 0.513798 l
31.132 +5 6 10 17 0 0 1 0.513798 l
31.133 +10 17 5 6 0 0 1 0.513798 l
31.134 +51 21 59 15 0 0 1 0.513798 l
31.135 +59 15 51 21 0 0 1 0.513798 l
31.136 +51 21 58 27 0 0 1 0.513798 l
31.137 +58 27 51 21 0 0 1 0.513798 l
31.138 +52 33 56 37 0 0 1 0.513798 l
31.139 +56 37 52 33 0 0 1 0.513798 l
31.140 +52 33 48 28 0 0 1 0.513798 l
31.141 +48 28 52 33 0 0 1 0.513798 l
31.142 +31 62 25 55 0 0 1 0.513798 l
31.143 +25 55 31 62 0 0 1 0.513798 l
31.144 +31 62 27 68 0 0 1 0.513798 l
31.145 +27 68 31 62 0 0 1 0.513798 l
31.146 +17 63 5 64 0 0 1 0.513798 l
31.147 +5 64 17 63 0 0 1 0.513798 l
31.148 +17 63 16 57 0 0 1 0.513798 l
31.149 +16 57 17 63 0 0 1 0.513798 l
31.150 +21 47 30 40 0 0 1 0.513798 l
31.151 +30 40 21 47 0 0 1 0.513798 l
31.152 +21 47 30 48 0 0 1 0.513798 l
31.153 +30 48 21 47 0 0 1 0.513798 l
31.154 +40 30 45 35 0 0 1 0.513798 l
31.155 +45 35 40 30 0 0 1 0.513798 l
31.156 +40 30 32 22 0 0 1 0.513798 l
31.157 +32 22 40 30 0 0 1 0.513798 l
31.158 +32 39 30 40 0 0 1 0.513798 l
31.159 +30 40 32 39 0 0 1 0.513798 l
31.160 +20 26 25 32 0 0 1 0.513798 l
31.161 +25 32 20 26 0 0 1 0.513798 l
31.162 +20 26 27 23 0 0 1 0.513798 l
31.163 +27 23 20 26 0 0 1 0.513798 l
31.164 +52 64 63 69 0 0 1 0.513798 l
31.165 +63 69 52 64 0 0 1 0.513798 l
31.166 +52 64 42 57 0 0 1 0.513798 l
31.167 +42 57 52 64 0 0 1 0.513798 l
31.168 +49 49 58 48 0 0 1 0.513798 l
31.169 +58 48 49 49 0 0 1 0.513798 l
31.170 +49 49 57 58 0 0 1 0.513798 l
31.171 +57 58 49 49 0 0 1 0.513798 l
31.172 +37 52 38 46 0 0 1 0.513798 l
31.173 +38 46 37 52 0 0 1 0.513798 l
31.174 +37 52 30 48 0 0 1 0.513798 l
31.175 +30 48 37 52 0 0 1 0.513798 l
31.176 +grestore
31.177 +%Nodes:
31.178 +gsave
31.179 +30 40 0.856329 1 1 1 nc
31.180 +56 37 0.856329 1 1 1 nc
31.181 +48 28 0.856329 1 1 1 nc
31.182 +25 55 0.856329 1 1 1 nc
31.183 +25 32 0.856329 1 1 1 nc
31.184 +32 39 0.856329 1 1 1 nc
31.185 +39 10 0.856329 1 1 1 nc
31.186 +30 15 0.856329 1 1 1 nc
31.187 +5 64 0.856329 1 1 1 nc
31.188 +21 10 0.856329 1 1 1 nc
31.189 +10 17 0.856329 1 1 1 nc
31.190 +5 6 0.856329 1 1 1 nc
31.191 +59 15 0.856329 1 1 1 nc
31.192 +45 35 0.856329 1 1 1 nc
31.193 +32 22 0.856329 1 1 1 nc
31.194 +63 69 0.856329 1 1 1 nc
31.195 +62 63 0.856329 1 1 1 nc
31.196 +61 33 0.856329 1 1 1 nc
31.197 +46 10 0.856329 1 1 1 nc
31.198 +38 46 0.856329 1 1 1 nc
31.199 +37 69 0.856329 1 1 1 nc
31.200 +58 27 0.856329 1 1 1 nc
31.201 +58 48 0.856329 1 1 1 nc
31.202 +43 67 0.856329 1 1 1 nc
31.203 +30 48 0.856329 1 1 1 nc
31.204 +27 68 0.856329 1 1 1 nc
31.205 +7 38 0.856329 1 1 1 nc
31.206 +8 52 0.856329 1 1 1 nc
31.207 +16 57 0.856329 1 1 1 nc
31.208 +42 57 0.856329 1 1 1 nc
31.209 +62 42 0.856329 1 1 1 nc
31.210 +57 58 0.856329 1 1 1 nc
31.211 +13 13 0.856329 1 1 1 nc
31.212 +17 33 0.856329 1 1 1 nc
31.213 +27 23 0.856329 1 1 1 nc
31.214 +52 41 0.856329 1 1 1 nc
31.215 +36 16 0.856329 1 1 1 nc
31.216 +12 42 0.856329 1 1 1 nc
31.217 +5 25 0.856329 1 1 1 nc
31.218 +31 32 0.856329 1 1 1 nc
31.219 +42 41 0.856329 1 1 1 nc
31.220 +51 21 0.856329 1 1 1 nc
31.221 +52 33 0.856329 1 1 1 nc
31.222 +31 62 0.856329 1 1 1 nc
31.223 +17 63 0.856329 1 1 1 nc
31.224 +21 47 0.856329 1 1 1 nc
31.225 +40 30 0.856329 1 1 1 nc
31.226 +20 26 0.856329 1 1 1 nc
31.227 +52 64 0.856329 1 1 1 nc
31.228 +49 49 0.856329 1 1 1 nc
31.229 +37 52 0.856329 1 1 1 nc
31.230 +grestore
31.231 +grestore
31.232 +showpage
32.1 --- a/doc/lgf.dox Mon Jul 16 16:21:40 2018 +0200
32.2 +++ b/doc/lgf.dox Wed Oct 17 19:14:07 2018 +0200
32.3 @@ -2,7 +2,7 @@
32.4 *
32.5 * This file is a part of LEMON, a generic C++ optimization library.
32.6 *
32.7 - * Copyright (C) 2003-2009
32.8 + * Copyright (C) 2003-2013
32.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
32.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
32.11 *
32.12 @@ -63,11 +63,28 @@
32.13 3 (40,10) 10 "Third node"
32.14 \endcode
32.15
32.16 -The \c \@arcs section is very similar to the \c \@nodes section, it
32.17 -again starts with a header line describing the names of the maps, but
32.18 -the \c "label" map is not obligatory here. The following lines
32.19 -describe the arcs. The first two tokens of each line are the source
32.20 -and the target node of the arc, respectively, then come the map
32.21 +The \e LGF files can also contain bipartite graphs, in this case a
32.22 +\c \@red_nodes and a \c \@blue_nodes sections describe the node set of the
32.23 +graph. If a map is in both of these sections, then it can be used as a
32.24 +regular node map.
32.25 +
32.26 +\code
32.27 + @red_nodes
32.28 + label only_red_map name
32.29 + 1 "cherry" "John"
32.30 + 2 "Santa Claus" "Jack"
32.31 + 3 "blood" "Jason"
32.32 + @blue_nodes
32.33 + label name
32.34 + 4 "Elisabeth"
32.35 + 5 "Eve"
32.36 +\endcode
32.37 +
32.38 +The \c \@arcs section is very similar to the \c \@nodes section,
32.39 +it again starts with a header line describing the names of the maps,
32.40 +but the \c "label" map is not obligatory here. The following lines
32.41 +describe the arcs. The first two tokens of each line are
32.42 +the source and the target node of the arc, respectively, then come the map
32.43 values. The source and target tokens must be node labels.
32.44
32.45 \code
33.1 --- a/doc/mainpage.dox.in Mon Jul 16 16:21:40 2018 +0200
33.2 +++ b/doc/mainpage.dox.in Wed Oct 17 19:14:07 2018 +0200
33.3 @@ -25,7 +25,7 @@
33.4 and <b>O</b>ptimization in <b>N</b>etworks</i>.
33.5 It is a C++ template library providing efficient implementations of common
33.6 data structures and algorithms with focus on combinatorial optimization
33.7 -tasks connected mainly with graphs and networks.
33.8 +tasks connected mainly with graphs and networks \cite DezsoJuttnerKovacs11Lemon.
33.9
33.10 <b>
33.11 LEMON is an <a class="el" href="http://opensource.org/">open source</a>
33.12 @@ -37,12 +37,12 @@
33.13
33.14 The project is maintained by the
33.15 <a href="http://www.cs.elte.hu/egres/">Egerváry Research Group on
33.16 -Combinatorial Optimization</a> \ref egres
33.17 +Combinatorial Optimization</a> \cite egres
33.18 at the Operations Research Department of the
33.19 <a href="http://www.elte.hu/en/">Eötvös Loránd University</a>,
33.20 Budapest, Hungary.
33.21 LEMON is also a member of the <a href="http://www.coin-or.org/">COIN-OR</a>
33.22 -initiative \ref coinor.
33.23 +initiative \cite coinor.
33.24
33.25 \section howtoread How to Read the Documentation
33.26
34.1 --- a/doc/min_cost_flow.dox Mon Jul 16 16:21:40 2018 +0200
34.2 +++ b/doc/min_cost_flow.dox Wed Oct 17 19:14:07 2018 +0200
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-2010
34.8 + * Copyright (C) 2003-2013
34.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
34.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
34.11 *
34.12 @@ -26,7 +26,7 @@
34.13 The \e minimum \e cost \e flow \e problem is to find a feasible flow of
34.14 minimum total cost from a set of supply nodes to a set of demand nodes
34.15 in a network with capacity constraints (lower and upper bounds)
34.16 -and arc costs \ref amo93networkflows.
34.17 +and arc costs \cite amo93networkflows.
34.18
34.19 Formally, let \f$G=(V,A)\f$ be a digraph, \f$lower: A\rightarrow\mathbf{R}\f$,
34.20 \f$upper: A\rightarrow\mathbf{R}\cup\{+\infty\}\f$ denote the lower and
34.21 @@ -101,7 +101,7 @@
34.22 sup(u) \quad \forall u\in V \f]
34.23 \f[ lower(uv) \leq f(uv) \leq upper(uv) \quad \forall uv\in A \f]
34.24
34.25 -However if the sum of the supply values is zero, then these two problems
34.26 +However, if the sum of the supply values is zero, then these two problems
34.27 are equivalent.
34.28 The \ref min_cost_flow_algs "algorithms" in LEMON support the general
34.29 form, so if you need the equality form, you have to ensure this additional
35.1 --- a/doc/references.bib Mon Jul 16 16:21:40 2018 +0200
35.2 +++ b/doc/references.bib Wed Oct 17 19:14:07 2018 +0200
35.3 @@ -4,8 +4,7 @@
35.4 key = {LEMON},
35.5 title = {{LEMON} -- {L}ibrary for {E}fficient {M}odeling and
35.6 {O}ptimization in {N}etworks},
35.7 - howpublished = {\url{http://lemon.cs.elte.hu/}},
35.8 - year = 2009
35.9 + howpublished = {\url{http://lemon.cs.elte.hu/}}
35.10 }
35.11
35.12 @misc{egres,
35.13 @@ -23,6 +22,28 @@
35.14 }
35.15
35.16
35.17 +%%%%% Papers related to LEMON %%%%%
35.18 +
35.19 +@article{DezsoJuttnerKovacs11Lemon,
35.20 + author = {B. Dezs{\H o} and A. J\"uttner and P. Kov\'acs},
35.21 + title = {{LEMON} -- an open source {C++} graph template library},
35.22 + journal = {Electronic Notes in Theoretical Computer Science},
35.23 + volume = {264},
35.24 + pages = {23--45},
35.25 + year = {2011},
35.26 + note = {Proc. 2nd Workshop on Generative Technologies}
35.27 +}
35.28 +
35.29 +@article{KiralyKovacs12MCF,
35.30 + author = {Z. Kir\'aly and P. Kov\'acs},
35.31 + title = {Efficient implementations of minimum-cost flow algorithms},
35.32 + journal = {Acta Universitatis Sapientiae, Informatica},
35.33 + year = {2012},
35.34 + volume = {4},
35.35 + pages = {67--118}
35.36 +}
35.37 +
35.38 +
35.39 %%%%% Other libraries %%%%%%
35.40
35.41 @misc{boost,
35.42 @@ -213,6 +234,16 @@
35.43 pages = {309-311}
35.44 }
35.45
35.46 +@article{hartmann93finding,
35.47 + author = {Mark Hartmann and James B. Orlin},
35.48 + title = {Finding minimum cost to time ratio cycles with small
35.49 + integral transit times},
35.50 + journal = {Networks},
35.51 + year = 1993,
35.52 + volume = 23,
35.53 + pages = {567-574}
35.54 +}
35.55 +
35.56 @article{dasdan98minmeancycle,
35.57 author = {Ali Dasdan and Rajesh K. Gupta},
35.58 title = {Faster Maximum and Minimum Mean Cycle Alogrithms for
35.59 @@ -225,6 +256,17 @@
35.60 pages = {889-899}
35.61 }
35.62
35.63 +@article{dasdan04experimental,
35.64 + author = {Ali Dasdan},
35.65 + title = {Experimental analysis of the fastest optimum cycle
35.66 + ratio and mean algorithms},
35.67 + journal = {ACM Trans. Des. Autom. Electron. Syst.},
35.68 + year = 2004,
35.69 + volume = 9,
35.70 + issue = 4,
35.71 + pages = {385-418}
35.72 +}
35.73 +
35.74
35.75 %%%%% Minimum cost flow algorithms %%%%%
35.76
35.77 @@ -297,5 +339,18 @@
35.78 school = {University College},
35.79 address = {Dublin, Ireland},
35.80 year = 1991,
35.81 - month = sep,
35.82 + month = sep
35.83 }
35.84 +
35.85 +%%%%% Other algorithms %%%%%
35.86 +
35.87 +@article{grosso08maxclique,
35.88 + author = {Andrea Grosso and Marco Locatelli and Wayne Pullan},
35.89 + title = {Simple ingredients leading to very efficient
35.90 + heuristics for the maximum clique problem},
35.91 + journal = {Journal of Heuristics},
35.92 + year = 2008,
35.93 + volume = 14,
35.94 + number = 6,
35.95 + pages = {587--612}
35.96 +}
36.1 --- a/lemon/CMakeLists.txt Mon Jul 16 16:21:40 2018 +0200
36.2 +++ b/lemon/CMakeLists.txt Wed Oct 17 19:14:07 2018 +0200
36.3 @@ -4,12 +4,12 @@
36.4 )
36.5
36.6 CONFIGURE_FILE(
36.7 - ${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake
36.8 + ${CMAKE_CURRENT_SOURCE_DIR}/config.h.in
36.9 ${CMAKE_CURRENT_BINARY_DIR}/config.h
36.10 )
36.11
36.12 CONFIGURE_FILE(
36.13 - ${CMAKE_CURRENT_SOURCE_DIR}/lemon.pc.cmake
36.14 + ${CMAKE_CURRENT_SOURCE_DIR}/lemon.pc.in
36.15 ${CMAKE_CURRENT_BINARY_DIR}/lemon.pc
36.16 @ONLY
36.17 )
36.18 @@ -36,7 +36,7 @@
36.19
36.20 IF(LEMON_HAVE_CPLEX)
36.21 SET(LEMON_SOURCES ${LEMON_SOURCES} cplex.cc)
36.22 - INCLUDE_DIRECTORIES(${CPLEX_INCLUDE_DIRS})
36.23 + INCLUDE_DIRECTORIES(${ILOG_INCLUDE_DIRS})
36.24 ENDIF()
36.25
36.26 IF(LEMON_HAVE_CLP)
36.27 @@ -49,9 +49,19 @@
36.28 INCLUDE_DIRECTORIES(${COIN_INCLUDE_DIRS})
36.29 ENDIF()
36.30
36.31 +IF(LEMON_HAVE_SOPLEX)
36.32 + SET(LEMON_SOURCES ${LEMON_SOURCES} soplex.cc)
36.33 + INCLUDE_DIRECTORIES(${SOPLEX_INCLUDE_DIRS})
36.34 +ENDIF()
36.35 +
36.36 ADD_LIBRARY(lemon ${LEMON_SOURCES})
36.37 +
36.38 +TARGET_LINK_LIBRARIES(lemon
36.39 + ${GLPK_LIBRARIES} ${COIN_LIBRARIES} ${ILOG_LIBRARIES} ${SOPLEX_LIBRARIES}
36.40 + )
36.41 +
36.42 IF(UNIX)
36.43 - SET_TARGET_PROPERTIES(lemon PROPERTIES OUTPUT_NAME emon)
36.44 + SET_TARGET_PROPERTIES(lemon PROPERTIES OUTPUT_NAME emon VERSION ${LEMON_VERSION} SOVERSION ${LEMON_VERSION})
36.45 ENDIF()
36.46
36.47 INSTALL(
37.1 --- a/lemon/Makefile.am Mon Jul 16 16:21:40 2018 +0200
37.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
37.3 @@ -1,151 +0,0 @@
37.4 -EXTRA_DIST += \
37.5 - lemon/lemon.pc.in \
37.6 - lemon/lemon.pc.cmake \
37.7 - lemon/CMakeLists.txt \
37.8 - lemon/config.h.cmake
37.9 -
37.10 -pkgconfig_DATA += lemon/lemon.pc
37.11 -
37.12 -lib_LTLIBRARIES += lemon/libemon.la
37.13 -
37.14 -lemon_libemon_la_SOURCES = \
37.15 - lemon/arg_parser.cc \
37.16 - lemon/base.cc \
37.17 - lemon/color.cc \
37.18 - lemon/lp_base.cc \
37.19 - lemon/lp_skeleton.cc \
37.20 - lemon/random.cc \
37.21 - lemon/bits/windows.cc
37.22 -
37.23 -nodist_lemon_HEADERS = lemon/config.h
37.24 -
37.25 -lemon_libemon_la_CXXFLAGS = \
37.26 - $(AM_CXXFLAGS) \
37.27 - $(GLPK_CFLAGS) \
37.28 - $(CPLEX_CFLAGS) \
37.29 - $(SOPLEX_CXXFLAGS) \
37.30 - $(CLP_CXXFLAGS) \
37.31 - $(CBC_CXXFLAGS)
37.32 -
37.33 -lemon_libemon_la_LDFLAGS = \
37.34 - $(GLPK_LIBS) \
37.35 - $(CPLEX_LIBS) \
37.36 - $(SOPLEX_LIBS) \
37.37 - $(CLP_LIBS) \
37.38 - $(CBC_LIBS)
37.39 -
37.40 -if HAVE_GLPK
37.41 -lemon_libemon_la_SOURCES += lemon/glpk.cc
37.42 -endif
37.43 -
37.44 -if HAVE_CPLEX
37.45 -lemon_libemon_la_SOURCES += lemon/cplex.cc
37.46 -endif
37.47 -
37.48 -if HAVE_SOPLEX
37.49 -lemon_libemon_la_SOURCES += lemon/soplex.cc
37.50 -endif
37.51 -
37.52 -if HAVE_CLP
37.53 -lemon_libemon_la_SOURCES += lemon/clp.cc
37.54 -endif
37.55 -
37.56 -if HAVE_CBC
37.57 -lemon_libemon_la_SOURCES += lemon/cbc.cc
37.58 -endif
37.59 -
37.60 -lemon_HEADERS += \
37.61 - lemon/adaptors.h \
37.62 - lemon/arg_parser.h \
37.63 - lemon/assert.h \
37.64 - lemon/bellman_ford.h \
37.65 - lemon/bfs.h \
37.66 - lemon/bin_heap.h \
37.67 - lemon/binomial_heap.h \
37.68 - lemon/bucket_heap.h \
37.69 - lemon/capacity_scaling.h \
37.70 - lemon/cbc.h \
37.71 - lemon/circulation.h \
37.72 - lemon/clp.h \
37.73 - lemon/color.h \
37.74 - lemon/concept_check.h \
37.75 - lemon/connectivity.h \
37.76 - lemon/core.h \
37.77 - lemon/cost_scaling.h \
37.78 - lemon/counter.h \
37.79 - lemon/cplex.h \
37.80 - lemon/cycle_canceling.h \
37.81 - lemon/dfs.h \
37.82 - lemon/dheap.h \
37.83 - lemon/dijkstra.h \
37.84 - lemon/dim2.h \
37.85 - lemon/dimacs.h \
37.86 - lemon/edge_set.h \
37.87 - lemon/elevator.h \
37.88 - lemon/error.h \
37.89 - lemon/euler.h \
37.90 - lemon/fib_heap.h \
37.91 - lemon/fractional_matching.h \
37.92 - lemon/full_graph.h \
37.93 - lemon/glpk.h \
37.94 - lemon/gomory_hu.h \
37.95 - lemon/graph_to_eps.h \
37.96 - lemon/grid_graph.h \
37.97 - lemon/hartmann_orlin_mmc.h \
37.98 - lemon/howard_mmc.h \
37.99 - lemon/hypercube_graph.h \
37.100 - lemon/karp_mmc.h \
37.101 - lemon/kruskal.h \
37.102 - lemon/hao_orlin.h \
37.103 - lemon/lgf_reader.h \
37.104 - lemon/lgf_writer.h \
37.105 - lemon/list_graph.h \
37.106 - lemon/lp.h \
37.107 - lemon/lp_base.h \
37.108 - lemon/lp_skeleton.h \
37.109 - lemon/maps.h \
37.110 - lemon/matching.h \
37.111 - lemon/math.h \
37.112 - lemon/min_cost_arborescence.h \
37.113 - lemon/nauty_reader.h \
37.114 - lemon/network_simplex.h \
37.115 - lemon/pairing_heap.h \
37.116 - lemon/path.h \
37.117 - lemon/planarity.h \
37.118 - lemon/preflow.h \
37.119 - lemon/quad_heap.h \
37.120 - lemon/radix_heap.h \
37.121 - lemon/radix_sort.h \
37.122 - lemon/random.h \
37.123 - lemon/smart_graph.h \
37.124 - lemon/soplex.h \
37.125 - lemon/static_graph.h \
37.126 - lemon/suurballe.h \
37.127 - lemon/time_measure.h \
37.128 - lemon/tolerance.h \
37.129 - lemon/unionfind.h \
37.130 - lemon/bits/windows.h
37.131 -
37.132 -bits_HEADERS += \
37.133 - lemon/bits/alteration_notifier.h \
37.134 - lemon/bits/array_map.h \
37.135 - lemon/bits/bezier.h \
37.136 - lemon/bits/default_map.h \
37.137 - lemon/bits/edge_set_extender.h \
37.138 - lemon/bits/enable_if.h \
37.139 - lemon/bits/graph_adaptor_extender.h \
37.140 - lemon/bits/graph_extender.h \
37.141 - lemon/bits/map_extender.h \
37.142 - lemon/bits/path_dump.h \
37.143 - lemon/bits/solver_bits.h \
37.144 - lemon/bits/traits.h \
37.145 - lemon/bits/variant.h \
37.146 - lemon/bits/vector_map.h
37.147 -
37.148 -concept_HEADERS += \
37.149 - lemon/concepts/digraph.h \
37.150 - lemon/concepts/graph.h \
37.151 - lemon/concepts/graph_components.h \
37.152 - lemon/concepts/heap.h \
37.153 - lemon/concepts/maps.h \
37.154 - lemon/concepts/path.h
38.1 --- a/lemon/adaptors.h Mon Jul 16 16:21:40 2018 +0200
38.2 +++ b/lemon/adaptors.h Wed Oct 17 19:14:07 2018 +0200
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-2010
38.8 + * Copyright (C) 2003-2013
38.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
38.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
38.11 *
39.1 --- a/lemon/arg_parser.cc Mon Jul 16 16:21:40 2018 +0200
39.2 +++ b/lemon/arg_parser.cc Wed Oct 17 19:14:07 2018 +0200
39.3 @@ -221,9 +221,9 @@
39.4 const std::string &opt)
39.5 {
39.6 Opts::iterator o = _opts.find(opt);
39.7 - Opts::iterator s = _opts.find(syn);
39.8 LEMON_ASSERT(o!=_opts.end(), "Unknown option: '"+opt+"'");
39.9 - LEMON_ASSERT(s==_opts.end(), "Option already used: '"+syn+"'");
39.10 + LEMON_ASSERT(_opts.find(syn)==_opts.end(),
39.11 + "Option already used: '"+syn+"'");
39.12 ParData p;
39.13 p.help=opt;
39.14 p.mandatory=false;
40.1 --- a/lemon/arg_parser.h Mon Jul 16 16:21:40 2018 +0200
40.2 +++ b/lemon/arg_parser.h Wed Oct 17 19:14:07 2018 +0200
40.3 @@ -26,6 +26,7 @@
40.4 #include <iostream>
40.5 #include <sstream>
40.6 #include <algorithm>
40.7 +#include <lemon/core.h>
40.8 #include <lemon/assert.h>
40.9
40.10 ///\ingroup misc
41.1 --- a/lemon/assert.h Mon Jul 16 16:21:40 2018 +0200
41.2 +++ b/lemon/assert.h Wed Oct 17 19:14:07 2018 +0200
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-2013
41.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
41.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
41.11 *
41.12 @@ -199,7 +199,7 @@
41.13 LEMON_FUNCTION_NAME, \
41.14 ::lemon::_assert_bits::cstringify(msg), \
41.15 #exp), 0)))
41.16 -# if LEMON_ENABLE_DEBUG
41.17 +# if defined LEMON_ENABLE_DEBUG
41.18 # define LEMON_DEBUG(exp, msg) \
41.19 (static_cast<void> (!!(exp) ? 0 : ( \
41.20 LEMON_ASSERT_HANDLER(__FILE__, __LINE__, \
42.1 --- a/lemon/base.cc Mon Jul 16 16:21:40 2018 +0200
42.2 +++ b/lemon/base.cc Wed Oct 17 19:14:07 2018 +0200
42.3 @@ -2,7 +2,7 @@
42.4 *
42.5 * This file is a part of LEMON, a generic C++ optimization library.
42.6 *
42.7 - * Copyright (C) 2003-2009
42.8 + * Copyright (C) 2003-2013
42.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
42.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
42.11 *
42.12 @@ -21,6 +21,7 @@
42.13
42.14 #include<lemon/tolerance.h>
42.15 #include<lemon/core.h>
42.16 +#include<lemon/time_measure.h>
42.17 namespace lemon {
42.18
42.19 float Tolerance<float>::def_epsilon = static_cast<float>(1e-4);
42.20 @@ -31,4 +32,6 @@
42.21 const Invalid INVALID = Invalid();
42.22 #endif
42.23
42.24 + TimeStamp::Format TimeStamp::_format = TimeStamp::NORMAL;
42.25 +
42.26 } //namespace lemon
43.1 --- a/lemon/bellman_ford.h Mon Jul 16 16:21:40 2018 +0200
43.2 +++ b/lemon/bellman_ford.h Wed Oct 17 19:14:07 2018 +0200
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-2010
43.8 + * Copyright (C) 2003-2013
43.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
43.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
43.11 *
43.12 @@ -149,7 +149,7 @@
43.13 /// \ingroup shortest_path
43.14 /// This class provides an efficient implementation of the Bellman-Ford
43.15 /// algorithm. The maximum time complexity of the algorithm is
43.16 - /// <tt>O(ne)</tt>.
43.17 + /// <tt>O(nm)</tt>.
43.18 ///
43.19 /// The Bellman-Ford algorithm solves the single-source shortest path
43.20 /// problem when the arcs can have negative lengths, but the digraph
43.21 @@ -200,11 +200,12 @@
43.22 typedef typename TR::DistMap DistMap;
43.23 /// The type of the paths.
43.24 typedef PredMapPath<Digraph, PredMap> Path;
43.25 - ///\brief The \ref BellmanFordDefaultOperationTraits
43.26 + ///\brief The \ref lemon::BellmanFordDefaultOperationTraits
43.27 /// "operation traits class" of the algorithm.
43.28 typedef typename TR::OperationTraits OperationTraits;
43.29
43.30 - ///The \ref BellmanFordDefaultTraits "traits class" of the algorithm.
43.31 + ///\brief The \ref lemon::BellmanFordDefaultTraits "traits class"
43.32 + ///of the algorithm.
43.33 typedef TR Traits;
43.34
43.35 private:
44.1 --- a/lemon/bfs.h Mon Jul 16 16:21:40 2018 +0200
44.2 +++ b/lemon/bfs.h Wed Oct 17 19:14:07 2018 +0200
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-2010
44.8 + * Copyright (C) 2003-2013
44.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
44.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
44.11 *
44.12 @@ -152,7 +152,7 @@
44.13 ///The type of the paths.
44.14 typedef PredMapPath<Digraph, PredMap> Path;
44.15
44.16 - ///The \ref BfsDefaultTraits "traits class" of the algorithm.
44.17 + ///The \ref lemon::BfsDefaultTraits "traits class" of the algorithm.
44.18 typedef TR Traits;
44.19
44.20 private:
45.1 --- a/lemon/bin_heap.h Mon Jul 16 16:21:40 2018 +0200
45.2 +++ b/lemon/bin_heap.h Wed Oct 17 19:14:07 2018 +0200
45.3 @@ -2,7 +2,7 @@
45.4 *
45.5 * This file is a part of LEMON, a generic C++ optimization library.
45.6 *
45.7 - * Copyright (C) 2003-2009
45.8 + * Copyright (C) 2003-2013
45.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
45.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
45.11 *
46.1 --- a/lemon/bits/alteration_notifier.h Mon Jul 16 16:21:40 2018 +0200
46.2 +++ b/lemon/bits/alteration_notifier.h Wed Oct 17 19:14:07 2018 +0200
46.3 @@ -2,7 +2,7 @@
46.4 *
46.5 * This file is a part of LEMON, a generic C++ optimization library.
46.6 *
46.7 - * Copyright (C) 2003-2009
46.8 + * Copyright (C) 2003-2013
46.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
46.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
46.11 *
46.12 @@ -23,6 +23,7 @@
46.13 #include <list>
46.14
46.15 #include <lemon/core.h>
46.16 +#include <lemon/bits/lock.h>
46.17
46.18 //\ingroup graphbits
46.19 //\file
46.20 @@ -251,7 +252,7 @@
46.21
46.22 typedef std::list<ObserverBase*> Observers;
46.23 Observers _observers;
46.24 -
46.25 + lemon::bits::Lock _lock;
46.26
46.27 public:
46.28
46.29 @@ -332,14 +333,18 @@
46.30 protected:
46.31
46.32 void attach(ObserverBase& observer) {
46.33 + _lock.lock();
46.34 observer._index = _observers.insert(_observers.begin(), &observer);
46.35 observer._notifier = this;
46.36 + _lock.unlock();
46.37 }
46.38
46.39 void detach(ObserverBase& observer) {
46.40 + _lock.lock();
46.41 _observers.erase(observer._index);
46.42 observer._index = _observers.end();
46.43 observer._notifier = 0;
46.44 + _lock.unlock();
46.45 }
46.46
46.47 public:
47.1 --- a/lemon/bits/array_map.h Mon Jul 16 16:21:40 2018 +0200
47.2 +++ b/lemon/bits/array_map.h Wed Oct 17 19:14:07 2018 +0200
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-2010
47.8 + * Copyright (C) 2003-2013
47.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
47.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
47.11 *
48.1 --- a/lemon/bits/bezier.h Mon Jul 16 16:21:40 2018 +0200
48.2 +++ b/lemon/bits/bezier.h Wed Oct 17 19:14:07 2018 +0200
48.3 @@ -2,7 +2,7 @@
48.4 *
48.5 * This file is a part of LEMON, a generic C++ optimization library.
48.6 *
48.7 - * Copyright (C) 2003-2009
48.8 + * Copyright (C) 2003-2013
48.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
48.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
48.11 *
49.1 --- a/lemon/bits/default_map.h Mon Jul 16 16:21:40 2018 +0200
49.2 +++ b/lemon/bits/default_map.h Wed Oct 17 19:14:07 2018 +0200
49.3 @@ -2,7 +2,7 @@
49.4 *
49.5 * This file is a part of LEMON, a generic C++ optimization library.
49.6 *
49.7 - * Copyright (C) 2003-2010
49.8 + * Copyright (C) 2003-2013
49.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
49.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
49.11 *
50.1 --- a/lemon/bits/edge_set_extender.h Mon Jul 16 16:21:40 2018 +0200
50.2 +++ b/lemon/bits/edge_set_extender.h Wed Oct 17 19:14:07 2018 +0200
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-2010
50.8 + * Copyright (C) 2003-2013
50.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
50.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
50.11 *
51.1 --- a/lemon/bits/graph_adaptor_extender.h Mon Jul 16 16:21:40 2018 +0200
51.2 +++ b/lemon/bits/graph_adaptor_extender.h Wed Oct 17 19:14:07 2018 +0200
51.3 @@ -2,7 +2,7 @@
51.4 *
51.5 * This file is a part of LEMON, a generic C++ optimization library.
51.6 *
51.7 - * Copyright (C) 2003-2009
51.8 + * Copyright (C) 2003-2013
51.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
51.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
51.11 *
52.1 --- a/lemon/bits/graph_extender.h Mon Jul 16 16:21:40 2018 +0200
52.2 +++ b/lemon/bits/graph_extender.h Wed Oct 17 19:14:07 2018 +0200
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-2013
52.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
52.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
52.11 *
52.12 @@ -746,6 +746,587 @@
52.13
52.14 };
52.15
52.16 + // \ingroup _graphbits
52.17 + //
52.18 + // \brief Extender for the BpGraphs
52.19 + template <typename Base>
52.20 + class BpGraphExtender : public Base {
52.21 + typedef Base Parent;
52.22 +
52.23 + public:
52.24 +
52.25 + typedef BpGraphExtender BpGraph;
52.26 +
52.27 + typedef True UndirectedTag;
52.28 +
52.29 + typedef typename Parent::Node Node;
52.30 + typedef typename Parent::RedNode RedNode;
52.31 + typedef typename Parent::BlueNode BlueNode;
52.32 + typedef typename Parent::Arc Arc;
52.33 + typedef typename Parent::Edge Edge;
52.34 +
52.35 + // BpGraph extension
52.36 +
52.37 + using Parent::first;
52.38 + using Parent::next;
52.39 + using Parent::id;
52.40 +
52.41 + int maxId(Node) const {
52.42 + return Parent::maxNodeId();
52.43 + }
52.44 +
52.45 + int maxId(RedNode) const {
52.46 + return Parent::maxRedId();
52.47 + }
52.48 +
52.49 + int maxId(BlueNode) const {
52.50 + return Parent::maxBlueId();
52.51 + }
52.52 +
52.53 + int maxId(Arc) const {
52.54 + return Parent::maxArcId();
52.55 + }
52.56 +
52.57 + int maxId(Edge) const {
52.58 + return Parent::maxEdgeId();
52.59 + }
52.60 +
52.61 + static Node fromId(int id, Node) {
52.62 + return Parent::nodeFromId(id);
52.63 + }
52.64 +
52.65 + static Arc fromId(int id, Arc) {
52.66 + return Parent::arcFromId(id);
52.67 + }
52.68 +
52.69 + static Edge fromId(int id, Edge) {
52.70 + return Parent::edgeFromId(id);
52.71 + }
52.72 +
52.73 + Node u(Edge e) const { return this->redNode(e); }
52.74 + Node v(Edge e) const { return this->blueNode(e); }
52.75 +
52.76 + Node oppositeNode(const Node &n, const Edge &e) const {
52.77 + if( n == u(e))
52.78 + return v(e);
52.79 + else if( n == v(e))
52.80 + return u(e);
52.81 + else
52.82 + return INVALID;
52.83 + }
52.84 +
52.85 + Arc oppositeArc(const Arc &arc) const {
52.86 + return Parent::direct(arc, !Parent::direction(arc));
52.87 + }
52.88 +
52.89 + using Parent::direct;
52.90 + Arc direct(const Edge &edge, const Node &node) const {
52.91 + return Parent::direct(edge, Parent::redNode(edge) == node);
52.92 + }
52.93 +
52.94 + RedNode asRedNode(const Node& node) const {
52.95 + if (node == INVALID || Parent::blue(node)) {
52.96 + return INVALID;
52.97 + } else {
52.98 + return Parent::asRedNodeUnsafe(node);
52.99 + }
52.100 + }
52.101 +
52.102 + BlueNode asBlueNode(const Node& node) const {
52.103 + if (node == INVALID || Parent::red(node)) {
52.104 + return INVALID;
52.105 + } else {
52.106 + return Parent::asBlueNodeUnsafe(node);
52.107 + }
52.108 + }
52.109 +
52.110 + // Alterable extension
52.111 +
52.112 + typedef AlterationNotifier<BpGraphExtender, Node> NodeNotifier;
52.113 + typedef AlterationNotifier<BpGraphExtender, RedNode> RedNodeNotifier;
52.114 + typedef AlterationNotifier<BpGraphExtender, BlueNode> BlueNodeNotifier;
52.115 + typedef AlterationNotifier<BpGraphExtender, Arc> ArcNotifier;
52.116 + typedef AlterationNotifier<BpGraphExtender, Edge> EdgeNotifier;
52.117 +
52.118 +
52.119 + protected:
52.120 +
52.121 + mutable NodeNotifier node_notifier;
52.122 + mutable RedNodeNotifier red_node_notifier;
52.123 + mutable BlueNodeNotifier blue_node_notifier;
52.124 + mutable ArcNotifier arc_notifier;
52.125 + mutable EdgeNotifier edge_notifier;
52.126 +
52.127 + public:
52.128 +
52.129 + NodeNotifier& notifier(Node) const {
52.130 + return node_notifier;
52.131 + }
52.132 +
52.133 + RedNodeNotifier& notifier(RedNode) const {
52.134 + return red_node_notifier;
52.135 + }
52.136 +
52.137 + BlueNodeNotifier& notifier(BlueNode) const {
52.138 + return blue_node_notifier;
52.139 + }
52.140 +
52.141 + ArcNotifier& notifier(Arc) const {
52.142 + return arc_notifier;
52.143 + }
52.144 +
52.145 + EdgeNotifier& notifier(Edge) const {
52.146 + return edge_notifier;
52.147 + }
52.148 +
52.149 +
52.150 +
52.151 + class NodeIt : public Node {
52.152 + const BpGraph* _graph;
52.153 + public:
52.154 +
52.155 + NodeIt() {}
52.156 +
52.157 + NodeIt(Invalid i) : Node(i) { }
52.158 +
52.159 + explicit NodeIt(const BpGraph& graph) : _graph(&graph) {
52.160 + _graph->first(static_cast<Node&>(*this));
52.161 + }
52.162 +
52.163 + NodeIt(const BpGraph& graph, const Node& node)
52.164 + : Node(node), _graph(&graph) {}
52.165 +
52.166 + NodeIt& operator++() {
52.167 + _graph->next(*this);
52.168 + return *this;
52.169 + }
52.170 +
52.171 + };
52.172 +
52.173 + class RedNodeIt : public RedNode {
52.174 + const BpGraph* _graph;
52.175 + public:
52.176 +
52.177 + RedNodeIt() {}
52.178 +
52.179 + RedNodeIt(Invalid i) : RedNode(i) { }
52.180 +
52.181 + explicit RedNodeIt(const BpGraph& graph) : _graph(&graph) {
52.182 + _graph->first(static_cast<RedNode&>(*this));
52.183 + }
52.184 +
52.185 + RedNodeIt(const BpGraph& graph, const RedNode& node)
52.186 + : RedNode(node), _graph(&graph) {}
52.187 +
52.188 + RedNodeIt& operator++() {
52.189 + _graph->next(static_cast<RedNode&>(*this));
52.190 + return *this;
52.191 + }
52.192 +
52.193 + };
52.194 +
52.195 + class BlueNodeIt : public BlueNode {
52.196 + const BpGraph* _graph;
52.197 + public:
52.198 +
52.199 + BlueNodeIt() {}
52.200 +
52.201 + BlueNodeIt(Invalid i) : BlueNode(i) { }
52.202 +
52.203 + explicit BlueNodeIt(const BpGraph& graph) : _graph(&graph) {
52.204 + _graph->first(static_cast<BlueNode&>(*this));
52.205 + }
52.206 +
52.207 + BlueNodeIt(const BpGraph& graph, const BlueNode& node)
52.208 + : BlueNode(node), _graph(&graph) {}
52.209 +
52.210 + BlueNodeIt& operator++() {
52.211 + _graph->next(static_cast<BlueNode&>(*this));
52.212 + return *this;
52.213 + }
52.214 +
52.215 + };
52.216 +
52.217 +
52.218 + class ArcIt : public Arc {
52.219 + const BpGraph* _graph;
52.220 + public:
52.221 +
52.222 + ArcIt() { }
52.223 +
52.224 + ArcIt(Invalid i) : Arc(i) { }
52.225 +
52.226 + explicit ArcIt(const BpGraph& graph) : _graph(&graph) {
52.227 + _graph->first(static_cast<Arc&>(*this));
52.228 + }
52.229 +
52.230 + ArcIt(const BpGraph& graph, const Arc& arc) :
52.231 + Arc(arc), _graph(&graph) { }
52.232 +
52.233 + ArcIt& operator++() {
52.234 + _graph->next(*this);
52.235 + return *this;
52.236 + }
52.237 +
52.238 + };
52.239 +
52.240 +
52.241 + class OutArcIt : public Arc {
52.242 + const BpGraph* _graph;
52.243 + public:
52.244 +
52.245 + OutArcIt() { }
52.246 +
52.247 + OutArcIt(Invalid i) : Arc(i) { }
52.248 +
52.249 + OutArcIt(const BpGraph& graph, const Node& node)
52.250 + : _graph(&graph) {
52.251 + _graph->firstOut(*this, node);
52.252 + }
52.253 +
52.254 + OutArcIt(const BpGraph& graph, const Arc& arc)
52.255 + : Arc(arc), _graph(&graph) {}
52.256 +
52.257 + OutArcIt& operator++() {
52.258 + _graph->nextOut(*this);
52.259 + return *this;
52.260 + }
52.261 +
52.262 + };
52.263 +
52.264 +
52.265 + class InArcIt : public Arc {
52.266 + const BpGraph* _graph;
52.267 + public:
52.268 +
52.269 + InArcIt() { }
52.270 +
52.271 + InArcIt(Invalid i) : Arc(i) { }
52.272 +
52.273 + InArcIt(const BpGraph& graph, const Node& node)
52.274 + : _graph(&graph) {
52.275 + _graph->firstIn(*this, node);
52.276 + }
52.277 +
52.278 + InArcIt(const BpGraph& graph, const Arc& arc) :
52.279 + Arc(arc), _graph(&graph) {}
52.280 +
52.281 + InArcIt& operator++() {
52.282 + _graph->nextIn(*this);
52.283 + return *this;
52.284 + }
52.285 +
52.286 + };
52.287 +
52.288 +
52.289 + class EdgeIt : public Parent::Edge {
52.290 + const BpGraph* _graph;
52.291 + public:
52.292 +
52.293 + EdgeIt() { }
52.294 +
52.295 + EdgeIt(Invalid i) : Edge(i) { }
52.296 +
52.297 + explicit EdgeIt(const BpGraph& graph) : _graph(&graph) {
52.298 + _graph->first(static_cast<Edge&>(*this));
52.299 + }
52.300 +
52.301 + EdgeIt(const BpGraph& graph, const Edge& edge) :
52.302 + Edge(edge), _graph(&graph) { }
52.303 +
52.304 + EdgeIt& operator++() {
52.305 + _graph->next(*this);
52.306 + return *this;
52.307 + }
52.308 +
52.309 + };
52.310 +
52.311 + class IncEdgeIt : public Parent::Edge {
52.312 + friend class BpGraphExtender;
52.313 + const BpGraph* _graph;
52.314 + bool _direction;
52.315 + public:
52.316 +
52.317 + IncEdgeIt() { }
52.318 +
52.319 + IncEdgeIt(Invalid i) : Edge(i), _direction(false) { }
52.320 +
52.321 + IncEdgeIt(const BpGraph& graph, const Node &node) : _graph(&graph) {
52.322 + _graph->firstInc(*this, _direction, node);
52.323 + }
52.324 +
52.325 + IncEdgeIt(const BpGraph& graph, const Edge &edge, const Node &node)
52.326 + : _graph(&graph), Edge(edge) {
52.327 + _direction = (_graph->source(edge) == node);
52.328 + }
52.329 +
52.330 + IncEdgeIt& operator++() {
52.331 + _graph->nextInc(*this, _direction);
52.332 + return *this;
52.333 + }
52.334 + };
52.335 +
52.336 + // \brief Base node of the iterator
52.337 + //
52.338 + // Returns the base node (ie. the source in this case) of the iterator
52.339 + Node baseNode(const OutArcIt &arc) const {
52.340 + return Parent::source(static_cast<const Arc&>(arc));
52.341 + }
52.342 + // \brief Running node of the iterator
52.343 + //
52.344 + // Returns the running node (ie. the target in this case) of the
52.345 + // iterator
52.346 + Node runningNode(const OutArcIt &arc) const {
52.347 + return Parent::target(static_cast<const Arc&>(arc));
52.348 + }
52.349 +
52.350 + // \brief Base node of the iterator
52.351 + //
52.352 + // Returns the base node (ie. the target in this case) of the iterator
52.353 + Node baseNode(const InArcIt &arc) const {
52.354 + return Parent::target(static_cast<const Arc&>(arc));
52.355 + }
52.356 + // \brief Running node of the iterator
52.357 + //
52.358 + // Returns the running node (ie. the source in this case) of the
52.359 + // iterator
52.360 + Node runningNode(const InArcIt &arc) const {
52.361 + return Parent::source(static_cast<const Arc&>(arc));
52.362 + }
52.363 +
52.364 + // Base node of the iterator
52.365 + //
52.366 + // Returns the base node of the iterator
52.367 + Node baseNode(const IncEdgeIt &edge) const {
52.368 + return edge._direction ? this->u(edge) : this->v(edge);
52.369 + }
52.370 + // Running node of the iterator
52.371 + //
52.372 + // Returns the running node of the iterator
52.373 + Node runningNode(const IncEdgeIt &edge) const {
52.374 + return edge._direction ? this->v(edge) : this->u(edge);
52.375 + }
52.376 +
52.377 + // Mappable extension
52.378 +
52.379 + template <typename _Value>
52.380 + class NodeMap
52.381 + : public MapExtender<DefaultMap<BpGraph, Node, _Value> > {
52.382 + typedef MapExtender<DefaultMap<BpGraph, Node, _Value> > Parent;
52.383 +
52.384 + public:
52.385 + explicit NodeMap(const BpGraph& bpgraph)
52.386 + : Parent(bpgraph) {}
52.387 + NodeMap(const BpGraph& bpgraph, const _Value& value)
52.388 + : Parent(bpgraph, value) {}
52.389 +
52.390 + private:
52.391 + NodeMap& operator=(const NodeMap& cmap) {
52.392 + return operator=<NodeMap>(cmap);
52.393 + }
52.394 +
52.395 + template <typename CMap>
52.396 + NodeMap& operator=(const CMap& cmap) {
52.397 + Parent::operator=(cmap);
52.398 + return *this;
52.399 + }
52.400 +
52.401 + };
52.402 +
52.403 + template <typename _Value>
52.404 + class RedNodeMap
52.405 + : public MapExtender<DefaultMap<BpGraph, RedNode, _Value> > {
52.406 + typedef MapExtender<DefaultMap<BpGraph, RedNode, _Value> > Parent;
52.407 +
52.408 + public:
52.409 + explicit RedNodeMap(const BpGraph& bpgraph)
52.410 + : Parent(bpgraph) {}
52.411 + RedNodeMap(const BpGraph& bpgraph, const _Value& value)
52.412 + : Parent(bpgraph, value) {}
52.413 +
52.414 + private:
52.415 + RedNodeMap& operator=(const RedNodeMap& cmap) {
52.416 + return operator=<RedNodeMap>(cmap);
52.417 + }
52.418 +
52.419 + template <typename CMap>
52.420 + RedNodeMap& operator=(const CMap& cmap) {
52.421 + Parent::operator=(cmap);
52.422 + return *this;
52.423 + }
52.424 +
52.425 + };
52.426 +
52.427 + template <typename _Value>
52.428 + class BlueNodeMap
52.429 + : public MapExtender<DefaultMap<BpGraph, BlueNode, _Value> > {
52.430 + typedef MapExtender<DefaultMap<BpGraph, BlueNode, _Value> > Parent;
52.431 +
52.432 + public:
52.433 + explicit BlueNodeMap(const BpGraph& bpgraph)
52.434 + : Parent(bpgraph) {}
52.435 + BlueNodeMap(const BpGraph& bpgraph, const _Value& value)
52.436 + : Parent(bpgraph, value) {}
52.437 +
52.438 + private:
52.439 + BlueNodeMap& operator=(const BlueNodeMap& cmap) {
52.440 + return operator=<BlueNodeMap>(cmap);
52.441 + }
52.442 +
52.443 + template <typename CMap>
52.444 + BlueNodeMap& operator=(const CMap& cmap) {
52.445 + Parent::operator=(cmap);
52.446 + return *this;
52.447 + }
52.448 +
52.449 + };
52.450 +
52.451 + template <typename _Value>
52.452 + class ArcMap
52.453 + : public MapExtender<DefaultMap<BpGraph, Arc, _Value> > {
52.454 + typedef MapExtender<DefaultMap<BpGraph, Arc, _Value> > Parent;
52.455 +
52.456 + public:
52.457 + explicit ArcMap(const BpGraph& graph)
52.458 + : Parent(graph) {}
52.459 + ArcMap(const BpGraph& graph, const _Value& value)
52.460 + : Parent(graph, value) {}
52.461 +
52.462 + private:
52.463 + ArcMap& operator=(const ArcMap& cmap) {
52.464 + return operator=<ArcMap>(cmap);
52.465 + }
52.466 +
52.467 + template <typename CMap>
52.468 + ArcMap& operator=(const CMap& cmap) {
52.469 + Parent::operator=(cmap);
52.470 + return *this;
52.471 + }
52.472 + };
52.473 +
52.474 +
52.475 + template <typename _Value>
52.476 + class EdgeMap
52.477 + : public MapExtender<DefaultMap<BpGraph, Edge, _Value> > {
52.478 + typedef MapExtender<DefaultMap<BpGraph, Edge, _Value> > Parent;
52.479 +
52.480 + public:
52.481 + explicit EdgeMap(const BpGraph& graph)
52.482 + : Parent(graph) {}
52.483 +
52.484 + EdgeMap(const BpGraph& graph, const _Value& value)
52.485 + : Parent(graph, value) {}
52.486 +
52.487 + private:
52.488 + EdgeMap& operator=(const EdgeMap& cmap) {
52.489 + return operator=<EdgeMap>(cmap);
52.490 + }
52.491 +
52.492 + template <typename CMap>
52.493 + EdgeMap& operator=(const CMap& cmap) {
52.494 + Parent::operator=(cmap);
52.495 + return *this;
52.496 + }
52.497 +
52.498 + };
52.499 +
52.500 + // Alteration extension
52.501 +
52.502 + RedNode addRedNode() {
52.503 + RedNode node = Parent::addRedNode();
52.504 + notifier(RedNode()).add(node);
52.505 + notifier(Node()).add(node);
52.506 + return node;
52.507 + }
52.508 +
52.509 + BlueNode addBlueNode() {
52.510 + BlueNode node = Parent::addBlueNode();
52.511 + notifier(BlueNode()).add(node);
52.512 + notifier(Node()).add(node);
52.513 + return node;
52.514 + }
52.515 +
52.516 + Edge addEdge(const RedNode& from, const BlueNode& to) {
52.517 + Edge edge = Parent::addEdge(from, to);
52.518 + notifier(Edge()).add(edge);
52.519 + std::vector<Arc> av;
52.520 + av.push_back(Parent::direct(edge, true));
52.521 + av.push_back(Parent::direct(edge, false));
52.522 + notifier(Arc()).add(av);
52.523 + return edge;
52.524 + }
52.525 +
52.526 + void clear() {
52.527 + notifier(Arc()).clear();
52.528 + notifier(Edge()).clear();
52.529 + notifier(Node()).clear();
52.530 + notifier(BlueNode()).clear();
52.531 + notifier(RedNode()).clear();
52.532 + Parent::clear();
52.533 + }
52.534 +
52.535 + template <typename BpGraph, typename NodeRefMap, typename EdgeRefMap>
52.536 + void build(const BpGraph& graph, NodeRefMap& nodeRef,
52.537 + EdgeRefMap& edgeRef) {
52.538 + Parent::build(graph, nodeRef, edgeRef);
52.539 + notifier(RedNode()).build();
52.540 + notifier(BlueNode()).build();
52.541 + notifier(Node()).build();
52.542 + notifier(Edge()).build();
52.543 + notifier(Arc()).build();
52.544 + }
52.545 +
52.546 + void erase(const Node& node) {
52.547 + Arc arc;
52.548 + Parent::firstOut(arc, node);
52.549 + while (arc != INVALID ) {
52.550 + erase(arc);
52.551 + Parent::firstOut(arc, node);
52.552 + }
52.553 +
52.554 + Parent::firstIn(arc, node);
52.555 + while (arc != INVALID ) {
52.556 + erase(arc);
52.557 + Parent::firstIn(arc, node);
52.558 + }
52.559 +
52.560 + if (Parent::red(node)) {
52.561 + notifier(RedNode()).erase(this->asRedNodeUnsafe(node));
52.562 + } else {
52.563 + notifier(BlueNode()).erase(this->asBlueNodeUnsafe(node));
52.564 + }
52.565 +
52.566 + notifier(Node()).erase(node);
52.567 + Parent::erase(node);
52.568 + }
52.569 +
52.570 + void erase(const Edge& edge) {
52.571 + std::vector<Arc> av;
52.572 + av.push_back(Parent::direct(edge, true));
52.573 + av.push_back(Parent::direct(edge, false));
52.574 + notifier(Arc()).erase(av);
52.575 + notifier(Edge()).erase(edge);
52.576 + Parent::erase(edge);
52.577 + }
52.578 +
52.579 + BpGraphExtender() {
52.580 + red_node_notifier.setContainer(*this);
52.581 + blue_node_notifier.setContainer(*this);
52.582 + node_notifier.setContainer(*this);
52.583 + arc_notifier.setContainer(*this);
52.584 + edge_notifier.setContainer(*this);
52.585 + }
52.586 +
52.587 + ~BpGraphExtender() {
52.588 + edge_notifier.clear();
52.589 + arc_notifier.clear();
52.590 + node_notifier.clear();
52.591 + blue_node_notifier.clear();
52.592 + red_node_notifier.clear();
52.593 + }
52.594 +
52.595 + };
52.596 +
52.597 }
52.598
52.599 #endif
53.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
53.2 +++ b/lemon/bits/lock.h Wed Oct 17 19:14:07 2018 +0200
53.3 @@ -0,0 +1,65 @@
53.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
53.5 + *
53.6 + * This file is a part of LEMON, a generic C++ optimization library.
53.7 + *
53.8 + * Copyright (C) 2003-2013
53.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
53.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
53.11 + *
53.12 + * Permission to use, modify and distribute this software is granted
53.13 + * provided that this copyright notice appears in all copies. For
53.14 + * precise terms see the accompanying LICENSE file.
53.15 + *
53.16 + * This software is provided "AS IS" with no warranty of any kind,
53.17 + * express or implied, and with no claim as to its suitability for any
53.18 + * purpose.
53.19 + *
53.20 + */
53.21 +
53.22 +#ifndef LEMON_BITS_LOCK_H
53.23 +#define LEMON_BITS_LOCK_H
53.24 +
53.25 +#include <lemon/config.h>
53.26 +#if defined(LEMON_USE_PTHREAD)
53.27 +#include <pthread.h>
53.28 +#elif defined(LEMON_USE_WIN32_THREADS)
53.29 +#include <lemon/bits/windows.h>
53.30 +#endif
53.31 +
53.32 +namespace lemon {
53.33 + namespace bits {
53.34 +
53.35 +#if defined(LEMON_USE_PTHREAD)
53.36 + class Lock {
53.37 + public:
53.38 + Lock() {
53.39 + pthread_mutex_init(&_lock, 0);
53.40 + }
53.41 + ~Lock() {
53.42 + pthread_mutex_destroy(&_lock);
53.43 + }
53.44 + void lock() {
53.45 + pthread_mutex_lock(&_lock);
53.46 + }
53.47 + void unlock() {
53.48 + pthread_mutex_unlock(&_lock);
53.49 + }
53.50 +
53.51 + private:
53.52 + pthread_mutex_t _lock;
53.53 + };
53.54 +#elif defined(LEMON_USE_WIN32_THREADS)
53.55 + class Lock : public WinLock {};
53.56 +#else
53.57 + class Lock {
53.58 + public:
53.59 + Lock() {}
53.60 + ~Lock() {}
53.61 + void lock() {}
53.62 + void unlock() {}
53.63 + };
53.64 +#endif
53.65 + }
53.66 +}
53.67 +
53.68 +#endif
54.1 --- a/lemon/bits/map_extender.h Mon Jul 16 16:21:40 2018 +0200
54.2 +++ b/lemon/bits/map_extender.h Wed Oct 17 19:14:07 2018 +0200
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-2013
54.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
54.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
54.11 *
55.1 --- a/lemon/bits/path_dump.h Mon Jul 16 16:21:40 2018 +0200
55.2 +++ b/lemon/bits/path_dump.h Wed Oct 17 19:14:07 2018 +0200
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-2009
55.8 + * Copyright (C) 2003-2013
55.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
55.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
55.11 *
56.1 --- a/lemon/bits/solver_bits.h Mon Jul 16 16:21:40 2018 +0200
56.2 +++ b/lemon/bits/solver_bits.h Wed Oct 17 19:14:07 2018 +0200
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-2010
56.8 + * Copyright (C) 2003-2013
56.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
56.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
56.11 *
57.1 --- a/lemon/bits/traits.h Mon Jul 16 16:21:40 2018 +0200
57.2 +++ b/lemon/bits/traits.h Wed Oct 17 19:14:07 2018 +0200
57.3 @@ -2,7 +2,7 @@
57.4 *
57.5 * This file is a part of LEMON, a generic C++ optimization library.
57.6 *
57.7 - * Copyright (C) 2003-2009
57.8 + * Copyright (C) 2003-2013
57.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
57.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
57.11 *
57.12 @@ -151,6 +151,88 @@
57.13
57.14 };
57.15
57.16 + template <typename GR, typename Enable = void>
57.17 + struct RedNodeNotifierIndicator {
57.18 + typedef InvalidType Type;
57.19 + };
57.20 + template <typename GR>
57.21 + struct RedNodeNotifierIndicator<
57.22 + GR,
57.23 + typename enable_if<typename GR::RedNodeNotifier::Notifier, void>::type
57.24 + > {
57.25 + typedef typename GR::RedNodeNotifier Type;
57.26 + };
57.27 +
57.28 + template <typename GR>
57.29 + class ItemSetTraits<GR, typename GR::RedNode> {
57.30 + public:
57.31 +
57.32 + typedef GR BpGraph;
57.33 + typedef GR Graph;
57.34 + typedef GR Digraph;
57.35 +
57.36 + typedef typename GR::RedNode Item;
57.37 + typedef typename GR::RedNodeIt ItemIt;
57.38 +
57.39 + typedef typename RedNodeNotifierIndicator<GR>::Type ItemNotifier;
57.40 +
57.41 + template <typename V>
57.42 + class Map : public GR::template RedNodeMap<V> {
57.43 + typedef typename GR::template RedNodeMap<V> Parent;
57.44 +
57.45 + public:
57.46 + typedef typename GR::template RedNodeMap<V> Type;
57.47 + typedef typename Parent::Value Value;
57.48 +
57.49 + Map(const GR& _bpgraph) : Parent(_bpgraph) {}
57.50 + Map(const GR& _bpgraph, const Value& _value)
57.51 + : Parent(_bpgraph, _value) {}
57.52 +
57.53 + };
57.54 +
57.55 + };
57.56 +
57.57 + template <typename GR, typename Enable = void>
57.58 + struct BlueNodeNotifierIndicator {
57.59 + typedef InvalidType Type;
57.60 + };
57.61 + template <typename GR>
57.62 + struct BlueNodeNotifierIndicator<
57.63 + GR,
57.64 + typename enable_if<typename GR::BlueNodeNotifier::Notifier, void>::type
57.65 + > {
57.66 + typedef typename GR::BlueNodeNotifier Type;
57.67 + };
57.68 +
57.69 + template <typename GR>
57.70 + class ItemSetTraits<GR, typename GR::BlueNode> {
57.71 + public:
57.72 +
57.73 + typedef GR BpGraph;
57.74 + typedef GR Graph;
57.75 + typedef GR Digraph;
57.76 +
57.77 + typedef typename GR::BlueNode Item;
57.78 + typedef typename GR::BlueNodeIt ItemIt;
57.79 +
57.80 + typedef typename BlueNodeNotifierIndicator<GR>::Type ItemNotifier;
57.81 +
57.82 + template <typename V>
57.83 + class Map : public GR::template BlueNodeMap<V> {
57.84 + typedef typename GR::template BlueNodeMap<V> Parent;
57.85 +
57.86 + public:
57.87 + typedef typename GR::template BlueNodeMap<V> Type;
57.88 + typedef typename Parent::Value Value;
57.89 +
57.90 + Map(const GR& _bpgraph) : Parent(_bpgraph) {}
57.91 + Map(const GR& _bpgraph, const Value& _value)
57.92 + : Parent(_bpgraph, _value) {}
57.93 +
57.94 + };
57.95 +
57.96 + };
57.97 +
57.98 template <typename Map, typename Enable = void>
57.99 struct MapTraits {
57.100 typedef False ReferenceMapTag;
58.1 --- a/lemon/bits/windows.cc Mon Jul 16 16:21:40 2018 +0200
58.2 +++ b/lemon/bits/windows.cc Wed Oct 17 19:14:07 2018 +0200
58.3 @@ -2,7 +2,7 @@
58.4 *
58.5 * This file is a part of LEMON, a generic C++ optimization library.
58.6 *
58.7 - * Copyright (C) 2003-2010
58.8 + * Copyright (C) 2003-2013
58.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
58.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
58.11 *
58.12 @@ -21,7 +21,11 @@
58.13
58.14 #include<lemon/bits/windows.h>
58.15
58.16 -#ifdef WIN32
58.17 +#if defined(LEMON_WIN32) && defined(__GNUC__)
58.18 +#pragma GCC diagnostic ignored "-Wold-style-cast"
58.19 +#endif
58.20 +
58.21 +#ifdef LEMON_WIN32
58.22 #ifndef WIN32_LEAN_AND_MEAN
58.23 #define WIN32_LEAN_AND_MEAN
58.24 #endif
58.25 @@ -40,7 +44,7 @@
58.26 #else
58.27 #include <unistd.h>
58.28 #include <ctime>
58.29 -#ifndef WIN32
58.30 +#ifndef LEMON_WIN32
58.31 #include <sys/times.h>
58.32 #endif
58.33 #include <sys/time.h>
58.34 @@ -55,7 +59,7 @@
58.35 double &utime, double &stime,
58.36 double &cutime, double &cstime)
58.37 {
58.38 -#ifdef WIN32
58.39 +#ifdef LEMON_WIN32
58.40 static const double ch = 4294967296.0e-7;
58.41 static const double cl = 1.0e-7;
58.42
58.43 @@ -94,11 +98,11 @@
58.44 std::string getWinFormattedDate()
58.45 {
58.46 std::ostringstream os;
58.47 -#ifdef WIN32
58.48 +#ifdef LEMON_WIN32
58.49 SYSTEMTIME time;
58.50 GetSystemTime(&time);
58.51 char buf1[11], buf2[9], buf3[5];
58.52 - if (GetDateFormat(MY_LOCALE, 0, &time,
58.53 + if (GetDateFormat(MY_LOCALE, 0, &time,
58.54 ("ddd MMM dd"), buf1, 11) &&
58.55 GetTimeFormat(MY_LOCALE, 0, &time,
58.56 ("HH':'mm':'ss"), buf2, 9) &&
58.57 @@ -120,7 +124,7 @@
58.58
58.59 int getWinRndSeed()
58.60 {
58.61 -#ifdef WIN32
58.62 +#ifdef LEMON_WIN32
58.63 FILETIME time;
58.64 GetSystemTimeAsFileTime(&time);
58.65 return GetCurrentProcessId() + time.dwHighDateTime + time.dwLowDateTime;
58.66 @@ -130,5 +134,37 @@
58.67 return getpid() + tv.tv_sec + tv.tv_usec;
58.68 #endif
58.69 }
58.70 +
58.71 + WinLock::WinLock() {
58.72 +#ifdef LEMON_WIN32
58.73 + CRITICAL_SECTION *lock = new CRITICAL_SECTION;
58.74 + InitializeCriticalSection(lock);
58.75 + _repr = lock;
58.76 +#else
58.77 + _repr = 0; //Just to avoid 'unused variable' warning with clang
58.78 +#endif
58.79 + }
58.80 +
58.81 + WinLock::~WinLock() {
58.82 +#ifdef LEMON_WIN32
58.83 + CRITICAL_SECTION *lock = static_cast<CRITICAL_SECTION*>(_repr);
58.84 + DeleteCriticalSection(lock);
58.85 + delete lock;
58.86 +#endif
58.87 + }
58.88 +
58.89 + void WinLock::lock() {
58.90 +#ifdef LEMON_WIN32
58.91 + CRITICAL_SECTION *lock = static_cast<CRITICAL_SECTION*>(_repr);
58.92 + EnterCriticalSection(lock);
58.93 +#endif
58.94 + }
58.95 +
58.96 + void WinLock::unlock() {
58.97 +#ifdef LEMON_WIN32
58.98 + CRITICAL_SECTION *lock = static_cast<CRITICAL_SECTION*>(_repr);
58.99 + LeaveCriticalSection(lock);
58.100 +#endif
58.101 + }
58.102 }
58.103 }
59.1 --- a/lemon/bits/windows.h Mon Jul 16 16:21:40 2018 +0200
59.2 +++ b/lemon/bits/windows.h Wed Oct 17 19:14:07 2018 +0200
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-2013
59.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
59.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
59.11 *
59.12 @@ -19,6 +19,7 @@
59.13 #ifndef LEMON_BITS_WINDOWS_H
59.14 #define LEMON_BITS_WINDOWS_H
59.15
59.16 +#include <lemon/config.h>
59.17 #include <string>
59.18
59.19 namespace lemon {
59.20 @@ -28,6 +29,16 @@
59.21 double &cutime, double &cstime);
59.22 std::string getWinFormattedDate();
59.23 int getWinRndSeed();
59.24 +
59.25 + class WinLock {
59.26 + public:
59.27 + WinLock();
59.28 + ~WinLock();
59.29 + void lock();
59.30 + void unlock();\
59.31 + private:
59.32 + void *_repr;
59.33 + };
59.34 }
59.35 }
59.36
60.1 --- a/lemon/capacity_scaling.h Mon Jul 16 16:21:40 2018 +0200
60.2 +++ b/lemon/capacity_scaling.h Wed Oct 17 19:14:07 2018 +0200
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-2010
60.8 + * Copyright (C) 2003-2013
60.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
60.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
60.11 *
60.12 @@ -27,6 +27,7 @@
60.13 #include <vector>
60.14 #include <limits>
60.15 #include <lemon/core.h>
60.16 +#include <lemon/maps.h>
60.17 #include <lemon/bin_heap.h>
60.18
60.19 namespace lemon {
60.20 @@ -66,9 +67,16 @@
60.21 ///
60.22 /// \ref CapacityScaling implements the capacity scaling version
60.23 /// of the successive shortest path algorithm for finding a
60.24 - /// \ref min_cost_flow "minimum cost flow" \ref amo93networkflows,
60.25 - /// \ref edmondskarp72theoretical. It is an efficient dual
60.26 - /// solution method.
60.27 + /// \ref min_cost_flow "minimum cost flow" \cite amo93networkflows,
60.28 + /// \cite edmondskarp72theoretical. It is an efficient dual
60.29 + /// solution method, which runs in polynomial time
60.30 + /// \f$O(m\log U (n+m)\log n)\f$, where <i>U</i> denotes the maximum
60.31 + /// of node supply and arc capacity values.
60.32 + ///
60.33 + /// This algorithm is typically slower than \ref CostScaling and
60.34 + /// \ref NetworkSimplex, but in special cases, it can be more
60.35 + /// efficient than them.
60.36 + /// (For more information, see \ref min_cost_flow_algs "the module page".)
60.37 ///
60.38 /// Most of the parameters of the problem (except for the digraph)
60.39 /// can be given using separate functions, and the algorithm can be
60.40 @@ -86,10 +94,11 @@
60.41 /// In most cases, this parameter should not be set directly,
60.42 /// consider to use the named template parameters instead.
60.43 ///
60.44 - /// \warning Both number types must be signed and all input data must
60.45 - /// be integer.
60.46 - /// \warning This algorithm does not support negative costs for such
60.47 - /// arcs that have infinite upper bound.
60.48 + /// \warning Both \c V and \c C must be signed number types.
60.49 + /// \warning Capacity bounds and supply values must be integer, but
60.50 + /// arc costs can be arbitrary real numbers.
60.51 + /// \warning This algorithm does not support negative costs for
60.52 + /// arcs having infinite upper bound.
60.53 #ifdef DOXYGEN
60.54 template <typename GR, typename V, typename C, typename TR>
60.55 #else
60.56 @@ -110,7 +119,8 @@
60.57 /// The type of the heap used for internal Dijkstra computations
60.58 typedef typename TR::Heap Heap;
60.59
60.60 - /// The \ref CapacityScalingDefaultTraits "traits class" of the algorithm
60.61 + /// \brief The \ref lemon::CapacityScalingDefaultTraits "traits class"
60.62 + /// of the algorithm
60.63 typedef TR Traits;
60.64
60.65 public:
60.66 @@ -154,7 +164,7 @@
60.67 int _root;
60.68
60.69 // Parameters of the problem
60.70 - bool _have_lower;
60.71 + bool _has_lower;
60.72 Value _sum_supply;
60.73
60.74 // Data structures for storing the digraph
60.75 @@ -347,10 +357,9 @@
60.76 /// \return <tt>(*this)</tt>
60.77 template <typename LowerMap>
60.78 CapacityScaling& lowerMap(const LowerMap& map) {
60.79 - _have_lower = true;
60.80 + _has_lower = true;
60.81 for (ArcIt a(_graph); a != INVALID; ++a) {
60.82 _lower[_arc_idf[a]] = map[a];
60.83 - _lower[_arc_idb[a]] = map[a];
60.84 }
60.85 return *this;
60.86 }
60.87 @@ -422,7 +431,7 @@
60.88 /// calling \ref run(), the supply of each node will be set to zero.
60.89 ///
60.90 /// Using this function has the same effect as using \ref supplyMap()
60.91 - /// with such a map in which \c k is assigned to \c s, \c -k is
60.92 + /// with a map in which \c k is assigned to \c s, \c -k is
60.93 /// assigned to \c t and all other nodes have zero supply value.
60.94 ///
60.95 /// \param s The source node.
60.96 @@ -534,7 +543,7 @@
60.97 _upper[j] = INF;
60.98 _cost[j] = _forward[j] ? 1 : -1;
60.99 }
60.100 - _have_lower = false;
60.101 + _has_lower = false;
60.102 return *this;
60.103 }
60.104
60.105 @@ -637,7 +646,7 @@
60.106 /// \brief Return the total cost of the found flow.
60.107 ///
60.108 /// This function returns the total cost of the found flow.
60.109 - /// Its complexity is O(e).
60.110 + /// Its complexity is O(m).
60.111 ///
60.112 /// \note The return type of the function can be specified as a
60.113 /// template parameter. For example,
60.114 @@ -675,7 +684,8 @@
60.115 return _res_cap[_arc_idb[a]];
60.116 }
60.117
60.118 - /// \brief Return the flow map (the primal solution).
60.119 + /// \brief Copy the flow values (the primal solution) into the
60.120 + /// given map.
60.121 ///
60.122 /// This function copies the flow value on each arc into the given
60.123 /// map. The \c Value type of the algorithm must be convertible to
60.124 @@ -699,7 +709,8 @@
60.125 return _pi[_node_id[n]];
60.126 }
60.127
60.128 - /// \brief Return the potential map (the dual solution).
60.129 + /// \brief Copy the potential values (the dual solution) into the
60.130 + /// given map.
60.131 ///
60.132 /// This function copies the potential (dual value) of each node
60.133 /// into the given map.
60.134 @@ -729,6 +740,11 @@
60.135 }
60.136 if (_sum_supply > 0) return INFEASIBLE;
60.137
60.138 + // Check lower and upper bounds
60.139 + LEMON_DEBUG(checkBoundMaps(),
60.140 + "Upper bounds must be greater or equal to the lower bounds");
60.141 +
60.142 +
60.143 // Initialize vectors
60.144 for (int i = 0; i != _root; ++i) {
60.145 _pi[i] = 0;
60.146 @@ -738,7 +754,7 @@
60.147 // Remove non-zero lower bounds
60.148 const Value MAX = std::numeric_limits<Value>::max();
60.149 int last_out;
60.150 - if (_have_lower) {
60.151 + if (_has_lower) {
60.152 for (int i = 0; i != _root; ++i) {
60.153 last_out = _first_out[i+1];
60.154 for (int j = _first_out[i]; j != last_out; ++j) {
60.155 @@ -823,6 +839,15 @@
60.156 return OPTIMAL;
60.157 }
60.158
60.159 + // Check if the upper bound is greater than or equal to the lower bound
60.160 + // on each forward arc.
60.161 + bool checkBoundMaps() {
60.162 + for (int j = 0; j != _res_arc_num; ++j) {
60.163 + if (_forward[j] && _upper[j] < _lower[j]) return false;
60.164 + }
60.165 + return true;
60.166 + }
60.167 +
60.168 ProblemType start() {
60.169 // Execute the algorithm
60.170 ProblemType pt;
60.171 @@ -832,10 +857,10 @@
60.172 pt = startWithoutScaling();
60.173
60.174 // Handle non-zero lower bounds
60.175 - if (_have_lower) {
60.176 + if (_has_lower) {
60.177 int limit = _first_out[_root];
60.178 for (int j = 0; j != limit; ++j) {
60.179 - if (!_forward[j]) _res_cap[j] += _lower[j];
60.180 + if (_forward[j]) _res_cap[_reverse[j]] += _lower[j];
60.181 }
60.182 }
60.183
61.1 --- a/lemon/cbc.cc Mon Jul 16 16:21:40 2018 +0200
61.2 +++ b/lemon/cbc.cc Wed Oct 17 19:14:07 2018 +0200
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-2009
61.8 + * Copyright (C) 2003-2013
61.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
61.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
61.11 *
62.1 --- a/lemon/cbc.h Mon Jul 16 16:21:40 2018 +0200
62.2 +++ b/lemon/cbc.h Wed Oct 17 19:14:07 2018 +0200
62.3 @@ -2,7 +2,7 @@
62.4 *
62.5 * This file is a part of LEMON, a generic C++ optimization library.
62.6 *
62.7 - * Copyright (C) 2003-2010
62.8 + * Copyright (C) 2003-2013
62.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
62.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
62.11 *
62.12 @@ -16,7 +16,6 @@
62.13 *
62.14 */
62.15
62.16 -// -*- C++ -*-
62.17 #ifndef LEMON_CBC_H
62.18 #define LEMON_CBC_H
62.19
63.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
63.2 +++ b/lemon/christofides_tsp.h Wed Oct 17 19:14:07 2018 +0200
63.3 @@ -0,0 +1,254 @@
63.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
63.5 + *
63.6 + * This file is a part of LEMON, a generic C++ optimization library.
63.7 + *
63.8 + * Copyright (C) 2003-2013
63.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
63.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
63.11 + *
63.12 + * Permission to use, modify and distribute this software is granted
63.13 + * provided that this copyright notice appears in all copies. For
63.14 + * precise terms see the accompanying LICENSE file.
63.15 + *
63.16 + * This software is provided "AS IS" with no warranty of any kind,
63.17 + * express or implied, and with no claim as to its suitability for any
63.18 + * purpose.
63.19 + *
63.20 + */
63.21 +
63.22 +#ifndef LEMON_CHRISTOFIDES_TSP_H
63.23 +#define LEMON_CHRISTOFIDES_TSP_H
63.24 +
63.25 +/// \ingroup tsp
63.26 +/// \file
63.27 +/// \brief Christofides algorithm for symmetric TSP
63.28 +
63.29 +#include <lemon/full_graph.h>
63.30 +#include <lemon/smart_graph.h>
63.31 +#include <lemon/kruskal.h>
63.32 +#include <lemon/matching.h>
63.33 +#include <lemon/euler.h>
63.34 +
63.35 +namespace lemon {
63.36 +
63.37 + /// \ingroup tsp
63.38 + ///
63.39 + /// \brief Christofides algorithm for symmetric TSP.
63.40 + ///
63.41 + /// ChristofidesTsp implements Christofides' heuristic for solving
63.42 + /// symmetric \ref tsp "TSP".
63.43 + ///
63.44 + /// This a well-known approximation method for the TSP problem with
63.45 + /// metric cost function.
63.46 + /// It has a guaranteed approximation factor of 3/2 (i.e. it finds a tour
63.47 + /// whose total cost is at most 3/2 of the optimum), but it usually
63.48 + /// provides better solutions in practice.
63.49 + /// This implementation runs in O(n<sup>3</sup>log(n)) time.
63.50 + ///
63.51 + /// The algorithm starts with a \ref spantree "minimum cost spanning tree" and
63.52 + /// finds a \ref MaxWeightedPerfectMatching "minimum cost perfect matching"
63.53 + /// in the subgraph induced by the nodes that have odd degree in the
63.54 + /// spanning tree.
63.55 + /// Finally, it constructs the tour from the \ref EulerIt "Euler traversal"
63.56 + /// of the union of the spanning tree and the matching.
63.57 + /// During this last step, the algorithm simply skips the visited nodes
63.58 + /// (i.e. creates shortcuts) assuming that the triangle inequality holds
63.59 + /// for the cost function.
63.60 + ///
63.61 + /// \tparam CM Type of the cost map.
63.62 + ///
63.63 + /// \warning CM::Value must be a signed number type.
63.64 + template <typename CM>
63.65 + class ChristofidesTsp
63.66 + {
63.67 + public:
63.68 +
63.69 + /// Type of the cost map
63.70 + typedef CM CostMap;
63.71 + /// Type of the edge costs
63.72 + typedef typename CM::Value Cost;
63.73 +
63.74 + private:
63.75 +
63.76 + GRAPH_TYPEDEFS(FullGraph);
63.77 +
63.78 + const FullGraph &_gr;
63.79 + const CostMap &_cost;
63.80 + std::vector<Node> _path;
63.81 + Cost _sum;
63.82 +
63.83 + public:
63.84 +
63.85 + /// \brief Constructor
63.86 + ///
63.87 + /// Constructor.
63.88 + /// \param gr The \ref FullGraph "full graph" the algorithm runs on.
63.89 + /// \param cost The cost map.
63.90 + ChristofidesTsp(const FullGraph &gr, const CostMap &cost)
63.91 + : _gr(gr), _cost(cost) {}
63.92 +
63.93 + /// \name Execution Control
63.94 + /// @{
63.95 +
63.96 + /// \brief Runs the algorithm.
63.97 + ///
63.98 + /// This function runs the algorithm.
63.99 + ///
63.100 + /// \return The total cost of the found tour.
63.101 + Cost run() {
63.102 + _path.clear();
63.103 +
63.104 + if (_gr.nodeNum() == 0) return _sum = 0;
63.105 + else if (_gr.nodeNum() == 1) {
63.106 + _path.push_back(_gr(0));
63.107 + return _sum = 0;
63.108 + }
63.109 + else if (_gr.nodeNum() == 2) {
63.110 + _path.push_back(_gr(0));
63.111 + _path.push_back(_gr(1));
63.112 + return _sum = 2 * _cost[_gr.edge(_gr(0), _gr(1))];
63.113 + }
63.114 +
63.115 + // Compute min. cost spanning tree
63.116 + std::vector<Edge> tree;
63.117 + kruskal(_gr, _cost, std::back_inserter(tree));
63.118 +
63.119 + FullGraph::NodeMap<int> deg(_gr, 0);
63.120 + for (int i = 0; i != int(tree.size()); ++i) {
63.121 + Edge e = tree[i];
63.122 + ++deg[_gr.u(e)];
63.123 + ++deg[_gr.v(e)];
63.124 + }
63.125 +
63.126 + // Copy the induced subgraph of odd nodes
63.127 + std::vector<Node> odd_nodes;
63.128 + for (NodeIt u(_gr); u != INVALID; ++u) {
63.129 + if (deg[u] % 2 == 1) odd_nodes.push_back(u);
63.130 + }
63.131 +
63.132 + SmartGraph sgr;
63.133 + SmartGraph::EdgeMap<Cost> scost(sgr);
63.134 + for (int i = 0; i != int(odd_nodes.size()); ++i) {
63.135 + sgr.addNode();
63.136 + }
63.137 + for (int i = 0; i != int(odd_nodes.size()); ++i) {
63.138 + for (int j = 0; j != int(odd_nodes.size()); ++j) {
63.139 + if (j == i) continue;
63.140 + SmartGraph::Edge e =
63.141 + sgr.addEdge(sgr.nodeFromId(i), sgr.nodeFromId(j));
63.142 + scost[e] = -_cost[_gr.edge(odd_nodes[i], odd_nodes[j])];
63.143 + }
63.144 + }
63.145 +
63.146 + // Compute min. cost perfect matching
63.147 + MaxWeightedPerfectMatching<SmartGraph, SmartGraph::EdgeMap<Cost> >
63.148 + mwpm(sgr, scost);
63.149 + mwpm.run();
63.150 +
63.151 + for (SmartGraph::EdgeIt e(sgr); e != INVALID; ++e) {
63.152 + if (mwpm.matching(e)) {
63.153 + tree.push_back( _gr.edge(odd_nodes[sgr.id(sgr.u(e))],
63.154 + odd_nodes[sgr.id(sgr.v(e))]) );
63.155 + }
63.156 + }
63.157 +
63.158 + // Join the spanning tree and the matching
63.159 + sgr.clear();
63.160 + for (int i = 0; i != _gr.nodeNum(); ++i) {
63.161 + sgr.addNode();
63.162 + }
63.163 + for (int i = 0; i != int(tree.size()); ++i) {
63.164 + int ui = _gr.id(_gr.u(tree[i])),
63.165 + vi = _gr.id(_gr.v(tree[i]));
63.166 + sgr.addEdge(sgr.nodeFromId(ui), sgr.nodeFromId(vi));
63.167 + }
63.168 +
63.169 + // Compute the tour from the Euler traversal
63.170 + SmartGraph::NodeMap<bool> visited(sgr, false);
63.171 + for (EulerIt<SmartGraph> e(sgr); e != INVALID; ++e) {
63.172 + SmartGraph::Node n = sgr.target(e);
63.173 + if (!visited[n]) {
63.174 + _path.push_back(_gr(sgr.id(n)));
63.175 + visited[n] = true;
63.176 + }
63.177 + }
63.178 +
63.179 + _sum = _cost[_gr.edge(_path.back(), _path.front())];
63.180 + for (int i = 0; i < int(_path.size())-1; ++i) {
63.181 + _sum += _cost[_gr.edge(_path[i], _path[i+1])];
63.182 + }
63.183 +
63.184 + return _sum;
63.185 + }
63.186 +
63.187 + /// @}
63.188 +
63.189 + /// \name Query Functions
63.190 + /// @{
63.191 +
63.192 + /// \brief The total cost of the found tour.
63.193 + ///
63.194 + /// This function returns the total cost of the found tour.
63.195 + ///
63.196 + /// \pre run() must be called before using this function.
63.197 + Cost tourCost() const {
63.198 + return _sum;
63.199 + }
63.200 +
63.201 + /// \brief Returns a const reference to the node sequence of the
63.202 + /// found tour.
63.203 + ///
63.204 + /// This function returns a const reference to a vector
63.205 + /// that stores the node sequence of the found tour.
63.206 + ///
63.207 + /// \pre run() must be called before using this function.
63.208 + const std::vector<Node>& tourNodes() const {
63.209 + return _path;
63.210 + }
63.211 +
63.212 + /// \brief Gives back the node sequence of the found tour.
63.213 + ///
63.214 + /// This function copies the node sequence of the found tour into
63.215 + /// an STL container through the given output iterator. The
63.216 + /// <tt>value_type</tt> of the container must be <tt>FullGraph::Node</tt>.
63.217 + /// For example,
63.218 + /// \code
63.219 + /// std::vector<FullGraph::Node> nodes(countNodes(graph));
63.220 + /// tsp.tourNodes(nodes.begin());
63.221 + /// \endcode
63.222 + /// or
63.223 + /// \code
63.224 + /// std::list<FullGraph::Node> nodes;
63.225 + /// tsp.tourNodes(std::back_inserter(nodes));
63.226 + /// \endcode
63.227 + ///
63.228 + /// \pre run() must be called before using this function.
63.229 + template <typename Iterator>
63.230 + void tourNodes(Iterator out) const {
63.231 + std::copy(_path.begin(), _path.end(), out);
63.232 + }
63.233 +
63.234 + /// \brief Gives back the found tour as a path.
63.235 + ///
63.236 + /// This function copies the found tour as a list of arcs/edges into
63.237 + /// the given \ref lemon::concepts::Path "path structure".
63.238 + ///
63.239 + /// \pre run() must be called before using this function.
63.240 + template <typename Path>
63.241 + void tour(Path &path) const {
63.242 + path.clear();
63.243 + for (int i = 0; i < int(_path.size()) - 1; ++i) {
63.244 + path.addBack(_gr.arc(_path[i], _path[i+1]));
63.245 + }
63.246 + if (int(_path.size()) >= 2) {
63.247 + path.addBack(_gr.arc(_path.back(), _path.front()));
63.248 + }
63.249 + }
63.250 +
63.251 + /// @}
63.252 +
63.253 + };
63.254 +
63.255 +}; // namespace lemon
63.256 +
63.257 +#endif
64.1 --- a/lemon/circulation.h Mon Jul 16 16:21:40 2018 +0200
64.2 +++ b/lemon/circulation.h Wed Oct 17 19:14:07 2018 +0200
64.3 @@ -2,7 +2,7 @@
64.4 *
64.5 * This file is a part of LEMON, a generic C++ optimization library.
64.6 *
64.7 - * Copyright (C) 2003-2010
64.8 + * Copyright (C) 2003-2013
64.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
64.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
64.11 *
64.12 @@ -195,7 +195,8 @@
64.13 class Circulation {
64.14 public:
64.15
64.16 - ///The \ref CirculationDefaultTraits "traits class" of the algorithm.
64.17 + /// \brief The \ref lemon::CirculationDefaultTraits "traits class"
64.18 + /// of the algorithm.
64.19 typedef TR Traits;
64.20 ///The type of the digraph the algorithm runs on.
64.21 typedef typename Traits::Digraph Digraph;
65.1 --- a/lemon/clp.cc Mon Jul 16 16:21:40 2018 +0200
65.2 +++ b/lemon/clp.cc Wed Oct 17 19:14:07 2018 +0200
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-2010
65.8 + * Copyright (C) 2003-2013
65.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
65.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
65.11 *
66.1 --- a/lemon/clp.h Mon Jul 16 16:21:40 2018 +0200
66.2 +++ b/lemon/clp.h Wed Oct 17 19:14:07 2018 +0200
66.3 @@ -2,7 +2,7 @@
66.4 *
66.5 * This file is a part of LEMON, a generic C++ optimization library.
66.6 *
66.7 - * Copyright (C) 2003-2010
66.8 + * Copyright (C) 2003-2013
66.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
66.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
66.11 *
67.1 --- a/lemon/concept_check.h Mon Jul 16 16:21:40 2018 +0200
67.2 +++ b/lemon/concept_check.h Wed Oct 17 19:14:07 2018 +0200
67.3 @@ -2,7 +2,7 @@
67.4 *
67.5 * This file is a part of LEMON, a generic C++ optimization library.
67.6 *
67.7 - * Copyright (C) 2003-2009
67.8 + * Copyright (C) 2003-2013
67.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
67.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
67.11 *
67.12 @@ -58,7 +58,7 @@
67.13 {
67.14 #if !defined(NDEBUG)
67.15 void (Concept::*x)() = & Concept::constraints;
67.16 - ignore_unused_variable_warning(x);
67.17 + ::lemon::ignore_unused_variable_warning(x);
67.18 #endif
67.19 }
67.20
67.21 @@ -68,7 +68,7 @@
67.22 #if !defined(NDEBUG)
67.23 typedef typename Concept::template Constraints<Type> ConceptCheck;
67.24 void (ConceptCheck::*x)() = & ConceptCheck::constraints;
67.25 - ignore_unused_variable_warning(x);
67.26 + ::lemon::ignore_unused_variable_warning(x);
67.27 #endif
67.28 }
67.29
68.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
68.2 +++ b/lemon/concepts/bpgraph.h Wed Oct 17 19:14:07 2018 +0200
68.3 @@ -0,0 +1,1029 @@
68.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
68.5 + *
68.6 + * This file is a part of LEMON, a generic C++ optimization library.
68.7 + *
68.8 + * Copyright (C) 2003-2013
68.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
68.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
68.11 + *
68.12 + * Permission to use, modify and distribute this software is granted
68.13 + * provided that this copyright notice appears in all copies. For
68.14 + * precise terms see the accompanying LICENSE file.
68.15 + *
68.16 + * This software is provided "AS IS" with no warranty of any kind,
68.17 + * express or implied, and with no claim as to its suitability for any
68.18 + * purpose.
68.19 + *
68.20 + */
68.21 +
68.22 +///\ingroup graph_concepts
68.23 +///\file
68.24 +///\brief The concept of undirected graphs.
68.25 +
68.26 +#ifndef LEMON_CONCEPTS_BPGRAPH_H
68.27 +#define LEMON_CONCEPTS_BPGRAPH_H
68.28 +
68.29 +#include <lemon/concepts/graph_components.h>
68.30 +#include <lemon/concepts/maps.h>
68.31 +#include <lemon/concept_check.h>
68.32 +#include <lemon/core.h>
68.33 +
68.34 +namespace lemon {
68.35 + namespace concepts {
68.36 +
68.37 + /// \ingroup graph_concepts
68.38 + ///
68.39 + /// \brief Class describing the concept of undirected bipartite graphs.
68.40 + ///
68.41 + /// This class describes the common interface of all undirected
68.42 + /// bipartite graphs.
68.43 + ///
68.44 + /// Like all concept classes, it only provides an interface
68.45 + /// without any sensible implementation. So any general algorithm for
68.46 + /// undirected bipartite graphs should compile with this class,
68.47 + /// but it will not run properly, of course.
68.48 + /// An actual graph implementation like \ref ListBpGraph or
68.49 + /// \ref SmartBpGraph may have additional functionality.
68.50 + ///
68.51 + /// The bipartite graphs also fulfill the concept of \ref Graph
68.52 + /// "undirected graphs". Bipartite graphs provide a bipartition of
68.53 + /// the node set, namely a red and blue set of the nodes. The
68.54 + /// nodes can be iterated with the RedNodeIt and BlueNodeIt in the
68.55 + /// two node sets. With RedNodeMap and BlueNodeMap values can be
68.56 + /// assigned to the nodes in the two sets.
68.57 + ///
68.58 + /// The edges of the graph cannot connect two nodes of the same
68.59 + /// set. The edges inherent orientation is from the red nodes to
68.60 + /// the blue nodes.
68.61 + ///
68.62 + /// \sa Graph
68.63 + class BpGraph {
68.64 + private:
68.65 + /// BpGraphs are \e not copy constructible. Use bpGraphCopy instead.
68.66 + BpGraph(const BpGraph&) {}
68.67 + /// \brief Assignment of a graph to another one is \e not allowed.
68.68 + /// Use bpGraphCopy instead.
68.69 + void operator=(const BpGraph&) {}
68.70 +
68.71 + public:
68.72 + /// Default constructor.
68.73 + BpGraph() {}
68.74 +
68.75 + /// \brief Undirected graphs should be tagged with \c UndirectedTag.
68.76 + ///
68.77 + /// Undirected graphs should be tagged with \c UndirectedTag.
68.78 + ///
68.79 + /// This tag helps the \c enable_if technics to make compile time
68.80 + /// specializations for undirected graphs.
68.81 + typedef True UndirectedTag;
68.82 +
68.83 + /// The node type of the graph
68.84 +
68.85 + /// This class identifies a node of the graph. It also serves
68.86 + /// as a base class of the node iterators,
68.87 + /// thus they convert to this type.
68.88 + class Node {
68.89 + public:
68.90 + /// Default constructor
68.91 +
68.92 + /// Default constructor.
68.93 + /// \warning It sets the object to an undefined value.
68.94 + Node() { }
68.95 + /// Copy constructor.
68.96 +
68.97 + /// Copy constructor.
68.98 + ///
68.99 + Node(const Node&) { }
68.100 +
68.101 + /// %Invalid constructor \& conversion.
68.102 +
68.103 + /// Initializes the object to be invalid.
68.104 + /// \sa Invalid for more details.
68.105 + Node(Invalid) { }
68.106 + /// Equality operator
68.107 +
68.108 + /// Equality operator.
68.109 + ///
68.110 + /// Two iterators are equal if and only if they point to the
68.111 + /// same object or both are \c INVALID.
68.112 + bool operator==(Node) const { return true; }
68.113 +
68.114 + /// Inequality operator
68.115 +
68.116 + /// Inequality operator.
68.117 + bool operator!=(Node) const { return true; }
68.118 +
68.119 + /// Artificial ordering operator.
68.120 +
68.121 + /// Artificial ordering operator.
68.122 + ///
68.123 + /// \note This operator only has to define some strict ordering of
68.124 + /// the items; this order has nothing to do with the iteration
68.125 + /// ordering of the items.
68.126 + bool operator<(Node) const { return false; }
68.127 +
68.128 + };
68.129 +
68.130 + /// Class to represent red nodes.
68.131 +
68.132 + /// This class represents the red nodes of the graph. It does
68.133 + /// not supposed to be used directly, because the nodes can be
68.134 + /// represented as Node instances. This class can be used as
68.135 + /// template parameter for special map classes.
68.136 + class RedNode : public Node {
68.137 + public:
68.138 + /// Default constructor
68.139 +
68.140 + /// Default constructor.
68.141 + /// \warning It sets the object to an undefined value.
68.142 + RedNode() { }
68.143 + /// Copy constructor.
68.144 +
68.145 + /// Copy constructor.
68.146 + ///
68.147 + RedNode(const RedNode&) : Node() { }
68.148 +
68.149 + /// %Invalid constructor \& conversion.
68.150 +
68.151 + /// Initializes the object to be invalid.
68.152 + /// \sa Invalid for more details.
68.153 + RedNode(Invalid) { }
68.154 +
68.155 + };
68.156 +
68.157 + /// Class to represent blue nodes.
68.158 +
68.159 + /// This class represents the blue nodes of the graph. It does
68.160 + /// not supposed to be used directly, because the nodes can be
68.161 + /// represented as Node instances. This class can be used as
68.162 + /// template parameter for special map classes.
68.163 + class BlueNode : public Node {
68.164 + public:
68.165 + /// Default constructor
68.166 +
68.167 + /// Default constructor.
68.168 + /// \warning It sets the object to an undefined value.
68.169 + BlueNode() { }
68.170 + /// Copy constructor.
68.171 +
68.172 + /// Copy constructor.
68.173 + ///
68.174 + BlueNode(const BlueNode&) : Node() { }
68.175 +
68.176 + /// %Invalid constructor \& conversion.
68.177 +
68.178 + /// Initializes the object to be invalid.
68.179 + /// \sa Invalid for more details.
68.180 + BlueNode(Invalid) { }
68.181 +
68.182 + };
68.183 +
68.184 + /// Iterator class for the red nodes.
68.185 +
68.186 + /// This iterator goes through each red node of the graph.
68.187 + /// Its usage is quite simple, for example, you can count the number
68.188 + /// of red nodes in a graph \c g of type \c %BpGraph like this:
68.189 + ///\code
68.190 + /// int count=0;
68.191 + /// for (BpGraph::RedNodeIt n(g); n!=INVALID; ++n) ++count;
68.192 + ///\endcode
68.193 + class RedNodeIt : public RedNode {
68.194 + public:
68.195 + /// Default constructor
68.196 +
68.197 + /// Default constructor.
68.198 + /// \warning It sets the iterator to an undefined value.
68.199 + RedNodeIt() { }
68.200 + /// Copy constructor.
68.201 +
68.202 + /// Copy constructor.
68.203 + ///
68.204 + RedNodeIt(const RedNodeIt& n) : RedNode(n) { }
68.205 + /// %Invalid constructor \& conversion.
68.206 +
68.207 + /// Initializes the iterator to be invalid.
68.208 + /// \sa Invalid for more details.
68.209 + RedNodeIt(Invalid) { }
68.210 + /// Sets the iterator to the first red node.
68.211 +
68.212 + /// Sets the iterator to the first red node of the given
68.213 + /// digraph.
68.214 + explicit RedNodeIt(const BpGraph&) { }
68.215 + /// Sets the iterator to the given red node.
68.216 +
68.217 + /// Sets the iterator to the given red node of the given
68.218 + /// digraph.
68.219 + RedNodeIt(const BpGraph&, const RedNode&) { }
68.220 + /// Next node.
68.221 +
68.222 + /// Assign the iterator to the next red node.
68.223 + ///
68.224 + RedNodeIt& operator++() { return *this; }
68.225 + };
68.226 +
68.227 + /// Iterator class for the blue nodes.
68.228 +
68.229 + /// This iterator goes through each blue node of the graph.
68.230 + /// Its usage is quite simple, for example, you can count the number
68.231 + /// of blue nodes in a graph \c g of type \c %BpGraph like this:
68.232 + ///\code
68.233 + /// int count=0;
68.234 + /// for (BpGraph::BlueNodeIt n(g); n!=INVALID; ++n) ++count;
68.235 + ///\endcode
68.236 + class BlueNodeIt : public BlueNode {
68.237 + public:
68.238 + /// Default constructor
68.239 +
68.240 + /// Default constructor.
68.241 + /// \warning It sets the iterator to an undefined value.
68.242 + BlueNodeIt() { }
68.243 + /// Copy constructor.
68.244 +
68.245 + /// Copy constructor.
68.246 + ///
68.247 + BlueNodeIt(const BlueNodeIt& n) : BlueNode(n) { }
68.248 + /// %Invalid constructor \& conversion.
68.249 +
68.250 + /// Initializes the iterator to be invalid.
68.251 + /// \sa Invalid for more details.
68.252 + BlueNodeIt(Invalid) { }
68.253 + /// Sets the iterator to the first blue node.
68.254 +
68.255 + /// Sets the iterator to the first blue node of the given
68.256 + /// digraph.
68.257 + explicit BlueNodeIt(const BpGraph&) { }
68.258 + /// Sets the iterator to the given blue node.
68.259 +
68.260 + /// Sets the iterator to the given blue node of the given
68.261 + /// digraph.
68.262 + BlueNodeIt(const BpGraph&, const BlueNode&) { }
68.263 + /// Next node.
68.264 +
68.265 + /// Assign the iterator to the next blue node.
68.266 + ///
68.267 + BlueNodeIt& operator++() { return *this; }
68.268 + };
68.269 +
68.270 + /// Iterator class for the nodes.
68.271 +
68.272 + /// This iterator goes through each node of the graph.
68.273 + /// Its usage is quite simple, for example, you can count the number
68.274 + /// of nodes in a graph \c g of type \c %BpGraph like this:
68.275 + ///\code
68.276 + /// int count=0;
68.277 + /// for (BpGraph::NodeIt n(g); n!=INVALID; ++n) ++count;
68.278 + ///\endcode
68.279 + class NodeIt : public Node {
68.280 + public:
68.281 + /// Default constructor
68.282 +
68.283 + /// Default constructor.
68.284 + /// \warning It sets the iterator to an undefined value.
68.285 + NodeIt() { }
68.286 + /// Copy constructor.
68.287 +
68.288 + /// Copy constructor.
68.289 + ///
68.290 + NodeIt(const NodeIt& n) : Node(n) { }
68.291 + /// %Invalid constructor \& conversion.
68.292 +
68.293 + /// Initializes the iterator to be invalid.
68.294 + /// \sa Invalid for more details.
68.295 + NodeIt(Invalid) { }
68.296 + /// Sets the iterator to the first node.
68.297 +
68.298 + /// Sets the iterator to the first node of the given digraph.
68.299 + ///
68.300 + explicit NodeIt(const BpGraph&) { }
68.301 + /// Sets the iterator to the given node.
68.302 +
68.303 + /// Sets the iterator to the given node of the given digraph.
68.304 + ///
68.305 + NodeIt(const BpGraph&, const Node&) { }
68.306 + /// Next node.
68.307 +
68.308 + /// Assign the iterator to the next node.
68.309 + ///
68.310 + NodeIt& operator++() { return *this; }
68.311 + };
68.312 +
68.313 +
68.314 + /// The edge type of the graph
68.315 +
68.316 + /// This class identifies an edge of the graph. It also serves
68.317 + /// as a base class of the edge iterators,
68.318 + /// thus they will convert to this type.
68.319 + class Edge {
68.320 + public:
68.321 + /// Default constructor
68.322 +
68.323 + /// Default constructor.
68.324 + /// \warning It sets the object to an undefined value.
68.325 + Edge() { }
68.326 + /// Copy constructor.
68.327 +
68.328 + /// Copy constructor.
68.329 + ///
68.330 + Edge(const Edge&) { }
68.331 + /// %Invalid constructor \& conversion.
68.332 +
68.333 + /// Initializes the object to be invalid.
68.334 + /// \sa Invalid for more details.
68.335 + Edge(Invalid) { }
68.336 + /// Equality operator
68.337 +
68.338 + /// Equality operator.
68.339 + ///
68.340 + /// Two iterators are equal if and only if they point to the
68.341 + /// same object or both are \c INVALID.
68.342 + bool operator==(Edge) const { return true; }
68.343 + /// Inequality operator
68.344 +
68.345 + /// Inequality operator.
68.346 + bool operator!=(Edge) const { return true; }
68.347 +
68.348 + /// Artificial ordering operator.
68.349 +
68.350 + /// Artificial ordering operator.
68.351 + ///
68.352 + /// \note This operator only has to define some strict ordering of
68.353 + /// the edges; this order has nothing to do with the iteration
68.354 + /// ordering of the edges.
68.355 + bool operator<(Edge) const { return false; }
68.356 + };
68.357 +
68.358 + /// Iterator class for the edges.
68.359 +
68.360 + /// This iterator goes through each edge of the graph.
68.361 + /// Its usage is quite simple, for example, you can count the number
68.362 + /// of edges in a graph \c g of type \c %BpGraph as follows:
68.363 + ///\code
68.364 + /// int count=0;
68.365 + /// for(BpGraph::EdgeIt e(g); e!=INVALID; ++e) ++count;
68.366 + ///\endcode
68.367 + class EdgeIt : public Edge {
68.368 + public:
68.369 + /// Default constructor
68.370 +
68.371 + /// Default constructor.
68.372 + /// \warning It sets the iterator to an undefined value.
68.373 + EdgeIt() { }
68.374 + /// Copy constructor.
68.375 +
68.376 + /// Copy constructor.
68.377 + ///
68.378 + EdgeIt(const EdgeIt& e) : Edge(e) { }
68.379 + /// %Invalid constructor \& conversion.
68.380 +
68.381 + /// Initializes the iterator to be invalid.
68.382 + /// \sa Invalid for more details.
68.383 + EdgeIt(Invalid) { }
68.384 + /// Sets the iterator to the first edge.
68.385 +
68.386 + /// Sets the iterator to the first edge of the given graph.
68.387 + ///
68.388 + explicit EdgeIt(const BpGraph&) { }
68.389 + /// Sets the iterator to the given edge.
68.390 +
68.391 + /// Sets the iterator to the given edge of the given graph.
68.392 + ///
68.393 + EdgeIt(const BpGraph&, const Edge&) { }
68.394 + /// Next edge
68.395 +
68.396 + /// Assign the iterator to the next edge.
68.397 + ///
68.398 + EdgeIt& operator++() { return *this; }
68.399 + };
68.400 +
68.401 + /// Iterator class for the incident edges of a node.
68.402 +
68.403 + /// This iterator goes trough the incident undirected edges
68.404 + /// of a certain node of a graph.
68.405 + /// Its usage is quite simple, for example, you can compute the
68.406 + /// degree (i.e. the number of incident edges) of a node \c n
68.407 + /// in a graph \c g of type \c %BpGraph as follows.
68.408 + ///
68.409 + ///\code
68.410 + /// int count=0;
68.411 + /// for(BpGraph::IncEdgeIt e(g, n); e!=INVALID; ++e) ++count;
68.412 + ///\endcode
68.413 + ///
68.414 + /// \warning Loop edges will be iterated twice.
68.415 + class IncEdgeIt : public Edge {
68.416 + public:
68.417 + /// Default constructor
68.418 +
68.419 + /// Default constructor.
68.420 + /// \warning It sets the iterator to an undefined value.
68.421 + IncEdgeIt() { }
68.422 + /// Copy constructor.
68.423 +
68.424 + /// Copy constructor.
68.425 + ///
68.426 + IncEdgeIt(const IncEdgeIt& e) : Edge(e) { }
68.427 + /// %Invalid constructor \& conversion.
68.428 +
68.429 + /// Initializes the iterator to be invalid.
68.430 + /// \sa Invalid for more details.
68.431 + IncEdgeIt(Invalid) { }
68.432 + /// Sets the iterator to the first incident edge.
68.433 +
68.434 + /// Sets the iterator to the first incident edge of the given node.
68.435 + ///
68.436 + IncEdgeIt(const BpGraph&, const Node&) { }
68.437 + /// Sets the iterator to the given edge.
68.438 +
68.439 + /// Sets the iterator to the given edge of the given graph.
68.440 + ///
68.441 + IncEdgeIt(const BpGraph&, const Edge&) { }
68.442 + /// Next incident edge
68.443 +
68.444 + /// Assign the iterator to the next incident edge
68.445 + /// of the corresponding node.
68.446 + IncEdgeIt& operator++() { return *this; }
68.447 + };
68.448 +
68.449 + /// The arc type of the graph
68.450 +
68.451 + /// This class identifies a directed arc of the graph. It also serves
68.452 + /// as a base class of the arc iterators,
68.453 + /// thus they will convert to this type.
68.454 + class Arc {
68.455 + public:
68.456 + /// Default constructor
68.457 +
68.458 + /// Default constructor.
68.459 + /// \warning It sets the object to an undefined value.
68.460 + Arc() { }
68.461 + /// Copy constructor.
68.462 +
68.463 + /// Copy constructor.
68.464 + ///
68.465 + Arc(const Arc&) { }
68.466 + /// %Invalid constructor \& conversion.
68.467 +
68.468 + /// Initializes the object to be invalid.
68.469 + /// \sa Invalid for more details.
68.470 + Arc(Invalid) { }
68.471 + /// Equality operator
68.472 +
68.473 + /// Equality operator.
68.474 + ///
68.475 + /// Two iterators are equal if and only if they point to the
68.476 + /// same object or both are \c INVALID.
68.477 + bool operator==(Arc) const { return true; }
68.478 + /// Inequality operator
68.479 +
68.480 + /// Inequality operator.
68.481 + bool operator!=(Arc) const { return true; }
68.482 +
68.483 + /// Artificial ordering operator.
68.484 +
68.485 + /// Artificial ordering operator.
68.486 + ///
68.487 + /// \note This operator only has to define some strict ordering of
68.488 + /// the arcs; this order has nothing to do with the iteration
68.489 + /// ordering of the arcs.
68.490 + bool operator<(Arc) const { return false; }
68.491 +
68.492 + /// Converison to \c Edge
68.493 +
68.494 + /// Converison to \c Edge.
68.495 + ///
68.496 + operator Edge() const { return Edge(); }
68.497 + };
68.498 +
68.499 + /// Iterator class for the arcs.
68.500 +
68.501 + /// This iterator goes through each directed arc of the graph.
68.502 + /// Its usage is quite simple, for example, you can count the number
68.503 + /// of arcs in a graph \c g of type \c %BpGraph as follows:
68.504 + ///\code
68.505 + /// int count=0;
68.506 + /// for(BpGraph::ArcIt a(g); a!=INVALID; ++a) ++count;
68.507 + ///\endcode
68.508 + class ArcIt : public Arc {
68.509 + public:
68.510 + /// Default constructor
68.511 +
68.512 + /// Default constructor.
68.513 + /// \warning It sets the iterator to an undefined value.
68.514 + ArcIt() { }
68.515 + /// Copy constructor.
68.516 +
68.517 + /// Copy constructor.
68.518 + ///
68.519 + ArcIt(const ArcIt& e) : Arc(e) { }
68.520 + /// %Invalid constructor \& conversion.
68.521 +
68.522 + /// Initializes the iterator to be invalid.
68.523 + /// \sa Invalid for more details.
68.524 + ArcIt(Invalid) { }
68.525 + /// Sets the iterator to the first arc.
68.526 +
68.527 + /// Sets the iterator to the first arc of the given graph.
68.528 + ///
68.529 + explicit ArcIt(const BpGraph &g)
68.530 + {
68.531 + ::lemon::ignore_unused_variable_warning(g);
68.532 + }
68.533 + /// Sets the iterator to the given arc.
68.534 +
68.535 + /// Sets the iterator to the given arc of the given graph.
68.536 + ///
68.537 + ArcIt(const BpGraph&, const Arc&) { }
68.538 + /// Next arc
68.539 +
68.540 + /// Assign the iterator to the next arc.
68.541 + ///
68.542 + ArcIt& operator++() { return *this; }
68.543 + };
68.544 +
68.545 + /// Iterator class for the outgoing arcs of a node.
68.546 +
68.547 + /// This iterator goes trough the \e outgoing directed arcs of a
68.548 + /// certain node of a graph.
68.549 + /// Its usage is quite simple, for example, you can count the number
68.550 + /// of outgoing arcs of a node \c n
68.551 + /// in a graph \c g of type \c %BpGraph as follows.
68.552 + ///\code
68.553 + /// int count=0;
68.554 + /// for (Digraph::OutArcIt a(g, n); a!=INVALID; ++a) ++count;
68.555 + ///\endcode
68.556 + class OutArcIt : public Arc {
68.557 + public:
68.558 + /// Default constructor
68.559 +
68.560 + /// Default constructor.
68.561 + /// \warning It sets the iterator to an undefined value.
68.562 + OutArcIt() { }
68.563 + /// Copy constructor.
68.564 +
68.565 + /// Copy constructor.
68.566 + ///
68.567 + OutArcIt(const OutArcIt& e) : Arc(e) { }
68.568 + /// %Invalid constructor \& conversion.
68.569 +
68.570 + /// Initializes the iterator to be invalid.
68.571 + /// \sa Invalid for more details.
68.572 + OutArcIt(Invalid) { }
68.573 + /// Sets the iterator to the first outgoing arc.
68.574 +
68.575 + /// Sets the iterator to the first outgoing arc of the given node.
68.576 + ///
68.577 + OutArcIt(const BpGraph& n, const Node& g) {
68.578 + ::lemon::ignore_unused_variable_warning(n);
68.579 + ::lemon::ignore_unused_variable_warning(g);
68.580 + }
68.581 + /// Sets the iterator to the given arc.
68.582 +
68.583 + /// Sets the iterator to the given arc of the given graph.
68.584 + ///
68.585 + OutArcIt(const BpGraph&, const Arc&) { }
68.586 + /// Next outgoing arc
68.587 +
68.588 + /// Assign the iterator to the next
68.589 + /// outgoing arc of the corresponding node.
68.590 + OutArcIt& operator++() { return *this; }
68.591 + };
68.592 +
68.593 + /// Iterator class for the incoming arcs of a node.
68.594 +
68.595 + /// This iterator goes trough the \e incoming directed arcs of a
68.596 + /// certain node of a graph.
68.597 + /// Its usage is quite simple, for example, you can count the number
68.598 + /// of incoming arcs of a node \c n
68.599 + /// in a graph \c g of type \c %BpGraph as follows.
68.600 + ///\code
68.601 + /// int count=0;
68.602 + /// for (Digraph::InArcIt a(g, n); a!=INVALID; ++a) ++count;
68.603 + ///\endcode
68.604 + class InArcIt : public Arc {
68.605 + public:
68.606 + /// Default constructor
68.607 +
68.608 + /// Default constructor.
68.609 + /// \warning It sets the iterator to an undefined value.
68.610 + InArcIt() { }
68.611 + /// Copy constructor.
68.612 +
68.613 + /// Copy constructor.
68.614 + ///
68.615 + InArcIt(const InArcIt& e) : Arc(e) { }
68.616 + /// %Invalid constructor \& conversion.
68.617 +
68.618 + /// Initializes the iterator to be invalid.
68.619 + /// \sa Invalid for more details.
68.620 + InArcIt(Invalid) { }
68.621 + /// Sets the iterator to the first incoming arc.
68.622 +
68.623 + /// Sets the iterator to the first incoming arc of the given node.
68.624 + ///
68.625 + InArcIt(const BpGraph& g, const Node& n) {
68.626 + ::lemon::ignore_unused_variable_warning(n);
68.627 + ::lemon::ignore_unused_variable_warning(g);
68.628 + }
68.629 + /// Sets the iterator to the given arc.
68.630 +
68.631 + /// Sets the iterator to the given arc of the given graph.
68.632 + ///
68.633 + InArcIt(const BpGraph&, const Arc&) { }
68.634 + /// Next incoming arc
68.635 +
68.636 + /// Assign the iterator to the next
68.637 + /// incoming arc of the corresponding node.
68.638 + InArcIt& operator++() { return *this; }
68.639 + };
68.640 +
68.641 + /// \brief Standard graph map type for the nodes.
68.642 + ///
68.643 + /// Standard graph map type for the nodes.
68.644 + /// It conforms to the ReferenceMap concept.
68.645 + template<class T>
68.646 + class NodeMap : public ReferenceMap<Node, T, T&, const T&>
68.647 + {
68.648 + public:
68.649 +
68.650 + /// Constructor
68.651 + explicit NodeMap(const BpGraph&) { }
68.652 + /// Constructor with given initial value
68.653 + NodeMap(const BpGraph&, T) { }
68.654 +
68.655 + private:
68.656 + ///Copy constructor
68.657 + NodeMap(const NodeMap& nm) :
68.658 + ReferenceMap<Node, T, T&, const T&>(nm) { }
68.659 + ///Assignment operator
68.660 + template <typename CMap>
68.661 + NodeMap& operator=(const CMap&) {
68.662 + checkConcept<ReadMap<Node, T>, CMap>();
68.663 + return *this;
68.664 + }
68.665 + };
68.666 +
68.667 + /// \brief Standard graph map type for the red nodes.
68.668 + ///
68.669 + /// Standard graph map type for the red nodes.
68.670 + /// It conforms to the ReferenceMap concept.
68.671 + template<class T>
68.672 + class RedNodeMap : public ReferenceMap<Node, T, T&, const T&>
68.673 + {
68.674 + public:
68.675 +
68.676 + /// Constructor
68.677 + explicit RedNodeMap(const BpGraph&) { }
68.678 + /// Constructor with given initial value
68.679 + RedNodeMap(const BpGraph&, T) { }
68.680 +
68.681 + private:
68.682 + ///Copy constructor
68.683 + RedNodeMap(const RedNodeMap& nm) :
68.684 + ReferenceMap<Node, T, T&, const T&>(nm) { }
68.685 + ///Assignment operator
68.686 + template <typename CMap>
68.687 + RedNodeMap& operator=(const CMap&) {
68.688 + checkConcept<ReadMap<Node, T>, CMap>();
68.689 + return *this;
68.690 + }
68.691 + };
68.692 +
68.693 + /// \brief Standard graph map type for the blue nodes.
68.694 + ///
68.695 + /// Standard graph map type for the blue nodes.
68.696 + /// It conforms to the ReferenceMap concept.
68.697 + template<class T>
68.698 + class BlueNodeMap : public ReferenceMap<Node, T, T&, const T&>
68.699 + {
68.700 + public:
68.701 +
68.702 + /// Constructor
68.703 + explicit BlueNodeMap(const BpGraph&) { }
68.704 + /// Constructor with given initial value
68.705 + BlueNodeMap(const BpGraph&, T) { }
68.706 +
68.707 + private:
68.708 + ///Copy constructor
68.709 + BlueNodeMap(const BlueNodeMap& nm) :
68.710 + ReferenceMap<Node, T, T&, const T&>(nm) { }
68.711 + ///Assignment operator
68.712 + template <typename CMap>
68.713 + BlueNodeMap& operator=(const CMap&) {
68.714 + checkConcept<ReadMap<Node, T>, CMap>();
68.715 + return *this;
68.716 + }
68.717 + };
68.718 +
68.719 + /// \brief Standard graph map type for the arcs.
68.720 + ///
68.721 + /// Standard graph map type for the arcs.
68.722 + /// It conforms to the ReferenceMap concept.
68.723 + template<class T>
68.724 + class ArcMap : public ReferenceMap<Arc, T, T&, const T&>
68.725 + {
68.726 + public:
68.727 +
68.728 + /// Constructor
68.729 + explicit ArcMap(const BpGraph&) { }
68.730 + /// Constructor with given initial value
68.731 + ArcMap(const BpGraph&, T) { }
68.732 +
68.733 + private:
68.734 + ///Copy constructor
68.735 + ArcMap(const ArcMap& em) :
68.736 + ReferenceMap<Arc, T, T&, const T&>(em) { }
68.737 + ///Assignment operator
68.738 + template <typename CMap>
68.739 + ArcMap& operator=(const CMap&) {
68.740 + checkConcept<ReadMap<Arc, T>, CMap>();
68.741 + return *this;
68.742 + }
68.743 + };
68.744 +
68.745 + /// \brief Standard graph map type for the edges.
68.746 + ///
68.747 + /// Standard graph map type for the edges.
68.748 + /// It conforms to the ReferenceMap concept.
68.749 + template<class T>
68.750 + class EdgeMap : public ReferenceMap<Edge, T, T&, const T&>
68.751 + {
68.752 + public:
68.753 +
68.754 + /// Constructor
68.755 + explicit EdgeMap(const BpGraph&) { }
68.756 + /// Constructor with given initial value
68.757 + EdgeMap(const BpGraph&, T) { }
68.758 +
68.759 + private:
68.760 + ///Copy constructor
68.761 + EdgeMap(const EdgeMap& em) :
68.762 + ReferenceMap<Edge, T, T&, const T&>(em) {}
68.763 + ///Assignment operator
68.764 + template <typename CMap>
68.765 + EdgeMap& operator=(const CMap&) {
68.766 + checkConcept<ReadMap<Edge, T>, CMap>();
68.767 + return *this;
68.768 + }
68.769 + };
68.770 +
68.771 + /// \brief Gives back %true for red nodes.
68.772 + ///
68.773 + /// Gives back %true for red nodes.
68.774 + bool red(const Node&) const { return true; }
68.775 +
68.776 + /// \brief Gives back %true for blue nodes.
68.777 + ///
68.778 + /// Gives back %true for blue nodes.
68.779 + bool blue(const Node&) const { return true; }
68.780 +
68.781 + /// \brief Converts the node to red node object.
68.782 + ///
68.783 + /// This function converts unsafely the node to red node
68.784 + /// object. It should be called only if the node is from the red
68.785 + /// partition or INVALID.
68.786 + RedNode asRedNodeUnsafe(const Node&) const { return RedNode(); }
68.787 +
68.788 + /// \brief Converts the node to blue node object.
68.789 + ///
68.790 + /// This function converts unsafely the node to blue node
68.791 + /// object. It should be called only if the node is from the red
68.792 + /// partition or INVALID.
68.793 + BlueNode asBlueNodeUnsafe(const Node&) const { return BlueNode(); }
68.794 +
68.795 + /// \brief Converts the node to red node object.
68.796 + ///
68.797 + /// This function converts safely the node to red node
68.798 + /// object. If the node is not from the red partition, then it
68.799 + /// returns INVALID.
68.800 + RedNode asRedNode(const Node&) const { return RedNode(); }
68.801 +
68.802 + /// \brief Converts the node to blue node object.
68.803 + ///
68.804 + /// This function converts unsafely the node to blue node
68.805 + /// object. If the node is not from the blue partition, then it
68.806 + /// returns INVALID.
68.807 + BlueNode asBlueNode(const Node&) const { return BlueNode(); }
68.808 +
68.809 + /// \brief Gives back the red end node of the edge.
68.810 + ///
68.811 + /// Gives back the red end node of the edge.
68.812 + RedNode redNode(const Edge&) const { return RedNode(); }
68.813 +
68.814 + /// \brief Gives back the blue end node of the edge.
68.815 + ///
68.816 + /// Gives back the blue end node of the edge.
68.817 + BlueNode blueNode(const Edge&) const { return BlueNode(); }
68.818 +
68.819 + /// \brief The first node of the edge.
68.820 + ///
68.821 + /// It is a synonim for the \c redNode().
68.822 + Node u(Edge) const { return INVALID; }
68.823 +
68.824 + /// \brief The second node of the edge.
68.825 + ///
68.826 + /// It is a synonim for the \c blueNode().
68.827 + Node v(Edge) const { return INVALID; }
68.828 +
68.829 + /// \brief The source node of the arc.
68.830 + ///
68.831 + /// Returns the source node of the given arc.
68.832 + Node source(Arc) const { return INVALID; }
68.833 +
68.834 + /// \brief The target node of the arc.
68.835 + ///
68.836 + /// Returns the target node of the given arc.
68.837 + Node target(Arc) const { return INVALID; }
68.838 +
68.839 + /// \brief The ID of the node.
68.840 + ///
68.841 + /// Returns the ID of the given node.
68.842 + int id(Node) const { return -1; }
68.843 +
68.844 + /// \brief The red ID of the node.
68.845 + ///
68.846 + /// Returns the red ID of the given node.
68.847 + int id(RedNode) const { return -1; }
68.848 +
68.849 + /// \brief The blue ID of the node.
68.850 + ///
68.851 + /// Returns the blue ID of the given node.
68.852 + int id(BlueNode) const { return -1; }
68.853 +
68.854 + /// \brief The ID of the edge.
68.855 + ///
68.856 + /// Returns the ID of the given edge.
68.857 + int id(Edge) const { return -1; }
68.858 +
68.859 + /// \brief The ID of the arc.
68.860 + ///
68.861 + /// Returns the ID of the given arc.
68.862 + int id(Arc) const { return -1; }
68.863 +
68.864 + /// \brief The node with the given ID.
68.865 + ///
68.866 + /// Returns the node with the given ID.
68.867 + /// \pre The argument should be a valid node ID in the graph.
68.868 + Node nodeFromId(int) const { return INVALID; }
68.869 +
68.870 + /// \brief The edge with the given ID.
68.871 + ///
68.872 + /// Returns the edge with the given ID.
68.873 + /// \pre The argument should be a valid edge ID in the graph.
68.874 + Edge edgeFromId(int) const { return INVALID; }
68.875 +
68.876 + /// \brief The arc with the given ID.
68.877 + ///
68.878 + /// Returns the arc with the given ID.
68.879 + /// \pre The argument should be a valid arc ID in the graph.
68.880 + Arc arcFromId(int) const { return INVALID; }
68.881 +
68.882 + /// \brief An upper bound on the node IDs.
68.883 + ///
68.884 + /// Returns an upper bound on the node IDs.
68.885 + int maxNodeId() const { return -1; }
68.886 +
68.887 + /// \brief An upper bound on the red IDs.
68.888 + ///
68.889 + /// Returns an upper bound on the red IDs.
68.890 + int maxRedId() const { return -1; }
68.891 +
68.892 + /// \brief An upper bound on the blue IDs.
68.893 + ///
68.894 + /// Returns an upper bound on the blue IDs.
68.895 + int maxBlueId() const { return -1; }
68.896 +
68.897 + /// \brief An upper bound on the edge IDs.
68.898 + ///
68.899 + /// Returns an upper bound on the edge IDs.
68.900 + int maxEdgeId() const { return -1; }
68.901 +
68.902 + /// \brief An upper bound on the arc IDs.
68.903 + ///
68.904 + /// Returns an upper bound on the arc IDs.
68.905 + int maxArcId() const { return -1; }
68.906 +
68.907 + /// \brief The direction of the arc.
68.908 + ///
68.909 + /// Returns \c true if the given arc goes from a red node to a blue node.
68.910 + bool direction(Arc) const { return true; }
68.911 +
68.912 + /// \brief Direct the edge.
68.913 + ///
68.914 + /// Direct the given edge. The returned arc
68.915 + /// represents the given edge and its direction comes
68.916 + /// from the bool parameter. If it is \c true, then the source of the node
68.917 + /// will be a red node.
68.918 + Arc direct(Edge, bool) const {
68.919 + return INVALID;
68.920 + }
68.921 +
68.922 + /// \brief Direct the edge.
68.923 + ///
68.924 + /// Direct the given edge. The returned arc represents the given
68.925 + /// edge and its source node is the given node.
68.926 + Arc direct(Edge, Node) const {
68.927 + return INVALID;
68.928 + }
68.929 +
68.930 + /// \brief The oppositely directed arc.
68.931 + ///
68.932 + /// Returns the oppositely directed arc representing the same edge.
68.933 + Arc oppositeArc(Arc) const { return INVALID; }
68.934 +
68.935 + /// \brief The opposite node on the edge.
68.936 + ///
68.937 + /// Returns the opposite node on the given edge.
68.938 + Node oppositeNode(Node, Edge) const { return INVALID; }
68.939 +
68.940 + void first(Node&) const {}
68.941 + void next(Node&) const {}
68.942 +
68.943 + void firstRed(RedNode&) const {}
68.944 + void nextRed(RedNode&) const {}
68.945 +
68.946 + void firstBlue(BlueNode&) const {}
68.947 + void nextBlue(BlueNode&) const {}
68.948 +
68.949 + void first(Edge&) const {}
68.950 + void next(Edge&) const {}
68.951 +
68.952 + void first(Arc&) const {}
68.953 + void next(Arc&) const {}
68.954 +
68.955 + void firstOut(Arc&, Node) const {}
68.956 + void nextOut(Arc&) const {}
68.957 +
68.958 + void firstIn(Arc&, Node) const {}
68.959 + void nextIn(Arc&) const {}
68.960 +
68.961 + void firstInc(Edge &, bool &, const Node &) const {}
68.962 + void nextInc(Edge &, bool &) const {}
68.963 +
68.964 + // The second parameter is dummy.
68.965 + Node fromId(int, Node) const { return INVALID; }
68.966 + // The second parameter is dummy.
68.967 + Edge fromId(int, Edge) const { return INVALID; }
68.968 + // The second parameter is dummy.
68.969 + Arc fromId(int, Arc) const { return INVALID; }
68.970 +
68.971 + // Dummy parameter.
68.972 + int maxId(Node) const { return -1; }
68.973 + // Dummy parameter.
68.974 + int maxId(RedNode) const { return -1; }
68.975 + // Dummy parameter.
68.976 + int maxId(BlueNode) const { return -1; }
68.977 + // Dummy parameter.
68.978 + int maxId(Edge) const { return -1; }
68.979 + // Dummy parameter.
68.980 + int maxId(Arc) const { return -1; }
68.981 +
68.982 + /// \brief The base node of the iterator.
68.983 + ///
68.984 + /// Returns the base node of the given incident edge iterator.
68.985 + Node baseNode(IncEdgeIt) const { return INVALID; }
68.986 +
68.987 + /// \brief The running node of the iterator.
68.988 + ///
68.989 + /// Returns the running node of the given incident edge iterator.
68.990 + Node runningNode(IncEdgeIt) const { return INVALID; }
68.991 +
68.992 + /// \brief The base node of the iterator.
68.993 + ///
68.994 + /// Returns the base node of the given outgoing arc iterator
68.995 + /// (i.e. the source node of the corresponding arc).
68.996 + Node baseNode(OutArcIt) const { return INVALID; }
68.997 +
68.998 + /// \brief The running node of the iterator.
68.999 + ///
68.1000 + /// Returns the running node of the given outgoing arc iterator
68.1001 + /// (i.e. the target node of the corresponding arc).
68.1002 + Node runningNode(OutArcIt) const { return INVALID; }
68.1003 +
68.1004 + /// \brief The base node of the iterator.
68.1005 + ///
68.1006 + /// Returns the base node of the given incoming arc iterator
68.1007 + /// (i.e. the target node of the corresponding arc).
68.1008 + Node baseNode(InArcIt) const { return INVALID; }
68.1009 +
68.1010 + /// \brief The running node of the iterator.
68.1011 + ///
68.1012 + /// Returns the running node of the given incoming arc iterator
68.1013 + /// (i.e. the source node of the corresponding arc).
68.1014 + Node runningNode(InArcIt) const { return INVALID; }
68.1015 +
68.1016 + template <typename _BpGraph>
68.1017 + struct Constraints {
68.1018 + void constraints() {
68.1019 + checkConcept<BaseBpGraphComponent, _BpGraph>();
68.1020 + checkConcept<IterableBpGraphComponent<>, _BpGraph>();
68.1021 + checkConcept<IDableBpGraphComponent<>, _BpGraph>();
68.1022 + checkConcept<MappableBpGraphComponent<>, _BpGraph>();
68.1023 + }
68.1024 + };
68.1025 +
68.1026 + };
68.1027 +
68.1028 + }
68.1029 +
68.1030 +}
68.1031 +
68.1032 +#endif
69.1 --- a/lemon/concepts/digraph.h Mon Jul 16 16:21:40 2018 +0200
69.2 +++ b/lemon/concepts/digraph.h Wed Oct 17 19:14:07 2018 +0200
69.3 @@ -2,7 +2,7 @@
69.4 *
69.5 * This file is a part of LEMON, a generic C++ optimization library.
69.6 *
69.7 - * Copyright (C) 2003-2010
69.8 + * Copyright (C) 2003-2013
69.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
69.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
69.11 *
69.12 @@ -312,7 +312,9 @@
69.13
69.14 /// Sets the iterator to the first arc of the given digraph.
69.15 ///
69.16 - explicit ArcIt(const Digraph& g) { ignore_unused_variable_warning(g); }
69.17 + explicit ArcIt(const Digraph& g) {
69.18 + ::lemon::ignore_unused_variable_warning(g);
69.19 + }
69.20 /// Sets the iterator to the given arc.
69.21
69.22 /// Sets the iterator to the given arc of the given digraph.
69.23 @@ -409,13 +411,13 @@
69.24
69.25 /// \brief The base node of the iterator.
69.26 ///
69.27 - /// Returns the base node of the given incomming arc iterator
69.28 + /// Returns the base node of the given incoming arc iterator
69.29 /// (i.e. the target node of the corresponding arc).
69.30 Node baseNode(InArcIt) const { return INVALID; }
69.31
69.32 /// \brief The running node of the iterator.
69.33 ///
69.34 - /// Returns the running node of the given incomming arc iterator
69.35 + /// Returns the running node of the given incoming arc iterator
69.36 /// (i.e. the source node of the corresponding arc).
69.37 Node runningNode(InArcIt) const { return INVALID; }
69.38
70.1 --- a/lemon/concepts/graph.h Mon Jul 16 16:21:40 2018 +0200
70.2 +++ b/lemon/concepts/graph.h Wed Oct 17 19:14:07 2018 +0200
70.3 @@ -2,7 +2,7 @@
70.4 *
70.5 * This file is a part of LEMON, a generic C++ optimization library.
70.6 *
70.7 - * Copyright (C) 2003-2010
70.8 + * Copyright (C) 2003-2013
70.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
70.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
70.11 *
70.12 @@ -72,10 +72,10 @@
70.13 /// \sa Digraph
70.14 class Graph {
70.15 private:
70.16 - /// Graphs are \e not copy constructible. Use DigraphCopy instead.
70.17 + /// Graphs are \e not copy constructible. Use GraphCopy instead.
70.18 Graph(const Graph&) {}
70.19 /// \brief Assignment of a graph to another one is \e not allowed.
70.20 - /// Use DigraphCopy instead.
70.21 + /// Use GraphCopy instead.
70.22 void operator=(const Graph&) {}
70.23
70.24 public:
70.25 @@ -396,7 +396,9 @@
70.26
70.27 /// Sets the iterator to the first arc of the given graph.
70.28 ///
70.29 - explicit ArcIt(const Graph &g) { ignore_unused_variable_warning(g); }
70.30 + explicit ArcIt(const Graph &g) {
70.31 + ::lemon::ignore_unused_variable_warning(g);
70.32 + }
70.33 /// Sets the iterator to the given arc.
70.34
70.35 /// Sets the iterator to the given arc of the given graph.
70.36 @@ -442,8 +444,8 @@
70.37 /// Sets the iterator to the first outgoing arc of the given node.
70.38 ///
70.39 OutArcIt(const Graph& n, const Node& g) {
70.40 - ignore_unused_variable_warning(n);
70.41 - ignore_unused_variable_warning(g);
70.42 + ::lemon::ignore_unused_variable_warning(n);
70.43 + ::lemon::ignore_unused_variable_warning(g);
70.44 }
70.45 /// Sets the iterator to the given arc.
70.46
70.47 @@ -490,8 +492,8 @@
70.48 /// Sets the iterator to the first incoming arc of the given node.
70.49 ///
70.50 InArcIt(const Graph& g, const Node& n) {
70.51 - ignore_unused_variable_warning(n);
70.52 - ignore_unused_variable_warning(g);
70.53 + ::lemon::ignore_unused_variable_warning(n);
70.54 + ::lemon::ignore_unused_variable_warning(g);
70.55 }
70.56 /// Sets the iterator to the given arc.
70.57
70.58 @@ -757,13 +759,13 @@
70.59
70.60 /// \brief The base node of the iterator.
70.61 ///
70.62 - /// Returns the base node of the given incomming arc iterator
70.63 + /// Returns the base node of the given incoming arc iterator
70.64 /// (i.e. the target node of the corresponding arc).
70.65 Node baseNode(InArcIt) const { return INVALID; }
70.66
70.67 /// \brief The running node of the iterator.
70.68 ///
70.69 - /// Returns the running node of the given incomming arc iterator
70.70 + /// Returns the running node of the given incoming arc iterator
70.71 /// (i.e. the source node of the corresponding arc).
70.72 Node runningNode(InArcIt) const { return INVALID; }
70.73
71.1 --- a/lemon/concepts/graph_components.h Mon Jul 16 16:21:40 2018 +0200
71.2 +++ b/lemon/concepts/graph_components.h Wed Oct 17 19:14:07 2018 +0200
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-2010
71.8 + * Copyright (C) 2003-2013
71.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
71.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
71.11 *
71.12 @@ -108,6 +108,8 @@
71.13 i1 = i2 = i3;
71.14
71.15 bool b;
71.16 + ::lemon::ignore_unused_variable_warning(b);
71.17 +
71.18 b = (ia == ib) && (ia != ib);
71.19 b = (ia == INVALID) && (ib != INVALID);
71.20 b = (ia < ib);
71.21 @@ -287,7 +289,7 @@
71.22 e = graph.oppositeArc(e);
71.23 ue = e;
71.24 bool d = graph.direction(e);
71.25 - ignore_unused_variable_warning(d);
71.26 + ::lemon::ignore_unused_variable_warning(d);
71.27 }
71.28 }
71.29
71.30 @@ -297,6 +299,172 @@
71.31
71.32 };
71.33
71.34 + /// \brief Base skeleton class for undirected bipartite graphs.
71.35 + ///
71.36 + /// This class describes the base interface of undirected
71.37 + /// bipartite graph types. All bipartite graph %concepts have to
71.38 + /// conform to this class. It extends the interface of \ref
71.39 + /// BaseGraphComponent with an \c Edge type and functions to get
71.40 + /// the end nodes of edges, to convert from arcs to edges and to
71.41 + /// get both direction of edges.
71.42 + class BaseBpGraphComponent : public BaseGraphComponent {
71.43 + public:
71.44 +
71.45 + typedef BaseBpGraphComponent BpGraph;
71.46 +
71.47 + typedef BaseDigraphComponent::Node Node;
71.48 + typedef BaseDigraphComponent::Arc Arc;
71.49 +
71.50 + /// \brief Class to represent red nodes.
71.51 + ///
71.52 + /// This class represents the red nodes of the graph. The red
71.53 + /// nodes can also be used as normal nodes.
71.54 + class RedNode : public Node {
71.55 + typedef Node Parent;
71.56 +
71.57 + public:
71.58 + /// \brief Default constructor.
71.59 + ///
71.60 + /// Default constructor.
71.61 + /// \warning The default constructor is not required to set
71.62 + /// the item to some well-defined value. So you should consider it
71.63 + /// as uninitialized.
71.64 + RedNode() {}
71.65 +
71.66 + /// \brief Copy constructor.
71.67 + ///
71.68 + /// Copy constructor.
71.69 + RedNode(const RedNode &) : Parent() {}
71.70 +
71.71 + /// \brief Constructor for conversion from \c INVALID.
71.72 + ///
71.73 + /// Constructor for conversion from \c INVALID.
71.74 + /// It initializes the item to be invalid.
71.75 + /// \sa Invalid for more details.
71.76 + RedNode(Invalid) {}
71.77 + };
71.78 +
71.79 + /// \brief Class to represent blue nodes.
71.80 + ///
71.81 + /// This class represents the blue nodes of the graph. The blue
71.82 + /// nodes can also be used as normal nodes.
71.83 + class BlueNode : public Node {
71.84 + typedef Node Parent;
71.85 +
71.86 + public:
71.87 + /// \brief Default constructor.
71.88 + ///
71.89 + /// Default constructor.
71.90 + /// \warning The default constructor is not required to set
71.91 + /// the item to some well-defined value. So you should consider it
71.92 + /// as uninitialized.
71.93 + BlueNode() {}
71.94 +
71.95 + /// \brief Copy constructor.
71.96 + ///
71.97 + /// Copy constructor.
71.98 + BlueNode(const BlueNode &) : Parent() {}
71.99 +
71.100 + /// \brief Constructor for conversion from \c INVALID.
71.101 + ///
71.102 + /// Constructor for conversion from \c INVALID.
71.103 + /// It initializes the item to be invalid.
71.104 + /// \sa Invalid for more details.
71.105 + BlueNode(Invalid) {}
71.106 +
71.107 + /// \brief Constructor for conversion from a node.
71.108 + ///
71.109 + /// Constructor for conversion from a node. The conversion can
71.110 + /// be invalid, since the Node can be member of the red
71.111 + /// set.
71.112 + BlueNode(const Node&) {}
71.113 + };
71.114 +
71.115 + /// \brief Gives back %true for red nodes.
71.116 + ///
71.117 + /// Gives back %true for red nodes.
71.118 + bool red(const Node&) const { return true; }
71.119 +
71.120 + /// \brief Gives back %true for blue nodes.
71.121 + ///
71.122 + /// Gives back %true for blue nodes.
71.123 + bool blue(const Node&) const { return true; }
71.124 +
71.125 + /// \brief Gives back the red end node of the edge.
71.126 + ///
71.127 + /// Gives back the red end node of the edge.
71.128 + RedNode redNode(const Edge&) const { return RedNode(); }
71.129 +
71.130 + /// \brief Gives back the blue end node of the edge.
71.131 + ///
71.132 + /// Gives back the blue end node of the edge.
71.133 + BlueNode blueNode(const Edge&) const { return BlueNode(); }
71.134 +
71.135 + /// \brief Converts the node to red node object.
71.136 + ///
71.137 + /// This function converts unsafely the node to red node
71.138 + /// object. It should be called only if the node is from the red
71.139 + /// partition or INVALID.
71.140 + RedNode asRedNodeUnsafe(const Node&) const { return RedNode(); }
71.141 +
71.142 + /// \brief Converts the node to blue node object.
71.143 + ///
71.144 + /// This function converts unsafely the node to blue node
71.145 + /// object. It should be called only if the node is from the red
71.146 + /// partition or INVALID.
71.147 + BlueNode asBlueNodeUnsafe(const Node&) const { return BlueNode(); }
71.148 +
71.149 + /// \brief Converts the node to red node object.
71.150 + ///
71.151 + /// This function converts safely the node to red node
71.152 + /// object. If the node is not from the red partition, then it
71.153 + /// returns INVALID.
71.154 + RedNode asRedNode(const Node&) const { return RedNode(); }
71.155 +
71.156 + /// \brief Converts the node to blue node object.
71.157 + ///
71.158 + /// This function converts unsafely the node to blue node
71.159 + /// object. If the node is not from the blue partition, then it
71.160 + /// returns INVALID.
71.161 + BlueNode asBlueNode(const Node&) const { return BlueNode(); }
71.162 +
71.163 + template <typename _BpGraph>
71.164 + struct Constraints {
71.165 + typedef typename _BpGraph::Node Node;
71.166 + typedef typename _BpGraph::RedNode RedNode;
71.167 + typedef typename _BpGraph::BlueNode BlueNode;
71.168 + typedef typename _BpGraph::Arc Arc;
71.169 + typedef typename _BpGraph::Edge Edge;
71.170 +
71.171 + void constraints() {
71.172 + checkConcept<BaseGraphComponent, _BpGraph>();
71.173 + checkConcept<GraphItem<'n'>, RedNode>();
71.174 + checkConcept<GraphItem<'n'>, BlueNode>();
71.175 + {
71.176 + Node n;
71.177 + RedNode rn;
71.178 + BlueNode bn;
71.179 + Node rnan = rn;
71.180 + Node bnan = bn;
71.181 + Edge e;
71.182 + bool b;
71.183 + b = bpgraph.red(rnan);
71.184 + b = bpgraph.blue(bnan);
71.185 + rn = bpgraph.redNode(e);
71.186 + bn = bpgraph.blueNode(e);
71.187 + rn = bpgraph.asRedNodeUnsafe(rnan);
71.188 + bn = bpgraph.asBlueNodeUnsafe(bnan);
71.189 + rn = bpgraph.asRedNode(rnan);
71.190 + bn = bpgraph.asBlueNode(bnan);
71.191 + ::lemon::ignore_unused_variable_warning(b);
71.192 + }
71.193 + }
71.194 +
71.195 + const _BpGraph& bpgraph;
71.196 + };
71.197 +
71.198 + };
71.199 +
71.200 /// \brief Skeleton class for \e idable directed graphs.
71.201 ///
71.202 /// This class describes the interface of \e idable directed graphs.
71.203 @@ -366,9 +534,9 @@
71.204 arc = digraph.arcFromId(eid);
71.205
71.206 nid = digraph.maxNodeId();
71.207 - ignore_unused_variable_warning(nid);
71.208 + ::lemon::ignore_unused_variable_warning(nid);
71.209 eid = digraph.maxArcId();
71.210 - ignore_unused_variable_warning(eid);
71.211 + ::lemon::ignore_unused_variable_warning(eid);
71.212 }
71.213
71.214 const _Digraph& digraph;
71.215 @@ -421,7 +589,7 @@
71.216 ueid = graph.id(edge);
71.217 edge = graph.edgeFromId(ueid);
71.218 ueid = graph.maxEdgeId();
71.219 - ignore_unused_variable_warning(ueid);
71.220 + ::lemon::ignore_unused_variable_warning(ueid);
71.221 }
71.222
71.223 const _Graph& graph;
71.224 @@ -429,6 +597,70 @@
71.225 };
71.226 };
71.227
71.228 + /// \brief Skeleton class for \e idable undirected bipartite graphs.
71.229 + ///
71.230 + /// This class describes the interface of \e idable undirected
71.231 + /// bipartite graphs. It extends \ref IDableGraphComponent with
71.232 + /// the core ID functions of undirected bipartite graphs. Beside
71.233 + /// the regular node ids, this class also provides ids within the
71.234 + /// the red and blue sets of the nodes. This concept is part of
71.235 + /// the BpGraph concept.
71.236 + template <typename BAS = BaseBpGraphComponent>
71.237 + class IDableBpGraphComponent : public IDableGraphComponent<BAS> {
71.238 + public:
71.239 +
71.240 + typedef BAS Base;
71.241 + typedef IDableGraphComponent<BAS> Parent;
71.242 + typedef typename Base::Node Node;
71.243 + typedef typename Base::RedNode RedNode;
71.244 + typedef typename Base::BlueNode BlueNode;
71.245 +
71.246 + using Parent::id;
71.247 +
71.248 + /// \brief Return a unique integer id for the given node in the red set.
71.249 + ///
71.250 + /// Return a unique integer id for the given node in the red set.
71.251 + int id(const RedNode&) const { return -1; }
71.252 +
71.253 + /// \brief Return a unique integer id for the given node in the blue set.
71.254 + ///
71.255 + /// Return a unique integer id for the given node in the blue set.
71.256 + int id(const BlueNode&) const { return -1; }
71.257 +
71.258 + /// \brief Return an integer greater or equal to the maximum
71.259 + /// node id in the red set.
71.260 + ///
71.261 + /// Return an integer greater or equal to the maximum
71.262 + /// node id in the red set.
71.263 + int maxRedId() const { return -1; }
71.264 +
71.265 + /// \brief Return an integer greater or equal to the maximum
71.266 + /// node id in the blue set.
71.267 + ///
71.268 + /// Return an integer greater or equal to the maximum
71.269 + /// node id in the blue set.
71.270 + int maxBlueId() const { return -1; }
71.271 +
71.272 + template <typename _BpGraph>
71.273 + struct Constraints {
71.274 +
71.275 + void constraints() {
71.276 + checkConcept<IDableGraphComponent<Base>, _BpGraph>();
71.277 + typename _BpGraph::Node node;
71.278 + typename _BpGraph::RedNode red;
71.279 + typename _BpGraph::BlueNode blue;
71.280 + int rid = bpgraph.id(red);
71.281 + int bid = bpgraph.id(blue);
71.282 + rid = bpgraph.maxRedId();
71.283 + bid = bpgraph.maxBlueId();
71.284 + ::lemon::ignore_unused_variable_warning(rid);
71.285 + ::lemon::ignore_unused_variable_warning(bid);
71.286 + }
71.287 +
71.288 + const _BpGraph& bpgraph;
71.289 + };
71.290 + };
71.291 +
71.292 /// \brief Concept class for \c NodeIt, \c ArcIt and \c EdgeIt types.
71.293 ///
71.294 /// This class describes the concept of \c NodeIt, \c ArcIt and
71.295 @@ -494,8 +726,8 @@
71.296 _GraphItemIt it2;
71.297 _GraphItemIt it3 = it1;
71.298 _GraphItemIt it4 = INVALID;
71.299 - ignore_unused_variable_warning(it3);
71.300 - ignore_unused_variable_warning(it4);
71.301 + ::lemon::ignore_unused_variable_warning(it3);
71.302 + ::lemon::ignore_unused_variable_warning(it4);
71.303
71.304 it2 = ++it1;
71.305 ++it2 = it1;
71.306 @@ -585,8 +817,8 @@
71.307 _GraphIncIt it2;
71.308 _GraphIncIt it3 = it1;
71.309 _GraphIncIt it4 = INVALID;
71.310 - ignore_unused_variable_warning(it3);
71.311 - ignore_unused_variable_warning(it4);
71.312 + ::lemon::ignore_unused_variable_warning(it3);
71.313 + ::lemon::ignore_unused_variable_warning(it4);
71.314
71.315 it2 = ++it1;
71.316 ++it2 = it1;
71.317 @@ -643,15 +875,15 @@
71.318 /// This function gives back the next arc in the iteration order.
71.319 void next(Arc&) const {}
71.320
71.321 - /// \brief Return the first arc incomming to the given node.
71.322 + /// \brief Return the first arc incoming to the given node.
71.323 ///
71.324 - /// This function gives back the first arc incomming to the
71.325 + /// This function gives back the first arc incoming to the
71.326 /// given node.
71.327 void firstIn(Arc&, const Node&) const {}
71.328
71.329 - /// \brief Return the next arc incomming to the given node.
71.330 + /// \brief Return the next arc incoming to the given node.
71.331 ///
71.332 - /// This function gives back the next arc incomming to the
71.333 + /// This function gives back the next arc incoming to the
71.334 /// given node.
71.335 void nextIn(Arc&) const {}
71.336
71.337 @@ -768,7 +1000,7 @@
71.338 n = digraph.runningNode(iait);
71.339 n = digraph.baseNode(oait);
71.340 n = digraph.runningNode(oait);
71.341 - ignore_unused_variable_warning(n);
71.342 + ::lemon::ignore_unused_variable_warning(n);
71.343 }
71.344 }
71.345
71.346 @@ -902,6 +1134,97 @@
71.347 };
71.348 };
71.349
71.350 + /// \brief Skeleton class for iterable undirected bipartite graphs.
71.351 + ///
71.352 + /// This class describes the interface of iterable undirected
71.353 + /// bipartite graphs. It extends \ref IterableGraphComponent with
71.354 + /// the core iterable interface of undirected bipartite graphs.
71.355 + /// This concept is part of the BpGraph concept.
71.356 + template <typename BAS = BaseBpGraphComponent>
71.357 + class IterableBpGraphComponent : public IterableGraphComponent<BAS> {
71.358 + public:
71.359 +
71.360 + typedef BAS Base;
71.361 + typedef typename Base::Node Node;
71.362 + typedef typename Base::RedNode RedNode;
71.363 + typedef typename Base::BlueNode BlueNode;
71.364 + typedef typename Base::Arc Arc;
71.365 + typedef typename Base::Edge Edge;
71.366 +
71.367 + typedef IterableBpGraphComponent BpGraph;
71.368 +
71.369 + using IterableGraphComponent<BAS>::first;
71.370 + using IterableGraphComponent<BAS>::next;
71.371 +
71.372 + /// \name Base Iteration
71.373 + ///
71.374 + /// This interface provides functions for iteration on red and blue nodes.
71.375 + ///
71.376 + /// @{
71.377 +
71.378 + /// \brief Return the first red node.
71.379 + ///
71.380 + /// This function gives back the first red node in the iteration order.
71.381 + void first(RedNode&) const {}
71.382 +
71.383 + /// \brief Return the next red node.
71.384 + ///
71.385 + /// This function gives back the next red node in the iteration order.
71.386 + void next(RedNode&) const {}
71.387 +
71.388 + /// \brief Return the first blue node.
71.389 + ///
71.390 + /// This function gives back the first blue node in the iteration order.
71.391 + void first(BlueNode&) const {}
71.392 +
71.393 + /// \brief Return the next blue node.
71.394 + ///
71.395 + /// This function gives back the next blue node in the iteration order.
71.396 + void next(BlueNode&) const {}
71.397 +
71.398 +
71.399 + /// @}
71.400 +
71.401 + /// \name Class Based Iteration
71.402 + ///
71.403 + /// This interface provides iterator classes for red and blue nodes.
71.404 + ///
71.405 + /// @{
71.406 +
71.407 + /// \brief This iterator goes through each red node.
71.408 + ///
71.409 + /// This iterator goes through each red node.
71.410 + typedef GraphItemIt<BpGraph, RedNode> RedNodeIt;
71.411 +
71.412 + /// \brief This iterator goes through each blue node.
71.413 + ///
71.414 + /// This iterator goes through each blue node.
71.415 + typedef GraphItemIt<BpGraph, BlueNode> BlueNodeIt;
71.416 +
71.417 + /// @}
71.418 +
71.419 + template <typename _BpGraph>
71.420 + struct Constraints {
71.421 + void constraints() {
71.422 + checkConcept<IterableGraphComponent<Base>, _BpGraph>();
71.423 +
71.424 + typename _BpGraph::RedNode rn(INVALID);
71.425 + bpgraph.first(rn);
71.426 + bpgraph.next(rn);
71.427 + typename _BpGraph::BlueNode bn(INVALID);
71.428 + bpgraph.first(bn);
71.429 + bpgraph.next(bn);
71.430 +
71.431 + checkConcept<GraphItemIt<_BpGraph, typename _BpGraph::RedNode>,
71.432 + typename _BpGraph::RedNodeIt>();
71.433 + checkConcept<GraphItemIt<_BpGraph, typename _BpGraph::BlueNode>,
71.434 + typename _BpGraph::BlueNodeIt>();
71.435 + }
71.436 +
71.437 + const _BpGraph& bpgraph;
71.438 + };
71.439 + };
71.440 +
71.441 /// \brief Skeleton class for alterable directed graphs.
71.442 ///
71.443 /// This class describes the interface of alterable directed
71.444 @@ -927,18 +1250,21 @@
71.445 typedef AlterationNotifier<AlterableDigraphComponent, Arc>
71.446 ArcNotifier;
71.447
71.448 + mutable NodeNotifier node_notifier;
71.449 + mutable ArcNotifier arc_notifier;
71.450 +
71.451 /// \brief Return the node alteration notifier.
71.452 ///
71.453 /// This function gives back the node alteration notifier.
71.454 NodeNotifier& notifier(Node) const {
71.455 - return NodeNotifier();
71.456 + return node_notifier;
71.457 }
71.458
71.459 /// \brief Return the arc alteration notifier.
71.460 ///
71.461 /// This function gives back the arc alteration notifier.
71.462 ArcNotifier& notifier(Arc) const {
71.463 - return ArcNotifier();
71.464 + return arc_notifier;
71.465 }
71.466
71.467 template <typename _Digraph>
71.468 @@ -951,8 +1277,8 @@
71.469 typename _Digraph::ArcNotifier& en
71.470 = digraph.notifier(typename _Digraph::Arc());
71.471
71.472 - ignore_unused_variable_warning(nn);
71.473 - ignore_unused_variable_warning(en);
71.474 + ::lemon::ignore_unused_variable_warning(nn);
71.475 + ::lemon::ignore_unused_variable_warning(en);
71.476 }
71.477
71.478 const _Digraph& digraph;
71.479 @@ -974,6 +1300,7 @@
71.480 public:
71.481
71.482 typedef BAS Base;
71.483 + typedef AlterableDigraphComponent<Base> Parent;
71.484 typedef typename Base::Edge Edge;
71.485
71.486
71.487 @@ -981,11 +1308,15 @@
71.488 typedef AlterationNotifier<AlterableGraphComponent, Edge>
71.489 EdgeNotifier;
71.490
71.491 + mutable EdgeNotifier edge_notifier;
71.492 +
71.493 + using Parent::notifier;
71.494 +
71.495 /// \brief Return the edge alteration notifier.
71.496 ///
71.497 /// This function gives back the edge alteration notifier.
71.498 EdgeNotifier& notifier(Edge) const {
71.499 - return EdgeNotifier();
71.500 + return edge_notifier;
71.501 }
71.502
71.503 template <typename _Graph>
71.504 @@ -994,7 +1325,7 @@
71.505 checkConcept<AlterableDigraphComponent<Base>, _Graph>();
71.506 typename _Graph::EdgeNotifier& uen
71.507 = graph.notifier(typename _Graph::Edge());
71.508 - ignore_unused_variable_warning(uen);
71.509 + ::lemon::ignore_unused_variable_warning(uen);
71.510 }
71.511
71.512 const _Graph& graph;
71.513 @@ -1002,6 +1333,68 @@
71.514 };
71.515 };
71.516
71.517 + /// \brief Skeleton class for alterable undirected bipartite graphs.
71.518 + ///
71.519 + /// This class describes the interface of alterable undirected
71.520 + /// bipartite graphs. It extends \ref AlterableGraphComponent with
71.521 + /// the alteration notifier interface of bipartite graphs. It
71.522 + /// implements an observer-notifier pattern for the red and blue
71.523 + /// nodes. More obsevers can be registered into the notifier and
71.524 + /// whenever an alteration occured in the graph all the observers
71.525 + /// will be notified about it.
71.526 + template <typename BAS = BaseBpGraphComponent>
71.527 + class AlterableBpGraphComponent : public AlterableGraphComponent<BAS> {
71.528 + public:
71.529 +
71.530 + typedef BAS Base;
71.531 + typedef AlterableGraphComponent<Base> Parent;
71.532 + typedef typename Base::RedNode RedNode;
71.533 + typedef typename Base::BlueNode BlueNode;
71.534 +
71.535 +
71.536 + /// Red node alteration notifier class.
71.537 + typedef AlterationNotifier<AlterableBpGraphComponent, RedNode>
71.538 + RedNodeNotifier;
71.539 +
71.540 + /// Blue node alteration notifier class.
71.541 + typedef AlterationNotifier<AlterableBpGraphComponent, BlueNode>
71.542 + BlueNodeNotifier;
71.543 +
71.544 + mutable RedNodeNotifier red_node_notifier;
71.545 + mutable BlueNodeNotifier blue_node_notifier;
71.546 +
71.547 + using Parent::notifier;
71.548 +
71.549 + /// \brief Return the red node alteration notifier.
71.550 + ///
71.551 + /// This function gives back the red node alteration notifier.
71.552 + RedNodeNotifier& notifier(RedNode) const {
71.553 + return red_node_notifier;
71.554 + }
71.555 +
71.556 + /// \brief Return the blue node alteration notifier.
71.557 + ///
71.558 + /// This function gives back the blue node alteration notifier.
71.559 + BlueNodeNotifier& notifier(BlueNode) const {
71.560 + return blue_node_notifier;
71.561 + }
71.562 +
71.563 + template <typename _BpGraph>
71.564 + struct Constraints {
71.565 + void constraints() {
71.566 + checkConcept<AlterableGraphComponent<Base>, _BpGraph>();
71.567 + typename _BpGraph::RedNodeNotifier& rnn
71.568 + = bpgraph.notifier(typename _BpGraph::RedNode());
71.569 + typename _BpGraph::BlueNodeNotifier& bnn
71.570 + = bpgraph.notifier(typename _BpGraph::BlueNode());
71.571 + ::lemon::ignore_unused_variable_warning(rnn);
71.572 + ::lemon::ignore_unused_variable_warning(bnn);
71.573 + }
71.574 +
71.575 + const _BpGraph& bpgraph;
71.576 + };
71.577 + };
71.578 +
71.579 /// \brief Concept class for standard graph maps.
71.580 ///
71.581 /// This class describes the concept of standard graph maps, i.e.
71.582 @@ -1068,9 +1461,9 @@
71.583 // ReadMap<Key, Value> cmap;
71.584 // m3 = cmap;
71.585
71.586 - ignore_unused_variable_warning(m1);
71.587 - ignore_unused_variable_warning(m2);
71.588 - // ignore_unused_variable_warning(m3);
71.589 + ::lemon::ignore_unused_variable_warning(m1);
71.590 + ::lemon::ignore_unused_variable_warning(m2);
71.591 + // ::lemon::ignore_unused_variable_warning(m3);
71.592 }
71.593
71.594 const _Map &m;
71.595 @@ -1305,6 +1698,150 @@
71.596 };
71.597 };
71.598
71.599 + /// \brief Skeleton class for mappable undirected bipartite graphs.
71.600 + ///
71.601 + /// This class describes the interface of mappable undirected
71.602 + /// bipartite graphs. It extends \ref MappableGraphComponent with
71.603 + /// the standard graph map class for red and blue nodes (\c
71.604 + /// RedNodeMap and BlueNodeMap). This concept is part of the
71.605 + /// BpGraph concept.
71.606 + template <typename BAS = BaseBpGraphComponent>
71.607 + class MappableBpGraphComponent : public MappableGraphComponent<BAS> {
71.608 + public:
71.609 +
71.610 + typedef BAS Base;
71.611 + typedef typename Base::Node Node;
71.612 +
71.613 + typedef MappableBpGraphComponent BpGraph;
71.614 +
71.615 + /// \brief Standard graph map for the red nodes.
71.616 + ///
71.617 + /// Standard graph map for the red nodes.
71.618 + /// It conforms to the ReferenceMap concept.
71.619 + template <typename V>
71.620 + class RedNodeMap : public GraphMap<MappableBpGraphComponent, Node, V> {
71.621 + typedef GraphMap<MappableBpGraphComponent, Node, V> Parent;
71.622 +
71.623 + public:
71.624 + /// \brief Construct a new map.
71.625 + ///
71.626 + /// Construct a new map for the graph.
71.627 + explicit RedNodeMap(const MappableBpGraphComponent& graph)
71.628 + : Parent(graph) {}
71.629 +
71.630 + /// \brief Construct a new map with default value.
71.631 + ///
71.632 + /// Construct a new map for the graph and initalize the values.
71.633 + RedNodeMap(const MappableBpGraphComponent& graph, const V& value)
71.634 + : Parent(graph, value) {}
71.635 +
71.636 + private:
71.637 + /// \brief Copy constructor.
71.638 + ///
71.639 + /// Copy Constructor.
71.640 + RedNodeMap(const RedNodeMap& nm) : Parent(nm) {}
71.641 +
71.642 + /// \brief Assignment operator.
71.643 + ///
71.644 + /// Assignment operator.
71.645 + template <typename CMap>
71.646 + RedNodeMap& operator=(const CMap&) {
71.647 + checkConcept<ReadMap<Node, V>, CMap>();
71.648 + return *this;
71.649 + }
71.650 +
71.651 + };
71.652 +
71.653 + /// \brief Standard graph map for the blue nodes.
71.654 + ///
71.655 + /// Standard graph map for the blue nodes.
71.656 + /// It conforms to the ReferenceMap concept.
71.657 + template <typename V>
71.658 + class BlueNodeMap : public GraphMap<MappableBpGraphComponent, Node, V> {
71.659 + typedef GraphMap<MappableBpGraphComponent, Node, V> Parent;
71.660 +
71.661 + public:
71.662 + /// \brief Construct a new map.
71.663 + ///
71.664 + /// Construct a new map for the graph.
71.665 + explicit BlueNodeMap(const MappableBpGraphComponent& graph)
71.666 + : Parent(graph) {}
71.667 +
71.668 + /// \brief Construct a new map with default value.
71.669 + ///
71.670 + /// Construct a new map for the graph and initalize the values.
71.671 + BlueNodeMap(const MappableBpGraphComponent& graph, const V& value)
71.672 + : Parent(graph, value) {}
71.673 +
71.674 + private:
71.675 + /// \brief Copy constructor.
71.676 + ///
71.677 + /// Copy Constructor.
71.678 + BlueNodeMap(const BlueNodeMap& nm) : Parent(nm) {}
71.679 +
71.680 + /// \brief Assignment operator.
71.681 + ///
71.682 + /// Assignment operator.
71.683 + template <typename CMap>
71.684 + BlueNodeMap& operator=(const CMap&) {
71.685 + checkConcept<ReadMap<Node, V>, CMap>();
71.686 + return *this;
71.687 + }
71.688 +
71.689 + };
71.690 +
71.691 +
71.692 + template <typename _BpGraph>
71.693 + struct Constraints {
71.694 +
71.695 + struct Dummy {
71.696 + int value;
71.697 + Dummy() : value(0) {}
71.698 + Dummy(int _v) : value(_v) {}
71.699 + };
71.700 +
71.701 + void constraints() {
71.702 + checkConcept<MappableGraphComponent<Base>, _BpGraph>();
71.703 +
71.704 + { // int map test
71.705 + typedef typename _BpGraph::template RedNodeMap<int>
71.706 + IntRedNodeMap;
71.707 + checkConcept<GraphMap<_BpGraph, typename _BpGraph::RedNode, int>,
71.708 + IntRedNodeMap >();
71.709 + } { // bool map test
71.710 + typedef typename _BpGraph::template RedNodeMap<bool>
71.711 + BoolRedNodeMap;
71.712 + checkConcept<GraphMap<_BpGraph, typename _BpGraph::RedNode, bool>,
71.713 + BoolRedNodeMap >();
71.714 + } { // Dummy map test
71.715 + typedef typename _BpGraph::template RedNodeMap<Dummy>
71.716 + DummyRedNodeMap;
71.717 + checkConcept<GraphMap<_BpGraph, typename _BpGraph::RedNode, Dummy>,
71.718 + DummyRedNodeMap >();
71.719 + }
71.720 +
71.721 + { // int map test
71.722 + typedef typename _BpGraph::template BlueNodeMap<int>
71.723 + IntBlueNodeMap;
71.724 + checkConcept<GraphMap<_BpGraph, typename _BpGraph::BlueNode, int>,
71.725 + IntBlueNodeMap >();
71.726 + } { // bool map test
71.727 + typedef typename _BpGraph::template BlueNodeMap<bool>
71.728 + BoolBlueNodeMap;
71.729 + checkConcept<GraphMap<_BpGraph, typename _BpGraph::BlueNode, bool>,
71.730 + BoolBlueNodeMap >();
71.731 + } { // Dummy map test
71.732 + typedef typename _BpGraph::template BlueNodeMap<Dummy>
71.733 + DummyBlueNodeMap;
71.734 + checkConcept<GraphMap<_BpGraph, typename _BpGraph::BlueNode, Dummy>,
71.735 + DummyBlueNodeMap >();
71.736 + }
71.737 + }
71.738 +
71.739 + const _BpGraph& bpgraph;
71.740 + };
71.741 + };
71.742 +
71.743 /// \brief Skeleton class for extendable directed graphs.
71.744 ///
71.745 /// This class describes the interface of extendable directed graphs.
71.746 @@ -1395,6 +1932,65 @@
71.747 };
71.748 };
71.749
71.750 + /// \brief Skeleton class for extendable undirected bipartite graphs.
71.751 + ///
71.752 + /// This class describes the interface of extendable undirected
71.753 + /// bipartite graphs. It extends \ref BaseGraphComponent with
71.754 + /// functions for adding nodes and edges to the graph. This
71.755 + /// concept requires \ref AlterableBpGraphComponent.
71.756 + template <typename BAS = BaseBpGraphComponent>
71.757 + class ExtendableBpGraphComponent : public BAS {
71.758 + public:
71.759 +
71.760 + typedef BAS Base;
71.761 + typedef typename Base::Node Node;
71.762 + typedef typename Base::RedNode RedNode;
71.763 + typedef typename Base::BlueNode BlueNode;
71.764 + typedef typename Base::Edge Edge;
71.765 +
71.766 + /// \brief Add a new red node to the digraph.
71.767 + ///
71.768 + /// This function adds a red new node to the digraph.
71.769 + RedNode addRedNode() {
71.770 + return INVALID;
71.771 + }
71.772 +
71.773 + /// \brief Add a new blue node to the digraph.
71.774 + ///
71.775 + /// This function adds a blue new node to the digraph.
71.776 + BlueNode addBlueNode() {
71.777 + return INVALID;
71.778 + }
71.779 +
71.780 + /// \brief Add a new edge connecting the given two nodes.
71.781 + ///
71.782 + /// This function adds a new edge connecting the given two nodes
71.783 + /// of the graph. The first node has to be a red node, and the
71.784 + /// second one a blue node.
71.785 + Edge addEdge(const RedNode&, const BlueNode&) {
71.786 + return INVALID;
71.787 + }
71.788 + Edge addEdge(const BlueNode&, const RedNode&) {
71.789 + return INVALID;
71.790 + }
71.791 +
71.792 + template <typename _BpGraph>
71.793 + struct Constraints {
71.794 + void constraints() {
71.795 + checkConcept<Base, _BpGraph>();
71.796 + typename _BpGraph::RedNode red_node;
71.797 + typename _BpGraph::BlueNode blue_node;
71.798 + red_node = bpgraph.addRedNode();
71.799 + blue_node = bpgraph.addBlueNode();
71.800 + typename _BpGraph::Edge edge;
71.801 + edge = bpgraph.addEdge(red_node, blue_node);
71.802 + edge = bpgraph.addEdge(blue_node, red_node);
71.803 + }
71.804 +
71.805 + _BpGraph& bpgraph;
71.806 + };
71.807 + };
71.808 +
71.809 /// \brief Skeleton class for erasable directed graphs.
71.810 ///
71.811 /// This class describes the interface of erasable directed graphs.
71.812 @@ -1475,6 +2071,15 @@
71.813 };
71.814 };
71.815
71.816 + /// \brief Skeleton class for erasable undirected graphs.
71.817 + ///
71.818 + /// This class describes the interface of erasable undirected
71.819 + /// bipartite graphs. It extends \ref BaseBpGraphComponent with
71.820 + /// functions for removing nodes and edges from the graph. This
71.821 + /// concept requires \ref AlterableBpGraphComponent.
71.822 + template <typename BAS = BaseBpGraphComponent>
71.823 + class ErasableBpGraphComponent : public ErasableGraphComponent<BAS> {};
71.824 +
71.825 /// \brief Skeleton class for clearable directed graphs.
71.826 ///
71.827 /// This class describes the interface of clearable directed graphs.
71.828 @@ -1511,27 +2116,16 @@
71.829 /// the graph.
71.830 /// This concept requires \ref AlterableGraphComponent.
71.831 template <typename BAS = BaseGraphComponent>
71.832 - class ClearableGraphComponent : public ClearableDigraphComponent<BAS> {
71.833 - public:
71.834 + class ClearableGraphComponent : public ClearableDigraphComponent<BAS> {};
71.835
71.836 - typedef BAS Base;
71.837 -
71.838 - /// \brief Erase all nodes and edges from the graph.
71.839 - ///
71.840 - /// This function erases all nodes and edges from the graph.
71.841 - void clear() {}
71.842 -
71.843 - template <typename _Graph>
71.844 - struct Constraints {
71.845 - void constraints() {
71.846 - checkConcept<Base, _Graph>();
71.847 - graph.clear();
71.848 - }
71.849 -
71.850 - _Graph& graph;
71.851 - Constraints() {}
71.852 - };
71.853 - };
71.854 + /// \brief Skeleton class for clearable undirected biparite graphs.
71.855 + ///
71.856 + /// This class describes the interface of clearable undirected
71.857 + /// bipartite graphs. It extends \ref BaseBpGraphComponent with a
71.858 + /// function for clearing the graph. This concept requires \ref
71.859 + /// AlterableBpGraphComponent.
71.860 + template <typename BAS = BaseBpGraphComponent>
71.861 + class ClearableBpGraphComponent : public ClearableGraphComponent<BAS> {};
71.862
71.863 }
71.864
72.1 --- a/lemon/concepts/heap.h Mon Jul 16 16:21:40 2018 +0200
72.2 +++ b/lemon/concepts/heap.h Wed Oct 17 19:14:07 2018 +0200
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-2010
72.8 + * Copyright (C) 2003-2013
72.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
72.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
72.11 *
72.12 @@ -260,27 +260,27 @@
72.13 Prio prio;
72.14 item=Item();
72.15 prio=Prio();
72.16 - ignore_unused_variable_warning(item);
72.17 - ignore_unused_variable_warning(prio);
72.18 + ::lemon::ignore_unused_variable_warning(item);
72.19 + ::lemon::ignore_unused_variable_warning(prio);
72.20
72.21 OwnItem own_item;
72.22 OwnPrio own_prio;
72.23 OwnState own_state;
72.24 own_item=Item();
72.25 own_prio=Prio();
72.26 - ignore_unused_variable_warning(own_item);
72.27 - ignore_unused_variable_warning(own_prio);
72.28 - ignore_unused_variable_warning(own_state);
72.29 + ::lemon::ignore_unused_variable_warning(own_item);
72.30 + ::lemon::ignore_unused_variable_warning(own_prio);
72.31 + ::lemon::ignore_unused_variable_warning(own_state);
72.32
72.33 _Heap heap1(map);
72.34 _Heap heap2 = heap1;
72.35 - ignore_unused_variable_warning(heap1);
72.36 - ignore_unused_variable_warning(heap2);
72.37 + ::lemon::ignore_unused_variable_warning(heap1);
72.38 + ::lemon::ignore_unused_variable_warning(heap2);
72.39
72.40 int s = heap.size();
72.41 - ignore_unused_variable_warning(s);
72.42 + ::lemon::ignore_unused_variable_warning(s);
72.43 bool e = heap.empty();
72.44 - ignore_unused_variable_warning(e);
72.45 + ::lemon::ignore_unused_variable_warning(e);
72.46
72.47 prio = heap.prio();
72.48 item = heap.top();
73.1 --- a/lemon/concepts/maps.h Mon Jul 16 16:21:40 2018 +0200
73.2 +++ b/lemon/concepts/maps.h Wed Oct 17 19:14:07 2018 +0200
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-2009
73.8 + * Copyright (C) 2003-2013
73.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
73.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
73.11 *
73.12 @@ -60,10 +60,10 @@
73.13 typename _ReadMap::Value own_val = m[own_key];
73.14 own_val = m[own_key];
73.15
73.16 - ignore_unused_variable_warning(key);
73.17 - ignore_unused_variable_warning(val);
73.18 - ignore_unused_variable_warning(own_key);
73.19 - ignore_unused_variable_warning(own_val);
73.20 + ::lemon::ignore_unused_variable_warning(key);
73.21 + ::lemon::ignore_unused_variable_warning(val);
73.22 + ::lemon::ignore_unused_variable_warning(own_key);
73.23 + ::lemon::ignore_unused_variable_warning(own_val);
73.24 }
73.25 const Key& key;
73.26 const typename _ReadMap::Key& own_key;
73.27 @@ -100,10 +100,10 @@
73.28 m.set(key, val);
73.29 m.set(own_key, own_val);
73.30
73.31 - ignore_unused_variable_warning(key);
73.32 - ignore_unused_variable_warning(val);
73.33 - ignore_unused_variable_warning(own_key);
73.34 - ignore_unused_variable_warning(own_val);
73.35 + ::lemon::ignore_unused_variable_warning(key);
73.36 + ::lemon::ignore_unused_variable_warning(val);
73.37 + ::lemon::ignore_unused_variable_warning(own_key);
73.38 + ::lemon::ignore_unused_variable_warning(own_val);
73.39 }
73.40 const Key& key;
73.41 const Value& val;
74.1 --- a/lemon/concepts/path.h Mon Jul 16 16:21:40 2018 +0200
74.2 +++ b/lemon/concepts/path.h Wed Oct 17 19:14:07 2018 +0200
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-2009
74.8 + * Copyright (C) 2003-2013
74.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
74.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
74.11 *
74.12 @@ -75,7 +75,7 @@
74.13 /// \brief Template assigment operator
74.14 template <typename CPath>
74.15 Path& operator=(const CPath& cpath) {
74.16 - ignore_unused_variable_warning(cpath);
74.17 + ::lemon::ignore_unused_variable_warning(cpath);
74.18 return *this;
74.19 }
74.20
74.21 @@ -135,12 +135,12 @@
74.22 e = (i != ii);
74.23 e = (i < ii);
74.24
74.25 - ignore_unused_variable_warning(l);
74.26 - ignore_unused_variable_warning(pp);
74.27 - ignore_unused_variable_warning(e);
74.28 - ignore_unused_variable_warning(id);
74.29 - ignore_unused_variable_warning(ii);
74.30 - ignore_unused_variable_warning(ed);
74.31 + ::lemon::ignore_unused_variable_warning(l);
74.32 + ::lemon::ignore_unused_variable_warning(pp);
74.33 + ::lemon::ignore_unused_variable_warning(e);
74.34 + ::lemon::ignore_unused_variable_warning(id);
74.35 + ::lemon::ignore_unused_variable_warning(ii);
74.36 + ::lemon::ignore_unused_variable_warning(ed);
74.37 }
74.38 };
74.39
74.40 @@ -162,10 +162,10 @@
74.41 e = (i == INVALID);
74.42 e = (i != INVALID);
74.43
74.44 - ignore_unused_variable_warning(l);
74.45 - ignore_unused_variable_warning(e);
74.46 - ignore_unused_variable_warning(id);
74.47 - ignore_unused_variable_warning(ed);
74.48 + ::lemon::ignore_unused_variable_warning(l);
74.49 + ::lemon::ignore_unused_variable_warning(e);
74.50 + ::lemon::ignore_unused_variable_warning(id);
74.51 + ::lemon::ignore_unused_variable_warning(ed);
74.52 }
74.53 _Path& p;
74.54 PathDumperConstraints() {}
74.55 @@ -188,10 +188,10 @@
74.56 e = (i == INVALID);
74.57 e = (i != INVALID);
74.58
74.59 - ignore_unused_variable_warning(l);
74.60 - ignore_unused_variable_warning(e);
74.61 - ignore_unused_variable_warning(id);
74.62 - ignore_unused_variable_warning(ed);
74.63 + ::lemon::ignore_unused_variable_warning(l);
74.64 + ::lemon::ignore_unused_variable_warning(e);
74.65 + ::lemon::ignore_unused_variable_warning(id);
74.66 + ::lemon::ignore_unused_variable_warning(ed);
74.67 }
74.68 _Path& p;
74.69 PathDumperConstraints() {}
75.1 --- a/lemon/config.h.cmake Mon Jul 16 16:21:40 2018 +0200
75.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
75.3 @@ -1,8 +0,0 @@
75.4 -#define LEMON_VERSION "@PROJECT_VERSION@"
75.5 -#cmakedefine LEMON_HAVE_LONG_LONG 1
75.6 -#cmakedefine LEMON_HAVE_LP 1
75.7 -#cmakedefine LEMON_HAVE_MIP 1
75.8 -#cmakedefine LEMON_HAVE_GLPK 1
75.9 -#cmakedefine LEMON_HAVE_CPLEX 1
75.10 -#cmakedefine LEMON_HAVE_CLP 1
75.11 -#cmakedefine LEMON_HAVE_CBC 1
76.1 --- a/lemon/config.h.in Mon Jul 16 16:21:40 2018 +0200
76.2 +++ b/lemon/config.h.in Wed Oct 17 19:14:07 2018 +0200
76.3 @@ -1,26 +1,29 @@
76.4 -/* The version string */
76.5 -#undef LEMON_VERSION
76.6 +#ifndef LEMON_CONFIG_H
76.7 +#define LEMON_CONFIG_H
76.8
76.9 -/* Define to 1 if you have long long */
76.10 -#undef LEMON_HAVE_LONG_LONG
76.11 +#define LEMON_VERSION "@PROJECT_VERSION@"
76.12 +#cmakedefine LEMON_HAVE_LONG_LONG 1
76.13
76.14 -/* Define to 1 if you have any LP solver. */
76.15 -#undef LEMON_HAVE_LP
76.16 +#cmakedefine LEMON_WIN32 1
76.17
76.18 -/* Define to 1 if you have any MIP solver. */
76.19 -#undef LEMON_HAVE_MIP
76.20 +#cmakedefine LEMON_HAVE_LP 1
76.21 +#cmakedefine LEMON_HAVE_MIP 1
76.22 +#cmakedefine LEMON_HAVE_GLPK 1
76.23 +#cmakedefine LEMON_HAVE_CPLEX 1
76.24 +#cmakedefine LEMON_HAVE_SOPLEX 1
76.25 +#cmakedefine LEMON_HAVE_CLP 1
76.26 +#cmakedefine LEMON_HAVE_CBC 1
76.27
76.28 -/* Define to 1 if you have CPLEX. */
76.29 -#undef LEMON_HAVE_CPLEX
76.30 +#define LEMON_CPLEX_ 1
76.31 +#define LEMON_CLP_ 2
76.32 +#define LEMON_GLPK_ 3
76.33 +#define LEMON_SOPLEX_ 4
76.34 +#define LEMON_CBC_ 5
76.35
76.36 -/* Define to 1 if you have GLPK. */
76.37 -#undef LEMON_HAVE_GLPK
76.38 +#cmakedefine LEMON_DEFAULT_LP LEMON_@LEMON_DEFAULT_LP@_
76.39 +#cmakedefine LEMON_DEFAULT_MIP LEMON_@LEMON_DEFAULT_MIP@_
76.40
76.41 -/* Define to 1 if you have SOPLEX */
76.42 -#undef LEMON_HAVE_SOPLEX
76.43 +#cmakedefine LEMON_USE_PTHREAD 1
76.44 +#cmakedefine LEMON_USE_WIN32_THREADS 1
76.45
76.46 -/* Define to 1 if you have CLP */
76.47 -#undef LEMON_HAVE_CLP
76.48 -
76.49 -/* Define to 1 if you have CBC */
76.50 -#undef LEMON_HAVE_CBC
76.51 +#endif
77.1 --- a/lemon/connectivity.h Mon Jul 16 16:21:40 2018 +0200
77.2 +++ b/lemon/connectivity.h Wed Oct 17 19:14:07 2018 +0200
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-2010
77.8 + * Copyright (C) 2003-2013
77.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
77.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
77.11 *
77.12 @@ -745,14 +745,37 @@
77.13 /// \brief Check whether an undirected graph is bi-node-connected.
77.14 ///
77.15 /// This function checks whether the given undirected graph is
77.16 - /// bi-node-connected, i.e. any two edges are on same circle.
77.17 + /// bi-node-connected, i.e. a connected graph without articulation
77.18 + /// node.
77.19 ///
77.20 /// \return \c true if the graph bi-node-connected.
77.21 - /// \note By definition, the empty graph is bi-node-connected.
77.22 + ///
77.23 + /// \note By definition,
77.24 + /// \li a graph consisting of zero or one node is bi-node-connected,
77.25 + /// \li a graph consisting of two isolated nodes
77.26 + /// is \e not bi-node-connected and
77.27 + /// \li a graph consisting of two nodes connected by an edge
77.28 + /// is bi-node-connected.
77.29 ///
77.30 /// \see countBiNodeConnectedComponents(), biNodeConnectedComponents()
77.31 template <typename Graph>
77.32 bool biNodeConnected(const Graph& graph) {
77.33 + bool hasNonIsolated = false, hasIsolated = false;
77.34 + for (typename Graph::NodeIt n(graph); n != INVALID; ++n) {
77.35 + if (typename Graph::OutArcIt(graph, n) == INVALID) {
77.36 + if (hasIsolated || hasNonIsolated) {
77.37 + return false;
77.38 + } else {
77.39 + hasIsolated = true;
77.40 + }
77.41 + } else {
77.42 + if (hasIsolated) {
77.43 + return false;
77.44 + } else {
77.45 + hasNonIsolated = true;
77.46 + }
77.47 + }
77.48 + }
77.49 return countBiNodeConnectedComponents(graph) <= 1;
77.50 }
77.51
78.1 --- a/lemon/core.h Mon Jul 16 16:21:40 2018 +0200
78.2 +++ b/lemon/core.h Wed Oct 17 19:14:07 2018 +0200
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-2010
78.8 + * Copyright (C) 2003-2013
78.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
78.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
78.11 *
78.12 @@ -19,6 +19,29 @@
78.13 #ifndef LEMON_CORE_H
78.14 #define LEMON_CORE_H
78.15
78.16 +///\file
78.17 +///\brief LEMON core utilities.
78.18 +///
78.19 +///This header file contains core utilities for LEMON.
78.20 +///It is automatically included by all graph types, therefore it usually
78.21 +///do not have to be included directly.
78.22 +
78.23 +// Disable the following warnings when compiling with MSVC:
78.24 +// C4250: 'class1' : inherits 'class2::member' via dominance
78.25 +// C4267: conversion from 'size_t' to 'type', possible loss of data
78.26 +// C4355: 'this' : used in base member initializer list
78.27 +// C4503: 'function' : decorated name length exceeded, name was truncated
78.28 +// C4800: 'type' : forcing value to bool 'true' or 'false' (performance warning)
78.29 +// C4996: 'function': was declared deprecated
78.30 +#ifdef _MSC_VER
78.31 +#pragma warning( disable : 4250 4267 4355 4503 4800 4996 )
78.32 +#endif
78.33 +
78.34 +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
78.35 +// Needed by the [DI]GRAPH_TYPEDEFS marcos for gcc 4.8
78.36 +#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
78.37 +#endif
78.38 +
78.39 #include <vector>
78.40 #include <algorithm>
78.41
78.42 @@ -27,22 +50,7 @@
78.43 #include <lemon/bits/traits.h>
78.44 #include <lemon/assert.h>
78.45
78.46 -// Disable the following warnings when compiling with MSVC:
78.47 -// C4250: 'class1' : inherits 'class2::member' via dominance
78.48 -// C4355: 'this' : used in base member initializer list
78.49 -// C4503: 'function' : decorated name length exceeded, name was truncated
78.50 -// C4800: 'type' : forcing value to bool 'true' or 'false' (performance warning)
78.51 -// C4996: 'function': was declared deprecated
78.52 -#ifdef _MSC_VER
78.53 -#pragma warning( disable : 4250 4355 4503 4800 4996 )
78.54 -#endif
78.55
78.56 -///\file
78.57 -///\brief LEMON core utilities.
78.58 -///
78.59 -///This header file contains core utilities for LEMON.
78.60 -///It is automatically included by all graph types, therefore it usually
78.61 -///do not have to be included directly.
78.62
78.63 namespace lemon {
78.64
78.65 @@ -148,6 +156,49 @@
78.66 typedef typename Graph::template EdgeMap<int> IntEdgeMap; \
78.67 typedef typename Graph::template EdgeMap<double> DoubleEdgeMap
78.68
78.69 + ///Create convenience typedefs for the bipartite graph types and iterators
78.70 +
78.71 + ///This \c \#define creates the same convenient type definitions as
78.72 + ///defined by \ref GRAPH_TYPEDEFS(BpGraph) and ten more, namely it
78.73 + ///creates \c RedNode, \c RedNodeIt, \c BoolRedNodeMap,
78.74 + ///\c IntRedNodeMap, \c DoubleRedNodeMap, \c BlueNode, \c BlueNodeIt,
78.75 + ///\c BoolBlueNodeMap, \c IntBlueNodeMap, \c DoubleBlueNodeMap.
78.76 + ///
78.77 + ///\note If the graph type is a dependent type, ie. the graph type depend
78.78 + ///on a template parameter, then use \c TEMPLATE_BPGRAPH_TYPEDEFS()
78.79 + ///macro.
78.80 +#define BPGRAPH_TYPEDEFS(BpGraph) \
78.81 + GRAPH_TYPEDEFS(BpGraph); \
78.82 + typedef BpGraph::RedNode RedNode; \
78.83 + typedef BpGraph::RedNodeIt RedNodeIt; \
78.84 + typedef BpGraph::RedNodeMap<bool> BoolRedNodeMap; \
78.85 + typedef BpGraph::RedNodeMap<int> IntRedNodeMap; \
78.86 + typedef BpGraph::RedNodeMap<double> DoubleRedNodeMap; \
78.87 + typedef BpGraph::BlueNode BlueNode; \
78.88 + typedef BpGraph::BlueNodeIt BlueNodeIt; \
78.89 + typedef BpGraph::BlueNodeMap<bool> BoolBlueNodeMap; \
78.90 + typedef BpGraph::BlueNodeMap<int> IntBlueNodeMap; \
78.91 + typedef BpGraph::BlueNodeMap<double> DoubleBlueNodeMap
78.92 +
78.93 + ///Create convenience typedefs for the bipartite graph types and iterators
78.94 +
78.95 + ///\see BPGRAPH_TYPEDEFS
78.96 + ///
78.97 + ///\note Use this macro, if the graph type is a dependent type,
78.98 + ///ie. the graph type depend on a template parameter.
78.99 +#define TEMPLATE_BPGRAPH_TYPEDEFS(BpGraph) \
78.100 + TEMPLATE_GRAPH_TYPEDEFS(BpGraph); \
78.101 + typedef typename BpGraph::RedNode RedNode; \
78.102 + typedef typename BpGraph::RedNodeIt RedNodeIt; \
78.103 + typedef typename BpGraph::template RedNodeMap<bool> BoolRedNodeMap; \
78.104 + typedef typename BpGraph::template RedNodeMap<int> IntRedNodeMap; \
78.105 + typedef typename BpGraph::template RedNodeMap<double> DoubleRedNodeMap; \
78.106 + typedef typename BpGraph::BlueNode BlueNode; \
78.107 + typedef typename BpGraph::BlueNodeIt BlueNodeIt; \
78.108 + typedef typename BpGraph::template BlueNodeMap<bool> BoolBlueNodeMap; \
78.109 + typedef typename BpGraph::template BlueNodeMap<int> IntBlueNodeMap; \
78.110 + typedef typename BpGraph::template BlueNodeMap<double> DoubleBlueNodeMap
78.111 +
78.112 /// \brief Function to count the items in a graph.
78.113 ///
78.114 /// This function counts the items (nodes, arcs etc.) in a graph.
78.115 @@ -199,6 +250,74 @@
78.116 return _core_bits::CountNodesSelector<Graph>::count(g);
78.117 }
78.118
78.119 + namespace _graph_utils_bits {
78.120 +
78.121 + template <typename Graph, typename Enable = void>
78.122 + struct CountRedNodesSelector {
78.123 + static int count(const Graph &g) {
78.124 + return countItems<Graph, typename Graph::RedNode>(g);
78.125 + }
78.126 + };
78.127 +
78.128 + template <typename Graph>
78.129 + struct CountRedNodesSelector<
78.130 + Graph, typename
78.131 + enable_if<typename Graph::NodeNumTag, void>::type>
78.132 + {
78.133 + static int count(const Graph &g) {
78.134 + return g.redNum();
78.135 + }
78.136 + };
78.137 + }
78.138 +
78.139 + /// \brief Function to count the red nodes in the graph.
78.140 + ///
78.141 + /// This function counts the red nodes in the graph.
78.142 + /// The complexity of the function is O(n) but for some
78.143 + /// graph structures it is specialized to run in O(1).
78.144 + ///
78.145 + /// If the graph contains a \e redNum() member function and a
78.146 + /// \e NodeNumTag tag then this function calls directly the member
78.147 + /// function to query the cardinality of the node set.
78.148 + template <typename Graph>
78.149 + inline int countRedNodes(const Graph& g) {
78.150 + return _graph_utils_bits::CountRedNodesSelector<Graph>::count(g);
78.151 + }
78.152 +
78.153 + namespace _graph_utils_bits {
78.154 +
78.155 + template <typename Graph, typename Enable = void>
78.156 + struct CountBlueNodesSelector {
78.157 + static int count(const Graph &g) {
78.158 + return countItems<Graph, typename Graph::BlueNode>(g);
78.159 + }
78.160 + };
78.161 +
78.162 + template <typename Graph>
78.163 + struct CountBlueNodesSelector<
78.164 + Graph, typename
78.165 + enable_if<typename Graph::NodeNumTag, void>::type>
78.166 + {
78.167 + static int count(const Graph &g) {
78.168 + return g.blueNum();
78.169 + }
78.170 + };
78.171 + }
78.172 +
78.173 + /// \brief Function to count the blue nodes in the graph.
78.174 + ///
78.175 + /// This function counts the blue nodes in the graph.
78.176 + /// The complexity of the function is O(n) but for some
78.177 + /// graph structures it is specialized to run in O(1).
78.178 + ///
78.179 + /// If the graph contains a \e blueNum() member function and a
78.180 + /// \e NodeNumTag tag then this function calls directly the member
78.181 + /// function to query the cardinality of the node set.
78.182 + template <typename Graph>
78.183 + inline int countBlueNodes(const Graph& g) {
78.184 + return _graph_utils_bits::CountBlueNodesSelector<Graph>::count(g);
78.185 + }
78.186 +
78.187 // Arc counting:
78.188
78.189 namespace _core_bits {
78.190 @@ -440,13 +559,70 @@
78.191 {
78.192 template <typename From, typename NodeRefMap, typename EdgeRefMap>
78.193 static void copy(const From& from, Graph &to,
78.194 - NodeRefMap& nodeRefMap, EdgeRefMap& edgeRefMap) {
78.195 + NodeRefMap& nodeRefMap,
78.196 + EdgeRefMap& edgeRefMap) {
78.197 to.build(from, nodeRefMap, edgeRefMap);
78.198 }
78.199 };
78.200
78.201 + template <typename BpGraph, typename Enable = void>
78.202 + struct BpGraphCopySelector {
78.203 + template <typename From, typename RedNodeRefMap,
78.204 + typename BlueNodeRefMap, typename EdgeRefMap>
78.205 + static void copy(const From& from, BpGraph &to,
78.206 + RedNodeRefMap& redNodeRefMap,
78.207 + BlueNodeRefMap& blueNodeRefMap,
78.208 + EdgeRefMap& edgeRefMap) {
78.209 + to.clear();
78.210 + for (typename From::RedNodeIt it(from); it != INVALID; ++it) {
78.211 + redNodeRefMap[it] = to.addRedNode();
78.212 + }
78.213 + for (typename From::BlueNodeIt it(from); it != INVALID; ++it) {
78.214 + blueNodeRefMap[it] = to.addBlueNode();
78.215 + }
78.216 + for (typename From::EdgeIt it(from); it != INVALID; ++it) {
78.217 + edgeRefMap[it] = to.addEdge(redNodeRefMap[from.redNode(it)],
78.218 + blueNodeRefMap[from.blueNode(it)]);
78.219 + }
78.220 + }
78.221 + };
78.222 +
78.223 + template <typename BpGraph>
78.224 + struct BpGraphCopySelector<
78.225 + BpGraph,
78.226 + typename enable_if<typename BpGraph::BuildTag, void>::type>
78.227 + {
78.228 + template <typename From, typename RedNodeRefMap,
78.229 + typename BlueNodeRefMap, typename EdgeRefMap>
78.230 + static void copy(const From& from, BpGraph &to,
78.231 + RedNodeRefMap& redNodeRefMap,
78.232 + BlueNodeRefMap& blueNodeRefMap,
78.233 + EdgeRefMap& edgeRefMap) {
78.234 + to.build(from, redNodeRefMap, blueNodeRefMap, edgeRefMap);
78.235 + }
78.236 + };
78.237 +
78.238 }
78.239
78.240 + /// \brief Check whether a graph is undirected.
78.241 + ///
78.242 + /// This function returns \c true if the given graph is undirected.
78.243 +#ifdef DOXYGEN
78.244 + template <typename GR>
78.245 + bool undirected(const GR& g) { return false; }
78.246 +#else
78.247 + template <typename GR>
78.248 + typename enable_if<UndirectedTagIndicator<GR>, bool>::type
78.249 + undirected(const GR&) {
78.250 + return true;
78.251 + }
78.252 + template <typename GR>
78.253 + typename disable_if<UndirectedTagIndicator<GR>, bool>::type
78.254 + undirected(const GR&) {
78.255 + return false;
78.256 + }
78.257 +#endif
78.258 +
78.259 /// \brief Class to copy a digraph.
78.260 ///
78.261 /// Class to copy a digraph to another digraph (duplicate a digraph). The
78.262 @@ -972,6 +1148,454 @@
78.263 return GraphCopy<From, To>(from, to);
78.264 }
78.265
78.266 + /// \brief Class to copy a bipartite graph.
78.267 + ///
78.268 + /// Class to copy a bipartite graph to another graph (duplicate a
78.269 + /// graph). The simplest way of using it is through the
78.270 + /// \c bpGraphCopy() function.
78.271 + ///
78.272 + /// This class not only make a copy of a bipartite graph, but it can
78.273 + /// create references and cross references between the nodes, edges
78.274 + /// and arcs of the two graphs, and it can copy maps for using with
78.275 + /// the newly created graph.
78.276 + ///
78.277 + /// To make a copy from a graph, first an instance of BpGraphCopy
78.278 + /// should be created, then the data belongs to the graph should
78.279 + /// assigned to copy. In the end, the \c run() member should be
78.280 + /// called.
78.281 + ///
78.282 + /// The next code copies a graph with several data:
78.283 + ///\code
78.284 + /// BpGraphCopy<OrigBpGraph, NewBpGraph> cg(orig_graph, new_graph);
78.285 + /// // Create references for the nodes
78.286 + /// OrigBpGraph::NodeMap<NewBpGraph::Node> nr(orig_graph);
78.287 + /// cg.nodeRef(nr);
78.288 + /// // Create cross references (inverse) for the edges
78.289 + /// NewBpGraph::EdgeMap<OrigBpGraph::Edge> ecr(new_graph);
78.290 + /// cg.edgeCrossRef(ecr);
78.291 + /// // Copy a red node map
78.292 + /// OrigBpGraph::RedNodeMap<double> ormap(orig_graph);
78.293 + /// NewBpGraph::RedNodeMap<double> nrmap(new_graph);
78.294 + /// cg.redNodeMap(ormap, nrmap);
78.295 + /// // Copy a node
78.296 + /// OrigBpGraph::Node on;
78.297 + /// NewBpGraph::Node nn;
78.298 + /// cg.node(on, nn);
78.299 + /// // Execute copying
78.300 + /// cg.run();
78.301 + ///\endcode
78.302 + template <typename From, typename To>
78.303 + class BpGraphCopy {
78.304 + private:
78.305 +
78.306 + typedef typename From::Node Node;
78.307 + typedef typename From::RedNode RedNode;
78.308 + typedef typename From::BlueNode BlueNode;
78.309 + typedef typename From::NodeIt NodeIt;
78.310 + typedef typename From::Arc Arc;
78.311 + typedef typename From::ArcIt ArcIt;
78.312 + typedef typename From::Edge Edge;
78.313 + typedef typename From::EdgeIt EdgeIt;
78.314 +
78.315 + typedef typename To::Node TNode;
78.316 + typedef typename To::RedNode TRedNode;
78.317 + typedef typename To::BlueNode TBlueNode;
78.318 + typedef typename To::Arc TArc;
78.319 + typedef typename To::Edge TEdge;
78.320 +
78.321 + typedef typename From::template RedNodeMap<TRedNode> RedNodeRefMap;
78.322 + typedef typename From::template BlueNodeMap<TBlueNode> BlueNodeRefMap;
78.323 + typedef typename From::template EdgeMap<TEdge> EdgeRefMap;
78.324 +
78.325 + struct NodeRefMap {
78.326 + NodeRefMap(const From& from, const RedNodeRefMap& red_node_ref,
78.327 + const BlueNodeRefMap& blue_node_ref)
78.328 + : _from(from), _red_node_ref(red_node_ref),
78.329 + _blue_node_ref(blue_node_ref) {}
78.330 +
78.331 + typedef typename From::Node Key;
78.332 + typedef typename To::Node Value;
78.333 +
78.334 + Value operator[](const Key& key) const {
78.335 + if (_from.red(key)) {
78.336 + return _red_node_ref[_from.asRedNodeUnsafe(key)];
78.337 + } else {
78.338 + return _blue_node_ref[_from.asBlueNodeUnsafe(key)];
78.339 + }
78.340 + }
78.341 +
78.342 + const From& _from;
78.343 + const RedNodeRefMap& _red_node_ref;
78.344 + const BlueNodeRefMap& _blue_node_ref;
78.345 + };
78.346 +
78.347 + struct ArcRefMap {
78.348 + ArcRefMap(const From& from, const To& to, const EdgeRefMap& edge_ref)
78.349 + : _from(from), _to(to), _edge_ref(edge_ref) {}
78.350 +
78.351 + typedef typename From::Arc Key;
78.352 + typedef typename To::Arc Value;
78.353 +
78.354 + Value operator[](const Key& key) const {
78.355 + return _to.direct(_edge_ref[key], _from.direction(key));
78.356 + }
78.357 +
78.358 + const From& _from;
78.359 + const To& _to;
78.360 + const EdgeRefMap& _edge_ref;
78.361 + };
78.362 +
78.363 + public:
78.364 +
78.365 + /// \brief Constructor of BpGraphCopy.
78.366 + ///
78.367 + /// Constructor of BpGraphCopy for copying the content of the
78.368 + /// \c from graph into the \c to graph.
78.369 + BpGraphCopy(const From& from, To& to)
78.370 + : _from(from), _to(to) {}
78.371 +
78.372 + /// \brief Destructor of BpGraphCopy
78.373 + ///
78.374 + /// Destructor of BpGraphCopy.
78.375 + ~BpGraphCopy() {
78.376 + for (int i = 0; i < int(_node_maps.size()); ++i) {
78.377 + delete _node_maps[i];
78.378 + }
78.379 + for (int i = 0; i < int(_red_maps.size()); ++i) {
78.380 + delete _red_maps[i];
78.381 + }
78.382 + for (int i = 0; i < int(_blue_maps.size()); ++i) {
78.383 + delete _blue_maps[i];
78.384 + }
78.385 + for (int i = 0; i < int(_arc_maps.size()); ++i) {
78.386 + delete _arc_maps[i];
78.387 + }
78.388 + for (int i = 0; i < int(_edge_maps.size()); ++i) {
78.389 + delete _edge_maps[i];
78.390 + }
78.391 + }
78.392 +
78.393 + /// \brief Copy the node references into the given map.
78.394 + ///
78.395 + /// This function copies the node references into the given map.
78.396 + /// The parameter should be a map, whose key type is the Node type of
78.397 + /// the source graph, while the value type is the Node type of the
78.398 + /// destination graph.
78.399 + template <typename NodeRef>
78.400 + BpGraphCopy& nodeRef(NodeRef& map) {
78.401 + _node_maps.push_back(new _core_bits::RefCopy<From, Node,
78.402 + NodeRefMap, NodeRef>(map));
78.403 + return *this;
78.404 + }
78.405 +
78.406 + /// \brief Copy the node cross references into the given map.
78.407 + ///
78.408 + /// This function copies the node cross references (reverse references)
78.409 + /// into the given map. The parameter should be a map, whose key type
78.410 + /// is the Node type of the destination graph, while the value type is
78.411 + /// the Node type of the source graph.
78.412 + template <typename NodeCrossRef>
78.413 + BpGraphCopy& nodeCrossRef(NodeCrossRef& map) {
78.414 + _node_maps.push_back(new _core_bits::CrossRefCopy<From, Node,
78.415 + NodeRefMap, NodeCrossRef>(map));
78.416 + return *this;
78.417 + }
78.418 +
78.419 + /// \brief Make a copy of the given node map.
78.420 + ///
78.421 + /// This function makes a copy of the given node map for the newly
78.422 + /// created graph.
78.423 + /// The key type of the new map \c tmap should be the Node type of the
78.424 + /// destination graph, and the key type of the original map \c map
78.425 + /// should be the Node type of the source graph.
78.426 + template <typename FromMap, typename ToMap>
78.427 + BpGraphCopy& nodeMap(const FromMap& map, ToMap& tmap) {
78.428 + _node_maps.push_back(new _core_bits::MapCopy<From, Node,
78.429 + NodeRefMap, FromMap, ToMap>(map, tmap));
78.430 + return *this;
78.431 + }
78.432 +
78.433 + /// \brief Make a copy of the given node.
78.434 + ///
78.435 + /// This function makes a copy of the given node.
78.436 + BpGraphCopy& node(const Node& node, TNode& tnode) {
78.437 + _node_maps.push_back(new _core_bits::ItemCopy<From, Node,
78.438 + NodeRefMap, TNode>(node, tnode));
78.439 + return *this;
78.440 + }
78.441 +
78.442 + /// \brief Copy the red node references into the given map.
78.443 + ///
78.444 + /// This function copies the red node references into the given
78.445 + /// map. The parameter should be a map, whose key type is the
78.446 + /// Node type of the source graph with the red item set, while the
78.447 + /// value type is the Node type of the destination graph.
78.448 + template <typename RedRef>
78.449 + BpGraphCopy& redRef(RedRef& map) {
78.450 + _red_maps.push_back(new _core_bits::RefCopy<From, RedNode,
78.451 + RedNodeRefMap, RedRef>(map));
78.452 + return *this;
78.453 + }
78.454 +
78.455 + /// \brief Copy the red node cross references into the given map.
78.456 + ///
78.457 + /// This function copies the red node cross references (reverse
78.458 + /// references) into the given map. The parameter should be a map,
78.459 + /// whose key type is the Node type of the destination graph with
78.460 + /// the red item set, while the value type is the Node type of the
78.461 + /// source graph.
78.462 + template <typename RedCrossRef>
78.463 + BpGraphCopy& redCrossRef(RedCrossRef& map) {
78.464 + _red_maps.push_back(new _core_bits::CrossRefCopy<From, RedNode,
78.465 + RedNodeRefMap, RedCrossRef>(map));
78.466 + return *this;
78.467 + }
78.468 +
78.469 + /// \brief Make a copy of the given red node map.
78.470 + ///
78.471 + /// This function makes a copy of the given red node map for the newly
78.472 + /// created graph.
78.473 + /// The key type of the new map \c tmap should be the Node type of
78.474 + /// the destination graph with the red items, and the key type of
78.475 + /// the original map \c map should be the Node type of the source
78.476 + /// graph.
78.477 + template <typename FromMap, typename ToMap>
78.478 + BpGraphCopy& redNodeMap(const FromMap& map, ToMap& tmap) {
78.479 + _red_maps.push_back(new _core_bits::MapCopy<From, RedNode,
78.480 + RedNodeRefMap, FromMap, ToMap>(map, tmap));
78.481 + return *this;
78.482 + }
78.483 +
78.484 + /// \brief Make a copy of the given red node.
78.485 + ///
78.486 + /// This function makes a copy of the given red node.
78.487 + BpGraphCopy& redNode(const RedNode& node, TRedNode& tnode) {
78.488 + _red_maps.push_back(new _core_bits::ItemCopy<From, RedNode,
78.489 + RedNodeRefMap, TRedNode>(node, tnode));
78.490 + return *this;
78.491 + }
78.492 +
78.493 + /// \brief Copy the blue node references into the given map.
78.494 + ///
78.495 + /// This function copies the blue node references into the given
78.496 + /// map. The parameter should be a map, whose key type is the
78.497 + /// Node type of the source graph with the blue item set, while the
78.498 + /// value type is the Node type of the destination graph.
78.499 + template <typename BlueRef>
78.500 + BpGraphCopy& blueRef(BlueRef& map) {
78.501 + _blue_maps.push_back(new _core_bits::RefCopy<From, BlueNode,
78.502 + BlueNodeRefMap, BlueRef>(map));
78.503 + return *this;
78.504 + }
78.505 +
78.506 + /// \brief Copy the blue node cross references into the given map.
78.507 + ///
78.508 + /// This function copies the blue node cross references (reverse
78.509 + /// references) into the given map. The parameter should be a map,
78.510 + /// whose key type is the Node type of the destination graph with
78.511 + /// the blue item set, while the value type is the Node type of the
78.512 + /// source graph.
78.513 + template <typename BlueCrossRef>
78.514 + BpGraphCopy& blueCrossRef(BlueCrossRef& map) {
78.515 + _blue_maps.push_back(new _core_bits::CrossRefCopy<From, BlueNode,
78.516 + BlueNodeRefMap, BlueCrossRef>(map));
78.517 + return *this;
78.518 + }
78.519 +
78.520 + /// \brief Make a copy of the given blue node map.
78.521 + ///
78.522 + /// This function makes a copy of the given blue node map for the newly
78.523 + /// created graph.
78.524 + /// The key type of the new map \c tmap should be the Node type of
78.525 + /// the destination graph with the blue items, and the key type of
78.526 + /// the original map \c map should be the Node type of the source
78.527 + /// graph.
78.528 + template <typename FromMap, typename ToMap>
78.529 + BpGraphCopy& blueNodeMap(const FromMap& map, ToMap& tmap) {
78.530 + _blue_maps.push_back(new _core_bits::MapCopy<From, BlueNode,
78.531 + BlueNodeRefMap, FromMap, ToMap>(map, tmap));
78.532 + return *this;
78.533 + }
78.534 +
78.535 + /// \brief Make a copy of the given blue node.
78.536 + ///
78.537 + /// This function makes a copy of the given blue node.
78.538 + BpGraphCopy& blueNode(const BlueNode& node, TBlueNode& tnode) {
78.539 + _blue_maps.push_back(new _core_bits::ItemCopy<From, BlueNode,
78.540 + BlueNodeRefMap, TBlueNode>(node, tnode));
78.541 + return *this;
78.542 + }
78.543 +
78.544 + /// \brief Copy the arc references into the given map.
78.545 + ///
78.546 + /// This function copies the arc references into the given map.
78.547 + /// The parameter should be a map, whose key type is the Arc type of
78.548 + /// the source graph, while the value type is the Arc type of the
78.549 + /// destination graph.
78.550 + template <typename ArcRef>
78.551 + BpGraphCopy& arcRef(ArcRef& map) {
78.552 + _arc_maps.push_back(new _core_bits::RefCopy<From, Arc,
78.553 + ArcRefMap, ArcRef>(map));
78.554 + return *this;
78.555 + }
78.556 +
78.557 + /// \brief Copy the arc cross references into the given map.
78.558 + ///
78.559 + /// This function copies the arc cross references (reverse references)
78.560 + /// into the given map. The parameter should be a map, whose key type
78.561 + /// is the Arc type of the destination graph, while the value type is
78.562 + /// the Arc type of the source graph.
78.563 + template <typename ArcCrossRef>
78.564 + BpGraphCopy& arcCrossRef(ArcCrossRef& map) {
78.565 + _arc_maps.push_back(new _core_bits::CrossRefCopy<From, Arc,
78.566 + ArcRefMap, ArcCrossRef>(map));
78.567 + return *this;
78.568 + }
78.569 +
78.570 + /// \brief Make a copy of the given arc map.
78.571 + ///
78.572 + /// This function makes a copy of the given arc map for the newly
78.573 + /// created graph.
78.574 + /// The key type of the new map \c tmap should be the Arc type of the
78.575 + /// destination graph, and the key type of the original map \c map
78.576 + /// should be the Arc type of the source graph.
78.577 + template <typename FromMap, typename ToMap>
78.578 + BpGraphCopy& arcMap(const FromMap& map, ToMap& tmap) {
78.579 + _arc_maps.push_back(new _core_bits::MapCopy<From, Arc,
78.580 + ArcRefMap, FromMap, ToMap>(map, tmap));
78.581 + return *this;
78.582 + }
78.583 +
78.584 + /// \brief Make a copy of the given arc.
78.585 + ///
78.586 + /// This function makes a copy of the given arc.
78.587 + BpGraphCopy& arc(const Arc& arc, TArc& tarc) {
78.588 + _arc_maps.push_back(new _core_bits::ItemCopy<From, Arc,
78.589 + ArcRefMap, TArc>(arc, tarc));
78.590 + return *this;
78.591 + }
78.592 +
78.593 + /// \brief Copy the edge references into the given map.
78.594 + ///
78.595 + /// This function copies the edge references into the given map.
78.596 + /// The parameter should be a map, whose key type is the Edge type of
78.597 + /// the source graph, while the value type is the Edge type of the
78.598 + /// destination graph.
78.599 + template <typename EdgeRef>
78.600 + BpGraphCopy& edgeRef(EdgeRef& map) {
78.601 + _edge_maps.push_back(new _core_bits::RefCopy<From, Edge,
78.602 + EdgeRefMap, EdgeRef>(map));
78.603 + return *this;
78.604 + }
78.605 +
78.606 + /// \brief Copy the edge cross references into the given map.
78.607 + ///
78.608 + /// This function copies the edge cross references (reverse references)
78.609 + /// into the given map. The parameter should be a map, whose key type
78.610 + /// is the Edge type of the destination graph, while the value type is
78.611 + /// the Edge type of the source graph.
78.612 + template <typename EdgeCrossRef>
78.613 + BpGraphCopy& edgeCrossRef(EdgeCrossRef& map) {
78.614 + _edge_maps.push_back(new _core_bits::CrossRefCopy<From,
78.615 + Edge, EdgeRefMap, EdgeCrossRef>(map));
78.616 + return *this;
78.617 + }
78.618 +
78.619 + /// \brief Make a copy of the given edge map.
78.620 + ///
78.621 + /// This function makes a copy of the given edge map for the newly
78.622 + /// created graph.
78.623 + /// The key type of the new map \c tmap should be the Edge type of the
78.624 + /// destination graph, and the key type of the original map \c map
78.625 + /// should be the Edge type of the source graph.
78.626 + template <typename FromMap, typename ToMap>
78.627 + BpGraphCopy& edgeMap(const FromMap& map, ToMap& tmap) {
78.628 + _edge_maps.push_back(new _core_bits::MapCopy<From, Edge,
78.629 + EdgeRefMap, FromMap, ToMap>(map, tmap));
78.630 + return *this;
78.631 + }
78.632 +
78.633 + /// \brief Make a copy of the given edge.
78.634 + ///
78.635 + /// This function makes a copy of the given edge.
78.636 + BpGraphCopy& edge(const Edge& edge, TEdge& tedge) {
78.637 + _edge_maps.push_back(new _core_bits::ItemCopy<From, Edge,
78.638 + EdgeRefMap, TEdge>(edge, tedge));
78.639 + return *this;
78.640 + }
78.641 +
78.642 + /// \brief Execute copying.
78.643 + ///
78.644 + /// This function executes the copying of the graph along with the
78.645 + /// copying of the assigned data.
78.646 + void run() {
78.647 + RedNodeRefMap redNodeRefMap(_from);
78.648 + BlueNodeRefMap blueNodeRefMap(_from);
78.649 + NodeRefMap nodeRefMap(_from, redNodeRefMap, blueNodeRefMap);
78.650 + EdgeRefMap edgeRefMap(_from);
78.651 + ArcRefMap arcRefMap(_from, _to, edgeRefMap);
78.652 + _core_bits::BpGraphCopySelector<To>::
78.653 + copy(_from, _to, redNodeRefMap, blueNodeRefMap, edgeRefMap);
78.654 + for (int i = 0; i < int(_node_maps.size()); ++i) {
78.655 + _node_maps[i]->copy(_from, nodeRefMap);
78.656 + }
78.657 + for (int i = 0; i < int(_red_maps.size()); ++i) {
78.658 + _red_maps[i]->copy(_from, redNodeRefMap);
78.659 + }
78.660 + for (int i = 0; i < int(_blue_maps.size()); ++i) {
78.661 + _blue_maps[i]->copy(_from, blueNodeRefMap);
78.662 + }
78.663 + for (int i = 0; i < int(_edge_maps.size()); ++i) {
78.664 + _edge_maps[i]->copy(_from, edgeRefMap);
78.665 + }
78.666 + for (int i = 0; i < int(_arc_maps.size()); ++i) {
78.667 + _arc_maps[i]->copy(_from, arcRefMap);
78.668 + }
78.669 + }
78.670 +
78.671 + private:
78.672 +
78.673 + const From& _from;
78.674 + To& _to;
78.675 +
78.676 + std::vector<_core_bits::MapCopyBase<From, Node, NodeRefMap>* >
78.677 + _node_maps;
78.678 +
78.679 + std::vector<_core_bits::MapCopyBase<From, RedNode, RedNodeRefMap>* >
78.680 + _red_maps;
78.681 +
78.682 + std::vector<_core_bits::MapCopyBase<From, BlueNode, BlueNodeRefMap>* >
78.683 + _blue_maps;
78.684 +
78.685 + std::vector<_core_bits::MapCopyBase<From, Arc, ArcRefMap>* >
78.686 + _arc_maps;
78.687 +
78.688 + std::vector<_core_bits::MapCopyBase<From, Edge, EdgeRefMap>* >
78.689 + _edge_maps;
78.690 +
78.691 + };
78.692 +
78.693 + /// \brief Copy a graph to another graph.
78.694 + ///
78.695 + /// This function copies a graph to another graph.
78.696 + /// The complete usage of it is detailed in the BpGraphCopy class,
78.697 + /// but a short example shows a basic work:
78.698 + ///\code
78.699 + /// graphCopy(src, trg).nodeRef(nr).edgeCrossRef(ecr).run();
78.700 + ///\endcode
78.701 + ///
78.702 + /// After the copy the \c nr map will contain the mapping from the
78.703 + /// nodes of the \c from graph to the nodes of the \c to graph and
78.704 + /// \c ecr will contain the mapping from the edges of the \c to graph
78.705 + /// to the edges of the \c from graph.
78.706 + ///
78.707 + /// \see BpGraphCopy
78.708 + template <typename From, typename To>
78.709 + BpGraphCopy<From, To>
78.710 + bpGraphCopy(const From& from, To& to) {
78.711 + return BpGraphCopy<From, To>(from, to);
78.712 + }
78.713 +
78.714 namespace _core_bits {
78.715
78.716 template <typename Graph, typename Enable = void>
79.1 --- a/lemon/cost_scaling.h Mon Jul 16 16:21:40 2018 +0200
79.2 +++ b/lemon/cost_scaling.h Wed Oct 17 19:14:07 2018 +0200
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-2010
79.8 + * Copyright (C) 2003-2013
79.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
79.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
79.11 *
79.12 @@ -91,11 +91,18 @@
79.13 ///
79.14 /// \ref CostScaling implements a cost scaling algorithm that performs
79.15 /// push/augment and relabel operations for finding a \ref min_cost_flow
79.16 - /// "minimum cost flow" \ref amo93networkflows, \ref goldberg90approximation,
79.17 - /// \ref goldberg97efficient, \ref bunnagel98efficient.
79.18 + /// "minimum cost flow" \cite amo93networkflows,
79.19 + /// \cite goldberg90approximation,
79.20 + /// \cite goldberg97efficient, \cite bunnagel98efficient.
79.21 /// It is a highly efficient primal-dual solution method, which
79.22 /// can be viewed as the generalization of the \ref Preflow
79.23 /// "preflow push-relabel" algorithm for the maximum flow problem.
79.24 + /// It is a polynomial algorithm, its running time complexity is
79.25 + /// \f$O(n^2m\log(nK))\f$, where <i>K</i> denotes the maximum arc cost.
79.26 + ///
79.27 + /// In general, \ref NetworkSimplex and \ref CostScaling are the fastest
79.28 + /// implementations available in LEMON for solving this problem.
79.29 + /// (For more information, see \ref min_cost_flow_algs "the module page".)
79.30 ///
79.31 /// Most of the parameters of the problem (except for the digraph)
79.32 /// can be given using separate functions, and the algorithm can be
79.33 @@ -113,10 +120,11 @@
79.34 /// In most cases, this parameter should not be set directly,
79.35 /// consider to use the named template parameters instead.
79.36 ///
79.37 - /// \warning Both number types must be signed and all input data must
79.38 + /// \warning Both \c V and \c C must be signed number types.
79.39 + /// \warning All input data (capacities, supply values, and costs) must
79.40 /// be integer.
79.41 - /// \warning This algorithm does not support negative costs for such
79.42 - /// arcs that have infinite upper bound.
79.43 + /// \warning This algorithm does not support negative costs for
79.44 + /// arcs having infinite upper bound.
79.45 ///
79.46 /// \note %CostScaling provides three different internal methods,
79.47 /// from which the most efficient one is used by default.
79.48 @@ -145,7 +153,8 @@
79.49 /// otherwise it is \c double.
79.50 typedef typename TR::LargeCost LargeCost;
79.51
79.52 - /// The \ref CostScalingDefaultTraits "traits class" of the algorithm
79.53 + /// \brief The \ref lemon::CostScalingDefaultTraits "traits class"
79.54 + /// of the algorithm
79.55 typedef TR Traits;
79.56
79.57 public:
79.58 @@ -178,7 +187,7 @@
79.59 /// in their base operations, which are used in conjunction with the
79.60 /// relabel operation.
79.61 /// By default, the so called \ref PARTIAL_AUGMENT
79.62 - /// "Partial Augment-Relabel" method is used, which proved to be
79.63 + /// "Partial Augment-Relabel" method is used, which turned out to be
79.64 /// the most efficient and the most robust on various test inputs.
79.65 /// However, the other methods can be selected using the \ref run()
79.66 /// function with the proper parameter.
79.67 @@ -205,7 +214,8 @@
79.68 typedef std::vector<Cost> CostVector;
79.69 typedef std::vector<LargeCost> LargeCostVector;
79.70 typedef std::vector<char> BoolVector;
79.71 - // Note: vector<char> is used instead of vector<bool> for efficiency reasons
79.72 + // Note: vector<char> is used instead of vector<bool>
79.73 + // for efficiency reasons
79.74
79.75 private:
79.76
79.77 @@ -233,7 +243,6 @@
79.78 std::vector<Value>& _v;
79.79 };
79.80
79.81 - typedef StaticVectorMap<StaticDigraph::Node, LargeCost> LargeCostNodeMap;
79.82 typedef StaticVectorMap<StaticDigraph::Arc, LargeCost> LargeCostArcMap;
79.83
79.84 private:
79.85 @@ -247,7 +256,7 @@
79.86 int _root;
79.87
79.88 // Parameters of the problem
79.89 - bool _have_lower;
79.90 + bool _has_lower;
79.91 Value _sum_supply;
79.92 int _sup_node_num;
79.93
79.94 @@ -284,14 +293,6 @@
79.95 IntVector _rank;
79.96 int _max_rank;
79.97
79.98 - // Data for a StaticDigraph structure
79.99 - typedef std::pair<int, int> IntPair;
79.100 - StaticDigraph _sgr;
79.101 - std::vector<IntPair> _arc_vec;
79.102 - std::vector<LargeCost> _cost_vec;
79.103 - LargeCostArcMap _cost_map;
79.104 - LargeCostNodeMap _pi_map;
79.105 -
79.106 public:
79.107
79.108 /// \brief Constant for infinite upper bounds (capacities).
79.109 @@ -338,7 +339,6 @@
79.110 /// \param graph The digraph the algorithm runs on.
79.111 CostScaling(const GR& graph) :
79.112 _graph(graph), _node_id(graph), _arc_idf(graph), _arc_idb(graph),
79.113 - _cost_map(_cost_vec), _pi_map(_pi),
79.114 INF(std::numeric_limits<Value>::has_infinity ?
79.115 std::numeric_limits<Value>::infinity() :
79.116 std::numeric_limits<Value>::max())
79.117 @@ -372,10 +372,9 @@
79.118 /// \return <tt>(*this)</tt>
79.119 template <typename LowerMap>
79.120 CostScaling& lowerMap(const LowerMap& map) {
79.121 - _have_lower = true;
79.122 + _has_lower = true;
79.123 for (ArcIt a(_graph); a != INVALID; ++a) {
79.124 _lower[_arc_idf[a]] = map[a];
79.125 - _lower[_arc_idb[a]] = map[a];
79.126 }
79.127 return *this;
79.128 }
79.129 @@ -447,7 +446,7 @@
79.130 /// calling \ref run(), the supply of each node will be set to zero.
79.131 ///
79.132 /// Using this function has the same effect as using \ref supplyMap()
79.133 - /// with such a map in which \c k is assigned to \c s, \c -k is
79.134 + /// with a map in which \c k is assigned to \c s, \c -k is
79.135 /// assigned to \c t and all other nodes have zero supply value.
79.136 ///
79.137 /// \param s The source node.
79.138 @@ -493,7 +492,7 @@
79.139 ///
79.140 /// \param method The internal method that will be used in the
79.141 /// algorithm. For more information, see \ref Method.
79.142 - /// \param factor The cost scaling factor. It must be larger than one.
79.143 + /// \param factor The cost scaling factor. It must be at least two.
79.144 ///
79.145 /// \return \c INFEASIBLE if no feasible flow exists,
79.146 /// \n \c OPTIMAL if the problem has optimal solution
79.147 @@ -507,7 +506,8 @@
79.148 ///
79.149 /// \see ProblemType, Method
79.150 /// \see resetParams(), reset()
79.151 - ProblemType run(Method method = PARTIAL_AUGMENT, int factor = 8) {
79.152 + ProblemType run(Method method = PARTIAL_AUGMENT, int factor = 16) {
79.153 + LEMON_ASSERT(factor >= 2, "The scaling factor must be at least 2");
79.154 _alpha = factor;
79.155 ProblemType pt = init();
79.156 if (pt != OPTIMAL) return pt;
79.157 @@ -567,22 +567,29 @@
79.158 _scost[j] = 0;
79.159 _scost[_reverse[j]] = 0;
79.160 }
79.161 - _have_lower = false;
79.162 + _has_lower = false;
79.163 return *this;
79.164 }
79.165
79.166 - /// \brief Reset all the parameters that have been given before.
79.167 + /// \brief Reset the internal data structures and all the parameters
79.168 + /// that have been given before.
79.169 ///
79.170 - /// This function resets all the paramaters that have been given
79.171 - /// before using functions \ref lowerMap(), \ref upperMap(),
79.172 - /// \ref costMap(), \ref supplyMap(), \ref stSupply().
79.173 + /// This function resets the internal data structures and all the
79.174 + /// paramaters that have been given before using functions \ref lowerMap(),
79.175 + /// \ref upperMap(), \ref costMap(), \ref supplyMap(), \ref stSupply().
79.176 ///
79.177 - /// It is useful for multiple run() calls. If this function is not
79.178 - /// used, all the parameters given before are kept for the next
79.179 - /// \ref run() call.
79.180 - /// However, the underlying digraph must not be modified after this
79.181 - /// class have been constructed, since it copies and extends the graph.
79.182 + /// It is useful for multiple \ref run() calls. By default, all the given
79.183 + /// parameters are kept for the next \ref run() call, unless
79.184 + /// \ref resetParams() or \ref reset() is used.
79.185 + /// If the underlying digraph was also modified after the construction
79.186 + /// of the class or the last \ref reset() call, then the \ref reset()
79.187 + /// function must be used, otherwise \ref resetParams() is sufficient.
79.188 + ///
79.189 + /// See \ref resetParams() for examples.
79.190 + ///
79.191 /// \return <tt>(*this)</tt>
79.192 + ///
79.193 + /// \see resetParams(), run()
79.194 CostScaling& reset() {
79.195 // Resize vectors
79.196 _node_num = countNodes(_graph);
79.197 @@ -608,9 +615,6 @@
79.198 _excess.resize(_res_node_num);
79.199 _next_out.resize(_res_node_num);
79.200
79.201 - _arc_vec.reserve(_res_arc_num);
79.202 - _cost_vec.reserve(_res_arc_num);
79.203 -
79.204 // Copy the graph
79.205 int i = 0, j = 0, k = 2 * _arc_num + _node_num;
79.206 for (NodeIt n(_graph); n != INVALID; ++n, ++i) {
79.207 @@ -667,7 +671,7 @@
79.208 /// \brief Return the total cost of the found flow.
79.209 ///
79.210 /// This function returns the total cost of the found flow.
79.211 - /// Its complexity is O(e).
79.212 + /// Its complexity is O(m).
79.213 ///
79.214 /// \note The return type of the function can be specified as a
79.215 /// template parameter. For example,
79.216 @@ -705,7 +709,8 @@
79.217 return _res_cap[_arc_idb[a]];
79.218 }
79.219
79.220 - /// \brief Return the flow map (the primal solution).
79.221 + /// \brief Copy the flow values (the primal solution) into the
79.222 + /// given map.
79.223 ///
79.224 /// This function copies the flow value on each arc into the given
79.225 /// map. The \c Value type of the algorithm must be convertible to
79.226 @@ -729,7 +734,8 @@
79.227 return static_cast<Cost>(_pi[_node_id[n]]);
79.228 }
79.229
79.230 - /// \brief Return the potential map (the dual solution).
79.231 + /// \brief Copy the potential values (the dual solution) into the
79.232 + /// given map.
79.233 ///
79.234 /// This function copies the potential (dual value) of each node
79.235 /// into the given map.
79.236 @@ -759,6 +765,10 @@
79.237 }
79.238 if (_sum_supply > 0) return INFEASIBLE;
79.239
79.240 + // Check lower and upper bounds
79.241 + LEMON_DEBUG(checkBoundMaps(),
79.242 + "Upper bounds must be greater or equal to the lower bounds");
79.243 +
79.244
79.245 // Initialize vectors
79.246 for (int i = 0; i != _res_node_num; ++i) {
79.247 @@ -769,7 +779,7 @@
79.248 // Remove infinite upper bounds and check negative arcs
79.249 const Value MAX = std::numeric_limits<Value>::max();
79.250 int last_out;
79.251 - if (_have_lower) {
79.252 + if (_has_lower) {
79.253 for (int i = 0; i != _root; ++i) {
79.254 last_out = _first_out[i+1];
79.255 for (int j = _first_out[i]; j != last_out; ++j) {
79.256 @@ -826,7 +836,7 @@
79.257 for (NodeIt n(_graph); n != INVALID; ++n) {
79.258 sup[n] = _supply[_node_id[n]];
79.259 }
79.260 - if (_have_lower) {
79.261 + if (_has_lower) {
79.262 for (ArcIt a(_graph); a != INVALID; ++a) {
79.263 int j = _arc_idf[a];
79.264 Value c = _lower[j];
79.265 @@ -886,14 +896,6 @@
79.266 }
79.267 }
79.268
79.269 - return OPTIMAL;
79.270 - }
79.271 -
79.272 - // Execute the algorithm and transform the results
79.273 - void start(Method method) {
79.274 - // Maximum path length for partial augment
79.275 - const int MAX_PATH_LENGTH = 4;
79.276 -
79.277 // Initialize data structures for buckets
79.278 _max_rank = _alpha * _res_node_num;
79.279 _buckets.resize(_max_rank);
79.280 @@ -901,7 +903,22 @@
79.281 _bucket_prev.resize(_res_node_num + 1);
79.282 _rank.resize(_res_node_num + 1);
79.283
79.284 - // Execute the algorithm
79.285 + return OPTIMAL;
79.286 + }
79.287 +
79.288 + // Check if the upper bound is greater than or equal to the lower bound
79.289 + // on each forward arc.
79.290 + bool checkBoundMaps() {
79.291 + for (int j = 0; j != _res_arc_num; ++j) {
79.292 + if (_forward[j] && _upper[j] < _lower[j]) return false;
79.293 + }
79.294 + return true;
79.295 + }
79.296 +
79.297 + // Execute the algorithm and transform the results
79.298 + void start(Method method) {
79.299 + const int MAX_PARTIAL_PATH_LENGTH = 4;
79.300 +
79.301 switch (method) {
79.302 case PUSH:
79.303 startPush();
79.304 @@ -910,32 +927,73 @@
79.305 startAugment(_res_node_num - 1);
79.306 break;
79.307 case PARTIAL_AUGMENT:
79.308 - startAugment(MAX_PATH_LENGTH);
79.309 + startAugment(MAX_PARTIAL_PATH_LENGTH);
79.310 break;
79.311 }
79.312
79.313 - // Compute node potentials for the original costs
79.314 - _arc_vec.clear();
79.315 - _cost_vec.clear();
79.316 - for (int j = 0; j != _res_arc_num; ++j) {
79.317 - if (_res_cap[j] > 0) {
79.318 - _arc_vec.push_back(IntPair(_source[j], _target[j]));
79.319 - _cost_vec.push_back(_scost[j]);
79.320 + // Compute node potentials (dual solution)
79.321 + for (int i = 0; i != _res_node_num; ++i) {
79.322 + _pi[i] = static_cast<Cost>(_pi[i] / (_res_node_num * _alpha));
79.323 + }
79.324 + bool optimal = true;
79.325 + for (int i = 0; optimal && i != _res_node_num; ++i) {
79.326 + LargeCost pi_i = _pi[i];
79.327 + int last_out = _first_out[i+1];
79.328 + for (int j = _first_out[i]; j != last_out; ++j) {
79.329 + if (_res_cap[j] > 0 && _scost[j] + pi_i - _pi[_target[j]] < 0) {
79.330 + optimal = false;
79.331 + break;
79.332 + }
79.333 }
79.334 }
79.335 - _sgr.build(_res_node_num, _arc_vec.begin(), _arc_vec.end());
79.336
79.337 - typename BellmanFord<StaticDigraph, LargeCostArcMap>
79.338 - ::template SetDistMap<LargeCostNodeMap>::Create bf(_sgr, _cost_map);
79.339 - bf.distMap(_pi_map);
79.340 - bf.init(0);
79.341 - bf.start();
79.342 + if (!optimal) {
79.343 + // Compute node potentials for the original costs with BellmanFord
79.344 + // (if it is necessary)
79.345 + typedef std::pair<int, int> IntPair;
79.346 + StaticDigraph sgr;
79.347 + std::vector<IntPair> arc_vec;
79.348 + std::vector<LargeCost> cost_vec;
79.349 + LargeCostArcMap cost_map(cost_vec);
79.350 +
79.351 + arc_vec.clear();
79.352 + cost_vec.clear();
79.353 + for (int j = 0; j != _res_arc_num; ++j) {
79.354 + if (_res_cap[j] > 0) {
79.355 + int u = _source[j], v = _target[j];
79.356 + arc_vec.push_back(IntPair(u, v));
79.357 + cost_vec.push_back(_scost[j] + _pi[u] - _pi[v]);
79.358 + }
79.359 + }
79.360 + sgr.build(_res_node_num, arc_vec.begin(), arc_vec.end());
79.361 +
79.362 + typename BellmanFord<StaticDigraph, LargeCostArcMap>::Create
79.363 + bf(sgr, cost_map);
79.364 + bf.init(0);
79.365 + bf.start();
79.366 +
79.367 + for (int i = 0; i != _res_node_num; ++i) {
79.368 + _pi[i] += bf.dist(sgr.node(i));
79.369 + }
79.370 + }
79.371 +
79.372 + // Shift potentials to meet the requirements of the GEQ type
79.373 + // optimality conditions
79.374 + LargeCost max_pot = _pi[_root];
79.375 + for (int i = 0; i != _res_node_num; ++i) {
79.376 + if (_pi[i] > max_pot) max_pot = _pi[i];
79.377 + }
79.378 + if (max_pot != 0) {
79.379 + for (int i = 0; i != _res_node_num; ++i) {
79.380 + _pi[i] -= max_pot;
79.381 + }
79.382 + }
79.383
79.384 // Handle non-zero lower bounds
79.385 - if (_have_lower) {
79.386 + if (_has_lower) {
79.387 int limit = _first_out[_root];
79.388 for (int j = 0; j != limit; ++j) {
79.389 - if (!_forward[j]) _res_cap[j] += _lower[j];
79.390 + if (_forward[j]) _res_cap[_reverse[j]] += _lower[j];
79.391 }
79.392 }
79.393 }
79.394 @@ -947,13 +1005,15 @@
79.395 int last_out = _first_out[u+1];
79.396 LargeCost pi_u = _pi[u];
79.397 for (int a = _first_out[u]; a != last_out; ++a) {
79.398 - int v = _target[a];
79.399 - if (_res_cap[a] > 0 && _cost[a] + pi_u - _pi[v] < 0) {
79.400 - Value delta = _res_cap[a];
79.401 - _excess[u] -= delta;
79.402 - _excess[v] += delta;
79.403 - _res_cap[a] = 0;
79.404 - _res_cap[_reverse[a]] += delta;
79.405 + Value delta = _res_cap[a];
79.406 + if (delta > 0) {
79.407 + int v = _target[a];
79.408 + if (_cost[a] + pi_u - _pi[v] < 0) {
79.409 + _excess[u] -= delta;
79.410 + _excess[v] += delta;
79.411 + _res_cap[a] = 0;
79.412 + _res_cap[_reverse[a]] += delta;
79.413 + }
79.414 }
79.415 }
79.416 }
79.417 @@ -969,53 +1029,254 @@
79.418 }
79.419 }
79.420
79.421 - // Early termination heuristic
79.422 - bool earlyTermination() {
79.423 - const double EARLY_TERM_FACTOR = 3.0;
79.424 + // Price (potential) refinement heuristic
79.425 + bool priceRefinement() {
79.426
79.427 - // Build a static residual graph
79.428 - _arc_vec.clear();
79.429 - _cost_vec.clear();
79.430 - for (int j = 0; j != _res_arc_num; ++j) {
79.431 - if (_res_cap[j] > 0) {
79.432 - _arc_vec.push_back(IntPair(_source[j], _target[j]));
79.433 - _cost_vec.push_back(_cost[j] + 1);
79.434 + // Stack for stroing the topological order
79.435 + IntVector stack(_res_node_num);
79.436 + int stack_top;
79.437 +
79.438 + // Perform phases
79.439 + while (topologicalSort(stack, stack_top)) {
79.440 +
79.441 + // Compute node ranks in the acyclic admissible network and
79.442 + // store the nodes in buckets
79.443 + for (int i = 0; i != _res_node_num; ++i) {
79.444 + _rank[i] = 0;
79.445 }
79.446 + const int bucket_end = _root + 1;
79.447 + for (int r = 0; r != _max_rank; ++r) {
79.448 + _buckets[r] = bucket_end;
79.449 + }
79.450 + int top_rank = 0;
79.451 + for ( ; stack_top >= 0; --stack_top) {
79.452 + int u = stack[stack_top], v;
79.453 + int rank_u = _rank[u];
79.454 +
79.455 + LargeCost rc, pi_u = _pi[u];
79.456 + int last_out = _first_out[u+1];
79.457 + for (int a = _first_out[u]; a != last_out; ++a) {
79.458 + if (_res_cap[a] > 0) {
79.459 + v = _target[a];
79.460 + rc = _cost[a] + pi_u - _pi[v];
79.461 + if (rc < 0) {
79.462 + LargeCost nrc = static_cast<LargeCost>((-rc - 0.5) / _epsilon);
79.463 + if (nrc < LargeCost(_max_rank)) {
79.464 + int new_rank_v = rank_u + static_cast<int>(nrc);
79.465 + if (new_rank_v > _rank[v]) {
79.466 + _rank[v] = new_rank_v;
79.467 + }
79.468 + }
79.469 + }
79.470 + }
79.471 + }
79.472 +
79.473 + if (rank_u > 0) {
79.474 + top_rank = std::max(top_rank, rank_u);
79.475 + int bfirst = _buckets[rank_u];
79.476 + _bucket_next[u] = bfirst;
79.477 + _bucket_prev[bfirst] = u;
79.478 + _buckets[rank_u] = u;
79.479 + }
79.480 + }
79.481 +
79.482 + // Check if the current flow is epsilon-optimal
79.483 + if (top_rank == 0) {
79.484 + return true;
79.485 + }
79.486 +
79.487 + // Process buckets in top-down order
79.488 + for (int rank = top_rank; rank > 0; --rank) {
79.489 + while (_buckets[rank] != bucket_end) {
79.490 + // Remove the first node from the current bucket
79.491 + int u = _buckets[rank];
79.492 + _buckets[rank] = _bucket_next[u];
79.493 +
79.494 + // Search the outgoing arcs of u
79.495 + LargeCost rc, pi_u = _pi[u];
79.496 + int last_out = _first_out[u+1];
79.497 + int v, old_rank_v, new_rank_v;
79.498 + for (int a = _first_out[u]; a != last_out; ++a) {
79.499 + if (_res_cap[a] > 0) {
79.500 + v = _target[a];
79.501 + old_rank_v = _rank[v];
79.502 +
79.503 + if (old_rank_v < rank) {
79.504 +
79.505 + // Compute the new rank of node v
79.506 + rc = _cost[a] + pi_u - _pi[v];
79.507 + if (rc < 0) {
79.508 + new_rank_v = rank;
79.509 + } else {
79.510 + LargeCost nrc = rc / _epsilon;
79.511 + new_rank_v = 0;
79.512 + if (nrc < LargeCost(_max_rank)) {
79.513 + new_rank_v = rank - 1 - static_cast<int>(nrc);
79.514 + }
79.515 + }
79.516 +
79.517 + // Change the rank of node v
79.518 + if (new_rank_v > old_rank_v) {
79.519 + _rank[v] = new_rank_v;
79.520 +
79.521 + // Remove v from its old bucket
79.522 + if (old_rank_v > 0) {
79.523 + if (_buckets[old_rank_v] == v) {
79.524 + _buckets[old_rank_v] = _bucket_next[v];
79.525 + } else {
79.526 + int pv = _bucket_prev[v], nv = _bucket_next[v];
79.527 + _bucket_next[pv] = nv;
79.528 + _bucket_prev[nv] = pv;
79.529 + }
79.530 + }
79.531 +
79.532 + // Insert v into its new bucket
79.533 + int nv = _buckets[new_rank_v];
79.534 + _bucket_next[v] = nv;
79.535 + _bucket_prev[nv] = v;
79.536 + _buckets[new_rank_v] = v;
79.537 + }
79.538 + }
79.539 + }
79.540 + }
79.541 +
79.542 + // Refine potential of node u
79.543 + _pi[u] -= rank * _epsilon;
79.544 + }
79.545 + }
79.546 +
79.547 }
79.548 - _sgr.build(_res_node_num, _arc_vec.begin(), _arc_vec.end());
79.549
79.550 - // Run Bellman-Ford algorithm to check if the current flow is optimal
79.551 - BellmanFord<StaticDigraph, LargeCostArcMap> bf(_sgr, _cost_map);
79.552 - bf.init(0);
79.553 - bool done = false;
79.554 - int K = int(EARLY_TERM_FACTOR * std::sqrt(double(_res_node_num)));
79.555 - for (int i = 0; i < K && !done; ++i) {
79.556 - done = bf.processNextWeakRound();
79.557 + return false;
79.558 + }
79.559 +
79.560 + // Find and cancel cycles in the admissible network and
79.561 + // determine topological order using DFS
79.562 + bool topologicalSort(IntVector &stack, int &stack_top) {
79.563 + const int MAX_CYCLE_CANCEL = 1;
79.564 +
79.565 + BoolVector reached(_res_node_num, false);
79.566 + BoolVector processed(_res_node_num, false);
79.567 + IntVector pred(_res_node_num);
79.568 + for (int i = 0; i != _res_node_num; ++i) {
79.569 + _next_out[i] = _first_out[i];
79.570 }
79.571 - return done;
79.572 + stack_top = -1;
79.573 +
79.574 + int cycle_cnt = 0;
79.575 + for (int start = 0; start != _res_node_num; ++start) {
79.576 + if (reached[start]) continue;
79.577 +
79.578 + // Start DFS search from this start node
79.579 + pred[start] = -1;
79.580 + int tip = start, v;
79.581 + while (true) {
79.582 + // Check the outgoing arcs of the current tip node
79.583 + reached[tip] = true;
79.584 + LargeCost pi_tip = _pi[tip];
79.585 + int a, last_out = _first_out[tip+1];
79.586 + for (a = _next_out[tip]; a != last_out; ++a) {
79.587 + if (_res_cap[a] > 0) {
79.588 + v = _target[a];
79.589 + if (_cost[a] + pi_tip - _pi[v] < 0) {
79.590 + if (!reached[v]) {
79.591 + // A new node is reached
79.592 + reached[v] = true;
79.593 + pred[v] = tip;
79.594 + _next_out[tip] = a;
79.595 + tip = v;
79.596 + a = _next_out[tip];
79.597 + last_out = _first_out[tip+1];
79.598 + break;
79.599 + }
79.600 + else if (!processed[v]) {
79.601 + // A cycle is found
79.602 + ++cycle_cnt;
79.603 + _next_out[tip] = a;
79.604 +
79.605 + // Find the minimum residual capacity along the cycle
79.606 + Value d, delta = _res_cap[a];
79.607 + int u, delta_node = tip;
79.608 + for (u = tip; u != v; ) {
79.609 + u = pred[u];
79.610 + d = _res_cap[_next_out[u]];
79.611 + if (d <= delta) {
79.612 + delta = d;
79.613 + delta_node = u;
79.614 + }
79.615 + }
79.616 +
79.617 + // Augment along the cycle
79.618 + _res_cap[a] -= delta;
79.619 + _res_cap[_reverse[a]] += delta;
79.620 + for (u = tip; u != v; ) {
79.621 + u = pred[u];
79.622 + int ca = _next_out[u];
79.623 + _res_cap[ca] -= delta;
79.624 + _res_cap[_reverse[ca]] += delta;
79.625 + }
79.626 +
79.627 + // Check the maximum number of cycle canceling
79.628 + if (cycle_cnt >= MAX_CYCLE_CANCEL) {
79.629 + return false;
79.630 + }
79.631 +
79.632 + // Roll back search to delta_node
79.633 + if (delta_node != tip) {
79.634 + for (u = tip; u != delta_node; u = pred[u]) {
79.635 + reached[u] = false;
79.636 + }
79.637 + tip = delta_node;
79.638 + a = _next_out[tip] + 1;
79.639 + last_out = _first_out[tip+1];
79.640 + break;
79.641 + }
79.642 + }
79.643 + }
79.644 + }
79.645 + }
79.646 +
79.647 + // Step back to the previous node
79.648 + if (a == last_out) {
79.649 + processed[tip] = true;
79.650 + stack[++stack_top] = tip;
79.651 + tip = pred[tip];
79.652 + if (tip < 0) {
79.653 + // Finish DFS from the current start node
79.654 + break;
79.655 + }
79.656 + ++_next_out[tip];
79.657 + }
79.658 + }
79.659 +
79.660 + }
79.661 +
79.662 + return (cycle_cnt == 0);
79.663 }
79.664
79.665 // Global potential update heuristic
79.666 void globalUpdate() {
79.667 - int bucket_end = _root + 1;
79.668 + const int bucket_end = _root + 1;
79.669
79.670 // Initialize buckets
79.671 for (int r = 0; r != _max_rank; ++r) {
79.672 _buckets[r] = bucket_end;
79.673 }
79.674 Value total_excess = 0;
79.675 + int b0 = bucket_end;
79.676 for (int i = 0; i != _res_node_num; ++i) {
79.677 if (_excess[i] < 0) {
79.678 _rank[i] = 0;
79.679 - _bucket_next[i] = _buckets[0];
79.680 - _bucket_prev[_buckets[0]] = i;
79.681 - _buckets[0] = i;
79.682 + _bucket_next[i] = b0;
79.683 + _bucket_prev[b0] = i;
79.684 + b0 = i;
79.685 } else {
79.686 total_excess += _excess[i];
79.687 _rank[i] = _max_rank;
79.688 }
79.689 }
79.690 if (total_excess == 0) return;
79.691 + _buckets[0] = b0;
79.692
79.693 // Search the buckets
79.694 int r = 0;
79.695 @@ -1025,7 +1286,7 @@
79.696 int u = _buckets[r];
79.697 _buckets[r] = _bucket_next[u];
79.698
79.699 - // Search the incomming arcs of u
79.700 + // Search the incoming arcs of u
79.701 LargeCost pi_u = _pi[u];
79.702 int last_out = _first_out[u+1];
79.703 for (int a = _first_out[u]; a != last_out; ++a) {
79.704 @@ -1037,8 +1298,9 @@
79.705 // Compute the new rank of v
79.706 LargeCost nrc = (_cost[ra] + _pi[v] - pi_u) / _epsilon;
79.707 int new_rank_v = old_rank_v;
79.708 - if (nrc < LargeCost(_max_rank))
79.709 - new_rank_v = r + 1 + int(nrc);
79.710 + if (nrc < LargeCost(_max_rank)) {
79.711 + new_rank_v = r + 1 + static_cast<int>(nrc);
79.712 + }
79.713
79.714 // Change the rank of v
79.715 if (new_rank_v < old_rank_v) {
79.716 @@ -1050,14 +1312,16 @@
79.717 if (_buckets[old_rank_v] == v) {
79.718 _buckets[old_rank_v] = _bucket_next[v];
79.719 } else {
79.720 - _bucket_next[_bucket_prev[v]] = _bucket_next[v];
79.721 - _bucket_prev[_bucket_next[v]] = _bucket_prev[v];
79.722 + int pv = _bucket_prev[v], nv = _bucket_next[v];
79.723 + _bucket_next[pv] = nv;
79.724 + _bucket_prev[nv] = pv;
79.725 }
79.726 }
79.727
79.728 - // Insert v to its new bucket
79.729 - _bucket_next[v] = _buckets[new_rank_v];
79.730 - _bucket_prev[_buckets[new_rank_v]] = v;
79.731 + // Insert v into its new bucket
79.732 + int nv = _buckets[new_rank_v];
79.733 + _bucket_next[v] = nv;
79.734 + _bucket_prev[nv] = v;
79.735 _buckets[new_rank_v] = v;
79.736 }
79.737 }
79.738 @@ -1086,23 +1350,25 @@
79.739 /// Execute the algorithm performing augment and relabel operations
79.740 void startAugment(int max_length) {
79.741 // Paramters for heuristics
79.742 - const int EARLY_TERM_EPSILON_LIMIT = 1000;
79.743 - const double GLOBAL_UPDATE_FACTOR = 3.0;
79.744 -
79.745 - const int global_update_freq = int(GLOBAL_UPDATE_FACTOR *
79.746 + const int PRICE_REFINEMENT_LIMIT = 2;
79.747 + const double GLOBAL_UPDATE_FACTOR = 1.0;
79.748 + const int global_update_skip = static_cast<int>(GLOBAL_UPDATE_FACTOR *
79.749 (_res_node_num + _sup_node_num * _sup_node_num));
79.750 - int next_update_limit = global_update_freq;
79.751 -
79.752 - int relabel_cnt = 0;
79.753 + int next_global_update_limit = global_update_skip;
79.754
79.755 // Perform cost scaling phases
79.756 - std::vector<int> path;
79.757 + IntVector path;
79.758 + BoolVector path_arc(_res_arc_num, false);
79.759 + int relabel_cnt = 0;
79.760 + int eps_phase_cnt = 0;
79.761 for ( ; _epsilon >= 1; _epsilon = _epsilon < _alpha && _epsilon > 1 ?
79.762 1 : _epsilon / _alpha )
79.763 {
79.764 - // Early termination heuristic
79.765 - if (_epsilon <= EARLY_TERM_EPSILON_LIMIT) {
79.766 - if (earlyTermination()) break;
79.767 + ++eps_phase_cnt;
79.768 +
79.769 + // Price refinement heuristic
79.770 + if (eps_phase_cnt >= PRICE_REFINEMENT_LIMIT) {
79.771 + if (priceRefinement()) continue;
79.772 }
79.773
79.774 // Initialize current phase
79.775 @@ -1119,32 +1385,45 @@
79.776 int start = _active_nodes.front();
79.777
79.778 // Find an augmenting path from the start node
79.779 - path.clear();
79.780 int tip = start;
79.781 - while (_excess[tip] >= 0 && int(path.size()) < max_length) {
79.782 + while (int(path.size()) < max_length && _excess[tip] >= 0) {
79.783 int u;
79.784 - LargeCost min_red_cost, rc, pi_tip = _pi[tip];
79.785 + LargeCost rc, min_red_cost = std::numeric_limits<LargeCost>::max();
79.786 + LargeCost pi_tip = _pi[tip];
79.787 int last_out = _first_out[tip+1];
79.788 for (int a = _next_out[tip]; a != last_out; ++a) {
79.789 - u = _target[a];
79.790 - if (_res_cap[a] > 0 && _cost[a] + pi_tip - _pi[u] < 0) {
79.791 - path.push_back(a);
79.792 - _next_out[tip] = a;
79.793 - tip = u;
79.794 - goto next_step;
79.795 + if (_res_cap[a] > 0) {
79.796 + u = _target[a];
79.797 + rc = _cost[a] + pi_tip - _pi[u];
79.798 + if (rc < 0) {
79.799 + path.push_back(a);
79.800 + _next_out[tip] = a;
79.801 + if (path_arc[a]) {
79.802 + goto augment; // a cycle is found, stop path search
79.803 + }
79.804 + tip = u;
79.805 + path_arc[a] = true;
79.806 + goto next_step;
79.807 + }
79.808 + else if (rc < min_red_cost) {
79.809 + min_red_cost = rc;
79.810 + }
79.811 }
79.812 }
79.813
79.814 // Relabel tip node
79.815 - min_red_cost = std::numeric_limits<LargeCost>::max();
79.816 if (tip != start) {
79.817 int ra = _reverse[path.back()];
79.818 - min_red_cost = _cost[ra] + pi_tip - _pi[_target[ra]];
79.819 + min_red_cost =
79.820 + std::min(min_red_cost, _cost[ra] + pi_tip - _pi[_target[ra]]);
79.821 }
79.822 + last_out = _next_out[tip];
79.823 for (int a = _first_out[tip]; a != last_out; ++a) {
79.824 - rc = _cost[a] + pi_tip - _pi[_target[a]];
79.825 - if (_res_cap[a] > 0 && rc < min_red_cost) {
79.826 - min_red_cost = rc;
79.827 + if (_res_cap[a] > 0) {
79.828 + rc = _cost[a] + pi_tip - _pi[_target[a]];
79.829 + if (rc < min_red_cost) {
79.830 + min_red_cost = rc;
79.831 + }
79.832 }
79.833 }
79.834 _pi[tip] -= min_red_cost + _epsilon;
79.835 @@ -1153,7 +1432,9 @@
79.836
79.837 // Step back
79.838 if (tip != start) {
79.839 - tip = _source[path.back()];
79.840 + int pa = path.back();
79.841 + path_arc[pa] = false;
79.842 + tip = _source[pa];
79.843 path.pop_back();
79.844 }
79.845
79.846 @@ -1161,51 +1442,59 @@
79.847 }
79.848
79.849 // Augment along the found path (as much flow as possible)
79.850 + augment:
79.851 Value delta;
79.852 int pa, u, v = start;
79.853 for (int i = 0; i != int(path.size()); ++i) {
79.854 pa = path[i];
79.855 u = v;
79.856 v = _target[pa];
79.857 + path_arc[pa] = false;
79.858 delta = std::min(_res_cap[pa], _excess[u]);
79.859 _res_cap[pa] -= delta;
79.860 _res_cap[_reverse[pa]] += delta;
79.861 _excess[u] -= delta;
79.862 _excess[v] += delta;
79.863 - if (_excess[v] > 0 && _excess[v] <= delta)
79.864 + if (_excess[v] > 0 && _excess[v] <= delta) {
79.865 _active_nodes.push_back(v);
79.866 + }
79.867 }
79.868 + path.clear();
79.869
79.870 // Global update heuristic
79.871 - if (relabel_cnt >= next_update_limit) {
79.872 + if (relabel_cnt >= next_global_update_limit) {
79.873 globalUpdate();
79.874 - next_update_limit += global_update_freq;
79.875 + next_global_update_limit += global_update_skip;
79.876 }
79.877 }
79.878 +
79.879 }
79.880 +
79.881 }
79.882
79.883 /// Execute the algorithm performing push and relabel operations
79.884 void startPush() {
79.885 // Paramters for heuristics
79.886 - const int EARLY_TERM_EPSILON_LIMIT = 1000;
79.887 + const int PRICE_REFINEMENT_LIMIT = 2;
79.888 const double GLOBAL_UPDATE_FACTOR = 2.0;
79.889
79.890 - const int global_update_freq = int(GLOBAL_UPDATE_FACTOR *
79.891 + const int global_update_skip = static_cast<int>(GLOBAL_UPDATE_FACTOR *
79.892 (_res_node_num + _sup_node_num * _sup_node_num));
79.893 - int next_update_limit = global_update_freq;
79.894 -
79.895 - int relabel_cnt = 0;
79.896 + int next_global_update_limit = global_update_skip;
79.897
79.898 // Perform cost scaling phases
79.899 BoolVector hyper(_res_node_num, false);
79.900 LargeCostVector hyper_cost(_res_node_num);
79.901 + int relabel_cnt = 0;
79.902 + int eps_phase_cnt = 0;
79.903 for ( ; _epsilon >= 1; _epsilon = _epsilon < _alpha && _epsilon > 1 ?
79.904 1 : _epsilon / _alpha )
79.905 {
79.906 - // Early termination heuristic
79.907 - if (_epsilon <= EARLY_TERM_EPSILON_LIMIT) {
79.908 - if (earlyTermination()) break;
79.909 + ++eps_phase_cnt;
79.910 +
79.911 + // Price refinement heuristic
79.912 + if (eps_phase_cnt >= PRICE_REFINEMENT_LIMIT) {
79.913 + if (priceRefinement()) continue;
79.914 }
79.915
79.916 // Initialize current phase
79.917 @@ -1277,9 +1566,11 @@
79.918 min_red_cost = hyper[n] ? -hyper_cost[n] :
79.919 std::numeric_limits<LargeCost>::max();
79.920 for (int a = _first_out[n]; a != last_out; ++a) {
79.921 - rc = _cost[a] + pi_n - _pi[_target[a]];
79.922 - if (_res_cap[a] > 0 && rc < min_red_cost) {
79.923 - min_red_cost = rc;
79.924 + if (_res_cap[a] > 0) {
79.925 + rc = _cost[a] + pi_n - _pi[_target[a]];
79.926 + if (rc < min_red_cost) {
79.927 + min_red_cost = rc;
79.928 + }
79.929 }
79.930 }
79.931 _pi[n] -= min_red_cost + _epsilon;
79.932 @@ -1297,11 +1588,11 @@
79.933 }
79.934
79.935 // Global update heuristic
79.936 - if (relabel_cnt >= next_update_limit) {
79.937 + if (relabel_cnt >= next_global_update_limit) {
79.938 globalUpdate();
79.939 for (int u = 0; u != _res_node_num; ++u)
79.940 hyper[u] = false;
79.941 - next_update_limit += global_update_freq;
79.942 + next_global_update_limit += global_update_skip;
79.943 }
79.944 }
79.945 }
80.1 --- a/lemon/counter.h Mon Jul 16 16:21:40 2018 +0200
80.2 +++ b/lemon/counter.h Wed Oct 17 19:14:07 2018 +0200
80.3 @@ -22,6 +22,8 @@
80.4 #include <string>
80.5 #include <iostream>
80.6
80.7 +#include <lemon/core.h>
80.8 +
80.9 ///\ingroup timecount
80.10 ///\file
80.11 ///\brief Tools for counting steps and events
81.1 --- a/lemon/cplex.cc Mon Jul 16 16:21:40 2018 +0200
81.2 +++ b/lemon/cplex.cc Wed Oct 17 19:14:07 2018 +0200
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-2010
81.8 + * Copyright (C) 2003-2013
81.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
81.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
81.11 *
81.12 @@ -37,36 +37,54 @@
81.13 }
81.14 }
81.15
81.16 + void CplexEnv::incCnt()
81.17 + {
81.18 + _cnt_lock->lock();
81.19 + ++(*_cnt);
81.20 + _cnt_lock->unlock();
81.21 + }
81.22 +
81.23 + void CplexEnv::decCnt()
81.24 + {
81.25 + _cnt_lock->lock();
81.26 + --(*_cnt);
81.27 + if (*_cnt == 0) {
81.28 + delete _cnt;
81.29 + _cnt_lock->unlock();
81.30 + delete _cnt_lock;
81.31 + CPXcloseCPLEX(&_env);
81.32 + }
81.33 + else _cnt_lock->unlock();
81.34 + }
81.35 +
81.36 CplexEnv::CplexEnv() {
81.37 int status;
81.38 + _env = CPXopenCPLEX(&status);
81.39 + if (_env == 0)
81.40 + throw LicenseError(status);
81.41 _cnt = new int;
81.42 - _env = CPXopenCPLEX(&status);
81.43 - if (_env == 0) {
81.44 - delete _cnt;
81.45 - _cnt = 0;
81.46 - throw LicenseError(status);
81.47 - }
81.48 + (*_cnt) = 1;
81.49 + _cnt_lock = new bits::Lock;
81.50 }
81.51
81.52 CplexEnv::CplexEnv(const CplexEnv& other) {
81.53 _env = other._env;
81.54 _cnt = other._cnt;
81.55 - ++(*_cnt);
81.56 + _cnt_lock = other._cnt_lock;
81.57 + incCnt();
81.58 }
81.59
81.60 CplexEnv& CplexEnv::operator=(const CplexEnv& other) {
81.61 + decCnt();
81.62 _env = other._env;
81.63 _cnt = other._cnt;
81.64 - ++(*_cnt);
81.65 + _cnt_lock = other._cnt_lock;
81.66 + incCnt();
81.67 return *this;
81.68 }
81.69
81.70 CplexEnv::~CplexEnv() {
81.71 - --(*_cnt);
81.72 - if (*_cnt == 0) {
81.73 - delete _cnt;
81.74 - CPXcloseCPLEX(&_env);
81.75 - }
81.76 + decCnt();
81.77 }
81.78
81.79 CplexBase::CplexBase() : LpBase() {
81.80 @@ -491,6 +509,17 @@
81.81 _message_enabled ? CPX_ON : CPX_OFF);
81.82 }
81.83
81.84 + void CplexBase::_write(std::string file, std::string format) const
81.85 + {
81.86 + if(format == "MPS" || format == "LP")
81.87 + CPXwriteprob(cplexEnv(), cplexLp(), file.c_str(), format.c_str());
81.88 + else if(format == "SOL")
81.89 + CPXsolwrite(cplexEnv(), cplexLp(), file.c_str());
81.90 + else throw UnsupportedFormatError(format);
81.91 + }
81.92 +
81.93 +
81.94 +
81.95 // CplexLp members
81.96
81.97 CplexLp::CplexLp()
82.1 --- a/lemon/cplex.h Mon Jul 16 16:21:40 2018 +0200
82.2 +++ b/lemon/cplex.h Wed Oct 17 19:14:07 2018 +0200
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-2013
82.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
82.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
82.11 *
82.12 @@ -23,6 +23,7 @@
82.13 ///\brief Header of the LEMON-CPLEX lp solver interface.
82.14
82.15 #include <lemon/lp_base.h>
82.16 +#include <lemon/bits/lock.h>
82.17
82.18 struct cpxenv;
82.19 struct cpxlp;
82.20 @@ -40,7 +41,11 @@
82.21 private:
82.22 cpxenv* _env;
82.23 mutable int* _cnt;
82.24 + mutable bits::Lock* _cnt_lock;
82.25
82.26 + void incCnt();
82.27 + void decCnt();
82.28 +
82.29 public:
82.30
82.31 /// \brief This exception is thrown when the license check is not
82.32 @@ -150,6 +155,8 @@
82.33
82.34 bool _message_enabled;
82.35
82.36 + void _write(std::string file, std::string format) const;
82.37 +
82.38 public:
82.39
82.40 /// Returns the used \c CplexEnv instance
82.41 @@ -170,6 +177,19 @@
82.42 /// Returns the cplex problem object
82.43 const cpxlp* cplexLp() const { return _prob; }
82.44
82.45 +#ifdef DOXYGEN
82.46 + /// Write the problem or the solution to a file in the given format
82.47 +
82.48 + /// This function writes the problem or the solution
82.49 + /// to a file in the given format.
82.50 + /// Trying to write in an unsupported format will trigger
82.51 + /// \ref lemon::LpBase::UnsupportedFormatError "UnsupportedFormatError".
82.52 + /// \param file The file path
82.53 + /// \param format The output file format.
82.54 + /// Supportted formats are "MPS", "LP" and "SOL".
82.55 + void write(std::string file, std::string format = "MPS") const {}
82.56 +#endif
82.57 +
82.58 };
82.59
82.60 /// \brief Interface for the CPLEX LP solver
83.1 --- a/lemon/cycle_canceling.h Mon Jul 16 16:21:40 2018 +0200
83.2 +++ b/lemon/cycle_canceling.h Wed Oct 17 19:14:07 2018 +0200
83.3 @@ -2,7 +2,7 @@
83.4 *
83.5 * This file is a part of LEMON, a generic C++ optimization library.
83.6 *
83.7 - * Copyright (C) 2003-2010
83.8 + * Copyright (C) 2003-2013
83.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
83.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
83.11 *
83.12 @@ -35,6 +35,7 @@
83.13 #include <lemon/circulation.h>
83.14 #include <lemon/bellman_ford.h>
83.15 #include <lemon/howard_mmc.h>
83.16 +#include <lemon/hartmann_orlin_mmc.h>
83.17
83.18 namespace lemon {
83.19
83.20 @@ -46,13 +47,14 @@
83.21 ///
83.22 /// \ref CycleCanceling implements three different cycle-canceling
83.23 /// algorithms for finding a \ref min_cost_flow "minimum cost flow"
83.24 - /// \ref amo93networkflows, \ref klein67primal,
83.25 - /// \ref goldberg89cyclecanceling.
83.26 - /// The most efficent one (both theoretically and practically)
83.27 - /// is the \ref CANCEL_AND_TIGHTEN "Cancel and Tighten" algorithm,
83.28 - /// thus it is the default method.
83.29 - /// It is strongly polynomial, but in practice, it is typically much
83.30 - /// slower than the scaling algorithms and NetworkSimplex.
83.31 + /// \cite amo93networkflows, \cite klein67primal,
83.32 + /// \cite goldberg89cyclecanceling.
83.33 + /// The most efficent one is the \ref CANCEL_AND_TIGHTEN
83.34 + /// "Cancel-and-Tighten" algorithm, thus it is the default method.
83.35 + /// It runs in strongly polynomial time \f$O(n^2 m^2 \log n)\f$,
83.36 + /// but in practice, it is typically orders of magnitude slower than
83.37 + /// the scaling algorithms and \ref NetworkSimplex.
83.38 + /// (For more information, see \ref min_cost_flow_algs "the module page".)
83.39 ///
83.40 /// Most of the parameters of the problem (except for the digraph)
83.41 /// can be given using separate functions, and the algorithm can be
83.42 @@ -65,10 +67,11 @@
83.43 /// \tparam C The number type used for costs and potentials in the
83.44 /// algorithm. By default, it is the same as \c V.
83.45 ///
83.46 - /// \warning Both number types must be signed and all input data must
83.47 + /// \warning Both \c V and \c C must be signed number types.
83.48 + /// \warning All input data (capacities, supply values, and costs) must
83.49 /// be integer.
83.50 - /// \warning This algorithm does not support negative costs for such
83.51 - /// arcs that have infinite upper bound.
83.52 + /// \warning This algorithm does not support negative costs for
83.53 + /// arcs having infinite upper bound.
83.54 ///
83.55 /// \note For more information about the three available methods,
83.56 /// see \ref Method.
83.57 @@ -115,27 +118,28 @@
83.58 /// for the \ref run() function.
83.59 ///
83.60 /// \ref CycleCanceling provides three different cycle-canceling
83.61 - /// methods. By default, \ref CANCEL_AND_TIGHTEN "Cancel and Tighten"
83.62 - /// is used, which proved to be the most efficient and the most robust
83.63 - /// on various test inputs.
83.64 + /// methods. By default, \ref CANCEL_AND_TIGHTEN "Cancel-and-Tighten"
83.65 + /// is used, which is by far the most efficient and the most robust.
83.66 /// However, the other methods can be selected using the \ref run()
83.67 /// function with the proper parameter.
83.68 enum Method {
83.69 /// A simple cycle-canceling method, which uses the
83.70 - /// \ref BellmanFord "Bellman-Ford" algorithm with limited iteration
83.71 - /// number for detecting negative cycles in the residual network.
83.72 + /// \ref BellmanFord "Bellman-Ford" algorithm for detecting negative
83.73 + /// cycles in the residual network.
83.74 + /// The number of Bellman-Ford iterations is bounded by a successively
83.75 + /// increased limit.
83.76 SIMPLE_CYCLE_CANCELING,
83.77 /// The "Minimum Mean Cycle-Canceling" algorithm, which is a
83.78 /// well-known strongly polynomial method
83.79 - /// \ref goldberg89cyclecanceling. It improves along a
83.80 + /// \cite goldberg89cyclecanceling. It improves along a
83.81 /// \ref min_mean_cycle "minimum mean cycle" in each iteration.
83.82 - /// Its running time complexity is O(n<sup>2</sup>m<sup>3</sup>log(n)).
83.83 + /// Its running time complexity is \f$O(n^2 m^3 \log n)\f$.
83.84 MINIMUM_MEAN_CYCLE_CANCELING,
83.85 - /// The "Cancel And Tighten" algorithm, which can be viewed as an
83.86 + /// The "Cancel-and-Tighten" algorithm, which can be viewed as an
83.87 /// improved version of the previous method
83.88 - /// \ref goldberg89cyclecanceling.
83.89 + /// \cite goldberg89cyclecanceling.
83.90 /// It is faster both in theory and in practice, its running time
83.91 - /// complexity is O(n<sup>2</sup>m<sup>2</sup>log(n)).
83.92 + /// complexity is \f$O(n^2 m^2 \log n)\f$.
83.93 CANCEL_AND_TIGHTEN
83.94 };
83.95
83.96 @@ -191,7 +195,7 @@
83.97 int _root;
83.98
83.99 // Parameters of the problem
83.100 - bool _have_lower;
83.101 + bool _has_lower;
83.102 Value _sum_supply;
83.103
83.104 // Data structures for storing the digraph
83.105 @@ -274,10 +278,9 @@
83.106 /// \return <tt>(*this)</tt>
83.107 template <typename LowerMap>
83.108 CycleCanceling& lowerMap(const LowerMap& map) {
83.109 - _have_lower = true;
83.110 + _has_lower = true;
83.111 for (ArcIt a(_graph); a != INVALID; ++a) {
83.112 _lower[_arc_idf[a]] = map[a];
83.113 - _lower[_arc_idb[a]] = map[a];
83.114 }
83.115 return *this;
83.116 }
83.117 @@ -349,7 +352,7 @@
83.118 /// calling \ref run(), the supply of each node will be set to zero.
83.119 ///
83.120 /// Using this function has the same effect as using \ref supplyMap()
83.121 - /// with such a map in which \c k is assigned to \c s, \c -k is
83.122 + /// with a map in which \c k is assigned to \c s, \c -k is
83.123 /// assigned to \c t and all other nodes have zero supply value.
83.124 ///
83.125 /// \param s The source node.
83.126 @@ -467,7 +470,7 @@
83.127 _cost[j] = 0;
83.128 _cost[_reverse[j]] = 0;
83.129 }
83.130 - _have_lower = false;
83.131 + _has_lower = false;
83.132 return *this;
83.133 }
83.134
83.135 @@ -572,7 +575,7 @@
83.136 /// \brief Return the total cost of the found flow.
83.137 ///
83.138 /// This function returns the total cost of the found flow.
83.139 - /// Its complexity is O(e).
83.140 + /// Its complexity is O(m).
83.141 ///
83.142 /// \note The return type of the function can be specified as a
83.143 /// template parameter. For example,
83.144 @@ -610,7 +613,8 @@
83.145 return _res_cap[_arc_idb[a]];
83.146 }
83.147
83.148 - /// \brief Return the flow map (the primal solution).
83.149 + /// \brief Copy the flow values (the primal solution) into the
83.150 + /// given map.
83.151 ///
83.152 /// This function copies the flow value on each arc into the given
83.153 /// map. The \c Value type of the algorithm must be convertible to
83.154 @@ -634,7 +638,8 @@
83.155 return static_cast<Cost>(_pi[_node_id[n]]);
83.156 }
83.157
83.158 - /// \brief Return the potential map (the dual solution).
83.159 + /// \brief Copy the potential values (the dual solution) into the
83.160 + /// given map.
83.161 ///
83.162 /// This function copies the potential (dual value) of each node
83.163 /// into the given map.
83.164 @@ -664,6 +669,10 @@
83.165 }
83.166 if (_sum_supply > 0) return INFEASIBLE;
83.167
83.168 + // Check lower and upper bounds
83.169 + LEMON_DEBUG(checkBoundMaps(),
83.170 + "Upper bounds must be greater or equal to the lower bounds");
83.171 +
83.172
83.173 // Initialize vectors
83.174 for (int i = 0; i != _res_node_num; ++i) {
83.175 @@ -674,7 +683,7 @@
83.176 // Remove infinite upper bounds and check negative arcs
83.177 const Value MAX = std::numeric_limits<Value>::max();
83.178 int last_out;
83.179 - if (_have_lower) {
83.180 + if (_has_lower) {
83.181 for (int i = 0; i != _root; ++i) {
83.182 last_out = _first_out[i+1];
83.183 for (int j = _first_out[i]; j != last_out; ++j) {
83.184 @@ -717,7 +726,7 @@
83.185 for (NodeIt n(_graph); n != INVALID; ++n) {
83.186 sup[n] = _supply[_node_id[n]];
83.187 }
83.188 - if (_have_lower) {
83.189 + if (_has_lower) {
83.190 for (ArcIt a(_graph); a != INVALID; ++a) {
83.191 int j = _arc_idf[a];
83.192 Value c = _lower[j];
83.193 @@ -774,6 +783,15 @@
83.194 return OPTIMAL;
83.195 }
83.196
83.197 + // Check if the upper bound is greater than or equal to the lower bound
83.198 + // on each forward arc.
83.199 + bool checkBoundMaps() {
83.200 + for (int j = 0; j != _res_arc_num; ++j) {
83.201 + if (_forward[j] && _upper[j] < _lower[j]) return false;
83.202 + }
83.203 + return true;
83.204 + }
83.205 +
83.206 // Build a StaticDigraph structure containing the current
83.207 // residual network
83.208 void buildResidualNetwork() {
83.209 @@ -816,10 +834,10 @@
83.210 }
83.211
83.212 // Handle non-zero lower bounds
83.213 - if (_have_lower) {
83.214 + if (_has_lower) {
83.215 int limit = _first_out[_root];
83.216 for (int j = 0; j != limit; ++j) {
83.217 - if (!_forward[j]) _res_cap[j] += _lower[j];
83.218 + if (_forward[j]) _res_cap[_reverse[j]] += _lower[j];
83.219 }
83.220 }
83.221 }
83.222 @@ -922,18 +940,41 @@
83.223
83.224 // Execute the "Minimum Mean Cycle Canceling" method
83.225 void startMinMeanCycleCanceling() {
83.226 - typedef SimplePath<StaticDigraph> SPath;
83.227 + typedef Path<StaticDigraph> SPath;
83.228 typedef typename SPath::ArcIt SPathArcIt;
83.229 typedef typename HowardMmc<StaticDigraph, CostArcMap>
83.230 - ::template SetPath<SPath>::Create MMC;
83.231 + ::template SetPath<SPath>::Create HwMmc;
83.232 + typedef typename HartmannOrlinMmc<StaticDigraph, CostArcMap>
83.233 + ::template SetPath<SPath>::Create HoMmc;
83.234 +
83.235 + const double HW_ITER_LIMIT_FACTOR = 1.0;
83.236 + const int HW_ITER_LIMIT_MIN_VALUE = 5;
83.237 +
83.238 + const int hw_iter_limit =
83.239 + std::max(static_cast<int>(HW_ITER_LIMIT_FACTOR * _node_num),
83.240 + HW_ITER_LIMIT_MIN_VALUE);
83.241
83.242 SPath cycle;
83.243 - MMC mmc(_sgr, _cost_map);
83.244 - mmc.cycle(cycle);
83.245 + HwMmc hw_mmc(_sgr, _cost_map);
83.246 + hw_mmc.cycle(cycle);
83.247 buildResidualNetwork();
83.248 - while (mmc.findCycleMean() && mmc.cycleCost() < 0) {
83.249 - // Find the cycle
83.250 - mmc.findCycle();
83.251 + while (true) {
83.252 +
83.253 + typename HwMmc::TerminationCause hw_tc =
83.254 + hw_mmc.findCycleMean(hw_iter_limit);
83.255 + if (hw_tc == HwMmc::ITERATION_LIMIT) {
83.256 + // Howard's algorithm reached the iteration limit, start a
83.257 + // strongly polynomial algorithm instead
83.258 + HoMmc ho_mmc(_sgr, _cost_map);
83.259 + ho_mmc.cycle(cycle);
83.260 + // Find a minimum mean cycle (Hartmann-Orlin algorithm)
83.261 + if (!(ho_mmc.findCycleMean() && ho_mmc.cycleCost() < 0)) break;
83.262 + ho_mmc.findCycle();
83.263 + } else {
83.264 + // Find a minimum mean cycle (Howard algorithm)
83.265 + if (!(hw_tc == HwMmc::OPTIMAL && hw_mmc.cycleCost() < 0)) break;
83.266 + hw_mmc.findCycle();
83.267 + }
83.268
83.269 // Compute delta value
83.270 Value delta = INF;
83.271 @@ -954,11 +995,17 @@
83.272 }
83.273 }
83.274
83.275 - // Execute the "Cancel And Tighten" method
83.276 + // Execute the "Cancel-and-Tighten" method
83.277 void startCancelAndTighten() {
83.278 // Constants for the min mean cycle computations
83.279 const double LIMIT_FACTOR = 1.0;
83.280 const int MIN_LIMIT = 5;
83.281 + const double HW_ITER_LIMIT_FACTOR = 1.0;
83.282 + const int HW_ITER_LIMIT_MIN_VALUE = 5;
83.283 +
83.284 + const int hw_iter_limit =
83.285 + std::max(static_cast<int>(HW_ITER_LIMIT_FACTOR * _node_num),
83.286 + HW_ITER_LIMIT_MIN_VALUE);
83.287
83.288 // Contruct auxiliary data vectors
83.289 DoubleVector pi(_res_node_num, 0.0);
83.290 @@ -1132,17 +1179,30 @@
83.291 }
83.292 }
83.293 } else {
83.294 - typedef HowardMmc<StaticDigraph, CostArcMap> MMC;
83.295 + typedef HowardMmc<StaticDigraph, CostArcMap> HwMmc;
83.296 + typedef HartmannOrlinMmc<StaticDigraph, CostArcMap> HoMmc;
83.297 typedef typename BellmanFord<StaticDigraph, CostArcMap>
83.298 ::template SetDistMap<CostNodeMap>::Create BF;
83.299
83.300 // Set epsilon to the minimum cycle mean
83.301 + Cost cycle_cost = 0;
83.302 + int cycle_size = 1;
83.303 buildResidualNetwork();
83.304 - MMC mmc(_sgr, _cost_map);
83.305 - mmc.findCycleMean();
83.306 - epsilon = -mmc.cycleMean();
83.307 - Cost cycle_cost = mmc.cycleCost();
83.308 - int cycle_size = mmc.cycleSize();
83.309 + HwMmc hw_mmc(_sgr, _cost_map);
83.310 + if (hw_mmc.findCycleMean(hw_iter_limit) == HwMmc::ITERATION_LIMIT) {
83.311 + // Howard's algorithm reached the iteration limit, start a
83.312 + // strongly polynomial algorithm instead
83.313 + HoMmc ho_mmc(_sgr, _cost_map);
83.314 + ho_mmc.findCycleMean();
83.315 + epsilon = -ho_mmc.cycleMean();
83.316 + cycle_cost = ho_mmc.cycleCost();
83.317 + cycle_size = ho_mmc.cycleSize();
83.318 + } else {
83.319 + // Set epsilon
83.320 + epsilon = -hw_mmc.cycleMean();
83.321 + cycle_cost = hw_mmc.cycleCost();
83.322 + cycle_size = hw_mmc.cycleSize();
83.323 + }
83.324
83.325 // Compute feasible potentials for the current epsilon
83.326 for (int i = 0; i != int(_cost_vec.size()); ++i) {
84.1 --- a/lemon/dfs.h Mon Jul 16 16:21:40 2018 +0200
84.2 +++ b/lemon/dfs.h Wed Oct 17 19:14:07 2018 +0200
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-2010
84.8 + * Copyright (C) 2003-2013
84.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
84.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
84.11 *
84.12 @@ -152,7 +152,7 @@
84.13 ///The type of the paths.
84.14 typedef PredMapPath<Digraph, PredMap> Path;
84.15
84.16 - ///The \ref DfsDefaultTraits "traits class" of the algorithm.
84.17 + ///The \ref lemon::DfsDefaultTraits "traits class" of the algorithm.
84.18 typedef TR Traits;
84.19
84.20 private:
85.1 --- a/lemon/dijkstra.h Mon Jul 16 16:21:40 2018 +0200
85.2 +++ b/lemon/dijkstra.h Wed Oct 17 19:14:07 2018 +0200
85.3 @@ -2,7 +2,7 @@
85.4 *
85.5 * This file is a part of LEMON, a generic C++ optimization library.
85.6 *
85.7 - * Copyright (C) 2003-2010
85.8 + * Copyright (C) 2003-2013
85.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
85.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
85.11 *
85.12 @@ -227,11 +227,11 @@
85.13 typedef typename TR::HeapCrossRef HeapCrossRef;
85.14 ///The heap type used by the algorithm.
85.15 typedef typename TR::Heap Heap;
85.16 - ///\brief The \ref DijkstraDefaultOperationTraits "operation traits class"
85.17 - ///of the algorithm.
85.18 + /// \brief The \ref lemon::DijkstraDefaultOperationTraits
85.19 + /// "operation traits class" of the algorithm.
85.20 typedef typename TR::OperationTraits OperationTraits;
85.21
85.22 - ///The \ref DijkstraDefaultTraits "traits class" of the algorithm.
85.23 + ///The \ref lemon::DijkstraDefaultTraits "traits class" of the algorithm.
85.24 typedef TR Traits;
85.25
85.26 private:
86.1 --- a/lemon/dim2.h Mon Jul 16 16:21:40 2018 +0200
86.2 +++ b/lemon/dim2.h Wed Oct 17 19:14:07 2018 +0200
86.3 @@ -20,6 +20,7 @@
86.4 #define LEMON_DIM2_H
86.5
86.6 #include <iostream>
86.7 +#include <algorithm>
86.8
86.9 ///\ingroup geomdat
86.10 ///\file
87.1 --- a/lemon/dimacs.h Mon Jul 16 16:21:40 2018 +0200
87.2 +++ b/lemon/dimacs.h Wed Oct 17 19:14:07 2018 +0200
87.3 @@ -2,7 +2,7 @@
87.4 *
87.5 * This file is a part of LEMON, a generic C++ optimization library.
87.6 *
87.7 - * Copyright (C) 2003-2010
87.8 + * Copyright (C) 2003-2013
87.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
87.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
87.11 *
87.12 @@ -25,6 +25,7 @@
87.13 #include <limits>
87.14 #include <lemon/maps.h>
87.15 #include <lemon/error.h>
87.16 +
87.17 /// \ingroup dimacs_group
87.18 /// \file
87.19 /// \brief DIMACS file format reader.
87.20 @@ -122,7 +123,7 @@
87.21 /// a non-zero value, that value will be used as "infinite".
87.22 ///
87.23 /// If the file type was previously evaluated by dimacsType(), then
87.24 - /// the descriptor struct should be given by the \c dest parameter.
87.25 + /// the descriptor struct should be given by the \c desc parameter.
87.26 template <typename Digraph, typename LowerMap,
87.27 typename CapacityMap, typename CostMap,
87.28 typename SupplyMap>
87.29 @@ -276,7 +277,7 @@
87.30 /// a non-zero value, that value will be used as "infinite".
87.31 ///
87.32 /// If the file type was previously evaluated by dimacsType(), then
87.33 - /// the descriptor struct should be given by the \c dest parameter.
87.34 + /// the descriptor struct should be given by the \c desc parameter.
87.35 template<typename Digraph, typename CapacityMap>
87.36 void readDimacsMax(std::istream& is,
87.37 Digraph &g,
87.38 @@ -303,7 +304,7 @@
87.39 /// source node.
87.40 ///
87.41 /// If the file type was previously evaluated by dimacsType(), then
87.42 - /// the descriptor struct should be given by the \c dest parameter.
87.43 + /// the descriptor struct should be given by the \c desc parameter.
87.44 template<typename Digraph, typename LengthMap>
87.45 void readDimacsSp(std::istream& is,
87.46 Digraph &g,
87.47 @@ -334,7 +335,7 @@
87.48 /// a non-zero value, that value will be used as "infinite".
87.49 ///
87.50 /// If the file type was previously evaluated by dimacsType(), then
87.51 - /// the descriptor struct should be given by the \c dest parameter.
87.52 + /// the descriptor struct should be given by the \c desc parameter.
87.53 template<typename Digraph, typename CapacityMap>
87.54 void readDimacsCap(std::istream& is,
87.55 Digraph &g,
87.56 @@ -343,7 +344,7 @@
87.57 DimacsDescriptor desc=DimacsDescriptor()) {
87.58 typename Digraph::Node u,v;
87.59 if(desc.type==DimacsDescriptor::NONE) desc=dimacsType(is);
87.60 - if(desc.type!=DimacsDescriptor::MAX || desc.type!=DimacsDescriptor::SP)
87.61 + if(desc.type!=DimacsDescriptor::MAX && desc.type!=DimacsDescriptor::SP)
87.62 throw FormatError("Problem type mismatch");
87.63 _readDimacs(is, g, capacity, u, v, infty, desc);
87.64 }
87.65 @@ -374,7 +375,7 @@
87.66 /// At the beginning, \c g is cleared by \c g.clear().
87.67 ///
87.68 /// If the file type was previously evaluated by dimacsType(), then
87.69 - /// the descriptor struct should be given by the \c dest parameter.
87.70 + /// the descriptor struct should be given by the \c desc parameter.
87.71 template<typename Graph>
87.72 void readDimacsMat(std::istream& is, Graph &g,
87.73 DimacsDescriptor desc=DimacsDescriptor())
88.1 --- a/lemon/edge_set.h Mon Jul 16 16:21:40 2018 +0200
88.2 +++ b/lemon/edge_set.h Wed Oct 17 19:14:07 2018 +0200
88.3 @@ -2,7 +2,7 @@
88.4 *
88.5 * This file is a part of LEMON, a generic C++ optimization library.
88.6 *
88.7 - * Copyright (C) 2003-2010
88.8 + * Copyright (C) 2003-2013
88.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
88.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
88.11 *
89.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
89.2 +++ b/lemon/edmonds_karp.h Wed Oct 17 19:14:07 2018 +0200
89.3 @@ -0,0 +1,556 @@
89.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
89.5 + *
89.6 + * This file is a part of LEMON, a generic C++ optimization library.
89.7 + *
89.8 + * Copyright (C) 2003-2013
89.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
89.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
89.11 + *
89.12 + * Permission to use, modify and distribute this software is granted
89.13 + * provided that this copyright notice appears in all copies. For
89.14 + * precise terms see the accompanying LICENSE file.
89.15 + *
89.16 + * This software is provided "AS IS" with no warranty of any kind,
89.17 + * express or implied, and with no claim as to its suitability for any
89.18 + * purpose.
89.19 + *
89.20 + */
89.21 +
89.22 +#ifndef LEMON_EDMONDS_KARP_H
89.23 +#define LEMON_EDMONDS_KARP_H
89.24 +
89.25 +/// \file
89.26 +/// \ingroup max_flow
89.27 +/// \brief Implementation of the Edmonds-Karp algorithm.
89.28 +
89.29 +#include <lemon/tolerance.h>
89.30 +#include <vector>
89.31 +
89.32 +namespace lemon {
89.33 +
89.34 + /// \brief Default traits class of EdmondsKarp class.
89.35 + ///
89.36 + /// Default traits class of EdmondsKarp class.
89.37 + /// \param GR Digraph type.
89.38 + /// \param CAP Type of capacity map.
89.39 + template <typename GR, typename CAP>
89.40 + struct EdmondsKarpDefaultTraits {
89.41 +
89.42 + /// \brief The digraph type the algorithm runs on.
89.43 + typedef GR Digraph;
89.44 +
89.45 + /// \brief The type of the map that stores the arc capacities.
89.46 + ///
89.47 + /// The type of the map that stores the arc capacities.
89.48 + /// It must meet the \ref concepts::ReadMap "ReadMap" concept.
89.49 + typedef CAP CapacityMap;
89.50 +
89.51 + /// \brief The type of the flow values.
89.52 + typedef typename CapacityMap::Value Value;
89.53 +
89.54 + /// \brief The type of the map that stores the flow values.
89.55 + ///
89.56 + /// The type of the map that stores the flow values.
89.57 + /// It must meet the \ref concepts::ReadWriteMap "ReadWriteMap" concept.
89.58 +#ifdef DOXYGEN
89.59 + typedef GR::ArcMap<Value> FlowMap;
89.60 +#else
89.61 + typedef typename Digraph::template ArcMap<Value> FlowMap;
89.62 +#endif
89.63 +
89.64 + /// \brief Instantiates a FlowMap.
89.65 + ///
89.66 + /// This function instantiates a \ref FlowMap.
89.67 + /// \param digraph The digraph for which we would like to define
89.68 + /// the flow map.
89.69 + static FlowMap* createFlowMap(const Digraph& digraph) {
89.70 + return new FlowMap(digraph);
89.71 + }
89.72 +
89.73 + /// \brief The tolerance used by the algorithm
89.74 + ///
89.75 + /// The tolerance used by the algorithm to handle inexact computation.
89.76 + typedef lemon::Tolerance<Value> Tolerance;
89.77 +
89.78 + };
89.79 +
89.80 + /// \ingroup max_flow
89.81 + ///
89.82 + /// \brief Edmonds-Karp algorithms class.
89.83 + ///
89.84 + /// This class provides an implementation of the \e Edmonds-Karp \e
89.85 + /// algorithm producing a \ref max_flow "flow of maximum value" in a
89.86 + /// digraph \cite clrs01algorithms, \cite amo93networkflows,
89.87 + /// \cite edmondskarp72theoretical.
89.88 + /// The Edmonds-Karp algorithm is slower than the Preflow
89.89 + /// algorithm, but it has an advantage of the step-by-step execution
89.90 + /// control with feasible flow solutions. The \e source node, the \e
89.91 + /// target node, the \e capacity of the arcs and the \e starting \e
89.92 + /// flow value of the arcs should be passed to the algorithm
89.93 + /// through the constructor.
89.94 + ///
89.95 + /// The time complexity of the algorithm is \f$ O(nm^2) \f$ in
89.96 + /// worst case. Always try the Preflow algorithm instead of this if
89.97 + /// you just want to compute the optimal flow.
89.98 + ///
89.99 + /// \tparam GR The type of the digraph the algorithm runs on.
89.100 + /// \tparam CAP The type of the capacity map. The default map
89.101 + /// type is \ref concepts::Digraph::ArcMap "GR::ArcMap<int>".
89.102 + /// \tparam TR The traits class that defines various types used by the
89.103 + /// algorithm. By default, it is \ref EdmondsKarpDefaultTraits
89.104 + /// "EdmondsKarpDefaultTraits<GR, CAP>".
89.105 + /// In most cases, this parameter should not be set directly,
89.106 + /// consider to use the named template parameters instead.
89.107 +
89.108 +#ifdef DOXYGEN
89.109 + template <typename GR, typename CAP, typename TR>
89.110 +#else
89.111 + template <typename GR,
89.112 + typename CAP = typename GR::template ArcMap<int>,
89.113 + typename TR = EdmondsKarpDefaultTraits<GR, CAP> >
89.114 +#endif
89.115 + class EdmondsKarp {
89.116 + public:
89.117 +
89.118 + /// \brief The \ref lemon::EdmondsKarpDefaultTraits "traits class"
89.119 + /// of the algorithm.
89.120 + typedef TR Traits;
89.121 + /// The type of the digraph the algorithm runs on.
89.122 + typedef typename Traits::Digraph Digraph;
89.123 + /// The type of the capacity map.
89.124 + typedef typename Traits::CapacityMap CapacityMap;
89.125 + /// The type of the flow values.
89.126 + typedef typename Traits::Value Value;
89.127 +
89.128 + /// The type of the flow map.
89.129 + typedef typename Traits::FlowMap FlowMap;
89.130 + /// The type of the tolerance.
89.131 + typedef typename Traits::Tolerance Tolerance;
89.132 +
89.133 + private:
89.134 +
89.135 + TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
89.136 + typedef typename Digraph::template NodeMap<Arc> PredMap;
89.137 +
89.138 + const Digraph& _graph;
89.139 + const CapacityMap* _capacity;
89.140 +
89.141 + Node _source, _target;
89.142 +
89.143 + FlowMap* _flow;
89.144 + bool _local_flow;
89.145 +
89.146 + PredMap* _pred;
89.147 + std::vector<Node> _queue;
89.148 +
89.149 + Tolerance _tolerance;
89.150 + Value _flow_value;
89.151 +
89.152 + void createStructures() {
89.153 + if (!_flow) {
89.154 + _flow = Traits::createFlowMap(_graph);
89.155 + _local_flow = true;
89.156 + }
89.157 + if (!_pred) {
89.158 + _pred = new PredMap(_graph);
89.159 + }
89.160 + _queue.resize(countNodes(_graph));
89.161 + }
89.162 +
89.163 + void destroyStructures() {
89.164 + if (_local_flow) {
89.165 + delete _flow;
89.166 + }
89.167 + if (_pred) {
89.168 + delete _pred;
89.169 + }
89.170 + }
89.171 +
89.172 + public:
89.173 +
89.174 + typedef EdmondsKarp Create;
89.175 +
89.176 + ///\name Named template parameters
89.177 +
89.178 + ///@{
89.179 +
89.180 + template <typename T>
89.181 + struct SetFlowMapTraits : public Traits {
89.182 + typedef T FlowMap;
89.183 + static FlowMap *createFlowMap(const Digraph&) {
89.184 + LEMON_ASSERT(false, "FlowMap is not initialized");
89.185 + return 0;
89.186 + }
89.187 + };
89.188 +
89.189 + /// \brief \ref named-templ-param "Named parameter" for setting
89.190 + /// FlowMap type
89.191 + ///
89.192 + /// \ref named-templ-param "Named parameter" for setting FlowMap
89.193 + /// type
89.194 + template <typename T>
89.195 + struct SetFlowMap
89.196 + : public EdmondsKarp<Digraph, CapacityMap, SetFlowMapTraits<T> > {
89.197 + typedef EdmondsKarp<Digraph, CapacityMap, SetFlowMapTraits<T> > Create;
89.198 + };
89.199 +
89.200 + /// @}
89.201 +
89.202 + protected:
89.203 +
89.204 + EdmondsKarp() {}
89.205 +
89.206 + public:
89.207 +
89.208 + /// \brief The constructor of the class.
89.209 + ///
89.210 + /// The constructor of the class.
89.211 + /// \param digraph The digraph the algorithm runs on.
89.212 + /// \param capacity The capacity of the arcs.
89.213 + /// \param source The source node.
89.214 + /// \param target The target node.
89.215 + EdmondsKarp(const Digraph& digraph, const CapacityMap& capacity,
89.216 + Node source, Node target)
89.217 + : _graph(digraph), _capacity(&capacity), _source(source), _target(target),
89.218 + _flow(0), _local_flow(false), _pred(0), _tolerance(), _flow_value()
89.219 + {
89.220 + LEMON_ASSERT(_source != _target,
89.221 + "Flow source and target are the same nodes.");
89.222 + }
89.223 +
89.224 + /// \brief Destructor.
89.225 + ///
89.226 + /// Destructor.
89.227 + ~EdmondsKarp() {
89.228 + destroyStructures();
89.229 + }
89.230 +
89.231 + /// \brief Sets the capacity map.
89.232 + ///
89.233 + /// Sets the capacity map.
89.234 + /// \return <tt>(*this)</tt>
89.235 + EdmondsKarp& capacityMap(const CapacityMap& map) {
89.236 + _capacity = ↦
89.237 + return *this;
89.238 + }
89.239 +
89.240 + /// \brief Sets the flow map.
89.241 + ///
89.242 + /// Sets the flow map.
89.243 + /// If you don't use this function before calling \ref run() or
89.244 + /// \ref init(), an instance will be allocated automatically.
89.245 + /// The destructor deallocates this automatically allocated map,
89.246 + /// of course.
89.247 + /// \return <tt>(*this)</tt>
89.248 + EdmondsKarp& flowMap(FlowMap& map) {
89.249 + if (_local_flow) {
89.250 + delete _flow;
89.251 + _local_flow = false;
89.252 + }
89.253 + _flow = ↦
89.254 + return *this;
89.255 + }
89.256 +
89.257 + /// \brief Sets the source node.
89.258 + ///
89.259 + /// Sets the source node.
89.260 + /// \return <tt>(*this)</tt>
89.261 + EdmondsKarp& source(const Node& node) {
89.262 + _source = node;
89.263 + return *this;
89.264 + }
89.265 +
89.266 + /// \brief Sets the target node.
89.267 + ///
89.268 + /// Sets the target node.
89.269 + /// \return <tt>(*this)</tt>
89.270 + EdmondsKarp& target(const Node& node) {
89.271 + _target = node;
89.272 + return *this;
89.273 + }
89.274 +
89.275 + /// \brief Sets the tolerance used by algorithm.
89.276 + ///
89.277 + /// Sets the tolerance used by algorithm.
89.278 + /// \return <tt>(*this)</tt>
89.279 + EdmondsKarp& tolerance(const Tolerance& tolerance) {
89.280 + _tolerance = tolerance;
89.281 + return *this;
89.282 + }
89.283 +
89.284 + /// \brief Returns a const reference to the tolerance.
89.285 + ///
89.286 + /// Returns a const reference to the tolerance object used by
89.287 + /// the algorithm.
89.288 + const Tolerance& tolerance() const {
89.289 + return _tolerance;
89.290 + }
89.291 +
89.292 + /// \name Execution control
89.293 + /// The simplest way to execute the algorithm is to use \ref run().\n
89.294 + /// If you need better control on the initial solution or the execution,
89.295 + /// you have to call one of the \ref init() functions first, then
89.296 + /// \ref start() or multiple times the \ref augment() function.
89.297 +
89.298 + ///@{
89.299 +
89.300 + /// \brief Initializes the algorithm.
89.301 + ///
89.302 + /// Initializes the internal data structures and sets the initial
89.303 + /// flow to zero on each arc.
89.304 + void init() {
89.305 + createStructures();
89.306 + for (ArcIt it(_graph); it != INVALID; ++it) {
89.307 + _flow->set(it, 0);
89.308 + }
89.309 + _flow_value = 0;
89.310 + }
89.311 +
89.312 + /// \brief Initializes the algorithm using the given flow map.
89.313 + ///
89.314 + /// Initializes the internal data structures and sets the initial
89.315 + /// flow to the given \c flowMap. The \c flowMap should
89.316 + /// contain a feasible flow, i.e. at each node excluding the source
89.317 + /// and the target, the incoming flow should be equal to the
89.318 + /// outgoing flow.
89.319 + template <typename FlowMap>
89.320 + void init(const FlowMap& flowMap) {
89.321 + createStructures();
89.322 + for (ArcIt e(_graph); e != INVALID; ++e) {
89.323 + _flow->set(e, flowMap[e]);
89.324 + }
89.325 + _flow_value = 0;
89.326 + for (OutArcIt jt(_graph, _source); jt != INVALID; ++jt) {
89.327 + _flow_value += (*_flow)[jt];
89.328 + }
89.329 + for (InArcIt jt(_graph, _source); jt != INVALID; ++jt) {
89.330 + _flow_value -= (*_flow)[jt];
89.331 + }
89.332 + }
89.333 +
89.334 + /// \brief Initializes the algorithm using the given flow map.
89.335 + ///
89.336 + /// Initializes the internal data structures and sets the initial
89.337 + /// flow to the given \c flowMap. The \c flowMap should
89.338 + /// contain a feasible flow, i.e. at each node excluding the source
89.339 + /// and the target, the incoming flow should be equal to the
89.340 + /// outgoing flow.
89.341 + /// \return \c false when the given \c flowMap does not contain a
89.342 + /// feasible flow.
89.343 + template <typename FlowMap>
89.344 + bool checkedInit(const FlowMap& flowMap) {
89.345 + createStructures();
89.346 + for (ArcIt e(_graph); e != INVALID; ++e) {
89.347 + _flow->set(e, flowMap[e]);
89.348 + }
89.349 + for (NodeIt it(_graph); it != INVALID; ++it) {
89.350 + if (it == _source || it == _target) continue;
89.351 + Value outFlow = 0;
89.352 + for (OutArcIt jt(_graph, it); jt != INVALID; ++jt) {
89.353 + outFlow += (*_flow)[jt];
89.354 + }
89.355 + Value inFlow = 0;
89.356 + for (InArcIt jt(_graph, it); jt != INVALID; ++jt) {
89.357 + inFlow += (*_flow)[jt];
89.358 + }
89.359 + if (_tolerance.different(outFlow, inFlow)) {
89.360 + return false;
89.361 + }
89.362 + }
89.363 + for (ArcIt it(_graph); it != INVALID; ++it) {
89.364 + if (_tolerance.less((*_flow)[it], 0)) return false;
89.365 + if (_tolerance.less((*_capacity)[it], (*_flow)[it])) return false;
89.366 + }
89.367 + _flow_value = 0;
89.368 + for (OutArcIt jt(_graph, _source); jt != INVALID; ++jt) {
89.369 + _flow_value += (*_flow)[jt];
89.370 + }
89.371 + for (InArcIt jt(_graph, _source); jt != INVALID; ++jt) {
89.372 + _flow_value -= (*_flow)[jt];
89.373 + }
89.374 + return true;
89.375 + }
89.376 +
89.377 + /// \brief Augments the solution along a shortest path.
89.378 + ///
89.379 + /// Augments the solution along a shortest path. This function searches a
89.380 + /// shortest path between the source and the target
89.381 + /// in the residual digraph by the Bfs algoritm.
89.382 + /// Then it increases the flow on this path with the minimal residual
89.383 + /// capacity on the path. If there is no such path, it gives back
89.384 + /// false.
89.385 + /// \return \c false when the augmenting did not success, i.e. the
89.386 + /// current flow is a feasible and optimal solution.
89.387 + bool augment() {
89.388 + for (NodeIt n(_graph); n != INVALID; ++n) {
89.389 + _pred->set(n, INVALID);
89.390 + }
89.391 +
89.392 + int first = 0, last = 1;
89.393 +
89.394 + _queue[0] = _source;
89.395 + _pred->set(_source, OutArcIt(_graph, _source));
89.396 +
89.397 + while (first != last && (*_pred)[_target] == INVALID) {
89.398 + Node n = _queue[first++];
89.399 +
89.400 + for (OutArcIt e(_graph, n); e != INVALID; ++e) {
89.401 + Value rem = (*_capacity)[e] - (*_flow)[e];
89.402 + Node t = _graph.target(e);
89.403 + if (_tolerance.positive(rem) && (*_pred)[t] == INVALID) {
89.404 + _pred->set(t, e);
89.405 + _queue[last++] = t;
89.406 + }
89.407 + }
89.408 + for (InArcIt e(_graph, n); e != INVALID; ++e) {
89.409 + Value rem = (*_flow)[e];
89.410 + Node t = _graph.source(e);
89.411 + if (_tolerance.positive(rem) && (*_pred)[t] == INVALID) {
89.412 + _pred->set(t, e);
89.413 + _queue[last++] = t;
89.414 + }
89.415 + }
89.416 + }
89.417 +
89.418 + if ((*_pred)[_target] != INVALID) {
89.419 + Node n = _target;
89.420 + Arc e = (*_pred)[n];
89.421 +
89.422 + Value prem = (*_capacity)[e] - (*_flow)[e];
89.423 + n = _graph.source(e);
89.424 + while (n != _source) {
89.425 + e = (*_pred)[n];
89.426 + if (_graph.target(e) == n) {
89.427 + Value rem = (*_capacity)[e] - (*_flow)[e];
89.428 + if (rem < prem) prem = rem;
89.429 + n = _graph.source(e);
89.430 + } else {
89.431 + Value rem = (*_flow)[e];
89.432 + if (rem < prem) prem = rem;
89.433 + n = _graph.target(e);
89.434 + }
89.435 + }
89.436 +
89.437 + n = _target;
89.438 + e = (*_pred)[n];
89.439 +
89.440 + _flow->set(e, (*_flow)[e] + prem);
89.441 + n = _graph.source(e);
89.442 + while (n != _source) {
89.443 + e = (*_pred)[n];
89.444 + if (_graph.target(e) == n) {
89.445 + _flow->set(e, (*_flow)[e] + prem);
89.446 + n = _graph.source(e);
89.447 + } else {
89.448 + _flow->set(e, (*_flow)[e] - prem);
89.449 + n = _graph.target(e);
89.450 + }
89.451 + }
89.452 +
89.453 + _flow_value += prem;
89.454 + return true;
89.455 + } else {
89.456 + return false;
89.457 + }
89.458 + }
89.459 +
89.460 + /// \brief Executes the algorithm
89.461 + ///
89.462 + /// Executes the algorithm by performing augmenting phases until the
89.463 + /// optimal solution is reached.
89.464 + /// \pre One of the \ref init() functions must be called before
89.465 + /// using this function.
89.466 + void start() {
89.467 + while (augment()) {}
89.468 + }
89.469 +
89.470 + /// \brief Runs the algorithm.
89.471 + ///
89.472 + /// Runs the Edmonds-Karp algorithm.
89.473 + /// \note ek.run() is just a shortcut of the following code.
89.474 + ///\code
89.475 + /// ek.init();
89.476 + /// ek.start();
89.477 + ///\endcode
89.478 + void run() {
89.479 + init();
89.480 + start();
89.481 + }
89.482 +
89.483 + /// @}
89.484 +
89.485 + /// \name Query Functions
89.486 + /// The result of the Edmonds-Karp algorithm can be obtained using these
89.487 + /// functions.\n
89.488 + /// Either \ref run() or \ref start() should be called before using them.
89.489 +
89.490 + ///@{
89.491 +
89.492 + /// \brief Returns the value of the maximum flow.
89.493 + ///
89.494 + /// Returns the value of the maximum flow found by the algorithm.
89.495 + ///
89.496 + /// \pre Either \ref run() or \ref init() must be called before
89.497 + /// using this function.
89.498 + Value flowValue() const {
89.499 + return _flow_value;
89.500 + }
89.501 +
89.502 + /// \brief Returns the flow value on the given arc.
89.503 + ///
89.504 + /// Returns the flow value on the given arc.
89.505 + ///
89.506 + /// \pre Either \ref run() or \ref init() must be called before
89.507 + /// using this function.
89.508 + Value flow(const Arc& arc) const {
89.509 + return (*_flow)[arc];
89.510 + }
89.511 +
89.512 + /// \brief Returns a const reference to the flow map.
89.513 + ///
89.514 + /// Returns a const reference to the arc map storing the found flow.
89.515 + ///
89.516 + /// \pre Either \ref run() or \ref init() must be called before
89.517 + /// using this function.
89.518 + const FlowMap& flowMap() const {
89.519 + return *_flow;
89.520 + }
89.521 +
89.522 + /// \brief Returns \c true when the node is on the source side of the
89.523 + /// minimum cut.
89.524 + ///
89.525 + /// Returns true when the node is on the source side of the found
89.526 + /// minimum cut.
89.527 + ///
89.528 + /// \pre Either \ref run() or \ref init() must be called before
89.529 + /// using this function.
89.530 + bool minCut(const Node& node) const {
89.531 + return ((*_pred)[node] != INVALID) || node == _source;
89.532 + }
89.533 +
89.534 + /// \brief Gives back a minimum value cut.
89.535 + ///
89.536 + /// Sets \c cutMap to the characteristic vector of a minimum value
89.537 + /// cut. \c cutMap should be a \ref concepts::WriteMap "writable"
89.538 + /// node map with \c bool (or convertible) value type.
89.539 + ///
89.540 + /// \note This function calls \ref minCut() for each node, so it runs in
89.541 + /// O(n) time.
89.542 + ///
89.543 + /// \pre Either \ref run() or \ref init() must be called before
89.544 + /// using this function.
89.545 + template <typename CutMap>
89.546 + void minCutMap(CutMap& cutMap) const {
89.547 + for (NodeIt n(_graph); n != INVALID; ++n) {
89.548 + cutMap.set(n, (*_pred)[n] != INVALID);
89.549 + }
89.550 + cutMap.set(_source, true);
89.551 + }
89.552 +
89.553 + /// @}
89.554 +
89.555 + };
89.556 +
89.557 +}
89.558 +
89.559 +#endif
90.1 --- a/lemon/elevator.h Mon Jul 16 16:21:40 2018 +0200
90.2 +++ b/lemon/elevator.h Wed Oct 17 19:14:07 2018 +0200
90.3 @@ -167,7 +167,7 @@
90.4 ///Return the number of items on level \c l.
90.5 int onLevel(int l) const
90.6 {
90.7 - return _first[l+1]-_first[l];
90.8 + return static_cast<int>(_first[l+1]-_first[l]);
90.9 }
90.10 ///Return true if level \c l is empty.
90.11 bool emptyLevel(int l) const
90.12 @@ -177,12 +177,12 @@
90.13 ///Return the number of items above level \c l.
90.14 int aboveLevel(int l) const
90.15 {
90.16 - return _first[_max_level+1]-_first[l+1];
90.17 + return static_cast<int>(_first[_max_level+1]-_first[l+1]);
90.18 }
90.19 ///Return the number of active items on level \c l.
90.20 int activesOnLevel(int l) const
90.21 {
90.22 - return _last_active[l]-_first[l]+1;
90.23 + return static_cast<int>(_last_active[l]-_first[l]+1);
90.24 }
90.25 ///Return true if there is no active item on level \c l.
90.26 bool activeFree(int l) const
91.1 --- a/lemon/euler.h Mon Jul 16 16:21:40 2018 +0200
91.2 +++ b/lemon/euler.h Wed Oct 17 19:14:07 2018 +0200
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-2010
91.8 + * Copyright (C) 2003-2013
91.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
91.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
91.11 *
91.12 @@ -36,7 +36,7 @@
91.13
91.14 ///Euler tour iterator for digraphs.
91.15
91.16 - /// \ingroup graph_prop
91.17 + /// \ingroup graph_properties
91.18 ///This iterator provides an Euler tour (Eulerian circuit) of a \e directed
91.19 ///graph (if there exists) and it converts to the \c Arc type of the digraph.
91.20 ///
92.1 --- a/lemon/fractional_matching.h Mon Jul 16 16:21:40 2018 +0200
92.2 +++ b/lemon/fractional_matching.h Wed Oct 17 19:14:07 2018 +0200
92.3 @@ -2,7 +2,7 @@
92.4 *
92.5 * This file is a part of LEMON, a generic C++ optimization library.
92.6 *
92.7 - * Copyright (C) 2003-2010
92.8 + * Copyright (C) 2003-2013
92.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
92.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
92.11 *
92.12 @@ -123,8 +123,8 @@
92.13 class MaxFractionalMatching {
92.14 public:
92.15
92.16 - /// \brief The \ref MaxFractionalMatchingDefaultTraits "traits
92.17 - /// class" of the algorithm.
92.18 + /// \brief The \ref lemon::MaxFractionalMatchingDefaultTraits
92.19 + /// "traits class" of the algorithm.
92.20 typedef TR Traits;
92.21 /// The type of the graph the algorithm runs on.
92.22 typedef typename TR::Graph Graph;
93.1 --- a/lemon/full_graph.h Mon Jul 16 16:21:40 2018 +0200
93.2 +++ b/lemon/full_graph.h Wed Oct 17 19:14:07 2018 +0200
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-2010
93.8 + * Copyright (C) 2003-2013
93.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
93.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
93.11 *
93.12 @@ -621,6 +621,460 @@
93.13
93.14 };
93.15
93.16 + class FullBpGraphBase {
93.17 +
93.18 + protected:
93.19 +
93.20 + int _red_num, _blue_num;
93.21 + int _node_num, _edge_num;
93.22 +
93.23 + public:
93.24 +
93.25 + typedef FullBpGraphBase Graph;
93.26 +
93.27 + class Node;
93.28 + class Arc;
93.29 + class Edge;
93.30 +
93.31 + class Node {
93.32 + friend class FullBpGraphBase;
93.33 + protected:
93.34 +
93.35 + int _id;
93.36 + explicit Node(int id) { _id = id;}
93.37 +
93.38 + public:
93.39 + Node() {}
93.40 + Node (Invalid) { _id = -1; }
93.41 + bool operator==(const Node& node) const {return _id == node._id;}
93.42 + bool operator!=(const Node& node) const {return _id != node._id;}
93.43 + bool operator<(const Node& node) const {return _id < node._id;}
93.44 + };
93.45 +
93.46 + class RedNode : public Node {
93.47 + friend class FullBpGraphBase;
93.48 + protected:
93.49 +
93.50 + explicit RedNode(int pid) : Node(pid) {}
93.51 +
93.52 + public:
93.53 + RedNode() {}
93.54 + RedNode(const RedNode& node) : Node(node) {}
93.55 + RedNode(Invalid) : Node(INVALID){}
93.56 + };
93.57 +
93.58 + class BlueNode : public Node {
93.59 + friend class FullBpGraphBase;
93.60 + protected:
93.61 +
93.62 + explicit BlueNode(int pid) : Node(pid) {}
93.63 +
93.64 + public:
93.65 + BlueNode() {}
93.66 + BlueNode(const BlueNode& node) : Node(node) {}
93.67 + BlueNode(Invalid) : Node(INVALID){}
93.68 + };
93.69 +
93.70 + class Edge {
93.71 + friend class FullBpGraphBase;
93.72 + protected:
93.73 +
93.74 + int _id;
93.75 + explicit Edge(int id) { _id = id;}
93.76 +
93.77 + public:
93.78 + Edge() {}
93.79 + Edge (Invalid) { _id = -1; }
93.80 + bool operator==(const Edge& arc) const {return _id == arc._id;}
93.81 + bool operator!=(const Edge& arc) const {return _id != arc._id;}
93.82 + bool operator<(const Edge& arc) const {return _id < arc._id;}
93.83 + };
93.84 +
93.85 + class Arc {
93.86 + friend class FullBpGraphBase;
93.87 + protected:
93.88 +
93.89 + int _id;
93.90 + explicit Arc(int id) { _id = id;}
93.91 +
93.92 + public:
93.93 + operator Edge() const {
93.94 + return _id != -1 ? edgeFromId(_id / 2) : INVALID;
93.95 + }
93.96 +
93.97 + Arc() {}
93.98 + Arc (Invalid) { _id = -1; }
93.99 + bool operator==(const Arc& arc) const {return _id == arc._id;}
93.100 + bool operator!=(const Arc& arc) const {return _id != arc._id;}
93.101 + bool operator<(const Arc& arc) const {return _id < arc._id;}
93.102 + };
93.103 +
93.104 +
93.105 + protected:
93.106 +
93.107 + FullBpGraphBase()
93.108 + : _red_num(0), _blue_num(0), _node_num(0), _edge_num(0) {}
93.109 +
93.110 + void construct(int redNum, int blueNum) {
93.111 + _red_num = redNum; _blue_num = blueNum;
93.112 + _node_num = redNum + blueNum; _edge_num = redNum * blueNum;
93.113 + }
93.114 +
93.115 + public:
93.116 +
93.117 + typedef True NodeNumTag;
93.118 + typedef True EdgeNumTag;
93.119 + typedef True ArcNumTag;
93.120 +
93.121 + int nodeNum() const { return _node_num; }
93.122 + int redNum() const { return _red_num; }
93.123 + int blueNum() const { return _blue_num; }
93.124 + int edgeNum() const { return _edge_num; }
93.125 + int arcNum() const { return 2 * _edge_num; }
93.126 +
93.127 + int maxNodeId() const { return _node_num - 1; }
93.128 + int maxRedId() const { return _red_num - 1; }
93.129 + int maxBlueId() const { return _blue_num - 1; }
93.130 + int maxEdgeId() const { return _edge_num - 1; }
93.131 + int maxArcId() const { return 2 * _edge_num - 1; }
93.132 +
93.133 + bool red(Node n) const { return n._id < _red_num; }
93.134 + bool blue(Node n) const { return n._id >= _red_num; }
93.135 +
93.136 + static RedNode asRedNodeUnsafe(Node n) { return RedNode(n._id); }
93.137 + static BlueNode asBlueNodeUnsafe(Node n) { return BlueNode(n._id); }
93.138 +
93.139 + Node source(Arc a) const {
93.140 + if (a._id & 1) {
93.141 + return Node((a._id >> 1) % _red_num);
93.142 + } else {
93.143 + return Node((a._id >> 1) / _red_num + _red_num);
93.144 + }
93.145 + }
93.146 + Node target(Arc a) const {
93.147 + if (a._id & 1) {
93.148 + return Node((a._id >> 1) / _red_num + _red_num);
93.149 + } else {
93.150 + return Node((a._id >> 1) % _red_num);
93.151 + }
93.152 + }
93.153 +
93.154 + RedNode redNode(Edge e) const {
93.155 + return RedNode(e._id % _red_num);
93.156 + }
93.157 + BlueNode blueNode(Edge e) const {
93.158 + return BlueNode(e._id / _red_num + _red_num);
93.159 + }
93.160 +
93.161 + static bool direction(Arc a) {
93.162 + return (a._id & 1) == 1;
93.163 + }
93.164 +
93.165 + static Arc direct(Edge e, bool d) {
93.166 + return Arc(e._id * 2 + (d ? 1 : 0));
93.167 + }
93.168 +
93.169 + void first(Node& node) const {
93.170 + node._id = _node_num - 1;
93.171 + }
93.172 +
93.173 + static void next(Node& node) {
93.174 + --node._id;
93.175 + }
93.176 +
93.177 + void first(RedNode& node) const {
93.178 + node._id = _red_num - 1;
93.179 + }
93.180 +
93.181 + static void next(RedNode& node) {
93.182 + --node._id;
93.183 + }
93.184 +
93.185 + void first(BlueNode& node) const {
93.186 + if (_red_num == _node_num) node._id = -1;
93.187 + else node._id = _node_num - 1;
93.188 + }
93.189 +
93.190 + void next(BlueNode& node) const {
93.191 + if (node._id == _red_num) node._id = -1;
93.192 + else --node._id;
93.193 + }
93.194 +
93.195 + void first(Arc& arc) const {
93.196 + arc._id = 2 * _edge_num - 1;
93.197 + }
93.198 +
93.199 + static void next(Arc& arc) {
93.200 + --arc._id;
93.201 + }
93.202 +
93.203 + void first(Edge& arc) const {
93.204 + arc._id = _edge_num - 1;
93.205 + }
93.206 +
93.207 + static void next(Edge& arc) {
93.208 + --arc._id;
93.209 + }
93.210 +
93.211 + void firstOut(Arc &a, const Node& v) const {
93.212 + if (v._id < _red_num) {
93.213 + a._id = 2 * (v._id + _red_num * (_blue_num - 1)) + 1;
93.214 + } else {
93.215 + a._id = 2 * (_red_num - 1 + _red_num * (v._id - _red_num));
93.216 + }
93.217 + }
93.218 + void nextOut(Arc &a) const {
93.219 + if (a._id & 1) {
93.220 + a._id -= 2 * _red_num;
93.221 + if (a._id < 0) a._id = -1;
93.222 + } else {
93.223 + if (a._id % (2 * _red_num) == 0) a._id = -1;
93.224 + else a._id -= 2;
93.225 + }
93.226 + }
93.227 +
93.228 + void firstIn(Arc &a, const Node& v) const {
93.229 + if (v._id < _red_num) {
93.230 + a._id = 2 * (v._id + _red_num * (_blue_num - 1));
93.231 + } else {
93.232 + a._id = 2 * (_red_num - 1 + _red_num * (v._id - _red_num)) + 1;
93.233 + }
93.234 + }
93.235 + void nextIn(Arc &a) const {
93.236 + if (a._id & 1) {
93.237 + if (a._id % (2 * _red_num) == 1) a._id = -1;
93.238 + else a._id -= 2;
93.239 + } else {
93.240 + a._id -= 2 * _red_num;
93.241 + if (a._id < 0) a._id = -1;
93.242 + }
93.243 + }
93.244 +
93.245 + void firstInc(Edge &e, bool& d, const Node& v) const {
93.246 + if (v._id < _red_num) {
93.247 + d = true;
93.248 + e._id = v._id + _red_num * (_blue_num - 1);
93.249 + } else {
93.250 + d = false;
93.251 + e._id = _red_num - 1 + _red_num * (v._id - _red_num);
93.252 + }
93.253 + }
93.254 + void nextInc(Edge &e, bool& d) const {
93.255 + if (d) {
93.256 + e._id -= _red_num;
93.257 + if (e._id < 0) e._id = -1;
93.258 + } else {
93.259 + if (e._id % _red_num == 0) e._id = -1;
93.260 + else --e._id;
93.261 + }
93.262 + }
93.263 +
93.264 + static int id(const Node& v) { return v._id; }
93.265 + int id(const RedNode& v) const { return v._id; }
93.266 + int id(const BlueNode& v) const { return v._id - _red_num; }
93.267 + static int id(Arc e) { return e._id; }
93.268 + static int id(Edge e) { return e._id; }
93.269 +
93.270 + static Node nodeFromId(int id) { return Node(id);}
93.271 + static Arc arcFromId(int id) { return Arc(id);}
93.272 + static Edge edgeFromId(int id) { return Edge(id);}
93.273 +
93.274 + bool valid(Node n) const {
93.275 + return n._id >= 0 && n._id < _node_num;
93.276 + }
93.277 + bool valid(Arc a) const {
93.278 + return a._id >= 0 && a._id < 2 * _edge_num;
93.279 + }
93.280 + bool valid(Edge e) const {
93.281 + return e._id >= 0 && e._id < _edge_num;
93.282 + }
93.283 +
93.284 + RedNode redNode(int index) const {
93.285 + return RedNode(index);
93.286 + }
93.287 +
93.288 + int index(RedNode n) const {
93.289 + return n._id;
93.290 + }
93.291 +
93.292 + BlueNode blueNode(int index) const {
93.293 + return BlueNode(index + _red_num);
93.294 + }
93.295 +
93.296 + int index(BlueNode n) const {
93.297 + return n._id - _red_num;
93.298 + }
93.299 +
93.300 + void clear() {
93.301 + _red_num = 0; _blue_num = 0;
93.302 + _node_num = 0; _edge_num = 0;
93.303 + }
93.304 +
93.305 + Edge edge(const Node& u, const Node& v) const {
93.306 + if (u._id < _red_num) {
93.307 + if (v._id < _red_num) {
93.308 + return Edge(-1);
93.309 + } else {
93.310 + return Edge(u._id + _red_num * (v._id - _red_num));
93.311 + }
93.312 + } else {
93.313 + if (v._id < _red_num) {
93.314 + return Edge(v._id + _red_num * (u._id - _red_num));
93.315 + } else {
93.316 + return Edge(-1);
93.317 + }
93.318 + }
93.319 + }
93.320 +
93.321 + Arc arc(const Node& u, const Node& v) const {
93.322 + if (u._id < _red_num) {
93.323 + if (v._id < _red_num) {
93.324 + return Arc(-1);
93.325 + } else {
93.326 + return Arc(2 * (u._id + _red_num * (v._id - _red_num)) + 1);
93.327 + }
93.328 + } else {
93.329 + if (v._id < _red_num) {
93.330 + return Arc(2 * (v._id + _red_num * (u._id - _red_num)));
93.331 + } else {
93.332 + return Arc(-1);
93.333 + }
93.334 + }
93.335 + }
93.336 +
93.337 + typedef True FindEdgeTag;
93.338 + typedef True FindArcTag;
93.339 +
93.340 + Edge findEdge(Node u, Node v, Edge prev = INVALID) const {
93.341 + return prev != INVALID ? INVALID : edge(u, v);
93.342 + }
93.343 +
93.344 + Arc findArc(Node s, Node t, Arc prev = INVALID) const {
93.345 + return prev != INVALID ? INVALID : arc(s, t);
93.346 + }
93.347 +
93.348 + };
93.349 +
93.350 + typedef BpGraphExtender<FullBpGraphBase> ExtendedFullBpGraphBase;
93.351 +
93.352 + /// \ingroup graphs
93.353 + ///
93.354 + /// \brief An undirected full bipartite graph class.
93.355 + ///
93.356 + /// FullBpGraph is a simple and fast implmenetation of undirected
93.357 + /// full bipartite graphs. It contains an edge between every
93.358 + /// red-blue pairs of nodes, therefore the number of edges is
93.359 + /// <tt>nr*nb</tt>. This class is completely static and it needs
93.360 + /// constant memory space. Thus you can neither add nor delete
93.361 + /// nodes or edges, however the structure can be resized using
93.362 + /// resize().
93.363 + ///
93.364 + /// This type fully conforms to the \ref concepts::BpGraph "BpGraph concept".
93.365 + /// Most of its member functions and nested classes are documented
93.366 + /// only in the concept class.
93.367 + ///
93.368 + /// This class provides constant time counting for nodes, edges and arcs.
93.369 + ///
93.370 + /// \sa FullGraph
93.371 + class FullBpGraph : public ExtendedFullBpGraphBase {
93.372 + public:
93.373 +
93.374 + typedef ExtendedFullBpGraphBase Parent;
93.375 +
93.376 + /// \brief Default constructor.
93.377 + ///
93.378 + /// Default constructor. The number of nodes and edges will be zero.
93.379 + FullBpGraph() { construct(0, 0); }
93.380 +
93.381 + /// \brief Constructor
93.382 + ///
93.383 + /// Constructor.
93.384 + /// \param redNum The number of the red nodes.
93.385 + /// \param blueNum The number of the blue nodes.
93.386 + FullBpGraph(int redNum, int blueNum) { construct(redNum, blueNum); }
93.387 +
93.388 + /// \brief Resizes the graph
93.389 + ///
93.390 + /// This function resizes the graph. It fully destroys and
93.391 + /// rebuilds the structure, therefore the maps of the graph will be
93.392 + /// reallocated automatically and the previous values will be lost.
93.393 + void resize(int redNum, int blueNum) {
93.394 + Parent::notifier(Arc()).clear();
93.395 + Parent::notifier(Edge()).clear();
93.396 + Parent::notifier(Node()).clear();
93.397 + Parent::notifier(BlueNode()).clear();
93.398 + Parent::notifier(RedNode()).clear();
93.399 + construct(redNum, blueNum);
93.400 + Parent::notifier(RedNode()).build();
93.401 + Parent::notifier(BlueNode()).build();
93.402 + Parent::notifier(Node()).build();
93.403 + Parent::notifier(Edge()).build();
93.404 + Parent::notifier(Arc()).build();
93.405 + }
93.406 +
93.407 + using Parent::redNode;
93.408 + using Parent::blueNode;
93.409 +
93.410 + /// \brief Returns the red node with the given index.
93.411 + ///
93.412 + /// Returns the red node with the given index. Since this
93.413 + /// structure is completely static, the red nodes can be indexed
93.414 + /// with integers from the range <tt>[0..redNum()-1]</tt>.
93.415 + /// \sa redIndex()
93.416 + RedNode redNode(int index) const { return Parent::redNode(index); }
93.417 +
93.418 + /// \brief Returns the index of the given red node.
93.419 + ///
93.420 + /// Returns the index of the given red node. Since this structure
93.421 + /// is completely static, the red nodes can be indexed with
93.422 + /// integers from the range <tt>[0..redNum()-1]</tt>.
93.423 + ///
93.424 + /// \sa operator()()
93.425 + int index(RedNode node) const { return Parent::index(node); }
93.426 +
93.427 + /// \brief Returns the blue node with the given index.
93.428 + ///
93.429 + /// Returns the blue node with the given index. Since this
93.430 + /// structure is completely static, the blue nodes can be indexed
93.431 + /// with integers from the range <tt>[0..blueNum()-1]</tt>.
93.432 + /// \sa blueIndex()
93.433 + BlueNode blueNode(int index) const { return Parent::blueNode(index); }
93.434 +
93.435 + /// \brief Returns the index of the given blue node.
93.436 + ///
93.437 + /// Returns the index of the given blue node. Since this structure
93.438 + /// is completely static, the blue nodes can be indexed with
93.439 + /// integers from the range <tt>[0..blueNum()-1]</tt>.
93.440 + ///
93.441 + /// \sa operator()()
93.442 + int index(BlueNode node) const { return Parent::index(node); }
93.443 +
93.444 + /// \brief Returns the edge which connects the given nodes.
93.445 + ///
93.446 + /// Returns the edge which connects the given nodes.
93.447 + Edge edge(const Node& u, const Node& v) const {
93.448 + return Parent::edge(u, v);
93.449 + }
93.450 +
93.451 + /// \brief Returns the arc which connects the given nodes.
93.452 + ///
93.453 + /// Returns the arc which connects the given nodes.
93.454 + Arc arc(const Node& u, const Node& v) const {
93.455 + return Parent::arc(u, v);
93.456 + }
93.457 +
93.458 + /// \brief Number of nodes.
93.459 + int nodeNum() const { return Parent::nodeNum(); }
93.460 + /// \brief Number of red nodes.
93.461 + int redNum() const { return Parent::redNum(); }
93.462 + /// \brief Number of blue nodes.
93.463 + int blueNum() const { return Parent::blueNum(); }
93.464 + /// \brief Number of arcs.
93.465 + int arcNum() const { return Parent::arcNum(); }
93.466 + /// \brief Number of edges.
93.467 + int edgeNum() const { return Parent::edgeNum(); }
93.468 + };
93.469 +
93.470
93.471 } //namespace lemon
93.472
94.1 --- a/lemon/glpk.cc Mon Jul 16 16:21:40 2018 +0200
94.2 +++ b/lemon/glpk.cc Wed Oct 17 19:14:07 2018 +0200
94.3 @@ -2,7 +2,7 @@
94.4 *
94.5 * This file is a part of LEMON, a generic C++ optimization library.
94.6 *
94.7 - * Copyright (C) 2003-2010
94.8 + * Copyright (C) 2003-2013
94.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
94.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
94.11 *
94.12 @@ -582,6 +582,15 @@
94.13 }
94.14 }
94.15
94.16 + void GlpkBase::_write(std::string file, std::string format) const
94.17 + {
94.18 + if(format == "MPS")
94.19 + glp_write_mps(lp, GLP_MPS_FILE, 0, file.c_str());
94.20 + else if(format == "LP")
94.21 + glp_write_lp(lp, 0, file.c_str());
94.22 + else throw UnsupportedFormatError(format);
94.23 + }
94.24 +
94.25 GlpkBase::FreeEnvHelper GlpkBase::freeEnvHelper;
94.26
94.27 // GlpkLp members
94.28 @@ -998,4 +1007,6 @@
94.29
94.30 const char* GlpkMip::_solverName() const { return "GlpkMip"; }
94.31
94.32 +
94.33 +
94.34 } //END OF NAMESPACE LEMON
95.1 --- a/lemon/glpk.h Mon Jul 16 16:21:40 2018 +0200
95.2 +++ b/lemon/glpk.h Wed Oct 17 19:14:07 2018 +0200
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-2010
95.8 + * Copyright (C) 2003-2013
95.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
95.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
95.11 *
95.12 @@ -115,6 +115,8 @@
95.13
95.14 virtual void _messageLevel(MessageLevel level);
95.15
95.16 + virtual void _write(std::string file, std::string format) const;
95.17 +
95.18 private:
95.19
95.20 static void freeEnv();
95.21 @@ -144,6 +146,19 @@
95.22 ///Returns the variable identifier understood by GLPK.
95.23 int lpxCol(Col c) const { return cols(id(c)); }
95.24
95.25 +#ifdef DOXYGEN
95.26 + /// Write the problem or the solution to a file in the given format
95.27 +
95.28 + /// This function writes the problem or the solution
95.29 + /// to a file in the given format.
95.30 + /// Trying to write in an unsupported format will trigger
95.31 + /// \ref LpBase::UnsupportedFormatError.
95.32 + /// \param file The file path
95.33 + /// \param format The output file format.
95.34 + /// Supportted formats are "MPS" and "LP".
95.35 + void write(std::string file, std::string format = "MPS") const {}
95.36 +#endif
95.37 +
95.38 };
95.39
95.40 /// \brief Interface for the GLPK LP solver
96.1 --- a/lemon/gomory_hu.h Mon Jul 16 16:21:40 2018 +0200
96.2 +++ b/lemon/gomory_hu.h Wed Oct 17 19:14:07 2018 +0200
96.3 @@ -2,7 +2,7 @@
96.4 *
96.5 * This file is a part of LEMON, a generic C++ optimization library.
96.6 *
96.7 - * Copyright (C) 2003-2010
96.8 + * Copyright (C) 2003-2013
96.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
96.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
96.11 *
96.12 @@ -46,7 +46,7 @@
96.13 /// of nodes can easily be obtained.
96.14 ///
96.15 /// The algorithm calculates \e n-1 distinct minimum cuts (currently with
96.16 - /// the \ref Preflow algorithm), thus it has \f$O(n^3\sqrt{e})\f$ overall
96.17 + /// the \ref Preflow algorithm), thus it has \f$O(n^3\sqrt{m})\f$ overall
96.18 /// time complexity. It calculates a rooted Gomory-Hu tree.
96.19 /// The structure of the tree and the edge weights can be
96.20 /// obtained using \c predNode(), \c predValue() and \c rootDist().
97.1 --- a/lemon/graph_to_eps.h Mon Jul 16 16:21:40 2018 +0200
97.2 +++ b/lemon/graph_to_eps.h Wed Oct 17 19:14:07 2018 +0200
97.3 @@ -2,7 +2,7 @@
97.4 *
97.5 * This file is a part of LEMON, a generic C++ optimization library.
97.6 *
97.7 - * Copyright (C) 2003-2010
97.8 + * Copyright (C) 2003-2013
97.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
97.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
97.11 *
97.12 @@ -25,7 +25,7 @@
97.13 #include<algorithm>
97.14 #include<vector>
97.15
97.16 -#ifndef WIN32
97.17 +#ifndef LEMON_WIN32
97.18 #include<sys/time.h>
97.19 #include<ctime>
97.20 #else
97.21 @@ -222,7 +222,6 @@
97.22 using T::_title;
97.23 using T::_copyright;
97.24
97.25 - using typename T::NodeTextColorType;
97.26 using T::CUST_COL;
97.27 using T::DIST_COL;
97.28 using T::DIST_BW;
97.29 @@ -675,7 +674,7 @@
97.30
97.31 {
97.32 os << "%%CreationDate: ";
97.33 -#ifndef WIN32
97.34 +#ifndef LEMON_WIN32
97.35 timeval tv;
97.36 gettimeofday(&tv, 0);
97.37
98.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
98.2 +++ b/lemon/greedy_tsp.h Wed Oct 17 19:14:07 2018 +0200
98.3 @@ -0,0 +1,251 @@
98.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
98.5 + *
98.6 + * This file is a part of LEMON, a generic C++ optimization library.
98.7 + *
98.8 + * Copyright (C) 2003-2013
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 +
98.22 +#ifndef LEMON_GREEDY_TSP_H
98.23 +#define LEMON_GREEDY_TSP_H
98.24 +
98.25 +/// \ingroup tsp
98.26 +/// \file
98.27 +/// \brief Greedy algorithm for symmetric TSP
98.28 +
98.29 +#include <vector>
98.30 +#include <algorithm>
98.31 +#include <lemon/full_graph.h>
98.32 +#include <lemon/unionfind.h>
98.33 +
98.34 +namespace lemon {
98.35 +
98.36 + /// \ingroup tsp
98.37 + ///
98.38 + /// \brief Greedy algorithm for symmetric TSP.
98.39 + ///
98.40 + /// GreedyTsp implements the greedy heuristic for solving
98.41 + /// symmetric \ref tsp "TSP".
98.42 + ///
98.43 + /// This algorithm is quite similar to the \ref NearestNeighborTsp
98.44 + /// "nearest neighbor" heuristic, but it maintains a set of disjoint paths.
98.45 + /// At each step, the shortest possible edge is added to these paths
98.46 + /// as long as it does not create a cycle of less than n edges and it does
98.47 + /// not increase the degree of any node above two.
98.48 + ///
98.49 + /// This method runs in O(n<sup>2</sup>) time.
98.50 + /// It quickly finds a relatively short tour for most TSP instances,
98.51 + /// but it could also yield a really bad (or even the worst) solution
98.52 + /// in special cases.
98.53 + ///
98.54 + /// \tparam CM Type of the cost map.
98.55 + template <typename CM>
98.56 + class GreedyTsp
98.57 + {
98.58 + public:
98.59 +
98.60 + /// Type of the cost map
98.61 + typedef CM CostMap;
98.62 + /// Type of the edge costs
98.63 + typedef typename CM::Value Cost;
98.64 +
98.65 + private:
98.66 +
98.67 + GRAPH_TYPEDEFS(FullGraph);
98.68 +
98.69 + const FullGraph &_gr;
98.70 + const CostMap &_cost;
98.71 + Cost _sum;
98.72 + std::vector<Node> _path;
98.73 +
98.74 + private:
98.75 +
98.76 + // Functor class to compare edges by their costs
98.77 + class EdgeComp {
98.78 + private:
98.79 + const CostMap &_cost;
98.80 +
98.81 + public:
98.82 + EdgeComp(const CostMap &cost) : _cost(cost) {}
98.83 +
98.84 + bool operator()(const Edge &a, const Edge &b) const {
98.85 + return _cost[a] < _cost[b];
98.86 + }
98.87 + };
98.88 +
98.89 + public:
98.90 +
98.91 + /// \brief Constructor
98.92 + ///
98.93 + /// Constructor.
98.94 + /// \param gr The \ref FullGraph "full graph" the algorithm runs on.
98.95 + /// \param cost The cost map.
98.96 + GreedyTsp(const FullGraph &gr, const CostMap &cost)
98.97 + : _gr(gr), _cost(cost) {}
98.98 +
98.99 + /// \name Execution Control
98.100 + /// @{
98.101 +
98.102 + /// \brief Runs the algorithm.
98.103 + ///
98.104 + /// This function runs the algorithm.
98.105 + ///
98.106 + /// \return The total cost of the found tour.
98.107 + Cost run() {
98.108 + _path.clear();
98.109 +
98.110 + if (_gr.nodeNum() == 0) return _sum = 0;
98.111 + else if (_gr.nodeNum() == 1) {
98.112 + _path.push_back(_gr(0));
98.113 + return _sum = 0;
98.114 + }
98.115 +
98.116 + std::vector<int> plist;
98.117 + plist.resize(_gr.nodeNum()*2, -1);
98.118 +
98.119 + std::vector<Edge> sorted_edges;
98.120 + sorted_edges.reserve(_gr.edgeNum());
98.121 + for (EdgeIt e(_gr); e != INVALID; ++e)
98.122 + sorted_edges.push_back(e);
98.123 + std::sort(sorted_edges.begin(), sorted_edges.end(), EdgeComp(_cost));
98.124 +
98.125 + FullGraph::NodeMap<int> item_int_map(_gr);
98.126 + UnionFind<FullGraph::NodeMap<int> > union_find(item_int_map);
98.127 + for (NodeIt n(_gr); n != INVALID; ++n)
98.128 + union_find.insert(n);
98.129 +
98.130 + FullGraph::NodeMap<int> degree(_gr, 0);
98.131 +
98.132 + int nodesNum = 0, i = 0;
98.133 + while (nodesNum != _gr.nodeNum()-1) {
98.134 + Edge e = sorted_edges[i++];
98.135 + Node u = _gr.u(e),
98.136 + v = _gr.v(e);
98.137 +
98.138 + if (degree[u] <= 1 && degree[v] <= 1) {
98.139 + if (union_find.join(u, v)) {
98.140 + const int uid = _gr.id(u),
98.141 + vid = _gr.id(v);
98.142 +
98.143 + plist[uid*2 + degree[u]] = vid;
98.144 + plist[vid*2 + degree[v]] = uid;
98.145 +
98.146 + ++degree[u];
98.147 + ++degree[v];
98.148 + ++nodesNum;
98.149 + }
98.150 + }
98.151 + }
98.152 +
98.153 + for (int i=0, n=-1; i<_gr.nodeNum()*2; ++i) {
98.154 + if (plist[i] == -1) {
98.155 + if (n==-1) {
98.156 + n = i;
98.157 + } else {
98.158 + plist[n] = i/2;
98.159 + plist[i] = n/2;
98.160 + break;
98.161 + }
98.162 + }
98.163 + }
98.164 +
98.165 + for (int i=0, next=0, last=-1; i!=_gr.nodeNum(); ++i) {
98.166 + _path.push_back(_gr.nodeFromId(next));
98.167 + if (plist[2*next] != last) {
98.168 + last = next;
98.169 + next = plist[2*next];
98.170 + } else {
98.171 + last = next;
98.172 + next = plist[2*next+1];
98.173 + }
98.174 + }
98.175 +
98.176 + _sum = _cost[_gr.edge(_path.back(), _path.front())];
98.177 + for (int i = 0; i < int(_path.size())-1; ++i) {
98.178 + _sum += _cost[_gr.edge(_path[i], _path[i+1])];
98.179 + }
98.180 +
98.181 + return _sum;
98.182 + }
98.183 +
98.184 + /// @}
98.185 +
98.186 + /// \name Query Functions
98.187 + /// @{
98.188 +
98.189 + /// \brief The total cost of the found tour.
98.190 + ///
98.191 + /// This function returns the total cost of the found tour.
98.192 + ///
98.193 + /// \pre run() must be called before using this function.
98.194 + Cost tourCost() const {
98.195 + return _sum;
98.196 + }
98.197 +
98.198 + /// \brief Returns a const reference to the node sequence of the
98.199 + /// found tour.
98.200 + ///
98.201 + /// This function returns a const reference to a vector
98.202 + /// that stores the node sequence of the found tour.
98.203 + ///
98.204 + /// \pre run() must be called before using this function.
98.205 + const std::vector<Node>& tourNodes() const {
98.206 + return _path;
98.207 + }
98.208 +
98.209 + /// \brief Gives back the node sequence of the found tour.
98.210 + ///
98.211 + /// This function copies the node sequence of the found tour into
98.212 + /// an STL container through the given output iterator. The
98.213 + /// <tt>value_type</tt> of the container must be <tt>FullGraph::Node</tt>.
98.214 + /// For example,
98.215 + /// \code
98.216 + /// std::vector<FullGraph::Node> nodes(countNodes(graph));
98.217 + /// tsp.tourNodes(nodes.begin());
98.218 + /// \endcode
98.219 + /// or
98.220 + /// \code
98.221 + /// std::list<FullGraph::Node> nodes;
98.222 + /// tsp.tourNodes(std::back_inserter(nodes));
98.223 + /// \endcode
98.224 + ///
98.225 + /// \pre run() must be called before using this function.
98.226 + template <typename Iterator>
98.227 + void tourNodes(Iterator out) const {
98.228 + std::copy(_path.begin(), _path.end(), out);
98.229 + }
98.230 +
98.231 + /// \brief Gives back the found tour as a path.
98.232 + ///
98.233 + /// This function copies the found tour as a list of arcs/edges into
98.234 + /// the given \ref lemon::concepts::Path "path structure".
98.235 + ///
98.236 + /// \pre run() must be called before using this function.
98.237 + template <typename Path>
98.238 + void tour(Path &path) const {
98.239 + path.clear();
98.240 + for (int i = 0; i < int(_path.size()) - 1; ++i) {
98.241 + path.addBack(_gr.arc(_path[i], _path[i+1]));
98.242 + }
98.243 + if (int(_path.size()) >= 2) {
98.244 + path.addBack(_gr.arc(_path.back(), _path.front()));
98.245 + }
98.246 + }
98.247 +
98.248 + /// @}
98.249 +
98.250 + };
98.251 +
98.252 +}; // namespace lemon
98.253 +
98.254 +#endif
99.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
99.2 +++ b/lemon/grosso_locatelli_pullan_mc.h Wed Oct 17 19:14:07 2018 +0200
99.3 @@ -0,0 +1,840 @@
99.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
99.5 + *
99.6 + * This file is a part of LEMON, a generic C++ optimization library.
99.7 + *
99.8 + * Copyright (C) 2003-2013
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 + */
99.21 +
99.22 +#ifndef LEMON_GROSSO_LOCATELLI_PULLAN_MC_H
99.23 +#define LEMON_GROSSO_LOCATELLI_PULLAN_MC_H
99.24 +
99.25 +/// \ingroup approx_algs
99.26 +///
99.27 +/// \file
99.28 +/// \brief The iterated local search algorithm of Grosso, Locatelli, and Pullan
99.29 +/// for the maximum clique problem
99.30 +
99.31 +#include <vector>
99.32 +#include <limits>
99.33 +#include <lemon/core.h>
99.34 +#include <lemon/random.h>
99.35 +
99.36 +namespace lemon {
99.37 +
99.38 + /// \addtogroup approx_algs
99.39 + /// @{
99.40 +
99.41 + /// \brief Implementation of the iterated local search algorithm of Grosso,
99.42 + /// Locatelli, and Pullan for the maximum clique problem
99.43 + ///
99.44 + /// \ref GrossoLocatelliPullanMc implements the iterated local search
99.45 + /// algorithm of Grosso, Locatelli, and Pullan for solving the \e maximum
99.46 + /// \e clique \e problem \cite grosso08maxclique.
99.47 + /// It is to find the largest complete subgraph (\e clique) in an
99.48 + /// undirected graph, i.e., the largest set of nodes where each
99.49 + /// pair of nodes is connected.
99.50 + ///
99.51 + /// This class provides a simple but highly efficient and robust heuristic
99.52 + /// method that quickly finds a quite large clique, but not necessarily the
99.53 + /// largest one.
99.54 + /// The algorithm performs a certain number of iterations to find several
99.55 + /// cliques and selects the largest one among them. Various limits can be
99.56 + /// specified to control the running time and the effectiveness of the
99.57 + /// search process.
99.58 + ///
99.59 + /// \tparam GR The undirected graph type the algorithm runs on.
99.60 + ///
99.61 + /// \note %GrossoLocatelliPullanMc provides three different node selection
99.62 + /// rules, from which the most powerful one is used by default.
99.63 + /// For more information, see \ref SelectionRule.
99.64 + template <typename GR>
99.65 + class GrossoLocatelliPullanMc
99.66 + {
99.67 + public:
99.68 +
99.69 + /// \brief Constants for specifying the node selection rule.
99.70 + ///
99.71 + /// Enum type containing constants for specifying the node selection rule
99.72 + /// for the \ref run() function.
99.73 + ///
99.74 + /// During the algorithm, nodes are selected for addition to the current
99.75 + /// clique according to the applied rule.
99.76 + /// In general, the PENALTY_BASED rule turned out to be the most powerful
99.77 + /// and the most robust, thus it is the default option.
99.78 + /// However, another selection rule can be specified using the \ref run()
99.79 + /// function with the proper parameter.
99.80 + enum SelectionRule {
99.81 +
99.82 + /// A node is selected randomly without any evaluation at each step.
99.83 + RANDOM,
99.84 +
99.85 + /// A node of maximum degree is selected randomly at each step.
99.86 + DEGREE_BASED,
99.87 +
99.88 + /// A node of minimum penalty is selected randomly at each step.
99.89 + /// The node penalties are updated adaptively after each stage of the
99.90 + /// search process.
99.91 + PENALTY_BASED
99.92 + };
99.93 +
99.94 + /// \brief Constants for the causes of search termination.
99.95 + ///
99.96 + /// Enum type containing constants for the different causes of search
99.97 + /// termination. The \ref run() function returns one of these values.
99.98 + enum TerminationCause {
99.99 +
99.100 + /// The iteration count limit is reached.
99.101 + ITERATION_LIMIT,
99.102 +
99.103 + /// The step count limit is reached.
99.104 + STEP_LIMIT,
99.105 +
99.106 + /// The clique size limit is reached.
99.107 + SIZE_LIMIT
99.108 + };
99.109 +
99.110 + private:
99.111 +
99.112 + TEMPLATE_GRAPH_TYPEDEFS(GR);
99.113 +
99.114 + typedef std::vector<int> IntVector;
99.115 + typedef std::vector<char> BoolVector;
99.116 + typedef std::vector<BoolVector> BoolMatrix;
99.117 + // Note: vector<char> is used instead of vector<bool> for efficiency reasons
99.118 +
99.119 + // The underlying graph
99.120 + const GR &_graph;
99.121 + IntNodeMap _id;
99.122 +
99.123 + // Internal matrix representation of the graph
99.124 + BoolMatrix _gr;
99.125 + int _n;
99.126 +
99.127 + // Search options
99.128 + bool _delta_based_restart;
99.129 + int _restart_delta_limit;
99.130 +
99.131 + // Search limits
99.132 + int _iteration_limit;
99.133 + int _step_limit;
99.134 + int _size_limit;
99.135 +
99.136 + // The current clique
99.137 + BoolVector _clique;
99.138 + int _size;
99.139 +
99.140 + // The best clique found so far
99.141 + BoolVector _best_clique;
99.142 + int _best_size;
99.143 +
99.144 + // The "distances" of the nodes from the current clique.
99.145 + // _delta[u] is the number of nodes in the clique that are
99.146 + // not connected with u.
99.147 + IntVector _delta;
99.148 +
99.149 + // The current tabu set
99.150 + BoolVector _tabu;
99.151 +
99.152 + // Random number generator
99.153 + Random _rnd;
99.154 +
99.155 + private:
99.156 +
99.157 + // Implementation of the RANDOM node selection rule.
99.158 + class RandomSelectionRule
99.159 + {
99.160 + private:
99.161 +
99.162 + // References to the algorithm instance
99.163 + const BoolVector &_clique;
99.164 + const IntVector &_delta;
99.165 + const BoolVector &_tabu;
99.166 + Random &_rnd;
99.167 +
99.168 + // Pivot rule data
99.169 + int _n;
99.170 +
99.171 + public:
99.172 +
99.173 + // Constructor
99.174 + RandomSelectionRule(GrossoLocatelliPullanMc &mc) :
99.175 + _clique(mc._clique), _delta(mc._delta), _tabu(mc._tabu),
99.176 + _rnd(mc._rnd), _n(mc._n)
99.177 + {}
99.178 +
99.179 + // Return a node index for a feasible add move or -1 if no one exists
99.180 + int nextFeasibleAddNode() const {
99.181 + int start_node = _rnd[_n];
99.182 + for (int i = start_node; i != _n; i++) {
99.183 + if (_delta[i] == 0 && !_tabu[i]) return i;
99.184 + }
99.185 + for (int i = 0; i != start_node; i++) {
99.186 + if (_delta[i] == 0 && !_tabu[i]) return i;
99.187 + }
99.188 + return -1;
99.189 + }
99.190 +
99.191 + // Return a node index for a feasible swap move or -1 if no one exists
99.192 + int nextFeasibleSwapNode() const {
99.193 + int start_node = _rnd[_n];
99.194 + for (int i = start_node; i != _n; i++) {
99.195 + if (!_clique[i] && _delta[i] == 1 && !_tabu[i]) return i;
99.196 + }
99.197 + for (int i = 0; i != start_node; i++) {
99.198 + if (!_clique[i] && _delta[i] == 1 && !_tabu[i]) return i;
99.199 + }
99.200 + return -1;
99.201 + }
99.202 +
99.203 + // Return a node index for an add move or -1 if no one exists
99.204 + int nextAddNode() const {
99.205 + int start_node = _rnd[_n];
99.206 + for (int i = start_node; i != _n; i++) {
99.207 + if (_delta[i] == 0) return i;
99.208 + }
99.209 + for (int i = 0; i != start_node; i++) {
99.210 + if (_delta[i] == 0) return i;
99.211 + }
99.212 + return -1;
99.213 + }
99.214 +
99.215 + // Update internal data structures between stages (if necessary)
99.216 + void update() {}
99.217 +
99.218 + }; //class RandomSelectionRule
99.219 +
99.220 +
99.221 + // Implementation of the DEGREE_BASED node selection rule.
99.222 + class DegreeBasedSelectionRule
99.223 + {
99.224 + private:
99.225 +
99.226 + // References to the algorithm instance
99.227 + const BoolVector &_clique;
99.228 + const IntVector &_delta;
99.229 + const BoolVector &_tabu;
99.230 + Random &_rnd;
99.231 +
99.232 + // Pivot rule data
99.233 + int _n;
99.234 + IntVector _deg;
99.235 +
99.236 + public:
99.237 +
99.238 + // Constructor
99.239 + DegreeBasedSelectionRule(GrossoLocatelliPullanMc &mc) :
99.240 + _clique(mc._clique), _delta(mc._delta), _tabu(mc._tabu),
99.241 + _rnd(mc._rnd), _n(mc._n), _deg(_n)
99.242 + {
99.243 + for (int i = 0; i != _n; i++) {
99.244 + int d = 0;
99.245 + BoolVector &row = mc._gr[i];
99.246 + for (int j = 0; j != _n; j++) {
99.247 + if (row[j]) d++;
99.248 + }
99.249 + _deg[i] = d;
99.250 + }
99.251 + }
99.252 +
99.253 + // Return a node index for a feasible add move or -1 if no one exists
99.254 + int nextFeasibleAddNode() const {
99.255 + int start_node = _rnd[_n];
99.256 + int node = -1, max_deg = -1;
99.257 + for (int i = start_node; i != _n; i++) {
99.258 + if (_delta[i] == 0 && !_tabu[i] && _deg[i] > max_deg) {
99.259 + node = i;
99.260 + max_deg = _deg[i];
99.261 + }
99.262 + }
99.263 + for (int i = 0; i != start_node; i++) {
99.264 + if (_delta[i] == 0 && !_tabu[i] && _deg[i] > max_deg) {
99.265 + node = i;
99.266 + max_deg = _deg[i];
99.267 + }
99.268 + }
99.269 + return node;
99.270 + }
99.271 +
99.272 + // Return a node index for a feasible swap move or -1 if no one exists
99.273 + int nextFeasibleSwapNode() const {
99.274 + int start_node = _rnd[_n];
99.275 + int node = -1, max_deg = -1;
99.276 + for (int i = start_node; i != _n; i++) {
99.277 + if (!_clique[i] && _delta[i] == 1 && !_tabu[i] &&
99.278 + _deg[i] > max_deg) {
99.279 + node = i;
99.280 + max_deg = _deg[i];
99.281 + }
99.282 + }
99.283 + for (int i = 0; i != start_node; i++) {
99.284 + if (!_clique[i] && _delta[i] == 1 && !_tabu[i] &&
99.285 + _deg[i] > max_deg) {
99.286 + node = i;
99.287 + max_deg = _deg[i];
99.288 + }
99.289 + }
99.290 + return node;
99.291 + }
99.292 +
99.293 + // Return a node index for an add move or -1 if no one exists
99.294 + int nextAddNode() const {
99.295 + int start_node = _rnd[_n];
99.296 + int node = -1, max_deg = -1;
99.297 + for (int i = start_node; i != _n; i++) {
99.298 + if (_delta[i] == 0 && _deg[i] > max_deg) {
99.299 + node = i;
99.300 + max_deg = _deg[i];
99.301 + }
99.302 + }
99.303 + for (int i = 0; i != start_node; i++) {
99.304 + if (_delta[i] == 0 && _deg[i] > max_deg) {
99.305 + node = i;
99.306 + max_deg = _deg[i];
99.307 + }
99.308 + }
99.309 + return node;
99.310 + }
99.311 +
99.312 + // Update internal data structures between stages (if necessary)
99.313 + void update() {}
99.314 +
99.315 + }; //class DegreeBasedSelectionRule
99.316 +
99.317 +
99.318 + // Implementation of the PENALTY_BASED node selection rule.
99.319 + class PenaltyBasedSelectionRule
99.320 + {
99.321 + private:
99.322 +
99.323 + // References to the algorithm instance
99.324 + const BoolVector &_clique;
99.325 + const IntVector &_delta;
99.326 + const BoolVector &_tabu;
99.327 + Random &_rnd;
99.328 +
99.329 + // Pivot rule data
99.330 + int _n;
99.331 + IntVector _penalty;
99.332 +
99.333 + public:
99.334 +
99.335 + // Constructor
99.336 + PenaltyBasedSelectionRule(GrossoLocatelliPullanMc &mc) :
99.337 + _clique(mc._clique), _delta(mc._delta), _tabu(mc._tabu),
99.338 + _rnd(mc._rnd), _n(mc._n), _penalty(_n, 0)
99.339 + {}
99.340 +
99.341 + // Return a node index for a feasible add move or -1 if no one exists
99.342 + int nextFeasibleAddNode() const {
99.343 + int start_node = _rnd[_n];
99.344 + int node = -1, min_p = std::numeric_limits<int>::max();
99.345 + for (int i = start_node; i != _n; i++) {
99.346 + if (_delta[i] == 0 && !_tabu[i] && _penalty[i] < min_p) {
99.347 + node = i;
99.348 + min_p = _penalty[i];
99.349 + }
99.350 + }
99.351 + for (int i = 0; i != start_node; i++) {
99.352 + if (_delta[i] == 0 && !_tabu[i] && _penalty[i] < min_p) {
99.353 + node = i;
99.354 + min_p = _penalty[i];
99.355 + }
99.356 + }
99.357 + return node;
99.358 + }
99.359 +
99.360 + // Return a node index for a feasible swap move or -1 if no one exists
99.361 + int nextFeasibleSwapNode() const {
99.362 + int start_node = _rnd[_n];
99.363 + int node = -1, min_p = std::numeric_limits<int>::max();
99.364 + for (int i = start_node; i != _n; i++) {
99.365 + if (!_clique[i] && _delta[i] == 1 && !_tabu[i] &&
99.366 + _penalty[i] < min_p) {
99.367 + node = i;
99.368 + min_p = _penalty[i];
99.369 + }
99.370 + }
99.371 + for (int i = 0; i != start_node; i++) {
99.372 + if (!_clique[i] && _delta[i] == 1 && !_tabu[i] &&
99.373 + _penalty[i] < min_p) {
99.374 + node = i;
99.375 + min_p = _penalty[i];
99.376 + }
99.377 + }
99.378 + return node;
99.379 + }
99.380 +
99.381 + // Return a node index for an add move or -1 if no one exists
99.382 + int nextAddNode() const {
99.383 + int start_node = _rnd[_n];
99.384 + int node = -1, min_p = std::numeric_limits<int>::max();
99.385 + for (int i = start_node; i != _n; i++) {
99.386 + if (_delta[i] == 0 && _penalty[i] < min_p) {
99.387 + node = i;
99.388 + min_p = _penalty[i];
99.389 + }
99.390 + }
99.391 + for (int i = 0; i != start_node; i++) {
99.392 + if (_delta[i] == 0 && _penalty[i] < min_p) {
99.393 + node = i;
99.394 + min_p = _penalty[i];
99.395 + }
99.396 + }
99.397 + return node;
99.398 + }
99.399 +
99.400 + // Update internal data structures between stages (if necessary)
99.401 + void update() {}
99.402 +
99.403 + }; //class PenaltyBasedSelectionRule
99.404 +
99.405 + public:
99.406 +
99.407 + /// \brief Constructor.
99.408 + ///
99.409 + /// Constructor.
99.410 + /// The global \ref rnd "random number generator instance" is used
99.411 + /// during the algorithm.
99.412 + ///
99.413 + /// \param graph The undirected graph the algorithm runs on.
99.414 + GrossoLocatelliPullanMc(const GR& graph) :
99.415 + _graph(graph), _id(_graph), _rnd(rnd)
99.416 + {
99.417 + initOptions();
99.418 + }
99.419 +
99.420 + /// \brief Constructor with random seed.
99.421 + ///
99.422 + /// Constructor with random seed.
99.423 + ///
99.424 + /// \param graph The undirected graph the algorithm runs on.
99.425 + /// \param seed Seed value for the internal random number generator
99.426 + /// that is used during the algorithm.
99.427 + GrossoLocatelliPullanMc(const GR& graph, int seed) :
99.428 + _graph(graph), _id(_graph), _rnd(seed)
99.429 + {
99.430 + initOptions();
99.431 + }
99.432 +
99.433 + /// \brief Constructor with random number generator.
99.434 + ///
99.435 + /// Constructor with random number generator.
99.436 + ///
99.437 + /// \param graph The undirected graph the algorithm runs on.
99.438 + /// \param random A random number generator that is used during the
99.439 + /// algorithm.
99.440 + GrossoLocatelliPullanMc(const GR& graph, const Random& random) :
99.441 + _graph(graph), _id(_graph), _rnd(random)
99.442 + {
99.443 + initOptions();
99.444 + }
99.445 +
99.446 + /// \name Execution Control
99.447 + /// The \ref run() function can be used to execute the algorithm.\n
99.448 + /// The functions \ref iterationLimit(int), \ref stepLimit(int), and
99.449 + /// \ref sizeLimit(int) can be used to specify various limits for the
99.450 + /// search process.
99.451 +
99.452 + /// @{
99.453 +
99.454 + /// \brief Sets the maximum number of iterations.
99.455 + ///
99.456 + /// This function sets the maximum number of iterations.
99.457 + /// Each iteration of the algorithm finds a maximal clique (but not
99.458 + /// necessarily the largest one) by performing several search steps
99.459 + /// (node selections).
99.460 + ///
99.461 + /// This limit controls the running time and the success of the
99.462 + /// algorithm. For larger values, the algorithm runs slower, but it more
99.463 + /// likely finds larger cliques. For smaller values, the algorithm is
99.464 + /// faster but probably gives worse results.
99.465 + ///
99.466 + /// The default value is \c 1000.
99.467 + /// \c -1 means that number of iterations is not limited.
99.468 + ///
99.469 + /// \warning You should specify a reasonable limit for the number of
99.470 + /// iterations and/or the number of search steps.
99.471 + ///
99.472 + /// \return <tt>(*this)</tt>
99.473 + ///
99.474 + /// \sa stepLimit(int)
99.475 + /// \sa sizeLimit(int)
99.476 + GrossoLocatelliPullanMc& iterationLimit(int limit) {
99.477 + _iteration_limit = limit;
99.478 + return *this;
99.479 + }
99.480 +
99.481 + /// \brief Sets the maximum number of search steps.
99.482 + ///
99.483 + /// This function sets the maximum number of elementary search steps.
99.484 + /// Each iteration of the algorithm finds a maximal clique (but not
99.485 + /// necessarily the largest one) by performing several search steps
99.486 + /// (node selections).
99.487 + ///
99.488 + /// This limit controls the running time and the success of the
99.489 + /// algorithm. For larger values, the algorithm runs slower, but it more
99.490 + /// likely finds larger cliques. For smaller values, the algorithm is
99.491 + /// faster but probably gives worse results.
99.492 + ///
99.493 + /// The default value is \c -1, which means that number of steps
99.494 + /// is not limited explicitly. However, the number of iterations is
99.495 + /// limited and each iteration performs a finite number of search steps.
99.496 + ///
99.497 + /// \warning You should specify a reasonable limit for the number of
99.498 + /// iterations and/or the number of search steps.
99.499 + ///
99.500 + /// \return <tt>(*this)</tt>
99.501 + ///
99.502 + /// \sa iterationLimit(int)
99.503 + /// \sa sizeLimit(int)
99.504 + GrossoLocatelliPullanMc& stepLimit(int limit) {
99.505 + _step_limit = limit;
99.506 + return *this;
99.507 + }
99.508 +
99.509 + /// \brief Sets the desired clique size.
99.510 + ///
99.511 + /// This function sets the desired clique size that serves as a search
99.512 + /// limit. If a clique of this size (or a larger one) is found, then the
99.513 + /// algorithm terminates.
99.514 + ///
99.515 + /// This function is especially useful if you know an exact upper bound
99.516 + /// for the size of the cliques in the graph or if any clique above
99.517 + /// a certain size limit is sufficient for your application.
99.518 + ///
99.519 + /// The default value is \c -1, which means that the size limit is set to
99.520 + /// the number of nodes in the graph.
99.521 + ///
99.522 + /// \return <tt>(*this)</tt>
99.523 + ///
99.524 + /// \sa iterationLimit(int)
99.525 + /// \sa stepLimit(int)
99.526 + GrossoLocatelliPullanMc& sizeLimit(int limit) {
99.527 + _size_limit = limit;
99.528 + return *this;
99.529 + }
99.530 +
99.531 + /// \brief The maximum number of iterations.
99.532 + ///
99.533 + /// This function gives back the maximum number of iterations.
99.534 + /// \c -1 means that no limit is specified.
99.535 + ///
99.536 + /// \sa iterationLimit(int)
99.537 + int iterationLimit() const {
99.538 + return _iteration_limit;
99.539 + }
99.540 +
99.541 + /// \brief The maximum number of search steps.
99.542 + ///
99.543 + /// This function gives back the maximum number of search steps.
99.544 + /// \c -1 means that no limit is specified.
99.545 + ///
99.546 + /// \sa stepLimit(int)
99.547 + int stepLimit() const {
99.548 + return _step_limit;
99.549 + }
99.550 +
99.551 + /// \brief The desired clique size.
99.552 + ///
99.553 + /// This function gives back the desired clique size that serves as a
99.554 + /// search limit. \c -1 means that this limit is set to the number of
99.555 + /// nodes in the graph.
99.556 + ///
99.557 + /// \sa sizeLimit(int)
99.558 + int sizeLimit() const {
99.559 + return _size_limit;
99.560 + }
99.561 +
99.562 + /// \brief Runs the algorithm.
99.563 + ///
99.564 + /// This function runs the algorithm. If one of the specified limits
99.565 + /// is reached, the search process terminates.
99.566 + ///
99.567 + /// \param rule The node selection rule. For more information, see
99.568 + /// \ref SelectionRule.
99.569 + ///
99.570 + /// \return The termination cause of the search. For more information,
99.571 + /// see \ref TerminationCause.
99.572 + TerminationCause run(SelectionRule rule = PENALTY_BASED)
99.573 + {
99.574 + init();
99.575 + switch (rule) {
99.576 + case RANDOM:
99.577 + return start<RandomSelectionRule>();
99.578 + case DEGREE_BASED:
99.579 + return start<DegreeBasedSelectionRule>();
99.580 + default:
99.581 + return start<PenaltyBasedSelectionRule>();
99.582 + }
99.583 + }
99.584 +
99.585 + /// @}
99.586 +
99.587 + /// \name Query Functions
99.588 + /// The results of the algorithm can be obtained using these functions.\n
99.589 + /// The run() function must be called before using them.
99.590 +
99.591 + /// @{
99.592 +
99.593 + /// \brief The size of the found clique
99.594 + ///
99.595 + /// This function returns the size of the found clique.
99.596 + ///
99.597 + /// \pre run() must be called before using this function.
99.598 + int cliqueSize() const {
99.599 + return _best_size;
99.600 + }
99.601 +
99.602 + /// \brief Gives back the found clique in a \c bool node map
99.603 + ///
99.604 + /// This function gives back the characteristic vector of the found
99.605 + /// clique in the given node map.
99.606 + /// It must be a \ref concepts::WriteMap "writable" node map with
99.607 + /// \c bool (or convertible) value type.
99.608 + ///
99.609 + /// \pre run() must be called before using this function.
99.610 + template <typename CliqueMap>
99.611 + void cliqueMap(CliqueMap &map) const {
99.612 + for (NodeIt n(_graph); n != INVALID; ++n) {
99.613 + map[n] = static_cast<bool>(_best_clique[_id[n]]);
99.614 + }
99.615 + }
99.616 +
99.617 + /// \brief Iterator to list the nodes of the found clique
99.618 + ///
99.619 + /// This iterator class lists the nodes of the found clique.
99.620 + /// Before using it, you must allocate a GrossoLocatelliPullanMc instance
99.621 + /// and call its \ref GrossoLocatelliPullanMc::run() "run()" method.
99.622 + ///
99.623 + /// The following example prints out the IDs of the nodes in the found
99.624 + /// clique.
99.625 + /// \code
99.626 + /// GrossoLocatelliPullanMc<Graph> mc(g);
99.627 + /// mc.run();
99.628 + /// for (GrossoLocatelliPullanMc<Graph>::CliqueNodeIt n(mc);
99.629 + /// n != INVALID; ++n)
99.630 + /// {
99.631 + /// std::cout << g.id(n) << std::endl;
99.632 + /// }
99.633 + /// \endcode
99.634 + class CliqueNodeIt
99.635 + {
99.636 + private:
99.637 + NodeIt _it;
99.638 + BoolNodeMap _map;
99.639 +
99.640 + public:
99.641 +
99.642 + /// Constructor
99.643 +
99.644 + /// Constructor.
99.645 + /// \param mc The algorithm instance.
99.646 + CliqueNodeIt(const GrossoLocatelliPullanMc &mc)
99.647 + : _map(mc._graph)
99.648 + {
99.649 + mc.cliqueMap(_map);
99.650 + for (_it = NodeIt(mc._graph); _it != INVALID && !_map[_it]; ++_it) ;
99.651 + }
99.652 +
99.653 + /// Conversion to \c Node
99.654 + operator Node() const { return _it; }
99.655 +
99.656 + bool operator==(Invalid) const { return _it == INVALID; }
99.657 + bool operator!=(Invalid) const { return _it != INVALID; }
99.658 +
99.659 + /// Next node
99.660 + CliqueNodeIt &operator++() {
99.661 + for (++_it; _it != INVALID && !_map[_it]; ++_it) ;
99.662 + return *this;
99.663 + }
99.664 +
99.665 + /// Postfix incrementation
99.666 +
99.667 + /// Postfix incrementation.
99.668 + ///
99.669 + /// \warning This incrementation returns a \c Node, not a
99.670 + /// \c CliqueNodeIt as one may expect.
99.671 + typename GR::Node operator++(int) {
99.672 + Node n=*this;
99.673 + ++(*this);
99.674 + return n;
99.675 + }
99.676 +
99.677 + };
99.678 +
99.679 + /// @}
99.680 +
99.681 + private:
99.682 +
99.683 + // Initialize search options and limits
99.684 + void initOptions() {
99.685 + // Search options
99.686 + _delta_based_restart = true;
99.687 + _restart_delta_limit = 4;
99.688 +
99.689 + // Search limits
99.690 + _iteration_limit = 1000;
99.691 + _step_limit = -1; // this is disabled by default
99.692 + _size_limit = -1; // this is disabled by default
99.693 + }
99.694 +
99.695 + // Adds a node to the current clique
99.696 + void addCliqueNode(int u) {
99.697 + if (_clique[u]) return;
99.698 + _clique[u] = true;
99.699 + _size++;
99.700 + BoolVector &row = _gr[u];
99.701 + for (int i = 0; i != _n; i++) {
99.702 + if (!row[i]) _delta[i]++;
99.703 + }
99.704 + }
99.705 +
99.706 + // Removes a node from the current clique
99.707 + void delCliqueNode(int u) {
99.708 + if (!_clique[u]) return;
99.709 + _clique[u] = false;
99.710 + _size--;
99.711 + BoolVector &row = _gr[u];
99.712 + for (int i = 0; i != _n; i++) {
99.713 + if (!row[i]) _delta[i]--;
99.714 + }
99.715 + }
99.716 +
99.717 + // Initialize data structures
99.718 + void init() {
99.719 + _n = countNodes(_graph);
99.720 + int ui = 0;
99.721 + for (NodeIt u(_graph); u != INVALID; ++u) {
99.722 + _id[u] = ui++;
99.723 + }
99.724 + _gr.clear();
99.725 + _gr.resize(_n, BoolVector(_n, false));
99.726 + ui = 0;
99.727 + for (NodeIt u(_graph); u != INVALID; ++u) {
99.728 + for (IncEdgeIt e(_graph, u); e != INVALID; ++e) {
99.729 + int vi = _id[_graph.runningNode(e)];
99.730 + _gr[ui][vi] = true;
99.731 + _gr[vi][ui] = true;
99.732 + }
99.733 + ++ui;
99.734 + }
99.735 +
99.736 + _clique.clear();
99.737 + _clique.resize(_n, false);
99.738 + _size = 0;
99.739 + _best_clique.clear();
99.740 + _best_clique.resize(_n, false);
99.741 + _best_size = 0;
99.742 + _delta.clear();
99.743 + _delta.resize(_n, 0);
99.744 + _tabu.clear();
99.745 + _tabu.resize(_n, false);
99.746 + }
99.747 +
99.748 + // Executes the algorithm
99.749 + template <typename SelectionRuleImpl>
99.750 + TerminationCause start() {
99.751 + if (_n == 0) return SIZE_LIMIT;
99.752 + if (_n == 1) {
99.753 + _best_clique[0] = true;
99.754 + _best_size = 1;
99.755 + return SIZE_LIMIT;
99.756 + }
99.757 +
99.758 + // Iterated local search algorithm
99.759 + const int max_size = _size_limit >= 0 ? _size_limit : _n;
99.760 + const int max_restart = _iteration_limit >= 0 ?
99.761 + _iteration_limit : std::numeric_limits<int>::max();
99.762 + const int max_select = _step_limit >= 0 ?
99.763 + _step_limit : std::numeric_limits<int>::max();
99.764 +
99.765 + SelectionRuleImpl sel_method(*this);
99.766 + int select = 0, restart = 0;
99.767 + IntVector restart_nodes;
99.768 + while (select < max_select && restart < max_restart) {
99.769 +
99.770 + // Perturbation/restart
99.771 + restart++;
99.772 + if (_delta_based_restart) {
99.773 + restart_nodes.clear();
99.774 + for (int i = 0; i != _n; i++) {
99.775 + if (_delta[i] >= _restart_delta_limit)
99.776 + restart_nodes.push_back(i);
99.777 + }
99.778 + }
99.779 + int rs_node = -1;
99.780 + if (restart_nodes.size() > 0) {
99.781 + rs_node = restart_nodes[_rnd[restart_nodes.size()]];
99.782 + } else {
99.783 + rs_node = _rnd[_n];
99.784 + }
99.785 + BoolVector &row = _gr[rs_node];
99.786 + for (int i = 0; i != _n; i++) {
99.787 + if (_clique[i] && !row[i]) delCliqueNode(i);
99.788 + }
99.789 + addCliqueNode(rs_node);
99.790 +
99.791 + // Local search
99.792 + _tabu.clear();
99.793 + _tabu.resize(_n, false);
99.794 + bool tabu_empty = true;
99.795 + int max_swap = _size;
99.796 + while (select < max_select) {
99.797 + select++;
99.798 + int u;
99.799 + if ((u = sel_method.nextFeasibleAddNode()) != -1) {
99.800 + // Feasible add move
99.801 + addCliqueNode(u);
99.802 + if (tabu_empty) max_swap = _size;
99.803 + }
99.804 + else if ((u = sel_method.nextFeasibleSwapNode()) != -1) {
99.805 + // Feasible swap move
99.806 + int v = -1;
99.807 + BoolVector &row = _gr[u];
99.808 + for (int i = 0; i != _n; i++) {
99.809 + if (_clique[i] && !row[i]) {
99.810 + v = i;
99.811 + break;
99.812 + }
99.813 + }
99.814 + addCliqueNode(u);
99.815 + delCliqueNode(v);
99.816 + _tabu[v] = true;
99.817 + tabu_empty = false;
99.818 + if (--max_swap <= 0) break;
99.819 + }
99.820 + else if ((u = sel_method.nextAddNode()) != -1) {
99.821 + // Non-feasible add move
99.822 + addCliqueNode(u);
99.823 + }
99.824 + else break;
99.825 + }
99.826 + if (_size > _best_size) {
99.827 + _best_clique = _clique;
99.828 + _best_size = _size;
99.829 + if (_best_size >= max_size) return SIZE_LIMIT;
99.830 + }
99.831 + sel_method.update();
99.832 + }
99.833 +
99.834 + return (restart >= max_restart ? ITERATION_LIMIT : STEP_LIMIT);
99.835 + }
99.836 +
99.837 + }; //class GrossoLocatelliPullanMc
99.838 +
99.839 + ///@}
99.840 +
99.841 +} //namespace lemon
99.842 +
99.843 +#endif //LEMON_GROSSO_LOCATELLI_PULLAN_MC_H
100.1 --- a/lemon/hao_orlin.h Mon Jul 16 16:21:40 2018 +0200
100.2 +++ b/lemon/hao_orlin.h Wed Oct 17 19:14:07 2018 +0200
100.3 @@ -2,7 +2,7 @@
100.4 *
100.5 * This file is a part of LEMON, a generic C++ optimization library.
100.6 *
100.7 - * Copyright (C) 2003-2010
100.8 + * Copyright (C) 2003-2013
100.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
100.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
100.11 *
100.12 @@ -53,8 +53,8 @@
100.13 /// minimum cut of \f$ D \f$. The algorithm is a modified
100.14 /// preflow push-relabel algorithm. Our implementation calculates
100.15 /// the minimum cut in \f$ O(n^2\sqrt{m}) \f$ time (we use the
100.16 - /// highest-label rule), or in \f$O(nm)\f$ for unit capacities. The
100.17 - /// purpose of such algorithm is e.g. testing network reliability.
100.18 + /// highest-label rule), or in \f$O(nm)\f$ for unit capacities. A notable
100.19 + /// use of this algorithm is testing network reliability.
100.20 ///
100.21 /// For an undirected graph you can run just the first phase of the
100.22 /// algorithm or you can use the algorithm of Nagamochi and Ibaraki,
100.23 @@ -912,6 +912,8 @@
100.24 /// This function calculates a minimum cut with \f$ source \f$ on the
100.25 /// source-side (i.e. a set \f$ X\subsetneq V \f$ with
100.26 /// \f$ source \in X \f$ and minimal outgoing capacity).
100.27 + /// It updates the stored cut if (and only if) the newly found one
100.28 + /// is better.
100.29 ///
100.30 /// \pre \ref init() must be called before using this function.
100.31 void calculateOut() {
100.32 @@ -924,6 +926,8 @@
100.33 /// This function calculates a minimum cut with \f$ source \f$ on the
100.34 /// sink-side (i.e. a set \f$ X\subsetneq V \f$ with
100.35 /// \f$ source \notin X \f$ and minimal outgoing capacity).
100.36 + /// It updates the stored cut if (and only if) the newly found one
100.37 + /// is better.
100.38 ///
100.39 /// \pre \ref init() must be called before using this function.
100.40 void calculateIn() {
100.41 @@ -933,8 +937,8 @@
100.42
100.43 /// \brief Run the algorithm.
100.44 ///
100.45 - /// This function runs the algorithm. It finds nodes \c source and
100.46 - /// \c target arbitrarily and then calls \ref init(), \ref calculateOut()
100.47 + /// This function runs the algorithm. It chooses source node,
100.48 + /// then calls \ref init(), \ref calculateOut()
100.49 /// and \ref calculateIn().
100.50 void run() {
100.51 init();
100.52 @@ -944,9 +948,9 @@
100.53
100.54 /// \brief Run the algorithm.
100.55 ///
100.56 - /// This function runs the algorithm. It uses the given \c source node,
100.57 - /// finds a proper \c target node and then calls the \ref init(),
100.58 - /// \ref calculateOut() and \ref calculateIn().
100.59 + /// This function runs the algorithm. It calls \ref init(),
100.60 + /// \ref calculateOut() and \ref calculateIn() with the given
100.61 + /// source node.
100.62 void run(const Node& s) {
100.63 init(s);
100.64 calculateOut();
100.65 @@ -965,7 +969,9 @@
100.66
100.67 /// \brief Return the value of the minimum cut.
100.68 ///
100.69 - /// This function returns the value of the minimum cut.
100.70 + /// This function returns the value of the best cut found by the
100.71 + /// previously called \ref run(), \ref calculateOut() or \ref
100.72 + /// calculateIn().
100.73 ///
100.74 /// \pre \ref run(), \ref calculateOut() or \ref calculateIn()
100.75 /// must be called before using this function.
100.76 @@ -976,9 +982,13 @@
100.77
100.78 /// \brief Return a minimum cut.
100.79 ///
100.80 - /// This function sets \c cutMap to the characteristic vector of a
100.81 - /// minimum value cut: it will give a non-empty set \f$ X\subsetneq V \f$
100.82 - /// with minimal outgoing capacity (i.e. \c cutMap will be \c true exactly
100.83 + /// This function gives the best cut found by the
100.84 + /// previously called \ref run(), \ref calculateOut() or \ref
100.85 + /// calculateIn().
100.86 + ///
100.87 + /// It sets \c cutMap to the characteristic vector of the found
100.88 + /// minimum value cut - a non-empty set \f$ X\subsetneq V \f$
100.89 + /// of minimum outgoing capacity (i.e. \c cutMap will be \c true exactly
100.90 /// for the nodes of \f$ X \f$).
100.91 ///
100.92 /// \param cutMap A \ref concepts::WriteMap "writable" node map with
101.1 --- a/lemon/hartmann_orlin_mmc.h Mon Jul 16 16:21:40 2018 +0200
101.2 +++ b/lemon/hartmann_orlin_mmc.h Wed Oct 17 19:14:07 2018 +0200
101.3 @@ -2,7 +2,7 @@
101.4 *
101.5 * This file is a part of LEMON, a generic C++ optimization library.
101.6 *
101.7 - * Copyright (C) 2003-2010
101.8 + * Copyright (C) 2003-2013
101.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
101.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
101.11 *
101.12 @@ -98,10 +98,11 @@
101.13 ///
101.14 /// This class implements the Hartmann-Orlin algorithm for finding
101.15 /// a directed cycle of minimum mean cost in a digraph
101.16 - /// \ref amo93networkflows, \ref dasdan98minmeancycle.
101.17 - /// It is an improved version of \ref KarpMmc "Karp"'s original algorithm,
101.18 - /// it applies an efficient early termination scheme.
101.19 - /// It runs in time O(ne) and uses space O(n<sup>2</sup>+e).
101.20 + /// \cite hartmann93finding, \cite dasdan98minmeancycle.
101.21 + /// This method is based on \ref KarpMmc "Karp"'s original algorithm, but
101.22 + /// applies an early termination scheme. It makes the algorithm
101.23 + /// significantly faster for some problem instances, but slower for others.
101.24 + /// The algorithm runs in time O(nm) and uses space O(n<sup>2</sup>+m).
101.25 ///
101.26 /// \tparam GR The type of the digraph the algorithm runs on.
101.27 /// \tparam CM The type of the cost map. The default
101.28 @@ -142,11 +143,14 @@
101.29 /// \brief The path type of the found cycles
101.30 ///
101.31 /// The path type of the found cycles.
101.32 - /// Using the \ref HartmannOrlinMmcDefaultTraits "default traits class",
101.33 + /// Using the \ref lemon::HartmannOrlinMmcDefaultTraits
101.34 + /// "default traits class",
101.35 /// it is \ref lemon::Path "Path<Digraph>".
101.36 typedef typename TR::Path Path;
101.37
101.38 - /// The \ref HartmannOrlinMmcDefaultTraits "traits class" of the algorithm
101.39 + /// \brief The
101.40 + /// \ref lemon::HartmannOrlinMmcDefaultTraits "traits class"
101.41 + /// of the algorithm
101.42 typedef TR Traits;
101.43
101.44 private:
101.45 @@ -274,8 +278,8 @@
101.46 /// found cycle.
101.47 ///
101.48 /// If you don't call this function before calling \ref run() or
101.49 - /// \ref findCycleMean(), it will allocate a local \ref Path "path"
101.50 - /// structure. The destuctor deallocates this automatically
101.51 + /// \ref findCycleMean(), a local \ref Path "path" structure
101.52 + /// will be allocated. The destuctor deallocates this automatically
101.53 /// allocated object, of course.
101.54 ///
101.55 /// \note The algorithm calls only the \ref lemon::Path::addFront()
102.1 --- a/lemon/howard_mmc.h Mon Jul 16 16:21:40 2018 +0200
102.2 +++ b/lemon/howard_mmc.h Wed Oct 17 19:14:07 2018 +0200
102.3 @@ -2,7 +2,7 @@
102.4 *
102.5 * This file is a part of LEMON, a generic C++ optimization library.
102.6 *
102.7 - * Copyright (C) 2003-2010
102.8 + * Copyright (C) 2003-2013
102.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
102.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
102.11 *
102.12 @@ -98,7 +98,7 @@
102.13 ///
102.14 /// This class implements Howard's policy iteration algorithm for finding
102.15 /// a directed cycle of minimum mean cost in a digraph
102.16 - /// \ref amo93networkflows, \ref dasdan98minmeancycle.
102.17 + /// \cite dasdan98minmeancycle, \cite dasdan04experimental.
102.18 /// This class provides the most efficient algorithm for the
102.19 /// minimum mean cycle problem, though the best known theoretical
102.20 /// bound on its running time is exponential.
102.21 @@ -142,13 +142,30 @@
102.22 /// \brief The path type of the found cycles
102.23 ///
102.24 /// The path type of the found cycles.
102.25 - /// Using the \ref HowardMmcDefaultTraits "default traits class",
102.26 + /// Using the \ref lemon::HowardMmcDefaultTraits "default traits class",
102.27 /// it is \ref lemon::Path "Path<Digraph>".
102.28 typedef typename TR::Path Path;
102.29
102.30 - /// The \ref HowardMmcDefaultTraits "traits class" of the algorithm
102.31 + /// The \ref lemon::HowardMmcDefaultTraits "traits class" of the algorithm
102.32 typedef TR Traits;
102.33
102.34 + /// \brief Constants for the causes of search termination.
102.35 + ///
102.36 + /// Enum type containing constants for the different causes of search
102.37 + /// termination. The \ref findCycleMean() function returns one of
102.38 + /// these values.
102.39 + enum TerminationCause {
102.40 +
102.41 + /// No directed cycle can be found in the digraph.
102.42 + NO_CYCLE = 0,
102.43 +
102.44 + /// Optimal solution (minimum cycle mean) is found.
102.45 + OPTIMAL = 1,
102.46 +
102.47 + /// The iteration count limit is reached.
102.48 + ITERATION_LIMIT
102.49 + };
102.50 +
102.51 private:
102.52
102.53 TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
102.54 @@ -265,8 +282,8 @@
102.55 /// found cycle.
102.56 ///
102.57 /// If you don't call this function before calling \ref run() or
102.58 - /// \ref findCycleMean(), it will allocate a local \ref Path "path"
102.59 - /// structure. The destuctor deallocates this automatically
102.60 + /// \ref findCycleMean(), a local \ref Path "path" structure
102.61 + /// will be allocated. The destuctor deallocates this automatically
102.62 /// allocated object, of course.
102.63 ///
102.64 /// \note The algorithm calls only the \ref lemon::Path::addBack()
102.65 @@ -324,25 +341,47 @@
102.66 return findCycleMean() && findCycle();
102.67 }
102.68
102.69 - /// \brief Find the minimum cycle mean.
102.70 + /// \brief Find the minimum cycle mean (or an upper bound).
102.71 ///
102.72 /// This function finds the minimum mean cost of the directed
102.73 - /// cycles in the digraph.
102.74 + /// cycles in the digraph (or an upper bound for it).
102.75 ///
102.76 - /// \return \c true if a directed cycle exists in the digraph.
102.77 - bool findCycleMean() {
102.78 + /// By default, the function finds the exact minimum cycle mean,
102.79 + /// but an optional limit can also be specified for the number of
102.80 + /// iterations performed during the search process.
102.81 + /// The return value indicates if the optimal solution is found
102.82 + /// or the iteration limit is reached. In the latter case, an
102.83 + /// approximate solution is provided, which corresponds to a directed
102.84 + /// cycle whose mean cost is relatively small, but not necessarily
102.85 + /// minimal.
102.86 + ///
102.87 + /// \param limit The maximum allowed number of iterations during
102.88 + /// the search process. Its default value implies that the algorithm
102.89 + /// runs until it finds the exact optimal solution.
102.90 + ///
102.91 + /// \return The termination cause of the search process.
102.92 + /// For more information, see \ref TerminationCause.
102.93 + TerminationCause findCycleMean(int limit =
102.94 + std::numeric_limits<int>::max()) {
102.95 // Initialize and find strongly connected components
102.96 init();
102.97 findComponents();
102.98
102.99 // Find the minimum cycle mean in the components
102.100 + int iter_count = 0;
102.101 + bool iter_limit_reached = false;
102.102 for (int comp = 0; comp < _comp_num; ++comp) {
102.103 // Find the minimum mean cycle in the current component
102.104 if (!buildPolicyGraph(comp)) continue;
102.105 while (true) {
102.106 + if (++iter_count > limit) {
102.107 + iter_limit_reached = true;
102.108 + break;
102.109 + }
102.110 findPolicyCycle();
102.111 if (!computeNodeDistances()) break;
102.112 }
102.113 +
102.114 // Update the best cycle (global minimum mean cycle)
102.115 if ( _curr_found && (!_best_found ||
102.116 _curr_cost * _best_size < _best_cost * _curr_size) ) {
102.117 @@ -351,8 +390,15 @@
102.118 _best_size = _curr_size;
102.119 _best_node = _curr_node;
102.120 }
102.121 +
102.122 + if (iter_limit_reached) break;
102.123 }
102.124 - return _best_found;
102.125 +
102.126 + if (iter_limit_reached) {
102.127 + return ITERATION_LIMIT;
102.128 + } else {
102.129 + return _best_found ? OPTIMAL : NO_CYCLE;
102.130 + }
102.131 }
102.132
102.133 /// \brief Find a minimum mean directed cycle.
103.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
103.2 +++ b/lemon/insertion_tsp.h Wed Oct 17 19:14:07 2018 +0200
103.3 @@ -0,0 +1,533 @@
103.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
103.5 + *
103.6 + * This file is a part of LEMON, a generic C++ optimization library.
103.7 + *
103.8 + * Copyright (C) 2003-2013
103.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
103.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
103.11 + *
103.12 + * Permission to use, modify and distribute this software is granted
103.13 + * provided that this copyright notice appears in all copies. For
103.14 + * precise terms see the accompanying LICENSE file.
103.15 + *
103.16 + * This software is provided "AS IS" with no warranty of any kind,
103.17 + * express or implied, and with no claim as to its suitability for any
103.18 + * purpose.
103.19 + *
103.20 + */
103.21 +
103.22 +#ifndef LEMON_INSERTION_TSP_H
103.23 +#define LEMON_INSERTION_TSP_H
103.24 +
103.25 +/// \ingroup tsp
103.26 +/// \file
103.27 +/// \brief Insertion algorithm for symmetric TSP
103.28 +
103.29 +#include <vector>
103.30 +#include <functional>
103.31 +#include <lemon/full_graph.h>
103.32 +#include <lemon/maps.h>
103.33 +#include <lemon/random.h>
103.34 +
103.35 +namespace lemon {
103.36 +
103.37 + /// \ingroup tsp
103.38 + ///
103.39 + /// \brief Insertion algorithm for symmetric TSP.
103.40 + ///
103.41 + /// InsertionTsp implements the insertion heuristic for solving
103.42 + /// symmetric \ref tsp "TSP".
103.43 + ///
103.44 + /// This is a fast and effective tour construction method that has
103.45 + /// many variants.
103.46 + /// It starts with a subtour containing a few nodes of the graph and it
103.47 + /// iteratively inserts the other nodes into this subtour according to a
103.48 + /// certain node selection rule.
103.49 + ///
103.50 + /// This method is among the fastest TSP algorithms, and it typically
103.51 + /// provides quite good solutions (usually much better than
103.52 + /// \ref NearestNeighborTsp and \ref GreedyTsp).
103.53 + ///
103.54 + /// InsertionTsp implements four different node selection rules,
103.55 + /// from which the most effective one (\e farthest \e node \e selection)
103.56 + /// is used by default.
103.57 + /// With this choice, the algorithm runs in O(n<sup>2</sup>) time.
103.58 + /// For more information, see \ref SelectionRule.
103.59 + ///
103.60 + /// \tparam CM Type of the cost map.
103.61 + template <typename CM>
103.62 + class InsertionTsp
103.63 + {
103.64 + public:
103.65 +
103.66 + /// Type of the cost map
103.67 + typedef CM CostMap;
103.68 + /// Type of the edge costs
103.69 + typedef typename CM::Value Cost;
103.70 +
103.71 + private:
103.72 +
103.73 + GRAPH_TYPEDEFS(FullGraph);
103.74 +
103.75 + const FullGraph &_gr;
103.76 + const CostMap &_cost;
103.77 + std::vector<Node> _notused;
103.78 + std::vector<Node> _tour;
103.79 + Cost _sum;
103.80 +
103.81 + public:
103.82 +
103.83 + /// \brief Constants for specifying the node selection rule.
103.84 + ///
103.85 + /// Enum type containing constants for specifying the node selection
103.86 + /// rule for the \ref run() function.
103.87 + ///
103.88 + /// During the algorithm, nodes are selected for addition to the current
103.89 + /// subtour according to the applied rule.
103.90 + /// The FARTHEST method is one of the fastest selection rules, and
103.91 + /// it is typically the most effective, thus it is the default
103.92 + /// option. The RANDOM rule usually gives slightly worse results,
103.93 + /// but it is more robust.
103.94 + ///
103.95 + /// The desired selection rule can be specified as a parameter of the
103.96 + /// \ref run() function.
103.97 + enum SelectionRule {
103.98 +
103.99 + /// An unvisited node having minimum distance from the current
103.100 + /// subtour is selected at each step.
103.101 + /// The algorithm runs in O(n<sup>2</sup>) time using this
103.102 + /// selection rule.
103.103 + NEAREST,
103.104 +
103.105 + /// An unvisited node having maximum distance from the current
103.106 + /// subtour is selected at each step.
103.107 + /// The algorithm runs in O(n<sup>2</sup>) time using this
103.108 + /// selection rule.
103.109 + FARTHEST,
103.110 +
103.111 + /// An unvisited node whose insertion results in the least
103.112 + /// increase of the subtour's total cost is selected at each step.
103.113 + /// The algorithm runs in O(n<sup>3</sup>) time using this
103.114 + /// selection rule, but in most cases, it is almost as fast as
103.115 + /// with other rules.
103.116 + CHEAPEST,
103.117 +
103.118 + /// An unvisited node is selected randomly without any evaluation
103.119 + /// at each step.
103.120 + /// The global \ref rnd "random number generator instance" is used.
103.121 + /// You can seed it before executing the algorithm, if you
103.122 + /// would like to.
103.123 + /// The algorithm runs in O(n<sup>2</sup>) time using this
103.124 + /// selection rule.
103.125 + RANDOM
103.126 + };
103.127 +
103.128 + public:
103.129 +
103.130 + /// \brief Constructor
103.131 + ///
103.132 + /// Constructor.
103.133 + /// \param gr The \ref FullGraph "full graph" the algorithm runs on.
103.134 + /// \param cost The cost map.
103.135 + InsertionTsp(const FullGraph &gr, const CostMap &cost)
103.136 + : _gr(gr), _cost(cost) {}
103.137 +
103.138 + /// \name Execution Control
103.139 + /// @{
103.140 +
103.141 + /// \brief Runs the algorithm.
103.142 + ///
103.143 + /// This function runs the algorithm.
103.144 + ///
103.145 + /// \param rule The node selection rule. For more information, see
103.146 + /// \ref SelectionRule.
103.147 + ///
103.148 + /// \return The total cost of the found tour.
103.149 + Cost run(SelectionRule rule = FARTHEST) {
103.150 + _tour.clear();
103.151 +
103.152 + if (_gr.nodeNum() == 0) return _sum = 0;
103.153 + else if (_gr.nodeNum() == 1) {
103.154 + _tour.push_back(_gr(0));
103.155 + return _sum = 0;
103.156 + }
103.157 +
103.158 + switch (rule) {
103.159 + case NEAREST:
103.160 + init(true);
103.161 + start<ComparingSelection<std::less<Cost> >,
103.162 + DefaultInsertion>();
103.163 + break;
103.164 + case FARTHEST:
103.165 + init(false);
103.166 + start<ComparingSelection<std::greater<Cost> >,
103.167 + DefaultInsertion>();
103.168 + break;
103.169 + case CHEAPEST:
103.170 + init(true);
103.171 + start<CheapestSelection, CheapestInsertion>();
103.172 + break;
103.173 + case RANDOM:
103.174 + init(true);
103.175 + start<RandomSelection, DefaultInsertion>();
103.176 + break;
103.177 + }
103.178 + return _sum;
103.179 + }
103.180 +
103.181 + /// @}
103.182 +
103.183 + /// \name Query Functions
103.184 + /// @{
103.185 +
103.186 + /// \brief The total cost of the found tour.
103.187 + ///
103.188 + /// This function returns the total cost of the found tour.
103.189 + ///
103.190 + /// \pre run() must be called before using this function.
103.191 + Cost tourCost() const {
103.192 + return _sum;
103.193 + }
103.194 +
103.195 + /// \brief Returns a const reference to the node sequence of the
103.196 + /// found tour.
103.197 + ///
103.198 + /// This function returns a const reference to a vector
103.199 + /// that stores the node sequence of the found tour.
103.200 + ///
103.201 + /// \pre run() must be called before using this function.
103.202 + const std::vector<Node>& tourNodes() const {
103.203 + return _tour;
103.204 + }
103.205 +
103.206 + /// \brief Gives back the node sequence of the found tour.
103.207 + ///
103.208 + /// This function copies the node sequence of the found tour into
103.209 + /// an STL container through the given output iterator. The
103.210 + /// <tt>value_type</tt> of the container must be <tt>FullGraph::Node</tt>.
103.211 + /// For example,
103.212 + /// \code
103.213 + /// std::vector<FullGraph::Node> nodes(countNodes(graph));
103.214 + /// tsp.tourNodes(nodes.begin());
103.215 + /// \endcode
103.216 + /// or
103.217 + /// \code
103.218 + /// std::list<FullGraph::Node> nodes;
103.219 + /// tsp.tourNodes(std::back_inserter(nodes));
103.220 + /// \endcode
103.221 + ///
103.222 + /// \pre run() must be called before using this function.
103.223 + template <typename Iterator>
103.224 + void tourNodes(Iterator out) const {
103.225 + std::copy(_tour.begin(), _tour.end(), out);
103.226 + }
103.227 +
103.228 + /// \brief Gives back the found tour as a path.
103.229 + ///
103.230 + /// This function copies the found tour as a list of arcs/edges into
103.231 + /// the given \ref lemon::concepts::Path "path structure".
103.232 + ///
103.233 + /// \pre run() must be called before using this function.
103.234 + template <typename Path>
103.235 + void tour(Path &path) const {
103.236 + path.clear();
103.237 + for (int i = 0; i < int(_tour.size()) - 1; ++i) {
103.238 + path.addBack(_gr.arc(_tour[i], _tour[i+1]));
103.239 + }
103.240 + if (int(_tour.size()) >= 2) {
103.241 + path.addBack(_gr.arc(_tour.back(), _tour.front()));
103.242 + }
103.243 + }
103.244 +
103.245 + /// @}
103.246 +
103.247 + private:
103.248 +
103.249 + // Initializes the algorithm
103.250 + void init(bool min) {
103.251 + Edge min_edge = min ? mapMin(_gr, _cost) : mapMax(_gr, _cost);
103.252 +
103.253 + _tour.clear();
103.254 + _tour.push_back(_gr.u(min_edge));
103.255 + _tour.push_back(_gr.v(min_edge));
103.256 +
103.257 + _notused.clear();
103.258 + for (NodeIt n(_gr); n!=INVALID; ++n) {
103.259 + if (n != _gr.u(min_edge) && n != _gr.v(min_edge)) {
103.260 + _notused.push_back(n);
103.261 + }
103.262 + }
103.263 +
103.264 + _sum = _cost[min_edge] * 2;
103.265 + }
103.266 +
103.267 + // Executes the algorithm
103.268 + template <class SelectionFunctor, class InsertionFunctor>
103.269 + void start() {
103.270 + SelectionFunctor selectNode(_gr, _cost, _tour, _notused);
103.271 + InsertionFunctor insertNode(_gr, _cost, _tour, _sum);
103.272 +
103.273 + for (int i=0; i<_gr.nodeNum()-2; ++i) {
103.274 + insertNode.insert(selectNode.select());
103.275 + }
103.276 +
103.277 + _sum = _cost[_gr.edge(_tour.back(), _tour.front())];
103.278 + for (int i = 0; i < int(_tour.size())-1; ++i) {
103.279 + _sum += _cost[_gr.edge(_tour[i], _tour[i+1])];
103.280 + }
103.281 + }
103.282 +
103.283 +
103.284 + // Implementation of the nearest and farthest selection rule
103.285 + template <typename Comparator>
103.286 + class ComparingSelection {
103.287 + public:
103.288 + ComparingSelection(const FullGraph &gr, const CostMap &cost,
103.289 + std::vector<Node> &tour, std::vector<Node> ¬used)
103.290 + : _gr(gr), _cost(cost), _tour(tour), _notused(notused),
103.291 + _dist(gr, 0), _compare()
103.292 + {
103.293 + // Compute initial distances for the unused nodes
103.294 + for (unsigned int i=0; i<_notused.size(); ++i) {
103.295 + Node u = _notused[i];
103.296 + Cost min_dist = _cost[_gr.edge(u, _tour[0])];
103.297 + for (unsigned int j=1; j<_tour.size(); ++j) {
103.298 + Cost curr = _cost[_gr.edge(u, _tour[j])];
103.299 + if (curr < min_dist) {
103.300 + min_dist = curr;
103.301 + }
103.302 + }
103.303 + _dist[u] = min_dist;
103.304 + }
103.305 + }
103.306 +
103.307 + Node select() {
103.308 +
103.309 + // Select an used node with minimum distance
103.310 + Cost ins_dist = 0;
103.311 + int ins_node = -1;
103.312 + for (unsigned int i=0; i<_notused.size(); ++i) {
103.313 + Cost curr = _dist[_notused[i]];
103.314 + if (_compare(curr, ins_dist) || ins_node == -1) {
103.315 + ins_dist = curr;
103.316 + ins_node = i;
103.317 + }
103.318 + }
103.319 +
103.320 + // Remove the selected node from the unused vector
103.321 + Node sn = _notused[ins_node];
103.322 + _notused[ins_node] = _notused.back();
103.323 + _notused.pop_back();
103.324 +
103.325 + // Update the distances of the remaining nodes
103.326 + for (unsigned int i=0; i<_notused.size(); ++i) {
103.327 + Node u = _notused[i];
103.328 + Cost nc = _cost[_gr.edge(sn, u)];
103.329 + if (nc < _dist[u]) {
103.330 + _dist[u] = nc;
103.331 + }
103.332 + }
103.333 +
103.334 + return sn;
103.335 + }
103.336 +
103.337 + private:
103.338 + const FullGraph &_gr;
103.339 + const CostMap &_cost;
103.340 + std::vector<Node> &_tour;
103.341 + std::vector<Node> &_notused;
103.342 + FullGraph::NodeMap<Cost> _dist;
103.343 + Comparator _compare;
103.344 + };
103.345 +
103.346 + // Implementation of the cheapest selection rule
103.347 + class CheapestSelection {
103.348 + private:
103.349 + Cost costDiff(Node u, Node v, Node w) const {
103.350 + return
103.351 + _cost[_gr.edge(u, w)] +
103.352 + _cost[_gr.edge(v, w)] -
103.353 + _cost[_gr.edge(u, v)];
103.354 + }
103.355 +
103.356 + public:
103.357 + CheapestSelection(const FullGraph &gr, const CostMap &cost,
103.358 + std::vector<Node> &tour, std::vector<Node> ¬used)
103.359 + : _gr(gr), _cost(cost), _tour(tour), _notused(notused),
103.360 + _ins_cost(gr, 0), _ins_pos(gr, -1)
103.361 + {
103.362 + // Compute insertion cost and position for the unused nodes
103.363 + for (unsigned int i=0; i<_notused.size(); ++i) {
103.364 + Node u = _notused[i];
103.365 + Cost min_cost = costDiff(_tour.back(), _tour.front(), u);
103.366 + int min_pos = 0;
103.367 + for (unsigned int j=1; j<_tour.size(); ++j) {
103.368 + Cost curr_cost = costDiff(_tour[j-1], _tour[j], u);
103.369 + if (curr_cost < min_cost) {
103.370 + min_cost = curr_cost;
103.371 + min_pos = j;
103.372 + }
103.373 + }
103.374 + _ins_cost[u] = min_cost;
103.375 + _ins_pos[u] = min_pos;
103.376 + }
103.377 + }
103.378 +
103.379 + Cost select() {
103.380 +
103.381 + // Select an used node with minimum insertion cost
103.382 + Cost min_cost = 0;
103.383 + int min_node = -1;
103.384 + for (unsigned int i=0; i<_notused.size(); ++i) {
103.385 + Cost curr_cost = _ins_cost[_notused[i]];
103.386 + if (curr_cost < min_cost || min_node == -1) {
103.387 + min_cost = curr_cost;
103.388 + min_node = i;
103.389 + }
103.390 + }
103.391 +
103.392 + // Remove the selected node from the unused vector
103.393 + Node sn = _notused[min_node];
103.394 + _notused[min_node] = _notused.back();
103.395 + _notused.pop_back();
103.396 +
103.397 + // Insert the selected node into the tour
103.398 + const int ipos = _ins_pos[sn];
103.399 + _tour.insert(_tour.begin() + ipos, sn);
103.400 +
103.401 + // Update the insertion cost and position of the remaining nodes
103.402 + for (unsigned int i=0; i<_notused.size(); ++i) {
103.403 + Node u = _notused[i];
103.404 + Cost curr_cost = _ins_cost[u];
103.405 + int curr_pos = _ins_pos[u];
103.406 +
103.407 + int ipos_prev = ipos == 0 ? _tour.size()-1 : ipos-1;
103.408 + int ipos_next = ipos == int(_tour.size())-1 ? 0 : ipos+1;
103.409 + Cost nc1 = costDiff(_tour[ipos_prev], _tour[ipos], u);
103.410 + Cost nc2 = costDiff(_tour[ipos], _tour[ipos_next], u);
103.411 +
103.412 + if (nc1 <= curr_cost || nc2 <= curr_cost) {
103.413 + // A new position is better than the old one
103.414 + if (nc1 <= nc2) {
103.415 + curr_cost = nc1;
103.416 + curr_pos = ipos;
103.417 + } else {
103.418 + curr_cost = nc2;
103.419 + curr_pos = ipos_next;
103.420 + }
103.421 + }
103.422 + else {
103.423 + if (curr_pos == ipos) {
103.424 + // The minimum should be found again
103.425 + curr_cost = costDiff(_tour.back(), _tour.front(), u);
103.426 + curr_pos = 0;
103.427 + for (unsigned int j=1; j<_tour.size(); ++j) {
103.428 + Cost tmp_cost = costDiff(_tour[j-1], _tour[j], u);
103.429 + if (tmp_cost < curr_cost) {
103.430 + curr_cost = tmp_cost;
103.431 + curr_pos = j;
103.432 + }
103.433 + }
103.434 + }
103.435 + else if (curr_pos > ipos) {
103.436 + ++curr_pos;
103.437 + }
103.438 + }
103.439 +
103.440 + _ins_cost[u] = curr_cost;
103.441 + _ins_pos[u] = curr_pos;
103.442 + }
103.443 +
103.444 + return min_cost;
103.445 + }
103.446 +
103.447 + private:
103.448 + const FullGraph &_gr;
103.449 + const CostMap &_cost;
103.450 + std::vector<Node> &_tour;
103.451 + std::vector<Node> &_notused;
103.452 + FullGraph::NodeMap<Cost> _ins_cost;
103.453 + FullGraph::NodeMap<int> _ins_pos;
103.454 + };
103.455 +
103.456 + // Implementation of the random selection rule
103.457 + class RandomSelection {
103.458 + public:
103.459 + RandomSelection(const FullGraph &, const CostMap &,
103.460 + std::vector<Node> &, std::vector<Node> ¬used)
103.461 + : _notused(notused) {}
103.462 +
103.463 + Node select() const {
103.464 + const int index = rnd[_notused.size()];
103.465 + Node n = _notused[index];
103.466 + _notused[index] = _notused.back();
103.467 + _notused.pop_back();
103.468 + return n;
103.469 + }
103.470 +
103.471 + private:
103.472 + std::vector<Node> &_notused;
103.473 + };
103.474 +
103.475 +
103.476 + // Implementation of the default insertion method
103.477 + class DefaultInsertion {
103.478 + private:
103.479 + Cost costDiff(Node u, Node v, Node w) const {
103.480 + return
103.481 + _cost[_gr.edge(u, w)] +
103.482 + _cost[_gr.edge(v, w)] -
103.483 + _cost[_gr.edge(u, v)];
103.484 + }
103.485 +
103.486 + public:
103.487 + DefaultInsertion(const FullGraph &gr, const CostMap &cost,
103.488 + std::vector<Node> &tour, Cost &total_cost) :
103.489 + _gr(gr), _cost(cost), _tour(tour), _total(total_cost) {}
103.490 +
103.491 + void insert(Node n) const {
103.492 + int min = 0;
103.493 + Cost min_val =
103.494 + costDiff(_tour.front(), _tour.back(), n);
103.495 +
103.496 + for (unsigned int i=1; i<_tour.size(); ++i) {
103.497 + Cost tmp = costDiff(_tour[i-1], _tour[i], n);
103.498 + if (tmp < min_val) {
103.499 + min = i;
103.500 + min_val = tmp;
103.501 + }
103.502 + }
103.503 +
103.504 + _tour.insert(_tour.begin()+min, n);
103.505 + _total += min_val;
103.506 + }
103.507 +
103.508 + private:
103.509 + const FullGraph &_gr;
103.510 + const CostMap &_cost;
103.511 + std::vector<Node> &_tour;
103.512 + Cost &_total;
103.513 + };
103.514 +
103.515 + // Implementation of a special insertion method for the cheapest
103.516 + // selection rule
103.517 + class CheapestInsertion {
103.518 + TEMPLATE_GRAPH_TYPEDEFS(FullGraph);
103.519 + public:
103.520 + CheapestInsertion(const FullGraph &, const CostMap &,
103.521 + std::vector<Node> &, Cost &total_cost) :
103.522 + _total(total_cost) {}
103.523 +
103.524 + void insert(Cost diff) const {
103.525 + _total += diff;
103.526 + }
103.527 +
103.528 + private:
103.529 + Cost &_total;
103.530 + };
103.531 +
103.532 + };
103.533 +
103.534 +}; // namespace lemon
103.535 +
103.536 +#endif
104.1 --- a/lemon/karp_mmc.h Mon Jul 16 16:21:40 2018 +0200
104.2 +++ b/lemon/karp_mmc.h Wed Oct 17 19:14:07 2018 +0200
104.3 @@ -2,7 +2,7 @@
104.4 *
104.5 * This file is a part of LEMON, a generic C++ optimization library.
104.6 *
104.7 - * Copyright (C) 2003-2010
104.8 + * Copyright (C) 2003-2013
104.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
104.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
104.11 *
104.12 @@ -98,8 +98,8 @@
104.13 ///
104.14 /// This class implements Karp's algorithm for finding a directed
104.15 /// cycle of minimum mean cost in a digraph
104.16 - /// \ref amo93networkflows, \ref dasdan98minmeancycle.
104.17 - /// It runs in time O(ne) and uses space O(n<sup>2</sup>+e).
104.18 + /// \cite karp78characterization, \cite dasdan98minmeancycle.
104.19 + /// It runs in time O(nm) and uses space O(n<sup>2</sup>+m).
104.20 ///
104.21 /// \tparam GR The type of the digraph the algorithm runs on.
104.22 /// \tparam CM The type of the cost map. The default
104.23 @@ -140,11 +140,11 @@
104.24 /// \brief The path type of the found cycles
104.25 ///
104.26 /// The path type of the found cycles.
104.27 - /// Using the \ref KarpMmcDefaultTraits "default traits class",
104.28 + /// Using the \ref lemon::KarpMmcDefaultTraits "default traits class",
104.29 /// it is \ref lemon::Path "Path<Digraph>".
104.30 typedef typename TR::Path Path;
104.31
104.32 - /// The \ref KarpMmcDefaultTraits "traits class" of the algorithm
104.33 + /// The \ref lemon::KarpMmcDefaultTraits "traits class" of the algorithm
104.34 typedef TR Traits;
104.35
104.36 private:
104.37 @@ -270,8 +270,8 @@
104.38 /// found cycle.
104.39 ///
104.40 /// If you don't call this function before calling \ref run() or
104.41 - /// \ref findCycleMean(), it will allocate a local \ref Path "path"
104.42 - /// structure. The destuctor deallocates this automatically
104.43 + /// \ref findCycleMean(), a local \ref Path "path" structure
104.44 + /// will be allocated. The destuctor deallocates this automatically
104.45 /// allocated object, of course.
104.46 ///
104.47 /// \note The algorithm calls only the \ref lemon::Path::addFront()
105.1 --- a/lemon/kruskal.h Mon Jul 16 16:21:40 2018 +0200
105.2 +++ b/lemon/kruskal.h Wed Oct 17 19:14:07 2018 +0200
105.3 @@ -2,7 +2,7 @@
105.4 *
105.5 * This file is a part of LEMON, a generic C++ optimization library.
105.6 *
105.7 - * Copyright (C) 2003-2009
105.8 + * Copyright (C) 2003-2013
105.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
105.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
105.11 *
105.12 @@ -30,9 +30,6 @@
105.13 ///\ingroup spantree
105.14 ///\file
105.15 ///\brief Kruskal's algorithm to compute a minimum cost spanning tree
105.16 -///
105.17 -///Kruskal's algorithm to compute a minimum cost spanning tree.
105.18 -///
105.19
105.20 namespace lemon {
105.21
106.1 --- a/lemon/lemon.pc.cmake Mon Jul 16 16:21:40 2018 +0200
106.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
106.3 @@ -1,10 +0,0 @@
106.4 -prefix=@CMAKE_INSTALL_PREFIX@
106.5 -exec_prefix=@CMAKE_INSTALL_PREFIX@/bin
106.6 -libdir=@CMAKE_INSTALL_PREFIX@/lib
106.7 -includedir=@CMAKE_INSTALL_PREFIX@/include
106.8 -
106.9 -Name: @PROJECT_NAME@
106.10 -Description: Library for Efficient Modeling and Optimization in Networks
106.11 -Version: @PROJECT_VERSION@
106.12 -Libs: -L${libdir} -lemon @GLPK_LIBS@ @CPLEX_LIBS@ @SOPLEX_LIBS@ @CLP_LIBS@ @CBC_LIBS@
106.13 -Cflags: -I${includedir}
107.1 --- a/lemon/lemon.pc.in Mon Jul 16 16:21:40 2018 +0200
107.2 +++ b/lemon/lemon.pc.in Wed Oct 17 19:14:07 2018 +0200
107.3 @@ -1,10 +1,10 @@
107.4 -prefix=@prefix@
107.5 -exec_prefix=@exec_prefix@
107.6 -libdir=@libdir@
107.7 -includedir=@includedir@
107.8 +prefix=@CMAKE_INSTALL_PREFIX@
107.9 +exec_prefix=@CMAKE_INSTALL_PREFIX@/bin
107.10 +libdir=@CMAKE_INSTALL_PREFIX@/lib
107.11 +includedir=@CMAKE_INSTALL_PREFIX@/include
107.12
107.13 -Name: @PACKAGE_NAME@
107.14 +Name: @PROJECT_NAME@
107.15 Description: Library for Efficient Modeling and Optimization in Networks
107.16 -Version: @PACKAGE_VERSION@
107.17 +Version: @PROJECT_VERSION@
107.18 Libs: -L${libdir} -lemon @GLPK_LIBS@ @CPLEX_LIBS@ @SOPLEX_LIBS@ @CLP_LIBS@ @CBC_LIBS@
107.19 Cflags: -I${includedir}
108.1 --- a/lemon/lgf_reader.h Mon Jul 16 16:21:40 2018 +0200
108.2 +++ b/lemon/lgf_reader.h Wed Oct 17 19:14:07 2018 +0200
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-2011
108.8 + * Copyright (C) 2003-2013
108.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
108.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
108.11 *
108.12 @@ -154,16 +154,16 @@
108.13 }
108.14 };
108.15
108.16 - template <typename Value>
108.17 + template <typename Value,
108.18 + typename Map = std::map<std::string, Value> >
108.19 struct MapLookUpConverter {
108.20 - const std::map<std::string, Value>& _map;
108.21 -
108.22 - MapLookUpConverter(const std::map<std::string, Value>& map)
108.23 + const Map& _map;
108.24 +
108.25 + MapLookUpConverter(const Map& map)
108.26 : _map(map) {}
108.27
108.28 Value operator()(const std::string& str) {
108.29 - typename std::map<std::string, Value>::const_iterator it =
108.30 - _map.find(str);
108.31 + typename Map::const_iterator it = _map.find(str);
108.32 if (it == _map.end()) {
108.33 std::ostringstream msg;
108.34 msg << "Item not found: " << str;
108.35 @@ -173,6 +173,39 @@
108.36 }
108.37 };
108.38
108.39 + template <typename Value,
108.40 + typename Map1 = std::map<std::string, Value>,
108.41 + typename Map2 = std::map<std::string, Value> >
108.42 + struct DoubleMapLookUpConverter {
108.43 + const Map1& _map1;
108.44 + const Map2& _map2;
108.45 +
108.46 + DoubleMapLookUpConverter(const Map1& map1, const Map2& map2)
108.47 + : _map1(map1), _map2(map2) {}
108.48 +
108.49 + Value operator()(const std::string& str) {
108.50 + typename Map1::const_iterator it1 = _map1.find(str);
108.51 + typename Map2::const_iterator it2 = _map2.find(str);
108.52 + if (it1 == _map1.end()) {
108.53 + if (it2 == _map2.end()) {
108.54 + std::ostringstream msg;
108.55 + msg << "Item not found: " << str;
108.56 + throw FormatError(msg.str());
108.57 + } else {
108.58 + return it2->second;
108.59 + }
108.60 + } else {
108.61 + if (it2 == _map2.end()) {
108.62 + return it1->second;
108.63 + } else {
108.64 + std::ostringstream msg;
108.65 + msg << "Item is ambigous: " << str;
108.66 + throw FormatError(msg.str());
108.67 + }
108.68 + }
108.69 + }
108.70 + };
108.71 +
108.72 template <typename GR>
108.73 struct GraphArcLookUpConverter {
108.74 const GR& _graph;
108.75 @@ -1197,9 +1230,10 @@
108.76
108.77 /// \ingroup lemon_io
108.78 ///
108.79 - /// \brief Return a \ref DigraphReader class
108.80 + /// \brief Return a \ref lemon::DigraphReader "DigraphReader" class
108.81 ///
108.82 - /// This function just returns a \ref DigraphReader class.
108.83 + /// This function just returns a \ref lemon::DigraphReader
108.84 + /// "DigraphReader" class.
108.85 ///
108.86 /// With this function a digraph can be read from an
108.87 /// \ref lgf-format "LGF" file or input stream with several maps and
108.88 @@ -1219,9 +1253,10 @@
108.89 /// run();
108.90 ///\endcode
108.91 ///
108.92 - /// For a complete documentation, please see the \ref DigraphReader
108.93 + /// For a complete documentation, please see the
108.94 + /// \ref lemon::DigraphReader "DigraphReader"
108.95 /// class documentation.
108.96 - /// \warning Don't forget to put the \ref DigraphReader::run() "run()"
108.97 + /// \warning Don't forget to put the \ref lemon::DigraphReader::run() "run()"
108.98 /// to the end of the parameter list.
108.99 /// \relates DigraphReader
108.100 /// \sa digraphReader(TDGR& digraph, const std::string& fn)
108.101 @@ -2075,9 +2110,9 @@
108.102
108.103 /// \ingroup lemon_io
108.104 ///
108.105 - /// \brief Return a \ref GraphReader class
108.106 + /// \brief Return a \ref lemon::GraphReader "GraphReader" class
108.107 ///
108.108 - /// This function just returns a \ref GraphReader class.
108.109 + /// This function just returns a \ref lemon::GraphReader "GraphReader" class.
108.110 ///
108.111 /// With this function a graph can be read from an
108.112 /// \ref lgf-format "LGF" file or input stream with several maps and
108.113 @@ -2093,9 +2128,10 @@
108.114 /// run();
108.115 ///\endcode
108.116 ///
108.117 - /// For a complete documentation, please see the \ref GraphReader
108.118 + /// For a complete documentation, please see the
108.119 + /// \ref lemon::GraphReader "GraphReader"
108.120 /// class documentation.
108.121 - /// \warning Don't forget to put the \ref GraphReader::run() "run()"
108.122 + /// \warning Don't forget to put the \ref lemon::GraphReader::run() "run()"
108.123 /// to the end of the parameter list.
108.124 /// \relates GraphReader
108.125 /// \sa graphReader(TGR& graph, const std::string& fn)
108.126 @@ -2128,6 +2164,1074 @@
108.127 return tmp;
108.128 }
108.129
108.130 + template <typename BGR>
108.131 + class BpGraphReader;
108.132 +
108.133 + template <typename TBGR>
108.134 + BpGraphReader<TBGR> bpGraphReader(TBGR& graph, std::istream& is = std::cin);
108.135 + template <typename TBGR>
108.136 + BpGraphReader<TBGR> bpGraphReader(TBGR& graph, const std::string& fn);
108.137 + template <typename TBGR>
108.138 + BpGraphReader<TBGR> bpGraphReader(TBGR& graph, const char *fn);
108.139 +
108.140 + /// \ingroup lemon_io
108.141 + ///
108.142 + /// \brief \ref lgf-format "LGF" reader for bipartite graphs
108.143 + ///
108.144 + /// This utility reads an \ref lgf-format "LGF" file.
108.145 + ///
108.146 + /// It can be used almost the same way as \c GraphReader, but it
108.147 + /// reads the red and blue nodes from separate sections, and these
108.148 + /// sections can contain different set of maps.
108.149 + ///
108.150 + /// The red and blue node maps are read from the corresponding
108.151 + /// sections. If a map is defined with the same name in both of
108.152 + /// these sections, then it can be read as a node map.
108.153 + template <typename BGR>
108.154 + class BpGraphReader {
108.155 + public:
108.156 +
108.157 + typedef BGR Graph;
108.158 +
108.159 + private:
108.160 +
108.161 + TEMPLATE_BPGRAPH_TYPEDEFS(BGR);
108.162 +
108.163 + std::istream* _is;
108.164 + bool local_is;
108.165 + std::string _filename;
108.166 +
108.167 + BGR& _graph;
108.168 +
108.169 + std::string _nodes_caption;
108.170 + std::string _edges_caption;
108.171 + std::string _attributes_caption;
108.172 +
108.173 + typedef std::map<std::string, RedNode> RedNodeIndex;
108.174 + RedNodeIndex _red_node_index;
108.175 + typedef std::map<std::string, BlueNode> BlueNodeIndex;
108.176 + BlueNodeIndex _blue_node_index;
108.177 + typedef std::map<std::string, Edge> EdgeIndex;
108.178 + EdgeIndex _edge_index;
108.179 +
108.180 + typedef std::vector<std::pair<std::string,
108.181 + _reader_bits::MapStorageBase<RedNode>*> > RedNodeMaps;
108.182 + RedNodeMaps _red_node_maps;
108.183 + typedef std::vector<std::pair<std::string,
108.184 + _reader_bits::MapStorageBase<BlueNode>*> > BlueNodeMaps;
108.185 + BlueNodeMaps _blue_node_maps;
108.186 +
108.187 + typedef std::vector<std::pair<std::string,
108.188 + _reader_bits::MapStorageBase<Edge>*> > EdgeMaps;
108.189 + EdgeMaps _edge_maps;
108.190 +
108.191 + typedef std::multimap<std::string, _reader_bits::ValueStorageBase*>
108.192 + Attributes;
108.193 + Attributes _attributes;
108.194 +
108.195 + bool _use_nodes;
108.196 + bool _use_edges;
108.197 +
108.198 + bool _skip_nodes;
108.199 + bool _skip_edges;
108.200 +
108.201 + int line_num;
108.202 + std::istringstream line;
108.203 +
108.204 + public:
108.205 +
108.206 + /// \brief Constructor
108.207 + ///
108.208 + /// Construct an undirected graph reader, which reads from the given
108.209 + /// input stream.
108.210 + BpGraphReader(BGR& graph, std::istream& is = std::cin)
108.211 + : _is(&is), local_is(false), _graph(graph),
108.212 + _use_nodes(false), _use_edges(false),
108.213 + _skip_nodes(false), _skip_edges(false) {}
108.214 +
108.215 + /// \brief Constructor
108.216 + ///
108.217 + /// Construct an undirected graph reader, which reads from the given
108.218 + /// file.
108.219 + BpGraphReader(BGR& graph, const std::string& fn)
108.220 + : _is(new std::ifstream(fn.c_str())), local_is(true),
108.221 + _filename(fn), _graph(graph),
108.222 + _use_nodes(false), _use_edges(false),
108.223 + _skip_nodes(false), _skip_edges(false) {
108.224 + if (!(*_is)) {
108.225 + delete _is;
108.226 + throw IoError("Cannot open file", fn);
108.227 + }
108.228 + }
108.229 +
108.230 + /// \brief Constructor
108.231 + ///
108.232 + /// Construct an undirected graph reader, which reads from the given
108.233 + /// file.
108.234 + BpGraphReader(BGR& graph, const char* fn)
108.235 + : _is(new std::ifstream(fn)), local_is(true),
108.236 + _filename(fn), _graph(graph),
108.237 + _use_nodes(false), _use_edges(false),
108.238 + _skip_nodes(false), _skip_edges(false) {
108.239 + if (!(*_is)) {
108.240 + delete _is;
108.241 + throw IoError("Cannot open file", fn);
108.242 + }
108.243 + }
108.244 +
108.245 + /// \brief Destructor
108.246 + ~BpGraphReader() {
108.247 + for (typename RedNodeMaps::iterator it = _red_node_maps.begin();
108.248 + it != _red_node_maps.end(); ++it) {
108.249 + delete it->second;
108.250 + }
108.251 +
108.252 + for (typename BlueNodeMaps::iterator it = _blue_node_maps.begin();
108.253 + it != _blue_node_maps.end(); ++it) {
108.254 + delete it->second;
108.255 + }
108.256 +
108.257 + for (typename EdgeMaps::iterator it = _edge_maps.begin();
108.258 + it != _edge_maps.end(); ++it) {
108.259 + delete it->second;
108.260 + }
108.261 +
108.262 + for (typename Attributes::iterator it = _attributes.begin();
108.263 + it != _attributes.end(); ++it) {
108.264 + delete it->second;
108.265 + }
108.266 +
108.267 + if (local_is) {
108.268 + delete _is;
108.269 + }
108.270 +
108.271 + }
108.272 +
108.273 + private:
108.274 + template <typename TBGR>
108.275 + friend BpGraphReader<TBGR> bpGraphReader(TBGR& graph, std::istream& is);
108.276 + template <typename TBGR>
108.277 + friend BpGraphReader<TBGR> bpGraphReader(TBGR& graph,
108.278 + const std::string& fn);
108.279 + template <typename TBGR>
108.280 + friend BpGraphReader<TBGR> bpGraphReader(TBGR& graph, const char *fn);
108.281 +
108.282 + BpGraphReader(BpGraphReader& other)
108.283 + : _is(other._is), local_is(other.local_is), _graph(other._graph),
108.284 + _use_nodes(other._use_nodes), _use_edges(other._use_edges),
108.285 + _skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
108.286 +
108.287 + other._is = 0;
108.288 + other.local_is = false;
108.289 +
108.290 + _red_node_index.swap(other._red_node_index);
108.291 + _blue_node_index.swap(other._blue_node_index);
108.292 + _edge_index.swap(other._edge_index);
108.293 +
108.294 + _red_node_maps.swap(other._red_node_maps);
108.295 + _blue_node_maps.swap(other._blue_node_maps);
108.296 + _edge_maps.swap(other._edge_maps);
108.297 + _attributes.swap(other._attributes);
108.298 +
108.299 + _nodes_caption = other._nodes_caption;
108.300 + _edges_caption = other._edges_caption;
108.301 + _attributes_caption = other._attributes_caption;
108.302 +
108.303 + }
108.304 +
108.305 + BpGraphReader& operator=(const BpGraphReader&);
108.306 +
108.307 + public:
108.308 +
108.309 + /// \name Reading Rules
108.310 + /// @{
108.311 +
108.312 + /// \brief Node map reading rule
108.313 + ///
108.314 + /// Add a node map reading rule to the reader.
108.315 + template <typename Map>
108.316 + BpGraphReader& nodeMap(const std::string& caption, Map& map) {
108.317 + checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
108.318 + _reader_bits::MapStorageBase<RedNode>* red_storage =
108.319 + new _reader_bits::MapStorage<RedNode, Map>(map);
108.320 + _red_node_maps.push_back(std::make_pair(caption, red_storage));
108.321 + _reader_bits::MapStorageBase<BlueNode>* blue_storage =
108.322 + new _reader_bits::MapStorage<BlueNode, Map>(map);
108.323 + _blue_node_maps.push_back(std::make_pair(caption, blue_storage));
108.324 + return *this;
108.325 + }
108.326 +
108.327 + /// \brief Node map reading rule
108.328 + ///
108.329 + /// Add a node map reading rule with specialized converter to the
108.330 + /// reader.
108.331 + template <typename Map, typename Converter>
108.332 + BpGraphReader& nodeMap(const std::string& caption, Map& map,
108.333 + const Converter& converter = Converter()) {
108.334 + checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
108.335 + _reader_bits::MapStorageBase<RedNode>* red_storage =
108.336 + new _reader_bits::MapStorage<RedNode, Map, Converter>(map, converter);
108.337 + _red_node_maps.push_back(std::make_pair(caption, red_storage));
108.338 + _reader_bits::MapStorageBase<BlueNode>* blue_storage =
108.339 + new _reader_bits::MapStorage<BlueNode, Map, Converter>(map, converter);
108.340 + _blue_node_maps.push_back(std::make_pair(caption, blue_storage));
108.341 + return *this;
108.342 + }
108.343 +
108.344 + /// Add a red node map reading rule to the reader.
108.345 + template <typename Map>
108.346 + BpGraphReader& redNodeMap(const std::string& caption, Map& map) {
108.347 + checkConcept<concepts::WriteMap<RedNode, typename Map::Value>, Map>();
108.348 + _reader_bits::MapStorageBase<RedNode>* storage =
108.349 + new _reader_bits::MapStorage<RedNode, Map>(map);
108.350 + _red_node_maps.push_back(std::make_pair(caption, storage));
108.351 + return *this;
108.352 + }
108.353 +
108.354 + /// \brief Red node map reading rule
108.355 + ///
108.356 + /// Add a red node map node reading rule with specialized converter to
108.357 + /// the reader.
108.358 + template <typename Map, typename Converter>
108.359 + BpGraphReader& redNodeMap(const std::string& caption, Map& map,
108.360 + const Converter& converter = Converter()) {
108.361 + checkConcept<concepts::WriteMap<RedNode, typename Map::Value>, Map>();
108.362 + _reader_bits::MapStorageBase<RedNode>* storage =
108.363 + new _reader_bits::MapStorage<RedNode, Map, Converter>(map, converter);
108.364 + _red_node_maps.push_back(std::make_pair(caption, storage));
108.365 + return *this;
108.366 + }
108.367 +
108.368 + /// Add a blue node map reading rule to the reader.
108.369 + template <typename Map>
108.370 + BpGraphReader& blueNodeMap(const std::string& caption, Map& map) {
108.371 + checkConcept<concepts::WriteMap<BlueNode, typename Map::Value>, Map>();
108.372 + _reader_bits::MapStorageBase<BlueNode>* storage =
108.373 + new _reader_bits::MapStorage<BlueNode, Map>(map);
108.374 + _blue_node_maps.push_back(std::make_pair(caption, storage));
108.375 + return *this;
108.376 + }
108.377 +
108.378 + /// \brief Blue node map reading rule
108.379 + ///
108.380 + /// Add a blue node map reading rule with specialized converter to
108.381 + /// the reader.
108.382 + template <typename Map, typename Converter>
108.383 + BpGraphReader& blueNodeMap(const std::string& caption, Map& map,
108.384 + const Converter& converter = Converter()) {
108.385 + checkConcept<concepts::WriteMap<BlueNode, typename Map::Value>, Map>();
108.386 + _reader_bits::MapStorageBase<BlueNode>* storage =
108.387 + new _reader_bits::MapStorage<BlueNode, Map, Converter>(map, converter);
108.388 + _blue_node_maps.push_back(std::make_pair(caption, storage));
108.389 + return *this;
108.390 + }
108.391 +
108.392 + /// \brief Edge map reading rule
108.393 + ///
108.394 + /// Add an edge map reading rule to the reader.
108.395 + template <typename Map>
108.396 + BpGraphReader& edgeMap(const std::string& caption, Map& map) {
108.397 + checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
108.398 + _reader_bits::MapStorageBase<Edge>* storage =
108.399 + new _reader_bits::MapStorage<Edge, Map>(map);
108.400 + _edge_maps.push_back(std::make_pair(caption, storage));
108.401 + return *this;
108.402 + }
108.403 +
108.404 + /// \brief Edge map reading rule
108.405 + ///
108.406 + /// Add an edge map reading rule with specialized converter to the
108.407 + /// reader.
108.408 + template <typename Map, typename Converter>
108.409 + BpGraphReader& edgeMap(const std::string& caption, Map& map,
108.410 + const Converter& converter = Converter()) {
108.411 + checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
108.412 + _reader_bits::MapStorageBase<Edge>* storage =
108.413 + new _reader_bits::MapStorage<Edge, Map, Converter>(map, converter);
108.414 + _edge_maps.push_back(std::make_pair(caption, storage));
108.415 + return *this;
108.416 + }
108.417 +
108.418 + /// \brief Arc map reading rule
108.419 + ///
108.420 + /// Add an arc map reading rule to the reader.
108.421 + template <typename Map>
108.422 + BpGraphReader& arcMap(const std::string& caption, Map& map) {
108.423 + checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
108.424 + _reader_bits::MapStorageBase<Edge>* forward_storage =
108.425 + new _reader_bits::GraphArcMapStorage<Graph, true, Map>(_graph, map);
108.426 + _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
108.427 + _reader_bits::MapStorageBase<Edge>* backward_storage =
108.428 + new _reader_bits::GraphArcMapStorage<BGR, false, Map>(_graph, map);
108.429 + _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
108.430 + return *this;
108.431 + }
108.432 +
108.433 + /// \brief Arc map reading rule
108.434 + ///
108.435 + /// Add an arc map reading rule with specialized converter to the
108.436 + /// reader.
108.437 + template <typename Map, typename Converter>
108.438 + BpGraphReader& arcMap(const std::string& caption, Map& map,
108.439 + const Converter& converter = Converter()) {
108.440 + checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
108.441 + _reader_bits::MapStorageBase<Edge>* forward_storage =
108.442 + new _reader_bits::GraphArcMapStorage<BGR, true, Map, Converter>
108.443 + (_graph, map, converter);
108.444 + _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
108.445 + _reader_bits::MapStorageBase<Edge>* backward_storage =
108.446 + new _reader_bits::GraphArcMapStorage<BGR, false, Map, Converter>
108.447 + (_graph, map, converter);
108.448 + _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
108.449 + return *this;
108.450 + }
108.451 +
108.452 + /// \brief Attribute reading rule
108.453 + ///
108.454 + /// Add an attribute reading rule to the reader.
108.455 + template <typename Value>
108.456 + BpGraphReader& attribute(const std::string& caption, Value& value) {
108.457 + _reader_bits::ValueStorageBase* storage =
108.458 + new _reader_bits::ValueStorage<Value>(value);
108.459 + _attributes.insert(std::make_pair(caption, storage));
108.460 + return *this;
108.461 + }
108.462 +
108.463 + /// \brief Attribute reading rule
108.464 + ///
108.465 + /// Add an attribute reading rule with specialized converter to the
108.466 + /// reader.
108.467 + template <typename Value, typename Converter>
108.468 + BpGraphReader& attribute(const std::string& caption, Value& value,
108.469 + const Converter& converter = Converter()) {
108.470 + _reader_bits::ValueStorageBase* storage =
108.471 + new _reader_bits::ValueStorage<Value, Converter>(value, converter);
108.472 + _attributes.insert(std::make_pair(caption, storage));
108.473 + return *this;
108.474 + }
108.475 +
108.476 + /// \brief Node reading rule
108.477 + ///
108.478 + /// Add a node reading rule to reader.
108.479 + BpGraphReader& node(const std::string& caption, Node& node) {
108.480 + typedef _reader_bits::DoubleMapLookUpConverter<
108.481 + Node, RedNodeIndex, BlueNodeIndex> Converter;
108.482 + Converter converter(_red_node_index, _blue_node_index);
108.483 + _reader_bits::ValueStorageBase* storage =
108.484 + new _reader_bits::ValueStorage<Node, Converter>(node, converter);
108.485 + _attributes.insert(std::make_pair(caption, storage));
108.486 + return *this;
108.487 + }
108.488 +
108.489 + /// \brief Red node reading rule
108.490 + ///
108.491 + /// Add a red node reading rule to reader.
108.492 + BpGraphReader& redNode(const std::string& caption, RedNode& node) {
108.493 + typedef _reader_bits::MapLookUpConverter<RedNode> Converter;
108.494 + Converter converter(_red_node_index);
108.495 + _reader_bits::ValueStorageBase* storage =
108.496 + new _reader_bits::ValueStorage<RedNode, Converter>(node, converter);
108.497 + _attributes.insert(std::make_pair(caption, storage));
108.498 + return *this;
108.499 + }
108.500 +
108.501 + /// \brief Blue node reading rule
108.502 + ///
108.503 + /// Add a blue node reading rule to reader.
108.504 + BpGraphReader& blueNode(const std::string& caption, BlueNode& node) {
108.505 + typedef _reader_bits::MapLookUpConverter<BlueNode> Converter;
108.506 + Converter converter(_blue_node_index);
108.507 + _reader_bits::ValueStorageBase* storage =
108.508 + new _reader_bits::ValueStorage<BlueNode, Converter>(node, converter);
108.509 + _attributes.insert(std::make_pair(caption, storage));
108.510 + return *this;
108.511 + }
108.512 +
108.513 + /// \brief Edge reading rule
108.514 + ///
108.515 + /// Add an edge reading rule to reader.
108.516 + BpGraphReader& edge(const std::string& caption, Edge& edge) {
108.517 + typedef _reader_bits::MapLookUpConverter<Edge> Converter;
108.518 + Converter converter(_edge_index);
108.519 + _reader_bits::ValueStorageBase* storage =
108.520 + new _reader_bits::ValueStorage<Edge, Converter>(edge, converter);
108.521 + _attributes.insert(std::make_pair(caption, storage));
108.522 + return *this;
108.523 + }
108.524 +
108.525 + /// \brief Arc reading rule
108.526 + ///
108.527 + /// Add an arc reading rule to reader.
108.528 + BpGraphReader& arc(const std::string& caption, Arc& arc) {
108.529 + typedef _reader_bits::GraphArcLookUpConverter<BGR> Converter;
108.530 + Converter converter(_graph, _edge_index);
108.531 + _reader_bits::ValueStorageBase* storage =
108.532 + new _reader_bits::ValueStorage<Arc, Converter>(arc, converter);
108.533 + _attributes.insert(std::make_pair(caption, storage));
108.534 + return *this;
108.535 + }
108.536 +
108.537 + /// @}
108.538 +
108.539 + /// \name Select Section by Name
108.540 + /// @{
108.541 +
108.542 + /// \brief Set \c \@nodes section to be read
108.543 + ///
108.544 + /// Set \c \@nodes section to be read.
108.545 + BpGraphReader& nodes(const std::string& caption) {
108.546 + _nodes_caption = caption;
108.547 + return *this;
108.548 + }
108.549 +
108.550 + /// \brief Set \c \@edges section to be read
108.551 + ///
108.552 + /// Set \c \@edges section to be read.
108.553 + BpGraphReader& edges(const std::string& caption) {
108.554 + _edges_caption = caption;
108.555 + return *this;
108.556 + }
108.557 +
108.558 + /// \brief Set \c \@attributes section to be read
108.559 + ///
108.560 + /// Set \c \@attributes section to be read.
108.561 + BpGraphReader& attributes(const std::string& caption) {
108.562 + _attributes_caption = caption;
108.563 + return *this;
108.564 + }
108.565 +
108.566 + /// @}
108.567 +
108.568 + /// \name Using Previously Constructed Node or Edge Set
108.569 + /// @{
108.570 +
108.571 + /// \brief Use previously constructed node set
108.572 + ///
108.573 + /// Use previously constructed node set, and specify the node
108.574 + /// label map.
108.575 + template <typename Map>
108.576 + BpGraphReader& useNodes(const Map& map) {
108.577 + checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
108.578 + LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
108.579 + _use_nodes = true;
108.580 + _writer_bits::DefaultConverter<typename Map::Value> converter;
108.581 + for (RedNodeIt n(_graph); n != INVALID; ++n) {
108.582 + _red_node_index.insert(std::make_pair(converter(map[n]), n));
108.583 + }
108.584 + for (BlueNodeIt n(_graph); n != INVALID; ++n) {
108.585 + _blue_node_index.insert(std::make_pair(converter(map[n]), n));
108.586 + }
108.587 + return *this;
108.588 + }
108.589 +
108.590 + /// \brief Use previously constructed node set
108.591 + ///
108.592 + /// Use previously constructed node set, and specify the node
108.593 + /// label map and a functor which converts the label map values to
108.594 + /// \c std::string.
108.595 + template <typename Map, typename Converter>
108.596 + BpGraphReader& useNodes(const Map& map,
108.597 + const Converter& converter = Converter()) {
108.598 + checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
108.599 + LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
108.600 + _use_nodes = true;
108.601 + for (RedNodeIt n(_graph); n != INVALID; ++n) {
108.602 + _red_node_index.insert(std::make_pair(converter(map[n]), n));
108.603 + }
108.604 + for (BlueNodeIt n(_graph); n != INVALID; ++n) {
108.605 + _blue_node_index.insert(std::make_pair(converter(map[n]), n));
108.606 + }
108.607 + return *this;
108.608 + }
108.609 +
108.610 + /// \brief Use previously constructed edge set
108.611 + ///
108.612 + /// Use previously constructed edge set, and specify the edge
108.613 + /// label map.
108.614 + template <typename Map>
108.615 + BpGraphReader& useEdges(const Map& map) {
108.616 + checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
108.617 + LEMON_ASSERT(!_use_edges, "Multiple usage of useEdges() member");
108.618 + _use_edges = true;
108.619 + _writer_bits::DefaultConverter<typename Map::Value> converter;
108.620 + for (EdgeIt a(_graph); a != INVALID; ++a) {
108.621 + _edge_index.insert(std::make_pair(converter(map[a]), a));
108.622 + }
108.623 + return *this;
108.624 + }
108.625 +
108.626 + /// \brief Use previously constructed edge set
108.627 + ///
108.628 + /// Use previously constructed edge set, and specify the edge
108.629 + /// label map and a functor which converts the label map values to
108.630 + /// \c std::string.
108.631 + template <typename Map, typename Converter>
108.632 + BpGraphReader& useEdges(const Map& map,
108.633 + const Converter& converter = Converter()) {
108.634 + checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
108.635 + LEMON_ASSERT(!_use_edges, "Multiple usage of useEdges() member");
108.636 + _use_edges = true;
108.637 + for (EdgeIt a(_graph); a != INVALID; ++a) {
108.638 + _edge_index.insert(std::make_pair(converter(map[a]), a));
108.639 + }
108.640 + return *this;
108.641 + }
108.642 +
108.643 + /// \brief Skip the reading of node section
108.644 + ///
108.645 + /// Omit the reading of the node section. This implies that each node
108.646 + /// map reading rule will be abandoned, and the nodes of the graph
108.647 + /// will not be constructed, which usually cause that the edge set
108.648 + /// could not be read due to lack of node name
108.649 + /// could not be read due to lack of node name resolving.
108.650 + /// Therefore \c skipEdges() function should also be used, or
108.651 + /// \c useNodes() should be used to specify the label of the nodes.
108.652 + BpGraphReader& skipNodes() {
108.653 + LEMON_ASSERT(!_skip_nodes, "Skip nodes already set");
108.654 + _skip_nodes = true;
108.655 + return *this;
108.656 + }
108.657 +
108.658 + /// \brief Skip the reading of edge section
108.659 + ///
108.660 + /// Omit the reading of the edge section. This implies that each edge
108.661 + /// map reading rule will be abandoned, and the edges of the graph
108.662 + /// will not be constructed.
108.663 + BpGraphReader& skipEdges() {
108.664 + LEMON_ASSERT(!_skip_edges, "Skip edges already set");
108.665 + _skip_edges = true;
108.666 + return *this;
108.667 + }
108.668 +
108.669 + /// @}
108.670 +
108.671 + private:
108.672 +
108.673 + bool readLine() {
108.674 + std::string str;
108.675 + while(++line_num, std::getline(*_is, str)) {
108.676 + line.clear(); line.str(str);
108.677 + char c;
108.678 + if (line >> std::ws >> c && c != '#') {
108.679 + line.putback(c);
108.680 + return true;
108.681 + }
108.682 + }
108.683 + return false;
108.684 + }
108.685 +
108.686 + bool readSuccess() {
108.687 + return static_cast<bool>(*_is);
108.688 + }
108.689 +
108.690 + void skipSection() {
108.691 + char c;
108.692 + while (readSuccess() && line >> c && c != '@') {
108.693 + readLine();
108.694 + }
108.695 + if (readSuccess()) {
108.696 + line.putback(c);
108.697 + }
108.698 + }
108.699 +
108.700 + void readRedNodes() {
108.701 +
108.702 + std::vector<int> map_index(_red_node_maps.size());
108.703 + int map_num, label_index;
108.704 +
108.705 + char c;
108.706 + if (!readLine() || !(line >> c) || c == '@') {
108.707 + if (readSuccess() && line) line.putback(c);
108.708 + if (!_red_node_maps.empty())
108.709 + throw FormatError("Cannot find map names");
108.710 + return;
108.711 + }
108.712 + line.putback(c);
108.713 +
108.714 + {
108.715 + std::map<std::string, int> maps;
108.716 +
108.717 + std::string map;
108.718 + int index = 0;
108.719 + while (_reader_bits::readToken(line, map)) {
108.720 + if (maps.find(map) != maps.end()) {
108.721 + std::ostringstream msg;
108.722 + msg << "Multiple occurence of red node map: " << map;
108.723 + throw FormatError(msg.str());
108.724 + }
108.725 + maps.insert(std::make_pair(map, index));
108.726 + ++index;
108.727 + }
108.728 +
108.729 + for (int i = 0; i < static_cast<int>(_red_node_maps.size()); ++i) {
108.730 + std::map<std::string, int>::iterator jt =
108.731 + maps.find(_red_node_maps[i].first);
108.732 + if (jt == maps.end()) {
108.733 + std::ostringstream msg;
108.734 + msg << "Map not found: " << _red_node_maps[i].first;
108.735 + throw FormatError(msg.str());
108.736 + }
108.737 + map_index[i] = jt->second;
108.738 + }
108.739 +
108.740 + {
108.741 + std::map<std::string, int>::iterator jt = maps.find("label");
108.742 + if (jt != maps.end()) {
108.743 + label_index = jt->second;
108.744 + } else {
108.745 + label_index = -1;
108.746 + }
108.747 + }
108.748 + map_num = maps.size();
108.749 + }
108.750 +
108.751 + while (readLine() && line >> c && c != '@') {
108.752 + line.putback(c);
108.753 +
108.754 + std::vector<std::string> tokens(map_num);
108.755 + for (int i = 0; i < map_num; ++i) {
108.756 + if (!_reader_bits::readToken(line, tokens[i])) {
108.757 + std::ostringstream msg;
108.758 + msg << "Column not found (" << i + 1 << ")";
108.759 + throw FormatError(msg.str());
108.760 + }
108.761 + }
108.762 + if (line >> std::ws >> c)
108.763 + throw FormatError("Extra character at the end of line");
108.764 +
108.765 + RedNode n;
108.766 + if (!_use_nodes) {
108.767 + n = _graph.addRedNode();
108.768 + if (label_index != -1)
108.769 + _red_node_index.insert(std::make_pair(tokens[label_index], n));
108.770 + } else {
108.771 + if (label_index == -1)
108.772 + throw FormatError("Label map not found");
108.773 + typename std::map<std::string, RedNode>::iterator it =
108.774 + _red_node_index.find(tokens[label_index]);
108.775 + if (it == _red_node_index.end()) {
108.776 + std::ostringstream msg;
108.777 + msg << "Node with label not found: " << tokens[label_index];
108.778 + throw FormatError(msg.str());
108.779 + }
108.780 + n = it->second;
108.781 + }
108.782 +
108.783 + for (int i = 0; i < static_cast<int>(_red_node_maps.size()); ++i) {
108.784 + _red_node_maps[i].second->set(n, tokens[map_index[i]]);
108.785 + }
108.786 +
108.787 + }
108.788 + if (readSuccess()) {
108.789 + line.putback(c);
108.790 + }
108.791 + }
108.792 +
108.793 + void readBlueNodes() {
108.794 +
108.795 + std::vector<int> map_index(_blue_node_maps.size());
108.796 + int map_num, label_index;
108.797 +
108.798 + char c;
108.799 + if (!readLine() || !(line >> c) || c == '@') {
108.800 + if (readSuccess() && line) line.putback(c);
108.801 + if (!_blue_node_maps.empty())
108.802 + throw FormatError("Cannot find map names");
108.803 + return;
108.804 + }
108.805 + line.putback(c);
108.806 +
108.807 + {
108.808 + std::map<std::string, int> maps;
108.809 +
108.810 + std::string map;
108.811 + int index = 0;
108.812 + while (_reader_bits::readToken(line, map)) {
108.813 + if (maps.find(map) != maps.end()) {
108.814 + std::ostringstream msg;
108.815 + msg << "Multiple occurence of blue node map: " << map;
108.816 + throw FormatError(msg.str());
108.817 + }
108.818 + maps.insert(std::make_pair(map, index));
108.819 + ++index;
108.820 + }
108.821 +
108.822 + for (int i = 0; i < static_cast<int>(_blue_node_maps.size()); ++i) {
108.823 + std::map<std::string, int>::iterator jt =
108.824 + maps.find(_blue_node_maps[i].first);
108.825 + if (jt == maps.end()) {
108.826 + std::ostringstream msg;
108.827 + msg << "Map not found: " << _blue_node_maps[i].first;
108.828 + throw FormatError(msg.str());
108.829 + }
108.830 + map_index[i] = jt->second;
108.831 + }
108.832 +
108.833 + {
108.834 + std::map<std::string, int>::iterator jt = maps.find("label");
108.835 + if (jt != maps.end()) {
108.836 + label_index = jt->second;
108.837 + } else {
108.838 + label_index = -1;
108.839 + }
108.840 + }
108.841 + map_num = maps.size();
108.842 + }
108.843 +
108.844 + while (readLine() && line >> c && c != '@') {
108.845 + line.putback(c);
108.846 +
108.847 + std::vector<std::string> tokens(map_num);
108.848 + for (int i = 0; i < map_num; ++i) {
108.849 + if (!_reader_bits::readToken(line, tokens[i])) {
108.850 + std::ostringstream msg;
108.851 + msg << "Column not found (" << i + 1 << ")";
108.852 + throw FormatError(msg.str());
108.853 + }
108.854 + }
108.855 + if (line >> std::ws >> c)
108.856 + throw FormatError("Extra character at the end of line");
108.857 +
108.858 + BlueNode n;
108.859 + if (!_use_nodes) {
108.860 + n = _graph.addBlueNode();
108.861 + if (label_index != -1)
108.862 + _blue_node_index.insert(std::make_pair(tokens[label_index], n));
108.863 + } else {
108.864 + if (label_index == -1)
108.865 + throw FormatError("Label map not found");
108.866 + typename std::map<std::string, BlueNode>::iterator it =
108.867 + _blue_node_index.find(tokens[label_index]);
108.868 + if (it == _blue_node_index.end()) {
108.869 + std::ostringstream msg;
108.870 + msg << "Node with label not found: " << tokens[label_index];
108.871 + throw FormatError(msg.str());
108.872 + }
108.873 + n = it->second;
108.874 + }
108.875 +
108.876 + for (int i = 0; i < static_cast<int>(_blue_node_maps.size()); ++i) {
108.877 + _blue_node_maps[i].second->set(n, tokens[map_index[i]]);
108.878 + }
108.879 +
108.880 + }
108.881 + if (readSuccess()) {
108.882 + line.putback(c);
108.883 + }
108.884 + }
108.885 +
108.886 + void readEdges() {
108.887 +
108.888 + std::vector<int> map_index(_edge_maps.size());
108.889 + int map_num, label_index;
108.890 +
108.891 + char c;
108.892 + if (!readLine() || !(line >> c) || c == '@') {
108.893 + if (readSuccess() && line) line.putback(c);
108.894 + if (!_edge_maps.empty())
108.895 + throw FormatError("Cannot find map names");
108.896 + return;
108.897 + }
108.898 + line.putback(c);
108.899 +
108.900 + {
108.901 + std::map<std::string, int> maps;
108.902 +
108.903 + std::string map;
108.904 + int index = 0;
108.905 + while (_reader_bits::readToken(line, map)) {
108.906 + if (maps.find(map) != maps.end()) {
108.907 + std::ostringstream msg;
108.908 + msg << "Multiple occurence of edge map: " << map;
108.909 + throw FormatError(msg.str());
108.910 + }
108.911 + maps.insert(std::make_pair(map, index));
108.912 + ++index;
108.913 + }
108.914 +
108.915 + for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
108.916 + std::map<std::string, int>::iterator jt =
108.917 + maps.find(_edge_maps[i].first);
108.918 + if (jt == maps.end()) {
108.919 + std::ostringstream msg;
108.920 + msg << "Map not found: " << _edge_maps[i].first;
108.921 + throw FormatError(msg.str());
108.922 + }
108.923 + map_index[i] = jt->second;
108.924 + }
108.925 +
108.926 + {
108.927 + std::map<std::string, int>::iterator jt = maps.find("label");
108.928 + if (jt != maps.end()) {
108.929 + label_index = jt->second;
108.930 + } else {
108.931 + label_index = -1;
108.932 + }
108.933 + }
108.934 + map_num = maps.size();
108.935 + }
108.936 +
108.937 + while (readLine() && line >> c && c != '@') {
108.938 + line.putback(c);
108.939 +
108.940 + std::string source_token;
108.941 + std::string target_token;
108.942 +
108.943 + if (!_reader_bits::readToken(line, source_token))
108.944 + throw FormatError("Red node not found");
108.945 +
108.946 + if (!_reader_bits::readToken(line, target_token))
108.947 + throw FormatError("Blue node not found");
108.948 +
108.949 + std::vector<std::string> tokens(map_num);
108.950 + for (int i = 0; i < map_num; ++i) {
108.951 + if (!_reader_bits::readToken(line, tokens[i])) {
108.952 + std::ostringstream msg;
108.953 + msg << "Column not found (" << i + 1 << ")";
108.954 + throw FormatError(msg.str());
108.955 + }
108.956 + }
108.957 + if (line >> std::ws >> c)
108.958 + throw FormatError("Extra character at the end of line");
108.959 +
108.960 + Edge e;
108.961 + if (!_use_edges) {
108.962 + typename RedNodeIndex::iterator rit =
108.963 + _red_node_index.find(source_token);
108.964 + if (rit == _red_node_index.end()) {
108.965 + std::ostringstream msg;
108.966 + msg << "Item not found: " << source_token;
108.967 + throw FormatError(msg.str());
108.968 + }
108.969 + RedNode source = rit->second;
108.970 + typename BlueNodeIndex::iterator it =
108.971 + _blue_node_index.find(target_token);
108.972 + if (it == _blue_node_index.end()) {
108.973 + std::ostringstream msg;
108.974 + msg << "Item not found: " << target_token;
108.975 + throw FormatError(msg.str());
108.976 + }
108.977 + BlueNode target = it->second;
108.978 +
108.979 + // It is checked that source is red and
108.980 + // target is blue, so this should be safe:
108.981 + e = _graph.addEdge(source, target);
108.982 + if (label_index != -1)
108.983 + _edge_index.insert(std::make_pair(tokens[label_index], e));
108.984 + } else {
108.985 + if (label_index == -1)
108.986 + throw FormatError("Label map not found");
108.987 + typename std::map<std::string, Edge>::iterator it =
108.988 + _edge_index.find(tokens[label_index]);
108.989 + if (it == _edge_index.end()) {
108.990 + std::ostringstream msg;
108.991 + msg << "Edge with label not found: " << tokens[label_index];
108.992 + throw FormatError(msg.str());
108.993 + }
108.994 + e = it->second;
108.995 + }
108.996 +
108.997 + for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
108.998 + _edge_maps[i].second->set(e, tokens[map_index[i]]);
108.999 + }
108.1000 +
108.1001 + }
108.1002 + if (readSuccess()) {
108.1003 + line.putback(c);
108.1004 + }
108.1005 + }
108.1006 +
108.1007 + void readAttributes() {
108.1008 +
108.1009 + std::set<std::string> read_attr;
108.1010 +
108.1011 + char c;
108.1012 + while (readLine() && line >> c && c != '@') {
108.1013 + line.putback(c);
108.1014 +
108.1015 + std::string attr, token;
108.1016 + if (!_reader_bits::readToken(line, attr))
108.1017 + throw FormatError("Attribute name not found");
108.1018 + if (!_reader_bits::readToken(line, token))
108.1019 + throw FormatError("Attribute value not found");
108.1020 + if (line >> c)
108.1021 + throw FormatError("Extra character at the end of line");
108.1022 +
108.1023 + {
108.1024 + std::set<std::string>::iterator it = read_attr.find(attr);
108.1025 + if (it != read_attr.end()) {
108.1026 + std::ostringstream msg;
108.1027 + msg << "Multiple occurence of attribute: " << attr;
108.1028 + throw FormatError(msg.str());
108.1029 + }
108.1030 + read_attr.insert(attr);
108.1031 + }
108.1032 +
108.1033 + {
108.1034 + typename Attributes::iterator it = _attributes.lower_bound(attr);
108.1035 + while (it != _attributes.end() && it->first == attr) {
108.1036 + it->second->set(token);
108.1037 + ++it;
108.1038 + }
108.1039 + }
108.1040 +
108.1041 + }
108.1042 + if (readSuccess()) {
108.1043 + line.putback(c);
108.1044 + }
108.1045 + for (typename Attributes::iterator it = _attributes.begin();
108.1046 + it != _attributes.end(); ++it) {
108.1047 + if (read_attr.find(it->first) == read_attr.end()) {
108.1048 + std::ostringstream msg;
108.1049 + msg << "Attribute not found: " << it->first;
108.1050 + throw FormatError(msg.str());
108.1051 + }
108.1052 + }
108.1053 + }
108.1054 +
108.1055 + public:
108.1056 +
108.1057 + /// \name Execution of the Reader
108.1058 + /// @{
108.1059 +
108.1060 + /// \brief Start the batch processing
108.1061 + ///
108.1062 + /// This function starts the batch processing
108.1063 + void run() {
108.1064 +
108.1065 + LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
108.1066 +
108.1067 + bool red_nodes_done = _skip_nodes;
108.1068 + bool blue_nodes_done = _skip_nodes;
108.1069 + bool edges_done = _skip_edges;
108.1070 + bool attributes_done = false;
108.1071 +
108.1072 + line_num = 0;
108.1073 + readLine();
108.1074 + skipSection();
108.1075 +
108.1076 + while (readSuccess()) {
108.1077 + try {
108.1078 + char c;
108.1079 + std::string section, caption;
108.1080 + line >> c;
108.1081 + _reader_bits::readToken(line, section);
108.1082 + _reader_bits::readToken(line, caption);
108.1083 +
108.1084 + if (line >> c)
108.1085 + throw FormatError("Extra character at the end of line");
108.1086 +
108.1087 + if (section == "red_nodes" && !red_nodes_done) {
108.1088 + if (_nodes_caption.empty() || _nodes_caption == caption) {
108.1089 + readRedNodes();
108.1090 + red_nodes_done = true;
108.1091 + }
108.1092 + } else if (section == "blue_nodes" && !blue_nodes_done) {
108.1093 + if (_nodes_caption.empty() || _nodes_caption == caption) {
108.1094 + readBlueNodes();
108.1095 + blue_nodes_done = true;
108.1096 + }
108.1097 + } else if ((section == "edges" || section == "arcs") &&
108.1098 + !edges_done) {
108.1099 + if (_edges_caption.empty() || _edges_caption == caption) {
108.1100 + readEdges();
108.1101 + edges_done = true;
108.1102 + }
108.1103 + } else if (section == "attributes" && !attributes_done) {
108.1104 + if (_attributes_caption.empty() || _attributes_caption == caption) {
108.1105 + readAttributes();
108.1106 + attributes_done = true;
108.1107 + }
108.1108 + } else {
108.1109 + readLine();
108.1110 + skipSection();
108.1111 + }
108.1112 + } catch (FormatError& error) {
108.1113 + error.line(line_num);
108.1114 + error.file(_filename);
108.1115 + throw;
108.1116 + }
108.1117 + }
108.1118 +
108.1119 + if (!red_nodes_done) {
108.1120 + throw FormatError("Section @red_nodes not found");
108.1121 + }
108.1122 +
108.1123 + if (!blue_nodes_done) {
108.1124 + throw FormatError("Section @blue_nodes not found");
108.1125 + }
108.1126 +
108.1127 + if (!edges_done) {
108.1128 + throw FormatError("Section @edges not found");
108.1129 + }
108.1130 +
108.1131 + if (!attributes_done && !_attributes.empty()) {
108.1132 + throw FormatError("Section @attributes not found");
108.1133 + }
108.1134 +
108.1135 + }
108.1136 +
108.1137 + /// @}
108.1138 +
108.1139 + };
108.1140 +
108.1141 + /// \ingroup lemon_io
108.1142 + ///
108.1143 + /// \brief Return a \ref lemon::BpGraphReader "BpGraphReader" class
108.1144 + ///
108.1145 + /// This function just returns a \ref lemon::BpGraphReader
108.1146 + /// "BpGraphReader" class.
108.1147 + ///
108.1148 + /// With this function a graph can be read from an
108.1149 + /// \ref lgf-format "LGF" file or input stream with several maps and
108.1150 + /// attributes. For example, there is bipartite weighted matching problem
108.1151 + /// on a graph, i.e. a graph with a \e weight map on the edges. This
108.1152 + /// graph can be read with the following code:
108.1153 + ///
108.1154 + ///\code
108.1155 + ///ListBpGraph graph;
108.1156 + ///ListBpGraph::EdgeMap<int> weight(graph);
108.1157 + ///bpGraphReader(graph, std::cin).
108.1158 + /// edgeMap("weight", weight).
108.1159 + /// run();
108.1160 + ///\endcode
108.1161 + ///
108.1162 + /// For a complete documentation, please see the
108.1163 + /// \ref lemon::BpGraphReader "BpGraphReader"
108.1164 + /// class documentation.
108.1165 + /// \warning Don't forget to put the \ref lemon::BpGraphReader::run() "run()"
108.1166 + /// to the end of the parameter list.
108.1167 + /// \relates BpGraphReader
108.1168 + /// \sa bpGraphReader(TBGR& graph, const std::string& fn)
108.1169 + /// \sa bpGraphReader(TBGR& graph, const char* fn)
108.1170 + template <typename TBGR>
108.1171 + BpGraphReader<TBGR> bpGraphReader(TBGR& graph, std::istream& is) {
108.1172 + BpGraphReader<TBGR> tmp(graph, is);
108.1173 + return tmp;
108.1174 + }
108.1175 +
108.1176 + /// \brief Return a \ref BpGraphReader class
108.1177 + ///
108.1178 + /// This function just returns a \ref BpGraphReader class.
108.1179 + /// \relates BpGraphReader
108.1180 + /// \sa bpGraphReader(TBGR& graph, std::istream& is)
108.1181 + template <typename TBGR>
108.1182 + BpGraphReader<TBGR> bpGraphReader(TBGR& graph, const std::string& fn) {
108.1183 + BpGraphReader<TBGR> tmp(graph, fn);
108.1184 + return tmp;
108.1185 + }
108.1186 +
108.1187 + /// \brief Return a \ref BpGraphReader class
108.1188 + ///
108.1189 + /// This function just returns a \ref BpGraphReader class.
108.1190 + /// \relates BpGraphReader
108.1191 + /// \sa bpGraphReader(TBGR& graph, std::istream& is)
108.1192 + template <typename TBGR>
108.1193 + BpGraphReader<TBGR> bpGraphReader(TBGR& graph, const char* fn) {
108.1194 + BpGraphReader<TBGR> tmp(graph, fn);
108.1195 + return tmp;
108.1196 + }
108.1197 +
108.1198 class SectionReader;
108.1199
108.1200 SectionReader sectionReader(std::istream& is);
109.1 --- a/lemon/lgf_writer.h Mon Jul 16 16:21:40 2018 +0200
109.2 +++ b/lemon/lgf_writer.h Wed Oct 17 19:14:07 2018 +0200
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-2010
109.8 + * Copyright (C) 2003-2013
109.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
109.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
109.11 *
109.12 @@ -191,16 +191,16 @@
109.13 }
109.14 };
109.15
109.16 - template <typename Value>
109.17 + template <typename Value,
109.18 + typename Map = std::map<Value, std::string> >
109.19 struct MapLookUpConverter {
109.20 - const std::map<Value, std::string>& _map;
109.21 + const Map& _map;
109.22
109.23 - MapLookUpConverter(const std::map<Value, std::string>& map)
109.24 + MapLookUpConverter(const Map& map)
109.25 : _map(map) {}
109.26
109.27 - std::string operator()(const Value& str) {
109.28 - typename std::map<Value, std::string>::const_iterator it =
109.29 - _map.find(str);
109.30 + std::string operator()(const Value& value) {
109.31 + typename Map::const_iterator it = _map.find(value);
109.32 if (it == _map.end()) {
109.33 throw FormatError("Item not found");
109.34 }
109.35 @@ -208,6 +208,35 @@
109.36 }
109.37 };
109.38
109.39 + template <typename Value,
109.40 + typename Map1 = std::map<Value, std::string>,
109.41 + typename Map2 = std::map<Value, std::string> >
109.42 + struct DoubleMapLookUpConverter {
109.43 + const Map1& _map1;
109.44 + const Map2& _map2;
109.45 +
109.46 + DoubleMapLookUpConverter(const Map1& map1, const Map2& map2)
109.47 + : _map1(map1), _map2(map2) {}
109.48 +
109.49 + std::string operator()(const Value& value) {
109.50 + typename Map1::const_iterator it1 = _map1.find(value);
109.51 + typename Map1::const_iterator it2 = _map2.find(value);
109.52 + if (it1 == _map1.end()) {
109.53 + if (it2 == _map2.end()) {
109.54 + throw FormatError("Item not found");
109.55 + } else {
109.56 + return it2->second;
109.57 + }
109.58 + } else {
109.59 + if (it2 == _map2.end()) {
109.60 + return it1->second;
109.61 + } else {
109.62 + throw FormatError("Item is ambigous");
109.63 + }
109.64 + }
109.65 + }
109.66 + };
109.67 +
109.68 template <typename Graph>
109.69 struct GraphArcLookUpConverter {
109.70 const Graph& _graph;
109.71 @@ -915,9 +944,10 @@
109.72
109.73 /// \ingroup lemon_io
109.74 ///
109.75 - /// \brief Return a \ref DigraphWriter class
109.76 + /// \brief Return a \ref lemon::DigraphWriter "DigraphWriter" class
109.77 ///
109.78 - /// This function just returns a \ref DigraphWriter class.
109.79 + /// This function just returns a \ref lemon::DigraphWriter
109.80 + /// "DigraphWriter" class.
109.81 ///
109.82 /// With this function a digraph can be write to a file or output
109.83 /// stream in \ref lgf-format "LGF" format with several maps and
109.84 @@ -938,9 +968,10 @@
109.85 /// run();
109.86 ///\endcode
109.87 ///
109.88 - /// For a complete documentation, please see the \ref DigraphWriter
109.89 + /// For a complete documentation, please see the
109.90 + /// \ref lemon::DigraphWriter "DigraphWriter"
109.91 /// class documentation.
109.92 - /// \warning Don't forget to put the \ref DigraphWriter::run() "run()"
109.93 + /// \warning Don't forget to put the \ref lemon::DigraphWriter::run() "run()"
109.94 /// to the end of the parameter list.
109.95 /// \relates DigraphWriter
109.96 /// \sa digraphWriter(const TDGR& digraph, const std::string& fn)
109.97 @@ -986,7 +1017,7 @@
109.98
109.99 /// \ingroup lemon_io
109.100 ///
109.101 - /// \brief \ref lgf-format "LGF" writer for directed graphs
109.102 + /// \brief \ref lgf-format "LGF" writer for undirected graphs
109.103 ///
109.104 /// This utility writes an \ref lgf-format "LGF" file.
109.105 ///
109.106 @@ -1042,15 +1073,15 @@
109.107
109.108 /// \brief Constructor
109.109 ///
109.110 - /// Construct a directed graph writer, which writes to the given
109.111 - /// output stream.
109.112 + /// Construct an undirected graph writer, which writes to the
109.113 + /// given output stream.
109.114 GraphWriter(const GR& graph, std::ostream& os = std::cout)
109.115 : _os(&os), local_os(false), _graph(graph),
109.116 _skip_nodes(false), _skip_edges(false) {}
109.117
109.118 /// \brief Constructor
109.119 ///
109.120 - /// Construct a directed graph writer, which writes to the given
109.121 + /// Construct a undirected graph writer, which writes to the given
109.122 /// output file.
109.123 GraphWriter(const GR& graph, const std::string& fn)
109.124 : _os(new std::ofstream(fn.c_str())), local_os(true), _graph(graph),
109.125 @@ -1063,7 +1094,7 @@
109.126
109.127 /// \brief Constructor
109.128 ///
109.129 - /// Construct a directed graph writer, which writes to the given
109.130 + /// Construct a undirected graph writer, which writes to the given
109.131 /// output file.
109.132 GraphWriter(const GR& graph, const char* fn)
109.133 : _os(new std::ofstream(fn)), local_os(true), _graph(graph),
109.134 @@ -1289,9 +1320,9 @@
109.135 return *this;
109.136 }
109.137
109.138 - /// \brief Add an additional caption to the \c \@arcs section
109.139 + /// \brief Add an additional caption to the \c \@edges section
109.140 ///
109.141 - /// Add an additional caption to the \c \@arcs section.
109.142 + /// Add an additional caption to the \c \@edges section.
109.143 GraphWriter& edges(const std::string& caption) {
109.144 _edges_caption = caption;
109.145 return *this;
109.146 @@ -1554,9 +1585,9 @@
109.147
109.148 /// \ingroup lemon_io
109.149 ///
109.150 - /// \brief Return a \ref GraphWriter class
109.151 + /// \brief Return a \ref lemon::GraphWriter "GraphWriter" class
109.152 ///
109.153 - /// This function just returns a \ref GraphWriter class.
109.154 + /// This function just returns a \ref lemon::GraphWriter "GraphWriter" class.
109.155 ///
109.156 /// With this function a graph can be write to a file or output
109.157 /// stream in \ref lgf-format "LGF" format with several maps and
109.158 @@ -1573,9 +1604,10 @@
109.159 /// run();
109.160 ///\endcode
109.161 ///
109.162 - /// For a complete documentation, please see the \ref GraphWriter
109.163 + /// For a complete documentation, please see the
109.164 + /// \ref lemon::GraphWriter "GraphWriter"
109.165 /// class documentation.
109.166 - /// \warning Don't forget to put the \ref GraphWriter::run() "run()"
109.167 + /// \warning Don't forget to put the \ref lemon::GraphWriter::run() "run()"
109.168 /// to the end of the parameter list.
109.169 /// \relates GraphWriter
109.170 /// \sa graphWriter(const TGR& graph, const std::string& fn)
109.171 @@ -1608,6 +1640,826 @@
109.172 return tmp;
109.173 }
109.174
109.175 + template <typename BGR>
109.176 + class BpGraphWriter;
109.177 +
109.178 + template <typename TBGR>
109.179 + BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph,
109.180 + std::ostream& os = std::cout);
109.181 + template <typename TBGR>
109.182 + BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph, const std::string& fn);
109.183 + template <typename TBGR>
109.184 + BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph, const char* fn);
109.185 +
109.186 + /// \ingroup lemon_io
109.187 + ///
109.188 + /// \brief \ref lgf-format "LGF" writer for undirected bipartite graphs
109.189 + ///
109.190 + /// This utility writes an \ref lgf-format "LGF" file.
109.191 + ///
109.192 + /// It can be used almost the same way as \c GraphWriter, but it
109.193 + /// reads the red and blue nodes from separate sections, and these
109.194 + /// sections can contain different set of maps.
109.195 + ///
109.196 + /// The red and blue node maps are written to the corresponding
109.197 + /// sections. The node maps are written to both of these sections
109.198 + /// with the same map name.
109.199 + template <typename BGR>
109.200 + class BpGraphWriter {
109.201 + public:
109.202 +
109.203 + typedef BGR BpGraph;
109.204 + TEMPLATE_BPGRAPH_TYPEDEFS(BGR);
109.205 +
109.206 + private:
109.207 +
109.208 +
109.209 + std::ostream* _os;
109.210 + bool local_os;
109.211 +
109.212 + const BGR& _graph;
109.213 +
109.214 + std::string _nodes_caption;
109.215 + std::string _edges_caption;
109.216 + std::string _attributes_caption;
109.217 +
109.218 + typedef std::map<Node, std::string> RedNodeIndex;
109.219 + RedNodeIndex _red_node_index;
109.220 + typedef std::map<Node, std::string> BlueNodeIndex;
109.221 + BlueNodeIndex _blue_node_index;
109.222 + typedef std::map<Edge, std::string> EdgeIndex;
109.223 + EdgeIndex _edge_index;
109.224 +
109.225 + typedef std::vector<std::pair<std::string,
109.226 + _writer_bits::MapStorageBase<RedNode>* > > RedNodeMaps;
109.227 + RedNodeMaps _red_node_maps;
109.228 + typedef std::vector<std::pair<std::string,
109.229 + _writer_bits::MapStorageBase<BlueNode>* > > BlueNodeMaps;
109.230 + BlueNodeMaps _blue_node_maps;
109.231 +
109.232 + typedef std::vector<std::pair<std::string,
109.233 + _writer_bits::MapStorageBase<Edge>* > >EdgeMaps;
109.234 + EdgeMaps _edge_maps;
109.235 +
109.236 + typedef std::vector<std::pair<std::string,
109.237 + _writer_bits::ValueStorageBase*> > Attributes;
109.238 + Attributes _attributes;
109.239 +
109.240 + bool _skip_nodes;
109.241 + bool _skip_edges;
109.242 +
109.243 + public:
109.244 +
109.245 + /// \brief Constructor
109.246 + ///
109.247 + /// Construct a bipartite graph writer, which writes to the given
109.248 + /// output stream.
109.249 + BpGraphWriter(const BGR& graph, std::ostream& os = std::cout)
109.250 + : _os(&os), local_os(false), _graph(graph),
109.251 + _skip_nodes(false), _skip_edges(false) {}
109.252 +
109.253 + /// \brief Constructor
109.254 + ///
109.255 + /// Construct a bipartite graph writer, which writes to the given
109.256 + /// output file.
109.257 + BpGraphWriter(const BGR& graph, const std::string& fn)
109.258 + : _os(new std::ofstream(fn.c_str())), local_os(true), _graph(graph),
109.259 + _skip_nodes(false), _skip_edges(false) {
109.260 + if (!(*_os)) {
109.261 + delete _os;
109.262 + throw IoError("Cannot write file", fn);
109.263 + }
109.264 + }
109.265 +
109.266 + /// \brief Constructor
109.267 + ///
109.268 + /// Construct a bipartite graph writer, which writes to the given
109.269 + /// output file.
109.270 + BpGraphWriter(const BGR& graph, const char* fn)
109.271 + : _os(new std::ofstream(fn)), local_os(true), _graph(graph),
109.272 + _skip_nodes(false), _skip_edges(false) {
109.273 + if (!(*_os)) {
109.274 + delete _os;
109.275 + throw IoError("Cannot write file", fn);
109.276 + }
109.277 + }
109.278 +
109.279 + /// \brief Destructor
109.280 + ~BpGraphWriter() {
109.281 + for (typename RedNodeMaps::iterator it = _red_node_maps.begin();
109.282 + it != _red_node_maps.end(); ++it) {
109.283 + delete it->second;
109.284 + }
109.285 +
109.286 + for (typename BlueNodeMaps::iterator it = _blue_node_maps.begin();
109.287 + it != _blue_node_maps.end(); ++it) {
109.288 + delete it->second;
109.289 + }
109.290 +
109.291 + for (typename EdgeMaps::iterator it = _edge_maps.begin();
109.292 + it != _edge_maps.end(); ++it) {
109.293 + delete it->second;
109.294 + }
109.295 +
109.296 + for (typename Attributes::iterator it = _attributes.begin();
109.297 + it != _attributes.end(); ++it) {
109.298 + delete it->second;
109.299 + }
109.300 +
109.301 + if (local_os) {
109.302 + delete _os;
109.303 + }
109.304 + }
109.305 +
109.306 + private:
109.307 +
109.308 + template <typename TBGR>
109.309 + friend BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph,
109.310 + std::ostream& os);
109.311 + template <typename TBGR>
109.312 + friend BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph,
109.313 + const std::string& fn);
109.314 + template <typename TBGR>
109.315 + friend BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph, const char *fn);
109.316 +
109.317 + BpGraphWriter(BpGraphWriter& other)
109.318 + : _os(other._os), local_os(other.local_os), _graph(other._graph),
109.319 + _skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
109.320 +
109.321 + other._os = 0;
109.322 + other.local_os = false;
109.323 +
109.324 + _red_node_index.swap(other._red_node_index);
109.325 + _blue_node_index.swap(other._blue_node_index);
109.326 + _edge_index.swap(other._edge_index);
109.327 +
109.328 + _red_node_maps.swap(other._red_node_maps);
109.329 + _blue_node_maps.swap(other._blue_node_maps);
109.330 + _edge_maps.swap(other._edge_maps);
109.331 + _attributes.swap(other._attributes);
109.332 +
109.333 + _nodes_caption = other._nodes_caption;
109.334 + _edges_caption = other._edges_caption;
109.335 + _attributes_caption = other._attributes_caption;
109.336 + }
109.337 +
109.338 + BpGraphWriter& operator=(const BpGraphWriter&);
109.339 +
109.340 + public:
109.341 +
109.342 + /// \name Writing Rules
109.343 + /// @{
109.344 +
109.345 + /// \brief Node map writing rule
109.346 + ///
109.347 + /// Add a node map writing rule to the writer.
109.348 + template <typename Map>
109.349 + BpGraphWriter& nodeMap(const std::string& caption, const Map& map) {
109.350 + checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
109.351 + _writer_bits::MapStorageBase<RedNode>* red_storage =
109.352 + new _writer_bits::MapStorage<RedNode, Map>(map);
109.353 + _red_node_maps.push_back(std::make_pair(caption, red_storage));
109.354 + _writer_bits::MapStorageBase<BlueNode>* blue_storage =
109.355 + new _writer_bits::MapStorage<BlueNode, Map>(map);
109.356 + _blue_node_maps.push_back(std::make_pair(caption, blue_storage));
109.357 + return *this;
109.358 + }
109.359 +
109.360 + /// \brief Node map writing rule
109.361 + ///
109.362 + /// Add a node map writing rule with specialized converter to the
109.363 + /// writer.
109.364 + template <typename Map, typename Converter>
109.365 + BpGraphWriter& nodeMap(const std::string& caption, const Map& map,
109.366 + const Converter& converter = Converter()) {
109.367 + checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
109.368 + _writer_bits::MapStorageBase<RedNode>* red_storage =
109.369 + new _writer_bits::MapStorage<RedNode, Map, Converter>(map, converter);
109.370 + _red_node_maps.push_back(std::make_pair(caption, red_storage));
109.371 + _writer_bits::MapStorageBase<BlueNode>* blue_storage =
109.372 + new _writer_bits::MapStorage<BlueNode, Map, Converter>(map, converter);
109.373 + _blue_node_maps.push_back(std::make_pair(caption, blue_storage));
109.374 + return *this;
109.375 + }
109.376 +
109.377 + /// \brief Red node map writing rule
109.378 + ///
109.379 + /// Add a red node map writing rule to the writer.
109.380 + template <typename Map>
109.381 + BpGraphWriter& redNodeMap(const std::string& caption, const Map& map) {
109.382 + checkConcept<concepts::ReadMap<RedNode, typename Map::Value>, Map>();
109.383 + _writer_bits::MapStorageBase<RedNode>* storage =
109.384 + new _writer_bits::MapStorage<RedNode, Map>(map);
109.385 + _red_node_maps.push_back(std::make_pair(caption, storage));
109.386 + return *this;
109.387 + }
109.388 +
109.389 + /// \brief Red node map writing rule
109.390 + ///
109.391 + /// Add a red node map writing rule with specialized converter to the
109.392 + /// writer.
109.393 + template <typename Map, typename Converter>
109.394 + BpGraphWriter& redNodeMap(const std::string& caption, const Map& map,
109.395 + const Converter& converter = Converter()) {
109.396 + checkConcept<concepts::ReadMap<RedNode, typename Map::Value>, Map>();
109.397 + _writer_bits::MapStorageBase<RedNode>* storage =
109.398 + new _writer_bits::MapStorage<RedNode, Map, Converter>(map, converter);
109.399 + _red_node_maps.push_back(std::make_pair(caption, storage));
109.400 + return *this;
109.401 + }
109.402 +
109.403 + /// \brief Blue node map writing rule
109.404 + ///
109.405 + /// Add a blue node map writing rule to the writer.
109.406 + template <typename Map>
109.407 + BpGraphWriter& blueNodeMap(const std::string& caption, const Map& map) {
109.408 + checkConcept<concepts::ReadMap<BlueNode, typename Map::Value>, Map>();
109.409 + _writer_bits::MapStorageBase<BlueNode>* storage =
109.410 + new _writer_bits::MapStorage<BlueNode, Map>(map);
109.411 + _blue_node_maps.push_back(std::make_pair(caption, storage));
109.412 + return *this;
109.413 + }
109.414 +
109.415 + /// \brief Blue node map writing rule
109.416 + ///
109.417 + /// Add a blue node map writing rule with specialized converter to the
109.418 + /// writer.
109.419 + template <typename Map, typename Converter>
109.420 + BpGraphWriter& blueNodeMap(const std::string& caption, const Map& map,
109.421 + const Converter& converter = Converter()) {
109.422 + checkConcept<concepts::ReadMap<BlueNode, typename Map::Value>, Map>();
109.423 + _writer_bits::MapStorageBase<BlueNode>* storage =
109.424 + new _writer_bits::MapStorage<BlueNode, Map, Converter>(map, converter);
109.425 + _blue_node_maps.push_back(std::make_pair(caption, storage));
109.426 + return *this;
109.427 + }
109.428 +
109.429 + /// \brief Edge map writing rule
109.430 + ///
109.431 + /// Add an edge map writing rule to the writer.
109.432 + template <typename Map>
109.433 + BpGraphWriter& edgeMap(const std::string& caption, const Map& map) {
109.434 + checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
109.435 + _writer_bits::MapStorageBase<Edge>* storage =
109.436 + new _writer_bits::MapStorage<Edge, Map>(map);
109.437 + _edge_maps.push_back(std::make_pair(caption, storage));
109.438 + return *this;
109.439 + }
109.440 +
109.441 + /// \brief Edge map writing rule
109.442 + ///
109.443 + /// Add an edge map writing rule with specialized converter to the
109.444 + /// writer.
109.445 + template <typename Map, typename Converter>
109.446 + BpGraphWriter& edgeMap(const std::string& caption, const Map& map,
109.447 + const Converter& converter = Converter()) {
109.448 + checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
109.449 + _writer_bits::MapStorageBase<Edge>* storage =
109.450 + new _writer_bits::MapStorage<Edge, Map, Converter>(map, converter);
109.451 + _edge_maps.push_back(std::make_pair(caption, storage));
109.452 + return *this;
109.453 + }
109.454 +
109.455 + /// \brief Arc map writing rule
109.456 + ///
109.457 + /// Add an arc map writing rule to the writer.
109.458 + template <typename Map>
109.459 + BpGraphWriter& arcMap(const std::string& caption, const Map& map) {
109.460 + checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
109.461 + _writer_bits::MapStorageBase<Edge>* forward_storage =
109.462 + new _writer_bits::GraphArcMapStorage<BGR, true, Map>(_graph, map);
109.463 + _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
109.464 + _writer_bits::MapStorageBase<Edge>* backward_storage =
109.465 + new _writer_bits::GraphArcMapStorage<BGR, false, Map>(_graph, map);
109.466 + _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
109.467 + return *this;
109.468 + }
109.469 +
109.470 + /// \brief Arc map writing rule
109.471 + ///
109.472 + /// Add an arc map writing rule with specialized converter to the
109.473 + /// writer.
109.474 + template <typename Map, typename Converter>
109.475 + BpGraphWriter& arcMap(const std::string& caption, const Map& map,
109.476 + const Converter& converter = Converter()) {
109.477 + checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
109.478 + _writer_bits::MapStorageBase<Edge>* forward_storage =
109.479 + new _writer_bits::GraphArcMapStorage<BGR, true, Map, Converter>
109.480 + (_graph, map, converter);
109.481 + _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
109.482 + _writer_bits::MapStorageBase<Edge>* backward_storage =
109.483 + new _writer_bits::GraphArcMapStorage<BGR, false, Map, Converter>
109.484 + (_graph, map, converter);
109.485 + _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
109.486 + return *this;
109.487 + }
109.488 +
109.489 + /// \brief Attribute writing rule
109.490 + ///
109.491 + /// Add an attribute writing rule to the writer.
109.492 + template <typename Value>
109.493 + BpGraphWriter& attribute(const std::string& caption, const Value& value) {
109.494 + _writer_bits::ValueStorageBase* storage =
109.495 + new _writer_bits::ValueStorage<Value>(value);
109.496 + _attributes.push_back(std::make_pair(caption, storage));
109.497 + return *this;
109.498 + }
109.499 +
109.500 + /// \brief Attribute writing rule
109.501 + ///
109.502 + /// Add an attribute writing rule with specialized converter to the
109.503 + /// writer.
109.504 + template <typename Value, typename Converter>
109.505 + BpGraphWriter& attribute(const std::string& caption, const Value& value,
109.506 + const Converter& converter = Converter()) {
109.507 + _writer_bits::ValueStorageBase* storage =
109.508 + new _writer_bits::ValueStorage<Value, Converter>(value, converter);
109.509 + _attributes.push_back(std::make_pair(caption, storage));
109.510 + return *this;
109.511 + }
109.512 +
109.513 + /// \brief Node writing rule
109.514 + ///
109.515 + /// Add a node writing rule to the writer.
109.516 + BpGraphWriter& node(const std::string& caption, const Node& node) {
109.517 + typedef _writer_bits::DoubleMapLookUpConverter<
109.518 + Node, RedNodeIndex, BlueNodeIndex> Converter;
109.519 + Converter converter(_red_node_index, _blue_node_index);
109.520 + _writer_bits::ValueStorageBase* storage =
109.521 + new _writer_bits::ValueStorage<Node, Converter>(node, converter);
109.522 + _attributes.push_back(std::make_pair(caption, storage));
109.523 + return *this;
109.524 + }
109.525 +
109.526 + /// \brief Red node writing rule
109.527 + ///
109.528 + /// Add a red node writing rule to the writer.
109.529 + BpGraphWriter& redNode(const std::string& caption, const RedNode& node) {
109.530 + typedef _writer_bits::MapLookUpConverter<Node> Converter;
109.531 + Converter converter(_red_node_index);
109.532 + _writer_bits::ValueStorageBase* storage =
109.533 + new _writer_bits::ValueStorage<Node, Converter>(node, converter);
109.534 + _attributes.push_back(std::make_pair(caption, storage));
109.535 + return *this;
109.536 + }
109.537 +
109.538 + /// \brief Blue node writing rule
109.539 + ///
109.540 + /// Add a blue node writing rule to the writer.
109.541 + BpGraphWriter& blueNode(const std::string& caption, const BlueNode& node) {
109.542 + typedef _writer_bits::MapLookUpConverter<Node> Converter;
109.543 + Converter converter(_blue_node_index);
109.544 + _writer_bits::ValueStorageBase* storage =
109.545 + new _writer_bits::ValueStorage<Node, Converter>(node, converter);
109.546 + _attributes.push_back(std::make_pair(caption, storage));
109.547 + return *this;
109.548 + }
109.549 +
109.550 + /// \brief Edge writing rule
109.551 + ///
109.552 + /// Add an edge writing rule to writer.
109.553 + BpGraphWriter& edge(const std::string& caption, const Edge& edge) {
109.554 + typedef _writer_bits::MapLookUpConverter<Edge> Converter;
109.555 + Converter converter(_edge_index);
109.556 + _writer_bits::ValueStorageBase* storage =
109.557 + new _writer_bits::ValueStorage<Edge, Converter>(edge, converter);
109.558 + _attributes.push_back(std::make_pair(caption, storage));
109.559 + return *this;
109.560 + }
109.561 +
109.562 + /// \brief Arc writing rule
109.563 + ///
109.564 + /// Add an arc writing rule to writer.
109.565 + BpGraphWriter& arc(const std::string& caption, const Arc& arc) {
109.566 + typedef _writer_bits::GraphArcLookUpConverter<BGR> Converter;
109.567 + Converter converter(_graph, _edge_index);
109.568 + _writer_bits::ValueStorageBase* storage =
109.569 + new _writer_bits::ValueStorage<Arc, Converter>(arc, converter);
109.570 + _attributes.push_back(std::make_pair(caption, storage));
109.571 + return *this;
109.572 + }
109.573 +
109.574 + /// \name Section Captions
109.575 + /// @{
109.576 +
109.577 + /// \brief Add an additional caption to the \c \@red_nodes and
109.578 + /// \c \@blue_nodes section
109.579 + ///
109.580 + /// Add an additional caption to the \c \@red_nodes and \c
109.581 + /// \@blue_nodes section.
109.582 + BpGraphWriter& nodes(const std::string& caption) {
109.583 + _nodes_caption = caption;
109.584 + return *this;
109.585 + }
109.586 +
109.587 + /// \brief Add an additional caption to the \c \@edges section
109.588 + ///
109.589 + /// Add an additional caption to the \c \@edges section.
109.590 + BpGraphWriter& edges(const std::string& caption) {
109.591 + _edges_caption = caption;
109.592 + return *this;
109.593 + }
109.594 +
109.595 + /// \brief Add an additional caption to the \c \@attributes section
109.596 + ///
109.597 + /// Add an additional caption to the \c \@attributes section.
109.598 + BpGraphWriter& attributes(const std::string& caption) {
109.599 + _attributes_caption = caption;
109.600 + return *this;
109.601 + }
109.602 +
109.603 + /// \name Skipping Section
109.604 + /// @{
109.605 +
109.606 + /// \brief Skip writing the node set
109.607 + ///
109.608 + /// The \c \@red_nodes and \c \@blue_nodes section will not be
109.609 + /// written to the stream.
109.610 + BpGraphWriter& skipNodes() {
109.611 + LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member");
109.612 + _skip_nodes = true;
109.613 + return *this;
109.614 + }
109.615 +
109.616 + /// \brief Skip writing edge set
109.617 + ///
109.618 + /// The \c \@edges section will not be written to the stream.
109.619 + BpGraphWriter& skipEdges() {
109.620 + LEMON_ASSERT(!_skip_edges, "Multiple usage of skipEdges() member");
109.621 + _skip_edges = true;
109.622 + return *this;
109.623 + }
109.624 +
109.625 + /// @}
109.626 +
109.627 + private:
109.628 +
109.629 + void writeRedNodes() {
109.630 + _writer_bits::MapStorageBase<RedNode>* label = 0;
109.631 + for (typename RedNodeMaps::iterator it = _red_node_maps.begin();
109.632 + it != _red_node_maps.end(); ++it) {
109.633 + if (it->first == "label") {
109.634 + label = it->second;
109.635 + break;
109.636 + }
109.637 + }
109.638 +
109.639 + *_os << "@red_nodes";
109.640 + if (!_nodes_caption.empty()) {
109.641 + _writer_bits::writeToken(*_os << ' ', _nodes_caption);
109.642 + }
109.643 + *_os << std::endl;
109.644 +
109.645 + if (label == 0) {
109.646 + *_os << "label" << '\t';
109.647 + }
109.648 + for (typename RedNodeMaps::iterator it = _red_node_maps.begin();
109.649 + it != _red_node_maps.end(); ++it) {
109.650 + _writer_bits::writeToken(*_os, it->first) << '\t';
109.651 + }
109.652 + *_os << std::endl;
109.653 +
109.654 + std::vector<RedNode> nodes;
109.655 + for (RedNodeIt n(_graph); n != INVALID; ++n) {
109.656 + nodes.push_back(n);
109.657 + }
109.658 +
109.659 + if (label == 0) {
109.660 + IdMap<BGR, Node> id_map(_graph);
109.661 + _writer_bits::MapLess<IdMap<BGR, Node> > id_less(id_map);
109.662 + std::sort(nodes.begin(), nodes.end(), id_less);
109.663 + } else {
109.664 + label->sort(nodes);
109.665 + }
109.666 +
109.667 + for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
109.668 + RedNode n = nodes[i];
109.669 + if (label == 0) {
109.670 + std::ostringstream os;
109.671 + os << _graph.id(static_cast<Node>(n));
109.672 + _writer_bits::writeToken(*_os, os.str());
109.673 + *_os << '\t';
109.674 + _red_node_index.insert(std::make_pair(n, os.str()));
109.675 + }
109.676 + for (typename RedNodeMaps::iterator it = _red_node_maps.begin();
109.677 + it != _red_node_maps.end(); ++it) {
109.678 + std::string value = it->second->get(n);
109.679 + _writer_bits::writeToken(*_os, value);
109.680 + if (it->first == "label") {
109.681 + _red_node_index.insert(std::make_pair(n, value));
109.682 + }
109.683 + *_os << '\t';
109.684 + }
109.685 + *_os << std::endl;
109.686 + }
109.687 + }
109.688 +
109.689 + void writeBlueNodes() {
109.690 + _writer_bits::MapStorageBase<BlueNode>* label = 0;
109.691 + for (typename BlueNodeMaps::iterator it = _blue_node_maps.begin();
109.692 + it != _blue_node_maps.end(); ++it) {
109.693 + if (it->first == "label") {
109.694 + label = it->second;
109.695 + break;
109.696 + }
109.697 + }
109.698 +
109.699 + *_os << "@blue_nodes";
109.700 + if (!_nodes_caption.empty()) {
109.701 + _writer_bits::writeToken(*_os << ' ', _nodes_caption);
109.702 + }
109.703 + *_os << std::endl;
109.704 +
109.705 + if (label == 0) {
109.706 + *_os << "label" << '\t';
109.707 + }
109.708 + for (typename BlueNodeMaps::iterator it = _blue_node_maps.begin();
109.709 + it != _blue_node_maps.end(); ++it) {
109.710 + _writer_bits::writeToken(*_os, it->first) << '\t';
109.711 + }
109.712 + *_os << std::endl;
109.713 +
109.714 + std::vector<BlueNode> nodes;
109.715 + for (BlueNodeIt n(_graph); n != INVALID; ++n) {
109.716 + nodes.push_back(n);
109.717 + }
109.718 +
109.719 + if (label == 0) {
109.720 + IdMap<BGR, Node> id_map(_graph);
109.721 + _writer_bits::MapLess<IdMap<BGR, Node> > id_less(id_map);
109.722 + std::sort(nodes.begin(), nodes.end(), id_less);
109.723 + } else {
109.724 + label->sort(nodes);
109.725 + }
109.726 +
109.727 + for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
109.728 + BlueNode n = nodes[i];
109.729 + if (label == 0) {
109.730 + std::ostringstream os;
109.731 + os << _graph.id(static_cast<Node>(n));
109.732 + _writer_bits::writeToken(*_os, os.str());
109.733 + *_os << '\t';
109.734 + _blue_node_index.insert(std::make_pair(n, os.str()));
109.735 + }
109.736 + for (typename BlueNodeMaps::iterator it = _blue_node_maps.begin();
109.737 + it != _blue_node_maps.end(); ++it) {
109.738 + std::string value = it->second->get(n);
109.739 + _writer_bits::writeToken(*_os, value);
109.740 + if (it->first == "label") {
109.741 + _blue_node_index.insert(std::make_pair(n, value));
109.742 + }
109.743 + *_os << '\t';
109.744 + }
109.745 + *_os << std::endl;
109.746 + }
109.747 + }
109.748 +
109.749 + void createRedNodeIndex() {
109.750 + _writer_bits::MapStorageBase<RedNode>* label = 0;
109.751 + for (typename RedNodeMaps::iterator it = _red_node_maps.begin();
109.752 + it != _red_node_maps.end(); ++it) {
109.753 + if (it->first == "label") {
109.754 + label = it->second;
109.755 + break;
109.756 + }
109.757 + }
109.758 +
109.759 + if (label == 0) {
109.760 + for (RedNodeIt n(_graph); n != INVALID; ++n) {
109.761 + std::ostringstream os;
109.762 + os << _graph.id(n);
109.763 + _red_node_index.insert(std::make_pair(n, os.str()));
109.764 + }
109.765 + } else {
109.766 + for (RedNodeIt n(_graph); n != INVALID; ++n) {
109.767 + std::string value = label->get(n);
109.768 + _red_node_index.insert(std::make_pair(n, value));
109.769 + }
109.770 + }
109.771 + }
109.772 +
109.773 + void createBlueNodeIndex() {
109.774 + _writer_bits::MapStorageBase<BlueNode>* label = 0;
109.775 + for (typename BlueNodeMaps::iterator it = _blue_node_maps.begin();
109.776 + it != _blue_node_maps.end(); ++it) {
109.777 + if (it->first == "label") {
109.778 + label = it->second;
109.779 + break;
109.780 + }
109.781 + }
109.782 +
109.783 + if (label == 0) {
109.784 + for (BlueNodeIt n(_graph); n != INVALID; ++n) {
109.785 + std::ostringstream os;
109.786 + os << _graph.id(n);
109.787 + _blue_node_index.insert(std::make_pair(n, os.str()));
109.788 + }
109.789 + } else {
109.790 + for (BlueNodeIt n(_graph); n != INVALID; ++n) {
109.791 + std::string value = label->get(n);
109.792 + _blue_node_index.insert(std::make_pair(n, value));
109.793 + }
109.794 + }
109.795 + }
109.796 +
109.797 + void writeEdges() {
109.798 + _writer_bits::MapStorageBase<Edge>* label = 0;
109.799 + for (typename EdgeMaps::iterator it = _edge_maps.begin();
109.800 + it != _edge_maps.end(); ++it) {
109.801 + if (it->first == "label") {
109.802 + label = it->second;
109.803 + break;
109.804 + }
109.805 + }
109.806 +
109.807 + *_os << "@edges";
109.808 + if (!_edges_caption.empty()) {
109.809 + _writer_bits::writeToken(*_os << ' ', _edges_caption);
109.810 + }
109.811 + *_os << std::endl;
109.812 +
109.813 + *_os << '\t' << '\t';
109.814 + if (label == 0) {
109.815 + *_os << "label" << '\t';
109.816 + }
109.817 + for (typename EdgeMaps::iterator it = _edge_maps.begin();
109.818 + it != _edge_maps.end(); ++it) {
109.819 + _writer_bits::writeToken(*_os, it->first) << '\t';
109.820 + }
109.821 + *_os << std::endl;
109.822 +
109.823 + std::vector<Edge> edges;
109.824 + for (EdgeIt n(_graph); n != INVALID; ++n) {
109.825 + edges.push_back(n);
109.826 + }
109.827 +
109.828 + if (label == 0) {
109.829 + IdMap<BGR, Edge> id_map(_graph);
109.830 + _writer_bits::MapLess<IdMap<BGR, Edge> > id_less(id_map);
109.831 + std::sort(edges.begin(), edges.end(), id_less);
109.832 + } else {
109.833 + label->sort(edges);
109.834 + }
109.835 +
109.836 + for (int i = 0; i < static_cast<int>(edges.size()); ++i) {
109.837 + Edge e = edges[i];
109.838 + _writer_bits::writeToken(*_os, _red_node_index.
109.839 + find(_graph.redNode(e))->second);
109.840 + *_os << '\t';
109.841 + _writer_bits::writeToken(*_os, _blue_node_index.
109.842 + find(_graph.blueNode(e))->second);
109.843 + *_os << '\t';
109.844 + if (label == 0) {
109.845 + std::ostringstream os;
109.846 + os << _graph.id(e);
109.847 + _writer_bits::writeToken(*_os, os.str());
109.848 + *_os << '\t';
109.849 + _edge_index.insert(std::make_pair(e, os.str()));
109.850 + }
109.851 + for (typename EdgeMaps::iterator it = _edge_maps.begin();
109.852 + it != _edge_maps.end(); ++it) {
109.853 + std::string value = it->second->get(e);
109.854 + _writer_bits::writeToken(*_os, value);
109.855 + if (it->first == "label") {
109.856 + _edge_index.insert(std::make_pair(e, value));
109.857 + }
109.858 + *_os << '\t';
109.859 + }
109.860 + *_os << std::endl;
109.861 + }
109.862 + }
109.863 +
109.864 + void createEdgeIndex() {
109.865 + _writer_bits::MapStorageBase<Edge>* label = 0;
109.866 + for (typename EdgeMaps::iterator it = _edge_maps.begin();
109.867 + it != _edge_maps.end(); ++it) {
109.868 + if (it->first == "label") {
109.869 + label = it->second;
109.870 + break;
109.871 + }
109.872 + }
109.873 +
109.874 + if (label == 0) {
109.875 + for (EdgeIt e(_graph); e != INVALID; ++e) {
109.876 + std::ostringstream os;
109.877 + os << _graph.id(e);
109.878 + _edge_index.insert(std::make_pair(e, os.str()));
109.879 + }
109.880 + } else {
109.881 + for (EdgeIt e(_graph); e != INVALID; ++e) {
109.882 + std::string value = label->get(e);
109.883 + _edge_index.insert(std::make_pair(e, value));
109.884 + }
109.885 + }
109.886 + }
109.887 +
109.888 + void writeAttributes() {
109.889 + if (_attributes.empty()) return;
109.890 + *_os << "@attributes";
109.891 + if (!_attributes_caption.empty()) {
109.892 + _writer_bits::writeToken(*_os << ' ', _attributes_caption);
109.893 + }
109.894 + *_os << std::endl;
109.895 + for (typename Attributes::iterator it = _attributes.begin();
109.896 + it != _attributes.end(); ++it) {
109.897 + _writer_bits::writeToken(*_os, it->first) << ' ';
109.898 + _writer_bits::writeToken(*_os, it->second->get());
109.899 + *_os << std::endl;
109.900 + }
109.901 + }
109.902 +
109.903 + public:
109.904 +
109.905 + /// \name Execution of the Writer
109.906 + /// @{
109.907 +
109.908 + /// \brief Start the batch processing
109.909 + ///
109.910 + /// This function starts the batch processing.
109.911 + void run() {
109.912 + if (!_skip_nodes) {
109.913 + writeRedNodes();
109.914 + writeBlueNodes();
109.915 + } else {
109.916 + createRedNodeIndex();
109.917 + createBlueNodeIndex();
109.918 + }
109.919 + if (!_skip_edges) {
109.920 + writeEdges();
109.921 + } else {
109.922 + createEdgeIndex();
109.923 + }
109.924 + writeAttributes();
109.925 + }
109.926 +
109.927 + /// \brief Give back the stream of the writer
109.928 + ///
109.929 + /// Give back the stream of the writer
109.930 + std::ostream& ostream() {
109.931 + return *_os;
109.932 + }
109.933 +
109.934 + /// @}
109.935 + };
109.936 +
109.937 + /// \ingroup lemon_io
109.938 + ///
109.939 + /// \brief Return a \ref lemon::BpGraphWriter "BpGraphWriter" class
109.940 + ///
109.941 + /// This function just returns a \ref lemon::BpGraphWriter
109.942 + /// "BpGraphWriter" class.
109.943 + ///
109.944 + /// With this function a bipartite graph can be write to a file or output
109.945 + /// stream in \ref lgf-format "LGF" format with several maps and
109.946 + /// attributes. For example, with the following code a bipartite
109.947 + /// weighted matching problem can be written to the standard output,
109.948 + /// i.e. a graph with a \e weight map on the edges:
109.949 + ///
109.950 + ///\code
109.951 + ///ListBpGraph graph;
109.952 + ///ListBpGraph::EdgeMap<int> weight(graph);
109.953 + /// // Setting the weight map
109.954 + ///bpGraphWriter(graph, std::cout).
109.955 + /// edgeMap("weight", weight).
109.956 + /// run();
109.957 + ///\endcode
109.958 + ///
109.959 + /// For a complete documentation, please see the
109.960 + /// \ref lemon::BpGraphWriter "BpGraphWriter"
109.961 + /// class documentation.
109.962 + /// \warning Don't forget to put the \ref lemon::BpGraphWriter::run() "run()"
109.963 + /// to the end of the parameter list.
109.964 + /// \relates BpGraphWriter
109.965 + /// \sa bpGraphWriter(const TBGR& graph, const std::string& fn)
109.966 + /// \sa bpGraphWriter(const TBGR& graph, const char* fn)
109.967 + template <typename TBGR>
109.968 + BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph, std::ostream& os) {
109.969 + BpGraphWriter<TBGR> tmp(graph, os);
109.970 + return tmp;
109.971 + }
109.972 +
109.973 + /// \brief Return a \ref BpGraphWriter class
109.974 + ///
109.975 + /// This function just returns a \ref BpGraphWriter class.
109.976 + /// \relates BpGraphWriter
109.977 + /// \sa graphWriter(const TBGR& graph, std::ostream& os)
109.978 + template <typename TBGR>
109.979 + BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph, const std::string& fn) {
109.980 + BpGraphWriter<TBGR> tmp(graph, fn);
109.981 + return tmp;
109.982 + }
109.983 +
109.984 + /// \brief Return a \ref BpGraphWriter class
109.985 + ///
109.986 + /// This function just returns a \ref BpGraphWriter class.
109.987 + /// \relates BpGraphWriter
109.988 + /// \sa graphWriter(const TBGR& graph, std::ostream& os)
109.989 + template <typename TBGR>
109.990 + BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph, const char* fn) {
109.991 + BpGraphWriter<TBGR> tmp(graph, fn);
109.992 + return tmp;
109.993 + }
109.994 +
109.995 class SectionWriter;
109.996
109.997 SectionWriter sectionWriter(std::istream& is);
110.1 --- a/lemon/list_graph.h Mon Jul 16 16:21:40 2018 +0200
110.2 +++ b/lemon/list_graph.h Wed Oct 17 19:14:07 2018 +0200
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-2010
110.8 + * Copyright (C) 2003-2013
110.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
110.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
110.11 *
110.12 @@ -445,7 +445,7 @@
110.13 ///\note The moved arcs are joined to node \c u using changeSource()
110.14 ///or changeTarget(), thus \c ArcIt and \c OutArcIt iterators are
110.15 ///invalidated for the outgoing arcs of node \c v and \c InArcIt
110.16 - ///iterators are invalidated for the incomming arcs of \c v.
110.17 + ///iterators are invalidated for the incoming arcs of \c v.
110.18 ///Moreover all iterators referencing node \c v or the removed
110.19 ///loops are also invalidated. Other iterators remain valid.
110.20 ///
110.21 @@ -582,7 +582,7 @@
110.22 snapshot.addNode(node);
110.23 }
110.24 virtual void add(const std::vector<Node>& nodes) {
110.25 - for (int i = nodes.size() - 1; i >= 0; ++i) {
110.26 + for (int i = nodes.size() - 1; i >= 0; --i) {
110.27 snapshot.addNode(nodes[i]);
110.28 }
110.29 }
110.30 @@ -632,7 +632,7 @@
110.31 snapshot.addArc(arc);
110.32 }
110.33 virtual void add(const std::vector<Arc>& arcs) {
110.34 - for (int i = arcs.size() - 1; i >= 0; ++i) {
110.35 + for (int i = arcs.size() - 1; i >= 0; --i) {
110.36 snapshot.addArc(arcs[i]);
110.37 }
110.38 }
110.39 @@ -1394,7 +1394,7 @@
110.40 snapshot.addNode(node);
110.41 }
110.42 virtual void add(const std::vector<Node>& nodes) {
110.43 - for (int i = nodes.size() - 1; i >= 0; ++i) {
110.44 + for (int i = nodes.size() - 1; i >= 0; --i) {
110.45 snapshot.addNode(nodes[i]);
110.46 }
110.47 }
110.48 @@ -1444,7 +1444,7 @@
110.49 snapshot.addEdge(edge);
110.50 }
110.51 virtual void add(const std::vector<Edge>& edges) {
110.52 - for (int i = edges.size() - 1; i >= 0; ++i) {
110.53 + for (int i = edges.size() - 1; i >= 0; --i) {
110.54 snapshot.addEdge(edges[i]);
110.55 }
110.56 }
110.57 @@ -1599,6 +1599,911 @@
110.58 };
110.59
110.60 /// @}
110.61 +
110.62 + class ListBpGraphBase {
110.63 +
110.64 + protected:
110.65 +
110.66 + struct NodeT {
110.67 + int first_out;
110.68 + int prev, next;
110.69 + int partition_prev, partition_next;
110.70 + int partition_index;
110.71 + bool red;
110.72 + };
110.73 +
110.74 + struct ArcT {
110.75 + int target;
110.76 + int prev_out, next_out;
110.77 + };
110.78 +
110.79 + std::vector<NodeT> nodes;
110.80 +
110.81 + int first_node, first_red, first_blue;
110.82 + int max_red, max_blue;
110.83 +
110.84 + int first_free_red, first_free_blue;
110.85 +
110.86 + std::vector<ArcT> arcs;
110.87 +
110.88 + int first_free_arc;
110.89 +
110.90 + public:
110.91 +
110.92 + typedef ListBpGraphBase BpGraph;
110.93 +
110.94 + class Node {
110.95 + friend class ListBpGraphBase;
110.96 + protected:
110.97 +
110.98 + int id;
110.99 + explicit Node(int pid) { id = pid;}
110.100 +
110.101 + public:
110.102 + Node() {}
110.103 + Node (Invalid) { id = -1; }
110.104 + bool operator==(const Node& node) const {return id == node.id;}
110.105 + bool operator!=(const Node& node) const {return id != node.id;}
110.106 + bool operator<(const Node& node) const {return id < node.id;}
110.107 + };
110.108 +
110.109 + class RedNode : public Node {
110.110 + friend class ListBpGraphBase;
110.111 + protected:
110.112 +
110.113 + explicit RedNode(int pid) : Node(pid) {}
110.114 +
110.115 + public:
110.116 + RedNode() {}
110.117 + RedNode(const RedNode& node) : Node(node) {}
110.118 + RedNode(Invalid) : Node(INVALID){}
110.119 + };
110.120 +
110.121 + class BlueNode : public Node {
110.122 + friend class ListBpGraphBase;
110.123 + protected:
110.124 +
110.125 + explicit BlueNode(int pid) : Node(pid) {}
110.126 +
110.127 + public:
110.128 + BlueNode() {}
110.129 + BlueNode(const BlueNode& node) : Node(node) {}
110.130 + BlueNode(Invalid) : Node(INVALID){}
110.131 + };
110.132 +
110.133 + class Edge {
110.134 + friend class ListBpGraphBase;
110.135 + protected:
110.136 +
110.137 + int id;
110.138 + explicit Edge(int pid) { id = pid;}
110.139 +
110.140 + public:
110.141 + Edge() {}
110.142 + Edge (Invalid) { id = -1; }
110.143 + bool operator==(const Edge& edge) const {return id == edge.id;}
110.144 + bool operator!=(const Edge& edge) const {return id != edge.id;}
110.145 + bool operator<(const Edge& edge) const {return id < edge.id;}
110.146 + };
110.147 +
110.148 + class Arc {
110.149 + friend class ListBpGraphBase;
110.150 + protected:
110.151 +
110.152 + int id;
110.153 + explicit Arc(int pid) { id = pid;}
110.154 +
110.155 + public:
110.156 + operator Edge() const {
110.157 + return id != -1 ? edgeFromId(id / 2) : INVALID;
110.158 + }
110.159 +
110.160 + Arc() {}
110.161 + Arc (Invalid) { id = -1; }
110.162 + bool operator==(const Arc& arc) const {return id == arc.id;}
110.163 + bool operator!=(const Arc& arc) const {return id != arc.id;}
110.164 + bool operator<(const Arc& arc) const {return id < arc.id;}
110.165 + };
110.166 +
110.167 + ListBpGraphBase()
110.168 + : nodes(), first_node(-1),
110.169 + first_red(-1), first_blue(-1),
110.170 + max_red(-1), max_blue(-1),
110.171 + first_free_red(-1), first_free_blue(-1),
110.172 + arcs(), first_free_arc(-1) {}
110.173 +
110.174 +
110.175 + bool red(Node n) const { return nodes[n.id].red; }
110.176 + bool blue(Node n) const { return !nodes[n.id].red; }
110.177 +
110.178 + static RedNode asRedNodeUnsafe(Node n) { return RedNode(n.id); }
110.179 + static BlueNode asBlueNodeUnsafe(Node n) { return BlueNode(n.id); }
110.180 +
110.181 + int maxNodeId() const { return nodes.size()-1; }
110.182 + int maxRedId() const { return max_red; }
110.183 + int maxBlueId() const { return max_blue; }
110.184 + int maxEdgeId() const { return arcs.size() / 2 - 1; }
110.185 + int maxArcId() const { return arcs.size()-1; }
110.186 +
110.187 + Node source(Arc e) const { return Node(arcs[e.id ^ 1].target); }
110.188 + Node target(Arc e) const { return Node(arcs[e.id].target); }
110.189 +
110.190 + RedNode redNode(Edge e) const {
110.191 + return RedNode(arcs[2 * e.id].target);
110.192 + }
110.193 + BlueNode blueNode(Edge e) const {
110.194 + return BlueNode(arcs[2 * e.id + 1].target);
110.195 + }
110.196 +
110.197 + static bool direction(Arc e) {
110.198 + return (e.id & 1) == 1;
110.199 + }
110.200 +
110.201 + static Arc direct(Edge e, bool d) {
110.202 + return Arc(e.id * 2 + (d ? 1 : 0));
110.203 + }
110.204 +
110.205 + void first(Node& node) const {
110.206 + node.id = first_node;
110.207 + }
110.208 +
110.209 + void next(Node& node) const {
110.210 + node.id = nodes[node.id].next;
110.211 + }
110.212 +
110.213 + void first(RedNode& node) const {
110.214 + node.id = first_red;
110.215 + }
110.216 +
110.217 + void next(RedNode& node) const {
110.218 + node.id = nodes[node.id].partition_next;
110.219 + }
110.220 +
110.221 + void first(BlueNode& node) const {
110.222 + node.id = first_blue;
110.223 + }
110.224 +
110.225 + void next(BlueNode& node) const {
110.226 + node.id = nodes[node.id].partition_next;
110.227 + }
110.228 +
110.229 + void first(Arc& e) const {
110.230 + int n = first_node;
110.231 + while (n != -1 && nodes[n].first_out == -1) {
110.232 + n = nodes[n].next;
110.233 + }
110.234 + e.id = (n == -1) ? -1 : nodes[n].first_out;
110.235 + }
110.236 +
110.237 + void next(Arc& e) const {
110.238 + if (arcs[e.id].next_out != -1) {
110.239 + e.id = arcs[e.id].next_out;
110.240 + } else {
110.241 + int n = nodes[arcs[e.id ^ 1].target].next;
110.242 + while(n != -1 && nodes[n].first_out == -1) {
110.243 + n = nodes[n].next;
110.244 + }
110.245 + e.id = (n == -1) ? -1 : nodes[n].first_out;
110.246 + }
110.247 + }
110.248 +
110.249 + void first(Edge& e) const {
110.250 + int n = first_node;
110.251 + while (n != -1) {
110.252 + e.id = nodes[n].first_out;
110.253 + while ((e.id & 1) != 1) {
110.254 + e.id = arcs[e.id].next_out;
110.255 + }
110.256 + if (e.id != -1) {
110.257 + e.id /= 2;
110.258 + return;
110.259 + }
110.260 + n = nodes[n].next;
110.261 + }
110.262 + e.id = -1;
110.263 + }
110.264 +
110.265 + void next(Edge& e) const {
110.266 + int n = arcs[e.id * 2].target;
110.267 + e.id = arcs[(e.id * 2) | 1].next_out;
110.268 + while ((e.id & 1) != 1) {
110.269 + e.id = arcs[e.id].next_out;
110.270 + }
110.271 + if (e.id != -1) {
110.272 + e.id /= 2;
110.273 + return;
110.274 + }
110.275 + n = nodes[n].next;
110.276 + while (n != -1) {
110.277 + e.id = nodes[n].first_out;
110.278 + while ((e.id & 1) != 1) {
110.279 + e.id = arcs[e.id].next_out;
110.280 + }
110.281 + if (e.id != -1) {
110.282 + e.id /= 2;
110.283 + return;
110.284 + }
110.285 + n = nodes[n].next;
110.286 + }
110.287 + e.id = -1;
110.288 + }
110.289 +
110.290 + void firstOut(Arc &e, const Node& v) const {
110.291 + e.id = nodes[v.id].first_out;
110.292 + }
110.293 + void nextOut(Arc &e) const {
110.294 + e.id = arcs[e.id].next_out;
110.295 + }
110.296 +
110.297 + void firstIn(Arc &e, const Node& v) const {
110.298 + e.id = ((nodes[v.id].first_out) ^ 1);
110.299 + if (e.id == -2) e.id = -1;
110.300 + }
110.301 + void nextIn(Arc &e) const {
110.302 + e.id = ((arcs[e.id ^ 1].next_out) ^ 1);
110.303 + if (e.id == -2) e.id = -1;
110.304 + }
110.305 +
110.306 + void firstInc(Edge &e, bool& d, const Node& v) const {
110.307 + int a = nodes[v.id].first_out;
110.308 + if (a != -1 ) {
110.309 + e.id = a / 2;
110.310 + d = ((a & 1) == 1);
110.311 + } else {
110.312 + e.id = -1;
110.313 + d = true;
110.314 + }
110.315 + }
110.316 + void nextInc(Edge &e, bool& d) const {
110.317 + int a = (arcs[(e.id * 2) | (d ? 1 : 0)].next_out);
110.318 + if (a != -1 ) {
110.319 + e.id = a / 2;
110.320 + d = ((a & 1) == 1);
110.321 + } else {
110.322 + e.id = -1;
110.323 + d = true;
110.324 + }
110.325 + }
110.326 +
110.327 + static int id(Node v) { return v.id; }
110.328 + int id(RedNode v) const { return nodes[v.id].partition_index; }
110.329 + int id(BlueNode v) const { return nodes[v.id].partition_index; }
110.330 + static int id(Arc e) { return e.id; }
110.331 + static int id(Edge e) { return e.id; }
110.332 +
110.333 + static Node nodeFromId(int id) { return Node(id);}
110.334 + static Arc arcFromId(int id) { return Arc(id);}
110.335 + static Edge edgeFromId(int id) { return Edge(id);}
110.336 +
110.337 + bool valid(Node n) const {
110.338 + return n.id >= 0 && n.id < static_cast<int>(nodes.size()) &&
110.339 + nodes[n.id].prev != -2;
110.340 + }
110.341 +
110.342 + bool valid(Arc a) const {
110.343 + return a.id >= 0 && a.id < static_cast<int>(arcs.size()) &&
110.344 + arcs[a.id].prev_out != -2;
110.345 + }
110.346 +
110.347 + bool valid(Edge e) const {
110.348 + return e.id >= 0 && 2 * e.id < static_cast<int>(arcs.size()) &&
110.349 + arcs[2 * e.id].prev_out != -2;
110.350 + }
110.351 +
110.352 + RedNode addRedNode() {
110.353 + int n;
110.354 +
110.355 + if(first_free_red==-1) {
110.356 + n = nodes.size();
110.357 + nodes.push_back(NodeT());
110.358 + nodes[n].partition_index = ++max_red;
110.359 + nodes[n].red = true;
110.360 + } else {
110.361 + n = first_free_red;
110.362 + first_free_red = nodes[n].next;
110.363 + }
110.364 +
110.365 + nodes[n].next = first_node;
110.366 + if (first_node != -1) nodes[first_node].prev = n;
110.367 + first_node = n;
110.368 + nodes[n].prev = -1;
110.369 +
110.370 + nodes[n].partition_next = first_red;
110.371 + if (first_red != -1) nodes[first_red].partition_prev = n;
110.372 + first_red = n;
110.373 + nodes[n].partition_prev = -1;
110.374 +
110.375 + nodes[n].first_out = -1;
110.376 +
110.377 + return RedNode(n);
110.378 + }
110.379 +
110.380 + BlueNode addBlueNode() {
110.381 + int n;
110.382 +
110.383 + if(first_free_blue==-1) {
110.384 + n = nodes.size();
110.385 + nodes.push_back(NodeT());
110.386 + nodes[n].partition_index = ++max_blue;
110.387 + nodes[n].red = false;
110.388 + } else {
110.389 + n = first_free_blue;
110.390 + first_free_blue = nodes[n].next;
110.391 + }
110.392 +
110.393 + nodes[n].next = first_node;
110.394 + if (first_node != -1) nodes[first_node].prev = n;
110.395 + first_node = n;
110.396 + nodes[n].prev = -1;
110.397 +
110.398 + nodes[n].partition_next = first_blue;
110.399 + if (first_blue != -1) nodes[first_blue].partition_prev = n;
110.400 + first_blue = n;
110.401 + nodes[n].partition_prev = -1;
110.402 +
110.403 + nodes[n].first_out = -1;
110.404 +
110.405 + return BlueNode(n);
110.406 + }
110.407 +
110.408 + Edge addEdge(Node u, Node v) {
110.409 + int n;
110.410 +
110.411 + if (first_free_arc == -1) {
110.412 + n = arcs.size();
110.413 + arcs.push_back(ArcT());
110.414 + arcs.push_back(ArcT());
110.415 + } else {
110.416 + n = first_free_arc;
110.417 + first_free_arc = arcs[n].next_out;
110.418 + }
110.419 +
110.420 + arcs[n].target = u.id;
110.421 + arcs[n | 1].target = v.id;
110.422 +
110.423 + arcs[n].next_out = nodes[v.id].first_out;
110.424 + if (nodes[v.id].first_out != -1) {
110.425 + arcs[nodes[v.id].first_out].prev_out = n;
110.426 + }
110.427 + arcs[n].prev_out = -1;
110.428 + nodes[v.id].first_out = n;
110.429 +
110.430 + arcs[n | 1].next_out = nodes[u.id].first_out;
110.431 + if (nodes[u.id].first_out != -1) {
110.432 + arcs[nodes[u.id].first_out].prev_out = (n | 1);
110.433 + }
110.434 + arcs[n | 1].prev_out = -1;
110.435 + nodes[u.id].first_out = (n | 1);
110.436 +
110.437 + return Edge(n / 2);
110.438 + }
110.439 +
110.440 + void erase(const Node& node) {
110.441 + int n = node.id;
110.442 +
110.443 + if(nodes[n].next != -1) {
110.444 + nodes[nodes[n].next].prev = nodes[n].prev;
110.445 + }
110.446 +
110.447 + if(nodes[n].prev != -1) {
110.448 + nodes[nodes[n].prev].next = nodes[n].next;
110.449 + } else {
110.450 + first_node = nodes[n].next;
110.451 + }
110.452 +
110.453 + if (nodes[n].partition_next != -1) {
110.454 + nodes[nodes[n].partition_next].partition_prev = nodes[n].partition_prev;
110.455 + }
110.456 +
110.457 + if (nodes[n].partition_prev != -1) {
110.458 + nodes[nodes[n].partition_prev].partition_next = nodes[n].partition_next;
110.459 + } else {
110.460 + if (nodes[n].red) {
110.461 + first_red = nodes[n].partition_next;
110.462 + } else {
110.463 + first_blue = nodes[n].partition_next;
110.464 + }
110.465 + }
110.466 +
110.467 + if (nodes[n].red) {
110.468 + nodes[n].next = first_free_red;
110.469 + first_free_red = n;
110.470 + } else {
110.471 + nodes[n].next = first_free_blue;
110.472 + first_free_blue = n;
110.473 + }
110.474 + nodes[n].prev = -2;
110.475 + }
110.476 +
110.477 + void erase(const Edge& edge) {
110.478 + int n = edge.id * 2;
110.479 +
110.480 + if (arcs[n].next_out != -1) {
110.481 + arcs[arcs[n].next_out].prev_out = arcs[n].prev_out;
110.482 + }
110.483 +
110.484 + if (arcs[n].prev_out != -1) {
110.485 + arcs[arcs[n].prev_out].next_out = arcs[n].next_out;
110.486 + } else {
110.487 + nodes[arcs[n | 1].target].first_out = arcs[n].next_out;
110.488 + }
110.489 +
110.490 + if (arcs[n | 1].next_out != -1) {
110.491 + arcs[arcs[n | 1].next_out].prev_out = arcs[n | 1].prev_out;
110.492 + }
110.493 +
110.494 + if (arcs[n | 1].prev_out != -1) {
110.495 + arcs[arcs[n | 1].prev_out].next_out = arcs[n | 1].next_out;
110.496 + } else {
110.497 + nodes[arcs[n].target].first_out = arcs[n | 1].next_out;
110.498 + }
110.499 +
110.500 + arcs[n].next_out = first_free_arc;
110.501 + first_free_arc = n;
110.502 + arcs[n].prev_out = -2;
110.503 + arcs[n | 1].prev_out = -2;
110.504 +
110.505 + }
110.506 +
110.507 + void clear() {
110.508 + arcs.clear();
110.509 + nodes.clear();
110.510 + first_node = first_free_arc = first_red = first_blue =
110.511 + max_red = max_blue = first_free_red = first_free_blue = -1;
110.512 + }
110.513 +
110.514 + protected:
110.515 +
110.516 + void changeRed(Edge e, RedNode n) {
110.517 + if(arcs[(2 * e.id) | 1].next_out != -1) {
110.518 + arcs[arcs[(2 * e.id) | 1].next_out].prev_out =
110.519 + arcs[(2 * e.id) | 1].prev_out;
110.520 + }
110.521 + if(arcs[(2 * e.id) | 1].prev_out != -1) {
110.522 + arcs[arcs[(2 * e.id) | 1].prev_out].next_out =
110.523 + arcs[(2 * e.id) | 1].next_out;
110.524 + } else {
110.525 + nodes[arcs[2 * e.id].target].first_out =
110.526 + arcs[(2 * e.id) | 1].next_out;
110.527 + }
110.528 +
110.529 + if (nodes[n.id].first_out != -1) {
110.530 + arcs[nodes[n.id].first_out].prev_out = ((2 * e.id) | 1);
110.531 + }
110.532 + arcs[2 * e.id].target = n.id;
110.533 + arcs[(2 * e.id) | 1].prev_out = -1;
110.534 + arcs[(2 * e.id) | 1].next_out = nodes[n.id].first_out;
110.535 + nodes[n.id].first_out = ((2 * e.id) | 1);
110.536 + }
110.537 +
110.538 + void changeBlue(Edge e, BlueNode n) {
110.539 + if(arcs[2 * e.id].next_out != -1) {
110.540 + arcs[arcs[2 * e.id].next_out].prev_out = arcs[2 * e.id].prev_out;
110.541 + }
110.542 + if(arcs[2 * e.id].prev_out != -1) {
110.543 + arcs[arcs[2 * e.id].prev_out].next_out =
110.544 + arcs[2 * e.id].next_out;
110.545 + } else {
110.546 + nodes[arcs[(2 * e.id) | 1].target].first_out =
110.547 + arcs[2 * e.id].next_out;
110.548 + }
110.549 +
110.550 + if (nodes[n.id].first_out != -1) {
110.551 + arcs[nodes[n.id].first_out].prev_out = 2 * e.id;
110.552 + }
110.553 + arcs[(2 * e.id) | 1].target = n.id;
110.554 + arcs[2 * e.id].prev_out = -1;
110.555 + arcs[2 * e.id].next_out = nodes[n.id].first_out;
110.556 + nodes[n.id].first_out = 2 * e.id;
110.557 + }
110.558 +
110.559 + };
110.560 +
110.561 + typedef BpGraphExtender<ListBpGraphBase> ExtendedListBpGraphBase;
110.562 +
110.563 +
110.564 + /// \addtogroup graphs
110.565 + /// @{
110.566 +
110.567 + ///A general undirected graph structure.
110.568 +
110.569 + ///\ref ListBpGraph is a versatile and fast undirected graph
110.570 + ///implementation based on linked lists that are stored in
110.571 + ///\c std::vector structures.
110.572 + ///
110.573 + ///This type fully conforms to the \ref concepts::BpGraph "BpGraph concept"
110.574 + ///and it also provides several useful additional functionalities.
110.575 + ///Most of its member functions and nested classes are documented
110.576 + ///only in the concept class.
110.577 + ///
110.578 + ///This class provides only linear time counting for nodes, edges and arcs.
110.579 + ///
110.580 + ///\sa concepts::BpGraph
110.581 + ///\sa ListDigraph
110.582 + class ListBpGraph : public ExtendedListBpGraphBase {
110.583 + typedef ExtendedListBpGraphBase Parent;
110.584 +
110.585 + private:
110.586 + /// BpGraphs are \e not copy constructible. Use BpGraphCopy instead.
110.587 + ListBpGraph(const ListBpGraph &) :ExtendedListBpGraphBase() {};
110.588 + /// \brief Assignment of a graph to another one is \e not allowed.
110.589 + /// Use BpGraphCopy instead.
110.590 + void operator=(const ListBpGraph &) {}
110.591 + public:
110.592 + /// Constructor
110.593 +
110.594 + /// Constructor.
110.595 + ///
110.596 + ListBpGraph() {}
110.597 +
110.598 + typedef Parent::OutArcIt IncEdgeIt;
110.599 +
110.600 + /// \brief Add a new red node to the graph.
110.601 + ///
110.602 + /// This function adds a red new node to the graph.
110.603 + /// \return The new node.
110.604 + RedNode addRedNode() { return Parent::addRedNode(); }
110.605 +
110.606 + /// \brief Add a new blue node to the graph.
110.607 + ///
110.608 + /// This function adds a blue new node to the graph.
110.609 + /// \return The new node.
110.610 + BlueNode addBlueNode() { return Parent::addBlueNode(); }
110.611 +
110.612 + /// \brief Add a new edge to the graph.
110.613 + ///
110.614 + /// This function adds a new edge to the graph between nodes
110.615 + /// \c u and \c v with inherent orientation from node \c u to
110.616 + /// node \c v.
110.617 + /// \return The new edge.
110.618 + Edge addEdge(RedNode u, BlueNode v) {
110.619 + return Parent::addEdge(u, v);
110.620 + }
110.621 + Edge addEdge(BlueNode v, RedNode u) {
110.622 + return Parent::addEdge(u, v);
110.623 + }
110.624 +
110.625 + ///\brief Erase a node from the graph.
110.626 + ///
110.627 + /// This function erases the given node along with its incident arcs
110.628 + /// from the graph.
110.629 + ///
110.630 + /// \note All iterators referencing the removed node or the incident
110.631 + /// edges are invalidated, of course.
110.632 + void erase(Node n) { Parent::erase(n); }
110.633 +
110.634 + ///\brief Erase an edge from the graph.
110.635 + ///
110.636 + /// This function erases the given edge from the graph.
110.637 + ///
110.638 + /// \note All iterators referencing the removed edge are invalidated,
110.639 + /// of course.
110.640 + void erase(Edge e) { Parent::erase(e); }
110.641 + /// Node validity check
110.642 +
110.643 + /// This function gives back \c true if the given node is valid,
110.644 + /// i.e. it is a real node of the graph.
110.645 + ///
110.646 + /// \warning A removed node could become valid again if new nodes are
110.647 + /// added to the graph.
110.648 + bool valid(Node n) const { return Parent::valid(n); }
110.649 + /// Edge validity check
110.650 +
110.651 + /// This function gives back \c true if the given edge is valid,
110.652 + /// i.e. it is a real edge of the graph.
110.653 + ///
110.654 + /// \warning A removed edge could become valid again if new edges are
110.655 + /// added to the graph.
110.656 + bool valid(Edge e) const { return Parent::valid(e); }
110.657 + /// Arc validity check
110.658 +
110.659 + /// This function gives back \c true if the given arc is valid,
110.660 + /// i.e. it is a real arc of the graph.
110.661 + ///
110.662 + /// \warning A removed arc could become valid again if new edges are
110.663 + /// added to the graph.
110.664 + bool valid(Arc a) const { return Parent::valid(a); }
110.665 +
110.666 + /// \brief Change the red node of an edge.
110.667 + ///
110.668 + /// This function changes the red node of the given edge \c e to \c n.
110.669 + ///
110.670 + ///\note \c EdgeIt and \c ArcIt iterators referencing the
110.671 + ///changed edge are invalidated and all other iterators whose
110.672 + ///base node is the changed node are also invalidated.
110.673 + ///
110.674 + ///\warning This functionality cannot be used together with the
110.675 + ///Snapshot feature.
110.676 + void changeRed(Edge e, RedNode n) {
110.677 + Parent::changeRed(e, n);
110.678 + }
110.679 + /// \brief Change the blue node of an edge.
110.680 + ///
110.681 + /// This function changes the blue node of the given edge \c e to \c n.
110.682 + ///
110.683 + ///\note \c EdgeIt iterators referencing the changed edge remain
110.684 + ///valid, but \c ArcIt iterators referencing the changed edge and
110.685 + ///all other iterators whose base node is the changed node are also
110.686 + ///invalidated.
110.687 + ///
110.688 + ///\warning This functionality cannot be used together with the
110.689 + ///Snapshot feature.
110.690 + void changeBlue(Edge e, BlueNode n) {
110.691 + Parent::changeBlue(e, n);
110.692 + }
110.693 +
110.694 + ///Clear the graph.
110.695 +
110.696 + ///This function erases all nodes and arcs from the graph.
110.697 + ///
110.698 + ///\note All iterators of the graph are invalidated, of course.
110.699 + void clear() {
110.700 + Parent::clear();
110.701 + }
110.702 +
110.703 + /// Reserve memory for nodes.
110.704 +
110.705 + /// Using this function, it is possible to avoid superfluous memory
110.706 + /// allocation: if you know that the graph you want to build will
110.707 + /// be large (e.g. it will contain millions of nodes and/or edges),
110.708 + /// then it is worth reserving space for this amount before starting
110.709 + /// to build the graph.
110.710 + /// \sa reserveEdge()
110.711 + void reserveNode(int n) { nodes.reserve(n); };
110.712 +
110.713 + /// Reserve memory for edges.
110.714 +
110.715 + /// Using this function, it is possible to avoid superfluous memory
110.716 + /// allocation: if you know that the graph you want to build will
110.717 + /// be large (e.g. it will contain millions of nodes and/or edges),
110.718 + /// then it is worth reserving space for this amount before starting
110.719 + /// to build the graph.
110.720 + /// \sa reserveNode()
110.721 + void reserveEdge(int m) { arcs.reserve(2 * m); };
110.722 +
110.723 + /// \brief Class to make a snapshot of the graph and restore
110.724 + /// it later.
110.725 + ///
110.726 + /// Class to make a snapshot of the graph and restore it later.
110.727 + ///
110.728 + /// The newly added nodes and edges can be removed
110.729 + /// using the restore() function.
110.730 + ///
110.731 + /// \note After a state is restored, you cannot restore a later state,
110.732 + /// i.e. you cannot add the removed nodes and edges again using
110.733 + /// another Snapshot instance.
110.734 + ///
110.735 + /// \warning Node and edge deletions and other modifications
110.736 + /// (e.g. changing the end-nodes of edges or contracting nodes)
110.737 + /// cannot be restored. These events invalidate the snapshot.
110.738 + /// However, the edges and nodes that were added to the graph after
110.739 + /// making the current snapshot can be removed without invalidating it.
110.740 + class Snapshot {
110.741 + protected:
110.742 +
110.743 + typedef Parent::NodeNotifier NodeNotifier;
110.744 +
110.745 + class NodeObserverProxy : public NodeNotifier::ObserverBase {
110.746 + public:
110.747 +
110.748 + NodeObserverProxy(Snapshot& _snapshot)
110.749 + : snapshot(_snapshot) {}
110.750 +
110.751 + using NodeNotifier::ObserverBase::attach;
110.752 + using NodeNotifier::ObserverBase::detach;
110.753 + using NodeNotifier::ObserverBase::attached;
110.754 +
110.755 + protected:
110.756 +
110.757 + virtual void add(const Node& node) {
110.758 + snapshot.addNode(node);
110.759 + }
110.760 + virtual void add(const std::vector<Node>& nodes) {
110.761 + for (int i = nodes.size() - 1; i >= 0; --i) {
110.762 + snapshot.addNode(nodes[i]);
110.763 + }
110.764 + }
110.765 + virtual void erase(const Node& node) {
110.766 + snapshot.eraseNode(node);
110.767 + }
110.768 + virtual void erase(const std::vector<Node>& nodes) {
110.769 + for (int i = 0; i < int(nodes.size()); ++i) {
110.770 + snapshot.eraseNode(nodes[i]);
110.771 + }
110.772 + }
110.773 + virtual void build() {
110.774 + Node node;
110.775 + std::vector<Node> nodes;
110.776 + for (notifier()->first(node); node != INVALID;
110.777 + notifier()->next(node)) {
110.778 + nodes.push_back(node);
110.779 + }
110.780 + for (int i = nodes.size() - 1; i >= 0; --i) {
110.781 + snapshot.addNode(nodes[i]);
110.782 + }
110.783 + }
110.784 + virtual void clear() {
110.785 + Node node;
110.786 + for (notifier()->first(node); node != INVALID;
110.787 + notifier()->next(node)) {
110.788 + snapshot.eraseNode(node);
110.789 + }
110.790 + }
110.791 +
110.792 + Snapshot& snapshot;
110.793 + };
110.794 +
110.795 + class EdgeObserverProxy : public EdgeNotifier::ObserverBase {
110.796 + public:
110.797 +
110.798 + EdgeObserverProxy(Snapshot& _snapshot)
110.799 + : snapshot(_snapshot) {}
110.800 +
110.801 + using EdgeNotifier::ObserverBase::attach;
110.802 + using EdgeNotifier::ObserverBase::detach;
110.803 + using EdgeNotifier::ObserverBase::attached;
110.804 +
110.805 + protected:
110.806 +
110.807 + virtual void add(const Edge& edge) {
110.808 + snapshot.addEdge(edge);
110.809 + }
110.810 + virtual void add(const std::vector<Edge>& edges) {
110.811 + for (int i = edges.size() - 1; i >= 0; --i) {
110.812 + snapshot.addEdge(edges[i]);
110.813 + }
110.814 + }
110.815 + virtual void erase(const Edge& edge) {
110.816 + snapshot.eraseEdge(edge);
110.817 + }
110.818 + virtual void erase(const std::vector<Edge>& edges) {
110.819 + for (int i = 0; i < int(edges.size()); ++i) {
110.820 + snapshot.eraseEdge(edges[i]);
110.821 + }
110.822 + }
110.823 + virtual void build() {
110.824 + Edge edge;
110.825 + std::vector<Edge> edges;
110.826 + for (notifier()->first(edge); edge != INVALID;
110.827 + notifier()->next(edge)) {
110.828 + edges.push_back(edge);
110.829 + }
110.830 + for (int i = edges.size() - 1; i >= 0; --i) {
110.831 + snapshot.addEdge(edges[i]);
110.832 + }
110.833 + }
110.834 + virtual void clear() {
110.835 + Edge edge;
110.836 + for (notifier()->first(edge); edge != INVALID;
110.837 + notifier()->next(edge)) {
110.838 + snapshot.eraseEdge(edge);
110.839 + }
110.840 + }
110.841 +
110.842 + Snapshot& snapshot;
110.843 + };
110.844 +
110.845 + ListBpGraph *graph;
110.846 +
110.847 + NodeObserverProxy node_observer_proxy;
110.848 + EdgeObserverProxy edge_observer_proxy;
110.849 +
110.850 + std::list<Node> added_nodes;
110.851 + std::list<Edge> added_edges;
110.852 +
110.853 +
110.854 + void addNode(const Node& node) {
110.855 + added_nodes.push_front(node);
110.856 + }
110.857 + void eraseNode(const Node& node) {
110.858 + std::list<Node>::iterator it =
110.859 + std::find(added_nodes.begin(), added_nodes.end(), node);
110.860 + if (it == added_nodes.end()) {
110.861 + clear();
110.862 + edge_observer_proxy.detach();
110.863 + throw NodeNotifier::ImmediateDetach();
110.864 + } else {
110.865 + added_nodes.erase(it);
110.866 + }
110.867 + }
110.868 +
110.869 + void addEdge(const Edge& edge) {
110.870 + added_edges.push_front(edge);
110.871 + }
110.872 + void eraseEdge(const Edge& edge) {
110.873 + std::list<Edge>::iterator it =
110.874 + std::find(added_edges.begin(), added_edges.end(), edge);
110.875 + if (it == added_edges.end()) {
110.876 + clear();
110.877 + node_observer_proxy.detach();
110.878 + throw EdgeNotifier::ImmediateDetach();
110.879 + } else {
110.880 + added_edges.erase(it);
110.881 + }
110.882 + }
110.883 +
110.884 + void attach(ListBpGraph &_graph) {
110.885 + graph = &_graph;
110.886 + node_observer_proxy.attach(graph->notifier(Node()));
110.887 + edge_observer_proxy.attach(graph->notifier(Edge()));
110.888 + }
110.889 +
110.890 + void detach() {
110.891 + node_observer_proxy.detach();
110.892 + edge_observer_proxy.detach();
110.893 + }
110.894 +
110.895 + bool attached() const {
110.896 + return node_observer_proxy.attached();
110.897 + }
110.898 +
110.899 + void clear() {
110.900 + added_nodes.clear();
110.901 + added_edges.clear();
110.902 + }
110.903 +
110.904 + public:
110.905 +
110.906 + /// \brief Default constructor.
110.907 + ///
110.908 + /// Default constructor.
110.909 + /// You have to call save() to actually make a snapshot.
110.910 + Snapshot()
110.911 + : graph(0), node_observer_proxy(*this),
110.912 + edge_observer_proxy(*this) {}
110.913 +
110.914 + /// \brief Constructor that immediately makes a snapshot.
110.915 + ///
110.916 + /// This constructor immediately makes a snapshot of the given graph.
110.917 + Snapshot(ListBpGraph &gr)
110.918 + : node_observer_proxy(*this),
110.919 + edge_observer_proxy(*this) {
110.920 + attach(gr);
110.921 + }
110.922 +
110.923 + /// \brief Make a snapshot.
110.924 + ///
110.925 + /// This function makes a snapshot of the given graph.
110.926 + /// It can be called more than once. In case of a repeated
110.927 + /// call, the previous snapshot gets lost.
110.928 + void save(ListBpGraph &gr) {
110.929 + if (attached()) {
110.930 + detach();
110.931 + clear();
110.932 + }
110.933 + attach(gr);
110.934 + }
110.935 +
110.936 + /// \brief Undo the changes until the last snapshot.
110.937 + ///
110.938 + /// This function undos the changes until the last snapshot
110.939 + /// created by save() or Snapshot(ListBpGraph&).
110.940 + ///
110.941 + /// \warning This method invalidates the snapshot, i.e. repeated
110.942 + /// restoring is not supported unless you call save() again.
110.943 + void restore() {
110.944 + detach();
110.945 + for(std::list<Edge>::iterator it = added_edges.begin();
110.946 + it != added_edges.end(); ++it) {
110.947 + graph->erase(*it);
110.948 + }
110.949 + for(std::list<Node>::iterator it = added_nodes.begin();
110.950 + it != added_nodes.end(); ++it) {
110.951 + graph->erase(*it);
110.952 + }
110.953 + clear();
110.954 + }
110.955 +
110.956 + /// \brief Returns \c true if the snapshot is valid.
110.957 + ///
110.958 + /// This function returns \c true if the snapshot is valid.
110.959 + bool valid() const {
110.960 + return attached();
110.961 + }
110.962 + };
110.963 + };
110.964 +
110.965 + /// @}
110.966 } //namespace lemon
110.967
110.968
111.1 --- a/lemon/lp.h Mon Jul 16 16:21:40 2018 +0200
111.2 +++ b/lemon/lp.h Wed Oct 17 19:14:07 2018 +0200
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-2010
111.8 + * Copyright (C) 2003-2013
111.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
111.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
111.11 *
111.12 @@ -22,15 +22,21 @@
111.13 #include<lemon/config.h>
111.14
111.15
111.16 -#ifdef LEMON_HAVE_GLPK
111.17 +#if LEMON_DEFAULT_LP == LEMON_GLPK_ || LEMON_DEFAULT_MIP == LEMON_GLPK_
111.18 #include <lemon/glpk.h>
111.19 -#elif LEMON_HAVE_CPLEX
111.20 +#endif
111.21 +#if LEMON_DEFAULT_LP == LEMON_CPLEX_ || LEMON_DEFAULT_MIP == LEMON_CPLEX_
111.22 #include <lemon/cplex.h>
111.23 -#elif LEMON_HAVE_SOPLEX
111.24 +#endif
111.25 +#if LEMON_DEFAULT_LP == LEMON_SOPLEX_
111.26 #include <lemon/soplex.h>
111.27 -#elif LEMON_HAVE_CLP
111.28 +#endif
111.29 +#if LEMON_DEFAULT_LP == LEMON_CLP_
111.30 #include <lemon/clp.h>
111.31 #endif
111.32 +#if LEMON_DEFAULT_MIP == LEMON_CBC_
111.33 +#include <lemon/cbc.h>
111.34 +#endif
111.35
111.36 ///\file
111.37 ///\brief Defines a default LP solver
111.38 @@ -43,8 +49,8 @@
111.39 ///The default LP solver identifier.
111.40 ///\ingroup lp_group
111.41 ///
111.42 - ///Currently, the possible values are \c GLPK, \c CPLEX,
111.43 - ///\c SOPLEX or \c CLP
111.44 + ///Currently, the possible values are \c LEMON_GLPK_, \c LEMON_CPLEX_,
111.45 + ///\c LEMON_SOPLEX_ or \c LEMON_CLP_
111.46 #define LEMON_DEFAULT_LP SOLVER
111.47 ///The default LP solver
111.48
111.49 @@ -59,32 +65,32 @@
111.50 ///The default MIP solver identifier.
111.51 ///\ingroup lp_group
111.52 ///
111.53 - ///Currently, the possible values are \c GLPK or \c CPLEX
111.54 + ///Currently, the possible values are \c LEMON_GLPK_, \c LEMON_CPLEX_
111.55 + ///or \c LEMON_CBC_
111.56 #define LEMON_DEFAULT_MIP SOLVER
111.57 ///The default MIP solver.
111.58
111.59 ///The default MIP solver.
111.60 ///\ingroup lp_group
111.61 ///
111.62 - ///Currently, it is either \c GlpkMip or \c CplexMip
111.63 + ///Currently, it is either \c GlpkMip, \c CplexMip , \c CbcMip
111.64 typedef GlpkMip Mip;
111.65 #else
111.66 -#ifdef LEMON_HAVE_GLPK
111.67 -# define LEMON_DEFAULT_LP GLPK
111.68 +#if LEMON_DEFAULT_LP == LEMON_GLPK_
111.69 typedef GlpkLp Lp;
111.70 -# define LEMON_DEFAULT_MIP GLPK
111.71 +#elif LEMON_DEFAULT_LP == LEMON_CPLEX_
111.72 + typedef CplexLp Lp;
111.73 +#elif LEMON_DEFAULT_LP == LEMON_SOPLEX_
111.74 + typedef SoplexLp Lp;
111.75 +#elif LEMON_DEFAULT_LP == LEMON_CLP_
111.76 + typedef ClpLp Lp;
111.77 +#endif
111.78 +#if LEMON_DEFAULT_MIP == LEMON_GLPK_
111.79 typedef GlpkMip Mip;
111.80 -#elif LEMON_HAVE_CPLEX
111.81 -# define LEMON_DEFAULT_LP CPLEX
111.82 - typedef CplexLp Lp;
111.83 -# define LEMON_DEFAULT_MIP CPLEX
111.84 +#elif LEMON_DEFAULT_MIP == LEMON_CPLEX_
111.85 typedef CplexMip Mip;
111.86 -#elif LEMON_HAVE_SOPLEX
111.87 -# define DEFAULT_LP SOPLEX
111.88 - typedef SoplexLp Lp;
111.89 -#elif LEMON_HAVE_CLP
111.90 -# define DEFAULT_LP CLP
111.91 - typedef ClpLp Lp;
111.92 +#elif LEMON_DEFAULT_MIP == LEMON_CBC_
111.93 + typedef CbcMip Mip;
111.94 #endif
111.95 #endif
111.96
112.1 --- a/lemon/lp_base.cc Mon Jul 16 16:21:40 2018 +0200
112.2 +++ b/lemon/lp_base.cc Wed Oct 17 19:14:07 2018 +0200
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-2010
112.8 + * Copyright (C) 2003-2013
112.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
112.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
112.11 *
113.1 --- a/lemon/lp_base.h Mon Jul 16 16:21:40 2018 +0200
113.2 +++ b/lemon/lp_base.h Wed Oct 17 19:14:07 2018 +0200
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-2010
113.8 + * Copyright (C) 2003-2013
113.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
113.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
113.11 *
113.12 @@ -1007,6 +1007,36 @@
113.13
113.14 public:
113.15
113.16 + ///Unsupported file format exception
113.17 + class UnsupportedFormatError : public Exception
113.18 + {
113.19 + std::string _format;
113.20 + mutable std::string _what;
113.21 + public:
113.22 + explicit UnsupportedFormatError(std::string format) throw()
113.23 + : _format(format) { }
113.24 + virtual ~UnsupportedFormatError() throw() {}
113.25 + virtual const char* what() const throw() {
113.26 + try {
113.27 + _what.clear();
113.28 + std::ostringstream oss;
113.29 + oss << "lemon::UnsupportedFormatError: " << _format;
113.30 + _what = oss.str();
113.31 + }
113.32 + catch (...) {}
113.33 + if (!_what.empty()) return _what.c_str();
113.34 + else return "lemon::UnsupportedFormatError";
113.35 + }
113.36 + };
113.37 +
113.38 + protected:
113.39 + virtual void _write(std::string, std::string format) const
113.40 + {
113.41 + throw UnsupportedFormatError(format);
113.42 + }
113.43 +
113.44 + public:
113.45 +
113.46 /// Virtual destructor
113.47 virtual ~LpBase() {}
113.48
113.49 @@ -1555,12 +1585,27 @@
113.50 ///Set the sense to maximization
113.51 void min() { _setSense(MIN); }
113.52
113.53 - ///Clears the problem
113.54 + ///Clear the problem
113.55 void clear() { _clear(); rows.clear(); cols.clear(); }
113.56
113.57 - /// Sets the message level of the solver
113.58 + /// Set the message level of the solver
113.59 void messageLevel(MessageLevel level) { _messageLevel(level); }
113.60
113.61 + /// Write the problem to a file in the given format
113.62 +
113.63 + /// This function writes the problem to a file in the given format.
113.64 + /// Different solver backends may support different formats.
113.65 + /// Trying to write in an unsupported format will trigger
113.66 + /// \ref UnsupportedFormatError. For the supported formats,
113.67 + /// visit the documentation of the base class of the related backends
113.68 + /// (\ref CplexBase, \ref GlpkBase etc.)
113.69 + /// \param file The file path
113.70 + /// \param format The output file format.
113.71 + void write(std::string file, std::string format = "MPS") const
113.72 + {
113.73 + _write(file.c_str(),format.c_str());
113.74 + }
113.75 +
113.76 ///@}
113.77
113.78 };
114.1 --- a/lemon/lp_skeleton.cc Mon Jul 16 16:21:40 2018 +0200
114.2 +++ b/lemon/lp_skeleton.cc Wed Oct 17 19:14:07 2018 +0200
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-2010
114.8 + * Copyright (C) 2003-2013
114.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
114.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
114.11 *
114.12 @@ -91,6 +91,8 @@
114.13
114.14 void SkeletonSolverBase::_messageLevel(MessageLevel) {}
114.15
114.16 + void SkeletonSolverBase::_write(std::string, std::string) const {}
114.17 +
114.18 LpSkeleton::SolveExitStatus LpSkeleton::_solve() { return SOLVED; }
114.19
114.20 LpSkeleton::Value LpSkeleton::_getPrimal(int) const { return 0; }
115.1 --- a/lemon/lp_skeleton.h Mon Jul 16 16:21:40 2018 +0200
115.2 +++ b/lemon/lp_skeleton.h Wed Oct 17 19:14:07 2018 +0200
115.3 @@ -2,7 +2,7 @@
115.4 *
115.5 * This file is a part of LEMON, a generic C++ optimization library.
115.6 *
115.7 - * Copyright (C) 2003-2010
115.8 + * Copyright (C) 2003-2013
115.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
115.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
115.11 *
115.12 @@ -144,6 +144,10 @@
115.13
115.14 ///\e
115.15 virtual void _messageLevel(MessageLevel);
115.16 +
115.17 + ///\e
115.18 + virtual void _write(std::string file, std::string format) const;
115.19 +
115.20 };
115.21
115.22 /// \brief Skeleton class for an LP solver interface
115.23 @@ -222,6 +226,7 @@
115.24
115.25 ///\e
115.26 virtual const char* _solverName() const;
115.27 +
115.28 };
115.29
115.30 } //namespace lemon
116.1 --- a/lemon/maps.h Mon Jul 16 16:21:40 2018 +0200
116.2 +++ b/lemon/maps.h Wed Oct 17 19:14:07 2018 +0200
116.3 @@ -2,7 +2,7 @@
116.4 *
116.5 * This file is a part of LEMON, a generic C++ optimization library.
116.6 *
116.7 - * Copyright (C) 2003-2010
116.8 + * Copyright (C) 2003-2013
116.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
116.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
116.11 *
117.1 --- a/lemon/matching.h Mon Jul 16 16:21:40 2018 +0200
117.2 +++ b/lemon/matching.h Wed Oct 17 19:14:07 2018 +0200
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-2010
117.8 + * Copyright (C) 2003-2013
117.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
117.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
117.11 *
118.1 --- a/lemon/math.h Mon Jul 16 16:21:40 2018 +0200
118.2 +++ b/lemon/math.h Wed Oct 17 19:14:07 2018 +0200
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-2010
118.8 + * Copyright (C) 2003-2013
118.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
118.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
118.11 *
118.12 @@ -65,8 +65,13 @@
118.13 return v!=v;
118.14 }
118.15
118.16 + ///Round a value to its closest integer
118.17 + inline double round(double r) {
118.18 + return (r > 0.0) ? std::floor(r + 0.5) : std::ceil(r - 0.5);
118.19 + }
118.20 +
118.21 /// @}
118.22
118.23 } //namespace lemon
118.24
118.25 -#endif //LEMON_TOLERANCE_H
118.26 +#endif //LEMON_MATH_H
119.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
119.2 +++ b/lemon/max_cardinality_search.h Wed Oct 17 19:14:07 2018 +0200
119.3 @@ -0,0 +1,794 @@
119.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
119.5 + *
119.6 + * This file is a part of LEMON, a generic C++ optimization library.
119.7 + *
119.8 + * Copyright (C) 2003-2013
119.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
119.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
119.11 + *
119.12 + * Permission to use, modify and distribute this software is granted
119.13 + * provided that this copyright notice appears in all copies. For
119.14 + * precise terms see the accompanying LICENSE file.
119.15 + *
119.16 + * This software is provided "AS IS" with no warranty of any kind,
119.17 + * express or implied, and with no claim as to its suitability for any
119.18 + * purpose.
119.19 + *
119.20 + */
119.21 +
119.22 +#ifndef LEMON_MAX_CARDINALITY_SEARCH_H
119.23 +#define LEMON_MAX_CARDINALITY_SEARCH_H
119.24 +
119.25 +
119.26 +/// \ingroup search
119.27 +/// \file
119.28 +/// \brief Maximum cardinality search in undirected digraphs.
119.29 +
119.30 +#include <lemon/bin_heap.h>
119.31 +#include <lemon/bucket_heap.h>
119.32 +
119.33 +#include <lemon/error.h>
119.34 +#include <lemon/maps.h>
119.35 +
119.36 +#include <functional>
119.37 +
119.38 +namespace lemon {
119.39 +
119.40 + /// \brief Default traits class of MaxCardinalitySearch class.
119.41 + ///
119.42 + /// Default traits class of MaxCardinalitySearch class.
119.43 + /// \param Digraph Digraph type.
119.44 + /// \param CapacityMap Type of capacity map.
119.45 + template <typename GR, typename CAP>
119.46 + struct MaxCardinalitySearchDefaultTraits {
119.47 + /// The digraph type the algorithm runs on.
119.48 + typedef GR Digraph;
119.49 +
119.50 + template <typename CM>
119.51 + struct CapMapSelector {
119.52 +
119.53 + typedef CM CapacityMap;
119.54 +
119.55 + static CapacityMap *createCapacityMap(const Digraph& g) {
119.56 + return new CapacityMap(g);
119.57 + }
119.58 + };
119.59 +
119.60 + template <typename CM>
119.61 + struct CapMapSelector<ConstMap<CM, Const<int, 1> > > {
119.62 +
119.63 + typedef ConstMap<CM, Const<int, 1> > CapacityMap;
119.64 +
119.65 + static CapacityMap *createCapacityMap(const Digraph&) {
119.66 + return new CapacityMap;
119.67 + }
119.68 + };
119.69 +
119.70 + /// \brief The type of the map that stores the arc capacities.
119.71 + ///
119.72 + /// The type of the map that stores the arc capacities.
119.73 + /// It must meet the \ref concepts::ReadMap "ReadMap" concept.
119.74 + typedef typename CapMapSelector<CAP>::CapacityMap CapacityMap;
119.75 +
119.76 + /// \brief The type of the capacity of the arcs.
119.77 + typedef typename CapacityMap::Value Value;
119.78 +
119.79 + /// \brief Instantiates a CapacityMap.
119.80 + ///
119.81 + /// This function instantiates a \ref CapacityMap.
119.82 + /// \param digraph is the digraph, to which we would like to define
119.83 + /// the CapacityMap.
119.84 + static CapacityMap *createCapacityMap(const Digraph& digraph) {
119.85 + return CapMapSelector<CapacityMap>::createCapacityMap(digraph);
119.86 + }
119.87 +
119.88 + /// \brief The cross reference type used by heap.
119.89 + ///
119.90 + /// The cross reference type used by heap.
119.91 + /// Usually it is \c Digraph::NodeMap<int>.
119.92 + typedef typename Digraph::template NodeMap<int> HeapCrossRef;
119.93 +
119.94 + /// \brief Instantiates a HeapCrossRef.
119.95 + ///
119.96 + /// This function instantiates a \ref HeapCrossRef.
119.97 + /// \param digraph is the digraph, to which we would like to define the
119.98 + /// HeapCrossRef.
119.99 + static HeapCrossRef *createHeapCrossRef(const Digraph &digraph) {
119.100 + return new HeapCrossRef(digraph);
119.101 + }
119.102 +
119.103 + template <typename CapacityMap>
119.104 + struct HeapSelector {
119.105 + template <typename Value, typename Ref>
119.106 + struct Selector {
119.107 + typedef BinHeap<Value, Ref, std::greater<Value> > Heap;
119.108 + };
119.109 + };
119.110 +
119.111 + template <typename CapacityKey>
119.112 + struct HeapSelector<ConstMap<CapacityKey, Const<int, 1> > > {
119.113 + template <typename Value, typename Ref>
119.114 + struct Selector {
119.115 + typedef BucketHeap<Ref, false > Heap;
119.116 + };
119.117 + };
119.118 +
119.119 + /// \brief The heap type used by MaxCardinalitySearch algorithm.
119.120 + ///
119.121 + /// The heap type used by MaxCardinalitySearch algorithm. It should
119.122 + /// maximalize the priorities. The default heap type is
119.123 + /// the \ref BinHeap, but it is specialized when the
119.124 + /// CapacityMap is ConstMap<Digraph::Node, Const<int, 1> >
119.125 + /// to BucketHeap.
119.126 + ///
119.127 + /// \sa MaxCardinalitySearch
119.128 + typedef typename HeapSelector<CapacityMap>
119.129 + ::template Selector<Value, HeapCrossRef>
119.130 + ::Heap Heap;
119.131 +
119.132 + /// \brief Instantiates a Heap.
119.133 + ///
119.134 + /// This function instantiates a \ref Heap.
119.135 + /// \param crossref The cross reference of the heap.
119.136 + static Heap *createHeap(HeapCrossRef& crossref) {
119.137 + return new Heap(crossref);
119.138 + }
119.139 +
119.140 + /// \brief The type of the map that stores whether a node is processed.
119.141 + ///
119.142 + /// The type of the map that stores whether a node is processed.
119.143 + /// It must meet the \ref concepts::WriteMap "WriteMap" concept.
119.144 + /// By default it is a NullMap.
119.145 + typedef NullMap<typename Digraph::Node, bool> ProcessedMap;
119.146 +
119.147 + /// \brief Instantiates a ProcessedMap.
119.148 + ///
119.149 + /// This function instantiates a \ref ProcessedMap.
119.150 + /// \param digraph is the digraph, to which
119.151 + /// we would like to define the \ref ProcessedMap
119.152 +#ifdef DOXYGEN
119.153 + static ProcessedMap *createProcessedMap(const Digraph &digraph)
119.154 +#else
119.155 + static ProcessedMap *createProcessedMap(const Digraph &)
119.156 +#endif
119.157 + {
119.158 + return new ProcessedMap();
119.159 + }
119.160 +
119.161 + /// \brief The type of the map that stores the cardinalities of the nodes.
119.162 + ///
119.163 + /// The type of the map that stores the cardinalities of the nodes.
119.164 + /// It must meet the \ref concepts::WriteMap "WriteMap" concept.
119.165 + typedef typename Digraph::template NodeMap<Value> CardinalityMap;
119.166 +
119.167 + /// \brief Instantiates a CardinalityMap.
119.168 + ///
119.169 + /// This function instantiates a \ref CardinalityMap.
119.170 + /// \param digraph is the digraph, to which we would like to
119.171 + /// define the \ref CardinalityMap
119.172 + static CardinalityMap *createCardinalityMap(const Digraph &digraph) {
119.173 + return new CardinalityMap(digraph);
119.174 + }
119.175 +
119.176 +
119.177 + };
119.178 +
119.179 + /// \ingroup search
119.180 + ///
119.181 + /// \brief Maximum Cardinality Search algorithm class.
119.182 + ///
119.183 + /// This class provides an efficient implementation of Maximum Cardinality
119.184 + /// Search algorithm. The maximum cardinality search first chooses any
119.185 + /// node of the digraph. Then every time it chooses one unprocessed node
119.186 + /// with maximum cardinality, i.e the sum of capacities on out arcs
119.187 + /// to the nodes
119.188 + /// which were previusly processed.
119.189 + /// If there is a cut in the digraph the algorithm should choose
119.190 + /// again any unprocessed node of the digraph.
119.191 +
119.192 + /// The arc capacities are passed to the algorithm using a
119.193 + /// \ref concepts::ReadMap "ReadMap", so it is easy to change it to any
119.194 + /// kind of capacity.
119.195 + ///
119.196 + /// The type of the capacity is determined by the \ref
119.197 + /// concepts::ReadMap::Value "Value" of the capacity map.
119.198 + ///
119.199 + /// It is also possible to change the underlying priority heap.
119.200 + ///
119.201 + ///
119.202 + /// \param GR The digraph type the algorithm runs on. The value of
119.203 + /// Digraph is not used directly by the search algorithm, it
119.204 + /// is only passed to \ref MaxCardinalitySearchDefaultTraits.
119.205 + /// \param CAP This read-only ArcMap determines the capacities of
119.206 + /// the arcs. It is read once for each arc, so the map may involve in
119.207 + /// relatively time consuming process to compute the arc capacity if
119.208 + /// it is necessary. The default map type is \ref
119.209 + /// ConstMap "ConstMap<concepts::Digraph::Arc, Const<int,1> >". The value
119.210 + /// of CapacityMap is not used directly by search algorithm, it is only
119.211 + /// passed to \ref MaxCardinalitySearchDefaultTraits.
119.212 + /// \param TR Traits class to set various data types used by the
119.213 + /// algorithm. The default traits class is
119.214 + /// \ref MaxCardinalitySearchDefaultTraits
119.215 + /// "MaxCardinalitySearchDefaultTraits<GR, CAP>".
119.216 + /// See \ref MaxCardinalitySearchDefaultTraits
119.217 + /// for the documentation of a MaxCardinalitySearch traits class.
119.218 +
119.219 +#ifdef DOXYGEN
119.220 + template <typename GR, typename CAP, typename TR>
119.221 +#else
119.222 + template <typename GR, typename CAP =
119.223 + ConstMap<typename GR::Arc, Const<int,1> >,
119.224 + typename TR =
119.225 + MaxCardinalitySearchDefaultTraits<GR, CAP> >
119.226 +#endif
119.227 + class MaxCardinalitySearch {
119.228 + public:
119.229 +
119.230 + typedef TR Traits;
119.231 + ///The type of the underlying digraph.
119.232 + typedef typename Traits::Digraph Digraph;
119.233 +
119.234 + ///The type of the capacity of the arcs.
119.235 + typedef typename Traits::CapacityMap::Value Value;
119.236 + ///The type of the map that stores the arc capacities.
119.237 + typedef typename Traits::CapacityMap CapacityMap;
119.238 + ///The type of the map indicating if a node is processed.
119.239 + typedef typename Traits::ProcessedMap ProcessedMap;
119.240 + ///The type of the map that stores the cardinalities of the nodes.
119.241 + typedef typename Traits::CardinalityMap CardinalityMap;
119.242 + ///The cross reference type used for the current heap.
119.243 + typedef typename Traits::HeapCrossRef HeapCrossRef;
119.244 + ///The heap type used by the algorithm. It maximizes the priorities.
119.245 + typedef typename Traits::Heap Heap;
119.246 + private:
119.247 + // Pointer to the underlying digraph.
119.248 + const Digraph *_graph;
119.249 + // Pointer to the capacity map
119.250 + const CapacityMap *_capacity;
119.251 + // Indicates if \ref _capacity is locally allocated (\c true) or not.
119.252 + bool local_capacity;
119.253 + // Pointer to the map of cardinality.
119.254 + CardinalityMap *_cardinality;
119.255 + // Indicates if \ref _cardinality is locally allocated (\c true) or not.
119.256 + bool local_cardinality;
119.257 + // Pointer to the map of processed status of the nodes.
119.258 + ProcessedMap *_processed;
119.259 + // Indicates if \ref _processed is locally allocated (\c true) or not.
119.260 + bool local_processed;
119.261 + // Pointer to the heap cross references.
119.262 + HeapCrossRef *_heap_cross_ref;
119.263 + // Indicates if \ref _heap_cross_ref is locally allocated (\c true) or not.
119.264 + bool local_heap_cross_ref;
119.265 + // Pointer to the heap.
119.266 + Heap *_heap;
119.267 + // Indicates if \ref _heap is locally allocated (\c true) or not.
119.268 + bool local_heap;
119.269 +
119.270 + public :
119.271 +
119.272 + typedef MaxCardinalitySearch Create;
119.273 +
119.274 + ///\name Named template parameters
119.275 +
119.276 + ///@{
119.277 +
119.278 + template <class T>
119.279 + struct DefCapacityMapTraits : public Traits {
119.280 + typedef T CapacityMap;
119.281 + static CapacityMap *createCapacityMap(const Digraph &) {
119.282 + LEMON_ASSERT(false,"Uninitialized parameter.");
119.283 + return 0;
119.284 + }
119.285 + };
119.286 + /// \brief \ref named-templ-param "Named parameter" for setting
119.287 + /// CapacityMap type
119.288 + ///
119.289 + /// \ref named-templ-param "Named parameter" for setting CapacityMap type
119.290 + /// for the algorithm.
119.291 + template <class T>
119.292 + struct SetCapacityMap
119.293 + : public MaxCardinalitySearch<Digraph, CapacityMap,
119.294 + DefCapacityMapTraits<T> > {
119.295 + typedef MaxCardinalitySearch<Digraph, CapacityMap,
119.296 + DefCapacityMapTraits<T> > Create;
119.297 + };
119.298 +
119.299 + template <class T>
119.300 + struct DefCardinalityMapTraits : public Traits {
119.301 + typedef T CardinalityMap;
119.302 + static CardinalityMap *createCardinalityMap(const Digraph &)
119.303 + {
119.304 + LEMON_ASSERT(false,"Uninitialized parameter.");
119.305 + return 0;
119.306 + }
119.307 + };
119.308 + /// \brief \ref named-templ-param "Named parameter" for setting
119.309 + /// CardinalityMap type
119.310 + ///
119.311 + /// \ref named-templ-param "Named parameter" for setting CardinalityMap
119.312 + /// type for the algorithm.
119.313 + template <class T>
119.314 + struct SetCardinalityMap
119.315 + : public MaxCardinalitySearch<Digraph, CapacityMap,
119.316 + DefCardinalityMapTraits<T> > {
119.317 + typedef MaxCardinalitySearch<Digraph, CapacityMap,
119.318 + DefCardinalityMapTraits<T> > Create;
119.319 + };
119.320 +
119.321 + template <class T>
119.322 + struct DefProcessedMapTraits : public Traits {
119.323 + typedef T ProcessedMap;
119.324 + static ProcessedMap *createProcessedMap(const Digraph &) {
119.325 + LEMON_ASSERT(false,"Uninitialized parameter.");
119.326 + return 0;
119.327 + }
119.328 + };
119.329 + /// \brief \ref named-templ-param "Named parameter" for setting
119.330 + /// ProcessedMap type
119.331 + ///
119.332 + /// \ref named-templ-param "Named parameter" for setting ProcessedMap type
119.333 + /// for the algorithm.
119.334 + template <class T>
119.335 + struct SetProcessedMap
119.336 + : public MaxCardinalitySearch<Digraph, CapacityMap,
119.337 + DefProcessedMapTraits<T> > {
119.338 + typedef MaxCardinalitySearch<Digraph, CapacityMap,
119.339 + DefProcessedMapTraits<T> > Create;
119.340 + };
119.341 +
119.342 + template <class H, class CR>
119.343 + struct DefHeapTraits : public Traits {
119.344 + typedef CR HeapCrossRef;
119.345 + typedef H Heap;
119.346 + static HeapCrossRef *createHeapCrossRef(const Digraph &) {
119.347 + LEMON_ASSERT(false,"Uninitialized parameter.");
119.348 + return 0;
119.349 + }
119.350 + static Heap *createHeap(HeapCrossRef &) {
119.351 + LEMON_ASSERT(false,"Uninitialized parameter.");
119.352 + return 0;
119.353 + }
119.354 + };
119.355 + /// \brief \ref named-templ-param "Named parameter" for setting heap
119.356 + /// and cross reference type
119.357 + ///
119.358 + /// \ref named-templ-param "Named parameter" for setting heap and cross
119.359 + /// reference type for the algorithm.
119.360 + template <class H, class CR = typename Digraph::template NodeMap<int> >
119.361 + struct SetHeap
119.362 + : public MaxCardinalitySearch<Digraph, CapacityMap,
119.363 + DefHeapTraits<H, CR> > {
119.364 + typedef MaxCardinalitySearch< Digraph, CapacityMap,
119.365 + DefHeapTraits<H, CR> > Create;
119.366 + };
119.367 +
119.368 + template <class H, class CR>
119.369 + struct DefStandardHeapTraits : public Traits {
119.370 + typedef CR HeapCrossRef;
119.371 + typedef H Heap;
119.372 + static HeapCrossRef *createHeapCrossRef(const Digraph &digraph) {
119.373 + return new HeapCrossRef(digraph);
119.374 + }
119.375 + static Heap *createHeap(HeapCrossRef &crossref) {
119.376 + return new Heap(crossref);
119.377 + }
119.378 + };
119.379 +
119.380 + /// \brief \ref named-templ-param "Named parameter" for setting heap and
119.381 + /// cross reference type with automatic allocation
119.382 + ///
119.383 + /// \ref named-templ-param "Named parameter" for setting heap and cross
119.384 + /// reference type. It can allocate the heap and the cross reference
119.385 + /// object if the cross reference's constructor waits for the digraph as
119.386 + /// parameter and the heap's constructor waits for the cross reference.
119.387 + template <class H, class CR = typename Digraph::template NodeMap<int> >
119.388 + struct SetStandardHeap
119.389 + : public MaxCardinalitySearch<Digraph, CapacityMap,
119.390 + DefStandardHeapTraits<H, CR> > {
119.391 + typedef MaxCardinalitySearch<Digraph, CapacityMap,
119.392 + DefStandardHeapTraits<H, CR> >
119.393 + Create;
119.394 + };
119.395 +
119.396 + ///@}
119.397 +
119.398 +
119.399 + protected:
119.400 +
119.401 + MaxCardinalitySearch() {}
119.402 +
119.403 + public:
119.404 +
119.405 + /// \brief Constructor.
119.406 + ///
119.407 + ///\param digraph the digraph the algorithm will run on.
119.408 + ///\param capacity the capacity map used by the algorithm.
119.409 + MaxCardinalitySearch(const Digraph& digraph,
119.410 + const CapacityMap& capacity) :
119.411 + _graph(&digraph),
119.412 + _capacity(&capacity), local_capacity(false),
119.413 + _cardinality(0), local_cardinality(false),
119.414 + _processed(0), local_processed(false),
119.415 + _heap_cross_ref(0), local_heap_cross_ref(false),
119.416 + _heap(0), local_heap(false)
119.417 + { }
119.418 +
119.419 + /// \brief Constructor.
119.420 + ///
119.421 + ///\param digraph the digraph the algorithm will run on.
119.422 + ///
119.423 + ///A constant 1 capacity map will be allocated.
119.424 + MaxCardinalitySearch(const Digraph& digraph) :
119.425 + _graph(&digraph),
119.426 + _capacity(0), local_capacity(false),
119.427 + _cardinality(0), local_cardinality(false),
119.428 + _processed(0), local_processed(false),
119.429 + _heap_cross_ref(0), local_heap_cross_ref(false),
119.430 + _heap(0), local_heap(false)
119.431 + { }
119.432 +
119.433 + /// \brief Destructor.
119.434 + ~MaxCardinalitySearch() {
119.435 + if(local_capacity) delete _capacity;
119.436 + if(local_cardinality) delete _cardinality;
119.437 + if(local_processed) delete _processed;
119.438 + if(local_heap_cross_ref) delete _heap_cross_ref;
119.439 + if(local_heap) delete _heap;
119.440 + }
119.441 +
119.442 + /// \brief Sets the capacity map.
119.443 + ///
119.444 + /// Sets the capacity map.
119.445 + /// \return <tt> (*this) </tt>
119.446 + MaxCardinalitySearch &capacityMap(const CapacityMap &m) {
119.447 + if (local_capacity) {
119.448 + delete _capacity;
119.449 + local_capacity=false;
119.450 + }
119.451 + _capacity=&m;
119.452 + return *this;
119.453 + }
119.454 +
119.455 + /// \brief Returns a const reference to the capacity map.
119.456 + ///
119.457 + /// Returns a const reference to the capacity map used by
119.458 + /// the algorithm.
119.459 + const CapacityMap &capacityMap() const {
119.460 + return *_capacity;
119.461 + }
119.462 +
119.463 + /// \brief Sets the map storing the cardinalities calculated by the
119.464 + /// algorithm.
119.465 + ///
119.466 + /// Sets the map storing the cardinalities calculated by the algorithm.
119.467 + /// If you don't use this function before calling \ref run(),
119.468 + /// it will allocate one. The destuctor deallocates this
119.469 + /// automatically allocated map, of course.
119.470 + /// \return <tt> (*this) </tt>
119.471 + MaxCardinalitySearch &cardinalityMap(CardinalityMap &m) {
119.472 + if(local_cardinality) {
119.473 + delete _cardinality;
119.474 + local_cardinality=false;
119.475 + }
119.476 + _cardinality = &m;
119.477 + return *this;
119.478 + }
119.479 +
119.480 + /// \brief Sets the map storing the processed nodes.
119.481 + ///
119.482 + /// Sets the map storing the processed nodes.
119.483 + /// If you don't use this function before calling \ref run(),
119.484 + /// it will allocate one. The destuctor deallocates this
119.485 + /// automatically allocated map, of course.
119.486 + /// \return <tt> (*this) </tt>
119.487 + MaxCardinalitySearch &processedMap(ProcessedMap &m)
119.488 + {
119.489 + if(local_processed) {
119.490 + delete _processed;
119.491 + local_processed=false;
119.492 + }
119.493 + _processed = &m;
119.494 + return *this;
119.495 + }
119.496 +
119.497 + /// \brief Returns a const reference to the cardinality map.
119.498 + ///
119.499 + /// Returns a const reference to the cardinality map used by
119.500 + /// the algorithm.
119.501 + const ProcessedMap &processedMap() const {
119.502 + return *_processed;
119.503 + }
119.504 +
119.505 + /// \brief Sets the heap and the cross reference used by algorithm.
119.506 + ///
119.507 + /// Sets the heap and the cross reference used by algorithm.
119.508 + /// If you don't use this function before calling \ref run(),
119.509 + /// it will allocate one. The destuctor deallocates this
119.510 + /// automatically allocated map, of course.
119.511 + /// \return <tt> (*this) </tt>
119.512 + MaxCardinalitySearch &heap(Heap& hp, HeapCrossRef &cr) {
119.513 + if(local_heap_cross_ref) {
119.514 + delete _heap_cross_ref;
119.515 + local_heap_cross_ref = false;
119.516 + }
119.517 + _heap_cross_ref = &cr;
119.518 + if(local_heap) {
119.519 + delete _heap;
119.520 + local_heap = false;
119.521 + }
119.522 + _heap = &hp;
119.523 + return *this;
119.524 + }
119.525 +
119.526 + /// \brief Returns a const reference to the heap.
119.527 + ///
119.528 + /// Returns a const reference to the heap used by
119.529 + /// the algorithm.
119.530 + const Heap &heap() const {
119.531 + return *_heap;
119.532 + }
119.533 +
119.534 + /// \brief Returns a const reference to the cross reference.
119.535 + ///
119.536 + /// Returns a const reference to the cross reference
119.537 + /// of the heap.
119.538 + const HeapCrossRef &heapCrossRef() const {
119.539 + return *_heap_cross_ref;
119.540 + }
119.541 +
119.542 + private:
119.543 +
119.544 + typedef typename Digraph::Node Node;
119.545 + typedef typename Digraph::NodeIt NodeIt;
119.546 + typedef typename Digraph::Arc Arc;
119.547 + typedef typename Digraph::InArcIt InArcIt;
119.548 +
119.549 + void create_maps() {
119.550 + if(!_capacity) {
119.551 + local_capacity = true;
119.552 + _capacity = Traits::createCapacityMap(*_graph);
119.553 + }
119.554 + if(!_cardinality) {
119.555 + local_cardinality = true;
119.556 + _cardinality = Traits::createCardinalityMap(*_graph);
119.557 + }
119.558 + if(!_processed) {
119.559 + local_processed = true;
119.560 + _processed = Traits::createProcessedMap(*_graph);
119.561 + }
119.562 + if (!_heap_cross_ref) {
119.563 + local_heap_cross_ref = true;
119.564 + _heap_cross_ref = Traits::createHeapCrossRef(*_graph);
119.565 + }
119.566 + if (!_heap) {
119.567 + local_heap = true;
119.568 + _heap = Traits::createHeap(*_heap_cross_ref);
119.569 + }
119.570 + }
119.571 +
119.572 + void finalizeNodeData(Node node, Value capacity) {
119.573 + _processed->set(node, true);
119.574 + _cardinality->set(node, capacity);
119.575 + }
119.576 +
119.577 + public:
119.578 + /// \name Execution control
119.579 + /// The simplest way to execute the algorithm is to use
119.580 + /// one of the member functions called \ref run().
119.581 + /// \n
119.582 + /// If you need more control on the execution,
119.583 + /// first you must call \ref init(), then you can add several source nodes
119.584 + /// with \ref addSource().
119.585 + /// Finally \ref start() will perform the computation.
119.586 +
119.587 + ///@{
119.588 +
119.589 + /// \brief Initializes the internal data structures.
119.590 + ///
119.591 + /// Initializes the internal data structures, and clears the heap.
119.592 + void init() {
119.593 + create_maps();
119.594 + _heap->clear();
119.595 + for (NodeIt it(*_graph) ; it != INVALID ; ++it) {
119.596 + _processed->set(it, false);
119.597 + _heap_cross_ref->set(it, Heap::PRE_HEAP);
119.598 + }
119.599 + }
119.600 +
119.601 + /// \brief Adds a new source node.
119.602 + ///
119.603 + /// Adds a new source node to the priority heap.
119.604 + ///
119.605 + /// It checks if the node has not yet been added to the heap.
119.606 + void addSource(Node source, Value capacity = 0) {
119.607 + if(_heap->state(source) == Heap::PRE_HEAP) {
119.608 + _heap->push(source, capacity);
119.609 + }
119.610 + }
119.611 +
119.612 + /// \brief Processes the next node in the priority heap
119.613 + ///
119.614 + /// Processes the next node in the priority heap.
119.615 + ///
119.616 + /// \return The processed node.
119.617 + ///
119.618 + /// \warning The priority heap must not be empty!
119.619 + Node processNextNode() {
119.620 + Node node = _heap->top();
119.621 + finalizeNodeData(node, _heap->prio());
119.622 + _heap->pop();
119.623 +
119.624 + for (InArcIt it(*_graph, node); it != INVALID; ++it) {
119.625 + Node source = _graph->source(it);
119.626 + switch (_heap->state(source)) {
119.627 + case Heap::PRE_HEAP:
119.628 + _heap->push(source, (*_capacity)[it]);
119.629 + break;
119.630 + case Heap::IN_HEAP:
119.631 + _heap->decrease(source, (*_heap)[source] + (*_capacity)[it]);
119.632 + break;
119.633 + case Heap::POST_HEAP:
119.634 + break;
119.635 + }
119.636 + }
119.637 + return node;
119.638 + }
119.639 +
119.640 + /// \brief Next node to be processed.
119.641 + ///
119.642 + /// Next node to be processed.
119.643 + ///
119.644 + /// \return The next node to be processed or INVALID if the
119.645 + /// priority heap is empty.
119.646 + Node nextNode() {
119.647 + return !_heap->empty() ? _heap->top() : INVALID;
119.648 + }
119.649 +
119.650 + /// \brief Returns \c false if there are nodes
119.651 + /// to be processed in the priority heap
119.652 + ///
119.653 + /// Returns \c false if there are nodes
119.654 + /// to be processed in the priority heap
119.655 + bool emptyQueue() { return _heap->empty(); }
119.656 + /// \brief Returns the number of the nodes to be processed
119.657 + /// in the priority heap
119.658 + ///
119.659 + /// Returns the number of the nodes to be processed in the priority heap
119.660 + int emptySize() { return _heap->size(); }
119.661 +
119.662 + /// \brief Executes the algorithm.
119.663 + ///
119.664 + /// Executes the algorithm.
119.665 + ///
119.666 + ///\pre init() must be called and at least one node should be added
119.667 + /// with addSource() before using this function.
119.668 + ///
119.669 + /// This method runs the Maximum Cardinality Search algorithm from the
119.670 + /// source node(s).
119.671 + void start() {
119.672 + while ( !_heap->empty() ) processNextNode();
119.673 + }
119.674 +
119.675 + /// \brief Executes the algorithm until \c dest is reached.
119.676 + ///
119.677 + /// Executes the algorithm until \c dest is reached.
119.678 + ///
119.679 + /// \pre init() must be called and at least one node should be added
119.680 + /// with addSource() before using this function.
119.681 + ///
119.682 + /// This method runs the %MaxCardinalitySearch algorithm from the source
119.683 + /// nodes.
119.684 + void start(Node dest) {
119.685 + while ( !_heap->empty() && _heap->top()!=dest ) processNextNode();
119.686 + if ( !_heap->empty() ) finalizeNodeData(_heap->top(), _heap->prio());
119.687 + }
119.688 +
119.689 + /// \brief Executes the algorithm until a condition is met.
119.690 + ///
119.691 + /// Executes the algorithm until a condition is met.
119.692 + ///
119.693 + /// \pre init() must be called and at least one node should be added
119.694 + /// with addSource() before using this function.
119.695 + ///
119.696 + /// \param nm must be a bool (or convertible) node map. The algorithm
119.697 + /// will stop when it reaches a node \c v with <tt>nm[v]==true</tt>.
119.698 + template <typename NodeBoolMap>
119.699 + void start(const NodeBoolMap &nm) {
119.700 + while ( !_heap->empty() && !nm[_heap->top()] ) processNextNode();
119.701 + if ( !_heap->empty() ) finalizeNodeData(_heap->top(),_heap->prio());
119.702 + }
119.703 +
119.704 + /// \brief Runs the maximum cardinality search algorithm from node \c s.
119.705 + ///
119.706 + /// This method runs the %MaxCardinalitySearch algorithm from a root
119.707 + /// node \c s.
119.708 + ///
119.709 + ///\note d.run(s) is just a shortcut of the following code.
119.710 + ///\code
119.711 + /// d.init();
119.712 + /// d.addSource(s);
119.713 + /// d.start();
119.714 + ///\endcode
119.715 + void run(Node s) {
119.716 + init();
119.717 + addSource(s);
119.718 + start();
119.719 + }
119.720 +
119.721 + /// \brief Runs the maximum cardinality search algorithm for the
119.722 + /// whole digraph.
119.723 + ///
119.724 + /// This method runs the %MaxCardinalitySearch algorithm from all
119.725 + /// unprocessed node of the digraph.
119.726 + ///
119.727 + ///\note d.run(s) is just a shortcut of the following code.
119.728 + ///\code
119.729 + /// d.init();
119.730 + /// for (NodeIt it(digraph); it != INVALID; ++it) {
119.731 + /// if (!d.reached(it)) {
119.732 + /// d.addSource(s);
119.733 + /// d.start();
119.734 + /// }
119.735 + /// }
119.736 + ///\endcode
119.737 + void run() {
119.738 + init();
119.739 + for (NodeIt it(*_graph); it != INVALID; ++it) {
119.740 + if (!reached(it)) {
119.741 + addSource(it);
119.742 + start();
119.743 + }
119.744 + }
119.745 + }
119.746 +
119.747 + ///@}
119.748 +
119.749 + /// \name Query Functions
119.750 + /// The results of the maximum cardinality search algorithm can be
119.751 + /// obtained using these functions.
119.752 + /// \n
119.753 + /// Before the use of these functions, either run() or start() must be
119.754 + /// called.
119.755 +
119.756 + ///@{
119.757 +
119.758 + /// \brief The cardinality of a node.
119.759 + ///
119.760 + /// Returns the cardinality of a node.
119.761 + /// \pre \ref run() must be called before using this function.
119.762 + /// \warning If node \c v in unreachable from the root the return value
119.763 + /// of this funcion is undefined.
119.764 + Value cardinality(Node node) const { return (*_cardinality)[node]; }
119.765 +
119.766 + /// \brief The current cardinality of a node.
119.767 + ///
119.768 + /// Returns the current cardinality of a node.
119.769 + /// \pre the given node should be reached but not processed
119.770 + Value currentCardinality(Node node) const { return (*_heap)[node]; }
119.771 +
119.772 + /// \brief Returns a reference to the NodeMap of cardinalities.
119.773 + ///
119.774 + /// Returns a reference to the NodeMap of cardinalities. \pre \ref run()
119.775 + /// must be called before using this function.
119.776 + const CardinalityMap &cardinalityMap() const { return *_cardinality;}
119.777 +
119.778 + /// \brief Checks if a node is reachable from the root.
119.779 + ///
119.780 + /// Returns \c true if \c v is reachable from the root.
119.781 + /// \warning The source nodes are initated as unreached.
119.782 + /// \pre \ref run() must be called before using this function.
119.783 + bool reached(Node v) { return (*_heap_cross_ref)[v] != Heap::PRE_HEAP; }
119.784 +
119.785 + /// \brief Checks if a node is processed.
119.786 + ///
119.787 + /// Returns \c true if \c v is processed, i.e. the shortest
119.788 + /// path to \c v has already found.
119.789 + /// \pre \ref run() must be called before using this function.
119.790 + bool processed(Node v) { return (*_heap_cross_ref)[v] == Heap::POST_HEAP; }
119.791 +
119.792 + ///@}
119.793 + };
119.794 +
119.795 +}
119.796 +
119.797 +#endif
120.1 --- a/lemon/min_cost_arborescence.h Mon Jul 16 16:21:40 2018 +0200
120.2 +++ b/lemon/min_cost_arborescence.h Wed Oct 17 19:14:07 2018 +0200
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-2010
120.8 + * Copyright (C) 2003-2013
120.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
120.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
120.11 *
120.12 @@ -101,7 +101,7 @@
120.13 /// more sources should be given to the algorithm and it will calculate
120.14 /// the minimum cost subgraph that is the union of arborescences with the
120.15 /// given sources and spans all the nodes which are reachable from the
120.16 - /// sources. The time complexity of the algorithm is O(n<sup>2</sup>+e).
120.17 + /// sources. The time complexity of the algorithm is O(n<sup>2</sup>+m).
120.18 ///
120.19 /// The algorithm also provides an optimal dual solution, therefore
120.20 /// the optimality of the solution can be checked.
120.21 @@ -128,7 +128,7 @@
120.22 class MinCostArborescence {
120.23 public:
120.24
120.25 - /// \brief The \ref MinCostArborescenceDefaultTraits "traits class"
120.26 + /// \brief The \ref lemon::MinCostArborescenceDefaultTraits "traits class"
120.27 /// of the algorithm.
120.28 typedef TR Traits;
120.29 /// The type of the underlying digraph.
121.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
121.2 +++ b/lemon/nagamochi_ibaraki.h Wed Oct 17 19:14:07 2018 +0200
121.3 @@ -0,0 +1,702 @@
121.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
121.5 + *
121.6 + * This file is a part of LEMON, a generic C++ optimization library.
121.7 + *
121.8 + * Copyright (C) 2003-2013
121.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
121.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
121.11 + *
121.12 + * Permission to use, modify and distribute this software is granted
121.13 + * provided that this copyright notice appears in all copies. For
121.14 + * precise terms see the accompanying LICENSE file.
121.15 + *
121.16 + * This software is provided "AS IS" with no warranty of any kind,
121.17 + * express or implied, and with no claim as to its suitability for any
121.18 + * purpose.
121.19 + *
121.20 + */
121.21 +
121.22 +#ifndef LEMON_NAGAMOCHI_IBARAKI_H
121.23 +#define LEMON_NAGAMOCHI_IBARAKI_H
121.24 +
121.25 +
121.26 +/// \ingroup min_cut
121.27 +/// \file
121.28 +/// \brief Implementation of the Nagamochi-Ibaraki algorithm.
121.29 +
121.30 +#include <lemon/core.h>
121.31 +#include <lemon/bin_heap.h>
121.32 +#include <lemon/bucket_heap.h>
121.33 +#include <lemon/maps.h>
121.34 +#include <lemon/radix_sort.h>
121.35 +#include <lemon/unionfind.h>
121.36 +
121.37 +#include <cassert>
121.38 +
121.39 +namespace lemon {
121.40 +
121.41 + /// \brief Default traits class for NagamochiIbaraki class.
121.42 + ///
121.43 + /// Default traits class for NagamochiIbaraki class.
121.44 + /// \param GR The undirected graph type.
121.45 + /// \param CM Type of capacity map.
121.46 + template <typename GR, typename CM>
121.47 + struct NagamochiIbarakiDefaultTraits {
121.48 + /// The type of the capacity map.
121.49 + typedef typename CM::Value Value;
121.50 +
121.51 + /// The undirected graph type the algorithm runs on.
121.52 + typedef GR Graph;
121.53 +
121.54 + /// \brief The type of the map that stores the edge capacities.
121.55 + ///
121.56 + /// The type of the map that stores the edge capacities.
121.57 + /// It must meet the \ref concepts::ReadMap "ReadMap" concept.
121.58 + typedef CM CapacityMap;
121.59 +
121.60 + /// \brief Instantiates a CapacityMap.
121.61 + ///
121.62 + /// This function instantiates a \ref CapacityMap.
121.63 +#ifdef DOXYGEN
121.64 + static CapacityMap *createCapacityMap(const Graph& graph)
121.65 +#else
121.66 + static CapacityMap *createCapacityMap(const Graph&)
121.67 +#endif
121.68 + {
121.69 + LEMON_ASSERT(false, "CapacityMap is not initialized");
121.70 + return 0; // ignore warnings
121.71 + }
121.72 +
121.73 + /// \brief The cross reference type used by heap.
121.74 + ///
121.75 + /// The cross reference type used by heap.
121.76 + /// Usually \c Graph::NodeMap<int>.
121.77 + typedef typename Graph::template NodeMap<int> HeapCrossRef;
121.78 +
121.79 + /// \brief Instantiates a HeapCrossRef.
121.80 + ///
121.81 + /// This function instantiates a \ref HeapCrossRef.
121.82 + /// \param g is the graph, to which we would like to define the
121.83 + /// \ref HeapCrossRef.
121.84 + static HeapCrossRef *createHeapCrossRef(const Graph& g) {
121.85 + return new HeapCrossRef(g);
121.86 + }
121.87 +
121.88 + /// \brief The heap type used by NagamochiIbaraki algorithm.
121.89 + ///
121.90 + /// The heap type used by NagamochiIbaraki algorithm. It has to
121.91 + /// maximize the priorities.
121.92 + ///
121.93 + /// \sa BinHeap
121.94 + /// \sa NagamochiIbaraki
121.95 + typedef BinHeap<Value, HeapCrossRef, std::greater<Value> > Heap;
121.96 +
121.97 + /// \brief Instantiates a Heap.
121.98 + ///
121.99 + /// This function instantiates a \ref Heap.
121.100 + /// \param r is the cross reference of the heap.
121.101 + static Heap *createHeap(HeapCrossRef& r) {
121.102 + return new Heap(r);
121.103 + }
121.104 + };
121.105 +
121.106 + /// \ingroup min_cut
121.107 + ///
121.108 + /// \brief Calculates the minimum cut in an undirected graph.
121.109 + ///
121.110 + /// Calculates the minimum cut in an undirected graph with the
121.111 + /// Nagamochi-Ibaraki algorithm. The algorithm separates the graph's
121.112 + /// nodes into two partitions with the minimum sum of edge capacities
121.113 + /// between the two partitions. The algorithm can be used to test
121.114 + /// the network reliability, especially to test how many links have
121.115 + /// to be destroyed in the network to split it to at least two
121.116 + /// distinict subnetworks.
121.117 + ///
121.118 + /// The complexity of the algorithm is \f$ O(nm\log(n)) \f$ but with
121.119 + /// \ref FibHeap "Fibonacci heap" it can be decreased to
121.120 + /// \f$ O(nm+n^2\log(n)) \f$. When the edges have unit capacities,
121.121 + /// \c BucketHeap can be used which yields \f$ O(nm) \f$ time
121.122 + /// complexity.
121.123 + ///
121.124 + /// \warning The value type of the capacity map should be able to
121.125 + /// hold any cut value of the graph, otherwise the result can
121.126 + /// overflow.
121.127 + /// \note This capacity is supposed to be integer type.
121.128 +#ifdef DOXYGEN
121.129 + template <typename GR, typename CM, typename TR>
121.130 +#else
121.131 + template <typename GR,
121.132 + typename CM = typename GR::template EdgeMap<int>,
121.133 + typename TR = NagamochiIbarakiDefaultTraits<GR, CM> >
121.134 +#endif
121.135 + class NagamochiIbaraki {
121.136 + public:
121.137 +
121.138 + typedef TR Traits;
121.139 + /// The type of the underlying graph.
121.140 + typedef typename Traits::Graph Graph;
121.141 +
121.142 + /// The type of the capacity map.
121.143 + typedef typename Traits::CapacityMap CapacityMap;
121.144 + /// The value type of the capacity map.
121.145 + typedef typename Traits::CapacityMap::Value Value;
121.146 +
121.147 + /// The heap type used by the algorithm.
121.148 + typedef typename Traits::Heap Heap;
121.149 + /// The cross reference type used for the heap.
121.150 + typedef typename Traits::HeapCrossRef HeapCrossRef;
121.151 +
121.152 + ///\name Named template parameters
121.153 +
121.154 + ///@{
121.155 +
121.156 + struct SetUnitCapacityTraits : public Traits {
121.157 + typedef ConstMap<typename Graph::Edge, Const<int, 1> > CapacityMap;
121.158 + static CapacityMap *createCapacityMap(const Graph&) {
121.159 + return new CapacityMap();
121.160 + }
121.161 + };
121.162 +
121.163 + /// \brief \ref named-templ-param "Named parameter" for setting
121.164 + /// the capacity map to a constMap<Edge, int, 1>() instance
121.165 + ///
121.166 + /// \ref named-templ-param "Named parameter" for setting
121.167 + /// the capacity map to a constMap<Edge, int, 1>() instance
121.168 + struct SetUnitCapacity
121.169 + : public NagamochiIbaraki<Graph, CapacityMap,
121.170 + SetUnitCapacityTraits> {
121.171 + typedef NagamochiIbaraki<Graph, CapacityMap,
121.172 + SetUnitCapacityTraits> Create;
121.173 + };
121.174 +
121.175 +
121.176 + template <class H, class CR>
121.177 + struct SetHeapTraits : public Traits {
121.178 + typedef CR HeapCrossRef;
121.179 + typedef H Heap;
121.180 + static HeapCrossRef *createHeapCrossRef(int num) {
121.181 + LEMON_ASSERT(false, "HeapCrossRef is not initialized");
121.182 + return 0; // ignore warnings
121.183 + }
121.184 + static Heap *createHeap(HeapCrossRef &) {
121.185 + LEMON_ASSERT(false, "Heap is not initialized");
121.186 + return 0; // ignore warnings
121.187 + }
121.188 + };
121.189 +
121.190 + /// \brief \ref named-templ-param "Named parameter" for setting
121.191 + /// heap and cross reference type
121.192 + ///
121.193 + /// \ref named-templ-param "Named parameter" for setting heap and
121.194 + /// cross reference type. The heap has to maximize the priorities.
121.195 + template <class H, class CR = RangeMap<int> >
121.196 + struct SetHeap
121.197 + : public NagamochiIbaraki<Graph, CapacityMap, SetHeapTraits<H, CR> > {
121.198 + typedef NagamochiIbaraki< Graph, CapacityMap, SetHeapTraits<H, CR> >
121.199 + Create;
121.200 + };
121.201 +
121.202 + template <class H, class CR>
121.203 + struct SetStandardHeapTraits : public Traits {
121.204 + typedef CR HeapCrossRef;
121.205 + typedef H Heap;
121.206 + static HeapCrossRef *createHeapCrossRef(int size) {
121.207 + return new HeapCrossRef(size);
121.208 + }
121.209 + static Heap *createHeap(HeapCrossRef &crossref) {
121.210 + return new Heap(crossref);
121.211 + }
121.212 + };
121.213 +
121.214 + /// \brief \ref named-templ-param "Named parameter" for setting
121.215 + /// heap and cross reference type with automatic allocation
121.216 + ///
121.217 + /// \ref named-templ-param "Named parameter" for setting heap and
121.218 + /// cross reference type with automatic allocation. They should
121.219 + /// have standard constructor interfaces to be able to
121.220 + /// automatically created by the algorithm (i.e. the graph should
121.221 + /// be passed to the constructor of the cross reference and the
121.222 + /// cross reference should be passed to the constructor of the
121.223 + /// heap). However, external heap and cross reference objects
121.224 + /// could also be passed to the algorithm using the \ref heap()
121.225 + /// function before calling \ref run() or \ref init(). The heap
121.226 + /// has to maximize the priorities.
121.227 + /// \sa SetHeap
121.228 + template <class H, class CR = RangeMap<int> >
121.229 + struct SetStandardHeap
121.230 + : public NagamochiIbaraki<Graph, CapacityMap,
121.231 + SetStandardHeapTraits<H, CR> > {
121.232 + typedef NagamochiIbaraki<Graph, CapacityMap,
121.233 + SetStandardHeapTraits<H, CR> > Create;
121.234 + };
121.235 +
121.236 + ///@}
121.237 +
121.238 +
121.239 + private:
121.240 +
121.241 + const Graph &_graph;
121.242 + const CapacityMap *_capacity;
121.243 + bool _local_capacity; // unit capacity
121.244 +
121.245 + struct ArcData {
121.246 + typename Graph::Node target;
121.247 + int prev, next;
121.248 + };
121.249 + struct EdgeData {
121.250 + Value capacity;
121.251 + Value cut;
121.252 + };
121.253 +
121.254 + struct NodeData {
121.255 + int first_arc;
121.256 + typename Graph::Node prev, next;
121.257 + int curr_arc;
121.258 + typename Graph::Node last_rep;
121.259 + Value sum;
121.260 + };
121.261 +
121.262 + typename Graph::template NodeMap<NodeData> *_nodes;
121.263 + std::vector<ArcData> _arcs;
121.264 + std::vector<EdgeData> _edges;
121.265 +
121.266 + typename Graph::Node _first_node;
121.267 + int _node_num;
121.268 +
121.269 + Value _min_cut;
121.270 +
121.271 + HeapCrossRef *_heap_cross_ref;
121.272 + bool _local_heap_cross_ref;
121.273 + Heap *_heap;
121.274 + bool _local_heap;
121.275 +
121.276 + typedef typename Graph::template NodeMap<typename Graph::Node> NodeList;
121.277 + NodeList *_next_rep;
121.278 +
121.279 + typedef typename Graph::template NodeMap<bool> MinCutMap;
121.280 + MinCutMap *_cut_map;
121.281 +
121.282 + void createStructures() {
121.283 + if (!_nodes) {
121.284 + _nodes = new (typename Graph::template NodeMap<NodeData>)(_graph);
121.285 + }
121.286 + if (!_capacity) {
121.287 + _local_capacity = true;
121.288 + _capacity = Traits::createCapacityMap(_graph);
121.289 + }
121.290 + if (!_heap_cross_ref) {
121.291 + _local_heap_cross_ref = true;
121.292 + _heap_cross_ref = Traits::createHeapCrossRef(_graph);
121.293 + }
121.294 + if (!_heap) {
121.295 + _local_heap = true;
121.296 + _heap = Traits::createHeap(*_heap_cross_ref);
121.297 + }
121.298 + if (!_next_rep) {
121.299 + _next_rep = new NodeList(_graph);
121.300 + }
121.301 + if (!_cut_map) {
121.302 + _cut_map = new MinCutMap(_graph);
121.303 + }
121.304 + }
121.305 +
121.306 + protected:
121.307 + //This is here to avoid a gcc-3.3 compilation error.
121.308 + //It should never be called.
121.309 + NagamochiIbaraki() {}
121.310 +
121.311 + public:
121.312 +
121.313 + typedef NagamochiIbaraki Create;
121.314 +
121.315 +
121.316 + /// \brief Constructor.
121.317 + ///
121.318 + /// \param graph The graph the algorithm runs on.
121.319 + /// \param capacity The capacity map used by the algorithm.
121.320 + NagamochiIbaraki(const Graph& graph, const CapacityMap& capacity)
121.321 + : _graph(graph), _capacity(&capacity), _local_capacity(false),
121.322 + _nodes(0), _arcs(), _edges(), _min_cut(),
121.323 + _heap_cross_ref(0), _local_heap_cross_ref(false),
121.324 + _heap(0), _local_heap(false),
121.325 + _next_rep(0), _cut_map(0) {}
121.326 +
121.327 + /// \brief Constructor.
121.328 + ///
121.329 + /// This constructor can be used only when the Traits class
121.330 + /// defines how can the local capacity map be instantiated.
121.331 + /// If the SetUnitCapacity used the algorithm automatically
121.332 + /// constructs the capacity map.
121.333 + ///
121.334 + ///\param graph The graph the algorithm runs on.
121.335 + NagamochiIbaraki(const Graph& graph)
121.336 + : _graph(graph), _capacity(0), _local_capacity(false),
121.337 + _nodes(0), _arcs(), _edges(), _min_cut(),
121.338 + _heap_cross_ref(0), _local_heap_cross_ref(false),
121.339 + _heap(0), _local_heap(false),
121.340 + _next_rep(0), _cut_map(0) {}
121.341 +
121.342 + /// \brief Destructor.
121.343 + ///
121.344 + /// Destructor.
121.345 + ~NagamochiIbaraki() {
121.346 + if (_local_capacity) delete _capacity;
121.347 + if (_nodes) delete _nodes;
121.348 + if (_local_heap) delete _heap;
121.349 + if (_local_heap_cross_ref) delete _heap_cross_ref;
121.350 + if (_next_rep) delete _next_rep;
121.351 + if (_cut_map) delete _cut_map;
121.352 + }
121.353 +
121.354 + /// \brief Sets the heap and the cross reference used by algorithm.
121.355 + ///
121.356 + /// Sets the heap and the cross reference used by algorithm.
121.357 + /// If you don't use this function before calling \ref run(),
121.358 + /// it will allocate one. The destuctor deallocates this
121.359 + /// automatically allocated heap and cross reference, of course.
121.360 + /// \return <tt> (*this) </tt>
121.361 + NagamochiIbaraki &heap(Heap& hp, HeapCrossRef &cr)
121.362 + {
121.363 + if (_local_heap_cross_ref) {
121.364 + delete _heap_cross_ref;
121.365 + _local_heap_cross_ref = false;
121.366 + }
121.367 + _heap_cross_ref = &cr;
121.368 + if (_local_heap) {
121.369 + delete _heap;
121.370 + _local_heap = false;
121.371 + }
121.372 + _heap = &hp;
121.373 + return *this;
121.374 + }
121.375 +
121.376 + /// \name Execution control
121.377 + /// The simplest way to execute the algorithm is to use
121.378 + /// one of the member functions called \c run().
121.379 + /// \n
121.380 + /// If you need more control on the execution,
121.381 + /// first you must call \ref init() and then call the start()
121.382 + /// or proper times the processNextPhase() member functions.
121.383 +
121.384 + ///@{
121.385 +
121.386 + /// \brief Initializes the internal data structures.
121.387 + ///
121.388 + /// Initializes the internal data structures.
121.389 + void init() {
121.390 + createStructures();
121.391 +
121.392 + int edge_num = countEdges(_graph);
121.393 + _edges.resize(edge_num);
121.394 + _arcs.resize(2 * edge_num);
121.395 +
121.396 + typename Graph::Node prev = INVALID;
121.397 + _node_num = 0;
121.398 + for (typename Graph::NodeIt n(_graph); n != INVALID; ++n) {
121.399 + (*_cut_map)[n] = false;
121.400 + (*_next_rep)[n] = INVALID;
121.401 + (*_nodes)[n].last_rep = n;
121.402 + (*_nodes)[n].first_arc = -1;
121.403 + (*_nodes)[n].curr_arc = -1;
121.404 + (*_nodes)[n].prev = prev;
121.405 + if (prev != INVALID) {
121.406 + (*_nodes)[prev].next = n;
121.407 + }
121.408 + (*_nodes)[n].next = INVALID;
121.409 + (*_nodes)[n].sum = 0;
121.410 + prev = n;
121.411 + ++_node_num;
121.412 + }
121.413 +
121.414 + _first_node = typename Graph::NodeIt(_graph);
121.415 +
121.416 + int index = 0;
121.417 + for (typename Graph::NodeIt n(_graph); n != INVALID; ++n) {
121.418 + for (typename Graph::OutArcIt a(_graph, n); a != INVALID; ++a) {
121.419 + typename Graph::Node m = _graph.target(a);
121.420 +
121.421 + if (!(n < m)) continue;
121.422 +
121.423 + (*_nodes)[n].sum += (*_capacity)[a];
121.424 + (*_nodes)[m].sum += (*_capacity)[a];
121.425 +
121.426 + int c = (*_nodes)[m].curr_arc;
121.427 + if (c != -1 && _arcs[c ^ 1].target == n) {
121.428 + _edges[c >> 1].capacity += (*_capacity)[a];
121.429 + } else {
121.430 + _edges[index].capacity = (*_capacity)[a];
121.431 +
121.432 + _arcs[index << 1].prev = -1;
121.433 + if ((*_nodes)[n].first_arc != -1) {
121.434 + _arcs[(*_nodes)[n].first_arc].prev = (index << 1);
121.435 + }
121.436 + _arcs[index << 1].next = (*_nodes)[n].first_arc;
121.437 + (*_nodes)[n].first_arc = (index << 1);
121.438 + _arcs[index << 1].target = m;
121.439 +
121.440 + (*_nodes)[m].curr_arc = (index << 1);
121.441 +
121.442 + _arcs[(index << 1) | 1].prev = -1;
121.443 + if ((*_nodes)[m].first_arc != -1) {
121.444 + _arcs[(*_nodes)[m].first_arc].prev = ((index << 1) | 1);
121.445 + }
121.446 + _arcs[(index << 1) | 1].next = (*_nodes)[m].first_arc;
121.447 + (*_nodes)[m].first_arc = ((index << 1) | 1);
121.448 + _arcs[(index << 1) | 1].target = n;
121.449 +
121.450 + ++index;
121.451 + }
121.452 + }
121.453 + }
121.454 +
121.455 + typename Graph::Node cut_node = INVALID;
121.456 + _min_cut = std::numeric_limits<Value>::max();
121.457 +
121.458 + for (typename Graph::Node n = _first_node;
121.459 + n != INVALID; n = (*_nodes)[n].next) {
121.460 + if ((*_nodes)[n].sum < _min_cut) {
121.461 + cut_node = n;
121.462 + _min_cut = (*_nodes)[n].sum;
121.463 + }
121.464 + }
121.465 + (*_cut_map)[cut_node] = true;
121.466 + if (_min_cut == 0) {
121.467 + _first_node = INVALID;
121.468 + }
121.469 + }
121.470 +
121.471 + public:
121.472 +
121.473 + /// \brief Processes the next phase
121.474 + ///
121.475 + /// Processes the next phase in the algorithm. It must be called
121.476 + /// at most one less the number of the nodes in the graph.
121.477 + ///
121.478 + ///\return %True when the algorithm finished.
121.479 + bool processNextPhase() {
121.480 + if (_first_node == INVALID) return true;
121.481 +
121.482 + _heap->clear();
121.483 + for (typename Graph::Node n = _first_node;
121.484 + n != INVALID; n = (*_nodes)[n].next) {
121.485 + (*_heap_cross_ref)[n] = Heap::PRE_HEAP;
121.486 + }
121.487 +
121.488 + std::vector<typename Graph::Node> order;
121.489 + order.reserve(_node_num);
121.490 + int sep = 0;
121.491 +
121.492 + Value alpha = 0;
121.493 + Value pmc = std::numeric_limits<Value>::max();
121.494 +
121.495 + _heap->push(_first_node, static_cast<Value>(0));
121.496 + while (!_heap->empty()) {
121.497 + typename Graph::Node n = _heap->top();
121.498 + Value v = _heap->prio();
121.499 +
121.500 + _heap->pop();
121.501 + for (int a = (*_nodes)[n].first_arc; a != -1; a = _arcs[a].next) {
121.502 + switch (_heap->state(_arcs[a].target)) {
121.503 + case Heap::PRE_HEAP:
121.504 + {
121.505 + Value nv = _edges[a >> 1].capacity;
121.506 + _heap->push(_arcs[a].target, nv);
121.507 + _edges[a >> 1].cut = nv;
121.508 + } break;
121.509 + case Heap::IN_HEAP:
121.510 + {
121.511 + Value nv = _edges[a >> 1].capacity + (*_heap)[_arcs[a].target];
121.512 + _heap->decrease(_arcs[a].target, nv);
121.513 + _edges[a >> 1].cut = nv;
121.514 + } break;
121.515 + case Heap::POST_HEAP:
121.516 + break;
121.517 + }
121.518 + }
121.519 +
121.520 + alpha += (*_nodes)[n].sum;
121.521 + alpha -= 2 * v;
121.522 +
121.523 + order.push_back(n);
121.524 + if (!_heap->empty()) {
121.525 + if (alpha < pmc) {
121.526 + pmc = alpha;
121.527 + sep = order.size();
121.528 + }
121.529 + }
121.530 + }
121.531 +
121.532 + if (static_cast<int>(order.size()) < _node_num) {
121.533 + _first_node = INVALID;
121.534 + for (typename Graph::NodeIt n(_graph); n != INVALID; ++n) {
121.535 + (*_cut_map)[n] = false;
121.536 + }
121.537 + for (int i = 0; i < static_cast<int>(order.size()); ++i) {
121.538 + typename Graph::Node n = order[i];
121.539 + while (n != INVALID) {
121.540 + (*_cut_map)[n] = true;
121.541 + n = (*_next_rep)[n];
121.542 + }
121.543 + }
121.544 + _min_cut = 0;
121.545 + return true;
121.546 + }
121.547 +
121.548 + if (pmc < _min_cut) {
121.549 + for (typename Graph::NodeIt n(_graph); n != INVALID; ++n) {
121.550 + (*_cut_map)[n] = false;
121.551 + }
121.552 + for (int i = 0; i < sep; ++i) {
121.553 + typename Graph::Node n = order[i];
121.554 + while (n != INVALID) {
121.555 + (*_cut_map)[n] = true;
121.556 + n = (*_next_rep)[n];
121.557 + }
121.558 + }
121.559 + _min_cut = pmc;
121.560 + }
121.561 +
121.562 + for (typename Graph::Node n = _first_node;
121.563 + n != INVALID; n = (*_nodes)[n].next) {
121.564 + bool merged = false;
121.565 + for (int a = (*_nodes)[n].first_arc; a != -1; a = _arcs[a].next) {
121.566 + if (!(_edges[a >> 1].cut < pmc)) {
121.567 + if (!merged) {
121.568 + for (int b = (*_nodes)[n].first_arc; b != -1; b = _arcs[b].next) {
121.569 + (*_nodes)[_arcs[b].target].curr_arc = b;
121.570 + }
121.571 + merged = true;
121.572 + }
121.573 + typename Graph::Node m = _arcs[a].target;
121.574 + int nb = 0;
121.575 + for (int b = (*_nodes)[m].first_arc; b != -1; b = nb) {
121.576 + nb = _arcs[b].next;
121.577 + if ((b ^ a) == 1) continue;
121.578 + typename Graph::Node o = _arcs[b].target;
121.579 + int c = (*_nodes)[o].curr_arc;
121.580 + if (c != -1 && _arcs[c ^ 1].target == n) {
121.581 + _edges[c >> 1].capacity += _edges[b >> 1].capacity;
121.582 + (*_nodes)[n].sum += _edges[b >> 1].capacity;
121.583 + if (_edges[b >> 1].cut < _edges[c >> 1].cut) {
121.584 + _edges[b >> 1].cut = _edges[c >> 1].cut;
121.585 + }
121.586 + if (_arcs[b ^ 1].prev != -1) {
121.587 + _arcs[_arcs[b ^ 1].prev].next = _arcs[b ^ 1].next;
121.588 + } else {
121.589 + (*_nodes)[o].first_arc = _arcs[b ^ 1].next;
121.590 + }
121.591 + if (_arcs[b ^ 1].next != -1) {
121.592 + _arcs[_arcs[b ^ 1].next].prev = _arcs[b ^ 1].prev;
121.593 + }
121.594 + } else {
121.595 + if (_arcs[a].next != -1) {
121.596 + _arcs[_arcs[a].next].prev = b;
121.597 + }
121.598 + _arcs[b].next = _arcs[a].next;
121.599 + _arcs[b].prev = a;
121.600 + _arcs[a].next = b;
121.601 + _arcs[b ^ 1].target = n;
121.602 +
121.603 + (*_nodes)[n].sum += _edges[b >> 1].capacity;
121.604 + (*_nodes)[o].curr_arc = b;
121.605 + }
121.606 + }
121.607 +
121.608 + if (_arcs[a].prev != -1) {
121.609 + _arcs[_arcs[a].prev].next = _arcs[a].next;
121.610 + } else {
121.611 + (*_nodes)[n].first_arc = _arcs[a].next;
121.612 + }
121.613 + if (_arcs[a].next != -1) {
121.614 + _arcs[_arcs[a].next].prev = _arcs[a].prev;
121.615 + }
121.616 +
121.617 + (*_nodes)[n].sum -= _edges[a >> 1].capacity;
121.618 + (*_next_rep)[(*_nodes)[n].last_rep] = m;
121.619 + (*_nodes)[n].last_rep = (*_nodes)[m].last_rep;
121.620 +
121.621 + if ((*_nodes)[m].prev != INVALID) {
121.622 + (*_nodes)[(*_nodes)[m].prev].next = (*_nodes)[m].next;
121.623 + } else{
121.624 + _first_node = (*_nodes)[m].next;
121.625 + }
121.626 + if ((*_nodes)[m].next != INVALID) {
121.627 + (*_nodes)[(*_nodes)[m].next].prev = (*_nodes)[m].prev;
121.628 + }
121.629 + --_node_num;
121.630 + }
121.631 + }
121.632 + }
121.633 +
121.634 + if (_node_num == 1) {
121.635 + _first_node = INVALID;
121.636 + return true;
121.637 + }
121.638 +
121.639 + return false;
121.640 + }
121.641 +
121.642 + /// \brief Executes the algorithm.
121.643 + ///
121.644 + /// Executes the algorithm.
121.645 + ///
121.646 + /// \pre init() must be called
121.647 + void start() {
121.648 + while (!processNextPhase()) {}
121.649 + }
121.650 +
121.651 +
121.652 + /// \brief Runs %NagamochiIbaraki algorithm.
121.653 + ///
121.654 + /// This method runs the %Min cut algorithm
121.655 + ///
121.656 + /// \note mc.run(s) is just a shortcut of the following code.
121.657 + ///\code
121.658 + /// mc.init();
121.659 + /// mc.start();
121.660 + ///\endcode
121.661 + void run() {
121.662 + init();
121.663 + start();
121.664 + }
121.665 +
121.666 + ///@}
121.667 +
121.668 + /// \name Query Functions
121.669 + ///
121.670 + /// The result of the %NagamochiIbaraki
121.671 + /// algorithm can be obtained using these functions.\n
121.672 + /// Before the use of these functions, either run() or start()
121.673 + /// must be called.
121.674 +
121.675 + ///@{
121.676 +
121.677 + /// \brief Returns the min cut value.
121.678 + ///
121.679 + /// Returns the min cut value if the algorithm finished.
121.680 + /// After the first processNextPhase() it is a value of a
121.681 + /// valid cut in the graph.
121.682 + Value minCutValue() const {
121.683 + return _min_cut;
121.684 + }
121.685 +
121.686 + /// \brief Returns a min cut in a NodeMap.
121.687 + ///
121.688 + /// It sets the nodes of one of the two partitions to true and
121.689 + /// the other partition to false.
121.690 + /// \param cutMap A \ref concepts::WriteMap "writable" node map with
121.691 + /// \c bool (or convertible) value type.
121.692 + template <typename CutMap>
121.693 + Value minCutMap(CutMap& cutMap) const {
121.694 + for (typename Graph::NodeIt n(_graph); n != INVALID; ++n) {
121.695 + cutMap.set(n, (*_cut_map)[n]);
121.696 + }
121.697 + return minCutValue();
121.698 + }
121.699 +
121.700 + ///@}
121.701 +
121.702 + };
121.703 +}
121.704 +
121.705 +#endif
122.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
122.2 +++ b/lemon/nearest_neighbor_tsp.h Wed Oct 17 19:14:07 2018 +0200
122.3 @@ -0,0 +1,238 @@
122.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
122.5 + *
122.6 + * This file is a part of LEMON, a generic C++ optimization library.
122.7 + *
122.8 + * Copyright (C) 2003-2013
122.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
122.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
122.11 + *
122.12 + * Permission to use, modify and distribute this software is granted
122.13 + * provided that this copyright notice appears in all copies. For
122.14 + * precise terms see the accompanying LICENSE file.
122.15 + *
122.16 + * This software is provided "AS IS" with no warranty of any kind,
122.17 + * express or implied, and with no claim as to its suitability for any
122.18 + * purpose.
122.19 + *
122.20 + */
122.21 +
122.22 +#ifndef LEMON_NEAREST_NEIGHBOUR_TSP_H
122.23 +#define LEMON_NEAREST_NEIGHBOUR_TSP_H
122.24 +
122.25 +/// \ingroup tsp
122.26 +/// \file
122.27 +/// \brief Nearest neighbor algorithm for symmetric TSP
122.28 +
122.29 +#include <deque>
122.30 +#include <vector>
122.31 +#include <limits>
122.32 +#include <lemon/full_graph.h>
122.33 +#include <lemon/maps.h>
122.34 +
122.35 +namespace lemon {
122.36 +
122.37 + /// \ingroup tsp
122.38 + ///
122.39 + /// \brief Nearest neighbor algorithm for symmetric TSP.
122.40 + ///
122.41 + /// NearestNeighborTsp implements the nearest neighbor heuristic for solving
122.42 + /// symmetric \ref tsp "TSP".
122.43 + ///
122.44 + /// This is probably the simplest TSP heuristic.
122.45 + /// It starts with a minimum cost edge and at each step, it connects the
122.46 + /// nearest unvisited node to the current path.
122.47 + /// Finally, it connects the two end points of the path to form a tour.
122.48 + ///
122.49 + /// This method runs in O(n<sup>2</sup>) time.
122.50 + /// It quickly finds a relatively short tour for most TSP instances,
122.51 + /// but it could also yield a really bad (or even the worst) solution
122.52 + /// in special cases.
122.53 + ///
122.54 + /// \tparam CM Type of the cost map.
122.55 + template <typename CM>
122.56 + class NearestNeighborTsp
122.57 + {
122.58 + public:
122.59 +
122.60 + /// Type of the cost map
122.61 + typedef CM CostMap;
122.62 + /// Type of the edge costs
122.63 + typedef typename CM::Value Cost;
122.64 +
122.65 + private:
122.66 +
122.67 + GRAPH_TYPEDEFS(FullGraph);
122.68 +
122.69 + const FullGraph &_gr;
122.70 + const CostMap &_cost;
122.71 + Cost _sum;
122.72 + std::vector<Node> _path;
122.73 +
122.74 + public:
122.75 +
122.76 + /// \brief Constructor
122.77 + ///
122.78 + /// Constructor.
122.79 + /// \param gr The \ref FullGraph "full graph" the algorithm runs on.
122.80 + /// \param cost The cost map.
122.81 + NearestNeighborTsp(const FullGraph &gr, const CostMap &cost)
122.82 + : _gr(gr), _cost(cost) {}
122.83 +
122.84 + /// \name Execution Control
122.85 + /// @{
122.86 +
122.87 + /// \brief Runs the algorithm.
122.88 + ///
122.89 + /// This function runs the algorithm.
122.90 + ///
122.91 + /// \return The total cost of the found tour.
122.92 + Cost run() {
122.93 + _path.clear();
122.94 + if (_gr.nodeNum() == 0) {
122.95 + return _sum = 0;
122.96 + }
122.97 + else if (_gr.nodeNum() == 1) {
122.98 + _path.push_back(_gr(0));
122.99 + return _sum = 0;
122.100 + }
122.101 +
122.102 + std::deque<Node> path_dq;
122.103 + Edge min_edge1 = INVALID,
122.104 + min_edge2 = INVALID;
122.105 +
122.106 + min_edge1 = mapMin(_gr, _cost);
122.107 + Node n1 = _gr.u(min_edge1),
122.108 + n2 = _gr.v(min_edge1);
122.109 + path_dq.push_back(n1);
122.110 + path_dq.push_back(n2);
122.111 +
122.112 + FullGraph::NodeMap<bool> used(_gr, false);
122.113 + used[n1] = true;
122.114 + used[n2] = true;
122.115 +
122.116 + min_edge1 = INVALID;
122.117 + while (int(path_dq.size()) != _gr.nodeNum()) {
122.118 + if (min_edge1 == INVALID) {
122.119 + for (IncEdgeIt e(_gr, n1); e != INVALID; ++e) {
122.120 + if (!used[_gr.runningNode(e)] &&
122.121 + (min_edge1 == INVALID || _cost[e] < _cost[min_edge1])) {
122.122 + min_edge1 = e;
122.123 + }
122.124 + }
122.125 + }
122.126 +
122.127 + if (min_edge2 == INVALID) {
122.128 + for (IncEdgeIt e(_gr, n2); e != INVALID; ++e) {
122.129 + if (!used[_gr.runningNode(e)] &&
122.130 + (min_edge2 == INVALID||_cost[e] < _cost[min_edge2])) {
122.131 + min_edge2 = e;
122.132 + }
122.133 + }
122.134 + }
122.135 +
122.136 + if (_cost[min_edge1] < _cost[min_edge2]) {
122.137 + n1 = _gr.oppositeNode(n1, min_edge1);
122.138 + path_dq.push_front(n1);
122.139 +
122.140 + used[n1] = true;
122.141 + min_edge1 = INVALID;
122.142 +
122.143 + if (_gr.u(min_edge2) == n1 || _gr.v(min_edge2) == n1)
122.144 + min_edge2 = INVALID;
122.145 + } else {
122.146 + n2 = _gr.oppositeNode(n2, min_edge2);
122.147 + path_dq.push_back(n2);
122.148 +
122.149 + used[n2] = true;
122.150 + min_edge2 = INVALID;
122.151 +
122.152 + if (_gr.u(min_edge1) == n2 || _gr.v(min_edge1) == n2)
122.153 + min_edge1 = INVALID;
122.154 + }
122.155 + }
122.156 +
122.157 + n1 = path_dq.back();
122.158 + n2 = path_dq.front();
122.159 + _path.push_back(n2);
122.160 + _sum = _cost[_gr.edge(n1, n2)];
122.161 + for (int i = 1; i < int(path_dq.size()); ++i) {
122.162 + n1 = n2;
122.163 + n2 = path_dq[i];
122.164 + _path.push_back(n2);
122.165 + _sum += _cost[_gr.edge(n1, n2)];
122.166 + }
122.167 +
122.168 + return _sum;
122.169 + }
122.170 +
122.171 + /// @}
122.172 +
122.173 + /// \name Query Functions
122.174 + /// @{
122.175 +
122.176 + /// \brief The total cost of the found tour.
122.177 + ///
122.178 + /// This function returns the total cost of the found tour.
122.179 + ///
122.180 + /// \pre run() must be called before using this function.
122.181 + Cost tourCost() const {
122.182 + return _sum;
122.183 + }
122.184 +
122.185 + /// \brief Returns a const reference to the node sequence of the
122.186 + /// found tour.
122.187 + ///
122.188 + /// This function returns a const reference to a vector
122.189 + /// that stores the node sequence of the found tour.
122.190 + ///
122.191 + /// \pre run() must be called before using this function.
122.192 + const std::vector<Node>& tourNodes() const {
122.193 + return _path;
122.194 + }
122.195 +
122.196 + /// \brief Gives back the node sequence of the found tour.
122.197 + ///
122.198 + /// This function copies the node sequence of the found tour into
122.199 + /// an STL container through the given output iterator. The
122.200 + /// <tt>value_type</tt> of the container must be <tt>FullGraph::Node</tt>.
122.201 + /// For example,
122.202 + /// \code
122.203 + /// std::vector<FullGraph::Node> nodes(countNodes(graph));
122.204 + /// tsp.tourNodes(nodes.begin());
122.205 + /// \endcode
122.206 + /// or
122.207 + /// \code
122.208 + /// std::list<FullGraph::Node> nodes;
122.209 + /// tsp.tourNodes(std::back_inserter(nodes));
122.210 + /// \endcode
122.211 + ///
122.212 + /// \pre run() must be called before using this function.
122.213 + template <typename Iterator>
122.214 + void tourNodes(Iterator out) const {
122.215 + std::copy(_path.begin(), _path.end(), out);
122.216 + }
122.217 +
122.218 + /// \brief Gives back the found tour as a path.
122.219 + ///
122.220 + /// This function copies the found tour as a list of arcs/edges into
122.221 + /// the given \ref lemon::concepts::Path "path structure".
122.222 + ///
122.223 + /// \pre run() must be called before using this function.
122.224 + template <typename Path>
122.225 + void tour(Path &path) const {
122.226 + path.clear();
122.227 + for (int i = 0; i < int(_path.size()) - 1; ++i) {
122.228 + path.addBack(_gr.arc(_path[i], _path[i+1]));
122.229 + }
122.230 + if (int(_path.size()) >= 2) {
122.231 + path.addBack(_gr.arc(_path.back(), _path.front()));
122.232 + }
122.233 + }
122.234 +
122.235 + /// @}
122.236 +
122.237 + };
122.238 +
122.239 +}; // namespace lemon
122.240 +
122.241 +#endif
123.1 --- a/lemon/network_simplex.h Mon Jul 16 16:21:40 2018 +0200
123.2 +++ b/lemon/network_simplex.h Wed Oct 17 19:14:07 2018 +0200
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-2010
123.8 + * Copyright (C) 2003-2013
123.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
123.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
123.11 *
123.12 @@ -41,16 +41,17 @@
123.13 ///
123.14 /// \ref NetworkSimplex implements the primal Network Simplex algorithm
123.15 /// for finding a \ref min_cost_flow "minimum cost flow"
123.16 - /// \ref amo93networkflows, \ref dantzig63linearprog,
123.17 - /// \ref kellyoneill91netsimplex.
123.18 + /// \cite amo93networkflows, \cite dantzig63linearprog,
123.19 + /// \cite kellyoneill91netsimplex.
123.20 /// This algorithm is a highly efficient specialized version of the
123.21 /// linear programming simplex method directly for the minimum cost
123.22 /// flow problem.
123.23 ///
123.24 - /// In general, %NetworkSimplex is the fastest implementation available
123.25 - /// in LEMON for this problem.
123.26 - /// Moreover, it supports both directions of the supply/demand inequality
123.27 - /// constraints. For more information, see \ref SupplyType.
123.28 + /// In general, \ref NetworkSimplex and \ref CostScaling are the fastest
123.29 + /// implementations available in LEMON for solving this problem.
123.30 + /// (For more information, see \ref min_cost_flow_algs "the module page".)
123.31 + /// Furthermore, this class supports both directions of the supply/demand
123.32 + /// inequality constraints. For more information, see \ref SupplyType.
123.33 ///
123.34 /// Most of the parameters of the problem (except for the digraph)
123.35 /// can be given using separate functions, and the algorithm can be
123.36 @@ -63,7 +64,8 @@
123.37 /// \tparam C The number type used for costs and potentials in the
123.38 /// algorithm. By default, it is the same as \c V.
123.39 ///
123.40 - /// \warning Both number types must be signed and all input data must
123.41 + /// \warning Both \c V and \c C must be signed number types.
123.42 + /// \warning All input data (capacities, supply values, and costs) must
123.43 /// be integer.
123.44 ///
123.45 /// \note %NetworkSimplex provides five different pivot rule
123.46 @@ -121,14 +123,17 @@
123.47 /// Enum type containing constants for selecting the pivot rule for
123.48 /// the \ref run() function.
123.49 ///
123.50 - /// \ref NetworkSimplex provides five different pivot rule
123.51 - /// implementations that significantly affect the running time
123.52 + /// \ref NetworkSimplex provides five different implementations for
123.53 + /// the pivot strategy that significantly affects the running time
123.54 /// of the algorithm.
123.55 - /// By default, \ref BLOCK_SEARCH "Block Search" is used, which
123.56 - /// proved to be the most efficient and the most robust on various
123.57 - /// test inputs.
123.58 - /// However, another pivot rule can be selected using the \ref run()
123.59 - /// function with the proper parameter.
123.60 + /// According to experimental tests conducted on various problem
123.61 + /// instances, \ref BLOCK_SEARCH "Block Search" and
123.62 + /// \ref ALTERING_LIST "Altering Candidate List" rules turned out
123.63 + /// to be the most efficient.
123.64 + /// Since \ref BLOCK_SEARCH "Block Search" is a simpler strategy that
123.65 + /// seemed to be slightly more robust, it is used by default.
123.66 + /// However, another pivot rule can easily be selected using the
123.67 + /// \ref run() function with the proper parameter.
123.68 enum PivotRule {
123.69
123.70 /// The \e First \e Eligible pivot rule.
123.71 @@ -154,7 +159,7 @@
123.72
123.73 /// The \e Altering \e Candidate \e List pivot rule.
123.74 /// It is a modified version of the Candidate List method.
123.75 - /// It keeps only the several best eligible arcs from the former
123.76 + /// It keeps only a few of the best eligible arcs from the former
123.77 /// candidate list and extends this list in every iteration.
123.78 ALTERING_LIST
123.79 };
123.80 @@ -166,8 +171,9 @@
123.81 typedef std::vector<int> IntVector;
123.82 typedef std::vector<Value> ValueVector;
123.83 typedef std::vector<Cost> CostVector;
123.84 - typedef std::vector<char> BoolVector;
123.85 - // Note: vector<char> is used instead of vector<bool> for efficiency reasons
123.86 + typedef std::vector<signed char> CharVector;
123.87 + // Note: vector<signed char> is used instead of vector<ArcState> and
123.88 + // vector<ArcDirection> for efficiency reasons
123.89
123.90 // State constants for arcs
123.91 enum ArcState {
123.92 @@ -176,9 +182,11 @@
123.93 STATE_LOWER = 1
123.94 };
123.95
123.96 - typedef std::vector<signed char> StateVector;
123.97 - // Note: vector<signed char> is used instead of vector<ArcState> for
123.98 - // efficiency reasons
123.99 + // Direction constants for tree arcs
123.100 + enum ArcDirection {
123.101 + DIR_DOWN = -1,
123.102 + DIR_UP = 1
123.103 + };
123.104
123.105 private:
123.106
123.107 @@ -190,7 +198,7 @@
123.108 int _search_arc_num;
123.109
123.110 // Parameters of the problem
123.111 - bool _have_lower;
123.112 + bool _has_lower;
123.113 SupplyType _stype;
123.114 Value _sum_supply;
123.115
123.116 @@ -217,15 +225,13 @@
123.117 IntVector _rev_thread;
123.118 IntVector _succ_num;
123.119 IntVector _last_succ;
123.120 + CharVector _pred_dir;
123.121 + CharVector _state;
123.122 IntVector _dirty_revs;
123.123 - BoolVector _forward;
123.124 - StateVector _state;
123.125 int _root;
123.126
123.127 // Temporary data used in the current pivot iteration
123.128 int in_arc, join, u_in, v_in, u_out, v_out;
123.129 - int first, second, right, last;
123.130 - int stem, par_stem, new_stem;
123.131 Value delta;
123.132
123.133 const Value MAX;
123.134 @@ -250,7 +256,7 @@
123.135 const IntVector &_source;
123.136 const IntVector &_target;
123.137 const CostVector &_cost;
123.138 - const StateVector &_state;
123.139 + const CharVector &_state;
123.140 const CostVector &_pi;
123.141 int &_in_arc;
123.142 int _search_arc_num;
123.143 @@ -302,7 +308,7 @@
123.144 const IntVector &_source;
123.145 const IntVector &_target;
123.146 const CostVector &_cost;
123.147 - const StateVector &_state;
123.148 + const CharVector &_state;
123.149 const CostVector &_pi;
123.150 int &_in_arc;
123.151 int _search_arc_num;
123.152 @@ -341,7 +347,7 @@
123.153 const IntVector &_source;
123.154 const IntVector &_target;
123.155 const CostVector &_cost;
123.156 - const StateVector &_state;
123.157 + const CharVector &_state;
123.158 const CostVector &_pi;
123.159 int &_in_arc;
123.160 int _search_arc_num;
123.161 @@ -414,7 +420,7 @@
123.162 const IntVector &_source;
123.163 const IntVector &_target;
123.164 const CostVector &_cost;
123.165 - const StateVector &_state;
123.166 + const CharVector &_state;
123.167 const CostVector &_pi;
123.168 int &_in_arc;
123.169 int _search_arc_num;
123.170 @@ -517,7 +523,7 @@
123.171 const IntVector &_source;
123.172 const IntVector &_target;
123.173 const CostVector &_cost;
123.174 - const StateVector &_state;
123.175 + const CharVector &_state;
123.176 const CostVector &_pi;
123.177 int &_in_arc;
123.178 int _search_arc_num;
123.179 @@ -536,7 +542,7 @@
123.180 public:
123.181 SortFunc(const CostVector &map) : _map(map) {}
123.182 bool operator()(int left, int right) {
123.183 - return _map[left] > _map[right];
123.184 + return _map[left] < _map[right];
123.185 }
123.186 };
123.187
123.188 @@ -554,7 +560,7 @@
123.189 // The main parameters of the pivot rule
123.190 const double BLOCK_SIZE_FACTOR = 1.0;
123.191 const int MIN_BLOCK_SIZE = 10;
123.192 - const double HEAD_LENGTH_FACTOR = 0.1;
123.193 + const double HEAD_LENGTH_FACTOR = 0.01;
123.194 const int MIN_HEAD_LENGTH = 3;
123.195
123.196 _block_size = std::max( int(BLOCK_SIZE_FACTOR *
123.197 @@ -570,11 +576,13 @@
123.198 bool findEnteringArc() {
123.199 // Check the current candidate list
123.200 int e;
123.201 + Cost c;
123.202 for (int i = 0; i != _curr_length; ++i) {
123.203 e = _candidates[i];
123.204 - _cand_cost[e] = _state[e] *
123.205 - (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
123.206 - if (_cand_cost[e] >= 0) {
123.207 + c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
123.208 + if (c < 0) {
123.209 + _cand_cost[e] = c;
123.210 + } else {
123.211 _candidates[i--] = _candidates[--_curr_length];
123.212 }
123.213 }
123.214 @@ -584,9 +592,9 @@
123.215 int limit = _head_length;
123.216
123.217 for (e = _next_arc; e != _search_arc_num; ++e) {
123.218 - _cand_cost[e] = _state[e] *
123.219 - (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
123.220 - if (_cand_cost[e] < 0) {
123.221 + c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
123.222 + if (c < 0) {
123.223 + _cand_cost[e] = c;
123.224 _candidates[_curr_length++] = e;
123.225 }
123.226 if (--cnt == 0) {
123.227 @@ -596,9 +604,9 @@
123.228 }
123.229 }
123.230 for (e = 0; e != _next_arc; ++e) {
123.231 - _cand_cost[e] = _state[e] *
123.232 - (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
123.233 - if (_cand_cost[e] < 0) {
123.234 + c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
123.235 + if (c < 0) {
123.236 + _cand_cost[e] = c;
123.237 _candidates[_curr_length++] = e;
123.238 }
123.239 if (--cnt == 0) {
123.240 @@ -611,16 +619,16 @@
123.241
123.242 search_end:
123.243
123.244 - // Make heap of the candidate list (approximating a partial sort)
123.245 - make_heap( _candidates.begin(), _candidates.begin() + _curr_length,
123.246 - _sort_func );
123.247 + // Perform partial sort operation on the candidate list
123.248 + int new_length = std::min(_head_length + 1, _curr_length);
123.249 + std::partial_sort(_candidates.begin(), _candidates.begin() + new_length,
123.250 + _candidates.begin() + _curr_length, _sort_func);
123.251
123.252 - // Pop the first element of the heap
123.253 + // Select the entering arc and remove it from the list
123.254 _in_arc = _candidates[0];
123.255 _next_arc = e;
123.256 - pop_heap( _candidates.begin(), _candidates.begin() + _curr_length,
123.257 - _sort_func );
123.258 - _curr_length = std::min(_head_length, _curr_length - 1);
123.259 + _candidates[0] = _candidates[new_length - 1];
123.260 + _curr_length = new_length - 1;
123.261 return true;
123.262 }
123.263
123.264 @@ -633,11 +641,12 @@
123.265 /// The constructor of the class.
123.266 ///
123.267 /// \param graph The digraph the algorithm runs on.
123.268 - /// \param arc_mixing Indicate if the arcs have to be stored in a
123.269 + /// \param arc_mixing Indicate if the arcs will be stored in a
123.270 /// mixed order in the internal data structure.
123.271 - /// In special cases, it could lead to better overall performance,
123.272 - /// but it is usually slower. Therefore it is disabled by default.
123.273 - NetworkSimplex(const GR& graph, bool arc_mixing = false) :
123.274 + /// In general, it leads to similar performance as using the original
123.275 + /// arc order, but it makes the algorithm more robust and in special
123.276 + /// cases, even significantly faster. Therefore, it is enabled by default.
123.277 + NetworkSimplex(const GR& graph, bool arc_mixing = true) :
123.278 _graph(graph), _node_id(graph), _arc_id(graph),
123.279 _arc_mixing(arc_mixing),
123.280 MAX(std::numeric_limits<Value>::max()),
123.281 @@ -673,7 +682,7 @@
123.282 /// \return <tt>(*this)</tt>
123.283 template <typename LowerMap>
123.284 NetworkSimplex& lowerMap(const LowerMap& map) {
123.285 - _have_lower = true;
123.286 + _has_lower = true;
123.287 for (ArcIt a(_graph); a != INVALID; ++a) {
123.288 _lower[_arc_id[a]] = map[a];
123.289 }
123.290 @@ -730,6 +739,8 @@
123.291 /// of the algorithm.
123.292 ///
123.293 /// \return <tt>(*this)</tt>
123.294 + ///
123.295 + /// \sa supplyType()
123.296 template<typename SupplyMap>
123.297 NetworkSimplex& supplyMap(const SupplyMap& map) {
123.298 for (NodeIt n(_graph); n != INVALID; ++n) {
123.299 @@ -746,7 +757,7 @@
123.300 /// calling \ref run(), the supply of each node will be set to zero.
123.301 ///
123.302 /// Using this function has the same effect as using \ref supplyMap()
123.303 - /// with such a map in which \c k is assigned to \c s, \c -k is
123.304 + /// with a map in which \c k is assigned to \c s, \c -k is
123.305 /// assigned to \c t and all other nodes have zero supply value.
123.306 ///
123.307 /// \param s The source node.
123.308 @@ -868,7 +879,7 @@
123.309 _upper[i] = INF;
123.310 _cost[i] = 1;
123.311 }
123.312 - _have_lower = false;
123.313 + _has_lower = false;
123.314 _stype = GEQ;
123.315 return *this;
123.316 }
123.317 @@ -913,7 +924,7 @@
123.318
123.319 _parent.resize(all_node_num);
123.320 _pred.resize(all_node_num);
123.321 - _forward.resize(all_node_num);
123.322 + _pred_dir.resize(all_node_num);
123.323 _thread.resize(all_node_num);
123.324 _rev_thread.resize(all_node_num);
123.325 _succ_num.resize(all_node_num);
123.326 @@ -925,15 +936,15 @@
123.327 for (NodeIt n(_graph); n != INVALID; ++n, ++i) {
123.328 _node_id[n] = i;
123.329 }
123.330 - if (_arc_mixing) {
123.331 + if (_arc_mixing && _node_num > 1) {
123.332 // Store the arcs in a mixed order
123.333 - int k = std::max(int(std::sqrt(double(_arc_num))), 10);
123.334 + const int skip = std::max(_arc_num / _node_num, 3);
123.335 int i = 0, j = 0;
123.336 for (ArcIt a(_graph); a != INVALID; ++a) {
123.337 _arc_id[a] = i;
123.338 _source[i] = _node_id[_graph.source(a)];
123.339 _target[i] = _node_id[_graph.target(a)];
123.340 - if ((i += k) >= _arc_num) i = ++j;
123.341 + if ((i += skip) >= _arc_num) i = ++j;
123.342 }
123.343 } else {
123.344 // Store the arcs in the original order
123.345 @@ -962,7 +973,7 @@
123.346 /// \brief Return the total cost of the found flow.
123.347 ///
123.348 /// This function returns the total cost of the found flow.
123.349 - /// Its complexity is O(e).
123.350 + /// Its complexity is O(m).
123.351 ///
123.352 /// \note The return type of the function can be specified as a
123.353 /// template parameter. For example,
123.354 @@ -999,7 +1010,8 @@
123.355 return _flow[_arc_id[a]];
123.356 }
123.357
123.358 - /// \brief Return the flow map (the primal solution).
123.359 + /// \brief Copy the flow values (the primal solution) into the
123.360 + /// given map.
123.361 ///
123.362 /// This function copies the flow value on each arc into the given
123.363 /// map. The \c Value type of the algorithm must be convertible to
123.364 @@ -1023,7 +1035,8 @@
123.365 return _pi[_node_id[n]];
123.366 }
123.367
123.368 - /// \brief Return the potential map (the dual solution).
123.369 + /// \brief Copy the potential values (the dual solution) into the
123.370 + /// given map.
123.371 ///
123.372 /// This function copies the potential (dual value) of each node
123.373 /// into the given map.
123.374 @@ -1054,8 +1067,12 @@
123.375 if ( !((_stype == GEQ && _sum_supply <= 0) ||
123.376 (_stype == LEQ && _sum_supply >= 0)) ) return false;
123.377
123.378 + // Check lower and upper bounds
123.379 + LEMON_DEBUG(checkBoundMaps(),
123.380 + "Upper bounds must be greater or equal to the lower bounds");
123.381 +
123.382 // Remove non-zero lower bounds
123.383 - if (_have_lower) {
123.384 + if (_has_lower) {
123.385 for (int i = 0; i != _arc_num; ++i) {
123.386 Value c = _lower[i];
123.387 if (c >= 0) {
123.388 @@ -1116,14 +1133,14 @@
123.389 _cap[e] = INF;
123.390 _state[e] = STATE_TREE;
123.391 if (_supply[u] >= 0) {
123.392 - _forward[u] = true;
123.393 + _pred_dir[u] = DIR_UP;
123.394 _pi[u] = 0;
123.395 _source[e] = u;
123.396 _target[e] = _root;
123.397 _flow[e] = _supply[u];
123.398 _cost[e] = 0;
123.399 } else {
123.400 - _forward[u] = false;
123.401 + _pred_dir[u] = DIR_DOWN;
123.402 _pi[u] = ART_COST;
123.403 _source[e] = _root;
123.404 _target[e] = u;
123.405 @@ -1143,7 +1160,7 @@
123.406 _succ_num[u] = 1;
123.407 _last_succ[u] = u;
123.408 if (_supply[u] >= 0) {
123.409 - _forward[u] = true;
123.410 + _pred_dir[u] = DIR_UP;
123.411 _pi[u] = 0;
123.412 _pred[u] = e;
123.413 _source[e] = u;
123.414 @@ -1153,7 +1170,7 @@
123.415 _cost[e] = 0;
123.416 _state[e] = STATE_TREE;
123.417 } else {
123.418 - _forward[u] = false;
123.419 + _pred_dir[u] = DIR_DOWN;
123.420 _pi[u] = ART_COST;
123.421 _pred[u] = f;
123.422 _source[f] = _root;
123.423 @@ -1184,7 +1201,7 @@
123.424 _succ_num[u] = 1;
123.425 _last_succ[u] = u;
123.426 if (_supply[u] <= 0) {
123.427 - _forward[u] = false;
123.428 + _pred_dir[u] = DIR_DOWN;
123.429 _pi[u] = 0;
123.430 _pred[u] = e;
123.431 _source[e] = _root;
123.432 @@ -1194,7 +1211,7 @@
123.433 _cost[e] = 0;
123.434 _state[e] = STATE_TREE;
123.435 } else {
123.436 - _forward[u] = true;
123.437 + _pred_dir[u] = DIR_UP;
123.438 _pi[u] = -ART_COST;
123.439 _pred[u] = f;
123.440 _source[f] = u;
123.441 @@ -1218,6 +1235,15 @@
123.442 return true;
123.443 }
123.444
123.445 + // Check if the upper bound is greater than or equal to the lower bound
123.446 + // on each arc.
123.447 + bool checkBoundMaps() {
123.448 + for (int j = 0; j != _arc_num; ++j) {
123.449 + if (_upper[j] < _lower[j]) return false;
123.450 + }
123.451 + return true;
123.452 + }
123.453 +
123.454 // Find the join node
123.455 void findJoinNode() {
123.456 int u = _source[in_arc];
123.457 @@ -1237,6 +1263,7 @@
123.458 bool findLeavingArc() {
123.459 // Initialize first and second nodes according to the direction
123.460 // of the cycle
123.461 + int first, second;
123.462 if (_state[in_arc] == STATE_LOWER) {
123.463 first = _source[in_arc];
123.464 second = _target[in_arc];
123.465 @@ -1246,25 +1273,32 @@
123.466 }
123.467 delta = _cap[in_arc];
123.468 int result = 0;
123.469 - Value d;
123.470 + Value c, d;
123.471 int e;
123.472
123.473 - // Search the cycle along the path form the first node to the root
123.474 + // Search the cycle form the first node to the join node
123.475 for (int u = first; u != join; u = _parent[u]) {
123.476 e = _pred[u];
123.477 - d = _forward[u] ?
123.478 - _flow[e] : (_cap[e] >= MAX ? INF : _cap[e] - _flow[e]);
123.479 + d = _flow[e];
123.480 + if (_pred_dir[u] == DIR_DOWN) {
123.481 + c = _cap[e];
123.482 + d = c >= MAX ? INF : c - d;
123.483 + }
123.484 if (d < delta) {
123.485 delta = d;
123.486 u_out = u;
123.487 result = 1;
123.488 }
123.489 }
123.490 - // Search the cycle along the path form the second node to the root
123.491 +
123.492 + // Search the cycle form the second node to the join node
123.493 for (int u = second; u != join; u = _parent[u]) {
123.494 e = _pred[u];
123.495 - d = _forward[u] ?
123.496 - (_cap[e] >= MAX ? INF : _cap[e] - _flow[e]) : _flow[e];
123.497 + d = _flow[e];
123.498 + if (_pred_dir[u] == DIR_UP) {
123.499 + c = _cap[e];
123.500 + d = c >= MAX ? INF : c - d;
123.501 + }
123.502 if (d <= delta) {
123.503 delta = d;
123.504 u_out = u;
123.505 @@ -1289,10 +1323,10 @@
123.506 Value val = _state[in_arc] * delta;
123.507 _flow[in_arc] += val;
123.508 for (int u = _source[in_arc]; u != join; u = _parent[u]) {
123.509 - _flow[_pred[u]] += _forward[u] ? -val : val;
123.510 + _flow[_pred[u]] -= _pred_dir[u] * val;
123.511 }
123.512 for (int u = _target[in_arc]; u != join; u = _parent[u]) {
123.513 - _flow[_pred[u]] += _forward[u] ? val : -val;
123.514 + _flow[_pred[u]] += _pred_dir[u] * val;
123.515 }
123.516 }
123.517 // Update the state of the entering and leaving arcs
123.518 @@ -1307,130 +1341,134 @@
123.519
123.520 // Update the tree structure
123.521 void updateTreeStructure() {
123.522 - int u, w;
123.523 int old_rev_thread = _rev_thread[u_out];
123.524 int old_succ_num = _succ_num[u_out];
123.525 int old_last_succ = _last_succ[u_out];
123.526 v_out = _parent[u_out];
123.527
123.528 - u = _last_succ[u_in]; // the last successor of u_in
123.529 - right = _thread[u]; // the node after it
123.530 + // Check if u_in and u_out coincide
123.531 + if (u_in == u_out) {
123.532 + // Update _parent, _pred, _pred_dir
123.533 + _parent[u_in] = v_in;
123.534 + _pred[u_in] = in_arc;
123.535 + _pred_dir[u_in] = u_in == _source[in_arc] ? DIR_UP : DIR_DOWN;
123.536
123.537 - // Handle the case when old_rev_thread equals to v_in
123.538 - // (it also means that join and v_out coincide)
123.539 - if (old_rev_thread == v_in) {
123.540 - last = _thread[_last_succ[u_out]];
123.541 + // Update _thread and _rev_thread
123.542 + if (_thread[v_in] != u_out) {
123.543 + int after = _thread[old_last_succ];
123.544 + _thread[old_rev_thread] = after;
123.545 + _rev_thread[after] = old_rev_thread;
123.546 + after = _thread[v_in];
123.547 + _thread[v_in] = u_out;
123.548 + _rev_thread[u_out] = v_in;
123.549 + _thread[old_last_succ] = after;
123.550 + _rev_thread[after] = old_last_succ;
123.551 + }
123.552 } else {
123.553 - last = _thread[v_in];
123.554 - }
123.555 + // Handle the case when old_rev_thread equals to v_in
123.556 + // (it also means that join and v_out coincide)
123.557 + int thread_continue = old_rev_thread == v_in ?
123.558 + _thread[old_last_succ] : _thread[v_in];
123.559
123.560 - // Update _thread and _parent along the stem nodes (i.e. the nodes
123.561 - // between u_in and u_out, whose parent have to be changed)
123.562 - _thread[v_in] = stem = u_in;
123.563 - _dirty_revs.clear();
123.564 - _dirty_revs.push_back(v_in);
123.565 - par_stem = v_in;
123.566 - while (stem != u_out) {
123.567 - // Insert the next stem node into the thread list
123.568 - new_stem = _parent[stem];
123.569 - _thread[u] = new_stem;
123.570 - _dirty_revs.push_back(u);
123.571 + // Update _thread and _parent along the stem nodes (i.e. the nodes
123.572 + // between u_in and u_out, whose parent have to be changed)
123.573 + int stem = u_in; // the current stem node
123.574 + int par_stem = v_in; // the new parent of stem
123.575 + int next_stem; // the next stem node
123.576 + int last = _last_succ[u_in]; // the last successor of stem
123.577 + int before, after = _thread[last];
123.578 + _thread[v_in] = u_in;
123.579 + _dirty_revs.clear();
123.580 + _dirty_revs.push_back(v_in);
123.581 + while (stem != u_out) {
123.582 + // Insert the next stem node into the thread list
123.583 + next_stem = _parent[stem];
123.584 + _thread[last] = next_stem;
123.585 + _dirty_revs.push_back(last);
123.586
123.587 - // Remove the subtree of stem from the thread list
123.588 - w = _rev_thread[stem];
123.589 - _thread[w] = right;
123.590 - _rev_thread[right] = w;
123.591 + // Remove the subtree of stem from the thread list
123.592 + before = _rev_thread[stem];
123.593 + _thread[before] = after;
123.594 + _rev_thread[after] = before;
123.595
123.596 - // Change the parent node and shift stem nodes
123.597 - _parent[stem] = par_stem;
123.598 - par_stem = stem;
123.599 - stem = new_stem;
123.600 + // Change the parent node and shift stem nodes
123.601 + _parent[stem] = par_stem;
123.602 + par_stem = stem;
123.603 + stem = next_stem;
123.604
123.605 - // Update u and right
123.606 - u = _last_succ[stem] == _last_succ[par_stem] ?
123.607 - _rev_thread[par_stem] : _last_succ[stem];
123.608 - right = _thread[u];
123.609 - }
123.610 - _parent[u_out] = par_stem;
123.611 - _thread[u] = last;
123.612 - _rev_thread[last] = u;
123.613 - _last_succ[u_out] = u;
123.614 + // Update last and after
123.615 + last = _last_succ[stem] == _last_succ[par_stem] ?
123.616 + _rev_thread[par_stem] : _last_succ[stem];
123.617 + after = _thread[last];
123.618 + }
123.619 + _parent[u_out] = par_stem;
123.620 + _thread[last] = thread_continue;
123.621 + _rev_thread[thread_continue] = last;
123.622 + _last_succ[u_out] = last;
123.623
123.624 - // Remove the subtree of u_out from the thread list except for
123.625 - // the case when old_rev_thread equals to v_in
123.626 - // (it also means that join and v_out coincide)
123.627 - if (old_rev_thread != v_in) {
123.628 - _thread[old_rev_thread] = right;
123.629 - _rev_thread[right] = old_rev_thread;
123.630 - }
123.631 + // Remove the subtree of u_out from the thread list except for
123.632 + // the case when old_rev_thread equals to v_in
123.633 + if (old_rev_thread != v_in) {
123.634 + _thread[old_rev_thread] = after;
123.635 + _rev_thread[after] = old_rev_thread;
123.636 + }
123.637
123.638 - // Update _rev_thread using the new _thread values
123.639 - for (int i = 0; i != int(_dirty_revs.size()); ++i) {
123.640 - u = _dirty_revs[i];
123.641 - _rev_thread[_thread[u]] = u;
123.642 - }
123.643 + // Update _rev_thread using the new _thread values
123.644 + for (int i = 0; i != int(_dirty_revs.size()); ++i) {
123.645 + int u = _dirty_revs[i];
123.646 + _rev_thread[_thread[u]] = u;
123.647 + }
123.648
123.649 - // Update _pred, _forward, _last_succ and _succ_num for the
123.650 - // stem nodes from u_out to u_in
123.651 - int tmp_sc = 0, tmp_ls = _last_succ[u_out];
123.652 - u = u_out;
123.653 - while (u != u_in) {
123.654 - w = _parent[u];
123.655 - _pred[u] = _pred[w];
123.656 - _forward[u] = !_forward[w];
123.657 - tmp_sc += _succ_num[u] - _succ_num[w];
123.658 - _succ_num[u] = tmp_sc;
123.659 - _last_succ[w] = tmp_ls;
123.660 - u = w;
123.661 - }
123.662 - _pred[u_in] = in_arc;
123.663 - _forward[u_in] = (u_in == _source[in_arc]);
123.664 - _succ_num[u_in] = old_succ_num;
123.665 -
123.666 - // Set limits for updating _last_succ form v_in and v_out
123.667 - // towards the root
123.668 - int up_limit_in = -1;
123.669 - int up_limit_out = -1;
123.670 - if (_last_succ[join] == v_in) {
123.671 - up_limit_out = join;
123.672 - } else {
123.673 - up_limit_in = join;
123.674 + // Update _pred, _pred_dir, _last_succ and _succ_num for the
123.675 + // stem nodes from u_out to u_in
123.676 + int tmp_sc = 0, tmp_ls = _last_succ[u_out];
123.677 + for (int u = u_out, p = _parent[u]; u != u_in; u = p, p = _parent[u]) {
123.678 + _pred[u] = _pred[p];
123.679 + _pred_dir[u] = -_pred_dir[p];
123.680 + tmp_sc += _succ_num[u] - _succ_num[p];
123.681 + _succ_num[u] = tmp_sc;
123.682 + _last_succ[p] = tmp_ls;
123.683 + }
123.684 + _pred[u_in] = in_arc;
123.685 + _pred_dir[u_in] = u_in == _source[in_arc] ? DIR_UP : DIR_DOWN;
123.686 + _succ_num[u_in] = old_succ_num;
123.687 }
123.688
123.689 // Update _last_succ from v_in towards the root
123.690 - for (u = v_in; u != up_limit_in && _last_succ[u] == v_in;
123.691 - u = _parent[u]) {
123.692 - _last_succ[u] = _last_succ[u_out];
123.693 + int up_limit_out = _last_succ[join] == v_in ? join : -1;
123.694 + int last_succ_out = _last_succ[u_out];
123.695 + for (int u = v_in; u != -1 && _last_succ[u] == v_in; u = _parent[u]) {
123.696 + _last_succ[u] = last_succ_out;
123.697 }
123.698 +
123.699 // Update _last_succ from v_out towards the root
123.700 if (join != old_rev_thread && v_in != old_rev_thread) {
123.701 - for (u = v_out; u != up_limit_out && _last_succ[u] == old_last_succ;
123.702 + for (int u = v_out; u != up_limit_out && _last_succ[u] == old_last_succ;
123.703 u = _parent[u]) {
123.704 _last_succ[u] = old_rev_thread;
123.705 }
123.706 - } else {
123.707 - for (u = v_out; u != up_limit_out && _last_succ[u] == old_last_succ;
123.708 + }
123.709 + else if (last_succ_out != old_last_succ) {
123.710 + for (int u = v_out; u != up_limit_out && _last_succ[u] == old_last_succ;
123.711 u = _parent[u]) {
123.712 - _last_succ[u] = _last_succ[u_out];
123.713 + _last_succ[u] = last_succ_out;
123.714 }
123.715 }
123.716
123.717 // Update _succ_num from v_in to join
123.718 - for (u = v_in; u != join; u = _parent[u]) {
123.719 + for (int u = v_in; u != join; u = _parent[u]) {
123.720 _succ_num[u] += old_succ_num;
123.721 }
123.722 // Update _succ_num from v_out to join
123.723 - for (u = v_out; u != join; u = _parent[u]) {
123.724 + for (int u = v_out; u != join; u = _parent[u]) {
123.725 _succ_num[u] -= old_succ_num;
123.726 }
123.727 }
123.728
123.729 - // Update potentials
123.730 + // Update potentials in the subtree that has been moved
123.731 void updatePotential() {
123.732 - Cost sigma = _forward[u_in] ?
123.733 - _pi[v_in] - _pi[u_in] - _cost[_pred[u_in]] :
123.734 - _pi[v_in] - _pi[u_in] + _cost[_pred[u_in]];
123.735 - // Update potentials in the subtree, which has been moved
123.736 + Cost sigma = _pi[v_in] - _pi[u_in] -
123.737 + _pred_dir[u_in] * _cost[in_arc];
123.738 int end = _thread[_last_succ[u_in]];
123.739 for (int u = u_in; u != end; u = _thread[u]) {
123.740 _pi[u] += sigma;
123.741 @@ -1478,7 +1516,7 @@
123.742 }
123.743 }
123.744 } else {
123.745 - // Find the min. cost incomming arc for each demand node
123.746 + // Find the min. cost incoming arc for each demand node
123.747 for (int i = 0; i != int(demand_nodes.size()); ++i) {
123.748 Node v = demand_nodes[i];
123.749 Cost c, min_cost = std::numeric_limits<Cost>::max();
123.750 @@ -1574,7 +1612,7 @@
123.751 }
123.752
123.753 // Transform the solution and the supply map to the original form
123.754 - if (_have_lower) {
123.755 + if (_has_lower) {
123.756 for (int i = 0; i != _arc_num; ++i) {
123.757 Value c = _lower[i];
123.758 if (c != 0) {
124.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
124.2 +++ b/lemon/opt2_tsp.h Wed Oct 17 19:14:07 2018 +0200
124.3 @@ -0,0 +1,367 @@
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-2013
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 +#ifndef LEMON_OPT2_TSP_H
124.23 +#define LEMON_OPT2_TSP_H
124.24 +
124.25 +/// \ingroup tsp
124.26 +/// \file
124.27 +/// \brief 2-opt algorithm for symmetric TSP.
124.28 +
124.29 +#include <vector>
124.30 +#include <lemon/full_graph.h>
124.31 +
124.32 +namespace lemon {
124.33 +
124.34 + /// \ingroup tsp
124.35 + ///
124.36 + /// \brief 2-opt algorithm for symmetric TSP.
124.37 + ///
124.38 + /// Opt2Tsp implements the 2-opt heuristic for solving
124.39 + /// symmetric \ref tsp "TSP".
124.40 + ///
124.41 + /// This algorithm starts with an initial tour and iteratively improves it.
124.42 + /// At each step, it removes two edges and the reconnects the created two
124.43 + /// paths in the other way if the resulting tour is shorter.
124.44 + /// The algorithm finishes when no such 2-opt move can be applied, and so
124.45 + /// the tour is 2-optimal.
124.46 + ///
124.47 + /// If no starting tour is given to the \ref run() function, then the
124.48 + /// algorithm uses the node sequence determined by the node IDs.
124.49 + /// Oherwise, it starts with the given tour.
124.50 + ///
124.51 + /// This is a rather slow but effective method.
124.52 + /// Its typical usage is the improvement of the result of a fast tour
124.53 + /// construction heuristic (e.g. the InsertionTsp algorithm).
124.54 + ///
124.55 + /// \tparam CM Type of the cost map.
124.56 + template <typename CM>
124.57 + class Opt2Tsp
124.58 + {
124.59 + public:
124.60 +
124.61 + /// Type of the cost map
124.62 + typedef CM CostMap;
124.63 + /// Type of the edge costs
124.64 + typedef typename CM::Value Cost;
124.65 +
124.66 + private:
124.67 +
124.68 + GRAPH_TYPEDEFS(FullGraph);
124.69 +
124.70 + const FullGraph &_gr;
124.71 + const CostMap &_cost;
124.72 + Cost _sum;
124.73 + std::vector<int> _plist;
124.74 + std::vector<Node> _path;
124.75 +
124.76 + public:
124.77 +
124.78 + /// \brief Constructor
124.79 + ///
124.80 + /// Constructor.
124.81 + /// \param gr The \ref FullGraph "full graph" the algorithm runs on.
124.82 + /// \param cost The cost map.
124.83 + Opt2Tsp(const FullGraph &gr, const CostMap &cost)
124.84 + : _gr(gr), _cost(cost) {}
124.85 +
124.86 + /// \name Execution Control
124.87 + /// @{
124.88 +
124.89 + /// \brief Runs the algorithm from scratch.
124.90 + ///
124.91 + /// This function runs the algorithm starting from the tour that is
124.92 + /// determined by the node ID sequence.
124.93 + ///
124.94 + /// \return The total cost of the found tour.
124.95 + Cost run() {
124.96 + _path.clear();
124.97 +
124.98 + if (_gr.nodeNum() == 0) return _sum = 0;
124.99 + else if (_gr.nodeNum() == 1) {
124.100 + _path.push_back(_gr(0));
124.101 + return _sum = 0;
124.102 + }
124.103 + else if (_gr.nodeNum() == 2) {
124.104 + _path.push_back(_gr(0));
124.105 + _path.push_back(_gr(1));
124.106 + return _sum = 2 * _cost[_gr.edge(_gr(0), _gr(1))];
124.107 + }
124.108 +
124.109 + _plist.resize(2*_gr.nodeNum());
124.110 + for (int i = 1; i < _gr.nodeNum()-1; ++i) {
124.111 + _plist[2*i] = i-1;
124.112 + _plist[2*i+1] = i+1;
124.113 + }
124.114 + _plist[0] = _gr.nodeNum()-1;
124.115 + _plist[1] = 1;
124.116 + _plist[2*_gr.nodeNum()-2] = _gr.nodeNum()-2;
124.117 + _plist[2*_gr.nodeNum()-1] = 0;
124.118 +
124.119 + return start();
124.120 + }
124.121 +
124.122 + /// \brief Runs the algorithm starting from the given tour.
124.123 + ///
124.124 + /// This function runs the algorithm starting from the given tour.
124.125 + ///
124.126 + /// \param tour The tour as a path structure. It must be a
124.127 + /// \ref checkPath() "valid path" containing excactly n arcs.
124.128 + ///
124.129 + /// \return The total cost of the found tour.
124.130 + template <typename Path>
124.131 + Cost run(const Path& tour) {
124.132 + _path.clear();
124.133 +
124.134 + if (_gr.nodeNum() == 0) return _sum = 0;
124.135 + else if (_gr.nodeNum() == 1) {
124.136 + _path.push_back(_gr(0));
124.137 + return _sum = 0;
124.138 + }
124.139 + else if (_gr.nodeNum() == 2) {
124.140 + _path.push_back(_gr(0));
124.141 + _path.push_back(_gr(1));
124.142 + return _sum = 2 * _cost[_gr.edge(_gr(0), _gr(1))];
124.143 + }
124.144 +
124.145 + _plist.resize(2*_gr.nodeNum());
124.146 + typename Path::ArcIt it(tour);
124.147 + int first = _gr.id(_gr.source(it)),
124.148 + prev = first,
124.149 + curr = _gr.id(_gr.target(it)),
124.150 + next = -1;
124.151 + _plist[2*first+1] = curr;
124.152 + for (++it; it != INVALID; ++it) {
124.153 + next = _gr.id(_gr.target(it));
124.154 + _plist[2*curr] = prev;
124.155 + _plist[2*curr+1] = next;
124.156 + prev = curr;
124.157 + curr = next;
124.158 + }
124.159 + _plist[2*first] = prev;
124.160 +
124.161 + return start();
124.162 + }
124.163 +
124.164 + /// \brief Runs the algorithm starting from the given tour.
124.165 + ///
124.166 + /// This function runs the algorithm starting from the given tour
124.167 + /// (node sequence).
124.168 + ///
124.169 + /// \param tour A vector that stores all <tt>Node</tt>s of the graph
124.170 + /// in the desired order.
124.171 + ///
124.172 + /// \return The total cost of the found tour.
124.173 + Cost run(const std::vector<Node>& tour) {
124.174 + _path.clear();
124.175 +
124.176 + if (_gr.nodeNum() == 0) return _sum = 0;
124.177 + else if (_gr.nodeNum() == 1) {
124.178 + _path.push_back(_gr(0));
124.179 + return _sum = 0;
124.180 + }
124.181 + else if (_gr.nodeNum() == 2) {
124.182 + _path.push_back(_gr(0));
124.183 + _path.push_back(_gr(1));
124.184 + return _sum = 2 * _cost[_gr.edge(_gr(0), _gr(1))];
124.185 + }
124.186 +
124.187 + _plist.resize(2*_gr.nodeNum());
124.188 + typename std::vector<Node>::const_iterator it = tour.begin();
124.189 + int first = _gr.id(*it),
124.190 + prev = first,
124.191 + curr = _gr.id(*(++it)),
124.192 + next = -1;
124.193 + _plist[2*first+1] = curr;
124.194 + for (++it; it != tour.end(); ++it) {
124.195 + next = _gr.id(*it);
124.196 + _plist[2*curr] = prev;
124.197 + _plist[2*curr+1] = next;
124.198 + prev = curr;
124.199 + curr = next;
124.200 + }
124.201 + _plist[2*first] = curr;
124.202 + _plist[2*curr] = prev;
124.203 + _plist[2*curr+1] = first;
124.204 +
124.205 + return start();
124.206 + }
124.207 +
124.208 + /// @}
124.209 +
124.210 + /// \name Query Functions
124.211 + /// @{
124.212 +
124.213 + /// \brief The total cost of the found tour.
124.214 + ///
124.215 + /// This function returns the total cost of the found tour.
124.216 + ///
124.217 + /// \pre run() must be called before using this function.
124.218 + Cost tourCost() const {
124.219 + return _sum;
124.220 + }
124.221 +
124.222 + /// \brief Returns a const reference to the node sequence of the
124.223 + /// found tour.
124.224 + ///
124.225 + /// This function returns a const reference to a vector
124.226 + /// that stores the node sequence of the found tour.
124.227 + ///
124.228 + /// \pre run() must be called before using this function.
124.229 + const std::vector<Node>& tourNodes() const {
124.230 + return _path;
124.231 + }
124.232 +
124.233 + /// \brief Gives back the node sequence of the found tour.
124.234 + ///
124.235 + /// This function copies the node sequence of the found tour into
124.236 + /// an STL container through the given output iterator. The
124.237 + /// <tt>value_type</tt> of the container must be <tt>FullGraph::Node</tt>.
124.238 + /// For example,
124.239 + /// \code
124.240 + /// std::vector<FullGraph::Node> nodes(countNodes(graph));
124.241 + /// tsp.tourNodes(nodes.begin());
124.242 + /// \endcode
124.243 + /// or
124.244 + /// \code
124.245 + /// std::list<FullGraph::Node> nodes;
124.246 + /// tsp.tourNodes(std::back_inserter(nodes));
124.247 + /// \endcode
124.248 + ///
124.249 + /// \pre run() must be called before using this function.
124.250 + template <typename Iterator>
124.251 + void tourNodes(Iterator out) const {
124.252 + std::copy(_path.begin(), _path.end(), out);
124.253 + }
124.254 +
124.255 + /// \brief Gives back the found tour as a path.
124.256 + ///
124.257 + /// This function copies the found tour as a list of arcs/edges into
124.258 + /// the given \ref lemon::concepts::Path "path structure".
124.259 + ///
124.260 + /// \pre run() must be called before using this function.
124.261 + template <typename Path>
124.262 + void tour(Path &path) const {
124.263 + path.clear();
124.264 + for (int i = 0; i < int(_path.size()) - 1; ++i) {
124.265 + path.addBack(_gr.arc(_path[i], _path[i+1]));
124.266 + }
124.267 + if (int(_path.size()) >= 2) {
124.268 + path.addBack(_gr.arc(_path.back(), _path.front()));
124.269 + }
124.270 + }
124.271 +
124.272 + /// @}
124.273 +
124.274 + private:
124.275 +
124.276 + // Iterator class for the linked list storage of the tour
124.277 + class PathListIt {
124.278 + public:
124.279 + PathListIt(const std::vector<int> &pl, int i=0)
124.280 + : plist(&pl), act(i), last(pl[2*act]) {}
124.281 + PathListIt(const std::vector<int> &pl, int i, int l)
124.282 + : plist(&pl), act(i), last(l) {}
124.283 +
124.284 + int nextIndex() const {
124.285 + return (*plist)[2*act] == last ? 2*act+1 : 2*act;
124.286 + }
124.287 +
124.288 + int prevIndex() const {
124.289 + return (*plist)[2*act] == last ? 2*act : 2*act+1;
124.290 + }
124.291 +
124.292 + int next() const {
124.293 + int x = (*plist)[2*act];
124.294 + return x == last ? (*plist)[2*act+1] : x;
124.295 + }
124.296 +
124.297 + int prev() const {
124.298 + return last;
124.299 + }
124.300 +
124.301 + PathListIt& operator++() {
124.302 + int tmp = act;
124.303 + act = next();
124.304 + last = tmp;
124.305 + return *this;
124.306 + }
124.307 +
124.308 + operator int() const {
124.309 + return act;
124.310 + }
124.311 +
124.312 + private:
124.313 + const std::vector<int> *plist;
124.314 + int act;
124.315 + int last;
124.316 + };
124.317 +
124.318 + // Checks and applies 2-opt move (if it improves the tour)
124.319 + bool checkOpt2(const PathListIt& i, const PathListIt& j) {
124.320 + Node u = _gr.nodeFromId(i),
124.321 + un = _gr.nodeFromId(i.next()),
124.322 + v = _gr.nodeFromId(j),
124.323 + vn = _gr.nodeFromId(j.next());
124.324 +
124.325 + if (_cost[_gr.edge(u, un)] + _cost[_gr.edge(v, vn)] >
124.326 + _cost[_gr.edge(u, v)] + _cost[_gr.edge(un, vn)])
124.327 + {
124.328 + _plist[PathListIt(_plist, i.next(), i).prevIndex()] = j.next();
124.329 + _plist[PathListIt(_plist, j.next(), j).prevIndex()] = i.next();
124.330 +
124.331 + _plist[i.nextIndex()] = j;
124.332 + _plist[j.nextIndex()] = i;
124.333 +
124.334 + return true;
124.335 + }
124.336 +
124.337 + return false;
124.338 + }
124.339 +
124.340 + // Executes the algorithm from the initial tour
124.341 + Cost start() {
124.342 +
124.343 + restart_search:
124.344 + for (PathListIt i(_plist); true; ++i) {
124.345 + PathListIt j = i;
124.346 + if (++j == 0 || ++j == 0) break;
124.347 + for (; j != 0 && j != i.prev(); ++j) {
124.348 + if (checkOpt2(i, j))
124.349 + goto restart_search;
124.350 + }
124.351 + }
124.352 +
124.353 + PathListIt i(_plist);
124.354 + _path.push_back(_gr.nodeFromId(i));
124.355 + for (++i; i != 0; ++i)
124.356 + _path.push_back(_gr.nodeFromId(i));
124.357 +
124.358 + _sum = _cost[_gr.edge(_path.back(), _path.front())];
124.359 + for (int i = 0; i < int(_path.size())-1; ++i) {
124.360 + _sum += _cost[_gr.edge(_path[i], _path[i+1])];
124.361 + }
124.362 +
124.363 + return _sum;
124.364 + }
124.365 +
124.366 + };
124.367 +
124.368 +}; // namespace lemon
124.369 +
124.370 +#endif
125.1 --- a/lemon/path.h Mon Jul 16 16:21:40 2018 +0200
125.2 +++ b/lemon/path.h Wed Oct 17 19:14:07 2018 +0200
125.3 @@ -2,7 +2,7 @@
125.4 *
125.5 * This file is a part of LEMON, a generic C++ optimization library.
125.6 *
125.7 - * Copyright (C) 2003-2010
125.8 + * Copyright (C) 2003-2013
125.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
125.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
125.11 *
125.12 @@ -43,7 +43,7 @@
125.13 /// \tparam GR The digraph type in which the path is.
125.14 ///
125.15 /// In a sense, the path can be treated as a list of arcs. The
125.16 - /// lemon path type stores just this list. As a consequence, it
125.17 + /// LEMON path type stores just this list. As a consequence, it
125.18 /// cannot enumerate the nodes of the path and the source node of
125.19 /// a zero length path is undefined.
125.20 ///
125.21 @@ -148,7 +148,7 @@
125.22 /// \brief Reset the path to an empty one.
125.23 void clear() { head.clear(); tail.clear(); }
125.24
125.25 - /// \brief The nth arc.
125.26 + /// \brief The n-th arc.
125.27 ///
125.28 /// \pre \c n is in the <tt>[0..length() - 1]</tt> range.
125.29 const Arc& nth(int n) const {
125.30 @@ -156,7 +156,7 @@
125.31 *(tail.begin() + (n - head.size()));
125.32 }
125.33
125.34 - /// \brief Initialize arc iterator to point to the nth arc
125.35 + /// \brief Initialize arc iterator to point to the n-th arc
125.36 ///
125.37 /// \pre \c n is in the <tt>[0..length() - 1]</tt> range.
125.38 ArcIt nthIt(int n) const {
125.39 @@ -244,7 +244,7 @@
125.40 /// \tparam GR The digraph type in which the path is.
125.41 ///
125.42 /// In a sense, the path can be treated as a list of arcs. The
125.43 - /// lemon path type stores just this list. As a consequence it
125.44 + /// LEMON path type stores just this list. As a consequence it
125.45 /// cannot enumerate the nodes in the path and the zero length paths
125.46 /// cannot store the source.
125.47 ///
125.48 @@ -317,7 +317,7 @@
125.49
125.50 /// Constructor with starting point
125.51 ArcIt(const SimplePath &_path, int _idx)
125.52 - : idx(_idx), path(&_path) {}
125.53 + : path(&_path), idx(_idx) {}
125.54
125.55 public:
125.56
125.57 @@ -353,14 +353,14 @@
125.58 /// \brief Reset the path to an empty one.
125.59 void clear() { data.clear(); }
125.60
125.61 - /// \brief The nth arc.
125.62 + /// \brief The n-th arc.
125.63 ///
125.64 /// \pre \c n is in the <tt>[0..length() - 1]</tt> range.
125.65 const Arc& nth(int n) const {
125.66 return data[n];
125.67 }
125.68
125.69 - /// \brief Initializes arc iterator to point to the nth arc.
125.70 + /// \brief Initializes arc iterator to point to the n-th arc.
125.71 ArcIt nthIt(int n) const {
125.72 return ArcIt(*this, n);
125.73 }
125.74 @@ -421,7 +421,7 @@
125.75 /// \tparam GR The digraph type in which the path is.
125.76 ///
125.77 /// In a sense, the path can be treated as a list of arcs. The
125.78 - /// lemon path type stores just this list. As a consequence it
125.79 + /// LEMON path type stores just this list. As a consequence it
125.80 /// cannot enumerate the nodes in the path and the zero length paths
125.81 /// cannot store the source.
125.82 ///
125.83 @@ -543,9 +543,9 @@
125.84 Node *node;
125.85 };
125.86
125.87 - /// \brief The nth arc.
125.88 + /// \brief The n-th arc.
125.89 ///
125.90 - /// This function looks for the nth arc in O(n) time.
125.91 + /// This function looks for the n-th arc in O(n) time.
125.92 /// \pre \c n is in the <tt>[0..length() - 1]</tt> range.
125.93 const Arc& nth(int n) const {
125.94 Node *node = first;
125.95 @@ -555,7 +555,7 @@
125.96 return node->arc;
125.97 }
125.98
125.99 - /// \brief Initializes arc iterator to point to the nth arc.
125.100 + /// \brief Initializes arc iterator to point to the n-th arc.
125.101 ArcIt nthIt(int n) const {
125.102 Node *node = first;
125.103 for (int i = 0; i < n; ++i) {
125.104 @@ -774,7 +774,7 @@
125.105 /// \tparam GR The digraph type in which the path is.
125.106 ///
125.107 /// In a sense, the path can be treated as a list of arcs. The
125.108 - /// lemon path type stores just this list. As a consequence it
125.109 + /// LEMON path type stores just this list. As a consequence it
125.110 /// cannot enumerate the nodes in the path and the source node of
125.111 /// a zero length path is undefined.
125.112 ///
125.113 @@ -883,14 +883,14 @@
125.114 int idx;
125.115 };
125.116
125.117 - /// \brief The nth arc.
125.118 + /// \brief The n-th arc.
125.119 ///
125.120 /// \pre \c n is in the <tt>[0..length() - 1]</tt> range.
125.121 const Arc& nth(int n) const {
125.122 return arcs[n];
125.123 }
125.124
125.125 - /// \brief The arc iterator pointing to the nth arc.
125.126 + /// \brief The arc iterator pointing to the n-th arc.
125.127 ArcIt nthIt(int n) const {
125.128 return ArcIt(*this, n);
125.129 }
125.130 @@ -1094,7 +1094,7 @@
125.131 /// \brief Class which helps to iterate through the nodes of a path
125.132 ///
125.133 /// In a sense, the path can be treated as a list of arcs. The
125.134 - /// lemon path type stores only this list. As a consequence, it
125.135 + /// LEMON path type stores only this list. As a consequence, it
125.136 /// cannot enumerate the nodes in the path and the zero length paths
125.137 /// cannot have a source node.
125.138 ///
126.1 --- a/lemon/planarity.h Mon Jul 16 16:21:40 2018 +0200
126.2 +++ b/lemon/planarity.h Wed Oct 17 19:14:07 2018 +0200
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-2010
126.8 + * Copyright (C) 2003-2013
126.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
126.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
126.11 *
126.12 @@ -72,7 +72,6 @@
126.13 }
126.14
126.15 void discover(const Arc& arc) {
126.16 - Node source = _graph.source(arc);
126.17 Node target = _graph.target(arc);
126.18
126.19 _tree_map[arc] = true;
126.20 @@ -2384,7 +2383,7 @@
126.21 PlanarEmbedding<Graph> pe(_graph);
126.22 if (!pe.run()) return false;
126.23
126.24 - run(pe);
126.25 + run(pe.embeddingMap());
126.26 return true;
126.27 }
126.28
126.29 @@ -2399,6 +2398,15 @@
126.30 void run(const EmbeddingMap& embedding) {
126.31 typedef SmartEdgeSet<Graph> AuxGraph;
126.32
126.33 + if (countNodes(_graph) < 3) {
126.34 + int y = 0;
126.35 + for (typename Graph::NodeIt n(_graph); n != INVALID; ++n) {
126.36 + _point_map[n].x = 0;
126.37 + _point_map[n].y = y++;
126.38 + }
126.39 + return;
126.40 + }
126.41 +
126.42 if (3 * countNodes(_graph) - 6 == countEdges(_graph)) {
126.43 drawing(_graph, embedding, _point_map);
126.44 return;
127.1 --- a/lemon/preflow.h Mon Jul 16 16:21:40 2018 +0200
127.2 +++ b/lemon/preflow.h Wed Oct 17 19:14:07 2018 +0200
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-2010
127.8 + * Copyright (C) 2003-2013
127.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
127.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
127.11 *
127.12 @@ -102,12 +102,12 @@
127.13 ///
127.14 /// This class provides an implementation of Goldberg-Tarjan's \e preflow
127.15 /// \e push-relabel algorithm producing a \ref max_flow
127.16 - /// "flow of maximum value" in a digraph \ref clrs01algorithms,
127.17 - /// \ref amo93networkflows, \ref goldberg88newapproach.
127.18 + /// "flow of maximum value" in a digraph \cite clrs01algorithms,
127.19 + /// \cite amo93networkflows, \cite goldberg88newapproach.
127.20 /// The preflow algorithms are the fastest known maximum
127.21 /// flow algorithms. The current implementation uses a mixture of the
127.22 /// \e "highest label" and the \e "bound decrease" heuristics.
127.23 - /// The worst case time complexity of the algorithm is \f$O(n^2\sqrt{e})\f$.
127.24 + /// The worst case time complexity of the algorithm is \f$O(n^2\sqrt{m})\f$.
127.25 ///
127.26 /// The algorithm consists of two phases. After the first phase
127.27 /// the maximum flow value and the minimum cut is obtained. The
127.28 @@ -134,7 +134,7 @@
127.29 class Preflow {
127.30 public:
127.31
127.32 - ///The \ref PreflowDefaultTraits "traits class" of the algorithm.
127.33 + ///The \ref lemon::PreflowDefaultTraits "traits class" of the algorithm.
127.34 typedef TR Traits;
127.35 ///The type of the digraph the algorithm runs on.
127.36 typedef typename Traits::Digraph Digraph;
127.37 @@ -476,7 +476,7 @@
127.38 /// Initializes the internal data structures and sets the initial
127.39 /// flow to the given \c flowMap. The \c flowMap should contain a
127.40 /// flow or at least a preflow, i.e. at each node excluding the
127.41 - /// source node the incoming flow should greater or equal to the
127.42 + /// source node the incoming flow should be greater or equal to the
127.43 /// outgoing flow.
127.44 /// \return \c false if the given \c flowMap is not a preflow.
127.45 template <typename FlowMap>
127.46 @@ -495,7 +495,7 @@
127.47 for (OutArcIt e(_graph, n); e != INVALID; ++e) {
127.48 excess -= (*_flow)[e];
127.49 }
127.50 - if (excess < 0 && n != _source) return false;
127.51 + if (_tolerance.negative(excess) && n != _source) return false;
127.52 (*_excess)[n] = excess;
127.53 }
127.54
127.55 @@ -554,10 +554,10 @@
127.56 (*_excess)[v] += rem;
127.57 }
127.58 }
127.59 - for (NodeIt n(_graph); n != INVALID; ++n)
127.60 + for (NodeIt n(_graph); n != INVALID; ++n)
127.61 if(n!=_source && n!=_target && _tolerance.positive((*_excess)[n]))
127.62 _level->activate(n);
127.63 -
127.64 +
127.65 return true;
127.66 }
127.67
127.68 @@ -585,7 +585,7 @@
127.69 if (n == INVALID) goto first_phase_done;
127.70 level = _level->highestActiveLevel();
127.71 --num;
127.72 -
127.73 +
127.74 Value excess = (*_excess)[n];
127.75 int new_level = _level->maxLevel();
127.76
127.77 @@ -639,7 +639,7 @@
127.78
127.79 (*_excess)[n] = excess;
127.80
127.81 - if (excess != 0) {
127.82 + if (_tolerance.nonZero(excess)) {
127.83 if (new_level + 1 < _level->maxLevel()) {
127.84 _level->liftHighestActive(new_level + 1);
127.85 } else {
127.86 @@ -720,7 +720,7 @@
127.87
127.88 (*_excess)[n] = excess;
127.89
127.90 - if (excess != 0) {
127.91 + if (_tolerance.nonZero(excess)) {
127.92 if (new_level + 1 < _level->maxLevel()) {
127.93 _level->liftActiveOn(level, new_level + 1);
127.94 } else {
127.95 @@ -791,7 +791,7 @@
127.96 for (NodeIt n(_graph); n != INVALID; ++n) {
127.97 if (!reached[n]) {
127.98 _level->dirtyTopButOne(n);
127.99 - } else if ((*_excess)[n] > 0 && _target != n) {
127.100 + } else if (_tolerance.positive((*_excess)[n]) && _target != n) {
127.101 _level->activate(n);
127.102 }
127.103 }
127.104 @@ -852,7 +852,7 @@
127.105
127.106 (*_excess)[n] = excess;
127.107
127.108 - if (excess != 0) {
127.109 + if (_tolerance.nonZero(excess)) {
127.110 if (new_level + 1 < _level->maxLevel()) {
127.111 _level->liftHighestActive(new_level + 1);
127.112 } else {
128.1 --- a/lemon/radix_sort.h Mon Jul 16 16:21:40 2018 +0200
128.2 +++ b/lemon/radix_sort.h Wed Oct 17 19:14:07 2018 +0200
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-2013
128.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
128.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
128.11 *
128.12 @@ -34,6 +34,12 @@
128.13
128.14 namespace _radix_sort_bits {
128.15
128.16 + template <typename Iterator>
128.17 + bool unitRange(Iterator first, Iterator last) {
128.18 + ++first;
128.19 + return first == last;
128.20 + }
128.21 +
128.22 template <typename Value>
128.23 struct Identity {
128.24 const Value& operator()(const Value& val) {
128.25 @@ -60,9 +66,6 @@
128.26 }
128.27 std::iter_swap(first, last);
128.28 ++first;
128.29 - if (!(first < last)) {
128.30 - return first;
128.31 - }
128.32 while (true) {
128.33 while (!(functor(*first) & mask)) {
128.34 ++first;
128.35 @@ -71,7 +74,7 @@
128.36 while (functor(*last) & mask) {
128.37 --last;
128.38 }
128.39 - if (!(first < last)) {
128.40 + if (unitRange(last, first)) {
128.41 return first;
128.42 }
128.43 std::iter_swap(first, last);
128.44 @@ -97,9 +100,6 @@
128.45 }
128.46 std::iter_swap(first, last);
128.47 ++first;
128.48 - if (!(first < last)) {
128.49 - return first;
128.50 - }
128.51 while (true) {
128.52 while (functor(*first) < 0) {
128.53 ++first;
128.54 @@ -108,7 +108,7 @@
128.55 while (functor(*last) >= 0) {
128.56 --last;
128.57 }
128.58 - if (!(first < last)) {
128.59 + if (unitRange(last, first)) {
128.60 return first;
128.61 }
128.62 std::iter_swap(first, last);
128.63 @@ -119,7 +119,7 @@
128.64 template <typename Value, typename Iterator, typename Functor>
128.65 void radixIntroSort(Iterator first, Iterator last,
128.66 Functor functor, Value mask) {
128.67 - while (mask != 0 && last - first > 1) {
128.68 + while (mask != 0 && first != last && !unitRange(first, last)) {
128.69 Iterator cut = radixSortPartition(first, last, functor, mask);
128.70 mask >>= 1;
128.71 radixIntroSort(first, cut, functor, mask);
128.72 @@ -328,7 +328,7 @@
128.73 typedef std::allocator<Key> Allocator;
128.74 Allocator allocator;
128.75
128.76 - int length = std::distance(first, last);
128.77 + int length = static_cast<int>(std::distance(first, last));
128.78 Key* buffer = allocator.allocate(2 * length);
128.79 try {
128.80 bool dir = true;
129.1 --- a/lemon/random.h Mon Jul 16 16:21:40 2018 +0200
129.2 +++ b/lemon/random.h Wed Oct 17 19:14:07 2018 +0200
129.3 @@ -62,6 +62,8 @@
129.4 #ifndef LEMON_RANDOM_H
129.5 #define LEMON_RANDOM_H
129.6
129.7 +#include <lemon/config.h>
129.8 +
129.9 #include <algorithm>
129.10 #include <iterator>
129.11 #include <vector>
129.12 @@ -71,7 +73,7 @@
129.13 #include <lemon/math.h>
129.14 #include <lemon/dim2.h>
129.15
129.16 -#ifndef WIN32
129.17 +#ifndef LEMON_WIN32
129.18 #include <sys/time.h>
129.19 #include <ctime>
129.20 #include <sys/types.h>
129.21 @@ -199,7 +201,7 @@
129.22
129.23 initState(init);
129.24
129.25 - num = length > end - begin ? length : end - begin;
129.26 + num = static_cast<int>(length > end - begin ? length : end - begin);
129.27 while (num--) {
129.28 curr[0] = (curr[0] ^ ((curr[1] ^ (curr[1] >> (bits - 2))) * mul1))
129.29 + *it + cnt;
129.30 @@ -213,7 +215,7 @@
129.31 --curr;
129.32 }
129.33
129.34 - num = length - 1; cnt = length - (curr - state) - 1;
129.35 + num = length - 1; cnt = static_cast<int>(length - (curr - state) - 1);
129.36 while (num--) {
129.37 curr[0] = (curr[0] ^ ((curr[1] ^ (curr[1] >> (bits - 2))) * mul2))
129.38 - cnt;
129.39 @@ -340,7 +342,7 @@
129.40 do {
129.41 num = rnd() & mask;
129.42 } while (num > max);
129.43 - return num;
129.44 + return static_cast<Result>(num);
129.45 }
129.46 };
129.47
129.48 @@ -605,7 +607,7 @@
129.49 /// it uses the \c seedFromTime().
129.50 /// \return Currently always \c true.
129.51 bool seed() {
129.52 -#ifndef WIN32
129.53 +#ifndef LEMON_WIN32
129.54 if (seedFromFile("/dev/urandom", 0)) return true;
129.55 #endif
129.56 if (seedFromTime()) return true;
129.57 @@ -625,7 +627,7 @@
129.58 /// \param file The source file
129.59 /// \param offset The offset, from the file read.
129.60 /// \return \c true when the seeding successes.
129.61 -#ifndef WIN32
129.62 +#ifndef LEMON_WIN32
129.63 bool seedFromFile(const std::string& file = "/dev/urandom", int offset = 0)
129.64 #else
129.65 bool seedFromFile(const std::string& file = "", int offset = 0)
129.66 @@ -647,7 +649,7 @@
129.67 /// random sequence.
129.68 /// \return Currently always \c true.
129.69 bool seedFromTime() {
129.70 -#ifndef WIN32
129.71 +#ifndef LEMON_WIN32
129.72 timeval tv;
129.73 gettimeofday(&tv, 0);
129.74 seed(getpid() + tv.tv_sec + tv.tv_usec);
130.1 --- a/lemon/smart_graph.h Mon Jul 16 16:21:40 2018 +0200
130.2 +++ b/lemon/smart_graph.h Wed Oct 17 19:14:07 2018 +0200
130.3 @@ -2,7 +2,7 @@
130.4 *
130.5 * This file is a part of LEMON, a generic C++ optimization library.
130.6 *
130.7 - * Copyright (C) 2003-2010
130.8 + * Copyright (C) 2003-2013
130.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
130.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
130.11 *
130.12 @@ -405,8 +405,6 @@
130.13 std::vector<NodeT> nodes;
130.14 std::vector<ArcT> arcs;
130.15
130.16 - int first_free_arc;
130.17 -
130.18 public:
130.19
130.20 typedef SmartGraphBase Graph;
130.21 @@ -811,6 +809,535 @@
130.22 };
130.23 };
130.24
130.25 + class SmartBpGraphBase {
130.26 +
130.27 + protected:
130.28 +
130.29 + struct NodeT {
130.30 + int first_out;
130.31 + int partition_next;
130.32 + int partition_index;
130.33 + bool red;
130.34 + };
130.35 +
130.36 + struct ArcT {
130.37 + int target;
130.38 + int next_out;
130.39 + };
130.40 +
130.41 + std::vector<NodeT> nodes;
130.42 + std::vector<ArcT> arcs;
130.43 +
130.44 + int first_red, first_blue;
130.45 + int max_red, max_blue;
130.46 +
130.47 + public:
130.48 +
130.49 + typedef SmartBpGraphBase Graph;
130.50 +
130.51 + class Node;
130.52 + class Arc;
130.53 + class Edge;
130.54 +
130.55 + class Node {
130.56 + friend class SmartBpGraphBase;
130.57 + protected:
130.58 +
130.59 + int _id;
130.60 + explicit Node(int id) { _id = id;}
130.61 +
130.62 + public:
130.63 + Node() {}
130.64 + Node (Invalid) { _id = -1; }
130.65 + bool operator==(const Node& node) const {return _id == node._id;}
130.66 + bool operator!=(const Node& node) const {return _id != node._id;}
130.67 + bool operator<(const Node& node) const {return _id < node._id;}
130.68 + };
130.69 +
130.70 + class RedNode : public Node {
130.71 + friend class SmartBpGraphBase;
130.72 + protected:
130.73 +
130.74 + explicit RedNode(int pid) : Node(pid) {}
130.75 +
130.76 + public:
130.77 + RedNode() {}
130.78 + RedNode(const RedNode& node) : Node(node) {}
130.79 + RedNode(Invalid) : Node(INVALID){}
130.80 + };
130.81 +
130.82 + class BlueNode : public Node {
130.83 + friend class SmartBpGraphBase;
130.84 + protected:
130.85 +
130.86 + explicit BlueNode(int pid) : Node(pid) {}
130.87 +
130.88 + public:
130.89 + BlueNode() {}
130.90 + BlueNode(const BlueNode& node) : Node(node) {}
130.91 + BlueNode(Invalid) : Node(INVALID){}
130.92 + };
130.93 +
130.94 + class Edge {
130.95 + friend class SmartBpGraphBase;
130.96 + protected:
130.97 +
130.98 + int _id;
130.99 + explicit Edge(int id) { _id = id;}
130.100 +
130.101 + public:
130.102 + Edge() {}
130.103 + Edge (Invalid) { _id = -1; }
130.104 + bool operator==(const Edge& arc) const {return _id == arc._id;}
130.105 + bool operator!=(const Edge& arc) const {return _id != arc._id;}
130.106 + bool operator<(const Edge& arc) const {return _id < arc._id;}
130.107 + };
130.108 +
130.109 + class Arc {
130.110 + friend class SmartBpGraphBase;
130.111 + protected:
130.112 +
130.113 + int _id;
130.114 + explicit Arc(int id) { _id = id;}
130.115 +
130.116 + public:
130.117 + operator Edge() const {
130.118 + return _id != -1 ? edgeFromId(_id / 2) : INVALID;
130.119 + }
130.120 +
130.121 + Arc() {}
130.122 + Arc (Invalid) { _id = -1; }
130.123 + bool operator==(const Arc& arc) const {return _id == arc._id;}
130.124 + bool operator!=(const Arc& arc) const {return _id != arc._id;}
130.125 + bool operator<(const Arc& arc) const {return _id < arc._id;}
130.126 + };
130.127 +
130.128 +
130.129 +
130.130 + SmartBpGraphBase()
130.131 + : nodes(), arcs(), first_red(-1), first_blue(-1),
130.132 + max_red(-1), max_blue(-1) {}
130.133 +
130.134 + typedef True NodeNumTag;
130.135 + typedef True EdgeNumTag;
130.136 + typedef True ArcNumTag;
130.137 +
130.138 + int nodeNum() const { return nodes.size(); }
130.139 + int redNum() const { return max_red + 1; }
130.140 + int blueNum() const { return max_blue + 1; }
130.141 + int edgeNum() const { return arcs.size() / 2; }
130.142 + int arcNum() const { return arcs.size(); }
130.143 +
130.144 + int maxNodeId() const { return nodes.size()-1; }
130.145 + int maxRedId() const { return max_red; }
130.146 + int maxBlueId() const { return max_blue; }
130.147 + int maxEdgeId() const { return arcs.size() / 2 - 1; }
130.148 + int maxArcId() const { return arcs.size()-1; }
130.149 +
130.150 + bool red(Node n) const { return nodes[n._id].red; }
130.151 + bool blue(Node n) const { return !nodes[n._id].red; }
130.152 +
130.153 + static RedNode asRedNodeUnsafe(Node n) { return RedNode(n._id); }
130.154 + static BlueNode asBlueNodeUnsafe(Node n) { return BlueNode(n._id); }
130.155 +
130.156 + Node source(Arc a) const { return Node(arcs[a._id ^ 1].target); }
130.157 + Node target(Arc a) const { return Node(arcs[a._id].target); }
130.158 +
130.159 + RedNode redNode(Edge e) const {
130.160 + return RedNode(arcs[2 * e._id].target);
130.161 + }
130.162 + BlueNode blueNode(Edge e) const {
130.163 + return BlueNode(arcs[2 * e._id + 1].target);
130.164 + }
130.165 +
130.166 + static bool direction(Arc a) {
130.167 + return (a._id & 1) == 1;
130.168 + }
130.169 +
130.170 + static Arc direct(Edge e, bool d) {
130.171 + return Arc(e._id * 2 + (d ? 1 : 0));
130.172 + }
130.173 +
130.174 + void first(Node& node) const {
130.175 + node._id = nodes.size() - 1;
130.176 + }
130.177 +
130.178 + static void next(Node& node) {
130.179 + --node._id;
130.180 + }
130.181 +
130.182 + void first(RedNode& node) const {
130.183 + node._id = first_red;
130.184 + }
130.185 +
130.186 + void next(RedNode& node) const {
130.187 + node._id = nodes[node._id].partition_next;
130.188 + }
130.189 +
130.190 + void first(BlueNode& node) const {
130.191 + node._id = first_blue;
130.192 + }
130.193 +
130.194 + void next(BlueNode& node) const {
130.195 + node._id = nodes[node._id].partition_next;
130.196 + }
130.197 +
130.198 + void first(Arc& arc) const {
130.199 + arc._id = arcs.size() - 1;
130.200 + }
130.201 +
130.202 + static void next(Arc& arc) {
130.203 + --arc._id;
130.204 + }
130.205 +
130.206 + void first(Edge& arc) const {
130.207 + arc._id = arcs.size() / 2 - 1;
130.208 + }
130.209 +
130.210 + static void next(Edge& arc) {
130.211 + --arc._id;
130.212 + }
130.213 +
130.214 + void firstOut(Arc &arc, const Node& v) const {
130.215 + arc._id = nodes[v._id].first_out;
130.216 + }
130.217 + void nextOut(Arc &arc) const {
130.218 + arc._id = arcs[arc._id].next_out;
130.219 + }
130.220 +
130.221 + void firstIn(Arc &arc, const Node& v) const {
130.222 + arc._id = ((nodes[v._id].first_out) ^ 1);
130.223 + if (arc._id == -2) arc._id = -1;
130.224 + }
130.225 + void nextIn(Arc &arc) const {
130.226 + arc._id = ((arcs[arc._id ^ 1].next_out) ^ 1);
130.227 + if (arc._id == -2) arc._id = -1;
130.228 + }
130.229 +
130.230 + void firstInc(Edge &arc, bool& d, const Node& v) const {
130.231 + int de = nodes[v._id].first_out;
130.232 + if (de != -1) {
130.233 + arc._id = de / 2;
130.234 + d = ((de & 1) == 1);
130.235 + } else {
130.236 + arc._id = -1;
130.237 + d = true;
130.238 + }
130.239 + }
130.240 + void nextInc(Edge &arc, bool& d) const {
130.241 + int de = (arcs[(arc._id * 2) | (d ? 1 : 0)].next_out);
130.242 + if (de != -1) {
130.243 + arc._id = de / 2;
130.244 + d = ((de & 1) == 1);
130.245 + } else {
130.246 + arc._id = -1;
130.247 + d = true;
130.248 + }
130.249 + }
130.250 +
130.251 + static int id(Node v) { return v._id; }
130.252 + int id(RedNode v) const { return nodes[v._id].partition_index; }
130.253 + int id(BlueNode v) const { return nodes[v._id].partition_index; }
130.254 + static int id(Arc e) { return e._id; }
130.255 + static int id(Edge e) { return e._id; }
130.256 +
130.257 + static Node nodeFromId(int id) { return Node(id);}
130.258 + static Arc arcFromId(int id) { return Arc(id);}
130.259 + static Edge edgeFromId(int id) { return Edge(id);}
130.260 +
130.261 + bool valid(Node n) const {
130.262 + return n._id >= 0 && n._id < static_cast<int>(nodes.size());
130.263 + }
130.264 + bool valid(Arc a) const {
130.265 + return a._id >= 0 && a._id < static_cast<int>(arcs.size());
130.266 + }
130.267 + bool valid(Edge e) const {
130.268 + return e._id >= 0 && 2 * e._id < static_cast<int>(arcs.size());
130.269 + }
130.270 +
130.271 + RedNode addRedNode() {
130.272 + int n = nodes.size();
130.273 + nodes.push_back(NodeT());
130.274 + nodes[n].first_out = -1;
130.275 + nodes[n].red = true;
130.276 + nodes[n].partition_index = ++max_red;
130.277 + nodes[n].partition_next = first_red;
130.278 + first_red = n;
130.279 +
130.280 + return RedNode(n);
130.281 + }
130.282 +
130.283 + BlueNode addBlueNode() {
130.284 + int n = nodes.size();
130.285 + nodes.push_back(NodeT());
130.286 + nodes[n].first_out = -1;
130.287 + nodes[n].red = false;
130.288 + nodes[n].partition_index = ++max_blue;
130.289 + nodes[n].partition_next = first_blue;
130.290 + first_blue = n;
130.291 +
130.292 + return BlueNode(n);
130.293 + }
130.294 +
130.295 + Edge addEdge(RedNode u, BlueNode v) {
130.296 + int n = arcs.size();
130.297 + arcs.push_back(ArcT());
130.298 + arcs.push_back(ArcT());
130.299 +
130.300 + arcs[n].target = u._id;
130.301 + arcs[n | 1].target = v._id;
130.302 +
130.303 + arcs[n].next_out = nodes[v._id].first_out;
130.304 + nodes[v._id].first_out = n;
130.305 +
130.306 + arcs[n | 1].next_out = nodes[u._id].first_out;
130.307 + nodes[u._id].first_out = (n | 1);
130.308 +
130.309 + return Edge(n / 2);
130.310 + }
130.311 +
130.312 + void clear() {
130.313 + arcs.clear();
130.314 + nodes.clear();
130.315 + first_red = -1;
130.316 + first_blue = -1;
130.317 + max_blue = -1;
130.318 + max_red = -1;
130.319 + }
130.320 +
130.321 + };
130.322 +
130.323 + typedef BpGraphExtender<SmartBpGraphBase> ExtendedSmartBpGraphBase;
130.324 +
130.325 + /// \ingroup graphs
130.326 + ///
130.327 + /// \brief A smart undirected bipartite graph class.
130.328 + ///
130.329 + /// \ref SmartBpGraph is a simple and fast bipartite graph implementation.
130.330 + /// It is also quite memory efficient but at the price
130.331 + /// that it does not support node and edge deletion
130.332 + /// (except for the Snapshot feature).
130.333 + ///
130.334 + /// This type fully conforms to the \ref concepts::BpGraph "BpGraph concept"
130.335 + /// and it also provides some additional functionalities.
130.336 + /// Most of its member functions and nested classes are documented
130.337 + /// only in the concept class.
130.338 + ///
130.339 + /// This class provides constant time counting for nodes, edges and arcs.
130.340 + ///
130.341 + /// \sa concepts::BpGraph
130.342 + /// \sa SmartGraph
130.343 + class SmartBpGraph : public ExtendedSmartBpGraphBase {
130.344 + typedef ExtendedSmartBpGraphBase Parent;
130.345 +
130.346 + private:
130.347 + /// Graphs are \e not copy constructible. Use GraphCopy instead.
130.348 + SmartBpGraph(const SmartBpGraph &) : ExtendedSmartBpGraphBase() {};
130.349 + /// \brief Assignment of a graph to another one is \e not allowed.
130.350 + /// Use GraphCopy instead.
130.351 + void operator=(const SmartBpGraph &) {}
130.352 +
130.353 + public:
130.354 +
130.355 + /// Constructor
130.356 +
130.357 + /// Constructor.
130.358 + ///
130.359 + SmartBpGraph() {}
130.360 +
130.361 + /// \brief Add a new red node to the graph.
130.362 + ///
130.363 + /// This function adds a red new node to the graph.
130.364 + /// \return The new node.
130.365 + RedNode addRedNode() { return Parent::addRedNode(); }
130.366 +
130.367 + /// \brief Add a new blue node to the graph.
130.368 + ///
130.369 + /// This function adds a blue new node to the graph.
130.370 + /// \return The new node.
130.371 + BlueNode addBlueNode() { return Parent::addBlueNode(); }
130.372 +
130.373 + /// \brief Add a new edge to the graph.
130.374 + ///
130.375 + /// This function adds a new edge to the graph between nodes
130.376 + /// \c u and \c v with inherent orientation from node \c u to
130.377 + /// node \c v.
130.378 + /// \return The new edge.
130.379 + Edge addEdge(RedNode u, BlueNode v) {
130.380 + return Parent::addEdge(u, v);
130.381 + }
130.382 + Edge addEdge(BlueNode v, RedNode u) {
130.383 + return Parent::addEdge(u, v);
130.384 + }
130.385 +
130.386 + /// \brief Node validity check
130.387 + ///
130.388 + /// This function gives back \c true if the given node is valid,
130.389 + /// i.e. it is a real node of the graph.
130.390 + ///
130.391 + /// \warning A removed node (using Snapshot) could become valid again
130.392 + /// if new nodes are added to the graph.
130.393 + bool valid(Node n) const { return Parent::valid(n); }
130.394 +
130.395 + /// \brief Edge validity check
130.396 + ///
130.397 + /// This function gives back \c true if the given edge is valid,
130.398 + /// i.e. it is a real edge of the graph.
130.399 + ///
130.400 + /// \warning A removed edge (using Snapshot) could become valid again
130.401 + /// if new edges are added to the graph.
130.402 + bool valid(Edge e) const { return Parent::valid(e); }
130.403 +
130.404 + /// \brief Arc validity check
130.405 + ///
130.406 + /// This function gives back \c true if the given arc is valid,
130.407 + /// i.e. it is a real arc of the graph.
130.408 + ///
130.409 + /// \warning A removed arc (using Snapshot) could become valid again
130.410 + /// if new edges are added to the graph.
130.411 + bool valid(Arc a) const { return Parent::valid(a); }
130.412 +
130.413 + ///Clear the graph.
130.414 +
130.415 + ///This function erases all nodes and arcs from the graph.
130.416 + ///
130.417 + void clear() {
130.418 + Parent::clear();
130.419 + }
130.420 +
130.421 + /// Reserve memory for nodes.
130.422 +
130.423 + /// Using this function, it is possible to avoid superfluous memory
130.424 + /// allocation: if you know that the graph you want to build will
130.425 + /// be large (e.g. it will contain millions of nodes and/or edges),
130.426 + /// then it is worth reserving space for this amount before starting
130.427 + /// to build the graph.
130.428 + /// \sa reserveEdge()
130.429 + void reserveNode(int n) { nodes.reserve(n); };
130.430 +
130.431 + /// Reserve memory for edges.
130.432 +
130.433 + /// Using this function, it is possible to avoid superfluous memory
130.434 + /// allocation: if you know that the graph you want to build will
130.435 + /// be large (e.g. it will contain millions of nodes and/or edges),
130.436 + /// then it is worth reserving space for this amount before starting
130.437 + /// to build the graph.
130.438 + /// \sa reserveNode()
130.439 + void reserveEdge(int m) { arcs.reserve(2 * m); };
130.440 +
130.441 + public:
130.442 +
130.443 + class Snapshot;
130.444 +
130.445 + protected:
130.446 +
130.447 + void saveSnapshot(Snapshot &s)
130.448 + {
130.449 + s._graph = this;
130.450 + s.node_num = nodes.size();
130.451 + s.arc_num = arcs.size();
130.452 + }
130.453 +
130.454 + void restoreSnapshot(const Snapshot &s)
130.455 + {
130.456 + while(s.arc_num<arcs.size()) {
130.457 + int n=arcs.size()-1;
130.458 + Edge arc=edgeFromId(n/2);
130.459 + Parent::notifier(Edge()).erase(arc);
130.460 + std::vector<Arc> dir;
130.461 + dir.push_back(arcFromId(n));
130.462 + dir.push_back(arcFromId(n-1));
130.463 + Parent::notifier(Arc()).erase(dir);
130.464 + nodes[arcs[n-1].target].first_out=arcs[n].next_out;
130.465 + nodes[arcs[n].target].first_out=arcs[n-1].next_out;
130.466 + arcs.pop_back();
130.467 + arcs.pop_back();
130.468 + }
130.469 + while(s.node_num<nodes.size()) {
130.470 + int n=nodes.size()-1;
130.471 + Node node = nodeFromId(n);
130.472 + if (Parent::red(node)) {
130.473 + first_red = nodes[n].partition_next;
130.474 + if (first_red != -1) {
130.475 + max_red = nodes[first_red].partition_index;
130.476 + } else {
130.477 + max_red = -1;
130.478 + }
130.479 + Parent::notifier(RedNode()).erase(asRedNodeUnsafe(node));
130.480 + } else {
130.481 + first_blue = nodes[n].partition_next;
130.482 + if (first_blue != -1) {
130.483 + max_blue = nodes[first_blue].partition_index;
130.484 + } else {
130.485 + max_blue = -1;
130.486 + }
130.487 + Parent::notifier(BlueNode()).erase(asBlueNodeUnsafe(node));
130.488 + }
130.489 + Parent::notifier(Node()).erase(node);
130.490 + nodes.pop_back();
130.491 + }
130.492 + }
130.493 +
130.494 + public:
130.495 +
130.496 + ///Class to make a snapshot of the graph and to restore it later.
130.497 +
130.498 + ///Class to make a snapshot of the graph and to restore it later.
130.499 + ///
130.500 + ///The newly added nodes and edges can be removed using the
130.501 + ///restore() function. This is the only way for deleting nodes and/or
130.502 + ///edges from a SmartBpGraph structure.
130.503 + ///
130.504 + ///\note After a state is restored, you cannot restore a later state,
130.505 + ///i.e. you cannot add the removed nodes and edges again using
130.506 + ///another Snapshot instance.
130.507 + ///
130.508 + ///\warning The validity of the snapshot is not stored due to
130.509 + ///performance reasons. If you do not use the snapshot correctly,
130.510 + ///it can cause broken program, invalid or not restored state of
130.511 + ///the graph or no change.
130.512 + class Snapshot
130.513 + {
130.514 + SmartBpGraph *_graph;
130.515 + protected:
130.516 + friend class SmartBpGraph;
130.517 + unsigned int node_num;
130.518 + unsigned int arc_num;
130.519 + public:
130.520 + ///Default constructor.
130.521 +
130.522 + ///Default constructor.
130.523 + ///You have to call save() to actually make a snapshot.
130.524 + Snapshot() : _graph(0) {}
130.525 + ///Constructor that immediately makes a snapshot
130.526 +
130.527 + /// This constructor immediately makes a snapshot of the given graph.
130.528 + ///
130.529 + Snapshot(SmartBpGraph &gr) {
130.530 + gr.saveSnapshot(*this);
130.531 + }
130.532 +
130.533 + ///Make a snapshot.
130.534 +
130.535 + ///This function makes a snapshot of the given graph.
130.536 + ///It can be called more than once. In case of a repeated
130.537 + ///call, the previous snapshot gets lost.
130.538 + void save(SmartBpGraph &gr)
130.539 + {
130.540 + gr.saveSnapshot(*this);
130.541 + }
130.542 +
130.543 + ///Undo the changes until the last snapshot.
130.544 +
130.545 + ///This function undos the changes until the last snapshot
130.546 + ///created by save() or Snapshot(SmartBpGraph&).
130.547 + void restore()
130.548 + {
130.549 + _graph->restoreSnapshot(*this);
130.550 + }
130.551 + };
130.552 + };
130.553 +
130.554 } //namespace lemon
130.555
130.556
131.1 --- a/lemon/soplex.cc Mon Jul 16 16:21:40 2018 +0200
131.2 +++ b/lemon/soplex.cc Wed Oct 17 19:14:07 2018 +0200
131.3 @@ -2,7 +2,7 @@
131.4 *
131.5 * This file is a part of LEMON, a generic C++ optimization library.
131.6 *
131.7 - * Copyright (C) 2003-2010
131.8 + * Copyright (C) 2003-2013
131.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
131.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
131.11 *
132.1 --- a/lemon/soplex.h Mon Jul 16 16:21:40 2018 +0200
132.2 +++ b/lemon/soplex.h Wed Oct 17 19:14:07 2018 +0200
132.3 @@ -2,7 +2,7 @@
132.4 *
132.5 * This file is a part of LEMON, a generic C++ optimization library.
132.6 *
132.7 - * Copyright (C) 2003-2010
132.8 + * Copyright (C) 2003-2013
132.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
132.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
132.11 *
133.1 --- a/lemon/static_graph.h Mon Jul 16 16:21:40 2018 +0200
133.2 +++ b/lemon/static_graph.h Wed Oct 17 19:14:07 2018 +0200
133.3 @@ -203,7 +203,7 @@
133.4 built = true;
133.5
133.6 node_num = n;
133.7 - arc_num = std::distance(first, last);
133.8 + arc_num = static_cast<int>(std::distance(first, last));
133.9
133.10 node_first_out = new int[node_num + 1];
133.11 node_first_in = new int[node_num];
134.1 --- a/lemon/suurballe.h Mon Jul 16 16:21:40 2018 +0200
134.2 +++ b/lemon/suurballe.h Wed Oct 17 19:14:07 2018 +0200
134.3 @@ -2,7 +2,7 @@
134.4 *
134.5 * This file is a part of LEMON, a generic C++ optimization library.
134.6 *
134.7 - * Copyright (C) 2003-2010
134.8 + * Copyright (C) 2003-2013
134.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
134.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
134.11 *
134.12 @@ -137,7 +137,7 @@
134.13 /// The heap type used for internal Dijkstra computations.
134.14 typedef typename TR::Heap Heap;
134.15
134.16 - /// The \ref SuurballeDefaultTraits "traits class" of the algorithm.
134.17 + /// The \ref lemon::SuurballeDefaultTraits "traits class" of the algorithm.
134.18 typedef TR Traits;
134.19
134.20 private:
134.21 @@ -682,7 +682,7 @@
134.22 ///
134.23 /// This function returns the total length of the found paths, i.e.
134.24 /// the total cost of the found flow.
134.25 - /// The complexity of the function is O(e).
134.26 + /// The complexity of the function is O(m).
134.27 ///
134.28 /// \pre \ref run() or \ref findFlow() must be called before using
134.29 /// this function.
135.1 --- a/lemon/time_measure.h Mon Jul 16 16:21:40 2018 +0200
135.2 +++ b/lemon/time_measure.h Wed Oct 17 19:14:07 2018 +0200
135.3 @@ -2,7 +2,7 @@
135.4 *
135.5 * This file is a part of LEMON, a generic C++ optimization library.
135.6 *
135.7 - * Copyright (C) 2003-2009
135.8 + * Copyright (C) 2003-2013
135.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
135.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
135.11 *
135.12 @@ -23,7 +23,9 @@
135.13 ///\file
135.14 ///\brief Tools for measuring cpu usage
135.15
135.16 -#ifdef WIN32
135.17 +#include <lemon/config.h>
135.18 +
135.19 +#ifdef LEMON_WIN32
135.20 #include <lemon/bits/windows.h>
135.21 #else
135.22 #include <unistd.h>
135.23 @@ -34,6 +36,7 @@
135.24 #include <string>
135.25 #include <fstream>
135.26 #include <iostream>
135.27 +#include <lemon/math.h>
135.28
135.29 namespace lemon {
135.30
135.31 @@ -63,16 +66,45 @@
135.32 double cstime;
135.33 double rtime;
135.34
135.35 + public:
135.36 + ///Display format specifier
135.37 +
135.38 + ///\e
135.39 + ///
135.40 + enum Format {
135.41 + /// Reports all measured values
135.42 + NORMAL = 0,
135.43 + /// Only real time and an error indicator is displayed
135.44 + SHORT = 1
135.45 + };
135.46 +
135.47 + private:
135.48 + static Format _format;
135.49 +
135.50 void _reset() {
135.51 utime = stime = cutime = cstime = rtime = 0;
135.52 }
135.53
135.54 public:
135.55
135.56 + ///Set output format
135.57 +
135.58 + ///Set output format.
135.59 + ///
135.60 + ///The output format is global for all timestamp instances.
135.61 + static void format(Format f) { _format = f; }
135.62 + ///Retrieve the current output format
135.63 +
135.64 + ///Retrieve the current output format
135.65 + ///
135.66 + ///The output format is global for all timestamp instances.
135.67 + static Format format() { return _format; }
135.68 +
135.69 +
135.70 ///Read the current time values of the process
135.71 void stamp()
135.72 {
135.73 -#ifndef WIN32
135.74 +#ifndef LEMON_WIN32
135.75 timeval tv;
135.76 gettimeofday(&tv, 0);
135.77 rtime=tv.tv_sec+double(tv.tv_usec)/1e6;
135.78 @@ -224,11 +256,24 @@
135.79 /// calculated.
135.80 inline std::ostream& operator<<(std::ostream& os,const TimeStamp &t)
135.81 {
135.82 - os << "u: " << t.userTime() <<
135.83 - "s, s: " << t.systemTime() <<
135.84 - "s, cu: " << t.cUserTime() <<
135.85 - "s, cs: " << t.cSystemTime() <<
135.86 - "s, real: " << t.realTime() << "s";
135.87 + switch(t._format)
135.88 + {
135.89 + case TimeStamp::NORMAL:
135.90 + os << "u: " << t.userTime() <<
135.91 + "s, s: " << t.systemTime() <<
135.92 + "s, cu: " << t.cUserTime() <<
135.93 + "s, cs: " << t.cSystemTime() <<
135.94 + "s, real: " << t.realTime() << "s";
135.95 + break;
135.96 + case TimeStamp::SHORT:
135.97 + double total = t.userTime()+t.systemTime()+
135.98 + t.cUserTime()+t.cSystemTime();
135.99 + os << t.realTime()
135.100 + << "s (err: " << round((t.realTime()-total)/
135.101 + t.realTime()*10000)/100
135.102 + << "%)";
135.103 + break;
135.104 + }
135.105 return os;
135.106 }
135.107
135.108 @@ -468,6 +513,7 @@
135.109 {
135.110 std::string _title;
135.111 std::ostream &_os;
135.112 + bool _active;
135.113 public:
135.114 ///Constructor
135.115
135.116 @@ -475,13 +521,27 @@
135.117 ///\param title This text will be printed before the ellapsed time.
135.118 ///\param os The stream to print the report to.
135.119 ///\param run Sets whether the timer should start immediately.
135.120 - TimeReport(std::string title,std::ostream &os=std::cerr,bool run=true)
135.121 - : Timer(run), _title(title), _os(os){}
135.122 + ///\param active Sets whether the report should actually be printed
135.123 + /// on destruction.
135.124 + TimeReport(std::string title,std::ostream &os=std::cerr,bool run=true,
135.125 + bool active=true)
135.126 + : Timer(run), _title(title), _os(os), _active(active) {}
135.127 ///Destructor that prints the ellapsed time
135.128 ~TimeReport()
135.129 {
135.130 - _os << _title << *this << std::endl;
135.131 + if(_active) _os << _title << *this << std::endl;
135.132 }
135.133 +
135.134 + ///Retrieve the activity status
135.135 +
135.136 + ///\e
135.137 + ///
135.138 + bool active() const { return _active; }
135.139 + ///Set the activity status
135.140 +
135.141 + /// This function set whether the time report should actually be printed
135.142 + /// on destruction.
135.143 + void active(bool a) { _active=a; }
135.144 };
135.145
135.146 ///'Do nothing' version of TimeReport
136.1 --- a/lemon/unionfind.h Mon Jul 16 16:21:40 2018 +0200
136.2 +++ b/lemon/unionfind.h Wed Oct 17 19:14:07 2018 +0200
136.3 @@ -2,7 +2,7 @@
136.4 *
136.5 * This file is a part of LEMON, a generic C++ optimization library.
136.6 *
136.7 - * Copyright (C) 2003-2010
136.8 + * Copyright (C) 2003-2013
136.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
136.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
136.11 *
137.1 --- a/m4/lx_check_coin.m4 Mon Jul 16 16:21:40 2018 +0200
137.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
137.3 @@ -1,136 +0,0 @@
137.4 -AC_DEFUN([LX_CHECK_COIN],
137.5 -[
137.6 - AC_ARG_WITH([coin],
137.7 -AS_HELP_STRING([--with-coin@<:@=PREFIX@:>@], [search for CLP under PREFIX or under the default search paths if PREFIX is not given @<:@default@:>@])
137.8 -AS_HELP_STRING([--without-coin], [disable checking for CLP]),
137.9 - [], [with_coin=yes])
137.10 -
137.11 - AC_ARG_WITH([coin-includedir],
137.12 -AS_HELP_STRING([--with-coin-includedir=DIR], [search for CLP headers in DIR]),
137.13 - [], [with_coin_includedir=no])
137.14 -
137.15 - AC_ARG_WITH([coin-libdir],
137.16 -AS_HELP_STRING([--with-coin-libdir=DIR], [search for CLP libraries in DIR]),
137.17 - [], [with_coin_libdir=no])
137.18 -
137.19 - lx_clp_found=no
137.20 - if test x"$with_coin" != x"no"; then
137.21 - AC_MSG_CHECKING([for CLP])
137.22 -
137.23 - if test x"$with_coin_includedir" != x"no"; then
137.24 - CLP_CXXFLAGS="-I$with_coin_includedir"
137.25 - elif test x"$with_coin" != x"yes"; then
137.26 - CLP_CXXFLAGS="-I$with_coin/include"
137.27 - fi
137.28 -
137.29 - if test x"$with_coin_libdir" != x"no"; then
137.30 - CLP_LDFLAGS="-L$with_coin_libdir"
137.31 - elif test x"$with_coin" != x"yes"; then
137.32 - CLP_LDFLAGS="-L$with_coin/lib"
137.33 - fi
137.34 - CLP_LIBS="-lClp -lCoinUtils -lm"
137.35 -
137.36 - lx_save_cxxflags="$CXXFLAGS"
137.37 - lx_save_ldflags="$LDFLAGS"
137.38 - lx_save_libs="$LIBS"
137.39 - CXXFLAGS="$CLP_CXXFLAGS"
137.40 - LDFLAGS="$CLP_LDFLAGS"
137.41 - LIBS="$CLP_LIBS"
137.42 -
137.43 - lx_clp_test_prog='
137.44 - #include <coin/ClpModel.hpp>
137.45 -
137.46 - int main(int argc, char** argv)
137.47 - {
137.48 - ClpModel clp;
137.49 - return 0;
137.50 - }'
137.51 -
137.52 - AC_LANG_PUSH(C++)
137.53 - AC_LINK_IFELSE([$lx_clp_test_prog], [lx_clp_found=yes], [lx_clp_found=no])
137.54 - AC_LANG_POP(C++)
137.55 -
137.56 - CXXFLAGS="$lx_save_cxxflags"
137.57 - LDFLAGS="$lx_save_ldflags"
137.58 - LIBS="$lx_save_libs"
137.59 -
137.60 - if test x"$lx_clp_found" = x"yes"; then
137.61 - AC_DEFINE([LEMON_HAVE_CLP], [1], [Define to 1 if you have CLP.])
137.62 - lx_lp_found=yes
137.63 - AC_DEFINE([LEMON_HAVE_LP], [1], [Define to 1 if you have any LP solver.])
137.64 - AC_MSG_RESULT([yes])
137.65 - else
137.66 - CLP_CXXFLAGS=""
137.67 - CLP_LDFLAGS=""
137.68 - CLP_LIBS=""
137.69 - AC_MSG_RESULT([no])
137.70 - fi
137.71 - fi
137.72 - CLP_LIBS="$CLP_LDFLAGS $CLP_LIBS"
137.73 - AC_SUBST(CLP_CXXFLAGS)
137.74 - AC_SUBST(CLP_LIBS)
137.75 - AM_CONDITIONAL([HAVE_CLP], [test x"$lx_clp_found" = x"yes"])
137.76 -
137.77 -
137.78 - lx_cbc_found=no
137.79 - if test x"$lx_clp_found" = x"yes"; then
137.80 - if test x"$with_coin" != x"no"; then
137.81 - AC_MSG_CHECKING([for CBC])
137.82 -
137.83 - if test x"$with_coin_includedir" != x"no"; then
137.84 - CBC_CXXFLAGS="-I$with_coin_includedir"
137.85 - elif test x"$with_coin" != x"yes"; then
137.86 - CBC_CXXFLAGS="-I$with_coin/include"
137.87 - fi
137.88 -
137.89 - if test x"$with_coin_libdir" != x"no"; then
137.90 - CBC_LDFLAGS="-L$with_coin_libdir"
137.91 - elif test x"$with_coin" != x"yes"; then
137.92 - CBC_LDFLAGS="-L$with_coin/lib"
137.93 - fi
137.94 - CBC_LIBS="-lOsi -lCbc -lCbcSolver -lClp -lOsiClp -lCoinUtils -lVol -lOsiVol -lCgl -lm -llapack -lblas"
137.95 -
137.96 - lx_save_cxxflags="$CXXFLAGS"
137.97 - lx_save_ldflags="$LDFLAGS"
137.98 - lx_save_libs="$LIBS"
137.99 - CXXFLAGS="$CBC_CXXFLAGS"
137.100 - LDFLAGS="$CBC_LDFLAGS"
137.101 - LIBS="$CBC_LIBS"
137.102 -
137.103 - lx_cbc_test_prog='
137.104 - #include <coin/CbcModel.hpp>
137.105 -
137.106 - int main(int argc, char** argv)
137.107 - {
137.108 - CbcModel cbc;
137.109 - return 0;
137.110 - }'
137.111 -
137.112 - AC_LANG_PUSH(C++)
137.113 - AC_LINK_IFELSE([$lx_cbc_test_prog], [lx_cbc_found=yes], [lx_cbc_found=no])
137.114 - AC_LANG_POP(C++)
137.115 -
137.116 - CXXFLAGS="$lx_save_cxxflags"
137.117 - LDFLAGS="$lx_save_ldflags"
137.118 - LIBS="$lx_save_libs"
137.119 -
137.120 - if test x"$lx_cbc_found" = x"yes"; then
137.121 - AC_DEFINE([LEMON_HAVE_CBC], [1], [Define to 1 if you have CBC.])
137.122 - lx_lp_found=yes
137.123 - AC_DEFINE([LEMON_HAVE_LP], [1], [Define to 1 if you have any LP solver.])
137.124 - lx_mip_found=yes
137.125 - AC_DEFINE([LEMON_HAVE_MIP], [1], [Define to 1 if you have any MIP solver.])
137.126 - AC_MSG_RESULT([yes])
137.127 - else
137.128 - CBC_CXXFLAGS=""
137.129 - CBC_LDFLAGS=""
137.130 - CBC_LIBS=""
137.131 - AC_MSG_RESULT([no])
137.132 - fi
137.133 - fi
137.134 - fi
137.135 - CBC_LIBS="$CBC_LDFLAGS $CBC_LIBS"
137.136 - AC_SUBST(CBC_CXXFLAGS)
137.137 - AC_SUBST(CBC_LIBS)
137.138 - AM_CONDITIONAL([HAVE_CBC], [test x"$lx_cbc_found" = x"yes"])
137.139 -])
138.1 --- a/m4/lx_check_cplex.m4 Mon Jul 16 16:21:40 2018 +0200
138.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
138.3 @@ -1,81 +0,0 @@
138.4 -AC_DEFUN([LX_CHECK_CPLEX],
138.5 -[
138.6 - AC_ARG_WITH([cplex],
138.7 -AS_HELP_STRING([--with-cplex@<:@=PREFIX@:>@], [search for CPLEX under PREFIX or under the default search paths if PREFIX is not given @<:@default@:>@])
138.8 -AS_HELP_STRING([--without-cplex], [disable checking for CPLEX]),
138.9 - [], [with_cplex=yes])
138.10 -
138.11 - AC_ARG_WITH([cplex-includedir],
138.12 -AS_HELP_STRING([--with-cplex-includedir=DIR], [search for CPLEX headers in DIR]),
138.13 - [], [with_cplex_includedir=no])
138.14 -
138.15 - AC_ARG_WITH([cplex-libdir],
138.16 -AS_HELP_STRING([--with-cplex-libdir=DIR], [search for CPLEX libraries in DIR]),
138.17 - [], [with_cplex_libdir=no])
138.18 -
138.19 - lx_cplex_found=no
138.20 - if test x"$with_cplex" != x"no"; then
138.21 - AC_MSG_CHECKING([for CPLEX])
138.22 -
138.23 - if test x"$with_cplex_includedir" != x"no"; then
138.24 - CPLEX_CFLAGS="-I$with_cplex_includedir"
138.25 - elif test x"$with_cplex" != x"yes"; then
138.26 - CPLEX_CFLAGS="-I$with_cplex/include"
138.27 - elif test x"$CPLEX_INCLUDEDIR" != x; then
138.28 - CPLEX_CFLAGS="-I$CPLEX_INCLUDEDIR"
138.29 - fi
138.30 -
138.31 - if test x"$with_cplex_libdir" != x"no"; then
138.32 - CPLEX_LDFLAGS="-L$with_cplex_libdir"
138.33 - elif test x"$with_cplex" != x"yes"; then
138.34 - CPLEX_LDFLAGS="-L$with_cplex/lib"
138.35 - elif test x"$CPLEX_LIBDIR" != x; then
138.36 - CPLEX_LDFLAGS="-L$CPLEX_LIBDIR"
138.37 - fi
138.38 - CPLEX_LIBS="-lcplex -lm -lpthread"
138.39 -
138.40 - lx_save_cxxflags="$CXXFLAGS"
138.41 - lx_save_ldflags="$LDFLAGS"
138.42 - lx_save_libs="$LIBS"
138.43 - CXXFLAGS="$CPLEX_CFLAGS"
138.44 - LDFLAGS="$CPLEX_LDFLAGS"
138.45 - LIBS="$CPLEX_LIBS"
138.46 -
138.47 - lx_cplex_test_prog='
138.48 - extern "C" {
138.49 - #include <ilcplex/cplex.h>
138.50 - }
138.51 -
138.52 - int main(int argc, char** argv)
138.53 - {
138.54 - CPXENVptr env = NULL;
138.55 - return 0;
138.56 - }'
138.57 -
138.58 - AC_LANG_PUSH(C++)
138.59 - AC_LINK_IFELSE([$lx_cplex_test_prog], [lx_cplex_found=yes], [lx_cplex_found=no])
138.60 - AC_LANG_POP(C++)
138.61 -
138.62 - CXXFLAGS="$lx_save_cxxflags"
138.63 - LDFLAGS="$lx_save_ldflags"
138.64 - LIBS="$lx_save_libs"
138.65 -
138.66 - if test x"$lx_cplex_found" = x"yes"; then
138.67 - AC_DEFINE([LEMON_HAVE_CPLEX], [1], [Define to 1 if you have CPLEX.])
138.68 - lx_lp_found=yes
138.69 - AC_DEFINE([LEMON_HAVE_LP], [1], [Define to 1 if you have any LP solver.])
138.70 - lx_mip_found=yes
138.71 - AC_DEFINE([LEMON_HAVE_MIP], [1], [Define to 1 if you have any MIP solver.])
138.72 - AC_MSG_RESULT([yes])
138.73 - else
138.74 - CPLEX_CFLAGS=""
138.75 - CPLEX_LDFLAGS=""
138.76 - CPLEX_LIBS=""
138.77 - AC_MSG_RESULT([no])
138.78 - fi
138.79 - fi
138.80 - CPLEX_LIBS="$CPLEX_LDFLAGS $CPLEX_LIBS"
138.81 - AC_SUBST(CPLEX_CFLAGS)
138.82 - AC_SUBST(CPLEX_LIBS)
138.83 - AM_CONDITIONAL([HAVE_CPLEX], [test x"$lx_cplex_found" = x"yes"])
138.84 -])
139.1 --- a/m4/lx_check_glpk.m4 Mon Jul 16 16:21:40 2018 +0200
139.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
139.3 @@ -1,84 +0,0 @@
139.4 -AC_DEFUN([LX_CHECK_GLPK],
139.5 -[
139.6 - AC_ARG_WITH([glpk],
139.7 -AS_HELP_STRING([--with-glpk@<:@=PREFIX@:>@], [search for GLPK under PREFIX or under the default search paths if PREFIX is not given @<:@default@:>@])
139.8 -AS_HELP_STRING([--without-glpk], [disable checking for GLPK]),
139.9 - [], [with_glpk=yes])
139.10 -
139.11 - AC_ARG_WITH([glpk-includedir],
139.12 -AS_HELP_STRING([--with-glpk-includedir=DIR], [search for GLPK headers in DIR]),
139.13 - [], [with_glpk_includedir=no])
139.14 -
139.15 - AC_ARG_WITH([glpk-libdir],
139.16 -AS_HELP_STRING([--with-glpk-libdir=DIR], [search for GLPK libraries in DIR]),
139.17 - [], [with_glpk_libdir=no])
139.18 -
139.19 - lx_glpk_found=no
139.20 - if test x"$with_glpk" != x"no"; then
139.21 - AC_MSG_CHECKING([for GLPK])
139.22 -
139.23 - if test x"$with_glpk_includedir" != x"no"; then
139.24 - GLPK_CFLAGS="-I$with_glpk_includedir"
139.25 - elif test x"$with_glpk" != x"yes"; then
139.26 - GLPK_CFLAGS="-I$with_glpk/include"
139.27 - fi
139.28 -
139.29 - if test x"$with_glpk_libdir" != x"no"; then
139.30 - GLPK_LDFLAGS="-L$with_glpk_libdir"
139.31 - elif test x"$with_glpk" != x"yes"; then
139.32 - GLPK_LDFLAGS="-L$with_glpk/lib"
139.33 - fi
139.34 - GLPK_LIBS="-lglpk"
139.35 -
139.36 - lx_save_cxxflags="$CXXFLAGS"
139.37 - lx_save_ldflags="$LDFLAGS"
139.38 - lx_save_libs="$LIBS"
139.39 - CXXFLAGS="$GLPK_CFLAGS"
139.40 - LDFLAGS="$GLPK_LDFLAGS"
139.41 - LIBS="$GLPK_LIBS"
139.42 -
139.43 - lx_glpk_test_prog='
139.44 - extern "C" {
139.45 - #include <glpk.h>
139.46 - }
139.47 -
139.48 - #if (GLP_MAJOR_VERSION < 4) \
139.49 - || (GLP_MAJOR_VERSION == 4 && GLP_MINOR_VERSION < 33)
139.50 - #error Supported GLPK versions: 4.33 or above
139.51 - #endif
139.52 -
139.53 - int main(int argc, char** argv)
139.54 - {
139.55 - LPX *lp;
139.56 - lp = lpx_create_prob();
139.57 - lpx_delete_prob(lp);
139.58 - return 0;
139.59 - }'
139.60 -
139.61 - AC_LANG_PUSH(C++)
139.62 - AC_LINK_IFELSE([$lx_glpk_test_prog], [lx_glpk_found=yes], [lx_glpk_found=no])
139.63 - AC_LANG_POP(C++)
139.64 -
139.65 - CXXFLAGS="$lx_save_cxxflags"
139.66 - LDFLAGS="$lx_save_ldflags"
139.67 - LIBS="$lx_save_libs"
139.68 -
139.69 - if test x"$lx_glpk_found" = x"yes"; then
139.70 - AC_DEFINE([LEMON_HAVE_GLPK], [1], [Define to 1 if you have GLPK.])
139.71 - lx_lp_found=yes
139.72 - AC_DEFINE([LEMON_HAVE_LP], [1], [Define to 1 if you have any LP solver.])
139.73 - lx_mip_found=yes
139.74 - AC_DEFINE([LEMON_HAVE_MIP], [1], [Define to 1 if you have any MIP solver.])
139.75 - AC_MSG_RESULT([yes])
139.76 - else
139.77 - GLPK_CFLAGS=""
139.78 - GLPK_LDFLAGS=""
139.79 - GLPK_LIBS=""
139.80 - AC_MSG_RESULT([no])
139.81 - fi
139.82 - fi
139.83 - GLPK_LIBS="$GLPK_LDFLAGS $GLPK_LIBS"
139.84 - AC_SUBST(GLPK_CFLAGS)
139.85 - AC_SUBST(GLPK_LIBS)
139.86 - AM_CONDITIONAL([HAVE_GLPK], [test x"$lx_glpk_found" = x"yes"])
139.87 -])
140.1 --- a/m4/lx_check_soplex.m4 Mon Jul 16 16:21:40 2018 +0200
140.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
140.3 @@ -1,73 +0,0 @@
140.4 -AC_DEFUN([LX_CHECK_SOPLEX],
140.5 -[
140.6 - AC_ARG_WITH([soplex],
140.7 -AS_HELP_STRING([--with-soplex@<:@=PREFIX@:>@], [search for SOPLEX under PREFIX or under the default search paths if PREFIX is not given @<:@default@:>@])
140.8 -AS_HELP_STRING([--without-soplex], [disable checking for SOPLEX]),
140.9 - [], [with_soplex=yes])
140.10 -
140.11 - AC_ARG_WITH([soplex-includedir],
140.12 -AS_HELP_STRING([--with-soplex-includedir=DIR], [search for SOPLEX headers in DIR]),
140.13 - [], [with_soplex_includedir=no])
140.14 -
140.15 - AC_ARG_WITH([soplex-libdir],
140.16 -AS_HELP_STRING([--with-soplex-libdir=DIR], [search for SOPLEX libraries in DIR]),
140.17 - [], [with_soplex_libdir=no])
140.18 -
140.19 - lx_soplex_found=no
140.20 - if test x"$with_soplex" != x"no"; then
140.21 - AC_MSG_CHECKING([for SOPLEX])
140.22 -
140.23 - if test x"$with_soplex_includedir" != x"no"; then
140.24 - SOPLEX_CXXFLAGS="-I$with_soplex_includedir"
140.25 - elif test x"$with_soplex" != x"yes"; then
140.26 - SOPLEX_CXXFLAGS="-I$with_soplex/src"
140.27 - fi
140.28 -
140.29 - if test x"$with_soplex_libdir" != x"no"; then
140.30 - SOPLEX_LDFLAGS="-L$with_soplex_libdir"
140.31 - elif test x"$with_soplex" != x"yes"; then
140.32 - SOPLEX_LDFLAGS="-L$with_soplex/lib"
140.33 - fi
140.34 - SOPLEX_LIBS="-lsoplex -lz"
140.35 -
140.36 - lx_save_cxxflags="$CXXFLAGS"
140.37 - lx_save_ldflags="$LDFLAGS"
140.38 - lx_save_libs="$LIBS"
140.39 - CXXFLAGS="$SOPLEX_CXXFLAGS"
140.40 - LDFLAGS="$SOPLEX_LDFLAGS"
140.41 - LIBS="$SOPLEX_LIBS"
140.42 -
140.43 - lx_soplex_test_prog='
140.44 - #include <soplex.h>
140.45 -
140.46 - int main(int argc, char** argv)
140.47 - {
140.48 - soplex::SoPlex soplex;
140.49 - return 0;
140.50 - }'
140.51 -
140.52 - AC_LANG_PUSH(C++)
140.53 - AC_LINK_IFELSE([$lx_soplex_test_prog], [lx_soplex_found=yes], [lx_soplex_found=no])
140.54 - AC_LANG_POP(C++)
140.55 -
140.56 - CXXFLAGS="$lx_save_cxxflags"
140.57 - LDFLAGS="$lx_save_ldflags"
140.58 - LIBS="$lx_save_libs"
140.59 -
140.60 - if test x"$lx_soplex_found" = x"yes"; then
140.61 - AC_DEFINE([LEMON_HAVE_SOPLEX], [1], [Define to 1 if you have SOPLEX.])
140.62 - lx_lp_found=yes
140.63 - AC_DEFINE([LEMON_HAVE_LP], [1], [Define to 1 if you have any LP solver.])
140.64 - AC_MSG_RESULT([yes])
140.65 - else
140.66 - SOPLEX_CXXFLAGS=""
140.67 - SOPLEX_LDFLAGS=""
140.68 - SOPLEX_LIBS=""
140.69 - AC_MSG_RESULT([no])
140.70 - fi
140.71 - fi
140.72 - SOPLEX_LIBS="$SOPLEX_LDFLAGS $SOPLEX_LIBS"
140.73 - AC_SUBST(SOPLEX_CXXFLAGS)
140.74 - AC_SUBST(SOPLEX_LIBS)
140.75 - AM_CONDITIONAL([HAVE_SOPLEX], [test x"$lx_soplex_found" = x"yes"])
140.76 -])
141.1 --- a/scripts/Makefile.am Mon Jul 16 16:21:40 2018 +0200
141.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
141.3 @@ -1,7 +0,0 @@
141.4 -EXTRA_DIST += \
141.5 - scripts/bib2dox.py \
141.6 - scripts/bootstrap.sh \
141.7 - scripts/chg-len.py \
141.8 - scripts/mk-release.sh \
141.9 - scripts/unify-sources.sh \
141.10 - scripts/valgrind-wrapper.sh
142.1 --- a/scripts/bib2dox.py Mon Jul 16 16:21:40 2018 +0200
142.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
142.3 @@ -1,816 +0,0 @@
142.4 -#! /usr/bin/env python
142.5 -"""
142.6 - BibTeX to Doxygen converter
142.7 - Usage: python bib2dox.py bibfile.bib > bibfile.dox
142.8 -
142.9 - This file is a part of LEMON, a generic C++ optimization library.
142.10 -
142.11 - **********************************************************************
142.12 -
142.13 - This code is the modification of the BibTeX to XML converter
142.14 - by Vidar Bronken Gundersen et al.
142.15 - See the original copyright notices below.
142.16 -
142.17 - **********************************************************************
142.18 -
142.19 - Decoder for bibliographic data, BibTeX
142.20 - Usage: python bibtex2xml.py bibfile.bib > bibfile.xml
142.21 -
142.22 - v.8
142.23 - (c)2002-06-23 Vidar Bronken Gundersen
142.24 - http://bibtexml.sf.net/
142.25 - Reuse approved as long as this notification is kept.
142.26 - Licence: GPL.
142.27 -
142.28 - Contributions/thanks to:
142.29 - Egon Willighagen, http://sf.net/projects/jreferences/
142.30 - Richard Mahoney (for providing a test case)
142.31 -
142.32 - Editted by Sara Sprenkle to be more robust and handle more bibtex features.
142.33 - (c) 2003-01-15
142.34 -
142.35 - 1. Changed bibtex: tags to bibxml: tags.
142.36 - 2. Use xmlns:bibxml="http://bibtexml.sf.net/"
142.37 - 3. Allow spaces between @type and first {
142.38 - 4. "author" fields with multiple authors split by " and "
142.39 - are put in separate xml "bibxml:author" tags.
142.40 - 5. Option for Titles: words are capitalized
142.41 - only if first letter in title or capitalized inside braces
142.42 - 6. Removes braces from within field values
142.43 - 7. Ignores comments in bibtex file (including @comment{ or % )
142.44 - 8. Replaces some special latex tags, e.g., replaces ~ with ' '
142.45 - 9. Handles bibtex @string abbreviations
142.46 - --> includes bibtex's default abbreviations for months
142.47 - --> does concatenation of abbr # " more " and " more " # abbr
142.48 - 10. Handles @type( ... ) or @type{ ... }
142.49 - 11. The keywords field is split on , or ; and put into separate xml
142.50 - "bibxml:keywords" tags
142.51 - 12. Ignores @preamble
142.52 -
142.53 - Known Limitations
142.54 - 1. Does not transform Latex encoding like math mode and special
142.55 - latex symbols.
142.56 - 2. Does not parse author fields into first and last names.
142.57 - E.g., It does not do anything special to an author whose name is
142.58 - in the form LAST_NAME, FIRST_NAME
142.59 - In "author" tag, will show up as
142.60 - <bibxml:author>LAST_NAME, FIRST_NAME</bibxml:author>
142.61 - 3. Does not handle "crossref" fields other than to print
142.62 - <bibxml:crossref>...</bibxml:crossref>
142.63 - 4. Does not inform user of the input's format errors. You just won't
142.64 - be able to transform the file later with XSL
142.65 -
142.66 - You will have to manually edit the XML output if you need to handle
142.67 - these (and unknown) limitations.
142.68 -
142.69 -"""
142.70 -
142.71 -import string, re
142.72 -
142.73 -# set of valid name characters
142.74 -valid_name_chars = '[\w\-:]'
142.75 -
142.76 -#
142.77 -# define global regular expression variables
142.78 -#
142.79 -author_rex = re.compile('\s+and\s+')
142.80 -rembraces_rex = re.compile('[{}]')
142.81 -capitalize_rex = re.compile('({[^}]*})')
142.82 -
142.83 -# used by bibtexkeywords(data)
142.84 -keywords_rex = re.compile('[,;]')
142.85 -
142.86 -# used by concat_line(line)
142.87 -concatsplit_rex = re.compile('\s*#\s*')
142.88 -
142.89 -# split on {, }, or " in verify_out_of_braces
142.90 -delimiter_rex = re.compile('([{}"])',re.I)
142.91 -
142.92 -field_rex = re.compile('\s*(\w*)\s*=\s*(.*)')
142.93 -data_rex = re.compile('\s*(\w*)\s*=\s*([^,]*),?')
142.94 -
142.95 -url_rex = re.compile('\\\url\{([^}]*)\}')
142.96 -
142.97 -#
142.98 -# styles for html formatting
142.99 -#
142.100 -divstyle = 'margin-top: -4ex; margin-left: 8em;'
142.101 -
142.102 -#
142.103 -# return the string parameter without braces
142.104 -#
142.105 -def transformurls(str):
142.106 - return url_rex.sub(r'<a href="\1">\1</a>', str)
142.107 -
142.108 -#
142.109 -# return the string parameter without braces
142.110 -#
142.111 -def removebraces(str):
142.112 - return rembraces_rex.sub('', str)
142.113 -
142.114 -#
142.115 -# latex-specific replacements
142.116 -# (do this after braces were removed)
142.117 -#
142.118 -def latexreplacements(line):
142.119 - line = string.replace(line, '~', ' ')
142.120 - line = string.replace(line, '\\\'a', 'á')
142.121 - line = string.replace(line, '\\"a', 'ä')
142.122 - line = string.replace(line, '\\\'e', 'é')
142.123 - line = string.replace(line, '\\"e', 'ë')
142.124 - line = string.replace(line, '\\\'i', 'í')
142.125 - line = string.replace(line, '\\"i', 'ï')
142.126 - line = string.replace(line, '\\\'o', 'ó')
142.127 - line = string.replace(line, '\\"o', 'ö')
142.128 - line = string.replace(line, '\\\'u', 'ú')
142.129 - line = string.replace(line, '\\"u', 'ü')
142.130 - line = string.replace(line, '\\H o', 'õ')
142.131 - line = string.replace(line, '\\H u', 'ü') # ũ does not exist
142.132 - line = string.replace(line, '\\\'A', 'Á')
142.133 - line = string.replace(line, '\\"A', 'Ä')
142.134 - line = string.replace(line, '\\\'E', 'É')
142.135 - line = string.replace(line, '\\"E', 'Ë')
142.136 - line = string.replace(line, '\\\'I', 'Í')
142.137 - line = string.replace(line, '\\"I', 'Ï')
142.138 - line = string.replace(line, '\\\'O', 'Ó')
142.139 - line = string.replace(line, '\\"O', 'Ö')
142.140 - line = string.replace(line, '\\\'U', 'Ú')
142.141 - line = string.replace(line, '\\"U', 'Ü')
142.142 - line = string.replace(line, '\\H O', 'Õ')
142.143 - line = string.replace(line, '\\H U', 'Ü') # Ũ does not exist
142.144 -
142.145 - return line
142.146 -
142.147 -#
142.148 -# copy characters form a string decoding html expressions (&xyz;)
142.149 -#
142.150 -def copychars(str, ifrom, count):
142.151 - result = ''
142.152 - i = ifrom
142.153 - c = 0
142.154 - html_spec = False
142.155 - while (i < len(str)) and (c < count):
142.156 - if str[i] == '&':
142.157 - html_spec = True;
142.158 - if i+1 < len(str):
142.159 - result += str[i+1]
142.160 - c += 1
142.161 - i += 2
142.162 - else:
142.163 - if not html_spec:
142.164 - if ((str[i] >= 'A') and (str[i] <= 'Z')) or \
142.165 - ((str[i] >= 'a') and (str[i] <= 'z')):
142.166 - result += str[i]
142.167 - c += 1
142.168 - elif str[i] == ';':
142.169 - html_spec = False;
142.170 - i += 1
142.171 -
142.172 - return result
142.173 -
142.174 -
142.175 -#
142.176 -# Handle a list of authors (separated by 'and').
142.177 -# It gives back an array of the follwing values:
142.178 -# - num: the number of authors,
142.179 -# - list: the list of the author names,
142.180 -# - text: the bibtex text (separated by commas and/or 'and')
142.181 -# - abbrev: abbreviation that can be used for indicate the
142.182 -# bibliography entries
142.183 -#
142.184 -def bibtexauthor(data):
142.185 - result = {}
142.186 - bibtex = ''
142.187 - result['list'] = author_rex.split(data)
142.188 - result['num'] = len(result['list'])
142.189 - for i, author in enumerate(result['list']):
142.190 - # general transformations
142.191 - author = latexreplacements(removebraces(author.strip()))
142.192 - # transform "Xyz, A. B." to "A. B. Xyz"
142.193 - pos = author.find(',')
142.194 - if pos != -1:
142.195 - author = author[pos+1:].strip() + ' ' + author[:pos].strip()
142.196 - result['list'][i] = author
142.197 - bibtex += author + '#'
142.198 - bibtex = bibtex[:-1]
142.199 - if result['num'] > 1:
142.200 - ix = bibtex.rfind('#')
142.201 - if result['num'] == 2:
142.202 - bibtex = bibtex[:ix] + ' and ' + bibtex[ix+1:]
142.203 - else:
142.204 - bibtex = bibtex[:ix] + ', and ' + bibtex[ix+1:]
142.205 - bibtex = bibtex.replace('#', ', ')
142.206 - result['text'] = bibtex
142.207 -
142.208 - result['abbrev'] = ''
142.209 - for author in result['list']:
142.210 - pos = author.rfind(' ') + 1
142.211 - count = 1
142.212 - if result['num'] == 1:
142.213 - count = 3
142.214 - result['abbrev'] += copychars(author, pos, count)
142.215 -
142.216 - return result
142.217 -
142.218 -
142.219 -#
142.220 -# data = title string
142.221 -# @return the capitalized title (first letter is capitalized), rest are capitalized
142.222 -# only if capitalized inside braces
142.223 -#
142.224 -def capitalizetitle(data):
142.225 - title_list = capitalize_rex.split(data)
142.226 - title = ''
142.227 - count = 0
142.228 - for phrase in title_list:
142.229 - check = string.lstrip(phrase)
142.230 -
142.231 - # keep phrase's capitalization the same
142.232 - if check.find('{') == 0:
142.233 - title += removebraces(phrase)
142.234 - else:
142.235 - # first word --> capitalize first letter (after spaces)
142.236 - if count == 0:
142.237 - title += check.capitalize()
142.238 - else:
142.239 - title += phrase.lower()
142.240 - count = count + 1
142.241 -
142.242 - return title
142.243 -
142.244 -
142.245 -#
142.246 -# @return the bibtex for the title
142.247 -# @param data --> title string
142.248 -# braces are removed from title
142.249 -#
142.250 -def bibtextitle(data, entrytype):
142.251 - if entrytype in ('book', 'inbook'):
142.252 - title = removebraces(data.strip())
142.253 - else:
142.254 - title = removebraces(capitalizetitle(data.strip()))
142.255 - bibtex = title
142.256 - return bibtex
142.257 -
142.258 -
142.259 -#
142.260 -# function to compare entry lists
142.261 -#
142.262 -def entry_cmp(x, y):
142.263 - return cmp(x[0], y[0])
142.264 -
142.265 -
142.266 -#
142.267 -# print the XML for the transformed "filecont_source"
142.268 -#
142.269 -def bibtexdecoder(filecont_source):
142.270 - filecont = []
142.271 - file = []
142.272 -
142.273 - # want @<alphanumeric chars><spaces>{<spaces><any chars>,
142.274 - pubtype_rex = re.compile('@(\w*)\s*{\s*(.*),')
142.275 - endtype_rex = re.compile('}\s*$')
142.276 - endtag_rex = re.compile('^\s*}\s*$')
142.277 -
142.278 - bracefield_rex = re.compile('\s*(\w*)\s*=\s*(.*)')
142.279 - bracedata_rex = re.compile('\s*(\w*)\s*=\s*{(.*)},?')
142.280 -
142.281 - quotefield_rex = re.compile('\s*(\w*)\s*=\s*(.*)')
142.282 - quotedata_rex = re.compile('\s*(\w*)\s*=\s*"(.*)",?')
142.283 -
142.284 - for line in filecont_source:
142.285 - line = line[:-1]
142.286 -
142.287 - # encode character entities
142.288 - line = string.replace(line, '&', '&')
142.289 - line = string.replace(line, '<', '<')
142.290 - line = string.replace(line, '>', '>')
142.291 -
142.292 - # start entry: publication type (store for later use)
142.293 - if pubtype_rex.match(line):
142.294 - # want @<alphanumeric chars><spaces>{<spaces><any chars>,
142.295 - entrycont = {}
142.296 - entry = []
142.297 - entrytype = pubtype_rex.sub('\g<1>',line)
142.298 - entrytype = string.lower(entrytype)
142.299 - entryid = pubtype_rex.sub('\g<2>', line)
142.300 -
142.301 - # end entry if just a }
142.302 - elif endtype_rex.match(line):
142.303 - # generate doxygen code for the entry
142.304 -
142.305 - # enty type related formattings
142.306 - if entrytype in ('book', 'inbook'):
142.307 - entrycont['title'] = '<em>' + entrycont['title'] + '</em>'
142.308 - if not entrycont.has_key('author'):
142.309 - entrycont['author'] = entrycont['editor']
142.310 - entrycont['author']['text'] += ', editors'
142.311 - elif entrytype == 'article':
142.312 - entrycont['journal'] = '<em>' + entrycont['journal'] + '</em>'
142.313 - elif entrytype in ('inproceedings', 'incollection', 'conference'):
142.314 - entrycont['booktitle'] = '<em>' + entrycont['booktitle'] + '</em>'
142.315 - elif entrytype == 'techreport':
142.316 - if not entrycont.has_key('type'):
142.317 - entrycont['type'] = 'Technical report'
142.318 - elif entrytype == 'mastersthesis':
142.319 - entrycont['type'] = 'Master\'s thesis'
142.320 - elif entrytype == 'phdthesis':
142.321 - entrycont['type'] = 'PhD thesis'
142.322 -
142.323 - for eline in entrycont:
142.324 - if eline != '':
142.325 - eline = latexreplacements(eline)
142.326 -
142.327 - if entrycont.has_key('pages') and (entrycont['pages'] != ''):
142.328 - entrycont['pages'] = string.replace(entrycont['pages'], '--', '-')
142.329 -
142.330 - if entrycont.has_key('author') and (entrycont['author'] != ''):
142.331 - entry.append(entrycont['author']['text'] + '.')
142.332 - if entrycont.has_key('title') and (entrycont['title'] != ''):
142.333 - entry.append(entrycont['title'] + '.')
142.334 - if entrycont.has_key('journal') and (entrycont['journal'] != ''):
142.335 - entry.append(entrycont['journal'] + ',')
142.336 - if entrycont.has_key('booktitle') and (entrycont['booktitle'] != ''):
142.337 - entry.append('In ' + entrycont['booktitle'] + ',')
142.338 - if entrycont.has_key('type') and (entrycont['type'] != ''):
142.339 - eline = entrycont['type']
142.340 - if entrycont.has_key('number') and (entrycont['number'] != ''):
142.341 - eline += ' ' + entrycont['number']
142.342 - eline += ','
142.343 - entry.append(eline)
142.344 - if entrycont.has_key('institution') and (entrycont['institution'] != ''):
142.345 - entry.append(entrycont['institution'] + ',')
142.346 - if entrycont.has_key('publisher') and (entrycont['publisher'] != ''):
142.347 - entry.append(entrycont['publisher'] + ',')
142.348 - if entrycont.has_key('school') and (entrycont['school'] != ''):
142.349 - entry.append(entrycont['school'] + ',')
142.350 - if entrycont.has_key('address') and (entrycont['address'] != ''):
142.351 - entry.append(entrycont['address'] + ',')
142.352 - if entrycont.has_key('edition') and (entrycont['edition'] != ''):
142.353 - entry.append(entrycont['edition'] + ' edition,')
142.354 - if entrycont.has_key('howpublished') and (entrycont['howpublished'] != ''):
142.355 - entry.append(entrycont['howpublished'] + ',')
142.356 - if entrycont.has_key('volume') and (entrycont['volume'] != ''):
142.357 - eline = entrycont['volume'];
142.358 - if entrycont.has_key('number') and (entrycont['number'] != ''):
142.359 - eline += '(' + entrycont['number'] + ')'
142.360 - if entrycont.has_key('pages') and (entrycont['pages'] != ''):
142.361 - eline += ':' + entrycont['pages']
142.362 - eline += ','
142.363 - entry.append(eline)
142.364 - else:
142.365 - if entrycont.has_key('pages') and (entrycont['pages'] != ''):
142.366 - entry.append('pages ' + entrycont['pages'] + ',')
142.367 - if entrycont.has_key('year') and (entrycont['year'] != ''):
142.368 - if entrycont.has_key('month') and (entrycont['month'] != ''):
142.369 - entry.append(entrycont['month'] + ' ' + entrycont['year'] + '.')
142.370 - else:
142.371 - entry.append(entrycont['year'] + '.')
142.372 - if entrycont.has_key('note') and (entrycont['note'] != ''):
142.373 - entry.append(entrycont['note'] + '.')
142.374 - if entrycont.has_key('url') and (entrycont['url'] != ''):
142.375 - entry.append(entrycont['url'] + '.')
142.376 -
142.377 - # generate keys for sorting and for the output
142.378 - sortkey = ''
142.379 - bibkey = ''
142.380 - if entrycont.has_key('author'):
142.381 - for author in entrycont['author']['list']:
142.382 - sortkey += copychars(author, author.rfind(' ')+1, len(author))
142.383 - bibkey = entrycont['author']['abbrev']
142.384 - else:
142.385 - bibkey = 'x'
142.386 - if entrycont.has_key('year'):
142.387 - sortkey += entrycont['year']
142.388 - bibkey += entrycont['year'][-2:]
142.389 - if entrycont.has_key('title'):
142.390 - sortkey += entrycont['title']
142.391 - if entrycont.has_key('key'):
142.392 - sortkey = entrycont['key'] + sortkey
142.393 - bibkey = entrycont['key']
142.394 - entry.insert(0, sortkey)
142.395 - entry.insert(1, bibkey)
142.396 - entry.insert(2, entryid)
142.397 -
142.398 - # add the entry to the file contents
142.399 - filecont.append(entry)
142.400 -
142.401 - else:
142.402 - # field, publication info
142.403 - field = ''
142.404 - data = ''
142.405 -
142.406 - # field = {data} entries
142.407 - if bracedata_rex.match(line):
142.408 - field = bracefield_rex.sub('\g<1>', line)
142.409 - field = string.lower(field)
142.410 - data = bracedata_rex.sub('\g<2>', line)
142.411 -
142.412 - # field = "data" entries
142.413 - elif quotedata_rex.match(line):
142.414 - field = quotefield_rex.sub('\g<1>', line)
142.415 - field = string.lower(field)
142.416 - data = quotedata_rex.sub('\g<2>', line)
142.417 -
142.418 - # field = data entries
142.419 - elif data_rex.match(line):
142.420 - field = field_rex.sub('\g<1>', line)
142.421 - field = string.lower(field)
142.422 - data = data_rex.sub('\g<2>', line)
142.423 -
142.424 - if field == 'url':
142.425 - data = '\\url{' + data.strip() + '}'
142.426 -
142.427 - if field in ('author', 'editor'):
142.428 - entrycont[field] = bibtexauthor(data)
142.429 - line = ''
142.430 - elif field == 'title':
142.431 - line = bibtextitle(data, entrytype)
142.432 - elif field != '':
142.433 - line = removebraces(transformurls(data.strip()))
142.434 -
142.435 - if line != '':
142.436 - line = latexreplacements(line)
142.437 - entrycont[field] = line
142.438 -
142.439 -
142.440 - # sort entries
142.441 - filecont.sort(entry_cmp)
142.442 -
142.443 - # count the bibtex keys
142.444 - keytable = {}
142.445 - counttable = {}
142.446 - for entry in filecont:
142.447 - bibkey = entry[1]
142.448 - if not keytable.has_key(bibkey):
142.449 - keytable[bibkey] = 1
142.450 - else:
142.451 - keytable[bibkey] += 1
142.452 -
142.453 - for bibkey in keytable.keys():
142.454 - counttable[bibkey] = 0
142.455 -
142.456 - # generate output
142.457 - for entry in filecont:
142.458 - # generate output key form the bibtex key
142.459 - bibkey = entry[1]
142.460 - entryid = entry[2]
142.461 - if keytable[bibkey] == 1:
142.462 - outkey = bibkey
142.463 - else:
142.464 - outkey = bibkey + chr(97 + counttable[bibkey])
142.465 - counttable[bibkey] += 1
142.466 -
142.467 - # append the entry code to the output
142.468 - file.append('\\section ' + entryid + ' [' + outkey + ']')
142.469 - file.append('<div style="' + divstyle + '">')
142.470 - for line in entry[3:]:
142.471 - file.append(line)
142.472 - file.append('</div>')
142.473 - file.append('')
142.474 -
142.475 - return file
142.476 -
142.477 -
142.478 -#
142.479 -# return 1 iff abbr is in line but not inside braces or quotes
142.480 -# assumes that abbr appears only once on the line (out of braces and quotes)
142.481 -#
142.482 -def verify_out_of_braces(line, abbr):
142.483 -
142.484 - phrase_split = delimiter_rex.split(line)
142.485 -
142.486 - abbr_rex = re.compile( '\\b' + abbr + '\\b', re.I)
142.487 -
142.488 - open_brace = 0
142.489 - open_quote = 0
142.490 -
142.491 - for phrase in phrase_split:
142.492 - if phrase == "{":
142.493 - open_brace = open_brace + 1
142.494 - elif phrase == "}":
142.495 - open_brace = open_brace - 1
142.496 - elif phrase == '"':
142.497 - if open_quote == 1:
142.498 - open_quote = 0
142.499 - else:
142.500 - open_quote = 1
142.501 - elif abbr_rex.search(phrase):
142.502 - if open_brace == 0 and open_quote == 0:
142.503 - return 1
142.504 -
142.505 - return 0
142.506 -
142.507 -
142.508 -#
142.509 -# a line in the form phrase1 # phrase2 # ... # phrasen
142.510 -# is returned as phrase1 phrase2 ... phrasen
142.511 -# with the correct punctuation
142.512 -# Bug: Doesn't always work with multiple abbreviations plugged in
142.513 -#
142.514 -def concat_line(line):
142.515 - # only look at part after equals
142.516 - field = field_rex.sub('\g<1>',line)
142.517 - rest = field_rex.sub('\g<2>',line)
142.518 -
142.519 - concat_line = field + ' ='
142.520 -
142.521 - pound_split = concatsplit_rex.split(rest)
142.522 -
142.523 - phrase_count = 0
142.524 - length = len(pound_split)
142.525 -
142.526 - for phrase in pound_split:
142.527 - phrase = phrase.strip()
142.528 - if phrase_count != 0:
142.529 - if phrase.startswith('"') or phrase.startswith('{'):
142.530 - phrase = phrase[1:]
142.531 - elif phrase.startswith('"'):
142.532 - phrase = phrase.replace('"','{',1)
142.533 -
142.534 - if phrase_count != length-1:
142.535 - if phrase.endswith('"') or phrase.endswith('}'):
142.536 - phrase = phrase[:-1]
142.537 - else:
142.538 - if phrase.endswith('"'):
142.539 - phrase = phrase[:-1]
142.540 - phrase = phrase + "}"
142.541 - elif phrase.endswith('",'):
142.542 - phrase = phrase[:-2]
142.543 - phrase = phrase + "},"
142.544 -
142.545 - # if phrase did have \#, add the \# back
142.546 - if phrase.endswith('\\'):
142.547 - phrase = phrase + "#"
142.548 - concat_line = concat_line + ' ' + phrase
142.549 -
142.550 - phrase_count = phrase_count + 1
142.551 -
142.552 - return concat_line
142.553 -
142.554 -
142.555 -#
142.556 -# substitute abbreviations into filecont
142.557 -# @param filecont_source - string of data from file
142.558 -#
142.559 -def bibtex_replace_abbreviations(filecont_source):
142.560 - filecont = filecont_source.splitlines()
142.561 -
142.562 - # These are defined in bibtex, so we'll define them too
142.563 - abbr_list = ['jan','feb','mar','apr','may','jun',
142.564 - 'jul','aug','sep','oct','nov','dec']
142.565 - value_list = ['January','February','March','April',
142.566 - 'May','June','July','August','September',
142.567 - 'October','November','December']
142.568 -
142.569 - abbr_rex = []
142.570 - total_abbr_count = 0
142.571 -
142.572 - front = '\\b'
142.573 - back = '(,?)\\b'
142.574 -
142.575 - for x in abbr_list:
142.576 - abbr_rex.append( re.compile( front + abbr_list[total_abbr_count] + back, re.I ) )
142.577 - total_abbr_count = total_abbr_count + 1
142.578 -
142.579 -
142.580 - abbrdef_rex = re.compile('\s*@string\s*{\s*('+ valid_name_chars +'*)\s*=(.*)',
142.581 - re.I)
142.582 -
142.583 - comment_rex = re.compile('@comment\s*{',re.I)
142.584 - preamble_rex = re.compile('@preamble\s*{',re.I)
142.585 -
142.586 - waiting_for_end_string = 0
142.587 - i = 0
142.588 - filecont2 = ''
142.589 -
142.590 - for line in filecont:
142.591 - if line == ' ' or line == '':
142.592 - continue
142.593 -
142.594 - if waiting_for_end_string:
142.595 - if re.search('}',line):
142.596 - waiting_for_end_string = 0
142.597 - continue
142.598 -
142.599 - if abbrdef_rex.search(line):
142.600 - abbr = abbrdef_rex.sub('\g<1>', line)
142.601 -
142.602 - if abbr_list.count(abbr) == 0:
142.603 - val = abbrdef_rex.sub('\g<2>', line)
142.604 - abbr_list.append(abbr)
142.605 - value_list.append(string.strip(val))
142.606 - abbr_rex.append( re.compile( front + abbr_list[total_abbr_count] + back, re.I ) )
142.607 - total_abbr_count = total_abbr_count + 1
142.608 - waiting_for_end_string = 1
142.609 - continue
142.610 -
142.611 - if comment_rex.search(line):
142.612 - waiting_for_end_string = 1
142.613 - continue
142.614 -
142.615 - if preamble_rex.search(line):
142.616 - waiting_for_end_string = 1
142.617 - continue
142.618 -
142.619 -
142.620 - # replace subsequent abbreviations with the value
142.621 - abbr_count = 0
142.622 -
142.623 - for x in abbr_list:
142.624 -
142.625 - if abbr_rex[abbr_count].search(line):
142.626 - if verify_out_of_braces(line,abbr_list[abbr_count]) == 1:
142.627 - line = abbr_rex[abbr_count].sub( value_list[abbr_count] + '\g<1>', line)
142.628 - # Check for # concatenations
142.629 - if concatsplit_rex.search(line):
142.630 - line = concat_line(line)
142.631 - abbr_count = abbr_count + 1
142.632 -
142.633 -
142.634 - filecont2 = filecont2 + line + '\n'
142.635 - i = i+1
142.636 -
142.637 -
142.638 - # Do one final pass over file
142.639 -
142.640 - # make sure that didn't end up with {" or }" after the substitution
142.641 - filecont2 = filecont2.replace('{"','{{')
142.642 - filecont2 = filecont2.replace('"}','}}')
142.643 -
142.644 - afterquotevalue_rex = re.compile('"\s*,\s*')
142.645 - afterbrace_rex = re.compile('"\s*}')
142.646 - afterbracevalue_rex = re.compile('(=\s*{[^=]*)},\s*')
142.647 -
142.648 - # add new lines to data that changed because of abbreviation substitutions
142.649 - filecont2 = afterquotevalue_rex.sub('",\n', filecont2)
142.650 - filecont2 = afterbrace_rex.sub('"\n}', filecont2)
142.651 - filecont2 = afterbracevalue_rex.sub('\g<1>},\n', filecont2)
142.652 -
142.653 - return filecont2
142.654 -
142.655 -#
142.656 -# convert @type( ... ) to @type{ ... }
142.657 -#
142.658 -def no_outer_parens(filecont):
142.659 -
142.660 - # do checking for open parens
142.661 - # will convert to braces
142.662 - paren_split = re.split('([(){}])',filecont)
142.663 -
142.664 - open_paren_count = 0
142.665 - open_type = 0
142.666 - look_next = 0
142.667 -
142.668 - # rebuild filecont
142.669 - filecont = ''
142.670 -
142.671 - at_rex = re.compile('@\w*')
142.672 -
142.673 - for phrase in paren_split:
142.674 - if look_next == 1:
142.675 - if phrase == '(':
142.676 - phrase = '{'
142.677 - open_paren_count = open_paren_count + 1
142.678 - else:
142.679 - open_type = 0
142.680 - look_next = 0
142.681 -
142.682 - if phrase == '(':
142.683 - open_paren_count = open_paren_count + 1
142.684 -
142.685 - elif phrase == ')':
142.686 - open_paren_count = open_paren_count - 1
142.687 - if open_type == 1 and open_paren_count == 0:
142.688 - phrase = '}'
142.689 - open_type = 0
142.690 -
142.691 - elif at_rex.search( phrase ):
142.692 - open_type = 1
142.693 - look_next = 1
142.694 -
142.695 - filecont = filecont + phrase
142.696 -
142.697 - return filecont
142.698 -
142.699 -
142.700 -#
142.701 -# make all whitespace into just one space
142.702 -# format the bibtex file into a usable form.
142.703 -#
142.704 -def bibtexwasher(filecont_source):
142.705 -
142.706 - space_rex = re.compile('\s+')
142.707 - comment_rex = re.compile('\s*%')
142.708 -
142.709 - filecont = []
142.710 -
142.711 - # remove trailing and excessive whitespace
142.712 - # ignore comments
142.713 - for line in filecont_source:
142.714 - line = string.strip(line)
142.715 - line = space_rex.sub(' ', line)
142.716 - # ignore comments
142.717 - if not comment_rex.match(line) and line != '':
142.718 - filecont.append(' '+ line)
142.719 -
142.720 - filecont = string.join(filecont, '')
142.721 -
142.722 - # the file is in one long string
142.723 -
142.724 - filecont = no_outer_parens(filecont)
142.725 -
142.726 - #
142.727 - # split lines according to preferred syntax scheme
142.728 - #
142.729 - filecont = re.sub('(=\s*{[^=]*)},', '\g<1>},\n', filecont)
142.730 -
142.731 - # add new lines after commas that are after values
142.732 - filecont = re.sub('"\s*,', '",\n', filecont)
142.733 - filecont = re.sub('=\s*([\w\d]+)\s*,', '= \g<1>,\n', filecont)
142.734 - filecont = re.sub('(@\w*)\s*({(\s*)[^,\s]*)\s*,',
142.735 - '\n\n\g<1>\g<2>,\n', filecont)
142.736 -
142.737 - # add new lines after }
142.738 - filecont = re.sub('"\s*}','"\n}\n', filecont)
142.739 - filecont = re.sub('}\s*,','},\n', filecont)
142.740 -
142.741 -
142.742 - filecont = re.sub('@(\w*)', '\n@\g<1>', filecont)
142.743 -
142.744 - # character encoding, reserved latex characters
142.745 - filecont = re.sub('{\\\&}', '&', filecont)
142.746 - filecont = re.sub('\\\&', '&', filecont)
142.747 -
142.748 - # do checking for open braces to get format correct
142.749 - open_brace_count = 0
142.750 - brace_split = re.split('([{}])',filecont)
142.751 -
142.752 - # rebuild filecont
142.753 - filecont = ''
142.754 -
142.755 - for phrase in brace_split:
142.756 - if phrase == '{':
142.757 - open_brace_count = open_brace_count + 1
142.758 - elif phrase == '}':
142.759 - open_brace_count = open_brace_count - 1
142.760 - if open_brace_count == 0:
142.761 - filecont = filecont + '\n'
142.762 -
142.763 - filecont = filecont + phrase
142.764 -
142.765 - filecont2 = bibtex_replace_abbreviations(filecont)
142.766 -
142.767 - # gather
142.768 - filecont = filecont2.splitlines()
142.769 - i=0
142.770 - j=0 # count the number of blank lines
142.771 - for line in filecont:
142.772 - # ignore blank lines
142.773 - if line == '' or line == ' ':
142.774 - j = j+1
142.775 - continue
142.776 - filecont[i] = line + '\n'
142.777 - i = i+1
142.778 -
142.779 - # get rid of the extra stuff at the end of the array
142.780 - # (The extra stuff are duplicates that are in the array because
142.781 - # blank lines were removed.)
142.782 - length = len( filecont)
142.783 - filecont[length-j:length] = []
142.784 -
142.785 - return filecont
142.786 -
142.787 -
142.788 -def filehandler(filepath):
142.789 - try:
142.790 - fd = open(filepath, 'r')
142.791 - filecont_source = fd.readlines()
142.792 - fd.close()
142.793 - except:
142.794 - print 'Could not open file:', filepath
142.795 - washeddata = bibtexwasher(filecont_source)
142.796 - outdata = bibtexdecoder(washeddata)
142.797 - print '/**'
142.798 - print '\page references References'
142.799 - print
142.800 - for line in outdata:
142.801 - print line
142.802 - print '*/'
142.803 -
142.804 -
142.805 -# main program
142.806 -
142.807 -def main():
142.808 - import sys
142.809 - if sys.argv[1:]:
142.810 - filepath = sys.argv[1]
142.811 - else:
142.812 - print "No input file"
142.813 - sys.exit()
142.814 - filehandler(filepath)
142.815 -
142.816 -if __name__ == "__main__": main()
142.817 -
142.818 -
142.819 -# end python script
143.1 --- a/scripts/bootstrap.sh Mon Jul 16 16:21:40 2018 +0200
143.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
143.3 @@ -1,157 +0,0 @@
143.4 -#!/bin/bash
143.5 -#
143.6 -# This file is a part of LEMON, a generic C++ optimization library.
143.7 -#
143.8 -# Copyright (C) 2003-2009
143.9 -# Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
143.10 -# (Egervary Research Group on Combinatorial Optimization, EGRES).
143.11 -#
143.12 -# Permission to use, modify and distribute this software is granted
143.13 -# provided that this copyright notice appears in all copies. For
143.14 -# precise terms see the accompanying LICENSE file.
143.15 -#
143.16 -# This software is provided "AS IS" with no warranty of any kind,
143.17 -# express or implied, and with no claim as to its suitability for any
143.18 -# purpose.
143.19 -
143.20 -
143.21 -if [ ! -f ~/.lemon-bootstrap ]; then
143.22 - echo 'Create ~/.lemon-bootstrap'.
143.23 - cat >~/.lemon-bootstrap <<EOF
143.24 -#
143.25 -# Default settings for bootstraping the LEMON source code repository
143.26 -#
143.27 -EOF
143.28 -fi
143.29 -
143.30 -source ~/.lemon-bootstrap
143.31 -if [ -f ../../../.lemon-bootstrap ]; then source ../../../.lemon-bootstrap; fi
143.32 -if [ -f ../../.lemon-bootstrap ]; then source ../../.lemon-bootstrap; fi
143.33 -if [ -f ../.lemon-bootstrap ]; then source ../.lemon-bootstrap; fi
143.34 -if [ -f ./.lemon-bootstrap ]; then source ./.lemon-bootstrap; fi
143.35 -
143.36 -
143.37 -function augment_config() {
143.38 - if [ "x${!1}" == "x" ]; then
143.39 - eval $1=$2
143.40 - echo Add "'$1'" to '~/.lemon-bootstrap'.
143.41 - echo >>~/.lemon-bootstrap
143.42 - echo $3 >>~/.lemon-bootstrap
143.43 - echo $1=$2 >>~/.lemon-bootstrap
143.44 - fi
143.45 -}
143.46 -
143.47 -augment_config LEMON_INSTALL_PREFIX /usr/local \
143.48 - "# LEMON installation prefix"
143.49 -
143.50 -augment_config GLPK_PREFIX /usr/local/ \
143.51 - "# GLPK installation root prefix"
143.52 -
143.53 -augment_config COIN_OR_PREFIX /usr/local/coin-or \
143.54 - "# COIN-OR installation root prefix (used for CLP/CBC)"
143.55 -
143.56 -augment_config SOPLEX_PREFIX /usr/local/soplex \
143.57 - "# Soplex build prefix"
143.58 -
143.59 -
143.60 -function ask() {
143.61 -echo -n "$1 [$2]? "
143.62 -read _an
143.63 -if [ "x$_an" == "x" ]; then
143.64 - ret="$2"
143.65 -else
143.66 - ret=$_an
143.67 -fi
143.68 -}
143.69 -
143.70 -function yesorno() {
143.71 - ret='rossz'
143.72 - while [ "$ret" != "y" -a "$ret" != "n" -a "$ret" != "yes" -a "$ret" != "no" ]; do
143.73 - ask "$1" "$2"
143.74 - done
143.75 - if [ "$ret" != "y" -a "$ret" != "yes" ]; then
143.76 - return 1
143.77 - else
143.78 - return 0
143.79 - fi
143.80 -}
143.81 -
143.82 -if yesorno "External build" "n"
143.83 -then
143.84 - CONFIGURE_PATH=".."
143.85 -else
143.86 - CONFIGURE_PATH="."
143.87 - if yesorno "Autoreconf" "y"
143.88 - then
143.89 - AUTORE=yes
143.90 - else
143.91 - AUTORE=no
143.92 - fi
143.93 -fi
143.94 -
143.95 -if yesorno "Optimize" "n"
143.96 -then
143.97 - opt_flags=' -O2'
143.98 -else
143.99 - opt_flags=''
143.100 -fi
143.101 -
143.102 -if yesorno "Stop on warning" "y"
143.103 -then
143.104 - werror_flags=' -Werror'
143.105 -else
143.106 - werror_flags=''
143.107 -fi
143.108 -
143.109 -cxx_flags="CXXFLAGS=-ggdb$opt_flags$werror_flags"
143.110 -
143.111 -if yesorno "Check with valgrind" "n"
143.112 -then
143.113 - valgrind_flags=' --enable-valgrind'
143.114 -else
143.115 - valgrind_flags=''
143.116 -fi
143.117 -
143.118 -if [ -f ${GLPK_PREFIX}/include/glpk.h ]; then
143.119 - if yesorno "Use GLPK" "y"
143.120 - then
143.121 - glpk_flag="--with-glpk=$GLPK_PREFIX"
143.122 - else
143.123 - glpk_flag="--without-glpk"
143.124 - fi
143.125 -else
143.126 - glpk_flag="--without-glpk"
143.127 -fi
143.128 -
143.129 -if [ -f ${COIN_OR_PREFIX}/include/coin/config_coinutils.h ]; then
143.130 - if yesorno "Use COIN-OR (CBC/CLP)" "n"
143.131 - then
143.132 - coin_flag="--with-coin=$COIN_OR_PREFIX"
143.133 - else
143.134 - coin_flag="--without-coin"
143.135 - fi
143.136 -else
143.137 - coin_flag="--without-coin"
143.138 -fi
143.139 -
143.140 -if [ -f ${SOPLEX_PREFIX}/src/soplex.h ]; then
143.141 - if yesorno "Use Soplex" "n"
143.142 - then
143.143 - soplex_flag="--with-soplex=$SOPLEX_PREFIX"
143.144 - else
143.145 - soplex_flag="--without-soplex"
143.146 - fi
143.147 -else
143.148 - soplex_flag="--without-soplex"
143.149 -fi
143.150 -
143.151 -if [ "x$AUTORE" == "xyes" ]; then
143.152 - autoreconf -vif;
143.153 -fi
143.154 -${CONFIGURE_PATH}/configure --prefix=$LEMON_INSTALL_PREFIX \
143.155 -$valgrind_flags \
143.156 -"$cxx_flags" \
143.157 -$glpk_flag \
143.158 -$coin_flag \
143.159 -$soplex_flag \
143.160 -$*
144.1 --- a/scripts/chg-len.py Mon Jul 16 16:21:40 2018 +0200
144.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
144.3 @@ -1,46 +0,0 @@
144.4 -#! /usr/bin/env python
144.5 -#
144.6 -# This file is a part of LEMON, a generic C++ optimization library.
144.7 -#
144.8 -# Copyright (C) 2003-2009
144.9 -# Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
144.10 -# (Egervary Research Group on Combinatorial Optimization, EGRES).
144.11 -#
144.12 -# Permission to use, modify and distribute this software is granted
144.13 -# provided that this copyright notice appears in all copies. For
144.14 -# precise terms see the accompanying LICENSE file.
144.15 -#
144.16 -# This software is provided "AS IS" with no warranty of any kind,
144.17 -# express or implied, and with no claim as to its suitability for any
144.18 -# purpose.
144.19 -
144.20 -import sys
144.21 -
144.22 -from mercurial import ui, hg
144.23 -from mercurial import util
144.24 -
144.25 -util.rcpath = lambda : []
144.26 -
144.27 -if len(sys.argv)>1 and sys.argv[1] in ["-h","--help"]:
144.28 - print """
144.29 -This utility just prints the length of the longest path
144.30 -in the revision graph from revison 0 to the current one.
144.31 -"""
144.32 - exit(0)
144.33 -
144.34 -u = ui.ui()
144.35 -r = hg.repository(u, ".")
144.36 -N = r.changectx(".").rev()
144.37 -lengths=[0]*(N+1)
144.38 -for i in range(N+1):
144.39 - p=r.changectx(i).parents()
144.40 - if p[0]:
144.41 - p0=lengths[p[0].rev()]
144.42 - else:
144.43 - p0=-1
144.44 - if len(p)>1 and p[1]:
144.45 - p1=lengths[p[1].rev()]
144.46 - else:
144.47 - p1=-1
144.48 - lengths[i]=max(p0,p1)+1
144.49 -print lengths[N]
145.1 --- a/scripts/mk-release.sh Mon Jul 16 16:21:40 2018 +0200
145.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
145.3 @@ -1,49 +0,0 @@
145.4 -#!/bin/bash
145.5 -#
145.6 -# This file is a part of LEMON, a generic C++ optimization library.
145.7 -#
145.8 -# Copyright (C) 2003-2009
145.9 -# Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
145.10 -# (Egervary Research Group on Combinatorial Optimization, EGRES).
145.11 -#
145.12 -# Permission to use, modify and distribute this software is granted
145.13 -# provided that this copyright notice appears in all copies. For
145.14 -# precise terms see the accompanying LICENSE file.
145.15 -#
145.16 -# This software is provided "AS IS" with no warranty of any kind,
145.17 -# express or implied, and with no claim as to its suitability for any
145.18 -# purpose.
145.19 -
145.20 -set -e
145.21 -
145.22 -if [ $# = 0 ]; then
145.23 - echo "Usage: $0 release-id"
145.24 - exit 1
145.25 -else
145.26 - export LEMON_VERSION=$1
145.27 -fi
145.28 -
145.29 -echo '*****************************************************************'
145.30 -echo ' Start making release tarballs for version '${LEMON_VERSION}
145.31 -echo '*****************************************************************'
145.32 -
145.33 -autoreconf -vif
145.34 -./configure
145.35 -
145.36 -make
145.37 -make html
145.38 -make distcheck
145.39 -tar xf lemon-${LEMON_VERSION}.tar.gz
145.40 -zip -r lemon-${LEMON_VERSION}.zip lemon-${LEMON_VERSION}
145.41 -mv lemon-${LEMON_VERSION}/doc/html lemon-doc-${LEMON_VERSION}
145.42 -tar czf lemon-doc-${LEMON_VERSION}.tar.gz lemon-doc-${LEMON_VERSION}
145.43 -zip -r lemon-doc-${LEMON_VERSION}.zip lemon-doc-${LEMON_VERSION}
145.44 -tar czf lemon-nodoc-${LEMON_VERSION}.tar.gz lemon-${LEMON_VERSION}
145.45 -zip -r lemon-nodoc-${LEMON_VERSION}.zip lemon-${LEMON_VERSION}
145.46 -hg tag -m 'LEMON '${LEMON_VERSION}' released ('$(hg par --template="{node|short}")' tagged as r'${LEMON_VERSION}')' r${LEMON_VERSION}
145.47 -
145.48 -rm -rf lemon-${LEMON_VERSION} lemon-doc-${LEMON_VERSION}
145.49 -
145.50 -echo '*****************************************************************'
145.51 -echo ' Release '${LEMON_VERSION}' has been created'
145.52 -echo '*****************************************************************'
146.1 --- a/test/CMakeLists.txt Mon Jul 16 16:21:40 2018 +0200
146.2 +++ b/test/CMakeLists.txt Wed Oct 17 19:14:07 2018 +0200
146.3 @@ -16,6 +16,7 @@
146.4 arc_look_up_test
146.5 bellman_ford_test
146.6 bfs_test
146.7 + bpgraph_test
146.8 circulation_test
146.9 connectivity_test
146.10 counter_test
146.11 @@ -34,19 +35,24 @@
146.12 hao_orlin_test
146.13 heap_test
146.14 kruskal_test
146.15 + lgf_reader_writer_test
146.16 lgf_test
146.17 maps_test
146.18 matching_test
146.19 + max_cardinality_search_test
146.20 + max_clique_test
146.21 + max_flow_test
146.22 min_cost_arborescence_test
146.23 min_cost_flow_test
146.24 min_mean_cycle_test
146.25 + nagamochi_ibaraki_test
146.26 path_test
146.27 planarity_test
146.28 - preflow_test
146.29 radix_sort_test
146.30 random_test
146.31 suurballe_test
146.32 time_measure_test
146.33 + tsp_test
146.34 unionfind_test
146.35 )
146.36
146.37 @@ -63,11 +69,14 @@
146.38 SET(LP_TEST_LIBS ${LP_TEST_LIBS} ${GLPK_LIBRARIES})
146.39 ENDIF()
146.40 IF(LEMON_HAVE_CPLEX)
146.41 - SET(LP_TEST_LIBS ${LP_TEST_LIBS} ${CPLEX_LIBRARIES})
146.42 + SET(LP_TEST_LIBS ${LP_TEST_LIBS} ${ILOG_LIBRARIES})
146.43 ENDIF()
146.44 IF(LEMON_HAVE_CLP)
146.45 SET(LP_TEST_LIBS ${LP_TEST_LIBS} ${COIN_CLP_LIBRARIES})
146.46 ENDIF()
146.47 + IF(LEMON_HAVE_SOPLEX)
146.48 + SET(LP_TEST_LIBS ${LP_TEST_LIBS} ${SOPLEX_LIBRARIES})
146.49 + ENDIF()
146.50
146.51 TARGET_LINK_LIBRARIES(lp_test ${LP_TEST_LIBS})
146.52 ADD_TEST(lp_test lp_test)
146.53 @@ -87,7 +96,7 @@
146.54 GET_TARGET_PROPERTY(TARGET_LOC lp_test LOCATION)
146.55 GET_FILENAME_COMPONENT(TARGET_PATH ${TARGET_LOC} PATH)
146.56 ADD_CUSTOM_COMMAND(TARGET lp_test POST_BUILD
146.57 - COMMAND ${CMAKE_COMMAND} -E copy ${CPLEX_BIN_DIR}/cplex.dll ${TARGET_PATH}
146.58 + COMMAND ${CMAKE_COMMAND} -E copy ${ILOG_CPLEX_DLL} ${TARGET_PATH}
146.59 )
146.60 ENDIF()
146.61 ENDIF()
146.62 @@ -105,7 +114,7 @@
146.63 SET(MIP_TEST_LIBS ${MIP_TEST_LIBS} ${GLPK_LIBRARIES})
146.64 ENDIF()
146.65 IF(LEMON_HAVE_CPLEX)
146.66 - SET(MIP_TEST_LIBS ${MIP_TEST_LIBS} ${CPLEX_LIBRARIES})
146.67 + SET(MIP_TEST_LIBS ${MIP_TEST_LIBS} ${ILOG_LIBRARIES})
146.68 ENDIF()
146.69 IF(LEMON_HAVE_CBC)
146.70 SET(MIP_TEST_LIBS ${MIP_TEST_LIBS} ${COIN_CBC_LIBRARIES})
146.71 @@ -129,7 +138,7 @@
146.72 GET_TARGET_PROPERTY(TARGET_LOC mip_test LOCATION)
146.73 GET_FILENAME_COMPONENT(TARGET_PATH ${TARGET_LOC} PATH)
146.74 ADD_CUSTOM_COMMAND(TARGET mip_test POST_BUILD
146.75 - COMMAND ${CMAKE_COMMAND} -E copy ${CPLEX_BIN_DIR}/cplex.dll ${TARGET_PATH}
146.76 + COMMAND ${CMAKE_COMMAND} -E copy ${ILOG_CPLEX_DLL} ${TARGET_PATH}
146.77 )
146.78 ENDIF()
146.79 ENDIF()
147.1 --- a/test/Makefile.am Mon Jul 16 16:21:40 2018 +0200
147.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
147.3 @@ -1,101 +0,0 @@
147.4 -if USE_VALGRIND
147.5 -TESTS_ENVIRONMENT=$(top_srcdir)/scripts/valgrind-wrapper.sh
147.6 -endif
147.7 -
147.8 -EXTRA_DIST += \
147.9 - test/CMakeLists.txt
147.10 -
147.11 -noinst_HEADERS += \
147.12 - test/graph_test.h \
147.13 - test/test_tools.h
147.14 -
147.15 -check_PROGRAMS += \
147.16 - test/adaptors_test \
147.17 - test/bellman_ford_test \
147.18 - test/bfs_test \
147.19 - test/circulation_test \
147.20 - test/connectivity_test \
147.21 - test/counter_test \
147.22 - test/dfs_test \
147.23 - test/digraph_test \
147.24 - test/dijkstra_test \
147.25 - test/dim_test \
147.26 - test/edge_set_test \
147.27 - test/error_test \
147.28 - test/euler_test \
147.29 - test/fractional_matching_test \
147.30 - test/gomory_hu_test \
147.31 - test/graph_copy_test \
147.32 - test/graph_test \
147.33 - test/graph_utils_test \
147.34 - test/hao_orlin_test \
147.35 - test/heap_test \
147.36 - test/kruskal_test \
147.37 - test/lgf_test \
147.38 - test/maps_test \
147.39 - test/matching_test \
147.40 - test/min_cost_arborescence_test \
147.41 - test/min_cost_flow_test \
147.42 - test/min_mean_cycle_test \
147.43 - test/path_test \
147.44 - test/planarity_test \
147.45 - test/preflow_test \
147.46 - test/radix_sort_test \
147.47 - test/random_test \
147.48 - test/suurballe_test \
147.49 - test/test_tools_fail \
147.50 - test/test_tools_pass \
147.51 - test/time_measure_test \
147.52 - test/unionfind_test
147.53 -
147.54 -test_test_tools_pass_DEPENDENCIES = demo
147.55 -
147.56 -if HAVE_LP
147.57 -check_PROGRAMS += test/lp_test
147.58 -endif HAVE_LP
147.59 -if HAVE_MIP
147.60 -check_PROGRAMS += test/mip_test
147.61 -endif HAVE_MIP
147.62 -
147.63 -TESTS += $(check_PROGRAMS)
147.64 -XFAIL_TESTS += test/test_tools_fail$(EXEEXT)
147.65 -
147.66 -test_adaptors_test_SOURCES = test/adaptors_test.cc
147.67 -test_bellman_ford_test_SOURCES = test/bellman_ford_test.cc
147.68 -test_bfs_test_SOURCES = test/bfs_test.cc
147.69 -test_circulation_test_SOURCES = test/circulation_test.cc
147.70 -test_counter_test_SOURCES = test/counter_test.cc
147.71 -test_connectivity_test_SOURCES = test/connectivity_test.cc
147.72 -test_dfs_test_SOURCES = test/dfs_test.cc
147.73 -test_digraph_test_SOURCES = test/digraph_test.cc
147.74 -test_dijkstra_test_SOURCES = test/dijkstra_test.cc
147.75 -test_dim_test_SOURCES = test/dim_test.cc
147.76 -test_edge_set_test_SOURCES = test/edge_set_test.cc
147.77 -test_error_test_SOURCES = test/error_test.cc
147.78 -test_euler_test_SOURCES = test/euler_test.cc
147.79 -test_fractional_matching_test_SOURCES = test/fractional_matching_test.cc
147.80 -test_gomory_hu_test_SOURCES = test/gomory_hu_test.cc
147.81 -test_graph_copy_test_SOURCES = test/graph_copy_test.cc
147.82 -test_graph_test_SOURCES = test/graph_test.cc
147.83 -test_graph_utils_test_SOURCES = test/graph_utils_test.cc
147.84 -test_heap_test_SOURCES = test/heap_test.cc
147.85 -test_kruskal_test_SOURCES = test/kruskal_test.cc
147.86 -test_hao_orlin_test_SOURCES = test/hao_orlin_test.cc
147.87 -test_lgf_test_SOURCES = test/lgf_test.cc
147.88 -test_lp_test_SOURCES = test/lp_test.cc
147.89 -test_maps_test_SOURCES = test/maps_test.cc
147.90 -test_mip_test_SOURCES = test/mip_test.cc
147.91 -test_matching_test_SOURCES = test/matching_test.cc
147.92 -test_min_cost_arborescence_test_SOURCES = test/min_cost_arborescence_test.cc
147.93 -test_min_cost_flow_test_SOURCES = test/min_cost_flow_test.cc
147.94 -test_min_mean_cycle_test_SOURCES = test/min_mean_cycle_test.cc
147.95 -test_path_test_SOURCES = test/path_test.cc
147.96 -test_planarity_test_SOURCES = test/planarity_test.cc
147.97 -test_preflow_test_SOURCES = test/preflow_test.cc
147.98 -test_radix_sort_test_SOURCES = test/radix_sort_test.cc
147.99 -test_suurballe_test_SOURCES = test/suurballe_test.cc
147.100 -test_random_test_SOURCES = test/random_test.cc
147.101 -test_test_tools_fail_SOURCES = test/test_tools_fail.cc
147.102 -test_test_tools_pass_SOURCES = test/test_tools_pass.cc
147.103 -test_time_measure_test_SOURCES = test/time_measure_test.cc
147.104 -test_unionfind_test_SOURCES = test/unionfind_test.cc
148.1 --- a/test/adaptors_test.cc Mon Jul 16 16:21:40 2018 +0200
148.2 +++ b/test/adaptors_test.cc Wed Oct 17 19:14:07 2018 +0200
148.3 @@ -2,7 +2,7 @@
148.4 *
148.5 * This file is a part of LEMON, a generic C++ optimization library.
148.6 *
148.7 - * Copyright (C) 2003-2009
148.8 + * Copyright (C) 2003-2013
148.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
148.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
148.11 *
148.12 @@ -65,7 +65,7 @@
148.13 Digraph::Arc a1 = digraph.addArc(n1, n2);
148.14 Digraph::Arc a2 = digraph.addArc(n1, n3);
148.15 Digraph::Arc a3 = digraph.addArc(n2, n3);
148.16 - ignore_unused_variable_warning(a3);
148.17 + ::lemon::ignore_unused_variable_warning(a3);
148.18
148.19 // Check the adaptor
148.20 checkGraphNodeList(adaptor, 3);
148.21 @@ -100,7 +100,7 @@
148.22 Adaptor::Arc a6 = adaptor.addArc(n2, n4);
148.23 Adaptor::Arc a7 = adaptor.addArc(n1, n4);
148.24 Adaptor::Arc a8 = adaptor.addArc(n1, n2);
148.25 - ignore_unused_variable_warning(a6,a7,a8);
148.26 + ::lemon::ignore_unused_variable_warning(a6,a7,a8);
148.27
148.28 adaptor.erase(a1);
148.29 adaptor.erase(n3);
148.30 @@ -760,7 +760,7 @@
148.31 Digraph::Arc a1 = digraph.addArc(n1, n2);
148.32 Digraph::Arc a2 = digraph.addArc(n1, n3);
148.33 Digraph::Arc a3 = digraph.addArc(n2, n3);
148.34 - ignore_unused_variable_warning(a1,a2,a3);
148.35 + ::lemon::ignore_unused_variable_warning(a1,a2,a3);
148.36
148.37 checkGraphNodeList(adaptor, 6);
148.38 checkGraphArcList(adaptor, 6);
149.1 --- a/test/arc_look_up_test.cc Mon Jul 16 16:21:40 2018 +0200
149.2 +++ b/test/arc_look_up_test.cc Wed Oct 17 19:14:07 2018 +0200
149.3 @@ -2,7 +2,7 @@
149.4 *
149.5 * This file is a part of LEMON, a generic C++ optimization library.
149.6 *
149.7 - * Copyright (C) 2003-2009
149.8 + * Copyright (C) 2003-2013
149.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
149.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
149.11 *
149.12 @@ -24,7 +24,6 @@
149.13
149.14 using namespace lemon;
149.15
149.16 -const int lgfn = 4;
149.17 const std::string lgf =
149.18 "@nodes\n"
149.19 "label\n"
149.20 @@ -68,17 +67,17 @@
149.21 ListDigraph graph;
149.22 std::istringstream lgfs(lgf);
149.23 DigraphReader<ListDigraph>(graph, lgfs).run();
149.24 -
149.25 +
149.26 AllArcLookUp<ListDigraph> lookup(graph);
149.27 -
149.28 +
149.29 int numArcs = countArcs(graph);
149.30 -
149.31 +
149.32 int arcCnt = 0;
149.33 for(ListDigraph::NodeIt n1(graph); n1 != INVALID; ++n1)
149.34 for(ListDigraph::NodeIt n2(graph); n2 != INVALID; ++n2)
149.35 for(ListDigraph::Arc a = lookup(n1, n2); a != INVALID;
149.36 - a = lookup(n1, n2, a))
149.37 - ++arcCnt;
149.38 + a = lookup(n1, n2, a))
149.39 + ++arcCnt;
149.40 check(arcCnt==numArcs, "Wrong total number of arcs");
149.41
149.42 return 0;
150.1 --- a/test/bellman_ford_test.cc Mon Jul 16 16:21:40 2018 +0200
150.2 +++ b/test/bellman_ford_test.cc Wed Oct 17 19:14:07 2018 +0200
150.3 @@ -2,7 +2,7 @@
150.4 *
150.5 * This file is a part of LEMON, a generic C++ optimization library.
150.6 *
150.7 - * Copyright (C) 2003-2010
150.8 + * Copyright (C) 2003-2013
150.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
150.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
150.11 *
150.12 @@ -65,8 +65,10 @@
150.13 Node s, t, n;
150.14 Arc e;
150.15 Value l;
150.16 + ::lemon::ignore_unused_variable_warning(l);
150.17 int k=3;
150.18 bool b;
150.19 + ::lemon::ignore_unused_variable_warning(b);
150.20 BF::DistMap d(gr);
150.21 BF::PredMap p(gr);
150.22 LengthMap length;
150.23 @@ -147,6 +149,8 @@
150.24
150.25 Digraph g;
150.26 bool b;
150.27 + ::lemon::ignore_unused_variable_warning(b);
150.28 +
150.29 bellmanFord(g,LengthMap()).run(Node());
150.30 b = bellmanFord(g,LengthMap()).run(Node(),Node());
150.31 bellmanFord(g,LengthMap())
150.32 @@ -190,7 +194,7 @@
150.33 check(pathTarget(gr, p) == t, "path() found a wrong path.");
150.34
150.35 ListPath<Digraph> path;
150.36 - Value dist;
150.37 + Value dist = 0;
150.38 bool reached = bellmanFord(gr,length).path(path).dist(dist).run(s,t);
150.39
150.40 check(reached && dist == -1, "Bellman-Ford found a wrong path.");
151.1 --- a/test/bfs_test.cc Mon Jul 16 16:21:40 2018 +0200
151.2 +++ b/test/bfs_test.cc Wed Oct 17 19:14:07 2018 +0200
151.3 @@ -2,7 +2,7 @@
151.4 *
151.5 * This file is a part of LEMON, a generic C++ optimization library.
151.6 *
151.7 - * Copyright (C) 2003-2010
151.8 + * Copyright (C) 2003-2013
151.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
151.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
151.11 *
151.12 @@ -61,6 +61,7 @@
151.13 Node s, t, n;
151.14 Arc e;
151.15 int l, i;
151.16 + ::lemon::ignore_unused_variable_warning(l,i);
151.17 bool b;
151.18 BType::DistMap d(G);
151.19 BType::PredMap p(G);
151.20 @@ -150,6 +151,8 @@
151.21
151.22 Digraph g;
151.23 bool b;
151.24 + ::lemon::ignore_unused_variable_warning(b);
151.25 +
151.26 bfs(g).run(Node());
151.27 b=bfs(g).run(Node(),Node());
151.28 bfs(g).run();
152.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
152.2 +++ b/test/bpgraph_test.cc Wed Oct 17 19:14:07 2018 +0200
152.3 @@ -0,0 +1,456 @@
152.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
152.5 + *
152.6 + * This file is a part of LEMON, a generic C++ optimization library.
152.7 + *
152.8 + * Copyright (C) 2003-2013
152.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
152.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
152.11 + *
152.12 + * Permission to use, modify and distribute this software is granted
152.13 + * provided that this copyright notice appears in all copies. For
152.14 + * precise terms see the accompanying LICENSE file.
152.15 + *
152.16 + * This software is provided "AS IS" with no warranty of any kind,
152.17 + * express or implied, and with no claim as to its suitability for any
152.18 + * purpose.
152.19 + *
152.20 + */
152.21 +
152.22 +#include <lemon/concepts/bpgraph.h>
152.23 +#include <lemon/list_graph.h>
152.24 +#include <lemon/smart_graph.h>
152.25 +#include <lemon/full_graph.h>
152.26 +
152.27 +#include "test_tools.h"
152.28 +#include "graph_test.h"
152.29 +
152.30 +using namespace lemon;
152.31 +using namespace lemon::concepts;
152.32 +
152.33 +template <class BpGraph>
152.34 +void checkBpGraphBuild() {
152.35 + TEMPLATE_BPGRAPH_TYPEDEFS(BpGraph);
152.36 +
152.37 + BpGraph G;
152.38 + checkGraphNodeList(G, 0);
152.39 + checkGraphRedNodeList(G, 0);
152.40 + checkGraphBlueNodeList(G, 0);
152.41 + checkGraphEdgeList(G, 0);
152.42 + checkGraphArcList(G, 0);
152.43 +
152.44 + G.reserveNode(3);
152.45 + G.reserveEdge(3);
152.46 +
152.47 + RedNode
152.48 + rn1 = G.addRedNode();
152.49 + checkGraphNodeList(G, 1);
152.50 + checkGraphRedNodeList(G, 1);
152.51 + checkGraphBlueNodeList(G, 0);
152.52 + checkGraphEdgeList(G, 0);
152.53 + checkGraphArcList(G, 0);
152.54 +
152.55 + BlueNode
152.56 + bn1 = G.addBlueNode(),
152.57 + bn2 = G.addBlueNode();
152.58 + checkGraphNodeList(G, 3);
152.59 + checkGraphRedNodeList(G, 1);
152.60 + checkGraphBlueNodeList(G, 2);
152.61 + checkGraphEdgeList(G, 0);
152.62 + checkGraphArcList(G, 0);
152.63 +
152.64 + Edge e1 = G.addEdge(rn1, bn2);
152.65 + check(G.redNode(e1) == rn1 && G.blueNode(e1) == bn2, "Wrong edge");
152.66 + check(G.u(e1) == rn1 && G.v(e1) == bn2, "Wrong edge");
152.67 +
152.68 + checkGraphNodeList(G, 3);
152.69 + checkGraphRedNodeList(G, 1);
152.70 + checkGraphBlueNodeList(G, 2);
152.71 + checkGraphEdgeList(G, 1);
152.72 + checkGraphArcList(G, 2);
152.73 +
152.74 + checkGraphIncEdgeArcLists(G, rn1, 1);
152.75 + checkGraphIncEdgeArcLists(G, bn1, 0);
152.76 + checkGraphIncEdgeArcLists(G, bn2, 1);
152.77 +
152.78 + checkGraphConEdgeList(G, 1);
152.79 + checkGraphConArcList(G, 2);
152.80 +
152.81 + Edge
152.82 + e2 = G.addEdge(bn1, rn1),
152.83 + e3 = G.addEdge(rn1, bn2);
152.84 + ::lemon::ignore_unused_variable_warning(e2,e3);
152.85 +
152.86 + checkGraphNodeList(G, 3);
152.87 + checkGraphRedNodeList(G, 1);
152.88 + checkGraphBlueNodeList(G, 2);
152.89 + checkGraphEdgeList(G, 3);
152.90 + checkGraphArcList(G, 6);
152.91 +
152.92 + checkGraphIncEdgeArcLists(G, rn1, 3);
152.93 + checkGraphIncEdgeArcLists(G, bn1, 1);
152.94 + checkGraphIncEdgeArcLists(G, bn2, 2);
152.95 +
152.96 + checkGraphConEdgeList(G, 3);
152.97 + checkGraphConArcList(G, 6);
152.98 +
152.99 + checkArcDirections(G);
152.100 +
152.101 + checkNodeIds(G);
152.102 + checkRedNodeIds(G);
152.103 + checkBlueNodeIds(G);
152.104 + checkArcIds(G);
152.105 + checkEdgeIds(G);
152.106 +
152.107 + checkGraphNodeMap(G);
152.108 + checkGraphRedNodeMap(G);
152.109 + checkGraphBlueNodeMap(G);
152.110 + checkGraphArcMap(G);
152.111 + checkGraphEdgeMap(G);
152.112 +}
152.113 +
152.114 +template <class BpGraph>
152.115 +void checkBpGraphErase() {
152.116 + TEMPLATE_BPGRAPH_TYPEDEFS(BpGraph);
152.117 +
152.118 + BpGraph G;
152.119 + RedNode
152.120 + n1 = G.addRedNode(), n4 = G.addRedNode();
152.121 + BlueNode
152.122 + n2 = G.addBlueNode(), n3 = G.addBlueNode();
152.123 + Edge
152.124 + e1 = G.addEdge(n1, n2), e2 = G.addEdge(n1, n3),
152.125 + e3 = G.addEdge(n4, n2), e4 = G.addEdge(n4, n3);
152.126 + ::lemon::ignore_unused_variable_warning(e1,e3,e4);
152.127 +
152.128 + // Check edge deletion
152.129 + G.erase(e2);
152.130 +
152.131 + checkGraphNodeList(G, 4);
152.132 + checkGraphRedNodeList(G, 2);
152.133 + checkGraphBlueNodeList(G, 2);
152.134 + checkGraphEdgeList(G, 3);
152.135 + checkGraphArcList(G, 6);
152.136 +
152.137 + checkGraphIncEdgeArcLists(G, n1, 1);
152.138 + checkGraphIncEdgeArcLists(G, n2, 2);
152.139 + checkGraphIncEdgeArcLists(G, n3, 1);
152.140 + checkGraphIncEdgeArcLists(G, n4, 2);
152.141 +
152.142 + checkGraphConEdgeList(G, 3);
152.143 + checkGraphConArcList(G, 6);
152.144 +
152.145 + // Check node deletion
152.146 + G.erase(n3);
152.147 +
152.148 + checkGraphNodeList(G, 3);
152.149 + checkGraphRedNodeList(G, 2);
152.150 + checkGraphBlueNodeList(G, 1);
152.151 + checkGraphEdgeList(G, 2);
152.152 + checkGraphArcList(G, 4);
152.153 +
152.154 + checkGraphIncEdgeArcLists(G, n1, 1);
152.155 + checkGraphIncEdgeArcLists(G, n2, 2);
152.156 + checkGraphIncEdgeArcLists(G, n4, 1);
152.157 +
152.158 + checkGraphConEdgeList(G, 2);
152.159 + checkGraphConArcList(G, 4);
152.160 +
152.161 +}
152.162 +
152.163 +template <class BpGraph>
152.164 +void checkBpGraphAlter() {
152.165 + TEMPLATE_BPGRAPH_TYPEDEFS(BpGraph);
152.166 +
152.167 + BpGraph G;
152.168 + RedNode
152.169 + n1 = G.addRedNode(), n4 = G.addRedNode();
152.170 + BlueNode
152.171 + n2 = G.addBlueNode(), n3 = G.addBlueNode();
152.172 + Edge
152.173 + e1 = G.addEdge(n1, n2), e2 = G.addEdge(n1, n3),
152.174 + e3 = G.addEdge(n4, n2), e4 = G.addEdge(n4, n3);
152.175 + ::lemon::ignore_unused_variable_warning(e1,e3,e4);
152.176 +
152.177 + G.changeRed(e2, n4);
152.178 + check(G.redNode(e2) == n4, "Wrong red node");
152.179 + check(G.blueNode(e2) == n3, "Wrong blue node");
152.180 +
152.181 + checkGraphNodeList(G, 4);
152.182 + checkGraphRedNodeList(G, 2);
152.183 + checkGraphBlueNodeList(G, 2);
152.184 + checkGraphEdgeList(G, 4);
152.185 + checkGraphArcList(G, 8);
152.186 +
152.187 + checkGraphIncEdgeArcLists(G, n1, 1);
152.188 + checkGraphIncEdgeArcLists(G, n2, 2);
152.189 + checkGraphIncEdgeArcLists(G, n3, 2);
152.190 + checkGraphIncEdgeArcLists(G, n4, 3);
152.191 +
152.192 + checkGraphConEdgeList(G, 4);
152.193 + checkGraphConArcList(G, 8);
152.194 +
152.195 + G.changeBlue(e2, n2);
152.196 + check(G.redNode(e2) == n4, "Wrong red node");
152.197 + check(G.blueNode(e2) == n2, "Wrong blue node");
152.198 +
152.199 + checkGraphNodeList(G, 4);
152.200 + checkGraphRedNodeList(G, 2);
152.201 + checkGraphBlueNodeList(G, 2);
152.202 + checkGraphEdgeList(G, 4);
152.203 + checkGraphArcList(G, 8);
152.204 +
152.205 + checkGraphIncEdgeArcLists(G, n1, 1);
152.206 + checkGraphIncEdgeArcLists(G, n2, 3);
152.207 + checkGraphIncEdgeArcLists(G, n3, 1);
152.208 + checkGraphIncEdgeArcLists(G, n4, 3);
152.209 +
152.210 + checkGraphConEdgeList(G, 4);
152.211 + checkGraphConArcList(G, 8);
152.212 +}
152.213 +
152.214 +
152.215 +template <class BpGraph>
152.216 +void checkBpGraphSnapshot() {
152.217 + TEMPLATE_BPGRAPH_TYPEDEFS(BpGraph);
152.218 +
152.219 + BpGraph G;
152.220 + RedNode
152.221 + n1 = G.addRedNode();
152.222 + BlueNode
152.223 + n2 = G.addBlueNode(),
152.224 + n3 = G.addBlueNode();
152.225 + Edge
152.226 + e1 = G.addEdge(n1, n2),
152.227 + e2 = G.addEdge(n1, n3);
152.228 + ::lemon::ignore_unused_variable_warning(e1,e2);
152.229 +
152.230 + checkGraphNodeList(G, 3);
152.231 + checkGraphRedNodeList(G, 1);
152.232 + checkGraphBlueNodeList(G, 2);
152.233 + checkGraphEdgeList(G, 2);
152.234 + checkGraphArcList(G, 4);
152.235 +
152.236 + typename BpGraph::Snapshot snapshot(G);
152.237 +
152.238 + RedNode n4 = G.addRedNode();
152.239 + G.addEdge(n4, n2);
152.240 + G.addEdge(n4, n3);
152.241 +
152.242 + checkGraphNodeList(G, 4);
152.243 + checkGraphRedNodeList(G, 2);
152.244 + checkGraphBlueNodeList(G, 2);
152.245 + checkGraphEdgeList(G, 4);
152.246 + checkGraphArcList(G, 8);
152.247 +
152.248 + snapshot.restore();
152.249 +
152.250 + checkGraphNodeList(G, 3);
152.251 + checkGraphRedNodeList(G, 1);
152.252 + checkGraphBlueNodeList(G, 2);
152.253 + checkGraphEdgeList(G, 2);
152.254 + checkGraphArcList(G, 4);
152.255 +
152.256 + checkGraphIncEdgeArcLists(G, n1, 2);
152.257 + checkGraphIncEdgeArcLists(G, n2, 1);
152.258 + checkGraphIncEdgeArcLists(G, n3, 1);
152.259 +
152.260 + checkGraphConEdgeList(G, 2);
152.261 + checkGraphConArcList(G, 4);
152.262 +
152.263 + checkNodeIds(G);
152.264 + checkRedNodeIds(G);
152.265 + checkBlueNodeIds(G);
152.266 + checkArcIds(G);
152.267 + checkEdgeIds(G);
152.268 +
152.269 + checkGraphNodeMap(G);
152.270 + checkGraphRedNodeMap(G);
152.271 + checkGraphBlueNodeMap(G);
152.272 + checkGraphArcMap(G);
152.273 + checkGraphEdgeMap(G);
152.274 +
152.275 + G.addRedNode();
152.276 + snapshot.save(G);
152.277 +
152.278 + G.addEdge(G.addRedNode(), G.addBlueNode());
152.279 +
152.280 + snapshot.restore();
152.281 + snapshot.save(G);
152.282 +
152.283 + checkGraphNodeList(G, 4);
152.284 + checkGraphRedNodeList(G, 2);
152.285 + checkGraphBlueNodeList(G, 2);
152.286 + checkGraphEdgeList(G, 2);
152.287 + checkGraphArcList(G, 4);
152.288 +
152.289 + G.addEdge(G.addRedNode(), G.addBlueNode());
152.290 +
152.291 + snapshot.restore();
152.292 +
152.293 + checkGraphNodeList(G, 4);
152.294 + checkGraphRedNodeList(G, 2);
152.295 + checkGraphBlueNodeList(G, 2);
152.296 + checkGraphEdgeList(G, 2);
152.297 + checkGraphArcList(G, 4);
152.298 +}
152.299 +
152.300 +template <typename BpGraph>
152.301 +void checkBpGraphValidity() {
152.302 + TEMPLATE_BPGRAPH_TYPEDEFS(BpGraph);
152.303 + BpGraph g;
152.304 +
152.305 + RedNode
152.306 + n1 = g.addRedNode();
152.307 + BlueNode
152.308 + n2 = g.addBlueNode(),
152.309 + n3 = g.addBlueNode();
152.310 +
152.311 + Edge
152.312 + e1 = g.addEdge(n1, n2),
152.313 + e2 = g.addEdge(n1, n3);
152.314 + ::lemon::ignore_unused_variable_warning(e2);
152.315 +
152.316 + check(g.valid(n1), "Wrong validity check");
152.317 + check(g.valid(e1), "Wrong validity check");
152.318 + check(g.valid(g.direct(e1, true)), "Wrong validity check");
152.319 +
152.320 + check(!g.valid(g.nodeFromId(-1)), "Wrong validity check");
152.321 + check(!g.valid(g.edgeFromId(-1)), "Wrong validity check");
152.322 + check(!g.valid(g.arcFromId(-1)), "Wrong validity check");
152.323 +}
152.324 +
152.325 +void checkConcepts() {
152.326 + { // Checking graph components
152.327 + checkConcept<BaseBpGraphComponent, BaseBpGraphComponent >();
152.328 +
152.329 + checkConcept<IDableBpGraphComponent<>,
152.330 + IDableBpGraphComponent<> >();
152.331 +
152.332 + checkConcept<IterableBpGraphComponent<>,
152.333 + IterableBpGraphComponent<> >();
152.334 +
152.335 + checkConcept<AlterableBpGraphComponent<>,
152.336 + AlterableBpGraphComponent<> >();
152.337 +
152.338 + checkConcept<MappableBpGraphComponent<>,
152.339 + MappableBpGraphComponent<> >();
152.340 +
152.341 + checkConcept<ExtendableBpGraphComponent<>,
152.342 + ExtendableBpGraphComponent<> >();
152.343 +
152.344 + checkConcept<ErasableBpGraphComponent<>,
152.345 + ErasableBpGraphComponent<> >();
152.346 +
152.347 + checkConcept<ClearableBpGraphComponent<>,
152.348 + ClearableBpGraphComponent<> >();
152.349 +
152.350 + }
152.351 + { // Checking skeleton graph
152.352 + checkConcept<BpGraph, BpGraph>();
152.353 + }
152.354 + { // Checking SmartBpGraph
152.355 + checkConcept<BpGraph, SmartBpGraph>();
152.356 + checkConcept<AlterableBpGraphComponent<>, SmartBpGraph>();
152.357 + checkConcept<ExtendableBpGraphComponent<>, SmartBpGraph>();
152.358 + checkConcept<ClearableBpGraphComponent<>, SmartBpGraph>();
152.359 + }
152.360 +}
152.361 +
152.362 +void checkFullBpGraph(int redNum, int blueNum) {
152.363 + typedef FullBpGraph BpGraph;
152.364 + BPGRAPH_TYPEDEFS(BpGraph);
152.365 +
152.366 + BpGraph G(redNum, blueNum);
152.367 + checkGraphNodeList(G, redNum + blueNum);
152.368 + checkGraphRedNodeList(G, redNum);
152.369 + checkGraphBlueNodeList(G, blueNum);
152.370 + checkGraphEdgeList(G, redNum * blueNum);
152.371 + checkGraphArcList(G, 2 * redNum * blueNum);
152.372 +
152.373 + G.resize(redNum, blueNum);
152.374 + checkGraphNodeList(G, redNum + blueNum);
152.375 + checkGraphRedNodeList(G, redNum);
152.376 + checkGraphBlueNodeList(G, blueNum);
152.377 + checkGraphEdgeList(G, redNum * blueNum);
152.378 + checkGraphArcList(G, 2 * redNum * blueNum);
152.379 +
152.380 + for (RedNodeIt n(G); n != INVALID; ++n) {
152.381 + checkGraphOutArcList(G, n, blueNum);
152.382 + checkGraphInArcList(G, n, blueNum);
152.383 + checkGraphIncEdgeList(G, n, blueNum);
152.384 + }
152.385 +
152.386 + for (BlueNodeIt n(G); n != INVALID; ++n) {
152.387 + checkGraphOutArcList(G, n, redNum);
152.388 + checkGraphInArcList(G, n, redNum);
152.389 + checkGraphIncEdgeList(G, n, redNum);
152.390 + }
152.391 +
152.392 + checkGraphConArcList(G, 2 * redNum * blueNum);
152.393 + checkGraphConEdgeList(G, redNum * blueNum);
152.394 +
152.395 + checkArcDirections(G);
152.396 +
152.397 + checkNodeIds(G);
152.398 + checkRedNodeIds(G);
152.399 + checkBlueNodeIds(G);
152.400 + checkArcIds(G);
152.401 + checkEdgeIds(G);
152.402 +
152.403 + checkGraphNodeMap(G);
152.404 + checkGraphRedNodeMap(G);
152.405 + checkGraphBlueNodeMap(G);
152.406 + checkGraphArcMap(G);
152.407 + checkGraphEdgeMap(G);
152.408 +
152.409 + for (int i = 0; i < G.redNum(); ++i) {
152.410 + check(G.red(G.redNode(i)), "Wrong node");
152.411 + check(G.index(G.redNode(i)) == i, "Wrong index");
152.412 + }
152.413 +
152.414 + for (int i = 0; i < G.blueNum(); ++i) {
152.415 + check(G.blue(G.blueNode(i)), "Wrong node");
152.416 + check(G.index(G.blueNode(i)) == i, "Wrong index");
152.417 + }
152.418 +
152.419 + for (NodeIt u(G); u != INVALID; ++u) {
152.420 + for (NodeIt v(G); v != INVALID; ++v) {
152.421 + Edge e = G.edge(u, v);
152.422 + Arc a = G.arc(u, v);
152.423 + if (G.red(u) == G.red(v)) {
152.424 + check(e == INVALID, "Wrong edge lookup");
152.425 + check(a == INVALID, "Wrong arc lookup");
152.426 + } else {
152.427 + check((G.u(e) == u && G.v(e) == v) ||
152.428 + (G.u(e) == v && G.v(e) == u), "Wrong edge lookup");
152.429 + check(G.source(a) == u && G.target(a) == v, "Wrong arc lookup");
152.430 + }
152.431 + }
152.432 + }
152.433 +
152.434 +}
152.435 +
152.436 +void checkGraphs() {
152.437 + { // Checking ListGraph
152.438 + checkBpGraphBuild<ListBpGraph>();
152.439 + checkBpGraphErase<ListBpGraph>();
152.440 + checkBpGraphAlter<ListBpGraph>();
152.441 + checkBpGraphSnapshot<ListBpGraph>();
152.442 + checkBpGraphValidity<ListBpGraph>();
152.443 + }
152.444 + { // Checking SmartGraph
152.445 + checkBpGraphBuild<SmartBpGraph>();
152.446 + checkBpGraphSnapshot<SmartBpGraph>();
152.447 + checkBpGraphValidity<SmartBpGraph>();
152.448 + }
152.449 + { // Checking FullBpGraph
152.450 + checkFullBpGraph(6, 8);
152.451 + checkFullBpGraph(7, 4);
152.452 + }
152.453 +}
152.454 +
152.455 +int main() {
152.456 + checkConcepts();
152.457 + checkGraphs();
152.458 + return 0;
152.459 +}
153.1 --- a/test/circulation_test.cc Mon Jul 16 16:21:40 2018 +0200
153.2 +++ b/test/circulation_test.cc Wed Oct 17 19:14:07 2018 +0200
153.3 @@ -2,7 +2,7 @@
153.4 *
153.5 * This file is a part of LEMON, a generic C++ optimization library.
153.6 *
153.7 - * Copyright (C) 2003-2010
153.8 + * Copyright (C) 2003-2013
153.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
153.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
153.11 *
153.12 @@ -73,6 +73,7 @@
153.13 BarrierMap bar;
153.14 VType v;
153.15 bool b;
153.16 + ::lemon::ignore_unused_variable_warning(v,b);
153.17
153.18 typedef Circulation<Digraph, CapMap, CapMap, SupplyMap>
153.19 ::SetFlowMap<FlowMap>
153.20 @@ -103,7 +104,7 @@
153.21 b = const_circ_test.barrier(n);
153.22 const_circ_test.barrierMap(bar);
153.23
153.24 - ignore_unused_variable_warning(fm);
153.25 + ::lemon::ignore_unused_variable_warning(fm);
153.26 }
153.27
153.28 template <class G, class LM, class UM, class DM>
154.1 --- a/test/connectivity_test.cc Mon Jul 16 16:21:40 2018 +0200
154.2 +++ b/test/connectivity_test.cc Wed Oct 17 19:14:07 2018 +0200
154.3 @@ -2,7 +2,7 @@
154.4 *
154.5 * This file is a part of LEMON, a generic C++ optimization library.
154.6 *
154.7 - * Copyright (C) 2003-2010
154.8 + * Copyright (C) 2003-2013
154.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
154.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
154.11 *
154.12 @@ -68,7 +68,7 @@
154.13 Digraph::NodeMap<int> order(d);
154.14 Graph g(d);
154.15 Digraph::Node n = d.addNode();
154.16 - ignore_unused_variable_warning(n);
154.17 + ::lemon::ignore_unused_variable_warning(n);
154.18
154.19 check(stronglyConnected(d), "This digraph is strongly connected");
154.20 check(countStronglyConnectedComponents(d) == 1,
154.21 @@ -99,6 +99,23 @@
154.22 }
154.23
154.24 {
154.25 + ListGraph g;
154.26 + ListGraph::NodeMap<bool> map(g);
154.27 +
154.28 + ListGraph::Node n1 = g.addNode();
154.29 + ListGraph::Node n2 = g.addNode();
154.30 +
154.31 + ListGraph::Edge e1 = g.addEdge(n1, n2);
154.32 + ::lemon::ignore_unused_variable_warning(e1);
154.33 + check(biNodeConnected(g), "Graph is bi-node-connected");
154.34 +
154.35 + ListGraph::Node n3 = g.addNode();
154.36 + ::lemon::ignore_unused_variable_warning(n3);
154.37 + check(!biNodeConnected(g), "Graph is not bi-node-connected");
154.38 + }
154.39 +
154.40 +
154.41 + {
154.42 Digraph d;
154.43 Digraph::NodeMap<int> order(d);
154.44 Graph g(d);
154.45 @@ -246,7 +263,7 @@
154.46 Digraph::Node shoe = d.addNode();
154.47 Digraph::Node watch = d.addNode();
154.48 Digraph::Node pants = d.addNode();
154.49 - ignore_unused_variable_warning(watch);
154.50 + ::lemon::ignore_unused_variable_warning(watch);
154.51
154.52 d.addArc(socks, shoe);
154.53 d.addArc(pants, shoe);
155.1 --- a/test/dfs_test.cc Mon Jul 16 16:21:40 2018 +0200
155.2 +++ b/test/dfs_test.cc Wed Oct 17 19:14:07 2018 +0200
155.3 @@ -2,7 +2,7 @@
155.4 *
155.5 * This file is a part of LEMON, a generic C++ optimization library.
155.6 *
155.7 - * Copyright (C) 2003-2010
155.8 + * Copyright (C) 2003-2013
155.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
155.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
155.11 *
155.12 @@ -67,6 +67,8 @@
155.13 Arc e;
155.14 int l, i;
155.15 bool b;
155.16 + ::lemon::ignore_unused_variable_warning(l,i,b);
155.17 +
155.18 DType::DistMap d(G);
155.19 DType::PredMap p(G);
155.20 Path<Digraph> pp;
155.21 @@ -151,6 +153,8 @@
155.22
155.23 Digraph g;
155.24 bool b;
155.25 + ::lemon::ignore_unused_variable_warning(b);
155.26 +
155.27 dfs(g).run(Node());
155.28 b=dfs(g).run(Node(),Node());
155.29 dfs(g).run();
155.30 @@ -219,7 +223,7 @@
155.31 Dfs<Digraph> dfs(G);
155.32 check(dfs.run(s1,t1) && dfs.reached(t1),"Node 3 is reachable from Node 6.");
155.33 }
155.34 -
155.35 +
155.36 {
155.37 NullMap<Node,Arc> myPredMap;
155.38 dfs(G).predMap(myPredMap).run(s);
156.1 --- a/test/digraph_test.cc Mon Jul 16 16:21:40 2018 +0200
156.2 +++ b/test/digraph_test.cc Wed Oct 17 19:14:07 2018 +0200
156.3 @@ -2,7 +2,7 @@
156.4 *
156.5 * This file is a part of LEMON, a generic C++ optimization library.
156.6 *
156.7 - * Copyright (C) 2003-2010
156.8 + * Copyright (C) 2003-2013
156.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
156.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
156.11 *
156.12 @@ -64,7 +64,7 @@
156.13 Arc a2 = G.addArc(n2, n1),
156.14 a3 = G.addArc(n2, n3),
156.15 a4 = G.addArc(n2, n3);
156.16 - ignore_unused_variable_warning(a2,a3,a4);
156.17 + ::lemon::ignore_unused_variable_warning(a2,a3,a4);
156.18
156.19 checkGraphNodeList(G, 3);
156.20 checkGraphArcList(G, 4);
156.21 @@ -93,7 +93,7 @@
156.22 Node n1 = G.addNode(), n2 = G.addNode(), n3 = G.addNode();
156.23 Arc a1 = G.addArc(n1, n2), a2 = G.addArc(n2, n1),
156.24 a3 = G.addArc(n2, n3), a4 = G.addArc(n2, n3);
156.25 - ignore_unused_variable_warning(a1,a2,a3,a4);
156.26 + ::lemon::ignore_unused_variable_warning(a1,a2,a3,a4);
156.27
156.28 Node n4 = G.split(n2);
156.29
156.30 @@ -127,7 +127,7 @@
156.31 Arc a1 = G.addArc(n1, n2), a2 = G.addArc(n4, n1),
156.32 a3 = G.addArc(n4, n3), a4 = G.addArc(n4, n3),
156.33 a5 = G.addArc(n2, n4);
156.34 - ignore_unused_variable_warning(a1,a2,a3,a5);
156.35 + ::lemon::ignore_unused_variable_warning(a1,a2,a3,a5);
156.36
156.37 checkGraphNodeList(G, 4);
156.38 checkGraphArcList(G, 5);
156.39 @@ -207,7 +207,7 @@
156.40 Arc a1 = G.addArc(n1, n2), a2 = G.addArc(n4, n1),
156.41 a3 = G.addArc(n4, n3), a4 = G.addArc(n3, n1),
156.42 a5 = G.addArc(n2, n4);
156.43 - ignore_unused_variable_warning(a2,a3,a4,a5);
156.44 + ::lemon::ignore_unused_variable_warning(a2,a3,a4,a5);
156.45
156.46 // Check arc deletion
156.47 G.erase(a1);
156.48 @@ -255,7 +255,7 @@
156.49 Node n1 = G.addNode(), n2 = G.addNode(), n3 = G.addNode();
156.50 Arc a1 = G.addArc(n1, n2), a2 = G.addArc(n2, n1),
156.51 a3 = G.addArc(n2, n3), a4 = G.addArc(n2, n3);
156.52 - ignore_unused_variable_warning(a1,a2,a3,a4);
156.53 + ::lemon::ignore_unused_variable_warning(a1,a2,a3,a4);
156.54
156.55 typename Digraph::Snapshot snapshot(G);
156.56
156.57 @@ -356,7 +356,7 @@
156.58 Arc
156.59 e1 = g.addArc(n1, n2),
156.60 e2 = g.addArc(n2, n3);
156.61 - ignore_unused_variable_warning(e2);
156.62 + ::lemon::ignore_unused_variable_warning(e2);
156.63
156.64 check(g.valid(n1), "Wrong validity check");
156.65 check(g.valid(e1), "Wrong validity check");
156.66 @@ -442,6 +442,7 @@
156.67 a2 = g.addArc(n2, n1),
156.68 a3 = g.addArc(n2, n3),
156.69 a4 = g.addArc(n2, n3);
156.70 + ::lemon::ignore_unused_variable_warning(a2,a3,a4);
156.71
156.72 digraphCopy(g, G).nodeRef(nref).run();
156.73
157.1 --- a/test/dijkstra_test.cc Mon Jul 16 16:21:40 2018 +0200
157.2 +++ b/test/dijkstra_test.cc Wed Oct 17 19:14:07 2018 +0200
157.3 @@ -2,7 +2,7 @@
157.4 *
157.5 * This file is a part of LEMON, a generic C++ optimization library.
157.6 *
157.7 - * Copyright (C) 2003-2010
157.8 + * Copyright (C) 2003-2013
157.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
157.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
157.11 *
157.12 @@ -65,6 +65,8 @@
157.13 VType l;
157.14 int i;
157.15 bool b;
157.16 + ::lemon::ignore_unused_variable_warning(l,i,b);
157.17 +
157.18 DType::DistMap d(G);
157.19 DType::PredMap p(G);
157.20 LengthMap length;
157.21 @@ -162,6 +164,8 @@
157.22
157.23 Digraph g;
157.24 bool b;
157.25 + ::lemon::ignore_unused_variable_warning(b);
157.26 +
157.27 dijkstra(g,LengthMap()).run(Node());
157.28 b=dijkstra(g,LengthMap()).run(Node(),Node());
157.29 dijkstra(g,LengthMap())
158.1 --- a/test/edge_set_test.cc Mon Jul 16 16:21:40 2018 +0200
158.2 +++ b/test/edge_set_test.cc Wed Oct 17 19:14:07 2018 +0200
158.3 @@ -2,7 +2,7 @@
158.4 *
158.5 * This file is a part of LEMON, a generic C++ optimization library.
158.6 *
158.7 - * Copyright (C) 2003-2010
158.8 + * Copyright (C) 2003-2013
158.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
158.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
158.11 *
158.12 @@ -44,12 +44,12 @@
158.13 n2 = digraph.addNode();
158.14
158.15 Digraph::Arc ga1 = digraph.addArc(n1, n2);
158.16 - ignore_unused_variable_warning(ga1);
158.17 + ::lemon::ignore_unused_variable_warning(ga1);
158.18
158.19 ArcSet arc_set(digraph);
158.20
158.21 Digraph::Arc ga2 = digraph.addArc(n2, n1);
158.22 - ignore_unused_variable_warning(ga2);
158.23 + ::lemon::ignore_unused_variable_warning(ga2);
158.24
158.25 checkGraphNodeList(arc_set, 2);
158.26 checkGraphArcList(arc_set, 0);
158.27 @@ -77,7 +77,7 @@
158.28 ArcSet::Arc a2 = arc_set.addArc(n2, n1),
158.29 a3 = arc_set.addArc(n2, n3),
158.30 a4 = arc_set.addArc(n2, n3);
158.31 - ignore_unused_variable_warning(a2,a3,a4);
158.32 + ::lemon::ignore_unused_variable_warning(a2,a3,a4);
158.33
158.34 checkGraphNodeList(arc_set, 3);
158.35 checkGraphArcList(arc_set, 4);
158.36 @@ -114,12 +114,12 @@
158.37 n2 = digraph.addNode();
158.38
158.39 Digraph::Arc ga1 = digraph.addArc(n1, n2);
158.40 - ignore_unused_variable_warning(ga1);
158.41 + ::lemon::ignore_unused_variable_warning(ga1);
158.42
158.43 ArcSet arc_set(digraph);
158.44
158.45 Digraph::Arc ga2 = digraph.addArc(n2, n1);
158.46 - ignore_unused_variable_warning(ga2);
158.47 + ::lemon::ignore_unused_variable_warning(ga2);
158.48
158.49 checkGraphNodeList(arc_set, 2);
158.50 checkGraphArcList(arc_set, 0);
158.51 @@ -147,7 +147,7 @@
158.52 ArcSet::Arc a2 = arc_set.addArc(n2, n1),
158.53 a3 = arc_set.addArc(n2, n3),
158.54 a4 = arc_set.addArc(n2, n3);
158.55 - ignore_unused_variable_warning(a2,a3,a4);
158.56 + ::lemon::ignore_unused_variable_warning(a2,a3,a4);
158.57
158.58 checkGraphNodeList(arc_set, 3);
158.59 checkGraphArcList(arc_set, 4);
158.60 @@ -198,12 +198,12 @@
158.61 n2 = digraph.addNode();
158.62
158.63 Digraph::Arc ga1 = digraph.addArc(n1, n2);
158.64 - ignore_unused_variable_warning(ga1);
158.65 + ::lemon::ignore_unused_variable_warning(ga1);
158.66
158.67 EdgeSet edge_set(digraph);
158.68
158.69 Digraph::Arc ga2 = digraph.addArc(n2, n1);
158.70 - ignore_unused_variable_warning(ga2);
158.71 + ::lemon::ignore_unused_variable_warning(ga2);
158.72
158.73 checkGraphNodeList(edge_set, 2);
158.74 checkGraphArcList(edge_set, 0);
158.75 @@ -240,7 +240,7 @@
158.76 EdgeSet::Edge e2 = edge_set.addEdge(n2, n1),
158.77 e3 = edge_set.addEdge(n2, n3),
158.78 e4 = edge_set.addEdge(n2, n3);
158.79 - ignore_unused_variable_warning(e2,e3,e4);
158.80 + ::lemon::ignore_unused_variable_warning(e2,e3,e4);
158.81
158.82 checkGraphNodeList(edge_set, 3);
158.83 checkGraphEdgeList(edge_set, 4);
158.84 @@ -286,12 +286,12 @@
158.85 n2 = digraph.addNode();
158.86
158.87 Digraph::Arc ga1 = digraph.addArc(n1, n2);
158.88 - ignore_unused_variable_warning(ga1);
158.89 + ::lemon::ignore_unused_variable_warning(ga1);
158.90
158.91 EdgeSet edge_set(digraph);
158.92
158.93 Digraph::Arc ga2 = digraph.addArc(n2, n1);
158.94 - ignore_unused_variable_warning(ga2);
158.95 + ::lemon::ignore_unused_variable_warning(ga2);
158.96
158.97 checkGraphNodeList(edge_set, 2);
158.98 checkGraphArcList(edge_set, 0);
158.99 @@ -328,7 +328,7 @@
158.100 EdgeSet::Edge e2 = edge_set.addEdge(n2, n1),
158.101 e3 = edge_set.addEdge(n2, n3),
158.102 e4 = edge_set.addEdge(n2, n3);
158.103 - ignore_unused_variable_warning(e2,e3,e4);
158.104 + ::lemon::ignore_unused_variable_warning(e2,e3,e4);
158.105
158.106 checkGraphNodeList(edge_set, 3);
158.107 checkGraphEdgeList(edge_set, 4);
159.1 --- a/test/euler_test.cc Mon Jul 16 16:21:40 2018 +0200
159.2 +++ b/test/euler_test.cc Wed Oct 17 19:14:07 2018 +0200
159.3 @@ -2,7 +2,7 @@
159.4 *
159.5 * This file is a part of LEMON, a generic C++ optimization library.
159.6 *
159.7 - * Copyright (C) 2003-2010
159.8 + * Copyright (C) 2003-2013
159.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
159.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
159.11 *
159.12 @@ -101,8 +101,8 @@
159.13 Digraph d;
159.14 Graph g(d);
159.15 Digraph::Node n = d.addNode();
159.16 - ignore_unused_variable_warning(n);
159.17 -
159.18 + ::lemon::ignore_unused_variable_warning(n);
159.19 +
159.20 checkDiEulerIt(d);
159.21 checkDiEulerIt(g);
159.22 checkEulerIt(g);
159.23 @@ -190,7 +190,7 @@
159.24 Digraph::Node n3 = d.addNode();
159.25 Digraph::Node n4 = d.addNode();
159.26 Digraph::Node n5 = d.addNode();
159.27 - ignore_unused_variable_warning(n0,n4,n5);
159.28 + ::lemon::ignore_unused_variable_warning(n0,n4,n5);
159.29
159.30 d.addArc(n1, n2);
159.31 d.addArc(n2, n3);
160.1 --- a/test/fractional_matching_test.cc Mon Jul 16 16:21:40 2018 +0200
160.2 +++ b/test/fractional_matching_test.cc Wed Oct 17 19:14:07 2018 +0200
160.3 @@ -2,7 +2,7 @@
160.4 *
160.5 * This file is a part of LEMON, a generic C++ optimization library.
160.6 *
160.7 - * Copyright (C) 2003-2010
160.8 + * Copyright (C) 2003-2013
160.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
160.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
160.11 *
160.12 @@ -342,6 +342,7 @@
160.13 check(indeg == 1, "Invalid matching");
160.14 pv += weight[mwfm.matching(n)];
160.15 SmartGraph::Node o = graph.target(mwfm.matching(n));
160.16 + ::lemon::ignore_unused_variable_warning(o);
160.17 } else {
160.18 check(mwfm.nodeValue(n) == 0, "Invalid matching");
160.19 check(indeg == 0, "Invalid matching");
160.20 @@ -406,6 +407,7 @@
160.21 check(indeg == 1, "Invalid perfect matching");
160.22 pv += weight[mwpfm.matching(n)];
160.23 SmartGraph::Node o = graph.target(mwpfm.matching(n));
160.24 + ::lemon::ignore_unused_variable_warning(o);
160.25 }
160.26
160.27 for (SmartGraph::EdgeIt e(graph); e != INVALID; ++e) {
161.1 --- a/test/gomory_hu_test.cc Mon Jul 16 16:21:40 2018 +0200
161.2 +++ b/test/gomory_hu_test.cc Wed Oct 17 19:14:07 2018 +0200
161.3 @@ -2,7 +2,7 @@
161.4 *
161.5 * This file is a part of LEMON, a generic C++ optimization library.
161.6 *
161.7 - * Copyright (C) 2003-2010
161.8 + * Copyright (C) 2003-2013
161.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
161.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
161.11 *
161.12 @@ -68,6 +68,7 @@
161.13 CutMap cut;
161.14 Value v;
161.15 int d;
161.16 + ::lemon::ignore_unused_variable_warning(v,d);
161.17
161.18 GomoryHu<Graph, CapMap> gh_test(g, cap);
161.19 const GomoryHu<Graph, CapMap>&
162.1 --- a/test/graph_copy_test.cc Mon Jul 16 16:21:40 2018 +0200
162.2 +++ b/test/graph_copy_test.cc Wed Oct 17 19:14:07 2018 +0200
162.3 @@ -2,7 +2,7 @@
162.4 *
162.5 * This file is a part of LEMON, a generic C++ optimization library.
162.6 *
162.7 - * Copyright (C) 2003-2009
162.8 + * Copyright (C) 2003-2013
162.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
162.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
162.11 *
162.12 @@ -18,6 +18,7 @@
162.13
162.14 #include <lemon/smart_graph.h>
162.15 #include <lemon/list_graph.h>
162.16 +#include <lemon/static_graph.h>
162.17 #include <lemon/lgf_reader.h>
162.18 #include <lemon/error.h>
162.19
162.20 @@ -26,6 +27,7 @@
162.21 using namespace std;
162.22 using namespace lemon;
162.23
162.24 +template <typename GR>
162.25 void digraph_copy_test() {
162.26 const int nn = 10;
162.27
162.28 @@ -53,24 +55,24 @@
162.29 }
162.30
162.31 // Test digraph copy
162.32 - ListDigraph to;
162.33 - ListDigraph::NodeMap<int> tnm(to);
162.34 - ListDigraph::ArcMap<int> tam(to);
162.35 - ListDigraph::Node tn;
162.36 - ListDigraph::Arc ta;
162.37 + GR to;
162.38 + typename GR::template NodeMap<int> tnm(to);
162.39 + typename GR::template ArcMap<int> tam(to);
162.40 + typename GR::Node tn;
162.41 + typename GR::Arc ta;
162.42
162.43 - SmartDigraph::NodeMap<ListDigraph::Node> nr(from);
162.44 - SmartDigraph::ArcMap<ListDigraph::Arc> er(from);
162.45 + SmartDigraph::NodeMap<typename GR::Node> nr(from);
162.46 + SmartDigraph::ArcMap<typename GR::Arc> er(from);
162.47
162.48 - ListDigraph::NodeMap<SmartDigraph::Node> ncr(to);
162.49 - ListDigraph::ArcMap<SmartDigraph::Arc> ecr(to);
162.50 + typename GR::template NodeMap<SmartDigraph::Node> ncr(to);
162.51 + typename GR::template ArcMap<SmartDigraph::Arc> ecr(to);
162.52
162.53 digraphCopy(from, to).
162.54 nodeMap(fnm, tnm).arcMap(fam, tam).
162.55 nodeRef(nr).arcRef(er).
162.56 nodeCrossRef(ncr).arcCrossRef(ecr).
162.57 node(fn, tn).arc(fa, ta).run();
162.58 -
162.59 +
162.60 check(countNodes(from) == countNodes(to), "Wrong copy.");
162.61 check(countArcs(from) == countArcs(to), "Wrong copy.");
162.62
162.63 @@ -86,11 +88,11 @@
162.64 check(nr[from.target(it)] == to.target(er[it]), "Wrong copy.");
162.65 }
162.66
162.67 - for (ListDigraph::NodeIt it(to); it != INVALID; ++it) {
162.68 + for (typename GR::NodeIt it(to); it != INVALID; ++it) {
162.69 check(nr[ncr[it]] == it, "Wrong copy.");
162.70 }
162.71
162.72 - for (ListDigraph::ArcIt it(to); it != INVALID; ++it) {
162.73 + for (typename GR::ArcIt it(to); it != INVALID; ++it) {
162.74 check(er[ecr[it]] == it, "Wrong copy.");
162.75 }
162.76 check(tn == nr[fn], "Wrong copy.");
162.77 @@ -98,11 +100,12 @@
162.78
162.79 // Test repeated copy
162.80 digraphCopy(from, to).run();
162.81 -
162.82 +
162.83 check(countNodes(from) == countNodes(to), "Wrong copy.");
162.84 check(countArcs(from) == countArcs(to), "Wrong copy.");
162.85 }
162.86
162.87 +template <typename GR>
162.88 void graph_copy_test() {
162.89 const int nn = 10;
162.90
162.91 @@ -135,21 +138,21 @@
162.92 }
162.93
162.94 // Test graph copy
162.95 - ListGraph to;
162.96 - ListGraph::NodeMap<int> tnm(to);
162.97 - ListGraph::ArcMap<int> tam(to);
162.98 - ListGraph::EdgeMap<int> tem(to);
162.99 - ListGraph::Node tn;
162.100 - ListGraph::Arc ta;
162.101 - ListGraph::Edge te;
162.102 + GR to;
162.103 + typename GR::template NodeMap<int> tnm(to);
162.104 + typename GR::template ArcMap<int> tam(to);
162.105 + typename GR::template EdgeMap<int> tem(to);
162.106 + typename GR::Node tn;
162.107 + typename GR::Arc ta;
162.108 + typename GR::Edge te;
162.109
162.110 - SmartGraph::NodeMap<ListGraph::Node> nr(from);
162.111 - SmartGraph::ArcMap<ListGraph::Arc> ar(from);
162.112 - SmartGraph::EdgeMap<ListGraph::Edge> er(from);
162.113 + SmartGraph::NodeMap<typename GR::Node> nr(from);
162.114 + SmartGraph::ArcMap<typename GR::Arc> ar(from);
162.115 + SmartGraph::EdgeMap<typename GR::Edge> er(from);
162.116
162.117 - ListGraph::NodeMap<SmartGraph::Node> ncr(to);
162.118 - ListGraph::ArcMap<SmartGraph::Arc> acr(to);
162.119 - ListGraph::EdgeMap<SmartGraph::Edge> ecr(to);
162.120 + typename GR::template NodeMap<SmartGraph::Node> ncr(to);
162.121 + typename GR::template ArcMap<SmartGraph::Arc> acr(to);
162.122 + typename GR::template EdgeMap<SmartGraph::Edge> ecr(to);
162.123
162.124 graphCopy(from, to).
162.125 nodeMap(fnm, tnm).arcMap(fam, tam).edgeMap(fem, tem).
162.126 @@ -184,14 +187,14 @@
162.127 "Wrong copy.");
162.128 }
162.129
162.130 - for (ListGraph::NodeIt it(to); it != INVALID; ++it) {
162.131 + for (typename GR::NodeIt it(to); it != INVALID; ++it) {
162.132 check(nr[ncr[it]] == it, "Wrong copy.");
162.133 }
162.134
162.135 - for (ListGraph::ArcIt it(to); it != INVALID; ++it) {
162.136 + for (typename GR::ArcIt it(to); it != INVALID; ++it) {
162.137 check(ar[acr[it]] == it, "Wrong copy.");
162.138 }
162.139 - for (ListGraph::EdgeIt it(to); it != INVALID; ++it) {
162.140 + for (typename GR::EdgeIt it(to); it != INVALID; ++it) {
162.141 check(er[ecr[it]] == it, "Wrong copy.");
162.142 }
162.143 check(tn == nr[fn], "Wrong copy.");
162.144 @@ -200,16 +203,186 @@
162.145
162.146 // Test repeated copy
162.147 graphCopy(from, to).run();
162.148 -
162.149 +
162.150 check(countNodes(from) == countNodes(to), "Wrong copy.");
162.151 check(countEdges(from) == countEdges(to), "Wrong copy.");
162.152 check(countArcs(from) == countArcs(to), "Wrong copy.");
162.153 }
162.154
162.155 +template <typename GR>
162.156 +void bpgraph_copy_test() {
162.157 + const int nn = 10;
162.158 +
162.159 + // Build a graph
162.160 + SmartBpGraph from;
162.161 + SmartBpGraph::NodeMap<int> fnm(from);
162.162 + SmartBpGraph::RedNodeMap<int> frnm(from);
162.163 + SmartBpGraph::BlueNodeMap<int> fbnm(from);
162.164 + SmartBpGraph::ArcMap<int> fam(from);
162.165 + SmartBpGraph::EdgeMap<int> fem(from);
162.166 + SmartBpGraph::Node fn = INVALID;
162.167 + SmartBpGraph::RedNode frn = INVALID;
162.168 + SmartBpGraph::BlueNode fbn = INVALID;
162.169 + SmartBpGraph::Arc fa = INVALID;
162.170 + SmartBpGraph::Edge fe = INVALID;
162.171 +
162.172 + std::vector<SmartBpGraph::RedNode> frnv;
162.173 + for (int i = 0; i < nn; ++i) {
162.174 + SmartBpGraph::RedNode node = from.addRedNode();
162.175 + frnv.push_back(node);
162.176 + fnm[node] = i * i;
162.177 + frnm[node] = i + i;
162.178 + if (i == 0) {
162.179 + fn = node;
162.180 + frn = node;
162.181 + }
162.182 + }
162.183 +
162.184 + std::vector<SmartBpGraph::BlueNode> fbnv;
162.185 + for (int i = 0; i < nn; ++i) {
162.186 + SmartBpGraph::BlueNode node = from.addBlueNode();
162.187 + fbnv.push_back(node);
162.188 + fnm[node] = i * i;
162.189 + fbnm[node] = i + i;
162.190 + if (i == 0) fbn = node;
162.191 + }
162.192 +
162.193 + for (int i = 0; i < nn; ++i) {
162.194 + for (int j = 0; j < nn; ++j) {
162.195 + SmartBpGraph::Edge edge = from.addEdge(frnv[i], fbnv[j]);
162.196 + fem[edge] = i * i + j * j;
162.197 + fam[from.direct(edge, true)] = i + j * j;
162.198 + fam[from.direct(edge, false)] = i * i + j;
162.199 + if (i == 0 && j == 0) fa = from.direct(edge, true);
162.200 + if (i == 0 && j == 0) fe = edge;
162.201 + }
162.202 + }
162.203 +
162.204 + // Test graph copy
162.205 + GR to;
162.206 + typename GR::template NodeMap<int> tnm(to);
162.207 + typename GR::template RedNodeMap<int> trnm(to);
162.208 + typename GR::template BlueNodeMap<int> tbnm(to);
162.209 + typename GR::template ArcMap<int> tam(to);
162.210 + typename GR::template EdgeMap<int> tem(to);
162.211 + typename GR::Node tn;
162.212 + typename GR::RedNode trn;
162.213 + typename GR::BlueNode tbn;
162.214 + typename GR::Arc ta;
162.215 + typename GR::Edge te;
162.216 +
162.217 + SmartBpGraph::NodeMap<typename GR::Node> nr(from);
162.218 + SmartBpGraph::RedNodeMap<typename GR::RedNode> rnr(from);
162.219 + SmartBpGraph::BlueNodeMap<typename GR::BlueNode> bnr(from);
162.220 + SmartBpGraph::ArcMap<typename GR::Arc> ar(from);
162.221 + SmartBpGraph::EdgeMap<typename GR::Edge> er(from);
162.222 +
162.223 + typename GR::template NodeMap<SmartBpGraph::Node> ncr(to);
162.224 + typename GR::template RedNodeMap<SmartBpGraph::RedNode> rncr(to);
162.225 + typename GR::template BlueNodeMap<SmartBpGraph::BlueNode> bncr(to);
162.226 + typename GR::template ArcMap<SmartBpGraph::Arc> acr(to);
162.227 + typename GR::template EdgeMap<SmartBpGraph::Edge> ecr(to);
162.228 +
162.229 + bpGraphCopy(from, to).
162.230 + nodeMap(fnm, tnm).
162.231 + redNodeMap(frnm, trnm).blueNodeMap(fbnm, tbnm).
162.232 + arcMap(fam, tam).edgeMap(fem, tem).
162.233 + nodeRef(nr).redRef(rnr).blueRef(bnr).
162.234 + arcRef(ar).edgeRef(er).
162.235 + nodeCrossRef(ncr).redCrossRef(rncr).blueCrossRef(bncr).
162.236 + arcCrossRef(acr).edgeCrossRef(ecr).
162.237 + node(fn, tn).redNode(frn, trn).blueNode(fbn, tbn).
162.238 + arc(fa, ta).edge(fe, te).run();
162.239 +
162.240 + check(countNodes(from) == countNodes(to), "Wrong copy.");
162.241 + check(countRedNodes(from) == countRedNodes(to), "Wrong copy.");
162.242 + check(countBlueNodes(from) == countBlueNodes(to), "Wrong copy.");
162.243 + check(countEdges(from) == countEdges(to), "Wrong copy.");
162.244 + check(countArcs(from) == countArcs(to), "Wrong copy.");
162.245 +
162.246 + for (SmartBpGraph::NodeIt it(from); it != INVALID; ++it) {
162.247 + check(ncr[nr[it]] == it, "Wrong copy.");
162.248 + check(fnm[it] == tnm[nr[it]], "Wrong copy.");
162.249 + }
162.250 +
162.251 + for (SmartBpGraph::RedNodeIt it(from); it != INVALID; ++it) {
162.252 + check(ncr[nr[it]] == it, "Wrong copy.");
162.253 + check(fnm[it] == tnm[nr[it]], "Wrong copy.");
162.254 + check(rnr[it] == nr[it], "Wrong copy.");
162.255 + check(rncr[rnr[it]] == it, "Wrong copy.");
162.256 + check(frnm[it] == trnm[rnr[it]], "Wrong copy.");
162.257 + check(to.red(rnr[it]), "Wrong copy.");
162.258 + }
162.259 +
162.260 + for (SmartBpGraph::BlueNodeIt it(from); it != INVALID; ++it) {
162.261 + check(ncr[nr[it]] == it, "Wrong copy.");
162.262 + check(fnm[it] == tnm[nr[it]], "Wrong copy.");
162.263 + check(bnr[it] == nr[it], "Wrong copy.");
162.264 + check(bncr[bnr[it]] == it, "Wrong copy.");
162.265 + check(fbnm[it] == tbnm[bnr[it]], "Wrong copy.");
162.266 + check(to.blue(bnr[it]), "Wrong copy.");
162.267 + }
162.268 +
162.269 + for (SmartBpGraph::ArcIt it(from); it != INVALID; ++it) {
162.270 + check(acr[ar[it]] == it, "Wrong copy.");
162.271 + check(fam[it] == tam[ar[it]], "Wrong copy.");
162.272 + check(nr[from.source(it)] == to.source(ar[it]), "Wrong copy.");
162.273 + check(nr[from.target(it)] == to.target(ar[it]), "Wrong copy.");
162.274 + }
162.275 +
162.276 + for (SmartBpGraph::EdgeIt it(from); it != INVALID; ++it) {
162.277 + check(ecr[er[it]] == it, "Wrong copy.");
162.278 + check(fem[it] == tem[er[it]], "Wrong copy.");
162.279 + check(nr[from.u(it)] == to.u(er[it]) || nr[from.u(it)] == to.v(er[it]),
162.280 + "Wrong copy.");
162.281 + check(nr[from.v(it)] == to.u(er[it]) || nr[from.v(it)] == to.v(er[it]),
162.282 + "Wrong copy.");
162.283 + check((from.u(it) != from.v(it)) == (to.u(er[it]) != to.v(er[it])),
162.284 + "Wrong copy.");
162.285 + }
162.286 +
162.287 + for (typename GR::NodeIt it(to); it != INVALID; ++it) {
162.288 + check(nr[ncr[it]] == it, "Wrong copy.");
162.289 + }
162.290 + for (typename GR::RedNodeIt it(to); it != INVALID; ++it) {
162.291 + check(rncr[it] == ncr[it], "Wrong copy.");
162.292 + check(rnr[rncr[it]] == it, "Wrong copy.");
162.293 + }
162.294 + for (typename GR::BlueNodeIt it(to); it != INVALID; ++it) {
162.295 + check(bncr[it] == ncr[it], "Wrong copy.");
162.296 + check(bnr[bncr[it]] == it, "Wrong copy.");
162.297 + }
162.298 + for (typename GR::ArcIt it(to); it != INVALID; ++it) {
162.299 + check(ar[acr[it]] == it, "Wrong copy.");
162.300 + }
162.301 + for (typename GR::EdgeIt it(to); it != INVALID; ++it) {
162.302 + check(er[ecr[it]] == it, "Wrong copy.");
162.303 + }
162.304 + check(tn == nr[fn], "Wrong copy.");
162.305 + check(trn == rnr[frn], "Wrong copy.");
162.306 + check(tbn == bnr[fbn], "Wrong copy.");
162.307 + check(ta == ar[fa], "Wrong copy.");
162.308 + check(te == er[fe], "Wrong copy.");
162.309 +
162.310 + // Test repeated copy
162.311 + bpGraphCopy(from, to).run();
162.312 +
162.313 + check(countNodes(from) == countNodes(to), "Wrong copy.");
162.314 + check(countRedNodes(from) == countRedNodes(to), "Wrong copy.");
162.315 + check(countBlueNodes(from) == countBlueNodes(to), "Wrong copy.");
162.316 + check(countEdges(from) == countEdges(to), "Wrong copy.");
162.317 + check(countArcs(from) == countArcs(to), "Wrong copy.");
162.318 +}
162.319 +
162.320
162.321 int main() {
162.322 - digraph_copy_test();
162.323 - graph_copy_test();
162.324 + digraph_copy_test<SmartDigraph>();
162.325 + digraph_copy_test<ListDigraph>();
162.326 + digraph_copy_test<StaticDigraph>();
162.327 + graph_copy_test<SmartGraph>();
162.328 + graph_copy_test<ListGraph>();
162.329 + bpgraph_copy_test<SmartBpGraph>();
162.330 + bpgraph_copy_test<ListBpGraph>();
162.331
162.332 return 0;
162.333 }
163.1 --- a/test/graph_test.cc Mon Jul 16 16:21:40 2018 +0200
163.2 +++ b/test/graph_test.cc Wed Oct 17 19:14:07 2018 +0200
163.3 @@ -2,7 +2,7 @@
163.4 *
163.5 * This file is a part of LEMON, a generic C++ optimization library.
163.6 *
163.7 - * Copyright (C) 2003-2010
163.8 + * Copyright (C) 2003-2013
163.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
163.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
163.11 *
163.12 @@ -66,7 +66,7 @@
163.13
163.14 Edge e2 = G.addEdge(n2, n1),
163.15 e3 = G.addEdge(n2, n3);
163.16 - ignore_unused_variable_warning(e2,e3);
163.17 + ::lemon::ignore_unused_variable_warning(e2,e3);
163.18
163.19 checkGraphNodeList(G, 3);
163.20 checkGraphEdgeList(G, 3);
163.21 @@ -99,7 +99,7 @@
163.22 Edge e1 = G.addEdge(n1, n2), e2 = G.addEdge(n2, n1),
163.23 e3 = G.addEdge(n2, n3), e4 = G.addEdge(n1, n4),
163.24 e5 = G.addEdge(n4, n3);
163.25 - ignore_unused_variable_warning(e1,e3,e4,e5);
163.26 + ::lemon::ignore_unused_variable_warning(e1,e3,e4,e5);
163.27
163.28 checkGraphNodeList(G, 4);
163.29 checkGraphEdgeList(G, 5);
163.30 @@ -179,7 +179,7 @@
163.31 Edge e1 = G.addEdge(n1, n2), e2 = G.addEdge(n2, n1),
163.32 e3 = G.addEdge(n2, n3), e4 = G.addEdge(n1, n4),
163.33 e5 = G.addEdge(n4, n3);
163.34 - ignore_unused_variable_warning(e1,e3,e4,e5);
163.35 + ::lemon::ignore_unused_variable_warning(e1,e3,e4,e5);
163.36
163.37 // Check edge deletion
163.38 G.erase(e2);
163.39 @@ -220,7 +220,7 @@
163.40 Node n1 = G.addNode(), n2 = G.addNode(), n3 = G.addNode();
163.41 Edge e1 = G.addEdge(n1, n2), e2 = G.addEdge(n2, n1),
163.42 e3 = G.addEdge(n2, n3);
163.43 - ignore_unused_variable_warning(e1,e2,e3);
163.44 + ::lemon::ignore_unused_variable_warning(e1,e2,e3);
163.45
163.46 checkGraphNodeList(G, 3);
163.47 checkGraphEdgeList(G, 3);
163.48 @@ -385,7 +385,7 @@
163.49 Edge
163.50 e1 = g.addEdge(n1, n2),
163.51 e2 = g.addEdge(n2, n3);
163.52 - ignore_unused_variable_warning(e2);
163.53 + ::lemon::ignore_unused_variable_warning(e2);
163.54
163.55 check(g.valid(n1), "Wrong validity check");
163.56 check(g.valid(e1), "Wrong validity check");
163.57 @@ -524,7 +524,7 @@
163.58 checkGraphArcList(G, dim * (1 << dim));
163.59
163.60 Node n = G.nodeFromId(dim);
163.61 - ignore_unused_variable_warning(n);
163.62 + ::lemon::ignore_unused_variable_warning(n);
163.63
163.64 for (NodeIt n(G); n != INVALID; ++n) {
163.65 checkGraphIncEdgeList(G, n, dim);
164.1 --- a/test/graph_test.h Mon Jul 16 16:21:40 2018 +0200
164.2 +++ b/test/graph_test.h Wed Oct 17 19:14:07 2018 +0200
164.3 @@ -2,7 +2,7 @@
164.4 *
164.5 * This file is a part of LEMON, a generic C++ optimization library.
164.6 *
164.7 - * Copyright (C) 2003-2009
164.8 + * Copyright (C) 2003-2013
164.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
164.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
164.11 *
164.12 @@ -41,6 +41,42 @@
164.13 }
164.14
164.15 template<class Graph>
164.16 + void checkGraphRedNodeList(const Graph &G, int cnt)
164.17 + {
164.18 + typename Graph::RedNodeIt n(G);
164.19 + for(int i=0;i<cnt;i++) {
164.20 + check(n!=INVALID,"Wrong red Node list linking.");
164.21 + check(G.red(n),"Wrong node set check.");
164.22 + check(!G.blue(n),"Wrong node set check.");
164.23 + typename Graph::Node nn = n;
164.24 + check(G.asRedNodeUnsafe(nn) == n,"Wrong node conversion.");
164.25 + check(G.asRedNode(nn) == n,"Wrong node conversion.");
164.26 + check(G.asBlueNode(nn) == INVALID,"Wrong node conversion.");
164.27 + ++n;
164.28 + }
164.29 + check(n==INVALID,"Wrong red Node list linking.");
164.30 + check(countRedNodes(G)==cnt,"Wrong red Node number.");
164.31 + }
164.32 +
164.33 + template<class Graph>
164.34 + void checkGraphBlueNodeList(const Graph &G, int cnt)
164.35 + {
164.36 + typename Graph::BlueNodeIt n(G);
164.37 + for(int i=0;i<cnt;i++) {
164.38 + check(n!=INVALID,"Wrong blue Node list linking.");
164.39 + check(G.blue(n),"Wrong node set check.");
164.40 + check(!G.red(n),"Wrong node set check.");
164.41 + typename Graph::Node nn = n;
164.42 + check(G.asBlueNodeUnsafe(nn) == n,"Wrong node conversion.");
164.43 + check(G.asBlueNode(nn) == n,"Wrong node conversion.");
164.44 + check(G.asRedNode(nn) == INVALID,"Wrong node conversion.");
164.45 + ++n;
164.46 + }
164.47 + check(n==INVALID,"Wrong blue Node list linking.");
164.48 + check(countBlueNodes(G)==cnt,"Wrong blue Node number.");
164.49 + }
164.50 +
164.51 + template<class Graph>
164.52 void checkGraphArcList(const Graph &G, int cnt)
164.53 {
164.54 typename Graph::ArcIt e(G);
164.55 @@ -166,6 +202,7 @@
164.56
164.57 template <typename Graph>
164.58 void checkNodeIds(const Graph& G) {
164.59 + typedef typename Graph::Node Node;
164.60 std::set<int> values;
164.61 for (typename Graph::NodeIt n(G); n != INVALID; ++n) {
164.62 check(G.nodeFromId(G.id(n)) == n, "Wrong id");
164.63 @@ -173,10 +210,38 @@
164.64 check(G.id(n) <= G.maxNodeId(), "Wrong maximum id");
164.65 values.insert(G.id(n));
164.66 }
164.67 + check(G.maxId(Node()) <= G.maxNodeId(), "Wrong maximum id");
164.68 + }
164.69 +
164.70 + template <typename Graph>
164.71 + void checkRedNodeIds(const Graph& G) {
164.72 + typedef typename Graph::RedNode RedNode;
164.73 + std::set<int> values;
164.74 + for (typename Graph::RedNodeIt n(G); n != INVALID; ++n) {
164.75 + check(G.red(n), "Wrong partition");
164.76 + check(values.find(G.id(n)) == values.end(), "Wrong id");
164.77 + check(G.id(n) <= G.maxRedId(), "Wrong maximum id");
164.78 + values.insert(G.id(n));
164.79 + }
164.80 + check(G.maxId(RedNode()) == G.maxRedId(), "Wrong maximum id");
164.81 + }
164.82 +
164.83 + template <typename Graph>
164.84 + void checkBlueNodeIds(const Graph& G) {
164.85 + typedef typename Graph::BlueNode BlueNode;
164.86 + std::set<int> values;
164.87 + for (typename Graph::BlueNodeIt n(G); n != INVALID; ++n) {
164.88 + check(G.blue(n), "Wrong partition");
164.89 + check(values.find(G.id(n)) == values.end(), "Wrong id");
164.90 + check(G.id(n) <= G.maxBlueId(), "Wrong maximum id");
164.91 + values.insert(G.id(n));
164.92 + }
164.93 + check(G.maxId(BlueNode()) == G.maxBlueId(), "Wrong maximum id");
164.94 }
164.95
164.96 template <typename Graph>
164.97 void checkArcIds(const Graph& G) {
164.98 + typedef typename Graph::Arc Arc;
164.99 std::set<int> values;
164.100 for (typename Graph::ArcIt a(G); a != INVALID; ++a) {
164.101 check(G.arcFromId(G.id(a)) == a, "Wrong id");
164.102 @@ -184,10 +249,12 @@
164.103 check(G.id(a) <= G.maxArcId(), "Wrong maximum id");
164.104 values.insert(G.id(a));
164.105 }
164.106 + check(G.maxId(Arc()) <= G.maxArcId(), "Wrong maximum id");
164.107 }
164.108
164.109 template <typename Graph>
164.110 void checkEdgeIds(const Graph& G) {
164.111 + typedef typename Graph::Edge Edge;
164.112 std::set<int> values;
164.113 for (typename Graph::EdgeIt e(G); e != INVALID; ++e) {
164.114 check(G.edgeFromId(G.id(e)) == e, "Wrong id");
164.115 @@ -195,6 +262,7 @@
164.116 check(G.id(e) <= G.maxEdgeId(), "Wrong maximum id");
164.117 values.insert(G.id(e));
164.118 }
164.119 + check(G.maxId(Edge()) <= G.maxEdgeId(), "Wrong maximum id");
164.120 }
164.121
164.122 template <typename Graph>
164.123 @@ -228,6 +296,66 @@
164.124 }
164.125
164.126 template <typename Graph>
164.127 + void checkGraphRedNodeMap(const Graph& G) {
164.128 + typedef typename Graph::Node Node;
164.129 + typedef typename Graph::RedNodeIt RedNodeIt;
164.130 +
164.131 + typedef typename Graph::template RedNodeMap<int> IntRedNodeMap;
164.132 + IntRedNodeMap map(G, 42);
164.133 + for (RedNodeIt it(G); it != INVALID; ++it) {
164.134 + check(map[it] == 42, "Wrong map constructor.");
164.135 + }
164.136 + int s = 0;
164.137 + for (RedNodeIt it(G); it != INVALID; ++it) {
164.138 + map[it] = 0;
164.139 + check(map[it] == 0, "Wrong operator[].");
164.140 + map.set(it, s);
164.141 + check(map[it] == s, "Wrong set.");
164.142 + ++s;
164.143 + }
164.144 + s = s * (s - 1) / 2;
164.145 + for (RedNodeIt it(G); it != INVALID; ++it) {
164.146 + s -= map[it];
164.147 + }
164.148 + check(s == 0, "Wrong sum.");
164.149 +
164.150 + // map = constMap<Node>(12);
164.151 + // for (NodeIt it(G); it != INVALID; ++it) {
164.152 + // check(map[it] == 12, "Wrong operator[].");
164.153 + // }
164.154 + }
164.155 +
164.156 + template <typename Graph>
164.157 + void checkGraphBlueNodeMap(const Graph& G) {
164.158 + typedef typename Graph::Node Node;
164.159 + typedef typename Graph::BlueNodeIt BlueNodeIt;
164.160 +
164.161 + typedef typename Graph::template BlueNodeMap<int> IntBlueNodeMap;
164.162 + IntBlueNodeMap map(G, 42);
164.163 + for (BlueNodeIt it(G); it != INVALID; ++it) {
164.164 + check(map[it] == 42, "Wrong map constructor.");
164.165 + }
164.166 + int s = 0;
164.167 + for (BlueNodeIt it(G); it != INVALID; ++it) {
164.168 + map[it] = 0;
164.169 + check(map[it] == 0, "Wrong operator[].");
164.170 + map.set(it, s);
164.171 + check(map[it] == s, "Wrong set.");
164.172 + ++s;
164.173 + }
164.174 + s = s * (s - 1) / 2;
164.175 + for (BlueNodeIt it(G); it != INVALID; ++it) {
164.176 + s -= map[it];
164.177 + }
164.178 + check(s == 0, "Wrong sum.");
164.179 +
164.180 + // map = constMap<Node>(12);
164.181 + // for (NodeIt it(G); it != INVALID; ++it) {
164.182 + // check(map[it] == 12, "Wrong operator[].");
164.183 + // }
164.184 + }
164.185 +
164.186 + template <typename Graph>
164.187 void checkGraphArcMap(const Graph& G) {
164.188 typedef typename Graph::Arc Arc;
164.189 typedef typename Graph::ArcIt ArcIt;
165.1 --- a/test/hao_orlin_test.cc Mon Jul 16 16:21:40 2018 +0200
165.2 +++ b/test/hao_orlin_test.cc Wed Oct 17 19:14:07 2018 +0200
165.3 @@ -2,7 +2,7 @@
165.4 *
165.5 * This file is a part of LEMON, a generic C++ optimization library.
165.6 *
165.7 - * Copyright (C) 2003-2010
165.8 + * Copyright (C) 2003-2013
165.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
165.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
165.11 *
165.12 @@ -66,6 +66,7 @@
165.13 CapMap cap;
165.14 CutMap cut;
165.15 Value v;
165.16 + ::lemon::ignore_unused_variable_warning(v);
165.17
165.18 HaoOrlin<Digraph, CapMap> ho_test(g, cap);
165.19 const HaoOrlin<Digraph, CapMap>&
166.1 --- a/test/heap_test.cc Mon Jul 16 16:21:40 2018 +0200
166.2 +++ b/test/heap_test.cc Wed Oct 17 19:14:07 2018 +0200
166.3 @@ -2,7 +2,7 @@
166.4 *
166.5 * This file is a part of LEMON, a generic C++ optimization library.
166.6 *
166.7 - * Copyright (C) 2003-2009
166.8 + * Copyright (C) 2003-2013
166.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
166.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
166.11 *
167.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
167.2 +++ b/test/lgf_reader_writer_test.cc Wed Oct 17 19:14:07 2018 +0200
167.3 @@ -0,0 +1,578 @@
167.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
167.5 + *
167.6 + * This file is a part of LEMON, a generic C++ optimization library.
167.7 + *
167.8 + * Copyright (C) 2003-2013
167.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
167.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
167.11 + *
167.12 + * Permission to use, modify and distribute this software is granted
167.13 + * provided that this copyright notice appears in all copies. For
167.14 + * precise terms see the accompanying LICENSE file.
167.15 + *
167.16 + * This software is provided "AS IS" with no warranty of any kind,
167.17 + * express or implied, and with no claim as to its suitability for any
167.18 + * purpose.
167.19 + *
167.20 + */
167.21 +
167.22 +#include <string>
167.23 +
167.24 +#include <lemon/concepts/digraph.h>
167.25 +#include <lemon/concepts/graph.h>
167.26 +#include <lemon/concepts/bpgraph.h>
167.27 +
167.28 +#include <lemon/list_graph.h>
167.29 +#include <lemon/smart_graph.h>
167.30 +#include <lemon/lgf_reader.h>
167.31 +
167.32 +#include "test_tools.h"
167.33 +
167.34 +struct ReaderConverter {
167.35 + int operator()(const std::string& str) const {
167.36 + return str.length();
167.37 + }
167.38 +};
167.39 +
167.40 +struct WriterConverter {
167.41 + std::string operator()(int value) const {
167.42 + return std::string(value, '*');
167.43 + }
167.44 +};
167.45 +
167.46 +void checkDigraphReaderCompile() {
167.47 + typedef lemon::concepts::ExtendableDigraphComponent<
167.48 + lemon::concepts::Digraph> Digraph;
167.49 + Digraph digraph;
167.50 + Digraph::NodeMap<int> node_map(digraph);
167.51 + Digraph::ArcMap<int> arc_map(digraph);
167.52 + Digraph::Node node;
167.53 + Digraph::Arc arc;
167.54 + int attr;
167.55 +
167.56 + lemon::DigraphReader<Digraph> reader(digraph, "filename");
167.57 + reader.nodeMap("node_map", node_map);
167.58 + reader.nodeMap("node_map", node_map, ReaderConverter());
167.59 + reader.arcMap("arc_map", arc_map);
167.60 + reader.arcMap("arc_map", arc_map, ReaderConverter());
167.61 + reader.attribute("attr", attr);
167.62 + reader.attribute("attr", attr, ReaderConverter());
167.63 + reader.node("node", node);
167.64 + reader.arc("arc", arc);
167.65 +
167.66 + reader.nodes("alt_nodes_caption");
167.67 + reader.arcs("alt_arcs_caption");
167.68 + reader.attributes("alt_attrs_caption");
167.69 +
167.70 + reader.useNodes(node_map);
167.71 + reader.useNodes(node_map, WriterConverter());
167.72 + reader.useArcs(arc_map);
167.73 + reader.useArcs(arc_map, WriterConverter());
167.74 +
167.75 + reader.skipNodes();
167.76 + reader.skipArcs();
167.77 +
167.78 + reader.run();
167.79 +
167.80 + lemon::DigraphReader<Digraph> reader2(digraph, std::cin);
167.81 +}
167.82 +
167.83 +void checkDigraphWriterCompile() {
167.84 + typedef lemon::concepts::Digraph Digraph;
167.85 + Digraph digraph;
167.86 + Digraph::NodeMap<int> node_map(digraph);
167.87 + Digraph::ArcMap<int> arc_map(digraph);
167.88 + Digraph::Node node;
167.89 + Digraph::Arc arc;
167.90 + int attr;
167.91 +
167.92 + lemon::DigraphWriter<Digraph> writer(digraph, "filename");
167.93 + writer.nodeMap("node_map", node_map);
167.94 + writer.nodeMap("node_map", node_map, WriterConverter());
167.95 + writer.arcMap("arc_map", arc_map);
167.96 + writer.arcMap("arc_map", arc_map, WriterConverter());
167.97 + writer.attribute("attr", attr);
167.98 + writer.attribute("attr", attr, WriterConverter());
167.99 + writer.node("node", node);
167.100 + writer.arc("arc", arc);
167.101 +
167.102 + writer.nodes("alt_nodes_caption");
167.103 + writer.arcs("alt_arcs_caption");
167.104 + writer.attributes("alt_attrs_caption");
167.105 +
167.106 + writer.skipNodes();
167.107 + writer.skipArcs();
167.108 +
167.109 + writer.run();
167.110 +}
167.111 +
167.112 +void checkGraphReaderCompile() {
167.113 + typedef lemon::concepts::ExtendableGraphComponent<
167.114 + lemon::concepts::Graph> Graph;
167.115 + Graph graph;
167.116 + Graph::NodeMap<int> node_map(graph);
167.117 + Graph::ArcMap<int> arc_map(graph);
167.118 + Graph::EdgeMap<int> edge_map(graph);
167.119 + Graph::Node node;
167.120 + Graph::Arc arc;
167.121 + Graph::Edge edge;
167.122 + int attr;
167.123 +
167.124 + lemon::GraphReader<Graph> reader(graph, "filename");
167.125 + reader.nodeMap("node_map", node_map);
167.126 + reader.nodeMap("node_map", node_map, ReaderConverter());
167.127 + reader.arcMap("arc_map", arc_map);
167.128 + reader.arcMap("arc_map", arc_map, ReaderConverter());
167.129 + reader.edgeMap("edge_map", edge_map);
167.130 + reader.edgeMap("edge_map", edge_map, ReaderConverter());
167.131 + reader.attribute("attr", attr);
167.132 + reader.attribute("attr", attr, ReaderConverter());
167.133 + reader.node("node", node);
167.134 + reader.arc("arc", arc);
167.135 +
167.136 + reader.nodes("alt_nodes_caption");
167.137 + reader.edges("alt_edges_caption");
167.138 + reader.attributes("alt_attrs_caption");
167.139 +
167.140 + reader.useNodes(node_map);
167.141 + reader.useNodes(node_map, WriterConverter());
167.142 + reader.useEdges(edge_map);
167.143 + reader.useEdges(edge_map, WriterConverter());
167.144 +
167.145 + reader.skipNodes();
167.146 + reader.skipEdges();
167.147 +
167.148 + reader.run();
167.149 +
167.150 + lemon::GraphReader<Graph> reader2(graph, std::cin);
167.151 +}
167.152 +
167.153 +void checkGraphWriterCompile() {
167.154 + typedef lemon::concepts::Graph Graph;
167.155 + Graph graph;
167.156 + Graph::NodeMap<int> node_map(graph);
167.157 + Graph::ArcMap<int> arc_map(graph);
167.158 + Graph::EdgeMap<int> edge_map(graph);
167.159 + Graph::Node node;
167.160 + Graph::Arc arc;
167.161 + Graph::Edge edge;
167.162 + int attr;
167.163 +
167.164 + lemon::GraphWriter<Graph> writer(graph, "filename");
167.165 + writer.nodeMap("node_map", node_map);
167.166 + writer.nodeMap("node_map", node_map, WriterConverter());
167.167 + writer.arcMap("arc_map", arc_map);
167.168 + writer.arcMap("arc_map", arc_map, WriterConverter());
167.169 + writer.edgeMap("edge_map", edge_map);
167.170 + writer.edgeMap("edge_map", edge_map, WriterConverter());
167.171 + writer.attribute("attr", attr);
167.172 + writer.attribute("attr", attr, WriterConverter());
167.173 + writer.node("node", node);
167.174 + writer.arc("arc", arc);
167.175 + writer.edge("edge", edge);
167.176 +
167.177 + writer.nodes("alt_nodes_caption");
167.178 + writer.edges("alt_edges_caption");
167.179 + writer.attributes("alt_attrs_caption");
167.180 +
167.181 + writer.skipNodes();
167.182 + writer.skipEdges();
167.183 +
167.184 + writer.run();
167.185 +
167.186 + lemon::GraphWriter<Graph> writer2(graph, std::cout);
167.187 +}
167.188 +
167.189 +void checkBpGraphReaderCompile() {
167.190 + typedef lemon::concepts::ExtendableBpGraphComponent<
167.191 + lemon::concepts::BpGraph> BpGraph;
167.192 + BpGraph graph;
167.193 + BpGraph::NodeMap<int> node_map(graph);
167.194 + BpGraph::RedNodeMap<int> red_node_map(graph);
167.195 + BpGraph::BlueNodeMap<int> blue_node_map(graph);
167.196 + BpGraph::ArcMap<int> arc_map(graph);
167.197 + BpGraph::EdgeMap<int> edge_map(graph);
167.198 + BpGraph::Node node;
167.199 + BpGraph::RedNode red_node;
167.200 + BpGraph::BlueNode blue_node;
167.201 + BpGraph::Arc arc;
167.202 + BpGraph::Edge edge;
167.203 + int attr;
167.204 +
167.205 + lemon::BpGraphReader<BpGraph> reader(graph, "filename");
167.206 + reader.nodeMap("node_map", node_map);
167.207 + reader.nodeMap("node_map", node_map, ReaderConverter());
167.208 + reader.redNodeMap("red_node_map", red_node_map);
167.209 + reader.redNodeMap("red_node_map", red_node_map, ReaderConverter());
167.210 + reader.blueNodeMap("blue_node_map", blue_node_map);
167.211 + reader.blueNodeMap("blue_node_map", blue_node_map, ReaderConverter());
167.212 + reader.arcMap("arc_map", arc_map);
167.213 + reader.arcMap("arc_map", arc_map, ReaderConverter());
167.214 + reader.edgeMap("edge_map", edge_map);
167.215 + reader.edgeMap("edge_map", edge_map, ReaderConverter());
167.216 + reader.attribute("attr", attr);
167.217 + reader.attribute("attr", attr, ReaderConverter());
167.218 + reader.node("node", node);
167.219 + reader.redNode("red_node", red_node);
167.220 + reader.blueNode("blue_node", blue_node);
167.221 + reader.arc("arc", arc);
167.222 +
167.223 + reader.nodes("alt_nodes_caption");
167.224 + reader.edges("alt_edges_caption");
167.225 + reader.attributes("alt_attrs_caption");
167.226 +
167.227 + reader.useNodes(node_map);
167.228 + reader.useNodes(node_map, WriterConverter());
167.229 + reader.useEdges(edge_map);
167.230 + reader.useEdges(edge_map, WriterConverter());
167.231 +
167.232 + reader.skipNodes();
167.233 + reader.skipEdges();
167.234 +
167.235 + reader.run();
167.236 +
167.237 + lemon::BpGraphReader<BpGraph> reader2(graph, std::cin);
167.238 +}
167.239 +
167.240 +void checkBpGraphWriterCompile() {
167.241 + typedef lemon::concepts::BpGraph BpGraph;
167.242 + BpGraph graph;
167.243 + BpGraph::NodeMap<int> node_map(graph);
167.244 + BpGraph::RedNodeMap<int> red_node_map(graph);
167.245 + BpGraph::BlueNodeMap<int> blue_node_map(graph);
167.246 + BpGraph::ArcMap<int> arc_map(graph);
167.247 + BpGraph::EdgeMap<int> edge_map(graph);
167.248 + BpGraph::Node node;
167.249 + BpGraph::RedNode red_node;
167.250 + BpGraph::BlueNode blue_node;
167.251 + BpGraph::Arc arc;
167.252 + BpGraph::Edge edge;
167.253 + int attr;
167.254 +
167.255 + lemon::BpGraphWriter<BpGraph> writer(graph, "filename");
167.256 + writer.nodeMap("node_map", node_map);
167.257 + writer.nodeMap("node_map", node_map, WriterConverter());
167.258 + writer.redNodeMap("red_node_map", red_node_map);
167.259 + writer.redNodeMap("red_node_map", red_node_map, WriterConverter());
167.260 + writer.blueNodeMap("blue_node_map", blue_node_map);
167.261 + writer.blueNodeMap("blue_node_map", blue_node_map, WriterConverter());
167.262 + writer.arcMap("arc_map", arc_map);
167.263 + writer.arcMap("arc_map", arc_map, WriterConverter());
167.264 + writer.edgeMap("edge_map", edge_map);
167.265 + writer.edgeMap("edge_map", edge_map, WriterConverter());
167.266 + writer.attribute("attr", attr);
167.267 + writer.attribute("attr", attr, WriterConverter());
167.268 + writer.node("node", node);
167.269 + writer.redNode("red_node", red_node);
167.270 + writer.blueNode("blue_node", blue_node);
167.271 + writer.arc("arc", arc);
167.272 +
167.273 + writer.nodes("alt_nodes_caption");
167.274 + writer.edges("alt_edges_caption");
167.275 + writer.attributes("alt_attrs_caption");
167.276 +
167.277 + writer.skipNodes();
167.278 + writer.skipEdges();
167.279 +
167.280 + writer.run();
167.281 +
167.282 + lemon::BpGraphWriter<BpGraph> writer2(graph, std::cout);
167.283 +}
167.284 +
167.285 +void checkDigraphReaderWriter() {
167.286 + typedef lemon::SmartDigraph Digraph;
167.287 + Digraph digraph;
167.288 + Digraph::Node n1 = digraph.addNode();
167.289 + Digraph::Node n2 = digraph.addNode();
167.290 + Digraph::Node n3 = digraph.addNode();
167.291 +
167.292 + Digraph::Arc a1 = digraph.addArc(n1, n2);
167.293 + Digraph::Arc a2 = digraph.addArc(n2, n3);
167.294 +
167.295 + Digraph::NodeMap<int> node_map(digraph);
167.296 + node_map[n1] = 11;
167.297 + node_map[n2] = 12;
167.298 + node_map[n3] = 13;
167.299 +
167.300 + Digraph::ArcMap<int> arc_map(digraph);
167.301 + arc_map[a1] = 21;
167.302 + arc_map[a2] = 22;
167.303 +
167.304 + int attr = 100;
167.305 +
167.306 + std::ostringstream os;
167.307 + lemon::DigraphWriter<Digraph> writer(digraph, os);
167.308 +
167.309 + writer.nodeMap("node_map1", node_map);
167.310 + writer.nodeMap("node_map2", node_map, WriterConverter());
167.311 + writer.arcMap("arc_map1", arc_map);
167.312 + writer.arcMap("arc_map2", arc_map, WriterConverter());
167.313 + writer.node("node", n2);
167.314 + writer.arc("arc", a1);
167.315 + writer.attribute("attr1", attr);
167.316 + writer.attribute("attr2", attr, WriterConverter());
167.317 +
167.318 + writer.run();
167.319 +
167.320 + typedef lemon::ListDigraph ExpDigraph;
167.321 + ExpDigraph exp_digraph;
167.322 + ExpDigraph::NodeMap<int> exp_node_map1(exp_digraph);
167.323 + ExpDigraph::NodeMap<int> exp_node_map2(exp_digraph);
167.324 + ExpDigraph::ArcMap<int> exp_arc_map1(exp_digraph);
167.325 + ExpDigraph::ArcMap<int> exp_arc_map2(exp_digraph);
167.326 + ExpDigraph::Node exp_n2;
167.327 + ExpDigraph::Arc exp_a1;
167.328 + int exp_attr1;
167.329 + int exp_attr2;
167.330 +
167.331 + std::istringstream is(os.str());
167.332 + lemon::DigraphReader<ExpDigraph> reader(exp_digraph, is);
167.333 +
167.334 + reader.nodeMap("node_map1", exp_node_map1);
167.335 + reader.nodeMap("node_map2", exp_node_map2, ReaderConverter());
167.336 + reader.arcMap("arc_map1", exp_arc_map1);
167.337 + reader.arcMap("arc_map2", exp_arc_map2, ReaderConverter());
167.338 + reader.node("node", exp_n2);
167.339 + reader.arc("arc", exp_a1);
167.340 + reader.attribute("attr1", exp_attr1);
167.341 + reader.attribute("attr2", exp_attr2, ReaderConverter());
167.342 +
167.343 + reader.run();
167.344 +
167.345 + check(lemon::countNodes(exp_digraph) == 3, "Wrong number of nodes");
167.346 + check(lemon::countArcs(exp_digraph) == 2, "Wrong number of arcs");
167.347 + check(exp_node_map1[exp_n2] == 12, "Wrong map value");
167.348 + check(exp_node_map2[exp_n2] == 12, "Wrong map value");
167.349 + check(exp_arc_map1[exp_a1] == 21, "Wrong map value");
167.350 + check(exp_arc_map2[exp_a1] == 21, "Wrong map value");
167.351 + check(exp_attr1 == 100, "Wrong attr value");
167.352 + check(exp_attr2 == 100, "Wrong attr value");
167.353 +}
167.354 +
167.355 +void checkGraphReaderWriter() {
167.356 + typedef lemon::SmartGraph Graph;
167.357 + Graph graph;
167.358 + Graph::Node n1 = graph.addNode();
167.359 + Graph::Node n2 = graph.addNode();
167.360 + Graph::Node n3 = graph.addNode();
167.361 +
167.362 + Graph::Edge e1 = graph.addEdge(n1, n2);
167.363 + Graph::Edge e2 = graph.addEdge(n2, n3);
167.364 +
167.365 + Graph::NodeMap<int> node_map(graph);
167.366 + node_map[n1] = 11;
167.367 + node_map[n2] = 12;
167.368 + node_map[n3] = 13;
167.369 +
167.370 + Graph::EdgeMap<int> edge_map(graph);
167.371 + edge_map[e1] = 21;
167.372 + edge_map[e2] = 22;
167.373 +
167.374 + Graph::ArcMap<int> arc_map(graph);
167.375 + arc_map[graph.direct(e1, true)] = 211;
167.376 + arc_map[graph.direct(e1, false)] = 212;
167.377 + arc_map[graph.direct(e2, true)] = 221;
167.378 + arc_map[graph.direct(e2, false)] = 222;
167.379 +
167.380 + int attr = 100;
167.381 +
167.382 + std::ostringstream os;
167.383 + lemon::GraphWriter<Graph> writer(graph, os);
167.384 +
167.385 + writer.nodeMap("node_map1", node_map);
167.386 + writer.nodeMap("node_map2", node_map, WriterConverter());
167.387 + writer.edgeMap("edge_map1", edge_map);
167.388 + writer.edgeMap("edge_map2", edge_map, WriterConverter());
167.389 + writer.arcMap("arc_map1", arc_map);
167.390 + writer.arcMap("arc_map2", arc_map, WriterConverter());
167.391 + writer.node("node", n2);
167.392 + writer.edge("edge", e1);
167.393 + writer.arc("arc", graph.direct(e1, false));
167.394 + writer.attribute("attr1", attr);
167.395 + writer.attribute("attr2", attr, WriterConverter());
167.396 +
167.397 + writer.run();
167.398 +
167.399 + typedef lemon::ListGraph ExpGraph;
167.400 + ExpGraph exp_graph;
167.401 + ExpGraph::NodeMap<int> exp_node_map1(exp_graph);
167.402 + ExpGraph::NodeMap<int> exp_node_map2(exp_graph);
167.403 + ExpGraph::EdgeMap<int> exp_edge_map1(exp_graph);
167.404 + ExpGraph::EdgeMap<int> exp_edge_map2(exp_graph);
167.405 + ExpGraph::ArcMap<int> exp_arc_map1(exp_graph);
167.406 + ExpGraph::ArcMap<int> exp_arc_map2(exp_graph);
167.407 + ExpGraph::Node exp_n2;
167.408 + ExpGraph::Edge exp_e1;
167.409 + ExpGraph::Arc exp_a1;
167.410 + int exp_attr1;
167.411 + int exp_attr2;
167.412 +
167.413 + std::istringstream is(os.str());
167.414 + lemon::GraphReader<ExpGraph> reader(exp_graph, is);
167.415 +
167.416 + reader.nodeMap("node_map1", exp_node_map1);
167.417 + reader.nodeMap("node_map2", exp_node_map2, ReaderConverter());
167.418 + reader.edgeMap("edge_map1", exp_edge_map1);
167.419 + reader.edgeMap("edge_map2", exp_edge_map2, ReaderConverter());
167.420 + reader.arcMap("arc_map1", exp_arc_map1);
167.421 + reader.arcMap("arc_map2", exp_arc_map2, ReaderConverter());
167.422 + reader.node("node", exp_n2);
167.423 + reader.edge("edge", exp_e1);
167.424 + reader.arc("arc", exp_a1);
167.425 + reader.attribute("attr1", exp_attr1);
167.426 + reader.attribute("attr2", exp_attr2, ReaderConverter());
167.427 +
167.428 + reader.run();
167.429 +
167.430 + check(lemon::countNodes(exp_graph) == 3, "Wrong number of nodes");
167.431 + check(lemon::countEdges(exp_graph) == 2, "Wrong number of edges");
167.432 + check(lemon::countArcs(exp_graph) == 4, "Wrong number of arcs");
167.433 + check(exp_node_map1[exp_n2] == 12, "Wrong map value");
167.434 + check(exp_node_map2[exp_n2] == 12, "Wrong map value");
167.435 + check(exp_edge_map1[exp_e1] == 21, "Wrong map value");
167.436 + check(exp_edge_map2[exp_e1] == 21, "Wrong map value");
167.437 + check(exp_arc_map1[exp_a1] == 212, "Wrong map value");
167.438 + check(exp_arc_map2[exp_a1] == 212, "Wrong map value");
167.439 + check(exp_attr1 == 100, "Wrong attr value");
167.440 + check(exp_attr2 == 100, "Wrong attr value");
167.441 +}
167.442 +
167.443 +void checkBpGraphReaderWriter() {
167.444 + typedef lemon::SmartBpGraph Graph;
167.445 + Graph graph;
167.446 + Graph::RedNode rn1 = graph.addRedNode();
167.447 + Graph::RedNode rn2 = graph.addRedNode();
167.448 + Graph::RedNode rn3 = graph.addRedNode();
167.449 + Graph::BlueNode bn1 = graph.addBlueNode();
167.450 + Graph::BlueNode bn2 = graph.addBlueNode();
167.451 + Graph::Node n = bn1;
167.452 +
167.453 + Graph::Edge e1 = graph.addEdge(rn1, bn1);
167.454 + Graph::Edge e2 = graph.addEdge(rn2, bn1);
167.455 +
167.456 + Graph::NodeMap<int> node_map(graph);
167.457 + node_map[rn1] = 11;
167.458 + node_map[rn2] = 12;
167.459 + node_map[rn3] = 13;
167.460 + node_map[bn1] = 14;
167.461 + node_map[bn2] = 15;
167.462 +
167.463 + Graph::NodeMap<int> red_node_map(graph);
167.464 + red_node_map[rn1] = 411;
167.465 + red_node_map[rn2] = 412;
167.466 + red_node_map[rn3] = 413;
167.467 +
167.468 + Graph::NodeMap<int> blue_node_map(graph);
167.469 + blue_node_map[bn1] = 414;
167.470 + blue_node_map[bn2] = 415;
167.471 +
167.472 + Graph::EdgeMap<int> edge_map(graph);
167.473 + edge_map[e1] = 21;
167.474 + edge_map[e2] = 22;
167.475 +
167.476 + Graph::ArcMap<int> arc_map(graph);
167.477 + arc_map[graph.direct(e1, true)] = 211;
167.478 + arc_map[graph.direct(e1, false)] = 212;
167.479 + arc_map[graph.direct(e2, true)] = 221;
167.480 + arc_map[graph.direct(e2, false)] = 222;
167.481 +
167.482 + int attr = 100;
167.483 +
167.484 + std::ostringstream os;
167.485 + lemon::BpGraphWriter<Graph> writer(graph, os);
167.486 +
167.487 + writer.nodeMap("node_map1", node_map);
167.488 + writer.nodeMap("node_map2", node_map, WriterConverter());
167.489 + writer.nodeMap("red_node_map1", red_node_map);
167.490 + writer.nodeMap("red_node_map2", red_node_map, WriterConverter());
167.491 + writer.nodeMap("blue_node_map1", blue_node_map);
167.492 + writer.nodeMap("blue_node_map2", blue_node_map, WriterConverter());
167.493 + writer.edgeMap("edge_map1", edge_map);
167.494 + writer.edgeMap("edge_map2", edge_map, WriterConverter());
167.495 + writer.arcMap("arc_map1", arc_map);
167.496 + writer.arcMap("arc_map2", arc_map, WriterConverter());
167.497 + writer.node("node", n);
167.498 + writer.redNode("red_node", rn1);
167.499 + writer.blueNode("blue_node", bn2);
167.500 + writer.edge("edge", e1);
167.501 + writer.arc("arc", graph.direct(e1, false));
167.502 + writer.attribute("attr1", attr);
167.503 + writer.attribute("attr2", attr, WriterConverter());
167.504 +
167.505 + writer.run();
167.506 +
167.507 + typedef lemon::ListBpGraph ExpGraph;
167.508 + ExpGraph exp_graph;
167.509 + ExpGraph::NodeMap<int> exp_node_map1(exp_graph);
167.510 + ExpGraph::NodeMap<int> exp_node_map2(exp_graph);
167.511 + ExpGraph::RedNodeMap<int> exp_red_node_map1(exp_graph);
167.512 + ExpGraph::RedNodeMap<int> exp_red_node_map2(exp_graph);
167.513 + ExpGraph::BlueNodeMap<int> exp_blue_node_map1(exp_graph);
167.514 + ExpGraph::BlueNodeMap<int> exp_blue_node_map2(exp_graph);
167.515 + ExpGraph::EdgeMap<int> exp_edge_map1(exp_graph);
167.516 + ExpGraph::EdgeMap<int> exp_edge_map2(exp_graph);
167.517 + ExpGraph::ArcMap<int> exp_arc_map1(exp_graph);
167.518 + ExpGraph::ArcMap<int> exp_arc_map2(exp_graph);
167.519 + ExpGraph::Node exp_n;
167.520 + ExpGraph::RedNode exp_rn1;
167.521 + ExpGraph::BlueNode exp_bn2;
167.522 + ExpGraph::Edge exp_e1;
167.523 + ExpGraph::Arc exp_a1;
167.524 + int exp_attr1;
167.525 + int exp_attr2;
167.526 +
167.527 + std::istringstream is(os.str());
167.528 + lemon::BpGraphReader<ExpGraph> reader(exp_graph, is);
167.529 +
167.530 + reader.nodeMap("node_map1", exp_node_map1);
167.531 + reader.nodeMap("node_map2", exp_node_map2, ReaderConverter());
167.532 + reader.redNodeMap("red_node_map1", exp_red_node_map1);
167.533 + reader.redNodeMap("red_node_map2", exp_red_node_map2, ReaderConverter());
167.534 + reader.blueNodeMap("blue_node_map1", exp_blue_node_map1);
167.535 + reader.blueNodeMap("blue_node_map2", exp_blue_node_map2, ReaderConverter());
167.536 + reader.edgeMap("edge_map1", exp_edge_map1);
167.537 + reader.edgeMap("edge_map2", exp_edge_map2, ReaderConverter());
167.538 + reader.arcMap("arc_map1", exp_arc_map1);
167.539 + reader.arcMap("arc_map2", exp_arc_map2, ReaderConverter());
167.540 + reader.node("node", exp_n);
167.541 + reader.redNode("red_node", exp_rn1);
167.542 + reader.blueNode("blue_node", exp_bn2);
167.543 + reader.edge("edge", exp_e1);
167.544 + reader.arc("arc", exp_a1);
167.545 + reader.attribute("attr1", exp_attr1);
167.546 + reader.attribute("attr2", exp_attr2, ReaderConverter());
167.547 +
167.548 + reader.run();
167.549 +
167.550 + check(lemon::countNodes(exp_graph) == 5, "Wrong number of nodes");
167.551 + check(lemon::countRedNodes(exp_graph) == 3, "Wrong number of red nodes");
167.552 + check(lemon::countBlueNodes(exp_graph) == 2, "Wrong number of blue nodes");
167.553 + check(lemon::countEdges(exp_graph) == 2, "Wrong number of edges");
167.554 + check(lemon::countArcs(exp_graph) == 4, "Wrong number of arcs");
167.555 + check(exp_node_map1[exp_n] == 14, "Wrong map value");
167.556 + check(exp_node_map2[exp_n] == 14, "Wrong map value");
167.557 + check(exp_red_node_map1[exp_rn1] == 411, "Wrong map value");
167.558 + check(exp_red_node_map2[exp_rn1] == 411, "Wrong map value");
167.559 + check(exp_blue_node_map1[exp_bn2] == 415, "Wrong map value");
167.560 + check(exp_blue_node_map2[exp_bn2] == 415, "Wrong map value");
167.561 + check(exp_edge_map1[exp_e1] == 21, "Wrong map value");
167.562 + check(exp_edge_map2[exp_e1] == 21, "Wrong map value");
167.563 + check(exp_arc_map1[exp_a1] == 212, "Wrong map value");
167.564 + check(exp_arc_map2[exp_a1] == 212, "Wrong map value");
167.565 + check(exp_attr1 == 100, "Wrong attr value");
167.566 + check(exp_attr2 == 100, "Wrong attr value");
167.567 +}
167.568 +
167.569 +
167.570 +int main() {
167.571 + { // Check digrpah
167.572 + checkDigraphReaderWriter();
167.573 + }
167.574 + { // Check graph
167.575 + checkGraphReaderWriter();
167.576 + }
167.577 + { // Check bipartite graph
167.578 + checkBpGraphReaderWriter();
167.579 + }
167.580 + return 0;
167.581 +}
168.1 --- a/test/lgf_test.cc Mon Jul 16 16:21:40 2018 +0200
168.2 +++ b/test/lgf_test.cc Wed Oct 17 19:14:07 2018 +0200
168.3 @@ -2,7 +2,7 @@
168.4 *
168.5 * This file is a part of LEMON, a generic C++ optimization library.
168.6 *
168.7 - * Copyright (C) 2003-2011
168.8 + * Copyright (C) 2003-2013
168.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
168.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
168.11 *
168.12 @@ -63,10 +63,10 @@
168.13 "0 1\n";
168.14
168.15
168.16 -int main()
168.17 +int main()
168.18 {
168.19 {
168.20 - ListDigraph d;
168.21 + ListDigraph d;
168.22 ListDigraph::Node s,t;
168.23 ListDigraph::ArcMap<int> label(d);
168.24 std::istringstream input(test_lgf);
168.25 @@ -93,7 +93,7 @@
168.26 }
168.27
168.28 {
168.29 - ListDigraph d;
168.30 + ListDigraph d;
168.31 std::istringstream input(test_lgf_nomap);
168.32 digraphReader(d, input).
168.33 run();
168.34 @@ -110,14 +110,14 @@
168.35 }
168.36
168.37 {
168.38 - ListDigraph d;
168.39 + ListDigraph d;
168.40 std::istringstream input(test_lgf_bad1);
168.41 bool ok=false;
168.42 try {
168.43 digraphReader(d, input).
168.44 run();
168.45 }
168.46 - catch (FormatError&)
168.47 + catch (FormatError&)
168.48 {
168.49 ok = true;
168.50 }
168.51 @@ -139,7 +139,7 @@
168.52 }
168.53
168.54 {
168.55 - ListDigraph d;
168.56 + ListDigraph d;
168.57 std::istringstream input(test_lgf_bad2);
168.58 bool ok=false;
168.59 try {
169.1 --- a/test/lp_test.cc Mon Jul 16 16:21:40 2018 +0200
169.2 +++ b/test/lp_test.cc Wed Oct 17 19:14:07 2018 +0200
169.3 @@ -2,7 +2,7 @@
169.4 *
169.5 * This file is a part of LEMON, a generic C++ optimization library.
169.6 *
169.7 - * Copyright (C) 2003-2009
169.8 + * Copyright (C) 2003-2013
169.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
169.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
169.11 *
169.12 @@ -39,6 +39,9 @@
169.13 #include <lemon/clp.h>
169.14 #endif
169.15
169.16 +#ifdef LEMON_HAVE_LP
169.17 +#include <lemon/lp.h>
169.18 +#endif
169.19 using namespace lemon;
169.20
169.21 int countCols(LpBase & lp) {
169.22 @@ -198,7 +201,12 @@
169.23 LP::Constr c = v >= -3;
169.24 c = c <= 4;
169.25 LP::Constr c2;
169.26 +#if ( __GNUC__ == 4 ) && ( __GNUC_MINOR__ == 3 )
169.27 + c2 = ( -3 <= v ) <= 4;
169.28 +#else
169.29 c2 = -3 <= v <= 4;
169.30 +#endif
169.31 +
169.32 }
169.33
169.34 e[x[3]]=2;
169.35 @@ -240,8 +248,7 @@
169.36
169.37 {
169.38 LP::DualExpr e,f,g;
169.39 - LP::Row p1 = INVALID, p2 = INVALID, p3 = INVALID,
169.40 - p4 = INVALID, p5 = INVALID;
169.41 + LP::Row p1 = INVALID, p2 = INVALID;
169.42
169.43 e[p1]=2;
169.44 e[p1]+=2;
169.45 @@ -412,6 +419,15 @@
169.46 LpSkeleton lp_skel;
169.47 lpTest(lp_skel);
169.48
169.49 +#ifdef LEMON_HAVE_LP
169.50 + {
169.51 + Lp lp,lp2;
169.52 + lpTest(lp);
169.53 + aTest(lp2);
169.54 + cloneTest<Lp>();
169.55 + }
169.56 +#endif
169.57 +
169.58 #ifdef LEMON_HAVE_GLPK
169.59 {
169.60 GlpkLp lp_glpk1,lp_glpk2;
170.1 --- a/test/maps_test.cc Mon Jul 16 16:21:40 2018 +0200
170.2 +++ b/test/maps_test.cc Wed Oct 17 19:14:07 2018 +0200
170.3 @@ -2,7 +2,7 @@
170.4 *
170.5 * This file is a part of LEMON, a generic C++ optimization library.
170.6 *
170.7 - * Copyright (C) 2003-2010
170.8 + * Copyright (C) 2003-2013
170.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
170.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
170.11 *
170.12 @@ -103,7 +103,7 @@
170.13 checkConcept<ReadWriteMap<A,B>, NullMap<A,B> >();
170.14 NullMap<A,B> map1;
170.15 NullMap<A,B> map2 = map1;
170.16 - ignore_unused_variable_warning(map2);
170.17 + ::lemon::ignore_unused_variable_warning(map2);
170.18 map1 = nullMap<A,B>();
170.19 }
170.20
170.21 @@ -114,14 +114,14 @@
170.22 ConstMap<A,B> map1;
170.23 ConstMap<A,B> map2 = B();
170.24 ConstMap<A,B> map3 = map1;
170.25 - ignore_unused_variable_warning(map2,map3);
170.26 + ::lemon::ignore_unused_variable_warning(map2,map3);
170.27
170.28 map1 = constMap<A>(B());
170.29 map1 = constMap<A,B>();
170.30 map1.setAll(B());
170.31 ConstMap<A,C> map4(C(1));
170.32 ConstMap<A,C> map5 = map4;
170.33 - ignore_unused_variable_warning(map5);
170.34 + ::lemon::ignore_unused_variable_warning(map5);
170.35
170.36 map4 = constMap<A>(C(2));
170.37 map4.setAll(C(3));
170.38 @@ -143,7 +143,7 @@
170.39 checkConcept<ReadMap<A,A>, IdentityMap<A> >();
170.40 IdentityMap<A> map1;
170.41 IdentityMap<A> map2 = map1;
170.42 - ignore_unused_variable_warning(map2);
170.43 + ::lemon::ignore_unused_variable_warning(map2);
170.44
170.45 map1 = identityMap<A>();
170.46
170.47 @@ -204,9 +204,9 @@
170.48 typedef ComposeMap<DoubleMap, ReadMap<B,A> > CompMap;
170.49 checkConcept<ReadMap<B,double>, CompMap>();
170.50 CompMap map1 = CompMap(DoubleMap(),ReadMap<B,A>());
170.51 - ignore_unused_variable_warning(map1);
170.52 + ::lemon::ignore_unused_variable_warning(map1);
170.53 CompMap map2 = composeMap(DoubleMap(), ReadMap<B,A>());
170.54 - ignore_unused_variable_warning(map2);
170.55 + ::lemon::ignore_unused_variable_warning(map2);
170.56
170.57 SparseMap<double, bool> m1(false); m1[3.14] = true;
170.58 RangeMap<double> m2(2); m2[0] = 3.0; m2[1] = 3.14;
170.59 @@ -219,9 +219,9 @@
170.60 typedef CombineMap<DoubleMap, DoubleMap, std::plus<double> > CombMap;
170.61 checkConcept<ReadMap<A,double>, CombMap>();
170.62 CombMap map1 = CombMap(DoubleMap(), DoubleMap());
170.63 - ignore_unused_variable_warning(map1);
170.64 + ::lemon::ignore_unused_variable_warning(map1);
170.65 CombMap map2 = combineMap(DoubleMap(), DoubleMap(), std::plus<double>());
170.66 - ignore_unused_variable_warning(map2);
170.67 + ::lemon::ignore_unused_variable_warning(map2);
170.68
170.69 check(combineMap(constMap<B,int,2>(), identityMap<B>(), &binc)[B()] == 3,
170.70 "Something is wrong with CombineMap");
170.71 @@ -233,15 +233,15 @@
170.72 checkConcept<ReadMap<A,B>, FunctorToMap<F> >();
170.73 FunctorToMap<F> map1;
170.74 FunctorToMap<F> map2 = FunctorToMap<F>(F());
170.75 - ignore_unused_variable_warning(map2);
170.76 + ::lemon::ignore_unused_variable_warning(map2);
170.77
170.78 B b = functorToMap(F())[A()];
170.79 - ignore_unused_variable_warning(b);
170.80 + ::lemon::ignore_unused_variable_warning(b);
170.81
170.82 checkConcept<ReadMap<A,B>, MapToFunctor<ReadMap<A,B> > >();
170.83 MapToFunctor<ReadMap<A,B> > map =
170.84 MapToFunctor<ReadMap<A,B> >(ReadMap<A,B>());
170.85 - ignore_unused_variable_warning(map);
170.86 + ::lemon::ignore_unused_variable_warning(map);
170.87
170.88 check(functorToMap(&func)[A()] == 3,
170.89 "Something is wrong with FunctorToMap");
170.90 @@ -259,9 +259,9 @@
170.91 checkConcept<ReadMap<double,double>,
170.92 ConvertMap<ReadMap<double, int>, double> >();
170.93 ConvertMap<RangeMap<bool>, int> map1(rangeMap(1, true));
170.94 - ignore_unused_variable_warning(map1);
170.95 + ::lemon::ignore_unused_variable_warning(map1);
170.96 ConvertMap<RangeMap<bool>, int> map2 = convertMap<int>(rangeMap(2, false));
170.97 - ignore_unused_variable_warning(map2);
170.98 + ::lemon::ignore_unused_variable_warning(map2);
170.99
170.100 }
170.101
170.102 @@ -535,7 +535,8 @@
170.103 "Wrong SourceMap or TargetMap");
170.104
170.105 typedef Orienter<Graph, const ConstMap<Edge, bool> > Digraph;
170.106 - Digraph dgr(gr, constMap<Edge, bool>(true));
170.107 + ConstMap<Edge, bool> true_edge_map(true);
170.108 + Digraph dgr(gr, true_edge_map);
170.109 OutDegMap<Digraph> odm(dgr);
170.110 InDegMap<Digraph> idm(dgr);
170.111
171.1 --- a/test/matching_test.cc Mon Jul 16 16:21:40 2018 +0200
171.2 +++ b/test/matching_test.cc Wed Oct 17 19:14:07 2018 +0200
171.3 @@ -2,7 +2,7 @@
171.4 *
171.5 * This file is a part of LEMON, a generic C++ optimization library.
171.6 *
171.7 - * Copyright (C) 2003-2010
171.8 + * Copyright (C) 2003-2013
171.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
171.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
171.11 *
171.12 @@ -145,6 +145,7 @@
171.13
171.14 MaxMatching<Graph>::Status stat =
171.15 const_mat_test.status(n);
171.16 + ::lemon::ignore_unused_variable_warning(stat);
171.17 const MaxMatching<Graph>::StatusMap& smap =
171.18 const_mat_test.statusMap();
171.19 stat = smap[n];
172.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
172.2 +++ b/test/max_cardinality_search_test.cc Wed Oct 17 19:14:07 2018 +0200
172.3 @@ -0,0 +1,162 @@
172.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
172.5 + *
172.6 + * This file is a part of LEMON, a generic C++ optimization library.
172.7 + *
172.8 + * Copyright (C) 2003-2013
172.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
172.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
172.11 + *
172.12 + * Permission to use, modify and distribute this software is granted
172.13 + * provided that this copyright notice appears in all copies. For
172.14 + * precise terms see the accompanying LICENSE file.
172.15 + *
172.16 + * This software is provided "AS IS" with no warranty of any kind,
172.17 + * express or implied, and with no claim as to its suitability for any
172.18 + * purpose.
172.19 + *
172.20 + */
172.21 +
172.22 +#include <iostream>
172.23 +
172.24 +#include "test_tools.h"
172.25 +#include <lemon/smart_graph.h>
172.26 +#include <lemon/max_cardinality_search.h>
172.27 +#include <lemon/concepts/digraph.h>
172.28 +#include <lemon/concepts/maps.h>
172.29 +#include <lemon/concepts/heap.h>
172.30 +#include <lemon/lgf_reader.h>
172.31 +
172.32 +using namespace lemon;
172.33 +using namespace std;
172.34 +
172.35 +char test_lgf[] =
172.36 + "@nodes\n"
172.37 + "label\n"
172.38 + "0\n"
172.39 + "1\n"
172.40 + "2\n"
172.41 + "3\n"
172.42 + "@arcs\n"
172.43 + " label capacity\n"
172.44 + "0 1 0 2\n"
172.45 + "1 0 1 2\n"
172.46 + "2 1 2 1\n"
172.47 + "2 3 3 3\n"
172.48 + "3 2 4 3\n"
172.49 + "3 1 5 5\n"
172.50 + "@attributes\n"
172.51 + "s 0\n"
172.52 + "x 1\n"
172.53 + "y 2\n"
172.54 + "z 3\n";
172.55 +
172.56 +void checkMaxCardSearchCompile() {
172.57 +
172.58 + typedef concepts::Digraph Digraph;
172.59 + typedef int Value;
172.60 + typedef Digraph::Node Node;
172.61 + typedef Digraph::Arc Arc;
172.62 + typedef concepts::ReadMap<Arc,Value> CapMap;
172.63 + typedef concepts::ReadWriteMap<Node,Value> CardMap;
172.64 + typedef concepts::ReadWriteMap<Node,bool> ProcMap;
172.65 + typedef Digraph::NodeMap<int> HeapCrossRef;
172.66 +
172.67 + Digraph g;
172.68 + Node n,s;
172.69 + CapMap cap;
172.70 + CardMap card;
172.71 + ProcMap proc;
172.72 + HeapCrossRef crossref(g);
172.73 +
172.74 + typedef MaxCardinalitySearch<Digraph,CapMap>
172.75 + ::SetCapacityMap<CapMap>
172.76 + ::SetCardinalityMap<CardMap>
172.77 + ::SetProcessedMap<ProcMap>
172.78 + ::SetStandardHeap<BinHeap<Value,HeapCrossRef> >
172.79 + ::Create MaxCardType;
172.80 +
172.81 + MaxCardType maxcard(g,cap);
172.82 + const MaxCardType& const_maxcard = maxcard;
172.83 +
172.84 + const MaxCardType::Heap& heap_const = const_maxcard.heap();
172.85 + MaxCardType::Heap& heap = const_cast<MaxCardType::Heap&>(heap_const);
172.86 + maxcard.heap(heap,crossref);
172.87 +
172.88 + maxcard.capacityMap(cap).cardinalityMap(card).processedMap(proc);
172.89 +
172.90 + maxcard.init();
172.91 + maxcard.addSource(s);
172.92 + n = maxcard.nextNode();
172.93 + maxcard.processNextNode();
172.94 + maxcard.start();
172.95 + maxcard.run(s);
172.96 + maxcard.run();
172.97 + }
172.98 +
172.99 + void checkWithIntMap( std::istringstream& input)
172.100 + {
172.101 + typedef SmartDigraph Digraph;
172.102 + typedef Digraph::Node Node;
172.103 + typedef Digraph::ArcMap<int> CapMap;
172.104 +
172.105 + Digraph g;
172.106 + Node s,x,y,z,a;
172.107 + CapMap cap(g);
172.108 +
172.109 + DigraphReader<Digraph>(g,input).
172.110 + arcMap("capacity", cap).
172.111 + node("s",s).
172.112 + node("x",x).
172.113 + node("y",y).
172.114 + node("z",z).
172.115 + run();
172.116 +
172.117 + MaxCardinalitySearch<Digraph,CapMap> maxcard(g,cap);
172.118 +
172.119 + maxcard.init();
172.120 + maxcard.addSource(s);
172.121 + maxcard.start(x);
172.122 +
172.123 + check(maxcard.processed(s) && !maxcard.processed(x) &&
172.124 + !maxcard.processed(y), "Wrong processed()!");
172.125 +
172.126 + a=maxcard.nextNode();
172.127 + check(maxcard.processNextNode()==a,
172.128 + "Wrong nextNode() or processNextNode() return value!");
172.129 +
172.130 + check(maxcard.processed(a), "Wrong processNextNode()!");
172.131 +
172.132 + maxcard.start();
172.133 + check(maxcard.cardinality(x)==2 && maxcard.cardinality(y)>=4,
172.134 + "Wrong cardinalities!");
172.135 + }
172.136 +
172.137 + void checkWithConst1Map(std::istringstream &input) {
172.138 + typedef SmartDigraph Digraph;
172.139 + typedef Digraph::Node Node;
172.140 +
172.141 + Digraph g;
172.142 + Node s,x,y,z;
172.143 +
172.144 + DigraphReader<Digraph>(g,input).
172.145 + node("s",s).
172.146 + node("x",x).
172.147 + node("y",y).
172.148 + node("z",z).
172.149 + run();
172.150 +
172.151 + MaxCardinalitySearch<Digraph> maxcard(g);
172.152 + maxcard.run(s);
172.153 + check(maxcard.cardinality(x)==1 &&
172.154 + maxcard.cardinality(y)+maxcard.cardinality(z)==3,
172.155 + "Wrong cardinalities!");
172.156 +}
172.157 +
172.158 +int main() {
172.159 +
172.160 + std::istringstream input1(test_lgf);
172.161 + checkWithIntMap(input1);
172.162 +
172.163 + std::istringstream input2(test_lgf);
172.164 + checkWithConst1Map(input2);
172.165 +}
173.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
173.2 +++ b/test/max_clique_test.cc Wed Oct 17 19:14:07 2018 +0200
173.3 @@ -0,0 +1,188 @@
173.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
173.5 + *
173.6 + * This file is a part of LEMON, a generic C++ optimization library.
173.7 + *
173.8 + * Copyright (C) 2003-2013
173.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
173.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
173.11 + *
173.12 + * Permission to use, modify and distribute this software is granted
173.13 + * provided that this copyright notice appears in all copies. For
173.14 + * precise terms see the accompanying LICENSE file.
173.15 + *
173.16 + * This software is provided "AS IS" with no warranty of any kind,
173.17 + * express or implied, and with no claim as to its suitability for any
173.18 + * purpose.
173.19 + *
173.20 + */
173.21 +
173.22 +#include <sstream>
173.23 +#include <lemon/list_graph.h>
173.24 +#include <lemon/full_graph.h>
173.25 +#include <lemon/grid_graph.h>
173.26 +#include <lemon/lgf_reader.h>
173.27 +#include <lemon/grosso_locatelli_pullan_mc.h>
173.28 +
173.29 +#include "test_tools.h"
173.30 +
173.31 +using namespace lemon;
173.32 +
173.33 +char test_lgf[] =
173.34 + "@nodes\n"
173.35 + "label max_clique\n"
173.36 + "1 0\n"
173.37 + "2 0\n"
173.38 + "3 0\n"
173.39 + "4 1\n"
173.40 + "5 1\n"
173.41 + "6 1\n"
173.42 + "7 1\n"
173.43 + "@edges\n"
173.44 + " label\n"
173.45 + "1 2 1\n"
173.46 + "1 3 2\n"
173.47 + "1 4 3\n"
173.48 + "1 6 4\n"
173.49 + "2 3 5\n"
173.50 + "2 5 6\n"
173.51 + "2 7 7\n"
173.52 + "3 4 8\n"
173.53 + "3 5 9\n"
173.54 + "4 5 10\n"
173.55 + "4 6 11\n"
173.56 + "4 7 12\n"
173.57 + "5 6 13\n"
173.58 + "5 7 14\n"
173.59 + "6 7 15\n";
173.60 +
173.61 +
173.62 +// Check with general graphs
173.63 +template <typename Param>
173.64 +void checkMaxCliqueGeneral(Param rule) {
173.65 + typedef ListGraph GR;
173.66 + typedef GrossoLocatelliPullanMc<GR> McAlg;
173.67 + typedef McAlg::CliqueNodeIt CliqueIt;
173.68 +
173.69 + // Basic tests
173.70 + {
173.71 + GR g;
173.72 + GR::NodeMap<bool> map(g);
173.73 + McAlg mc(g);
173.74 + mc.iterationLimit(50);
173.75 + check(mc.run(rule) == McAlg::SIZE_LIMIT, "Wrong termination cause");
173.76 + check(mc.cliqueSize() == 0, "Wrong clique size");
173.77 + check(CliqueIt(mc) == INVALID, "Wrong CliqueNodeIt");
173.78 +
173.79 + GR::Node u = g.addNode();
173.80 + check(mc.run(rule) == McAlg::SIZE_LIMIT, "Wrong termination cause");
173.81 + check(mc.cliqueSize() == 1, "Wrong clique size");
173.82 + mc.cliqueMap(map);
173.83 + check(map[u], "Wrong clique map");
173.84 + CliqueIt it1(mc);
173.85 + check(static_cast<GR::Node>(it1) == u && ++it1 == INVALID,
173.86 + "Wrong CliqueNodeIt");
173.87 +
173.88 + GR::Node v = g.addNode();
173.89 + check(mc.run(rule) == McAlg::ITERATION_LIMIT, "Wrong termination cause");
173.90 + check(mc.cliqueSize() == 1, "Wrong clique size");
173.91 + mc.cliqueMap(map);
173.92 + check((map[u] && !map[v]) || (map[v] && !map[u]), "Wrong clique map");
173.93 + CliqueIt it2(mc);
173.94 + check(it2 != INVALID && ++it2 == INVALID, "Wrong CliqueNodeIt");
173.95 +
173.96 + g.addEdge(u, v);
173.97 + check(mc.run(rule) == McAlg::SIZE_LIMIT, "Wrong termination cause");
173.98 + check(mc.cliqueSize() == 2, "Wrong clique size");
173.99 + mc.cliqueMap(map);
173.100 + check(map[u] && map[v], "Wrong clique map");
173.101 + CliqueIt it3(mc);
173.102 + check(it3 != INVALID && ++it3 != INVALID && ++it3 == INVALID,
173.103 + "Wrong CliqueNodeIt");
173.104 + }
173.105 +
173.106 + // Test graph
173.107 + {
173.108 + GR g;
173.109 + GR::NodeMap<bool> max_clique(g);
173.110 + GR::NodeMap<bool> map(g);
173.111 + std::istringstream input(test_lgf);
173.112 + graphReader(g, input)
173.113 + .nodeMap("max_clique", max_clique)
173.114 + .run();
173.115 +
173.116 + McAlg mc(g);
173.117 + mc.iterationLimit(50);
173.118 + check(mc.run(rule) == McAlg::ITERATION_LIMIT, "Wrong termination cause");
173.119 + check(mc.cliqueSize() == 4, "Wrong clique size");
173.120 + mc.cliqueMap(map);
173.121 + for (GR::NodeIt n(g); n != INVALID; ++n) {
173.122 + check(map[n] == max_clique[n], "Wrong clique map");
173.123 + }
173.124 + int cnt = 0;
173.125 + for (CliqueIt n(mc); n != INVALID; ++n) {
173.126 + cnt++;
173.127 + check(map[n] && max_clique[n], "Wrong CliqueNodeIt");
173.128 + }
173.129 + check(cnt == 4, "Wrong CliqueNodeIt");
173.130 + }
173.131 +}
173.132 +
173.133 +// Check with full graphs
173.134 +template <typename Param>
173.135 +void checkMaxCliqueFullGraph(Param rule) {
173.136 + typedef FullGraph GR;
173.137 + typedef GrossoLocatelliPullanMc<FullGraph> McAlg;
173.138 + typedef McAlg::CliqueNodeIt CliqueIt;
173.139 +
173.140 + for (int size = 0; size <= 40; size = size * 3 + 1) {
173.141 + GR g(size);
173.142 + GR::NodeMap<bool> map(g);
173.143 + McAlg mc(g);
173.144 + check(mc.run(rule) == McAlg::SIZE_LIMIT, "Wrong termination cause");
173.145 + check(mc.cliqueSize() == size, "Wrong clique size");
173.146 + mc.cliqueMap(map);
173.147 + for (GR::NodeIt n(g); n != INVALID; ++n) {
173.148 + check(map[n], "Wrong clique map");
173.149 + }
173.150 + int cnt = 0;
173.151 + for (CliqueIt n(mc); n != INVALID; ++n) cnt++;
173.152 + check(cnt == size, "Wrong CliqueNodeIt");
173.153 + }
173.154 +}
173.155 +
173.156 +// Check with grid graphs
173.157 +template <typename Param>
173.158 +void checkMaxCliqueGridGraph(Param rule) {
173.159 + GridGraph g(5, 7);
173.160 + GridGraph::NodeMap<char> map(g);
173.161 + GrossoLocatelliPullanMc<GridGraph> mc(g);
173.162 +
173.163 + mc.iterationLimit(100);
173.164 + check(mc.run(rule) == mc.ITERATION_LIMIT, "Wrong termination cause");
173.165 + check(mc.cliqueSize() == 2, "Wrong clique size");
173.166 +
173.167 + mc.stepLimit(100);
173.168 + check(mc.run(rule) == mc.STEP_LIMIT, "Wrong termination cause");
173.169 + check(mc.cliqueSize() == 2, "Wrong clique size");
173.170 +
173.171 + mc.sizeLimit(2);
173.172 + check(mc.run(rule) == mc.SIZE_LIMIT, "Wrong termination cause");
173.173 + check(mc.cliqueSize() == 2, "Wrong clique size");
173.174 +}
173.175 +
173.176 +
173.177 +int main() {
173.178 + checkMaxCliqueGeneral(GrossoLocatelliPullanMc<ListGraph>::RANDOM);
173.179 + checkMaxCliqueGeneral(GrossoLocatelliPullanMc<ListGraph>::DEGREE_BASED);
173.180 + checkMaxCliqueGeneral(GrossoLocatelliPullanMc<ListGraph>::PENALTY_BASED);
173.181 +
173.182 + checkMaxCliqueFullGraph(GrossoLocatelliPullanMc<FullGraph>::RANDOM);
173.183 + checkMaxCliqueFullGraph(GrossoLocatelliPullanMc<FullGraph>::DEGREE_BASED);
173.184 + checkMaxCliqueFullGraph(GrossoLocatelliPullanMc<FullGraph>::PENALTY_BASED);
173.185 +
173.186 + checkMaxCliqueGridGraph(GrossoLocatelliPullanMc<GridGraph>::RANDOM);
173.187 + checkMaxCliqueGridGraph(GrossoLocatelliPullanMc<GridGraph>::DEGREE_BASED);
173.188 + checkMaxCliqueGridGraph(GrossoLocatelliPullanMc<GridGraph>::PENALTY_BASED);
173.189 +
173.190 + return 0;
173.191 +}
174.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
174.2 +++ b/test/max_flow_test.cc Wed Oct 17 19:14:07 2018 +0200
174.3 @@ -0,0 +1,440 @@
174.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
174.5 + *
174.6 + * This file is a part of LEMON, a generic C++ optimization library.
174.7 + *
174.8 + * Copyright (C) 2003-2013
174.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
174.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
174.11 + *
174.12 + * Permission to use, modify and distribute this software is granted
174.13 + * provided that this copyright notice appears in all copies. For
174.14 + * precise terms see the accompanying LICENSE file.
174.15 + *
174.16 + * This software is provided "AS IS" with no warranty of any kind,
174.17 + * express or implied, and with no claim as to its suitability for any
174.18 + * purpose.
174.19 + *
174.20 + */
174.21 +
174.22 +#include <iostream>
174.23 +
174.24 +#include "test_tools.h"
174.25 +#include <lemon/smart_graph.h>
174.26 +#include <lemon/preflow.h>
174.27 +#include <lemon/edmonds_karp.h>
174.28 +#include <lemon/concepts/digraph.h>
174.29 +#include <lemon/concepts/maps.h>
174.30 +#include <lemon/lgf_reader.h>
174.31 +#include <lemon/elevator.h>
174.32 +#include <lemon/tolerance.h>
174.33 +
174.34 +using namespace lemon;
174.35 +
174.36 +char test_lgf[] =
174.37 + "@nodes\n"
174.38 + "label\n"
174.39 + "0\n"
174.40 + "1\n"
174.41 + "2\n"
174.42 + "3\n"
174.43 + "4\n"
174.44 + "5\n"
174.45 + "6\n"
174.46 + "7\n"
174.47 + "8\n"
174.48 + "9\n"
174.49 + "@arcs\n"
174.50 + " label capacity\n"
174.51 + "0 1 0 20\n"
174.52 + "0 2 1 0\n"
174.53 + "1 1 2 3\n"
174.54 + "1 2 3 8\n"
174.55 + "1 3 4 8\n"
174.56 + "2 5 5 5\n"
174.57 + "3 2 6 5\n"
174.58 + "3 5 7 5\n"
174.59 + "3 6 8 5\n"
174.60 + "4 3 9 3\n"
174.61 + "5 7 10 3\n"
174.62 + "5 6 11 10\n"
174.63 + "5 8 12 10\n"
174.64 + "6 8 13 8\n"
174.65 + "8 9 14 20\n"
174.66 + "8 1 15 5\n"
174.67 + "9 5 16 5\n"
174.68 + "@attributes\n"
174.69 + "source 1\n"
174.70 + "target 8\n";
174.71 +
174.72 +char test_lgf_float[] =
174.73 + "@nodes\n"
174.74 + "label\n"
174.75 + "0\n"
174.76 + "1\n"
174.77 + "2\n"
174.78 + "3\n"
174.79 + "4\n"
174.80 + "5\n"
174.81 + "6\n"
174.82 + "7\n"
174.83 + "8\n"
174.84 + "9\n"
174.85 + "@arcs\n"
174.86 + " capacity\n"
174.87 + "0 1 0.1\n"
174.88 + "0 2 0.1\n"
174.89 + "0 3 0.1\n"
174.90 + "1 4 0.1\n"
174.91 + "2 4 0.1\n"
174.92 + "3 4 0.1\n"
174.93 + "4 5 0.3\n"
174.94 + "5 6 0.1\n"
174.95 + "5 7 0.1\n"
174.96 + "5 8 0.1\n"
174.97 + "6 9 0.1\n"
174.98 + "7 9 0.1\n"
174.99 + "8 9 0.1\n"
174.100 + "@attributes\n"
174.101 + "source 0\n"
174.102 + "target 9\n";
174.103 +
174.104 +// Checks the general interface of a max flow algorithm
174.105 +template <typename GR, typename CAP>
174.106 +struct MaxFlowClassConcept
174.107 +{
174.108 +
174.109 + template <typename MF>
174.110 + struct Constraints {
174.111 +
174.112 + typedef typename GR::Node Node;
174.113 + typedef typename GR::Arc Arc;
174.114 + typedef typename CAP::Value Value;
174.115 + typedef concepts::ReadWriteMap<Arc, Value> FlowMap;
174.116 + typedef concepts::WriteMap<Node, bool> CutMap;
174.117 +
174.118 + GR g;
174.119 + Node n;
174.120 + Arc e;
174.121 + CAP cap;
174.122 + FlowMap flow;
174.123 + CutMap cut;
174.124 + Value v;
174.125 + bool b;
174.126 +
174.127 + void constraints() {
174.128 + checkConcept<concepts::Digraph, GR>();
174.129 +
174.130 + const Constraints& me = *this;
174.131 +
174.132 + typedef typename MF
174.133 + ::template SetFlowMap<FlowMap>
174.134 + ::Create MaxFlowType;
174.135 + typedef typename MF::Create MaxFlowType2;
174.136 + MaxFlowType max_flow(me.g, me.cap, me.n, me.n);
174.137 + const MaxFlowType& const_max_flow = max_flow;
174.138 +
174.139 + max_flow
174.140 + .capacityMap(cap)
174.141 + .flowMap(flow)
174.142 + .source(n)
174.143 + .target(n);
174.144 +
174.145 + typename MaxFlowType::Tolerance tol = const_max_flow.tolerance();
174.146 + max_flow.tolerance(tol);
174.147 +
174.148 + max_flow.init();
174.149 + max_flow.init(cap);
174.150 + max_flow.run();
174.151 +
174.152 + v = const_max_flow.flowValue();
174.153 + v = const_max_flow.flow(e);
174.154 + const FlowMap& fm = const_max_flow.flowMap();
174.155 +
174.156 + b = const_max_flow.minCut(n);
174.157 + const_max_flow.minCutMap(cut);
174.158 +
174.159 + ::lemon::ignore_unused_variable_warning(fm);
174.160 + }
174.161 +
174.162 + };
174.163 +
174.164 +};
174.165 +
174.166 +// Checks the specific parts of Preflow's interface
174.167 +void checkPreflowCompile()
174.168 +{
174.169 + typedef int Value;
174.170 + typedef concepts::Digraph Digraph;
174.171 + typedef concepts::ReadMap<Digraph::Arc, Value> CapMap;
174.172 + typedef Elevator<Digraph, Digraph::Node> Elev;
174.173 + typedef LinkedElevator<Digraph, Digraph::Node> LinkedElev;
174.174 +
174.175 + Digraph g;
174.176 + Digraph::Node n;
174.177 + CapMap cap;
174.178 +
174.179 + typedef Preflow<Digraph, CapMap>
174.180 + ::SetElevator<Elev>
174.181 + ::SetStandardElevator<LinkedElev>
174.182 + ::Create PreflowType;
174.183 + PreflowType preflow_test(g, cap, n, n);
174.184 + const PreflowType& const_preflow_test = preflow_test;
174.185 +
174.186 + const PreflowType::Elevator& elev = const_preflow_test.elevator();
174.187 + preflow_test.elevator(const_cast<PreflowType::Elevator&>(elev));
174.188 +
174.189 + bool b = preflow_test.init(cap);
174.190 + preflow_test.startFirstPhase();
174.191 + preflow_test.startSecondPhase();
174.192 + preflow_test.runMinCut();
174.193 +
174.194 + ::lemon::ignore_unused_variable_warning(b);
174.195 +}
174.196 +
174.197 +// Checks the specific parts of EdmondsKarp's interface
174.198 +void checkEdmondsKarpCompile()
174.199 +{
174.200 + typedef int Value;
174.201 + typedef concepts::Digraph Digraph;
174.202 + typedef concepts::ReadMap<Digraph::Arc, Value> CapMap;
174.203 +
174.204 + Digraph g;
174.205 + Digraph::Node n;
174.206 + CapMap cap;
174.207 +
174.208 + EdmondsKarp<Digraph, CapMap> ek_test(g, cap, n, n);
174.209 +
174.210 + ek_test.init(cap);
174.211 + bool b = ek_test.checkedInit(cap);
174.212 + b = ek_test.augment();
174.213 + ek_test.start();
174.214 +
174.215 + ::lemon::ignore_unused_variable_warning(b);
174.216 +}
174.217 +
174.218 +
174.219 +template <typename T>
174.220 +T cutValue(const SmartDigraph& g,
174.221 + const SmartDigraph::NodeMap<bool>& cut,
174.222 + const SmartDigraph::ArcMap<T>& cap) {
174.223 +
174.224 + T c = 0;
174.225 + for (SmartDigraph::ArcIt e(g); e != INVALID; ++e) {
174.226 + if (cut[g.source(e)] && !cut[g.target(e)]) c += cap[e];
174.227 + }
174.228 + return c;
174.229 +}
174.230 +
174.231 +template <typename T>
174.232 +bool checkFlow(const SmartDigraph& g,
174.233 + const SmartDigraph::ArcMap<T>& flow,
174.234 + const SmartDigraph::ArcMap<T>& cap,
174.235 + SmartDigraph::Node s, SmartDigraph::Node t,
174.236 + const Tolerance<T>& tol) {
174.237 +
174.238 + for (SmartDigraph::ArcIt e(g); e != INVALID; ++e) {
174.239 + if (tol.negative(flow[e]) || tol.less(cap[e], flow[e])) return false;
174.240 + }
174.241 +
174.242 + for (SmartDigraph::NodeIt n(g); n != INVALID; ++n) {
174.243 + if (n == s || n == t) continue;
174.244 + T sum = 0;
174.245 + for (SmartDigraph::OutArcIt e(g, n); e != INVALID; ++e) {
174.246 + sum += flow[e];
174.247 + }
174.248 + for (SmartDigraph::InArcIt e(g, n); e != INVALID; ++e) {
174.249 + sum -= flow[e];
174.250 + }
174.251 + if (tol.nonZero(sum)) return false;
174.252 + }
174.253 + return true;
174.254 +}
174.255 +
174.256 +void checkInitPreflow()
174.257 +{
174.258 + DIGRAPH_TYPEDEFS(SmartDigraph);
174.259 +
174.260 + SmartDigraph g;
174.261 + SmartDigraph::ArcMap<int> cap(g), iflow(g);
174.262 + Node s = g.addNode(); Node t = g.addNode();
174.263 + Node n1 = g.addNode(); Node n2 = g.addNode();
174.264 + Arc a;
174.265 + a = g.addArc(s, n1); cap[a] = 20; iflow[a] = 20;
174.266 + a = g.addArc(n1, n2); cap[a] = 10; iflow[a] = 0;
174.267 + a = g.addArc(n2, t); cap[a] = 20; iflow[a] = 0;
174.268 +
174.269 + Preflow<SmartDigraph> pre(g, cap, s, t);
174.270 + pre.init(iflow);
174.271 + pre.startFirstPhase();
174.272 +
174.273 + check(pre.flowValue() == 10, "Incorrect max flow value.");
174.274 + check(pre.minCut(s), "Wrong min cut (Node s).");
174.275 + check(pre.minCut(n1), "Wrong min cut (Node n1).");
174.276 + check(!pre.minCut(n2), "Wrong min cut (Node n2).");
174.277 + check(!pre.minCut(t), "Wrong min cut (Node t).");
174.278 +}
174.279 +
174.280 +template <typename MF, typename SF>
174.281 +void checkMaxFlowAlg(const char *input_lgf, typename MF::Value expected) {
174.282 + typedef SmartDigraph Digraph;
174.283 + DIGRAPH_TYPEDEFS(Digraph);
174.284 +
174.285 + typedef typename MF::Value Value;
174.286 + typedef Digraph::ArcMap<Value> CapMap;
174.287 + typedef CapMap FlowMap;
174.288 + typedef BoolNodeMap CutMap;
174.289 +
174.290 + Tolerance<Value> tol;
174.291 +
174.292 + Digraph g;
174.293 + Node s, t;
174.294 + CapMap cap(g);
174.295 + std::istringstream input(input_lgf);
174.296 + DigraphReader<Digraph>(g, input)
174.297 + .arcMap("capacity", cap)
174.298 + .node("source", s)
174.299 + .node("target", t)
174.300 + .run();
174.301 +
174.302 + MF max_flow(g, cap, s, t);
174.303 + max_flow.run();
174.304 +
174.305 + check(!tol.different(expected, max_flow.flowValue()),
174.306 + "Incorrect max flow value.");
174.307 + check(checkFlow(g, max_flow.flowMap(), cap, s, t, tol),
174.308 + "The flow is not feasible.");
174.309 +
174.310 + CutMap min_cut(g);
174.311 + max_flow.minCutMap(min_cut);
174.312 + Value min_cut_value = cutValue(g, min_cut, cap);
174.313 +
174.314 + check(!tol.different(expected, min_cut_value),
174.315 + "Incorrect min cut value.");
174.316 +
174.317 + FlowMap flow(g);
174.318 + for (ArcIt e(g); e != INVALID; ++e) flow[e] = 13 * max_flow.flowMap()[e];
174.319 + for (ArcIt e(g); e != INVALID; ++e) cap[e] = 17 * cap[e];
174.320 + max_flow.init(flow);
174.321 +
174.322 + SF::startFirstPhase(max_flow); // start first phase of the algorithm
174.323 +
174.324 + CutMap min_cut1(g);
174.325 + max_flow.minCutMap(min_cut1);
174.326 + min_cut_value = cutValue(g, min_cut1, cap);
174.327 +
174.328 + check(!tol.different(17 * expected, max_flow.flowValue()),
174.329 + "Incorrect max flow value.");
174.330 + check(!tol.different(17 * expected, min_cut_value),
174.331 + "Incorrect min cut value.");
174.332 +
174.333 + SF::startSecondPhase(max_flow); // start second phase of the algorithm
174.334 +
174.335 + check(checkFlow(g, max_flow.flowMap(), cap, s, t, tol),
174.336 + "The flow is not feasible.");
174.337 +
174.338 + CutMap min_cut2(g);
174.339 + max_flow.minCutMap(min_cut2);
174.340 + min_cut_value = cutValue(g, min_cut2, cap);
174.341 +
174.342 + check(!tol.different(17 * expected, max_flow.flowValue()),
174.343 + "Incorrect max flow value.");
174.344 + check(!tol.different(17 * expected, min_cut_value),
174.345 + "Incorrect min cut value.");
174.346 +
174.347 + max_flow.flowMap(flow);
174.348 +
174.349 + NodeIt tmp1(g, s);
174.350 + ++tmp1;
174.351 + if (tmp1 != INVALID) s = tmp1;
174.352 +
174.353 + NodeIt tmp2(g, t);
174.354 + ++tmp2;
174.355 + if (tmp2 != INVALID) t = tmp2;
174.356 +
174.357 + max_flow.source(s);
174.358 + max_flow.target(t);
174.359 +
174.360 + max_flow.run();
174.361 +
174.362 + CutMap min_cut3(g);
174.363 + max_flow.minCutMap(min_cut3);
174.364 + min_cut_value = cutValue(g, min_cut3, cap);
174.365 +
174.366 + check(!tol.different(max_flow.flowValue(), min_cut_value),
174.367 + "The max flow value or the min cut value is wrong.");
174.368 +}
174.369 +
174.370 +// Struct for calling start functions of a general max flow algorithm
174.371 +template <typename MF>
174.372 +struct GeneralStartFunctions {
174.373 +
174.374 + static void startFirstPhase(MF& mf) {
174.375 + mf.start();
174.376 + }
174.377 +
174.378 + static void startSecondPhase(MF& mf) {
174.379 + ::lemon::ignore_unused_variable_warning(mf);
174.380 + }
174.381 +
174.382 +};
174.383 +
174.384 +// Struct for calling start functions of Preflow
174.385 +template <typename MF>
174.386 +struct PreflowStartFunctions {
174.387 +
174.388 + static void startFirstPhase(MF& mf) {
174.389 + mf.startFirstPhase();
174.390 + }
174.391 +
174.392 + static void startSecondPhase(MF& mf) {
174.393 + mf.startSecondPhase();
174.394 + }
174.395 +
174.396 +};
174.397 +
174.398 +int main() {
174.399 +
174.400 + typedef concepts::Digraph GR;
174.401 + typedef concepts::ReadMap<GR::Arc, int> CM1;
174.402 + typedef concepts::ReadMap<GR::Arc, double> CM2;
174.403 +
174.404 + // Check the interface of Preflow
174.405 + checkConcept< MaxFlowClassConcept<GR, CM1>,
174.406 + Preflow<GR, CM1> >();
174.407 + checkConcept< MaxFlowClassConcept<GR, CM2>,
174.408 + Preflow<GR, CM2> >();
174.409 +
174.410 + // Check the interface of EdmondsKarp
174.411 + checkConcept< MaxFlowClassConcept<GR, CM1>,
174.412 + EdmondsKarp<GR, CM1> >();
174.413 + checkConcept< MaxFlowClassConcept<GR, CM2>,
174.414 + EdmondsKarp<GR, CM2> >();
174.415 +
174.416 + // Check Preflow
174.417 + typedef Preflow<SmartDigraph, SmartDigraph::ArcMap<int> > PType1;
174.418 + typedef Preflow<SmartDigraph, SmartDigraph::ArcMap<float> > PType2;
174.419 + typedef Preflow<SmartDigraph, SmartDigraph::ArcMap<double> > PType3;
174.420 +
174.421 + checkMaxFlowAlg<PType1, PreflowStartFunctions<PType1> >(test_lgf, 13);
174.422 + checkMaxFlowAlg<PType2, PreflowStartFunctions<PType2> >(test_lgf, 13);
174.423 + checkMaxFlowAlg<PType3, PreflowStartFunctions<PType3> >(test_lgf, 13);
174.424 +
174.425 + checkMaxFlowAlg<PType2, PreflowStartFunctions<PType2> >(test_lgf_float, 0.3f);
174.426 + checkMaxFlowAlg<PType3, PreflowStartFunctions<PType3> >(test_lgf_float, 0.3);
174.427 +
174.428 + checkInitPreflow();
174.429 +
174.430 + // Check EdmondsKarp
174.431 + typedef EdmondsKarp<SmartDigraph, SmartDigraph::ArcMap<int> > EKType1;
174.432 + typedef EdmondsKarp<SmartDigraph, SmartDigraph::ArcMap<float> > EKType2;
174.433 + typedef EdmondsKarp<SmartDigraph, SmartDigraph::ArcMap<double> > EKType3;
174.434 +
174.435 + checkMaxFlowAlg<EKType1, GeneralStartFunctions<EKType1> >(test_lgf, 13);
174.436 + checkMaxFlowAlg<EKType2, GeneralStartFunctions<EKType2> >(test_lgf, 13);
174.437 + checkMaxFlowAlg<EKType3, GeneralStartFunctions<EKType3> >(test_lgf, 13);
174.438 +
174.439 + checkMaxFlowAlg<EKType2, GeneralStartFunctions<EKType2> >(test_lgf_float, 0.3f);
174.440 + checkMaxFlowAlg<EKType3, GeneralStartFunctions<EKType3> >(test_lgf_float, 0.3);
174.441 +
174.442 + return 0;
174.443 +}
175.1 --- a/test/min_cost_arborescence_test.cc Mon Jul 16 16:21:40 2018 +0200
175.2 +++ b/test/min_cost_arborescence_test.cc Wed Oct 17 19:14:07 2018 +0200
175.3 @@ -2,7 +2,7 @@
175.4 *
175.5 * This file is a part of LEMON, a generic C++ optimization library.
175.6 *
175.7 - * Copyright (C) 2003-2010
175.8 + * Copyright (C) 2003-2013
175.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
175.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
175.11 *
175.12 @@ -91,6 +91,7 @@
175.13 Arc e;
175.14 VType c;
175.15 bool b;
175.16 + ::lemon::ignore_unused_variable_warning(c,b);
175.17 int i;
175.18 CostMap cost;
175.19 ArbMap arb;
175.20 @@ -126,8 +127,8 @@
175.21 i = const_mcarb_test.dualSize(i);
175.22 c = const_mcarb_test.dualValue(i);
175.23
175.24 - ignore_unused_variable_warning(am);
175.25 - ignore_unused_variable_warning(pm);
175.26 + ::lemon::ignore_unused_variable_warning(am);
175.27 + ::lemon::ignore_unused_variable_warning(pm);
175.28 }
175.29
175.30 int main() {
176.1 --- a/test/min_cost_flow_test.cc Mon Jul 16 16:21:40 2018 +0200
176.2 +++ b/test/min_cost_flow_test.cc Wed Oct 17 19:14:07 2018 +0200
176.3 @@ -2,7 +2,7 @@
176.4 *
176.5 * This file is a part of LEMON, a generic C++ optimization library.
176.6 *
176.7 - * Copyright (C) 2003-2010
176.8 + * Copyright (C) 2003-2013
176.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
176.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
176.11 *
176.12 @@ -395,6 +395,12 @@
176.13 mcf3.upperMap(neg2_u);
176.14 checkMcf(mcf3, mcf3.run(param), neg2_gr, neg2_l, neg2_u, neg2_c, neg2_s,
176.15 mcf3.OPTIMAL, true, -300, test_str + "-18", GEQ);
176.16 +
176.17 + // Tests for empty graph
176.18 + Digraph gr0;
176.19 + MCF mcf0(gr0);
176.20 + mcf0.run(param);
176.21 + check(mcf0.totalCost() == 0, "Wrong total cost");
176.22 }
176.23
176.24 template < typename MCF, typename Param >
177.1 --- a/test/min_mean_cycle_test.cc Mon Jul 16 16:21:40 2018 +0200
177.2 +++ b/test/min_mean_cycle_test.cc Wed Oct 17 19:14:07 2018 +0200
177.3 @@ -2,7 +2,7 @@
177.4 *
177.5 * This file is a part of LEMON, a generic C++ optimization library.
177.6 *
177.7 - * Copyright (C) 2003-2010
177.8 + * Copyright (C) 2003-2013
177.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
177.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
177.11 *
177.12 @@ -110,7 +110,7 @@
177.13 const SmartDigraph::ArcMap<int>& cm,
177.14 int cost, int size) {
177.15 MMC alg(gr, lm);
177.16 - alg.findCycleMean();
177.17 + check(alg.findCycleMean(), "Wrong result");
177.18 check(alg.cycleMean() == static_cast<double>(cost) / size,
177.19 "Wrong cycle mean");
177.20 alg.findCycle();
177.21 @@ -210,6 +210,13 @@
177.22 checkMmcAlg<HowardMmc<GR, IntArcMap> >(gr, l2, c2, 5, 2);
177.23 checkMmcAlg<HowardMmc<GR, IntArcMap> >(gr, l3, c3, 0, 1);
177.24 checkMmcAlg<HowardMmc<GR, IntArcMap> >(gr, l4, c4, -1, 1);
177.25 +
177.26 + // Howard with iteration limit
177.27 + HowardMmc<GR, IntArcMap> mmc(gr, l1);
177.28 + check((mmc.findCycleMean(2) == HowardMmc<GR, IntArcMap>::ITERATION_LIMIT),
177.29 + "Wrong termination cause");
177.30 + check((mmc.findCycleMean(4) == HowardMmc<GR, IntArcMap>::OPTIMAL),
177.31 + "Wrong termination cause");
177.32 }
177.33
177.34 return 0;
178.1 --- a/test/mip_test.cc Mon Jul 16 16:21:40 2018 +0200
178.2 +++ b/test/mip_test.cc Wed Oct 17 19:14:07 2018 +0200
178.3 @@ -32,6 +32,10 @@
178.4 #include <lemon/cbc.h>
178.5 #endif
178.6
178.7 +#ifdef LEMON_HAVE_MIP
178.8 +#include <lemon/lp.h>
178.9 +#endif
178.10 +
178.11
178.12 using namespace lemon;
178.13
178.14 @@ -128,6 +132,14 @@
178.15 int main()
178.16 {
178.17
178.18 +#ifdef LEMON_HAVE_MIP
178.19 + {
178.20 + Mip mip1;
178.21 + aTest(mip1);
178.22 + cloneTest<Mip>();
178.23 + }
178.24 +#endif
178.25 +
178.26 #ifdef LEMON_HAVE_GLPK
178.27 {
178.28 GlpkMip mip1;
179.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
179.2 +++ b/test/nagamochi_ibaraki_test.cc Wed Oct 17 19:14:07 2018 +0200
179.3 @@ -0,0 +1,142 @@
179.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
179.5 + *
179.6 + * This file is a part of LEMON, a generic C++ optimization library.
179.7 + *
179.8 + * Copyright (C) 2003-2013
179.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
179.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
179.11 + *
179.12 + * Permission to use, modify and distribute this software is granted
179.13 + * provided that this copyright notice appears in all copies. For
179.14 + * precise terms see the accompanying LICENSE file.
179.15 + *
179.16 + * This software is provided "AS IS" with no warranty of any kind,
179.17 + * express or implied, and with no claim as to its suitability for any
179.18 + * purpose.
179.19 + *
179.20 + */
179.21 +
179.22 +#include <sstream>
179.23 +
179.24 +#include <lemon/smart_graph.h>
179.25 +#include <lemon/adaptors.h>
179.26 +#include <lemon/concepts/graph.h>
179.27 +#include <lemon/concepts/maps.h>
179.28 +#include <lemon/lgf_reader.h>
179.29 +#include <lemon/nagamochi_ibaraki.h>
179.30 +
179.31 +#include "test_tools.h"
179.32 +
179.33 +using namespace lemon;
179.34 +using namespace std;
179.35 +
179.36 +const std::string lgf =
179.37 + "@nodes\n"
179.38 + "label\n"
179.39 + "0\n"
179.40 + "1\n"
179.41 + "2\n"
179.42 + "3\n"
179.43 + "4\n"
179.44 + "5\n"
179.45 + "@edges\n"
179.46 + " cap1 cap2 cap3\n"
179.47 + "0 1 1 1 1 \n"
179.48 + "0 2 2 2 4 \n"
179.49 + "1 2 4 4 4 \n"
179.50 + "3 4 1 1 1 \n"
179.51 + "3 5 2 2 4 \n"
179.52 + "4 5 4 4 4 \n"
179.53 + "2 3 1 6 6 \n";
179.54 +
179.55 +void checkNagamochiIbarakiCompile()
179.56 +{
179.57 + typedef int Value;
179.58 + typedef concepts::Graph Graph;
179.59 +
179.60 + typedef Graph::Node Node;
179.61 + typedef Graph::Edge Edge;
179.62 + typedef concepts::ReadMap<Edge, Value> CapMap;
179.63 + typedef concepts::WriteMap<Node, bool> CutMap;
179.64 +
179.65 + Graph g;
179.66 + Node n;
179.67 + CapMap cap;
179.68 + CutMap cut;
179.69 + Value v;
179.70 + bool b;
179.71 + ::lemon::ignore_unused_variable_warning(v,b);
179.72 +
179.73 + NagamochiIbaraki<Graph, CapMap> ni_test(g, cap);
179.74 + const NagamochiIbaraki<Graph, CapMap>& const_ni_test = ni_test;
179.75 +
179.76 + ni_test.init();
179.77 + ni_test.start();
179.78 + b = ni_test.processNextPhase();
179.79 + ni_test.run();
179.80 +
179.81 + v = const_ni_test.minCutValue();
179.82 + v = const_ni_test.minCutMap(cut);
179.83 +}
179.84 +
179.85 +template <typename Graph, typename CapMap, typename CutMap>
179.86 +typename CapMap::Value
179.87 + cutValue(const Graph& graph, const CapMap& cap, const CutMap& cut)
179.88 +{
179.89 + typename CapMap::Value sum = 0;
179.90 + for (typename Graph::EdgeIt e(graph); e != INVALID; ++e) {
179.91 + if (cut[graph.u(e)] != cut[graph.v(e)]) {
179.92 + sum += cap[e];
179.93 + }
179.94 + }
179.95 + return sum;
179.96 +}
179.97 +
179.98 +int main() {
179.99 + SmartGraph graph;
179.100 + SmartGraph::EdgeMap<int> cap1(graph), cap2(graph), cap3(graph);
179.101 + SmartGraph::NodeMap<bool> cut(graph);
179.102 +
179.103 + istringstream input(lgf);
179.104 + graphReader(graph, input)
179.105 + .edgeMap("cap1", cap1)
179.106 + .edgeMap("cap2", cap2)
179.107 + .edgeMap("cap3", cap3)
179.108 + .run();
179.109 +
179.110 + {
179.111 + NagamochiIbaraki<SmartGraph> ni(graph, cap1);
179.112 + ni.run();
179.113 + ni.minCutMap(cut);
179.114 +
179.115 + check(ni.minCutValue() == 1, "Wrong cut value");
179.116 + check(ni.minCutValue() == cutValue(graph, cap1, cut), "Wrong cut value");
179.117 + }
179.118 + {
179.119 + NagamochiIbaraki<SmartGraph> ni(graph, cap2);
179.120 + ni.run();
179.121 + ni.minCutMap(cut);
179.122 +
179.123 + check(ni.minCutValue() == 3, "Wrong cut value");
179.124 + check(ni.minCutValue() == cutValue(graph, cap2, cut), "Wrong cut value");
179.125 + }
179.126 + {
179.127 + NagamochiIbaraki<SmartGraph> ni(graph, cap3);
179.128 + ni.run();
179.129 + ni.minCutMap(cut);
179.130 +
179.131 + check(ni.minCutValue() == 5, "Wrong cut value");
179.132 + check(ni.minCutValue() == cutValue(graph, cap3, cut), "Wrong cut value");
179.133 + }
179.134 + {
179.135 + NagamochiIbaraki<SmartGraph>::SetUnitCapacity::Create ni(graph);
179.136 + ni.run();
179.137 + ni.minCutMap(cut);
179.138 +
179.139 + ConstMap<SmartGraph::Edge, int> cap4(1);
179.140 + check(ni.minCutValue() == 1, "Wrong cut value");
179.141 + check(ni.minCutValue() == cutValue(graph, cap4, cut), "Wrong cut value");
179.142 + }
179.143 +
179.144 + return 0;
179.145 +}
180.1 --- a/test/path_test.cc Mon Jul 16 16:21:40 2018 +0200
180.2 +++ b/test/path_test.cc Wed Oct 17 19:14:07 2018 +0200
180.3 @@ -2,7 +2,7 @@
180.4 *
180.5 * This file is a part of LEMON, a generic C++ optimization library.
180.6 *
180.7 - * Copyright (C) 2003-2009
180.8 + * Copyright (C) 2003-2013
180.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
180.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
180.11 *
180.12 @@ -21,6 +21,7 @@
180.13
180.14 #include <lemon/concepts/path.h>
180.15 #include <lemon/concepts/digraph.h>
180.16 +#include <lemon/concept_check.h>
180.17
180.18 #include <lemon/path.h>
180.19 #include <lemon/list_graph.h>
180.20 @@ -30,44 +31,309 @@
180.21 using namespace std;
180.22 using namespace lemon;
180.23
180.24 -void check_concepts() {
180.25 - checkConcept<concepts::Path<ListDigraph>, concepts::Path<ListDigraph> >();
180.26 - checkConcept<concepts::Path<ListDigraph>, Path<ListDigraph> >();
180.27 - checkConcept<concepts::Path<ListDigraph>, SimplePath<ListDigraph> >();
180.28 - checkConcept<concepts::Path<ListDigraph>, StaticPath<ListDigraph> >();
180.29 - checkConcept<concepts::Path<ListDigraph>, ListPath<ListDigraph> >();
180.30 +template <typename GR>
180.31 +void checkConcepts() {
180.32 + checkConcept<concepts::Path<GR>, concepts::Path<GR> >();
180.33 + checkConcept<concepts::Path<GR>, Path<GR> >();
180.34 + checkConcept<concepts::Path<GR>, SimplePath<GR> >();
180.35 + checkConcept<concepts::Path<GR>, StaticPath<GR> >();
180.36 + checkConcept<concepts::Path<GR>, ListPath<GR> >();
180.37 +}
180.38 +
180.39 +// Conecpt checking for path structures
180.40 +void checkPathConcepts() {
180.41 + checkConcepts<concepts::Digraph>();
180.42 + checkConcepts<ListDigraph>();
180.43 }
180.44
180.45 // Check if proper copy consructor is called (use valgrind for testing)
180.46 -template<class _Path>
180.47 -void checkCopy()
180.48 -{
180.49 +template <typename GR, typename P1, typename P2>
180.50 +void checkCopy(typename GR::Arc a) {
180.51 + P1 p;
180.52 + p.addBack(a);
180.53 + P1 q;
180.54 + q = p;
180.55 + P1 r(p);
180.56 + P2 q2;
180.57 + q2 = p;
180.58 + P2 r2(p);
180.59 +}
180.60 +
180.61 +// Tests for copy constructors and assignment operators of paths
180.62 +void checkPathCopy() {
180.63 ListDigraph g;
180.64 - ListDigraph::Arc a = g.addArc(g.addNode(), g.addNode());
180.65 -
180.66 - _Path p,q;
180.67 - p.addBack(a);
180.68 - q=p;
180.69 - _Path r(p);
180.70 - StaticPath<ListDigraph> s(r);
180.71 + ListDigraph::Arc a = g.addArc(g.addNode(), g.addNode());
180.72 +
180.73 + typedef Path<ListDigraph> Path1;
180.74 + typedef SimplePath<ListDigraph> Path2;
180.75 + typedef ListPath<ListDigraph> Path3;
180.76 + typedef StaticPath<ListDigraph> Path4;
180.77 + checkCopy<ListDigraph, Path1, Path2>(a);
180.78 + checkCopy<ListDigraph, Path1, Path3>(a);
180.79 + checkCopy<ListDigraph, Path1, Path4>(a);
180.80 + checkCopy<ListDigraph, Path2, Path1>(a);
180.81 + checkCopy<ListDigraph, Path2, Path3>(a);
180.82 + checkCopy<ListDigraph, Path2, Path4>(a);
180.83 + checkCopy<ListDigraph, Path3, Path1>(a);
180.84 + checkCopy<ListDigraph, Path3, Path2>(a);
180.85 + checkCopy<ListDigraph, Path3, Path4>(a);
180.86 }
180.87 -
180.88 +
180.89 +// Class for testing path functions
180.90 +class CheckPathFunctions {
180.91 + typedef ListDigraph GR;
180.92 + DIGRAPH_TYPEDEFS(GR);
180.93 + GR gr;
180.94 + const GR& cgr;
180.95 + Node n1, n2, n3, n4;
180.96 + Node tmp_n;
180.97 + Arc a1, a2, a3, a4;
180.98 + Arc tmp_a;
180.99 +
180.100 +public:
180.101 +
180.102 + CheckPathFunctions() : cgr(gr) {
180.103 + n1 = gr.addNode();
180.104 + n2 = gr.addNode();
180.105 + n3 = gr.addNode();
180.106 + n4 = gr.addNode();
180.107 + a1 = gr.addArc(n1, n2);
180.108 + a2 = gr.addArc(n2, n3);
180.109 + a3 = gr.addArc(n3, n4);
180.110 + a4 = gr.addArc(n4, n1);
180.111 + }
180.112 +
180.113 + void run() {
180.114 + checkBackAndFrontInsertablePath<Path<GR> >();
180.115 + checkBackAndFrontInsertablePath<ListPath<GR> >();
180.116 + checkBackInsertablePath<SimplePath<GR> >();
180.117 +
180.118 + checkListPathSplitAndSplice();
180.119 + }
180.120 +
180.121 +private:
180.122 +
180.123 + template <typename P>
180.124 + void checkBackInsertablePath() {
180.125 +
180.126 + // Create and check empty path
180.127 + P p;
180.128 + const P& cp = p;
180.129 + check(cp.empty(), "The path is not empty");
180.130 + check(cp.length() == 0, "The path is not empty");
180.131 +// check(cp.front() == INVALID, "Wrong front()");
180.132 +// check(cp.back() == INVALID, "Wrong back()");
180.133 + typename P::ArcIt ai(cp);
180.134 + check(ai == INVALID, "Wrong ArcIt");
180.135 + check(pathSource(cgr, cp) == INVALID, "Wrong pathSource()");
180.136 + check(pathTarget(cgr, cp) == INVALID, "Wrong pathTarget()");
180.137 + check(checkPath(cgr, cp), "Wrong checkPath()");
180.138 + PathNodeIt<P> ni(cgr, cp);
180.139 + check(ni == INVALID, "Wrong PathNodeIt");
180.140 +
180.141 + // Check single-arc path
180.142 + p.addBack(a1);
180.143 + check(!cp.empty(), "Wrong empty()");
180.144 + check(cp.length() == 1, "Wrong length");
180.145 + check(cp.front() == a1, "Wrong front()");
180.146 + check(cp.back() == a1, "Wrong back()");
180.147 + check(cp.nth(0) == a1, "Wrong nth()");
180.148 + ai = cp.nthIt(0);
180.149 + check((tmp_a = ai) == a1, "Wrong nthIt()");
180.150 + check(++ai == INVALID, "Wrong nthIt()");
180.151 + typename P::ArcIt ai2(cp);
180.152 + check((tmp_a = ai2) == a1, "Wrong ArcIt");
180.153 + check(++ai2 == INVALID, "Wrong ArcIt");
180.154 + check(pathSource(cgr, cp) == n1, "Wrong pathSource()");
180.155 + check(pathTarget(cgr, cp) == n2, "Wrong pathTarget()");
180.156 + check(checkPath(cgr, cp), "Wrong checkPath()");
180.157 + PathNodeIt<P> ni2(cgr, cp);
180.158 + check((tmp_n = ni2) == n1, "Wrong PathNodeIt");
180.159 + check((tmp_n = ++ni2) == n2, "Wrong PathNodeIt");
180.160 + check(++ni2 == INVALID, "Wrong PathNodeIt");
180.161 +
180.162 + // Check adding more arcs
180.163 + p.addBack(a2);
180.164 + p.addBack(a3);
180.165 + check(!cp.empty(), "Wrong empty()");
180.166 + check(cp.length() == 3, "Wrong length");
180.167 + check(cp.front() == a1, "Wrong front()");
180.168 + check(cp.back() == a3, "Wrong back()");
180.169 + check(cp.nth(0) == a1, "Wrong nth()");
180.170 + check(cp.nth(1) == a2, "Wrong nth()");
180.171 + check(cp.nth(2) == a3, "Wrong nth()");
180.172 + typename P::ArcIt ai3(cp);
180.173 + check((tmp_a = ai3) == a1, "Wrong ArcIt");
180.174 + check((tmp_a = ++ai3) == a2, "Wrong nthIt()");
180.175 + check((tmp_a = ++ai3) == a3, "Wrong nthIt()");
180.176 + check(++ai3 == INVALID, "Wrong nthIt()");
180.177 + ai = cp.nthIt(0);
180.178 + check((tmp_a = ai) == a1, "Wrong nthIt()");
180.179 + check((tmp_a = ++ai) == a2, "Wrong nthIt()");
180.180 + ai = cp.nthIt(2);
180.181 + check((tmp_a = ai) == a3, "Wrong nthIt()");
180.182 + check(++ai == INVALID, "Wrong nthIt()");
180.183 + check(pathSource(cgr, cp) == n1, "Wrong pathSource()");
180.184 + check(pathTarget(cgr, cp) == n4, "Wrong pathTarget()");
180.185 + check(checkPath(cgr, cp), "Wrong checkPath()");
180.186 + PathNodeIt<P> ni3(cgr, cp);
180.187 + check((tmp_n = ni3) == n1, "Wrong PathNodeIt");
180.188 + check((tmp_n = ++ni3) == n2, "Wrong PathNodeIt");
180.189 + check((tmp_n = ++ni3) == n3, "Wrong PathNodeIt");
180.190 + check((tmp_n = ++ni3) == n4, "Wrong PathNodeIt");
180.191 + check(++ni3 == INVALID, "Wrong PathNodeIt");
180.192 +
180.193 + // Check arc removal and addition
180.194 + p.eraseBack();
180.195 + p.eraseBack();
180.196 + p.addBack(a2);
180.197 + check(!cp.empty(), "Wrong empty()");
180.198 + check(cp.length() == 2, "Wrong length");
180.199 + check(cp.front() == a1, "Wrong front()");
180.200 + check(cp.back() == a2, "Wrong back()");
180.201 + check(pathSource(cgr, cp) == n1, "Wrong pathSource()");
180.202 + check(pathTarget(cgr, cp) == n3, "Wrong pathTarget()");
180.203 + check(checkPath(cgr, cp), "Wrong checkPath()");
180.204 +
180.205 + // Check clear()
180.206 + p.clear();
180.207 + check(cp.empty(), "The path is not empty");
180.208 + check(cp.length() == 0, "The path is not empty");
180.209 +
180.210 + // Check inconsistent path
180.211 + p.addBack(a4);
180.212 + p.addBack(a2);
180.213 + p.addBack(a1);
180.214 + check(!cp.empty(), "Wrong empty()");
180.215 + check(cp.length() == 3, "Wrong length");
180.216 + check(cp.front() == a4, "Wrong front()");
180.217 + check(cp.back() == a1, "Wrong back()");
180.218 + check(pathSource(cgr, cp) == n4, "Wrong pathSource()");
180.219 + check(pathTarget(cgr, cp) == n2, "Wrong pathTarget()");
180.220 + check(!checkPath(cgr, cp), "Wrong checkPath()");
180.221 + }
180.222 +
180.223 + template <typename P>
180.224 + void checkBackAndFrontInsertablePath() {
180.225 +
180.226 + // Include back insertable test cases
180.227 + checkBackInsertablePath<P>();
180.228 +
180.229 + // Check front and back insertion
180.230 + P p;
180.231 + const P& cp = p;
180.232 + p.addFront(a4);
180.233 + p.addBack(a1);
180.234 + p.addFront(a3);
180.235 + check(!cp.empty(), "Wrong empty()");
180.236 + check(cp.length() == 3, "Wrong length");
180.237 + check(cp.front() == a3, "Wrong front()");
180.238 + check(cp.back() == a1, "Wrong back()");
180.239 + check(cp.nth(0) == a3, "Wrong nth()");
180.240 + check(cp.nth(1) == a4, "Wrong nth()");
180.241 + check(cp.nth(2) == a1, "Wrong nth()");
180.242 + typename P::ArcIt ai(cp);
180.243 + check((tmp_a = ai) == a3, "Wrong ArcIt");
180.244 + check((tmp_a = ++ai) == a4, "Wrong nthIt()");
180.245 + check((tmp_a = ++ai) == a1, "Wrong nthIt()");
180.246 + check(++ai == INVALID, "Wrong nthIt()");
180.247 + ai = cp.nthIt(0);
180.248 + check((tmp_a = ai) == a3, "Wrong nthIt()");
180.249 + check((tmp_a = ++ai) == a4, "Wrong nthIt()");
180.250 + ai = cp.nthIt(2);
180.251 + check((tmp_a = ai) == a1, "Wrong nthIt()");
180.252 + check(++ai == INVALID, "Wrong nthIt()");
180.253 + check(pathSource(cgr, cp) == n3, "Wrong pathSource()");
180.254 + check(pathTarget(cgr, cp) == n2, "Wrong pathTarget()");
180.255 + check(checkPath(cgr, cp), "Wrong checkPath()");
180.256 +
180.257 + // Check eraseFront()
180.258 + p.eraseFront();
180.259 + p.addBack(a2);
180.260 + check(!cp.empty(), "Wrong empty()");
180.261 + check(cp.length() == 3, "Wrong length");
180.262 + check(cp.front() == a4, "Wrong front()");
180.263 + check(cp.back() == a2, "Wrong back()");
180.264 + check(cp.nth(0) == a4, "Wrong nth()");
180.265 + check(cp.nth(1) == a1, "Wrong nth()");
180.266 + check(cp.nth(2) == a2, "Wrong nth()");
180.267 + typename P::ArcIt ai2(cp);
180.268 + check((tmp_a = ai2) == a4, "Wrong ArcIt");
180.269 + check((tmp_a = ++ai2) == a1, "Wrong nthIt()");
180.270 + check((tmp_a = ++ai2) == a2, "Wrong nthIt()");
180.271 + check(++ai2 == INVALID, "Wrong nthIt()");
180.272 + ai = cp.nthIt(0);
180.273 + check((tmp_a = ai) == a4, "Wrong nthIt()");
180.274 + check((tmp_a = ++ai) == a1, "Wrong nthIt()");
180.275 + ai = cp.nthIt(2);
180.276 + check((tmp_a = ai) == a2, "Wrong nthIt()");
180.277 + check(++ai == INVALID, "Wrong nthIt()");
180.278 + check(pathSource(cgr, cp) == n4, "Wrong pathSource()");
180.279 + check(pathTarget(cgr, cp) == n3, "Wrong pathTarget()");
180.280 + check(checkPath(cgr, cp), "Wrong checkPath()");
180.281 + }
180.282 +
180.283 + void checkListPathSplitAndSplice() {
180.284 +
180.285 + // Build a path with spliceFront() and spliceBack()
180.286 + ListPath<GR> p1, p2, p3, p4;
180.287 + p1.addBack(a3);
180.288 + p1.addFront(a2);
180.289 + p2.addBack(a1);
180.290 + p1.spliceFront(p2);
180.291 + p3.addFront(a4);
180.292 + p1.spliceBack(p3);
180.293 + check(p1.length() == 4, "Wrong length");
180.294 + check(p1.front() == a1, "Wrong front()");
180.295 + check(p1.back() == a4, "Wrong back()");
180.296 + ListPath<GR>::ArcIt ai(p1);
180.297 + check((tmp_a = ai) == a1, "Wrong ArcIt");
180.298 + check((tmp_a = ++ai) == a2, "Wrong nthIt()");
180.299 + check((tmp_a = ++ai) == a3, "Wrong nthIt()");
180.300 + check((tmp_a = ++ai) == a4, "Wrong nthIt()");
180.301 + check(++ai == INVALID, "Wrong nthIt()");
180.302 + check(checkPath(cgr, p1), "Wrong checkPath()");
180.303 +
180.304 + // Check split()
180.305 + p1.split(p1.nthIt(2), p2);
180.306 + check(p1.length() == 2, "Wrong length");
180.307 + ai = p1.nthIt(0);
180.308 + check((tmp_a = ai) == a1, "Wrong ArcIt");
180.309 + check((tmp_a = ++ai) == a2, "Wrong nthIt()");
180.310 + check(++ai == INVALID, "Wrong nthIt()");
180.311 + check(checkPath(cgr, p1), "Wrong checkPath()");
180.312 + check(p2.length() == 2, "Wrong length");
180.313 + ai = p2.nthIt(0);
180.314 + check((tmp_a = ai) == a3, "Wrong ArcIt");
180.315 + check((tmp_a = ++ai) == a4, "Wrong nthIt()");
180.316 + check(++ai == INVALID, "Wrong nthIt()");
180.317 + check(checkPath(cgr, p2), "Wrong checkPath()");
180.318 +
180.319 + // Check split() and splice()
180.320 + p1.spliceFront(p2);
180.321 + p1.split(p1.nthIt(2), p2);
180.322 + p2.split(p2.nthIt(1), p3);
180.323 + p2.spliceBack(p1);
180.324 + p2.splice(p2.nthIt(1), p3);
180.325 + check(p2.length() == 4, "Wrong length");
180.326 + check(p2.front() == a1, "Wrong front()");
180.327 + check(p2.back() == a4, "Wrong back()");
180.328 + ai = p2.nthIt(0);
180.329 + check((tmp_a = ai) == a1, "Wrong ArcIt");
180.330 + check((tmp_a = ++ai) == a2, "Wrong nthIt()");
180.331 + check((tmp_a = ++ai) == a3, "Wrong nthIt()");
180.332 + check((tmp_a = ++ai) == a4, "Wrong nthIt()");
180.333 + check(++ai == INVALID, "Wrong nthIt()");
180.334 + check(checkPath(cgr, p2), "Wrong checkPath()");
180.335 + }
180.336 +
180.337 +};
180.338 +
180.339 int main() {
180.340 - check_concepts();
180.341 -
180.342 - checkCopy<Path<ListDigraph> >();
180.343 - checkCopy<SimplePath<ListDigraph> >();
180.344 - checkCopy<ListPath<ListDigraph> >();
180.345 -
180.346 - ListDigraph g;
180.347 - ListDigraph::Arc a = g.addArc(g.addNode(), g.addNode());
180.348 -
180.349 - Path<ListDigraph> p;
180.350 - StaticPath<ListDigraph> q,r;
180.351 - p.addBack(a);
180.352 - q=p;
180.353 - r=q;
180.354 - StaticPath<ListDigraph> s(q);
180.355 + checkPathConcepts();
180.356 + checkPathCopy();
180.357 + CheckPathFunctions cpf;
180.358 + cpf.run();
180.359
180.360 return 0;
180.361 }
181.1 --- a/test/planarity_test.cc Mon Jul 16 16:21:40 2018 +0200
181.2 +++ b/test/planarity_test.cc Wed Oct 17 19:14:07 2018 +0200
181.3 @@ -30,10 +30,40 @@
181.4 using namespace lemon;
181.5 using namespace lemon::dim2;
181.6
181.7 -const int lgfn = 4;
181.8 +const int lgfn = 8;
181.9 const std::string lgf[lgfn] = {
181.10 "@nodes\n"
181.11 "label\n"
181.12 + "@edges\n"
181.13 + " label\n",
181.14 +
181.15 + "@nodes\n"
181.16 + "label\n"
181.17 + "0\n"
181.18 + "@edges\n"
181.19 + " label\n",
181.20 +
181.21 + "@nodes\n"
181.22 + "label\n"
181.23 + "0\n"
181.24 + "1\n"
181.25 + "@edges\n"
181.26 + " label\n"
181.27 + "0 1 0\n",
181.28 +
181.29 + "@nodes\n"
181.30 + "label\n"
181.31 + "0\n"
181.32 + "1\n"
181.33 + "2\n"
181.34 + "@edges\n"
181.35 + " label\n"
181.36 + "0 1 0\n"
181.37 + "1 2 1\n"
181.38 + "2 0 2\n",
181.39 +
181.40 + "@nodes\n"
181.41 + "label\n"
181.42 "0\n"
181.43 "1\n"
181.44 "2\n"
181.45 @@ -136,8 +166,11 @@
181.46 ++face_num;
181.47 }
181.48 }
181.49 - check(face_num + countNodes(graph) - countConnectedComponents(graph) ==
181.50 - countEdges(graph) + 1, "Euler test does not passed");
181.51 +
181.52 + if (face_num != 0) {
181.53 + check(face_num + countNodes(graph) - countConnectedComponents(graph) ==
181.54 + countEdges(graph) + 1, "Euler test does not passed");
181.55 + }
181.56 }
181.57
181.58 void checkKuratowski(const Graph& graph, PE& pe) {
181.59 @@ -245,13 +278,29 @@
181.60 if (planar) {
181.61 checkEmbedding(graph, pe);
181.62
181.63 - PlanarDrawing<Graph> pd(graph);
181.64 - pd.run(pe.embeddingMap());
181.65 - checkDrawing(graph, pd);
181.66 + {
181.67 + PlanarDrawing<Graph> pd(graph);
181.68 + pd.run(pe.embeddingMap());
181.69 + checkDrawing(graph, pd);
181.70 + }
181.71
181.72 - PlanarColoring<Graph> pc(graph);
181.73 - pc.runFiveColoring(pe.embeddingMap());
181.74 - checkColoring(graph, pc, 5);
181.75 + {
181.76 + PlanarDrawing<Graph> pd(graph);
181.77 + pd.run();
181.78 + checkDrawing(graph, pd);
181.79 + }
181.80 +
181.81 + {
181.82 + PlanarColoring<Graph> pc(graph);
181.83 + pc.runFiveColoring(pe.embeddingMap());
181.84 + checkColoring(graph, pc, 5);
181.85 + }
181.86 +
181.87 + {
181.88 + PlanarColoring<Graph> pc(graph);
181.89 + pc.runFiveColoring();
181.90 + checkColoring(graph, pc, 5);
181.91 + }
181.92
181.93 } else {
181.94 checkKuratowski(graph, pe);
182.1 --- a/test/preflow_test.cc Mon Jul 16 16:21:40 2018 +0200
182.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
182.3 @@ -1,276 +0,0 @@
182.4 -/* -*- mode: C++; indent-tabs-mode: nil; -*-
182.5 - *
182.6 - * This file is a part of LEMON, a generic C++ optimization library.
182.7 - *
182.8 - * Copyright (C) 2003-2010
182.9 - * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
182.10 - * (Egervary Research Group on Combinatorial Optimization, EGRES).
182.11 - *
182.12 - * Permission to use, modify and distribute this software is granted
182.13 - * provided that this copyright notice appears in all copies. For
182.14 - * precise terms see the accompanying LICENSE file.
182.15 - *
182.16 - * This software is provided "AS IS" with no warranty of any kind,
182.17 - * express or implied, and with no claim as to its suitability for any
182.18 - * purpose.
182.19 - *
182.20 - */
182.21 -
182.22 -#include <iostream>
182.23 -
182.24 -#include "test_tools.h"
182.25 -#include <lemon/smart_graph.h>
182.26 -#include <lemon/preflow.h>
182.27 -#include <lemon/concepts/digraph.h>
182.28 -#include <lemon/concepts/maps.h>
182.29 -#include <lemon/lgf_reader.h>
182.30 -#include <lemon/elevator.h>
182.31 -
182.32 -using namespace lemon;
182.33 -
182.34 -char test_lgf[] =
182.35 - "@nodes\n"
182.36 - "label\n"
182.37 - "0\n"
182.38 - "1\n"
182.39 - "2\n"
182.40 - "3\n"
182.41 - "4\n"
182.42 - "5\n"
182.43 - "6\n"
182.44 - "7\n"
182.45 - "8\n"
182.46 - "9\n"
182.47 - "@arcs\n"
182.48 - " label capacity\n"
182.49 - "0 1 0 20\n"
182.50 - "0 2 1 0\n"
182.51 - "1 1 2 3\n"
182.52 - "1 2 3 8\n"
182.53 - "1 3 4 8\n"
182.54 - "2 5 5 5\n"
182.55 - "3 2 6 5\n"
182.56 - "3 5 7 5\n"
182.57 - "3 6 8 5\n"
182.58 - "4 3 9 3\n"
182.59 - "5 7 10 3\n"
182.60 - "5 6 11 10\n"
182.61 - "5 8 12 10\n"
182.62 - "6 8 13 8\n"
182.63 - "8 9 14 20\n"
182.64 - "8 1 15 5\n"
182.65 - "9 5 16 5\n"
182.66 - "@attributes\n"
182.67 - "source 1\n"
182.68 - "target 8\n";
182.69 -
182.70 -void checkPreflowCompile()
182.71 -{
182.72 - typedef int VType;
182.73 - typedef concepts::Digraph Digraph;
182.74 -
182.75 - typedef Digraph::Node Node;
182.76 - typedef Digraph::Arc Arc;
182.77 - typedef concepts::ReadMap<Arc,VType> CapMap;
182.78 - typedef concepts::ReadWriteMap<Arc,VType> FlowMap;
182.79 - typedef concepts::WriteMap<Node,bool> CutMap;
182.80 -
182.81 - typedef Elevator<Digraph, Digraph::Node> Elev;
182.82 - typedef LinkedElevator<Digraph, Digraph::Node> LinkedElev;
182.83 -
182.84 - Digraph g;
182.85 - Node n;
182.86 - Arc e;
182.87 - CapMap cap;
182.88 - FlowMap flow;
182.89 - CutMap cut;
182.90 - VType v;
182.91 - bool b;
182.92 -
182.93 - typedef Preflow<Digraph, CapMap>
182.94 - ::SetFlowMap<FlowMap>
182.95 - ::SetElevator<Elev>
182.96 - ::SetStandardElevator<LinkedElev>
182.97 - ::Create PreflowType;
182.98 - PreflowType preflow_test(g, cap, n, n);
182.99 - const PreflowType& const_preflow_test = preflow_test;
182.100 -
182.101 - const PreflowType::Elevator& elev = const_preflow_test.elevator();
182.102 - preflow_test.elevator(const_cast<PreflowType::Elevator&>(elev));
182.103 - PreflowType::Tolerance tol = const_preflow_test.tolerance();
182.104 - preflow_test.tolerance(tol);
182.105 -
182.106 - preflow_test
182.107 - .capacityMap(cap)
182.108 - .flowMap(flow)
182.109 - .source(n)
182.110 - .target(n);
182.111 -
182.112 - preflow_test.init();
182.113 - preflow_test.init(cap);
182.114 - preflow_test.startFirstPhase();
182.115 - preflow_test.startSecondPhase();
182.116 - preflow_test.run();
182.117 - preflow_test.runMinCut();
182.118 -
182.119 - v = const_preflow_test.flowValue();
182.120 - v = const_preflow_test.flow(e);
182.121 - const FlowMap& fm = const_preflow_test.flowMap();
182.122 - b = const_preflow_test.minCut(n);
182.123 - const_preflow_test.minCutMap(cut);
182.124 -
182.125 - ignore_unused_variable_warning(fm);
182.126 -}
182.127 -
182.128 -int cutValue (const SmartDigraph& g,
182.129 - const SmartDigraph::NodeMap<bool>& cut,
182.130 - const SmartDigraph::ArcMap<int>& cap) {
182.131 -
182.132 - int c=0;
182.133 - for(SmartDigraph::ArcIt e(g); e!=INVALID; ++e) {
182.134 - if (cut[g.source(e)] && !cut[g.target(e)]) c+=cap[e];
182.135 - }
182.136 - return c;
182.137 -}
182.138 -
182.139 -bool checkFlow(const SmartDigraph& g,
182.140 - const SmartDigraph::ArcMap<int>& flow,
182.141 - const SmartDigraph::ArcMap<int>& cap,
182.142 - SmartDigraph::Node s, SmartDigraph::Node t) {
182.143 -
182.144 - for (SmartDigraph::ArcIt e(g); e != INVALID; ++e) {
182.145 - if (flow[e] < 0 || flow[e] > cap[e]) return false;
182.146 - }
182.147 -
182.148 - for (SmartDigraph::NodeIt n(g); n != INVALID; ++n) {
182.149 - if (n == s || n == t) continue;
182.150 - int sum = 0;
182.151 - for (SmartDigraph::OutArcIt e(g, n); e != INVALID; ++e) {
182.152 - sum += flow[e];
182.153 - }
182.154 - for (SmartDigraph::InArcIt e(g, n); e != INVALID; ++e) {
182.155 - sum -= flow[e];
182.156 - }
182.157 - if (sum != 0) return false;
182.158 - }
182.159 - return true;
182.160 -}
182.161 -
182.162 -void initFlowTest()
182.163 -{
182.164 - DIGRAPH_TYPEDEFS(SmartDigraph);
182.165 -
182.166 - SmartDigraph g;
182.167 - SmartDigraph::ArcMap<int> cap(g),iflow(g);
182.168 - Node s=g.addNode(); Node t=g.addNode();
182.169 - Node n1=g.addNode(); Node n2=g.addNode();
182.170 - Arc a;
182.171 - a=g.addArc(s,n1); cap[a]=20; iflow[a]=20;
182.172 - a=g.addArc(n1,n2); cap[a]=10; iflow[a]=0;
182.173 - a=g.addArc(n2,t); cap[a]=20; iflow[a]=0;
182.174 -
182.175 - Preflow<SmartDigraph> pre(g,cap,s,t);
182.176 - pre.init(iflow);
182.177 - pre.startFirstPhase();
182.178 - check(pre.flowValue() == 10, "The incorrect max flow value.");
182.179 - check(pre.minCut(s), "Wrong min cut (Node s).");
182.180 - check(pre.minCut(n1), "Wrong min cut (Node n1).");
182.181 - check(!pre.minCut(n2), "Wrong min cut (Node n2).");
182.182 - check(!pre.minCut(t), "Wrong min cut (Node t).");
182.183 -}
182.184 -
182.185 -
182.186 -int main() {
182.187 -
182.188 - typedef SmartDigraph Digraph;
182.189 -
182.190 - typedef Digraph::Node Node;
182.191 - typedef Digraph::NodeIt NodeIt;
182.192 - typedef Digraph::ArcIt ArcIt;
182.193 - typedef Digraph::ArcMap<int> CapMap;
182.194 - typedef Digraph::ArcMap<int> FlowMap;
182.195 - typedef Digraph::NodeMap<bool> CutMap;
182.196 -
182.197 - typedef Preflow<Digraph, CapMap> PType;
182.198 -
182.199 - Digraph g;
182.200 - Node s, t;
182.201 - CapMap cap(g);
182.202 - std::istringstream input(test_lgf);
182.203 - DigraphReader<Digraph>(g,input).
182.204 - arcMap("capacity", cap).
182.205 - node("source",s).
182.206 - node("target",t).
182.207 - run();
182.208 -
182.209 - PType preflow_test(g, cap, s, t);
182.210 - preflow_test.run();
182.211 -
182.212 - check(checkFlow(g, preflow_test.flowMap(), cap, s, t),
182.213 - "The flow is not feasible.");
182.214 -
182.215 - CutMap min_cut(g);
182.216 - preflow_test.minCutMap(min_cut);
182.217 - int min_cut_value=cutValue(g,min_cut,cap);
182.218 -
182.219 - check(preflow_test.flowValue() == min_cut_value,
182.220 - "The max flow value is not equal to the three min cut values.");
182.221 -
182.222 - FlowMap flow(g);
182.223 - for(ArcIt e(g); e!=INVALID; ++e) flow[e] = preflow_test.flowMap()[e];
182.224 -
182.225 - int flow_value=preflow_test.flowValue();
182.226 -
182.227 - for(ArcIt e(g); e!=INVALID; ++e) cap[e]=2*cap[e];
182.228 - preflow_test.init(flow);
182.229 - preflow_test.startFirstPhase();
182.230 -
182.231 - CutMap min_cut1(g);
182.232 - preflow_test.minCutMap(min_cut1);
182.233 - min_cut_value=cutValue(g,min_cut1,cap);
182.234 -
182.235 - check(preflow_test.flowValue() == min_cut_value &&
182.236 - min_cut_value == 2*flow_value,
182.237 - "The max flow value or the min cut value is wrong.");
182.238 -
182.239 - preflow_test.startSecondPhase();
182.240 -
182.241 - check(checkFlow(g, preflow_test.flowMap(), cap, s, t),
182.242 - "The flow is not feasible.");
182.243 -
182.244 - CutMap min_cut2(g);
182.245 - preflow_test.minCutMap(min_cut2);
182.246 - min_cut_value=cutValue(g,min_cut2,cap);
182.247 -
182.248 - check(preflow_test.flowValue() == min_cut_value &&
182.249 - min_cut_value == 2*flow_value,
182.250 - "The max flow value or the three min cut values were not doubled");
182.251 -
182.252 -
182.253 - preflow_test.flowMap(flow);
182.254 -
182.255 - NodeIt tmp1(g,s);
182.256 - ++tmp1;
182.257 - if ( tmp1 != INVALID ) s=tmp1;
182.258 -
182.259 - NodeIt tmp2(g,t);
182.260 - ++tmp2;
182.261 - if ( tmp2 != INVALID ) t=tmp2;
182.262 -
182.263 - preflow_test.source(s);
182.264 - preflow_test.target(t);
182.265 -
182.266 - preflow_test.run();
182.267 -
182.268 - CutMap min_cut3(g);
182.269 - preflow_test.minCutMap(min_cut3);
182.270 - min_cut_value=cutValue(g,min_cut3,cap);
182.271 -
182.272 -
182.273 - check(preflow_test.flowValue() == min_cut_value,
182.274 - "The max flow value or the three min cut values are incorrect.");
182.275 -
182.276 - initFlowTest();
182.277 -
182.278 - return 0;
182.279 -}
183.1 --- a/test/radix_sort_test.cc Mon Jul 16 16:21:40 2018 +0200
183.2 +++ b/test/radix_sort_test.cc Wed Oct 17 19:14:07 2018 +0200
183.3 @@ -2,7 +2,7 @@
183.4 *
183.5 * This file is a part of LEMON, a generic C++ optimization library.
183.6 *
183.7 - * Copyright (C) 2003-2009
183.8 + * Copyright (C) 2003-2013
183.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
183.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
183.11 *
183.12 @@ -16,6 +16,8 @@
183.13 *
183.14 */
183.15
183.16 +#include <lemon/core.h>
183.17 +
183.18 #include <lemon/time_measure.h>
183.19 #include <lemon/smart_graph.h>
183.20 #include <lemon/maps.h>
183.21 @@ -25,6 +27,7 @@
183.22 #include "test_tools.h"
183.23
183.24 #include <vector>
183.25 +#include <list>
183.26 #include <algorithm>
183.27
183.28 using namespace lemon;
183.29 @@ -39,8 +42,58 @@
183.30
183.31 int negate(int a) { return - a; }
183.32
183.33 +template<class T>
183.34 +bool isTheSame(T &a, T&b)
183.35 +{
183.36 + typename T::iterator ai=a.begin();
183.37 + typename T::iterator bi=b.begin();
183.38 + for(;ai!=a.end()||bi!=b.end();++ai,++bi)
183.39 + if(*ai!=*bi) return false;
183.40 + return ai==a.end()&&bi==b.end();
183.41 +}
183.42
183.43 -void generateIntSequence(int n, std::vector<int>& data) {
183.44 +template<class T>
183.45 +T listsort(typename T::iterator b, typename T::iterator e)
183.46 +{
183.47 + if(b==e) return T();
183.48 + typename T::iterator bn=b;
183.49 + if(++bn==e) {
183.50 + T l;
183.51 + l.push_back(*b);
183.52 + return l;
183.53 + }
183.54 + typename T::iterator m=b;
183.55 + bool x=false;
183.56 + for(typename T::iterator i=b;i!=e;++i,x=!x)
183.57 + if(x) ++m;
183.58 + T l1(listsort<T>(b,m));
183.59 + T l2(listsort<T>(m,e));
183.60 + T l;
183.61 + while((!l1.empty())&&(!l2.empty()))
183.62 + if(l1.front()<=l2.front())
183.63 + {
183.64 + l.push_back(l1.front());
183.65 + l1.pop_front();
183.66 + }
183.67 + else {
183.68 + l.push_back(l2.front());
183.69 + l2.pop_front();
183.70 + }
183.71 + while(!l1.empty())
183.72 + {
183.73 + l.push_back(l1.front());
183.74 + l1.pop_front();
183.75 + }
183.76 + while(!l2.empty())
183.77 + {
183.78 + l.push_back(l2.front());
183.79 + l2.pop_front();
183.80 + }
183.81 + return l;
183.82 +}
183.83 +
183.84 +template<class T>
183.85 +void generateIntSequence(int n, T & data) {
183.86 int prime = 9973;
183.87 int root = 136, value = 1;
183.88 for (int i = 0; i < n; ++i) {
183.89 @@ -49,7 +102,8 @@
183.90 }
183.91 }
183.92
183.93 -void generateCharSequence(int n, std::vector<unsigned char>& data) {
183.94 +template<class T>
183.95 +void generateCharSequence(int n, T & data) {
183.96 int prime = 251;
183.97 int root = 3, value = root;
183.98 for (int i = 0; i < n; ++i) {
183.99 @@ -71,15 +125,15 @@
183.100 check(data1[i] == data2[i], "Test failed");
183.101 }
183.102
183.103 - radixSort(data2.begin(), data2.end(), Negate());
183.104 - for (int i = 0; i < n; ++i) {
183.105 - check(data1[i] == data2[n - 1 - i], "Test failed");
183.106 - }
183.107 + // radixSort(data2.begin(), data2.end(), Negate());
183.108 + // for (int i = 0; i < n; ++i) {
183.109 + // check(data1[i] == data2[n - 1 - i], "Test failed");
183.110 + // }
183.111
183.112 - radixSort(data2.begin(), data2.end(), negate);
183.113 - for (int i = 0; i < n; ++i) {
183.114 - check(data1[i] == data2[n - 1 - i], "Test failed");
183.115 - }
183.116 + // radixSort(data2.begin(), data2.end(), negate);
183.117 + // for (int i = 0; i < n; ++i) {
183.118 + // check(data1[i] == data2[n - 1 - i], "Test failed");
183.119 + // }
183.120
183.121 }
183.122
183.123 @@ -96,6 +150,42 @@
183.124 }
183.125
183.126 }
183.127 + {
183.128 + std::list<int> data1;
183.129 + generateIntSequence(n, data1);
183.130 +
183.131 + std::list<int> data2(listsort<std::list<int> >(data1.begin(), data1.end()));
183.132 +
183.133 + radixSort(data1.begin(), data1.end());
183.134 +
183.135 + check(isTheSame(data1,data2), "Test failed");
183.136 +
183.137 +
183.138 + // radixSort(data2.begin(), data2.end(), Negate());
183.139 + // check(isTheSame(data1,data2), "Test failed");
183.140 + // for (int i = 0; i < n; ++i) {
183.141 + // check(data1[i] == data2[n - 1 - i], "Test failed");
183.142 + // }
183.143 +
183.144 + // radixSort(data2.begin(), data2.end(), negate);
183.145 + // for (int i = 0; i < n; ++i) {
183.146 + // check(data1[i] == data2[n - 1 - i], "Test failed");
183.147 + // }
183.148 +
183.149 + }
183.150 +
183.151 + {
183.152 + std::list<unsigned char> data1(n);
183.153 + generateCharSequence(n, data1);
183.154 +
183.155 + std::list<unsigned char> data2(listsort<std::list<unsigned char> >
183.156 + (data1.begin(),
183.157 + data1.end()));
183.158 +
183.159 + radixSort(data1.begin(), data1.end());
183.160 + check(isTheSame(data1,data2), "Test failed");
183.161 +
183.162 + }
183.163 }
183.164
183.165
183.166 @@ -136,6 +226,37 @@
183.167 }
183.168
183.169 }
183.170 + {
183.171 + std::list<int> data1;
183.172 + generateIntSequence(n, data1);
183.173 +
183.174 + std::list<int> data2(listsort<std::list<int> >(data1.begin(),
183.175 + data1.end()));
183.176 + stableRadixSort(data1.begin(), data1.end());
183.177 + check(isTheSame(data1,data2), "Test failed");
183.178 +
183.179 + // stableRadixSort(data2.begin(), data2.end(), Negate());
183.180 + // for (int i = 0; i < n; ++i) {
183.181 + // check(data1[i] == data2[n - 1 - i], "Test failed");
183.182 + // }
183.183 +
183.184 + // stableRadixSort(data2.begin(), data2.end(), negate);
183.185 + // for (int i = 0; i < n; ++i) {
183.186 + // check(data1[i] == data2[n - 1 - i], "Test failed");
183.187 + // }
183.188 + }
183.189 +
183.190 + {
183.191 + std::list<unsigned char> data1(n);
183.192 + generateCharSequence(n, data1);
183.193 +
183.194 + std::list<unsigned char> data2(listsort<std::list<unsigned char> >
183.195 + (data1.begin(),
183.196 + data1.end()));
183.197 + radixSort(data1.begin(), data1.end());
183.198 + check(isTheSame(data1,data2), "Test failed");
183.199 +
183.200 + }
183.201 }
183.202
183.203 int main() {
184.1 --- a/test/suurballe_test.cc Mon Jul 16 16:21:40 2018 +0200
184.2 +++ b/test/suurballe_test.cc Wed Oct 17 19:14:07 2018 +0200
184.3 @@ -2,7 +2,7 @@
184.4 *
184.5 * This file is a part of LEMON, a generic C++ optimization library.
184.6 *
184.7 - * Copyright (C) 2003-2010
184.8 + * Copyright (C) 2003-2013
184.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
184.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
184.11 *
184.12 @@ -117,6 +117,8 @@
184.13
184.14 int f;
184.15 VType c;
184.16 + ::lemon::ignore_unused_variable_warning(f,c);
184.17 +
184.18 c = const_suurb_test.totalLength();
184.19 f = const_suurb_test.flow(e);
184.20 const SuurballeType::FlowMap& fm =
184.21 @@ -127,8 +129,8 @@
184.22 k = const_suurb_test.pathNum();
184.23 Path<Digraph> p = const_suurb_test.path(k);
184.24
184.25 - ignore_unused_variable_warning(fm);
184.26 - ignore_unused_variable_warning(pm);
184.27 + ::lemon::ignore_unused_variable_warning(fm);
184.28 + ::lemon::ignore_unused_variable_warning(pm);
184.29 }
184.30
184.31 // Check the feasibility of the flow
185.1 --- a/test/time_measure_test.cc Mon Jul 16 16:21:40 2018 +0200
185.2 +++ b/test/time_measure_test.cc Wed Oct 17 19:14:07 2018 +0200
185.3 @@ -2,7 +2,7 @@
185.4 *
185.5 * This file is a part of LEMON, a generic C++ optimization library.
185.6 *
185.7 - * Copyright (C) 2003-2009
185.8 + * Copyright (C) 2003-2013
185.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
185.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
185.11 *
185.12 @@ -35,7 +35,7 @@
185.13 for(int i=0;i<1000;i++)
185.14 {
185.15 TimeStamp x(T);
185.16 - ignore_unused_variable_warning(x);
185.17 + ::lemon::ignore_unused_variable_warning(x);
185.18 }
185.19 }
185.20
186.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
186.2 +++ b/test/tsp_test.cc Wed Oct 17 19:14:07 2018 +0200
186.3 @@ -0,0 +1,287 @@
186.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
186.5 + *
186.6 + * This file is a part of LEMON, a generic C++ optimization library.
186.7 + *
186.8 + * Copyright (C) 2003-2013
186.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
186.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
186.11 + *
186.12 + * Permission to use, modify and distribute this software is granted
186.13 + * provided that this copyright notice appears in all copies. For
186.14 + * precise terms see the accompanying LICENSE file.
186.15 + *
186.16 + * This software is provided "AS IS" with no warranty of any kind,
186.17 + * express or implied, and with no claim as to its suitability for any
186.18 + * purpose.
186.19 + *
186.20 + */
186.21 +
186.22 +#include <iostream>
186.23 +
186.24 +#include <lemon/full_graph.h>
186.25 +#include <lemon/math.h>
186.26 +#include <lemon/maps.h>
186.27 +#include <lemon/random.h>
186.28 +#include <lemon/dim2.h>
186.29 +
186.30 +#include <lemon/nearest_neighbor_tsp.h>
186.31 +#include <lemon/greedy_tsp.h>
186.32 +#include <lemon/insertion_tsp.h>
186.33 +#include <lemon/christofides_tsp.h>
186.34 +#include <lemon/opt2_tsp.h>
186.35 +
186.36 +#include "test_tools.h"
186.37 +
186.38 +using namespace lemon;
186.39 +
186.40 +// // Tests checkMetricCost() function
186.41 +// void metricCostTest() {
186.42 +// GRAPH_TYPEDEFS(FullGraph);
186.43 +// FullGraph g(10);
186.44 +// check(checkMetricCost(g, constMap<Edge>(0)), "Wrong checkMetricCost()");
186.45 +// check(checkMetricCost(g, constMap<Edge>(1)), "Wrong checkMetricCost()");
186.46 +// check(!checkMetricCost(g, constMap<Edge>(-1)), "Wrong checkMetricCost()");
186.47 +//
186.48 +// FullGraph::EdgeMap<float> cost(g);
186.49 +// for (NodeIt u(g); u != INVALID; ++u) {
186.50 +// for (NodeIt v(g); v != INVALID; ++v) {
186.51 +// if (u == v) continue;
186.52 +// float x1 = g.id(u), x2 = g.id(v);
186.53 +// float y1 = x1 * x1, y2 = x2 * x2;
186.54 +// cost[g.edge(u, v)] = std::sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1));
186.55 +// }
186.56 +// }
186.57 +// check(checkMetricCost(g, cost), "Wrong checkMetricCost()");
186.58 +// float eps = Tolerance<float>::defaultEpsilon();
186.59 +// cost[g.edge(g(0), g(9))] =
186.60 +// cost[g.edge(g(0), g(8))] + cost[g.edge(g(8), g(9))] + eps * 2;
186.61 +// check(!checkMetricCost(g, cost), "Wrong checkMetricCost()");
186.62 +// check(checkMetricCost(g, cost, Tolerance<float>(eps * 4)),
186.63 +// "Wrong checkMetricCost()");
186.64 +// }
186.65 +
186.66 +// Checks tour validity
186.67 +template <typename Container>
186.68 +bool checkTour(const FullGraph &gr, const Container &p) {
186.69 + FullGraph::NodeMap<bool> used(gr, false);
186.70 +
186.71 + int node_cnt = 0;
186.72 + for (typename Container::const_iterator it = p.begin(); it != p.end(); ++it)
186.73 + {
186.74 + FullGraph::Node node = *it;
186.75 + if (used[node]) return false;
186.76 + used[node] = true;
186.77 + ++node_cnt;
186.78 + }
186.79 +
186.80 + return (node_cnt == gr.nodeNum());
186.81 +}
186.82 +
186.83 +// Checks tour validity
186.84 +bool checkTourPath(const FullGraph &gr, const Path<FullGraph> &p) {
186.85 + FullGraph::NodeMap<bool> used(gr, false);
186.86 +
186.87 + if (!checkPath(gr, p)) return false;
186.88 + if (gr.nodeNum() <= 1 && p.length() != 0) return false;
186.89 + if (gr.nodeNum() > 1 && p.length() != gr.nodeNum()) return false;
186.90 +
186.91 + for (int i = 0; i < p.length(); ++i) {
186.92 + if (used[gr.target(p.nth(i))]) return false;
186.93 + used[gr.target(p.nth(i))] = true;
186.94 + }
186.95 + return true;
186.96 +}
186.97 +
186.98 +// Checks tour cost
186.99 +template <typename CostMap>
186.100 +bool checkCost(const FullGraph &gr, const std::vector<FullGraph::Node> &p,
186.101 + const CostMap &cost, typename CostMap::Value total)
186.102 +{
186.103 + typedef typename CostMap::Value Cost;
186.104 +
186.105 + Cost s = 0;
186.106 + for (int i = 0; i < int(p.size()) - 1; ++i)
186.107 + s += cost[gr.edge(p[i], p[i+1])];
186.108 + if (int(p.size()) >= 2)
186.109 + s += cost[gr.edge(p.back(), p.front())];
186.110 +
186.111 + return !Tolerance<Cost>().different(s, total);
186.112 +}
186.113 +
186.114 +// Checks tour cost
186.115 +template <typename CostMap>
186.116 +bool checkCost(const FullGraph &, const Path<FullGraph> &p,
186.117 + const CostMap &cost, typename CostMap::Value total)
186.118 +{
186.119 + typedef typename CostMap::Value Cost;
186.120 +
186.121 + Cost s = 0;
186.122 + for (int i = 0; i < p.length(); ++i)
186.123 + s += cost[p.nth(i)];
186.124 +
186.125 + return !Tolerance<Cost>().different(s, total);
186.126 +}
186.127 +
186.128 +// Tests a TSP algorithm on small graphs
186.129 +template <typename TSP>
186.130 +void tspTestSmall(const std::string &alg_name) {
186.131 + GRAPH_TYPEDEFS(FullGraph);
186.132 +
186.133 + for (int n = 0; n <= 5; ++n) {
186.134 + FullGraph g(n);
186.135 + unsigned nsize = n;
186.136 + int esize = n <= 1 ? 0 : n;
186.137 +
186.138 + ConstMap<Edge, int> cost_map(1);
186.139 + TSP alg(g, cost_map);
186.140 +
186.141 + check(alg.run() == esize, alg_name + ": Wrong total cost");
186.142 + check(alg.tourCost() == esize, alg_name + ": Wrong total cost");
186.143 +
186.144 + std::list<Node> list1(nsize), list2;
186.145 + std::vector<Node> vec1(nsize), vec2;
186.146 + alg.tourNodes(list1.begin());
186.147 + alg.tourNodes(vec1.begin());
186.148 + alg.tourNodes(std::front_inserter(list2));
186.149 + alg.tourNodes(std::back_inserter(vec2));
186.150 + check(checkTour(g, alg.tourNodes()), alg_name + ": Wrong node sequence");
186.151 + check(checkTour(g, list1), alg_name + ": Wrong node sequence");
186.152 + check(checkTour(g, vec1), alg_name + ": Wrong node sequence");
186.153 + check(checkTour(g, list2), alg_name + ": Wrong node sequence");
186.154 + check(checkTour(g, vec2), alg_name + ": Wrong node sequence");
186.155 + check(checkCost(g, vec1, constMap<Edge, int>(1), esize),
186.156 + alg_name + ": Wrong tour cost");
186.157 +
186.158 + SimplePath<FullGraph> path;
186.159 + alg.tour(path);
186.160 + check(path.length() == esize, alg_name + ": Wrong tour");
186.161 + check(checkTourPath(g, path), alg_name + ": Wrong tour");
186.162 + check(checkCost(g, path, constMap<Edge, int>(1), esize),
186.163 + alg_name + ": Wrong tour cost");
186.164 + }
186.165 +}
186.166 +
186.167 +// Tests a TSP algorithm on random graphs
186.168 +template <typename TSP>
186.169 +void tspTestRandom(const std::string &alg_name) {
186.170 + GRAPH_TYPEDEFS(FullGraph);
186.171 +
186.172 + FullGraph g(20);
186.173 + FullGraph::NodeMap<dim2::Point<double> > pos(g);
186.174 + DoubleEdgeMap cost(g);
186.175 +
186.176 + TSP alg(g, cost);
186.177 + Opt2Tsp<DoubleEdgeMap > opt2(g, cost);
186.178 +
186.179 + for (int i = 1; i <= 3; i++) {
186.180 + for (NodeIt u(g); u != INVALID; ++u) {
186.181 + pos[u] = dim2::Point<double>(rnd(), rnd());
186.182 + }
186.183 + for (NodeIt u(g); u != INVALID; ++u) {
186.184 + for (NodeIt v(g); v != INVALID; ++v) {
186.185 + if (u == v) continue;
186.186 + cost[g.edge(u, v)] = (pos[u] - pos[v]).normSquare();
186.187 + }
186.188 + }
186.189 +
186.190 + check(alg.run() > 0, alg_name + ": Wrong total cost");
186.191 +
186.192 + std::vector<Node> vec;
186.193 + alg.tourNodes(std::back_inserter(vec));
186.194 + check(checkTour(g, vec), alg_name + ": Wrong node sequence");
186.195 + check(checkCost(g, vec, cost, alg.tourCost()),
186.196 + alg_name + ": Wrong tour cost");
186.197 +
186.198 + SimplePath<FullGraph> path;
186.199 + alg.tour(path);
186.200 + check(checkTourPath(g, path), alg_name + ": Wrong tour");
186.201 + check(checkCost(g, path, cost, alg.tourCost()),
186.202 + alg_name + ": Wrong tour cost");
186.203 +
186.204 + check(!Tolerance<double>().less(alg.tourCost(), opt2.run(alg.tourNodes())),
186.205 + "2-opt improvement: Wrong total cost");
186.206 + check(checkTour(g, opt2.tourNodes()),
186.207 + "2-opt improvement: Wrong node sequence");
186.208 + check(checkCost(g, opt2.tourNodes(), cost, opt2.tourCost()),
186.209 + "2-opt improvement: Wrong tour cost");
186.210 +
186.211 + check(!Tolerance<double>().less(alg.tourCost(), opt2.run(path)),
186.212 + "2-opt improvement: Wrong total cost");
186.213 + check(checkTour(g, opt2.tourNodes()),
186.214 + "2-opt improvement: Wrong node sequence");
186.215 + check(checkCost(g, opt2.tourNodes(), cost, opt2.tourCost()),
186.216 + "2-opt improvement: Wrong tour cost");
186.217 + }
186.218 +}
186.219 +
186.220 +// Algorithm class for Nearest Insertion
186.221 +template <typename CM>
186.222 +class NearestInsertionTsp : public InsertionTsp<CM> {
186.223 +public:
186.224 + NearestInsertionTsp(const FullGraph &gr, const CM &cost)
186.225 + : InsertionTsp<CM>(gr, cost) {}
186.226 + typename CM::Value run() {
186.227 + return InsertionTsp<CM>::run(InsertionTsp<CM>::NEAREST);
186.228 + }
186.229 +};
186.230 +
186.231 +// Algorithm class for Farthest Insertion
186.232 +template <typename CM>
186.233 +class FarthestInsertionTsp : public InsertionTsp<CM> {
186.234 +public:
186.235 + FarthestInsertionTsp(const FullGraph &gr, const CM &cost)
186.236 + : InsertionTsp<CM>(gr, cost) {}
186.237 + typename CM::Value run() {
186.238 + return InsertionTsp<CM>::run(InsertionTsp<CM>::FARTHEST);
186.239 + }
186.240 +};
186.241 +
186.242 +// Algorithm class for Cheapest Insertion
186.243 +template <typename CM>
186.244 +class CheapestInsertionTsp : public InsertionTsp<CM> {
186.245 +public:
186.246 + CheapestInsertionTsp(const FullGraph &gr, const CM &cost)
186.247 + : InsertionTsp<CM>(gr, cost) {}
186.248 + typename CM::Value run() {
186.249 + return InsertionTsp<CM>::run(InsertionTsp<CM>::CHEAPEST);
186.250 + }
186.251 +};
186.252 +
186.253 +// Algorithm class for Random Insertion
186.254 +template <typename CM>
186.255 +class RandomInsertionTsp : public InsertionTsp<CM> {
186.256 +public:
186.257 + RandomInsertionTsp(const FullGraph &gr, const CM &cost)
186.258 + : InsertionTsp<CM>(gr, cost) {}
186.259 + typename CM::Value run() {
186.260 + return InsertionTsp<CM>::run(InsertionTsp<CM>::RANDOM);
186.261 + }
186.262 +};
186.263 +
186.264 +int main() {
186.265 + GRAPH_TYPEDEFS(FullGraph);
186.266 +
186.267 + // metricCostTest();
186.268 +
186.269 + tspTestSmall<NearestNeighborTsp<ConstMap<Edge, int> > >("Nearest Neighbor");
186.270 + tspTestSmall<GreedyTsp<ConstMap<Edge, int> > >("Greedy");
186.271 + tspTestSmall<NearestInsertionTsp<ConstMap<Edge, int> > >("Nearest Insertion");
186.272 + tspTestSmall<FarthestInsertionTsp<ConstMap<Edge, int> > >
186.273 + ("Farthest Insertion");
186.274 + tspTestSmall<CheapestInsertionTsp<ConstMap<Edge, int> > >
186.275 + ("Cheapest Insertion");
186.276 + tspTestSmall<RandomInsertionTsp<ConstMap<Edge, int> > >("Random Insertion");
186.277 + tspTestSmall<ChristofidesTsp<ConstMap<Edge, int> > >("Christofides");
186.278 + tspTestSmall<Opt2Tsp<ConstMap<Edge, int> > >("2-opt");
186.279 +
186.280 + tspTestRandom<NearestNeighborTsp<DoubleEdgeMap > >("Nearest Neighbor");
186.281 + tspTestRandom<GreedyTsp<DoubleEdgeMap > >("Greedy");
186.282 + tspTestRandom<NearestInsertionTsp<DoubleEdgeMap > >("Nearest Insertion");
186.283 + tspTestRandom<FarthestInsertionTsp<DoubleEdgeMap > >("Farthest Insertion");
186.284 + tspTestRandom<CheapestInsertionTsp<DoubleEdgeMap > >("Cheapest Insertion");
186.285 + tspTestRandom<RandomInsertionTsp<DoubleEdgeMap > >("Random Insertion");
186.286 + tspTestRandom<ChristofidesTsp<DoubleEdgeMap > >("Christofides");
186.287 + tspTestRandom<Opt2Tsp<DoubleEdgeMap > >("2-opt");
186.288 +
186.289 + return 0;
186.290 +}
187.1 --- a/tools/Makefile.am Mon Jul 16 16:21:40 2018 +0200
187.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
187.3 @@ -1,17 +0,0 @@
187.4 -EXTRA_DIST += \
187.5 - tools/CMakeLists.txt
187.6 -
187.7 -if WANT_TOOLS
187.8 -
187.9 -bin_PROGRAMS += \
187.10 - tools/dimacs-solver \
187.11 - tools/dimacs-to-lgf \
187.12 - tools/lgf-gen
187.13 -
187.14 -dist_bin_SCRIPTS += tools/lemon-0.x-to-1.x.sh
187.15 -
187.16 -endif WANT_TOOLS
187.17 -
187.18 -tools_dimacs_solver_SOURCES = tools/dimacs-solver.cc
187.19 -tools_dimacs_to_lgf_SOURCES = tools/dimacs-to-lgf.cc
187.20 -tools_lgf_gen_SOURCES = tools/lgf-gen.cc
188.1 --- a/tools/dimacs-solver.cc Mon Jul 16 16:21:40 2018 +0200
188.2 +++ b/tools/dimacs-solver.cc Wed Oct 17 19:14:07 2018 +0200
188.3 @@ -2,7 +2,7 @@
188.4 *
188.5 * This file is a part of LEMON, a generic C++ optimization library.
188.6 *
188.7 - * Copyright (C) 2003-2010
188.8 + * Copyright (C) 2003-2013
188.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
188.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
188.11 *
188.12 @@ -117,16 +117,18 @@
188.13 }
188.14 if (report) std::cerr << "Read the file: " << ti << '\n';
188.15
188.16 + typedef NetworkSimplex<Digraph, Value> MCF;
188.17 ti.restart();
188.18 - NetworkSimplex<Digraph, Value> ns(g);
188.19 + MCF ns(g);
188.20 ns.lowerMap(lower).upperMap(cap).costMap(cost).supplyMap(sup);
188.21 if (sum_sup > 0) ns.supplyType(ns.LEQ);
188.22 if (report) std::cerr << "Setup NetworkSimplex class: " << ti << '\n';
188.23 ti.restart();
188.24 - bool res = ns.run();
188.25 + typename MCF::ProblemType res = ns.run();
188.26 if (report) {
188.27 std::cerr << "Run NetworkSimplex: " << ti << "\n\n";
188.28 - std::cerr << "Feasible flow: " << (res ? "found" : "not found") << '\n';
188.29 + std::cerr << "Feasible flow: " << (res == MCF::OPTIMAL ? "found" :
188.30 + "not found") << '\n';
188.31 if (res) std::cerr << "Min flow cost: "
188.32 << ns.template totalCost<LargeValue>() << '\n';
188.33 }
188.34 @@ -187,9 +189,6 @@
188.35 }
188.36
188.37 int main(int argc, const char *argv[]) {
188.38 - typedef SmartDigraph Digraph;
188.39 -
188.40 - typedef Digraph::Arc Arc;
188.41
188.42 std::string inputName;
188.43 std::string outputName;
188.44 @@ -223,11 +222,13 @@
188.45 if (!output) {
188.46 throw IoError("Cannot open the file for writing", ap.files()[1]);
188.47 }
188.48 + // fall through
188.49 case 1:
188.50 input.open(ap.files()[0].c_str());
188.51 if (!input) {
188.52 throw IoError("File cannot be found", ap.files()[0]);
188.53 }
188.54 + // fall through
188.55 case 0:
188.56 break;
188.57 default:
188.58 @@ -252,6 +253,7 @@
188.59 break;
188.60 case DimacsDescriptor::SP:
188.61 std::cout << "sp";
188.62 + break;
188.63 case DimacsDescriptor::MAT:
188.64 std::cout << "mat";
188.65 break;
189.1 --- a/tools/dimacs-to-lgf.cc Mon Jul 16 16:21:40 2018 +0200
189.2 +++ b/tools/dimacs-to-lgf.cc Wed Oct 17 19:14:07 2018 +0200
189.3 @@ -73,11 +73,13 @@
189.4 if (!output) {
189.5 throw IoError("Cannot open the file for writing", ap.files()[1]);
189.6 }
189.7 + // fall through
189.8 case 1:
189.9 input.open(ap.files()[0].c_str());
189.10 if (!input) {
189.11 throw IoError("File cannot be found", ap.files()[0]);
189.12 }
189.13 + // fall through
189.14 case 0:
189.15 break;
189.16 default:
190.1 --- a/tools/lgf-gen.cc Mon Jul 16 16:21:40 2018 +0200
190.2 +++ b/tools/lgf-gen.cc Wed Oct 17 19:14:07 2018 +0200
190.3 @@ -246,7 +246,7 @@
190.4
190.5 struct BeachIt;
190.6
190.7 - typedef std::multimap<double, BeachIt> SpikeHeap;
190.8 + typedef std::multimap<double, BeachIt*> SpikeHeap;
190.9
190.10 typedef std::multimap<Part, SpikeHeap::iterator, YLess> Beach;
190.11
190.12 @@ -329,6 +329,7 @@
190.13 Beach::iterator bit = beach.upper_bound(Part(site, site, site));
190.14
190.15 if (bit->second != spikeheap.end()) {
190.16 + delete bit->second->second;
190.17 spikeheap.erase(bit->second);
190.18 }
190.19
190.20 @@ -342,8 +343,8 @@
190.21 if (prev != -1 &&
190.22 circle_form(points[prev], points[curr], points[site])) {
190.23 double x = circle_point(points[prev], points[curr], points[site]);
190.24 - pit = spikeheap.insert(std::make_pair(x, BeachIt(beach.end())));
190.25 - pit->second.it =
190.26 + pit = spikeheap.insert(std::make_pair(x, new BeachIt(beach.end())));
190.27 + pit->second->it =
190.28 beach.insert(std::make_pair(Part(prev, curr, site), pit));
190.29 } else {
190.30 beach.insert(std::make_pair(Part(prev, curr, site), pit));
190.31 @@ -355,8 +356,8 @@
190.32 if (next != -1 &&
190.33 circle_form(points[site], points[curr],points[next])) {
190.34 double x = circle_point(points[site], points[curr], points[next]);
190.35 - nit = spikeheap.insert(std::make_pair(x, BeachIt(beach.end())));
190.36 - nit->second.it =
190.37 + nit = spikeheap.insert(std::make_pair(x, new BeachIt(beach.end())));
190.38 + nit->second->it =
190.39 beach.insert(std::make_pair(Part(site, curr, next), nit));
190.40 } else {
190.41 beach.insert(std::make_pair(Part(site, curr, next), nit));
190.42 @@ -366,7 +367,7 @@
190.43 } else {
190.44 sweep = spit->first;
190.45
190.46 - Beach::iterator bit = spit->second.it;
190.47 + Beach::iterator bit = spit->second->it;
190.48
190.49 int prev = bit->first.prev;
190.50 int curr = bit->first.curr;
190.51 @@ -399,10 +400,22 @@
190.52 Beach::iterator nbit = bit; ++nbit;
190.53 int nnt = nbit->first.next;
190.54
190.55 - if (bit->second != spikeheap.end()) spikeheap.erase(bit->second);
190.56 - if (pbit->second != spikeheap.end()) spikeheap.erase(pbit->second);
190.57 - if (nbit->second != spikeheap.end()) spikeheap.erase(nbit->second);
190.58 -
190.59 + if (bit->second != spikeheap.end())
190.60 + {
190.61 + delete bit->second->second;
190.62 + spikeheap.erase(bit->second);
190.63 + }
190.64 + if (pbit->second != spikeheap.end())
190.65 + {
190.66 + delete pbit->second->second;
190.67 + spikeheap.erase(pbit->second);
190.68 + }
190.69 + if (nbit->second != spikeheap.end())
190.70 + {
190.71 + delete nbit->second->second;
190.72 + spikeheap.erase(nbit->second);
190.73 + }
190.74 +
190.75 beach.erase(nbit);
190.76 beach.erase(bit);
190.77 beach.erase(pbit);
190.78 @@ -412,8 +425,8 @@
190.79 circle_form(points[ppv], points[prev], points[next])) {
190.80 double x = circle_point(points[ppv], points[prev], points[next]);
190.81 if (x < sweep) x = sweep;
190.82 - pit = spikeheap.insert(std::make_pair(x, BeachIt(beach.end())));
190.83 - pit->second.it =
190.84 + pit = spikeheap.insert(std::make_pair(x, new BeachIt(beach.end())));
190.85 + pit->second->it =
190.86 beach.insert(std::make_pair(Part(ppv, prev, next), pit));
190.87 } else {
190.88 beach.insert(std::make_pair(Part(ppv, prev, next), pit));
190.89 @@ -424,8 +437,8 @@
190.90 circle_form(points[prev], points[next], points[nnt])) {
190.91 double x = circle_point(points[prev], points[next], points[nnt]);
190.92 if (x < sweep) x = sweep;
190.93 - nit = spikeheap.insert(std::make_pair(x, BeachIt(beach.end())));
190.94 - nit->second.it =
190.95 + nit = spikeheap.insert(std::make_pair(x, new BeachIt(beach.end())));
190.96 + nit->second->it =
190.97 beach.insert(std::make_pair(Part(prev, next, nnt), nit));
190.98 } else {
190.99 beach.insert(std::make_pair(Part(prev, next, nnt), nit));