Add QuadriFlow remesher

This commit is contained in:
Sebastian Parborg
2019-08-26 18:34:11 +02:00
parent 1c44d08a69
commit 57e55906f0
254 changed files with 119812 additions and 9 deletions

View File

@@ -263,6 +263,8 @@ endif()
option(WITH_HEADLESS "Build without graphical support (renderfarm, server mode only)" OFF)
mark_as_advanced(WITH_HEADLESS)
option(WITH_QUADRIFLOW "Build with quadriflow remesher support" ON)
option(WITH_AUDASPACE "Build with blenders audio library (only disable if you know what you're doing!)" ON)
option(WITH_SYSTEM_AUDASPACE "Build with external audaspace library installed on the system (only enable if you know what you're doing!)" OFF)
mark_as_advanced(WITH_AUDASPACE)
@@ -673,6 +675,7 @@ if(NOT WITH_BOOST)
set_and_warn(WITH_INTERNATIONAL OFF)
set_and_warn(WITH_OPENVDB OFF)
set_and_warn(WITH_OPENCOLORIO OFF)
set_and_warn(WITH_QUADRIFLOW OFF)
elseif(WITH_CYCLES OR WITH_OPENIMAGEIO OR WITH_INTERNATIONAL OR
WITH_OPENVDB OR WITH_OPENCOLORIO)
# Keep enabled
@@ -1765,6 +1768,7 @@ if(FIRST_RUN)
info_cfg_option(WITH_OPENIMAGEDENOISE)
info_cfg_option(WITH_OPENVDB)
info_cfg_option(WITH_ALEMBIC)
info_cfg_option(WITH_QUADRIFLOW)
info_cfg_text("Compiler Options:")
info_cfg_option(WITH_BUILDINFO)

View File

@@ -46,6 +46,7 @@ set(WITH_OPENSUBDIV ON CACHE BOOL "" FORCE)
set(WITH_OPENVDB ON CACHE BOOL "" FORCE)
set(WITH_OPENVDB_BLOSC ON CACHE BOOL "" FORCE)
set(WITH_PYTHON_INSTALL ON CACHE BOOL "" FORCE)
set(WITH_QUADRIFLOW ON CACHE BOOL "" FORCE)
set(WITH_RAYOPTIMIZATION ON CACHE BOOL "" FORCE)
set(WITH_SDL ON CACHE BOOL "" FORCE)
set(WITH_X11_XINPUT ON CACHE BOOL "" FORCE)

View File

@@ -50,6 +50,7 @@ set(WITH_OPENIMAGEIO OFF CACHE BOOL "" FORCE)
set(WITH_OPENMP OFF CACHE BOOL "" FORCE)
set(WITH_OPENSUBDIV OFF CACHE BOOL "" FORCE)
set(WITH_OPENVDB OFF CACHE BOOL "" FORCE)
set(WITH_QUADRIFLOW OFF CACHE BOOL "" FORCE)
set(WITH_RAYOPTIMIZATION OFF CACHE BOOL "" FORCE)
set(WITH_SDL OFF CACHE BOOL "" FORCE)
set(WITH_X11_XINPUT OFF CACHE BOOL "" FORCE)

View File

@@ -47,6 +47,7 @@ set(WITH_OPENSUBDIV ON CACHE BOOL "" FORCE)
set(WITH_OPENVDB ON CACHE BOOL "" FORCE)
set(WITH_OPENVDB_BLOSC ON CACHE BOOL "" FORCE)
set(WITH_PYTHON_INSTALL ON CACHE BOOL "" FORCE)
set(WITH_QUADRIFLOW ON CACHE BOOL "" FORCE)
set(WITH_RAYOPTIMIZATION ON CACHE BOOL "" FORCE)
set(WITH_SDL ON CACHE BOOL "" FORCE)
set(WITH_X11_XINPUT ON CACHE BOOL "" FORCE)

View File

@@ -105,3 +105,8 @@ if(WITH_AUDASPACE AND NOT WITH_SYSTEM_AUDASPACE)
set(AUDASPACE_CMAKE_CFG ${CMAKE_CURRENT_SOURCE_DIR}/audaspace/blender_config.cmake)
add_subdirectory(audaspace)
endif()
if(WITH_QUADRIFLOW)
set(QUADRIFLOW_CMAKE_CFG ${CMAKE_CURRENT_SOURCE_DIR}/quadriflow/blender_config.cmake)
add_subdirectory(quadriflow)
endif()

View File

@@ -0,0 +1,26 @@
The main developers of release series 1.x are
* Balazs Dezso <deba@inf.elte.hu>
* Alpar Juttner <alpar@cs.elte.hu>
* Peter Kovacs <kpeter@inf.elte.hu>
* Akos Ladanyi <ladanyi@tmit.bme.hu>
For more complete list of contributors, please visit the history of
the LEMON source code repository: http://lemon.cs.elte.hu/hg/lemon
Moreover, this version is heavily based on version 0.x of LEMON. Here
is the list of people who contributed to those versions.
* Mihaly Barasz <klao@cs.elte.hu>
* Johanna Becker <beckerjc@cs.elte.hu>
* Attila Bernath <athos@cs.elte.hu>
* Balazs Dezso <deba@inf.elte.hu>
* Peter Hegyi <hegyi@tmit.bme.hu>
* Alpar Juttner <alpar@cs.elte.hu>
* Peter Kovacs <kpeter@inf.elte.hu>
* Akos Ladanyi <ladanyi@tmit.bme.hu>
* Marton Makai <marci@cs.elte.hu>
* Jacint Szabo <jacint@cs.elte.hu>
Again, please visit the history of the old LEMON repository for more
details: http://lemon.cs.elte.hu/hg/lemon-0.x

View File

@@ -0,0 +1,373 @@
CMAKE_MINIMUM_REQUIRED(VERSION 3.1)
SET(PROJECT_NAME "LEMON")
PROJECT(${PROJECT_NAME})
INCLUDE(FindPythonInterp)
INCLUDE(FindWget)
IF(EXISTS ${PROJECT_SOURCE_DIR}/cmake/version.cmake)
INCLUDE(${PROJECT_SOURCE_DIR}/cmake/version.cmake)
ELSEIF(DEFINED ENV{LEMON_VERSION})
SET(LEMON_VERSION $ENV{LEMON_VERSION} CACHE STRING "LEMON version string.")
ELSE()
EXECUTE_PROCESS(
COMMAND
hg log -r. --template "{latesttag}"
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
OUTPUT_VARIABLE HG_REVISION_TAG
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE
)
EXECUTE_PROCESS(
COMMAND
hg log -r. --template "{latesttagdistance}"
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
OUTPUT_VARIABLE HG_REVISION_DIST
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE
)
EXECUTE_PROCESS(
COMMAND
hg log -r. --template "{node|short}"
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
OUTPUT_VARIABLE HG_REVISION_ID
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE
)
IF(HG_REVISION_TAG STREQUAL "")
SET(HG_REVISION_ID "hg-tip")
ELSE()
IF(HG_REVISION_TAG STREQUAL "null")
SET(HG_REVISION_TAG "trunk")
ELSEIF(HG_REVISION_TAG MATCHES "^r")
STRING(SUBSTRING ${HG_REVISION_TAG} 1 -1 HG_REVISION_TAG)
ENDIF()
IF(HG_REVISION_DIST STREQUAL "0")
SET(HG_REVISION ${HG_REVISION_TAG})
ELSE()
SET(HG_REVISION
"${HG_REVISION_TAG}+${HG_REVISION_DIST}-${HG_REVISION_ID}")
ENDIF()
ENDIF()
SET(LEMON_VERSION ${HG_REVISION} CACHE STRING "LEMON version string.")
ENDIF()
SET(PROJECT_VERSION ${LEMON_VERSION})
SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
FIND_PACKAGE(Doxygen)
FIND_PACKAGE(Ghostscript)
SET(LEMON_ENABLE_GLPK YES CACHE STRING "Enable GLPK solver backend.")
SET(LEMON_ENABLE_ILOG YES CACHE STRING "Enable ILOG (CPLEX) solver backend.")
SET(LEMON_ENABLE_COIN YES CACHE STRING "Enable COIN solver backend.")
SET(LEMON_ENABLE_SOPLEX YES CACHE STRING "Enable SoPlex solver backend.")
IF(LEMON_ENABLE_GLPK)
FIND_PACKAGE(GLPK 4.33)
ENDIF(LEMON_ENABLE_GLPK)
IF(LEMON_ENABLE_ILOG)
FIND_PACKAGE(ILOG)
ENDIF(LEMON_ENABLE_ILOG)
IF(LEMON_ENABLE_COIN)
FIND_PACKAGE(COIN)
ENDIF(LEMON_ENABLE_COIN)
IF(LEMON_ENABLE_SOPLEX)
FIND_PACKAGE(SOPLEX)
ENDIF(LEMON_ENABLE_SOPLEX)
IF(GLPK_FOUND)
SET(LEMON_HAVE_LP TRUE)
SET(LEMON_HAVE_MIP TRUE)
SET(LEMON_HAVE_GLPK TRUE)
ENDIF(GLPK_FOUND)
IF(ILOG_FOUND)
SET(LEMON_HAVE_LP TRUE)
SET(LEMON_HAVE_MIP TRUE)
SET(LEMON_HAVE_CPLEX TRUE)
ENDIF(ILOG_FOUND)
IF(COIN_FOUND)
SET(LEMON_HAVE_LP TRUE)
SET(LEMON_HAVE_MIP TRUE)
SET(LEMON_HAVE_CLP TRUE)
SET(LEMON_HAVE_CBC TRUE)
ENDIF(COIN_FOUND)
IF(SOPLEX_FOUND)
SET(LEMON_HAVE_LP TRUE)
SET(LEMON_HAVE_SOPLEX TRUE)
ENDIF(SOPLEX_FOUND)
IF(ILOG_FOUND)
SET(DEFAULT_LP "CPLEX")
SET(DEFAULT_MIP "CPLEX")
ELSEIF(COIN_FOUND)
SET(DEFAULT_LP "CLP")
SET(DEFAULT_MIP "CBC")
ELSEIF(GLPK_FOUND)
SET(DEFAULT_LP "GLPK")
SET(DEFAULT_MIP "GLPK")
ELSEIF(SOPLEX_FOUND)
SET(DEFAULT_LP "SOPLEX")
ENDIF()
IF(NOT LEMON_DEFAULT_LP OR
(NOT ILOG_FOUND AND (LEMON_DEFAULT_LP STREQUAL "CPLEX")) OR
(NOT COIN_FOUND AND (LEMON_DEFAULT_LP STREQUAL "CLP")) OR
(NOT GLPK_FOUND AND (LEMON_DEFAULT_LP STREQUAL "GLPK")) OR
(NOT SOPLEX_FOUND AND (LEMON_DEFAULT_LP STREQUAL "SOPLEX")))
SET(LEMON_DEFAULT_LP ${DEFAULT_LP} CACHE STRING
"Default LP solver backend (GLPK, CPLEX, CLP or SOPLEX)" FORCE)
ELSE()
SET(LEMON_DEFAULT_LP ${DEFAULT_LP} CACHE STRING
"Default LP solver backend (GLPK, CPLEX, CLP or SOPLEX)")
ENDIF()
IF(NOT LEMON_DEFAULT_MIP OR
(NOT ILOG_FOUND AND (LEMON_DEFAULT_MIP STREQUAL "CPLEX")) OR
(NOT COIN_FOUND AND (LEMON_DEFAULT_MIP STREQUAL "CBC")) OR
(NOT GLPK_FOUND AND (LEMON_DEFAULT_MIP STREQUAL "GLPK")))
SET(LEMON_DEFAULT_MIP ${DEFAULT_MIP} CACHE STRING
"Default MIP solver backend (GLPK, CPLEX or CBC)" FORCE)
ELSE()
SET(LEMON_DEFAULT_MIP ${DEFAULT_MIP} CACHE STRING
"Default MIP solver backend (GLPK, CPLEX or CBC)")
ENDIF()
IF(DEFINED ENV{LEMON_CXX_WARNING})
SET(CXX_WARNING $ENV{LEMON_CXX_WARNING})
ELSE()
IF(CMAKE_COMPILER_IS_GNUCXX)
SET(CXX_WARNING "-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 -fno-strict-aliasing -Wold-style-cast -Wno-unknown-pragmas")
SET(CMAKE_CXX_FLAGS_DEBUG CACHE STRING "-ggdb")
SET(CMAKE_C_FLAGS_DEBUG CACHE STRING "-ggdb")
ELSEIF(MSVC)
# This part is unnecessary 'casue the same is set by the lemon/core.h.
# Still keep it as an example.
SET(CXX_WARNING "/wd4250 /wd4355 /wd4503 /wd4800 /wd4996")
# Suppressed warnings:
# C4250: 'class1' : inherits 'class2::member' via dominance
# C4355: 'this' : used in base member initializer list
# C4503: 'function' : decorated name length exceeded, name was truncated
# C4800: 'type' : forcing value to bool 'true' or 'false'
# (performance warning)
# C4996: 'function': was declared deprecated
ELSE()
SET(CXX_WARNING "-Wall")
ENDIF()
ENDIF()
SET(LEMON_CXX_WARNING_FLAGS ${CXX_WARNING} CACHE STRING "LEMON warning flags.")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${LEMON_CXX_WARNING_FLAGS}")
IF(MSVC)
SET( CMAKE_CXX_FLAGS_MAINTAINER "/WX ${CMAKE_CXX_FLAGS_DEBUG}" CACHE STRING
"Flags used by the C++ compiler during maintainer builds."
)
SET( CMAKE_C_FLAGS_MAINTAINER "/WX ${CMAKE_CXX_FLAGS_DEBUG}" CACHE STRING
"Flags used by the C compiler during maintainer builds."
)
SET( CMAKE_EXE_LINKER_FLAGS_MAINTAINER
"${CMAKE_EXE_LINKER_FLAGS_DEBUG}" CACHE STRING
"Flags used for linking binaries during maintainer builds."
)
SET( CMAKE_SHARED_LINKER_FLAGS_MAINTAINER
"${CMAKE_SHARED_LINKER_FLAGS_DEBUG}" CACHE STRING
"Flags used by the shared libraries linker during maintainer builds."
)
ELSE()
SET( CMAKE_CXX_FLAGS_MAINTAINER "-Werror -ggdb -O0" CACHE STRING
"Flags used by the C++ compiler during maintainer builds."
)
SET( CMAKE_C_FLAGS_MAINTAINER "-Werror -O0" CACHE STRING
"Flags used by the C compiler during maintainer builds."
)
SET( CMAKE_EXE_LINKER_FLAGS_MAINTAINER
"${CMAKE_EXE_LINKER_FLAGS_DEBUG}" CACHE STRING
"Flags used for linking binaries during maintainer builds."
)
SET( CMAKE_SHARED_LINKER_FLAGS_MAINTAINER
"${CMAKE_SHARED_LINKER_FLAGS_DEBUG}" CACHE STRING
"Flags used by the shared libraries linker during maintainer builds."
)
ENDIF()
MARK_AS_ADVANCED(
CMAKE_CXX_FLAGS_MAINTAINER
CMAKE_C_FLAGS_MAINTAINER
CMAKE_EXE_LINKER_FLAGS_MAINTAINER
CMAKE_SHARED_LINKER_FLAGS_MAINTAINER )
IF(CMAKE_CONFIGURATION_TYPES)
LIST(APPEND CMAKE_CONFIGURATION_TYPES Maintainer)
LIST(REMOVE_DUPLICATES CMAKE_CONFIGURATION_TYPES)
SET(CMAKE_CONFIGURATION_TYPES "${CMAKE_CONFIGURATION_TYPES}" CACHE STRING
"Add the configurations that we need"
FORCE)
endif()
IF(NOT CMAKE_BUILD_TYPE)
SET(CMAKE_BUILD_TYPE "Release")
ENDIF()
SET( CMAKE_BUILD_TYPE "${CMAKE_BUILD_TYPE}" CACHE STRING
"Choose the type of build, options are: None(CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel Maintainer."
FORCE )
INCLUDE(CheckTypeSize)
CHECK_TYPE_SIZE("long long" LONG_LONG)
SET(LEMON_HAVE_LONG_LONG ${HAVE_LONG_LONG})
INCLUDE(FindThreads)
IF(NOT LEMON_THREADING)
IF(CMAKE_USE_PTHREADS_INIT)
SET(LEMON_THREADING "Pthread")
ELSEIF(CMAKE_USE_WIN32_THREADS_INIT)
SET(LEMON_THREADING "Win32")
ELSE()
SET(LEMON_THREADING "None")
ENDIF()
ENDIF()
SET( LEMON_THREADING "${LEMON_THREADING}" CACHE STRING
"Choose the threading library, options are: Pthread Win32 None."
FORCE )
IF(LEMON_THREADING STREQUAL "Pthread")
SET(LEMON_USE_PTHREAD TRUE)
ELSEIF(LEMON_THREADING STREQUAL "Win32")
SET(LEMON_USE_WIN32_THREADS TRUE)
ENDIF()
ENABLE_TESTING()
IF(${CMAKE_BUILD_TYPE} STREQUAL "Maintainer")
ADD_CUSTOM_TARGET(check ALL COMMAND ${CMAKE_CTEST_COMMAND})
ELSE()
ADD_CUSTOM_TARGET(check COMMAND ${CMAKE_CTEST_COMMAND})
ENDIF()
ADD_SUBDIRECTORY(lemon)
IF(${CMAKE_SOURCE_DIR} STREQUAL ${PROJECT_SOURCE_DIR})
ADD_SUBDIRECTORY(contrib)
ADD_SUBDIRECTORY(demo)
ADD_SUBDIRECTORY(tools)
ADD_SUBDIRECTORY(doc)
ADD_SUBDIRECTORY(test)
ENDIF()
CONFIGURE_FILE(
${PROJECT_SOURCE_DIR}/cmake/LEMONConfig.cmake.in
${PROJECT_BINARY_DIR}/cmake/LEMONConfig.cmake
@ONLY
)
IF(UNIX)
INSTALL(
FILES ${PROJECT_BINARY_DIR}/cmake/LEMONConfig.cmake
DESTINATION share/lemon/cmake
)
ELSEIF(WIN32)
INSTALL(
FILES ${PROJECT_BINARY_DIR}/cmake/LEMONConfig.cmake
DESTINATION cmake
)
ENDIF()
CONFIGURE_FILE(
${PROJECT_SOURCE_DIR}/cmake/version.cmake.in
${PROJECT_BINARY_DIR}/cmake/version.cmake
@ONLY
)
SET(ARCHIVE_BASE_NAME ${CMAKE_PROJECT_NAME})
STRING(TOLOWER ${ARCHIVE_BASE_NAME} ARCHIVE_BASE_NAME)
SET(ARCHIVE_NAME ${ARCHIVE_BASE_NAME}-${PROJECT_VERSION})
ADD_CUSTOM_TARGET(dist
COMMAND cmake -E remove_directory ${ARCHIVE_NAME}
COMMAND hg archive ${ARCHIVE_NAME}
COMMAND cmake -E copy cmake/version.cmake ${ARCHIVE_NAME}/cmake/version.cmake
COMMAND tar -czf ${ARCHIVE_BASE_NAME}-nodoc-${PROJECT_VERSION}.tar.gz ${ARCHIVE_NAME}
COMMAND zip -r ${ARCHIVE_BASE_NAME}-nodoc-${PROJECT_VERSION}.zip ${ARCHIVE_NAME}
COMMAND cmake -E copy_directory doc/html ${ARCHIVE_NAME}/doc/html
COMMAND tar -czf ${ARCHIVE_NAME}.tar.gz ${ARCHIVE_NAME}
COMMAND zip -r ${ARCHIVE_NAME}.zip ${ARCHIVE_NAME}
COMMAND cmake -E copy_directory doc/html ${ARCHIVE_BASE_NAME}-doc-${PROJECT_VERSION}
COMMAND tar -czf ${ARCHIVE_BASE_NAME}-doc-${PROJECT_VERSION}.tar.gz ${ARCHIVE_BASE_NAME}-doc-${PROJECT_VERSION}
COMMAND zip -r ${ARCHIVE_BASE_NAME}-doc-${PROJECT_VERSION}.zip ${ARCHIVE_BASE_NAME}-doc-${PROJECT_VERSION}
COMMAND cmake -E remove_directory ${ARCHIVE_NAME}
COMMAND cmake -E remove_directory ${ARCHIVE_BASE_NAME}-doc-${PROJECT_VERSION}
DEPENDS html
WORKING_DIRECTORY ${PROJECT_BINARY_DIR})
# CPACK config (Basically for NSIS)
IF(${CMAKE_SOURCE_DIR} STREQUAL ${PROJECT_SOURCE_DIR})
SET(CPACK_PACKAGE_NAME ${PROJECT_NAME})
SET(CPACK_PACKAGE_VENDOR "EGRES")
SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY
"LEMON - Library for Efficient Modeling and Optimization in Networks")
SET(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE")
SET(CPACK_PACKAGE_VERSION ${PROJECT_VERSION})
SET(CPACK_PACKAGE_INSTALL_DIRECTORY
"${PROJECT_NAME} ${PROJECT_VERSION}")
SET(CPACK_PACKAGE_INSTALL_REGISTRY_KEY
"${PROJECT_NAME} ${PROJECT_VERSION}")
SET(CPACK_COMPONENTS_ALL headers library html_documentation bin)
SET(CPACK_COMPONENT_HEADERS_DISPLAY_NAME "C++ headers")
SET(CPACK_COMPONENT_LIBRARY_DISPLAY_NAME "Dynamic-link library")
SET(CPACK_COMPONENT_BIN_DISPLAY_NAME "Command line utilities")
SET(CPACK_COMPONENT_HTML_DOCUMENTATION_DISPLAY_NAME "HTML documentation")
SET(CPACK_COMPONENT_HEADERS_DESCRIPTION
"C++ header files")
SET(CPACK_COMPONENT_LIBRARY_DESCRIPTION
"DLL and import library")
SET(CPACK_COMPONENT_BIN_DESCRIPTION
"Command line utilities")
SET(CPACK_COMPONENT_HTML_DOCUMENTATION_DESCRIPTION
"Doxygen generated documentation")
SET(CPACK_COMPONENT_HEADERS_DEPENDS library)
SET(CPACK_COMPONENT_HEADERS_GROUP "Development")
SET(CPACK_COMPONENT_LIBRARY_GROUP "Development")
SET(CPACK_COMPONENT_HTML_DOCUMENTATION_GROUP "Documentation")
SET(CPACK_COMPONENT_GROUP_DEVELOPMENT_DESCRIPTION
"Components needed to develop software using LEMON")
SET(CPACK_COMPONENT_GROUP_DOCUMENTATION_DESCRIPTION
"Documentation of LEMON")
SET(CPACK_ALL_INSTALL_TYPES Full Developer)
SET(CPACK_COMPONENT_HEADERS_INSTALL_TYPES Developer Full)
SET(CPACK_COMPONENT_LIBRARY_INSTALL_TYPES Developer Full)
SET(CPACK_COMPONENT_HTML_DOCUMENTATION_INSTALL_TYPES Full)
SET(CPACK_GENERATOR "NSIS")
SET(CPACK_NSIS_MUI_ICON "${PROJECT_SOURCE_DIR}/cmake/nsis/lemon.ico")
SET(CPACK_NSIS_MUI_UNIICON "${PROJECT_SOURCE_DIR}/cmake/nsis/uninstall.ico")
#SET(CPACK_PACKAGE_ICON "${PROJECT_SOURCE_DIR}/cmake/nsis\\\\installer.bmp")
SET(CPACK_NSIS_INSTALLED_ICON_NAME "bin\\\\lemon.ico")
SET(CPACK_NSIS_DISPLAY_NAME "${CPACK_PACKAGE_INSTALL_DIRECTORY} ${PROJECT_NAME}")
SET(CPACK_NSIS_HELP_LINK "http:\\\\\\\\lemon.cs.elte.hu")
SET(CPACK_NSIS_URL_INFO_ABOUT "http:\\\\\\\\lemon.cs.elte.hu")
SET(CPACK_NSIS_CONTACT "lemon-user@lemon.cs.elte.hu")
SET(CPACK_NSIS_CREATE_ICONS_EXTRA "
CreateShortCut \\\"$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\Documentation.lnk\\\" \\\"$INSTDIR\\\\share\\\\doc\\\\index.html\\\"
")
SET(CPACK_NSIS_DELETE_ICONS_EXTRA "
!insertmacro MUI_STARTMENU_GETFOLDER Application $MUI_TEMP
Delete \\\"$SMPROGRAMS\\\\$MUI_TEMP\\\\Documentation.lnk\\\"
")
INCLUDE(CPack)
ENDIF()

View File

@@ -0,0 +1,167 @@
Installation Instructions
=========================
This file contains instructions for building and installing LEMON from
source on Linux. The process on Windows is similar.
Note that it is not necessary to install LEMON in order to use
it. Instead, you can easily integrate it with your own code
directly. For instructions, see
https://lemon.cs.elte.hu/trac/lemon/wiki/HowToCompile
In order to install LEMON from the extracted source tarball you have to
issue the following commands:
1. Step into the root of the source directory.
$ cd lemon-x.y.z
2. Create a build subdirectory and step into it.
$ mkdir build
$ cd build
3. Perform system checks and create the makefiles.
$ cmake ..
4. Build LEMON.
$ make
This command compiles the non-template part of LEMON into
libemon.a file. It also compiles the programs in the 'tools' and
'demo' subdirectories.
5. [Optional] Compile and run the self-tests.
$ make check
5. [Optional] Generate the user documentation.
$ make html
The release tarballs already include the documentation.
Note that for this step you need to have the following tools
installed: Python, Doxygen, Graphviz, Ghostscript, LaTeX.
6. [Optional] Install LEMON
$ make install
This command installs LEMON under /usr/local (you will need root
privileges to be able to do that). If you want to install it to
some other location, then pass the
-DCMAKE_INSTALL_PREFIX=DIRECTORY flag to cmake in Step 3.
For example:
$ cmake -DCMAKE_INSTALL_PREFIX=/home/username/lemon'
Configure Options and Variables
===============================
In Step 3, you can customize the build process by passing options to CMAKE.
$ cmake [OPTIONS] ..
You find a list of the most useful options below.
-DCMAKE_INSTALL_PREFIX=PREFIX
Set the installation prefix to PREFIX. By default it is /usr/local.
-DCMAKE_BUILD_TYPE=[Release|Debug|Maintainer|...]
This sets the compiler options. The choices are the following
'Release': A strong optimization is turned on (-O3 with gcc). This
is the default setting and we strongly recommend using this for
the final compilation.
'Debug': Optimization is turned off and debug info is added (-O0
-ggdb with gcc). If is recommended during the development.
'Maintainer': The same as 'Debug' but the compiler warnings are
converted to errors (-Werror with gcc). In addition, 'make' will
also automatically compile and execute the test codes. It is the
best way of ensuring that LEMON codebase is clean and safe.
'RelWithDebInfo': Optimized build with debug info.
'MinSizeRel': Size optimized build (-Os with gcc)
-DTEST_WITH_VALGRIND=YES
Using this, the test codes will be executed using valgrind. It is a
very effective way of identifying indexing problems and memory leaks.
-DCMAKE_CXX_COMPILER=path-to-compiler
Change the compiler to be used.
-DBUILD_SHARED_LIBS=TRUE
Build shared library instead of static one. Think twice if you
really want to use this option.
-DLEMON_DOC_SOURCE_BROWSER=YES
Include the browsable cross referenced LEMON source code into the
doc. It makes the doc quite bloated, but may be useful for
developing LEMON itself.
-DLEMON_DOC_USE_MATHJAX=YES
Use MathJax (http://mathjax.org) for rendering the math formulae in
the doc. It of much higher quality compared to the default LaTeX
generated static images and it allows copy&paste of the formulae to
LaTeX, Open Office, MS Word etc. documents.
On the other hand, it needs either Internet access or a locally
installed version of MathJax to properly render the doc.
-DLEMON_DOC_MATHJAX_RELPATH=DIRECTORY
The location of the MathJax library. It defaults to
http://www.mathjax.org/mathjax, which necessitates Internet access
for proper rendering. The easiest way to make it usable offline is
to set this parameter to 'mathjax' and copy all files of the MathJax
library into the 'doc/html/mathjax' subdirectory of the build
location.
See http://docs.mathjax.org/en/latest/installation.html for more details.
-DLEMON_ENABLE_GLPK=NO
-DLEMON_ENABLE_COIN=NO
-DLEMON_ENABLE_ILOG=NO
Enable optional third party libraries. They are all enabled by default.
-DLEMON_DEFAULT_LP=GLPK
Sets the default LP solver backend. The supported values are
CPLEX, CLP and GLPK. By default, it is set to the first one which
is enabled and succesfully discovered.
-DLEMON_DEFAULT_MIP=GLPK
Sets the default MIP solver backend. The supported values are
CPLEX, CBC and GLPK. By default, it is set to the first one which
is enabled and succesfully discovered.
-DGLPK_ROOT_DIR=DIRECTORY
-DCOIN_ROOT_DIR=DIRECTORY
-DILOG_ROOT_DIR=DIRECTORY
Root directory prefixes of optional third party libraries.
Makefile Variables
==================
make VERBOSE=1
This results in a more verbose output by showing the full
compiler and linker commands.

View File

@@ -0,0 +1,32 @@
LEMON code without an explicit copyright notice is covered by the following
copyright/license.
Copyright (C) 2003-2012 Egervary Jeno Kombinatorikus Optimalizalasi
Kutatocsoport (Egervary Combinatorial Optimization Research Group,
EGRES).
===========================================================================
Boost Software License, Version 1.0
===========================================================================
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

337
extern/quadriflow/3rd/lemon-1.3.1/NEWS vendored Normal file
View File

@@ -0,0 +1,337 @@
2014-07-07 Version 1.3.1 released
Bugfix release.
#484: Require CMAKE 2.8
#471, #472, #480: Various clang compatibility fixes
#481, #482: Fix shared lib build and versioning
#476: Fix invalid map query in NearestNeighborTsp
#478: Bugfix in debug checking and lower bound handling
in min cost flow algorithms
#479, #465: Bugfix in default LP/MIP backend settings
#476: Bugfix in tsp_test
#487: Add missing include header and std:: namespace spec.
#474: Fix division by zero error in NetworkSimplex
2013-08-10 Version 1.3 released
This is major feature release
* New data structures
#69 : Bipartite graph concepts and implementations
* New algorithms
#177: Port Edmonds-Karp algorithm
#380, #405: Heuristic algorithm for the max clique problem
#386: Heuristic algorithms for symmetric TSP
----: Nagamochi-Ibaraki algorithm [5087694945e4]
#397, #56: Max. cardinality search
* Other new features
#223: Thread safe graph and graph map implementations
#442: Different TimeStamp print formats
#457: File export functionality to LpBase
#362: Bidirectional iterator support for radixSort()
* Implementation improvements
----: Network Simplex
#391: Better update process, pivot rule and arc mixing
#435: Improved Altering List pivot rule
#417: Various fine tunings in CostScaling
#438: Optional iteration limit in HowardMmc
#436: Ensure strongly polynomial running time for CycleCanceling
while keeping the same performance
----: Make the CBC interface be compatible with latest CBC releases
[ee581a0ecfbf]
* CMAKE has become the default build environment (#434)
----: Autotool support has been dropped
----: Improved LP/MIP configuration
#465: Enable/disable options for LP/MIP backends
#446: Better CPLEX discovery
#460: Add cmake config to find SoPlex
----: Allow CPACK configuration on all platforms
#390: Add 'Maintainer' CMAKE build type
#388: Add 'check' target.
#401: Add contrib dir
#389: Better version string setting in CMAKE
#433: Support shared library build
#416: Support testing with valgrind
* Doc improvements
#395: SOURCE_BROWSER Doxygen switch is configurable from CMAKE
update-external-tags CMAKE target
#455: Optionally use MathJax for rendering the math formulae
#402, #437, #459, #456, #463: Various doc improvements
* Bugfixes (compared to release 1.2):
#432: Add missing doc/template.h and doc/references.bib to release
tarball
----: Intel C++ compatibility fixes
#441: Fix buggy reinitialization in _solver_bits::VarIndex::clear()
#444: Bugfix in path copy constructors and assignment operators
#447: Bugfix in AllArcLookUp<>
#448: Bugfix in adaptor_test.cc
#449: Fix clang compilation warnings and errors
#440: Fix a bug + remove redundant typedefs in dimacs-solver
#453: Avoid GCC 4.7 compiler warnings
#445: Fix missing initialization in CplexEnv::CplexEnv()
#428: Add missing lemon/lemon.pc.cmake to the release tarball
#393: Create and install lemon.pc
#429: Fix VS warnings
#430: Fix LpBase::Constr two-side limit bug
#392: Bug fix in Dfs::start(s,t)
#414: Fix wrong initialization in Preflow
#418: Better Win CodeBlock/MinGW support
#419: Build environment improvements
- Build of mip_test and lp_test precede the running of the tests
- Also search for coin libs under ${COIN_ROOT_DIR}/lib/coin
- Do not look for COIN_VOL libraries
#382: Allow lgf file without Arc maps
#417: Bug fix in CostScaling
#366: Fix Pred[Matrix]MapPath::empty()
#371: Bug fix in (di)graphCopy()
The target graph is cleared before adding nodes and arcs/edges.
#364: Add missing UndirectedTags
#368: Fix the usage of std::numeric_limits<>::min() in Network Simplex
#372: Fix a critical bug in preflow
#461: Bugfix in assert.h
#470: Fix compilation issues related to various gcc versions
#446: Fix #define indicating CPLEX availability
#294: Add explicit namespace to
ignore_unused_variable_warning() usages
#420: Bugfix in IterableValueMap
#439: Bugfix in biNodeConnected()
2010-03-19 Version 1.2 released
This is major feature release
* New algorithms
* Bellman-Ford algorithm (#51)
* Minimum mean cycle algorithms (#179)
* Karp, Hartman-Orlin and Howard algorithms
* New minimum cost flow algorithms (#180)
* Cost Scaling algorithms
* Capacity Scaling algorithm
* Cycle-Canceling algorithms
* Planarity related algorithms (#62)
* Planarity checking algorithm
* Planar embedding algorithm
* Schnyder's planar drawing algorithm
* Coloring planar graphs with five or six colors
* Fractional matching algorithms (#314)
* New data structures
* StaticDigraph structure (#68)
* Several new priority queue structures (#50, #301)
* Fibonacci, Radix, Bucket, Pairing, Binomial
D-ary and fourary heaps (#301)
* Iterable map structures (#73)
* Other new tools and functionality
* Map utility functions (#320)
* Reserve functions are added to ListGraph and SmartGraph (#311)
* A resize() function is added to HypercubeGraph (#311)
* A count() function is added to CrossRefMap (#302)
* Support for multiple targets in Suurballe using fullInit() (#181)
* Traits class and named parameters for Suurballe (#323)
* Separate reset() and resetParams() functions in NetworkSimplex
to handle graph changes (#327)
* tolerance() functions are added to HaoOrlin (#306)
* Implementation improvements
* Improvements in weighted matching algorithms (#314)
* Jumpstart initialization
* ArcIt iteration is based on out-arc lists instead of in-arc lists
in ListDigraph (#311)
* Faster add row operation in CbcMip (#203)
* Better implementation for split() in ListDigraph (#311)
* ArgParser can also throw exception instead of exit(1) (#332)
* Miscellaneous
* A simple interactive bootstrap script
* Doc improvements (#62,#180,#299,#302,#303,#304,#307,#311,#331,#315,
#316,#319)
* BibTeX references in the doc (#184)
* Optionally use valgrind when running tests
* Also check ReferenceMapTag in concept checks (#312)
* dimacs-solver uses long long type by default.
* Several bugfixes (compared to release 1.1):
#295: Suppress MSVC warnings using pragmas
----: Various CMAKE related improvements
* Remove duplications from doc/CMakeLists.txt
* Rename documentation install folder from 'docs' to 'html'
* Add tools/CMakeLists.txt to the tarball
* Generate and install LEMONConfig.cmake
* Change the label of the html project in Visual Studio
* Fix the check for the 'long long' type
* Put the version string into config.h
* Minor CMake improvements
* Set the version to 'hg-tip' if everything fails
#311: Add missing 'explicit' keywords
#302: Fix the implementation and doc of CrossRefMap
#308: Remove duplicate list_graph.h entry from source list
#307: Bugfix in Preflow and Circulation
#305: Bugfix and extension in the rename script
#312: Also check ReferenceMapTag in concept checks
#250: Bugfix in pathSource() and pathTarget()
#321: Use pathCopy(from,to) instead of copyPath(to,from)
#322: Distribure LEMONConfig.cmake.in
#330: Bug fix in map_extender.h
#336: Fix the date field comment of graphToEps() output
#323: Bug fix in Suurballe
#335: Fix clear() function in ExtendFindEnum
#337: Use void* as the LPX object pointer
#317: Fix (and improve) error message in mip_test.cc
Remove unnecessary OsiCbc dependency
#356: Allow multiple executions of weighted matching algorithms (#356)
2009-05-13 Version 1.1 released
This is the second stable release of the 1.x series. It
features a better coverage of the tools available in the 0.x
series, a thoroughly reworked LP/MIP interface plus various
improvements in the existing tools.
* Much improved M$ Windows support
* Various improvements in the CMAKE build system
* Compilation warnings are fixed/suppressed
* Support IBM xlC compiler
* New algorithms
* Connectivity related algorithms (#61)
* Euler walks (#65)
* Preflow push-relabel max. flow algorithm (#176)
* Circulation algorithm (push-relabel based) (#175)
* Suurballe algorithm (#47)
* Gomory-Hu algorithm (#66)
* Hao-Orlin algorithm (#58)
* Edmond's maximum cardinality and weighted matching algorithms
in general graphs (#48,#265)
* Minimum cost arborescence/branching (#60)
* Network Simplex min. cost flow algorithm (#234)
* New data structures
* Full graph structure (#57)
* Grid graph structure (#57)
* Hypercube graph structure (#57)
* Graph adaptors (#67)
* ArcSet and EdgeSet classes (#67)
* Elevator class (#174)
* Other new tools
* LP/MIP interface (#44)
* Support for GLPK, CPLEX, Soplex, COIN-OR CLP and CBC
* Reader for the Nauty file format (#55)
* DIMACS readers (#167)
* Radix sort algorithms (#72)
* RangeIdMap and CrossRefMap (#160)
* New command line tools
* DIMACS to LGF converter (#182)
* lgf-gen - a graph generator (#45)
* DIMACS solver utility (#226)
* Other code improvements
* Lognormal distribution added to Random (#102)
* Better (i.e. O(1) time) item counting in SmartGraph (#3)
* The standard maps of graphs are guaranteed to be
reference maps (#190)
* Miscellaneous
* Various doc improvements
* Improved 0.x -> 1.x converter script
* Several bugfixes (compared to release 1.0):
#170: Bugfix SmartDigraph::split()
#171: Bugfix in SmartGraph::restoreSnapshot()
#172: Extended test cases for graphs and digraphs
#173: Bugfix in Random
* operator()s always return a double now
* the faulty real<Num>(Num) and real<Num>(Num,Num)
have been removed
#187: Remove DijkstraWidestPathOperationTraits
#61: Bugfix in DfsVisit
#193: Bugfix in GraphReader::skipSection()
#195: Bugfix in ConEdgeIt()
#197: Bugfix in heap unionfind
* This bug affects Edmond's general matching algorithms
#207: Fix 'make install' without 'make html' using CMAKE
#208: Suppress or fix VS2008 compilation warnings
----: Update the LEMON icon
----: Enable the component-based installer
(in installers made by CPACK)
----: Set the proper version for CMAKE in the tarballs
(made by autotools)
----: Minor clarification in the LICENSE file
----: Add missing unistd.h include to time_measure.h
#204: Compilation bug fixed in graph_to_eps.h with VS2005
#214,#215: windows.h should never be included by LEMON headers
#230: Build systems check the availability of 'long long' type
#229: Default implementation of Tolerance<> is used for integer types
#211,#212: Various fixes for compiling on AIX
----: Improvements in CMAKE config
- docs is installed in share/doc/
- detects newer versions of Ghostscript
#239: Fix missing 'inline' specifier in time_measure.h
#274,#280: Install lemon/config.h
#275: Prefix macro names with LEMON_ in lemon/config.h
----: Small script for making the release tarballs added
----: Minor improvement in unify-sources.sh (a76f55d7d397)
2009-03-27 LEMON joins to the COIN-OR initiative
COIN-OR (Computational Infrastructure for Operations Research,
http://www.coin-or.org) project is an initiative to spur the
development of open-source software for the operations research
community.
2008-10-13 Version 1.0 released
This is the first stable release of LEMON. Compared to the 0.x
release series, it features a considerably smaller but more
matured set of tools. The API has also completely revised and
changed in several places.
* The major name changes compared to the 0.x series (see the
Migration Guide in the doc for more details)
* Graph -> Digraph, UGraph -> Graph
* Edge -> Arc, UEdge -> Edge
* source(UEdge)/target(UEdge) -> u(Edge)/v(Edge)
* Other improvements
* Better documentation
* Reviewed and cleaned up codebase
* CMake based build system (along with the autotools based one)
* Contents of the library (ported from 0.x)
* Algorithms
* breadth-first search (bfs.h)
* depth-first search (dfs.h)
* Dijkstra's algorithm (dijkstra.h)
* Kruskal's algorithm (kruskal.h)
* Data structures
* graph data structures (list_graph.h, smart_graph.h)
* path data structures (path.h)
* binary heap data structure (bin_heap.h)
* union-find data structures (unionfind.h)
* miscellaneous property maps (maps.h)
* two dimensional vector and bounding box (dim2.h)
* Concepts
* graph structure concepts (concepts/digraph.h, concepts/graph.h,
concepts/graph_components.h)
* concepts for other structures (concepts/heap.h, concepts/maps.h,
concepts/path.h)
* Tools
* Mersenne twister random number generator (random.h)
* tools for measuring cpu and wall clock time (time_measure.h)
* tools for counting steps and events (counter.h)
* tool for parsing command line arguments (arg_parser.h)
* tool for visualizing graphs (graph_to_eps.h)
* tools for reading and writing data in LEMON Graph Format
(lgf_reader.h, lgf_writer.h)
* tools to handle the anomalies of calculations with
floating point numbers (tolerance.h)
* tools to manage RGB colors (color.h)
* Infrastructure
* extended assertion handling (assert.h)
* exception classes and error handling (error.h)
* concept checking (concept_check.h)
* commonly used mathematical constants (math.h)

View File

@@ -0,0 +1,50 @@
=====================================================================
LEMON - a Library for Efficient Modeling and Optimization in Networks
=====================================================================
LEMON is an open source library written in C++. It provides
easy-to-use implementations of common data structures and algorithms
in the area of optimization and helps implementing new ones. The main
focus is on graphs and graph algorithms, thus it is especially
suitable for solving design and optimization problems of
telecommunication networks. To achieve wide usability its data
structures and algorithms provide generic interfaces.
Contents
========
LICENSE
Copying, distribution and modification conditions and terms.
NEWS
News and version history.
INSTALL
General building and installation instructions.
lemon/
Source code of LEMON library.
doc/
Documentation of LEMON. The starting page is doc/html/index.html.
demo/
Some example programs to make you easier to get familiar with LEMON.
scripts/
Scripts that make it easier to develop LEMON.
test/
Programs to check the integrity and correctness of LEMON.
tools/
Various utilities related to LEMON.

View File

@@ -0,0 +1,110 @@
SET(COIN_ROOT_DIR "" CACHE PATH "COIN root directory")
FIND_PATH(COIN_INCLUDE_DIR coin/CoinUtilsConfig.h
HINTS ${COIN_ROOT_DIR}/include
)
FIND_LIBRARY(COIN_CBC_LIBRARY
NAMES Cbc libCbc
HINTS ${COIN_ROOT_DIR}/lib/coin
HINTS ${COIN_ROOT_DIR}/lib
)
FIND_LIBRARY(COIN_CBC_SOLVER_LIBRARY
NAMES CbcSolver libCbcSolver
HINTS ${COIN_ROOT_DIR}/lib/coin
HINTS ${COIN_ROOT_DIR}/lib
)
FIND_LIBRARY(COIN_CGL_LIBRARY
NAMES Cgl libCgl
HINTS ${COIN_ROOT_DIR}/lib/coin
HINTS ${COIN_ROOT_DIR}/lib
)
FIND_LIBRARY(COIN_CLP_LIBRARY
NAMES Clp libClp
HINTS ${COIN_ROOT_DIR}/lib/coin
HINTS ${COIN_ROOT_DIR}/lib
)
FIND_LIBRARY(COIN_COIN_UTILS_LIBRARY
NAMES CoinUtils libCoinUtils
HINTS ${COIN_ROOT_DIR}/lib/coin
HINTS ${COIN_ROOT_DIR}/lib
)
FIND_LIBRARY(COIN_OSI_LIBRARY
NAMES Osi libOsi
HINTS ${COIN_ROOT_DIR}/lib/coin
HINTS ${COIN_ROOT_DIR}/lib
)
FIND_LIBRARY(COIN_OSI_CBC_LIBRARY
NAMES OsiCbc libOsiCbc
HINTS ${COIN_ROOT_DIR}/lib/coin
HINTS ${COIN_ROOT_DIR}/lib
)
FIND_LIBRARY(COIN_OSI_CLP_LIBRARY
NAMES OsiClp libOsiClp
HINTS ${COIN_ROOT_DIR}/lib/coin
HINTS ${COIN_ROOT_DIR}/lib
)
FIND_LIBRARY(COIN_OSI_VOL_LIBRARY
NAMES OsiVol libOsiVol
HINTS ${COIN_ROOT_DIR}/lib/coin
HINTS ${COIN_ROOT_DIR}/lib
)
FIND_LIBRARY(COIN_VOL_LIBRARY
NAMES Vol libVol
HINTS ${COIN_ROOT_DIR}/lib/coin
HINTS ${COIN_ROOT_DIR}/lib
)
FIND_LIBRARY(COIN_ZLIB_LIBRARY
NAMES z libz
HINTS ${COIN_ROOT_DIR}/lib/coin
HINTS ${COIN_ROOT_DIR}/lib
)
FIND_LIBRARY(COIN_BZ2_LIBRARY
NAMES bz2 libbz2
HINTS ${COIN_ROOT_DIR}/lib/coin
HINTS ${COIN_ROOT_DIR}/lib
)
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(COIN DEFAULT_MSG
COIN_INCLUDE_DIR
COIN_CBC_LIBRARY
COIN_CBC_SOLVER_LIBRARY
COIN_CGL_LIBRARY
COIN_CLP_LIBRARY
COIN_COIN_UTILS_LIBRARY
COIN_OSI_LIBRARY
COIN_OSI_CBC_LIBRARY
COIN_OSI_CLP_LIBRARY
# COIN_OSI_VOL_LIBRARY
# COIN_VOL_LIBRARY
)
IF(COIN_FOUND)
SET(COIN_INCLUDE_DIRS ${COIN_INCLUDE_DIR})
SET(COIN_CLP_LIBRARIES "${COIN_CLP_LIBRARY};${COIN_COIN_UTILS_LIBRARY};${COIN_ZLIB_LIBRARY};${COIN_BZ2_LIBRARY}")
IF(COIN_ZLIB_LIBRARY)
SET(COIN_CLP_LIBRARIES "${COIN_CLP_LIBRARIES};${COIN_ZLIB_LIBRARY}")
ENDIF(COIN_ZLIB_LIBRARY)
IF(COIN_BZ2_LIBRARY)
SET(COIN_CLP_LIBRARIES "${COIN_CLP_LIBRARIES};${COIN_BZ2_LIBRARY}")
ENDIF(COIN_BZ2_LIBRARY)
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}")
SET(COIN_LIBRARIES ${COIN_CBC_LIBRARIES})
ENDIF(COIN_FOUND)
MARK_AS_ADVANCED(
COIN_INCLUDE_DIR
COIN_CBC_LIBRARY
COIN_CBC_SOLVER_LIBRARY
COIN_CGL_LIBRARY
COIN_CLP_LIBRARY
COIN_COIN_UTILS_LIBRARY
COIN_OSI_LIBRARY
COIN_OSI_CBC_LIBRARY
COIN_OSI_CLP_LIBRARY
COIN_OSI_VOL_LIBRARY
COIN_VOL_LIBRARY
COIN_ZLIB_LIBRARY
COIN_BZ2_LIBRARY
)

View File

@@ -0,0 +1,55 @@
SET(GLPK_ROOT_DIR "" CACHE PATH "GLPK root directory")
SET(GLPK_REGKEY "[HKEY_LOCAL_MACHINE\\SOFTWARE\\GnuWin32\\Glpk;InstallPath]")
GET_FILENAME_COMPONENT(GLPK_ROOT_PATH ${GLPK_REGKEY} ABSOLUTE)
FIND_PATH(GLPK_INCLUDE_DIR
glpk.h
PATHS ${GLPK_REGKEY}/include
HINTS ${GLPK_ROOT_DIR}/include
)
FIND_LIBRARY(GLPK_LIBRARY
glpk
PATHS ${GLPK_REGKEY}/lib
HINTS ${GLPK_ROOT_DIR}/lib
)
IF(GLPK_INCLUDE_DIR AND GLPK_LIBRARY)
FILE(READ ${GLPK_INCLUDE_DIR}/glpk.h GLPK_GLPK_H)
STRING(REGEX MATCH "define[ ]+GLP_MAJOR_VERSION[ ]+[0-9]+" GLPK_MAJOR_VERSION_LINE "${GLPK_GLPK_H}")
STRING(REGEX REPLACE "define[ ]+GLP_MAJOR_VERSION[ ]+([0-9]+)" "\\1" GLPK_VERSION_MAJOR "${GLPK_MAJOR_VERSION_LINE}")
STRING(REGEX MATCH "define[ ]+GLP_MINOR_VERSION[ ]+[0-9]+" GLPK_MINOR_VERSION_LINE "${GLPK_GLPK_H}")
STRING(REGEX REPLACE "define[ ]+GLP_MINOR_VERSION[ ]+([0-9]+)" "\\1" GLPK_VERSION_MINOR "${GLPK_MINOR_VERSION_LINE}")
SET(GLPK_VERSION_STRING "${GLPK_VERSION_MAJOR}.${GLPK_VERSION_MINOR}")
IF(GLPK_FIND_VERSION)
IF(GLPK_FIND_VERSION_COUNT GREATER 2)
MESSAGE(SEND_ERROR "unexpected version string")
ENDIF(GLPK_FIND_VERSION_COUNT GREATER 2)
MATH(EXPR GLPK_REQUESTED_VERSION "${GLPK_FIND_VERSION_MAJOR}*100 + ${GLPK_FIND_VERSION_MINOR}")
MATH(EXPR GLPK_FOUND_VERSION "${GLPK_VERSION_MAJOR}*100 + ${GLPK_VERSION_MINOR}")
IF(GLPK_FOUND_VERSION LESS GLPK_REQUESTED_VERSION)
SET(GLPK_PROPER_VERSION_FOUND FALSE)
ELSE(GLPK_FOUND_VERSION LESS GLPK_REQUESTED_VERSION)
SET(GLPK_PROPER_VERSION_FOUND TRUE)
ENDIF(GLPK_FOUND_VERSION LESS GLPK_REQUESTED_VERSION)
ELSE(GLPK_FIND_VERSION)
SET(GLPK_PROPER_VERSION_FOUND TRUE)
ENDIF(GLPK_FIND_VERSION)
ENDIF(GLPK_INCLUDE_DIR AND GLPK_LIBRARY)
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(GLPK DEFAULT_MSG GLPK_LIBRARY GLPK_INCLUDE_DIR GLPK_PROPER_VERSION_FOUND)
IF(GLPK_FOUND)
SET(GLPK_INCLUDE_DIRS ${GLPK_INCLUDE_DIR})
SET(GLPK_LIBRARIES ${GLPK_LIBRARY})
SET(GLPK_BIN_DIR ${GLPK_ROOT_PATH}/bin)
ENDIF(GLPK_FOUND)
MARK_AS_ADVANCED(GLPK_LIBRARY GLPK_INCLUDE_DIR GLPK_BIN_DIR)

View File

@@ -0,0 +1,10 @@
INCLUDE(FindPackageHandleStandardArgs)
FIND_PROGRAM(GHOSTSCRIPT_EXECUTABLE
NAMES gs gswin32c
PATHS "$ENV{ProgramFiles}/gs"
PATH_SUFFIXES gs8.61/bin gs8.62/bin gs8.63/bin gs8.64/bin gs8.65/bin
DOC "Ghostscript: PostScript and PDF language interpreter and previewer."
)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Ghostscript DEFAULT_MSG GHOSTSCRIPT_EXECUTABLE)

View File

@@ -0,0 +1,102 @@
FIND_PATH(ILOG_ROOT_DIR
NAMES cplex
DOC "CPLEX STUDIO root directory"
PATHS /opt/ibm/ILOG /usr/local/ibm/ILOG /usr/local/ILOG /usr/local/ilog
PATHS "$ENV{HOME}/ILOG" "$ENV{HOME}/.local/ILOG"
PATHS "$ENV{HOME}/ibm/ILOG" "$ENV{HOME}/.local/ibm/ILOG"
PATHS "C:/Program Files/IBM/ILOG"
PATH_SUFFIXES "CPLEX_Studio126" "CPLEX_Studio125"
"CPLEX_Studio124" "CPLEX_Studio123" "CPLEX_Studio122"
NO_DEFAULT_PATH
)
IF(WIN32)
IF(MSVC_VERSION STREQUAL "1400")
SET(ILOG_WIN_COMPILER "windows_vs2005")
ELSEIF(MSVC_VERSION STREQUAL "1500")
SET(ILOG_WIN_COMPILER "windows_vs2008")
ELSEIF(MSVC_VERSION STREQUAL "1600")
SET(ILOG_WIN_COMPILER "windows_vs2010")
ELSE()
SET(ILOG_WIN_COMPILER "windows_vs2008")
ENDIF()
IF(CMAKE_CL_64)
SET(ILOG_WIN_COMPILER "x64_${ILOG_WIN_COMPILER}")
SET(ILOG_WIN_PLATFORM "x64_win32")
ELSE()
SET(ILOG_WIN_COMPILER "x86_${ILOG_WIN_COMPILER}")
SET(ILOG_WIN_PLATFORM "x86_win32")
ENDIF()
ENDIF()
FIND_PATH(ILOG_CPLEX_ROOT_DIR
NAMES include/ilcplex
HINTS ${ILOG_ROOT_DIR}/cplex ${ILOG_ROOT_DIR}/cplex121
${ILOG_ROOT_DIR}/cplex122 ${ILOG_ROOT_DIR}/cplex123
DOC "CPLEX root directory"
NO_DEFAULT_PATH
)
FIND_PATH(ILOG_CONCERT_ROOT_DIR
NAMES include/ilconcert
HINTS ${ILOG_ROOT_DIR}/concert ${ILOG_ROOT_DIR}/concert29
DOC "CONCERT root directory"
NO_DEFAULT_PATH
)
FIND_PATH(ILOG_CPLEX_INCLUDE_DIR
ilcplex/cplex.h
HINTS ${ILOG_CPLEX_ROOT_DIR}/include
NO_DEFAULT_PATH
)
FIND_PATH(ILOG_CONCERT_INCLUDE_DIR
ilconcert/ilobasic.h
HINTS ${ILOG_CONCERT_ROOT_DIR}/include
NO_DEFAULT_PATH
)
FIND_LIBRARY(ILOG_CPLEX_LIBRARY
cplex cplex121 cplex122 cplex123 cplex124
HINTS ${ILOG_CPLEX_ROOT_DIR}/lib/x86_sles10_4.1/static_pic
${ILOG_CPLEX_ROOT_DIR}/lib/x86-64_sles10_4.1/static_pic
${ILOG_CPLEX_ROOT_DIR}/lib/x86_debian4.0_4.1/static_pic
${ILOG_CPLEX_ROOT_DIR}/lib/x86-64_debian4.0_4.1/static_pic
${ILOG_CPLEX_ROOT_DIR}/lib/${ILOG_WIN_COMPILER}/stat_mda
NO_DEFAULT_PATH
)
FIND_LIBRARY(ILOG_CONCERT_LIBRARY
concert
HINTS ${ILOG_CONCERT_ROOT_DIR}/lib/x86_sles10_4.1/static_pic
${ILOG_CONCERT_ROOT_DIR}/lib/x86-64_sles10_4.1/static_pic
${ILOG_CONCERT_ROOT_DIR}/lib/x86_debian4.0_4.1/static_pic
${ILOG_CONCERT_ROOT_DIR}/lib/x86-64_debian4.0_4.1/static_pic
${ILOG_CONCERT_ROOT_DIR}/lib/${ILOG_WIN_COMPILER}/stat_mda
NO_DEFAULT_PATH
)
FIND_FILE(ILOG_CPLEX_DLL
cplex121.dll cplex122.dll cplex123.dll cplex124.dll
HINTS ${ILOG_CPLEX_ROOT_DIR}/bin/${ILOG_WIN_PLATFORM}
NO_DEFAULT_PATH
)
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(ILOG
DEFAULT_MSG ILOG_CPLEX_LIBRARY ILOG_CPLEX_INCLUDE_DIR
)
IF(ILOG_FOUND)
SET(ILOG_INCLUDE_DIRS ${ILOG_CPLEX_INCLUDE_DIR} ${ILOG_CONCERT_INCLUDE_DIR})
SET(ILOG_LIBRARIES ${ILOG_CPLEX_LIBRARY} ${ILOG_CONCERT_LIBRARY})
IF(CMAKE_SYSTEM_NAME STREQUAL "Linux")
# SET(CPLEX_LIBRARIES "${CPLEX_LIBRARIES};m;pthread")
SET(ILOG_LIBRARIES ${ILOG_LIBRARIES} "m" "pthread")
ENDIF(CMAKE_SYSTEM_NAME STREQUAL "Linux")
ENDIF(ILOG_FOUND)
MARK_AS_ADVANCED(
ILOG_CPLEX_LIBRARY ILOG_CPLEX_INCLUDE_DIR ILOG_CPLEX_DLL
ILOG_CONCERT_LIBRARY ILOG_CONCERT_INCLUDE_DIR ILOG_CONCERT_DLL
)

View File

@@ -0,0 +1,23 @@
SET(SOPLEX_ROOT_DIR "" CACHE PATH "SoPlex root directory")
FIND_PATH(SOPLEX_INCLUDE_DIR
soplex.h
HINTS ${SOPLEX_ROOT_DIR}/src
)
FIND_LIBRARY(SOPLEX_LIBRARY
soplex
HINTS ${SOPLEX_ROOT_DIR}/lib
)
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(SOPLEX DEFAULT_MSG SOPLEX_LIBRARY SOPLEX_INCLUDE_DIR)
IF(SOPLEX_FOUND)
SET(SOPLEX_INCLUDE_DIRS ${SOPLEX_INCLUDE_DIR})
SET(SOPLEX_LIBRARIES ${SOPLEX_LIBRARY})
IF(CMAKE_SYSTEM_NAME STREQUAL "Linux")
SET(SOPLEX_LIBRARIES "${SOPLEX_LIBRARIES};z")
ENDIF(CMAKE_SYSTEM_NAME STREQUAL "Linux")
ENDIF(SOPLEX_FOUND)
MARK_AS_ADVANCED(SOPLEX_LIBRARY SOPLEX_INCLUDE_DIR)

View File

@@ -0,0 +1,13 @@
SET(LEMON_INCLUDE_DIR "@CMAKE_INSTALL_PREFIX@/include" CACHE PATH "LEMON include directory")
SET(LEMON_INCLUDE_DIRS "${LEMON_INCLUDE_DIR}")
IF(UNIX)
SET(LEMON_LIB_NAME "libemon.a")
ELSEIF(WIN32)
SET(LEMON_LIB_NAME "lemon.lib")
ENDIF(UNIX)
SET(LEMON_LIBRARY "@CMAKE_INSTALL_PREFIX@/lib/${LEMON_LIB_NAME}" CACHE FILEPATH "LEMON library")
SET(LEMON_LIBRARIES "${LEMON_LIBRARY}")
MARK_AS_ADVANCED(LEMON_LIBRARY LEMON_INCLUDE_DIR)

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -0,0 +1 @@
SET(LEMON_VERSION "1.3.1" CACHE STRING "LEMON version string.")

View File

@@ -0,0 +1 @@
SET(LEMON_VERSION "@LEMON_VERSION@" CACHE STRING "LEMON version string.")

View File

@@ -0,0 +1,19 @@
INCLUDE_DIRECTORIES(
${PROJECT_SOURCE_DIR}
${PROJECT_BINARY_DIR}
)
LINK_DIRECTORIES(
${PROJECT_BINARY_DIR}/lemon
)
# Uncomment (and adjust) the following two lines. 'myprog' is the name
# of the final executable ('.exe' will automatically be added to the
# name on Windows) and 'myprog-main.cc' is the source code it is
# compiled from. You can add more source files separated by
# whitespaces. Moreover, you can add multiple similar blocks if you
# want to build more than one executables.
# ADD_EXECUTABLE(myprog myprog-main.cc)
# TARGET_LINK_LIBRARIES(myprog lemon)

View File

@@ -0,0 +1,19 @@
INCLUDE_DIRECTORIES(
${PROJECT_SOURCE_DIR}
${PROJECT_BINARY_DIR}
)
LINK_DIRECTORIES(
${PROJECT_BINARY_DIR}/lemon
)
SET(DEMOS
arg_parser_demo
graph_to_eps_demo
lgf_demo
)
FOREACH(DEMO_NAME ${DEMOS})
ADD_EXECUTABLE(${DEMO_NAME} ${DEMO_NAME}.cc)
TARGET_LINK_LIBRARIES(${DEMO_NAME} lemon)
ENDFOREACH()

View File

@@ -0,0 +1,112 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2010
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
///\ingroup demos
///\file
///\brief Argument parser demo
///
/// This example shows how the argument parser can be used.
///
/// \include arg_parser_demo.cc
#include <lemon/arg_parser.h>
using namespace lemon;
int main(int argc, char **argv)
{
// Initialize the argument parser
ArgParser ap(argc, argv);
int i;
std::string s;
double d = 1.0;
bool b, nh;
bool g1, g2, g3;
// Add a mandatory integer option with storage reference
ap.refOption("n", "An integer input.", i, true);
// Add a double option with storage reference (the default value is 1.0)
ap.refOption("val", "A double input.", d);
// Add a double option without storage reference (the default value is 3.14)
ap.doubleOption("val2", "A double input.", 3.14);
// Set synonym for -val option
ap.synonym("vals", "val");
// Add a string option
ap.refOption("name", "A string input.", s);
// Add bool options
ap.refOption("f", "A switch.", b)
.refOption("nohelp", "", nh)
.refOption("gra", "Choice A", g1)
.refOption("grb", "Choice B", g2)
.refOption("grc", "Choice C", g3);
// Bundle -gr* options into a group
ap.optionGroup("gr", "gra")
.optionGroup("gr", "grb")
.optionGroup("gr", "grc");
// Set the group mandatory
ap.mandatoryGroup("gr");
// Set the options of the group exclusive (only one option can be given)
ap.onlyOneGroup("gr");
// Add non-parsed arguments (e.g. input files)
ap.other("infile", "The input file.")
.other("...");
// Throw an exception when problems occurs. The default behavior is to
// exit(1) on these cases, but this makes Valgrind falsely warn
// about memory leaks.
ap.throwOnProblems();
// Perform the parsing process
// (in case of any error it terminates the program)
// The try {} construct is necessary only if the ap.trowOnProblems()
// setting is in use.
try {
ap.parse();
} catch (ArgParserException &) { return 1; }
// Check each option if it has been given and print its value
std::cout << "Parameters of '" << ap.commandName() << "':\n";
std::cout << " Value of -n: " << i << std::endl;
if(ap.given("val")) std::cout << " Value of -val: " << d << std::endl;
if(ap.given("val2")) {
d = ap["val2"];
std::cout << " Value of -val2: " << d << std::endl;
}
if(ap.given("name")) std::cout << " Value of -name: " << s << std::endl;
if(ap.given("f")) std::cout << " -f is given\n";
if(ap.given("nohelp")) std::cout << " Value of -nohelp: " << nh << std::endl;
if(ap.given("gra")) std::cout << " -gra is given\n";
if(ap.given("grb")) std::cout << " -grb is given\n";
if(ap.given("grc")) std::cout << " -grc is given\n";
switch(ap.files().size()) {
case 0:
std::cout << " No file argument was given.\n";
break;
case 1:
std::cout << " 1 file argument was given. It is:\n";
break;
default:
std::cout << " "
<< ap.files().size() << " file arguments were given. They are:\n";
}
for(unsigned int i=0;i<ap.files().size();++i)
std::cout << " '" << ap.files()[i] << "'\n";
return 0;
}

View File

@@ -0,0 +1,29 @@
@nodes
label
0
1
2
3
4
5
6
7
@arcs
label capacity
0 1 0 16
0 2 1 12
0 3 2 20
1 2 3 10
1 4 4 10
1 5 5 13
2 3 6 10
2 4 7 8
2 6 8 8
5 3 9 20
3 6 10 25
4 7 11 15
5 7 12 15
6 7 13 18
@attributes
source 0
target 7

View File

@@ -0,0 +1,206 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2009
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
/// \ingroup demos
/// \file
/// \brief Demo of the graph drawing function \ref graphToEps()
///
/// This demo program shows examples how to use the function \ref
/// graphToEps(). It takes no input but simply creates seven
/// <tt>.eps</tt> files demonstrating the capability of \ref
/// graphToEps(), and showing how to draw directed graphs,
/// how to handle parallel egdes, how to change the properties (like
/// color, shape, size, title etc.) of nodes and arcs individually
/// using appropriate graph maps.
///
/// \include graph_to_eps_demo.cc
#include<lemon/list_graph.h>
#include<lemon/graph_to_eps.h>
#include<lemon/math.h>
using namespace std;
using namespace lemon;
int main()
{
Palette palette;
Palette paletteW(true);
// Create a small digraph
ListDigraph g;
typedef ListDigraph::Node Node;
typedef ListDigraph::NodeIt NodeIt;
typedef ListDigraph::Arc Arc;
typedef dim2::Point<int> Point;
Node n1=g.addNode();
Node n2=g.addNode();
Node n3=g.addNode();
Node n4=g.addNode();
Node n5=g.addNode();
ListDigraph::NodeMap<Point> coords(g);
ListDigraph::NodeMap<double> sizes(g);
ListDigraph::NodeMap<int> colors(g);
ListDigraph::NodeMap<int> shapes(g);
ListDigraph::ArcMap<int> acolors(g);
ListDigraph::ArcMap<int> widths(g);
coords[n1]=Point(50,50); sizes[n1]=1; colors[n1]=1; shapes[n1]=0;
coords[n2]=Point(50,70); sizes[n2]=2; colors[n2]=2; shapes[n2]=2;
coords[n3]=Point(70,70); sizes[n3]=1; colors[n3]=3; shapes[n3]=0;
coords[n4]=Point(70,50); sizes[n4]=2; colors[n4]=4; shapes[n4]=1;
coords[n5]=Point(85,60); sizes[n5]=3; colors[n5]=5; shapes[n5]=2;
Arc a;
a=g.addArc(n1,n2); acolors[a]=0; widths[a]=1;
a=g.addArc(n2,n3); acolors[a]=0; widths[a]=1;
a=g.addArc(n3,n5); acolors[a]=0; widths[a]=3;
a=g.addArc(n5,n4); acolors[a]=0; widths[a]=1;
a=g.addArc(n4,n1); acolors[a]=0; widths[a]=1;
a=g.addArc(n2,n4); acolors[a]=1; widths[a]=2;
a=g.addArc(n3,n4); acolors[a]=2; widths[a]=1;
IdMap<ListDigraph,Node> id(g);
// Create .eps files showing the digraph with different options
cout << "Create 'graph_to_eps_demo_out_1_pure.eps'" << endl;
graphToEps(g,"graph_to_eps_demo_out_1_pure.eps").
coords(coords).
title("Sample .eps figure").
copyright("(C) 2003-2009 LEMON Project").
run();
cout << "Create 'graph_to_eps_demo_out_2.eps'" << endl;
graphToEps(g,"graph_to_eps_demo_out_2.eps").
coords(coords).
title("Sample .eps figure").
copyright("(C) 2003-2009 LEMON Project").
absoluteNodeSizes().absoluteArcWidths().
nodeScale(2).nodeSizes(sizes).
nodeShapes(shapes).
nodeColors(composeMap(palette,colors)).
arcColors(composeMap(palette,acolors)).
arcWidthScale(.4).arcWidths(widths).
nodeTexts(id).nodeTextSize(3).
run();
cout << "Create 'graph_to_eps_demo_out_3_arr.eps'" << endl;
graphToEps(g,"graph_to_eps_demo_out_3_arr.eps").
title("Sample .eps figure (with arrowheads)").
copyright("(C) 2003-2009 LEMON Project").
absoluteNodeSizes().absoluteArcWidths().
nodeColors(composeMap(palette,colors)).
coords(coords).
nodeScale(2).nodeSizes(sizes).
nodeShapes(shapes).
arcColors(composeMap(palette,acolors)).
arcWidthScale(.4).arcWidths(widths).
nodeTexts(id).nodeTextSize(3).
drawArrows().arrowWidth(2).arrowLength(2).
run();
// Add more arcs to the digraph
a=g.addArc(n1,n4); acolors[a]=2; widths[a]=1;
a=g.addArc(n4,n1); acolors[a]=1; widths[a]=2;
a=g.addArc(n1,n2); acolors[a]=1; widths[a]=1;
a=g.addArc(n1,n2); acolors[a]=2; widths[a]=1;
a=g.addArc(n1,n2); acolors[a]=3; widths[a]=1;
a=g.addArc(n1,n2); acolors[a]=4; widths[a]=1;
a=g.addArc(n1,n2); acolors[a]=5; widths[a]=1;
a=g.addArc(n1,n2); acolors[a]=6; widths[a]=1;
a=g.addArc(n1,n2); acolors[a]=7; widths[a]=1;
cout << "Create 'graph_to_eps_demo_out_4_par.eps'" << endl;
graphToEps(g,"graph_to_eps_demo_out_4_par.eps").
title("Sample .eps figure (parallel arcs)").
copyright("(C) 2003-2009 LEMON Project").
absoluteNodeSizes().absoluteArcWidths().
nodeShapes(shapes).
coords(coords).
nodeScale(2).nodeSizes(sizes).
nodeColors(composeMap(palette,colors)).
arcColors(composeMap(palette,acolors)).
arcWidthScale(.4).arcWidths(widths).
nodeTexts(id).nodeTextSize(3).
enableParallel().parArcDist(1.5).
run();
cout << "Create 'graph_to_eps_demo_out_5_par_arr.eps'" << endl;
graphToEps(g,"graph_to_eps_demo_out_5_par_arr.eps").
title("Sample .eps figure (parallel arcs and arrowheads)").
copyright("(C) 2003-2009 LEMON Project").
absoluteNodeSizes().absoluteArcWidths().
nodeScale(2).nodeSizes(sizes).
coords(coords).
nodeShapes(shapes).
nodeColors(composeMap(palette,colors)).
arcColors(composeMap(palette,acolors)).
arcWidthScale(.3).arcWidths(widths).
nodeTexts(id).nodeTextSize(3).
enableParallel().parArcDist(1).
drawArrows().arrowWidth(1).arrowLength(1).
run();
cout << "Create 'graph_to_eps_demo_out_6_par_arr_a4.eps'" << endl;
graphToEps(g,"graph_to_eps_demo_out_6_par_arr_a4.eps").
title("Sample .eps figure (fits to A4)").
copyright("(C) 2003-2009 LEMON Project").
scaleToA4().
absoluteNodeSizes().absoluteArcWidths().
nodeScale(2).nodeSizes(sizes).
coords(coords).
nodeShapes(shapes).
nodeColors(composeMap(palette,colors)).
arcColors(composeMap(palette,acolors)).
arcWidthScale(.3).arcWidths(widths).
nodeTexts(id).nodeTextSize(3).
enableParallel().parArcDist(1).
drawArrows().arrowWidth(1).arrowLength(1).
run();
// Create an .eps file showing the colors of a default Palette
ListDigraph h;
ListDigraph::NodeMap<int> hcolors(h);
ListDigraph::NodeMap<Point> hcoords(h);
int cols=int(std::sqrt(double(palette.size())));
for(int i=0;i<int(paletteW.size());i++) {
Node n=h.addNode();
hcoords[n]=Point(1+i%cols,1+i/cols);
hcolors[n]=i;
}
cout << "Create 'graph_to_eps_demo_out_7_colors.eps'" << endl;
graphToEps(h,"graph_to_eps_demo_out_7_colors.eps").
scale(60).
title("Sample .eps figure (Palette demo)").
copyright("(C) 2003-2009 LEMON Project").
coords(hcoords).
absoluteNodeSizes().absoluteArcWidths().
nodeScale(.45).
distantColorNodeTexts().
nodeTexts(hcolors).nodeTextSize(.6).
nodeColors(composeMap(paletteW,hcolors)).
run();
return 0;
}

View File

@@ -0,0 +1,70 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2009
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
///\ingroup demos
///\file
///\brief Demonstrating graph input and output
///
/// This program gives an example of how to read and write a digraph
/// and additional maps from/to a stream or a file using the
/// \ref lgf-format "LGF" format.
///
/// The \c "digraph.lgf" file:
/// \include digraph.lgf
///
/// And the program which reads it and prints the digraph to the
/// standard output:
/// \include lgf_demo.cc
#include <iostream>
#include <lemon/smart_graph.h>
#include <lemon/lgf_reader.h>
#include <lemon/lgf_writer.h>
using namespace lemon;
int main() {
SmartDigraph g;
SmartDigraph::ArcMap<int> cap(g);
SmartDigraph::Node s, t;
try {
digraphReader(g, "digraph.lgf"). // read the directed graph into g
arcMap("capacity", cap). // read the 'capacity' arc map into cap
node("source", s). // read 'source' node to s
node("target", t). // read 'target' node to t
run();
} catch (Exception& error) { // check if there was any error
std::cerr << "Error: " << error.what() << std::endl;
return -1;
}
std::cout << "A digraph is read from 'digraph.lgf'." << std::endl;
std::cout << "Number of nodes: " << countNodes(g) << std::endl;
std::cout << "Number of arcs: " << countArcs(g) << std::endl;
std::cout << "We can write it to the standard output:" << std::endl;
digraphWriter(g). // write g to the standard output
arcMap("capacity", cap). // write cap into 'capacity'
node("source", s). // write s to 'source'
node("target", t). // write t to 'target'
run();
return 0;
}

View File

@@ -0,0 +1,91 @@
INCLUDE_DIRECTORIES(
${PROJECT_SOURCE_DIR}
${PROJECT_BINARY_DIR}
)
CONFIGURE_FILE(
${CMAKE_CURRENT_SOURCE_DIR}/config.h.in
${CMAKE_CURRENT_BINARY_DIR}/config.h
)
CONFIGURE_FILE(
${CMAKE_CURRENT_SOURCE_DIR}/lemon.pc.in
${CMAKE_CURRENT_BINARY_DIR}/lemon.pc
@ONLY
)
SET(LEMON_SOURCES
arg_parser.cc
base.cc
color.cc
lp_base.cc
lp_skeleton.cc
random.cc
bits/windows.cc
)
IF(LEMON_HAVE_GLPK)
SET(LEMON_SOURCES ${LEMON_SOURCES} glpk.cc)
INCLUDE_DIRECTORIES(${GLPK_INCLUDE_DIRS})
IF(WIN32)
INSTALL(FILES ${GLPK_BIN_DIR}/glpk.dll DESTINATION bin)
INSTALL(FILES ${GLPK_BIN_DIR}/libltdl3.dll DESTINATION bin)
INSTALL(FILES ${GLPK_BIN_DIR}/zlib1.dll DESTINATION bin)
ENDIF()
ENDIF()
IF(LEMON_HAVE_CPLEX)
SET(LEMON_SOURCES ${LEMON_SOURCES} cplex.cc)
INCLUDE_DIRECTORIES(${ILOG_INCLUDE_DIRS})
ENDIF()
IF(LEMON_HAVE_CLP)
SET(LEMON_SOURCES ${LEMON_SOURCES} clp.cc)
INCLUDE_DIRECTORIES(${COIN_INCLUDE_DIRS})
ENDIF()
IF(LEMON_HAVE_CBC)
SET(LEMON_SOURCES ${LEMON_SOURCES} cbc.cc)
INCLUDE_DIRECTORIES(${COIN_INCLUDE_DIRS})
ENDIF()
IF(LEMON_HAVE_SOPLEX)
SET(LEMON_SOURCES ${LEMON_SOURCES} soplex.cc)
INCLUDE_DIRECTORIES(${SOPLEX_INCLUDE_DIRS})
ENDIF()
ADD_LIBRARY(lemon ${LEMON_SOURCES})
TARGET_LINK_LIBRARIES(lemon
${GLPK_LIBRARIES} ${COIN_LIBRARIES} ${ILOG_LIBRARIES} ${SOPLEX_LIBRARIES}
)
IF(UNIX)
SET_TARGET_PROPERTIES(lemon PROPERTIES OUTPUT_NAME emon VERSION ${LEMON_VERSION} SOVERSION ${LEMON_VERSION})
ENDIF()
INSTALL(
TARGETS lemon
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
COMPONENT library
)
INSTALL(
DIRECTORY . bits concepts
DESTINATION include/lemon
COMPONENT headers
FILES_MATCHING PATTERN "*.h"
)
INSTALL(
FILES ${CMAKE_CURRENT_BINARY_DIR}/config.h
DESTINATION include/lemon
COMPONENT headers
)
INSTALL(
FILES ${CMAKE_CURRENT_BINARY_DIR}/lemon.pc
DESTINATION lib/pkgconfig
)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,474 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2010
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
#include <lemon/arg_parser.h>
namespace lemon {
void ArgParser::_terminate(ArgParserException::Reason reason) const
{
if(_exit_on_problems)
exit(1);
else throw(ArgParserException(reason));
}
void ArgParser::_showHelp(void *p)
{
(static_cast<ArgParser*>(p))->showHelp();
(static_cast<ArgParser*>(p))->_terminate(ArgParserException::HELP);
}
ArgParser::ArgParser(int argc, const char * const *argv)
:_argc(argc), _argv(argv), _command_name(argv[0]),
_exit_on_problems(true) {
funcOption("-help","Print a short help message",_showHelp,this);
synonym("help","-help");
synonym("h","-help");
}
ArgParser::~ArgParser()
{
for(Opts::iterator i=_opts.begin();i!=_opts.end();++i)
if(i->second.self_delete)
switch(i->second.type) {
case BOOL:
delete i->second.bool_p;
break;
case STRING:
delete i->second.string_p;
break;
case DOUBLE:
delete i->second.double_p;
break;
case INTEGER:
delete i->second.int_p;
break;
case UNKNOWN:
break;
case FUNC:
break;
}
}
ArgParser &ArgParser::intOption(const std::string &name,
const std::string &help,
int value, bool obl)
{
ParData p;
p.int_p=new int(value);
p.self_delete=true;
p.help=help;
p.type=INTEGER;
p.mandatory=obl;
_opts[name]=p;
return *this;
}
ArgParser &ArgParser::doubleOption(const std::string &name,
const std::string &help,
double value, bool obl)
{
ParData p;
p.double_p=new double(value);
p.self_delete=true;
p.help=help;
p.type=DOUBLE;
p.mandatory=obl;
_opts[name]=p;
return *this;
}
ArgParser &ArgParser::boolOption(const std::string &name,
const std::string &help,
bool value, bool obl)
{
ParData p;
p.bool_p=new bool(value);
p.self_delete=true;
p.help=help;
p.type=BOOL;
p.mandatory=obl;
_opts[name]=p;
return *this;
}
ArgParser &ArgParser::stringOption(const std::string &name,
const std::string &help,
std::string value, bool obl)
{
ParData p;
p.string_p=new std::string(value);
p.self_delete=true;
p.help=help;
p.type=STRING;
p.mandatory=obl;
_opts[name]=p;
return *this;
}
ArgParser &ArgParser::refOption(const std::string &name,
const std::string &help,
int &ref, bool obl)
{
ParData p;
p.int_p=&ref;
p.self_delete=false;
p.help=help;
p.type=INTEGER;
p.mandatory=obl;
_opts[name]=p;
return *this;
}
ArgParser &ArgParser::refOption(const std::string &name,
const std::string &help,
double &ref, bool obl)
{
ParData p;
p.double_p=&ref;
p.self_delete=false;
p.help=help;
p.type=DOUBLE;
p.mandatory=obl;
_opts[name]=p;
return *this;
}
ArgParser &ArgParser::refOption(const std::string &name,
const std::string &help,
bool &ref, bool obl)
{
ParData p;
p.bool_p=&ref;
p.self_delete=false;
p.help=help;
p.type=BOOL;
p.mandatory=obl;
_opts[name]=p;
ref = false;
return *this;
}
ArgParser &ArgParser::refOption(const std::string &name,
const std::string &help,
std::string &ref, bool obl)
{
ParData p;
p.string_p=&ref;
p.self_delete=false;
p.help=help;
p.type=STRING;
p.mandatory=obl;
_opts[name]=p;
return *this;
}
ArgParser &ArgParser::funcOption(const std::string &name,
const std::string &help,
void (*func)(void *),void *data)
{
ParData p;
p.func_p.p=func;
p.func_p.data=data;
p.self_delete=false;
p.help=help;
p.type=FUNC;
p.mandatory=false;
_opts[name]=p;
return *this;
}
ArgParser &ArgParser::optionGroup(const std::string &group,
const std::string &opt)
{
Opts::iterator i = _opts.find(opt);
LEMON_ASSERT(i!=_opts.end(), "Unknown option: '"+opt+"'");
LEMON_ASSERT(!(i->second.ingroup),
"Option already in option group: '"+opt+"'");
GroupData &g=_groups[group];
g.opts.push_back(opt);
i->second.ingroup=true;
return *this;
}
ArgParser &ArgParser::onlyOneGroup(const std::string &group)
{
GroupData &g=_groups[group];
g.only_one=true;
return *this;
}
ArgParser &ArgParser::synonym(const std::string &syn,
const std::string &opt)
{
Opts::iterator o = _opts.find(opt);
Opts::iterator s = _opts.find(syn);
LEMON_ASSERT(o!=_opts.end(), "Unknown option: '"+opt+"'");
LEMON_ASSERT(s==_opts.end(), "Option already used: '"+syn+"'");
ParData p;
p.help=opt;
p.mandatory=false;
p.syn=true;
_opts[syn]=p;
o->second.has_syn=true;
return *this;
}
ArgParser &ArgParser::mandatoryGroup(const std::string &group)
{
GroupData &g=_groups[group];
g.mandatory=true;
return *this;
}
ArgParser &ArgParser::other(const std::string &name,
const std::string &help)
{
_others_help.push_back(OtherArg(name,help));
return *this;
}
void ArgParser::show(std::ostream &os,Opts::const_iterator i) const
{
os << "-" << i->first;
if(i->second.has_syn)
for(Opts::const_iterator j=_opts.begin();j!=_opts.end();++j)
if(j->second.syn&&j->second.help==i->first)
os << "|-" << j->first;
switch(i->second.type) {
case STRING:
os << " str";
break;
case INTEGER:
os << " int";
break;
case DOUBLE:
os << " num";
break;
default:
break;
}
}
void ArgParser::show(std::ostream &os,Groups::const_iterator i) const
{
GroupData::Opts::const_iterator o=i->second.opts.begin();
while(o!=i->second.opts.end()) {
show(os,_opts.find(*o));
++o;
if(o!=i->second.opts.end()) os<<'|';
}
}
void ArgParser::showHelp(Opts::const_iterator i) const
{
if(i->second.help.size()==0||i->second.syn) return;
std::cerr << " ";
show(std::cerr,i);
std::cerr << std::endl;
std::cerr << " " << i->second.help << std::endl;
}
void ArgParser::showHelp(std::vector<ArgParser::OtherArg>::const_iterator i)
const
{
if(i->help.size()==0) return;
std::cerr << " " << i->name << std::endl
<< " " << i->help << std::endl;
}
void ArgParser::shortHelp() const
{
const unsigned int LINE_LEN=77;
const std::string indent(" ");
std::cerr << "Usage:\n " << _command_name;
int pos=_command_name.size()+2;
for(Groups::const_iterator g=_groups.begin();g!=_groups.end();++g) {
std::ostringstream cstr;
cstr << ' ';
if(!g->second.mandatory) cstr << '[';
show(cstr,g);
if(!g->second.mandatory) cstr << ']';
if(pos+cstr.str().size()>LINE_LEN) {
std::cerr << std::endl << indent;
pos=indent.size();
}
std::cerr << cstr.str();
pos+=cstr.str().size();
}
for(Opts::const_iterator i=_opts.begin();i!=_opts.end();++i)
if(!i->second.ingroup&&!i->second.syn) {
std::ostringstream cstr;
cstr << ' ';
if(!i->second.mandatory) cstr << '[';
show(cstr,i);
if(!i->second.mandatory) cstr << ']';
if(pos+cstr.str().size()>LINE_LEN) {
std::cerr << std::endl << indent;
pos=indent.size();
}
std::cerr << cstr.str();
pos+=cstr.str().size();
}
for(std::vector<OtherArg>::const_iterator i=_others_help.begin();
i!=_others_help.end();++i)
{
std::ostringstream cstr;
cstr << ' ' << i->name;
if(pos+cstr.str().size()>LINE_LEN) {
std::cerr << std::endl << indent;
pos=indent.size();
}
std::cerr << cstr.str();
pos+=cstr.str().size();
}
std::cerr << std::endl;
}
void ArgParser::showHelp() const
{
shortHelp();
std::cerr << "Where:\n";
for(std::vector<OtherArg>::const_iterator i=_others_help.begin();
i!=_others_help.end();++i) showHelp(i);
for(Opts::const_iterator i=_opts.begin();i!=_opts.end();++i) showHelp(i);
_terminate(ArgParserException::HELP);
}
void ArgParser::unknownOpt(std::string arg) const
{
std::cerr << "\nUnknown option: " << arg << "\n";
std::cerr << "\nType '" << _command_name <<
" --help' to obtain a short summary on the usage.\n\n";
_terminate(ArgParserException::UNKNOWN_OPT);
}
void ArgParser::requiresValue(std::string arg, OptType t) const
{
std::cerr << "Argument '" << arg << "' requires a";
switch(t) {
case STRING:
std::cerr << " string";
break;
case INTEGER:
std::cerr << "n integer";
break;
case DOUBLE:
std::cerr << " floating point";
break;
default:
break;
}
std::cerr << " value\n\n";
showHelp();
}
void ArgParser::checkMandatories() const
{
bool ok=true;
for(Opts::const_iterator i=_opts.begin();i!=_opts.end();++i)
if(i->second.mandatory&&!i->second.set)
{
if(ok)
std::cerr << _command_name
<< ": The following mandatory arguments are missing.\n";
ok=false;
showHelp(i);
}
for(Groups::const_iterator i=_groups.begin();i!=_groups.end();++i)
if(i->second.mandatory||i->second.only_one)
{
int set=0;
for(GroupData::Opts::const_iterator o=i->second.opts.begin();
o!=i->second.opts.end();++o)
if(_opts.find(*o)->second.set) ++set;
if(i->second.mandatory&&!set) {
std::cerr << _command_name <<
": At least one of the following arguments is mandatory.\n";
ok=false;
for(GroupData::Opts::const_iterator o=i->second.opts.begin();
o!=i->second.opts.end();++o)
showHelp(_opts.find(*o));
}
if(i->second.only_one&&set>1) {
std::cerr << _command_name <<
": At most one of the following arguments can be given.\n";
ok=false;
for(GroupData::Opts::const_iterator o=i->second.opts.begin();
o!=i->second.opts.end();++o)
showHelp(_opts.find(*o));
}
}
if(!ok) {
std::cerr << "\nType '" << _command_name <<
" --help' to obtain a short summary on the usage.\n\n";
_terminate(ArgParserException::INVALID_OPT);
}
}
ArgParser &ArgParser::parse()
{
for(int ar=1; ar<_argc; ++ar) {
std::string arg(_argv[ar]);
if (arg[0] != '-' || arg.size() == 1) {
_file_args.push_back(arg);
}
else {
Opts::iterator i = _opts.find(arg.substr(1));
if(i==_opts.end()) unknownOpt(arg);
else {
if(i->second.syn) i=_opts.find(i->second.help);
ParData &p(i->second);
if (p.type==BOOL) *p.bool_p=true;
else if (p.type==FUNC) p.func_p.p(p.func_p.data);
else if(++ar==_argc) requiresValue(arg, p.type);
else {
std::string val(_argv[ar]);
std::istringstream vals(val);
switch(p.type) {
case STRING:
*p.string_p=val;
break;
case INTEGER:
vals >> *p.int_p;
break;
case DOUBLE:
vals >> *p.double_p;
break;
default:
break;
}
if(p.type!=STRING&&(!vals||!vals.eof()))
requiresValue(arg, p.type);
}
p.set = true;
}
}
}
checkMandatories();
return *this;
}
}

View File

@@ -0,0 +1,440 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2010
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
#ifndef LEMON_ARG_PARSER_H
#define LEMON_ARG_PARSER_H
#include <vector>
#include <map>
#include <list>
#include <string>
#include <iostream>
#include <sstream>
#include <algorithm>
#include <lemon/assert.h>
///\ingroup misc
///\file
///\brief A tool to parse command line arguments.
namespace lemon {
///Exception used by ArgParser
///Exception used by ArgParser.
///
class ArgParserException : public Exception {
public:
/// Reasons for failure
/// Reasons for failure.
///
enum Reason {
HELP, ///< <tt>--help</tt> option was given.
UNKNOWN_OPT, ///< Unknown option was given.
INVALID_OPT ///< Invalid combination of options.
};
private:
Reason _reason;
public:
///Constructor
ArgParserException(Reason r) throw() : _reason(r) {}
///Virtual destructor
virtual ~ArgParserException() throw() {}
///A short description of the exception
virtual const char* what() const throw() {
switch(_reason)
{
case HELP:
return "lemon::ArgParseException: ask for help";
break;
case UNKNOWN_OPT:
return "lemon::ArgParseException: unknown option";
break;
case INVALID_OPT:
return "lemon::ArgParseException: invalid combination of options";
break;
}
return "";
}
///Return the reason for the failure
Reason reason() const {return _reason; }
};
///Command line arguments parser
///\ingroup misc
///Command line arguments parser.
///
///For a complete example see the \ref arg_parser_demo.cc demo file.
class ArgParser {
static void _showHelp(void *p);
protected:
int _argc;
const char * const *_argv;
enum OptType { UNKNOWN=0, BOOL=1, STRING=2, DOUBLE=3, INTEGER=4, FUNC=5 };
class ParData {
public:
union {
bool *bool_p;
int *int_p;
double *double_p;
std::string *string_p;
struct {
void (*p)(void *);
void *data;
} func_p;
};
std::string help;
bool mandatory;
OptType type;
bool set;
bool ingroup;
bool has_syn;
bool syn;
bool self_delete;
ParData() : mandatory(false), type(UNKNOWN), set(false), ingroup(false),
has_syn(false), syn(false), self_delete(false) {}
};
typedef std::map<std::string,ParData> Opts;
Opts _opts;
class GroupData
{
public:
typedef std::list<std::string> Opts;
Opts opts;
bool only_one;
bool mandatory;
GroupData() :only_one(false), mandatory(false) {}
};
typedef std::map<std::string,GroupData> Groups;
Groups _groups;
struct OtherArg
{
std::string name;
std::string help;
OtherArg(std::string n, std::string h) :name(n), help(h) {}
};
std::vector<OtherArg> _others_help;
std::vector<std::string> _file_args;
std::string _command_name;
private:
//Bind a function to an option.
//\param name The name of the option. The leading '-' must be omitted.
//\param help A help string.
//\retval func The function to be called when the option is given. It
// must be of type "void f(void *)"
//\param data Data to be passed to \c func
ArgParser &funcOption(const std::string &name,
const std::string &help,
void (*func)(void *),void *data);
bool _exit_on_problems;
void _terminate(ArgParserException::Reason reason) const;
public:
///Constructor
ArgParser(int argc, const char * const *argv);
~ArgParser();
///\name Options
///
///@{
///Add a new integer type option
///Add a new integer type option.
///\param name The name of the option. The leading '-' must be omitted.
///\param help A help string.
///\param value A default value for the option.
///\param obl Indicate if the option is mandatory.
ArgParser &intOption(const std::string &name,
const std::string &help,
int value=0, bool obl=false);
///Add a new floating point type option
///Add a new floating point type option.
///\param name The name of the option. The leading '-' must be omitted.
///\param help A help string.
///\param value A default value for the option.
///\param obl Indicate if the option is mandatory.
ArgParser &doubleOption(const std::string &name,
const std::string &help,
double value=0, bool obl=false);
///Add a new bool type option
///Add a new bool type option.
///\param name The name of the option. The leading '-' must be omitted.
///\param help A help string.
///\param value A default value for the option.
///\param obl Indicate if the option is mandatory.
///\note A mandatory bool obtion is of very little use.
ArgParser &boolOption(const std::string &name,
const std::string &help,
bool value=false, bool obl=false);
///Add a new string type option
///Add a new string type option.
///\param name The name of the option. The leading '-' must be omitted.
///\param help A help string.
///\param value A default value for the option.
///\param obl Indicate if the option is mandatory.
ArgParser &stringOption(const std::string &name,
const std::string &help,
std::string value="", bool obl=false);
///Give help string for non-parsed arguments.
///With this function you can give help string for non-parsed arguments.
///The parameter \c name will be printed in the short usage line, while
///\c help gives a more detailed description.
ArgParser &other(const std::string &name,
const std::string &help="");
///@}
///\name Options with External Storage
///Using this functions, the value of the option will be directly written
///into a variable once the option appears in the command line.
///@{
///Add a new integer type option with a storage reference
///Add a new integer type option with a storage reference.
///\param name The name of the option. The leading '-' must be omitted.
///\param help A help string.
///\param obl Indicate if the option is mandatory.
///\retval ref The value of the argument will be written to this variable.
ArgParser &refOption(const std::string &name,
const std::string &help,
int &ref, bool obl=false);
///Add a new floating type option with a storage reference
///Add a new floating type option with a storage reference.
///\param name The name of the option. The leading '-' must be omitted.
///\param help A help string.
///\param obl Indicate if the option is mandatory.
///\retval ref The value of the argument will be written to this variable.
ArgParser &refOption(const std::string &name,
const std::string &help,
double &ref, bool obl=false);
///Add a new bool type option with a storage reference
///Add a new bool type option with a storage reference.
///\param name The name of the option. The leading '-' must be omitted.
///\param help A help string.
///\param obl Indicate if the option is mandatory.
///\retval ref The value of the argument will be written to this variable.
///\note A mandatory bool obtion is of very little use.
ArgParser &refOption(const std::string &name,
const std::string &help,
bool &ref, bool obl=false);
///Add a new string type option with a storage reference
///Add a new string type option with a storage reference.
///\param name The name of the option. The leading '-' must be omitted.
///\param help A help string.
///\param obl Indicate if the option is mandatory.
///\retval ref The value of the argument will be written to this variable.
ArgParser &refOption(const std::string &name,
const std::string &help,
std::string &ref, bool obl=false);
///@}
///\name Option Groups and Synonyms
///
///@{
///Bundle some options into a group
/// You can group some option by calling this function repeatedly for each
/// option to be grouped with the same groupname.
///\param group The group name.
///\param opt The option name.
ArgParser &optionGroup(const std::string &group,
const std::string &opt);
///Make the members of a group exclusive
///If you call this function for a group, than at most one of them can be
///given at the same time.
ArgParser &onlyOneGroup(const std::string &group);
///Make a group mandatory
///Using this function, at least one of the members of \c group
///must be given.
ArgParser &mandatoryGroup(const std::string &group);
///Create synonym to an option
///With this function you can create a synonym \c syn of the
///option \c opt.
ArgParser &synonym(const std::string &syn,
const std::string &opt);
///@}
private:
void show(std::ostream &os,Opts::const_iterator i) const;
void show(std::ostream &os,Groups::const_iterator i) const;
void showHelp(Opts::const_iterator i) const;
void showHelp(std::vector<OtherArg>::const_iterator i) const;
void unknownOpt(std::string arg) const;
void requiresValue(std::string arg, OptType t) const;
void checkMandatories() const;
void shortHelp() const;
void showHelp() const;
public:
///Start the parsing process
ArgParser &parse();
/// Synonym for parse()
ArgParser &run()
{
return parse();
}
///Give back the command name (the 0th argument)
const std::string &commandName() const { return _command_name; }
///Check if an opion has been given to the command.
bool given(std::string op) const
{
Opts::const_iterator i = _opts.find(op);
return i!=_opts.end()?i->second.set:false;
}
///Magic type for operator[]
///This is the type of the return value of ArgParser::operator[]().
///It automatically converts to \c int, \c double, \c bool or
///\c std::string if the type of the option matches, which is checked
///with an \ref LEMON_ASSERT "assertion" (i.e. it performs runtime
///type checking).
class RefType
{
const ArgParser &_parser;
std::string _name;
public:
///\e
RefType(const ArgParser &p,const std::string &n) :_parser(p),_name(n) {}
///\e
operator bool()
{
Opts::const_iterator i = _parser._opts.find(_name);
LEMON_ASSERT(i!=_parser._opts.end(),
std::string()+"Unkown option: '"+_name+"'");
LEMON_ASSERT(i->second.type==ArgParser::BOOL,
std::string()+"'"+_name+"' is a bool option");
return *(i->second.bool_p);
}
///\e
operator std::string()
{
Opts::const_iterator i = _parser._opts.find(_name);
LEMON_ASSERT(i!=_parser._opts.end(),
std::string()+"Unkown option: '"+_name+"'");
LEMON_ASSERT(i->second.type==ArgParser::STRING,
std::string()+"'"+_name+"' is a string option");
return *(i->second.string_p);
}
///\e
operator double()
{
Opts::const_iterator i = _parser._opts.find(_name);
LEMON_ASSERT(i!=_parser._opts.end(),
std::string()+"Unkown option: '"+_name+"'");
LEMON_ASSERT(i->second.type==ArgParser::DOUBLE ||
i->second.type==ArgParser::INTEGER,
std::string()+"'"+_name+"' is a floating point option");
return i->second.type==ArgParser::DOUBLE ?
*(i->second.double_p) : *(i->second.int_p);
}
///\e
operator int()
{
Opts::const_iterator i = _parser._opts.find(_name);
LEMON_ASSERT(i!=_parser._opts.end(),
std::string()+"Unkown option: '"+_name+"'");
LEMON_ASSERT(i->second.type==ArgParser::INTEGER,
std::string()+"'"+_name+"' is an integer option");
return *(i->second.int_p);
}
};
///Give back the value of an option
///Give back the value of an option.
///\sa RefType
RefType operator[](const std::string &n) const
{
return RefType(*this, n);
}
///Give back the non-option type arguments.
///Give back a reference to a vector consisting of the program arguments
///not starting with a '-' character.
const std::vector<std::string> &files() const { return _file_args; }
///Throw instead of exit in case of problems
void throwOnProblems()
{
_exit_on_problems=false;
}
};
}
#endif // LEMON_ARG_PARSER_H

View File

@@ -0,0 +1,214 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2013
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
#ifndef LEMON_ASSERT_H
#define LEMON_ASSERT_H
/// \ingroup exceptions
/// \file
/// \brief Extended assertion handling
#include <lemon/error.h>
namespace lemon {
inline void assert_fail_abort(const char *file, int line,
const char *function, const char* message,
const char *assertion)
{
std::cerr << file << ":" << line << ": ";
if (function)
std::cerr << function << ": ";
std::cerr << message;
if (assertion)
std::cerr << " (assertion '" << assertion << "' failed)";
std::cerr << std::endl;
std::abort();
}
namespace _assert_bits {
inline const char* cstringify(const std::string& str) {
return str.c_str();
}
inline const char* cstringify(const char* str) {
return str;
}
}
}
#endif // LEMON_ASSERT_H
#undef LEMON_ASSERT
#undef LEMON_DEBUG
#if (defined(LEMON_ASSERT_ABORT) ? 1 : 0) + \
(defined(LEMON_ASSERT_CUSTOM) ? 1 : 0) > 1
#error "LEMON assertion system is not set properly"
#endif
#if ((defined(LEMON_ASSERT_ABORT) ? 1 : 0) + \
(defined(LEMON_ASSERT_CUSTOM) ? 1 : 0) == 1 || \
defined(LEMON_ENABLE_ASSERTS)) && \
(defined(LEMON_DISABLE_ASSERTS) || \
defined(NDEBUG))
#error "LEMON assertion system is not set properly"
#endif
#if defined LEMON_ASSERT_ABORT
# undef LEMON_ASSERT_HANDLER
# define LEMON_ASSERT_HANDLER ::lemon::assert_fail_abort
#elif defined LEMON_ASSERT_CUSTOM
# undef LEMON_ASSERT_HANDLER
# ifndef LEMON_CUSTOM_ASSERT_HANDLER
# error "LEMON_CUSTOM_ASSERT_HANDLER is not set"
# endif
# define LEMON_ASSERT_HANDLER LEMON_CUSTOM_ASSERT_HANDLER
#elif defined LEMON_DISABLE_ASSERTS
# undef LEMON_ASSERT_HANDLER
#elif defined NDEBUG
# undef LEMON_ASSERT_HANDLER
#else
# define LEMON_ASSERT_HANDLER ::lemon::assert_fail_abort
#endif
#ifndef LEMON_FUNCTION_NAME
# if defined __GNUC__
# define LEMON_FUNCTION_NAME (__PRETTY_FUNCTION__)
# elif defined _MSC_VER
# define LEMON_FUNCTION_NAME (__FUNCSIG__)
# elif __STDC_VERSION__ >= 199901L
# define LEMON_FUNCTION_NAME (__func__)
# else
# define LEMON_FUNCTION_NAME ("<unknown>")
# endif
#endif
#ifdef DOXYGEN
/// \ingroup exceptions
///
/// \brief Macro for assertion with customizable message
///
/// Macro for assertion with customizable message.
/// \param exp An expression that must be convertible to \c bool. If it is \c
/// false, then an assertion is raised. The concrete behaviour depends on the
/// settings of the assertion system.
/// \param msg A <tt>const char*</tt> parameter, which can be used to provide
/// information about the circumstances of the failed assertion.
///
/// The assertions are enabled in the default behaviour.
/// You can disable them with the following code:
/// \code
/// #define LEMON_DISABLE_ASSERTS
/// \endcode
/// or with compilation parameters:
/// \code
/// g++ -DLEMON_DISABLE_ASSERTS
/// make CXXFLAGS='-DLEMON_DISABLE_ASSERTS'
/// \endcode
/// The checking is also disabled when the standard macro \c NDEBUG is defined.
///
/// As a default behaviour the failed assertion prints a short log message to
/// the standard error and aborts the execution.
///
/// However, the following modes can be used in the assertion system:
/// - \c LEMON_ASSERT_ABORT The failed assertion prints a short log message to
/// the standard error and aborts the program. It is the default behaviour.
/// - \c LEMON_ASSERT_CUSTOM The user can define own assertion handler
/// function.
/// \code
/// void custom_assert_handler(const char* file, int line,
/// const char* function, const char* message,
/// const char* assertion);
/// \endcode
/// The name of the function should be defined as the \c
/// LEMON_CUSTOM_ASSERT_HANDLER macro name.
/// \code
/// #define LEMON_CUSTOM_ASSERT_HANDLER custom_assert_handler
/// \endcode
/// Whenever an assertion is occured, the custom assertion
/// handler is called with appropiate parameters.
///
/// The assertion mode can also be changed within one compilation unit.
/// If the macros are redefined with other settings and the
/// \ref lemon/assert.h "assert.h" file is reincluded, then the
/// behaviour is changed appropiately to the new settings.
# define LEMON_ASSERT(exp, msg) \
(static_cast<void> (!!(exp) ? 0 : ( \
LEMON_ASSERT_HANDLER(__FILE__, __LINE__, \
LEMON_FUNCTION_NAME, \
::lemon::_assert_bits::cstringify(msg), #exp), 0)))
/// \ingroup exceptions
///
/// \brief Macro for internal assertions
///
/// Macro for internal assertions, it is used in the library to check
/// the consistency of results of algorithms, several pre- and
/// postconditions and invariants. The checking is disabled by
/// default, but it can be turned on with the macro \c
/// LEMON_ENABLE_DEBUG.
/// \code
/// #define LEMON_ENABLE_DEBUG
/// \endcode
/// or with compilation parameters:
/// \code
/// g++ -DLEMON_ENABLE_DEBUG
/// make CXXFLAGS='-DLEMON_ENABLE_DEBUG'
/// \endcode
///
/// This macro works like the \c LEMON_ASSERT macro, therefore the
/// current behaviour depends on the settings of \c LEMON_ASSERT
/// macro.
///
/// \see LEMON_ASSERT
# define LEMON_DEBUG(exp, msg) \
(static_cast<void> (!!(exp) ? 0 : ( \
LEMON_ASSERT_HANDLER(__FILE__, __LINE__, \
LEMON_FUNCTION_NAME, \
::lemon::_assert_bits::cstringify(msg), #exp), 0)))
#else
# ifndef LEMON_ASSERT_HANDLER
# define LEMON_ASSERT(exp, msg) (static_cast<void>(0))
# define LEMON_DEBUG(exp, msg) (static_cast<void>(0))
# else
# define LEMON_ASSERT(exp, msg) \
(static_cast<void> (!!(exp) ? 0 : ( \
LEMON_ASSERT_HANDLER(__FILE__, __LINE__, \
LEMON_FUNCTION_NAME, \
::lemon::_assert_bits::cstringify(msg), \
#exp), 0)))
# if defined LEMON_ENABLE_DEBUG
# define LEMON_DEBUG(exp, msg) \
(static_cast<void> (!!(exp) ? 0 : ( \
LEMON_ASSERT_HANDLER(__FILE__, __LINE__, \
LEMON_FUNCTION_NAME, \
::lemon::_assert_bits::cstringify(msg), \
#exp), 0)))
# else
# define LEMON_DEBUG(exp, msg) (static_cast<void>(0))
# endif
# endif
#endif

View File

@@ -0,0 +1,37 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2013
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
///\file
///\brief Some basic non-inline functions and static global data.
#include<lemon/tolerance.h>
#include<lemon/core.h>
#include<lemon/time_measure.h>
namespace lemon {
float Tolerance<float>::def_epsilon = static_cast<float>(1e-4);
double Tolerance<double>::def_epsilon = 1e-10;
long double Tolerance<long double>::def_epsilon = 1e-14;
#ifndef LEMON_ONLY_TEMPLATES
const Invalid INVALID = Invalid();
#endif
TimeStamp::Format TimeStamp::_format = TimeStamp::NORMAL;
} //namespace lemon

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,347 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2013
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
#ifndef LEMON_BIN_HEAP_H
#define LEMON_BIN_HEAP_H
///\ingroup heaps
///\file
///\brief Binary heap implementation.
#include <vector>
#include <utility>
#include <functional>
namespace lemon {
/// \ingroup heaps
///
/// \brief Binary heap data structure.
///
/// This class implements the \e binary \e heap data structure.
/// It fully conforms to the \ref concepts::Heap "heap concept".
///
/// \tparam PR Type of the priorities of the items.
/// \tparam IM A read-writable item map with \c int values, used
/// internally to handle the cross references.
/// \tparam CMP A functor class for comparing the priorities.
/// The default is \c std::less<PR>.
#ifdef DOXYGEN
template <typename PR, typename IM, typename CMP>
#else
template <typename PR, typename IM, typename CMP = std::less<PR> >
#endif
class BinHeap {
public:
/// Type of the item-int map.
typedef IM ItemIntMap;
/// Type of the priorities.
typedef PR Prio;
/// Type of the items stored in the heap.
typedef typename ItemIntMap::Key Item;
/// Type of the item-priority pairs.
typedef std::pair<Item,Prio> Pair;
/// Functor type for comparing the priorities.
typedef CMP Compare;
/// \brief Type to represent the states of the items.
///
/// Each item has a state associated to it. It can be "in heap",
/// "pre-heap" or "post-heap". The latter two are indifferent from the
/// heap's point of view, but may be useful to the user.
///
/// The item-int map must be initialized in such way that it assigns
/// \c PRE_HEAP (<tt>-1</tt>) to any element to be put in the heap.
enum State {
IN_HEAP = 0, ///< = 0.
PRE_HEAP = -1, ///< = -1.
POST_HEAP = -2 ///< = -2.
};
private:
std::vector<Pair> _data;
Compare _comp;
ItemIntMap &_iim;
public:
/// \brief Constructor.
///
/// Constructor.
/// \param map A map that assigns \c int values to the items.
/// It is used internally to handle the cross references.
/// The assigned value must be \c PRE_HEAP (<tt>-1</tt>) for each item.
explicit BinHeap(ItemIntMap &map) : _iim(map) {}
/// \brief Constructor.
///
/// Constructor.
/// \param map A map that assigns \c int values to the items.
/// It is used internally to handle the cross references.
/// The assigned value must be \c PRE_HEAP (<tt>-1</tt>) for each item.
/// \param comp The function object used for comparing the priorities.
BinHeap(ItemIntMap &map, const Compare &comp)
: _iim(map), _comp(comp) {}
/// \brief The number of items stored in the heap.
///
/// This function returns the number of items stored in the heap.
int size() const { return _data.size(); }
/// \brief Check if the heap is empty.
///
/// This function returns \c true if the heap is empty.
bool empty() const { return _data.empty(); }
/// \brief Make the heap empty.
///
/// This functon makes the heap empty.
/// It does not change the cross reference map. If you want to reuse
/// a heap that is not surely empty, you should first clear it and
/// then you should set the cross reference map to \c PRE_HEAP
/// for each item.
void clear() {
_data.clear();
}
private:
static int parent(int i) { return (i-1)/2; }
static int secondChild(int i) { return 2*i+2; }
bool less(const Pair &p1, const Pair &p2) const {
return _comp(p1.second, p2.second);
}
int bubbleUp(int hole, Pair p) {
int par = parent(hole);
while( hole>0 && less(p,_data[par]) ) {
move(_data[par],hole);
hole = par;
par = parent(hole);
}
move(p, hole);
return hole;
}
int bubbleDown(int hole, Pair p, int length) {
int child = secondChild(hole);
while(child < length) {
if( less(_data[child-1], _data[child]) ) {
--child;
}
if( !less(_data[child], p) )
goto ok;
move(_data[child], hole);
hole = child;
child = secondChild(hole);
}
child--;
if( child<length && less(_data[child], p) ) {
move(_data[child], hole);
hole=child;
}
ok:
move(p, hole);
return hole;
}
void move(const Pair &p, int i) {
_data[i] = p;
_iim.set(p.first, i);
}
public:
/// \brief Insert a pair of item and priority into the heap.
///
/// This function inserts \c p.first to the heap with priority
/// \c p.second.
/// \param p The pair to insert.
/// \pre \c p.first must not be stored in the heap.
void push(const Pair &p) {
int n = _data.size();
_data.resize(n+1);
bubbleUp(n, p);
}
/// \brief Insert an item into the heap with the given priority.
///
/// This function inserts the given item into the heap with the
/// given priority.
/// \param i The item to insert.
/// \param p The priority of the item.
/// \pre \e i must not be stored in the heap.
void push(const Item &i, const Prio &p) { push(Pair(i,p)); }
/// \brief Return the item having minimum priority.
///
/// This function returns the item having minimum priority.
/// \pre The heap must be non-empty.
Item top() const {
return _data[0].first;
}
/// \brief The minimum priority.
///
/// This function returns the minimum priority.
/// \pre The heap must be non-empty.
Prio prio() const {
return _data[0].second;
}
/// \brief Remove the item having minimum priority.
///
/// This function removes the item having minimum priority.
/// \pre The heap must be non-empty.
void pop() {
int n = _data.size()-1;
_iim.set(_data[0].first, POST_HEAP);
if (n > 0) {
bubbleDown(0, _data[n], n);
}
_data.pop_back();
}
/// \brief Remove the given item from the heap.
///
/// This function removes the given item from the heap if it is
/// already stored.
/// \param i The item to delete.
/// \pre \e i must be in the heap.
void erase(const Item &i) {
int h = _iim[i];
int n = _data.size()-1;
_iim.set(_data[h].first, POST_HEAP);
if( h < n ) {
if ( bubbleUp(h, _data[n]) == h) {
bubbleDown(h, _data[n], n);
}
}
_data.pop_back();
}
/// \brief The priority of the given item.
///
/// This function returns the priority of the given item.
/// \param i The item.
/// \pre \e i must be in the heap.
Prio operator[](const Item &i) const {
int idx = _iim[i];
return _data[idx].second;
}
/// \brief Set the priority of an item or insert it, if it is
/// not stored in the heap.
///
/// This method sets the priority of the given item if it is
/// already stored in the heap. Otherwise it inserts the given
/// item into the heap with the given priority.
/// \param i The item.
/// \param p The priority.
void set(const Item &i, const Prio &p) {
int idx = _iim[i];
if( idx < 0 ) {
push(i,p);
}
else if( _comp(p, _data[idx].second) ) {
bubbleUp(idx, Pair(i,p));
}
else {
bubbleDown(idx, Pair(i,p), _data.size());
}
}
/// \brief Decrease the priority of an item to the given value.
///
/// This function decreases the priority of an item to the given value.
/// \param i The item.
/// \param p The priority.
/// \pre \e i must be stored in the heap with priority at least \e p.
void decrease(const Item &i, const Prio &p) {
int idx = _iim[i];
bubbleUp(idx, Pair(i,p));
}
/// \brief Increase the priority of an item to the given value.
///
/// This function increases the priority of an item to the given value.
/// \param i The item.
/// \param p The priority.
/// \pre \e i must be stored in the heap with priority at most \e p.
void increase(const Item &i, const Prio &p) {
int idx = _iim[i];
bubbleDown(idx, Pair(i,p), _data.size());
}
/// \brief Return the state of an item.
///
/// This method returns \c PRE_HEAP if the given item has never
/// been in the heap, \c IN_HEAP if it is in the heap at the moment,
/// and \c POST_HEAP otherwise.
/// In the latter case it is possible that the item will get back
/// to the heap again.
/// \param i The item.
State state(const Item &i) const {
int s = _iim[i];
if( s>=0 )
s=0;
return State(s);
}
/// \brief Set the state of an item in the heap.
///
/// This function sets the state of the given item in the heap.
/// It can be used to manually clear the heap when it is important
/// to achive better time complexity.
/// \param i The item.
/// \param st The state. It should not be \c IN_HEAP.
void state(const Item& i, State st) {
switch (st) {
case POST_HEAP:
case PRE_HEAP:
if (state(i) == IN_HEAP) {
erase(i);
}
_iim[i] = st;
break;
case IN_HEAP:
break;
}
}
/// \brief Replace an item in the heap.
///
/// This function replaces item \c i with item \c j.
/// Item \c i must be in the heap, while \c j must be out of the heap.
/// After calling this method, item \c i will be out of the
/// heap and \c j will be in the heap with the same prioriority
/// as item \c i had before.
void replace(const Item& i, const Item& j) {
int idx = _iim[i];
_iim.set(i, _iim[j]);
_iim.set(j, idx);
_data[idx].first = j;
}
}; // class BinHeap
} // namespace lemon
#endif // LEMON_BIN_HEAP_H

View File

@@ -0,0 +1,445 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2010
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
#ifndef LEMON_BINOMIAL_HEAP_H
#define LEMON_BINOMIAL_HEAP_H
///\file
///\ingroup heaps
///\brief Binomial Heap implementation.
#include <vector>
#include <utility>
#include <functional>
#include <lemon/math.h>
#include <lemon/counter.h>
namespace lemon {
/// \ingroup heaps
///
///\brief Binomial heap data structure.
///
/// This class implements the \e binomial \e heap data structure.
/// It fully conforms to the \ref concepts::Heap "heap concept".
///
/// The methods \ref increase() and \ref erase() are not efficient
/// in a binomial heap. In case of many calls of these operations,
/// it is better to use other heap structure, e.g. \ref BinHeap
/// "binary heap".
///
/// \tparam PR Type of the priorities of the items.
/// \tparam IM A read-writable item map with \c int values, used
/// internally to handle the cross references.
/// \tparam CMP A functor class for comparing the priorities.
/// The default is \c std::less<PR>.
#ifdef DOXYGEN
template <typename PR, typename IM, typename CMP>
#else
template <typename PR, typename IM, typename CMP = std::less<PR> >
#endif
class BinomialHeap {
public:
/// Type of the item-int map.
typedef IM ItemIntMap;
/// Type of the priorities.
typedef PR Prio;
/// Type of the items stored in the heap.
typedef typename ItemIntMap::Key Item;
/// Functor type for comparing the priorities.
typedef CMP Compare;
/// \brief Type to represent the states of the items.
///
/// Each item has a state associated to it. It can be "in heap",
/// "pre-heap" or "post-heap". The latter two are indifferent from the
/// heap's point of view, but may be useful to the user.
///
/// The item-int map must be initialized in such way that it assigns
/// \c PRE_HEAP (<tt>-1</tt>) to any element to be put in the heap.
enum State {
IN_HEAP = 0, ///< = 0.
PRE_HEAP = -1, ///< = -1.
POST_HEAP = -2 ///< = -2.
};
private:
class Store;
std::vector<Store> _data;
int _min, _head;
ItemIntMap &_iim;
Compare _comp;
int _num_items;
public:
/// \brief Constructor.
///
/// Constructor.
/// \param map A map that assigns \c int values to the items.
/// It is used internally to handle the cross references.
/// The assigned value must be \c PRE_HEAP (<tt>-1</tt>) for each item.
explicit BinomialHeap(ItemIntMap &map)
: _min(0), _head(-1), _iim(map), _num_items(0) {}
/// \brief Constructor.
///
/// Constructor.
/// \param map A map that assigns \c int values to the items.
/// It is used internally to handle the cross references.
/// The assigned value must be \c PRE_HEAP (<tt>-1</tt>) for each item.
/// \param comp The function object used for comparing the priorities.
BinomialHeap(ItemIntMap &map, const Compare &comp)
: _min(0), _head(-1), _iim(map), _comp(comp), _num_items(0) {}
/// \brief The number of items stored in the heap.
///
/// This function returns the number of items stored in the heap.
int size() const { return _num_items; }
/// \brief Check if the heap is empty.
///
/// This function returns \c true if the heap is empty.
bool empty() const { return _num_items==0; }
/// \brief Make the heap empty.
///
/// This functon makes the heap empty.
/// It does not change the cross reference map. If you want to reuse
/// a heap that is not surely empty, you should first clear it and
/// then you should set the cross reference map to \c PRE_HEAP
/// for each item.
void clear() {
_data.clear(); _min=0; _num_items=0; _head=-1;
}
/// \brief Set the priority of an item or insert it, if it is
/// not stored in the heap.
///
/// This method sets the priority of the given item if it is
/// already stored in the heap. Otherwise it inserts the given
/// item into the heap with the given priority.
/// \param item The item.
/// \param value The priority.
void set (const Item& item, const Prio& value) {
int i=_iim[item];
if ( i >= 0 && _data[i].in ) {
if ( _comp(value, _data[i].prio) ) decrease(item, value);
if ( _comp(_data[i].prio, value) ) increase(item, value);
} else push(item, value);
}
/// \brief Insert an item into the heap with the given priority.
///
/// This function inserts the given item into the heap with the
/// given priority.
/// \param item The item to insert.
/// \param value The priority of the item.
/// \pre \e item must not be stored in the heap.
void push (const Item& item, const Prio& value) {
int i=_iim[item];
if ( i<0 ) {
int s=_data.size();
_iim.set( item,s );
Store st;
st.name=item;
st.prio=value;
_data.push_back(st);
i=s;
}
else {
_data[i].parent=_data[i].right_neighbor=_data[i].child=-1;
_data[i].degree=0;
_data[i].in=true;
_data[i].prio=value;
}
if( 0==_num_items ) {
_head=i;
_min=i;
} else {
merge(i);
if( _comp(_data[i].prio, _data[_min].prio) ) _min=i;
}
++_num_items;
}
/// \brief Return the item having minimum priority.
///
/// This function returns the item having minimum priority.
/// \pre The heap must be non-empty.
Item top() const { return _data[_min].name; }
/// \brief The minimum priority.
///
/// This function returns the minimum priority.
/// \pre The heap must be non-empty.
Prio prio() const { return _data[_min].prio; }
/// \brief The priority of the given item.
///
/// This function returns the priority of the given item.
/// \param item The item.
/// \pre \e item must be in the heap.
const Prio& operator[](const Item& item) const {
return _data[_iim[item]].prio;
}
/// \brief Remove the item having minimum priority.
///
/// This function removes the item having minimum priority.
/// \pre The heap must be non-empty.
void pop() {
_data[_min].in=false;
int head_child=-1;
if ( _data[_min].child!=-1 ) {
int child=_data[_min].child;
int neighb;
while( child!=-1 ) {
neighb=_data[child].right_neighbor;
_data[child].parent=-1;
_data[child].right_neighbor=head_child;
head_child=child;
child=neighb;
}
}
if ( _data[_head].right_neighbor==-1 ) {
// there was only one root
_head=head_child;
}
else {
// there were more roots
if( _head!=_min ) { unlace(_min); }
else { _head=_data[_head].right_neighbor; }
merge(head_child);
}
_min=findMin();
--_num_items;
}
/// \brief Remove the given item from the heap.
///
/// This function removes the given item from the heap if it is
/// already stored.
/// \param item The item to delete.
/// \pre \e item must be in the heap.
void erase (const Item& item) {
int i=_iim[item];
if ( i >= 0 && _data[i].in ) {
decrease( item, _data[_min].prio-1 );
pop();
}
}
/// \brief Decrease the priority of an item to the given value.
///
/// This function decreases the priority of an item to the given value.
/// \param item The item.
/// \param value The priority.
/// \pre \e item must be stored in the heap with priority at least \e value.
void decrease (Item item, const Prio& value) {
int i=_iim[item];
int p=_data[i].parent;
_data[i].prio=value;
while( p!=-1 && _comp(value, _data[p].prio) ) {
_data[i].name=_data[p].name;
_data[i].prio=_data[p].prio;
_data[p].name=item;
_data[p].prio=value;
_iim[_data[i].name]=i;
i=p;
p=_data[p].parent;
}
_iim[item]=i;
if ( _comp(value, _data[_min].prio) ) _min=i;
}
/// \brief Increase the priority of an item to the given value.
///
/// This function increases the priority of an item to the given value.
/// \param item The item.
/// \param value The priority.
/// \pre \e item must be stored in the heap with priority at most \e value.
void increase (Item item, const Prio& value) {
erase(item);
push(item, value);
}
/// \brief Return the state of an item.
///
/// This method returns \c PRE_HEAP if the given item has never
/// been in the heap, \c IN_HEAP if it is in the heap at the moment,
/// and \c POST_HEAP otherwise.
/// In the latter case it is possible that the item will get back
/// to the heap again.
/// \param item The item.
State state(const Item &item) const {
int i=_iim[item];
if( i>=0 ) {
if ( _data[i].in ) i=0;
else i=-2;
}
return State(i);
}
/// \brief Set the state of an item in the heap.
///
/// This function sets the state of the given item in the heap.
/// It can be used to manually clear the heap when it is important
/// to achive better time complexity.
/// \param i The item.
/// \param st The state. It should not be \c IN_HEAP.
void state(const Item& i, State st) {
switch (st) {
case POST_HEAP:
case PRE_HEAP:
if (state(i) == IN_HEAP) {
erase(i);
}
_iim[i] = st;
break;
case IN_HEAP:
break;
}
}
private:
// Find the minimum of the roots
int findMin() {
if( _head!=-1 ) {
int min_loc=_head, min_val=_data[_head].prio;
for( int x=_data[_head].right_neighbor; x!=-1;
x=_data[x].right_neighbor ) {
if( _comp( _data[x].prio,min_val ) ) {
min_val=_data[x].prio;
min_loc=x;
}
}
return min_loc;
}
else return -1;
}
// Merge the heap with another heap starting at the given position
void merge(int a) {
if( _head==-1 || a==-1 ) return;
if( _data[a].right_neighbor==-1 &&
_data[a].degree<=_data[_head].degree ) {
_data[a].right_neighbor=_head;
_head=a;
} else {
interleave(a);
}
if( _data[_head].right_neighbor==-1 ) return;
int x=_head;
int x_prev=-1, x_next=_data[x].right_neighbor;
while( x_next!=-1 ) {
if( _data[x].degree!=_data[x_next].degree ||
( _data[x_next].right_neighbor!=-1 &&
_data[_data[x_next].right_neighbor].degree==_data[x].degree ) ) {
x_prev=x;
x=x_next;
}
else {
if( _comp(_data[x_next].prio,_data[x].prio) ) {
if( x_prev==-1 ) {
_head=x_next;
} else {
_data[x_prev].right_neighbor=x_next;
}
fuse(x,x_next);
x=x_next;
}
else {
_data[x].right_neighbor=_data[x_next].right_neighbor;
fuse(x_next,x);
}
}
x_next=_data[x].right_neighbor;
}
}
// Interleave the elements of the given list into the list of the roots
void interleave(int a) {
int p=_head, q=a;
int curr=_data.size();
_data.push_back(Store());
while( p!=-1 || q!=-1 ) {
if( q==-1 || ( p!=-1 && _data[p].degree<_data[q].degree ) ) {
_data[curr].right_neighbor=p;
curr=p;
p=_data[p].right_neighbor;
}
else {
_data[curr].right_neighbor=q;
curr=q;
q=_data[q].right_neighbor;
}
}
_head=_data.back().right_neighbor;
_data.pop_back();
}
// Lace node a under node b
void fuse(int a, int b) {
_data[a].parent=b;
_data[a].right_neighbor=_data[b].child;
_data[b].child=a;
++_data[b].degree;
}
// Unlace node a (if it has siblings)
void unlace(int a) {
int neighb=_data[a].right_neighbor;
int other=_head;
while( _data[other].right_neighbor!=a )
other=_data[other].right_neighbor;
_data[other].right_neighbor=neighb;
}
private:
class Store {
friend class BinomialHeap;
Item name;
int parent;
int right_neighbor;
int child;
int degree;
bool in;
Prio prio;
Store() : parent(-1), right_neighbor(-1), child(-1), degree(0),
in(true) {}
};
};
} //namespace lemon
#endif //LEMON_BINOMIAL_HEAP_H

View File

@@ -0,0 +1,472 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2013
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
#ifndef LEMON_BITS_ALTERATION_NOTIFIER_H
#define LEMON_BITS_ALTERATION_NOTIFIER_H
#include <vector>
#include <list>
#include <lemon/core.h>
#include <lemon/bits/lock.h>
//\ingroup graphbits
//\file
//\brief Observer notifier for graph alteration observers.
namespace lemon {
// \ingroup graphbits
//
// \brief Notifier class to notify observes about alterations in
// a container.
//
// The simple graphs can be refered as two containers: a node container
// and an edge container. But they do not store values directly, they
// are just key continars for more value containers, which are the
// node and edge maps.
//
// The node and edge sets of the graphs can be changed as we add or erase
// nodes and edges in the graph. LEMON would like to handle easily
// that the node and edge maps should contain values for all nodes or
// edges. If we want to check on every indicing if the map contains
// the current indicing key that cause a drawback in the performance
// in the library. We use another solution: we notify all maps about
// an alteration in the graph, which cause only drawback on the
// alteration of the graph.
//
// This class provides an interface to a node or edge container.
// The first() and next() member functions make possible
// to iterate on the keys of the container.
// The id() function returns an integer id for each key.
// The maxId() function gives back an upper bound of the ids.
//
// For the proper functonality of this class, we should notify it
// about each alteration in the container. The alterations have four type:
// add(), erase(), build() and clear(). The add() and
// erase() signal that only one or few items added or erased to or
// from the graph. If all items are erased from the graph or if a new graph
// is built from an empty graph, then it can be signaled with the
// clear() and build() members. Important rule that if we erase items
// from graphs we should first signal the alteration and after that erase
// them from the container, on the other way on item addition we should
// first extend the container and just after that signal the alteration.
//
// The alteration can be observed with a class inherited from the
// ObserverBase nested class. The signals can be handled with
// overriding the virtual functions defined in the base class. The
// observer base can be attached to the notifier with the
// attach() member and can be detached with detach() function. The
// alteration handlers should not call any function which signals
// an other alteration in the same notifier and should not
// detach any observer from the notifier.
//
// Alteration observers try to be exception safe. If an add() or
// a clear() function throws an exception then the remaining
// observeres will not be notified and the fulfilled additions will
// be rolled back by calling the erase() or clear() functions.
// Hence erase() and clear() should not throw exception.
// Actullay, they can throw only \ref ImmediateDetach exception,
// which detach the observer from the notifier.
//
// There are some cases, when the alteration observing is not completly
// reliable. If we want to carry out the node degree in the graph
// as in the \ref InDegMap and we use the reverseArc(), then it cause
// unreliable functionality. Because the alteration observing signals
// only erasing and adding but not the reversing, it will stores bad
// degrees. Apart form that the subgraph adaptors cannot even signal
// the alterations because just a setting in the filter map can modify
// the graph and this cannot be watched in any way.
//
// \param _Container The container which is observed.
// \param _Item The item type which is obserbved.
template <typename _Container, typename _Item>
class AlterationNotifier {
public:
typedef True Notifier;
typedef _Container Container;
typedef _Item Item;
// \brief Exception which can be called from clear() and
// erase().
//
// From the clear() and erase() function only this
// exception is allowed to throw. The exception immediatly
// detaches the current observer from the notifier. Because the
// clear() and erase() should not throw other exceptions
// it can be used to invalidate the observer.
struct ImmediateDetach {};
// \brief ObserverBase is the base class for the observers.
//
// ObserverBase is the abstract base class for the observers.
// It will be notified about an item was inserted into or
// erased from the graph.
//
// The observer interface contains some pure virtual functions
// to override. The add() and erase() functions are
// to notify the oberver when one item is added or erased.
//
// The build() and clear() members are to notify the observer
// about the container is built from an empty container or
// is cleared to an empty container.
class ObserverBase {
protected:
typedef AlterationNotifier Notifier;
friend class AlterationNotifier;
// \brief Default constructor.
//
// Default constructor for ObserverBase.
ObserverBase() : _notifier(0) {}
// \brief Constructor which attach the observer into notifier.
//
// Constructor which attach the observer into notifier.
ObserverBase(AlterationNotifier& nf) {
attach(nf);
}
// \brief Constructor which attach the obserever to the same notifier.
//
// Constructor which attach the obserever to the same notifier as
// the other observer is attached to.
ObserverBase(const ObserverBase& copy) {
if (copy.attached()) {
attach(*copy.notifier());
}
}
// \brief Destructor
virtual ~ObserverBase() {
if (attached()) {
detach();
}
}
// \brief Attaches the observer into an AlterationNotifier.
//
// This member attaches the observer into an AlterationNotifier.
void attach(AlterationNotifier& nf) {
nf.attach(*this);
}
// \brief Detaches the observer into an AlterationNotifier.
//
// This member detaches the observer from an AlterationNotifier.
void detach() {
_notifier->detach(*this);
}
// \brief Gives back a pointer to the notifier which the map
// attached into.
//
// This function gives back a pointer to the notifier which the map
// attached into.
Notifier* notifier() const { return const_cast<Notifier*>(_notifier); }
// Gives back true when the observer is attached into a notifier.
bool attached() const { return _notifier != 0; }
private:
ObserverBase& operator=(const ObserverBase& copy);
protected:
Notifier* _notifier;
typename std::list<ObserverBase*>::iterator _index;
// \brief The member function to notificate the observer about an
// item is added to the container.
//
// The add() member function notificates the observer about an item
// is added to the container. It have to be overrided in the
// subclasses.
virtual void add(const Item&) = 0;
// \brief The member function to notificate the observer about
// more item is added to the container.
//
// The add() member function notificates the observer about more item
// is added to the container. It have to be overrided in the
// subclasses.
virtual void add(const std::vector<Item>& items) = 0;
// \brief The member function to notificate the observer about an
// item is erased from the container.
//
// The erase() member function notificates the observer about an
// item is erased from the container. It have to be overrided in
// the subclasses.
virtual void erase(const Item&) = 0;
// \brief The member function to notificate the observer about
// more item is erased from the container.
//
// The erase() member function notificates the observer about more item
// is erased from the container. It have to be overrided in the
// subclasses.
virtual void erase(const std::vector<Item>& items) = 0;
// \brief The member function to notificate the observer about the
// container is built.
//
// The build() member function notificates the observer about the
// container is built from an empty container. It have to be
// overrided in the subclasses.
virtual void build() = 0;
// \brief The member function to notificate the observer about all
// items are erased from the container.
//
// The clear() member function notificates the observer about all
// items are erased from the container. It have to be overrided in
// the subclasses.
virtual void clear() = 0;
};
protected:
const Container* container;
typedef std::list<ObserverBase*> Observers;
Observers _observers;
lemon::bits::Lock _lock;
public:
// \brief Default constructor.
//
// The default constructor of the AlterationNotifier.
// It creates an empty notifier.
AlterationNotifier()
: container(0) {}
// \brief Constructor.
//
// Constructor with the observed container parameter.
AlterationNotifier(const Container& _container)
: container(&_container) {}
// \brief Copy Constructor of the AlterationNotifier.
//
// Copy constructor of the AlterationNotifier.
// It creates only an empty notifier because the copiable
// notifier's observers have to be registered still into that notifier.
AlterationNotifier(const AlterationNotifier& _notifier)
: container(_notifier.container) {}
// \brief Destructor.
//
// Destructor of the AlterationNotifier.
~AlterationNotifier() {
typename Observers::iterator it;
for (it = _observers.begin(); it != _observers.end(); ++it) {
(*it)->_notifier = 0;
}
}
// \brief Sets the container.
//
// Sets the container.
void setContainer(const Container& _container) {
container = &_container;
}
protected:
AlterationNotifier& operator=(const AlterationNotifier&);
public:
// \brief First item in the container.
//
// Returns the first item in the container. It is
// for start the iteration on the container.
void first(Item& item) const {
container->first(item);
}
// \brief Next item in the container.
//
// Returns the next item in the container. It is
// for iterate on the container.
void next(Item& item) const {
container->next(item);
}
// \brief Returns the id of the item.
//
// Returns the id of the item provided by the container.
int id(const Item& item) const {
return container->id(item);
}
// \brief Returns the maximum id of the container.
//
// Returns the maximum id of the container.
int maxId() const {
return container->maxId(Item());
}
protected:
void attach(ObserverBase& observer) {
_lock.lock();
observer._index = _observers.insert(_observers.begin(), &observer);
observer._notifier = this;
_lock.unlock();
}
void detach(ObserverBase& observer) {
_lock.lock();
_observers.erase(observer._index);
observer._index = _observers.end();
observer._notifier = 0;
_lock.unlock();
}
public:
// \brief Notifies all the registed observers about an item added to
// the container.
//
// It notifies all the registed observers about an item added to
// the container.
void add(const Item& item) {
typename Observers::reverse_iterator it;
try {
for (it = _observers.rbegin(); it != _observers.rend(); ++it) {
(*it)->add(item);
}
} catch (...) {
typename Observers::iterator jt;
for (jt = it.base(); jt != _observers.end(); ++jt) {
(*jt)->erase(item);
}
throw;
}
}
// \brief Notifies all the registed observers about more item added to
// the container.
//
// It notifies all the registed observers about more item added to
// the container.
void add(const std::vector<Item>& items) {
typename Observers::reverse_iterator it;
try {
for (it = _observers.rbegin(); it != _observers.rend(); ++it) {
(*it)->add(items);
}
} catch (...) {
typename Observers::iterator jt;
for (jt = it.base(); jt != _observers.end(); ++jt) {
(*jt)->erase(items);
}
throw;
}
}
// \brief Notifies all the registed observers about an item erased from
// the container.
//
// It notifies all the registed observers about an item erased from
// the container.
void erase(const Item& item) throw() {
typename Observers::iterator it = _observers.begin();
while (it != _observers.end()) {
try {
(*it)->erase(item);
++it;
} catch (const ImmediateDetach&) {
(*it)->_index = _observers.end();
(*it)->_notifier = 0;
it = _observers.erase(it);
}
}
}
// \brief Notifies all the registed observers about more item erased
// from the container.
//
// It notifies all the registed observers about more item erased from
// the container.
void erase(const std::vector<Item>& items) {
typename Observers::iterator it = _observers.begin();
while (it != _observers.end()) {
try {
(*it)->erase(items);
++it;
} catch (const ImmediateDetach&) {
(*it)->_index = _observers.end();
(*it)->_notifier = 0;
it = _observers.erase(it);
}
}
}
// \brief Notifies all the registed observers about the container is
// built.
//
// Notifies all the registed observers about the container is built
// from an empty container.
void build() {
typename Observers::reverse_iterator it;
try {
for (it = _observers.rbegin(); it != _observers.rend(); ++it) {
(*it)->build();
}
} catch (...) {
typename Observers::iterator jt;
for (jt = it.base(); jt != _observers.end(); ++jt) {
(*jt)->clear();
}
throw;
}
}
// \brief Notifies all the registed observers about all items are
// erased.
//
// Notifies all the registed observers about all items are erased
// from the container.
void clear() {
typename Observers::iterator it = _observers.begin();
while (it != _observers.end()) {
try {
(*it)->clear();
++it;
} catch (const ImmediateDetach&) {
(*it)->_index = _observers.end();
(*it)->_notifier = 0;
it = _observers.erase(it);
}
}
}
};
}
#endif

View File

@@ -0,0 +1,351 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2013
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
#ifndef LEMON_BITS_ARRAY_MAP_H
#define LEMON_BITS_ARRAY_MAP_H
#include <memory>
#include <lemon/bits/traits.h>
#include <lemon/bits/alteration_notifier.h>
#include <lemon/concept_check.h>
#include <lemon/concepts/maps.h>
// \ingroup graphbits
// \file
// \brief Graph map based on the array storage.
namespace lemon {
// \ingroup graphbits
//
// \brief Graph map based on the array storage.
//
// The ArrayMap template class is graph map structure that automatically
// updates the map when a key is added to or erased from the graph.
// This map uses the allocators to implement the container functionality.
//
// The template parameters are the Graph, the current Item type and
// the Value type of the map.
template <typename _Graph, typename _Item, typename _Value>
class ArrayMap
: public ItemSetTraits<_Graph, _Item>::ItemNotifier::ObserverBase {
public:
// The graph type.
typedef _Graph GraphType;
// The item type.
typedef _Item Item;
// The reference map tag.
typedef True ReferenceMapTag;
// The key type of the map.
typedef _Item Key;
// The value type of the map.
typedef _Value Value;
// The const reference type of the map.
typedef const _Value& ConstReference;
// The reference type of the map.
typedef _Value& Reference;
// The map type.
typedef ArrayMap Map;
// The notifier type.
typedef typename ItemSetTraits<_Graph, _Item>::ItemNotifier Notifier;
private:
// The MapBase of the Map which imlements the core regisitry function.
typedef typename Notifier::ObserverBase Parent;
typedef std::allocator<Value> Allocator;
public:
// \brief Graph initialized map constructor.
//
// Graph initialized map constructor.
explicit ArrayMap(const GraphType& graph) {
Parent::attach(graph.notifier(Item()));
allocate_memory();
Notifier* nf = Parent::notifier();
Item it;
for (nf->first(it); it != INVALID; nf->next(it)) {
int id = nf->id(it);;
allocator.construct(&(values[id]), Value());
}
}
// \brief Constructor to use default value to initialize the map.
//
// It constructs a map and initialize all of the the map.
ArrayMap(const GraphType& graph, const Value& value) {
Parent::attach(graph.notifier(Item()));
allocate_memory();
Notifier* nf = Parent::notifier();
Item it;
for (nf->first(it); it != INVALID; nf->next(it)) {
int id = nf->id(it);;
allocator.construct(&(values[id]), value);
}
}
private:
// \brief Constructor to copy a map of the same map type.
//
// Constructor to copy a map of the same map type.
ArrayMap(const ArrayMap& copy) : Parent() {
if (copy.attached()) {
attach(*copy.notifier());
}
capacity = copy.capacity;
if (capacity == 0) return;
values = allocator.allocate(capacity);
Notifier* nf = Parent::notifier();
Item it;
for (nf->first(it); it != INVALID; nf->next(it)) {
int id = nf->id(it);;
allocator.construct(&(values[id]), copy.values[id]);
}
}
// \brief Assign operator.
//
// This operator assigns for each item in the map the
// value mapped to the same item in the copied map.
// The parameter map should be indiced with the same
// itemset because this assign operator does not change
// the container of the map.
ArrayMap& operator=(const ArrayMap& cmap) {
return operator=<ArrayMap>(cmap);
}
// \brief Template assign operator.
//
// The given parameter should conform to the ReadMap
// concecpt and could be indiced by the current item set of
// the NodeMap. In this case the value for each item
// is assigned by the value of the given ReadMap.
template <typename CMap>
ArrayMap& operator=(const CMap& cmap) {
checkConcept<concepts::ReadMap<Key, _Value>, CMap>();
const typename Parent::Notifier* nf = Parent::notifier();
Item it;
for (nf->first(it); it != INVALID; nf->next(it)) {
set(it, cmap[it]);
}
return *this;
}
public:
// \brief The destructor of the map.
//
// The destructor of the map.
virtual ~ArrayMap() {
if (attached()) {
clear();
detach();
}
}
protected:
using Parent::attach;
using Parent::detach;
using Parent::attached;
public:
// \brief The subscript operator.
//
// The subscript operator. The map can be subscripted by the
// actual keys of the graph.
Value& operator[](const Key& key) {
int id = Parent::notifier()->id(key);
return values[id];
}
// \brief The const subscript operator.
//
// The const subscript operator. The map can be subscripted by the
// actual keys of the graph.
const Value& operator[](const Key& key) const {
int id = Parent::notifier()->id(key);
return values[id];
}
// \brief Setter function of the map.
//
// Setter function of the map. Equivalent with map[key] = val.
// This is a compatibility feature with the not dereferable maps.
void set(const Key& key, const Value& val) {
(*this)[key] = val;
}
protected:
// \brief Adds a new key to the map.
//
// It adds a new key to the map. It is called by the observer notifier
// and it overrides the add() member function of the observer base.
virtual void add(const Key& key) {
Notifier* nf = Parent::notifier();
int id = nf->id(key);
if (id >= capacity) {
int new_capacity = (capacity == 0 ? 1 : capacity);
while (new_capacity <= id) {
new_capacity <<= 1;
}
Value* new_values = allocator.allocate(new_capacity);
Item it;
for (nf->first(it); it != INVALID; nf->next(it)) {
int jd = nf->id(it);;
if (id != jd) {
allocator.construct(&(new_values[jd]), values[jd]);
allocator.destroy(&(values[jd]));
}
}
if (capacity != 0) allocator.deallocate(values, capacity);
values = new_values;
capacity = new_capacity;
}
allocator.construct(&(values[id]), Value());
}
// \brief Adds more new keys to the map.
//
// It adds more new keys to the map. It is called by the observer notifier
// and it overrides the add() member function of the observer base.
virtual void add(const std::vector<Key>& keys) {
Notifier* nf = Parent::notifier();
int max_id = -1;
for (int i = 0; i < int(keys.size()); ++i) {
int id = nf->id(keys[i]);
if (id > max_id) {
max_id = id;
}
}
if (max_id >= capacity) {
int new_capacity = (capacity == 0 ? 1 : capacity);
while (new_capacity <= max_id) {
new_capacity <<= 1;
}
Value* new_values = allocator.allocate(new_capacity);
Item it;
for (nf->first(it); it != INVALID; nf->next(it)) {
int id = nf->id(it);
bool found = false;
for (int i = 0; i < int(keys.size()); ++i) {
int jd = nf->id(keys[i]);
if (id == jd) {
found = true;
break;
}
}
if (found) continue;
allocator.construct(&(new_values[id]), values[id]);
allocator.destroy(&(values[id]));
}
if (capacity != 0) allocator.deallocate(values, capacity);
values = new_values;
capacity = new_capacity;
}
for (int i = 0; i < int(keys.size()); ++i) {
int id = nf->id(keys[i]);
allocator.construct(&(values[id]), Value());
}
}
// \brief Erase a key from the map.
//
// Erase a key from the map. It is called by the observer notifier
// and it overrides the erase() member function of the observer base.
virtual void erase(const Key& key) {
int id = Parent::notifier()->id(key);
allocator.destroy(&(values[id]));
}
// \brief Erase more keys from the map.
//
// Erase more keys from the map. It is called by the observer notifier
// and it overrides the erase() member function of the observer base.
virtual void erase(const std::vector<Key>& keys) {
for (int i = 0; i < int(keys.size()); ++i) {
int id = Parent::notifier()->id(keys[i]);
allocator.destroy(&(values[id]));
}
}
// \brief Builds the map.
//
// It builds the map. It is called by the observer notifier
// and it overrides the build() member function of the observer base.
virtual void build() {
Notifier* nf = Parent::notifier();
allocate_memory();
Item it;
for (nf->first(it); it != INVALID; nf->next(it)) {
int id = nf->id(it);;
allocator.construct(&(values[id]), Value());
}
}
// \brief Clear the map.
//
// It erase all items from the map. It is called by the observer notifier
// and it overrides the clear() member function of the observer base.
virtual void clear() {
Notifier* nf = Parent::notifier();
if (capacity != 0) {
Item it;
for (nf->first(it); it != INVALID; nf->next(it)) {
int id = nf->id(it);
allocator.destroy(&(values[id]));
}
allocator.deallocate(values, capacity);
capacity = 0;
}
}
private:
void allocate_memory() {
int max_id = Parent::notifier()->maxId();
if (max_id == -1) {
capacity = 0;
values = 0;
return;
}
capacity = 1;
while (capacity <= max_id) {
capacity <<= 1;
}
values = allocator.allocate(capacity);
}
int capacity;
Value* values;
Allocator allocator;
};
}
#endif

View File

@@ -0,0 +1,174 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2013
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
#ifndef LEMON_BEZIER_H
#define LEMON_BEZIER_H
//\ingroup misc
//\file
//\brief Classes to compute with Bezier curves.
//
//Up to now this file is used internally by \ref graph_to_eps.h
#include<lemon/dim2.h>
namespace lemon {
namespace dim2 {
class BezierBase {
public:
typedef lemon::dim2::Point<double> Point;
protected:
static Point conv(Point x,Point y,double t) {return (1-t)*x+t*y;}
};
class Bezier1 : public BezierBase
{
public:
Point p1,p2;
Bezier1() {}
Bezier1(Point _p1, Point _p2) :p1(_p1), p2(_p2) {}
Point operator()(double t) const
{
// return conv(conv(p1,p2,t),conv(p2,p3,t),t);
return conv(p1,p2,t);
}
Bezier1 before(double t) const
{
return Bezier1(p1,conv(p1,p2,t));
}
Bezier1 after(double t) const
{
return Bezier1(conv(p1,p2,t),p2);
}
Bezier1 revert() const { return Bezier1(p2,p1);}
Bezier1 operator()(double a,double b) const { return before(b).after(a/b); }
Point grad() const { return p2-p1; }
Point norm() const { return rot90(p2-p1); }
Point grad(double) const { return grad(); }
Point norm(double t) const { return rot90(grad(t)); }
};
class Bezier2 : public BezierBase
{
public:
Point p1,p2,p3;
Bezier2() {}
Bezier2(Point _p1, Point _p2, Point _p3) :p1(_p1), p2(_p2), p3(_p3) {}
Bezier2(const Bezier1 &b) : p1(b.p1), p2(conv(b.p1,b.p2,.5)), p3(b.p2) {}
Point operator()(double t) const
{
// return conv(conv(p1,p2,t),conv(p2,p3,t),t);
return ((1-t)*(1-t))*p1+(2*(1-t)*t)*p2+(t*t)*p3;
}
Bezier2 before(double t) const
{
Point q(conv(p1,p2,t));
Point r(conv(p2,p3,t));
return Bezier2(p1,q,conv(q,r,t));
}
Bezier2 after(double t) const
{
Point q(conv(p1,p2,t));
Point r(conv(p2,p3,t));
return Bezier2(conv(q,r,t),r,p3);
}
Bezier2 revert() const { return Bezier2(p3,p2,p1);}
Bezier2 operator()(double a,double b) const { return before(b).after(a/b); }
Bezier1 grad() const { return Bezier1(2.0*(p2-p1),2.0*(p3-p2)); }
Bezier1 norm() const { return Bezier1(2.0*rot90(p2-p1),2.0*rot90(p3-p2)); }
Point grad(double t) const { return grad()(t); }
Point norm(double t) const { return rot90(grad(t)); }
};
class Bezier3 : public BezierBase
{
public:
Point p1,p2,p3,p4;
Bezier3() {}
Bezier3(Point _p1, Point _p2, Point _p3, Point _p4)
: p1(_p1), p2(_p2), p3(_p3), p4(_p4) {}
Bezier3(const Bezier1 &b) : p1(b.p1), p2(conv(b.p1,b.p2,1.0/3.0)),
p3(conv(b.p1,b.p2,2.0/3.0)), p4(b.p2) {}
Bezier3(const Bezier2 &b) : p1(b.p1), p2(conv(b.p1,b.p2,2.0/3.0)),
p3(conv(b.p2,b.p3,1.0/3.0)), p4(b.p3) {}
Point operator()(double t) const
{
// return Bezier2(conv(p1,p2,t),conv(p2,p3,t),conv(p3,p4,t))(t);
return ((1-t)*(1-t)*(1-t))*p1+(3*t*(1-t)*(1-t))*p2+
(3*t*t*(1-t))*p3+(t*t*t)*p4;
}
Bezier3 before(double t) const
{
Point p(conv(p1,p2,t));
Point q(conv(p2,p3,t));
Point r(conv(p3,p4,t));
Point a(conv(p,q,t));
Point b(conv(q,r,t));
Point c(conv(a,b,t));
return Bezier3(p1,p,a,c);
}
Bezier3 after(double t) const
{
Point p(conv(p1,p2,t));
Point q(conv(p2,p3,t));
Point r(conv(p3,p4,t));
Point a(conv(p,q,t));
Point b(conv(q,r,t));
Point c(conv(a,b,t));
return Bezier3(c,b,r,p4);
}
Bezier3 revert() const { return Bezier3(p4,p3,p2,p1);}
Bezier3 operator()(double a,double b) const { return before(b).after(a/b); }
Bezier2 grad() const { return Bezier2(3.0*(p2-p1),3.0*(p3-p2),3.0*(p4-p3)); }
Bezier2 norm() const { return Bezier2(3.0*rot90(p2-p1),
3.0*rot90(p3-p2),
3.0*rot90(p4-p3)); }
Point grad(double t) const { return grad()(t); }
Point norm(double t) const { return rot90(grad(t)); }
template<class R,class F,class S,class D>
R recSplit(F &_f,const S &_s,D _d) const
{
const Point a=(p1+p2)/2;
const Point b=(p2+p3)/2;
const Point c=(p3+p4)/2;
const Point d=(a+b)/2;
const Point e=(b+c)/2;
// const Point f=(d+e)/2;
R f1=_f(Bezier3(p1,a,d,e),_d);
R f2=_f(Bezier3(e,d,c,p4),_d);
return _s(f1,f2);
}
};
} //END OF NAMESPACE dim2
} //END OF NAMESPACE lemon
#endif // LEMON_BEZIER_H

View File

@@ -0,0 +1,182 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2013
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
#ifndef LEMON_BITS_DEFAULT_MAP_H
#define LEMON_BITS_DEFAULT_MAP_H
#include <lemon/config.h>
#include <lemon/bits/array_map.h>
#include <lemon/bits/vector_map.h>
//#include <lemon/bits/debug_map.h>
//\ingroup graphbits
//\file
//\brief Graph maps that construct and destruct their elements dynamically.
namespace lemon {
//#ifndef LEMON_USE_DEBUG_MAP
template <typename _Graph, typename _Item, typename _Value>
struct DefaultMapSelector {
typedef ArrayMap<_Graph, _Item, _Value> Map;
};
// bool
template <typename _Graph, typename _Item>
struct DefaultMapSelector<_Graph, _Item, bool> {
typedef VectorMap<_Graph, _Item, bool> Map;
};
// char
template <typename _Graph, typename _Item>
struct DefaultMapSelector<_Graph, _Item, char> {
typedef VectorMap<_Graph, _Item, char> Map;
};
template <typename _Graph, typename _Item>
struct DefaultMapSelector<_Graph, _Item, signed char> {
typedef VectorMap<_Graph, _Item, signed char> Map;
};
template <typename _Graph, typename _Item>
struct DefaultMapSelector<_Graph, _Item, unsigned char> {
typedef VectorMap<_Graph, _Item, unsigned char> Map;
};
// int
template <typename _Graph, typename _Item>
struct DefaultMapSelector<_Graph, _Item, signed int> {
typedef VectorMap<_Graph, _Item, signed int> Map;
};
template <typename _Graph, typename _Item>
struct DefaultMapSelector<_Graph, _Item, unsigned int> {
typedef VectorMap<_Graph, _Item, unsigned int> Map;
};
// short
template <typename _Graph, typename _Item>
struct DefaultMapSelector<_Graph, _Item, signed short> {
typedef VectorMap<_Graph, _Item, signed short> Map;
};
template <typename _Graph, typename _Item>
struct DefaultMapSelector<_Graph, _Item, unsigned short> {
typedef VectorMap<_Graph, _Item, unsigned short> Map;
};
// long
template <typename _Graph, typename _Item>
struct DefaultMapSelector<_Graph, _Item, signed long> {
typedef VectorMap<_Graph, _Item, signed long> Map;
};
template <typename _Graph, typename _Item>
struct DefaultMapSelector<_Graph, _Item, unsigned long> {
typedef VectorMap<_Graph, _Item, unsigned long> Map;
};
#if defined LEMON_HAVE_LONG_LONG
// long long
template <typename _Graph, typename _Item>
struct DefaultMapSelector<_Graph, _Item, signed long long> {
typedef VectorMap<_Graph, _Item, signed long long> Map;
};
template <typename _Graph, typename _Item>
struct DefaultMapSelector<_Graph, _Item, unsigned long long> {
typedef VectorMap<_Graph, _Item, unsigned long long> Map;
};
#endif
// float
template <typename _Graph, typename _Item>
struct DefaultMapSelector<_Graph, _Item, float> {
typedef VectorMap<_Graph, _Item, float> Map;
};
// double
template <typename _Graph, typename _Item>
struct DefaultMapSelector<_Graph, _Item, double> {
typedef VectorMap<_Graph, _Item, double> Map;
};
// long double
template <typename _Graph, typename _Item>
struct DefaultMapSelector<_Graph, _Item, long double> {
typedef VectorMap<_Graph, _Item, long double> Map;
};
// pointer
template <typename _Graph, typename _Item, typename _Ptr>
struct DefaultMapSelector<_Graph, _Item, _Ptr*> {
typedef VectorMap<_Graph, _Item, _Ptr*> Map;
};
// #else
// template <typename _Graph, typename _Item, typename _Value>
// struct DefaultMapSelector {
// typedef DebugMap<_Graph, _Item, _Value> Map;
// };
// #endif
// DefaultMap class
template <typename _Graph, typename _Item, typename _Value>
class DefaultMap
: public DefaultMapSelector<_Graph, _Item, _Value>::Map {
typedef typename DefaultMapSelector<_Graph, _Item, _Value>::Map Parent;
public:
typedef DefaultMap<_Graph, _Item, _Value> Map;
typedef typename Parent::GraphType GraphType;
typedef typename Parent::Value Value;
explicit DefaultMap(const GraphType& graph) : Parent(graph) {}
DefaultMap(const GraphType& graph, const Value& value)
: Parent(graph, value) {}
DefaultMap& operator=(const DefaultMap& cmap) {
return operator=<DefaultMap>(cmap);
}
template <typename CMap>
DefaultMap& operator=(const CMap& cmap) {
Parent::operator=(cmap);
return *this;
}
};
}
#endif

View File

@@ -0,0 +1,627 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2013
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
#ifndef LEMON_BITS_EDGE_SET_EXTENDER_H
#define LEMON_BITS_EDGE_SET_EXTENDER_H
#include <lemon/core.h>
#include <lemon/error.h>
#include <lemon/bits/default_map.h>
#include <lemon/bits/map_extender.h>
//\ingroup digraphbits
//\file
//\brief Extenders for the arc set types
namespace lemon {
// \ingroup digraphbits
//
// \brief Extender for the ArcSets
template <typename Base>
class ArcSetExtender : public Base {
typedef Base Parent;
public:
typedef ArcSetExtender Digraph;
// Base extensions
typedef typename Parent::Node Node;
typedef typename Parent::Arc Arc;
int maxId(Node) const {
return Parent::maxNodeId();
}
int maxId(Arc) const {
return Parent::maxArcId();
}
Node fromId(int id, Node) const {
return Parent::nodeFromId(id);
}
Arc fromId(int id, Arc) const {
return Parent::arcFromId(id);
}
Node oppositeNode(const Node &n, const Arc &e) const {
if (n == Parent::source(e))
return Parent::target(e);
else if(n==Parent::target(e))
return Parent::source(e);
else
return INVALID;
}
// Alteration notifier extensions
// The arc observer registry.
typedef AlterationNotifier<ArcSetExtender, Arc> ArcNotifier;
protected:
mutable ArcNotifier arc_notifier;
public:
using Parent::notifier;
// Gives back the arc alteration notifier.
ArcNotifier& notifier(Arc) const {
return arc_notifier;
}
// Iterable extensions
class NodeIt : public Node {
const Digraph* digraph;
public:
NodeIt() {}
NodeIt(Invalid i) : Node(i) { }
explicit NodeIt(const Digraph& _graph) : digraph(&_graph) {
_graph.first(static_cast<Node&>(*this));
}
NodeIt(const Digraph& _graph, const Node& node)
: Node(node), digraph(&_graph) {}
NodeIt& operator++() {
digraph->next(*this);
return *this;
}
};
class ArcIt : public Arc {
const Digraph* digraph;
public:
ArcIt() { }
ArcIt(Invalid i) : Arc(i) { }
explicit ArcIt(const Digraph& _graph) : digraph(&_graph) {
_graph.first(static_cast<Arc&>(*this));
}
ArcIt(const Digraph& _graph, const Arc& e) :
Arc(e), digraph(&_graph) { }
ArcIt& operator++() {
digraph->next(*this);
return *this;
}
};
class OutArcIt : public Arc {
const Digraph* digraph;
public:
OutArcIt() { }
OutArcIt(Invalid i) : Arc(i) { }
OutArcIt(const Digraph& _graph, const Node& node)
: digraph(&_graph) {
_graph.firstOut(*this, node);
}
OutArcIt(const Digraph& _graph, const Arc& arc)
: Arc(arc), digraph(&_graph) {}
OutArcIt& operator++() {
digraph->nextOut(*this);
return *this;
}
};
class InArcIt : public Arc {
const Digraph* digraph;
public:
InArcIt() { }
InArcIt(Invalid i) : Arc(i) { }
InArcIt(const Digraph& _graph, const Node& node)
: digraph(&_graph) {
_graph.firstIn(*this, node);
}
InArcIt(const Digraph& _graph, const Arc& arc) :
Arc(arc), digraph(&_graph) {}
InArcIt& operator++() {
digraph->nextIn(*this);
return *this;
}
};
// \brief Base node of the iterator
//
// Returns the base node (ie. the source in this case) of the iterator
Node baseNode(const OutArcIt &e) const {
return Parent::source(static_cast<const Arc&>(e));
}
// \brief Running node of the iterator
//
// Returns the running node (ie. the target in this case) of the
// iterator
Node runningNode(const OutArcIt &e) const {
return Parent::target(static_cast<const Arc&>(e));
}
// \brief Base node of the iterator
//
// Returns the base node (ie. the target in this case) of the iterator
Node baseNode(const InArcIt &e) const {
return Parent::target(static_cast<const Arc&>(e));
}
// \brief Running node of the iterator
//
// Returns the running node (ie. the source in this case) of the
// iterator
Node runningNode(const InArcIt &e) const {
return Parent::source(static_cast<const Arc&>(e));
}
using Parent::first;
// Mappable extension
template <typename _Value>
class ArcMap
: public MapExtender<DefaultMap<Digraph, Arc, _Value> > {
typedef MapExtender<DefaultMap<Digraph, Arc, _Value> > Parent;
public:
explicit ArcMap(const Digraph& _g)
: Parent(_g) {}
ArcMap(const Digraph& _g, const _Value& _v)
: Parent(_g, _v) {}
ArcMap& operator=(const ArcMap& cmap) {
return operator=<ArcMap>(cmap);
}
template <typename CMap>
ArcMap& operator=(const CMap& cmap) {
Parent::operator=(cmap);
return *this;
}
};
// Alteration extension
Arc addArc(const Node& from, const Node& to) {
Arc arc = Parent::addArc(from, to);
notifier(Arc()).add(arc);
return arc;
}
void clear() {
notifier(Arc()).clear();
Parent::clear();
}
void erase(const Arc& arc) {
notifier(Arc()).erase(arc);
Parent::erase(arc);
}
ArcSetExtender() {
arc_notifier.setContainer(*this);
}
~ArcSetExtender() {
arc_notifier.clear();
}
};
// \ingroup digraphbits
//
// \brief Extender for the EdgeSets
template <typename Base>
class EdgeSetExtender : public Base {
typedef Base Parent;
public:
typedef EdgeSetExtender Graph;
typedef True UndirectedTag;
typedef typename Parent::Node Node;
typedef typename Parent::Arc Arc;
typedef typename Parent::Edge Edge;
int maxId(Node) const {
return Parent::maxNodeId();
}
int maxId(Arc) const {
return Parent::maxArcId();
}
int maxId(Edge) const {
return Parent::maxEdgeId();
}
Node fromId(int id, Node) const {
return Parent::nodeFromId(id);
}
Arc fromId(int id, Arc) const {
return Parent::arcFromId(id);
}
Edge fromId(int id, Edge) const {
return Parent::edgeFromId(id);
}
Node oppositeNode(const Node &n, const Edge &e) const {
if( n == Parent::u(e))
return Parent::v(e);
else if( n == Parent::v(e))
return Parent::u(e);
else
return INVALID;
}
Arc oppositeArc(const Arc &e) const {
return Parent::direct(e, !Parent::direction(e));
}
using Parent::direct;
Arc direct(const Edge &e, const Node &s) const {
return Parent::direct(e, Parent::u(e) == s);
}
typedef AlterationNotifier<EdgeSetExtender, Arc> ArcNotifier;
typedef AlterationNotifier<EdgeSetExtender, Edge> EdgeNotifier;
protected:
mutable ArcNotifier arc_notifier;
mutable EdgeNotifier edge_notifier;
public:
using Parent::notifier;
ArcNotifier& notifier(Arc) const {
return arc_notifier;
}
EdgeNotifier& notifier(Edge) const {
return edge_notifier;
}
class NodeIt : public Node {
const Graph* graph;
public:
NodeIt() {}
NodeIt(Invalid i) : Node(i) { }
explicit NodeIt(const Graph& _graph) : graph(&_graph) {
_graph.first(static_cast<Node&>(*this));
}
NodeIt(const Graph& _graph, const Node& node)
: Node(node), graph(&_graph) {}
NodeIt& operator++() {
graph->next(*this);
return *this;
}
};
class ArcIt : public Arc {
const Graph* graph;
public:
ArcIt() { }
ArcIt(Invalid i) : Arc(i) { }
explicit ArcIt(const Graph& _graph) : graph(&_graph) {
_graph.first(static_cast<Arc&>(*this));
}
ArcIt(const Graph& _graph, const Arc& e) :
Arc(e), graph(&_graph) { }
ArcIt& operator++() {
graph->next(*this);
return *this;
}
};
class OutArcIt : public Arc {
const Graph* graph;
public:
OutArcIt() { }
OutArcIt(Invalid i) : Arc(i) { }
OutArcIt(const Graph& _graph, const Node& node)
: graph(&_graph) {
_graph.firstOut(*this, node);
}
OutArcIt(const Graph& _graph, const Arc& arc)
: Arc(arc), graph(&_graph) {}
OutArcIt& operator++() {
graph->nextOut(*this);
return *this;
}
};
class InArcIt : public Arc {
const Graph* graph;
public:
InArcIt() { }
InArcIt(Invalid i) : Arc(i) { }
InArcIt(const Graph& _graph, const Node& node)
: graph(&_graph) {
_graph.firstIn(*this, node);
}
InArcIt(const Graph& _graph, const Arc& arc) :
Arc(arc), graph(&_graph) {}
InArcIt& operator++() {
graph->nextIn(*this);
return *this;
}
};
class EdgeIt : public Parent::Edge {
const Graph* graph;
public:
EdgeIt() { }
EdgeIt(Invalid i) : Edge(i) { }
explicit EdgeIt(const Graph& _graph) : graph(&_graph) {
_graph.first(static_cast<Edge&>(*this));
}
EdgeIt(const Graph& _graph, const Edge& e) :
Edge(e), graph(&_graph) { }
EdgeIt& operator++() {
graph->next(*this);
return *this;
}
};
class IncEdgeIt : public Parent::Edge {
friend class EdgeSetExtender;
const Graph* graph;
bool direction;
public:
IncEdgeIt() { }
IncEdgeIt(Invalid i) : Edge(i), direction(false) { }
IncEdgeIt(const Graph& _graph, const Node &n) : graph(&_graph) {
_graph.firstInc(*this, direction, n);
}
IncEdgeIt(const Graph& _graph, const Edge &ue, const Node &n)
: graph(&_graph), Edge(ue) {
direction = (_graph.source(ue) == n);
}
IncEdgeIt& operator++() {
graph->nextInc(*this, direction);
return *this;
}
};
// \brief Base node of the iterator
//
// Returns the base node (ie. the source in this case) of the iterator
Node baseNode(const OutArcIt &e) const {
return Parent::source(static_cast<const Arc&>(e));
}
// \brief Running node of the iterator
//
// Returns the running node (ie. the target in this case) of the
// iterator
Node runningNode(const OutArcIt &e) const {
return Parent::target(static_cast<const Arc&>(e));
}
// \brief Base node of the iterator
//
// Returns the base node (ie. the target in this case) of the iterator
Node baseNode(const InArcIt &e) const {
return Parent::target(static_cast<const Arc&>(e));
}
// \brief Running node of the iterator
//
// Returns the running node (ie. the source in this case) of the
// iterator
Node runningNode(const InArcIt &e) const {
return Parent::source(static_cast<const Arc&>(e));
}
// Base node of the iterator
//
// Returns the base node of the iterator
Node baseNode(const IncEdgeIt &e) const {
return e.direction ? this->u(e) : this->v(e);
}
// Running node of the iterator
//
// Returns the running node of the iterator
Node runningNode(const IncEdgeIt &e) const {
return e.direction ? this->v(e) : this->u(e);
}
template <typename _Value>
class ArcMap
: public MapExtender<DefaultMap<Graph, Arc, _Value> > {
typedef MapExtender<DefaultMap<Graph, Arc, _Value> > Parent;
public:
explicit ArcMap(const Graph& _g)
: Parent(_g) {}
ArcMap(const Graph& _g, const _Value& _v)
: Parent(_g, _v) {}
ArcMap& operator=(const ArcMap& cmap) {
return operator=<ArcMap>(cmap);
}
template <typename CMap>
ArcMap& operator=(const CMap& cmap) {
Parent::operator=(cmap);
return *this;
}
};
template <typename _Value>
class EdgeMap
: public MapExtender<DefaultMap<Graph, Edge, _Value> > {
typedef MapExtender<DefaultMap<Graph, Edge, _Value> > Parent;
public:
explicit EdgeMap(const Graph& _g)
: Parent(_g) {}
EdgeMap(const Graph& _g, const _Value& _v)
: Parent(_g, _v) {}
EdgeMap& operator=(const EdgeMap& cmap) {
return operator=<EdgeMap>(cmap);
}
template <typename CMap>
EdgeMap& operator=(const CMap& cmap) {
Parent::operator=(cmap);
return *this;
}
};
// Alteration extension
Edge addEdge(const Node& from, const Node& to) {
Edge edge = Parent::addEdge(from, to);
notifier(Edge()).add(edge);
std::vector<Arc> arcs;
arcs.push_back(Parent::direct(edge, true));
arcs.push_back(Parent::direct(edge, false));
notifier(Arc()).add(arcs);
return edge;
}
void clear() {
notifier(Arc()).clear();
notifier(Edge()).clear();
Parent::clear();
}
void erase(const Edge& edge) {
std::vector<Arc> arcs;
arcs.push_back(Parent::direct(edge, true));
arcs.push_back(Parent::direct(edge, false));
notifier(Arc()).erase(arcs);
notifier(Edge()).erase(edge);
Parent::erase(edge);
}
EdgeSetExtender() {
arc_notifier.setContainer(*this);
edge_notifier.setContainer(*this);
}
~EdgeSetExtender() {
edge_notifier.clear();
arc_notifier.clear();
}
};
}
#endif

View File

@@ -0,0 +1,131 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2009
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
// This file contains a modified version of the enable_if library from BOOST.
// See the appropriate copyright notice below.
// Boost enable_if library
// Copyright 2003 (c) The Trustees of Indiana University.
// Use, modification, and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Authors: Jaakko Jarvi (jajarvi at osl.iu.edu)
// Jeremiah Willcock (jewillco at osl.iu.edu)
// Andrew Lumsdaine (lums at osl.iu.edu)
#ifndef LEMON_BITS_ENABLE_IF_H
#define LEMON_BITS_ENABLE_IF_H
//\file
//\brief Miscellaneous basic utilities
namespace lemon
{
// Basic type for defining "tags". A "YES" condition for \c enable_if.
// Basic type for defining "tags". A "YES" condition for \c enable_if.
//
//\sa False
struct True {
//\e
static const bool value = true;
};
// Basic type for defining "tags". A "NO" condition for \c enable_if.
// Basic type for defining "tags". A "NO" condition for \c enable_if.
//
//\sa True
struct False {
//\e
static const bool value = false;
};
template <typename T>
struct Wrap {
const T &value;
Wrap(const T &t) : value(t) {}
};
/**************** dummy class to avoid ambiguity ****************/
template<int T> struct dummy { dummy(int) {} };
/**************** enable_if from BOOST ****************/
template <typename Type, typename T = void>
struct exists {
typedef T type;
};
template <bool B, class T = void>
struct enable_if_c {
typedef T type;
};
template <class T>
struct enable_if_c<false, T> {};
template <class Cond, class T = void>
struct enable_if : public enable_if_c<Cond::value, T> {};
template <bool B, class T>
struct lazy_enable_if_c {
typedef typename T::type type;
};
template <class T>
struct lazy_enable_if_c<false, T> {};
template <class Cond, class T>
struct lazy_enable_if : public lazy_enable_if_c<Cond::value, T> {};
template <bool B, class T = void>
struct disable_if_c {
typedef T type;
};
template <class T>
struct disable_if_c<true, T> {};
template <class Cond, class T = void>
struct disable_if : public disable_if_c<Cond::value, T> {};
template <bool B, class T>
struct lazy_disable_if_c {
typedef typename T::type type;
};
template <class T>
struct lazy_disable_if_c<true, T> {};
template <class Cond, class T>
struct lazy_disable_if : public lazy_disable_if_c<Cond::value, T> {};
} // namespace lemon
#endif

View File

@@ -0,0 +1,401 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2013
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
#ifndef LEMON_BITS_GRAPH_ADAPTOR_EXTENDER_H
#define LEMON_BITS_GRAPH_ADAPTOR_EXTENDER_H
#include <lemon/core.h>
#include <lemon/error.h>
namespace lemon {
template <typename _Digraph>
class DigraphAdaptorExtender : public _Digraph {
typedef _Digraph Parent;
public:
typedef _Digraph Digraph;
typedef DigraphAdaptorExtender Adaptor;
// Base extensions
typedef typename Parent::Node Node;
typedef typename Parent::Arc Arc;
int maxId(Node) const {
return Parent::maxNodeId();
}
int maxId(Arc) const {
return Parent::maxArcId();
}
Node fromId(int id, Node) const {
return Parent::nodeFromId(id);
}
Arc fromId(int id, Arc) const {
return Parent::arcFromId(id);
}
Node oppositeNode(const Node &n, const Arc &e) const {
if (n == Parent::source(e))
return Parent::target(e);
else if(n==Parent::target(e))
return Parent::source(e);
else
return INVALID;
}
class NodeIt : public Node {
const Adaptor* _adaptor;
public:
NodeIt() {}
NodeIt(Invalid i) : Node(i) { }
explicit NodeIt(const Adaptor& adaptor) : _adaptor(&adaptor) {
_adaptor->first(static_cast<Node&>(*this));
}
NodeIt(const Adaptor& adaptor, const Node& node)
: Node(node), _adaptor(&adaptor) {}
NodeIt& operator++() {
_adaptor->next(*this);
return *this;
}
};
class ArcIt : public Arc {
const Adaptor* _adaptor;
public:
ArcIt() { }
ArcIt(Invalid i) : Arc(i) { }
explicit ArcIt(const Adaptor& adaptor) : _adaptor(&adaptor) {
_adaptor->first(static_cast<Arc&>(*this));
}
ArcIt(const Adaptor& adaptor, const Arc& e) :
Arc(e), _adaptor(&adaptor) { }
ArcIt& operator++() {
_adaptor->next(*this);
return *this;
}
};
class OutArcIt : public Arc {
const Adaptor* _adaptor;
public:
OutArcIt() { }
OutArcIt(Invalid i) : Arc(i) { }
OutArcIt(const Adaptor& adaptor, const Node& node)
: _adaptor(&adaptor) {
_adaptor->firstOut(*this, node);
}
OutArcIt(const Adaptor& adaptor, const Arc& arc)
: Arc(arc), _adaptor(&adaptor) {}
OutArcIt& operator++() {
_adaptor->nextOut(*this);
return *this;
}
};
class InArcIt : public Arc {
const Adaptor* _adaptor;
public:
InArcIt() { }
InArcIt(Invalid i) : Arc(i) { }
InArcIt(const Adaptor& adaptor, const Node& node)
: _adaptor(&adaptor) {
_adaptor->firstIn(*this, node);
}
InArcIt(const Adaptor& adaptor, const Arc& arc) :
Arc(arc), _adaptor(&adaptor) {}
InArcIt& operator++() {
_adaptor->nextIn(*this);
return *this;
}
};
Node baseNode(const OutArcIt &e) const {
return Parent::source(e);
}
Node runningNode(const OutArcIt &e) const {
return Parent::target(e);
}
Node baseNode(const InArcIt &e) const {
return Parent::target(e);
}
Node runningNode(const InArcIt &e) const {
return Parent::source(e);
}
};
template <typename _Graph>
class GraphAdaptorExtender : public _Graph {
typedef _Graph Parent;
public:
typedef _Graph Graph;
typedef GraphAdaptorExtender Adaptor;
typedef True UndirectedTag;
typedef typename Parent::Node Node;
typedef typename Parent::Arc Arc;
typedef typename Parent::Edge Edge;
// Graph extension
int maxId(Node) const {
return Parent::maxNodeId();
}
int maxId(Arc) const {
return Parent::maxArcId();
}
int maxId(Edge) const {
return Parent::maxEdgeId();
}
Node fromId(int id, Node) const {
return Parent::nodeFromId(id);
}
Arc fromId(int id, Arc) const {
return Parent::arcFromId(id);
}
Edge fromId(int id, Edge) const {
return Parent::edgeFromId(id);
}
Node oppositeNode(const Node &n, const Edge &e) const {
if( n == Parent::u(e))
return Parent::v(e);
else if( n == Parent::v(e))
return Parent::u(e);
else
return INVALID;
}
Arc oppositeArc(const Arc &a) const {
return Parent::direct(a, !Parent::direction(a));
}
using Parent::direct;
Arc direct(const Edge &e, const Node &s) const {
return Parent::direct(e, Parent::u(e) == s);
}
class NodeIt : public Node {
const Adaptor* _adaptor;
public:
NodeIt() {}
NodeIt(Invalid i) : Node(i) { }
explicit NodeIt(const Adaptor& adaptor) : _adaptor(&adaptor) {
_adaptor->first(static_cast<Node&>(*this));
}
NodeIt(const Adaptor& adaptor, const Node& node)
: Node(node), _adaptor(&adaptor) {}
NodeIt& operator++() {
_adaptor->next(*this);
return *this;
}
};
class ArcIt : public Arc {
const Adaptor* _adaptor;
public:
ArcIt() { }
ArcIt(Invalid i) : Arc(i) { }
explicit ArcIt(const Adaptor& adaptor) : _adaptor(&adaptor) {
_adaptor->first(static_cast<Arc&>(*this));
}
ArcIt(const Adaptor& adaptor, const Arc& e) :
Arc(e), _adaptor(&adaptor) { }
ArcIt& operator++() {
_adaptor->next(*this);
return *this;
}
};
class OutArcIt : public Arc {
const Adaptor* _adaptor;
public:
OutArcIt() { }
OutArcIt(Invalid i) : Arc(i) { }
OutArcIt(const Adaptor& adaptor, const Node& node)
: _adaptor(&adaptor) {
_adaptor->firstOut(*this, node);
}
OutArcIt(const Adaptor& adaptor, const Arc& arc)
: Arc(arc), _adaptor(&adaptor) {}
OutArcIt& operator++() {
_adaptor->nextOut(*this);
return *this;
}
};
class InArcIt : public Arc {
const Adaptor* _adaptor;
public:
InArcIt() { }
InArcIt(Invalid i) : Arc(i) { }
InArcIt(const Adaptor& adaptor, const Node& node)
: _adaptor(&adaptor) {
_adaptor->firstIn(*this, node);
}
InArcIt(const Adaptor& adaptor, const Arc& arc) :
Arc(arc), _adaptor(&adaptor) {}
InArcIt& operator++() {
_adaptor->nextIn(*this);
return *this;
}
};
class EdgeIt : public Parent::Edge {
const Adaptor* _adaptor;
public:
EdgeIt() { }
EdgeIt(Invalid i) : Edge(i) { }
explicit EdgeIt(const Adaptor& adaptor) : _adaptor(&adaptor) {
_adaptor->first(static_cast<Edge&>(*this));
}
EdgeIt(const Adaptor& adaptor, const Edge& e) :
Edge(e), _adaptor(&adaptor) { }
EdgeIt& operator++() {
_adaptor->next(*this);
return *this;
}
};
class IncEdgeIt : public Edge {
friend class GraphAdaptorExtender;
const Adaptor* _adaptor;
bool direction;
public:
IncEdgeIt() { }
IncEdgeIt(Invalid i) : Edge(i), direction(false) { }
IncEdgeIt(const Adaptor& adaptor, const Node &n) : _adaptor(&adaptor) {
_adaptor->firstInc(static_cast<Edge&>(*this), direction, n);
}
IncEdgeIt(const Adaptor& adaptor, const Edge &e, const Node &n)
: _adaptor(&adaptor), Edge(e) {
direction = (_adaptor->u(e) == n);
}
IncEdgeIt& operator++() {
_adaptor->nextInc(*this, direction);
return *this;
}
};
Node baseNode(const OutArcIt &a) const {
return Parent::source(a);
}
Node runningNode(const OutArcIt &a) const {
return Parent::target(a);
}
Node baseNode(const InArcIt &a) const {
return Parent::target(a);
}
Node runningNode(const InArcIt &a) const {
return Parent::source(a);
}
Node baseNode(const IncEdgeIt &e) const {
return e.direction ? Parent::u(e) : Parent::v(e);
}
Node runningNode(const IncEdgeIt &e) const {
return e.direction ? Parent::v(e) : Parent::u(e);
}
};
}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,65 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2013
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
#ifndef LEMON_BITS_LOCK_H
#define LEMON_BITS_LOCK_H
#include <lemon/config.h>
#if defined(LEMON_USE_PTHREAD)
#include <pthread.h>
#elif defined(LEMON_USE_WIN32_THREADS)
#include <lemon/bits/windows.h>
#endif
namespace lemon {
namespace bits {
#if defined(LEMON_USE_PTHREAD)
class Lock {
public:
Lock() {
pthread_mutex_init(&_lock, 0);
}
~Lock() {
pthread_mutex_destroy(&_lock);
}
void lock() {
pthread_mutex_lock(&_lock);
}
void unlock() {
pthread_mutex_unlock(&_lock);
}
private:
pthread_mutex_t _lock;
};
#elif defined(LEMON_USE_WIN32_THREADS)
class Lock : public WinLock {};
#else
class Lock {
public:
Lock() {}
~Lock() {}
void lock() {}
void unlock() {}
};
#endif
}
}
#endif

View File

@@ -0,0 +1,332 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2013
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
#ifndef LEMON_BITS_MAP_EXTENDER_H
#define LEMON_BITS_MAP_EXTENDER_H
#include <iterator>
#include <lemon/bits/traits.h>
#include <lemon/concept_check.h>
#include <lemon/concepts/maps.h>
//\file
//\brief Extenders for iterable maps.
namespace lemon {
// \ingroup graphbits
//
// \brief Extender for maps
template <typename _Map>
class MapExtender : public _Map {
typedef _Map Parent;
typedef typename Parent::GraphType GraphType;
public:
typedef MapExtender Map;
typedef typename Parent::Key Item;
typedef typename Parent::Key Key;
typedef typename Parent::Value Value;
typedef typename Parent::Reference Reference;
typedef typename Parent::ConstReference ConstReference;
typedef typename Parent::ReferenceMapTag ReferenceMapTag;
class MapIt;
class ConstMapIt;
friend class MapIt;
friend class ConstMapIt;
public:
MapExtender(const GraphType& graph)
: Parent(graph) {}
MapExtender(const GraphType& graph, const Value& value)
: Parent(graph, value) {}
private:
MapExtender& operator=(const MapExtender& cmap) {
return operator=<MapExtender>(cmap);
}
template <typename CMap>
MapExtender& operator=(const CMap& cmap) {
Parent::operator=(cmap);
return *this;
}
public:
class MapIt : public Item {
typedef Item Parent;
public:
typedef typename Map::Value Value;
MapIt() : map(NULL) {}
MapIt(Invalid i) : Parent(i), map(NULL) {}
explicit MapIt(Map& _map) : map(&_map) {
map->notifier()->first(*this);
}
MapIt(const Map& _map, const Item& item)
: Parent(item), map(&_map) {}
MapIt& operator++() {
map->notifier()->next(*this);
return *this;
}
typename MapTraits<Map>::ConstReturnValue operator*() const {
return (*map)[*this];
}
typename MapTraits<Map>::ReturnValue operator*() {
return (*map)[*this];
}
void set(const Value& value) {
map->set(*this, value);
}
protected:
Map* map;
};
class ConstMapIt : public Item {
typedef Item Parent;
public:
typedef typename Map::Value Value;
ConstMapIt() : map(NULL) {}
ConstMapIt(Invalid i) : Parent(i), map(NULL) {}
explicit ConstMapIt(Map& _map) : map(&_map) {
map->notifier()->first(*this);
}
ConstMapIt(const Map& _map, const Item& item)
: Parent(item), map(_map) {}
ConstMapIt& operator++() {
map->notifier()->next(*this);
return *this;
}
typename MapTraits<Map>::ConstReturnValue operator*() const {
return map[*this];
}
protected:
const Map* map;
};
class ItemIt : public Item {
typedef Item Parent;
public:
ItemIt() : map(NULL) {}
ItemIt(Invalid i) : Parent(i), map(NULL) {}
explicit ItemIt(Map& _map) : map(&_map) {
map->notifier()->first(*this);
}
ItemIt(const Map& _map, const Item& item)
: Parent(item), map(&_map) {}
ItemIt& operator++() {
map->notifier()->next(*this);
return *this;
}
protected:
const Map* map;
};
};
// \ingroup graphbits
//
// \brief Extender for maps which use a subset of the items.
template <typename _Graph, typename _Map>
class SubMapExtender : public _Map {
typedef _Map Parent;
typedef _Graph GraphType;
public:
typedef SubMapExtender Map;
typedef typename Parent::Key Item;
typedef typename Parent::Key Key;
typedef typename Parent::Value Value;
typedef typename Parent::Reference Reference;
typedef typename Parent::ConstReference ConstReference;
typedef typename Parent::ReferenceMapTag ReferenceMapTag;
class MapIt;
class ConstMapIt;
friend class MapIt;
friend class ConstMapIt;
public:
SubMapExtender(const GraphType& _graph)
: Parent(_graph), graph(_graph) {}
SubMapExtender(const GraphType& _graph, const Value& _value)
: Parent(_graph, _value), graph(_graph) {}
private:
SubMapExtender& operator=(const SubMapExtender& cmap) {
return operator=<MapExtender>(cmap);
}
template <typename CMap>
SubMapExtender& operator=(const CMap& cmap) {
checkConcept<concepts::ReadMap<Key, Value>, CMap>();
Item it;
for (graph.first(it); it != INVALID; graph.next(it)) {
Parent::set(it, cmap[it]);
}
return *this;
}
public:
class MapIt : public Item {
typedef Item Parent;
public:
typedef typename Map::Value Value;
MapIt() : map(NULL) {}
MapIt(Invalid i) : Parent(i), map(NULL) { }
explicit MapIt(Map& _map) : map(&_map) {
map->graph.first(*this);
}
MapIt(const Map& _map, const Item& item)
: Parent(item), map(&_map) {}
MapIt& operator++() {
map->graph.next(*this);
return *this;
}
typename MapTraits<Map>::ConstReturnValue operator*() const {
return (*map)[*this];
}
typename MapTraits<Map>::ReturnValue operator*() {
return (*map)[*this];
}
void set(const Value& value) {
map->set(*this, value);
}
protected:
Map* map;
};
class ConstMapIt : public Item {
typedef Item Parent;
public:
typedef typename Map::Value Value;
ConstMapIt() : map(NULL) {}
ConstMapIt(Invalid i) : Parent(i), map(NULL) { }
explicit ConstMapIt(Map& _map) : map(&_map) {
map->graph.first(*this);
}
ConstMapIt(const Map& _map, const Item& item)
: Parent(item), map(&_map) {}
ConstMapIt& operator++() {
map->graph.next(*this);
return *this;
}
typename MapTraits<Map>::ConstReturnValue operator*() const {
return (*map)[*this];
}
protected:
const Map* map;
};
class ItemIt : public Item {
typedef Item Parent;
public:
ItemIt() : map(NULL) {}
ItemIt(Invalid i) : Parent(i), map(NULL) { }
explicit ItemIt(Map& _map) : map(&_map) {
map->graph.first(*this);
}
ItemIt(const Map& _map, const Item& item)
: Parent(item), map(&_map) {}
ItemIt& operator++() {
map->graph.next(*this);
return *this;
}
protected:
const Map* map;
};
private:
const GraphType& graph;
};
}
#endif

View File

@@ -0,0 +1,177 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2013
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
#ifndef LEMON_BITS_PATH_DUMP_H
#define LEMON_BITS_PATH_DUMP_H
#include <lemon/core.h>
#include <lemon/concept_check.h>
namespace lemon {
template <typename _Digraph, typename _PredMap>
class PredMapPath {
public:
typedef True RevPathTag;
typedef _Digraph Digraph;
typedef typename Digraph::Arc Arc;
typedef _PredMap PredMap;
PredMapPath(const Digraph& _digraph, const PredMap& _predMap,
typename Digraph::Node _target)
: digraph(_digraph), predMap(_predMap), target(_target) {}
int length() const {
int len = 0;
typename Digraph::Node node = target;
typename Digraph::Arc arc;
while ((arc = predMap[node]) != INVALID) {
node = digraph.source(arc);
++len;
}
return len;
}
bool empty() const {
return predMap[target] == INVALID;
}
class RevArcIt {
public:
RevArcIt() {}
RevArcIt(Invalid) : path(0), current(INVALID) {}
RevArcIt(const PredMapPath& _path)
: path(&_path), current(_path.target) {
if (path->predMap[current] == INVALID) current = INVALID;
}
operator const typename Digraph::Arc() const {
return path->predMap[current];
}
RevArcIt& operator++() {
current = path->digraph.source(path->predMap[current]);
if (path->predMap[current] == INVALID) current = INVALID;
return *this;
}
bool operator==(const RevArcIt& e) const {
return current == e.current;
}
bool operator!=(const RevArcIt& e) const {
return current != e.current;
}
bool operator<(const RevArcIt& e) const {
return current < e.current;
}
private:
const PredMapPath* path;
typename Digraph::Node current;
};
private:
const Digraph& digraph;
const PredMap& predMap;
typename Digraph::Node target;
};
template <typename _Digraph, typename _PredMatrixMap>
class PredMatrixMapPath {
public:
typedef True RevPathTag;
typedef _Digraph Digraph;
typedef typename Digraph::Arc Arc;
typedef _PredMatrixMap PredMatrixMap;
PredMatrixMapPath(const Digraph& _digraph,
const PredMatrixMap& _predMatrixMap,
typename Digraph::Node _source,
typename Digraph::Node _target)
: digraph(_digraph), predMatrixMap(_predMatrixMap),
source(_source), target(_target) {}
int length() const {
int len = 0;
typename Digraph::Node node = target;
typename Digraph::Arc arc;
while ((arc = predMatrixMap(source, node)) != INVALID) {
node = digraph.source(arc);
++len;
}
return len;
}
bool empty() const {
return predMatrixMap(source, target) == INVALID;
}
class RevArcIt {
public:
RevArcIt() {}
RevArcIt(Invalid) : path(0), current(INVALID) {}
RevArcIt(const PredMatrixMapPath& _path)
: path(&_path), current(_path.target) {
if (path->predMatrixMap(path->source, current) == INVALID)
current = INVALID;
}
operator const typename Digraph::Arc() const {
return path->predMatrixMap(path->source, current);
}
RevArcIt& operator++() {
current =
path->digraph.source(path->predMatrixMap(path->source, current));
if (path->predMatrixMap(path->source, current) == INVALID)
current = INVALID;
return *this;
}
bool operator==(const RevArcIt& e) const {
return current == e.current;
}
bool operator!=(const RevArcIt& e) const {
return current != e.current;
}
bool operator<(const RevArcIt& e) const {
return current < e.current;
}
private:
const PredMatrixMapPath* path;
typename Digraph::Node current;
};
private:
const Digraph& digraph;
const PredMatrixMap& predMatrixMap;
typename Digraph::Node source;
typename Digraph::Node target;
};
}
#endif

View File

@@ -0,0 +1,194 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2013
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
#ifndef LEMON_BITS_SOLVER_BITS_H
#define LEMON_BITS_SOLVER_BITS_H
#include <vector>
namespace lemon {
namespace _solver_bits {
class VarIndex {
private:
struct ItemT {
int prev, next;
int index;
};
std::vector<ItemT> items;
int first_item, last_item, first_free_item;
std::vector<int> cross;
public:
VarIndex()
: first_item(-1), last_item(-1), first_free_item(-1) {
}
void clear() {
first_item = -1;
last_item = -1;
first_free_item = -1;
items.clear();
cross.clear();
}
int addIndex(int idx) {
int n;
if (first_free_item == -1) {
n = items.size();
items.push_back(ItemT());
} else {
n = first_free_item;
first_free_item = items[n].next;
if (first_free_item != -1) {
items[first_free_item].prev = -1;
}
}
items[n].index = idx;
if (static_cast<int>(cross.size()) <= idx) {
cross.resize(idx + 1, -1);
}
cross[idx] = n;
items[n].prev = last_item;
items[n].next = -1;
if (last_item != -1) {
items[last_item].next = n;
} else {
first_item = n;
}
last_item = n;
return n;
}
int addIndex(int idx, int n) {
while (n >= static_cast<int>(items.size())) {
items.push_back(ItemT());
items.back().prev = -1;
items.back().next = first_free_item;
if (first_free_item != -1) {
items[first_free_item].prev = items.size() - 1;
}
first_free_item = items.size() - 1;
}
if (items[n].next != -1) {
items[items[n].next].prev = items[n].prev;
}
if (items[n].prev != -1) {
items[items[n].prev].next = items[n].next;
} else {
first_free_item = items[n].next;
}
items[n].index = idx;
if (static_cast<int>(cross.size()) <= idx) {
cross.resize(idx + 1, -1);
}
cross[idx] = n;
items[n].prev = last_item;
items[n].next = -1;
if (last_item != -1) {
items[last_item].next = n;
} else {
first_item = n;
}
last_item = n;
return n;
}
void eraseIndex(int idx) {
int n = cross[idx];
if (items[n].prev != -1) {
items[items[n].prev].next = items[n].next;
} else {
first_item = items[n].next;
}
if (items[n].next != -1) {
items[items[n].next].prev = items[n].prev;
} else {
last_item = items[n].prev;
}
if (first_free_item != -1) {
items[first_free_item].prev = n;
}
items[n].next = first_free_item;
items[n].prev = -1;
first_free_item = n;
while (!cross.empty() && cross.back() == -1) {
cross.pop_back();
}
}
int maxIndex() const {
return cross.size() - 1;
}
void shiftIndices(int idx) {
for (int i = idx + 1; i < static_cast<int>(cross.size()); ++i) {
cross[i - 1] = cross[i];
if (cross[i] != -1) {
--items[cross[i]].index;
}
}
cross.back() = -1;
cross.pop_back();
while (!cross.empty() && cross.back() == -1) {
cross.pop_back();
}
}
void relocateIndex(int idx, int jdx) {
cross[idx] = cross[jdx];
items[cross[jdx]].index = idx;
cross[jdx] = -1;
while (!cross.empty() && cross.back() == -1) {
cross.pop_back();
}
}
int operator[](int idx) const {
return cross[idx];
}
int operator()(int fdx) const {
return items[fdx].index;
}
void firstItem(int& fdx) const {
fdx = first_item;
}
void nextItem(int& fdx) const {
fdx = items[fdx].next;
}
};
}
}
#endif

View File

@@ -0,0 +1,388 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2013
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
#ifndef LEMON_BITS_TRAITS_H
#define LEMON_BITS_TRAITS_H
//\file
//\brief Traits for graphs and maps
//
#include <lemon/bits/enable_if.h>
namespace lemon {
struct InvalidType {};
template <typename GR, typename _Item>
class ItemSetTraits {};
template <typename GR, typename Enable = void>
struct NodeNotifierIndicator {
typedef InvalidType Type;
};
template <typename GR>
struct NodeNotifierIndicator<
GR,
typename enable_if<typename GR::NodeNotifier::Notifier, void>::type
> {
typedef typename GR::NodeNotifier Type;
};
template <typename GR>
class ItemSetTraits<GR, typename GR::Node> {
public:
typedef GR Graph;
typedef GR Digraph;
typedef typename GR::Node Item;
typedef typename GR::NodeIt ItemIt;
typedef typename NodeNotifierIndicator<GR>::Type ItemNotifier;
template <typename V>
class Map : public GR::template NodeMap<V> {
typedef typename GR::template NodeMap<V> Parent;
public:
typedef typename GR::template NodeMap<V> Type;
typedef typename Parent::Value Value;
Map(const GR& _digraph) : Parent(_digraph) {}
Map(const GR& _digraph, const Value& _value)
: Parent(_digraph, _value) {}
};
};
template <typename GR, typename Enable = void>
struct ArcNotifierIndicator {
typedef InvalidType Type;
};
template <typename GR>
struct ArcNotifierIndicator<
GR,
typename enable_if<typename GR::ArcNotifier::Notifier, void>::type
> {
typedef typename GR::ArcNotifier Type;
};
template <typename GR>
class ItemSetTraits<GR, typename GR::Arc> {
public:
typedef GR Graph;
typedef GR Digraph;
typedef typename GR::Arc Item;
typedef typename GR::ArcIt ItemIt;
typedef typename ArcNotifierIndicator<GR>::Type ItemNotifier;
template <typename V>
class Map : public GR::template ArcMap<V> {
typedef typename GR::template ArcMap<V> Parent;
public:
typedef typename GR::template ArcMap<V> Type;
typedef typename Parent::Value Value;
Map(const GR& _digraph) : Parent(_digraph) {}
Map(const GR& _digraph, const Value& _value)
: Parent(_digraph, _value) {}
};
};
template <typename GR, typename Enable = void>
struct EdgeNotifierIndicator {
typedef InvalidType Type;
};
template <typename GR>
struct EdgeNotifierIndicator<
GR,
typename enable_if<typename GR::EdgeNotifier::Notifier, void>::type
> {
typedef typename GR::EdgeNotifier Type;
};
template <typename GR>
class ItemSetTraits<GR, typename GR::Edge> {
public:
typedef GR Graph;
typedef GR Digraph;
typedef typename GR::Edge Item;
typedef typename GR::EdgeIt ItemIt;
typedef typename EdgeNotifierIndicator<GR>::Type ItemNotifier;
template <typename V>
class Map : public GR::template EdgeMap<V> {
typedef typename GR::template EdgeMap<V> Parent;
public:
typedef typename GR::template EdgeMap<V> Type;
typedef typename Parent::Value Value;
Map(const GR& _digraph) : Parent(_digraph) {}
Map(const GR& _digraph, const Value& _value)
: Parent(_digraph, _value) {}
};
};
template <typename GR, typename Enable = void>
struct RedNodeNotifierIndicator {
typedef InvalidType Type;
};
template <typename GR>
struct RedNodeNotifierIndicator<
GR,
typename enable_if<typename GR::RedNodeNotifier::Notifier, void>::type
> {
typedef typename GR::RedNodeNotifier Type;
};
template <typename GR>
class ItemSetTraits<GR, typename GR::RedNode> {
public:
typedef GR BpGraph;
typedef GR Graph;
typedef GR Digraph;
typedef typename GR::RedNode Item;
typedef typename GR::RedNodeIt ItemIt;
typedef typename RedNodeNotifierIndicator<GR>::Type ItemNotifier;
template <typename V>
class Map : public GR::template RedNodeMap<V> {
typedef typename GR::template RedNodeMap<V> Parent;
public:
typedef typename GR::template RedNodeMap<V> Type;
typedef typename Parent::Value Value;
Map(const GR& _bpgraph) : Parent(_bpgraph) {}
Map(const GR& _bpgraph, const Value& _value)
: Parent(_bpgraph, _value) {}
};
};
template <typename GR, typename Enable = void>
struct BlueNodeNotifierIndicator {
typedef InvalidType Type;
};
template <typename GR>
struct BlueNodeNotifierIndicator<
GR,
typename enable_if<typename GR::BlueNodeNotifier::Notifier, void>::type
> {
typedef typename GR::BlueNodeNotifier Type;
};
template <typename GR>
class ItemSetTraits<GR, typename GR::BlueNode> {
public:
typedef GR BpGraph;
typedef GR Graph;
typedef GR Digraph;
typedef typename GR::BlueNode Item;
typedef typename GR::BlueNodeIt ItemIt;
typedef typename BlueNodeNotifierIndicator<GR>::Type ItemNotifier;
template <typename V>
class Map : public GR::template BlueNodeMap<V> {
typedef typename GR::template BlueNodeMap<V> Parent;
public:
typedef typename GR::template BlueNodeMap<V> Type;
typedef typename Parent::Value Value;
Map(const GR& _bpgraph) : Parent(_bpgraph) {}
Map(const GR& _bpgraph, const Value& _value)
: Parent(_bpgraph, _value) {}
};
};
template <typename Map, typename Enable = void>
struct MapTraits {
typedef False ReferenceMapTag;
typedef typename Map::Key Key;
typedef typename Map::Value Value;
typedef Value ConstReturnValue;
typedef Value ReturnValue;
};
template <typename Map>
struct MapTraits<
Map, typename enable_if<typename Map::ReferenceMapTag, void>::type >
{
typedef True ReferenceMapTag;
typedef typename Map::Key Key;
typedef typename Map::Value Value;
typedef typename Map::ConstReference ConstReturnValue;
typedef typename Map::Reference ReturnValue;
typedef typename Map::ConstReference ConstReference;
typedef typename Map::Reference Reference;
};
template <typename MatrixMap, typename Enable = void>
struct MatrixMapTraits {
typedef False ReferenceMapTag;
typedef typename MatrixMap::FirstKey FirstKey;
typedef typename MatrixMap::SecondKey SecondKey;
typedef typename MatrixMap::Value Value;
typedef Value ConstReturnValue;
typedef Value ReturnValue;
};
template <typename MatrixMap>
struct MatrixMapTraits<
MatrixMap, typename enable_if<typename MatrixMap::ReferenceMapTag,
void>::type >
{
typedef True ReferenceMapTag;
typedef typename MatrixMap::FirstKey FirstKey;
typedef typename MatrixMap::SecondKey SecondKey;
typedef typename MatrixMap::Value Value;
typedef typename MatrixMap::ConstReference ConstReturnValue;
typedef typename MatrixMap::Reference ReturnValue;
typedef typename MatrixMap::ConstReference ConstReference;
typedef typename MatrixMap::Reference Reference;
};
// Indicators for the tags
template <typename GR, typename Enable = void>
struct NodeNumTagIndicator {
static const bool value = false;
};
template <typename GR>
struct NodeNumTagIndicator<
GR,
typename enable_if<typename GR::NodeNumTag, void>::type
> {
static const bool value = true;
};
template <typename GR, typename Enable = void>
struct ArcNumTagIndicator {
static const bool value = false;
};
template <typename GR>
struct ArcNumTagIndicator<
GR,
typename enable_if<typename GR::ArcNumTag, void>::type
> {
static const bool value = true;
};
template <typename GR, typename Enable = void>
struct EdgeNumTagIndicator {
static const bool value = false;
};
template <typename GR>
struct EdgeNumTagIndicator<
GR,
typename enable_if<typename GR::EdgeNumTag, void>::type
> {
static const bool value = true;
};
template <typename GR, typename Enable = void>
struct FindArcTagIndicator {
static const bool value = false;
};
template <typename GR>
struct FindArcTagIndicator<
GR,
typename enable_if<typename GR::FindArcTag, void>::type
> {
static const bool value = true;
};
template <typename GR, typename Enable = void>
struct FindEdgeTagIndicator {
static const bool value = false;
};
template <typename GR>
struct FindEdgeTagIndicator<
GR,
typename enable_if<typename GR::FindEdgeTag, void>::type
> {
static const bool value = true;
};
template <typename GR, typename Enable = void>
struct UndirectedTagIndicator {
static const bool value = false;
};
template <typename GR>
struct UndirectedTagIndicator<
GR,
typename enable_if<typename GR::UndirectedTag, void>::type
> {
static const bool value = true;
};
template <typename GR, typename Enable = void>
struct BuildTagIndicator {
static const bool value = false;
};
template <typename GR>
struct BuildTagIndicator<
GR,
typename enable_if<typename GR::BuildTag, void>::type
> {
static const bool value = true;
};
}
#endif

View File

@@ -0,0 +1,494 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2009
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
#ifndef LEMON_BITS_VARIANT_H
#define LEMON_BITS_VARIANT_H
#include <lemon/assert.h>
// \file
// \brief Variant types
namespace lemon {
namespace _variant_bits {
template <int left, int right>
struct CTMax {
static const int value = left < right ? right : left;
};
}
// \brief Simple Variant type for two types
//
// Simple Variant type for two types. The Variant type is a type-safe
// union. C++ has strong limitations for using unions, for
// example you cannot store a type with non-default constructor or
// destructor in a union. This class always knowns the current
// state of the variant and it cares for the proper construction
// and destruction.
template <typename _First, typename _Second>
class BiVariant {
public:
// \brief The \c First type.
typedef _First First;
// \brief The \c Second type.
typedef _Second Second;
// \brief Constructor
//
// This constructor initalizes to the default value of the \c First
// type.
BiVariant() {
flag = true;
new(reinterpret_cast<First*>(data)) First();
}
// \brief Constructor
//
// This constructor initalizes to the given value of the \c First
// type.
BiVariant(const First& f) {
flag = true;
new(reinterpret_cast<First*>(data)) First(f);
}
// \brief Constructor
//
// This constructor initalizes to the given value of the \c
// Second type.
BiVariant(const Second& s) {
flag = false;
new(reinterpret_cast<Second*>(data)) Second(s);
}
// \brief Copy constructor
//
// Copy constructor
BiVariant(const BiVariant& bivariant) {
flag = bivariant.flag;
if (flag) {
new(reinterpret_cast<First*>(data)) First(bivariant.first());
} else {
new(reinterpret_cast<Second*>(data)) Second(bivariant.second());
}
}
// \brief Destrcutor
//
// Destructor
~BiVariant() {
destroy();
}
// \brief Set to the default value of the \c First type.
//
// This function sets the variant to the default value of the \c
// First type.
BiVariant& setFirst() {
destroy();
flag = true;
new(reinterpret_cast<First*>(data)) First();
return *this;
}
// \brief Set to the given value of the \c First type.
//
// This function sets the variant to the given value of the \c
// First type.
BiVariant& setFirst(const First& f) {
destroy();
flag = true;
new(reinterpret_cast<First*>(data)) First(f);
return *this;
}
// \brief Set to the default value of the \c Second type.
//
// This function sets the variant to the default value of the \c
// Second type.
BiVariant& setSecond() {
destroy();
flag = false;
new(reinterpret_cast<Second*>(data)) Second();
return *this;
}
// \brief Set to the given value of the \c Second type.
//
// This function sets the variant to the given value of the \c
// Second type.
BiVariant& setSecond(const Second& s) {
destroy();
flag = false;
new(reinterpret_cast<Second*>(data)) Second(s);
return *this;
}
// \brief Operator form of the \c setFirst()
BiVariant& operator=(const First& f) {
return setFirst(f);
}
// \brief Operator form of the \c setSecond()
BiVariant& operator=(const Second& s) {
return setSecond(s);
}
// \brief Assign operator
BiVariant& operator=(const BiVariant& bivariant) {
if (this == &bivariant) return *this;
destroy();
flag = bivariant.flag;
if (flag) {
new(reinterpret_cast<First*>(data)) First(bivariant.first());
} else {
new(reinterpret_cast<Second*>(data)) Second(bivariant.second());
}
return *this;
}
// \brief Reference to the value
//
// Reference to the value of the \c First type.
// \pre The BiVariant should store value of \c First type.
First& first() {
LEMON_DEBUG(flag, "Variant wrong state");
return *reinterpret_cast<First*>(data);
}
// \brief Const reference to the value
//
// Const reference to the value of the \c First type.
// \pre The BiVariant should store value of \c First type.
const First& first() const {
LEMON_DEBUG(flag, "Variant wrong state");
return *reinterpret_cast<const First*>(data);
}
// \brief Operator form of the \c first()
operator First&() { return first(); }
// \brief Operator form of the const \c first()
operator const First&() const { return first(); }
// \brief Reference to the value
//
// Reference to the value of the \c Second type.
// \pre The BiVariant should store value of \c Second type.
Second& second() {
LEMON_DEBUG(!flag, "Variant wrong state");
return *reinterpret_cast<Second*>(data);
}
// \brief Const reference to the value
//
// Const reference to the value of the \c Second type.
// \pre The BiVariant should store value of \c Second type.
const Second& second() const {
LEMON_DEBUG(!flag, "Variant wrong state");
return *reinterpret_cast<const Second*>(data);
}
// \brief Operator form of the \c second()
operator Second&() { return second(); }
// \brief Operator form of the const \c second()
operator const Second&() const { return second(); }
// \brief %True when the variant is in the first state
//
// %True when the variant stores value of the \c First type.
bool firstState() const { return flag; }
// \brief %True when the variant is in the second state
//
// %True when the variant stores value of the \c Second type.
bool secondState() const { return !flag; }
private:
void destroy() {
if (flag) {
reinterpret_cast<First*>(data)->~First();
} else {
reinterpret_cast<Second*>(data)->~Second();
}
}
char data[_variant_bits::CTMax<sizeof(First), sizeof(Second)>::value];
bool flag;
};
namespace _variant_bits {
template <int _idx, typename _TypeMap>
struct Memory {
typedef typename _TypeMap::template Map<_idx>::Type Current;
static void destroy(int index, char* place) {
if (index == _idx) {
reinterpret_cast<Current*>(place)->~Current();
} else {
Memory<_idx - 1, _TypeMap>::destroy(index, place);
}
}
static void copy(int index, char* to, const char* from) {
if (index == _idx) {
new (reinterpret_cast<Current*>(to))
Current(reinterpret_cast<const Current*>(from));
} else {
Memory<_idx - 1, _TypeMap>::copy(index, to, from);
}
}
};
template <typename _TypeMap>
struct Memory<-1, _TypeMap> {
static void destroy(int, char*) {
LEMON_DEBUG(false, "Variant wrong index.");
}
static void copy(int, char*, const char*) {
LEMON_DEBUG(false, "Variant wrong index.");
}
};
template <int _idx, typename _TypeMap>
struct Size {
static const int value =
CTMax<sizeof(typename _TypeMap::template Map<_idx>::Type),
Size<_idx - 1, _TypeMap>::value>::value;
};
template <typename _TypeMap>
struct Size<0, _TypeMap> {
static const int value =
sizeof(typename _TypeMap::template Map<0>::Type);
};
}
// \brief Variant type
//
// Simple Variant type. The Variant type is a type-safe union.
// C++ has strong limitations for using unions, for example you
// cannot store type with non-default constructor or destructor in
// a union. This class always knowns the current state of the
// variant and it cares for the proper construction and
// destruction.
//
// \param _num The number of the types which can be stored in the
// variant type.
// \param _TypeMap This class describes the types of the Variant. The
// _TypeMap::Map<index>::Type should be a valid type for each index
// in the range {0, 1, ..., _num - 1}. The \c VariantTypeMap is helper
// class to define such type mappings up to 10 types.
//
// And the usage of the class:
//\code
// typedef Variant<3, VariantTypeMap<int, std::string, double> > MyVariant;
// MyVariant var;
// var.set<0>(12);
// std::cout << var.get<0>() << std::endl;
// var.set<1>("alpha");
// std::cout << var.get<1>() << std::endl;
// var.set<2>(0.75);
// std::cout << var.get<2>() << std::endl;
//\endcode
//
// The result of course:
//\code
// 12
// alpha
// 0.75
//\endcode
template <int _num, typename _TypeMap>
class Variant {
public:
static const int num = _num;
typedef _TypeMap TypeMap;
// \brief Constructor
//
// This constructor initalizes to the default value of the \c type
// with 0 index.
Variant() {
flag = 0;
new(reinterpret_cast<typename TypeMap::template Map<0>::Type*>(data))
typename TypeMap::template Map<0>::Type();
}
// \brief Copy constructor
//
// Copy constructor
Variant(const Variant& variant) {
flag = variant.flag;
_variant_bits::Memory<num - 1, TypeMap>::copy(flag, data, variant.data);
}
// \brief Assign operator
//
// Assign operator
Variant& operator=(const Variant& variant) {
if (this == &variant) return *this;
_variant_bits::Memory<num - 1, TypeMap>::
destroy(flag, data);
flag = variant.flag;
_variant_bits::Memory<num - 1, TypeMap>::
copy(flag, data, variant.data);
return *this;
}
// \brief Destrcutor
//
// Destructor
~Variant() {
_variant_bits::Memory<num - 1, TypeMap>::destroy(flag, data);
}
// \brief Set to the default value of the type with \c _idx index.
//
// This function sets the variant to the default value of the
// type with \c _idx index.
template <int _idx>
Variant& set() {
_variant_bits::Memory<num - 1, TypeMap>::destroy(flag, data);
flag = _idx;
new(reinterpret_cast<typename TypeMap::template Map<_idx>::Type*>(data))
typename TypeMap::template Map<_idx>::Type();
return *this;
}
// \brief Set to the given value of the type with \c _idx index.
//
// This function sets the variant to the given value of the type
// with \c _idx index.
template <int _idx>
Variant& set(const typename _TypeMap::template Map<_idx>::Type& init) {
_variant_bits::Memory<num - 1, TypeMap>::destroy(flag, data);
flag = _idx;
new(reinterpret_cast<typename TypeMap::template Map<_idx>::Type*>(data))
typename TypeMap::template Map<_idx>::Type(init);
return *this;
}
// \brief Gets the current value of the type with \c _idx index.
//
// Gets the current value of the type with \c _idx index.
template <int _idx>
const typename TypeMap::template Map<_idx>::Type& get() const {
LEMON_DEBUG(_idx == flag, "Variant wrong index");
return *reinterpret_cast<const typename TypeMap::
template Map<_idx>::Type*>(data);
}
// \brief Gets the current value of the type with \c _idx index.
//
// Gets the current value of the type with \c _idx index.
template <int _idx>
typename _TypeMap::template Map<_idx>::Type& get() {
LEMON_DEBUG(_idx == flag, "Variant wrong index");
return *reinterpret_cast<typename TypeMap::template Map<_idx>::Type*>
(data);
}
// \brief Returns the current state of the variant.
//
// Returns the current state of the variant.
int state() const {
return flag;
}
private:
char data[_variant_bits::Size<num - 1, TypeMap>::value];
int flag;
};
namespace _variant_bits {
template <int _index, typename _List>
struct Get {
typedef typename Get<_index - 1, typename _List::Next>::Type Type;
};
template <typename _List>
struct Get<0, _List> {
typedef typename _List::Type Type;
};
struct List {};
template <typename _Type, typename _List>
struct Insert {
typedef _List Next;
typedef _Type Type;
};
template <int _idx, typename _T0, typename _T1, typename _T2,
typename _T3, typename _T4, typename _T5, typename _T6,
typename _T7, typename _T8, typename _T9>
struct Mapper {
typedef List L10;
typedef Insert<_T9, L10> L9;
typedef Insert<_T8, L9> L8;
typedef Insert<_T7, L8> L7;
typedef Insert<_T6, L7> L6;
typedef Insert<_T5, L6> L5;
typedef Insert<_T4, L5> L4;
typedef Insert<_T3, L4> L3;
typedef Insert<_T2, L3> L2;
typedef Insert<_T1, L2> L1;
typedef Insert<_T0, L1> L0;
typedef typename Get<_idx, L0>::Type Type;
};
}
// \brief Helper class for Variant
//
// Helper class to define type mappings for Variant. This class
// converts the template parameters to be mappable by integer.
// \see Variant
template <
typename _T0,
typename _T1 = void, typename _T2 = void, typename _T3 = void,
typename _T4 = void, typename _T5 = void, typename _T6 = void,
typename _T7 = void, typename _T8 = void, typename _T9 = void>
struct VariantTypeMap {
template <int _idx>
struct Map {
typedef typename _variant_bits::
Mapper<_idx, _T0, _T1, _T2, _T3, _T4, _T5, _T6, _T7, _T8, _T9>::Type
Type;
};
};
}
#endif

View File

@@ -0,0 +1,244 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2009
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
#ifndef LEMON_BITS_VECTOR_MAP_H
#define LEMON_BITS_VECTOR_MAP_H
#include <vector>
#include <algorithm>
#include <lemon/core.h>
#include <lemon/bits/alteration_notifier.h>
#include <lemon/concept_check.h>
#include <lemon/concepts/maps.h>
//\ingroup graphbits
//
//\file
//\brief Vector based graph maps.
namespace lemon {
// \ingroup graphbits
//
// \brief Graph map based on the std::vector storage.
//
// The VectorMap template class is graph map structure that automatically
// updates the map when a key is added to or erased from the graph.
// This map type uses std::vector to store the values.
//
// \tparam _Graph The graph this map is attached to.
// \tparam _Item The item type of the graph items.
// \tparam _Value The value type of the map.
template <typename _Graph, typename _Item, typename _Value>
class VectorMap
: public ItemSetTraits<_Graph, _Item>::ItemNotifier::ObserverBase {
private:
// The container type of the map.
typedef std::vector<_Value> Container;
public:
// The graph type of the map.
typedef _Graph GraphType;
// The item type of the map.
typedef _Item Item;
// The reference map tag.
typedef True ReferenceMapTag;
// The key type of the map.
typedef _Item Key;
// The value type of the map.
typedef _Value Value;
// The notifier type.
typedef typename ItemSetTraits<_Graph, _Item>::ItemNotifier Notifier;
// The map type.
typedef VectorMap Map;
// The reference type of the map;
typedef typename Container::reference Reference;
// The const reference type of the map;
typedef typename Container::const_reference ConstReference;
private:
// The base class of the map.
typedef typename Notifier::ObserverBase Parent;
public:
// \brief Constructor to attach the new map into the notifier.
//
// It constructs a map and attachs it into the notifier.
// It adds all the items of the graph to the map.
VectorMap(const GraphType& graph) {
Parent::attach(graph.notifier(Item()));
container.resize(Parent::notifier()->maxId() + 1);
}
// \brief Constructor uses given value to initialize the map.
//
// It constructs a map uses a given value to initialize the map.
// It adds all the items of the graph to the map.
VectorMap(const GraphType& graph, const Value& value) {
Parent::attach(graph.notifier(Item()));
container.resize(Parent::notifier()->maxId() + 1, value);
}
private:
// \brief Copy constructor
//
// Copy constructor.
VectorMap(const VectorMap& _copy) : Parent() {
if (_copy.attached()) {
Parent::attach(*_copy.notifier());
container = _copy.container;
}
}
// \brief Assign operator.
//
// This operator assigns for each item in the map the
// value mapped to the same item in the copied map.
// The parameter map should be indiced with the same
// itemset because this assign operator does not change
// the container of the map.
VectorMap& operator=(const VectorMap& cmap) {
return operator=<VectorMap>(cmap);
}
// \brief Template assign operator.
//
// The given parameter should conform to the ReadMap
// concecpt and could be indiced by the current item set of
// the NodeMap. In this case the value for each item
// is assigned by the value of the given ReadMap.
template <typename CMap>
VectorMap& operator=(const CMap& cmap) {
checkConcept<concepts::ReadMap<Key, _Value>, CMap>();
const typename Parent::Notifier* nf = Parent::notifier();
Item it;
for (nf->first(it); it != INVALID; nf->next(it)) {
set(it, cmap[it]);
}
return *this;
}
public:
// \brief The subcript operator.
//
// The subscript operator. The map can be subscripted by the
// actual items of the graph.
Reference operator[](const Key& key) {
return container[Parent::notifier()->id(key)];
}
// \brief The const subcript operator.
//
// The const subscript operator. The map can be subscripted by the
// actual items of the graph.
ConstReference operator[](const Key& key) const {
return container[Parent::notifier()->id(key)];
}
// \brief The setter function of the map.
//
// It the same as operator[](key) = value expression.
void set(const Key& key, const Value& value) {
(*this)[key] = value;
}
protected:
// \brief Adds a new key to the map.
//
// It adds a new key to the map. It is called by the observer notifier
// and it overrides the add() member function of the observer base.
virtual void add(const Key& key) {
int id = Parent::notifier()->id(key);
if (id >= int(container.size())) {
container.resize(id + 1);
}
}
// \brief Adds more new keys to the map.
//
// It adds more new keys to the map. It is called by the observer notifier
// and it overrides the add() member function of the observer base.
virtual void add(const std::vector<Key>& keys) {
int max = container.size() - 1;
for (int i = 0; i < int(keys.size()); ++i) {
int id = Parent::notifier()->id(keys[i]);
if (id >= max) {
max = id;
}
}
container.resize(max + 1);
}
// \brief Erase a key from the map.
//
// Erase a key from the map. It is called by the observer notifier
// and it overrides the erase() member function of the observer base.
virtual void erase(const Key& key) {
container[Parent::notifier()->id(key)] = Value();
}
// \brief Erase more keys from the map.
//
// It erases more keys from the map. It is called by the observer notifier
// and it overrides the erase() member function of the observer base.
virtual void erase(const std::vector<Key>& keys) {
for (int i = 0; i < int(keys.size()); ++i) {
container[Parent::notifier()->id(keys[i])] = Value();
}
}
// \brief Build the map.
//
// It builds the map. It is called by the observer notifier
// and it overrides the build() member function of the observer base.
virtual void build() {
int size = Parent::notifier()->maxId() + 1;
container.reserve(size);
container.resize(size);
}
// \brief Clear the map.
//
// It erases all items from the map. It is called by the observer notifier
// and it overrides the clear() member function of the observer base.
virtual void clear() {
container.clear();
}
private:
Container container;
};
}
#endif

View File

@@ -0,0 +1,166 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2013
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
///\file
///\brief Some basic non-inline functions and static global data.
#include<lemon/bits/windows.h>
#ifdef WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#ifndef NOMINMAX
#define NOMINMAX
#endif
#ifdef UNICODE
#undef UNICODE
#endif
#include <windows.h>
#ifdef LOCALE_INVARIANT
#define MY_LOCALE LOCALE_INVARIANT
#else
#define MY_LOCALE LOCALE_NEUTRAL
#endif
#else
#include <unistd.h>
#include <ctime>
#ifndef WIN32
#include <sys/times.h>
#endif
#include <sys/time.h>
#endif
#include <cmath>
#include <sstream>
namespace lemon {
namespace bits {
void getWinProcTimes(double &rtime,
double &utime, double &stime,
double &cutime, double &cstime)
{
#ifdef WIN32
static const double ch = 4294967296.0e-7;
static const double cl = 1.0e-7;
FILETIME system;
GetSystemTimeAsFileTime(&system);
rtime = ch * system.dwHighDateTime + cl * system.dwLowDateTime;
FILETIME create, exit, kernel, user;
if (GetProcessTimes(GetCurrentProcess(),&create, &exit, &kernel, &user)) {
utime = ch * user.dwHighDateTime + cl * user.dwLowDateTime;
stime = ch * kernel.dwHighDateTime + cl * kernel.dwLowDateTime;
cutime = 0;
cstime = 0;
} else {
rtime = 0;
utime = 0;
stime = 0;
cutime = 0;
cstime = 0;
}
#else
timeval tv;
gettimeofday(&tv, 0);
rtime=tv.tv_sec+double(tv.tv_usec)/1e6;
tms ts;
double tck=sysconf(_SC_CLK_TCK);
times(&ts);
utime=ts.tms_utime/tck;
stime=ts.tms_stime/tck;
cutime=ts.tms_cutime/tck;
cstime=ts.tms_cstime/tck;
#endif
}
std::string getWinFormattedDate()
{
std::ostringstream os;
#ifdef WIN32
SYSTEMTIME time;
GetSystemTime(&time);
char buf1[11], buf2[9], buf3[5];
if (GetDateFormat(MY_LOCALE, 0, &time,
("ddd MMM dd"), buf1, 11) &&
GetTimeFormat(MY_LOCALE, 0, &time,
("HH':'mm':'ss"), buf2, 9) &&
GetDateFormat(MY_LOCALE, 0, &time,
("yyyy"), buf3, 5)) {
os << buf1 << ' ' << buf2 << ' ' << buf3;
}
else os << "unknown";
#else
timeval tv;
gettimeofday(&tv, 0);
char cbuf[26];
ctime_r(&tv.tv_sec,cbuf);
os << cbuf;
#endif
return os.str();
}
int getWinRndSeed()
{
#ifdef WIN32
FILETIME time;
GetSystemTimeAsFileTime(&time);
return GetCurrentProcessId() + time.dwHighDateTime + time.dwLowDateTime;
#else
timeval tv;
gettimeofday(&tv, 0);
return getpid() + tv.tv_sec + tv.tv_usec;
#endif
}
WinLock::WinLock() {
#ifdef WIN32
CRITICAL_SECTION *lock = new CRITICAL_SECTION;
InitializeCriticalSection(lock);
_repr = lock;
#else
_repr = 0; //Just to avoid 'unused variable' warning with clang
#endif
}
WinLock::~WinLock() {
#ifdef WIN32
CRITICAL_SECTION *lock = static_cast<CRITICAL_SECTION*>(_repr);
DeleteCriticalSection(lock);
delete lock;
#endif
}
void WinLock::lock() {
#ifdef WIN32
CRITICAL_SECTION *lock = static_cast<CRITICAL_SECTION*>(_repr);
EnterCriticalSection(lock);
#endif
}
void WinLock::unlock() {
#ifdef WIN32
CRITICAL_SECTION *lock = static_cast<CRITICAL_SECTION*>(_repr);
LeaveCriticalSection(lock);
#endif
}
}
}

View File

@@ -0,0 +1,44 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2013
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
#ifndef LEMON_BITS_WINDOWS_H
#define LEMON_BITS_WINDOWS_H
#include <string>
namespace lemon {
namespace bits {
void getWinProcTimes(double &rtime,
double &utime, double &stime,
double &cutime, double &cstime);
std::string getWinFormattedDate();
int getWinRndSeed();
class WinLock {
public:
WinLock();
~WinLock();
void lock();
void unlock();
private:
void *_repr;
};
}
}
#endif

View File

@@ -0,0 +1,594 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2010
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
#ifndef LEMON_BUCKET_HEAP_H
#define LEMON_BUCKET_HEAP_H
///\ingroup heaps
///\file
///\brief Bucket heap implementation.
#include <vector>
#include <utility>
#include <functional>
namespace lemon {
namespace _bucket_heap_bits {
template <bool MIN>
struct DirectionTraits {
static bool less(int left, int right) {
return left < right;
}
static void increase(int& value) {
++value;
}
};
template <>
struct DirectionTraits<false> {
static bool less(int left, int right) {
return left > right;
}
static void increase(int& value) {
--value;
}
};
}
/// \ingroup heaps
///
/// \brief Bucket heap data structure.
///
/// This class implements the \e bucket \e heap data structure.
/// It practically conforms to the \ref concepts::Heap "heap concept",
/// but it has some limitations.
///
/// The bucket heap is a very simple structure. It can store only
/// \c int priorities and it maintains a list of items for each priority
/// in the range <tt>[0..C)</tt>. So it should only be used when the
/// priorities are small. It is not intended to use as a Dijkstra heap.
///
/// \tparam IM A read-writable item map with \c int values, used
/// internally to handle the cross references.
/// \tparam MIN Indicate if the heap is a \e min-heap or a \e max-heap.
/// The default is \e min-heap. If this parameter is set to \c false,
/// then the comparison is reversed, so the top(), prio() and pop()
/// functions deal with the item having maximum priority instead of the
/// minimum.
///
/// \sa SimpleBucketHeap
template <typename IM, bool MIN = true>
class BucketHeap {
public:
/// Type of the item-int map.
typedef IM ItemIntMap;
/// Type of the priorities.
typedef int Prio;
/// Type of the items stored in the heap.
typedef typename ItemIntMap::Key Item;
/// Type of the item-priority pairs.
typedef std::pair<Item,Prio> Pair;
private:
typedef _bucket_heap_bits::DirectionTraits<MIN> Direction;
public:
/// \brief Type to represent the states of the items.
///
/// Each item has a state associated to it. It can be "in heap",
/// "pre-heap" or "post-heap". The latter two are indifferent from the
/// heap's point of view, but may be useful to the user.
///
/// The item-int map must be initialized in such way that it assigns
/// \c PRE_HEAP (<tt>-1</tt>) to any element to be put in the heap.
enum State {
IN_HEAP = 0, ///< = 0.
PRE_HEAP = -1, ///< = -1.
POST_HEAP = -2 ///< = -2.
};
public:
/// \brief Constructor.
///
/// Constructor.
/// \param map A map that assigns \c int values to the items.
/// It is used internally to handle the cross references.
/// The assigned value must be \c PRE_HEAP (<tt>-1</tt>) for each item.
explicit BucketHeap(ItemIntMap &map) : _iim(map), _minimum(0) {}
/// \brief The number of items stored in the heap.
///
/// This function returns the number of items stored in the heap.
int size() const { return _data.size(); }
/// \brief Check if the heap is empty.
///
/// This function returns \c true if the heap is empty.
bool empty() const { return _data.empty(); }
/// \brief Make the heap empty.
///
/// This functon makes the heap empty.
/// It does not change the cross reference map. If you want to reuse
/// a heap that is not surely empty, you should first clear it and
/// then you should set the cross reference map to \c PRE_HEAP
/// for each item.
void clear() {
_data.clear(); _first.clear(); _minimum = 0;
}
private:
void relocateLast(int idx) {
if (idx + 1 < int(_data.size())) {
_data[idx] = _data.back();
if (_data[idx].prev != -1) {
_data[_data[idx].prev].next = idx;
} else {
_first[_data[idx].value] = idx;
}
if (_data[idx].next != -1) {
_data[_data[idx].next].prev = idx;
}
_iim[_data[idx].item] = idx;
}
_data.pop_back();
}
void unlace(int idx) {
if (_data[idx].prev != -1) {
_data[_data[idx].prev].next = _data[idx].next;
} else {
_first[_data[idx].value] = _data[idx].next;
}
if (_data[idx].next != -1) {
_data[_data[idx].next].prev = _data[idx].prev;
}
}
void lace(int idx) {
if (int(_first.size()) <= _data[idx].value) {
_first.resize(_data[idx].value + 1, -1);
}
_data[idx].next = _first[_data[idx].value];
if (_data[idx].next != -1) {
_data[_data[idx].next].prev = idx;
}
_first[_data[idx].value] = idx;
_data[idx].prev = -1;
}
public:
/// \brief Insert a pair of item and priority into the heap.
///
/// This function inserts \c p.first to the heap with priority
/// \c p.second.
/// \param p The pair to insert.
/// \pre \c p.first must not be stored in the heap.
void push(const Pair& p) {
push(p.first, p.second);
}
/// \brief Insert an item into the heap with the given priority.
///
/// This function inserts the given item into the heap with the
/// given priority.
/// \param i The item to insert.
/// \param p The priority of the item.
/// \pre \e i must not be stored in the heap.
void push(const Item &i, const Prio &p) {
int idx = _data.size();
_iim[i] = idx;
_data.push_back(BucketItem(i, p));
lace(idx);
if (Direction::less(p, _minimum)) {
_minimum = p;
}
}
/// \brief Return the item having minimum priority.
///
/// This function returns the item having minimum priority.
/// \pre The heap must be non-empty.
Item top() const {
while (_first[_minimum] == -1) {
Direction::increase(_minimum);
}
return _data[_first[_minimum]].item;
}
/// \brief The minimum priority.
///
/// This function returns the minimum priority.
/// \pre The heap must be non-empty.
Prio prio() const {
while (_first[_minimum] == -1) {
Direction::increase(_minimum);
}
return _minimum;
}
/// \brief Remove the item having minimum priority.
///
/// This function removes the item having minimum priority.
/// \pre The heap must be non-empty.
void pop() {
while (_first[_minimum] == -1) {
Direction::increase(_minimum);
}
int idx = _first[_minimum];
_iim[_data[idx].item] = -2;
unlace(idx);
relocateLast(idx);
}
/// \brief Remove the given item from the heap.
///
/// This function removes the given item from the heap if it is
/// already stored.
/// \param i The item to delete.
/// \pre \e i must be in the heap.
void erase(const Item &i) {
int idx = _iim[i];
_iim[_data[idx].item] = -2;
unlace(idx);
relocateLast(idx);
}
/// \brief The priority of the given item.
///
/// This function returns the priority of the given item.
/// \param i The item.
/// \pre \e i must be in the heap.
Prio operator[](const Item &i) const {
int idx = _iim[i];
return _data[idx].value;
}
/// \brief Set the priority of an item or insert it, if it is
/// not stored in the heap.
///
/// This method sets the priority of the given item if it is
/// already stored in the heap. Otherwise it inserts the given
/// item into the heap with the given priority.
/// \param i The item.
/// \param p The priority.
void set(const Item &i, const Prio &p) {
int idx = _iim[i];
if (idx < 0) {
push(i, p);
} else if (Direction::less(p, _data[idx].value)) {
decrease(i, p);
} else {
increase(i, p);
}
}
/// \brief Decrease the priority of an item to the given value.
///
/// This function decreases the priority of an item to the given value.
/// \param i The item.
/// \param p The priority.
/// \pre \e i must be stored in the heap with priority at least \e p.
void decrease(const Item &i, const Prio &p) {
int idx = _iim[i];
unlace(idx);
_data[idx].value = p;
if (Direction::less(p, _minimum)) {
_minimum = p;
}
lace(idx);
}
/// \brief Increase the priority of an item to the given value.
///
/// This function increases the priority of an item to the given value.
/// \param i The item.
/// \param p The priority.
/// \pre \e i must be stored in the heap with priority at most \e p.
void increase(const Item &i, const Prio &p) {
int idx = _iim[i];
unlace(idx);
_data[idx].value = p;
lace(idx);
}
/// \brief Return the state of an item.
///
/// This method returns \c PRE_HEAP if the given item has never
/// been in the heap, \c IN_HEAP if it is in the heap at the moment,
/// and \c POST_HEAP otherwise.
/// In the latter case it is possible that the item will get back
/// to the heap again.
/// \param i The item.
State state(const Item &i) const {
int idx = _iim[i];
if (idx >= 0) idx = 0;
return State(idx);
}
/// \brief Set the state of an item in the heap.
///
/// This function sets the state of the given item in the heap.
/// It can be used to manually clear the heap when it is important
/// to achive better time complexity.
/// \param i The item.
/// \param st The state. It should not be \c IN_HEAP.
void state(const Item& i, State st) {
switch (st) {
case POST_HEAP:
case PRE_HEAP:
if (state(i) == IN_HEAP) {
erase(i);
}
_iim[i] = st;
break;
case IN_HEAP:
break;
}
}
private:
struct BucketItem {
BucketItem(const Item& _item, int _value)
: item(_item), value(_value) {}
Item item;
int value;
int prev, next;
};
ItemIntMap& _iim;
std::vector<int> _first;
std::vector<BucketItem> _data;
mutable int _minimum;
}; // class BucketHeap
/// \ingroup heaps
///
/// \brief Simplified bucket heap data structure.
///
/// This class implements a simplified \e bucket \e heap data
/// structure. It does not provide some functionality, but it is
/// faster and simpler than BucketHeap. The main difference is
/// that BucketHeap stores a doubly-linked list for each key while
/// this class stores only simply-linked lists. It supports erasing
/// only for the item having minimum priority and it does not support
/// key increasing and decreasing.
///
/// Note that this implementation does not conform to the
/// \ref concepts::Heap "heap concept" due to the lack of some
/// functionality.
///
/// \tparam IM A read-writable item map with \c int values, used
/// internally to handle the cross references.
/// \tparam MIN Indicate if the heap is a \e min-heap or a \e max-heap.
/// The default is \e min-heap. If this parameter is set to \c false,
/// then the comparison is reversed, so the top(), prio() and pop()
/// functions deal with the item having maximum priority instead of the
/// minimum.
///
/// \sa BucketHeap
template <typename IM, bool MIN = true >
class SimpleBucketHeap {
public:
/// Type of the item-int map.
typedef IM ItemIntMap;
/// Type of the priorities.
typedef int Prio;
/// Type of the items stored in the heap.
typedef typename ItemIntMap::Key Item;
/// Type of the item-priority pairs.
typedef std::pair<Item,Prio> Pair;
private:
typedef _bucket_heap_bits::DirectionTraits<MIN> Direction;
public:
/// \brief Type to represent the states of the items.
///
/// Each item has a state associated to it. It can be "in heap",
/// "pre-heap" or "post-heap". The latter two are indifferent from the
/// heap's point of view, but may be useful to the user.
///
/// The item-int map must be initialized in such way that it assigns
/// \c PRE_HEAP (<tt>-1</tt>) to any element to be put in the heap.
enum State {
IN_HEAP = 0, ///< = 0.
PRE_HEAP = -1, ///< = -1.
POST_HEAP = -2 ///< = -2.
};
public:
/// \brief Constructor.
///
/// Constructor.
/// \param map A map that assigns \c int values to the items.
/// It is used internally to handle the cross references.
/// The assigned value must be \c PRE_HEAP (<tt>-1</tt>) for each item.
explicit SimpleBucketHeap(ItemIntMap &map)
: _iim(map), _free(-1), _num(0), _minimum(0) {}
/// \brief The number of items stored in the heap.
///
/// This function returns the number of items stored in the heap.
int size() const { return _num; }
/// \brief Check if the heap is empty.
///
/// This function returns \c true if the heap is empty.
bool empty() const { return _num == 0; }
/// \brief Make the heap empty.
///
/// This functon makes the heap empty.
/// It does not change the cross reference map. If you want to reuse
/// a heap that is not surely empty, you should first clear it and
/// then you should set the cross reference map to \c PRE_HEAP
/// for each item.
void clear() {
_data.clear(); _first.clear(); _free = -1; _num = 0; _minimum = 0;
}
/// \brief Insert a pair of item and priority into the heap.
///
/// This function inserts \c p.first to the heap with priority
/// \c p.second.
/// \param p The pair to insert.
/// \pre \c p.first must not be stored in the heap.
void push(const Pair& p) {
push(p.first, p.second);
}
/// \brief Insert an item into the heap with the given priority.
///
/// This function inserts the given item into the heap with the
/// given priority.
/// \param i The item to insert.
/// \param p The priority of the item.
/// \pre \e i must not be stored in the heap.
void push(const Item &i, const Prio &p) {
int idx;
if (_free == -1) {
idx = _data.size();
_data.push_back(BucketItem(i));
} else {
idx = _free;
_free = _data[idx].next;
_data[idx].item = i;
}
_iim[i] = idx;
if (p >= int(_first.size())) _first.resize(p + 1, -1);
_data[idx].next = _first[p];
_first[p] = idx;
if (Direction::less(p, _minimum)) {
_minimum = p;
}
++_num;
}
/// \brief Return the item having minimum priority.
///
/// This function returns the item having minimum priority.
/// \pre The heap must be non-empty.
Item top() const {
while (_first[_minimum] == -1) {
Direction::increase(_minimum);
}
return _data[_first[_minimum]].item;
}
/// \brief The minimum priority.
///
/// This function returns the minimum priority.
/// \pre The heap must be non-empty.
Prio prio() const {
while (_first[_minimum] == -1) {
Direction::increase(_minimum);
}
return _minimum;
}
/// \brief Remove the item having minimum priority.
///
/// This function removes the item having minimum priority.
/// \pre The heap must be non-empty.
void pop() {
while (_first[_minimum] == -1) {
Direction::increase(_minimum);
}
int idx = _first[_minimum];
_iim[_data[idx].item] = -2;
_first[_minimum] = _data[idx].next;
_data[idx].next = _free;
_free = idx;
--_num;
}
/// \brief The priority of the given item.
///
/// This function returns the priority of the given item.
/// \param i The item.
/// \pre \e i must be in the heap.
/// \warning This operator is not a constant time function because
/// it scans the whole data structure to find the proper value.
Prio operator[](const Item &i) const {
for (int k = 0; k < int(_first.size()); ++k) {
int idx = _first[k];
while (idx != -1) {
if (_data[idx].item == i) {
return k;
}
idx = _data[idx].next;
}
}
return -1;
}
/// \brief Return the state of an item.
///
/// This method returns \c PRE_HEAP if the given item has never
/// been in the heap, \c IN_HEAP if it is in the heap at the moment,
/// and \c POST_HEAP otherwise.
/// In the latter case it is possible that the item will get back
/// to the heap again.
/// \param i The item.
State state(const Item &i) const {
int idx = _iim[i];
if (idx >= 0) idx = 0;
return State(idx);
}
private:
struct BucketItem {
BucketItem(const Item& _item)
: item(_item) {}
Item item;
int next;
};
ItemIntMap& _iim;
std::vector<int> _first;
std::vector<BucketItem> _data;
int _free, _num;
mutable int _minimum;
}; // class SimpleBucketHeap
}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,460 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2013
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
///\file
///\brief Implementation of the CBC MIP solver interface.
#include "cbc.h"
#include <coin/CoinModel.hpp>
#include <coin/CbcModel.hpp>
#include <coin/OsiSolverInterface.hpp>
#include "coin/OsiClpSolverInterface.hpp"
#include "coin/CbcCutGenerator.hpp"
#include "coin/CbcHeuristicLocal.hpp"
#include "coin/CbcHeuristicGreedy.hpp"
#include "coin/CbcHeuristicFPump.hpp"
#include "coin/CbcHeuristicRINS.hpp"
#include "coin/CglGomory.hpp"
#include "coin/CglProbing.hpp"
#include "coin/CglKnapsackCover.hpp"
#include "coin/CglOddHole.hpp"
#include "coin/CglClique.hpp"
#include "coin/CglFlowCover.hpp"
#include "coin/CglMixedIntegerRounding.hpp"
#include "coin/CbcHeuristic.hpp"
namespace lemon {
CbcMip::CbcMip() {
_prob = new CoinModel();
_prob->setProblemName("LEMON");
_osi_solver = 0;
_cbc_model = 0;
messageLevel(MESSAGE_NOTHING);
}
CbcMip::CbcMip(const CbcMip& other) {
_prob = new CoinModel(*other._prob);
_prob->setProblemName("LEMON");
_osi_solver = 0;
_cbc_model = 0;
messageLevel(MESSAGE_NOTHING);
}
CbcMip::~CbcMip() {
delete _prob;
if (_osi_solver) delete _osi_solver;
if (_cbc_model) delete _cbc_model;
}
const char* CbcMip::_solverName() const { return "CbcMip"; }
int CbcMip::_addCol() {
_prob->addColumn(0, 0, 0, -COIN_DBL_MAX, COIN_DBL_MAX, 0.0, 0, false);
return _prob->numberColumns() - 1;
}
CbcMip* CbcMip::newSolver() const {
CbcMip* newlp = new CbcMip;
return newlp;
}
CbcMip* CbcMip::cloneSolver() const {
CbcMip* copylp = new CbcMip(*this);
return copylp;
}
int CbcMip::_addRow() {
_prob->addRow(0, 0, 0, -COIN_DBL_MAX, COIN_DBL_MAX);
return _prob->numberRows() - 1;
}
int CbcMip::_addRow(Value l, ExprIterator b, ExprIterator e, Value u) {
std::vector<int> indexes;
std::vector<Value> values;
for(ExprIterator it = b; it != e; ++it) {
indexes.push_back(it->first);
values.push_back(it->second);
}
_prob->addRow(values.size(), &indexes.front(), &values.front(), l, u);
return _prob->numberRows() - 1;
}
void CbcMip::_eraseCol(int i) {
_prob->deleteColumn(i);
}
void CbcMip::_eraseRow(int i) {
_prob->deleteRow(i);
}
void CbcMip::_eraseColId(int i) {
cols.eraseIndex(i);
}
void CbcMip::_eraseRowId(int i) {
rows.eraseIndex(i);
}
void CbcMip::_getColName(int c, std::string& name) const {
name = _prob->getColumnName(c);
}
void CbcMip::_setColName(int c, const std::string& name) {
_prob->setColumnName(c, name.c_str());
}
int CbcMip::_colByName(const std::string& name) const {
return _prob->column(name.c_str());
}
void CbcMip::_getRowName(int r, std::string& name) const {
name = _prob->getRowName(r);
}
void CbcMip::_setRowName(int r, const std::string& name) {
_prob->setRowName(r, name.c_str());
}
int CbcMip::_rowByName(const std::string& name) const {
return _prob->row(name.c_str());
}
void CbcMip::_setRowCoeffs(int i, ExprIterator b, ExprIterator e) {
for (ExprIterator it = b; it != e; ++it) {
_prob->setElement(i, it->first, it->second);
}
}
void CbcMip::_getRowCoeffs(int ix, InsertIterator b) const {
int length = _prob->numberRows();
std::vector<int> indices(length);
std::vector<Value> values(length);
length = _prob->getRow(ix, &indices[0], &values[0]);
for (int i = 0; i < length; ++i) {
*b = std::make_pair(indices[i], values[i]);
++b;
}
}
void CbcMip::_setColCoeffs(int ix, ExprIterator b, ExprIterator e) {
for (ExprIterator it = b; it != e; ++it) {
_prob->setElement(it->first, ix, it->second);
}
}
void CbcMip::_getColCoeffs(int ix, InsertIterator b) const {
int length = _prob->numberColumns();
std::vector<int> indices(length);
std::vector<Value> values(length);
length = _prob->getColumn(ix, &indices[0], &values[0]);
for (int i = 0; i < length; ++i) {
*b = std::make_pair(indices[i], values[i]);
++b;
}
}
void CbcMip::_setCoeff(int ix, int jx, Value value) {
_prob->setElement(ix, jx, value);
}
CbcMip::Value CbcMip::_getCoeff(int ix, int jx) const {
return _prob->getElement(ix, jx);
}
void CbcMip::_setColLowerBound(int i, Value lo) {
LEMON_ASSERT(lo != INF, "Invalid bound");
_prob->setColumnLower(i, lo == - INF ? - COIN_DBL_MAX : lo);
}
CbcMip::Value CbcMip::_getColLowerBound(int i) const {
double val = _prob->getColumnLower(i);
return val == - COIN_DBL_MAX ? - INF : val;
}
void CbcMip::_setColUpperBound(int i, Value up) {
LEMON_ASSERT(up != -INF, "Invalid bound");
_prob->setColumnUpper(i, up == INF ? COIN_DBL_MAX : up);
}
CbcMip::Value CbcMip::_getColUpperBound(int i) const {
double val = _prob->getColumnUpper(i);
return val == COIN_DBL_MAX ? INF : val;
}
void CbcMip::_setRowLowerBound(int i, Value lo) {
LEMON_ASSERT(lo != INF, "Invalid bound");
_prob->setRowLower(i, lo == - INF ? - COIN_DBL_MAX : lo);
}
CbcMip::Value CbcMip::_getRowLowerBound(int i) const {
double val = _prob->getRowLower(i);
return val == - COIN_DBL_MAX ? - INF : val;
}
void CbcMip::_setRowUpperBound(int i, Value up) {
LEMON_ASSERT(up != -INF, "Invalid bound");
_prob->setRowUpper(i, up == INF ? COIN_DBL_MAX : up);
}
CbcMip::Value CbcMip::_getRowUpperBound(int i) const {
double val = _prob->getRowUpper(i);
return val == COIN_DBL_MAX ? INF : val;
}
void CbcMip::_setObjCoeffs(ExprIterator b, ExprIterator e) {
int num = _prob->numberColumns();
for (int i = 0; i < num; ++i) {
_prob->setColumnObjective(i, 0.0);
}
for (ExprIterator it = b; it != e; ++it) {
_prob->setColumnObjective(it->first, it->second);
}
}
void CbcMip::_getObjCoeffs(InsertIterator b) const {
int num = _prob->numberColumns();
for (int i = 0; i < num; ++i) {
Value coef = _prob->getColumnObjective(i);
if (coef != 0.0) {
*b = std::make_pair(i, coef);
++b;
}
}
}
void CbcMip::_setObjCoeff(int i, Value obj_coef) {
_prob->setColumnObjective(i, obj_coef);
}
CbcMip::Value CbcMip::_getObjCoeff(int i) const {
return _prob->getColumnObjective(i);
}
CbcMip::SolveExitStatus CbcMip::_solve() {
if (_osi_solver) {
delete _osi_solver;
}
_osi_solver = new OsiClpSolverInterface();
_osi_solver->loadFromCoinModel(*_prob);
if (_cbc_model) {
delete _cbc_model;
}
_cbc_model= new CbcModel(*_osi_solver);
_osi_solver->messageHandler()->setLogLevel(_message_level);
_cbc_model->setLogLevel(_message_level);
_cbc_model->initialSolve();
_cbc_model->solver()->setHintParam(OsiDoReducePrint, true, OsiHintTry);
if (!_cbc_model->isInitialSolveAbandoned() &&
_cbc_model->isInitialSolveProvenOptimal() &&
!_cbc_model->isInitialSolveProvenPrimalInfeasible() &&
!_cbc_model->isInitialSolveProvenDualInfeasible()) {
CglProbing generator1;
generator1.setUsingObjective(true);
generator1.setMaxPass(3);
generator1.setMaxProbe(100);
generator1.setMaxLook(50);
generator1.setRowCuts(3);
_cbc_model->addCutGenerator(&generator1, -1, "Probing");
CglGomory generator2;
generator2.setLimit(300);
_cbc_model->addCutGenerator(&generator2, -1, "Gomory");
CglKnapsackCover generator3;
_cbc_model->addCutGenerator(&generator3, -1, "Knapsack");
CglOddHole generator4;
generator4.setMinimumViolation(0.005);
generator4.setMinimumViolationPer(0.00002);
generator4.setMaximumEntries(200);
_cbc_model->addCutGenerator(&generator4, -1, "OddHole");
CglClique generator5;
generator5.setStarCliqueReport(false);
generator5.setRowCliqueReport(false);
_cbc_model->addCutGenerator(&generator5, -1, "Clique");
CglMixedIntegerRounding mixedGen;
_cbc_model->addCutGenerator(&mixedGen, -1, "MixedIntegerRounding");
CglFlowCover flowGen;
_cbc_model->addCutGenerator(&flowGen, -1, "FlowCover");
OsiClpSolverInterface* osiclp =
dynamic_cast<OsiClpSolverInterface*>(_cbc_model->solver());
if (osiclp->getNumRows() < 300 && osiclp->getNumCols() < 500) {
osiclp->setupForRepeatedUse(2, 0);
}
CbcRounding heuristic1(*_cbc_model);
heuristic1.setWhen(3);
_cbc_model->addHeuristic(&heuristic1);
CbcHeuristicLocal heuristic2(*_cbc_model);
heuristic2.setWhen(3);
_cbc_model->addHeuristic(&heuristic2);
CbcHeuristicGreedyCover heuristic3(*_cbc_model);
heuristic3.setAlgorithm(11);
heuristic3.setWhen(3);
_cbc_model->addHeuristic(&heuristic3);
CbcHeuristicFPump heuristic4(*_cbc_model);
heuristic4.setWhen(3);
_cbc_model->addHeuristic(&heuristic4);
CbcHeuristicRINS heuristic5(*_cbc_model);
heuristic5.setWhen(3);
_cbc_model->addHeuristic(&heuristic5);
if (_cbc_model->getNumCols() < 500) {
_cbc_model->setMaximumCutPassesAtRoot(-100);
} else if (_cbc_model->getNumCols() < 5000) {
_cbc_model->setMaximumCutPassesAtRoot(100);
} else {
_cbc_model->setMaximumCutPassesAtRoot(20);
}
if (_cbc_model->getNumCols() < 5000) {
_cbc_model->setNumberStrong(10);
}
_cbc_model->solver()->setIntParam(OsiMaxNumIterationHotStart, 100);
_cbc_model->branchAndBound();
}
if (_cbc_model->isAbandoned()) {
return UNSOLVED;
} else {
return SOLVED;
}
}
CbcMip::Value CbcMip::_getSol(int i) const {
return _cbc_model->getColSolution()[i];
}
CbcMip::Value CbcMip::_getSolValue() const {
return _cbc_model->getObjValue();
}
CbcMip::ProblemType CbcMip::_getType() const {
if (_cbc_model->isProvenOptimal()) {
return OPTIMAL;
} else if (_cbc_model->isContinuousUnbounded()) {
return UNBOUNDED;
}
return FEASIBLE;
}
void CbcMip::_setSense(Sense sense) {
switch (sense) {
case MIN:
_prob->setOptimizationDirection(1.0);
break;
case MAX:
_prob->setOptimizationDirection(- 1.0);
break;
}
}
CbcMip::Sense CbcMip::_getSense() const {
if (_prob->optimizationDirection() > 0.0) {
return MIN;
} else if (_prob->optimizationDirection() < 0.0) {
return MAX;
} else {
LEMON_ASSERT(false, "Wrong sense");
return CbcMip::Sense();
}
}
void CbcMip::_setColType(int i, CbcMip::ColTypes col_type) {
switch (col_type){
case INTEGER:
_prob->setInteger(i);
break;
case REAL:
_prob->setContinuous(i);
break;
default:;
LEMON_ASSERT(false, "Wrong sense");
}
}
CbcMip::ColTypes CbcMip::_getColType(int i) const {
return _prob->getColumnIsInteger(i) ? INTEGER : REAL;
}
void CbcMip::_clear() {
delete _prob;
if (_osi_solver) {
delete _osi_solver;
_osi_solver = 0;
}
if (_cbc_model) {
delete _cbc_model;
_cbc_model = 0;
}
_prob = new CoinModel();
}
void CbcMip::_messageLevel(MessageLevel level) {
switch (level) {
case MESSAGE_NOTHING:
_message_level = 0;
break;
case MESSAGE_ERROR:
_message_level = 1;
break;
case MESSAGE_WARNING:
_message_level = 1;
break;
case MESSAGE_NORMAL:
_message_level = 2;
break;
case MESSAGE_VERBOSE:
_message_level = 3;
break;
}
}
} //END OF NAMESPACE LEMON

View File

@@ -0,0 +1,129 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2013
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
#ifndef LEMON_CBC_H
#define LEMON_CBC_H
///\file
///\brief Header of the LEMON-CBC mip solver interface.
///\ingroup lp_group
#include <lemon/lp_base.h>
class CoinModel;
class OsiSolverInterface;
class CbcModel;
namespace lemon {
/// \brief Interface for the CBC MIP solver
///
/// This class implements an interface for the CBC MIP solver.
///\ingroup lp_group
class CbcMip : public MipSolver {
protected:
CoinModel *_prob;
OsiSolverInterface *_osi_solver;
CbcModel *_cbc_model;
public:
/// \e
CbcMip();
/// \e
CbcMip(const CbcMip&);
/// \e
~CbcMip();
/// \e
virtual CbcMip* newSolver() const;
/// \e
virtual CbcMip* cloneSolver() const;
protected:
virtual const char* _solverName() const;
virtual int _addCol();
virtual int _addRow();
virtual int _addRow(Value l, ExprIterator b, ExprIterator e, Value u);
virtual void _eraseCol(int i);
virtual void _eraseRow(int i);
virtual void _eraseColId(int i);
virtual void _eraseRowId(int i);
virtual void _getColName(int col, std::string& name) const;
virtual void _setColName(int col, const std::string& name);
virtual int _colByName(const std::string& name) const;
virtual void _getRowName(int row, std::string& name) const;
virtual void _setRowName(int row, const std::string& name);
virtual int _rowByName(const std::string& name) const;
virtual void _setRowCoeffs(int i, ExprIterator b, ExprIterator e);
virtual void _getRowCoeffs(int i, InsertIterator b) const;
virtual void _setColCoeffs(int i, ExprIterator b, ExprIterator e);
virtual void _getColCoeffs(int i, InsertIterator b) const;
virtual void _setCoeff(int row, int col, Value value);
virtual Value _getCoeff(int row, int col) const;
virtual void _setColLowerBound(int i, Value value);
virtual Value _getColLowerBound(int i) const;
virtual void _setColUpperBound(int i, Value value);
virtual Value _getColUpperBound(int i) const;
virtual void _setRowLowerBound(int i, Value value);
virtual Value _getRowLowerBound(int i) const;
virtual void _setRowUpperBound(int i, Value value);
virtual Value _getRowUpperBound(int i) const;
virtual void _setObjCoeffs(ExprIterator b, ExprIterator e);
virtual void _getObjCoeffs(InsertIterator b) const;
virtual void _setObjCoeff(int i, Value obj_coef);
virtual Value _getObjCoeff(int i) const;
virtual void _setSense(Sense sense);
virtual Sense _getSense() const;
virtual ColTypes _getColType(int col) const;
virtual void _setColType(int col, ColTypes col_type);
virtual SolveExitStatus _solve();
virtual ProblemType _getType() const;
virtual Value _getSol(int i) const;
virtual Value _getSolValue() const;
virtual void _clear();
virtual void _messageLevel(MessageLevel level);
void _applyMessageLevel();
int _message_level;
};
}
#endif

View File

@@ -0,0 +1,254 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2013
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
#ifndef LEMON_CHRISTOFIDES_TSP_H
#define LEMON_CHRISTOFIDES_TSP_H
/// \ingroup tsp
/// \file
/// \brief Christofides algorithm for symmetric TSP
#include <lemon/full_graph.h>
#include <lemon/smart_graph.h>
#include <lemon/kruskal.h>
#include <lemon/matching.h>
#include <lemon/euler.h>
namespace lemon {
/// \ingroup tsp
///
/// \brief Christofides algorithm for symmetric TSP.
///
/// ChristofidesTsp implements Christofides' heuristic for solving
/// symmetric \ref tsp "TSP".
///
/// This a well-known approximation method for the TSP problem with
/// metric cost function.
/// It has a guaranteed approximation factor of 3/2 (i.e. it finds a tour
/// whose total cost is at most 3/2 of the optimum), but it usually
/// provides better solutions in practice.
/// This implementation runs in O(n<sup>3</sup>log(n)) time.
///
/// The algorithm starts with a \ref spantree "minimum cost spanning tree" and
/// finds a \ref MaxWeightedPerfectMatching "minimum cost perfect matching"
/// in the subgraph induced by the nodes that have odd degree in the
/// spanning tree.
/// Finally, it constructs the tour from the \ref EulerIt "Euler traversal"
/// of the union of the spanning tree and the matching.
/// During this last step, the algorithm simply skips the visited nodes
/// (i.e. creates shortcuts) assuming that the triangle inequality holds
/// for the cost function.
///
/// \tparam CM Type of the cost map.
///
/// \warning CM::Value must be a signed number type.
template <typename CM>
class ChristofidesTsp
{
public:
/// Type of the cost map
typedef CM CostMap;
/// Type of the edge costs
typedef typename CM::Value Cost;
private:
GRAPH_TYPEDEFS(FullGraph);
const FullGraph &_gr;
const CostMap &_cost;
std::vector<Node> _path;
Cost _sum;
public:
/// \brief Constructor
///
/// Constructor.
/// \param gr The \ref FullGraph "full graph" the algorithm runs on.
/// \param cost The cost map.
ChristofidesTsp(const FullGraph &gr, const CostMap &cost)
: _gr(gr), _cost(cost) {}
/// \name Execution Control
/// @{
/// \brief Runs the algorithm.
///
/// This function runs the algorithm.
///
/// \return The total cost of the found tour.
Cost run() {
_path.clear();
if (_gr.nodeNum() == 0) return _sum = 0;
else if (_gr.nodeNum() == 1) {
_path.push_back(_gr(0));
return _sum = 0;
}
else if (_gr.nodeNum() == 2) {
_path.push_back(_gr(0));
_path.push_back(_gr(1));
return _sum = 2 * _cost[_gr.edge(_gr(0), _gr(1))];
}
// Compute min. cost spanning tree
std::vector<Edge> tree;
kruskal(_gr, _cost, std::back_inserter(tree));
FullGraph::NodeMap<int> deg(_gr, 0);
for (int i = 0; i != int(tree.size()); ++i) {
Edge e = tree[i];
++deg[_gr.u(e)];
++deg[_gr.v(e)];
}
// Copy the induced subgraph of odd nodes
std::vector<Node> odd_nodes;
for (NodeIt u(_gr); u != INVALID; ++u) {
if (deg[u] % 2 == 1) odd_nodes.push_back(u);
}
SmartGraph sgr;
SmartGraph::EdgeMap<Cost> scost(sgr);
for (int i = 0; i != int(odd_nodes.size()); ++i) {
sgr.addNode();
}
for (int i = 0; i != int(odd_nodes.size()); ++i) {
for (int j = 0; j != int(odd_nodes.size()); ++j) {
if (j == i) continue;
SmartGraph::Edge e =
sgr.addEdge(sgr.nodeFromId(i), sgr.nodeFromId(j));
scost[e] = -_cost[_gr.edge(odd_nodes[i], odd_nodes[j])];
}
}
// Compute min. cost perfect matching
MaxWeightedPerfectMatching<SmartGraph, SmartGraph::EdgeMap<Cost> >
mwpm(sgr, scost);
mwpm.run();
for (SmartGraph::EdgeIt e(sgr); e != INVALID; ++e) {
if (mwpm.matching(e)) {
tree.push_back( _gr.edge(odd_nodes[sgr.id(sgr.u(e))],
odd_nodes[sgr.id(sgr.v(e))]) );
}
}
// Join the spanning tree and the matching
sgr.clear();
for (int i = 0; i != _gr.nodeNum(); ++i) {
sgr.addNode();
}
for (int i = 0; i != int(tree.size()); ++i) {
int ui = _gr.id(_gr.u(tree[i])),
vi = _gr.id(_gr.v(tree[i]));
sgr.addEdge(sgr.nodeFromId(ui), sgr.nodeFromId(vi));
}
// Compute the tour from the Euler traversal
SmartGraph::NodeMap<bool> visited(sgr, false);
for (EulerIt<SmartGraph> e(sgr); e != INVALID; ++e) {
SmartGraph::Node n = sgr.target(e);
if (!visited[n]) {
_path.push_back(_gr(sgr.id(n)));
visited[n] = true;
}
}
_sum = _cost[_gr.edge(_path.back(), _path.front())];
for (int i = 0; i < int(_path.size())-1; ++i) {
_sum += _cost[_gr.edge(_path[i], _path[i+1])];
}
return _sum;
}
/// @}
/// \name Query Functions
/// @{
/// \brief The total cost of the found tour.
///
/// This function returns the total cost of the found tour.
///
/// \pre run() must be called before using this function.
Cost tourCost() const {
return _sum;
}
/// \brief Returns a const reference to the node sequence of the
/// found tour.
///
/// This function returns a const reference to a vector
/// that stores the node sequence of the found tour.
///
/// \pre run() must be called before using this function.
const std::vector<Node>& tourNodes() const {
return _path;
}
/// \brief Gives back the node sequence of the found tour.
///
/// This function copies the node sequence of the found tour into
/// an STL container through the given output iterator. The
/// <tt>value_type</tt> of the container must be <tt>FullGraph::Node</tt>.
/// For example,
/// \code
/// std::vector<FullGraph::Node> nodes(countNodes(graph));
/// tsp.tourNodes(nodes.begin());
/// \endcode
/// or
/// \code
/// std::list<FullGraph::Node> nodes;
/// tsp.tourNodes(std::back_inserter(nodes));
/// \endcode
///
/// \pre run() must be called before using this function.
template <typename Iterator>
void tourNodes(Iterator out) const {
std::copy(_path.begin(), _path.end(), out);
}
/// \brief Gives back the found tour as a path.
///
/// This function copies the found tour as a list of arcs/edges into
/// the given \ref lemon::concepts::Path "path structure".
///
/// \pre run() must be called before using this function.
template <typename Path>
void tour(Path &path) const {
path.clear();
for (int i = 0; i < int(_path.size()) - 1; ++i) {
path.addBack(_gr.arc(_path[i], _path[i+1]));
}
if (int(_path.size()) >= 2) {
path.addBack(_gr.arc(_path.back(), _path.front()));
}
}
/// @}
};
}; // namespace lemon
#endif

View File

@@ -0,0 +1,807 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2013
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
#ifndef LEMON_CIRCULATION_H
#define LEMON_CIRCULATION_H
#include <lemon/tolerance.h>
#include <lemon/elevator.h>
#include <limits>
///\ingroup max_flow
///\file
///\brief Push-relabel algorithm for finding a feasible circulation.
///
namespace lemon {
/// \brief Default traits class of Circulation class.
///
/// Default traits class of Circulation class.
///
/// \tparam GR Type of the digraph the algorithm runs on.
/// \tparam LM The type of the lower bound map.
/// \tparam UM The type of the upper bound (capacity) map.
/// \tparam SM The type of the supply map.
template <typename GR, typename LM,
typename UM, typename SM>
struct CirculationDefaultTraits {
/// \brief The type of the digraph the algorithm runs on.
typedef GR Digraph;
/// \brief The type of the lower bound map.
///
/// The type of the map that stores the lower bounds on the arcs.
/// It must conform to the \ref concepts::ReadMap "ReadMap" concept.
typedef LM LowerMap;
/// \brief The type of the upper bound (capacity) map.
///
/// The type of the map that stores the upper bounds (capacities)
/// on the arcs.
/// It must conform to the \ref concepts::ReadMap "ReadMap" concept.
typedef UM UpperMap;
/// \brief The type of supply map.
///
/// The type of the map that stores the signed supply values of the
/// nodes.
/// It must conform to the \ref concepts::ReadMap "ReadMap" concept.
typedef SM SupplyMap;
/// \brief The type of the flow and supply values.
typedef typename SupplyMap::Value Value;
/// \brief The type of the map that stores the flow values.
///
/// The type of the map that stores the flow values.
/// It must conform to the \ref concepts::ReadWriteMap "ReadWriteMap"
/// concept.
#ifdef DOXYGEN
typedef GR::ArcMap<Value> FlowMap;
#else
typedef typename Digraph::template ArcMap<Value> FlowMap;
#endif
/// \brief Instantiates a FlowMap.
///
/// This function instantiates a \ref FlowMap.
/// \param digraph The digraph for which we would like to define
/// the flow map.
static FlowMap* createFlowMap(const Digraph& digraph) {
return new FlowMap(digraph);
}
/// \brief The elevator type used by the algorithm.
///
/// The elevator type used by the algorithm.
///
/// \sa Elevator, LinkedElevator
#ifdef DOXYGEN
typedef lemon::Elevator<GR, GR::Node> Elevator;
#else
typedef lemon::Elevator<Digraph, typename Digraph::Node> Elevator;
#endif
/// \brief Instantiates an Elevator.
///
/// This function instantiates an \ref Elevator.
/// \param digraph The digraph for which we would like to define
/// the elevator.
/// \param max_level The maximum level of the elevator.
static Elevator* createElevator(const Digraph& digraph, int max_level) {
return new Elevator(digraph, max_level);
}
/// \brief The tolerance used by the algorithm
///
/// The tolerance used by the algorithm to handle inexact computation.
typedef lemon::Tolerance<Value> Tolerance;
};
/**
\brief Push-relabel algorithm for the network circulation problem.
\ingroup max_flow
This class implements a push-relabel algorithm for the \e network
\e circulation problem.
It is to find a feasible circulation when lower and upper bounds
are given for the flow values on the arcs and lower bounds are
given for the difference between the outgoing and incoming flow
at the nodes.
The exact formulation of this problem is the following.
Let \f$G=(V,A)\f$ be a digraph, \f$lower: A\rightarrow\mathbf{R}\f$
\f$upper: A\rightarrow\mathbf{R}\cup\{\infty\}\f$ denote the lower and
upper bounds on the arcs, for which \f$lower(uv) \leq upper(uv)\f$
holds for all \f$uv\in A\f$, and \f$sup: V\rightarrow\mathbf{R}\f$
denotes the signed supply values of the nodes.
If \f$sup(u)>0\f$, then \f$u\f$ is a supply node with \f$sup(u)\f$
supply, if \f$sup(u)<0\f$, then \f$u\f$ is a demand node with
\f$-sup(u)\f$ demand.
A feasible circulation is an \f$f: A\rightarrow\mathbf{R}\f$
solution of the following problem.
\f[ \sum_{uv\in A} f(uv) - \sum_{vu\in A} f(vu)
\geq sup(u) \quad \forall u\in V, \f]
\f[ lower(uv) \leq f(uv) \leq upper(uv) \quad \forall uv\in A. \f]
The sum of the supply values, i.e. \f$\sum_{u\in V} sup(u)\f$ must be
zero or negative in order to have a feasible solution (since the sum
of the expressions on the left-hand side of the inequalities is zero).
It means that the total demand must be greater or equal to the total
supply and all the supplies have to be carried out from the supply nodes,
but there could be demands that are not satisfied.
If \f$\sum_{u\in V} sup(u)\f$ is zero, then all the supply/demand
constraints have to be satisfied with equality, i.e. all demands
have to be satisfied and all supplies have to be used.
If you need the opposite inequalities in the supply/demand constraints
(i.e. the total demand is less than the total supply and all the demands
have to be satisfied while there could be supplies that are not used),
then you could easily transform the problem to the above form by reversing
the direction of the arcs and taking the negative of the supply values
(e.g. using \ref ReverseDigraph and \ref NegMap adaptors).
This algorithm either calculates a feasible circulation, or provides
a \ref barrier() "barrier", which prooves that a feasible soultion
cannot exist.
Note that this algorithm also provides a feasible solution for the
\ref min_cost_flow "minimum cost flow problem".
\tparam GR The type of the digraph the algorithm runs on.
\tparam LM The type of the lower bound map. The default
map type is \ref concepts::Digraph::ArcMap "GR::ArcMap<int>".
\tparam UM The type of the upper bound (capacity) map.
The default map type is \c LM.
\tparam SM The type of the supply map. The default map type is
\ref concepts::Digraph::NodeMap "GR::NodeMap<UM::Value>".
\tparam TR The traits class that defines various types used by the
algorithm. By default, it is \ref CirculationDefaultTraits
"CirculationDefaultTraits<GR, LM, UM, SM>".
In most cases, this parameter should not be set directly,
consider to use the named template parameters instead.
*/
#ifdef DOXYGEN
template< typename GR,
typename LM,
typename UM,
typename SM,
typename TR >
#else
template< typename GR,
typename LM = typename GR::template ArcMap<int>,
typename UM = LM,
typename SM = typename GR::template NodeMap<typename UM::Value>,
typename TR = CirculationDefaultTraits<GR, LM, UM, SM> >
#endif
class Circulation {
public:
/// \brief The \ref lemon::CirculationDefaultTraits "traits class"
/// of the algorithm.
typedef TR Traits;
///The type of the digraph the algorithm runs on.
typedef typename Traits::Digraph Digraph;
///The type of the flow and supply values.
typedef typename Traits::Value Value;
///The type of the lower bound map.
typedef typename Traits::LowerMap LowerMap;
///The type of the upper bound (capacity) map.
typedef typename Traits::UpperMap UpperMap;
///The type of the supply map.
typedef typename Traits::SupplyMap SupplyMap;
///The type of the flow map.
typedef typename Traits::FlowMap FlowMap;
///The type of the elevator.
typedef typename Traits::Elevator Elevator;
///The type of the tolerance.
typedef typename Traits::Tolerance Tolerance;
private:
TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
const Digraph &_g;
int _node_num;
const LowerMap *_lo;
const UpperMap *_up;
const SupplyMap *_supply;
FlowMap *_flow;
bool _local_flow;
Elevator* _level;
bool _local_level;
typedef typename Digraph::template NodeMap<Value> ExcessMap;
ExcessMap* _excess;
Tolerance _tol;
int _el;
public:
typedef Circulation Create;
///\name Named Template Parameters
///@{
template <typename T>
struct SetFlowMapTraits : public Traits {
typedef T FlowMap;
static FlowMap *createFlowMap(const Digraph&) {
LEMON_ASSERT(false, "FlowMap is not initialized");
return 0; // ignore warnings
}
};
/// \brief \ref named-templ-param "Named parameter" for setting
/// FlowMap type
///
/// \ref named-templ-param "Named parameter" for setting FlowMap
/// type.
template <typename T>
struct SetFlowMap
: public Circulation<Digraph, LowerMap, UpperMap, SupplyMap,
SetFlowMapTraits<T> > {
typedef Circulation<Digraph, LowerMap, UpperMap, SupplyMap,
SetFlowMapTraits<T> > Create;
};
template <typename T>
struct SetElevatorTraits : public Traits {
typedef T Elevator;
static Elevator *createElevator(const Digraph&, int) {
LEMON_ASSERT(false, "Elevator is not initialized");
return 0; // ignore warnings
}
};
/// \brief \ref named-templ-param "Named parameter" for setting
/// Elevator type
///
/// \ref named-templ-param "Named parameter" for setting Elevator
/// type. If this named parameter is used, then an external
/// elevator object must be passed to the algorithm using the
/// \ref elevator(Elevator&) "elevator()" function before calling
/// \ref run() or \ref init().
/// \sa SetStandardElevator
template <typename T>
struct SetElevator
: public Circulation<Digraph, LowerMap, UpperMap, SupplyMap,
SetElevatorTraits<T> > {
typedef Circulation<Digraph, LowerMap, UpperMap, SupplyMap,
SetElevatorTraits<T> > Create;
};
template <typename T>
struct SetStandardElevatorTraits : public Traits {
typedef T Elevator;
static Elevator *createElevator(const Digraph& digraph, int max_level) {
return new Elevator(digraph, max_level);
}
};
/// \brief \ref named-templ-param "Named parameter" for setting
/// Elevator type with automatic allocation
///
/// \ref named-templ-param "Named parameter" for setting Elevator
/// type with automatic allocation.
/// The Elevator should have standard constructor interface to be
/// able to automatically created by the algorithm (i.e. the
/// digraph and the maximum level should be passed to it).
/// However, an external elevator object could also be passed to the
/// algorithm with the \ref elevator(Elevator&) "elevator()" function
/// before calling \ref run() or \ref init().
/// \sa SetElevator
template <typename T>
struct SetStandardElevator
: public Circulation<Digraph, LowerMap, UpperMap, SupplyMap,
SetStandardElevatorTraits<T> > {
typedef Circulation<Digraph, LowerMap, UpperMap, SupplyMap,
SetStandardElevatorTraits<T> > Create;
};
/// @}
protected:
Circulation() {}
public:
/// Constructor.
/// The constructor of the class.
///
/// \param graph The digraph the algorithm runs on.
/// \param lower The lower bounds for the flow values on the arcs.
/// \param upper The upper bounds (capacities) for the flow values
/// on the arcs.
/// \param supply The signed supply values of the nodes.
Circulation(const Digraph &graph, const LowerMap &lower,
const UpperMap &upper, const SupplyMap &supply)
: _g(graph), _lo(&lower), _up(&upper), _supply(&supply),
_flow(NULL), _local_flow(false), _level(NULL), _local_level(false),
_excess(NULL) {}
/// Destructor.
~Circulation() {
destroyStructures();
}
private:
bool checkBoundMaps() {
for (ArcIt e(_g);e!=INVALID;++e) {
if (_tol.less((*_up)[e], (*_lo)[e])) return false;
}
return true;
}
void createStructures() {
_node_num = _el = countNodes(_g);
if (!_flow) {
_flow = Traits::createFlowMap(_g);
_local_flow = true;
}
if (!_level) {
_level = Traits::createElevator(_g, _node_num);
_local_level = true;
}
if (!_excess) {
_excess = new ExcessMap(_g);
}
}
void destroyStructures() {
if (_local_flow) {
delete _flow;
}
if (_local_level) {
delete _level;
}
if (_excess) {
delete _excess;
}
}
public:
/// Sets the lower bound map.
/// Sets the lower bound map.
/// \return <tt>(*this)</tt>
Circulation& lowerMap(const LowerMap& map) {
_lo = &map;
return *this;
}
/// Sets the upper bound (capacity) map.
/// Sets the upper bound (capacity) map.
/// \return <tt>(*this)</tt>
Circulation& upperMap(const UpperMap& map) {
_up = &map;
return *this;
}
/// Sets the supply map.
/// Sets the supply map.
/// \return <tt>(*this)</tt>
Circulation& supplyMap(const SupplyMap& map) {
_supply = &map;
return *this;
}
/// \brief Sets the flow map.
///
/// Sets the flow map.
/// If you don't use this function before calling \ref run() or
/// \ref init(), an instance will be allocated automatically.
/// The destructor deallocates this automatically allocated map,
/// of course.
/// \return <tt>(*this)</tt>
Circulation& flowMap(FlowMap& map) {
if (_local_flow) {
delete _flow;
_local_flow = false;
}
_flow = &map;
return *this;
}
/// \brief Sets the elevator used by algorithm.
///
/// Sets the elevator used by algorithm.
/// If you don't use this function before calling \ref run() or
/// \ref init(), an instance will be allocated automatically.
/// The destructor deallocates this automatically allocated elevator,
/// of course.
/// \return <tt>(*this)</tt>
Circulation& elevator(Elevator& elevator) {
if (_local_level) {
delete _level;
_local_level = false;
}
_level = &elevator;
return *this;
}
/// \brief Returns a const reference to the elevator.
///
/// Returns a const reference to the elevator.
///
/// \pre Either \ref run() or \ref init() must be called before
/// using this function.
const Elevator& elevator() const {
return *_level;
}
/// \brief Sets the tolerance used by the algorithm.
///
/// Sets the tolerance object used by the algorithm.
/// \return <tt>(*this)</tt>
Circulation& tolerance(const Tolerance& tolerance) {
_tol = tolerance;
return *this;
}
/// \brief Returns a const reference to the tolerance.
///
/// Returns a const reference to the tolerance object used by
/// the algorithm.
const Tolerance& tolerance() const {
return _tol;
}
/// \name Execution Control
/// The simplest way to execute the algorithm is to call \ref run().\n
/// If you need better control on the initial solution or the execution,
/// you have to call one of the \ref init() functions first, then
/// the \ref start() function.
///@{
/// Initializes the internal data structures.
/// Initializes the internal data structures and sets all flow values
/// to the lower bound.
void init()
{
LEMON_DEBUG(checkBoundMaps(),
"Upper bounds must be greater or equal to the lower bounds");
createStructures();
for(NodeIt n(_g);n!=INVALID;++n) {
(*_excess)[n] = (*_supply)[n];
}
for (ArcIt e(_g);e!=INVALID;++e) {
_flow->set(e, (*_lo)[e]);
(*_excess)[_g.target(e)] += (*_flow)[e];
(*_excess)[_g.source(e)] -= (*_flow)[e];
}
// global relabeling tested, but in general case it provides
// worse performance for random digraphs
_level->initStart();
for(NodeIt n(_g);n!=INVALID;++n)
_level->initAddItem(n);
_level->initFinish();
for(NodeIt n(_g);n!=INVALID;++n)
if(_tol.positive((*_excess)[n]))
_level->activate(n);
}
/// Initializes the internal data structures using a greedy approach.
/// Initializes the internal data structures using a greedy approach
/// to construct the initial solution.
void greedyInit()
{
LEMON_DEBUG(checkBoundMaps(),
"Upper bounds must be greater or equal to the lower bounds");
createStructures();
for(NodeIt n(_g);n!=INVALID;++n) {
(*_excess)[n] = (*_supply)[n];
}
for (ArcIt e(_g);e!=INVALID;++e) {
if (!_tol.less(-(*_excess)[_g.target(e)], (*_up)[e])) {
_flow->set(e, (*_up)[e]);
(*_excess)[_g.target(e)] += (*_up)[e];
(*_excess)[_g.source(e)] -= (*_up)[e];
} else if (_tol.less(-(*_excess)[_g.target(e)], (*_lo)[e])) {
_flow->set(e, (*_lo)[e]);
(*_excess)[_g.target(e)] += (*_lo)[e];
(*_excess)[_g.source(e)] -= (*_lo)[e];
} else {
Value fc = -(*_excess)[_g.target(e)];
_flow->set(e, fc);
(*_excess)[_g.target(e)] = 0;
(*_excess)[_g.source(e)] -= fc;
}
}
_level->initStart();
for(NodeIt n(_g);n!=INVALID;++n)
_level->initAddItem(n);
_level->initFinish();
for(NodeIt n(_g);n!=INVALID;++n)
if(_tol.positive((*_excess)[n]))
_level->activate(n);
}
///Executes the algorithm
///This function executes the algorithm.
///
///\return \c true if a feasible circulation is found.
///
///\sa barrier()
///\sa barrierMap()
bool start()
{
Node act;
while((act=_level->highestActive())!=INVALID) {
int actlevel=(*_level)[act];
int mlevel=_node_num;
Value exc=(*_excess)[act];
for(OutArcIt e(_g,act);e!=INVALID; ++e) {
Node v = _g.target(e);
Value fc=(*_up)[e]-(*_flow)[e];
if(!_tol.positive(fc)) continue;
if((*_level)[v]<actlevel) {
if(!_tol.less(fc, exc)) {
_flow->set(e, (*_flow)[e] + exc);
(*_excess)[v] += exc;
if(!_level->active(v) && _tol.positive((*_excess)[v]))
_level->activate(v);
(*_excess)[act] = 0;
_level->deactivate(act);
goto next_l;
}
else {
_flow->set(e, (*_up)[e]);
(*_excess)[v] += fc;
if(!_level->active(v) && _tol.positive((*_excess)[v]))
_level->activate(v);
exc-=fc;
}
}
else if((*_level)[v]<mlevel) mlevel=(*_level)[v];
}
for(InArcIt e(_g,act);e!=INVALID; ++e) {
Node v = _g.source(e);
Value fc=(*_flow)[e]-(*_lo)[e];
if(!_tol.positive(fc)) continue;
if((*_level)[v]<actlevel) {
if(!_tol.less(fc, exc)) {
_flow->set(e, (*_flow)[e] - exc);
(*_excess)[v] += exc;
if(!_level->active(v) && _tol.positive((*_excess)[v]))
_level->activate(v);
(*_excess)[act] = 0;
_level->deactivate(act);
goto next_l;
}
else {
_flow->set(e, (*_lo)[e]);
(*_excess)[v] += fc;
if(!_level->active(v) && _tol.positive((*_excess)[v]))
_level->activate(v);
exc-=fc;
}
}
else if((*_level)[v]<mlevel) mlevel=(*_level)[v];
}
(*_excess)[act] = exc;
if(!_tol.positive(exc)) _level->deactivate(act);
else if(mlevel==_node_num) {
_level->liftHighestActiveToTop();
_el = _node_num;
return false;
}
else {
_level->liftHighestActive(mlevel+1);
if(_level->onLevel(actlevel)==0) {
_el = actlevel;
return false;
}
}
next_l:
;
}
return true;
}
/// Runs the algorithm.
/// This function runs the algorithm.
///
/// \return \c true if a feasible circulation is found.
///
/// \note Apart from the return value, c.run() is just a shortcut of
/// the following code.
/// \code
/// c.greedyInit();
/// c.start();
/// \endcode
bool run() {
greedyInit();
return start();
}
/// @}
/// \name Query Functions
/// The results of the circulation algorithm can be obtained using
/// these functions.\n
/// Either \ref run() or \ref start() should be called before
/// using them.
///@{
/// \brief Returns the flow value on the given arc.
///
/// Returns the flow value on the given arc.
///
/// \pre Either \ref run() or \ref init() must be called before
/// using this function.
Value flow(const Arc& arc) const {
return (*_flow)[arc];
}
/// \brief Returns a const reference to the flow map.
///
/// Returns a const reference to the arc map storing the found flow.
///
/// \pre Either \ref run() or \ref init() must be called before
/// using this function.
const FlowMap& flowMap() const {
return *_flow;
}
/**
\brief Returns \c true if the given node is in a barrier.
Barrier is a set \e B of nodes for which
\f[ \sum_{uv\in A: u\in B} upper(uv) -
\sum_{uv\in A: v\in B} lower(uv) < \sum_{v\in B} sup(v) \f]
holds. The existence of a set with this property prooves that a
feasible circualtion cannot exist.
This function returns \c true if the given node is in the found
barrier. If a feasible circulation is found, the function
gives back \c false for every node.
\pre Either \ref run() or \ref init() must be called before
using this function.
\sa barrierMap()
\sa checkBarrier()
*/
bool barrier(const Node& node) const
{
return (*_level)[node] >= _el;
}
/// \brief Gives back a barrier.
///
/// This function sets \c bar to the characteristic vector of the
/// found barrier. \c bar should be a \ref concepts::WriteMap "writable"
/// node map with \c bool (or convertible) value type.
///
/// If a feasible circulation is found, the function gives back an
/// empty set, so \c bar[v] will be \c false for all nodes \c v.
///
/// \note This function calls \ref barrier() for each node,
/// so it runs in O(n) time.
///
/// \pre Either \ref run() or \ref init() must be called before
/// using this function.
///
/// \sa barrier()
/// \sa checkBarrier()
template<class BarrierMap>
void barrierMap(BarrierMap &bar) const
{
for(NodeIt n(_g);n!=INVALID;++n)
bar.set(n, (*_level)[n] >= _el);
}
/// @}
/// \name Checker Functions
/// The feasibility of the results can be checked using
/// these functions.\n
/// Either \ref run() or \ref start() should be called before
/// using them.
///@{
///Check if the found flow is a feasible circulation
///Check if the found flow is a feasible circulation,
///
bool checkFlow() const {
for(ArcIt e(_g);e!=INVALID;++e)
if((*_flow)[e]<(*_lo)[e]||(*_flow)[e]>(*_up)[e]) return false;
for(NodeIt n(_g);n!=INVALID;++n)
{
Value dif=-(*_supply)[n];
for(InArcIt e(_g,n);e!=INVALID;++e) dif-=(*_flow)[e];
for(OutArcIt e(_g,n);e!=INVALID;++e) dif+=(*_flow)[e];
if(_tol.negative(dif)) return false;
}
return true;
}
///Check whether or not the last execution provides a barrier
///Check whether or not the last execution provides a barrier.
///\sa barrier()
///\sa barrierMap()
bool checkBarrier() const
{
Value delta=0;
Value inf_cap = std::numeric_limits<Value>::has_infinity ?
std::numeric_limits<Value>::infinity() :
std::numeric_limits<Value>::max();
for(NodeIt n(_g);n!=INVALID;++n)
if(barrier(n))
delta-=(*_supply)[n];
for(ArcIt e(_g);e!=INVALID;++e)
{
Node s=_g.source(e);
Node t=_g.target(e);
if(barrier(s)&&!barrier(t)) {
if (_tol.less(inf_cap - (*_up)[e], delta)) return false;
delta+=(*_up)[e];
}
else if(barrier(t)&&!barrier(s)) delta-=(*_lo)[e];
}
return _tol.negative(delta);
}
/// @}
};
}
#endif

View File

@@ -0,0 +1,464 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2013
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
#include <lemon/clp.h>
#include <coin/ClpSimplex.hpp>
namespace lemon {
ClpLp::ClpLp() {
_prob = new ClpSimplex();
_init_temporals();
messageLevel(MESSAGE_NOTHING);
}
ClpLp::ClpLp(const ClpLp& other) {
_prob = new ClpSimplex(*other._prob);
rows = other.rows;
cols = other.cols;
_init_temporals();
messageLevel(MESSAGE_NOTHING);
}
ClpLp::~ClpLp() {
delete _prob;
_clear_temporals();
}
void ClpLp::_init_temporals() {
_primal_ray = 0;
_dual_ray = 0;
}
void ClpLp::_clear_temporals() {
if (_primal_ray) {
delete[] _primal_ray;
_primal_ray = 0;
}
if (_dual_ray) {
delete[] _dual_ray;
_dual_ray = 0;
}
}
ClpLp* ClpLp::newSolver() const {
ClpLp* newlp = new ClpLp;
return newlp;
}
ClpLp* ClpLp::cloneSolver() const {
ClpLp* copylp = new ClpLp(*this);
return copylp;
}
const char* ClpLp::_solverName() const { return "ClpLp"; }
int ClpLp::_addCol() {
_prob->addColumn(0, 0, 0, -COIN_DBL_MAX, COIN_DBL_MAX, 0.0);
return _prob->numberColumns() - 1;
}
int ClpLp::_addRow() {
_prob->addRow(0, 0, 0, -COIN_DBL_MAX, COIN_DBL_MAX);
return _prob->numberRows() - 1;
}
int ClpLp::_addRow(Value l, ExprIterator b, ExprIterator e, Value u) {
std::vector<int> indexes;
std::vector<Value> values;
for(ExprIterator it = b; it != e; ++it) {
indexes.push_back(it->first);
values.push_back(it->second);
}
_prob->addRow(values.size(), &indexes.front(), &values.front(), l, u);
return _prob->numberRows() - 1;
}
void ClpLp::_eraseCol(int c) {
_col_names_ref.erase(_prob->getColumnName(c));
_prob->deleteColumns(1, &c);
}
void ClpLp::_eraseRow(int r) {
_row_names_ref.erase(_prob->getRowName(r));
_prob->deleteRows(1, &r);
}
void ClpLp::_eraseColId(int i) {
cols.eraseIndex(i);
cols.shiftIndices(i);
}
void ClpLp::_eraseRowId(int i) {
rows.eraseIndex(i);
rows.shiftIndices(i);
}
void ClpLp::_getColName(int c, std::string& name) const {
name = _prob->getColumnName(c);
}
void ClpLp::_setColName(int c, const std::string& name) {
_prob->setColumnName(c, const_cast<std::string&>(name));
_col_names_ref[name] = c;
}
int ClpLp::_colByName(const std::string& name) const {
std::map<std::string, int>::const_iterator it = _col_names_ref.find(name);
return it != _col_names_ref.end() ? it->second : -1;
}
void ClpLp::_getRowName(int r, std::string& name) const {
name = _prob->getRowName(r);
}
void ClpLp::_setRowName(int r, const std::string& name) {
_prob->setRowName(r, const_cast<std::string&>(name));
_row_names_ref[name] = r;
}
int ClpLp::_rowByName(const std::string& name) const {
std::map<std::string, int>::const_iterator it = _row_names_ref.find(name);
return it != _row_names_ref.end() ? it->second : -1;
}
void ClpLp::_setRowCoeffs(int ix, ExprIterator b, ExprIterator e) {
std::map<int, Value> coeffs;
int n = _prob->clpMatrix()->getNumCols();
const int* indices = _prob->clpMatrix()->getIndices();
const double* elements = _prob->clpMatrix()->getElements();
for (int i = 0; i < n; ++i) {
CoinBigIndex begin = _prob->clpMatrix()->getVectorStarts()[i];
CoinBigIndex end = begin + _prob->clpMatrix()->getVectorLengths()[i];
const int* it = std::lower_bound(indices + begin, indices + end, ix);
if (it != indices + end && *it == ix && elements[it - indices] != 0.0) {
coeffs[i] = 0.0;
}
}
for (ExprIterator it = b; it != e; ++it) {
coeffs[it->first] = it->second;
}
for (std::map<int, Value>::iterator it = coeffs.begin();
it != coeffs.end(); ++it) {
_prob->modifyCoefficient(ix, it->first, it->second);
}
}
void ClpLp::_getRowCoeffs(int ix, InsertIterator b) const {
int n = _prob->clpMatrix()->getNumCols();
const int* indices = _prob->clpMatrix()->getIndices();
const double* elements = _prob->clpMatrix()->getElements();
for (int i = 0; i < n; ++i) {
CoinBigIndex begin = _prob->clpMatrix()->getVectorStarts()[i];
CoinBigIndex end = begin + _prob->clpMatrix()->getVectorLengths()[i];
const int* it = std::lower_bound(indices + begin, indices + end, ix);
if (it != indices + end && *it == ix) {
*b = std::make_pair(i, elements[it - indices]);
}
}
}
void ClpLp::_setColCoeffs(int ix, ExprIterator b, ExprIterator e) {
std::map<int, Value> coeffs;
CoinBigIndex begin = _prob->clpMatrix()->getVectorStarts()[ix];
CoinBigIndex end = begin + _prob->clpMatrix()->getVectorLengths()[ix];
const int* indices = _prob->clpMatrix()->getIndices();
const double* elements = _prob->clpMatrix()->getElements();
for (CoinBigIndex i = begin; i != end; ++i) {
if (elements[i] != 0.0) {
coeffs[indices[i]] = 0.0;
}
}
for (ExprIterator it = b; it != e; ++it) {
coeffs[it->first] = it->second;
}
for (std::map<int, Value>::iterator it = coeffs.begin();
it != coeffs.end(); ++it) {
_prob->modifyCoefficient(it->first, ix, it->second);
}
}
void ClpLp::_getColCoeffs(int ix, InsertIterator b) const {
CoinBigIndex begin = _prob->clpMatrix()->getVectorStarts()[ix];
CoinBigIndex end = begin + _prob->clpMatrix()->getVectorLengths()[ix];
const int* indices = _prob->clpMatrix()->getIndices();
const double* elements = _prob->clpMatrix()->getElements();
for (CoinBigIndex i = begin; i != end; ++i) {
*b = std::make_pair(indices[i], elements[i]);
++b;
}
}
void ClpLp::_setCoeff(int ix, int jx, Value value) {
_prob->modifyCoefficient(ix, jx, value);
}
ClpLp::Value ClpLp::_getCoeff(int ix, int jx) const {
CoinBigIndex begin = _prob->clpMatrix()->getVectorStarts()[ix];
CoinBigIndex end = begin + _prob->clpMatrix()->getVectorLengths()[ix];
const int* indices = _prob->clpMatrix()->getIndices();
const double* elements = _prob->clpMatrix()->getElements();
const int* it = std::lower_bound(indices + begin, indices + end, jx);
if (it != indices + end && *it == jx) {
return elements[it - indices];
} else {
return 0.0;
}
}
void ClpLp::_setColLowerBound(int i, Value lo) {
_prob->setColumnLower(i, lo == - INF ? - COIN_DBL_MAX : lo);
}
ClpLp::Value ClpLp::_getColLowerBound(int i) const {
double val = _prob->getColLower()[i];
return val == - COIN_DBL_MAX ? - INF : val;
}
void ClpLp::_setColUpperBound(int i, Value up) {
_prob->setColumnUpper(i, up == INF ? COIN_DBL_MAX : up);
}
ClpLp::Value ClpLp::_getColUpperBound(int i) const {
double val = _prob->getColUpper()[i];
return val == COIN_DBL_MAX ? INF : val;
}
void ClpLp::_setRowLowerBound(int i, Value lo) {
_prob->setRowLower(i, lo == - INF ? - COIN_DBL_MAX : lo);
}
ClpLp::Value ClpLp::_getRowLowerBound(int i) const {
double val = _prob->getRowLower()[i];
return val == - COIN_DBL_MAX ? - INF : val;
}
void ClpLp::_setRowUpperBound(int i, Value up) {
_prob->setRowUpper(i, up == INF ? COIN_DBL_MAX : up);
}
ClpLp::Value ClpLp::_getRowUpperBound(int i) const {
double val = _prob->getRowUpper()[i];
return val == COIN_DBL_MAX ? INF : val;
}
void ClpLp::_setObjCoeffs(ExprIterator b, ExprIterator e) {
int num = _prob->clpMatrix()->getNumCols();
for (int i = 0; i < num; ++i) {
_prob->setObjectiveCoefficient(i, 0.0);
}
for (ExprIterator it = b; it != e; ++it) {
_prob->setObjectiveCoefficient(it->first, it->second);
}
}
void ClpLp::_getObjCoeffs(InsertIterator b) const {
int num = _prob->clpMatrix()->getNumCols();
for (int i = 0; i < num; ++i) {
Value coef = _prob->getObjCoefficients()[i];
if (coef != 0.0) {
*b = std::make_pair(i, coef);
++b;
}
}
}
void ClpLp::_setObjCoeff(int i, Value obj_coef) {
_prob->setObjectiveCoefficient(i, obj_coef);
}
ClpLp::Value ClpLp::_getObjCoeff(int i) const {
return _prob->getObjCoefficients()[i];
}
ClpLp::SolveExitStatus ClpLp::_solve() {
return _prob->primal() >= 0 ? SOLVED : UNSOLVED;
}
ClpLp::SolveExitStatus ClpLp::solvePrimal() {
return _prob->primal() >= 0 ? SOLVED : UNSOLVED;
}
ClpLp::SolveExitStatus ClpLp::solveDual() {
return _prob->dual() >= 0 ? SOLVED : UNSOLVED;
}
ClpLp::SolveExitStatus ClpLp::solveBarrier() {
return _prob->barrier() >= 0 ? SOLVED : UNSOLVED;
}
ClpLp::Value ClpLp::_getPrimal(int i) const {
return _prob->primalColumnSolution()[i];
}
ClpLp::Value ClpLp::_getPrimalValue() const {
return _prob->objectiveValue();
}
ClpLp::Value ClpLp::_getDual(int i) const {
return _prob->dualRowSolution()[i];
}
ClpLp::Value ClpLp::_getPrimalRay(int i) const {
if (!_primal_ray) {
_primal_ray = _prob->unboundedRay();
LEMON_ASSERT(_primal_ray != 0, "Primal ray is not provided");
}
return _primal_ray[i];
}
ClpLp::Value ClpLp::_getDualRay(int i) const {
if (!_dual_ray) {
_dual_ray = _prob->infeasibilityRay();
LEMON_ASSERT(_dual_ray != 0, "Dual ray is not provided");
}
return _dual_ray[i];
}
ClpLp::VarStatus ClpLp::_getColStatus(int i) const {
switch (_prob->getColumnStatus(i)) {
case ClpSimplex::basic:
return BASIC;
case ClpSimplex::isFree:
return FREE;
case ClpSimplex::atUpperBound:
return UPPER;
case ClpSimplex::atLowerBound:
return LOWER;
case ClpSimplex::isFixed:
return FIXED;
case ClpSimplex::superBasic:
return FREE;
default:
LEMON_ASSERT(false, "Wrong column status");
return VarStatus();
}
}
ClpLp::VarStatus ClpLp::_getRowStatus(int i) const {
switch (_prob->getColumnStatus(i)) {
case ClpSimplex::basic:
return BASIC;
case ClpSimplex::isFree:
return FREE;
case ClpSimplex::atUpperBound:
return UPPER;
case ClpSimplex::atLowerBound:
return LOWER;
case ClpSimplex::isFixed:
return FIXED;
case ClpSimplex::superBasic:
return FREE;
default:
LEMON_ASSERT(false, "Wrong row status");
return VarStatus();
}
}
ClpLp::ProblemType ClpLp::_getPrimalType() const {
if (_prob->isProvenOptimal()) {
return OPTIMAL;
} else if (_prob->isProvenPrimalInfeasible()) {
return INFEASIBLE;
} else if (_prob->isProvenDualInfeasible()) {
return UNBOUNDED;
} else {
return UNDEFINED;
}
}
ClpLp::ProblemType ClpLp::_getDualType() const {
if (_prob->isProvenOptimal()) {
return OPTIMAL;
} else if (_prob->isProvenDualInfeasible()) {
return INFEASIBLE;
} else if (_prob->isProvenPrimalInfeasible()) {
return INFEASIBLE;
} else {
return UNDEFINED;
}
}
void ClpLp::_setSense(ClpLp::Sense sense) {
switch (sense) {
case MIN:
_prob->setOptimizationDirection(1);
break;
case MAX:
_prob->setOptimizationDirection(-1);
break;
}
}
ClpLp::Sense ClpLp::_getSense() const {
double dir = _prob->optimizationDirection();
if (dir > 0.0) {
return MIN;
} else {
return MAX;
}
}
void ClpLp::_clear() {
delete _prob;
_prob = new ClpSimplex();
_col_names_ref.clear();
_clear_temporals();
}
void ClpLp::_messageLevel(MessageLevel level) {
switch (level) {
case MESSAGE_NOTHING:
_prob->setLogLevel(0);
break;
case MESSAGE_ERROR:
_prob->setLogLevel(1);
break;
case MESSAGE_WARNING:
_prob->setLogLevel(2);
break;
case MESSAGE_NORMAL:
_prob->setLogLevel(3);
break;
case MESSAGE_VERBOSE:
_prob->setLogLevel(4);
break;
}
}
} //END OF NAMESPACE LEMON

View File

@@ -0,0 +1,164 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2013
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
#ifndef LEMON_CLP_H
#define LEMON_CLP_H
///\file
///\brief Header of the LEMON-CLP lp solver interface.
#include <vector>
#include <string>
#include <lemon/lp_base.h>
class ClpSimplex;
namespace lemon {
/// \ingroup lp_group
///
/// \brief Interface for the CLP solver
///
/// This class implements an interface for the Clp LP solver. The
/// Clp library is an object oriented lp solver library developed at
/// the IBM. The CLP is part of the COIN-OR package and it can be
/// used with Common Public License.
class ClpLp : public LpSolver {
protected:
ClpSimplex* _prob;
std::map<std::string, int> _col_names_ref;
std::map<std::string, int> _row_names_ref;
public:
/// \e
ClpLp();
/// \e
ClpLp(const ClpLp&);
/// \e
~ClpLp();
/// \e
virtual ClpLp* newSolver() const;
/// \e
virtual ClpLp* cloneSolver() const;
protected:
mutable double* _primal_ray;
mutable double* _dual_ray;
void _init_temporals();
void _clear_temporals();
protected:
virtual const char* _solverName() const;
virtual int _addCol();
virtual int _addRow();
virtual int _addRow(Value l, ExprIterator b, ExprIterator e, Value u);
virtual void _eraseCol(int i);
virtual void _eraseRow(int i);
virtual void _eraseColId(int i);
virtual void _eraseRowId(int i);
virtual void _getColName(int col, std::string& name) const;
virtual void _setColName(int col, const std::string& name);
virtual int _colByName(const std::string& name) const;
virtual void _getRowName(int row, std::string& name) const;
virtual void _setRowName(int row, const std::string& name);
virtual int _rowByName(const std::string& name) const;
virtual void _setRowCoeffs(int i, ExprIterator b, ExprIterator e);
virtual void _getRowCoeffs(int i, InsertIterator b) const;
virtual void _setColCoeffs(int i, ExprIterator b, ExprIterator e);
virtual void _getColCoeffs(int i, InsertIterator b) const;
virtual void _setCoeff(int row, int col, Value value);
virtual Value _getCoeff(int row, int col) const;
virtual void _setColLowerBound(int i, Value value);
virtual Value _getColLowerBound(int i) const;
virtual void _setColUpperBound(int i, Value value);
virtual Value _getColUpperBound(int i) const;
virtual void _setRowLowerBound(int i, Value value);
virtual Value _getRowLowerBound(int i) const;
virtual void _setRowUpperBound(int i, Value value);
virtual Value _getRowUpperBound(int i) const;
virtual void _setObjCoeffs(ExprIterator, ExprIterator);
virtual void _getObjCoeffs(InsertIterator) const;
virtual void _setObjCoeff(int i, Value obj_coef);
virtual Value _getObjCoeff(int i) const;
virtual void _setSense(Sense sense);
virtual Sense _getSense() const;
virtual SolveExitStatus _solve();
virtual Value _getPrimal(int i) const;
virtual Value _getDual(int i) const;
virtual Value _getPrimalValue() const;
virtual Value _getPrimalRay(int i) const;
virtual Value _getDualRay(int i) const;
virtual VarStatus _getColStatus(int i) const;
virtual VarStatus _getRowStatus(int i) const;
virtual ProblemType _getPrimalType() const;
virtual ProblemType _getDualType() const;
virtual void _clear();
virtual void _messageLevel(MessageLevel);
public:
///Solves LP with primal simplex method.
SolveExitStatus solvePrimal();
///Solves LP with dual simplex method.
SolveExitStatus solveDual();
///Solves LP with barrier method.
SolveExitStatus solveBarrier();
///Returns the constraint identifier understood by CLP.
int clpRow(Row r) const { return rows(id(r)); }
///Returns the variable identifier understood by CLP.
int clpCol(Col c) const { return cols(id(c)); }
};
} //END OF NAMESPACE LEMON
#endif //LEMON_CLP_H

View File

@@ -0,0 +1,44 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2009
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
///\file
///\brief Color constants
#include<lemon/color.h>
namespace lemon {
const Color WHITE(1,1,1);
const Color BLACK(0,0,0);
const Color RED(1,0,0);
const Color GREEN(0,1,0);
const Color BLUE(0,0,1);
const Color YELLOW(1,1,0);
const Color MAGENTA(1,0,1);
const Color CYAN(0,1,1);
const Color GREY(0,0,0);
const Color DARK_RED(.5,0,0);
const Color DARK_GREEN(0,.5,0);
const Color DARK_BLUE(0,0,.5);
const Color DARK_YELLOW(.5,.5,0);
const Color DARK_MAGENTA(.5,0,.5);
const Color DARK_CYAN(0,.5,.5);
} //namespace lemon

View File

@@ -0,0 +1,204 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2009
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
#ifndef LEMON_COLOR_H
#define LEMON_COLOR_H
#include<vector>
#include<lemon/math.h>
#include<lemon/maps.h>
///\ingroup misc
///\file
///\brief Tools to manage RGB colors.
namespace lemon {
/// \addtogroup misc
/// @{
///Data structure representing RGB colors.
///Data structure representing RGB colors.
class Color
{
double _r,_g,_b;
public:
///Default constructor
Color() {}
///Constructor
Color(double r,double g,double b) :_r(r),_g(g),_b(b) {};
///Set the red component
double & red() {return _r;}
///Return the red component
const double & red() const {return _r;}
///Set the green component
double & green() {return _g;}
///Return the green component
const double & green() const {return _g;}
///Set the blue component
double & blue() {return _b;}
///Return the blue component
const double & blue() const {return _b;}
///Set the color components
void set(double r,double g,double b) { _r=r;_g=g;_b=b; };
};
/// White color constant
extern const Color WHITE;
/// Black color constant
extern const Color BLACK;
/// Red color constant
extern const Color RED;
/// Green color constant
extern const Color GREEN;
/// Blue color constant
extern const Color BLUE;
/// Yellow color constant
extern const Color YELLOW;
/// Magenta color constant
extern const Color MAGENTA;
/// Cyan color constant
extern const Color CYAN;
/// Grey color constant
extern const Color GREY;
/// Dark red color constant
extern const Color DARK_RED;
/// Dark green color constant
extern const Color DARK_GREEN;
/// Drak blue color constant
extern const Color DARK_BLUE;
/// Dark yellow color constant
extern const Color DARK_YELLOW;
/// Dark magenta color constant
extern const Color DARK_MAGENTA;
/// Dark cyan color constant
extern const Color DARK_CYAN;
///Map <tt>int</tt>s to different <tt>Color</tt>s
///This map assigns one of the predefined \ref Color "Color"s to
///each <tt>int</tt>. It is possible to change the colors as well as
///their number. The integer range is cyclically mapped to the
///provided set of colors.
///
///This is a true \ref concepts::ReferenceMap "reference map", so
///you can also change the actual colors.
class Palette : public MapBase<int,Color>
{
std::vector<Color> colors;
public:
///Constructor
///Constructor.
///\param have_white Indicates whether white is among the
///provided initial colors (\c true) or not (\c false). If it is true,
///white will be assigned to \c 0.
///\param num The number of the allocated colors. If it is \c -1,
///the default color configuration is set up (26 color plus optionaly the
///white). If \c num is less then 26/27 then the default color
///list is cut. Otherwise the color list is filled repeatedly with
///the default color list. (The colors can be changed later on.)
Palette(bool have_white=false,int num=-1)
{
if (num==0) return;
do {
if(have_white) colors.push_back(Color(1,1,1));
colors.push_back(Color(0,0,0));
colors.push_back(Color(1,0,0));
colors.push_back(Color(0,1,0));
colors.push_back(Color(0,0,1));
colors.push_back(Color(1,1,0));
colors.push_back(Color(1,0,1));
colors.push_back(Color(0,1,1));
colors.push_back(Color(.5,0,0));
colors.push_back(Color(0,.5,0));
colors.push_back(Color(0,0,.5));
colors.push_back(Color(.5,.5,0));
colors.push_back(Color(.5,0,.5));
colors.push_back(Color(0,.5,.5));
colors.push_back(Color(.5,.5,.5));
colors.push_back(Color(1,.5,.5));
colors.push_back(Color(.5,1,.5));
colors.push_back(Color(.5,.5,1));
colors.push_back(Color(1,1,.5));
colors.push_back(Color(1,.5,1));
colors.push_back(Color(.5,1,1));
colors.push_back(Color(1,.5,0));
colors.push_back(Color(.5,1,0));
colors.push_back(Color(1,0,.5));
colors.push_back(Color(0,1,.5));
colors.push_back(Color(0,.5,1));
colors.push_back(Color(.5,0,1));
} while(int(colors.size())<num);
if(num>=0) colors.resize(num);
}
///\e
Color &operator[](int i)
{
return colors[i%colors.size()];
}
///\e
const Color &operator[](int i) const
{
return colors[i%colors.size()];
}
///\e
void set(int i,const Color &c)
{
colors[i%colors.size()]=c;
}
///Adds a new color to the end of the color list.
void add(const Color &c)
{
colors.push_back(c);
}
///Sets the number of the existing colors.
void resize(int s) { colors.resize(s);}
///Returns the number of the existing colors.
int size() const { return int(colors.size());}
};
///Returns a visibly distinct \ref Color
///Returns a \ref Color which is as different from the given parameter
///as it is possible.
inline Color distantColor(const Color &c)
{
return Color(c.red()<.5?1:0,c.green()<.5?1:0,c.blue()<.5?1:0);
}
///Returns black for light colors and white for the dark ones.
///Returns black for light colors and white for the dark ones.
inline Color distantBW(const Color &c){
return (.2125*c.red()+.7154*c.green()+.0721*c.blue())<.5 ? WHITE : BLACK;
}
/// @}
} //END OF NAMESPACE LEMON
#endif // LEMON_COLOR_H

View File

@@ -0,0 +1,77 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2013
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
// The contents of this file was inspired by the concept checking
// utility of the BOOST library (http://www.boost.org).
///\file
///\brief Basic utilities for concept checking.
///
#ifndef LEMON_CONCEPT_CHECK_H
#define LEMON_CONCEPT_CHECK_H
namespace lemon {
/*
"inline" is used for ignore_unused_variable_warning()
and function_requires() to make sure there is no
overtarget with g++.
*/
template <class T> inline void ignore_unused_variable_warning(const T&) { }
template <class T1, class T2>
inline void ignore_unused_variable_warning(const T1&, const T2&) { }
template <class T1, class T2, class T3>
inline void ignore_unused_variable_warning(const T1&, const T2&,
const T3&) { }
template <class T1, class T2, class T3, class T4>
inline void ignore_unused_variable_warning(const T1&, const T2&,
const T3&, const T4&) { }
template <class T1, class T2, class T3, class T4, class T5>
inline void ignore_unused_variable_warning(const T1&, const T2&,
const T3&, const T4&,
const T5&) { }
template <class T1, class T2, class T3, class T4, class T5, class T6>
inline void ignore_unused_variable_warning(const T1&, const T2&,
const T3&, const T4&,
const T5&, const T6&) { }
///\e
template <class Concept>
inline void function_requires()
{
#if !defined(NDEBUG)
void (Concept::*x)() = & Concept::constraints;
::lemon::ignore_unused_variable_warning(x);
#endif
}
///\e
template <typename Concept, typename Type>
inline void checkConcept() {
#if !defined(NDEBUG)
typedef typename Concept::template Constraints<Type> ConceptCheck;
void (ConceptCheck::*x)() = & ConceptCheck::constraints;
::lemon::ignore_unused_variable_warning(x);
#endif
}
} // namespace lemon
#endif // LEMON_CONCEPT_CHECK_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,491 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2013
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
#ifndef LEMON_CONCEPTS_DIGRAPH_H
#define LEMON_CONCEPTS_DIGRAPH_H
///\ingroup graph_concepts
///\file
///\brief The concept of directed graphs.
#include <lemon/core.h>
#include <lemon/concepts/maps.h>
#include <lemon/concept_check.h>
#include <lemon/concepts/graph_components.h>
namespace lemon {
namespace concepts {
/// \ingroup graph_concepts
///
/// \brief Class describing the concept of directed graphs.
///
/// This class describes the common interface of all directed
/// graphs (digraphs).
///
/// Like all concept classes, it only provides an interface
/// without any sensible implementation. So any general algorithm for
/// directed graphs should compile with this class, but it will not
/// run properly, of course.
/// An actual digraph implementation like \ref ListDigraph or
/// \ref SmartDigraph may have additional functionality.
///
/// \sa Graph
class Digraph {
private:
/// Diraphs are \e not copy constructible. Use DigraphCopy instead.
Digraph(const Digraph &) {}
/// \brief Assignment of a digraph to another one is \e not allowed.
/// Use DigraphCopy instead.
void operator=(const Digraph &) {}
public:
/// Default constructor.
Digraph() { }
/// The node type of the digraph
/// This class identifies a node of the digraph. It also serves
/// as a base class of the node iterators,
/// thus they convert to this type.
class Node {
public:
/// Default constructor
/// Default constructor.
/// \warning It sets the object to an undefined value.
Node() { }
/// Copy constructor.
/// Copy constructor.
///
Node(const Node&) { }
/// %Invalid constructor \& conversion.
/// Initializes the object to be invalid.
/// \sa Invalid for more details.
Node(Invalid) { }
/// Equality operator
/// Equality operator.
///
/// Two iterators are equal if and only if they point to the
/// same object or both are \c INVALID.
bool operator==(Node) const { return true; }
/// Inequality operator
/// Inequality operator.
bool operator!=(Node) const { return true; }
/// Artificial ordering operator.
/// Artificial ordering operator.
///
/// \note This operator only has to define some strict ordering of
/// the nodes; this order has nothing to do with the iteration
/// ordering of the nodes.
bool operator<(Node) const { return false; }
};
/// Iterator class for the nodes.
/// This iterator goes through each node of the digraph.
/// Its usage is quite simple, for example, you can count the number
/// of nodes in a digraph \c g of type \c %Digraph like this:
///\code
/// int count=0;
/// for (Digraph::NodeIt n(g); n!=INVALID; ++n) ++count;
///\endcode
class NodeIt : public Node {
public:
/// Default constructor
/// Default constructor.
/// \warning It sets the iterator to an undefined value.
NodeIt() { }
/// Copy constructor.
/// Copy constructor.
///
NodeIt(const NodeIt& n) : Node(n) { }
/// %Invalid constructor \& conversion.
/// Initializes the iterator to be invalid.
/// \sa Invalid for more details.
NodeIt(Invalid) { }
/// Sets the iterator to the first node.
/// Sets the iterator to the first node of the given digraph.
///
explicit NodeIt(const Digraph&) { }
/// Sets the iterator to the given node.
/// Sets the iterator to the given node of the given digraph.
///
NodeIt(const Digraph&, const Node&) { }
/// Next node.
/// Assign the iterator to the next node.
///
NodeIt& operator++() { return *this; }
};
/// The arc type of the digraph
/// This class identifies an arc of the digraph. It also serves
/// as a base class of the arc iterators,
/// thus they will convert to this type.
class Arc {
public:
/// Default constructor
/// Default constructor.
/// \warning It sets the object to an undefined value.
Arc() { }
/// Copy constructor.
/// Copy constructor.
///
Arc(const Arc&) { }
/// %Invalid constructor \& conversion.
/// Initializes the object to be invalid.
/// \sa Invalid for more details.
Arc(Invalid) { }
/// Equality operator
/// Equality operator.
///
/// Two iterators are equal if and only if they point to the
/// same object or both are \c INVALID.
bool operator==(Arc) const { return true; }
/// Inequality operator
/// Inequality operator.
bool operator!=(Arc) const { return true; }
/// Artificial ordering operator.
/// Artificial ordering operator.
///
/// \note This operator only has to define some strict ordering of
/// the arcs; this order has nothing to do with the iteration
/// ordering of the arcs.
bool operator<(Arc) const { return false; }
};
/// Iterator class for the outgoing arcs of a node.
/// This iterator goes trough the \e outgoing arcs of a certain node
/// of a digraph.
/// Its usage is quite simple, for example, you can count the number
/// of outgoing arcs of a node \c n
/// in a digraph \c g of type \c %Digraph as follows.
///\code
/// int count=0;
/// for (Digraph::OutArcIt a(g, n); a!=INVALID; ++a) ++count;
///\endcode
class OutArcIt : public Arc {
public:
/// Default constructor
/// Default constructor.
/// \warning It sets the iterator to an undefined value.
OutArcIt() { }
/// Copy constructor.
/// Copy constructor.
///
OutArcIt(const OutArcIt& e) : Arc(e) { }
/// %Invalid constructor \& conversion.
/// Initializes the iterator to be invalid.
/// \sa Invalid for more details.
OutArcIt(Invalid) { }
/// Sets the iterator to the first outgoing arc.
/// Sets the iterator to the first outgoing arc of the given node.
///
OutArcIt(const Digraph&, const Node&) { }
/// Sets the iterator to the given arc.
/// Sets the iterator to the given arc of the given digraph.
///
OutArcIt(const Digraph&, const Arc&) { }
/// Next outgoing arc
/// Assign the iterator to the next
/// outgoing arc of the corresponding node.
OutArcIt& operator++() { return *this; }
};
/// Iterator class for the incoming arcs of a node.
/// This iterator goes trough the \e incoming arcs of a certain node
/// of a digraph.
/// Its usage is quite simple, for example, you can count the number
/// of incoming arcs of a node \c n
/// in a digraph \c g of type \c %Digraph as follows.
///\code
/// int count=0;
/// for(Digraph::InArcIt a(g, n); a!=INVALID; ++a) ++count;
///\endcode
class InArcIt : public Arc {
public:
/// Default constructor
/// Default constructor.
/// \warning It sets the iterator to an undefined value.
InArcIt() { }
/// Copy constructor.
/// Copy constructor.
///
InArcIt(const InArcIt& e) : Arc(e) { }
/// %Invalid constructor \& conversion.
/// Initializes the iterator to be invalid.
/// \sa Invalid for more details.
InArcIt(Invalid) { }
/// Sets the iterator to the first incoming arc.
/// Sets the iterator to the first incoming arc of the given node.
///
InArcIt(const Digraph&, const Node&) { }
/// Sets the iterator to the given arc.
/// Sets the iterator to the given arc of the given digraph.
///
InArcIt(const Digraph&, const Arc&) { }
/// Next incoming arc
/// Assign the iterator to the next
/// incoming arc of the corresponding node.
InArcIt& operator++() { return *this; }
};
/// Iterator class for the arcs.
/// This iterator goes through each arc of the digraph.
/// Its usage is quite simple, for example, you can count the number
/// of arcs in a digraph \c g of type \c %Digraph as follows:
///\code
/// int count=0;
/// for(Digraph::ArcIt a(g); a!=INVALID; ++a) ++count;
///\endcode
class ArcIt : public Arc {
public:
/// Default constructor
/// Default constructor.
/// \warning It sets the iterator to an undefined value.
ArcIt() { }
/// Copy constructor.
/// Copy constructor.
///
ArcIt(const ArcIt& e) : Arc(e) { }
/// %Invalid constructor \& conversion.
/// Initializes the iterator to be invalid.
/// \sa Invalid for more details.
ArcIt(Invalid) { }
/// Sets the iterator to the first arc.
/// Sets the iterator to the first arc of the given digraph.
///
explicit ArcIt(const Digraph& g) {
::lemon::ignore_unused_variable_warning(g);
}
/// Sets the iterator to the given arc.
/// Sets the iterator to the given arc of the given digraph.
///
ArcIt(const Digraph&, const Arc&) { }
/// Next arc
/// Assign the iterator to the next arc.
///
ArcIt& operator++() { return *this; }
};
/// \brief The source node of the arc.
///
/// Returns the source node of the given arc.
Node source(Arc) const { return INVALID; }
/// \brief The target node of the arc.
///
/// Returns the target node of the given arc.
Node target(Arc) const { return INVALID; }
/// \brief The ID of the node.
///
/// Returns the ID of the given node.
int id(Node) const { return -1; }
/// \brief The ID of the arc.
///
/// Returns the ID of the given arc.
int id(Arc) const { return -1; }
/// \brief The node with the given ID.
///
/// Returns the node with the given ID.
/// \pre The argument should be a valid node ID in the digraph.
Node nodeFromId(int) const { return INVALID; }
/// \brief The arc with the given ID.
///
/// Returns the arc with the given ID.
/// \pre The argument should be a valid arc ID in the digraph.
Arc arcFromId(int) const { return INVALID; }
/// \brief An upper bound on the node IDs.
///
/// Returns an upper bound on the node IDs.
int maxNodeId() const { return -1; }
/// \brief An upper bound on the arc IDs.
///
/// Returns an upper bound on the arc IDs.
int maxArcId() const { return -1; }
void first(Node&) const {}
void next(Node&) const {}
void first(Arc&) const {}
void next(Arc&) const {}
void firstIn(Arc&, const Node&) const {}
void nextIn(Arc&) const {}
void firstOut(Arc&, const Node&) const {}
void nextOut(Arc&) const {}
// The second parameter is dummy.
Node fromId(int, Node) const { return INVALID; }
// The second parameter is dummy.
Arc fromId(int, Arc) const { return INVALID; }
// Dummy parameter.
int maxId(Node) const { return -1; }
// Dummy parameter.
int maxId(Arc) const { return -1; }
/// \brief The opposite node on the arc.
///
/// Returns the opposite node on the given arc.
Node oppositeNode(Node, Arc) const { return INVALID; }
/// \brief The base node of the iterator.
///
/// Returns the base node of the given outgoing arc iterator
/// (i.e. the source node of the corresponding arc).
Node baseNode(OutArcIt) const { return INVALID; }
/// \brief The running node of the iterator.
///
/// Returns the running node of the given outgoing arc iterator
/// (i.e. the target node of the corresponding arc).
Node runningNode(OutArcIt) const { return INVALID; }
/// \brief The base node of the iterator.
///
/// Returns the base node of the given incoming arc iterator
/// (i.e. the target node of the corresponding arc).
Node baseNode(InArcIt) const { return INVALID; }
/// \brief The running node of the iterator.
///
/// Returns the running node of the given incoming arc iterator
/// (i.e. the source node of the corresponding arc).
Node runningNode(InArcIt) const { return INVALID; }
/// \brief Standard graph map type for the nodes.
///
/// Standard graph map type for the nodes.
/// It conforms to the ReferenceMap concept.
template<class T>
class NodeMap : public ReferenceMap<Node, T, T&, const T&> {
public:
/// Constructor
explicit NodeMap(const Digraph&) { }
/// Constructor with given initial value
NodeMap(const Digraph&, T) { }
private:
///Copy constructor
NodeMap(const NodeMap& nm) :
ReferenceMap<Node, T, T&, const T&>(nm) { }
///Assignment operator
template <typename CMap>
NodeMap& operator=(const CMap&) {
checkConcept<ReadMap<Node, T>, CMap>();
return *this;
}
};
/// \brief Standard graph map type for the arcs.
///
/// Standard graph map type for the arcs.
/// It conforms to the ReferenceMap concept.
template<class T>
class ArcMap : public ReferenceMap<Arc, T, T&, const T&> {
public:
/// Constructor
explicit ArcMap(const Digraph&) { }
/// Constructor with given initial value
ArcMap(const Digraph&, T) { }
private:
///Copy constructor
ArcMap(const ArcMap& em) :
ReferenceMap<Arc, T, T&, const T&>(em) { }
///Assignment operator
template <typename CMap>
ArcMap& operator=(const CMap&) {
checkConcept<ReadMap<Arc, T>, CMap>();
return *this;
}
};
template <typename _Digraph>
struct Constraints {
void constraints() {
checkConcept<BaseDigraphComponent, _Digraph>();
checkConcept<IterableDigraphComponent<>, _Digraph>();
checkConcept<IDableDigraphComponent<>, _Digraph>();
checkConcept<MappableDigraphComponent<>, _Digraph>();
}
};
};
} //namespace concepts
} //namespace lemon
#endif

View File

@@ -0,0 +1,788 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2013
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
///\ingroup graph_concepts
///\file
///\brief The concept of undirected graphs.
#ifndef LEMON_CONCEPTS_GRAPH_H
#define LEMON_CONCEPTS_GRAPH_H
#include <lemon/concepts/graph_components.h>
#include <lemon/concepts/maps.h>
#include <lemon/concept_check.h>
#include <lemon/core.h>
namespace lemon {
namespace concepts {
/// \ingroup graph_concepts
///
/// \brief Class describing the concept of undirected graphs.
///
/// This class describes the common interface of all undirected
/// graphs.
///
/// Like all concept classes, it only provides an interface
/// without any sensible implementation. So any general algorithm for
/// undirected graphs should compile with this class, but it will not
/// run properly, of course.
/// An actual graph implementation like \ref ListGraph or
/// \ref SmartGraph may have additional functionality.
///
/// The undirected graphs also fulfill the concept of \ref Digraph
/// "directed graphs", since each edge can also be regarded as two
/// oppositely directed arcs.
/// Undirected graphs provide an Edge type for the undirected edges and
/// an Arc type for the directed arcs. The Arc type is convertible to
/// Edge or inherited from it, i.e. the corresponding edge can be
/// obtained from an arc.
/// EdgeIt and EdgeMap classes can be used for the edges, while ArcIt
/// and ArcMap classes can be used for the arcs (just like in digraphs).
/// Both InArcIt and OutArcIt iterates on the same edges but with
/// opposite direction. IncEdgeIt also iterates on the same edges
/// as OutArcIt and InArcIt, but it is not convertible to Arc,
/// only to Edge.
///
/// In LEMON, each undirected edge has an inherent orientation.
/// Thus it can defined if an arc is forward or backward oriented in
/// an undirected graph with respect to this default oriantation of
/// the represented edge.
/// With the direction() and direct() functions the direction
/// of an arc can be obtained and set, respectively.
///
/// Only nodes and edges can be added to or removed from an undirected
/// graph and the corresponding arcs are added or removed automatically.
///
/// \sa Digraph
class Graph {
private:
/// Graphs are \e not copy constructible. Use GraphCopy instead.
Graph(const Graph&) {}
/// \brief Assignment of a graph to another one is \e not allowed.
/// Use GraphCopy instead.
void operator=(const Graph&) {}
public:
/// Default constructor.
Graph() {}
/// \brief Undirected graphs should be tagged with \c UndirectedTag.
///
/// Undirected graphs should be tagged with \c UndirectedTag.
///
/// This tag helps the \c enable_if technics to make compile time
/// specializations for undirected graphs.
typedef True UndirectedTag;
/// The node type of the graph
/// This class identifies a node of the graph. It also serves
/// as a base class of the node iterators,
/// thus they convert to this type.
class Node {
public:
/// Default constructor
/// Default constructor.
/// \warning It sets the object to an undefined value.
Node() { }
/// Copy constructor.
/// Copy constructor.
///
Node(const Node&) { }
/// %Invalid constructor \& conversion.
/// Initializes the object to be invalid.
/// \sa Invalid for more details.
Node(Invalid) { }
/// Equality operator
/// Equality operator.
///
/// Two iterators are equal if and only if they point to the
/// same object or both are \c INVALID.
bool operator==(Node) const { return true; }
/// Inequality operator
/// Inequality operator.
bool operator!=(Node) const { return true; }
/// Artificial ordering operator.
/// Artificial ordering operator.
///
/// \note This operator only has to define some strict ordering of
/// the items; this order has nothing to do with the iteration
/// ordering of the items.
bool operator<(Node) const { return false; }
};
/// Iterator class for the nodes.
/// This iterator goes through each node of the graph.
/// Its usage is quite simple, for example, you can count the number
/// of nodes in a graph \c g of type \c %Graph like this:
///\code
/// int count=0;
/// for (Graph::NodeIt n(g); n!=INVALID; ++n) ++count;
///\endcode
class NodeIt : public Node {
public:
/// Default constructor
/// Default constructor.
/// \warning It sets the iterator to an undefined value.
NodeIt() { }
/// Copy constructor.
/// Copy constructor.
///
NodeIt(const NodeIt& n) : Node(n) { }
/// %Invalid constructor \& conversion.
/// Initializes the iterator to be invalid.
/// \sa Invalid for more details.
NodeIt(Invalid) { }
/// Sets the iterator to the first node.
/// Sets the iterator to the first node of the given digraph.
///
explicit NodeIt(const Graph&) { }
/// Sets the iterator to the given node.
/// Sets the iterator to the given node of the given digraph.
///
NodeIt(const Graph&, const Node&) { }
/// Next node.
/// Assign the iterator to the next node.
///
NodeIt& operator++() { return *this; }
};
/// The edge type of the graph
/// This class identifies an edge of the graph. It also serves
/// as a base class of the edge iterators,
/// thus they will convert to this type.
class Edge {
public:
/// Default constructor
/// Default constructor.
/// \warning It sets the object to an undefined value.
Edge() { }
/// Copy constructor.
/// Copy constructor.
///
Edge(const Edge&) { }
/// %Invalid constructor \& conversion.
/// Initializes the object to be invalid.
/// \sa Invalid for more details.
Edge(Invalid) { }
/// Equality operator
/// Equality operator.
///
/// Two iterators are equal if and only if they point to the
/// same object or both are \c INVALID.
bool operator==(Edge) const { return true; }
/// Inequality operator
/// Inequality operator.
bool operator!=(Edge) const { return true; }
/// Artificial ordering operator.
/// Artificial ordering operator.
///
/// \note This operator only has to define some strict ordering of
/// the edges; this order has nothing to do with the iteration
/// ordering of the edges.
bool operator<(Edge) const { return false; }
};
/// Iterator class for the edges.
/// This iterator goes through each edge of the graph.
/// Its usage is quite simple, for example, you can count the number
/// of edges in a graph \c g of type \c %Graph as follows:
///\code
/// int count=0;
/// for(Graph::EdgeIt e(g); e!=INVALID; ++e) ++count;
///\endcode
class EdgeIt : public Edge {
public:
/// Default constructor
/// Default constructor.
/// \warning It sets the iterator to an undefined value.
EdgeIt() { }
/// Copy constructor.
/// Copy constructor.
///
EdgeIt(const EdgeIt& e) : Edge(e) { }
/// %Invalid constructor \& conversion.
/// Initializes the iterator to be invalid.
/// \sa Invalid for more details.
EdgeIt(Invalid) { }
/// Sets the iterator to the first edge.
/// Sets the iterator to the first edge of the given graph.
///
explicit EdgeIt(const Graph&) { }
/// Sets the iterator to the given edge.
/// Sets the iterator to the given edge of the given graph.
///
EdgeIt(const Graph&, const Edge&) { }
/// Next edge
/// Assign the iterator to the next edge.
///
EdgeIt& operator++() { return *this; }
};
/// Iterator class for the incident edges of a node.
/// This iterator goes trough the incident undirected edges
/// of a certain node of a graph.
/// Its usage is quite simple, for example, you can compute the
/// degree (i.e. the number of incident edges) of a node \c n
/// in a graph \c g of type \c %Graph as follows.
///
///\code
/// int count=0;
/// for(Graph::IncEdgeIt e(g, n); e!=INVALID; ++e) ++count;
///\endcode
///
/// \warning Loop edges will be iterated twice.
class IncEdgeIt : public Edge {
public:
/// Default constructor
/// Default constructor.
/// \warning It sets the iterator to an undefined value.
IncEdgeIt() { }
/// Copy constructor.
/// Copy constructor.
///
IncEdgeIt(const IncEdgeIt& e) : Edge(e) { }
/// %Invalid constructor \& conversion.
/// Initializes the iterator to be invalid.
/// \sa Invalid for more details.
IncEdgeIt(Invalid) { }
/// Sets the iterator to the first incident edge.
/// Sets the iterator to the first incident edge of the given node.
///
IncEdgeIt(const Graph&, const Node&) { }
/// Sets the iterator to the given edge.
/// Sets the iterator to the given edge of the given graph.
///
IncEdgeIt(const Graph&, const Edge&) { }
/// Next incident edge
/// Assign the iterator to the next incident edge
/// of the corresponding node.
IncEdgeIt& operator++() { return *this; }
};
/// The arc type of the graph
/// This class identifies a directed arc of the graph. It also serves
/// as a base class of the arc iterators,
/// thus they will convert to this type.
class Arc {
public:
/// Default constructor
/// Default constructor.
/// \warning It sets the object to an undefined value.
Arc() { }
/// Copy constructor.
/// Copy constructor.
///
Arc(const Arc&) { }
/// %Invalid constructor \& conversion.
/// Initializes the object to be invalid.
/// \sa Invalid for more details.
Arc(Invalid) { }
/// Equality operator
/// Equality operator.
///
/// Two iterators are equal if and only if they point to the
/// same object or both are \c INVALID.
bool operator==(Arc) const { return true; }
/// Inequality operator
/// Inequality operator.
bool operator!=(Arc) const { return true; }
/// Artificial ordering operator.
/// Artificial ordering operator.
///
/// \note This operator only has to define some strict ordering of
/// the arcs; this order has nothing to do with the iteration
/// ordering of the arcs.
bool operator<(Arc) const { return false; }
/// Converison to \c Edge
/// Converison to \c Edge.
///
operator Edge() const { return Edge(); }
};
/// Iterator class for the arcs.
/// This iterator goes through each directed arc of the graph.
/// Its usage is quite simple, for example, you can count the number
/// of arcs in a graph \c g of type \c %Graph as follows:
///\code
/// int count=0;
/// for(Graph::ArcIt a(g); a!=INVALID; ++a) ++count;
///\endcode
class ArcIt : public Arc {
public:
/// Default constructor
/// Default constructor.
/// \warning It sets the iterator to an undefined value.
ArcIt() { }
/// Copy constructor.
/// Copy constructor.
///
ArcIt(const ArcIt& e) : Arc(e) { }
/// %Invalid constructor \& conversion.
/// Initializes the iterator to be invalid.
/// \sa Invalid for more details.
ArcIt(Invalid) { }
/// Sets the iterator to the first arc.
/// Sets the iterator to the first arc of the given graph.
///
explicit ArcIt(const Graph &g) {
::lemon::ignore_unused_variable_warning(g);
}
/// Sets the iterator to the given arc.
/// Sets the iterator to the given arc of the given graph.
///
ArcIt(const Graph&, const Arc&) { }
/// Next arc
/// Assign the iterator to the next arc.
///
ArcIt& operator++() { return *this; }
};
/// Iterator class for the outgoing arcs of a node.
/// This iterator goes trough the \e outgoing directed arcs of a
/// certain node of a graph.
/// Its usage is quite simple, for example, you can count the number
/// of outgoing arcs of a node \c n
/// in a graph \c g of type \c %Graph as follows.
///\code
/// int count=0;
/// for (Digraph::OutArcIt a(g, n); a!=INVALID; ++a) ++count;
///\endcode
class OutArcIt : public Arc {
public:
/// Default constructor
/// Default constructor.
/// \warning It sets the iterator to an undefined value.
OutArcIt() { }
/// Copy constructor.
/// Copy constructor.
///
OutArcIt(const OutArcIt& e) : Arc(e) { }
/// %Invalid constructor \& conversion.
/// Initializes the iterator to be invalid.
/// \sa Invalid for more details.
OutArcIt(Invalid) { }
/// Sets the iterator to the first outgoing arc.
/// Sets the iterator to the first outgoing arc of the given node.
///
OutArcIt(const Graph& n, const Node& g) {
::lemon::ignore_unused_variable_warning(n);
::lemon::ignore_unused_variable_warning(g);
}
/// Sets the iterator to the given arc.
/// Sets the iterator to the given arc of the given graph.
///
OutArcIt(const Graph&, const Arc&) { }
/// Next outgoing arc
/// Assign the iterator to the next
/// outgoing arc of the corresponding node.
OutArcIt& operator++() { return *this; }
};
/// Iterator class for the incoming arcs of a node.
/// This iterator goes trough the \e incoming directed arcs of a
/// certain node of a graph.
/// Its usage is quite simple, for example, you can count the number
/// of incoming arcs of a node \c n
/// in a graph \c g of type \c %Graph as follows.
///\code
/// int count=0;
/// for (Digraph::InArcIt a(g, n); a!=INVALID; ++a) ++count;
///\endcode
class InArcIt : public Arc {
public:
/// Default constructor
/// Default constructor.
/// \warning It sets the iterator to an undefined value.
InArcIt() { }
/// Copy constructor.
/// Copy constructor.
///
InArcIt(const InArcIt& e) : Arc(e) { }
/// %Invalid constructor \& conversion.
/// Initializes the iterator to be invalid.
/// \sa Invalid for more details.
InArcIt(Invalid) { }
/// Sets the iterator to the first incoming arc.
/// Sets the iterator to the first incoming arc of the given node.
///
InArcIt(const Graph& g, const Node& n) {
::lemon::ignore_unused_variable_warning(n);
::lemon::ignore_unused_variable_warning(g);
}
/// Sets the iterator to the given arc.
/// Sets the iterator to the given arc of the given graph.
///
InArcIt(const Graph&, const Arc&) { }
/// Next incoming arc
/// Assign the iterator to the next
/// incoming arc of the corresponding node.
InArcIt& operator++() { return *this; }
};
/// \brief Standard graph map type for the nodes.
///
/// Standard graph map type for the nodes.
/// It conforms to the ReferenceMap concept.
template<class T>
class NodeMap : public ReferenceMap<Node, T, T&, const T&>
{
public:
/// Constructor
explicit NodeMap(const Graph&) { }
/// Constructor with given initial value
NodeMap(const Graph&, T) { }
private:
///Copy constructor
NodeMap(const NodeMap& nm) :
ReferenceMap<Node, T, T&, const T&>(nm) { }
///Assignment operator
template <typename CMap>
NodeMap& operator=(const CMap&) {
checkConcept<ReadMap<Node, T>, CMap>();
return *this;
}
};
/// \brief Standard graph map type for the arcs.
///
/// Standard graph map type for the arcs.
/// It conforms to the ReferenceMap concept.
template<class T>
class ArcMap : public ReferenceMap<Arc, T, T&, const T&>
{
public:
/// Constructor
explicit ArcMap(const Graph&) { }
/// Constructor with given initial value
ArcMap(const Graph&, T) { }
private:
///Copy constructor
ArcMap(const ArcMap& em) :
ReferenceMap<Arc, T, T&, const T&>(em) { }
///Assignment operator
template <typename CMap>
ArcMap& operator=(const CMap&) {
checkConcept<ReadMap<Arc, T>, CMap>();
return *this;
}
};
/// \brief Standard graph map type for the edges.
///
/// Standard graph map type for the edges.
/// It conforms to the ReferenceMap concept.
template<class T>
class EdgeMap : public ReferenceMap<Edge, T, T&, const T&>
{
public:
/// Constructor
explicit EdgeMap(const Graph&) { }
/// Constructor with given initial value
EdgeMap(const Graph&, T) { }
private:
///Copy constructor
EdgeMap(const EdgeMap& em) :
ReferenceMap<Edge, T, T&, const T&>(em) {}
///Assignment operator
template <typename CMap>
EdgeMap& operator=(const CMap&) {
checkConcept<ReadMap<Edge, T>, CMap>();
return *this;
}
};
/// \brief The first node of the edge.
///
/// Returns the first node of the given edge.
///
/// Edges don't have source and target nodes, however, methods
/// u() and v() are used to query the two end-nodes of an edge.
/// The orientation of an edge that arises this way is called
/// the inherent direction, it is used to define the default
/// direction for the corresponding arcs.
/// \sa v()
/// \sa direction()
Node u(Edge) const { return INVALID; }
/// \brief The second node of the edge.
///
/// Returns the second node of the given edge.
///
/// Edges don't have source and target nodes, however, methods
/// u() and v() are used to query the two end-nodes of an edge.
/// The orientation of an edge that arises this way is called
/// the inherent direction, it is used to define the default
/// direction for the corresponding arcs.
/// \sa u()
/// \sa direction()
Node v(Edge) const { return INVALID; }
/// \brief The source node of the arc.
///
/// Returns the source node of the given arc.
Node source(Arc) const { return INVALID; }
/// \brief The target node of the arc.
///
/// Returns the target node of the given arc.
Node target(Arc) const { return INVALID; }
/// \brief The ID of the node.
///
/// Returns the ID of the given node.
int id(Node) const { return -1; }
/// \brief The ID of the edge.
///
/// Returns the ID of the given edge.
int id(Edge) const { return -1; }
/// \brief The ID of the arc.
///
/// Returns the ID of the given arc.
int id(Arc) const { return -1; }
/// \brief The node with the given ID.
///
/// Returns the node with the given ID.
/// \pre The argument should be a valid node ID in the graph.
Node nodeFromId(int) const { return INVALID; }
/// \brief The edge with the given ID.
///
/// Returns the edge with the given ID.
/// \pre The argument should be a valid edge ID in the graph.
Edge edgeFromId(int) const { return INVALID; }
/// \brief The arc with the given ID.
///
/// Returns the arc with the given ID.
/// \pre The argument should be a valid arc ID in the graph.
Arc arcFromId(int) const { return INVALID; }
/// \brief An upper bound on the node IDs.
///
/// Returns an upper bound on the node IDs.
int maxNodeId() const { return -1; }
/// \brief An upper bound on the edge IDs.
///
/// Returns an upper bound on the edge IDs.
int maxEdgeId() const { return -1; }
/// \brief An upper bound on the arc IDs.
///
/// Returns an upper bound on the arc IDs.
int maxArcId() const { return -1; }
/// \brief The direction of the arc.
///
/// Returns \c true if the direction of the given arc is the same as
/// the inherent orientation of the represented edge.
bool direction(Arc) const { return true; }
/// \brief Direct the edge.
///
/// Direct the given edge. The returned arc
/// represents the given edge and its direction comes
/// from the bool parameter. If it is \c true, then the direction
/// of the arc is the same as the inherent orientation of the edge.
Arc direct(Edge, bool) const {
return INVALID;
}
/// \brief Direct the edge.
///
/// Direct the given edge. The returned arc represents the given
/// edge and its source node is the given node.
Arc direct(Edge, Node) const {
return INVALID;
}
/// \brief The oppositely directed arc.
///
/// Returns the oppositely directed arc representing the same edge.
Arc oppositeArc(Arc) const { return INVALID; }
/// \brief The opposite node on the edge.
///
/// Returns the opposite node on the given edge.
Node oppositeNode(Node, Edge) const { return INVALID; }
void first(Node&) const {}
void next(Node&) const {}
void first(Edge&) const {}
void next(Edge&) const {}
void first(Arc&) const {}
void next(Arc&) const {}
void firstOut(Arc&, Node) const {}
void nextOut(Arc&) const {}
void firstIn(Arc&, Node) const {}
void nextIn(Arc&) const {}
void firstInc(Edge &, bool &, const Node &) const {}
void nextInc(Edge &, bool &) const {}
// The second parameter is dummy.
Node fromId(int, Node) const { return INVALID; }
// The second parameter is dummy.
Edge fromId(int, Edge) const { return INVALID; }
// The second parameter is dummy.
Arc fromId(int, Arc) const { return INVALID; }
// Dummy parameter.
int maxId(Node) const { return -1; }
// Dummy parameter.
int maxId(Edge) const { return -1; }
// Dummy parameter.
int maxId(Arc) const { return -1; }
/// \brief The base node of the iterator.
///
/// Returns the base node of the given incident edge iterator.
Node baseNode(IncEdgeIt) const { return INVALID; }
/// \brief The running node of the iterator.
///
/// Returns the running node of the given incident edge iterator.
Node runningNode(IncEdgeIt) const { return INVALID; }
/// \brief The base node of the iterator.
///
/// Returns the base node of the given outgoing arc iterator
/// (i.e. the source node of the corresponding arc).
Node baseNode(OutArcIt) const { return INVALID; }
/// \brief The running node of the iterator.
///
/// Returns the running node of the given outgoing arc iterator
/// (i.e. the target node of the corresponding arc).
Node runningNode(OutArcIt) const { return INVALID; }
/// \brief The base node of the iterator.
///
/// Returns the base node of the given incoming arc iterator
/// (i.e. the target node of the corresponding arc).
Node baseNode(InArcIt) const { return INVALID; }
/// \brief The running node of the iterator.
///
/// Returns the running node of the given incoming arc iterator
/// (i.e. the source node of the corresponding arc).
Node runningNode(InArcIt) const { return INVALID; }
template <typename _Graph>
struct Constraints {
void constraints() {
checkConcept<BaseGraphComponent, _Graph>();
checkConcept<IterableGraphComponent<>, _Graph>();
checkConcept<IDableGraphComponent<>, _Graph>();
checkConcept<MappableGraphComponent<>, _Graph>();
}
};
};
}
}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,324 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2013
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
#ifndef LEMON_CONCEPTS_HEAP_H
#define LEMON_CONCEPTS_HEAP_H
///\ingroup concept
///\file
///\brief The concept of heaps.
#include <lemon/core.h>
#include <lemon/concept_check.h>
namespace lemon {
namespace concepts {
/// \addtogroup concept
/// @{
/// \brief The heap concept.
///
/// This concept class describes the main interface of heaps.
/// The various \ref heaps "heap structures" are efficient
/// implementations of the abstract data type \e priority \e queue.
/// They store items with specified values called \e priorities
/// in such a way that finding and removing the item with minimum
/// priority are efficient. The basic operations are adding and
/// erasing items, changing the priority of an item, etc.
///
/// Heaps are crucial in several algorithms, such as Dijkstra and Prim.
/// Any class that conforms to this concept can be used easily in such
/// algorithms.
///
/// \tparam PR Type of the priorities of the items.
/// \tparam IM A read-writable item map with \c int values, used
/// internally to handle the cross references.
/// \tparam CMP A functor class for comparing the priorities.
/// The default is \c std::less<PR>.
#ifdef DOXYGEN
template <typename PR, typename IM, typename CMP>
#else
template <typename PR, typename IM, typename CMP = std::less<PR> >
#endif
class Heap {
public:
/// Type of the item-int map.
typedef IM ItemIntMap;
/// Type of the priorities.
typedef PR Prio;
/// Type of the items stored in the heap.
typedef typename ItemIntMap::Key Item;
/// \brief Type to represent the states of the items.
///
/// Each item has a state associated to it. It can be "in heap",
/// "pre-heap" or "post-heap". The latter two are indifferent from the
/// heap's point of view, but may be useful to the user.
///
/// The item-int map must be initialized in such way that it assigns
/// \c PRE_HEAP (<tt>-1</tt>) to any element to be put in the heap.
enum State {
IN_HEAP = 0, ///< = 0. The "in heap" state constant.
PRE_HEAP = -1, ///< = -1. The "pre-heap" state constant.
POST_HEAP = -2 ///< = -2. The "post-heap" state constant.
};
/// \brief Constructor.
///
/// Constructor.
/// \param map A map that assigns \c int values to keys of type
/// \c Item. It is used internally by the heap implementations to
/// handle the cross references. The assigned value must be
/// \c PRE_HEAP (<tt>-1</tt>) for each item.
#ifdef DOXYGEN
explicit Heap(ItemIntMap &map) {}
#else
explicit Heap(ItemIntMap&) {}
#endif
/// \brief Constructor.
///
/// Constructor.
/// \param map A map that assigns \c int values to keys of type
/// \c Item. It is used internally by the heap implementations to
/// handle the cross references. The assigned value must be
/// \c PRE_HEAP (<tt>-1</tt>) for each item.
/// \param comp The function object used for comparing the priorities.
#ifdef DOXYGEN
explicit Heap(ItemIntMap &map, const CMP &comp) {}
#else
explicit Heap(ItemIntMap&, const CMP&) {}
#endif
/// \brief The number of items stored in the heap.
///
/// This function returns the number of items stored in the heap.
int size() const { return 0; }
/// \brief Check if the heap is empty.
///
/// This function returns \c true if the heap is empty.
bool empty() const { return false; }
/// \brief Make the heap empty.
///
/// This functon makes the heap empty.
/// It does not change the cross reference map. If you want to reuse
/// a heap that is not surely empty, you should first clear it and
/// then you should set the cross reference map to \c PRE_HEAP
/// for each item.
void clear() {}
/// \brief Insert an item into the heap with the given priority.
///
/// This function inserts the given item into the heap with the
/// given priority.
/// \param i The item to insert.
/// \param p The priority of the item.
/// \pre \e i must not be stored in the heap.
#ifdef DOXYGEN
void push(const Item &i, const Prio &p) {}
#else
void push(const Item&, const Prio&) {}
#endif
/// \brief Return the item having minimum priority.
///
/// This function returns the item having minimum priority.
/// \pre The heap must be non-empty.
Item top() const { return Item(); }
/// \brief The minimum priority.
///
/// This function returns the minimum priority.
/// \pre The heap must be non-empty.
Prio prio() const { return Prio(); }
/// \brief Remove the item having minimum priority.
///
/// This function removes the item having minimum priority.
/// \pre The heap must be non-empty.
void pop() {}
/// \brief Remove the given item from the heap.
///
/// This function removes the given item from the heap if it is
/// already stored.
/// \param i The item to delete.
/// \pre \e i must be in the heap.
#ifdef DOXYGEN
void erase(const Item &i) {}
#else
void erase(const Item&) {}
#endif
/// \brief The priority of the given item.
///
/// This function returns the priority of the given item.
/// \param i The item.
/// \pre \e i must be in the heap.
#ifdef DOXYGEN
Prio operator[](const Item &i) const {}
#else
Prio operator[](const Item&) const { return Prio(); }
#endif
/// \brief Set the priority of an item or insert it, if it is
/// not stored in the heap.
///
/// This method sets the priority of the given item if it is
/// already stored in the heap. Otherwise it inserts the given
/// item into the heap with the given priority.
///
/// \param i The item.
/// \param p The priority.
#ifdef DOXYGEN
void set(const Item &i, const Prio &p) {}
#else
void set(const Item&, const Prio&) {}
#endif
/// \brief Decrease the priority of an item to the given value.
///
/// This function decreases the priority of an item to the given value.
/// \param i The item.
/// \param p The priority.
/// \pre \e i must be stored in the heap with priority at least \e p.
#ifdef DOXYGEN
void decrease(const Item &i, const Prio &p) {}
#else
void decrease(const Item&, const Prio&) {}
#endif
/// \brief Increase the priority of an item to the given value.
///
/// This function increases the priority of an item to the given value.
/// \param i The item.
/// \param p The priority.
/// \pre \e i must be stored in the heap with priority at most \e p.
#ifdef DOXYGEN
void increase(const Item &i, const Prio &p) {}
#else
void increase(const Item&, const Prio&) {}
#endif
/// \brief Return the state of an item.
///
/// This method returns \c PRE_HEAP if the given item has never
/// been in the heap, \c IN_HEAP if it is in the heap at the moment,
/// and \c POST_HEAP otherwise.
/// In the latter case it is possible that the item will get back
/// to the heap again.
/// \param i The item.
#ifdef DOXYGEN
State state(const Item &i) const {}
#else
State state(const Item&) const { return PRE_HEAP; }
#endif
/// \brief Set the state of an item in the heap.
///
/// This function sets the state of the given item in the heap.
/// It can be used to manually clear the heap when it is important
/// to achive better time complexity.
/// \param i The item.
/// \param st The state. It should not be \c IN_HEAP.
#ifdef DOXYGEN
void state(const Item& i, State st) {}
#else
void state(const Item&, State) {}
#endif
template <typename _Heap>
struct Constraints {
public:
void constraints() {
typedef typename _Heap::Item OwnItem;
typedef typename _Heap::Prio OwnPrio;
typedef typename _Heap::State OwnState;
Item item;
Prio prio;
item=Item();
prio=Prio();
::lemon::ignore_unused_variable_warning(item);
::lemon::ignore_unused_variable_warning(prio);
OwnItem own_item;
OwnPrio own_prio;
OwnState own_state;
own_item=Item();
own_prio=Prio();
::lemon::ignore_unused_variable_warning(own_item);
::lemon::ignore_unused_variable_warning(own_prio);
::lemon::ignore_unused_variable_warning(own_state);
_Heap heap1(map);
_Heap heap2 = heap1;
::lemon::ignore_unused_variable_warning(heap1);
::lemon::ignore_unused_variable_warning(heap2);
int s = heap.size();
::lemon::ignore_unused_variable_warning(s);
bool e = heap.empty();
::lemon::ignore_unused_variable_warning(e);
prio = heap.prio();
item = heap.top();
prio = heap[item];
own_prio = heap.prio();
own_item = heap.top();
own_prio = heap[own_item];
heap.push(item, prio);
heap.push(own_item, own_prio);
heap.pop();
heap.set(item, prio);
heap.decrease(item, prio);
heap.increase(item, prio);
heap.set(own_item, own_prio);
heap.decrease(own_item, own_prio);
heap.increase(own_item, own_prio);
heap.erase(item);
heap.erase(own_item);
heap.clear();
own_state = heap.state(own_item);
heap.state(own_item, own_state);
own_state = _Heap::PRE_HEAP;
own_state = _Heap::IN_HEAP;
own_state = _Heap::POST_HEAP;
}
_Heap& heap;
ItemIntMap& map;
Constraints() {}
};
};
/// @}
} // namespace lemon
}
#endif

View File

@@ -0,0 +1,223 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2013
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
#ifndef LEMON_CONCEPTS_MAPS_H
#define LEMON_CONCEPTS_MAPS_H
#include <lemon/core.h>
#include <lemon/concept_check.h>
///\ingroup map_concepts
///\file
///\brief The concept of maps.
namespace lemon {
namespace concepts {
/// \addtogroup map_concepts
/// @{
/// Readable map concept
/// Readable map concept.
///
template<typename K, typename T>
class ReadMap
{
public:
/// The key type of the map.
typedef K Key;
/// \brief The value type of the map.
/// (The type of objects associated with the keys).
typedef T Value;
/// Returns the value associated with the given key.
Value operator[](const Key &) const {
return *(static_cast<Value *>(0)+1);
}
template<typename _ReadMap>
struct Constraints {
void constraints() {
Value val = m[key];
val = m[key];
typename _ReadMap::Value own_val = m[own_key];
own_val = m[own_key];
::lemon::ignore_unused_variable_warning(key);
::lemon::ignore_unused_variable_warning(val);
::lemon::ignore_unused_variable_warning(own_key);
::lemon::ignore_unused_variable_warning(own_val);
}
const Key& key;
const typename _ReadMap::Key& own_key;
const _ReadMap& m;
Constraints() {}
};
};
/// Writable map concept
/// Writable map concept.
///
template<typename K, typename T>
class WriteMap
{
public:
/// The key type of the map.
typedef K Key;
/// \brief The value type of the map.
/// (The type of objects associated with the keys).
typedef T Value;
/// Sets the value associated with the given key.
void set(const Key &, const Value &) {}
/// Default constructor.
WriteMap() {}
template <typename _WriteMap>
struct Constraints {
void constraints() {
m.set(key, val);
m.set(own_key, own_val);
::lemon::ignore_unused_variable_warning(key);
::lemon::ignore_unused_variable_warning(val);
::lemon::ignore_unused_variable_warning(own_key);
::lemon::ignore_unused_variable_warning(own_val);
}
const Key& key;
const Value& val;
const typename _WriteMap::Key& own_key;
const typename _WriteMap::Value& own_val;
_WriteMap& m;
Constraints() {}
};
};
/// Read/writable map concept
/// Read/writable map concept.
///
template<typename K, typename T>
class ReadWriteMap : public ReadMap<K,T>,
public WriteMap<K,T>
{
public:
/// The key type of the map.
typedef K Key;
/// \brief The value type of the map.
/// (The type of objects associated with the keys).
typedef T Value;
/// Returns the value associated with the given key.
Value operator[](const Key &) const {
Value *r = 0;
return *r;
}
/// Sets the value associated with the given key.
void set(const Key &, const Value &) {}
template<typename _ReadWriteMap>
struct Constraints {
void constraints() {
checkConcept<ReadMap<K, T>, _ReadWriteMap >();
checkConcept<WriteMap<K, T>, _ReadWriteMap >();
}
};
};
/// Dereferable map concept
/// Dereferable map concept.
///
template<typename K, typename T, typename R, typename CR>
class ReferenceMap : public ReadWriteMap<K,T>
{
public:
/// Tag for reference maps.
typedef True ReferenceMapTag;
/// The key type of the map.
typedef K Key;
/// \brief The value type of the map.
/// (The type of objects associated with the keys).
typedef T Value;
/// The reference type of the map.
typedef R Reference;
/// The const reference type of the map.
typedef CR ConstReference;
public:
/// Returns a reference to the value associated with the given key.
Reference operator[](const Key &) {
Value *r = 0;
return *r;
}
/// Returns a const reference to the value associated with the given key.
ConstReference operator[](const Key &) const {
Value *r = 0;
return *r;
}
/// Sets the value associated with the given key.
void set(const Key &k,const Value &t) { operator[](k)=t; }
template<typename _ReferenceMap>
struct Constraints {
typename enable_if<typename _ReferenceMap::ReferenceMapTag, void>::type
constraints() {
checkConcept<ReadWriteMap<K, T>, _ReferenceMap >();
ref = m[key];
m[key] = val;
m[key] = ref;
m[key] = cref;
own_ref = m[own_key];
m[own_key] = own_val;
m[own_key] = own_ref;
m[own_key] = own_cref;
m[key] = m[own_key];
m[own_key] = m[key];
}
const Key& key;
Value& val;
Reference ref;
ConstReference cref;
const typename _ReferenceMap::Key& own_key;
typename _ReferenceMap::Value& own_val;
typename _ReferenceMap::Reference own_ref;
typename _ReferenceMap::ConstReference own_cref;
_ReferenceMap& m;
Constraints() {}
};
};
// @}
} //namespace concepts
} //namespace lemon
#endif

View File

@@ -0,0 +1,312 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2013
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
///\ingroup concept
///\file
///\brief The concept of paths
///
#ifndef LEMON_CONCEPTS_PATH_H
#define LEMON_CONCEPTS_PATH_H
#include <lemon/core.h>
#include <lemon/concept_check.h>
namespace lemon {
namespace concepts {
/// \addtogroup concept
/// @{
/// \brief A skeleton structure for representing directed paths in
/// a digraph.
///
/// A skeleton structure for representing directed paths in a
/// digraph.
/// In a sense, a path can be treated as a list of arcs.
/// LEMON path types just store this list. As a consequence, they cannot
/// enumerate the nodes on the path directly and a zero length path
/// cannot store its source node.
///
/// The arcs of a path should be stored in the order of their directions,
/// i.e. the target node of each arc should be the same as the source
/// node of the next arc. This consistency could be checked using
/// \ref checkPath().
/// The source and target nodes of a (consistent) path can be obtained
/// using \ref pathSource() and \ref pathTarget().
///
/// A path can be constructed from another path of any type using the
/// copy constructor or the assignment operator.
///
/// \tparam GR The digraph type in which the path is.
template <typename GR>
class Path {
public:
/// Type of the underlying digraph.
typedef GR Digraph;
/// Arc type of the underlying digraph.
typedef typename Digraph::Arc Arc;
class ArcIt;
/// \brief Default constructor
Path() {}
/// \brief Template copy constructor
template <typename CPath>
Path(const CPath& cpath) {}
/// \brief Template assigment operator
template <typename CPath>
Path& operator=(const CPath& cpath) {
::lemon::ignore_unused_variable_warning(cpath);
return *this;
}
/// Length of the path, i.e. the number of arcs on the path.
int length() const { return 0;}
/// Returns whether the path is empty.
bool empty() const { return true;}
/// Resets the path to an empty path.
void clear() {}
/// \brief LEMON style iterator for enumerating the arcs of a path.
///
/// LEMON style iterator class for enumerating the arcs of a path.
class ArcIt {
public:
/// Default constructor
ArcIt() {}
/// Invalid constructor
ArcIt(Invalid) {}
/// Sets the iterator to the first arc of the given path
ArcIt(const Path &) {}
/// Conversion to \c Arc
operator Arc() const { return INVALID; }
/// Next arc
ArcIt& operator++() {return *this;}
/// Comparison operator
bool operator==(const ArcIt&) const {return true;}
/// Comparison operator
bool operator!=(const ArcIt&) const {return true;}
/// Comparison operator
bool operator<(const ArcIt&) const {return false;}
};
template <typename _Path>
struct Constraints {
void constraints() {
Path<Digraph> pc;
_Path p, pp(pc);
int l = p.length();
int e = p.empty();
p.clear();
p = pc;
typename _Path::ArcIt id, ii(INVALID), i(p);
++i;
typename Digraph::Arc ed = i;
e = (i == ii);
e = (i != ii);
e = (i < ii);
::lemon::ignore_unused_variable_warning(l);
::lemon::ignore_unused_variable_warning(pp);
::lemon::ignore_unused_variable_warning(e);
::lemon::ignore_unused_variable_warning(id);
::lemon::ignore_unused_variable_warning(ii);
::lemon::ignore_unused_variable_warning(ed);
}
};
};
namespace _path_bits {
template <typename _Digraph, typename _Path, typename RevPathTag = void>
struct PathDumperConstraints {
void constraints() {
int l = p.length();
int e = p.empty();
typename _Path::ArcIt id, i(p);
++i;
typename _Digraph::Arc ed = i;
e = (i == INVALID);
e = (i != INVALID);
::lemon::ignore_unused_variable_warning(l);
::lemon::ignore_unused_variable_warning(e);
::lemon::ignore_unused_variable_warning(id);
::lemon::ignore_unused_variable_warning(ed);
}
_Path& p;
PathDumperConstraints() {}
};
template <typename _Digraph, typename _Path>
struct PathDumperConstraints<
_Digraph, _Path,
typename enable_if<typename _Path::RevPathTag, void>::type
> {
void constraints() {
int l = p.length();
int e = p.empty();
typename _Path::RevArcIt id, i(p);
++i;
typename _Digraph::Arc ed = i;
e = (i == INVALID);
e = (i != INVALID);
::lemon::ignore_unused_variable_warning(l);
::lemon::ignore_unused_variable_warning(e);
::lemon::ignore_unused_variable_warning(id);
::lemon::ignore_unused_variable_warning(ed);
}
_Path& p;
PathDumperConstraints() {}
};
}
/// \brief A skeleton structure for path dumpers.
///
/// A skeleton structure for path dumpers. The path dumpers are
/// the generalization of the paths, they can enumerate the arcs
/// of the path either in forward or in backward order.
/// These classes are typically not used directly, they are rather
/// used to be assigned to a real path type.
///
/// The main purpose of this concept is that the shortest path
/// algorithms can enumerate the arcs easily in reverse order.
/// In LEMON, such algorithms give back a (reverse) path dumper that
/// can be assigned to a real path. The dumpers can be implemented as
/// an adaptor class to the predecessor map.
///
/// \tparam GR The digraph type in which the path is.
template <typename GR>
class PathDumper {
public:
/// Type of the underlying digraph.
typedef GR Digraph;
/// Arc type of the underlying digraph.
typedef typename Digraph::Arc Arc;
/// Length of the path, i.e. the number of arcs on the path.
int length() const { return 0;}
/// Returns whether the path is empty.
bool empty() const { return true;}
/// \brief Forward or reverse dumping
///
/// If this tag is defined to be \c True, then reverse dumping
/// is provided in the path dumper. In this case, \c RevArcIt
/// iterator should be implemented instead of \c ArcIt iterator.
typedef False RevPathTag;
/// \brief LEMON style iterator for enumerating the arcs of a path.
///
/// LEMON style iterator class for enumerating the arcs of a path.
class ArcIt {
public:
/// Default constructor
ArcIt() {}
/// Invalid constructor
ArcIt(Invalid) {}
/// Sets the iterator to the first arc of the given path
ArcIt(const PathDumper&) {}
/// Conversion to \c Arc
operator Arc() const { return INVALID; }
/// Next arc
ArcIt& operator++() {return *this;}
/// Comparison operator
bool operator==(const ArcIt&) const {return true;}
/// Comparison operator
bool operator!=(const ArcIt&) const {return true;}
/// Comparison operator
bool operator<(const ArcIt&) const {return false;}
};
/// \brief LEMON style iterator for enumerating the arcs of a path
/// in reverse direction.
///
/// LEMON style iterator class for enumerating the arcs of a path
/// in reverse direction.
class RevArcIt {
public:
/// Default constructor
RevArcIt() {}
/// Invalid constructor
RevArcIt(Invalid) {}
/// Sets the iterator to the last arc of the given path
RevArcIt(const PathDumper &) {}
/// Conversion to \c Arc
operator Arc() const { return INVALID; }
/// Next arc
RevArcIt& operator++() {return *this;}
/// Comparison operator
bool operator==(const RevArcIt&) const {return true;}
/// Comparison operator
bool operator!=(const RevArcIt&) const {return true;}
/// Comparison operator
bool operator<(const RevArcIt&) const {return false;}
};
template <typename _Path>
struct Constraints {
void constraints() {
function_requires<_path_bits::
PathDumperConstraints<Digraph, _Path> >();
}
};
};
///@}
}
} // namespace lemon
#endif

View File

@@ -0,0 +1,22 @@
#define LEMON_VERSION ""
/* #undef LEMON_HAVE_LONG_LONG */
/* #undef LEMON_HAVE_LP */
/* #undef LEMON_HAVE_MIP */
/* #undef LEMON_HAVE_GLPK */
/* #undef LEMON_HAVE_CPLEX */
/* #undef LEMON_HAVE_SOPLEX */
/* #undef LEMON_HAVE_CLP */
/* #undef LEMON_HAVE_CBC */
#define _LEMON_CPLEX 1
#define _LEMON_CLP 2
#define _LEMON_GLPK 3
#define _LEMON_SOPLEX 4
#define _LEMON_CBC 5
/* #undef LEMON_DEFAULT_LP */
/* #undef LEMON_DEFAULT_MIP */
/* #undef LEMON_USE_PTHREAD */
/* #undef LEMON_USE_WIN32_THREADS */

View File

@@ -0,0 +1,22 @@
#define LEMON_VERSION "@PROJECT_VERSION@"
#cmakedefine LEMON_HAVE_LONG_LONG 1
#cmakedefine LEMON_HAVE_LP 1
#cmakedefine LEMON_HAVE_MIP 1
#cmakedefine LEMON_HAVE_GLPK 1
#cmakedefine LEMON_HAVE_CPLEX 1
#cmakedefine LEMON_HAVE_SOPLEX 1
#cmakedefine LEMON_HAVE_CLP 1
#cmakedefine LEMON_HAVE_CBC 1
#define _LEMON_CPLEX 1
#define _LEMON_CLP 2
#define _LEMON_GLPK 3
#define _LEMON_SOPLEX 4
#define _LEMON_CBC 5
#cmakedefine LEMON_DEFAULT_LP _LEMON_@LEMON_DEFAULT_LP@
#cmakedefine LEMON_DEFAULT_MIP _LEMON_@LEMON_DEFAULT_MIP@
#cmakedefine LEMON_USE_PTHREAD 1
#cmakedefine LEMON_USE_WIN32_THREADS 1

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,249 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2009
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
#ifndef LEMON_COUNTER_H
#define LEMON_COUNTER_H
#include <string>
#include <iostream>
///\ingroup timecount
///\file
///\brief Tools for counting steps and events
namespace lemon
{
template<class P> class _NoSubCounter;
template<class P>
class _SubCounter
{
P &_parent;
std::string _title;
std::ostream &_os;
int count;
public:
typedef _SubCounter<_SubCounter<P> > SubCounter;
typedef _NoSubCounter<_SubCounter<P> > NoSubCounter;
_SubCounter(P &parent)
: _parent(parent), _title(), _os(std::cerr), count(0) {}
_SubCounter(P &parent,std::string title,std::ostream &os=std::cerr)
: _parent(parent), _title(title), _os(os), count(0) {}
_SubCounter(P &parent,const char *title,std::ostream &os=std::cerr)
: _parent(parent), _title(title), _os(os), count(0) {}
~_SubCounter() {
_os << _title << count <<std::endl;
_parent+=count;
}
_SubCounter &operator++() { count++; return *this;}
int operator++(int) { return count++; }
_SubCounter &operator--() { count--; return *this;}
int operator--(int) { return count--; }
_SubCounter &operator+=(int c) { count+=c; return *this;}
_SubCounter &operator-=(int c) { count-=c; return *this;}
operator int() {return count;}
};
template<class P>
class _NoSubCounter
{
P &_parent;
public:
typedef _NoSubCounter<_NoSubCounter<P> > SubCounter;
typedef _NoSubCounter<_NoSubCounter<P> > NoSubCounter;
_NoSubCounter(P &parent) :_parent(parent) {}
_NoSubCounter(P &parent,std::string,std::ostream &)
:_parent(parent) {}
_NoSubCounter(P &parent,std::string)
:_parent(parent) {}
_NoSubCounter(P &parent,const char *,std::ostream &)
:_parent(parent) {}
_NoSubCounter(P &parent,const char *)
:_parent(parent) {}
~_NoSubCounter() {}
_NoSubCounter &operator++() { ++_parent; return *this;}
int operator++(int) { _parent++; return 0;}
_NoSubCounter &operator--() { --_parent; return *this;}
int operator--(int) { _parent--; return 0;}
_NoSubCounter &operator+=(int c) { _parent+=c; return *this;}
_NoSubCounter &operator-=(int c) { _parent-=c; return *this;}
operator int() {return 0;}
};
/// \addtogroup timecount
/// @{
/// A counter class
/// This class makes it easier to count certain events (e.g. for debug
/// reasons).
/// You can increment or decrement the counter using \c operator++,
/// \c operator--, \c operator+= and \c operator-=. You can also
/// define subcounters for the different phases of the algorithm or
/// for different types of operations.
/// A report containing the given title and the value of the counter
/// is automatically printed on destruction.
///
/// The following example shows the usage of counters and subcounters.
/// \code
/// // Bubble sort
/// std::vector<T> v;
/// ...
/// Counter op("Operations: ");
/// Counter::SubCounter as(op, "Assignments: ");
/// Counter::SubCounter co(op, "Comparisons: ");
/// for (int i = v.size()-1; i > 0; --i) {
/// for (int j = 0; j < i; ++j) {
/// if (v[j] > v[j+1]) {
/// T tmp = v[j];
/// v[j] = v[j+1];
/// v[j+1] = tmp;
/// as += 3; // three assignments
/// }
/// ++co; // one comparison
/// }
/// }
/// \endcode
///
/// This code prints out something like that:
/// \code
/// Comparisons: 45
/// Assignments: 57
/// Operations: 102
/// \endcode
///
/// \sa NoCounter
class Counter
{
std::string _title;
std::ostream &_os;
int count;
public:
/// SubCounter class
/// This class can be used to setup subcounters for a \ref Counter
/// to have finer reports. A subcounter provides exactly the same
/// operations as the main \ref Counter, but it also increments and
/// decrements the value of its parent.
/// Subcounters can also have subcounters.
///
/// The parent counter must be given as the first parameter of the
/// constructor. Apart from that a title and an \c ostream object
/// can also be given just like for the main \ref Counter.
///
/// A report containing the given title and the value of the
/// subcounter is automatically printed on destruction. If you
/// would like to turn off this report, use \ref NoSubCounter
/// instead.
///
/// \sa NoSubCounter
typedef _SubCounter<Counter> SubCounter;
/// SubCounter class without printing report on destruction
/// This class can be used to setup subcounters for a \ref Counter.
/// It is the same as \ref SubCounter but it does not print report
/// on destruction. (It modifies the value of its parent, so 'No'
/// only means 'do not print'.)
///
/// Replacing \ref SubCounter "SubCounter"s with \ref NoSubCounter
/// "NoSubCounter"s makes it possible to turn off reporting
/// subcounter values without actually removing the definitions
/// and the increment or decrement operators.
///
/// \sa SubCounter
typedef _NoSubCounter<Counter> NoSubCounter;
/// Constructor.
Counter() : _title(), _os(std::cerr), count(0) {}
/// Constructor.
Counter(std::string title,std::ostream &os=std::cerr)
: _title(title), _os(os), count(0) {}
/// Constructor.
Counter(const char *title,std::ostream &os=std::cerr)
: _title(title), _os(os), count(0) {}
/// Destructor. Prints the given title and the value of the counter.
~Counter() {
_os << _title << count <<std::endl;
}
///\e
Counter &operator++() { count++; return *this;}
///\e
int operator++(int) { return count++;}
///\e
Counter &operator--() { count--; return *this;}
///\e
int operator--(int) { return count--;}
///\e
Counter &operator+=(int c) { count+=c; return *this;}
///\e
Counter &operator-=(int c) { count-=c; return *this;}
/// Resets the counter to the given value.
/// Resets the counter to the given value.
/// \note This function does not reset the values of
/// \ref SubCounter "SubCounter"s but it resets \ref NoSubCounter
/// "NoSubCounter"s along with the main counter.
void reset(int c=0) {count=c;}
/// Returns the value of the counter.
operator int() {return count;}
};
/// 'Do nothing' version of Counter.
/// This class can be used in the same way as \ref Counter, but it
/// does not count at all and does not print report on destruction.
///
/// Replacing a \ref Counter with a \ref NoCounter makes it possible
/// to turn off all counting and reporting (SubCounters should also
/// be replaced with NoSubCounters), so it does not affect the
/// efficiency of the program at all.
///
/// \sa Counter
class NoCounter
{
public:
typedef _NoSubCounter<NoCounter> SubCounter;
typedef _NoSubCounter<NoCounter> NoSubCounter;
NoCounter() {}
NoCounter(std::string,std::ostream &) {}
NoCounter(const char *,std::ostream &) {}
NoCounter(std::string) {}
NoCounter(const char *) {}
NoCounter &operator++() { return *this; }
int operator++(int) { return 0; }
NoCounter &operator--() { return *this; }
int operator--(int) { return 0; }
NoCounter &operator+=(int) { return *this;}
NoCounter &operator-=(int) { return *this;}
void reset(int) {}
void reset() {}
operator int() {return 0;}
};
///@}
}
#endif

View File

@@ -0,0 +1,994 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2013
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
#include <iostream>
#include <vector>
#include <cstring>
#include <lemon/cplex.h>
extern "C" {
#include <ilcplex/cplex.h>
}
///\file
///\brief Implementation of the LEMON-CPLEX lp solver interface.
namespace lemon {
CplexEnv::LicenseError::LicenseError(int status) {
if (!CPXgeterrorstring(0, status, _message)) {
std::strcpy(_message, "Cplex unknown error");
}
}
CplexEnv::CplexEnv() {
int status;
_cnt = new int;
(*_cnt) = 1;
_env = CPXopenCPLEX(&status);
if (_env == 0) {
delete _cnt;
_cnt = 0;
throw LicenseError(status);
}
}
CplexEnv::CplexEnv(const CplexEnv& other) {
_env = other._env;
_cnt = other._cnt;
++(*_cnt);
}
CplexEnv& CplexEnv::operator=(const CplexEnv& other) {
_env = other._env;
_cnt = other._cnt;
++(*_cnt);
return *this;
}
CplexEnv::~CplexEnv() {
--(*_cnt);
if (*_cnt == 0) {
delete _cnt;
CPXcloseCPLEX(&_env);
}
}
CplexBase::CplexBase() : LpBase() {
int status;
_prob = CPXcreateprob(cplexEnv(), &status, "Cplex problem");
messageLevel(MESSAGE_NOTHING);
}
CplexBase::CplexBase(const CplexEnv& env)
: LpBase(), _env(env) {
int status;
_prob = CPXcreateprob(cplexEnv(), &status, "Cplex problem");
messageLevel(MESSAGE_NOTHING);
}
CplexBase::CplexBase(const CplexBase& cplex)
: LpBase() {
int status;
_prob = CPXcloneprob(cplexEnv(), cplex._prob, &status);
rows = cplex.rows;
cols = cplex.cols;
messageLevel(MESSAGE_NOTHING);
}
CplexBase::~CplexBase() {
CPXfreeprob(cplexEnv(),&_prob);
}
int CplexBase::_addCol() {
int i = CPXgetnumcols(cplexEnv(), _prob);
double lb = -INF, ub = INF;
CPXnewcols(cplexEnv(), _prob, 1, 0, &lb, &ub, 0, 0);
return i;
}
int CplexBase::_addRow() {
int i = CPXgetnumrows(cplexEnv(), _prob);
const double ub = INF;
const char s = 'L';
CPXnewrows(cplexEnv(), _prob, 1, &ub, &s, 0, 0);
return i;
}
int CplexBase::_addRow(Value lb, ExprIterator b,
ExprIterator e, Value ub) {
int i = CPXgetnumrows(cplexEnv(), _prob);
if (lb == -INF) {
const char s = 'L';
CPXnewrows(cplexEnv(), _prob, 1, &ub, &s, 0, 0);
} else if (ub == INF) {
const char s = 'G';
CPXnewrows(cplexEnv(), _prob, 1, &lb, &s, 0, 0);
} else if (lb == ub){
const char s = 'E';
CPXnewrows(cplexEnv(), _prob, 1, &lb, &s, 0, 0);
} else {
const char s = 'R';
double len = ub - lb;
CPXnewrows(cplexEnv(), _prob, 1, &lb, &s, &len, 0);
}
std::vector<int> indices;
std::vector<int> rowlist;
std::vector<Value> values;
for(ExprIterator it=b; it!=e; ++it) {
indices.push_back(it->first);
values.push_back(it->second);
rowlist.push_back(i);
}
CPXchgcoeflist(cplexEnv(), _prob, values.size(),
&rowlist.front(), &indices.front(), &values.front());
return i;
}
void CplexBase::_eraseCol(int i) {
CPXdelcols(cplexEnv(), _prob, i, i);
}
void CplexBase::_eraseRow(int i) {
CPXdelrows(cplexEnv(), _prob, i, i);
}
void CplexBase::_eraseColId(int i) {
cols.eraseIndex(i);
cols.shiftIndices(i);
}
void CplexBase::_eraseRowId(int i) {
rows.eraseIndex(i);
rows.shiftIndices(i);
}
void CplexBase::_getColName(int col, std::string &name) const {
int size;
CPXgetcolname(cplexEnv(), _prob, 0, 0, 0, &size, col, col);
if (size == 0) {
name.clear();
return;
}
size *= -1;
std::vector<char> buf(size);
char *cname;
int tmp;
CPXgetcolname(cplexEnv(), _prob, &cname, &buf.front(), size,
&tmp, col, col);
name = cname;
}
void CplexBase::_setColName(int col, const std::string &name) {
char *cname;
cname = const_cast<char*>(name.c_str());
CPXchgcolname(cplexEnv(), _prob, 1, &col, &cname);
}
int CplexBase::_colByName(const std::string& name) const {
int index;
if (CPXgetcolindex(cplexEnv(), _prob,
const_cast<char*>(name.c_str()), &index) == 0) {
return index;
}
return -1;
}
void CplexBase::_getRowName(int row, std::string &name) const {
int size;
CPXgetrowname(cplexEnv(), _prob, 0, 0, 0, &size, row, row);
if (size == 0) {
name.clear();
return;
}
size *= -1;
std::vector<char> buf(size);
char *cname;
int tmp;
CPXgetrowname(cplexEnv(), _prob, &cname, &buf.front(), size,
&tmp, row, row);
name = cname;
}
void CplexBase::_setRowName(int row, const std::string &name) {
char *cname;
cname = const_cast<char*>(name.c_str());
CPXchgrowname(cplexEnv(), _prob, 1, &row, &cname);
}
int CplexBase::_rowByName(const std::string& name) const {
int index;
if (CPXgetrowindex(cplexEnv(), _prob,
const_cast<char*>(name.c_str()), &index) == 0) {
return index;
}
return -1;
}
void CplexBase::_setRowCoeffs(int i, ExprIterator b,
ExprIterator e)
{
std::vector<int> indices;
std::vector<int> rowlist;
std::vector<Value> values;
for(ExprIterator it=b; it!=e; ++it) {
indices.push_back(it->first);
values.push_back(it->second);
rowlist.push_back(i);
}
CPXchgcoeflist(cplexEnv(), _prob, values.size(),
&rowlist.front(), &indices.front(), &values.front());
}
void CplexBase::_getRowCoeffs(int i, InsertIterator b) const {
int tmp1, tmp2, tmp3, length;
CPXgetrows(cplexEnv(), _prob, &tmp1, &tmp2, 0, 0, 0, &length, i, i);
length = -length;
std::vector<int> indices(length);
std::vector<double> values(length);
CPXgetrows(cplexEnv(), _prob, &tmp1, &tmp2,
&indices.front(), &values.front(),
length, &tmp3, i, i);
for (int i = 0; i < length; ++i) {
*b = std::make_pair(indices[i], values[i]);
++b;
}
}
void CplexBase::_setColCoeffs(int i, ExprIterator b, ExprIterator e) {
std::vector<int> indices;
std::vector<int> collist;
std::vector<Value> values;
for(ExprIterator it=b; it!=e; ++it) {
indices.push_back(it->first);
values.push_back(it->second);
collist.push_back(i);
}
CPXchgcoeflist(cplexEnv(), _prob, values.size(),
&indices.front(), &collist.front(), &values.front());
}
void CplexBase::_getColCoeffs(int i, InsertIterator b) const {
int tmp1, tmp2, tmp3, length;
CPXgetcols(cplexEnv(), _prob, &tmp1, &tmp2, 0, 0, 0, &length, i, i);
length = -length;
std::vector<int> indices(length);
std::vector<double> values(length);
CPXgetcols(cplexEnv(), _prob, &tmp1, &tmp2,
&indices.front(), &values.front(),
length, &tmp3, i, i);
for (int i = 0; i < length; ++i) {
*b = std::make_pair(indices[i], values[i]);
++b;
}
}
void CplexBase::_setCoeff(int row, int col, Value value) {
CPXchgcoef(cplexEnv(), _prob, row, col, value);
}
CplexBase::Value CplexBase::_getCoeff(int row, int col) const {
CplexBase::Value value;
CPXgetcoef(cplexEnv(), _prob, row, col, &value);
return value;
}
void CplexBase::_setColLowerBound(int i, Value value) {
const char s = 'L';
CPXchgbds(cplexEnv(), _prob, 1, &i, &s, &value);
}
CplexBase::Value CplexBase::_getColLowerBound(int i) const {
CplexBase::Value res;
CPXgetlb(cplexEnv(), _prob, &res, i, i);
return res <= -CPX_INFBOUND ? -INF : res;
}
void CplexBase::_setColUpperBound(int i, Value value)
{
const char s = 'U';
CPXchgbds(cplexEnv(), _prob, 1, &i, &s, &value);
}
CplexBase::Value CplexBase::_getColUpperBound(int i) const {
CplexBase::Value res;
CPXgetub(cplexEnv(), _prob, &res, i, i);
return res >= CPX_INFBOUND ? INF : res;
}
CplexBase::Value CplexBase::_getRowLowerBound(int i) const {
char s;
CPXgetsense(cplexEnv(), _prob, &s, i, i);
CplexBase::Value res;
switch (s) {
case 'G':
case 'R':
case 'E':
CPXgetrhs(cplexEnv(), _prob, &res, i, i);
return res <= -CPX_INFBOUND ? -INF : res;
default:
return -INF;
}
}
CplexBase::Value CplexBase::_getRowUpperBound(int i) const {
char s;
CPXgetsense(cplexEnv(), _prob, &s, i, i);
CplexBase::Value res;
switch (s) {
case 'L':
case 'E':
CPXgetrhs(cplexEnv(), _prob, &res, i, i);
return res >= CPX_INFBOUND ? INF : res;
case 'R':
CPXgetrhs(cplexEnv(), _prob, &res, i, i);
{
double rng;
CPXgetrngval(cplexEnv(), _prob, &rng, i, i);
res += rng;
}
return res >= CPX_INFBOUND ? INF : res;
default:
return INF;
}
}
//This is easier to implement
void CplexBase::_set_row_bounds(int i, Value lb, Value ub) {
if (lb == -INF) {
const char s = 'L';
CPXchgsense(cplexEnv(), _prob, 1, &i, &s);
CPXchgrhs(cplexEnv(), _prob, 1, &i, &ub);
} else if (ub == INF) {
const char s = 'G';
CPXchgsense(cplexEnv(), _prob, 1, &i, &s);
CPXchgrhs(cplexEnv(), _prob, 1, &i, &lb);
} else if (lb == ub){
const char s = 'E';
CPXchgsense(cplexEnv(), _prob, 1, &i, &s);
CPXchgrhs(cplexEnv(), _prob, 1, &i, &lb);
} else {
const char s = 'R';
CPXchgsense(cplexEnv(), _prob, 1, &i, &s);
CPXchgrhs(cplexEnv(), _prob, 1, &i, &lb);
double len = ub - lb;
CPXchgrngval(cplexEnv(), _prob, 1, &i, &len);
}
}
void CplexBase::_setRowLowerBound(int i, Value lb)
{
LEMON_ASSERT(lb != INF, "Invalid bound");
_set_row_bounds(i, lb, CplexBase::_getRowUpperBound(i));
}
void CplexBase::_setRowUpperBound(int i, Value ub)
{
LEMON_ASSERT(ub != -INF, "Invalid bound");
_set_row_bounds(i, CplexBase::_getRowLowerBound(i), ub);
}
void CplexBase::_setObjCoeffs(ExprIterator b, ExprIterator e)
{
std::vector<int> indices;
std::vector<Value> values;
for(ExprIterator it=b; it!=e; ++it) {
indices.push_back(it->first);
values.push_back(it->second);
}
CPXchgobj(cplexEnv(), _prob, values.size(),
&indices.front(), &values.front());
}
void CplexBase::_getObjCoeffs(InsertIterator b) const
{
int num = CPXgetnumcols(cplexEnv(), _prob);
std::vector<Value> x(num);
CPXgetobj(cplexEnv(), _prob, &x.front(), 0, num - 1);
for (int i = 0; i < num; ++i) {
if (x[i] != 0.0) {
*b = std::make_pair(i, x[i]);
++b;
}
}
}
void CplexBase::_setObjCoeff(int i, Value obj_coef)
{
CPXchgobj(cplexEnv(), _prob, 1, &i, &obj_coef);
}
CplexBase::Value CplexBase::_getObjCoeff(int i) const
{
Value x;
CPXgetobj(cplexEnv(), _prob, &x, i, i);
return x;
}
void CplexBase::_setSense(CplexBase::Sense sense) {
switch (sense) {
case MIN:
CPXchgobjsen(cplexEnv(), _prob, CPX_MIN);
break;
case MAX:
CPXchgobjsen(cplexEnv(), _prob, CPX_MAX);
break;
}
}
CplexBase::Sense CplexBase::_getSense() const {
switch (CPXgetobjsen(cplexEnv(), _prob)) {
case CPX_MIN:
return MIN;
case CPX_MAX:
return MAX;
default:
LEMON_ASSERT(false, "Invalid sense");
return CplexBase::Sense();
}
}
void CplexBase::_clear() {
CPXfreeprob(cplexEnv(),&_prob);
int status;
_prob = CPXcreateprob(cplexEnv(), &status, "Cplex problem");
}
void CplexBase::_messageLevel(MessageLevel level) {
switch (level) {
case MESSAGE_NOTHING:
_message_enabled = false;
break;
case MESSAGE_ERROR:
case MESSAGE_WARNING:
case MESSAGE_NORMAL:
case MESSAGE_VERBOSE:
_message_enabled = true;
break;
}
}
void CplexBase::_applyMessageLevel() {
CPXsetintparam(cplexEnv(), CPX_PARAM_SCRIND,
_message_enabled ? CPX_ON : CPX_OFF);
}
void CplexBase::_write(std::string file, std::string format) const
{
if(format == "MPS" || format == "LP")
CPXwriteprob(cplexEnv(), cplexLp(), file.c_str(), format.c_str());
else if(format == "SOL")
CPXsolwrite(cplexEnv(), cplexLp(), file.c_str());
else throw UnsupportedFormatError(format);
}
// CplexLp members
CplexLp::CplexLp()
: LpBase(), LpSolver(), CplexBase() {}
CplexLp::CplexLp(const CplexEnv& env)
: LpBase(), LpSolver(), CplexBase(env) {}
CplexLp::CplexLp(const CplexLp& other)
: LpBase(), LpSolver(), CplexBase(other) {}
CplexLp::~CplexLp() {}
CplexLp* CplexLp::newSolver() const { return new CplexLp; }
CplexLp* CplexLp::cloneSolver() const {return new CplexLp(*this); }
const char* CplexLp::_solverName() const { return "CplexLp"; }
void CplexLp::_clear_temporals() {
_col_status.clear();
_row_status.clear();
_primal_ray.clear();
_dual_ray.clear();
}
// The routine returns zero unless an error occurred during the
// optimization. Examples of errors include exhausting available
// memory (CPXERR_NO_MEMORY) or encountering invalid data in the
// CPLEX problem object (CPXERR_NO_PROBLEM). Exceeding a
// user-specified CPLEX limit, or proving the model infeasible or
// unbounded, are not considered errors. Note that a zero return
// value does not necessarily mean that a solution exists. Use query
// routines CPXsolninfo, CPXgetstat, and CPXsolution to obtain
// further information about the status of the optimization.
CplexLp::SolveExitStatus CplexLp::convertStatus(int status) {
#if CPX_VERSION >= 800
if (status == 0) {
switch (CPXgetstat(cplexEnv(), _prob)) {
case CPX_STAT_OPTIMAL:
case CPX_STAT_INFEASIBLE:
case CPX_STAT_UNBOUNDED:
return SOLVED;
default:
return UNSOLVED;
}
} else {
return UNSOLVED;
}
#else
if (status == 0) {
//We want to exclude some cases
switch (CPXgetstat(cplexEnv(), _prob)) {
case CPX_OBJ_LIM:
case CPX_IT_LIM_FEAS:
case CPX_IT_LIM_INFEAS:
case CPX_TIME_LIM_FEAS:
case CPX_TIME_LIM_INFEAS:
return UNSOLVED;
default:
return SOLVED;
}
} else {
return UNSOLVED;
}
#endif
}
CplexLp::SolveExitStatus CplexLp::_solve() {
_clear_temporals();
_applyMessageLevel();
return convertStatus(CPXlpopt(cplexEnv(), _prob));
}
CplexLp::SolveExitStatus CplexLp::solvePrimal() {
_clear_temporals();
_applyMessageLevel();
return convertStatus(CPXprimopt(cplexEnv(), _prob));
}
CplexLp::SolveExitStatus CplexLp::solveDual() {
_clear_temporals();
_applyMessageLevel();
return convertStatus(CPXdualopt(cplexEnv(), _prob));
}
CplexLp::SolveExitStatus CplexLp::solveBarrier() {
_clear_temporals();
_applyMessageLevel();
return convertStatus(CPXbaropt(cplexEnv(), _prob));
}
CplexLp::Value CplexLp::_getPrimal(int i) const {
Value x;
CPXgetx(cplexEnv(), _prob, &x, i, i);
return x;
}
CplexLp::Value CplexLp::_getDual(int i) const {
Value y;
CPXgetpi(cplexEnv(), _prob, &y, i, i);
return y;
}
CplexLp::Value CplexLp::_getPrimalValue() const {
Value objval;
CPXgetobjval(cplexEnv(), _prob, &objval);
return objval;
}
CplexLp::VarStatus CplexLp::_getColStatus(int i) const {
if (_col_status.empty()) {
_col_status.resize(CPXgetnumcols(cplexEnv(), _prob));
CPXgetbase(cplexEnv(), _prob, &_col_status.front(), 0);
}
switch (_col_status[i]) {
case CPX_BASIC:
return BASIC;
case CPX_FREE_SUPER:
return FREE;
case CPX_AT_LOWER:
return LOWER;
case CPX_AT_UPPER:
return UPPER;
default:
LEMON_ASSERT(false, "Wrong column status");
return CplexLp::VarStatus();
}
}
CplexLp::VarStatus CplexLp::_getRowStatus(int i) const {
if (_row_status.empty()) {
_row_status.resize(CPXgetnumrows(cplexEnv(), _prob));
CPXgetbase(cplexEnv(), _prob, 0, &_row_status.front());
}
switch (_row_status[i]) {
case CPX_BASIC:
return BASIC;
case CPX_AT_LOWER:
{
char s;
CPXgetsense(cplexEnv(), _prob, &s, i, i);
return s != 'L' ? LOWER : UPPER;
}
case CPX_AT_UPPER:
return UPPER;
default:
LEMON_ASSERT(false, "Wrong row status");
return CplexLp::VarStatus();
}
}
CplexLp::Value CplexLp::_getPrimalRay(int i) const {
if (_primal_ray.empty()) {
_primal_ray.resize(CPXgetnumcols(cplexEnv(), _prob));
CPXgetray(cplexEnv(), _prob, &_primal_ray.front());
}
return _primal_ray[i];
}
CplexLp::Value CplexLp::_getDualRay(int i) const {
if (_dual_ray.empty()) {
}
return _dual_ray[i];
}
// Cplex 7.0 status values
// This table lists the statuses, returned by the CPXgetstat()
// routine, for solutions to LP problems or mixed integer problems. If
// no solution exists, the return value is zero.
// For Simplex, Barrier
// 1 CPX_OPTIMAL
// Optimal solution found
// 2 CPX_INFEASIBLE
// Problem infeasible
// 3 CPX_UNBOUNDED
// Problem unbounded
// 4 CPX_OBJ_LIM
// Objective limit exceeded in Phase II
// 5 CPX_IT_LIM_FEAS
// Iteration limit exceeded in Phase II
// 6 CPX_IT_LIM_INFEAS
// Iteration limit exceeded in Phase I
// 7 CPX_TIME_LIM_FEAS
// Time limit exceeded in Phase II
// 8 CPX_TIME_LIM_INFEAS
// Time limit exceeded in Phase I
// 9 CPX_NUM_BEST_FEAS
// Problem non-optimal, singularities in Phase II
// 10 CPX_NUM_BEST_INFEAS
// Problem non-optimal, singularities in Phase I
// 11 CPX_OPTIMAL_INFEAS
// Optimal solution found, unscaled infeasibilities
// 12 CPX_ABORT_FEAS
// Aborted in Phase II
// 13 CPX_ABORT_INFEAS
// Aborted in Phase I
// 14 CPX_ABORT_DUAL_INFEAS
// Aborted in barrier, dual infeasible
// 15 CPX_ABORT_PRIM_INFEAS
// Aborted in barrier, primal infeasible
// 16 CPX_ABORT_PRIM_DUAL_INFEAS
// Aborted in barrier, primal and dual infeasible
// 17 CPX_ABORT_PRIM_DUAL_FEAS
// Aborted in barrier, primal and dual feasible
// 18 CPX_ABORT_CROSSOVER
// Aborted in crossover
// 19 CPX_INForUNBD
// Infeasible or unbounded
// 20 CPX_PIVOT
// User pivot used
//
// Pending return values
// ??case CPX_ABORT_DUAL_INFEAS
// ??case CPX_ABORT_CROSSOVER
// ??case CPX_INForUNBD
// ??case CPX_PIVOT
//Some more interesting stuff:
// CPX_PARAM_PROBMETHOD 1062 int LPMETHOD
// 0 Automatic
// 1 Primal Simplex
// 2 Dual Simplex
// 3 Network Simplex
// 4 Standard Barrier
// Default: 0
// Description: Method for linear optimization.
// Determines which algorithm is used when CPXlpopt() (or "optimize"
// in the Interactive Optimizer) is called. Currently the behavior of
// the "Automatic" setting is that CPLEX simply invokes the dual
// simplex method, but this capability may be expanded in the future
// so that CPLEX chooses the method based on problem characteristics
#if CPX_VERSION < 900
void statusSwitch(CPXENVptr cplexEnv(),int& stat){
int lpmethod;
CPXgetintparam (cplexEnv(),CPX_PARAM_PROBMETHOD,&lpmethod);
if (lpmethod==2){
if (stat==CPX_UNBOUNDED){
stat=CPX_INFEASIBLE;
}
else{
if (stat==CPX_INFEASIBLE)
stat=CPX_UNBOUNDED;
}
}
}
#else
void statusSwitch(CPXENVptr,int&){}
#endif
CplexLp::ProblemType CplexLp::_getPrimalType() const {
// Unboundedness not treated well: the following is from cplex 9.0 doc
// About Unboundedness
// The treatment of models that are unbounded involves a few
// subtleties. Specifically, a declaration of unboundedness means that
// ILOG CPLEX has determined that the model has an unbounded
// ray. Given any feasible solution x with objective z, a multiple of
// the unbounded ray can be added to x to give a feasible solution
// with objective z-1 (or z+1 for maximization models). Thus, if a
// feasible solution exists, then the optimal objective is
// unbounded. Note that ILOG CPLEX has not necessarily concluded that
// a feasible solution exists. Users can call the routine CPXsolninfo
// to determine whether ILOG CPLEX has also concluded that the model
// has a feasible solution.
int stat = CPXgetstat(cplexEnv(), _prob);
#if CPX_VERSION >= 800
switch (stat)
{
case CPX_STAT_OPTIMAL:
return OPTIMAL;
case CPX_STAT_UNBOUNDED:
return UNBOUNDED;
case CPX_STAT_INFEASIBLE:
return INFEASIBLE;
default:
return UNDEFINED;
}
#else
statusSwitch(cplexEnv(),stat);
//CPXgetstat(cplexEnv(), _prob);
switch (stat) {
case 0:
return UNDEFINED; //Undefined
case CPX_OPTIMAL://Optimal
return OPTIMAL;
case CPX_UNBOUNDED://Unbounded
return INFEASIBLE;//In case of dual simplex
//return UNBOUNDED;
case CPX_INFEASIBLE://Infeasible
// case CPX_IT_LIM_INFEAS:
// case CPX_TIME_LIM_INFEAS:
// case CPX_NUM_BEST_INFEAS:
// case CPX_OPTIMAL_INFEAS:
// case CPX_ABORT_INFEAS:
// case CPX_ABORT_PRIM_INFEAS:
// case CPX_ABORT_PRIM_DUAL_INFEAS:
return UNBOUNDED;//In case of dual simplex
//return INFEASIBLE;
// case CPX_OBJ_LIM:
// case CPX_IT_LIM_FEAS:
// case CPX_TIME_LIM_FEAS:
// case CPX_NUM_BEST_FEAS:
// case CPX_ABORT_FEAS:
// case CPX_ABORT_PRIM_DUAL_FEAS:
// return FEASIBLE;
default:
return UNDEFINED; //Everything else comes here
//FIXME error
}
#endif
}
// Cplex 9.0 status values
// CPX_STAT_ABORT_DUAL_OBJ_LIM
// CPX_STAT_ABORT_IT_LIM
// CPX_STAT_ABORT_OBJ_LIM
// CPX_STAT_ABORT_PRIM_OBJ_LIM
// CPX_STAT_ABORT_TIME_LIM
// CPX_STAT_ABORT_USER
// CPX_STAT_FEASIBLE_RELAXED
// CPX_STAT_INFEASIBLE
// CPX_STAT_INForUNBD
// CPX_STAT_NUM_BEST
// CPX_STAT_OPTIMAL
// CPX_STAT_OPTIMAL_FACE_UNBOUNDED
// CPX_STAT_OPTIMAL_INFEAS
// CPX_STAT_OPTIMAL_RELAXED
// CPX_STAT_UNBOUNDED
CplexLp::ProblemType CplexLp::_getDualType() const {
int stat = CPXgetstat(cplexEnv(), _prob);
#if CPX_VERSION >= 800
switch (stat) {
case CPX_STAT_OPTIMAL:
return OPTIMAL;
case CPX_STAT_UNBOUNDED:
return INFEASIBLE;
default:
return UNDEFINED;
}
#else
statusSwitch(cplexEnv(),stat);
switch (stat) {
case 0:
return UNDEFINED; //Undefined
case CPX_OPTIMAL://Optimal
return OPTIMAL;
case CPX_UNBOUNDED:
return INFEASIBLE;
default:
return UNDEFINED; //Everything else comes here
//FIXME error
}
#endif
}
// CplexMip members
CplexMip::CplexMip()
: LpBase(), MipSolver(), CplexBase() {
#if CPX_VERSION < 800
CPXchgprobtype(cplexEnv(), _prob, CPXPROB_MIP);
#else
CPXchgprobtype(cplexEnv(), _prob, CPXPROB_MILP);
#endif
}
CplexMip::CplexMip(const CplexEnv& env)
: LpBase(), MipSolver(), CplexBase(env) {
#if CPX_VERSION < 800
CPXchgprobtype(cplexEnv(), _prob, CPXPROB_MIP);
#else
CPXchgprobtype(cplexEnv(), _prob, CPXPROB_MILP);
#endif
}
CplexMip::CplexMip(const CplexMip& other)
: LpBase(), MipSolver(), CplexBase(other) {}
CplexMip::~CplexMip() {}
CplexMip* CplexMip::newSolver() const { return new CplexMip; }
CplexMip* CplexMip::cloneSolver() const {return new CplexMip(*this); }
const char* CplexMip::_solverName() const { return "CplexMip"; }
void CplexMip::_setColType(int i, CplexMip::ColTypes col_type) {
// Note If a variable is to be changed to binary, a call to CPXchgbds
// should also be made to change the bounds to 0 and 1.
switch (col_type){
case INTEGER: {
const char t = 'I';
CPXchgctype (cplexEnv(), _prob, 1, &i, &t);
} break;
case REAL: {
const char t = 'C';
CPXchgctype (cplexEnv(), _prob, 1, &i, &t);
} break;
default:
break;
}
}
CplexMip::ColTypes CplexMip::_getColType(int i) const {
char t;
CPXgetctype (cplexEnv(), _prob, &t, i, i);
switch (t) {
case 'I':
return INTEGER;
case 'C':
return REAL;
default:
LEMON_ASSERT(false, "Invalid column type");
return ColTypes();
}
}
CplexMip::SolveExitStatus CplexMip::_solve() {
int status;
_applyMessageLevel();
status = CPXmipopt (cplexEnv(), _prob);
if (status==0)
return SOLVED;
else
return UNSOLVED;
}
CplexMip::ProblemType CplexMip::_getType() const {
int stat = CPXgetstat(cplexEnv(), _prob);
//Fortunately, MIP statuses did not change for cplex 8.0
switch (stat) {
case CPXMIP_OPTIMAL:
// Optimal integer solution has been found.
case CPXMIP_OPTIMAL_TOL:
// Optimal soluton with the tolerance defined by epgap or epagap has
// been found.
return OPTIMAL;
//This also exists in later issues
// case CPXMIP_UNBOUNDED:
//return UNBOUNDED;
case CPXMIP_INFEASIBLE:
return INFEASIBLE;
default:
return UNDEFINED;
}
//Unboundedness not treated well: the following is from cplex 9.0 doc
// About Unboundedness
// The treatment of models that are unbounded involves a few
// subtleties. Specifically, a declaration of unboundedness means that
// ILOG CPLEX has determined that the model has an unbounded
// ray. Given any feasible solution x with objective z, a multiple of
// the unbounded ray can be added to x to give a feasible solution
// with objective z-1 (or z+1 for maximization models). Thus, if a
// feasible solution exists, then the optimal objective is
// unbounded. Note that ILOG CPLEX has not necessarily concluded that
// a feasible solution exists. Users can call the routine CPXsolninfo
// to determine whether ILOG CPLEX has also concluded that the model
// has a feasible solution.
}
CplexMip::Value CplexMip::_getSol(int i) const {
Value x;
CPXgetmipx(cplexEnv(), _prob, &x, i, i);
return x;
}
CplexMip::Value CplexMip::_getSolValue() const {
Value objval;
CPXgetmipobjval(cplexEnv(), _prob, &objval);
return objval;
}
} //namespace lemon

View File

@@ -0,0 +1,292 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2013
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
#ifndef LEMON_CPLEX_H
#define LEMON_CPLEX_H
///\file
///\brief Header of the LEMON-CPLEX lp solver interface.
#include <lemon/lp_base.h>
struct cpxenv;
struct cpxlp;
namespace lemon {
/// \brief Reference counted wrapper around cpxenv pointer
///
/// The cplex uses environment object which is responsible for
/// checking the proper license usage. This class provides a simple
/// interface for share the environment object between different
/// problems.
class CplexEnv {
friend class CplexBase;
private:
cpxenv* _env;
mutable int* _cnt;
public:
/// \brief This exception is thrown when the license check is not
/// sufficient
class LicenseError : public Exception {
friend class CplexEnv;
private:
LicenseError(int status);
char _message[510];
public:
/// The short error message
virtual const char* what() const throw() {
return _message;
}
};
/// Constructor
CplexEnv();
/// Shallow copy constructor
CplexEnv(const CplexEnv&);
/// Shallow assignement
CplexEnv& operator=(const CplexEnv&);
/// Destructor
virtual ~CplexEnv();
protected:
cpxenv* cplexEnv() { return _env; }
const cpxenv* cplexEnv() const { return _env; }
};
/// \brief Base interface for the CPLEX LP and MIP solver
///
/// This class implements the common interface of the CPLEX LP and
/// MIP solvers.
/// \ingroup lp_group
class CplexBase : virtual public LpBase {
protected:
CplexEnv _env;
cpxlp* _prob;
CplexBase();
CplexBase(const CplexEnv&);
CplexBase(const CplexBase &);
virtual ~CplexBase();
virtual int _addCol();
virtual int _addRow();
virtual int _addRow(Value l, ExprIterator b, ExprIterator e, Value u);
virtual void _eraseCol(int i);
virtual void _eraseRow(int i);
virtual void _eraseColId(int i);
virtual void _eraseRowId(int i);
virtual void _getColName(int col, std::string& name) const;
virtual void _setColName(int col, const std::string& name);
virtual int _colByName(const std::string& name) const;
virtual void _getRowName(int row, std::string& name) const;
virtual void _setRowName(int row, const std::string& name);
virtual int _rowByName(const std::string& name) const;
virtual void _setRowCoeffs(int i, ExprIterator b, ExprIterator e);
virtual void _getRowCoeffs(int i, InsertIterator b) const;
virtual void _setColCoeffs(int i, ExprIterator b, ExprIterator e);
virtual void _getColCoeffs(int i, InsertIterator b) const;
virtual void _setCoeff(int row, int col, Value value);
virtual Value _getCoeff(int row, int col) const;
virtual void _setColLowerBound(int i, Value value);
virtual Value _getColLowerBound(int i) const;
virtual void _setColUpperBound(int i, Value value);
virtual Value _getColUpperBound(int i) const;
private:
void _set_row_bounds(int i, Value lb, Value ub);
protected:
virtual void _setRowLowerBound(int i, Value value);
virtual Value _getRowLowerBound(int i) const;
virtual void _setRowUpperBound(int i, Value value);
virtual Value _getRowUpperBound(int i) const;
virtual void _setObjCoeffs(ExprIterator b, ExprIterator e);
virtual void _getObjCoeffs(InsertIterator b) const;
virtual void _setObjCoeff(int i, Value obj_coef);
virtual Value _getObjCoeff(int i) const;
virtual void _setSense(Sense sense);
virtual Sense _getSense() const;
virtual void _clear();
virtual void _messageLevel(MessageLevel level);
void _applyMessageLevel();
bool _message_enabled;
void _write(std::string file, std::string format) const;
public:
/// Returns the used \c CplexEnv instance
const CplexEnv& env() const { return _env; }
/// \brief Returns the const cpxenv pointer
///
/// \note The cpxenv might be destructed with the solver.
const cpxenv* cplexEnv() const { return _env.cplexEnv(); }
/// \brief Returns the const cpxenv pointer
///
/// \note The cpxenv might be destructed with the solver.
cpxenv* cplexEnv() { return _env.cplexEnv(); }
/// Returns the cplex problem object
cpxlp* cplexLp() { return _prob; }
/// Returns the cplex problem object
const cpxlp* cplexLp() const { return _prob; }
#ifdef DOXYGEN
/// Write the problem or the solution to a file in the given format
/// This function writes the problem or the solution
/// to a file in the given format.
/// Trying to write in an unsupported format will trigger
/// \ref lemon::LpBase::UnsupportedFormatError "UnsupportedFormatError".
/// \param file The file path
/// \param format The output file format.
/// Supportted formats are "MPS", "LP" and "SOL".
void write(std::string file, std::string format = "MPS") const {}
#endif
};
/// \brief Interface for the CPLEX LP solver
///
/// This class implements an interface for the CPLEX LP solver.
///\ingroup lp_group
class CplexLp : public LpSolver, public CplexBase {
public:
/// \e
CplexLp();
/// \e
CplexLp(const CplexEnv&);
/// \e
CplexLp(const CplexLp&);
/// \e
virtual ~CplexLp();
/// \e
virtual CplexLp* cloneSolver() const;
/// \e
virtual CplexLp* newSolver() const;
private:
// these values cannot retrieved element by element
mutable std::vector<int> _col_status;
mutable std::vector<int> _row_status;
mutable std::vector<Value> _primal_ray;
mutable std::vector<Value> _dual_ray;
void _clear_temporals();
SolveExitStatus convertStatus(int status);
protected:
virtual const char* _solverName() const;
virtual SolveExitStatus _solve();
virtual Value _getPrimal(int i) const;
virtual Value _getDual(int i) const;
virtual Value _getPrimalValue() const;
virtual VarStatus _getColStatus(int i) const;
virtual VarStatus _getRowStatus(int i) const;
virtual Value _getPrimalRay(int i) const;
virtual Value _getDualRay(int i) const;
virtual ProblemType _getPrimalType() const;
virtual ProblemType _getDualType() const;
public:
/// Solve with primal simplex method
SolveExitStatus solvePrimal();
/// Solve with dual simplex method
SolveExitStatus solveDual();
/// Solve with barrier method
SolveExitStatus solveBarrier();
};
/// \brief Interface for the CPLEX MIP solver
///
/// This class implements an interface for the CPLEX MIP solver.
///\ingroup lp_group
class CplexMip : public MipSolver, public CplexBase {
public:
/// \e
CplexMip();
/// \e
CplexMip(const CplexEnv&);
/// \e
CplexMip(const CplexMip&);
/// \e
virtual ~CplexMip();
/// \e
virtual CplexMip* cloneSolver() const;
/// \e
virtual CplexMip* newSolver() const;
protected:
virtual const char* _solverName() const;
virtual ColTypes _getColType(int col) const;
virtual void _setColType(int col, ColTypes col_type);
virtual SolveExitStatus _solve();
virtual ProblemType _getType() const;
virtual Value _getSol(int i) const;
virtual Value _getSolValue() const;
};
} //END OF NAMESPACE LEMON
#endif //LEMON_CPLEX_H

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,352 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2009
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
#ifndef LEMON_DHEAP_H
#define LEMON_DHEAP_H
///\ingroup heaps
///\file
///\brief D-ary heap implementation.
#include <vector>
#include <utility>
#include <functional>
namespace lemon {
/// \ingroup heaps
///
///\brief D-ary heap data structure.
///
/// This class implements the \e D-ary \e heap data structure.
/// It fully conforms to the \ref concepts::Heap "heap concept".
///
/// The \ref DHeap "D-ary heap" is a generalization of the
/// \ref BinHeap "binary heap" structure, its nodes have at most
/// \c D children, instead of two.
/// \ref BinHeap and \ref QuadHeap are specialized implementations
/// of this structure for <tt>D=2</tt> and <tt>D=4</tt>, respectively.
///
/// \tparam PR Type of the priorities of the items.
/// \tparam IM A read-writable item map with \c int values, used
/// internally to handle the cross references.
/// \tparam D The degree of the heap, each node have at most \e D
/// children. The default is 16. Powers of two are suggested to use
/// so that the multiplications and divisions needed to traverse the
/// nodes of the heap could be performed faster.
/// \tparam CMP A functor class for comparing the priorities.
/// The default is \c std::less<PR>.
///
///\sa BinHeap
///\sa FouraryHeap
#ifdef DOXYGEN
template <typename PR, typename IM, int D, typename CMP>
#else
template <typename PR, typename IM, int D = 16,
typename CMP = std::less<PR> >
#endif
class DHeap {
public:
/// Type of the item-int map.
typedef IM ItemIntMap;
/// Type of the priorities.
typedef PR Prio;
/// Type of the items stored in the heap.
typedef typename ItemIntMap::Key Item;
/// Type of the item-priority pairs.
typedef std::pair<Item,Prio> Pair;
/// Functor type for comparing the priorities.
typedef CMP Compare;
/// \brief Type to represent the states of the items.
///
/// Each item has a state associated to it. It can be "in heap",
/// "pre-heap" or "post-heap". The latter two are indifferent from the
/// heap's point of view, but may be useful to the user.
///
/// The item-int map must be initialized in such way that it assigns
/// \c PRE_HEAP (<tt>-1</tt>) to any element to be put in the heap.
enum State {
IN_HEAP = 0, ///< = 0.
PRE_HEAP = -1, ///< = -1.
POST_HEAP = -2 ///< = -2.
};
private:
std::vector<Pair> _data;
Compare _comp;
ItemIntMap &_iim;
public:
/// \brief Constructor.
///
/// Constructor.
/// \param map A map that assigns \c int values to the items.
/// It is used internally to handle the cross references.
/// The assigned value must be \c PRE_HEAP (<tt>-1</tt>) for each item.
explicit DHeap(ItemIntMap &map) : _iim(map) {}
/// \brief Constructor.
///
/// Constructor.
/// \param map A map that assigns \c int values to the items.
/// It is used internally to handle the cross references.
/// The assigned value must be \c PRE_HEAP (<tt>-1</tt>) for each item.
/// \param comp The function object used for comparing the priorities.
DHeap(ItemIntMap &map, const Compare &comp)
: _iim(map), _comp(comp) {}
/// \brief The number of items stored in the heap.
///
/// This function returns the number of items stored in the heap.
int size() const { return _data.size(); }
/// \brief Check if the heap is empty.
///
/// This function returns \c true if the heap is empty.
bool empty() const { return _data.empty(); }
/// \brief Make the heap empty.
///
/// This functon makes the heap empty.
/// It does not change the cross reference map. If you want to reuse
/// a heap that is not surely empty, you should first clear it and
/// then you should set the cross reference map to \c PRE_HEAP
/// for each item.
void clear() { _data.clear(); }
private:
int parent(int i) { return (i-1)/D; }
int firstChild(int i) { return D*i+1; }
bool less(const Pair &p1, const Pair &p2) const {
return _comp(p1.second, p2.second);
}
void bubbleUp(int hole, Pair p) {
int par = parent(hole);
while( hole>0 && less(p,_data[par]) ) {
move(_data[par],hole);
hole = par;
par = parent(hole);
}
move(p, hole);
}
void bubbleDown(int hole, Pair p, int length) {
if( length>1 ) {
int child = firstChild(hole);
while( child+D<=length ) {
int min=child;
for (int i=1; i<D; ++i) {
if( less(_data[child+i], _data[min]) )
min=child+i;
}
if( !less(_data[min], p) )
goto ok;
move(_data[min], hole);
hole = min;
child = firstChild(hole);
}
if ( child<length ) {
int min = child;
while (++child < length) {
if( less(_data[child], _data[min]) )
min=child;
}
if( less(_data[min], p) ) {
move(_data[min], hole);
hole = min;
}
}
}
ok:
move(p, hole);
}
void move(const Pair &p, int i) {
_data[i] = p;
_iim.set(p.first, i);
}
public:
/// \brief Insert a pair of item and priority into the heap.
///
/// This function inserts \c p.first to the heap with priority
/// \c p.second.
/// \param p The pair to insert.
/// \pre \c p.first must not be stored in the heap.
void push(const Pair &p) {
int n = _data.size();
_data.resize(n+1);
bubbleUp(n, p);
}
/// \brief Insert an item into the heap with the given priority.
///
/// This function inserts the given item into the heap with the
/// given priority.
/// \param i The item to insert.
/// \param p The priority of the item.
/// \pre \e i must not be stored in the heap.
void push(const Item &i, const Prio &p) { push(Pair(i,p)); }
/// \brief Return the item having minimum priority.
///
/// This function returns the item having minimum priority.
/// \pre The heap must be non-empty.
Item top() const { return _data[0].first; }
/// \brief The minimum priority.
///
/// This function returns the minimum priority.
/// \pre The heap must be non-empty.
Prio prio() const { return _data[0].second; }
/// \brief Remove the item having minimum priority.
///
/// This function removes the item having minimum priority.
/// \pre The heap must be non-empty.
void pop() {
int n = _data.size()-1;
_iim.set(_data[0].first, POST_HEAP);
if (n>0) bubbleDown(0, _data[n], n);
_data.pop_back();
}
/// \brief Remove the given item from the heap.
///
/// This function removes the given item from the heap if it is
/// already stored.
/// \param i The item to delete.
/// \pre \e i must be in the heap.
void erase(const Item &i) {
int h = _iim[i];
int n = _data.size()-1;
_iim.set(_data[h].first, POST_HEAP);
if( h<n ) {
if( less(_data[parent(h)], _data[n]) )
bubbleDown(h, _data[n], n);
else
bubbleUp(h, _data[n]);
}
_data.pop_back();
}
/// \brief The priority of the given item.
///
/// This function returns the priority of the given item.
/// \param i The item.
/// \pre \e i must be in the heap.
Prio operator[](const Item &i) const {
int idx = _iim[i];
return _data[idx].second;
}
/// \brief Set the priority of an item or insert it, if it is
/// not stored in the heap.
///
/// This method sets the priority of the given item if it is
/// already stored in the heap. Otherwise it inserts the given
/// item into the heap with the given priority.
/// \param i The item.
/// \param p The priority.
void set(const Item &i, const Prio &p) {
int idx = _iim[i];
if( idx<0 )
push(i,p);
else if( _comp(p, _data[idx].second) )
bubbleUp(idx, Pair(i,p));
else
bubbleDown(idx, Pair(i,p), _data.size());
}
/// \brief Decrease the priority of an item to the given value.
///
/// This function decreases the priority of an item to the given value.
/// \param i The item.
/// \param p The priority.
/// \pre \e i must be stored in the heap with priority at least \e p.
void decrease(const Item &i, const Prio &p) {
int idx = _iim[i];
bubbleUp(idx, Pair(i,p));
}
/// \brief Increase the priority of an item to the given value.
///
/// This function increases the priority of an item to the given value.
/// \param i The item.
/// \param p The priority.
/// \pre \e i must be stored in the heap with priority at most \e p.
void increase(const Item &i, const Prio &p) {
int idx = _iim[i];
bubbleDown(idx, Pair(i,p), _data.size());
}
/// \brief Return the state of an item.
///
/// This method returns \c PRE_HEAP if the given item has never
/// been in the heap, \c IN_HEAP if it is in the heap at the moment,
/// and \c POST_HEAP otherwise.
/// In the latter case it is possible that the item will get back
/// to the heap again.
/// \param i The item.
State state(const Item &i) const {
int s = _iim[i];
if (s>=0) s=0;
return State(s);
}
/// \brief Set the state of an item in the heap.
///
/// This function sets the state of the given item in the heap.
/// It can be used to manually clear the heap when it is important
/// to achive better time complexity.
/// \param i The item.
/// \param st The state. It should not be \c IN_HEAP.
void state(const Item& i, State st) {
switch (st) {
case POST_HEAP:
case PRE_HEAP:
if (state(i) == IN_HEAP) erase(i);
_iim[i] = st;
break;
case IN_HEAP:
break;
}
}
/// \brief Replace an item in the heap.
///
/// This function replaces item \c i with item \c j.
/// Item \c i must be in the heap, while \c j must be out of the heap.
/// After calling this method, item \c i will be out of the
/// heap and \c j will be in the heap with the same prioriority
/// as item \c i had before.
void replace(const Item& i, const Item& j) {
int idx=_iim[i];
_iim.set(i, _iim[j]);
_iim.set(j, idx);
_data[idx].first=j;
}
}; // class DHeap
} // namespace lemon
#endif // LEMON_DHEAP_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,726 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2009
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
#ifndef LEMON_DIM2_H
#define LEMON_DIM2_H
#include <iostream>
#include <algorithm>
///\ingroup geomdat
///\file
///\brief A simple two dimensional vector and a bounding box implementation
namespace lemon {
///Tools for handling two dimensional coordinates
///This namespace is a storage of several
///tools for handling two dimensional coordinates
namespace dim2 {
/// \addtogroup geomdat
/// @{
/// Two dimensional vector (plain vector)
/// A simple two dimensional vector (plain vector) implementation
/// with the usual vector operations.
template<typename T>
class Point {
public:
typedef T Value;
///First coordinate
T x;
///Second coordinate
T y;
///Default constructor
Point() {}
///Construct an instance from coordinates
Point(T a, T b) : x(a), y(b) { }
///Returns the dimension of the vector (i.e. returns 2).
///The dimension of the vector.
///This function always returns 2.
int size() const { return 2; }
///Subscripting operator
///\c p[0] is \c p.x and \c p[1] is \c p.y
///
T& operator[](int idx) { return idx == 0 ? x : y; }
///Const subscripting operator
///\c p[0] is \c p.x and \c p[1] is \c p.y
///
const T& operator[](int idx) const { return idx == 0 ? x : y; }
///Conversion constructor
template<class TT> Point(const Point<TT> &p) : x(p.x), y(p.y) {}
///Give back the square of the norm of the vector
T normSquare() const {
return x*x+y*y;
}
///Increment the left hand side by \c u
Point<T>& operator +=(const Point<T>& u) {
x += u.x;
y += u.y;
return *this;
}
///Decrement the left hand side by \c u
Point<T>& operator -=(const Point<T>& u) {
x -= u.x;
y -= u.y;
return *this;
}
///Multiply the left hand side with a scalar
Point<T>& operator *=(const T &u) {
x *= u;
y *= u;
return *this;
}
///Divide the left hand side by a scalar
Point<T>& operator /=(const T &u) {
x /= u;
y /= u;
return *this;
}
///Return the scalar product of two vectors
T operator *(const Point<T>& u) const {
return x*u.x+y*u.y;
}
///Return the sum of two vectors
Point<T> operator+(const Point<T> &u) const {
Point<T> b=*this;
return b+=u;
}
///Return the negative of the vector
Point<T> operator-() const {
Point<T> b=*this;
b.x=-b.x; b.y=-b.y;
return b;
}
///Return the difference of two vectors
Point<T> operator-(const Point<T> &u) const {
Point<T> b=*this;
return b-=u;
}
///Return a vector multiplied by a scalar
Point<T> operator*(const T &u) const {
Point<T> b=*this;
return b*=u;
}
///Return a vector divided by a scalar
Point<T> operator/(const T &u) const {
Point<T> b=*this;
return b/=u;
}
///Test equality
bool operator==(const Point<T> &u) const {
return (x==u.x) && (y==u.y);
}
///Test inequality
bool operator!=(Point u) const {
return (x!=u.x) || (y!=u.y);
}
};
///Return a Point
///Return a Point.
///\relates Point
template <typename T>
inline Point<T> makePoint(const T& x, const T& y) {
return Point<T>(x, y);
}
///Return a vector multiplied by a scalar
///Return a vector multiplied by a scalar.
///\relates Point
template<typename T> Point<T> operator*(const T &u,const Point<T> &x) {
return x*u;
}
///Read a plain vector from a stream
///Read a plain vector from a stream.
///\relates Point
///
template<typename T>
inline std::istream& operator>>(std::istream &is, Point<T> &z) {
char c;
if (is >> c) {
if (c != '(') is.putback(c);
} else {
is.clear();
}
if (!(is >> z.x)) return is;
if (is >> c) {
if (c != ',') is.putback(c);
} else {
is.clear();
}
if (!(is >> z.y)) return is;
if (is >> c) {
if (c != ')') is.putback(c);
} else {
is.clear();
}
return is;
}
///Write a plain vector to a stream
///Write a plain vector to a stream.
///\relates Point
///
template<typename T>
inline std::ostream& operator<<(std::ostream &os, const Point<T>& z)
{
os << "(" << z.x << "," << z.y << ")";
return os;
}
///Rotate by 90 degrees
///Returns the parameter rotated by 90 degrees in positive direction.
///\relates Point
///
template<typename T>
inline Point<T> rot90(const Point<T> &z)
{
return Point<T>(-z.y,z.x);
}
///Rotate by 180 degrees
///Returns the parameter rotated by 180 degrees.
///\relates Point
///
template<typename T>
inline Point<T> rot180(const Point<T> &z)
{
return Point<T>(-z.x,-z.y);
}
///Rotate by 270 degrees
///Returns the parameter rotated by 90 degrees in negative direction.
///\relates Point
///
template<typename T>
inline Point<T> rot270(const Point<T> &z)
{
return Point<T>(z.y,-z.x);
}
/// Bounding box of plain vectors (points).
/// A class to calculate or store the bounding box of plain vectors
/// (\ref Point "points").
template<typename T>
class Box {
Point<T> _bottom_left, _top_right;
bool _empty;
public:
///Default constructor: creates an empty box
Box() { _empty = true; }
///Construct a box from one point
Box(Point<T> a) {
_bottom_left = _top_right = a;
_empty = false;
}
///Construct a box from two points
///Construct a box from two points.
///\param a The bottom left corner.
///\param b The top right corner.
///\warning The coordinates of the bottom left corner must be no more
///than those of the top right one.
Box(Point<T> a,Point<T> b)
{
_bottom_left = a;
_top_right = b;
_empty = false;
}
///Construct a box from four numbers
///Construct a box from four numbers.
///\param l The left side of the box.
///\param b The bottom of the box.
///\param r The right side of the box.
///\param t The top of the box.
///\warning The left side must be no more than the right side and
///bottom must be no more than the top.
Box(T l,T b,T r,T t)
{
_bottom_left=Point<T>(l,b);
_top_right=Point<T>(r,t);
_empty = false;
}
///Return \c true if the box is empty.
///Return \c true if the box is empty (i.e. return \c false
///if at least one point was added to the box or the coordinates of
///the box were set).
///
///The coordinates of an empty box are not defined.
bool empty() const {
return _empty;
}
///Make the box empty
void clear() {
_empty = true;
}
///Give back the bottom left corner of the box
///Give back the bottom left corner of the box.
///If the box is empty, then the return value is not defined.
Point<T> bottomLeft() const {
return _bottom_left;
}
///Set the bottom left corner of the box
///Set the bottom left corner of the box.
///\pre The box must not be empty.
void bottomLeft(Point<T> p) {
_bottom_left = p;
}
///Give back the top right corner of the box
///Give back the top right corner of the box.
///If the box is empty, then the return value is not defined.
Point<T> topRight() const {
return _top_right;
}
///Set the top right corner of the box
///Set the top right corner of the box.
///\pre The box must not be empty.
void topRight(Point<T> p) {
_top_right = p;
}
///Give back the bottom right corner of the box
///Give back the bottom right corner of the box.
///If the box is empty, then the return value is not defined.
Point<T> bottomRight() const {
return Point<T>(_top_right.x,_bottom_left.y);
}
///Set the bottom right corner of the box
///Set the bottom right corner of the box.
///\pre The box must not be empty.
void bottomRight(Point<T> p) {
_top_right.x = p.x;
_bottom_left.y = p.y;
}
///Give back the top left corner of the box
///Give back the top left corner of the box.
///If the box is empty, then the return value is not defined.
Point<T> topLeft() const {
return Point<T>(_bottom_left.x,_top_right.y);
}
///Set the top left corner of the box
///Set the top left corner of the box.
///\pre The box must not be empty.
void topLeft(Point<T> p) {
_top_right.y = p.y;
_bottom_left.x = p.x;
}
///Give back the bottom of the box
///Give back the bottom of the box.
///If the box is empty, then the return value is not defined.
T bottom() const {
return _bottom_left.y;
}
///Set the bottom of the box
///Set the bottom of the box.
///\pre The box must not be empty.
void bottom(T t) {
_bottom_left.y = t;
}
///Give back the top of the box
///Give back the top of the box.
///If the box is empty, then the return value is not defined.
T top() const {
return _top_right.y;
}
///Set the top of the box
///Set the top of the box.
///\pre The box must not be empty.
void top(T t) {
_top_right.y = t;
}
///Give back the left side of the box
///Give back the left side of the box.
///If the box is empty, then the return value is not defined.
T left() const {
return _bottom_left.x;
}
///Set the left side of the box
///Set the left side of the box.
///\pre The box must not be empty.
void left(T t) {
_bottom_left.x = t;
}
/// Give back the right side of the box
/// Give back the right side of the box.
///If the box is empty, then the return value is not defined.
T right() const {
return _top_right.x;
}
///Set the right side of the box
///Set the right side of the box.
///\pre The box must not be empty.
void right(T t) {
_top_right.x = t;
}
///Give back the height of the box
///Give back the height of the box.
///If the box is empty, then the return value is not defined.
T height() const {
return _top_right.y-_bottom_left.y;
}
///Give back the width of the box
///Give back the width of the box.
///If the box is empty, then the return value is not defined.
T width() const {
return _top_right.x-_bottom_left.x;
}
///Checks whether a point is inside the box
bool inside(const Point<T>& u) const {
if (_empty)
return false;
else {
return ( (u.x-_bottom_left.x)*(_top_right.x-u.x) >= 0 &&
(u.y-_bottom_left.y)*(_top_right.y-u.y) >= 0 );
}
}
///Increments the box with a point
///Increments the box with a point.
///
Box& add(const Point<T>& u){
if (_empty) {
_bottom_left = _top_right = u;
_empty = false;
}
else {
if (_bottom_left.x > u.x) _bottom_left.x = u.x;
if (_bottom_left.y > u.y) _bottom_left.y = u.y;
if (_top_right.x < u.x) _top_right.x = u.x;
if (_top_right.y < u.y) _top_right.y = u.y;
}
return *this;
}
///Increments the box to contain another box
///Increments the box to contain another box.
///
Box& add(const Box &u){
if ( !u.empty() ){
add(u._bottom_left);
add(u._top_right);
}
return *this;
}
///Intersection of two boxes
///Intersection of two boxes.
///
Box operator&(const Box& u) const {
Box b;
if (_empty || u._empty) {
b._empty = true;
} else {
b._bottom_left.x = std::max(_bottom_left.x, u._bottom_left.x);
b._bottom_left.y = std::max(_bottom_left.y, u._bottom_left.y);
b._top_right.x = std::min(_top_right.x, u._top_right.x);
b._top_right.y = std::min(_top_right.y, u._top_right.y);
b._empty = b._bottom_left.x > b._top_right.x ||
b._bottom_left.y > b._top_right.y;
}
return b;
}
};//class Box
///Read a box from a stream
///Read a box from a stream.
///\relates Box
template<typename T>
inline std::istream& operator>>(std::istream &is, Box<T>& b) {
char c;
Point<T> p;
if (is >> c) {
if (c != '(') is.putback(c);
} else {
is.clear();
}
if (!(is >> p)) return is;
b.bottomLeft(p);
if (is >> c) {
if (c != ',') is.putback(c);
} else {
is.clear();
}
if (!(is >> p)) return is;
b.topRight(p);
if (is >> c) {
if (c != ')') is.putback(c);
} else {
is.clear();
}
return is;
}
///Write a box to a stream
///Write a box to a stream.
///\relates Box
template<typename T>
inline std::ostream& operator<<(std::ostream &os, const Box<T>& b)
{
os << "(" << b.bottomLeft() << "," << b.topRight() << ")";
return os;
}
///Map of x-coordinates of a <tt>Point</tt>-map
///Map of x-coordinates of a \ref Point "Point"-map.
///
template<class M>
class XMap
{
M& _map;
public:
typedef typename M::Value::Value Value;
typedef typename M::Key Key;
///\e
XMap(M& map) : _map(map) {}
Value operator[](Key k) const {return _map[k].x;}
void set(Key k,Value v) {_map.set(k,typename M::Value(v,_map[k].y));}
};
///Returns an XMap class
///This function just returns an XMap class.
///\relates XMap
template<class M>
inline XMap<M> xMap(M &m)
{
return XMap<M>(m);
}
template<class M>
inline XMap<M> xMap(const M &m)
{
return XMap<M>(m);
}
///Constant (read only) version of XMap
///Constant (read only) version of XMap.
///
template<class M>
class ConstXMap
{
const M& _map;
public:
typedef typename M::Value::Value Value;
typedef typename M::Key Key;
///\e
ConstXMap(const M &map) : _map(map) {}
Value operator[](Key k) const {return _map[k].x;}
};
///Returns a ConstXMap class
///This function just returns a ConstXMap class.
///\relates ConstXMap
template<class M>
inline ConstXMap<M> xMap(const M &m)
{
return ConstXMap<M>(m);
}
///Map of y-coordinates of a <tt>Point</tt>-map
///Map of y-coordinates of a \ref Point "Point"-map.
///
template<class M>
class YMap
{
M& _map;
public:
typedef typename M::Value::Value Value;
typedef typename M::Key Key;
///\e
YMap(M& map) : _map(map) {}
Value operator[](Key k) const {return _map[k].y;}
void set(Key k,Value v) {_map.set(k,typename M::Value(_map[k].x,v));}
};
///Returns a YMap class
///This function just returns a YMap class.
///\relates YMap
template<class M>
inline YMap<M> yMap(M &m)
{
return YMap<M>(m);
}
template<class M>
inline YMap<M> yMap(const M &m)
{
return YMap<M>(m);
}
///Constant (read only) version of YMap
///Constant (read only) version of YMap.
///
template<class M>
class ConstYMap
{
const M& _map;
public:
typedef typename M::Value::Value Value;
typedef typename M::Key Key;
///\e
ConstYMap(const M &map) : _map(map) {}
Value operator[](Key k) const {return _map[k].y;}
};
///Returns a ConstYMap class
///This function just returns a ConstYMap class.
///\relates ConstYMap
template<class M>
inline ConstYMap<M> yMap(const M &m)
{
return ConstYMap<M>(m);
}
///\brief Map of the normSquare() of a <tt>Point</tt>-map
///
///Map of the \ref Point::normSquare() "normSquare()"
///of a \ref Point "Point"-map.
template<class M>
class NormSquareMap
{
const M& _map;
public:
typedef typename M::Value::Value Value;
typedef typename M::Key Key;
///\e
NormSquareMap(const M &map) : _map(map) {}
Value operator[](Key k) const {return _map[k].normSquare();}
};
///Returns a NormSquareMap class
///This function just returns a NormSquareMap class.
///\relates NormSquareMap
template<class M>
inline NormSquareMap<M> normSquareMap(const M &m)
{
return NormSquareMap<M>(m);
}
/// @}
} //namespce dim2
} //namespace lemon
#endif //LEMON_DIM2_H

View File

@@ -0,0 +1,448 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2013
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
#ifndef LEMON_DIMACS_H
#define LEMON_DIMACS_H
#include <iostream>
#include <string>
#include <vector>
#include <limits>
#include <lemon/maps.h>
#include <lemon/error.h>
/// \ingroup dimacs_group
/// \file
/// \brief DIMACS file format reader.
namespace lemon {
/// \addtogroup dimacs_group
/// @{
/// DIMACS file type descriptor.
struct DimacsDescriptor
{
///\brief DIMACS file type enum
///
///DIMACS file type enum.
enum Type {
NONE, ///< Undefined type.
MIN, ///< DIMACS file type for minimum cost flow problems.
MAX, ///< DIMACS file type for maximum flow problems.
SP, ///< DIMACS file type for shostest path problems.
MAT ///< DIMACS file type for plain graphs and matching problems.
};
///The file type
Type type;
///The number of nodes in the graph
int nodeNum;
///The number of edges in the graph
int edgeNum;
int lineShift;
///Constructor. It sets the type to \c NONE.
DimacsDescriptor() : type(NONE) {}
};
///Discover the type of a DIMACS file
///This function starts seeking the beginning of the given file for the
///problem type and size info.
///The found data is returned in a special struct that can be evaluated
///and passed to the appropriate reader function.
DimacsDescriptor dimacsType(std::istream& is)
{
DimacsDescriptor r;
std::string problem,str;
char c;
r.lineShift=0;
while (is >> c)
switch(c)
{
case 'p':
if(is >> problem >> r.nodeNum >> r.edgeNum)
{
getline(is, str);
r.lineShift++;
if(problem=="min") r.type=DimacsDescriptor::MIN;
else if(problem=="max") r.type=DimacsDescriptor::MAX;
else if(problem=="sp") r.type=DimacsDescriptor::SP;
else if(problem=="mat") r.type=DimacsDescriptor::MAT;
else throw FormatError("Unknown problem type");
return r;
}
else
{
throw FormatError("Missing or wrong problem type declaration.");
}
break;
case 'c':
getline(is, str);
r.lineShift++;
break;
default:
throw FormatError("Unknown DIMACS declaration.");
}
throw FormatError("Missing problem type declaration.");
}
/// \brief DIMACS minimum cost flow reader function.
///
/// This function reads a minimum cost flow instance from DIMACS format,
/// i.e. from a DIMACS file having a line starting with
/// \code
/// p min
/// \endcode
/// At the beginning, \c g is cleared by \c g.clear(). The supply
/// amount of the nodes are written to the \c supply node map
/// (they are signed values). The lower bounds, capacities and costs
/// of the arcs are written to the \c lower, \c capacity and \c cost
/// arc maps.
///
/// If the capacity of an arc is less than the lower bound, it will
/// be set to "infinite" instead. The actual value of "infinite" is
/// contolled by the \c infty parameter. If it is 0 (the default value),
/// \c std::numeric_limits<Capacity>::infinity() will be used if available,
/// \c std::numeric_limits<Capacity>::max() otherwise. If \c infty is set to
/// a non-zero value, that value will be used as "infinite".
///
/// If the file type was previously evaluated by dimacsType(), then
/// the descriptor struct should be given by the \c dest parameter.
template <typename Digraph, typename LowerMap,
typename CapacityMap, typename CostMap,
typename SupplyMap>
void readDimacsMin(std::istream& is,
Digraph &g,
LowerMap& lower,
CapacityMap& capacity,
CostMap& cost,
SupplyMap& supply,
typename CapacityMap::Value infty = 0,
DimacsDescriptor desc=DimacsDescriptor())
{
g.clear();
std::vector<typename Digraph::Node> nodes;
typename Digraph::Arc e;
std::string problem, str;
char c;
int i, j;
if(desc.type==DimacsDescriptor::NONE) desc=dimacsType(is);
if(desc.type!=DimacsDescriptor::MIN)
throw FormatError("Problem type mismatch");
nodes.resize(desc.nodeNum + 1);
for (int k = 1; k <= desc.nodeNum; ++k) {
nodes[k] = g.addNode();
supply.set(nodes[k], 0);
}
typename SupplyMap::Value sup;
typename CapacityMap::Value low;
typename CapacityMap::Value cap;
typename CostMap::Value co;
typedef typename CapacityMap::Value Capacity;
if(infty==0)
infty = std::numeric_limits<Capacity>::has_infinity ?
std::numeric_limits<Capacity>::infinity() :
std::numeric_limits<Capacity>::max();
while (is >> c) {
switch (c) {
case 'c': // comment line
getline(is, str);
break;
case 'n': // node definition line
is >> i >> sup;
getline(is, str);
supply.set(nodes[i], sup);
break;
case 'a': // arc definition line
is >> i >> j >> low >> cap >> co;
getline(is, str);
e = g.addArc(nodes[i], nodes[j]);
lower.set(e, low);
if (cap >= low)
capacity.set(e, cap);
else
capacity.set(e, infty);
cost.set(e, co);
break;
}
}
}
template<typename Digraph, typename CapacityMap>
void _readDimacs(std::istream& is,
Digraph &g,
CapacityMap& capacity,
typename Digraph::Node &s,
typename Digraph::Node &t,
typename CapacityMap::Value infty = 0,
DimacsDescriptor desc=DimacsDescriptor()) {
g.clear();
s=t=INVALID;
std::vector<typename Digraph::Node> nodes;
typename Digraph::Arc e;
char c, d;
int i, j;
typename CapacityMap::Value _cap;
std::string str;
nodes.resize(desc.nodeNum + 1);
for (int k = 1; k <= desc.nodeNum; ++k) {
nodes[k] = g.addNode();
}
typedef typename CapacityMap::Value Capacity;
if(infty==0)
infty = std::numeric_limits<Capacity>::has_infinity ?
std::numeric_limits<Capacity>::infinity() :
std::numeric_limits<Capacity>::max();
while (is >> c) {
switch (c) {
case 'c': // comment line
getline(is, str);
break;
case 'n': // node definition line
if (desc.type==DimacsDescriptor::SP) { // shortest path problem
is >> i;
getline(is, str);
s = nodes[i];
}
if (desc.type==DimacsDescriptor::MAX) { // max flow problem
is >> i >> d;
getline(is, str);
if (d == 's') s = nodes[i];
if (d == 't') t = nodes[i];
}
break;
case 'a': // arc definition line
if (desc.type==DimacsDescriptor::SP) {
is >> i >> j >> _cap;
getline(is, str);
e = g.addArc(nodes[i], nodes[j]);
capacity.set(e, _cap);
}
else if (desc.type==DimacsDescriptor::MAX) {
is >> i >> j >> _cap;
getline(is, str);
e = g.addArc(nodes[i], nodes[j]);
if (_cap >= 0)
capacity.set(e, _cap);
else
capacity.set(e, infty);
}
else {
is >> i >> j;
getline(is, str);
g.addArc(nodes[i], nodes[j]);
}
break;
}
}
}
/// \brief DIMACS maximum flow reader function.
///
/// This function reads a maximum flow instance from DIMACS format,
/// i.e. from a DIMACS file having a line starting with
/// \code
/// p max
/// \endcode
/// At the beginning, \c g is cleared by \c g.clear(). The arc
/// capacities are written to the \c capacity arc map and \c s and
/// \c t are set to the source and the target nodes.
///
/// If the capacity of an arc is negative, it will
/// be set to "infinite" instead. The actual value of "infinite" is
/// contolled by the \c infty parameter. If it is 0 (the default value),
/// \c std::numeric_limits<Capacity>::infinity() will be used if available,
/// \c std::numeric_limits<Capacity>::max() otherwise. If \c infty is set to
/// a non-zero value, that value will be used as "infinite".
///
/// If the file type was previously evaluated by dimacsType(), then
/// the descriptor struct should be given by the \c dest parameter.
template<typename Digraph, typename CapacityMap>
void readDimacsMax(std::istream& is,
Digraph &g,
CapacityMap& capacity,
typename Digraph::Node &s,
typename Digraph::Node &t,
typename CapacityMap::Value infty = 0,
DimacsDescriptor desc=DimacsDescriptor()) {
if(desc.type==DimacsDescriptor::NONE) desc=dimacsType(is);
if(desc.type!=DimacsDescriptor::MAX)
throw FormatError("Problem type mismatch");
_readDimacs(is,g,capacity,s,t,infty,desc);
}
/// \brief DIMACS shortest path reader function.
///
/// This function reads a shortest path instance from DIMACS format,
/// i.e. from a DIMACS file having a line starting with
/// \code
/// p sp
/// \endcode
/// At the beginning, \c g is cleared by \c g.clear(). The arc
/// lengths are written to the \c length arc map and \c s is set to the
/// source node.
///
/// If the file type was previously evaluated by dimacsType(), then
/// the descriptor struct should be given by the \c dest parameter.
template<typename Digraph, typename LengthMap>
void readDimacsSp(std::istream& is,
Digraph &g,
LengthMap& length,
typename Digraph::Node &s,
DimacsDescriptor desc=DimacsDescriptor()) {
typename Digraph::Node t;
if(desc.type==DimacsDescriptor::NONE) desc=dimacsType(is);
if(desc.type!=DimacsDescriptor::SP)
throw FormatError("Problem type mismatch");
_readDimacs(is, g, length, s, t, 0, desc);
}
/// \brief DIMACS capacitated digraph reader function.
///
/// This function reads an arc capacitated digraph instance from
/// DIMACS 'max' or 'sp' format.
/// At the beginning, \c g is cleared by \c g.clear()
/// and the arc capacities/lengths are written to the \c capacity
/// arc map.
///
/// In case of the 'max' format, if the capacity of an arc is negative,
/// it will
/// be set to "infinite" instead. The actual value of "infinite" is
/// contolled by the \c infty parameter. If it is 0 (the default value),
/// \c std::numeric_limits<Capacity>::infinity() will be used if available,
/// \c std::numeric_limits<Capacity>::max() otherwise. If \c infty is set to
/// a non-zero value, that value will be used as "infinite".
///
/// If the file type was previously evaluated by dimacsType(), then
/// the descriptor struct should be given by the \c dest parameter.
template<typename Digraph, typename CapacityMap>
void readDimacsCap(std::istream& is,
Digraph &g,
CapacityMap& capacity,
typename CapacityMap::Value infty = 0,
DimacsDescriptor desc=DimacsDescriptor()) {
typename Digraph::Node u,v;
if(desc.type==DimacsDescriptor::NONE) desc=dimacsType(is);
if(desc.type!=DimacsDescriptor::MAX || desc.type!=DimacsDescriptor::SP)
throw FormatError("Problem type mismatch");
_readDimacs(is, g, capacity, u, v, infty, desc);
}
template<typename Graph>
typename enable_if<lemon::UndirectedTagIndicator<Graph>,void>::type
_addArcEdge(Graph &g, typename Graph::Node s, typename Graph::Node t,
dummy<0> = 0)
{
g.addEdge(s,t);
}
template<typename Graph>
typename disable_if<lemon::UndirectedTagIndicator<Graph>,void>::type
_addArcEdge(Graph &g, typename Graph::Node s, typename Graph::Node t,
dummy<1> = 1)
{
g.addArc(s,t);
}
/// \brief DIMACS plain (di)graph reader function.
///
/// This function reads a plain (di)graph without any designated nodes
/// and maps (e.g. a matching instance) from DIMACS format, i.e. from
/// DIMACS files having a line starting with
/// \code
/// p mat
/// \endcode
/// At the beginning, \c g is cleared by \c g.clear().
///
/// If the file type was previously evaluated by dimacsType(), then
/// the descriptor struct should be given by the \c dest parameter.
template<typename Graph>
void readDimacsMat(std::istream& is, Graph &g,
DimacsDescriptor desc=DimacsDescriptor())
{
if(desc.type==DimacsDescriptor::NONE) desc=dimacsType(is);
if(desc.type!=DimacsDescriptor::MAT)
throw FormatError("Problem type mismatch");
g.clear();
std::vector<typename Graph::Node> nodes;
char c;
int i, j;
std::string str;
nodes.resize(desc.nodeNum + 1);
for (int k = 1; k <= desc.nodeNum; ++k) {
nodes[k] = g.addNode();
}
while (is >> c) {
switch (c) {
case 'c': // comment line
getline(is, str);
break;
case 'n': // node definition line
break;
case 'a': // arc definition line
is >> i >> j;
getline(is, str);
_addArcEdge(g,nodes[i], nodes[j]);
break;
}
}
}
/// DIMACS plain digraph writer function.
///
/// This function writes a digraph without any designated nodes and
/// maps into DIMACS format, i.e. into DIMACS file having a line
/// starting with
/// \code
/// p mat
/// \endcode
/// If \c comment is not empty, then it will be printed in the first line
/// prefixed by 'c'.
template<typename Digraph>
void writeDimacsMat(std::ostream& os, const Digraph &g,
std::string comment="") {
typedef typename Digraph::NodeIt NodeIt;
typedef typename Digraph::ArcIt ArcIt;
if(!comment.empty())
os << "c " << comment << std::endl;
os << "p mat " << g.nodeNum() << " " << g.arcNum() << std::endl;
typename Digraph::template NodeMap<int> nodes(g);
int i = 1;
for(NodeIt v(g); v != INVALID; ++v) {
nodes.set(v, i);
++i;
}
for(ArcIt e(g); e != INVALID; ++e) {
os << "a " << nodes[g.source(e)] << " " << nodes[g.target(e)]
<< std::endl;
}
}
/// @}
} //namespace lemon
#endif //LEMON_DIMACS_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,556 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2013
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
#ifndef LEMON_EDMONDS_KARP_H
#define LEMON_EDMONDS_KARP_H
/// \file
/// \ingroup max_flow
/// \brief Implementation of the Edmonds-Karp algorithm.
#include <lemon/tolerance.h>
#include <vector>
namespace lemon {
/// \brief Default traits class of EdmondsKarp class.
///
/// Default traits class of EdmondsKarp class.
/// \param GR Digraph type.
/// \param CAP Type of capacity map.
template <typename GR, typename CAP>
struct EdmondsKarpDefaultTraits {
/// \brief The digraph type the algorithm runs on.
typedef GR Digraph;
/// \brief The type of the map that stores the arc capacities.
///
/// The type of the map that stores the arc capacities.
/// It must meet the \ref concepts::ReadMap "ReadMap" concept.
typedef CAP CapacityMap;
/// \brief The type of the flow values.
typedef typename CapacityMap::Value Value;
/// \brief The type of the map that stores the flow values.
///
/// The type of the map that stores the flow values.
/// It must meet the \ref concepts::ReadWriteMap "ReadWriteMap" concept.
#ifdef DOXYGEN
typedef GR::ArcMap<Value> FlowMap;
#else
typedef typename Digraph::template ArcMap<Value> FlowMap;
#endif
/// \brief Instantiates a FlowMap.
///
/// This function instantiates a \ref FlowMap.
/// \param digraph The digraph for which we would like to define
/// the flow map.
static FlowMap* createFlowMap(const Digraph& digraph) {
return new FlowMap(digraph);
}
/// \brief The tolerance used by the algorithm
///
/// The tolerance used by the algorithm to handle inexact computation.
typedef lemon::Tolerance<Value> Tolerance;
};
/// \ingroup max_flow
///
/// \brief Edmonds-Karp algorithms class.
///
/// This class provides an implementation of the \e Edmonds-Karp \e
/// algorithm producing a \ref max_flow "flow of maximum value" in a
/// digraph \cite clrs01algorithms, \cite amo93networkflows,
/// \cite edmondskarp72theoretical.
/// The Edmonds-Karp algorithm is slower than the Preflow
/// algorithm, but it has an advantage of the step-by-step execution
/// control with feasible flow solutions. The \e source node, the \e
/// target node, the \e capacity of the arcs and the \e starting \e
/// flow value of the arcs should be passed to the algorithm
/// through the constructor.
///
/// The time complexity of the algorithm is \f$ O(nm^2) \f$ in
/// worst case. Always try the Preflow algorithm instead of this if
/// you just want to compute the optimal flow.
///
/// \tparam GR The type of the digraph the algorithm runs on.
/// \tparam CAP The type of the capacity map. The default map
/// type is \ref concepts::Digraph::ArcMap "GR::ArcMap<int>".
/// \tparam TR The traits class that defines various types used by the
/// algorithm. By default, it is \ref EdmondsKarpDefaultTraits
/// "EdmondsKarpDefaultTraits<GR, CAP>".
/// In most cases, this parameter should not be set directly,
/// consider to use the named template parameters instead.
#ifdef DOXYGEN
template <typename GR, typename CAP, typename TR>
#else
template <typename GR,
typename CAP = typename GR::template ArcMap<int>,
typename TR = EdmondsKarpDefaultTraits<GR, CAP> >
#endif
class EdmondsKarp {
public:
/// \brief The \ref lemon::EdmondsKarpDefaultTraits "traits class"
/// of the algorithm.
typedef TR Traits;
/// The type of the digraph the algorithm runs on.
typedef typename Traits::Digraph Digraph;
/// The type of the capacity map.
typedef typename Traits::CapacityMap CapacityMap;
/// The type of the flow values.
typedef typename Traits::Value Value;
/// The type of the flow map.
typedef typename Traits::FlowMap FlowMap;
/// The type of the tolerance.
typedef typename Traits::Tolerance Tolerance;
private:
TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
typedef typename Digraph::template NodeMap<Arc> PredMap;
const Digraph& _graph;
const CapacityMap* _capacity;
Node _source, _target;
FlowMap* _flow;
bool _local_flow;
PredMap* _pred;
std::vector<Node> _queue;
Tolerance _tolerance;
Value _flow_value;
void createStructures() {
if (!_flow) {
_flow = Traits::createFlowMap(_graph);
_local_flow = true;
}
if (!_pred) {
_pred = new PredMap(_graph);
}
_queue.resize(countNodes(_graph));
}
void destroyStructures() {
if (_local_flow) {
delete _flow;
}
if (_pred) {
delete _pred;
}
}
public:
typedef EdmondsKarp Create;
///\name Named template parameters
///@{
template <typename T>
struct SetFlowMapTraits : public Traits {
typedef T FlowMap;
static FlowMap *createFlowMap(const Digraph&) {
LEMON_ASSERT(false, "FlowMap is not initialized");
return 0;
}
};
/// \brief \ref named-templ-param "Named parameter" for setting
/// FlowMap type
///
/// \ref named-templ-param "Named parameter" for setting FlowMap
/// type
template <typename T>
struct SetFlowMap
: public EdmondsKarp<Digraph, CapacityMap, SetFlowMapTraits<T> > {
typedef EdmondsKarp<Digraph, CapacityMap, SetFlowMapTraits<T> > Create;
};
/// @}
protected:
EdmondsKarp() {}
public:
/// \brief The constructor of the class.
///
/// The constructor of the class.
/// \param digraph The digraph the algorithm runs on.
/// \param capacity The capacity of the arcs.
/// \param source The source node.
/// \param target The target node.
EdmondsKarp(const Digraph& digraph, const CapacityMap& capacity,
Node source, Node target)
: _graph(digraph), _capacity(&capacity), _source(source), _target(target),
_flow(0), _local_flow(false), _pred(0), _tolerance(), _flow_value()
{
LEMON_ASSERT(_source != _target,
"Flow source and target are the same nodes.");
}
/// \brief Destructor.
///
/// Destructor.
~EdmondsKarp() {
destroyStructures();
}
/// \brief Sets the capacity map.
///
/// Sets the capacity map.
/// \return <tt>(*this)</tt>
EdmondsKarp& capacityMap(const CapacityMap& map) {
_capacity = &map;
return *this;
}
/// \brief Sets the flow map.
///
/// Sets the flow map.
/// If you don't use this function before calling \ref run() or
/// \ref init(), an instance will be allocated automatically.
/// The destructor deallocates this automatically allocated map,
/// of course.
/// \return <tt>(*this)</tt>
EdmondsKarp& flowMap(FlowMap& map) {
if (_local_flow) {
delete _flow;
_local_flow = false;
}
_flow = &map;
return *this;
}
/// \brief Sets the source node.
///
/// Sets the source node.
/// \return <tt>(*this)</tt>
EdmondsKarp& source(const Node& node) {
_source = node;
return *this;
}
/// \brief Sets the target node.
///
/// Sets the target node.
/// \return <tt>(*this)</tt>
EdmondsKarp& target(const Node& node) {
_target = node;
return *this;
}
/// \brief Sets the tolerance used by algorithm.
///
/// Sets the tolerance used by algorithm.
/// \return <tt>(*this)</tt>
EdmondsKarp& tolerance(const Tolerance& tolerance) {
_tolerance = tolerance;
return *this;
}
/// \brief Returns a const reference to the tolerance.
///
/// Returns a const reference to the tolerance object used by
/// the algorithm.
const Tolerance& tolerance() const {
return _tolerance;
}
/// \name Execution control
/// The simplest way to execute the algorithm is to use \ref run().\n
/// If you need better control on the initial solution or the execution,
/// you have to call one of the \ref init() functions first, then
/// \ref start() or multiple times the \ref augment() function.
///@{
/// \brief Initializes the algorithm.
///
/// Initializes the internal data structures and sets the initial
/// flow to zero on each arc.
void init() {
createStructures();
for (ArcIt it(_graph); it != INVALID; ++it) {
_flow->set(it, 0);
}
_flow_value = 0;
}
/// \brief Initializes the algorithm using the given flow map.
///
/// Initializes the internal data structures and sets the initial
/// flow to the given \c flowMap. The \c flowMap should
/// contain a feasible flow, i.e. at each node excluding the source
/// and the target, the incoming flow should be equal to the
/// outgoing flow.
template <typename FlowMap>
void init(const FlowMap& flowMap) {
createStructures();
for (ArcIt e(_graph); e != INVALID; ++e) {
_flow->set(e, flowMap[e]);
}
_flow_value = 0;
for (OutArcIt jt(_graph, _source); jt != INVALID; ++jt) {
_flow_value += (*_flow)[jt];
}
for (InArcIt jt(_graph, _source); jt != INVALID; ++jt) {
_flow_value -= (*_flow)[jt];
}
}
/// \brief Initializes the algorithm using the given flow map.
///
/// Initializes the internal data structures and sets the initial
/// flow to the given \c flowMap. The \c flowMap should
/// contain a feasible flow, i.e. at each node excluding the source
/// and the target, the incoming flow should be equal to the
/// outgoing flow.
/// \return \c false when the given \c flowMap does not contain a
/// feasible flow.
template <typename FlowMap>
bool checkedInit(const FlowMap& flowMap) {
createStructures();
for (ArcIt e(_graph); e != INVALID; ++e) {
_flow->set(e, flowMap[e]);
}
for (NodeIt it(_graph); it != INVALID; ++it) {
if (it == _source || it == _target) continue;
Value outFlow = 0;
for (OutArcIt jt(_graph, it); jt != INVALID; ++jt) {
outFlow += (*_flow)[jt];
}
Value inFlow = 0;
for (InArcIt jt(_graph, it); jt != INVALID; ++jt) {
inFlow += (*_flow)[jt];
}
if (_tolerance.different(outFlow, inFlow)) {
return false;
}
}
for (ArcIt it(_graph); it != INVALID; ++it) {
if (_tolerance.less((*_flow)[it], 0)) return false;
if (_tolerance.less((*_capacity)[it], (*_flow)[it])) return false;
}
_flow_value = 0;
for (OutArcIt jt(_graph, _source); jt != INVALID; ++jt) {
_flow_value += (*_flow)[jt];
}
for (InArcIt jt(_graph, _source); jt != INVALID; ++jt) {
_flow_value -= (*_flow)[jt];
}
return true;
}
/// \brief Augments the solution along a shortest path.
///
/// Augments the solution along a shortest path. This function searches a
/// shortest path between the source and the target
/// in the residual digraph by the Bfs algoritm.
/// Then it increases the flow on this path with the minimal residual
/// capacity on the path. If there is no such path, it gives back
/// false.
/// \return \c false when the augmenting did not success, i.e. the
/// current flow is a feasible and optimal solution.
bool augment() {
for (NodeIt n(_graph); n != INVALID; ++n) {
_pred->set(n, INVALID);
}
int first = 0, last = 1;
_queue[0] = _source;
_pred->set(_source, OutArcIt(_graph, _source));
while (first != last && (*_pred)[_target] == INVALID) {
Node n = _queue[first++];
for (OutArcIt e(_graph, n); e != INVALID; ++e) {
Value rem = (*_capacity)[e] - (*_flow)[e];
Node t = _graph.target(e);
if (_tolerance.positive(rem) && (*_pred)[t] == INVALID) {
_pred->set(t, e);
_queue[last++] = t;
}
}
for (InArcIt e(_graph, n); e != INVALID; ++e) {
Value rem = (*_flow)[e];
Node t = _graph.source(e);
if (_tolerance.positive(rem) && (*_pred)[t] == INVALID) {
_pred->set(t, e);
_queue[last++] = t;
}
}
}
if ((*_pred)[_target] != INVALID) {
Node n = _target;
Arc e = (*_pred)[n];
Value prem = (*_capacity)[e] - (*_flow)[e];
n = _graph.source(e);
while (n != _source) {
e = (*_pred)[n];
if (_graph.target(e) == n) {
Value rem = (*_capacity)[e] - (*_flow)[e];
if (rem < prem) prem = rem;
n = _graph.source(e);
} else {
Value rem = (*_flow)[e];
if (rem < prem) prem = rem;
n = _graph.target(e);
}
}
n = _target;
e = (*_pred)[n];
_flow->set(e, (*_flow)[e] + prem);
n = _graph.source(e);
while (n != _source) {
e = (*_pred)[n];
if (_graph.target(e) == n) {
_flow->set(e, (*_flow)[e] + prem);
n = _graph.source(e);
} else {
_flow->set(e, (*_flow)[e] - prem);
n = _graph.target(e);
}
}
_flow_value += prem;
return true;
} else {
return false;
}
}
/// \brief Executes the algorithm
///
/// Executes the algorithm by performing augmenting phases until the
/// optimal solution is reached.
/// \pre One of the \ref init() functions must be called before
/// using this function.
void start() {
while (augment()) {}
}
/// \brief Runs the algorithm.
///
/// Runs the Edmonds-Karp algorithm.
/// \note ek.run() is just a shortcut of the following code.
///\code
/// ek.init();
/// ek.start();
///\endcode
void run() {
init();
start();
}
/// @}
/// \name Query Functions
/// The result of the Edmonds-Karp algorithm can be obtained using these
/// functions.\n
/// Either \ref run() or \ref start() should be called before using them.
///@{
/// \brief Returns the value of the maximum flow.
///
/// Returns the value of the maximum flow found by the algorithm.
///
/// \pre Either \ref run() or \ref init() must be called before
/// using this function.
Value flowValue() const {
return _flow_value;
}
/// \brief Returns the flow value on the given arc.
///
/// Returns the flow value on the given arc.
///
/// \pre Either \ref run() or \ref init() must be called before
/// using this function.
Value flow(const Arc& arc) const {
return (*_flow)[arc];
}
/// \brief Returns a const reference to the flow map.
///
/// Returns a const reference to the arc map storing the found flow.
///
/// \pre Either \ref run() or \ref init() must be called before
/// using this function.
const FlowMap& flowMap() const {
return *_flow;
}
/// \brief Returns \c true when the node is on the source side of the
/// minimum cut.
///
/// Returns true when the node is on the source side of the found
/// minimum cut.
///
/// \pre Either \ref run() or \ref init() must be called before
/// using this function.
bool minCut(const Node& node) const {
return ((*_pred)[node] != INVALID) || node == _source;
}
/// \brief Gives back a minimum value cut.
///
/// Sets \c cutMap to the characteristic vector of a minimum value
/// cut. \c cutMap should be a \ref concepts::WriteMap "writable"
/// node map with \c bool (or convertible) value type.
///
/// \note This function calls \ref minCut() for each node, so it runs in
/// O(n) time.
///
/// \pre Either \ref run() or \ref init() must be called before
/// using this function.
template <typename CutMap>
void minCutMap(CutMap& cutMap) const {
for (NodeIt n(_graph); n != INVALID; ++n) {
cutMap.set(n, (*_pred)[n] != INVALID);
}
cutMap.set(_source, true);
}
/// @}
};
}
#endif

View File

@@ -0,0 +1,982 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2009
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
#ifndef LEMON_ELEVATOR_H
#define LEMON_ELEVATOR_H
///\ingroup auxdat
///\file
///\brief Elevator class
///
///Elevator class implements an efficient data structure
///for labeling items in push-relabel type algorithms.
///
#include <lemon/core.h>
#include <lemon/bits/traits.h>
namespace lemon {
///Class for handling "labels" in push-relabel type algorithms.
///A class for handling "labels" in push-relabel type algorithms.
///
///\ingroup auxdat
///Using this class you can assign "labels" (nonnegative integer numbers)
///to the edges or nodes of a graph, manipulate and query them through
///operations typically arising in "push-relabel" type algorithms.
///
///Each item is either \em active or not, and you can also choose a
///highest level active item.
///
///\sa LinkedElevator
///
///\param GR Type of the underlying graph.
///\param Item Type of the items the data is assigned to (\c GR::Node,
///\c GR::Arc or \c GR::Edge).
template<class GR, class Item>
class Elevator
{
public:
typedef Item Key;
typedef int Value;
private:
typedef Item *Vit;
typedef typename ItemSetTraits<GR,Item>::template Map<Vit>::Type VitMap;
typedef typename ItemSetTraits<GR,Item>::template Map<int>::Type IntMap;
const GR &_g;
int _max_level;
int _item_num;
VitMap _where;
IntMap _level;
std::vector<Item> _items;
std::vector<Vit> _first;
std::vector<Vit> _last_active;
int _highest_active;
void copy(Item i, Vit p)
{
_where[*p=i] = p;
}
void copy(Vit s, Vit p)
{
if(s!=p)
{
Item i=*s;
*p=i;
_where[i] = p;
}
}
void swap(Vit i, Vit j)
{
Item ti=*i;
Vit ct = _where[ti];
_where[ti] = _where[*i=*j];
_where[*j] = ct;
*j=ti;
}
public:
///Constructor with given maximum level.
///Constructor with given maximum level.
///
///\param graph The underlying graph.
///\param max_level The maximum allowed level.
///Set the range of the possible labels to <tt>[0..max_level]</tt>.
Elevator(const GR &graph,int max_level) :
_g(graph),
_max_level(max_level),
_item_num(_max_level),
_where(graph),
_level(graph,0),
_items(_max_level),
_first(_max_level+2),
_last_active(_max_level+2),
_highest_active(-1) {}
///Constructor.
///Constructor.
///
///\param graph The underlying graph.
///Set the range of the possible labels to <tt>[0..max_level]</tt>,
///where \c max_level is equal to the number of labeled items in the graph.
Elevator(const GR &graph) :
_g(graph),
_max_level(countItems<GR, Item>(graph)),
_item_num(_max_level),
_where(graph),
_level(graph,0),
_items(_max_level),
_first(_max_level+2),
_last_active(_max_level+2),
_highest_active(-1)
{
}
///Activate item \c i.
///Activate item \c i.
///\pre Item \c i shouldn't be active before.
void activate(Item i)
{
const int l=_level[i];
swap(_where[i],++_last_active[l]);
if(l>_highest_active) _highest_active=l;
}
///Deactivate item \c i.
///Deactivate item \c i.
///\pre Item \c i must be active before.
void deactivate(Item i)
{
swap(_where[i],_last_active[_level[i]]--);
while(_highest_active>=0 &&
_last_active[_highest_active]<_first[_highest_active])
_highest_active--;
}
///Query whether item \c i is active
bool active(Item i) const { return _where[i]<=_last_active[_level[i]]; }
///Return the level of item \c i.
int operator[](Item i) const { return _level[i]; }
///Return the number of items on level \c l.
int onLevel(int l) const
{
return _first[l+1]-_first[l];
}
///Return true if level \c l is empty.
bool emptyLevel(int l) const
{
return _first[l+1]-_first[l]==0;
}
///Return the number of items above level \c l.
int aboveLevel(int l) const
{
return _first[_max_level+1]-_first[l+1];
}
///Return the number of active items on level \c l.
int activesOnLevel(int l) const
{
return _last_active[l]-_first[l]+1;
}
///Return true if there is no active item on level \c l.
bool activeFree(int l) const
{
return _last_active[l]<_first[l];
}
///Return the maximum allowed level.
int maxLevel() const
{
return _max_level;
}
///\name Highest Active Item
///Functions for working with the highest level
///active item.
///@{
///Return a highest level active item.
///Return a highest level active item or INVALID if there is no active
///item.
Item highestActive() const
{
return _highest_active>=0?*_last_active[_highest_active]:INVALID;
}
///Return the highest active level.
///Return the level of the highest active item or -1 if there is no active
///item.
int highestActiveLevel() const
{
return _highest_active;
}
///Lift the highest active item by one.
///Lift the item returned by highestActive() by one.
///
void liftHighestActive()
{
Item it = *_last_active[_highest_active];
++_level[it];
swap(_last_active[_highest_active]--,_last_active[_highest_active+1]);
--_first[++_highest_active];
}
///Lift the highest active item to the given level.
///Lift the item returned by highestActive() to level \c new_level.
///
///\warning \c new_level must be strictly higher
///than the current level.
///
void liftHighestActive(int new_level)
{
const Item li = *_last_active[_highest_active];
copy(--_first[_highest_active+1],_last_active[_highest_active]--);
for(int l=_highest_active+1;l<new_level;l++)
{
copy(--_first[l+1],_first[l]);
--_last_active[l];
}
copy(li,_first[new_level]);
_level[li] = new_level;
_highest_active=new_level;
}
///Lift the highest active item to the top level.
///Lift the item returned by highestActive() to the top level and
///deactivate it.
void liftHighestActiveToTop()
{
const Item li = *_last_active[_highest_active];
copy(--_first[_highest_active+1],_last_active[_highest_active]--);
for(int l=_highest_active+1;l<_max_level;l++)
{
copy(--_first[l+1],_first[l]);
--_last_active[l];
}
copy(li,_first[_max_level]);
--_last_active[_max_level];
_level[li] = _max_level;
while(_highest_active>=0 &&
_last_active[_highest_active]<_first[_highest_active])
_highest_active--;
}
///@}
///\name Active Item on Certain Level
///Functions for working with the active items.
///@{
///Return an active item on level \c l.
///Return an active item on level \c l or \ref INVALID if there is no such
///an item. (\c l must be from the range [0...\c max_level].
Item activeOn(int l) const
{
return _last_active[l]>=_first[l]?*_last_active[l]:INVALID;
}
///Lift the active item returned by \c activeOn(level) by one.
///Lift the active item returned by \ref activeOn() "activeOn(level)"
///by one.
Item liftActiveOn(int level)
{
Item it =*_last_active[level];
++_level[it];
swap(_last_active[level]--, --_first[level+1]);
if (level+1>_highest_active) ++_highest_active;
}
///Lift the active item returned by \c activeOn(level) to the given level.
///Lift the active item returned by \ref activeOn() "activeOn(level)"
///to the given level.
void liftActiveOn(int level, int new_level)
{
const Item ai = *_last_active[level];
copy(--_first[level+1], _last_active[level]--);
for(int l=level+1;l<new_level;l++)
{
copy(_last_active[l],_first[l]);
copy(--_first[l+1], _last_active[l]--);
}
copy(ai,_first[new_level]);
_level[ai] = new_level;
if (new_level>_highest_active) _highest_active=new_level;
}
///Lift the active item returned by \c activeOn(level) to the top level.
///Lift the active item returned by \ref activeOn() "activeOn(level)"
///to the top level and deactivate it.
void liftActiveToTop(int level)
{
const Item ai = *_last_active[level];
copy(--_first[level+1],_last_active[level]--);
for(int l=level+1;l<_max_level;l++)
{
copy(_last_active[l],_first[l]);
copy(--_first[l+1], _last_active[l]--);
}
copy(ai,_first[_max_level]);
--_last_active[_max_level];
_level[ai] = _max_level;
if (_highest_active==level) {
while(_highest_active>=0 &&
_last_active[_highest_active]<_first[_highest_active])
_highest_active--;
}
}
///@}
///Lift an active item to a higher level.
///Lift an active item to a higher level.
///\param i The item to be lifted. It must be active.
///\param new_level The new level of \c i. It must be strictly higher
///than the current level.
///
void lift(Item i, int new_level)
{
const int lo = _level[i];
const Vit w = _where[i];
copy(_last_active[lo],w);
copy(--_first[lo+1],_last_active[lo]--);
for(int l=lo+1;l<new_level;l++)
{
copy(_last_active[l],_first[l]);
copy(--_first[l+1],_last_active[l]--);
}
copy(i,_first[new_level]);
_level[i] = new_level;
if(new_level>_highest_active) _highest_active=new_level;
}
///Move an inactive item to the top but one level (in a dirty way).
///This function moves an inactive item from the top level to the top
///but one level (in a dirty way).
///\warning It makes the underlying datastructure corrupt, so use it
///only if you really know what it is for.
///\pre The item is on the top level.
void dirtyTopButOne(Item i) {
_level[i] = _max_level - 1;
}
///Lift all items on and above the given level to the top level.
///This function lifts all items on and above level \c l to the top
///level and deactivates them.
void liftToTop(int l)
{
const Vit f=_first[l];
const Vit tl=_first[_max_level];
for(Vit i=f;i!=tl;++i)
_level[*i] = _max_level;
for(int i=l;i<=_max_level;i++)
{
_first[i]=f;
_last_active[i]=f-1;
}
for(_highest_active=l-1;
_highest_active>=0 &&
_last_active[_highest_active]<_first[_highest_active];
_highest_active--) ;
}
private:
int _init_lev;
Vit _init_num;
public:
///\name Initialization
///Using these functions you can initialize the levels of the items.
///\n
///The initialization must be started with calling \c initStart().
///Then the items should be listed level by level starting with the
///lowest one (level 0) using \c initAddItem() and \c initNewLevel().
///Finally \c initFinish() must be called.
///The items not listed are put on the highest level.
///@{
///Start the initialization process.
void initStart()
{
_init_lev=0;
_init_num=&_items[0];
_first[0]=&_items[0];
_last_active[0]=&_items[0]-1;
Vit n=&_items[0];
for(typename ItemSetTraits<GR,Item>::ItemIt i(_g);i!=INVALID;++i)
{
*n=i;
_where[i] = n;
_level[i] = _max_level;
++n;
}
}
///Add an item to the current level.
void initAddItem(Item i)
{
swap(_where[i],_init_num);
_level[i] = _init_lev;
++_init_num;
}
///Start a new level.
///Start a new level.
///It shouldn't be used before the items on level 0 are listed.
void initNewLevel()
{
_init_lev++;
_first[_init_lev]=_init_num;
_last_active[_init_lev]=_init_num-1;
}
///Finalize the initialization process.
void initFinish()
{
for(_init_lev++;_init_lev<=_max_level;_init_lev++)
{
_first[_init_lev]=_init_num;
_last_active[_init_lev]=_init_num-1;
}
_first[_max_level+1]=&_items[0]+_item_num;
_last_active[_max_level+1]=&_items[0]+_item_num-1;
_highest_active = -1;
}
///@}
};
///Class for handling "labels" in push-relabel type algorithms.
///A class for handling "labels" in push-relabel type algorithms.
///
///\ingroup auxdat
///Using this class you can assign "labels" (nonnegative integer numbers)
///to the edges or nodes of a graph, manipulate and query them through
///operations typically arising in "push-relabel" type algorithms.
///
///Each item is either \em active or not, and you can also choose a
///highest level active item.
///
///\sa Elevator
///
///\param GR Type of the underlying graph.
///\param Item Type of the items the data is assigned to (\c GR::Node,
///\c GR::Arc or \c GR::Edge).
template <class GR, class Item>
class LinkedElevator {
public:
typedef Item Key;
typedef int Value;
private:
typedef typename ItemSetTraits<GR,Item>::
template Map<Item>::Type ItemMap;
typedef typename ItemSetTraits<GR,Item>::
template Map<int>::Type IntMap;
typedef typename ItemSetTraits<GR,Item>::
template Map<bool>::Type BoolMap;
const GR &_graph;
int _max_level;
int _item_num;
std::vector<Item> _first, _last;
ItemMap _prev, _next;
int _highest_active;
IntMap _level;
BoolMap _active;
public:
///Constructor with given maximum level.
///Constructor with given maximum level.
///
///\param graph The underlying graph.
///\param max_level The maximum allowed level.
///Set the range of the possible labels to <tt>[0..max_level]</tt>.
LinkedElevator(const GR& graph, int max_level)
: _graph(graph), _max_level(max_level), _item_num(_max_level),
_first(_max_level + 1), _last(_max_level + 1),
_prev(graph), _next(graph),
_highest_active(-1), _level(graph), _active(graph) {}
///Constructor.
///Constructor.
///
///\param graph The underlying graph.
///Set the range of the possible labels to <tt>[0..max_level]</tt>,
///where \c max_level is equal to the number of labeled items in the graph.
LinkedElevator(const GR& graph)
: _graph(graph), _max_level(countItems<GR, Item>(graph)),
_item_num(_max_level),
_first(_max_level + 1), _last(_max_level + 1),
_prev(graph, INVALID), _next(graph, INVALID),
_highest_active(-1), _level(graph), _active(graph) {}
///Activate item \c i.
///Activate item \c i.
///\pre Item \c i shouldn't be active before.
void activate(Item i) {
_active[i] = true;
int level = _level[i];
if (level > _highest_active) {
_highest_active = level;
}
if (_prev[i] == INVALID || _active[_prev[i]]) return;
//unlace
_next[_prev[i]] = _next[i];
if (_next[i] != INVALID) {
_prev[_next[i]] = _prev[i];
} else {
_last[level] = _prev[i];
}
//lace
_next[i] = _first[level];
_prev[_first[level]] = i;
_prev[i] = INVALID;
_first[level] = i;
}
///Deactivate item \c i.
///Deactivate item \c i.
///\pre Item \c i must be active before.
void deactivate(Item i) {
_active[i] = false;
int level = _level[i];
if (_next[i] == INVALID || !_active[_next[i]])
goto find_highest_level;
//unlace
_prev[_next[i]] = _prev[i];
if (_prev[i] != INVALID) {
_next[_prev[i]] = _next[i];
} else {
_first[_level[i]] = _next[i];
}
//lace
_prev[i] = _last[level];
_next[_last[level]] = i;
_next[i] = INVALID;
_last[level] = i;
find_highest_level:
if (level == _highest_active) {
while (_highest_active >= 0 && activeFree(_highest_active))
--_highest_active;
}
}
///Query whether item \c i is active
bool active(Item i) const { return _active[i]; }
///Return the level of item \c i.
int operator[](Item i) const { return _level[i]; }
///Return the number of items on level \c l.
int onLevel(int l) const {
int num = 0;
Item n = _first[l];
while (n != INVALID) {
++num;
n = _next[n];
}
return num;
}
///Return true if the level is empty.
bool emptyLevel(int l) const {
return _first[l] == INVALID;
}
///Return the number of items above level \c l.
int aboveLevel(int l) const {
int num = 0;
for (int level = l + 1; level < _max_level; ++level)
num += onLevel(level);
return num;
}
///Return the number of active items on level \c l.
int activesOnLevel(int l) const {
int num = 0;
Item n = _first[l];
while (n != INVALID && _active[n]) {
++num;
n = _next[n];
}
return num;
}
///Return true if there is no active item on level \c l.
bool activeFree(int l) const {
return _first[l] == INVALID || !_active[_first[l]];
}
///Return the maximum allowed level.
int maxLevel() const {
return _max_level;
}
///\name Highest Active Item
///Functions for working with the highest level
///active item.
///@{
///Return a highest level active item.
///Return a highest level active item or INVALID if there is no active
///item.
Item highestActive() const {
return _highest_active >= 0 ? _first[_highest_active] : INVALID;
}
///Return the highest active level.
///Return the level of the highest active item or -1 if there is no active
///item.
int highestActiveLevel() const {
return _highest_active;
}
///Lift the highest active item by one.
///Lift the item returned by highestActive() by one.
///
void liftHighestActive() {
Item i = _first[_highest_active];
if (_next[i] != INVALID) {
_prev[_next[i]] = INVALID;
_first[_highest_active] = _next[i];
} else {
_first[_highest_active] = INVALID;
_last[_highest_active] = INVALID;
}
_level[i] = ++_highest_active;
if (_first[_highest_active] == INVALID) {
_first[_highest_active] = i;
_last[_highest_active] = i;
_prev[i] = INVALID;
_next[i] = INVALID;
} else {
_prev[_first[_highest_active]] = i;
_next[i] = _first[_highest_active];
_first[_highest_active] = i;
}
}
///Lift the highest active item to the given level.
///Lift the item returned by highestActive() to level \c new_level.
///
///\warning \c new_level must be strictly higher
///than the current level.
///
void liftHighestActive(int new_level) {
Item i = _first[_highest_active];
if (_next[i] != INVALID) {
_prev[_next[i]] = INVALID;
_first[_highest_active] = _next[i];
} else {
_first[_highest_active] = INVALID;
_last[_highest_active] = INVALID;
}
_level[i] = _highest_active = new_level;
if (_first[_highest_active] == INVALID) {
_first[_highest_active] = _last[_highest_active] = i;
_prev[i] = INVALID;
_next[i] = INVALID;
} else {
_prev[_first[_highest_active]] = i;
_next[i] = _first[_highest_active];
_first[_highest_active] = i;
}
}
///Lift the highest active item to the top level.
///Lift the item returned by highestActive() to the top level and
///deactivate it.
void liftHighestActiveToTop() {
Item i = _first[_highest_active];
_level[i] = _max_level;
if (_next[i] != INVALID) {
_prev[_next[i]] = INVALID;
_first[_highest_active] = _next[i];
} else {
_first[_highest_active] = INVALID;
_last[_highest_active] = INVALID;
}
while (_highest_active >= 0 && activeFree(_highest_active))
--_highest_active;
}
///@}
///\name Active Item on Certain Level
///Functions for working with the active items.
///@{
///Return an active item on level \c l.
///Return an active item on level \c l or \ref INVALID if there is no such
///an item. (\c l must be from the range [0...\c max_level].
Item activeOn(int l) const
{
return _active[_first[l]] ? _first[l] : INVALID;
}
///Lift the active item returned by \c activeOn(l) by one.
///Lift the active item returned by \ref activeOn() "activeOn(l)"
///by one.
Item liftActiveOn(int l)
{
Item i = _first[l];
if (_next[i] != INVALID) {
_prev[_next[i]] = INVALID;
_first[l] = _next[i];
} else {
_first[l] = INVALID;
_last[l] = INVALID;
}
_level[i] = ++l;
if (_first[l] == INVALID) {
_first[l] = _last[l] = i;
_prev[i] = INVALID;
_next[i] = INVALID;
} else {
_prev[_first[l]] = i;
_next[i] = _first[l];
_first[l] = i;
}
if (_highest_active < l) {
_highest_active = l;
}
}
///Lift the active item returned by \c activeOn(l) to the given level.
///Lift the active item returned by \ref activeOn() "activeOn(l)"
///to the given level.
void liftActiveOn(int l, int new_level)
{
Item i = _first[l];
if (_next[i] != INVALID) {
_prev[_next[i]] = INVALID;
_first[l] = _next[i];
} else {
_first[l] = INVALID;
_last[l] = INVALID;
}
_level[i] = l = new_level;
if (_first[l] == INVALID) {
_first[l] = _last[l] = i;
_prev[i] = INVALID;
_next[i] = INVALID;
} else {
_prev[_first[l]] = i;
_next[i] = _first[l];
_first[l] = i;
}
if (_highest_active < l) {
_highest_active = l;
}
}
///Lift the active item returned by \c activeOn(l) to the top level.
///Lift the active item returned by \ref activeOn() "activeOn(l)"
///to the top level and deactivate it.
void liftActiveToTop(int l)
{
Item i = _first[l];
if (_next[i] != INVALID) {
_prev[_next[i]] = INVALID;
_first[l] = _next[i];
} else {
_first[l] = INVALID;
_last[l] = INVALID;
}
_level[i] = _max_level;
if (l == _highest_active) {
while (_highest_active >= 0 && activeFree(_highest_active))
--_highest_active;
}
}
///@}
/// \brief Lift an active item to a higher level.
///
/// Lift an active item to a higher level.
/// \param i The item to be lifted. It must be active.
/// \param new_level The new level of \c i. It must be strictly higher
/// than the current level.
///
void lift(Item i, int new_level) {
if (_next[i] != INVALID) {
_prev[_next[i]] = _prev[i];
} else {
_last[new_level] = _prev[i];
}
if (_prev[i] != INVALID) {
_next[_prev[i]] = _next[i];
} else {
_first[new_level] = _next[i];
}
_level[i] = new_level;
if (_first[new_level] == INVALID) {
_first[new_level] = _last[new_level] = i;
_prev[i] = INVALID;
_next[i] = INVALID;
} else {
_prev[_first[new_level]] = i;
_next[i] = _first[new_level];
_first[new_level] = i;
}
if (_highest_active < new_level) {
_highest_active = new_level;
}
}
///Move an inactive item to the top but one level (in a dirty way).
///This function moves an inactive item from the top level to the top
///but one level (in a dirty way).
///\warning It makes the underlying datastructure corrupt, so use it
///only if you really know what it is for.
///\pre The item is on the top level.
void dirtyTopButOne(Item i) {
_level[i] = _max_level - 1;
}
///Lift all items on and above the given level to the top level.
///This function lifts all items on and above level \c l to the top
///level and deactivates them.
void liftToTop(int l) {
for (int i = l + 1; _first[i] != INVALID; ++i) {
Item n = _first[i];
while (n != INVALID) {
_level[n] = _max_level;
n = _next[n];
}
_first[i] = INVALID;
_last[i] = INVALID;
}
if (_highest_active > l - 1) {
_highest_active = l - 1;
while (_highest_active >= 0 && activeFree(_highest_active))
--_highest_active;
}
}
private:
int _init_level;
public:
///\name Initialization
///Using these functions you can initialize the levels of the items.
///\n
///The initialization must be started with calling \c initStart().
///Then the items should be listed level by level starting with the
///lowest one (level 0) using \c initAddItem() and \c initNewLevel().
///Finally \c initFinish() must be called.
///The items not listed are put on the highest level.
///@{
///Start the initialization process.
void initStart() {
for (int i = 0; i <= _max_level; ++i) {
_first[i] = _last[i] = INVALID;
}
_init_level = 0;
for(typename ItemSetTraits<GR,Item>::ItemIt i(_graph);
i != INVALID; ++i) {
_level[i] = _max_level;
_active[i] = false;
}
}
///Add an item to the current level.
void initAddItem(Item i) {
_level[i] = _init_level;
if (_last[_init_level] == INVALID) {
_first[_init_level] = i;
_last[_init_level] = i;
_prev[i] = INVALID;
_next[i] = INVALID;
} else {
_prev[i] = _last[_init_level];
_next[i] = INVALID;
_next[_last[_init_level]] = i;
_last[_init_level] = i;
}
}
///Start a new level.
///Start a new level.
///It shouldn't be used before the items on level 0 are listed.
void initNewLevel() {
++_init_level;
}
///Finalize the initialization process.
void initFinish() {
_highest_active = -1;
}
///@}
};
} //END OF NAMESPACE LEMON
#endif

View File

@@ -0,0 +1,276 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2009
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
#ifndef LEMON_ERROR_H
#define LEMON_ERROR_H
/// \ingroup exceptions
/// \file
/// \brief Basic exception classes and error handling.
#include <exception>
#include <string>
#include <sstream>
#include <iostream>
#include <cstdlib>
#include <memory>
namespace lemon {
/// \addtogroup exceptions
/// @{
/// \brief Generic exception class.
///
/// Base class for exceptions used in LEMON.
///
class Exception : public std::exception {
public:
///Constructor
Exception() throw() {}
///Virtual destructor
virtual ~Exception() throw() {}
///A short description of the exception
virtual const char* what() const throw() {
return "lemon::Exception";
}
};
/// \brief Input-Output error
///
/// This exception is thrown when a file operation cannot be
/// succeeded.
class IoError : public Exception {
protected:
std::string _message;
std::string _file;
mutable std::string _what;
public:
/// Copy constructor
IoError(const IoError &error) throw() : Exception() {
message(error._message);
file(error._file);
}
/// Constructor
explicit IoError(const char *message) throw() {
IoError::message(message);
}
/// Constructor
explicit IoError(const std::string &message) throw() {
IoError::message(message);
}
/// Constructor
explicit IoError(const char *message,
const std::string &file) throw() {
IoError::message(message);
IoError::file(file);
}
/// Constructor
explicit IoError(const std::string &message,
const std::string &file) throw() {
IoError::message(message);
IoError::file(file);
}
/// Virtual destructor
virtual ~IoError() throw() {}
/// Set the error message
void message(const char *message) throw() {
try {
_message = message;
} catch (...) {}
}
/// Set the error message
void message(const std::string& message) throw() {
try {
_message = message;
} catch (...) {}
}
/// Set the file name
void file(const std::string &file) throw() {
try {
_file = file;
} catch (...) {}
}
/// Returns the error message
const std::string& message() const throw() {
return _message;
}
/// \brief Returns the filename
///
/// Returns the filename or an empty string if it was not specified.
const std::string& file() const throw() {
return _file;
}
/// \brief Returns a short error message
///
/// Returns a short error message which contains the message and the
/// file name.
virtual const char* what() const throw() {
try {
_what.clear();
std::ostringstream oss;
oss << "lemon:IoError" << ": ";
oss << _message;
if (!_file.empty()) {
oss << " ('" << _file << "')";
}
_what = oss.str();
}
catch (...) {}
if (!_what.empty()) return _what.c_str();
else return "lemon:IoError";
}
};
/// \brief Format error
///
/// This exception is thrown when an input file has wrong
/// format or a data representation is not legal.
class FormatError : public Exception {
protected:
std::string _message;
std::string _file;
int _line;
mutable std::string _what;
public:
/// Copy constructor
FormatError(const FormatError &error) throw() : Exception() {
message(error._message);
file(error._file);
line(error._line);
}
/// Constructor
explicit FormatError(const char *message) throw() {
FormatError::message(message);
_line = 0;
}
/// Constructor
explicit FormatError(const std::string &message) throw() {
FormatError::message(message);
_line = 0;
}
/// Constructor
explicit FormatError(const char *message,
const std::string &file, int line = 0) throw() {
FormatError::message(message);
FormatError::file(file);
FormatError::line(line);
}
/// Constructor
explicit FormatError(const std::string &message,
const std::string &file, int line = 0) throw() {
FormatError::message(message);
FormatError::file(file);
FormatError::line(line);
}
/// Virtual destructor
virtual ~FormatError() throw() {}
/// Set the line number
void line(int line) throw() { _line = line; }
/// Set the error message
void message(const char *message) throw() {
try {
_message = message;
} catch (...) {}
}
/// Set the error message
void message(const std::string& message) throw() {
try {
_message = message;
} catch (...) {}
}
/// Set the file name
void file(const std::string &file) throw() {
try {
_file = file;
} catch (...) {}
}
/// \brief Returns the line number
///
/// Returns the line number or zero if it was not specified.
int line() const throw() { return _line; }
/// Returns the error message
const std::string& message() const throw() {
return _message;
}
/// \brief Returns the filename
///
/// Returns the filename or an empty string if it was not specified.
const std::string& file() const throw() {
return _file;
}
/// \brief Returns a short error message
///
/// Returns a short error message which contains the message, the
/// file name and the line number.
virtual const char* what() const throw() {
try {
_what.clear();
std::ostringstream oss;
oss << "lemon:FormatError" << ": ";
oss << _message;
if (!_file.empty() || _line != 0) {
oss << " (";
if (!_file.empty()) oss << "in file '" << _file << "'";
if (!_file.empty() && _line != 0) oss << " ";
if (_line != 0) oss << "at line " << _line;
oss << ")";
}
_what = oss.str();
}
catch (...) {}
if (!_what.empty()) return _what.c_str();
else return "lemon:FormatError";
}
};
/// @}
}
#endif // LEMON_ERROR_H

View File

@@ -0,0 +1,287 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2013
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
#ifndef LEMON_EULER_H
#define LEMON_EULER_H
#include<lemon/core.h>
#include<lemon/adaptors.h>
#include<lemon/connectivity.h>
#include <list>
/// \ingroup graph_properties
/// \file
/// \brief Euler tour iterators and a function for checking the \e Eulerian
/// property.
///
///This file provides Euler tour iterators and a function to check
///if a (di)graph is \e Eulerian.
namespace lemon {
///Euler tour iterator for digraphs.
/// \ingroup graph_properties
///This iterator provides an Euler tour (Eulerian circuit) of a \e directed
///graph (if there exists) and it converts to the \c Arc type of the digraph.
///
///For example, if the given digraph has an Euler tour (i.e it has only one
///non-trivial component and the in-degree is equal to the out-degree
///for all nodes), then the following code will put the arcs of \c g
///to the vector \c et according to an Euler tour of \c g.
///\code
/// std::vector<ListDigraph::Arc> et;
/// for(DiEulerIt<ListDigraph> e(g); e!=INVALID; ++e)
/// et.push_back(e);
///\endcode
///If \c g has no Euler tour, then the resulted walk will not be closed
///or not contain all arcs.
///\sa EulerIt
template<typename GR>
class DiEulerIt
{
typedef typename GR::Node Node;
typedef typename GR::NodeIt NodeIt;
typedef typename GR::Arc Arc;
typedef typename GR::ArcIt ArcIt;
typedef typename GR::OutArcIt OutArcIt;
typedef typename GR::InArcIt InArcIt;
const GR &g;
typename GR::template NodeMap<OutArcIt> narc;
std::list<Arc> euler;
public:
///Constructor
///Constructor.
///\param gr A digraph.
///\param start The starting point of the tour. If it is not given,
///the tour will start from the first node that has an outgoing arc.
DiEulerIt(const GR &gr, typename GR::Node start = INVALID)
: g(gr), narc(g)
{
if (start==INVALID) {
NodeIt n(g);
while (n!=INVALID && OutArcIt(g,n)==INVALID) ++n;
start=n;
}
if (start!=INVALID) {
for (NodeIt n(g); n!=INVALID; ++n) narc[n]=OutArcIt(g,n);
while (narc[start]!=INVALID) {
euler.push_back(narc[start]);
Node next=g.target(narc[start]);
++narc[start];
start=next;
}
}
}
///Arc conversion
operator Arc() { return euler.empty()?INVALID:euler.front(); }
///Compare with \c INVALID
bool operator==(Invalid) { return euler.empty(); }
///Compare with \c INVALID
bool operator!=(Invalid) { return !euler.empty(); }
///Next arc of the tour
///Next arc of the tour
///
DiEulerIt &operator++() {
Node s=g.target(euler.front());
euler.pop_front();
typename std::list<Arc>::iterator next=euler.begin();
while(narc[s]!=INVALID) {
euler.insert(next,narc[s]);
Node n=g.target(narc[s]);
++narc[s];
s=n;
}
return *this;
}
///Postfix incrementation
/// Postfix incrementation.
///
///\warning This incrementation
///returns an \c Arc, not a \ref DiEulerIt, as one may
///expect.
Arc operator++(int)
{
Arc e=*this;
++(*this);
return e;
}
};
///Euler tour iterator for graphs.
/// \ingroup graph_properties
///This iterator provides an Euler tour (Eulerian circuit) of an
///\e undirected graph (if there exists) and it converts to the \c Arc
///and \c Edge types of the graph.
///
///For example, if the given graph has an Euler tour (i.e it has only one
///non-trivial component and the degree of each node is even),
///the following code will print the arc IDs according to an
///Euler tour of \c g.
///\code
/// for(EulerIt<ListGraph> e(g); e!=INVALID; ++e) {
/// std::cout << g.id(Edge(e)) << std::eol;
/// }
///\endcode
///Although this iterator is for undirected graphs, it still returns
///arcs in order to indicate the direction of the tour.
///(But arcs convert to edges, of course.)
///
///If \c g has no Euler tour, then the resulted walk will not be closed
///or not contain all edges.
template<typename GR>
class EulerIt
{
typedef typename GR::Node Node;
typedef typename GR::NodeIt NodeIt;
typedef typename GR::Arc Arc;
typedef typename GR::Edge Edge;
typedef typename GR::ArcIt ArcIt;
typedef typename GR::OutArcIt OutArcIt;
typedef typename GR::InArcIt InArcIt;
const GR &g;
typename GR::template NodeMap<OutArcIt> narc;
typename GR::template EdgeMap<bool> visited;
std::list<Arc> euler;
public:
///Constructor
///Constructor.
///\param gr A graph.
///\param start The starting point of the tour. If it is not given,
///the tour will start from the first node that has an incident edge.
EulerIt(const GR &gr, typename GR::Node start = INVALID)
: g(gr), narc(g), visited(g, false)
{
if (start==INVALID) {
NodeIt n(g);
while (n!=INVALID && OutArcIt(g,n)==INVALID) ++n;
start=n;
}
if (start!=INVALID) {
for (NodeIt n(g); n!=INVALID; ++n) narc[n]=OutArcIt(g,n);
while(narc[start]!=INVALID) {
euler.push_back(narc[start]);
visited[narc[start]]=true;
Node next=g.target(narc[start]);
++narc[start];
start=next;
while(narc[start]!=INVALID && visited[narc[start]]) ++narc[start];
}
}
}
///Arc conversion
operator Arc() const { return euler.empty()?INVALID:euler.front(); }
///Edge conversion
operator Edge() const { return euler.empty()?INVALID:euler.front(); }
///Compare with \c INVALID
bool operator==(Invalid) const { return euler.empty(); }
///Compare with \c INVALID
bool operator!=(Invalid) const { return !euler.empty(); }
///Next arc of the tour
///Next arc of the tour
///
EulerIt &operator++() {
Node s=g.target(euler.front());
euler.pop_front();
typename std::list<Arc>::iterator next=euler.begin();
while(narc[s]!=INVALID) {
while(narc[s]!=INVALID && visited[narc[s]]) ++narc[s];
if(narc[s]==INVALID) break;
else {
euler.insert(next,narc[s]);
visited[narc[s]]=true;
Node n=g.target(narc[s]);
++narc[s];
s=n;
}
}
return *this;
}
///Postfix incrementation
/// Postfix incrementation.
///
///\warning This incrementation returns an \c Arc (which converts to
///an \c Edge), not an \ref EulerIt, as one may expect.
Arc operator++(int)
{
Arc e=*this;
++(*this);
return e;
}
};
///Check if the given graph is Eulerian
/// \ingroup graph_properties
///This function checks if the given graph is Eulerian.
///It works for both directed and undirected graphs.
///
///By definition, a digraph is called \e Eulerian if
///and only if it is connected and the number of incoming and outgoing
///arcs are the same for each node.
///Similarly, an undirected graph is called \e Eulerian if
///and only if it is connected and the number of incident edges is even
///for each node.
///
///\note There are (di)graphs that are not Eulerian, but still have an
/// Euler tour, since they may contain isolated nodes.
///
///\sa DiEulerIt, EulerIt
template<typename GR>
#ifdef DOXYGEN
bool
#else
typename enable_if<UndirectedTagIndicator<GR>,bool>::type
eulerian(const GR &g)
{
for(typename GR::NodeIt n(g);n!=INVALID;++n)
if(countIncEdges(g,n)%2) return false;
return connected(g);
}
template<class GR>
typename disable_if<UndirectedTagIndicator<GR>,bool>::type
#endif
eulerian(const GR &g)
{
for(typename GR::NodeIt n(g);n!=INVALID;++n)
if(countInArcs(g,n)!=countOutArcs(g,n)) return false;
return connected(undirector(g));
}
}
#endif

View File

@@ -0,0 +1,475 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2009
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
#ifndef LEMON_FIB_HEAP_H
#define LEMON_FIB_HEAP_H
///\file
///\ingroup heaps
///\brief Fibonacci heap implementation.
#include <vector>
#include <utility>
#include <functional>
#include <lemon/math.h>
namespace lemon {
/// \ingroup heaps
///
/// \brief Fibonacci heap data structure.
///
/// This class implements the \e Fibonacci \e heap data structure.
/// It fully conforms to the \ref concepts::Heap "heap concept".
///
/// The methods \ref increase() and \ref erase() are not efficient in a
/// Fibonacci heap. In case of many calls of these operations, it is
/// better to use other heap structure, e.g. \ref BinHeap "binary heap".
///
/// \tparam PR Type of the priorities of the items.
/// \tparam IM A read-writable item map with \c int values, used
/// internally to handle the cross references.
/// \tparam CMP A functor class for comparing the priorities.
/// The default is \c std::less<PR>.
#ifdef DOXYGEN
template <typename PR, typename IM, typename CMP>
#else
template <typename PR, typename IM, typename CMP = std::less<PR> >
#endif
class FibHeap {
public:
/// Type of the item-int map.
typedef IM ItemIntMap;
/// Type of the priorities.
typedef PR Prio;
/// Type of the items stored in the heap.
typedef typename ItemIntMap::Key Item;
/// Type of the item-priority pairs.
typedef std::pair<Item,Prio> Pair;
/// Functor type for comparing the priorities.
typedef CMP Compare;
private:
class Store;
std::vector<Store> _data;
int _minimum;
ItemIntMap &_iim;
Compare _comp;
int _num;
public:
/// \brief Type to represent the states of the items.
///
/// Each item has a state associated to it. It can be "in heap",
/// "pre-heap" or "post-heap". The latter two are indifferent from the
/// heap's point of view, but may be useful to the user.
///
/// The item-int map must be initialized in such way that it assigns
/// \c PRE_HEAP (<tt>-1</tt>) to any element to be put in the heap.
enum State {
IN_HEAP = 0, ///< = 0.
PRE_HEAP = -1, ///< = -1.
POST_HEAP = -2 ///< = -2.
};
/// \brief Constructor.
///
/// Constructor.
/// \param map A map that assigns \c int values to the items.
/// It is used internally to handle the cross references.
/// The assigned value must be \c PRE_HEAP (<tt>-1</tt>) for each item.
explicit FibHeap(ItemIntMap &map)
: _minimum(0), _iim(map), _num() {}
/// \brief Constructor.
///
/// Constructor.
/// \param map A map that assigns \c int values to the items.
/// It is used internally to handle the cross references.
/// The assigned value must be \c PRE_HEAP (<tt>-1</tt>) for each item.
/// \param comp The function object used for comparing the priorities.
FibHeap(ItemIntMap &map, const Compare &comp)
: _minimum(0), _iim(map), _comp(comp), _num() {}
/// \brief The number of items stored in the heap.
///
/// This function returns the number of items stored in the heap.
int size() const { return _num; }
/// \brief Check if the heap is empty.
///
/// This function returns \c true if the heap is empty.
bool empty() const { return _num==0; }
/// \brief Make the heap empty.
///
/// This functon makes the heap empty.
/// It does not change the cross reference map. If you want to reuse
/// a heap that is not surely empty, you should first clear it and
/// then you should set the cross reference map to \c PRE_HEAP
/// for each item.
void clear() {
_data.clear(); _minimum = 0; _num = 0;
}
/// \brief Insert an item into the heap with the given priority.
///
/// This function inserts the given item into the heap with the
/// given priority.
/// \param item The item to insert.
/// \param prio The priority of the item.
/// \pre \e item must not be stored in the heap.
void push (const Item& item, const Prio& prio) {
int i=_iim[item];
if ( i < 0 ) {
int s=_data.size();
_iim.set( item, s );
Store st;
st.name=item;
_data.push_back(st);
i=s;
} else {
_data[i].parent=_data[i].child=-1;
_data[i].degree=0;
_data[i].in=true;
_data[i].marked=false;
}
if ( _num ) {
_data[_data[_minimum].right_neighbor].left_neighbor=i;
_data[i].right_neighbor=_data[_minimum].right_neighbor;
_data[_minimum].right_neighbor=i;
_data[i].left_neighbor=_minimum;
if ( _comp( prio, _data[_minimum].prio) ) _minimum=i;
} else {
_data[i].right_neighbor=_data[i].left_neighbor=i;
_minimum=i;
}
_data[i].prio=prio;
++_num;
}
/// \brief Return the item having minimum priority.
///
/// This function returns the item having minimum priority.
/// \pre The heap must be non-empty.
Item top() const { return _data[_minimum].name; }
/// \brief The minimum priority.
///
/// This function returns the minimum priority.
/// \pre The heap must be non-empty.
Prio prio() const { return _data[_minimum].prio; }
/// \brief Remove the item having minimum priority.
///
/// This function removes the item having minimum priority.
/// \pre The heap must be non-empty.
void pop() {
/*The first case is that there are only one root.*/
if ( _data[_minimum].left_neighbor==_minimum ) {
_data[_minimum].in=false;
if ( _data[_minimum].degree!=0 ) {
makeRoot(_data[_minimum].child);
_minimum=_data[_minimum].child;
balance();
}
} else {
int right=_data[_minimum].right_neighbor;
unlace(_minimum);
_data[_minimum].in=false;
if ( _data[_minimum].degree > 0 ) {
int left=_data[_minimum].left_neighbor;
int child=_data[_minimum].child;
int last_child=_data[child].left_neighbor;
makeRoot(child);
_data[left].right_neighbor=child;
_data[child].left_neighbor=left;
_data[right].left_neighbor=last_child;
_data[last_child].right_neighbor=right;
}
_minimum=right;
balance();
} // the case where there are more roots
--_num;
}
/// \brief Remove the given item from the heap.
///
/// This function removes the given item from the heap if it is
/// already stored.
/// \param item The item to delete.
/// \pre \e item must be in the heap.
void erase (const Item& item) {
int i=_iim[item];
if ( i >= 0 && _data[i].in ) {
if ( _data[i].parent!=-1 ) {
int p=_data[i].parent;
cut(i,p);
cascade(p);
}
_minimum=i; //As if its prio would be -infinity
pop();
}
}
/// \brief The priority of the given item.
///
/// This function returns the priority of the given item.
/// \param item The item.
/// \pre \e item must be in the heap.
Prio operator[](const Item& item) const {
return _data[_iim[item]].prio;
}
/// \brief Set the priority of an item or insert it, if it is
/// not stored in the heap.
///
/// This method sets the priority of the given item if it is
/// already stored in the heap. Otherwise it inserts the given
/// item into the heap with the given priority.
/// \param item The item.
/// \param prio The priority.
void set (const Item& item, const Prio& prio) {
int i=_iim[item];
if ( i >= 0 && _data[i].in ) {
if ( _comp(prio, _data[i].prio) ) decrease(item, prio);
if ( _comp(_data[i].prio, prio) ) increase(item, prio);
} else push(item, prio);
}
/// \brief Decrease the priority of an item to the given value.
///
/// This function decreases the priority of an item to the given value.
/// \param item The item.
/// \param prio The priority.
/// \pre \e item must be stored in the heap with priority at least \e prio.
void decrease (const Item& item, const Prio& prio) {
int i=_iim[item];
_data[i].prio=prio;
int p=_data[i].parent;
if ( p!=-1 && _comp(prio, _data[p].prio) ) {
cut(i,p);
cascade(p);
}
if ( _comp(prio, _data[_minimum].prio) ) _minimum=i;
}
/// \brief Increase the priority of an item to the given value.
///
/// This function increases the priority of an item to the given value.
/// \param item The item.
/// \param prio The priority.
/// \pre \e item must be stored in the heap with priority at most \e prio.
void increase (const Item& item, const Prio& prio) {
erase(item);
push(item, prio);
}
/// \brief Return the state of an item.
///
/// This method returns \c PRE_HEAP if the given item has never
/// been in the heap, \c IN_HEAP if it is in the heap at the moment,
/// and \c POST_HEAP otherwise.
/// In the latter case it is possible that the item will get back
/// to the heap again.
/// \param item The item.
State state(const Item &item) const {
int i=_iim[item];
if( i>=0 ) {
if ( _data[i].in ) i=0;
else i=-2;
}
return State(i);
}
/// \brief Set the state of an item in the heap.
///
/// This function sets the state of the given item in the heap.
/// It can be used to manually clear the heap when it is important
/// to achive better time complexity.
/// \param i The item.
/// \param st The state. It should not be \c IN_HEAP.
void state(const Item& i, State st) {
switch (st) {
case POST_HEAP:
case PRE_HEAP:
if (state(i) == IN_HEAP) {
erase(i);
}
_iim[i] = st;
break;
case IN_HEAP:
break;
}
}
private:
void balance() {
int maxdeg=int( std::floor( 2.08*log(double(_data.size()))))+1;
std::vector<int> A(maxdeg,-1);
/*
*Recall that now minimum does not point to the minimum prio element.
*We set minimum to this during balance().
*/
int anchor=_data[_minimum].left_neighbor;
int next=_minimum;
bool end=false;
do {
int active=next;
if ( anchor==active ) end=true;
int d=_data[active].degree;
next=_data[active].right_neighbor;
while (A[d]!=-1) {
if( _comp(_data[active].prio, _data[A[d]].prio) ) {
fuse(active,A[d]);
} else {
fuse(A[d],active);
active=A[d];
}
A[d]=-1;
++d;
}
A[d]=active;
} while ( !end );
while ( _data[_minimum].parent >=0 )
_minimum=_data[_minimum].parent;
int s=_minimum;
int m=_minimum;
do {
if ( _comp(_data[s].prio, _data[_minimum].prio) ) _minimum=s;
s=_data[s].right_neighbor;
} while ( s != m );
}
void makeRoot(int c) {
int s=c;
do {
_data[s].parent=-1;
s=_data[s].right_neighbor;
} while ( s != c );
}
void cut(int a, int b) {
/*
*Replacing a from the children of b.
*/
--_data[b].degree;
if ( _data[b].degree !=0 ) {
int child=_data[b].child;
if ( child==a )
_data[b].child=_data[child].right_neighbor;
unlace(a);
}
/*Lacing a to the roots.*/
int right=_data[_minimum].right_neighbor;
_data[_minimum].right_neighbor=a;
_data[a].left_neighbor=_minimum;
_data[a].right_neighbor=right;
_data[right].left_neighbor=a;
_data[a].parent=-1;
_data[a].marked=false;
}
void cascade(int a) {
if ( _data[a].parent!=-1 ) {
int p=_data[a].parent;
if ( _data[a].marked==false ) _data[a].marked=true;
else {
cut(a,p);
cascade(p);
}
}
}
void fuse(int a, int b) {
unlace(b);
/*Lacing b under a.*/
_data[b].parent=a;
if (_data[a].degree==0) {
_data[b].left_neighbor=b;
_data[b].right_neighbor=b;
_data[a].child=b;
} else {
int child=_data[a].child;
int last_child=_data[child].left_neighbor;
_data[child].left_neighbor=b;
_data[b].right_neighbor=child;
_data[last_child].right_neighbor=b;
_data[b].left_neighbor=last_child;
}
++_data[a].degree;
_data[b].marked=false;
}
/*
*It is invoked only if a has siblings.
*/
void unlace(int a) {
int leftn=_data[a].left_neighbor;
int rightn=_data[a].right_neighbor;
_data[leftn].right_neighbor=rightn;
_data[rightn].left_neighbor=leftn;
}
class Store {
friend class FibHeap;
Item name;
int parent;
int left_neighbor;
int right_neighbor;
int child;
int degree;
bool marked;
bool in;
Prio prio;
Store() : parent(-1), child(-1), degree(), marked(false), in(true) {}
};
};
} //namespace lemon
#endif //LEMON_FIB_HEAP_H

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,263 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2013
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
#ifndef LEMON_GLPK_H
#define LEMON_GLPK_H
///\file
///\brief Header of the LEMON-GLPK lp solver interface.
///\ingroup lp_group
#include <lemon/lp_base.h>
namespace lemon {
namespace _solver_bits {
class VoidPtr {
private:
void *_ptr;
public:
VoidPtr() : _ptr(0) {}
template <typename T>
VoidPtr(T* ptr) : _ptr(reinterpret_cast<void*>(ptr)) {}
template <typename T>
VoidPtr& operator=(T* ptr) {
_ptr = reinterpret_cast<void*>(ptr);
return *this;
}
template <typename T>
operator T*() const { return reinterpret_cast<T*>(_ptr); }
};
}
/// \brief Base interface for the GLPK LP and MIP solver
///
/// This class implements the common interface of the GLPK LP and MIP solver.
/// \ingroup lp_group
class GlpkBase : virtual public LpBase {
protected:
_solver_bits::VoidPtr lp;
GlpkBase();
GlpkBase(const GlpkBase&);
virtual ~GlpkBase();
protected:
virtual int _addCol();
virtual int _addRow();
virtual int _addRow(Value l, ExprIterator b, ExprIterator e, Value u);
virtual void _eraseCol(int i);
virtual void _eraseRow(int i);
virtual void _eraseColId(int i);
virtual void _eraseRowId(int i);
virtual void _getColName(int col, std::string& name) const;
virtual void _setColName(int col, const std::string& name);
virtual int _colByName(const std::string& name) const;
virtual void _getRowName(int row, std::string& name) const;
virtual void _setRowName(int row, const std::string& name);
virtual int _rowByName(const std::string& name) const;
virtual void _setRowCoeffs(int i, ExprIterator b, ExprIterator e);
virtual void _getRowCoeffs(int i, InsertIterator b) const;
virtual void _setColCoeffs(int i, ExprIterator b, ExprIterator e);
virtual void _getColCoeffs(int i, InsertIterator b) const;
virtual void _setCoeff(int row, int col, Value value);
virtual Value _getCoeff(int row, int col) const;
virtual void _setColLowerBound(int i, Value value);
virtual Value _getColLowerBound(int i) const;
virtual void _setColUpperBound(int i, Value value);
virtual Value _getColUpperBound(int i) const;
virtual void _setRowLowerBound(int i, Value value);
virtual Value _getRowLowerBound(int i) const;
virtual void _setRowUpperBound(int i, Value value);
virtual Value _getRowUpperBound(int i) const;
virtual void _setObjCoeffs(ExprIterator b, ExprIterator e);
virtual void _getObjCoeffs(InsertIterator b) const;
virtual void _setObjCoeff(int i, Value obj_coef);
virtual Value _getObjCoeff(int i) const;
virtual void _setSense(Sense);
virtual Sense _getSense() const;
virtual void _clear();
virtual void _messageLevel(MessageLevel level);
virtual void _write(std::string file, std::string format) const;
private:
static void freeEnv();
struct FreeEnvHelper {
~FreeEnvHelper() {
freeEnv();
}
};
static FreeEnvHelper freeEnvHelper;
protected:
int _message_level;
public:
///Pointer to the underlying GLPK data structure.
_solver_bits::VoidPtr lpx() {return lp;}
///Const pointer to the underlying GLPK data structure.
_solver_bits::VoidPtr lpx() const {return lp;}
///Returns the constraint identifier understood by GLPK.
int lpxRow(Row r) const { return rows(id(r)); }
///Returns the variable identifier understood by GLPK.
int lpxCol(Col c) const { return cols(id(c)); }
#ifdef DOXYGEN
/// Write the problem or the solution to a file in the given format
/// This function writes the problem or the solution
/// to a file in the given format.
/// Trying to write in an unsupported format will trigger
/// \ref LpBase::UnsupportedFormatError.
/// \param file The file path
/// \param format The output file format.
/// Supportted formats are "MPS" and "LP".
void write(std::string file, std::string format = "MPS") const {}
#endif
};
/// \brief Interface for the GLPK LP solver
///
/// This class implements an interface for the GLPK LP solver.
///\ingroup lp_group
class GlpkLp : public LpSolver, public GlpkBase {
public:
///\e
GlpkLp();
///\e
GlpkLp(const GlpkLp&);
///\e
virtual GlpkLp* cloneSolver() const;
///\e
virtual GlpkLp* newSolver() const;
private:
mutable std::vector<double> _primal_ray;
mutable std::vector<double> _dual_ray;
void _clear_temporals();
protected:
virtual const char* _solverName() const;
virtual SolveExitStatus _solve();
virtual Value _getPrimal(int i) const;
virtual Value _getDual(int i) const;
virtual Value _getPrimalValue() const;
virtual VarStatus _getColStatus(int i) const;
virtual VarStatus _getRowStatus(int i) const;
virtual Value _getPrimalRay(int i) const;
virtual Value _getDualRay(int i) const;
virtual ProblemType _getPrimalType() const;
virtual ProblemType _getDualType() const;
public:
///Solve with primal simplex
SolveExitStatus solvePrimal();
///Solve with dual simplex
SolveExitStatus solveDual();
private:
bool _presolve;
public:
///Turns on or off the presolver
///Turns on (\c b is \c true) or off (\c b is \c false) the presolver
///
///The presolver is off by default.
void presolver(bool presolve);
};
/// \brief Interface for the GLPK MIP solver
///
/// This class implements an interface for the GLPK MIP solver.
///\ingroup lp_group
class GlpkMip : public MipSolver, public GlpkBase {
public:
///\e
GlpkMip();
///\e
GlpkMip(const GlpkMip&);
virtual GlpkMip* cloneSolver() const;
virtual GlpkMip* newSolver() const;
protected:
virtual const char* _solverName() const;
virtual ColTypes _getColType(int col) const;
virtual void _setColType(int col, ColTypes col_type);
virtual SolveExitStatus _solve();
virtual ProblemType _getType() const;
virtual Value _getSol(int i) const;
virtual Value _getSolValue() const;
};
} //END OF NAMESPACE LEMON
#endif //LEMON_GLPK_H

View File

@@ -0,0 +1,568 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2013
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
#ifndef LEMON_GOMORY_HU_TREE_H
#define LEMON_GOMORY_HU_TREE_H
#include <limits>
#include <lemon/core.h>
#include <lemon/preflow.h>
#include <lemon/concept_check.h>
#include <lemon/concepts/maps.h>
/// \ingroup min_cut
/// \file
/// \brief Gomory-Hu cut tree in graphs.
namespace lemon {
/// \ingroup min_cut
///
/// \brief Gomory-Hu cut tree algorithm
///
/// The Gomory-Hu tree is a tree on the node set of a given graph, but it
/// may contain edges which are not in the original graph. It has the
/// property that the minimum capacity edge of the path between two nodes
/// in this tree has the same weight as the minimum cut in the graph
/// between these nodes. Moreover the components obtained by removing
/// this edge from the tree determine the corresponding minimum cut.
/// Therefore once this tree is computed, the minimum cut between any pair
/// of nodes can easily be obtained.
///
/// The algorithm calculates \e n-1 distinct minimum cuts (currently with
/// the \ref Preflow algorithm), thus it has \f$O(n^3\sqrt{m})\f$ overall
/// time complexity. It calculates a rooted Gomory-Hu tree.
/// The structure of the tree and the edge weights can be
/// obtained using \c predNode(), \c predValue() and \c rootDist().
/// The functions \c minCutMap() and \c minCutValue() calculate
/// the minimum cut and the minimum cut value between any two nodes
/// in the graph. You can also list (iterate on) the nodes and the
/// edges of the cuts using \c MinCutNodeIt and \c MinCutEdgeIt.
///
/// \tparam GR The type of the undirected graph the algorithm runs on.
/// \tparam CAP The type of the edge map containing the capacities.
/// The default map type is \ref concepts::Graph::EdgeMap "GR::EdgeMap<int>".
#ifdef DOXYGEN
template <typename GR,
typename CAP>
#else
template <typename GR,
typename CAP = typename GR::template EdgeMap<int> >
#endif
class GomoryHu {
public:
/// The graph type of the algorithm
typedef GR Graph;
/// The capacity map type of the algorithm
typedef CAP Capacity;
/// The value type of capacities
typedef typename Capacity::Value Value;
private:
TEMPLATE_GRAPH_TYPEDEFS(Graph);
const Graph& _graph;
const Capacity& _capacity;
Node _root;
typename Graph::template NodeMap<Node>* _pred;
typename Graph::template NodeMap<Value>* _weight;
typename Graph::template NodeMap<int>* _order;
void createStructures() {
if (!_pred) {
_pred = new typename Graph::template NodeMap<Node>(_graph);
}
if (!_weight) {
_weight = new typename Graph::template NodeMap<Value>(_graph);
}
if (!_order) {
_order = new typename Graph::template NodeMap<int>(_graph);
}
}
void destroyStructures() {
if (_pred) {
delete _pred;
}
if (_weight) {
delete _weight;
}
if (_order) {
delete _order;
}
}
public:
/// \brief Constructor
///
/// Constructor.
/// \param graph The undirected graph the algorithm runs on.
/// \param capacity The edge capacity map.
GomoryHu(const Graph& graph, const Capacity& capacity)
: _graph(graph), _capacity(capacity),
_pred(0), _weight(0), _order(0)
{
checkConcept<concepts::ReadMap<Edge, Value>, Capacity>();
}
/// \brief Destructor
///
/// Destructor.
~GomoryHu() {
destroyStructures();
}
private:
// Initialize the internal data structures
void init() {
createStructures();
_root = NodeIt(_graph);
for (NodeIt n(_graph); n != INVALID; ++n) {
(*_pred)[n] = _root;
(*_order)[n] = -1;
}
(*_pred)[_root] = INVALID;
(*_weight)[_root] = std::numeric_limits<Value>::max();
}
// Start the algorithm
void start() {
Preflow<Graph, Capacity> fa(_graph, _capacity, _root, INVALID);
for (NodeIt n(_graph); n != INVALID; ++n) {
if (n == _root) continue;
Node pn = (*_pred)[n];
fa.source(n);
fa.target(pn);
fa.runMinCut();
(*_weight)[n] = fa.flowValue();
for (NodeIt nn(_graph); nn != INVALID; ++nn) {
if (nn != n && fa.minCut(nn) && (*_pred)[nn] == pn) {
(*_pred)[nn] = n;
}
}
if ((*_pred)[pn] != INVALID && fa.minCut((*_pred)[pn])) {
(*_pred)[n] = (*_pred)[pn];
(*_pred)[pn] = n;
(*_weight)[n] = (*_weight)[pn];
(*_weight)[pn] = fa.flowValue();
}
}
(*_order)[_root] = 0;
int index = 1;
for (NodeIt n(_graph); n != INVALID; ++n) {
std::vector<Node> st;
Node nn = n;
while ((*_order)[nn] == -1) {
st.push_back(nn);
nn = (*_pred)[nn];
}
while (!st.empty()) {
(*_order)[st.back()] = index++;
st.pop_back();
}
}
}
public:
///\name Execution Control
///@{
/// \brief Run the Gomory-Hu algorithm.
///
/// This function runs the Gomory-Hu algorithm.
void run() {
init();
start();
}
/// @}
///\name Query Functions
///The results of the algorithm can be obtained using these
///functions.\n
///\ref run() should be called before using them.\n
///See also \ref MinCutNodeIt and \ref MinCutEdgeIt.
///@{
/// \brief Return the predecessor node in the Gomory-Hu tree.
///
/// This function returns the predecessor node of the given node
/// in the Gomory-Hu tree.
/// If \c node is the root of the tree, then it returns \c INVALID.
///
/// \pre \ref run() must be called before using this function.
Node predNode(const Node& node) const {
return (*_pred)[node];
}
/// \brief Return the weight of the predecessor edge in the
/// Gomory-Hu tree.
///
/// This function returns the weight of the predecessor edge of the
/// given node in the Gomory-Hu tree.
/// If \c node is the root of the tree, the result is undefined.
///
/// \pre \ref run() must be called before using this function.
Value predValue(const Node& node) const {
return (*_weight)[node];
}
/// \brief Return the distance from the root node in the Gomory-Hu tree.
///
/// This function returns the distance of the given node from the root
/// node in the Gomory-Hu tree.
///
/// \pre \ref run() must be called before using this function.
int rootDist(const Node& node) const {
return (*_order)[node];
}
/// \brief Return the minimum cut value between two nodes
///
/// This function returns the minimum cut value between the nodes
/// \c s and \c t.
/// It finds the nearest common ancestor of the given nodes in the
/// Gomory-Hu tree and calculates the minimum weight edge on the
/// paths to the ancestor.
///
/// \pre \ref run() must be called before using this function.
Value minCutValue(const Node& s, const Node& t) const {
Node sn = s, tn = t;
Value value = std::numeric_limits<Value>::max();
while (sn != tn) {
if ((*_order)[sn] < (*_order)[tn]) {
if ((*_weight)[tn] <= value) value = (*_weight)[tn];
tn = (*_pred)[tn];
} else {
if ((*_weight)[sn] <= value) value = (*_weight)[sn];
sn = (*_pred)[sn];
}
}
return value;
}
/// \brief Return the minimum cut between two nodes
///
/// This function returns the minimum cut between the nodes \c s and \c t
/// in the \c cutMap parameter by setting the nodes in the component of
/// \c s to \c true and the other nodes to \c false.
///
/// For higher level interfaces see MinCutNodeIt and MinCutEdgeIt.
///
/// \param s The base node.
/// \param t The node you want to separate from node \c s.
/// \param cutMap The cut will be returned in this map.
/// It must be a \c bool (or convertible) \ref concepts::ReadWriteMap
/// "ReadWriteMap" on the graph nodes.
///
/// \return The value of the minimum cut between \c s and \c t.
///
/// \pre \ref run() must be called before using this function.
template <typename CutMap>
Value minCutMap(const Node& s,
const Node& t,
CutMap& cutMap
) const {
Node sn = s, tn = t;
bool s_root=false;
Node rn = INVALID;
Value value = std::numeric_limits<Value>::max();
while (sn != tn) {
if ((*_order)[sn] < (*_order)[tn]) {
if ((*_weight)[tn] <= value) {
rn = tn;
s_root = false;
value = (*_weight)[tn];
}
tn = (*_pred)[tn];
} else {
if ((*_weight)[sn] <= value) {
rn = sn;
s_root = true;
value = (*_weight)[sn];
}
sn = (*_pred)[sn];
}
}
typename Graph::template NodeMap<bool> reached(_graph, false);
reached[_root] = true;
cutMap.set(_root, !s_root);
reached[rn] = true;
cutMap.set(rn, s_root);
std::vector<Node> st;
for (NodeIt n(_graph); n != INVALID; ++n) {
st.clear();
Node nn = n;
while (!reached[nn]) {
st.push_back(nn);
nn = (*_pred)[nn];
}
while (!st.empty()) {
cutMap.set(st.back(), cutMap[nn]);
st.pop_back();
}
}
return value;
}
///@}
friend class MinCutNodeIt;
/// Iterate on the nodes of a minimum cut
/// This iterator class lists the nodes of a minimum cut found by
/// GomoryHu. Before using it, you must allocate a GomoryHu class
/// and call its \ref GomoryHu::run() "run()" method.
///
/// This example counts the nodes in the minimum cut separating \c s from
/// \c t.
/// \code
/// GomoryHu<Graph> gom(g, capacities);
/// gom.run();
/// int cnt=0;
/// for(GomoryHu<Graph>::MinCutNodeIt n(gom,s,t); n!=INVALID; ++n) ++cnt;
/// \endcode
class MinCutNodeIt
{
bool _side;
typename Graph::NodeIt _node_it;
typename Graph::template NodeMap<bool> _cut;
public:
/// Constructor
/// Constructor.
///
MinCutNodeIt(GomoryHu const &gomory,
///< The GomoryHu class. You must call its
/// run() method
/// before initializing this iterator.
const Node& s, ///< The base node.
const Node& t,
///< The node you want to separate from node \c s.
bool side=true
///< If it is \c true (default) then the iterator lists
/// the nodes of the component containing \c s,
/// otherwise it lists the other component.
/// \note As the minimum cut is not always unique,
/// \code
/// MinCutNodeIt(gomory, s, t, true);
/// \endcode
/// and
/// \code
/// MinCutNodeIt(gomory, t, s, false);
/// \endcode
/// does not necessarily give the same set of nodes.
/// However, it is ensured that
/// \code
/// MinCutNodeIt(gomory, s, t, true);
/// \endcode
/// and
/// \code
/// MinCutNodeIt(gomory, s, t, false);
/// \endcode
/// together list each node exactly once.
)
: _side(side), _cut(gomory._graph)
{
gomory.minCutMap(s,t,_cut);
for(_node_it=typename Graph::NodeIt(gomory._graph);
_node_it!=INVALID && _cut[_node_it]!=_side;
++_node_it) {}
}
/// Conversion to \c Node
/// Conversion to \c Node.
///
operator typename Graph::Node() const
{
return _node_it;
}
bool operator==(Invalid) { return _node_it==INVALID; }
bool operator!=(Invalid) { return _node_it!=INVALID; }
/// Next node
/// Next node.
///
MinCutNodeIt &operator++()
{
for(++_node_it;_node_it!=INVALID&&_cut[_node_it]!=_side;++_node_it) {}
return *this;
}
/// Postfix incrementation
/// Postfix incrementation.
///
/// \warning This incrementation
/// returns a \c Node, not a \c MinCutNodeIt, as one may
/// expect.
typename Graph::Node operator++(int)
{
typename Graph::Node n=*this;
++(*this);
return n;
}
};
friend class MinCutEdgeIt;
/// Iterate on the edges of a minimum cut
/// This iterator class lists the edges of a minimum cut found by
/// GomoryHu. Before using it, you must allocate a GomoryHu class
/// and call its \ref GomoryHu::run() "run()" method.
///
/// This example computes the value of the minimum cut separating \c s from
/// \c t.
/// \code
/// GomoryHu<Graph> gom(g, capacities);
/// gom.run();
/// int value=0;
/// for(GomoryHu<Graph>::MinCutEdgeIt e(gom,s,t); e!=INVALID; ++e)
/// value+=capacities[e];
/// \endcode
/// The result will be the same as the value returned by
/// \ref GomoryHu::minCutValue() "gom.minCutValue(s,t)".
class MinCutEdgeIt
{
bool _side;
const Graph &_graph;
typename Graph::NodeIt _node_it;
typename Graph::OutArcIt _arc_it;
typename Graph::template NodeMap<bool> _cut;
void step()
{
++_arc_it;
while(_node_it!=INVALID && _arc_it==INVALID)
{
for(++_node_it;_node_it!=INVALID&&!_cut[_node_it];++_node_it) {}
if(_node_it!=INVALID)
_arc_it=typename Graph::OutArcIt(_graph,_node_it);
}
}
public:
/// Constructor
/// Constructor.
///
MinCutEdgeIt(GomoryHu const &gomory,
///< The GomoryHu class. You must call its
/// run() method
/// before initializing this iterator.
const Node& s, ///< The base node.
const Node& t,
///< The node you want to separate from node \c s.
bool side=true
///< If it is \c true (default) then the listed arcs
/// will be oriented from the
/// nodes of the component containing \c s,
/// otherwise they will be oriented in the opposite
/// direction.
)
: _graph(gomory._graph), _cut(_graph)
{
gomory.minCutMap(s,t,_cut);
if(!side)
for(typename Graph::NodeIt n(_graph);n!=INVALID;++n)
_cut[n]=!_cut[n];
for(_node_it=typename Graph::NodeIt(_graph);
_node_it!=INVALID && !_cut[_node_it];
++_node_it) {}
_arc_it = _node_it!=INVALID ?
typename Graph::OutArcIt(_graph,_node_it) : INVALID;
while(_node_it!=INVALID && _arc_it == INVALID)
{
for(++_node_it; _node_it!=INVALID&&!_cut[_node_it]; ++_node_it) {}
if(_node_it!=INVALID)
_arc_it= typename Graph::OutArcIt(_graph,_node_it);
}
while(_arc_it!=INVALID && _cut[_graph.target(_arc_it)]) step();
}
/// Conversion to \c Arc
/// Conversion to \c Arc.
///
operator typename Graph::Arc() const
{
return _arc_it;
}
/// Conversion to \c Edge
/// Conversion to \c Edge.
///
operator typename Graph::Edge() const
{
return _arc_it;
}
bool operator==(Invalid) { return _node_it==INVALID; }
bool operator!=(Invalid) { return _node_it!=INVALID; }
/// Next edge
/// Next edge.
///
MinCutEdgeIt &operator++()
{
step();
while(_arc_it!=INVALID && _cut[_graph.target(_arc_it)]) step();
return *this;
}
/// Postfix incrementation
/// Postfix incrementation.
///
/// \warning This incrementation
/// returns an \c Arc, not a \c MinCutEdgeIt, as one may expect.
typename Graph::Arc operator++(int)
{
typename Graph::Arc e=*this;
++(*this);
return e;
}
};
};
}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,251 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2013
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
#ifndef LEMON_GREEDY_TSP_H
#define LEMON_GREEDY_TSP_H
/// \ingroup tsp
/// \file
/// \brief Greedy algorithm for symmetric TSP
#include <vector>
#include <algorithm>
#include <lemon/full_graph.h>
#include <lemon/unionfind.h>
namespace lemon {
/// \ingroup tsp
///
/// \brief Greedy algorithm for symmetric TSP.
///
/// GreedyTsp implements the greedy heuristic for solving
/// symmetric \ref tsp "TSP".
///
/// This algorithm is quite similar to the \ref NearestNeighborTsp
/// "nearest neighbor" heuristic, but it maintains a set of disjoint paths.
/// At each step, the shortest possible edge is added to these paths
/// as long as it does not create a cycle of less than n edges and it does
/// not increase the degree of any node above two.
///
/// This method runs in O(n<sup>2</sup>) time.
/// It quickly finds a relatively short tour for most TSP instances,
/// but it could also yield a really bad (or even the worst) solution
/// in special cases.
///
/// \tparam CM Type of the cost map.
template <typename CM>
class GreedyTsp
{
public:
/// Type of the cost map
typedef CM CostMap;
/// Type of the edge costs
typedef typename CM::Value Cost;
private:
GRAPH_TYPEDEFS(FullGraph);
const FullGraph &_gr;
const CostMap &_cost;
Cost _sum;
std::vector<Node> _path;
private:
// Functor class to compare edges by their costs
class EdgeComp {
private:
const CostMap &_cost;
public:
EdgeComp(const CostMap &cost) : _cost(cost) {}
bool operator()(const Edge &a, const Edge &b) const {
return _cost[a] < _cost[b];
}
};
public:
/// \brief Constructor
///
/// Constructor.
/// \param gr The \ref FullGraph "full graph" the algorithm runs on.
/// \param cost The cost map.
GreedyTsp(const FullGraph &gr, const CostMap &cost)
: _gr(gr), _cost(cost) {}
/// \name Execution Control
/// @{
/// \brief Runs the algorithm.
///
/// This function runs the algorithm.
///
/// \return The total cost of the found tour.
Cost run() {
_path.clear();
if (_gr.nodeNum() == 0) return _sum = 0;
else if (_gr.nodeNum() == 1) {
_path.push_back(_gr(0));
return _sum = 0;
}
std::vector<int> plist;
plist.resize(_gr.nodeNum()*2, -1);
std::vector<Edge> sorted_edges;
sorted_edges.reserve(_gr.edgeNum());
for (EdgeIt e(_gr); e != INVALID; ++e)
sorted_edges.push_back(e);
std::sort(sorted_edges.begin(), sorted_edges.end(), EdgeComp(_cost));
FullGraph::NodeMap<int> item_int_map(_gr);
UnionFind<FullGraph::NodeMap<int> > union_find(item_int_map);
for (NodeIt n(_gr); n != INVALID; ++n)
union_find.insert(n);
FullGraph::NodeMap<int> degree(_gr, 0);
int nodesNum = 0, i = 0;
while (nodesNum != _gr.nodeNum()-1) {
Edge e = sorted_edges[i++];
Node u = _gr.u(e),
v = _gr.v(e);
if (degree[u] <= 1 && degree[v] <= 1) {
if (union_find.join(u, v)) {
const int uid = _gr.id(u),
vid = _gr.id(v);
plist[uid*2 + degree[u]] = vid;
plist[vid*2 + degree[v]] = uid;
++degree[u];
++degree[v];
++nodesNum;
}
}
}
for (int i=0, n=-1; i<_gr.nodeNum()*2; ++i) {
if (plist[i] == -1) {
if (n==-1) {
n = i;
} else {
plist[n] = i/2;
plist[i] = n/2;
break;
}
}
}
for (int i=0, next=0, last=-1; i!=_gr.nodeNum(); ++i) {
_path.push_back(_gr.nodeFromId(next));
if (plist[2*next] != last) {
last = next;
next = plist[2*next];
} else {
last = next;
next = plist[2*next+1];
}
}
_sum = _cost[_gr.edge(_path.back(), _path.front())];
for (int i = 0; i < int(_path.size())-1; ++i) {
_sum += _cost[_gr.edge(_path[i], _path[i+1])];
}
return _sum;
}
/// @}
/// \name Query Functions
/// @{
/// \brief The total cost of the found tour.
///
/// This function returns the total cost of the found tour.
///
/// \pre run() must be called before using this function.
Cost tourCost() const {
return _sum;
}
/// \brief Returns a const reference to the node sequence of the
/// found tour.
///
/// This function returns a const reference to a vector
/// that stores the node sequence of the found tour.
///
/// \pre run() must be called before using this function.
const std::vector<Node>& tourNodes() const {
return _path;
}
/// \brief Gives back the node sequence of the found tour.
///
/// This function copies the node sequence of the found tour into
/// an STL container through the given output iterator. The
/// <tt>value_type</tt> of the container must be <tt>FullGraph::Node</tt>.
/// For example,
/// \code
/// std::vector<FullGraph::Node> nodes(countNodes(graph));
/// tsp.tourNodes(nodes.begin());
/// \endcode
/// or
/// \code
/// std::list<FullGraph::Node> nodes;
/// tsp.tourNodes(std::back_inserter(nodes));
/// \endcode
///
/// \pre run() must be called before using this function.
template <typename Iterator>
void tourNodes(Iterator out) const {
std::copy(_path.begin(), _path.end(), out);
}
/// \brief Gives back the found tour as a path.
///
/// This function copies the found tour as a list of arcs/edges into
/// the given \ref lemon::concepts::Path "path structure".
///
/// \pre run() must be called before using this function.
template <typename Path>
void tour(Path &path) const {
path.clear();
for (int i = 0; i < int(_path.size()) - 1; ++i) {
path.addBack(_gr.arc(_path[i], _path[i+1]));
}
if (int(_path.size()) >= 2) {
path.addBack(_gr.arc(_path.back(), _path.front()));
}
}
/// @}
};
}; // namespace lemon
#endif

View File

@@ -0,0 +1,699 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2009
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
#ifndef GRID_GRAPH_H
#define GRID_GRAPH_H
#include <lemon/core.h>
#include <lemon/bits/graph_extender.h>
#include <lemon/dim2.h>
#include <lemon/assert.h>
///\ingroup graphs
///\file
///\brief GridGraph class.
namespace lemon {
class GridGraphBase {
public:
typedef GridGraphBase Graph;
class Node;
class Edge;
class Arc;
public:
GridGraphBase() {}
protected:
void construct(int width, int height) {
_width = width; _height = height;
_node_num = width * height;
_edge_num = 2 * _node_num - width - height;
_edge_limit = _node_num - _width;
}
public:
Node operator()(int i, int j) const {
LEMON_DEBUG(0 <= i && i < _width &&
0 <= j && j < _height, "Index out of range");
return Node(i + j * _width);
}
int col(Node n) const {
return n._id % _width;
}
int row(Node n) const {
return n._id / _width;
}
dim2::Point<int> pos(Node n) const {
return dim2::Point<int>(col(n), row(n));
}
int width() const {
return _width;
}
int height() const {
return _height;
}
typedef True NodeNumTag;
typedef True EdgeNumTag;
typedef True ArcNumTag;
int nodeNum() const { return _node_num; }
int edgeNum() const { return _edge_num; }
int arcNum() const { return 2 * _edge_num; }
Node u(Edge edge) const {
if (edge._id < _edge_limit) {
return edge._id;
} else {
return (edge._id - _edge_limit) % (_width - 1) +
(edge._id - _edge_limit) / (_width - 1) * _width;
}
}
Node v(Edge edge) const {
if (edge._id < _edge_limit) {
return edge._id + _width;
} else {
return (edge._id - _edge_limit) % (_width - 1) +
(edge._id - _edge_limit) / (_width - 1) * _width + 1;
}
}
Node source(Arc arc) const {
return (arc._id & 1) == 1 ? u(arc) : v(arc);
}
Node target(Arc arc) const {
return (arc._id & 1) == 1 ? v(arc) : u(arc);
}
static int id(Node node) { return node._id; }
static int id(Edge edge) { return edge._id; }
static int id(Arc arc) { return arc._id; }
int maxNodeId() const { return _node_num - 1; }
int maxEdgeId() const { return _edge_num - 1; }
int maxArcId() const { return 2 * _edge_num - 1; }
static Node nodeFromId(int id) { return Node(id);}
static Edge edgeFromId(int id) { return Edge(id);}
static Arc arcFromId(int id) { return Arc(id);}
typedef True FindEdgeTag;
typedef True FindArcTag;
Edge findEdge(Node u, Node v, Edge prev = INVALID) const {
if (prev != INVALID) return INVALID;
if (v._id > u._id) {
if (v._id - u._id == _width)
return Edge(u._id);
if (v._id - u._id == 1 && u._id % _width < _width - 1) {
return Edge(u._id / _width * (_width - 1) +
u._id % _width + _edge_limit);
}
} else {
if (u._id - v._id == _width)
return Edge(v._id);
if (u._id - v._id == 1 && v._id % _width < _width - 1) {
return Edge(v._id / _width * (_width - 1) +
v._id % _width + _edge_limit);
}
}
return INVALID;
}
Arc findArc(Node u, Node v, Arc prev = INVALID) const {
if (prev != INVALID) return INVALID;
if (v._id > u._id) {
if (v._id - u._id == _width)
return Arc((u._id << 1) | 1);
if (v._id - u._id == 1 && u._id % _width < _width - 1) {
return Arc(((u._id / _width * (_width - 1) +
u._id % _width + _edge_limit) << 1) | 1);
}
} else {
if (u._id - v._id == _width)
return Arc(v._id << 1);
if (u._id - v._id == 1 && v._id % _width < _width - 1) {
return Arc((v._id / _width * (_width - 1) +
v._id % _width + _edge_limit) << 1);
}
}
return INVALID;
}
class Node {
friend class GridGraphBase;
protected:
int _id;
Node(int id) : _id(id) {}
public:
Node() {}
Node (Invalid) : _id(-1) {}
bool operator==(const Node node) const {return _id == node._id;}
bool operator!=(const Node node) const {return _id != node._id;}
bool operator<(const Node node) const {return _id < node._id;}
};
class Edge {
friend class GridGraphBase;
friend class Arc;
protected:
int _id;
Edge(int id) : _id(id) {}
public:
Edge() {}
Edge (Invalid) : _id(-1) {}
bool operator==(const Edge edge) const {return _id == edge._id;}
bool operator!=(const Edge edge) const {return _id != edge._id;}
bool operator<(const Edge edge) const {return _id < edge._id;}
};
class Arc {
friend class GridGraphBase;
protected:
int _id;
Arc(int id) : _id(id) {}
public:
Arc() {}
Arc (Invalid) : _id(-1) {}
operator Edge() const { return _id != -1 ? Edge(_id >> 1) : INVALID; }
bool operator==(const Arc arc) const {return _id == arc._id;}
bool operator!=(const Arc arc) const {return _id != arc._id;}
bool operator<(const Arc arc) const {return _id < arc._id;}
};
static bool direction(Arc arc) {
return (arc._id & 1) == 1;
}
static Arc direct(Edge edge, bool dir) {
return Arc((edge._id << 1) | (dir ? 1 : 0));
}
void first(Node& node) const {
node._id = _node_num - 1;
}
static void next(Node& node) {
--node._id;
}
void first(Edge& edge) const {
edge._id = _edge_num - 1;
}
static void next(Edge& edge) {
--edge._id;
}
void first(Arc& arc) const {
arc._id = 2 * _edge_num - 1;
}
static void next(Arc& arc) {
--arc._id;
}
void firstOut(Arc& arc, const Node& node) const {
if (node._id % _width < _width - 1) {
arc._id = (_edge_limit + node._id % _width +
(node._id / _width) * (_width - 1)) << 1 | 1;
return;
}
if (node._id < _node_num - _width) {
arc._id = node._id << 1 | 1;
return;
}
if (node._id % _width > 0) {
arc._id = (_edge_limit + node._id % _width +
(node._id / _width) * (_width - 1) - 1) << 1;
return;
}
if (node._id >= _width) {
arc._id = (node._id - _width) << 1;
return;
}
arc._id = -1;
}
void nextOut(Arc& arc) const {
int nid = arc._id >> 1;
if ((arc._id & 1) == 1) {
if (nid >= _edge_limit) {
nid = (nid - _edge_limit) % (_width - 1) +
(nid - _edge_limit) / (_width - 1) * _width;
if (nid < _node_num - _width) {
arc._id = nid << 1 | 1;
return;
}
}
if (nid % _width > 0) {
arc._id = (_edge_limit + nid % _width +
(nid / _width) * (_width - 1) - 1) << 1;
return;
}
if (nid >= _width) {
arc._id = (nid - _width) << 1;
return;
}
} else {
if (nid >= _edge_limit) {
nid = (nid - _edge_limit) % (_width - 1) +
(nid - _edge_limit) / (_width - 1) * _width + 1;
if (nid >= _width) {
arc._id = (nid - _width) << 1;
return;
}
}
}
arc._id = -1;
}
void firstIn(Arc& arc, const Node& node) const {
if (node._id % _width < _width - 1) {
arc._id = (_edge_limit + node._id % _width +
(node._id / _width) * (_width - 1)) << 1;
return;
}
if (node._id < _node_num - _width) {
arc._id = node._id << 1;
return;
}
if (node._id % _width > 0) {
arc._id = (_edge_limit + node._id % _width +
(node._id / _width) * (_width - 1) - 1) << 1 | 1;
return;
}
if (node._id >= _width) {
arc._id = (node._id - _width) << 1 | 1;
return;
}
arc._id = -1;
}
void nextIn(Arc& arc) const {
int nid = arc._id >> 1;
if ((arc._id & 1) == 0) {
if (nid >= _edge_limit) {
nid = (nid - _edge_limit) % (_width - 1) +
(nid - _edge_limit) / (_width - 1) * _width;
if (nid < _node_num - _width) {
arc._id = nid << 1;
return;
}
}
if (nid % _width > 0) {
arc._id = (_edge_limit + nid % _width +
(nid / _width) * (_width - 1) - 1) << 1 | 1;
return;
}
if (nid >= _width) {
arc._id = (nid - _width) << 1 | 1;
return;
}
} else {
if (nid >= _edge_limit) {
nid = (nid - _edge_limit) % (_width - 1) +
(nid - _edge_limit) / (_width - 1) * _width + 1;
if (nid >= _width) {
arc._id = (nid - _width) << 1 | 1;
return;
}
}
}
arc._id = -1;
}
void firstInc(Edge& edge, bool& dir, const Node& node) const {
if (node._id % _width < _width - 1) {
edge._id = _edge_limit + node._id % _width +
(node._id / _width) * (_width - 1);
dir = true;
return;
}
if (node._id < _node_num - _width) {
edge._id = node._id;
dir = true;
return;
}
if (node._id % _width > 0) {
edge._id = _edge_limit + node._id % _width +
(node._id / _width) * (_width - 1) - 1;
dir = false;
return;
}
if (node._id >= _width) {
edge._id = node._id - _width;
dir = false;
return;
}
edge._id = -1;
dir = true;
}
void nextInc(Edge& edge, bool& dir) const {
int nid = edge._id;
if (dir) {
if (nid >= _edge_limit) {
nid = (nid - _edge_limit) % (_width - 1) +
(nid - _edge_limit) / (_width - 1) * _width;
if (nid < _node_num - _width) {
edge._id = nid;
return;
}
}
if (nid % _width > 0) {
edge._id = _edge_limit + nid % _width +
(nid / _width) * (_width - 1) - 1;
dir = false;
return;
}
if (nid >= _width) {
edge._id = nid - _width;
dir = false;
return;
}
} else {
if (nid >= _edge_limit) {
nid = (nid - _edge_limit) % (_width - 1) +
(nid - _edge_limit) / (_width - 1) * _width + 1;
if (nid >= _width) {
edge._id = nid - _width;
return;
}
}
}
edge._id = -1;
dir = true;
}
Arc right(Node n) const {
if (n._id % _width < _width - 1) {
return Arc(((_edge_limit + n._id % _width +
(n._id / _width) * (_width - 1)) << 1) | 1);
} else {
return INVALID;
}
}
Arc left(Node n) const {
if (n._id % _width > 0) {
return Arc((_edge_limit + n._id % _width +
(n._id / _width) * (_width - 1) - 1) << 1);
} else {
return INVALID;
}
}
Arc up(Node n) const {
if (n._id < _edge_limit) {
return Arc((n._id << 1) | 1);
} else {
return INVALID;
}
}
Arc down(Node n) const {
if (n._id >= _width) {
return Arc((n._id - _width) << 1);
} else {
return INVALID;
}
}
private:
int _width, _height;
int _node_num, _edge_num;
int _edge_limit;
};
typedef GraphExtender<GridGraphBase> ExtendedGridGraphBase;
/// \ingroup graphs
///
/// \brief Grid graph class
///
/// GridGraph implements a special graph type. The nodes of the
/// graph can be indexed by two integer values \c (i,j) where \c i is
/// in the range <tt>[0..width()-1]</tt> and j is in the range
/// <tt>[0..height()-1]</tt>. Two nodes are connected in the graph if
/// the indices differ exactly on one position and the difference is
/// also exactly one. The nodes of the graph can be obtained by position
/// using the \c operator()() function and the indices of the nodes can
/// be obtained using \c pos(), \c col() and \c row() members. The outgoing
/// arcs can be retrieved with the \c right(), \c up(), \c left()
/// and \c down() functions, where the bottom-left corner is the
/// origin.
///
/// This class is completely static and it needs constant memory space.
/// Thus you can neither add nor delete nodes or edges, however
/// the structure can be resized using resize().
///
/// \image html grid_graph.png
/// \image latex grid_graph.eps "Grid graph" width=\textwidth
///
/// A short example about the basic usage:
///\code
/// GridGraph graph(rows, cols);
/// GridGraph::NodeMap<int> val(graph);
/// for (int i = 0; i < graph.width(); ++i) {
/// for (int j = 0; j < graph.height(); ++j) {
/// val[graph(i, j)] = i + j;
/// }
/// }
///\endcode
///
/// This type fully conforms to the \ref concepts::Graph "Graph concept".
/// Most of its member functions and nested classes are documented
/// only in the concept class.
///
/// This class provides constant time counting for nodes, edges and arcs.
class GridGraph : public ExtendedGridGraphBase {
typedef ExtendedGridGraphBase Parent;
public:
/// \brief Map to get the indices of the nodes as \ref dim2::Point
/// "dim2::Point<int>".
///
/// Map to get the indices of the nodes as \ref dim2::Point
/// "dim2::Point<int>".
class IndexMap {
public:
/// \brief The key type of the map
typedef GridGraph::Node Key;
/// \brief The value type of the map
typedef dim2::Point<int> Value;
/// \brief Constructor
IndexMap(const GridGraph& graph) : _graph(graph) {}
/// \brief The subscript operator
Value operator[](Key key) const {
return _graph.pos(key);
}
private:
const GridGraph& _graph;
};
/// \brief Map to get the column of the nodes.
///
/// Map to get the column of the nodes.
class ColMap {
public:
/// \brief The key type of the map
typedef GridGraph::Node Key;
/// \brief The value type of the map
typedef int Value;
/// \brief Constructor
ColMap(const GridGraph& graph) : _graph(graph) {}
/// \brief The subscript operator
Value operator[](Key key) const {
return _graph.col(key);
}
private:
const GridGraph& _graph;
};
/// \brief Map to get the row of the nodes.
///
/// Map to get the row of the nodes.
class RowMap {
public:
/// \brief The key type of the map
typedef GridGraph::Node Key;
/// \brief The value type of the map
typedef int Value;
/// \brief Constructor
RowMap(const GridGraph& graph) : _graph(graph) {}
/// \brief The subscript operator
Value operator[](Key key) const {
return _graph.row(key);
}
private:
const GridGraph& _graph;
};
/// \brief Constructor
///
/// Construct a grid graph with the given size.
GridGraph(int width, int height) { construct(width, height); }
/// \brief Resizes the graph
///
/// This function resizes the graph. It fully destroys and
/// rebuilds the structure, therefore the maps of the graph will be
/// reallocated automatically and the previous values will be lost.
void resize(int width, int height) {
Parent::notifier(Arc()).clear();
Parent::notifier(Edge()).clear();
Parent::notifier(Node()).clear();
construct(width, height);
Parent::notifier(Node()).build();
Parent::notifier(Edge()).build();
Parent::notifier(Arc()).build();
}
/// \brief The node on the given position.
///
/// Gives back the node on the given position.
Node operator()(int i, int j) const {
return Parent::operator()(i, j);
}
/// \brief The column index of the node.
///
/// Gives back the column index of the node.
int col(Node n) const {
return Parent::col(n);
}
/// \brief The row index of the node.
///
/// Gives back the row index of the node.
int row(Node n) const {
return Parent::row(n);
}
/// \brief The position of the node.
///
/// Gives back the position of the node, ie. the <tt>(col,row)</tt> pair.
dim2::Point<int> pos(Node n) const {
return Parent::pos(n);
}
/// \brief The number of the columns.
///
/// Gives back the number of the columns.
int width() const {
return Parent::width();
}
/// \brief The number of the rows.
///
/// Gives back the number of the rows.
int height() const {
return Parent::height();
}
/// \brief The arc goes right from the node.
///
/// Gives back the arc goes right from the node. If there is not
/// outgoing arc then it gives back INVALID.
Arc right(Node n) const {
return Parent::right(n);
}
/// \brief The arc goes left from the node.
///
/// Gives back the arc goes left from the node. If there is not
/// outgoing arc then it gives back INVALID.
Arc left(Node n) const {
return Parent::left(n);
}
/// \brief The arc goes up from the node.
///
/// Gives back the arc goes up from the node. If there is not
/// outgoing arc then it gives back INVALID.
Arc up(Node n) const {
return Parent::up(n);
}
/// \brief The arc goes down from the node.
///
/// Gives back the arc goes down from the node. If there is not
/// outgoing arc then it gives back INVALID.
Arc down(Node n) const {
return Parent::down(n);
}
/// \brief Index map of the grid graph
///
/// Just returns an IndexMap for the grid graph.
IndexMap indexMap() const {
return IndexMap(*this);
}
/// \brief Row map of the grid graph
///
/// Just returns a RowMap for the grid graph.
RowMap rowMap() const {
return RowMap(*this);
}
/// \brief Column map of the grid graph
///
/// Just returns a ColMap for the grid graph.
ColMap colMap() const {
return ColMap(*this);
}
};
}
#endif

Some files were not shown because too many files have changed in this diff Show More