diff --git a/CMakeLists.txt b/CMakeLists.txt index 06195f63b..bbf8e4824 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -137,7 +137,7 @@ else(CLANG) endif() add_definitions(-DBOOST_RESULT_OF_USE_DECLTYPE) - set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -stdlib=${CLANG_STDLIB} -Wall -pedantic -Wno-newline-eof -Wno-mismatched-tags -Wno-unused-local-typedefs -ftemplate-depth=1024") + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -stdlib=${CLANG_STDLIB} -Wall -pedantic -Wno-newline-eof -Wno-mismatched-tags -Wno-unused-local-typedefs -ftemplate-depth=1024 -Wno-parentheses-equality") if(FORCE_COLOR) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fcolor-diagnostics") @@ -194,11 +194,11 @@ if(CUSTOM_BOOST_ROOT) endif(CUSTOM_BOOST_ROOT) if(STORM_PYTHON) - find_package(Boost REQUIRED COMPONENTS python3) + find_package(Boost 1.56 REQUIRED COMPONENTS python3) #HACK for DEBIAN if(NOT Boost_PYTHON3_FOUND) set(PYVERSION 34) - load_library(pycarl Boost 1.55 COMPONENTS python-py${PYVERSION}) + find_package(Boost 1.56 COMPONENTS python-py${PYVERSION}) if(NOT Boost_PYTHON-PY${PYVERSION}_FOUND) message(FATAL_ERROR "Could not find Boost Python") endif() @@ -207,6 +207,7 @@ else() find_package(Boost REQUIRED) endif() + if ((NOT Boost_LIBRARY_DIRS) OR ("${Boost_LIBRARY_DIRS}" STREQUAL "")) set(Boost_LIBRARY_DIRS "${Boost_INCLUDE_DIRS}/stage/lib") endif () @@ -256,9 +257,11 @@ endif(STORM_HAVE_Z3) set(STORM_HAVE_GLPK 1) message (STATUS "StoRM - Linking with glpk") -add_subdirectory("${PROJECT_SOURCE_DIR}/resources/3rdparty/glpk-4.53") -include_directories("${PROJECT_SOURCE_DIR}/resources/3rdparty/glpk-4.53/src") -list(APPEND STORM_LINK_LIBRARIES "glpk") + +set(GLPK_LIBRARIES ${CMAKE_BINARY_DIR}/resources/3rdparty/glpk-4.57/lib/libglpk.a) +set(GLPK_INCLUDE_DIR ${CMAKE_BINARY_DIR}/resources/3rdparty/glpk-4.57/include) +include_directories(${GLPK_INCLUDE_DIR}) +list(APPEND STORM_LINK_LIBRARIES ${GLPK_LIBRARIES}) diff --git a/resources/3rdparty/CMakeLists.txt b/resources/3rdparty/CMakeLists.txt index c360fa366..4cc396d80 100644 --- a/resources/3rdparty/CMakeLists.txt +++ b/resources/3rdparty/CMakeLists.txt @@ -6,4 +6,15 @@ ExternalProject_Add( PREFIX ${CMAKE_CURRENT_BINARY_DIR}/xercesc-3.1.2 BUILD_COMMAND make BUILD_IN_SOURCE 0 -) \ No newline at end of file +) + +ExternalProject_Add( + glpk + DOWNLOAD_COMMAND "" + PREFIX ${CMAKE_CURRENT_BINARY_DIR}/glpk-4.57 + SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/glpk-4.57 + CONFIGURE_COMMAND CC=${CMAKE_C_COMPILER} ${CMAKE_CURRENT_SOURCE_DIR}/glpk-4.57/configure --prefix=${CMAKE_CURRENT_BINARY_DIR}/glpk-4.57 + BUILD_COMMAND make + INSTALL_COMMAND make install + BUILD_IN_SOURCE 0 +) diff --git a/resources/3rdparty/cudd-2.5.0/CMakeLists.txt b/resources/3rdparty/cudd-2.5.0/CMakeLists.txt index 4a39bd5da..5df298c34 100644 --- a/resources/3rdparty/cudd-2.5.0/CMakeLists.txt +++ b/resources/3rdparty/cudd-2.5.0/CMakeLists.txt @@ -26,7 +26,7 @@ elseif(MSVC) # required for GMM to compile, ugly error directive in their code add_definitions(/D_SCL_SECURE_NO_DEPRECATE /D_CRT_SECURE_NO_WARNINGS) else(CLANG) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-newline-eof -Wno-unneeded-internal-declaration -Wno-unused-variable -Wno-unused-const-variable") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-newline-eof -Wno-unneeded-internal-declaration -Wno-unused-variable -Wno-unused-const-variable -Wno-parentheses-equality") endif() # Since we do not target Alphas, this symbol is always set diff --git a/resources/3rdparty/glpk-4.53/CMakeLists.txt b/resources/3rdparty/glpk-4.53/CMakeLists.txt deleted file mode 100644 index 8302fa365..000000000 --- a/resources/3rdparty/glpk-4.53/CMakeLists.txt +++ /dev/null @@ -1,281 +0,0 @@ -cmake_minimum_required (VERSION 2.8.6) - -# Set project name -project (glpk CXX C) - -# Add the resources/cmake folder to Module Search Path for FindMySQL.cmake -set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/resources/") - -# Add base folder for better inclusion paths -include_directories("${PROJECT_SOURCE_DIR}") -include_directories("${PROJECT_SOURCE_DIR}/src") -include_directories("${PROJECT_SOURCE_DIR}/src/amd") -include_directories("${PROJECT_SOURCE_DIR}/src/bflib") -include_directories("${PROJECT_SOURCE_DIR}/src/cglib") -include_directories("${PROJECT_SOURCE_DIR}/src/colamd") -include_directories("${PROJECT_SOURCE_DIR}/src/env") -include_directories("${PROJECT_SOURCE_DIR}/src/minisat") -include_directories("${PROJECT_SOURCE_DIR}/src/misc") -include_directories("${PROJECT_SOURCE_DIR}/src/proxy") -include_directories("${PROJECT_SOURCE_DIR}/src/zlib") - -############################################################# -## -## CMake options of GLPK -## -############################################################# -option(WITH_GLPK_EXAMPLES "Also build examples and standalone executables" OFF) -option(WITH_GMP "Use GNU MO bignum library" OFF) -option(ENABLE_DL "Enable shared library support" OFF) -option(ENABLE_ODBC "Enable MathProg ODBC support" OFF) -option(ENABLE_MYSQL "Enable MathProg MySQL support" OFF) -option(DEBUG "Sets whether the DEBUG mode is used" OFF) -set(ADDITIONAL_INCLUDE_DIRS "" CACHE STRING "Additional directories added to the include directories.") -set(ADDITIONAL_LINK_DIRS "" CACHE STRING "Additional directories added to the link directories.") - -MARK_AS_ADVANCED(WITH_GLPK_EXAMPLES WITH_GMP ENABLE_DL ENABLE_ODBC ENABLE_MYSQL) - -# If the DEBUG option was turned on, we will target a debug version and a release version otherwise -if (DEBUG) - set (CMAKE_BUILD_TYPE "DEBUG") -else() - set (CMAKE_BUILD_TYPE "RELEASE") -endif() -message(STATUS "GLPK - Building ${CMAKE_BUILD_TYPE} version.") -message(STATUS "GLPK - CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}") -message(STATUS "GLPK - CMAKE_BUILD_TYPE (ENV): $ENV{CMAKE_BUILD_TYPE}") - - -############################################################# -## -## Compiler specific settings and definitions -## -############################################################# - -if(CMAKE_COMPILER_IS_GNUCC) - message(STATUS "GLPK - Using Compiler Configuration: GCC") - # Set standard flags for GCC - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-return-type -Wno-parentheses -Wno-unused-variable -Wno-unused-but-set-variable -Wno-unused-value -Wno-unused-function -Wno-address -Wno-unused-label") - add_definitions(-DHAVE_CONFIG_H=1) -elseif(MSVC) - message(STATUS "GLPK - Using Compiler Configuration: MSVC") - add_definitions(/D_SCL_SECURE_NO_DEPRECATE /D_CRT_SECURE_NO_WARNINGS) - add_definitions(/D_VARIADIC_MAX=10) - add_definitions(/DNOMINMAX) - add_definitions(/DHAVE_CONFIG_H=1) -else(CLANG) - message(STATUS "GLPK - Using Compiler Configuration: Clang (LLVM)") - # As CLANG is not set as a variable, we need to set it in case we have not matched another compiler. - set (CLANG ON) - # Set standard flags for clang - set (CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -funroll-loops -O3") - - set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-return-type -Wno-return-type-c-linkage -Wno-unused-label -Wno-unused-value -Wno-unused-function -Wno-unused-variable -Wno-logical-op-parentheses -Wno-macro-redefined -Wno-uninitialized -Wno-sometimes-uninitialized -Wno-self-assign") - - set (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -g") - add_definitions(-DHAVE_CONFIG_H=1) - set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -version-info=37:0:1 -export-symbols-regex='^glp_*'") -endif() - -############################################################# -## -## CMake-generated Config File for GLPK -## -############################################################# -include(CheckIncludeFiles) -include(CheckFunctionExists) -CHECK_INCLUDE_FILES(sys/time.h HAVE_SYS_TIME_H) -CHECK_FUNCTION_EXISTS(gettimeofday HAVE_GETTIMEOFDAY) -CHECK_INCLUDE_FILES(ltdl.h HAVE_LTDL) -CHECK_INCLUDE_FILES(dlfcn.h HAVE_DLFCN) -if(WITH_GMP) - message(STATUS "GLPK - Building with GMP Support") - CHECK_INCLUDE_FILE(gmp.h HAVE_GMP_H) - if (NOT HAVE_GMP_H) - message(SEND_ERROR "Could not find gmp.h!") - endif() - set(GLPK_HAVE_GMP "define") -else() - set(GLPK_HAVE_GMP "undef") -endif() - -if (UNIX AND NOT APPLE) - set(LIBIODBC "libiodbc.so") - set(LIBODBC "libodbc.so") - set(LIBMYSQL "libmysqlclient.so") -elseif(UNIX AND APPLE) - set(LIBIODBC "libiodbc.dylib") - set(LIBODBC "libodbc.dylib") - set(LIBMYSQL "libmysqlclient.dylib") -elseif(MSVC) - set(LIBIODBC "odbc32.lib") - set(LIBODBC "odbc32.lib") - set(LIBMYSQL "mysqlclient.lib") -endif() - -if(ENABLE_ODBC) - message(STATUS "GLPK - Building with ODBC Support") - find_package(ODBC REQUIRED) - if (NOT ENABLE_DL) - message(SEND_ERROR "ENABLE_ODBC required ENABLE_DL") - endif() - include_directories(ODBC_INCLUDE_DIRECTORIES) - set(GLPK_HAVE_ODBC "define") - set(GLPK_ODBC_DLNAME "${ODBC_LIBRARIES}") -else() - set(GLPK_HAVE_ODBC "undef") - set(GLPK_ODBC_DLNAME "") -endif() - -if(ENABLE_MYSQL) - message(STATUS "GLPK - Building with MySQL Support") - find_package(MySQL REQUIRED) - if (NOT ENABLE_DL) - message(SEND_ERROR "ENABLE_MYSQL required ENABLE_DL") - endif() - include_directories(MYSQL_INCLUDE_DIR) - set(GLPK_HAVE_MYSQL "define") - set(GLPK_MYSQL_DLNAME "${MYSQL_LIBRARIES}") -else() - set(GLPK_HAVE_MYSQL "undef") - set(GLPK_MYSQL_DLNAME "") -endif() - -# Convert to CMake Variables to be used in the Config File -if(HAVE_SYS_TIME_H) - set(GLPK_HAVE_SYS_TIME_H "define") -else() - set (GLPK_HAVE_SYS_TIME_H "undef") -endif() -if(HAVE_GETTIMEOFDAY) - set(GLPK_HAVE_GETTIMEOFDAY "define") -else() - set (GLPK_HAVE_GETTIMEOFDAY "undef") -endif() -if(HAVE_LTDL) - set(GLPK_HAVE_LTDL "define") -else() - set (GLPK_HAVE_LTDL "undef") -endif() -if(HAVE_DLFCN) - set(GLPK_HAVE_DLFCN "define") -else() - set (GLPK_HAVE_DLFCN "undef") -endif() - - -# Configure a header file to pass some of the CMake settings to the source code -configure_file ( - "${PROJECT_SOURCE_DIR}/config.h.cmake.in" - "${PROJECT_BINARY_DIR}/include/config.h" -) -# Add the binary dir include directory for config.h -include_directories("${PROJECT_BINARY_DIR}/include") - -############################################################# -## -## Source file aggregation and clustering -## -############################################################# -file(GLOB_RECURSE GLPK_LIB_HEADERS ${PROJECT_SOURCE_DIR}/src/*.h) -file(GLOB_RECURSE GLPK_LIB_SOURCES ${PROJECT_SOURCE_DIR}/src/*.c) - -file(GLOB_RECURSE GLPK_LIB_DEF ${PROJECT_SOURCE_DIR}/w64/*.def) - -set(GLPK_EXAMPLE_GLPSOL_SOURCES ${PROJECT_SOURCE_DIR}/examples/glpsol.c) -set(GLPK_EXAMPLE_IPTSAMP_SOURCES ${PROJECT_SOURCE_DIR}/examples/iptsamp.c) -set(GLPK_EXAMPLE_MPLSAMP1_SOURCES ${PROJECT_SOURCE_DIR}/examples/mplsamp1.c) -set(GLPK_EXAMPLE_MPLSAMP2_SOURCES ${PROJECT_SOURCE_DIR}/examples/mplsamp2.c) -set(GLPK_EXAMPLE_SAMPLE_SOURCES ${PROJECT_SOURCE_DIR}/examples/sample.c) -set(GLPK_EXAMPLE_SPXSAMP1_SOURCES ${PROJECT_SOURCE_DIR}/examples/spxsamp1.c) -set(GLPK_EXAMPLE_SPXSAMP2_SOURCES ${PROJECT_SOURCE_DIR}/examples/spxsamp2.c) -set(GLPK_EXAMPLE_NETGEN_SOURCES ${PROJECT_SOURCE_DIR}/examples/netgen.c) - -# Additional include files like the storm-config.h -file(GLOB_RECURSE GLPK_BUILD_HEADERS ${PROJECT_BINARY_DIR}/include/*.h) - -# Add custom additional include or link directories -if (ADDITIONAL_INCLUDE_DIRS) - message(STATUS "GLPK - Using additional include directories ${ADDITIONAL_INCLUDE_DIRS}") - include_directories(${ADDITIONAL_INCLUDE_DIRS}) -endif(ADDITIONAL_INCLUDE_DIRS) -if (ADDITIONAL_LINK_DIRS) - message(STATUS "GLPK - Using additional link directories ${ADDITIONAL_LINK_DIRS}") - link_directories(${ADDITIONAL_LINK_DIRS}) -endif(ADDITIONAL_LINK_DIRS) - -############################################################################### -## # -## Executable Creation # -## # -## All link_directories() calls MUST be made before this point # -## # -############################################################################### -if(WITH_GLPK_EXAMPLES) - add_executable(glpsol ${GLPK_EXAMPLE_GLPSOL_SOURCES}) - add_executable(iptsamp ${GLPK_EXAMPLE_IPTSAMP_SOURCES}) - add_executable(mplsamp1 ${GLPK_EXAMPLE_MPLSAMP1_SOURCES}) - add_executable(mplsamp2 ${GLPK_EXAMPLE_MPLSAMP2_SOURCES}) - add_executable(spxsamp1 ${GLPK_EXAMPLE_SPXSAMP1_SOURCES}) - add_executable(spxsamp2 ${GLPK_EXAMPLE_SPXSAMP2_SOURCES}) - add_executable(netgen ${GLPK_EXAMPLE_NETGEN_SOURCES}) - add_executable(sample ${GLPK_EXAMPLE_SAMPLE_SOURCES}) -endif() - -if(ENABLE_DL) - set(GLPK_BUILD_TYPE SHARED) -else() - set(GLPK_BUILD_TYPE STATIC) -endif() -if (NOT MSVC) - set(GLPK_LIB_DEF "") -endif() - -add_library(glpk ${GLPK_BUILD_TYPE} ${GLPK_LIB_SOURCES} ${GLPK_LIB_HEADERS} ${GLPK_LIB_DEF}) -IF(UNIX) - target_link_libraries(glpk m) -ENDIF(UNIX) -if(HAVE_LTDL) - target_link_libraries(glpk ltdl) -endif(HAVE_LTDL) -if(HAVE_DLFCN) - target_link_libraries(glpk dl) -endif(HAVE_DLFCN) - -if(WITH_GLPK_EXAMPLES) - # Dependency for the Executable - add_dependencies(glpsol glpk) - add_dependencies(iptsamp glpk) - add_dependencies(mplsamp1 glpk) - add_dependencies(mplsamp2 glpk) - add_dependencies(spxsamp1 glpk) - add_dependencies(spxsamp2 glpk) - add_dependencies(netgen glpk) - add_dependencies(sample glpk) - target_link_libraries(glpsol glpk) - target_link_libraries(iptsamp glpk) - target_link_libraries(mplsamp1 glpk) - target_link_libraries(mplsamp2 glpk) - target_link_libraries(spxsamp1 glpk) - target_link_libraries(spxsamp2 glpk) - target_link_libraries(netgen glpk) - target_link_libraries(sample glpk) -endif() - -############################################################# -## -## ODBC -## -############################################################# -if(ODBC_FOUND) - target_link_libraries(glpk ${ODBC_LIBRARIES}) -endif() - -############################################################# -## -## MySQL -## -############################################################# -if(MYSQL_FOUND) - target_link_libraries(glpk ${MYSQL_LIBRARIES}) -endif() diff --git a/resources/3rdparty/glpk-4.53/config.h.cmake.in b/resources/3rdparty/glpk-4.53/config.h.cmake.in deleted file mode 100644 index ebde8d1b6..000000000 --- a/resources/3rdparty/glpk-4.53/config.h.cmake.in +++ /dev/null @@ -1,27 +0,0 @@ -/* config.h.in (GLPK configuration template file) */ - -#@GLPK_HAVE_SYS_TIME_H@ HAVE_SYS_TIME_H -/* defined if the header can be used */ - -#@GLPK_HAVE_GETTIMEOFDAY@ HAVE_GETTIMEOFDAY -/* defined if the gettimeofday function can be used */ - -#@GLPK_HAVE_GMP@ HAVE_GMP -/* defined if the GNU MP bignum library is available */ -/* requires and -lgmp */ - -#@GLPK_HAVE_LTDL@ HAVE_LTDL -/* defined if the GNU Libtool shared library support is enabled */ -/* requires and -lltdl */ - -#@GLPK_HAVE_DLFCN@ HAVE_DLFCN -/* defined if the POSIX shared library support is enabled */ -/* requires */ - -#@GLPK_HAVE_ODBC@ ODBC_DLNAME @GLPK_ODBC_DLNAME@ -/* ODBC shared library name if this feature is enabled */ - -#@GLPK_HAVE_MYSQL@ MYSQL_DLNAME @GLPK_MYSQL_DLNAME@ -/* MySQL shared library name if this feature is enabled */ - -/* eof */ diff --git a/resources/3rdparty/glpk-4.53/doc/notes/scaling.pdf b/resources/3rdparty/glpk-4.53/doc/notes/scaling.pdf deleted file mode 100644 index 732f614db..000000000 Binary files a/resources/3rdparty/glpk-4.53/doc/notes/scaling.pdf and /dev/null differ diff --git a/resources/3rdparty/glpk-4.53/doc/notes/updating.pdf b/resources/3rdparty/glpk-4.53/doc/notes/updating.pdf deleted file mode 100644 index 65b0966aa..000000000 Binary files a/resources/3rdparty/glpk-4.53/doc/notes/updating.pdf and /dev/null differ diff --git a/resources/3rdparty/glpk-4.53/resources/FindMySQL.cmake b/resources/3rdparty/glpk-4.53/resources/FindMySQL.cmake deleted file mode 100644 index 939582362..000000000 --- a/resources/3rdparty/glpk-4.53/resources/FindMySQL.cmake +++ /dev/null @@ -1,47 +0,0 @@ -# - Find mysqlclient -# Find the native MySQL includes and library -# -# MYSQL_INCLUDE_DIR - where to find mysql.h, etc. -# MYSQL_LIBRARIES - List of libraries when using MySQL. -# MYSQL_FOUND - True if MySQL found. - -IF (MYSQL_INCLUDE_DIR) - # Already in cache, be silent - SET(MYSQL_FIND_QUIETLY TRUE) -ENDIF (MYSQL_INCLUDE_DIR) - -FIND_PATH(MYSQL_INCLUDE_DIR mysql.h - /usr/local/include/mysql - /usr/include/mysql -) - -SET(MYSQL_NAMES mysqlclient mysqlclient_r) -FIND_LIBRARY(MYSQL_LIBRARY - NAMES ${MYSQL_NAMES} - PATHS /usr/lib /usr/local/lib - PATH_SUFFIXES mysql -) - -IF (MYSQL_INCLUDE_DIR AND MYSQL_LIBRARY) - SET(MYSQL_FOUND TRUE) - SET( MYSQL_LIBRARIES ${MYSQL_LIBRARY} ) -ELSE (MYSQL_INCLUDE_DIR AND MYSQL_LIBRARY) - SET(MYSQL_FOUND FALSE) - SET( MYSQL_LIBRARIES ) -ENDIF (MYSQL_INCLUDE_DIR AND MYSQL_LIBRARY) - -IF (MYSQL_FOUND) - IF (NOT MYSQL_FIND_QUIETLY) - MESSAGE(STATUS "Found MySQL: ${MYSQL_LIBRARY}") - ENDIF (NOT MYSQL_FIND_QUIETLY) -ELSE (MYSQL_FOUND) - IF (MYSQL_FIND_REQUIRED) - MESSAGE(STATUS "Looked for MySQL libraries named ${MYSQL_NAMES}.") - MESSAGE(FATAL_ERROR "Could NOT find MySQL library") - ENDIF (MYSQL_FIND_REQUIRED) -ENDIF (MYSQL_FOUND) - -MARK_AS_ADVANCED( - MYSQL_LIBRARY - MYSQL_INCLUDE_DIR -) \ No newline at end of file diff --git a/resources/3rdparty/glpk-4.53/resources/FindODBC.cmake b/resources/3rdparty/glpk-4.53/resources/FindODBC.cmake deleted file mode 100644 index dacb1f6c6..000000000 --- a/resources/3rdparty/glpk-4.53/resources/FindODBC.cmake +++ /dev/null @@ -1,60 +0,0 @@ -# -# Find the ODBC driver manager includes and library. -# -# ODBC is an open standard for connecting to different databases in a -# semi-vendor-independent fashion. First you install the ODBC driver -# manager. Then you need a driver for each separate database you want -# to connect to (unless a generic one works). VTK includes neither -# the driver manager nor the vendor-specific drivers: you have to find -# those yourself. -# -# This module defines -# ODBC_INCLUDE_DIRECTORIES, where to find sql.h -# ODBC_LIBRARIES, the libraries to link against to use ODBC -# ODBC_FOUND. If false, you cannot build anything that requires MySQL. - -find_path(ODBC_INCLUDE_DIRECTORIES - NAMES sql.h - HINTS - /usr/include - /usr/include/odbc - /usr/local/include - /usr/local/include/odbc - /usr/local/odbc/include - "C:/Program Files/ODBC/include" - "C:/Program Files/Microsoft SDKs/Windows/v7.0/include" - "C:/Program Files (x86)/Microsoft SDKs/Windows/v7.1A/include" - "C:/Program Files/Microsoft SDKs/Windows/v6.0a/include" - "C:/ODBC/include" - DOC "Specify the directory containing sql.h." -) - -find_library(ODBC_LIBRARIES - NAMES iodbc odbc odbcinst odbc32 - HINTS - /usr/lib - /usr/lib/odbc - /usr/local/lib - /usr/local/lib/odbc - /usr/local/odbc/lib - "C:/Program Files/ODBC/lib" - "C:/ODBC/lib/debug" - "C:/Program Files (x86)/Microsoft SDKs/Windows/v7.1A/Lib" - "C:/Program Files (x86)/Microsoft SDKs/Windows/v7.0A/Lib" - DOC "Specify the ODBC driver manager library here." -) - -# MinGW find usually fails -if(MINGW) - set(ODBC_INCLUDE_DIRECTORIES ".") - set(ODBC_LIBRARIES odbc32) -endif() - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(ODBC - DEFAULT_MSG - ODBC_INCLUDE_DIRECTORIES - ODBC_LIBRARIES - ) - -mark_as_advanced(ODBC_FOUND ODBC_LIBRARIES ODBC_INCLUDE_DIRECTORIES) \ No newline at end of file diff --git a/resources/3rdparty/glpk-4.53/src/bfd.c b/resources/3rdparty/glpk-4.53/src/bfd.c deleted file mode 100644 index 2ce5dcd37..000000000 --- a/resources/3rdparty/glpk-4.53/src/bfd.c +++ /dev/null @@ -1,576 +0,0 @@ -/* bfd.c (LP basis factorization driver) */ - -/*********************************************************************** -* This code is part of GLPK (GNU Linear Programming Kit). -* -* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, -* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied -* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights -* reserved. E-mail: . -* -* GLPK is free software: you can redistribute it and/or modify it -* under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* GLPK is distributed in the hope that it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -* License for more details. -* -* You should have received a copy of the GNU General Public License -* along with GLPK. If not, see . -***********************************************************************/ - -#include "env.h" -#if 0 /* 27/IV-2013 */ -#include "glpfhv.h" -#else -#include "fhvint.h" -#endif -#include "glplpf.h" -#include "prob.h" - -/* CAUTION: DO NOT CHANGE THE LIMIT BELOW */ - -#define M_MAX 100000000 /* = 100*10^6 */ -/* maximal order of the basis matrix */ - -struct BFD -{ /* LP basis factorization */ - int valid; - /* factorization is valid only if this flag is set */ - int type; - /* factorization type: - GLP_BF_FT - LUF + Forrest-Tomlin - GLP_BF_BG - LUF + Schur compl. + Bartels-Golub - GLP_BF_GR - LUF + Schur compl. + Givens rotation */ -#if 0 /* 27/IV-2013 */ - FHV *fhv; - /* LP basis factorization (GLP_BF_FT) */ -#else - FHVINT *fi; - /* interface to FHV-factorization (GLP_BF_FT) */ -#endif - LPF *lpf; - /* LP basis factorization (GLP_BF_BG, GLP_BF_GR) */ - int lu_size; /* luf.sv_size */ - double piv_tol; /* luf.piv_tol */ - int piv_lim; /* luf.piv_lim */ - int suhl; /* luf.suhl */ - double eps_tol; /* luf.eps_tol */ - double max_gro; /* luf.max_gro */ - int nfs_max; /* fhv.hh_max */ - double upd_tol; /* fhv.upd_tol */ - int nrs_max; /* lpf.n_max */ - int rs_size; /* lpf.v_size */ - /* internal control parameters */ - int upd_lim; - /* the factorization update limit */ - int upd_cnt; - /* the factorization update count */ -}; - -/*********************************************************************** -* NAME -* -* bfd_create_it - create LP basis factorization -* -* SYNOPSIS -* -* #include "glpbfd.h" -* BFD *bfd_create_it(void); -* -* DESCRIPTION -* -* The routine bfd_create_it creates a program object, which represents -* a factorization of LP basis. -* -* RETURNS -* -* The routine bfd_create_it returns a pointer to the object created. */ - -BFD *bfd_create_it(void) -{ BFD *bfd; - bfd = xmalloc(sizeof(BFD)); - bfd->valid = 0; - bfd->type = GLP_BF_FT; -#if 0 /* 27/IV-2013 */ - bfd->fhv = NULL; -#else - bfd->fi = NULL; -#endif - bfd->lpf = NULL; - bfd->lu_size = 0; - bfd->piv_tol = 0.10; - bfd->piv_lim = 4; - bfd->suhl = 1; - bfd->eps_tol = 1e-15; - bfd->max_gro = 1e+10; - bfd->nfs_max = 100; - bfd->upd_tol = 1e-6; - bfd->nrs_max = 100; - bfd->rs_size = 1000; - bfd->upd_lim = -1; - bfd->upd_cnt = 0; - return bfd; -} - -/**********************************************************************/ - -void bfd_set_parm(BFD *bfd, const void *_parm) -{ /* change LP basis factorization control parameters */ - const glp_bfcp *parm = _parm; - xassert(bfd != NULL); - bfd->type = parm->type; - bfd->lu_size = parm->lu_size; - bfd->piv_tol = parm->piv_tol; - bfd->piv_lim = parm->piv_lim; - bfd->suhl = parm->suhl; - bfd->eps_tol = parm->eps_tol; - bfd->max_gro = parm->max_gro; - bfd->nfs_max = parm->nfs_max; - bfd->upd_tol = parm->upd_tol; - bfd->nrs_max = parm->nrs_max; - bfd->rs_size = parm->rs_size; - return; -} - -/*********************************************************************** -* NAME -* -* bfd_factorize - compute LP basis factorization -* -* SYNOPSIS -* -* #include "glpbfd.h" -* int bfd_factorize(BFD *bfd, int m, int bh[], int (*col)(void *info, -* int j, int ind[], double val[]), void *info); -* -* DESCRIPTION -* -* The routine bfd_factorize computes the factorization of the basis -* matrix B specified by the routine col. -* -* The parameter bfd specified the basis factorization data structure -* created with the routine bfd_create_it. -* -* The parameter m specifies the order of B, m > 0. -* -* The array bh specifies the basis header: bh[j], 1 <= j <= m, is the -* number of j-th column of B in some original matrix. The array bh is -* optional and can be specified as NULL. -* -* The formal routine col specifies the matrix B to be factorized. To -* obtain j-th column of A the routine bfd_factorize calls the routine -* col with the parameter j (1 <= j <= n). In response the routine col -* should store row indices and numerical values of non-zero elements -* of j-th column of B to locations ind[1,...,len] and val[1,...,len], -* respectively, where len is the number of non-zeros in j-th column -* returned on exit. Neither zero nor duplicate elements are allowed. -* -* The parameter info is a transit pointer passed to the routine col. -* -* RETURNS -* -* 0 The factorization has been successfully computed. -* -* BFD_ESING -* The specified matrix is singular within the working precision. -* -* BFD_ECOND -* The specified matrix is ill-conditioned. -* -* For more details see comments to the routine luf_factorize. */ - -int bfd_factorize(BFD *bfd, int m, const int bh[], int (*col) - (void *info, int j, int ind[], double val[]), void *info) -#if 0 /* 06/VI-2013 */ -{ LUF *luf; -#else -{ -#endif - int nov, ret; - xassert(bfd != NULL); - xassert(1 <= m && m <= M_MAX); - /* invalidate the factorization */ - bfd->valid = 0; - /* create the factorization, if necessary */ - nov = 0; - switch (bfd->type) - { case GLP_BF_FT: - if (bfd->lpf != NULL) - lpf_delete_it(bfd->lpf), bfd->lpf = NULL; -#if 0 /* 27/IV-2013 */ - if (bfd->fhv == NULL) - bfd->fhv = fhv_create_it(), nov = 1; -#else - if (bfd->fi == NULL) - bfd->fi = fhvint_create(), nov = 1; -#endif - break; - case GLP_BF_BG: - case GLP_BF_GR: -#if 0 /* 27/IV-2013 */ - if (bfd->fhv != NULL) - fhv_delete_it(bfd->fhv), bfd->fhv = NULL; -#else - if (bfd->fi != NULL) - fhvint_delete(bfd->fi), bfd->fi = NULL; -#endif - if (bfd->lpf == NULL) - bfd->lpf = lpf_create_it(), nov = 1; - break; - default: - xassert(bfd != bfd); - } -#if 0 /* 06/VI-2013 */ - /* set control parameters specific to LUF */ -#if 0 /* 27/IV-2013 */ - if (bfd->fhv != NULL) - luf = bfd->fhv->luf; -#else - if (bfd->fi != NULL) - goto skip; -#endif - else if (bfd->lpf != NULL) - luf = bfd->lpf->luf; - else - xassert(bfd != bfd); - if (nov) luf->new_sva = bfd->lu_size; - luf->piv_tol = bfd->piv_tol; - luf->piv_lim = bfd->piv_lim; - luf->suhl = bfd->suhl; - luf->eps_tol = bfd->eps_tol; - luf->max_gro = bfd->max_gro; -#endif -#if 0 /* 27/IV-2013 */ - /* set control parameters specific to FHV */ - if (bfd->fhv != NULL) - { if (nov) bfd->fhv->hh_max = bfd->nfs_max; - bfd->fhv->upd_tol = bfd->upd_tol; - } -#endif - /* set control parameters specific to LPF */ - if (bfd->lpf != NULL) - { if (nov) bfd->lpf->n_max = bfd->nrs_max; - if (nov) bfd->lpf->v_size = bfd->rs_size; - } -#if 0 /* 27/IV-2013 */ - /* try to factorize the basis matrix */ - if (bfd->fhv != NULL) - { switch (fhv_factorize(bfd->fhv, m, col, info)) - { case 0: - break; - case FHV_ESING: - ret = BFD_ESING; - goto done; - case FHV_ECOND: - ret = BFD_ECOND; - goto done; - default: - xassert(bfd != bfd); - } - } -#else -skip: /* try to factorize the basis matrix */ - if (bfd->fi != NULL) - { /* FIXME */ - if (fhvint_factorize(bfd->fi, m, col, info) != 0) - { ret = BFD_ESING; - goto done; - } - /* printf("*** FACTORIZED; m = %d ***\n", m); */ - } -#endif - else if (bfd->lpf != NULL) - { switch (lpf_factorize(bfd->lpf, m, bh, col, info)) - { case 0: - /* set the Schur complement update type */ - switch (bfd->type) - { case GLP_BF_BG: - /* Bartels-Golub update */ -#if 0 /* 11/VIII-2013 */ - bfd->lpf->scf->t_opt = SCF_TBG; -#else - bfd->lpf->t_opt = SCF_TBG; -#endif - break; - case GLP_BF_GR: - /* Givens rotations update */ -#if 0 /* 11/VIII-2013 */ - bfd->lpf->scf->t_opt = SCF_TGR; -#else - bfd->lpf->t_opt = SCF_TGR; -#endif - break; - default: - xassert(bfd != bfd); - } - break; - case LPF_ESING: - ret = BFD_ESING; - goto done; - case LPF_ECOND: - ret = BFD_ECOND; - goto done; - default: - xassert(bfd != bfd); - } - } - else - xassert(bfd != bfd); - /* the basis matrix has been successfully factorized */ - bfd->valid = 1; - bfd->upd_cnt = 0; - ret = 0; -done: /* return to the calling program */ - return ret; -} - -/*********************************************************************** -* NAME -* -* bfd_ftran - perform forward transformation (solve system B*x = b) -* -* SYNOPSIS -* -* #include "glpbfd.h" -* void bfd_ftran(BFD *bfd, double x[]); -* -* DESCRIPTION -* -* The routine bfd_ftran performs forward transformation, i.e. solves -* the system B*x = b, where B is the basis matrix, x is the vector of -* unknowns to be computed, b is the vector of right-hand sides. -* -* On entry elements of the vector b should be stored in dense format -* in locations x[1], ..., x[m], where m is the number of rows. On exit -* the routine stores elements of the vector x in the same locations. */ - -void bfd_ftran(BFD *bfd, double x[]) -{ xassert(bfd != NULL); - xassert(bfd->valid); -#if 0 /* 27/IV-2013 */ - if (bfd->fhv != NULL) - fhv_ftran(bfd->fhv, x); -#else - if (bfd->fi != NULL) - fhvint_ftran(bfd->fi, x); -#endif - else if (bfd->lpf != NULL) - lpf_ftran(bfd->lpf, x); - else - xassert(bfd != bfd); - return; -} - -/*********************************************************************** -* NAME -* -* bfd_btran - perform backward transformation (solve system B'*x = b) -* -* SYNOPSIS -* -* #include "glpbfd.h" -* void bfd_btran(BFD *bfd, double x[]); -* -* DESCRIPTION -* -* The routine bfd_btran performs backward transformation, i.e. solves -* the system B'*x = b, where B' is a matrix transposed to the basis -* matrix B, x is the vector of unknowns to be computed, b is the vector -* of right-hand sides. -* -* On entry elements of the vector b should be stored in dense format -* in locations x[1], ..., x[m], where m is the number of rows. On exit -* the routine stores elements of the vector x in the same locations. */ - -void bfd_btran(BFD *bfd, double x[]) -{ xassert(bfd != NULL); - xassert(bfd->valid); -#if 0 /* 27/IV-2013 */ - if (bfd->fhv != NULL) - fhv_btran(bfd->fhv, x); -#else - if (bfd->fi != NULL) - fhvint_btran(bfd->fi, x); -#endif - else if (bfd->lpf != NULL) - lpf_btran(bfd->lpf, x); - else - xassert(bfd != bfd); - return; -} - -/*********************************************************************** -* NAME -* -* bfd_update_it - update LP basis factorization -* -* SYNOPSIS -* -* #include "glpbfd.h" -* int bfd_update_it(BFD *bfd, int j, int bh, int len, const int ind[], -* const double val[]); -* -* DESCRIPTION -* -* The routine bfd_update_it updates the factorization of the basis -* matrix B after replacing its j-th column by a new vector. -* -* The parameter j specifies the number of column of B, which has been -* replaced, 1 <= j <= m, where m is the order of B. -* -* The parameter bh specifies the basis header entry for the new column -* of B, which is the number of the new column in some original matrix. -* This parameter is optional and can be specified as 0. -* -* Row indices and numerical values of non-zero elements of the new -* column of B should be placed in locations ind[1], ..., ind[len] and -* val[1], ..., val[len], resp., where len is the number of non-zeros -* in the column. Neither zero nor duplicate elements are allowed. -* -* RETURNS -* -* 0 The factorization has been successfully updated. -* -* BFD_ESING -* New basis matrix is singular within the working precision. -* -* BFD_ECHECK -* The factorization is inaccurate. -* -* BFD_ELIMIT -* Factorization update limit has been reached. -* -* BFD_EROOM -* Overflow of the sparse vector area. -* -* In case of non-zero return code the factorization becomes invalid. -* It should not be used until it has been recomputed with the routine -* bfd_factorize. */ - -int bfd_update_it(BFD *bfd, int j, int bh, int len, const int ind[], - const double val[]) -{ int ret; - xassert(bfd != NULL); - xassert(bfd->valid); - /* try to update the factorization */ -#if 0 /* 27/IV-2013 */ - if (bfd->fhv != NULL) - { switch (fhv_update_it(bfd->fhv, j, len, ind, val)) - { case 0: - break; - case FHV_ESING: - bfd->valid = 0; - ret = BFD_ESING; - goto done; - case FHV_ECHECK: - bfd->valid = 0; - ret = BFD_ECHECK; - goto done; - case FHV_ELIMIT: - bfd->valid = 0; - ret = BFD_ELIMIT; - goto done; - case FHV_EROOM: - bfd->valid = 0; - ret = BFD_EROOM; - goto done; - default: - xassert(bfd != bfd); - } - } -#else - if (bfd->fi != NULL) - { /* see fhv_ft_update for return codes */ - switch (fhvint_update(bfd->fi, j, len, ind, val)) - { case 0: - break; - case 1: - bfd->valid = 0; - ret = BFD_ESING; - goto done; - case 2: - case 3: - case 5: - bfd->valid = 0; - ret = BFD_ECHECK; - goto done; - case 4: - bfd->valid = 0; - ret = BFD_ELIMIT; - goto done; - default: - xassert(bfd != bfd); - } - } -#endif - else if (bfd->lpf != NULL) - { switch (lpf_update_it(bfd->lpf, j, bh, len, ind, val)) - { case 0: - break; - case LPF_ESING: - bfd->valid = 0; - ret = BFD_ESING; - goto done; - case LPF_ELIMIT: - bfd->valid = 0; - ret = BFD_ELIMIT; - goto done; - default: - xassert(bfd != bfd); - } - } - else - xassert(bfd != bfd); - /* the factorization has been successfully updated */ - /* increase the update count */ - bfd->upd_cnt++; - ret = 0; -done: /* return to the calling program */ - return ret; -} - -/**********************************************************************/ - -int bfd_get_count(BFD *bfd) -{ /* determine factorization update count */ - xassert(bfd != NULL); - xassert(bfd->valid); - return bfd->upd_cnt; -} - -/*********************************************************************** -* NAME -* -* bfd_delete_it - delete LP basis factorization -* -* SYNOPSIS -* -* #include "glpbfd.h" -* void bfd_delete_it(BFD *bfd); -* -* DESCRIPTION -* -* The routine bfd_delete_it deletes LP basis factorization specified -* by the parameter fhv and frees all memory allocated to this program -* object. */ - -void bfd_delete_it(BFD *bfd) -{ xassert(bfd != NULL); -#if 0 /* 27/IV-2013 */ - if (bfd->fhv != NULL) - fhv_delete_it(bfd->fhv); -#else - if (bfd->fi != NULL) - fhvint_delete(bfd->fi); -#endif - if (bfd->lpf != NULL) - lpf_delete_it(bfd->lpf); - xfree(bfd); - return; -} - -/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glplpf.c b/resources/3rdparty/glpk-4.53/src/glplpf.c deleted file mode 100644 index 8f858531d..000000000 --- a/resources/3rdparty/glpk-4.53/src/glplpf.c +++ /dev/null @@ -1,1097 +0,0 @@ -/* glplpf.c (LP basis factorization, Schur complement version) */ - -/*********************************************************************** -* This code is part of GLPK (GNU Linear Programming Kit). -* -* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, -* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied -* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights -* reserved. E-mail: . -* -* GLPK is free software: you can redistribute it and/or modify it -* under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* GLPK is distributed in the hope that it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -* License for more details. -* -* You should have received a copy of the GNU General Public License -* along with GLPK. If not, see . -***********************************************************************/ - -#include "env.h" -#include "glplpf.h" - -#define xfault xerror - -#define GLPLPF_DEBUG 0 - -/* CAUTION: DO NOT CHANGE THE LIMIT BELOW */ - -#define M_MAX 100000000 /* = 100*10^6 */ -/* maximal order of the basis matrix */ - -/*********************************************************************** -* NAME -* -* lpf_create_it - create LP basis factorization -* -* SYNOPSIS -* -* #include "glplpf.h" -* LPF *lpf_create_it(void); -* -* DESCRIPTION -* -* The routine lpf_create_it creates a program object, which represents -* a factorization of LP basis. -* -* RETURNS -* -* The routine lpf_create_it returns a pointer to the object created. */ - -LPF *lpf_create_it(void) -{ LPF *lpf; -#if GLPLPF_DEBUG - xprintf("lpf_create_it: warning: debug mode enabled\n"); -#endif - lpf = xmalloc(sizeof(LPF)); - lpf->valid = 0; - lpf->m0_max = lpf->m0 = 0; -#if 0 /* 06/VI-2013 */ - lpf->luf = luf_create_it(); -#else - lpf->lufint = lufint_create(); -#endif - lpf->m = 0; - lpf->B = NULL; - lpf->n_max = 50; - lpf->n = 0; - lpf->R_ptr = lpf->R_len = NULL; - lpf->S_ptr = lpf->S_len = NULL; -#if 0 /* 11/VIII-2013 */ - lpf->scf = NULL; -#else - lpf->ifu.n_max = 0; - lpf->ifu.n = 0; - lpf->ifu.f = NULL; - lpf->ifu.u = NULL; - lpf->t_opt = 0; -#endif - lpf->P_row = lpf->P_col = NULL; - lpf->Q_row = lpf->Q_col = NULL; - lpf->v_size = 1000; - lpf->v_ptr = 0; - lpf->v_ind = NULL; - lpf->v_val = NULL; - lpf->work1 = lpf->work2 = NULL; - return lpf; -} - -/*********************************************************************** -* NAME -* -* lpf_factorize - compute LP basis factorization -* -* SYNOPSIS -* -* #include "glplpf.h" -* int lpf_factorize(LPF *lpf, int m, const int bh[], int (*col) -* (void *info, int j, int ind[], double val[]), void *info); -* -* DESCRIPTION -* -* The routine lpf_factorize computes the factorization of the basis -* matrix B specified by the routine col. -* -* The parameter lpf specified the basis factorization data structure -* created with the routine lpf_create_it. -* -* The parameter m specifies the order of B, m > 0. -* -* The array bh specifies the basis header: bh[j], 1 <= j <= m, is the -* number of j-th column of B in some original matrix. The array bh is -* optional and can be specified as NULL. -* -* The formal routine col specifies the matrix B to be factorized. To -* obtain j-th column of A the routine lpf_factorize calls the routine -* col with the parameter j (1 <= j <= n). In response the routine col -* should store row indices and numerical values of non-zero elements -* of j-th column of B to locations ind[1,...,len] and val[1,...,len], -* respectively, where len is the number of non-zeros in j-th column -* returned on exit. Neither zero nor duplicate elements are allowed. -* -* The parameter info is a transit pointer passed to the routine col. -* -* RETURNS -* -* 0 The factorization has been successfully computed. -* -* LPF_ESING -* The specified matrix is singular within the working precision. -* -* LPF_ECOND -* The specified matrix is ill-conditioned. -* -* For more details see comments to the routine luf_factorize. */ - -int lpf_factorize(LPF *lpf, int m, const int bh[], int (*col) - (void *info, int j, int ind[], double val[]), void *info) -{ int k, ret; -#if GLPLPF_DEBUG - int i, j, len, *ind; - double *B, *val; -#endif - xassert(bh == bh); - if (m < 1) - xfault("lpf_factorize: m = %d; invalid parameter\n", m); - if (m > M_MAX) - xfault("lpf_factorize: m = %d; matrix too big\n", m); - lpf->m0 = lpf->m = m; - /* invalidate the factorization */ - lpf->valid = 0; - /* allocate/reallocate arrays, if necessary */ - if (lpf->R_ptr == NULL) - lpf->R_ptr = xcalloc(1+lpf->n_max, sizeof(int)); - if (lpf->R_len == NULL) - lpf->R_len = xcalloc(1+lpf->n_max, sizeof(int)); - if (lpf->S_ptr == NULL) - lpf->S_ptr = xcalloc(1+lpf->n_max, sizeof(int)); - if (lpf->S_len == NULL) - lpf->S_len = xcalloc(1+lpf->n_max, sizeof(int)); -#if 0 /* 11/VIII-2013 */ - if (lpf->scf == NULL) - lpf->scf = scf_create_it(lpf->n_max); -#else - if (lpf->ifu.n_max == 0) - { int n_max = lpf->n_max; - lpf->ifu.n_max = n_max; - lpf->ifu.n = 0; - xassert(n_max > 0); - xassert(lpf->ifu.f == NULL); - lpf->ifu.f = talloc(n_max * n_max, double); - xassert(lpf->ifu.u == NULL); - lpf->ifu.u = talloc(n_max * n_max, double); - lpf->t_opt = 0; - } -#endif - if (lpf->v_ind == NULL) - lpf->v_ind = xcalloc(1+lpf->v_size, sizeof(int)); - if (lpf->v_val == NULL) - lpf->v_val = xcalloc(1+lpf->v_size, sizeof(double)); - if (lpf->m0_max < m) - { if (lpf->P_row != NULL) xfree(lpf->P_row); - if (lpf->P_col != NULL) xfree(lpf->P_col); - if (lpf->Q_row != NULL) xfree(lpf->Q_row); - if (lpf->Q_col != NULL) xfree(lpf->Q_col); - if (lpf->work1 != NULL) xfree(lpf->work1); - if (lpf->work2 != NULL) xfree(lpf->work2); - lpf->m0_max = m + 100; - lpf->P_row = xcalloc(1+lpf->m0_max+lpf->n_max, sizeof(int)); - lpf->P_col = xcalloc(1+lpf->m0_max+lpf->n_max, sizeof(int)); - lpf->Q_row = xcalloc(1+lpf->m0_max+lpf->n_max, sizeof(int)); - lpf->Q_col = xcalloc(1+lpf->m0_max+lpf->n_max, sizeof(int)); - lpf->work1 = xcalloc(1+lpf->m0_max+lpf->n_max, sizeof(double)); - lpf->work2 = xcalloc(1+lpf->m0_max+lpf->n_max, sizeof(double)); - } - /* try to factorize the basis matrix */ -#if 0 /* 06/VI-2013 */ - switch (luf_factorize(lpf->luf, m, col, info)) - { case 0: - break; - case LUF_ESING: - ret = LPF_ESING; - goto done; - case LUF_ECOND: - ret = LPF_ECOND; - goto done; - default: - xassert(lpf != lpf); - } -#else - if (lufint_factorize(lpf->lufint, m, col, info) != 0) - { ret = LPF_ESING; - goto done; - } -#endif - /* the basis matrix has been successfully factorized */ - lpf->valid = 1; -#if GLPLPF_DEBUG - /* store the basis matrix for debugging */ - if (lpf->B != NULL) xfree(lpf->B); - xassert(m <= 32767); - lpf->B = B = xcalloc(1+m*m, sizeof(double)); - ind = xcalloc(1+m, sizeof(int)); - val = xcalloc(1+m, sizeof(double)); - for (k = 1; k <= m * m; k++) - B[k] = 0.0; - for (j = 1; j <= m; j++) - { len = col(info, j, ind, val); - xassert(0 <= len && len <= m); - for (k = 1; k <= len; k++) - { i = ind[k]; - xassert(1 <= i && i <= m); - xassert(B[(i - 1) * m + j] == 0.0); - xassert(val[k] != 0.0); - B[(i - 1) * m + j] = val[k]; - } - } - xfree(ind); - xfree(val); -#endif - /* B = B0, so there are no additional rows/columns */ - lpf->n = 0; - /* reset the Schur complement factorization */ -#if 0 /* 11/VIII-2013 */ - scf_reset_it(lpf->scf); -#else - lpf->ifu.n = 0; -#endif - /* P := Q := I */ - for (k = 1; k <= m; k++) - { lpf->P_row[k] = lpf->P_col[k] = k; - lpf->Q_row[k] = lpf->Q_col[k] = k; - } - /* make all SVA locations free */ - lpf->v_ptr = 1; - ret = 0; -done: /* return to the calling program */ - return ret; -} - -/*********************************************************************** -* The routine r_prod computes the product y := y + alpha * R * x, -* where x is a n-vector, alpha is a scalar, y is a m0-vector. -* -* Since matrix R is available by columns, the product is computed as -* a linear combination: -* -* y := y + alpha * (R[1] * x[1] + ... + R[n] * x[n]), -* -* where R[j] is j-th column of R. */ - -static void r_prod(LPF *lpf, double y[], double a, const double x[]) -{ int n = lpf->n; - int *R_ptr = lpf->R_ptr; - int *R_len = lpf->R_len; - int *v_ind = lpf->v_ind; - double *v_val = lpf->v_val; - int j, beg, end, ptr; - double t; - for (j = 1; j <= n; j++) - { if (x[j] == 0.0) continue; - /* y := y + alpha * R[j] * x[j] */ - t = a * x[j]; - beg = R_ptr[j]; - end = beg + R_len[j]; - for (ptr = beg; ptr < end; ptr++) - y[v_ind[ptr]] += t * v_val[ptr]; - } - return; -} - -/*********************************************************************** -* The routine rt_prod computes the product y := y + alpha * R' * x, -* where R' is a matrix transposed to R, x is a m0-vector, alpha is a -* scalar, y is a n-vector. -* -* Since matrix R is available by columns, the product components are -* computed as inner products: -* -* y[j] := y[j] + alpha * (j-th column of R) * x -* -* for j = 1, 2, ..., n. */ - -static void rt_prod(LPF *lpf, double y[], double a, const double x[]) -{ int n = lpf->n; - int *R_ptr = lpf->R_ptr; - int *R_len = lpf->R_len; - int *v_ind = lpf->v_ind; - double *v_val = lpf->v_val; - int j, beg, end, ptr; - double t; - for (j = 1; j <= n; j++) - { /* t := (j-th column of R) * x */ - t = 0.0; - beg = R_ptr[j]; - end = beg + R_len[j]; - for (ptr = beg; ptr < end; ptr++) - t += v_val[ptr] * x[v_ind[ptr]]; - /* y[j] := y[j] + alpha * t */ - y[j] += a * t; - } - return; -} - -/*********************************************************************** -* The routine s_prod computes the product y := y + alpha * S * x, -* where x is a m0-vector, alpha is a scalar, y is a n-vector. -* -* Since matrix S is available by rows, the product components are -* computed as inner products: -* -* y[i] = y[i] + alpha * (i-th row of S) * x -* -* for i = 1, 2, ..., n. */ - -static void s_prod(LPF *lpf, double y[], double a, const double x[]) -{ int n = lpf->n; - int *S_ptr = lpf->S_ptr; - int *S_len = lpf->S_len; - int *v_ind = lpf->v_ind; - double *v_val = lpf->v_val; - int i, beg, end, ptr; - double t; - for (i = 1; i <= n; i++) - { /* t := (i-th row of S) * x */ - t = 0.0; - beg = S_ptr[i]; - end = beg + S_len[i]; - for (ptr = beg; ptr < end; ptr++) - t += v_val[ptr] * x[v_ind[ptr]]; - /* y[i] := y[i] + alpha * t */ - y[i] += a * t; - } - return; -} - -/*********************************************************************** -* The routine st_prod computes the product y := y + alpha * S' * x, -* where S' is a matrix transposed to S, x is a n-vector, alpha is a -* scalar, y is m0-vector. -* -* Since matrix R is available by rows, the product is computed as a -* linear combination: -* -* y := y + alpha * (S'[1] * x[1] + ... + S'[n] * x[n]), -* -* where S'[i] is i-th row of S. */ - -static void st_prod(LPF *lpf, double y[], double a, const double x[]) -{ int n = lpf->n; - int *S_ptr = lpf->S_ptr; - int *S_len = lpf->S_len; - int *v_ind = lpf->v_ind; - double *v_val = lpf->v_val; - int i, beg, end, ptr; - double t; - for (i = 1; i <= n; i++) - { if (x[i] == 0.0) continue; - /* y := y + alpha * S'[i] * x[i] */ - t = a * x[i]; - beg = S_ptr[i]; - end = beg + S_len[i]; - for (ptr = beg; ptr < end; ptr++) - y[v_ind[ptr]] += t * v_val[ptr]; - } - return; -} - -#if GLPLPF_DEBUG -/*********************************************************************** -* The routine check_error computes the maximal relative error between -* left- and right-hand sides for the system B * x = b (if tr is zero) -* or B' * x = b (if tr is non-zero), where B' is a matrix transposed -* to B. (This routine is intended for debugging only.) */ - -static void check_error(LPF *lpf, int tr, const double x[], - const double b[]) -{ int m = lpf->m; - double *B = lpf->B; - int i, j; - double d, dmax = 0.0, s, t, tmax; - for (i = 1; i <= m; i++) - { s = 0.0; - tmax = 1.0; - for (j = 1; j <= m; j++) - { if (!tr) - t = B[m * (i - 1) + j] * x[j]; - else - t = B[m * (j - 1) + i] * x[j]; - if (tmax < fabs(t)) tmax = fabs(t); - s += t; - } - d = fabs(s - b[i]) / tmax; - if (dmax < d) dmax = d; - } - if (dmax > 1e-8) - xprintf("%s: dmax = %g; relative error too large\n", - !tr ? "lpf_ftran" : "lpf_btran", dmax); - return; -} -#endif - -/*********************************************************************** -* NAME -* -* lpf_ftran - perform forward transformation (solve system B*x = b) -* -* SYNOPSIS -* -* #include "glplpf.h" -* void lpf_ftran(LPF *lpf, double x[]); -* -* DESCRIPTION -* -* The routine lpf_ftran performs forward transformation, i.e. solves -* the system B*x = b, where B is the basis matrix, x is the vector of -* unknowns to be computed, b is the vector of right-hand sides. -* -* On entry elements of the vector b should be stored in dense format -* in locations x[1], ..., x[m], where m is the number of rows. On exit -* the routine stores elements of the vector x in the same locations. -* -* BACKGROUND -* -* Solution of the system B * x = b can be obtained by solving the -* following augmented system: -* -* ( B F^) ( x ) ( b ) -* ( ) ( ) = ( ) -* ( G^ H^) ( y ) ( 0 ) -* -* which, using the main equality, can be written as follows: -* -* ( L0 0 ) ( U0 R ) ( x ) ( b ) -* P ( ) ( ) Q ( ) = ( ) -* ( S I ) ( 0 C ) ( y ) ( 0 ) -* -* therefore, -* -* ( x ) ( U0 R )-1 ( L0 0 )-1 ( b ) -* ( ) = Q' ( ) ( ) P' ( ) -* ( y ) ( 0 C ) ( S I ) ( 0 ) -* -* Thus, computing the solution includes the following steps: -* -* 1. Compute -* -* ( f ) ( b ) -* ( ) = P' ( ) -* ( g ) ( 0 ) -* -* 2. Solve the system -* -* ( f1 ) ( L0 0 )-1 ( f ) ( L0 0 ) ( f1 ) ( f ) -* ( ) = ( ) ( ) => ( ) ( ) = ( ) -* ( g1 ) ( S I ) ( g ) ( S I ) ( g1 ) ( g ) -* -* from which it follows that: -* -* { L0 * f1 = f f1 = inv(L0) * f -* { => -* { S * f1 + g1 = g g1 = g - S * f1 -* -* 3. Solve the system -* -* ( f2 ) ( U0 R )-1 ( f1 ) ( U0 R ) ( f2 ) ( f1 ) -* ( ) = ( ) ( ) => ( ) ( ) = ( ) -* ( g2 ) ( 0 C ) ( g1 ) ( 0 C ) ( g2 ) ( g1 ) -* -* from which it follows that: -* -* { U0 * f2 + R * g2 = f1 f2 = inv(U0) * (f1 - R * g2) -* { => -* { C * g2 = g1 g2 = inv(C) * g1 -* -* 4. Compute -* -* ( x ) ( f2 ) -* ( ) = Q' ( ) -* ( y ) ( g2 ) */ - -void lpf_ftran(LPF *lpf, double x[]) -{ int m0 = lpf->m0; - int m = lpf->m; - int n = lpf->n; - int *P_col = lpf->P_col; - int *Q_col = lpf->Q_col; - double *fg = lpf->work1; - double *f = fg; - double *g = fg + m0; - int i, ii; -#if GLPLPF_DEBUG - double *b; -#endif - if (!lpf->valid) - xfault("lpf_ftran: the factorization is not valid\n"); - xassert(0 <= m && m <= m0 + n); -#if GLPLPF_DEBUG - /* save the right-hand side vector */ - b = xcalloc(1+m, sizeof(double)); - for (i = 1; i <= m; i++) b[i] = x[i]; -#endif - /* (f g) := inv(P) * (b 0) */ - for (i = 1; i <= m0 + n; i++) - fg[i] = ((ii = P_col[i]) <= m ? x[ii] : 0.0); - /* f1 := inv(L0) * f */ -#if 0 /* 06/VI-2013 */ - luf_f_solve(lpf->luf, 0, f); -#else - luf_f_solve(lpf->lufint->luf, f); -#endif - /* g1 := g - S * f1 */ - s_prod(lpf, g, -1.0, f); - /* g2 := inv(C) * g1 */ -#if 0 /* 11/VIII-2013 */ - scf_solve_it(lpf->scf, 0, g); -#else - ifu_a_solve(&lpf->ifu, g, lpf->work2); -#endif - /* f2 := inv(U0) * (f1 - R * g2) */ - r_prod(lpf, f, -1.0, g); -#if 0 /* 06/VI-2013 */ - luf_v_solve(lpf->luf, 0, f); -#else - { double *work = lpf->lufint->sgf->work; - luf_v_solve(lpf->lufint->luf, f, work); - memcpy(&f[1], &work[1], m0 * sizeof(double)); - } -#endif - /* (x y) := inv(Q) * (f2 g2) */ - for (i = 1; i <= m; i++) - x[i] = fg[Q_col[i]]; -#if GLPLPF_DEBUG - /* check relative error in solution */ - check_error(lpf, 0, x, b); - xfree(b); -#endif - return; -} - -/*********************************************************************** -* NAME -* -* lpf_btran - perform backward transformation (solve system B'*x = b) -* -* SYNOPSIS -* -* #include "glplpf.h" -* void lpf_btran(LPF *lpf, double x[]); -* -* DESCRIPTION -* -* The routine lpf_btran performs backward transformation, i.e. solves -* the system B'*x = b, where B' is a matrix transposed to the basis -* matrix B, x is the vector of unknowns to be computed, b is the vector -* of right-hand sides. -* -* On entry elements of the vector b should be stored in dense format -* in locations x[1], ..., x[m], where m is the number of rows. On exit -* the routine stores elements of the vector x in the same locations. -* -* BACKGROUND -* -* Solution of the system B' * x = b, where B' is a matrix transposed -* to B, can be obtained by solving the following augmented system: -* -* ( B F^)T ( x ) ( b ) -* ( ) ( ) = ( ) -* ( G^ H^) ( y ) ( 0 ) -* -* which, using the main equality, can be written as follows: -* -* T ( U0 R )T ( L0 0 )T T ( x ) ( b ) -* Q ( ) ( ) P ( ) = ( ) -* ( 0 C ) ( S I ) ( y ) ( 0 ) -* -* or, equivalently, as follows: -* -* ( U'0 0 ) ( L'0 S') ( x ) ( b ) -* Q' ( ) ( ) P' ( ) = ( ) -* ( R' C') ( 0 I ) ( y ) ( 0 ) -* -* therefore, -* -* ( x ) ( L'0 S')-1 ( U'0 0 )-1 ( b ) -* ( ) = P ( ) ( ) Q ( ) -* ( y ) ( 0 I ) ( R' C') ( 0 ) -* -* Thus, computing the solution includes the following steps: -* -* 1. Compute -* -* ( f ) ( b ) -* ( ) = Q ( ) -* ( g ) ( 0 ) -* -* 2. Solve the system -* -* ( f1 ) ( U'0 0 )-1 ( f ) ( U'0 0 ) ( f1 ) ( f ) -* ( ) = ( ) ( ) => ( ) ( ) = ( ) -* ( g1 ) ( R' C') ( g ) ( R' C') ( g1 ) ( g ) -* -* from which it follows that: -* -* { U'0 * f1 = f f1 = inv(U'0) * f -* { => -* { R' * f1 + C' * g1 = g g1 = inv(C') * (g - R' * f1) -* -* 3. Solve the system -* -* ( f2 ) ( L'0 S')-1 ( f1 ) ( L'0 S') ( f2 ) ( f1 ) -* ( ) = ( ) ( ) => ( ) ( ) = ( ) -* ( g2 ) ( 0 I ) ( g1 ) ( 0 I ) ( g2 ) ( g1 ) -* -* from which it follows that: -* -* { L'0 * f2 + S' * g2 = f1 -* { => f2 = inv(L'0) * ( f1 - S' * g2) -* { g2 = g1 -* -* 4. Compute -* -* ( x ) ( f2 ) -* ( ) = P ( ) -* ( y ) ( g2 ) */ - -void lpf_btran(LPF *lpf, double x[]) -{ int m0 = lpf->m0; - int m = lpf->m; - int n = lpf->n; - int *P_row = lpf->P_row; - int *Q_row = lpf->Q_row; - double *fg = lpf->work1; - double *f = fg; - double *g = fg + m0; - int i, ii; -#if GLPLPF_DEBUG - double *b; -#endif - if (!lpf->valid) - xfault("lpf_btran: the factorization is not valid\n"); - xassert(0 <= m && m <= m0 + n); -#if GLPLPF_DEBUG - /* save the right-hand side vector */ - b = xcalloc(1+m, sizeof(double)); - for (i = 1; i <= m; i++) b[i] = x[i]; -#endif - /* (f g) := Q * (b 0) */ - for (i = 1; i <= m0 + n; i++) - fg[i] = ((ii = Q_row[i]) <= m ? x[ii] : 0.0); - /* f1 := inv(U'0) * f */ -#if 0 /* 06/VI-2013 */ - luf_v_solve(lpf->luf, 1, f); -#else - { double *work = lpf->lufint->sgf->work; - luf_vt_solve(lpf->lufint->luf, f, work); - memcpy(&f[1], &work[1], m0 * sizeof(double)); - } -#endif - /* g1 := inv(C') * (g - R' * f1) */ - rt_prod(lpf, g, -1.0, f); -#if 0 /* 11/VIII-2013 */ - scf_solve_it(lpf->scf, 1, g); -#else - ifu_at_solve(&lpf->ifu, g, lpf->work2); -#endif - /* g2 := g1 */ - g = g; - /* f2 := inv(L'0) * (f1 - S' * g2) */ - st_prod(lpf, f, -1.0, g); -#if 0 /* 06/VI-2013 */ - luf_f_solve(lpf->luf, 1, f); -#else - luf_ft_solve(lpf->lufint->luf, f); -#endif - /* (x y) := P * (f2 g2) */ - for (i = 1; i <= m; i++) - x[i] = fg[P_row[i]]; -#if GLPLPF_DEBUG - /* check relative error in solution */ - check_error(lpf, 1, x, b); - xfree(b); -#endif - return; -} - -/*********************************************************************** -* The routine enlarge_sva enlarges the Sparse Vector Area to new_size -* locations by reallocating the arrays v_ind and v_val. */ - -static void enlarge_sva(LPF *lpf, int new_size) -{ int v_size = lpf->v_size; - int used = lpf->v_ptr - 1; - int *v_ind = lpf->v_ind; - double *v_val = lpf->v_val; - xassert(v_size < new_size); - while (v_size < new_size) v_size += v_size; - lpf->v_size = v_size; - lpf->v_ind = xcalloc(1+v_size, sizeof(int)); - lpf->v_val = xcalloc(1+v_size, sizeof(double)); - xassert(used >= 0); - memcpy(&lpf->v_ind[1], &v_ind[1], used * sizeof(int)); - memcpy(&lpf->v_val[1], &v_val[1], used * sizeof(double)); - xfree(v_ind); - xfree(v_val); - return; -} - -/*********************************************************************** -* NAME -* -* lpf_update_it - update LP basis factorization -* -* SYNOPSIS -* -* #include "glplpf.h" -* int lpf_update_it(LPF *lpf, int j, int bh, int len, const int ind[], -* const double val[]); -* -* DESCRIPTION -* -* The routine lpf_update_it updates the factorization of the basis -* matrix B after replacing its j-th column by a new vector. -* -* The parameter j specifies the number of column of B, which has been -* replaced, 1 <= j <= m, where m is the order of B. -* -* The parameter bh specifies the basis header entry for the new column -* of B, which is the number of the new column in some original matrix. -* This parameter is optional and can be specified as 0. -* -* Row indices and numerical values of non-zero elements of the new -* column of B should be placed in locations ind[1], ..., ind[len] and -* val[1], ..., val[len], resp., where len is the number of non-zeros -* in the column. Neither zero nor duplicate elements are allowed. -* -* RETURNS -* -* 0 The factorization has been successfully updated. -* -* LPF_ESING -* New basis B is singular within the working precision. -* -* LPF_ELIMIT -* Maximal number of additional rows and columns has been reached. -* -* BACKGROUND -* -* Let j-th column of the current basis matrix B have to be replaced by -* a new column a. This replacement is equivalent to removing the old -* j-th column by fixing it at zero and introducing the new column as -* follows: -* -* ( B F^| a ) -* ( B F^) ( | ) -* ( ) ---> ( G^ H^| 0 ) -* ( G^ H^) (-------+---) -* ( e'j 0 | 0 ) -* -* where ej is a unit vector with 1 in j-th position which used to fix -* the old j-th column of B (at zero). Then using the main equality we -* have: -* -* ( B F^| a ) ( B0 F | f ) -* ( | ) ( P 0 ) ( | ) ( Q 0 ) -* ( G^ H^| 0 ) = ( ) ( G H | g ) ( ) = -* (-------+---) ( 0 1 ) (-------+---) ( 0 1 ) -* ( e'j 0 | 0 ) ( v' w'| 0 ) -* -* [ ( B0 F )| ( f ) ] [ ( B0 F ) | ( f ) ] -* [ P ( )| P ( ) ] ( Q 0 ) [ P ( ) Q| P ( ) ] -* = [ ( G H )| ( g ) ] ( ) = [ ( G H ) | ( g ) ] -* [------------+-------- ] ( 0 1 ) [-------------+---------] -* [ ( v' w')| 0 ] [ ( v' w') Q| 0 ] -* -* where: -* -* ( a ) ( f ) ( f ) ( a ) -* ( ) = P ( ) => ( ) = P' * ( ) -* ( 0 ) ( g ) ( g ) ( 0 ) -* -* ( ej ) ( v ) ( v ) ( ej ) -* ( e'j 0 ) = ( v' w' ) Q => ( ) = Q' ( ) => ( ) = Q ( ) -* ( 0 ) ( w ) ( w ) ( 0 ) -* -* On the other hand: -* -* ( B0| F f ) -* ( P 0 ) (---+------) ( Q 0 ) ( B0 new F ) -* ( ) ( G | H g ) ( ) = new P ( ) new Q -* ( 0 1 ) ( | ) ( 0 1 ) ( new G new H ) -* ( v'| w' 0 ) -* -* where: -* ( G ) ( H g ) -* new F = ( F f ), new G = ( ), new H = ( ), -* ( v') ( w' 0 ) -* -* ( P 0 ) ( Q 0 ) -* new P = ( ) , new Q = ( ) . -* ( 0 1 ) ( 0 1 ) -* -* The factorization structure for the new augmented matrix remains the -* same, therefore: -* -* ( B0 new F ) ( L0 0 ) ( U0 new R ) -* new P ( ) new Q = ( ) ( ) -* ( new G new H ) ( new S I ) ( 0 new C ) -* -* where: -* -* new F = L0 * new R => -* -* new R = inv(L0) * new F = inv(L0) * (F f) = ( R inv(L0)*f ) -* -* new G = new S * U0 => -* -* ( G ) ( S ) -* new S = new G * inv(U0) = ( ) * inv(U0) = ( ) -* ( v') ( v'*inv(U0) ) -* -* new H = new S * new R + new C => -* -* new C = new H - new S * new R = -* -* ( H g ) ( S ) -* = ( ) - ( ) * ( R inv(L0)*f ) = -* ( w' 0 ) ( v'*inv(U0) ) -* -* ( H - S*R g - S*inv(L0)*f ) ( C x ) -* = ( ) = ( ) -* ( w'- v'*inv(U0)*R -v'*inv(U0)*inv(L0)*f) ( y' z ) -* -* Note that new C is resulted by expanding old C with new column x, -* row y', and diagonal element z, where: -* -* x = g - S * inv(L0) * f = g - S * (new column of R) -* -* y = w - R'* inv(U'0)* v = w - R'* (new row of S) -* -* z = - (new row of S) * (new column of R) -* -* Finally, to replace old B by new B we have to permute j-th and last -* (just added) columns of the matrix -* -* ( B F^| a ) -* ( | ) -* ( G^ H^| 0 ) -* (-------+---) -* ( e'j 0 | 0 ) -* -* and to keep the main equality do the same for matrix Q. */ - -int lpf_update_it(LPF *lpf, int j, int bh, int len, const int ind[], - const double val[]) -{ int m0 = lpf->m0; - int m = lpf->m; -#if GLPLPF_DEBUG - double *B = lpf->B; -#endif - int n = lpf->n; - int *R_ptr = lpf->R_ptr; - int *R_len = lpf->R_len; - int *S_ptr = lpf->S_ptr; - int *S_len = lpf->S_len; - int *P_row = lpf->P_row; - int *P_col = lpf->P_col; - int *Q_row = lpf->Q_row; - int *Q_col = lpf->Q_col; - int v_ptr = lpf->v_ptr; - int *v_ind = lpf->v_ind; - double *v_val = lpf->v_val; - double *a = lpf->work2; /* new column */ - double *fg = lpf->work1, *f = fg, *g = fg + m0; - double *vw = lpf->work2, *v = vw, *w = vw + m0; - double *x = g, *y = w, z; - int i, ii, k, ret; - xassert(bh == bh); - if (!lpf->valid) - xfault("lpf_update_it: the factorization is not valid\n"); - if (!(1 <= j && j <= m)) - xfault("lpf_update_it: j = %d; column number out of range\n", - j); - xassert(0 <= m && m <= m0 + n); - /* check if the basis factorization can be expanded */ - if (n == lpf->n_max) - { lpf->valid = 0; - ret = LPF_ELIMIT; - goto done; - } - /* convert new j-th column of B to dense format */ - for (i = 1; i <= m; i++) - a[i] = 0.0; - for (k = 1; k <= len; k++) - { i = ind[k]; - if (!(1 <= i && i <= m)) - xfault("lpf_update_it: ind[%d] = %d; row number out of rang" - "e\n", k, i); - if (a[i] != 0.0) - xfault("lpf_update_it: ind[%d] = %d; duplicate row index no" - "t allowed\n", k, i); - if (val[k] == 0.0) - xfault("lpf_update_it: val[%d] = %g; zero element not allow" - "ed\n", k, val[k]); - a[i] = val[k]; - } -#if GLPLPF_DEBUG - /* change column in the basis matrix for debugging */ - for (i = 1; i <= m; i++) - B[(i - 1) * m + j] = a[i]; -#endif - /* (f g) := inv(P) * (a 0) */ - for (i = 1; i <= m0+n; i++) - fg[i] = ((ii = P_col[i]) <= m ? a[ii] : 0.0); - /* (v w) := Q * (ej 0) */ - for (i = 1; i <= m0+n; i++) vw[i] = 0.0; - vw[Q_col[j]] = 1.0; - /* f1 := inv(L0) * f (new column of R) */ -#if 0 /* 06/VI-2013 */ - luf_f_solve(lpf->luf, 0, f); -#else - luf_f_solve(lpf->lufint->luf, f); -#endif - /* v1 := inv(U'0) * v (new row of S) */ -#if 0 /* 06/VI-2013 */ - luf_v_solve(lpf->luf, 1, v); -#else - { double *work = lpf->lufint->sgf->work; - luf_vt_solve(lpf->lufint->luf, v, work); - memcpy(&v[1], &work[1], m0 * sizeof(double)); - } -#endif - /* we need at most 2 * m0 available locations in the SVA to store - new column of matrix R and new row of matrix S */ - if (lpf->v_size < v_ptr + m0 + m0) - { enlarge_sva(lpf, v_ptr + m0 + m0); - v_ind = lpf->v_ind; - v_val = lpf->v_val; - } - /* store new column of R */ - R_ptr[n+1] = v_ptr; - for (i = 1; i <= m0; i++) - { if (f[i] != 0.0) - v_ind[v_ptr] = i, v_val[v_ptr] = f[i], v_ptr++; - } - R_len[n+1] = v_ptr - lpf->v_ptr; - lpf->v_ptr = v_ptr; - /* store new row of S */ - S_ptr[n+1] = v_ptr; - for (i = 1; i <= m0; i++) - { if (v[i] != 0.0) - v_ind[v_ptr] = i, v_val[v_ptr] = v[i], v_ptr++; - } - S_len[n+1] = v_ptr - lpf->v_ptr; - lpf->v_ptr = v_ptr; - /* x := g - S * f1 (new column of C) */ - s_prod(lpf, x, -1.0, f); - /* y := w - R' * v1 (new row of C) */ - rt_prod(lpf, y, -1.0, v); - /* z := - v1 * f1 (new diagonal element of C) */ - z = 0.0; - for (i = 1; i <= m0; i++) z -= v[i] * f[i]; - /* update factorization of new matrix C */ -#if 0 /* 11/VIII-2013 */ - switch (scf_update_exp(lpf->scf, x, y, z)) - { case 0: - break; - case SCF_ESING: - lpf->valid = 0; - ret = LPF_ESING; - goto done; - case SCF_ELIMIT: - xassert(lpf != lpf); - default: - xassert(lpf != lpf); - } -#else - if (lpf->t_opt == SCF_TBG) - { if (ifu_bg_update(&lpf->ifu, x, y, z) != 0) -#if 0 - { xprintf("Warning: insufficient accuracy (Bartels-Golub upda" - "te)\n"); -#else - { -#endif - lpf->valid = 0; - ret = LPF_ESING; - goto done; - } - } - else if (lpf->t_opt == SCF_TGR) - { if (ifu_gr_update(&lpf->ifu, x, y, z) != 0) -#if 0 - { xprintf("Warning: insufficient accuracy (Givens rotations u" - "pdate)\n"); -#else - { -#endif - lpf->valid = 0; - ret = LPF_ESING; - goto done; - } - } - else - xassert(lpf != lpf); -#endif - /* expand matrix P */ - P_row[m0+n+1] = P_col[m0+n+1] = m0+n+1; - /* expand matrix Q */ - Q_row[m0+n+1] = Q_col[m0+n+1] = m0+n+1; - /* permute j-th and last (just added) column of matrix Q */ - i = Q_col[j], ii = Q_col[m0+n+1]; - Q_row[i] = m0+n+1, Q_col[m0+n+1] = i; - Q_row[ii] = j, Q_col[j] = ii; - /* increase the number of additional rows and columns */ - lpf->n++; - xassert(lpf->n <= lpf->n_max); - /* the factorization has been successfully updated */ - ret = 0; -done: /* return to the calling program */ - return ret; -} - -/*********************************************************************** -* NAME -* -* lpf_delete_it - delete LP basis factorization -* -* SYNOPSIS -* -* #include "glplpf.h" -* void lpf_delete_it(LPF *lpf) -* -* DESCRIPTION -* -* The routine lpf_delete_it deletes LP basis factorization specified -* by the parameter lpf and frees all memory allocated to this program -* object. */ - -void lpf_delete_it(LPF *lpf) -#if 0 /* 06/VI-2013 */ -{ luf_delete_it(lpf->luf); -#else -{ lufint_delete(lpf->lufint); -#endif -#if GLPLPF_DEBUG - if (lpf->B != NULL) xfree(lpf->B); -#else - xassert(lpf->B == NULL); -#endif - if (lpf->R_ptr != NULL) xfree(lpf->R_ptr); - if (lpf->R_len != NULL) xfree(lpf->R_len); - if (lpf->S_ptr != NULL) xfree(lpf->S_ptr); - if (lpf->S_len != NULL) xfree(lpf->S_len); -#if 0 /* 11/VIII-2013 */ - if (lpf->scf != NULL) scf_delete_it(lpf->scf); -#else - if (lpf->ifu.f != NULL) tfree(lpf->ifu.f); - if (lpf->ifu.u != NULL) tfree(lpf->ifu.u); -#endif - if (lpf->P_row != NULL) xfree(lpf->P_row); - if (lpf->P_col != NULL) xfree(lpf->P_col); - if (lpf->Q_row != NULL) xfree(lpf->Q_row); - if (lpf->Q_col != NULL) xfree(lpf->Q_col); - if (lpf->v_ind != NULL) xfree(lpf->v_ind); - if (lpf->v_val != NULL) xfree(lpf->v_val); - if (lpf->work1 != NULL) xfree(lpf->work1); - if (lpf->work2 != NULL) xfree(lpf->work2); - xfree(lpf); - return; -} - -/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glplpf.h b/resources/3rdparty/glpk-4.53/src/glplpf.h deleted file mode 100644 index e06e6c595..000000000 --- a/resources/3rdparty/glpk-4.53/src/glplpf.h +++ /dev/null @@ -1,216 +0,0 @@ -/* glplpf.h (LP basis factorization, Schur complement version) */ - -/*********************************************************************** -* This code is part of GLPK (GNU Linear Programming Kit). -* -* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, -* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied -* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights -* reserved. E-mail: . -* -* GLPK is free software: you can redistribute it and/or modify it -* under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* GLPK is distributed in the hope that it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -* License for more details. -* -* You should have received a copy of the GNU General Public License -* along with GLPK. If not, see . -***********************************************************************/ - -#ifndef GLPLPF_H -#define GLPLPF_H - -#if 0 /* 11/VIII-2013 */ -#include "glpscf.h" -#else -#include "ifu.h" -#endif -#if 0 /* 06/VI-2013 */ -#include "glpluf.h" -#else -#include "lufint.h" -#endif - -/*********************************************************************** -* The structure LPF defines the factorization of the basis mxm matrix -* B, where m is the number of rows in corresponding problem instance. -* -* This factorization is the following septet: -* -* [B] = (L0, U0, R, S, C, P, Q), (1) -* -* and is based on the following main equality: -* -* ( B F^) ( B0 F ) ( L0 0 ) ( U0 R ) -* ( ) = P ( ) Q = P ( ) ( ) Q, (2) -* ( G^ H^) ( G H ) ( S I ) ( 0 C ) -* -* where: -* -* B is the current basis matrix (not stored); -* -* F^, G^, H^ are some additional matrices (not stored); -* -* B0 is some initial basis matrix (not stored); -* -* F, G, H are some additional matrices (not stored); -* -* P, Q are permutation matrices (stored in both row- and column-like -* formats); -* -* L0, U0 are some matrices that defines a factorization of the initial -* basis matrix B0 = L0 * U0 (stored in an invertable form); -* -* R is a matrix defined from L0 * R = F, so R = inv(L0) * F (stored in -* a column-wise sparse format); -* -* S is a matrix defined from S * U0 = G, so S = G * inv(U0) (stored in -* a row-wise sparse format); -* -* C is the Schur complement for matrix (B0 F G H). It is defined from -* S * R + C = H, so C = H - S * R = H - G * inv(U0) * inv(L0) * F = -* = H - G * inv(B0) * F. Matrix C is stored in an invertable form. -* -* REFERENCES -* -* 1. M.A.Saunders, "LUSOL: A basis package for constrained optimiza- -* tion," SCCM, Stanford University, 2006. -* -* 2. M.A.Saunders, "Notes 5: Basis Updates," CME 318, Stanford Univer- -* sity, Spring 2006. -* -* 3. M.A.Saunders, "Notes 6: LUSOL---a Basis Factorization Package," -* ibid. */ - -typedef struct LPF LPF; - -struct LPF -{ /* LP basis factorization */ - int valid; - /* the factorization is valid only if this flag is set */ - /*--------------------------------------------------------------*/ - /* initial basis matrix B0 */ - int m0_max; - /* maximal value of m0 (increased automatically, if necessary) */ - int m0; - /* the order of B0 */ -#if 0 /* 06/VI-2013 */ - LUF *luf; -#else - LUFINT *lufint; -#endif - /* LU-factorization of B0 */ - /*--------------------------------------------------------------*/ - /* current basis matrix B */ - int m; - /* the order of B */ - double *B; /* double B[1+m*m]; */ - /* B in dense format stored by rows and used only for debugging; - normally this array is not allocated */ - /*--------------------------------------------------------------*/ - /* augmented matrix (B0 F G H) of the order m0+n */ - int n_max; - /* maximal number of additional rows and columns */ - int n; - /* current number of additional rows and columns */ - /*--------------------------------------------------------------*/ - /* m0xn matrix R in column-wise format */ - int *R_ptr; /* int R_ptr[1+n_max]; */ - /* R_ptr[j], 1 <= j <= n, is a pointer to j-th column */ - int *R_len; /* int R_len[1+n_max]; */ - /* R_len[j], 1 <= j <= n, is the length of j-th column */ - /*--------------------------------------------------------------*/ - /* nxm0 matrix S in row-wise format */ - int *S_ptr; /* int S_ptr[1+n_max]; */ - /* S_ptr[i], 1 <= i <= n, is a pointer to i-th row */ - int *S_len; /* int S_len[1+n_max]; */ - /* S_len[i], 1 <= i <= n, is the length of i-th row */ - /*--------------------------------------------------------------*/ - /* Schur complement C of the order n */ -#if 0 /* 11/VIII-2013 */ - SCF *scf; /* SCF scf[1:n_max]; */ - /* factorization of the Schur complement */ -#else - IFU ifu; - /* IFU-factorization of the Schur complement */ - int t_opt; - /* type of transformation used to restore triangular structure of - matrix U: */ -#define SCF_TBG 1 /* Bartels-Golub elimination */ -#define SCF_TGR 2 /* Givens plane rotations */ -#endif - /*--------------------------------------------------------------*/ - /* matrix P of the order m0+n */ - int *P_row; /* int P_row[1+m0_max+n_max]; */ - /* P_row[i] = j means that P[i,j] = 1 */ - int *P_col; /* int P_col[1+m0_max+n_max]; */ - /* P_col[j] = i means that P[i,j] = 1 */ - /*--------------------------------------------------------------*/ - /* matrix Q of the order m0+n */ - int *Q_row; /* int Q_row[1+m0_max+n_max]; */ - /* Q_row[i] = j means that Q[i,j] = 1 */ - int *Q_col; /* int Q_col[1+m0_max+n_max]; */ - /* Q_col[j] = i means that Q[i,j] = 1 */ - /*--------------------------------------------------------------*/ - /* Sparse Vector Area (SVA) is a set of locations intended to - store sparse vectors which represent columns of matrix R and - rows of matrix S; each location is a doublet (ind, val), where - ind is an index, val is a numerical value of a sparse vector - element; in the whole each sparse vector is a set of adjacent - locations defined by a pointer to its first element and its - length, i.e. the number of its elements */ - int v_size; - /* the SVA size, in locations; locations are numbered by integers - 1, 2, ..., v_size, and location 0 is not used */ - int v_ptr; - /* pointer to the first available location */ - int *v_ind; /* int v_ind[1+v_size]; */ - /* v_ind[k], 1 <= k <= v_size, is the index field of location k */ - double *v_val; /* double v_val[1+v_size]; */ - /* v_val[k], 1 <= k <= v_size, is the value field of location k */ - /*--------------------------------------------------------------*/ - double *work1; /* double work1[1+m0+n_max]; */ - /* working array */ - double *work2; /* double work2[1+m0+n_max]; */ - /* working array */ -}; - -/* return codes: */ -#define LPF_ESING 1 /* singular matrix */ -#define LPF_ECOND 2 /* ill-conditioned matrix */ -#define LPF_ELIMIT 3 /* update limit reached */ - -#define lpf_create_it _glp_lpf_create_it -LPF *lpf_create_it(void); -/* create LP basis factorization */ - -#define lpf_factorize _glp_lpf_factorize -int lpf_factorize(LPF *lpf, int m, const int bh[], int (*col) - (void *info, int j, int ind[], double val[]), void *info); -/* compute LP basis factorization */ - -#define lpf_ftran _glp_lpf_ftran -void lpf_ftran(LPF *lpf, double x[]); -/* perform forward transformation (solve system B*x = b) */ - -#define lpf_btran _glp_lpf_btran -void lpf_btran(LPF *lpf, double x[]); -/* perform backward transformation (solve system B'*x = b) */ - -#define lpf_update_it _glp_lpf_update_it -int lpf_update_it(LPF *lpf, int j, int bh, int len, const int ind[], - const double val[]); -/* update LP basis factorization */ - -#define lpf_delete_it _glp_lpf_delete_it -void lpf_delete_it(LPF *lpf); -/* delete LP basis factorization */ - -#endif - -/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpspx01.c b/resources/3rdparty/glpk-4.53/src/glpspx01.c deleted file mode 100644 index eb0e4b50c..000000000 --- a/resources/3rdparty/glpk-4.53/src/glpspx01.c +++ /dev/null @@ -1,2971 +0,0 @@ -/* glpspx01.c (primal simplex method) */ - -/*********************************************************************** -* This code is part of GLPK (GNU Linear Programming Kit). -* -* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, -* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied -* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights -* reserved. E-mail: . -* -* GLPK is free software: you can redistribute it and/or modify it -* under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* GLPK is distributed in the hope that it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -* License for more details. -* -* You should have received a copy of the GNU General Public License -* along with GLPK. If not, see . -***********************************************************************/ - -#include "env.h" -#include "glpspx.h" - -struct csa -{ /* common storage area */ - /*--------------------------------------------------------------*/ - /* LP data */ - int m; - /* number of rows (auxiliary variables), m > 0 */ - int n; - /* number of columns (structural variables), n > 0 */ - char *type; /* char type[1+m+n]; */ - /* type[0] is not used; - type[k], 1 <= k <= m+n, is the type of variable x[k]: - GLP_FR - free variable - GLP_LO - variable with lower bound - GLP_UP - variable with upper bound - GLP_DB - double-bounded variable - GLP_FX - fixed variable */ - double *lb; /* double lb[1+m+n]; */ - /* lb[0] is not used; - lb[k], 1 <= k <= m+n, is an lower bound of variable x[k]; - if x[k] has no lower bound, lb[k] is zero */ - double *ub; /* double ub[1+m+n]; */ - /* ub[0] is not used; - ub[k], 1 <= k <= m+n, is an upper bound of variable x[k]; - if x[k] has no upper bound, ub[k] is zero; - if x[k] is of fixed type, ub[k] is the same as lb[k] */ - double *coef; /* double coef[1+m+n]; */ - /* coef[0] is not used; - coef[k], 1 <= k <= m+n, is an objective coefficient at - variable x[k] (note that on phase I auxiliary variables also - may have non-zero objective coefficients) */ - /*--------------------------------------------------------------*/ - /* original objective function */ - double *obj; /* double obj[1+n]; */ - /* obj[0] is a constant term of the original objective function; - obj[j], 1 <= j <= n, is an original objective coefficient at - structural variable x[m+j] */ - double zeta; - /* factor used to scale original objective coefficients; its - sign defines original optimization direction: zeta > 0 means - minimization, zeta < 0 means maximization */ - /*--------------------------------------------------------------*/ - /* constraint matrix A; it has m rows and n columns and is stored - by columns */ - int *A_ptr; /* int A_ptr[1+n+1]; */ - /* A_ptr[0] is not used; - A_ptr[j], 1 <= j <= n, is starting position of j-th column in - arrays A_ind and A_val; note that A_ptr[1] is always 1; - A_ptr[n+1] indicates the position after the last element in - arrays A_ind and A_val */ - int *A_ind; /* int A_ind[A_ptr[n+1]]; */ - /* row indices */ - double *A_val; /* double A_val[A_ptr[n+1]]; */ - /* non-zero element values */ - /*--------------------------------------------------------------*/ - /* basis header */ - int *head; /* int head[1+m+n]; */ - /* head[0] is not used; - head[i], 1 <= i <= m, is the ordinal number of basic variable - xB[i]; head[i] = k means that xB[i] = x[k] and i-th column of - matrix B is k-th column of matrix (I|-A); - head[m+j], 1 <= j <= n, is the ordinal number of non-basic - variable xN[j]; head[m+j] = k means that xN[j] = x[k] and j-th - column of matrix N is k-th column of matrix (I|-A) */ - char *stat; /* char stat[1+n]; */ - /* stat[0] is not used; - stat[j], 1 <= j <= n, is the status of non-basic variable - xN[j], which defines its active bound: - GLP_NL - lower bound is active - GLP_NU - upper bound is active - GLP_NF - free variable - GLP_NS - fixed variable */ - /*--------------------------------------------------------------*/ - /* matrix B is the basis matrix; it is composed from columns of - the augmented constraint matrix (I|-A) corresponding to basic - variables and stored in a factorized (invertable) form */ - int valid; - /* factorization is valid only if this flag is set */ - BFD *bfd; /* BFD bfd[1:m,1:m]; */ - /* factorized (invertable) form of the basis matrix */ - /*--------------------------------------------------------------*/ - /* matrix N is a matrix composed from columns of the augmented - constraint matrix (I|-A) corresponding to non-basic variables - except fixed ones; it is stored by rows and changes every time - the basis changes */ - int *N_ptr; /* int N_ptr[1+m+1]; */ - /* N_ptr[0] is not used; - N_ptr[i], 1 <= i <= m, is starting position of i-th row in - arrays N_ind and N_val; note that N_ptr[1] is always 1; - N_ptr[m+1] indicates the position after the last element in - arrays N_ind and N_val */ - int *N_len; /* int N_len[1+m]; */ - /* N_len[0] is not used; - N_len[i], 1 <= i <= m, is length of i-th row (0 to n) */ - int *N_ind; /* int N_ind[N_ptr[m+1]]; */ - /* column indices */ - double *N_val; /* double N_val[N_ptr[m+1]]; */ - /* non-zero element values */ - /*--------------------------------------------------------------*/ - /* working parameters */ - int phase; - /* search phase: - 0 - not determined yet - 1 - search for primal feasible solution - 2 - search for optimal solution */ -#if 0 /* 10/VI-2013 */ - glp_long tm_beg; - /* time value at the beginning of the search */ -#else - double tm_beg; -#endif - int it_beg; - /* simplex iteration count at the beginning of the search */ - int it_cnt; - /* simplex iteration count; it increases by one every time the - basis changes (including the case when a non-basic variable - jumps to its opposite bound) */ - int it_dpy; - /* simplex iteration count at the most recent display output */ - /*--------------------------------------------------------------*/ - /* basic solution components */ - double *bbar; /* double bbar[1+m]; */ - /* bbar[0] is not used; - bbar[i], 1 <= i <= m, is primal value of basic variable xB[i] - (if xB[i] is free, its primal value is not updated) */ - double *cbar; /* double cbar[1+n]; */ - /* cbar[0] is not used; - cbar[j], 1 <= j <= n, is reduced cost of non-basic variable - xN[j] (if xN[j] is fixed, its reduced cost is not updated) */ - /*--------------------------------------------------------------*/ - /* the following pricing technique options may be used: - GLP_PT_STD - standard ("textbook") pricing; - GLP_PT_PSE - projected steepest edge; - GLP_PT_DVX - Devex pricing (not implemented yet); - in case of GLP_PT_STD the reference space is not used, and all - steepest edge coefficients are set to 1 */ - int refct; - /* this count is set to an initial value when the reference space - is defined and decreases by one every time the basis changes; - once this count reaches zero, the reference space is redefined - again */ - char *refsp; /* char refsp[1+m+n]; */ - /* refsp[0] is not used; - refsp[k], 1 <= k <= m+n, is the flag which means that variable - x[k] belongs to the current reference space */ - double *gamma; /* double gamma[1+n]; */ - /* gamma[0] is not used; - gamma[j], 1 <= j <= n, is the steepest edge coefficient for - non-basic variable xN[j]; if xN[j] is fixed, gamma[j] is not - used and just set to 1 */ - /*--------------------------------------------------------------*/ - /* non-basic variable xN[q] chosen to enter the basis */ - int q; - /* index of the non-basic variable xN[q] chosen, 1 <= q <= n; - if the set of eligible non-basic variables is empty and thus - no variable has been chosen, q is set to 0 */ - /*--------------------------------------------------------------*/ - /* pivot column of the simplex table corresponding to non-basic - variable xN[q] chosen is the following vector: - T * e[q] = - inv(B) * N * e[q] = - inv(B) * N[q], - where B is the current basis matrix, N[q] is a column of the - matrix (I|-A) corresponding to xN[q] */ - int tcol_nnz; - /* number of non-zero components, 0 <= nnz <= m */ - int *tcol_ind; /* int tcol_ind[1+m]; */ - /* tcol_ind[0] is not used; - tcol_ind[t], 1 <= t <= nnz, is an index of non-zero component, - i.e. tcol_ind[t] = i means that tcol_vec[i] != 0 */ - double *tcol_vec; /* double tcol_vec[1+m]; */ - /* tcol_vec[0] is not used; - tcol_vec[i], 1 <= i <= m, is a numeric value of i-th component - of the column */ - double tcol_max; - /* infinity (maximum) norm of the column (max |tcol_vec[i]|) */ - int tcol_num; - /* number of significant non-zero components, which means that: - |tcol_vec[i]| >= eps for i in tcol_ind[1,...,num], - |tcol_vec[i]| < eps for i in tcol_ind[num+1,...,nnz], - where eps is a pivot tolerance */ - /*--------------------------------------------------------------*/ - /* basic variable xB[p] chosen to leave the basis */ - int p; - /* index of the basic variable xB[p] chosen, 1 <= p <= m; - p = 0 means that no basic variable reaches its bound; - p < 0 means that non-basic variable xN[q] reaches its opposite - bound before any basic variable */ - int p_stat; - /* new status (GLP_NL, GLP_NU, or GLP_NS) to be assigned to xB[p] - once it has left the basis */ - double teta; - /* change of non-basic variable xN[q] (see above), on which xB[p] - (or, if p < 0, xN[q] itself) reaches its bound */ - /*--------------------------------------------------------------*/ - /* pivot row of the simplex table corresponding to basic variable - xB[p] chosen is the following vector: - T' * e[p] = - N' * inv(B') * e[p] = - N' * rho, - where B' is a matrix transposed to the current basis matrix, - N' is a matrix, whose rows are columns of the matrix (I|-A) - corresponding to non-basic non-fixed variables */ - int trow_nnz; - /* number of non-zero components, 0 <= nnz <= n */ - int *trow_ind; /* int trow_ind[1+n]; */ - /* trow_ind[0] is not used; - trow_ind[t], 1 <= t <= nnz, is an index of non-zero component, - i.e. trow_ind[t] = j means that trow_vec[j] != 0 */ - double *trow_vec; /* int trow_vec[1+n]; */ - /* trow_vec[0] is not used; - trow_vec[j], 1 <= j <= n, is a numeric value of j-th component - of the row */ - /*--------------------------------------------------------------*/ - /* working arrays */ - double *work1; /* double work1[1+m]; */ - double *work2; /* double work2[1+m]; */ - double *work3; /* double work3[1+m]; */ - double *work4; /* double work4[1+m]; */ -}; - -static const double kappa = 0.10; - -/*********************************************************************** -* alloc_csa - allocate common storage area -* -* This routine allocates all arrays in the common storage area (CSA) -* and returns a pointer to the CSA. */ - -static struct csa *alloc_csa(glp_prob *lp) -{ struct csa *csa; - int m = lp->m; - int n = lp->n; - int nnz = lp->nnz; - csa = xmalloc(sizeof(struct csa)); - xassert(m > 0 && n > 0); - csa->m = m; - csa->n = n; - csa->type = xcalloc(1+m+n, sizeof(char)); - csa->lb = xcalloc(1+m+n, sizeof(double)); - csa->ub = xcalloc(1+m+n, sizeof(double)); - csa->coef = xcalloc(1+m+n, sizeof(double)); - csa->obj = xcalloc(1+n, sizeof(double)); - csa->A_ptr = xcalloc(1+n+1, sizeof(int)); - csa->A_ind = xcalloc(1+nnz, sizeof(int)); - csa->A_val = xcalloc(1+nnz, sizeof(double)); - csa->head = xcalloc(1+m+n, sizeof(int)); - csa->stat = xcalloc(1+n, sizeof(char)); - csa->N_ptr = xcalloc(1+m+1, sizeof(int)); - csa->N_len = xcalloc(1+m, sizeof(int)); - csa->N_ind = NULL; /* will be allocated later */ - csa->N_val = NULL; /* will be allocated later */ - csa->bbar = xcalloc(1+m, sizeof(double)); - csa->cbar = xcalloc(1+n, sizeof(double)); - csa->refsp = xcalloc(1+m+n, sizeof(char)); - csa->gamma = xcalloc(1+n, sizeof(double)); - csa->tcol_ind = xcalloc(1+m, sizeof(int)); - csa->tcol_vec = xcalloc(1+m, sizeof(double)); - csa->trow_ind = xcalloc(1+n, sizeof(int)); - csa->trow_vec = xcalloc(1+n, sizeof(double)); - csa->work1 = xcalloc(1+m, sizeof(double)); - csa->work2 = xcalloc(1+m, sizeof(double)); - csa->work3 = xcalloc(1+m, sizeof(double)); - csa->work4 = xcalloc(1+m, sizeof(double)); - return csa; -} - -/*********************************************************************** -* init_csa - initialize common storage area -* -* This routine initializes all data structures in the common storage -* area (CSA). */ - -static void alloc_N(struct csa *csa); -static void build_N(struct csa *csa); - -static void init_csa(struct csa *csa, glp_prob *lp) -{ int m = csa->m; - int n = csa->n; - char *type = csa->type; - double *lb = csa->lb; - double *ub = csa->ub; - double *coef = csa->coef; - double *obj = csa->obj; - int *A_ptr = csa->A_ptr; - int *A_ind = csa->A_ind; - double *A_val = csa->A_val; - int *head = csa->head; - char *stat = csa->stat; - char *refsp = csa->refsp; - double *gamma = csa->gamma; - int i, j, k, loc; - double cmax; - /* auxiliary variables */ - for (i = 1; i <= m; i++) - { GLPROW *row = lp->row[i]; - type[i] = (char)row->type; - lb[i] = row->lb * row->rii; - ub[i] = row->ub * row->rii; - coef[i] = 0.0; - } - /* structural variables */ - for (j = 1; j <= n; j++) - { GLPCOL *col = lp->col[j]; - type[m+j] = (char)col->type; - lb[m+j] = col->lb / col->sjj; - ub[m+j] = col->ub / col->sjj; - coef[m+j] = col->coef * col->sjj; - } - /* original objective function */ - obj[0] = lp->c0; - memcpy(&obj[1], &coef[m+1], n * sizeof(double)); - /* factor used to scale original objective coefficients */ - cmax = 0.0; - for (j = 1; j <= n; j++) - if (cmax < fabs(obj[j])) cmax = fabs(obj[j]); - if (cmax == 0.0) cmax = 1.0; - switch (lp->dir) - { case GLP_MIN: - csa->zeta = + 1.0 / cmax; - break; - case GLP_MAX: - csa->zeta = - 1.0 / cmax; - break; - default: - xassert(lp != lp); - } -#if 1 - if (fabs(csa->zeta) < 1.0) csa->zeta *= 1000.0; -#endif - /* matrix A (by columns) */ - loc = 1; - for (j = 1; j <= n; j++) - { GLPAIJ *aij; - A_ptr[j] = loc; - for (aij = lp->col[j]->ptr; aij != NULL; aij = aij->c_next) - { A_ind[loc] = aij->row->i; - A_val[loc] = aij->row->rii * aij->val * aij->col->sjj; - loc++; - } - } - A_ptr[n+1] = loc; - xassert(loc == lp->nnz+1); - /* basis header */ - xassert(lp->valid); - memcpy(&head[1], &lp->head[1], m * sizeof(int)); - k = 0; - for (i = 1; i <= m; i++) - { GLPROW *row = lp->row[i]; - if (row->stat != GLP_BS) - { k++; - xassert(k <= n); - head[m+k] = i; - stat[k] = (char)row->stat; - } - } - for (j = 1; j <= n; j++) - { GLPCOL *col = lp->col[j]; - if (col->stat != GLP_BS) - { k++; - xassert(k <= n); - head[m+k] = m + j; - stat[k] = (char)col->stat; - } - } - xassert(k == n); - /* factorization of matrix B */ - csa->valid = 1, lp->valid = 0; - csa->bfd = lp->bfd, lp->bfd = NULL; - /* matrix N (by rows) */ - alloc_N(csa); - build_N(csa); - /* working parameters */ - csa->phase = 0; - csa->tm_beg = xtime(); - csa->it_beg = csa->it_cnt = lp->it_cnt; - csa->it_dpy = -1; - /* reference space and steepest edge coefficients */ - csa->refct = 0; - memset(&refsp[1], 0, (m+n) * sizeof(char)); - for (j = 1; j <= n; j++) gamma[j] = 1.0; - return; -} - -/*********************************************************************** -* invert_B - compute factorization of the basis matrix -* -* This routine computes factorization of the current basis matrix B. -* -* If the operation is successful, the routine returns zero, otherwise -* non-zero. */ - -static int inv_col(void *info, int i, int ind[], double val[]) -{ /* this auxiliary routine returns row indices and numeric values - of non-zero elements of i-th column of the basis matrix */ - struct csa *csa = info; - int m = csa->m; -#ifdef GLP_DEBUG - int n = csa->n; -#endif - int *A_ptr = csa->A_ptr; - int *A_ind = csa->A_ind; - double *A_val = csa->A_val; - int *head = csa->head; - int k, len, ptr, t; -#ifdef GLP_DEBUG - xassert(1 <= i && i <= m); -#endif - k = head[i]; /* B[i] is k-th column of (I|-A) */ -#ifdef GLP_DEBUG - xassert(1 <= k && k <= m+n); -#endif - if (k <= m) - { /* B[i] is k-th column of submatrix I */ - len = 1; - ind[1] = k; - val[1] = 1.0; - } - else - { /* B[i] is (k-m)-th column of submatrix (-A) */ - ptr = A_ptr[k-m]; - len = A_ptr[k-m+1] - ptr; - memcpy(&ind[1], &A_ind[ptr], len * sizeof(int)); - memcpy(&val[1], &A_val[ptr], len * sizeof(double)); - for (t = 1; t <= len; t++) val[t] = - val[t]; - } - return len; -} - -static int invert_B(struct csa *csa) -{ int ret; - ret = bfd_factorize(csa->bfd, csa->m, NULL, inv_col, csa); - csa->valid = (ret == 0); - return ret; -} - -/*********************************************************************** -* update_B - update factorization of the basis matrix -* -* This routine replaces i-th column of the basis matrix B by k-th -* column of the augmented constraint matrix (I|-A) and then updates -* the factorization of B. -* -* If the factorization has been successfully updated, the routine -* returns zero, otherwise non-zero. */ - -static int update_B(struct csa *csa, int i, int k) -{ int m = csa->m; -#ifdef GLP_DEBUG - int n = csa->n; -#endif - int ret; -#ifdef GLP_DEBUG - xassert(1 <= i && i <= m); - xassert(1 <= k && k <= m+n); -#endif - if (k <= m) - { /* new i-th column of B is k-th column of I */ - int ind[1+1]; - double val[1+1]; - ind[1] = k; - val[1] = 1.0; - xassert(csa->valid); - ret = bfd_update_it(csa->bfd, i, 0, 1, ind, val); - } - else - { /* new i-th column of B is (k-m)-th column of (-A) */ - int *A_ptr = csa->A_ptr; - int *A_ind = csa->A_ind; - double *A_val = csa->A_val; - double *val = csa->work1; - int beg, end, ptr, len; - beg = A_ptr[k-m]; - end = A_ptr[k-m+1]; - len = 0; - for (ptr = beg; ptr < end; ptr++) - val[++len] = - A_val[ptr]; - xassert(csa->valid); - ret = bfd_update_it(csa->bfd, i, 0, len, &A_ind[beg-1], val); - } - csa->valid = (ret == 0); - return ret; -} - -/*********************************************************************** -* error_ftran - compute residual vector r = h - B * x -* -* This routine computes the residual vector r = h - B * x, where B is -* the current basis matrix, h is the vector of right-hand sides, x is -* the solution vector. */ - -static void error_ftran(struct csa *csa, double h[], double x[], - double r[]) -{ int m = csa->m; -#ifdef GLP_DEBUG - int n = csa->n; -#endif - int *A_ptr = csa->A_ptr; - int *A_ind = csa->A_ind; - double *A_val = csa->A_val; - int *head = csa->head; - int i, k, beg, end, ptr; - double temp; - /* compute the residual vector: - r = h - B * x = h - B[1] * x[1] - ... - B[m] * x[m], - where B[1], ..., B[m] are columns of matrix B */ - memcpy(&r[1], &h[1], m * sizeof(double)); - for (i = 1; i <= m; i++) - { temp = x[i]; - if (temp == 0.0) continue; - k = head[i]; /* B[i] is k-th column of (I|-A) */ -#ifdef GLP_DEBUG - xassert(1 <= k && k <= m+n); -#endif - if (k <= m) - { /* B[i] is k-th column of submatrix I */ - r[k] -= temp; - } - else - { /* B[i] is (k-m)-th column of submatrix (-A) */ - beg = A_ptr[k-m]; - end = A_ptr[k-m+1]; - for (ptr = beg; ptr < end; ptr++) - r[A_ind[ptr]] += A_val[ptr] * temp; - } - } - return; -} - -/*********************************************************************** -* refine_ftran - refine solution of B * x = h -* -* This routine performs one iteration to refine the solution of -* the system B * x = h, where B is the current basis matrix, h is the -* vector of right-hand sides, x is the solution vector. */ - -static void refine_ftran(struct csa *csa, double h[], double x[]) -{ int m = csa->m; - double *r = csa->work1; - double *d = csa->work1; - int i; - /* compute the residual vector r = h - B * x */ - error_ftran(csa, h, x, r); - /* compute the correction vector d = inv(B) * r */ - xassert(csa->valid); - bfd_ftran(csa->bfd, d); - /* refine the solution vector (new x) = (old x) + d */ - for (i = 1; i <= m; i++) x[i] += d[i]; - return; -} - -/*********************************************************************** -* error_btran - compute residual vector r = h - B'* x -* -* This routine computes the residual vector r = h - B'* x, where B' -* is a matrix transposed to the current basis matrix, h is the vector -* of right-hand sides, x is the solution vector. */ - -static void error_btran(struct csa *csa, double h[], double x[], - double r[]) -{ int m = csa->m; -#ifdef GLP_DEBUG - int n = csa->n; -#endif - int *A_ptr = csa->A_ptr; - int *A_ind = csa->A_ind; - double *A_val = csa->A_val; - int *head = csa->head; - int i, k, beg, end, ptr; - double temp; - /* compute the residual vector r = b - B'* x */ - for (i = 1; i <= m; i++) - { /* r[i] := b[i] - (i-th column of B)'* x */ - k = head[i]; /* B[i] is k-th column of (I|-A) */ -#ifdef GLP_DEBUG - xassert(1 <= k && k <= m+n); -#endif - temp = h[i]; - if (k <= m) - { /* B[i] is k-th column of submatrix I */ - temp -= x[k]; - } - else - { /* B[i] is (k-m)-th column of submatrix (-A) */ - beg = A_ptr[k-m]; - end = A_ptr[k-m+1]; - for (ptr = beg; ptr < end; ptr++) - temp += A_val[ptr] * x[A_ind[ptr]]; - } - r[i] = temp; - } - return; -} - -/*********************************************************************** -* refine_btran - refine solution of B'* x = h -* -* This routine performs one iteration to refine the solution of the -* system B'* x = h, where B' is a matrix transposed to the current -* basis matrix, h is the vector of right-hand sides, x is the solution -* vector. */ - -static void refine_btran(struct csa *csa, double h[], double x[]) -{ int m = csa->m; - double *r = csa->work1; - double *d = csa->work1; - int i; - /* compute the residual vector r = h - B'* x */ - error_btran(csa, h, x, r); - /* compute the correction vector d = inv(B') * r */ - xassert(csa->valid); - bfd_btran(csa->bfd, d); - /* refine the solution vector (new x) = (old x) + d */ - for (i = 1; i <= m; i++) x[i] += d[i]; - return; -} - -/*********************************************************************** -* alloc_N - allocate matrix N -* -* This routine determines maximal row lengths of matrix N, sets its -* row pointers, and then allocates arrays N_ind and N_val. -* -* Note that some fixed structural variables may temporarily become -* double-bounded, so corresponding columns of matrix A should not be -* ignored on calculating maximal row lengths of matrix N. */ - -static void alloc_N(struct csa *csa) -{ int m = csa->m; - int n = csa->n; - int *A_ptr = csa->A_ptr; - int *A_ind = csa->A_ind; - int *N_ptr = csa->N_ptr; - int *N_len = csa->N_len; - int i, j, beg, end, ptr; - /* determine number of non-zeros in each row of the augmented - constraint matrix (I|-A) */ - for (i = 1; i <= m; i++) - N_len[i] = 1; - for (j = 1; j <= n; j++) - { beg = A_ptr[j]; - end = A_ptr[j+1]; - for (ptr = beg; ptr < end; ptr++) - N_len[A_ind[ptr]]++; - } - /* determine maximal row lengths of matrix N and set its row - pointers */ - N_ptr[1] = 1; - for (i = 1; i <= m; i++) - { /* row of matrix N cannot have more than n non-zeros */ - if (N_len[i] > n) N_len[i] = n; - N_ptr[i+1] = N_ptr[i] + N_len[i]; - } - /* now maximal number of non-zeros in matrix N is known */ - csa->N_ind = xcalloc(N_ptr[m+1], sizeof(int)); - csa->N_val = xcalloc(N_ptr[m+1], sizeof(double)); - return; -} - -/*********************************************************************** -* add_N_col - add column of matrix (I|-A) to matrix N -* -* This routine adds j-th column to matrix N which is k-th column of -* the augmented constraint matrix (I|-A). (It is assumed that old j-th -* column was previously removed from matrix N.) */ - -static void add_N_col(struct csa *csa, int j, int k) -{ int m = csa->m; -#ifdef GLP_DEBUG - int n = csa->n; -#endif - int *N_ptr = csa->N_ptr; - int *N_len = csa->N_len; - int *N_ind = csa->N_ind; - double *N_val = csa->N_val; - int pos; -#ifdef GLP_DEBUG - xassert(1 <= j && j <= n); - xassert(1 <= k && k <= m+n); -#endif - if (k <= m) - { /* N[j] is k-th column of submatrix I */ - pos = N_ptr[k] + (N_len[k]++); -#ifdef GLP_DEBUG - xassert(pos < N_ptr[k+1]); -#endif - N_ind[pos] = j; - N_val[pos] = 1.0; - } - else - { /* N[j] is (k-m)-th column of submatrix (-A) */ - int *A_ptr = csa->A_ptr; - int *A_ind = csa->A_ind; - double *A_val = csa->A_val; - int i, beg, end, ptr; - beg = A_ptr[k-m]; - end = A_ptr[k-m+1]; - for (ptr = beg; ptr < end; ptr++) - { i = A_ind[ptr]; /* row number */ - pos = N_ptr[i] + (N_len[i]++); -#ifdef GLP_DEBUG - xassert(pos < N_ptr[i+1]); -#endif - N_ind[pos] = j; - N_val[pos] = - A_val[ptr]; - } - } - return; -} - -/*********************************************************************** -* del_N_col - remove column of matrix (I|-A) from matrix N -* -* This routine removes j-th column from matrix N which is k-th column -* of the augmented constraint matrix (I|-A). */ - -static void del_N_col(struct csa *csa, int j, int k) -{ int m = csa->m; -#ifdef GLP_DEBUG - int n = csa->n; -#endif - int *N_ptr = csa->N_ptr; - int *N_len = csa->N_len; - int *N_ind = csa->N_ind; - double *N_val = csa->N_val; - int pos, head, tail; -#ifdef GLP_DEBUG - xassert(1 <= j && j <= n); - xassert(1 <= k && k <= m+n); -#endif - if (k <= m) - { /* N[j] is k-th column of submatrix I */ - /* find element in k-th row of N */ - head = N_ptr[k]; - for (pos = head; N_ind[pos] != j; pos++) /* nop */; - /* and remove it from the row list */ - tail = head + (--N_len[k]); -#ifdef GLP_DEBUG - xassert(pos <= tail); -#endif - N_ind[pos] = N_ind[tail]; - N_val[pos] = N_val[tail]; - } - else - { /* N[j] is (k-m)-th column of submatrix (-A) */ - int *A_ptr = csa->A_ptr; - int *A_ind = csa->A_ind; - int i, beg, end, ptr; - beg = A_ptr[k-m]; - end = A_ptr[k-m+1]; - for (ptr = beg; ptr < end; ptr++) - { i = A_ind[ptr]; /* row number */ - /* find element in i-th row of N */ - head = N_ptr[i]; - for (pos = head; N_ind[pos] != j; pos++) /* nop */; - /* and remove it from the row list */ - tail = head + (--N_len[i]); -#ifdef GLP_DEBUG - xassert(pos <= tail); -#endif - N_ind[pos] = N_ind[tail]; - N_val[pos] = N_val[tail]; - } - } - return; -} - -/*********************************************************************** -* build_N - build matrix N for current basis -* -* This routine builds matrix N for the current basis from columns -* of the augmented constraint matrix (I|-A) corresponding to non-basic -* non-fixed variables. */ - -static void build_N(struct csa *csa) -{ int m = csa->m; - int n = csa->n; - int *head = csa->head; - char *stat = csa->stat; - int *N_len = csa->N_len; - int j, k; - /* N := empty matrix */ - memset(&N_len[1], 0, m * sizeof(int)); - /* go through non-basic columns of matrix (I|-A) */ - for (j = 1; j <= n; j++) - { if (stat[j] != GLP_NS) - { /* xN[j] is non-fixed; add j-th column to matrix N which is - k-th column of matrix (I|-A) */ - k = head[m+j]; /* x[k] = xN[j] */ -#ifdef GLP_DEBUG - xassert(1 <= k && k <= m+n); -#endif - add_N_col(csa, j, k); - } - } - return; -} - -/*********************************************************************** -* get_xN - determine current value of non-basic variable xN[j] -* -* This routine returns the current value of non-basic variable xN[j], -* which is a value of its active bound. */ - -static double get_xN(struct csa *csa, int j) -{ int m = csa->m; -#ifdef GLP_DEBUG - int n = csa->n; -#endif - double *lb = csa->lb; - double *ub = csa->ub; - int *head = csa->head; - char *stat = csa->stat; - int k; - double xN; -#ifdef GLP_DEBUG - xassert(1 <= j && j <= n); -#endif - k = head[m+j]; /* x[k] = xN[j] */ -#ifdef GLP_DEBUG - xassert(1 <= k && k <= m+n); -#endif - switch (stat[j]) - { case GLP_NL: - /* x[k] is on its lower bound */ - xN = lb[k]; break; - case GLP_NU: - /* x[k] is on its upper bound */ - xN = ub[k]; break; - case GLP_NF: - /* x[k] is free non-basic variable */ - xN = 0.0; break; - case GLP_NS: - /* x[k] is fixed non-basic variable */ - xN = lb[k]; break; - default: - xassert(stat != stat); - } - return xN; -} - -/*********************************************************************** -* eval_beta - compute primal values of basic variables -* -* This routine computes current primal values of all basic variables: -* -* beta = - inv(B) * N * xN, -* -* where B is the current basis matrix, N is a matrix built of columns -* of matrix (I|-A) corresponding to non-basic variables, and xN is the -* vector of current values of non-basic variables. */ - -static void eval_beta(struct csa *csa, double beta[]) -{ int m = csa->m; - int n = csa->n; - int *A_ptr = csa->A_ptr; - int *A_ind = csa->A_ind; - double *A_val = csa->A_val; - int *head = csa->head; - double *h = csa->work2; - int i, j, k, beg, end, ptr; - double xN; - /* compute the right-hand side vector: - h := - N * xN = - N[1] * xN[1] - ... - N[n] * xN[n], - where N[1], ..., N[n] are columns of matrix N */ - for (i = 1; i <= m; i++) - h[i] = 0.0; - for (j = 1; j <= n; j++) - { k = head[m+j]; /* x[k] = xN[j] */ -#ifdef GLP_DEBUG - xassert(1 <= k && k <= m+n); -#endif - /* determine current value of xN[j] */ - xN = get_xN(csa, j); - if (xN == 0.0) continue; - if (k <= m) - { /* N[j] is k-th column of submatrix I */ - h[k] -= xN; - } - else - { /* N[j] is (k-m)-th column of submatrix (-A) */ - beg = A_ptr[k-m]; - end = A_ptr[k-m+1]; - for (ptr = beg; ptr < end; ptr++) - h[A_ind[ptr]] += xN * A_val[ptr]; - } - } - /* solve system B * beta = h */ - memcpy(&beta[1], &h[1], m * sizeof(double)); - xassert(csa->valid); - bfd_ftran(csa->bfd, beta); - /* and refine the solution */ - refine_ftran(csa, h, beta); - return; -} - -/*********************************************************************** -* eval_pi - compute vector of simplex multipliers -* -* This routine computes the vector of current simplex multipliers: -* -* pi = inv(B') * cB, -* -* where B' is a matrix transposed to the current basis matrix, cB is -* a subvector of objective coefficients at basic variables. */ - -static void eval_pi(struct csa *csa, double pi[]) -{ int m = csa->m; - double *c = csa->coef; - int *head = csa->head; - double *cB = csa->work2; - int i; - /* construct the right-hand side vector cB */ - for (i = 1; i <= m; i++) - cB[i] = c[head[i]]; - /* solve system B'* pi = cB */ - memcpy(&pi[1], &cB[1], m * sizeof(double)); - xassert(csa->valid); - bfd_btran(csa->bfd, pi); - /* and refine the solution */ - refine_btran(csa, cB, pi); - return; -} - -/*********************************************************************** -* eval_cost - compute reduced cost of non-basic variable xN[j] -* -* This routine computes the current reduced cost of non-basic variable -* xN[j]: -* -* d[j] = cN[j] - N'[j] * pi, -* -* where cN[j] is the objective coefficient at variable xN[j], N[j] is -* a column of the augmented constraint matrix (I|-A) corresponding to -* xN[j], pi is the vector of simplex multipliers. */ - -static double eval_cost(struct csa *csa, double pi[], int j) -{ int m = csa->m; -#ifdef GLP_DEBUG - int n = csa->n; -#endif - double *coef = csa->coef; - int *head = csa->head; - int k; - double dj; -#ifdef GLP_DEBUG - xassert(1 <= j && j <= n); -#endif - k = head[m+j]; /* x[k] = xN[j] */ -#ifdef GLP_DEBUG - xassert(1 <= k && k <= m+n); -#endif - dj = coef[k]; - if (k <= m) - { /* N[j] is k-th column of submatrix I */ - dj -= pi[k]; - } - else - { /* N[j] is (k-m)-th column of submatrix (-A) */ - int *A_ptr = csa->A_ptr; - int *A_ind = csa->A_ind; - double *A_val = csa->A_val; - int beg, end, ptr; - beg = A_ptr[k-m]; - end = A_ptr[k-m+1]; - for (ptr = beg; ptr < end; ptr++) - dj += A_val[ptr] * pi[A_ind[ptr]]; - } - return dj; -} - -/*********************************************************************** -* eval_bbar - compute and store primal values of basic variables -* -* This routine computes primal values of all basic variables and then -* stores them in the solution array. */ - -static void eval_bbar(struct csa *csa) -{ eval_beta(csa, csa->bbar); - return; -} - -/*********************************************************************** -* eval_cbar - compute and store reduced costs of non-basic variables -* -* This routine computes reduced costs of all non-basic variables and -* then stores them in the solution array. */ - -static void eval_cbar(struct csa *csa) -{ -#ifdef GLP_DEBUG - int m = csa->m; -#endif - int n = csa->n; -#ifdef GLP_DEBUG - int *head = csa->head; -#endif - double *cbar = csa->cbar; - double *pi = csa->work3; - int j; -#ifdef GLP_DEBUG - int k; -#endif - /* compute simplex multipliers */ - eval_pi(csa, pi); - /* compute and store reduced costs */ - for (j = 1; j <= n; j++) - { -#ifdef GLP_DEBUG - k = head[m+j]; /* x[k] = xN[j] */ - xassert(1 <= k && k <= m+n); -#endif - cbar[j] = eval_cost(csa, pi, j); - } - return; -} - -/*********************************************************************** -* reset_refsp - reset the reference space -* -* This routine resets (redefines) the reference space used in the -* projected steepest edge pricing algorithm. */ - -static void reset_refsp(struct csa *csa) -{ int m = csa->m; - int n = csa->n; - int *head = csa->head; - char *refsp = csa->refsp; - double *gamma = csa->gamma; - int j, k; - xassert(csa->refct == 0); - csa->refct = 1000; - memset(&refsp[1], 0, (m+n) * sizeof(char)); - for (j = 1; j <= n; j++) - { k = head[m+j]; /* x[k] = xN[j] */ - refsp[k] = 1; - gamma[j] = 1.0; - } - return; -} - -/*********************************************************************** -* eval_gamma - compute steepest edge coefficient -* -* This routine computes the steepest edge coefficient for non-basic -* variable xN[j] using its direct definition: -* -* gamma[j] = delta[j] + sum alfa[i,j]^2, -* i in R -* -* where delta[j] = 1, if xN[j] is in the current reference space, -* and 0 otherwise; R is a set of basic variables xB[i], which are in -* the current reference space; alfa[i,j] are elements of the current -* simplex table. -* -* NOTE: The routine is intended only for debugginig purposes. */ - -static double eval_gamma(struct csa *csa, int j) -{ int m = csa->m; -#ifdef GLP_DEBUG - int n = csa->n; -#endif - int *head = csa->head; - char *refsp = csa->refsp; - double *alfa = csa->work3; - double *h = csa->work3; - int i, k; - double gamma; -#ifdef GLP_DEBUG - xassert(1 <= j && j <= n); -#endif - k = head[m+j]; /* x[k] = xN[j] */ -#ifdef GLP_DEBUG - xassert(1 <= k && k <= m+n); -#endif - /* construct the right-hand side vector h = - N[j] */ - for (i = 1; i <= m; i++) - h[i] = 0.0; - if (k <= m) - { /* N[j] is k-th column of submatrix I */ - h[k] = -1.0; - } - else - { /* N[j] is (k-m)-th column of submatrix (-A) */ - int *A_ptr = csa->A_ptr; - int *A_ind = csa->A_ind; - double *A_val = csa->A_val; - int beg, end, ptr; - beg = A_ptr[k-m]; - end = A_ptr[k-m+1]; - for (ptr = beg; ptr < end; ptr++) - h[A_ind[ptr]] = A_val[ptr]; - } - /* solve system B * alfa = h */ - xassert(csa->valid); - bfd_ftran(csa->bfd, alfa); - /* compute gamma */ - gamma = (refsp[k] ? 1.0 : 0.0); - for (i = 1; i <= m; i++) - { k = head[i]; -#ifdef GLP_DEBUG - xassert(1 <= k && k <= m+n); -#endif - if (refsp[k]) gamma += alfa[i] * alfa[i]; - } - return gamma; -} - -/*********************************************************************** -* chuzc - choose non-basic variable (column of the simplex table) -* -* This routine chooses non-basic variable xN[q], which has largest -* weighted reduced cost: -* -* |d[q]| / sqrt(gamma[q]) = max |d[j]| / sqrt(gamma[j]), -* j in J -* -* where J is a subset of eligible non-basic variables xN[j], d[j] is -* reduced cost of xN[j], gamma[j] is the steepest edge coefficient. -* -* The working objective function is always minimized, so the sign of -* d[q] determines direction, in which xN[q] has to change: -* -* if d[q] < 0, xN[q] has to increase; -* -* if d[q] > 0, xN[q] has to decrease. -* -* If |d[j]| <= tol_dj, where tol_dj is a specified tolerance, xN[j] -* is not included in J and therefore ignored. (It is assumed that the -* working objective row is appropriately scaled, i.e. max|c[k]| = 1.) -* -* If J is empty and no variable has been chosen, q is set to 0. */ - -static void chuzc(struct csa *csa, double tol_dj) -{ int n = csa->n; - char *stat = csa->stat; - double *cbar = csa->cbar; - double *gamma = csa->gamma; - int j, q; - double dj, best, temp; - /* nothing is chosen so far */ - q = 0, best = 0.0; - /* look through the list of non-basic variables */ - for (j = 1; j <= n; j++) - { dj = cbar[j]; - switch (stat[j]) - { case GLP_NL: - /* xN[j] can increase */ - if (dj >= - tol_dj) continue; - break; - case GLP_NU: - /* xN[j] can decrease */ - if (dj <= + tol_dj) continue; - break; - case GLP_NF: - /* xN[j] can change in any direction */ - if (- tol_dj <= dj && dj <= + tol_dj) continue; - break; - case GLP_NS: - /* xN[j] cannot change at all */ - continue; - default: - xassert(stat != stat); - } - /* xN[j] is eligible non-basic variable; choose one which has - largest weighted reduced cost */ -#ifdef GLP_DEBUG - xassert(gamma[j] > 0.0); -#endif - temp = (dj * dj) / gamma[j]; - if (best < temp) - q = j, best = temp; - } - /* store the index of non-basic variable xN[q] chosen */ - csa->q = q; - return; -} - -/*********************************************************************** -* eval_tcol - compute pivot column of the simplex table -* -* This routine computes the pivot column of the simplex table, which -* corresponds to non-basic variable xN[q] chosen. -* -* The pivot column is the following vector: -* -* tcol = T * e[q] = - inv(B) * N * e[q] = - inv(B) * N[q], -* -* where B is the current basis matrix, N[q] is a column of the matrix -* (I|-A) corresponding to variable xN[q]. */ - -static void eval_tcol(struct csa *csa) -{ int m = csa->m; -#ifdef GLP_DEBUG - int n = csa->n; -#endif - int *head = csa->head; - int q = csa->q; - int *tcol_ind = csa->tcol_ind; - double *tcol_vec = csa->tcol_vec; - double *h = csa->tcol_vec; - int i, k, nnz; -#ifdef GLP_DEBUG - xassert(1 <= q && q <= n); -#endif - k = head[m+q]; /* x[k] = xN[q] */ -#ifdef GLP_DEBUG - xassert(1 <= k && k <= m+n); -#endif - /* construct the right-hand side vector h = - N[q] */ - for (i = 1; i <= m; i++) - h[i] = 0.0; - if (k <= m) - { /* N[q] is k-th column of submatrix I */ - h[k] = -1.0; - } - else - { /* N[q] is (k-m)-th column of submatrix (-A) */ - int *A_ptr = csa->A_ptr; - int *A_ind = csa->A_ind; - double *A_val = csa->A_val; - int beg, end, ptr; - beg = A_ptr[k-m]; - end = A_ptr[k-m+1]; - for (ptr = beg; ptr < end; ptr++) - h[A_ind[ptr]] = A_val[ptr]; - } - /* solve system B * tcol = h */ - xassert(csa->valid); - bfd_ftran(csa->bfd, tcol_vec); - /* construct sparse pattern of the pivot column */ - nnz = 0; - for (i = 1; i <= m; i++) - { if (tcol_vec[i] != 0.0) - tcol_ind[++nnz] = i; - } - csa->tcol_nnz = nnz; - return; -} - -/*********************************************************************** -* refine_tcol - refine pivot column of the simplex table -* -* This routine refines the pivot column of the simplex table assuming -* that it was previously computed by the routine eval_tcol. */ - -static void refine_tcol(struct csa *csa) -{ int m = csa->m; -#ifdef GLP_DEBUG - int n = csa->n; -#endif - int *head = csa->head; - int q = csa->q; - int *tcol_ind = csa->tcol_ind; - double *tcol_vec = csa->tcol_vec; - double *h = csa->work3; - int i, k, nnz; -#ifdef GLP_DEBUG - xassert(1 <= q && q <= n); -#endif - k = head[m+q]; /* x[k] = xN[q] */ -#ifdef GLP_DEBUG - xassert(1 <= k && k <= m+n); -#endif - /* construct the right-hand side vector h = - N[q] */ - for (i = 1; i <= m; i++) - h[i] = 0.0; - if (k <= m) - { /* N[q] is k-th column of submatrix I */ - h[k] = -1.0; - } - else - { /* N[q] is (k-m)-th column of submatrix (-A) */ - int *A_ptr = csa->A_ptr; - int *A_ind = csa->A_ind; - double *A_val = csa->A_val; - int beg, end, ptr; - beg = A_ptr[k-m]; - end = A_ptr[k-m+1]; - for (ptr = beg; ptr < end; ptr++) - h[A_ind[ptr]] = A_val[ptr]; - } - /* refine solution of B * tcol = h */ - refine_ftran(csa, h, tcol_vec); - /* construct sparse pattern of the pivot column */ - nnz = 0; - for (i = 1; i <= m; i++) - { if (tcol_vec[i] != 0.0) - tcol_ind[++nnz] = i; - } - csa->tcol_nnz = nnz; - return; -} - -/*********************************************************************** -* sort_tcol - sort pivot column of the simplex table -* -* This routine reorders the list of non-zero elements of the pivot -* column to put significant elements, whose magnitude is not less than -* a specified tolerance, in front of the list, and stores the number -* of significant elements in tcol_num. */ - -static void sort_tcol(struct csa *csa, double tol_piv) -{ -#ifdef GLP_DEBUG - int m = csa->m; -#endif - int nnz = csa->tcol_nnz; - int *tcol_ind = csa->tcol_ind; - double *tcol_vec = csa->tcol_vec; - int i, num, pos; - double big, eps, temp; - /* compute infinity (maximum) norm of the column */ - big = 0.0; - for (pos = 1; pos <= nnz; pos++) - { -#ifdef GLP_DEBUG - i = tcol_ind[pos]; - xassert(1 <= i && i <= m); -#endif - temp = fabs(tcol_vec[tcol_ind[pos]]); - if (big < temp) big = temp; - } - csa->tcol_max = big; - /* determine absolute pivot tolerance */ - eps = tol_piv * (1.0 + 0.01 * big); - /* move significant column components to front of the list */ - for (num = 0; num < nnz; ) - { i = tcol_ind[nnz]; - if (fabs(tcol_vec[i]) < eps) - nnz--; - else - { num++; - tcol_ind[nnz] = tcol_ind[num]; - tcol_ind[num] = i; - } - } - csa->tcol_num = num; - return; -} - -/*********************************************************************** -* chuzr - choose basic variable (row of the simplex table) -* -* This routine chooses basic variable xB[p], which reaches its bound -* first on changing non-basic variable xN[q] in valid direction. -* -* The parameter rtol is a relative tolerance used to relax bounds of -* basic variables. If rtol = 0, the routine implements the standard -* ratio test. Otherwise, if rtol > 0, the routine implements Harris' -* two-pass ratio test. In the latter case rtol should be about three -* times less than a tolerance used to check primal feasibility. */ - -static void chuzr(struct csa *csa, double rtol) -{ int m = csa->m; -#ifdef GLP_DEBUG - int n = csa->n; -#endif - char *type = csa->type; - double *lb = csa->lb; - double *ub = csa->ub; - double *coef = csa->coef; - int *head = csa->head; - int phase = csa->phase; - double *bbar = csa->bbar; - double *cbar = csa->cbar; - int q = csa->q; - int *tcol_ind = csa->tcol_ind; - double *tcol_vec = csa->tcol_vec; - int tcol_num = csa->tcol_num; - int i, i_stat, k, p, p_stat, pos; - double alfa, big, delta, s, t, teta, tmax; -#ifdef GLP_DEBUG - xassert(1 <= q && q <= n); -#endif - /* s := - sign(d[q]), where d[q] is reduced cost of xN[q] */ -#ifdef GLP_DEBUG - xassert(cbar[q] != 0.0); -#endif - s = (cbar[q] > 0.0 ? -1.0 : +1.0); - /*** FIRST PASS ***/ - k = head[m+q]; /* x[k] = xN[q] */ -#ifdef GLP_DEBUG - xassert(1 <= k && k <= m+n); -#endif - if (type[k] == GLP_DB) - { /* xN[q] has both lower and upper bounds */ - p = -1, p_stat = 0, teta = ub[k] - lb[k], big = 1.0; - } - else - { /* xN[q] has no opposite bound */ - p = 0, p_stat = 0, teta = DBL_MAX, big = 0.0; - } - /* walk through significant elements of the pivot column */ - for (pos = 1; pos <= tcol_num; pos++) - { i = tcol_ind[pos]; -#ifdef GLP_DEBUG - xassert(1 <= i && i <= m); -#endif - k = head[i]; /* x[k] = xB[i] */ -#ifdef GLP_DEBUG - xassert(1 <= k && k <= m+n); -#endif - alfa = s * tcol_vec[i]; -#ifdef GLP_DEBUG - xassert(alfa != 0.0); -#endif - /* xB[i] = ... + alfa * xN[q] + ..., and due to s we need to - consider the only case when xN[q] is increasing */ - if (alfa > 0.0) - { /* xB[i] is increasing */ - if (phase == 1 && coef[k] < 0.0) - { /* xB[i] violates its lower bound, which plays the role - of an upper bound on phase I */ - delta = rtol * (1.0 + kappa * fabs(lb[k])); - t = ((lb[k] + delta) - bbar[i]) / alfa; - i_stat = GLP_NL; - } - else if (phase == 1 && coef[k] > 0.0) - { /* xB[i] violates its upper bound, which plays the role - of an lower bound on phase I */ - continue; - } - else if (type[k] == GLP_UP || type[k] == GLP_DB || - type[k] == GLP_FX) - { /* xB[i] is within its bounds and has an upper bound */ - delta = rtol * (1.0 + kappa * fabs(ub[k])); - t = ((ub[k] + delta) - bbar[i]) / alfa; - i_stat = GLP_NU; - } - else - { /* xB[i] is within its bounds and has no upper bound */ - continue; - } - } - else - { /* xB[i] is decreasing */ - if (phase == 1 && coef[k] > 0.0) - { /* xB[i] violates its upper bound, which plays the role - of an lower bound on phase I */ - delta = rtol * (1.0 + kappa * fabs(ub[k])); - t = ((ub[k] - delta) - bbar[i]) / alfa; - i_stat = GLP_NU; - } - else if (phase == 1 && coef[k] < 0.0) - { /* xB[i] violates its lower bound, which plays the role - of an upper bound on phase I */ - continue; - } - else if (type[k] == GLP_LO || type[k] == GLP_DB || - type[k] == GLP_FX) - { /* xB[i] is within its bounds and has an lower bound */ - delta = rtol * (1.0 + kappa * fabs(lb[k])); - t = ((lb[k] - delta) - bbar[i]) / alfa; - i_stat = GLP_NL; - } - else - { /* xB[i] is within its bounds and has no lower bound */ - continue; - } - } - /* t is a change of xN[q], on which xB[i] reaches its bound - (possibly relaxed); since the basic solution is assumed to - be primal feasible (or pseudo feasible on phase I), t has - to be non-negative by definition; however, it may happen - that xB[i] slightly (i.e. within a tolerance) violates its - bound, that leads to negative t; in the latter case, if - xB[i] is chosen, negative t means that xN[q] changes in - wrong direction; if pivot alfa[i,q] is close to zero, even - small bound violation of xB[i] may lead to a large change - of xN[q] in wrong direction; let, for example, xB[i] >= 0 - and in the current basis its value be -5e-9; let also xN[q] - be on its zero bound and should increase; from the ratio - test rule it follows that the pivot alfa[i,q] < 0; however, - if alfa[i,q] is, say, -1e-9, the change of xN[q] in wrong - direction is 5e-9 / (-1e-9) = -5, and using it for updating - values of other basic variables will give absolutely wrong - results; therefore, if t is negative, we should replace it - by exact zero assuming that xB[i] is exactly on its bound, - and the violation appears due to round-off errors */ - if (t < 0.0) t = 0.0; - /* apply minimal ratio test */ - if (teta > t || teta == t && big < fabs(alfa)) - p = i, p_stat = i_stat, teta = t, big = fabs(alfa); - } - /* the second pass is skipped in the following cases: */ - /* if the standard ratio test is used */ - if (rtol == 0.0) goto done; - /* if xN[q] reaches its opposite bound or if no basic variable - has been chosen on the first pass */ - if (p <= 0) goto done; - /* if xB[p] is a blocking variable, i.e. if it prevents xN[q] - from any change */ - if (teta == 0.0) goto done; - /*** SECOND PASS ***/ - /* here tmax is a maximal change of xN[q], on which the solution - remains primal feasible (or pseudo feasible on phase I) within - a tolerance */ -#if 0 - tmax = (1.0 + 10.0 * DBL_EPSILON) * teta; -#else - tmax = teta; -#endif - /* nothing is chosen so far */ - p = 0, p_stat = 0, teta = DBL_MAX, big = 0.0; - /* walk through significant elements of the pivot column */ - for (pos = 1; pos <= tcol_num; pos++) - { i = tcol_ind[pos]; -#ifdef GLP_DEBUG - xassert(1 <= i && i <= m); -#endif - k = head[i]; /* x[k] = xB[i] */ -#ifdef GLP_DEBUG - xassert(1 <= k && k <= m+n); -#endif - alfa = s * tcol_vec[i]; -#ifdef GLP_DEBUG - xassert(alfa != 0.0); -#endif - /* xB[i] = ... + alfa * xN[q] + ..., and due to s we need to - consider the only case when xN[q] is increasing */ - if (alfa > 0.0) - { /* xB[i] is increasing */ - if (phase == 1 && coef[k] < 0.0) - { /* xB[i] violates its lower bound, which plays the role - of an upper bound on phase I */ - t = (lb[k] - bbar[i]) / alfa; - i_stat = GLP_NL; - } - else if (phase == 1 && coef[k] > 0.0) - { /* xB[i] violates its upper bound, which plays the role - of an lower bound on phase I */ - continue; - } - else if (type[k] == GLP_UP || type[k] == GLP_DB || - type[k] == GLP_FX) - { /* xB[i] is within its bounds and has an upper bound */ - t = (ub[k] - bbar[i]) / alfa; - i_stat = GLP_NU; - } - else - { /* xB[i] is within its bounds and has no upper bound */ - continue; - } - } - else - { /* xB[i] is decreasing */ - if (phase == 1 && coef[k] > 0.0) - { /* xB[i] violates its upper bound, which plays the role - of an lower bound on phase I */ - t = (ub[k] - bbar[i]) / alfa; - i_stat = GLP_NU; - } - else if (phase == 1 && coef[k] < 0.0) - { /* xB[i] violates its lower bound, which plays the role - of an upper bound on phase I */ - continue; - } - else if (type[k] == GLP_LO || type[k] == GLP_DB || - type[k] == GLP_FX) - { /* xB[i] is within its bounds and has an lower bound */ - t = (lb[k] - bbar[i]) / alfa; - i_stat = GLP_NL; - } - else - { /* xB[i] is within its bounds and has no lower bound */ - continue; - } - } - /* (see comments for the first pass) */ - if (t < 0.0) t = 0.0; - /* t is a change of xN[q], on which xB[i] reaches its bound; - if t <= tmax, all basic variables can violate their bounds - only within relaxation tolerance delta; we can use this - freedom and choose basic variable having largest influence - coefficient to avoid possible numeric instability */ - if (t <= tmax && big < fabs(alfa)) - p = i, p_stat = i_stat, teta = t, big = fabs(alfa); - } - /* something must be chosen on the second pass */ - xassert(p != 0); -done: /* store the index and status of basic variable xB[p] chosen */ - csa->p = p; - if (p > 0 && type[head[p]] == GLP_FX) - csa->p_stat = GLP_NS; - else - csa->p_stat = p_stat; - /* store corresponding change of non-basic variable xN[q] */ -#ifdef GLP_DEBUG - xassert(teta >= 0.0); -#endif - csa->teta = s * teta; - return; -} - -/*********************************************************************** -* eval_rho - compute pivot row of the inverse -* -* This routine computes the pivot (p-th) row of the inverse inv(B), -* which corresponds to basic variable xB[p] chosen: -* -* rho = inv(B') * e[p], -* -* where B' is a matrix transposed to the current basis matrix, e[p] -* is unity vector. */ - -static void eval_rho(struct csa *csa, double rho[]) -{ int m = csa->m; - int p = csa->p; - double *e = rho; - int i; -#ifdef GLP_DEBUG - xassert(1 <= p && p <= m); -#endif - /* construct the right-hand side vector e[p] */ - for (i = 1; i <= m; i++) - e[i] = 0.0; - e[p] = 1.0; - /* solve system B'* rho = e[p] */ - xassert(csa->valid); - bfd_btran(csa->bfd, rho); - return; -} - -/*********************************************************************** -* refine_rho - refine pivot row of the inverse -* -* This routine refines the pivot row of the inverse inv(B) assuming -* that it was previously computed by the routine eval_rho. */ - -static void refine_rho(struct csa *csa, double rho[]) -{ int m = csa->m; - int p = csa->p; - double *e = csa->work3; - int i; -#ifdef GLP_DEBUG - xassert(1 <= p && p <= m); -#endif - /* construct the right-hand side vector e[p] */ - for (i = 1; i <= m; i++) - e[i] = 0.0; - e[p] = 1.0; - /* refine solution of B'* rho = e[p] */ - refine_btran(csa, e, rho); - return; -} - -/*********************************************************************** -* eval_trow - compute pivot row of the simplex table -* -* This routine computes the pivot row of the simplex table, which -* corresponds to basic variable xB[p] chosen. -* -* The pivot row is the following vector: -* -* trow = T'* e[p] = - N'* inv(B') * e[p] = - N' * rho, -* -* where rho is the pivot row of the inverse inv(B) previously computed -* by the routine eval_rho. -* -* Note that elements of the pivot row corresponding to fixed non-basic -* variables are not computed. */ - -static void eval_trow(struct csa *csa, double rho[]) -{ int m = csa->m; - int n = csa->n; -#ifdef GLP_DEBUG - char *stat = csa->stat; -#endif - int *N_ptr = csa->N_ptr; - int *N_len = csa->N_len; - int *N_ind = csa->N_ind; - double *N_val = csa->N_val; - int *trow_ind = csa->trow_ind; - double *trow_vec = csa->trow_vec; - int i, j, beg, end, ptr, nnz; - double temp; - /* clear the pivot row */ - for (j = 1; j <= n; j++) - trow_vec[j] = 0.0; - /* compute the pivot row as a linear combination of rows of the - matrix N: trow = - rho[1] * N'[1] - ... - rho[m] * N'[m] */ - for (i = 1; i <= m; i++) - { temp = rho[i]; - if (temp == 0.0) continue; - /* trow := trow - rho[i] * N'[i] */ - beg = N_ptr[i]; - end = beg + N_len[i]; - for (ptr = beg; ptr < end; ptr++) - { -#ifdef GLP_DEBUG - j = N_ind[ptr]; - xassert(1 <= j && j <= n); - xassert(stat[j] != GLP_NS); -#endif - trow_vec[N_ind[ptr]] -= temp * N_val[ptr]; - } - } - /* construct sparse pattern of the pivot row */ - nnz = 0; - for (j = 1; j <= n; j++) - { if (trow_vec[j] != 0.0) - trow_ind[++nnz] = j; - } - csa->trow_nnz = nnz; - return; -} - -/*********************************************************************** -* update_bbar - update values of basic variables -* -* This routine updates values of all basic variables for the adjacent -* basis. */ - -static void update_bbar(struct csa *csa) -{ -#ifdef GLP_DEBUG - int m = csa->m; - int n = csa->n; -#endif - double *bbar = csa->bbar; - int q = csa->q; - int tcol_nnz = csa->tcol_nnz; - int *tcol_ind = csa->tcol_ind; - double *tcol_vec = csa->tcol_vec; - int p = csa->p; - double teta = csa->teta; - int i, pos; -#ifdef GLP_DEBUG - xassert(1 <= q && q <= n); - xassert(p < 0 || 1 <= p && p <= m); -#endif - /* if xN[q] leaves the basis, compute its value in the adjacent - basis, where it will replace xB[p] */ - if (p > 0) - bbar[p] = get_xN(csa, q) + teta; - /* update values of other basic variables (except xB[p], because - it will be replaced by xN[q]) */ - if (teta == 0.0) goto done; - for (pos = 1; pos <= tcol_nnz; pos++) - { i = tcol_ind[pos]; - /* skip xB[p] */ - if (i == p) continue; - /* (change of xB[i]) = alfa[i,q] * (change of xN[q]) */ - bbar[i] += tcol_vec[i] * teta; - } -done: return; -} - -/*********************************************************************** -* reeval_cost - recompute reduced cost of non-basic variable xN[q] -* -* This routine recomputes reduced cost of non-basic variable xN[q] for -* the current basis more accurately using its direct definition: -* -* d[q] = cN[q] - N'[q] * pi = -* -* = cN[q] - N'[q] * (inv(B') * cB) = -* -* = cN[q] - (cB' * inv(B) * N[q]) = -* -* = cN[q] + cB' * (pivot column). -* -* It is assumed that the pivot column of the simplex table is already -* computed. */ - -static double reeval_cost(struct csa *csa) -{ int m = csa->m; -#ifdef GLP_DEBUG - int n = csa->n; -#endif - double *coef = csa->coef; - int *head = csa->head; - int q = csa->q; - int tcol_nnz = csa->tcol_nnz; - int *tcol_ind = csa->tcol_ind; - double *tcol_vec = csa->tcol_vec; - int i, pos; - double dq; -#ifdef GLP_DEBUG - xassert(1 <= q && q <= n); -#endif - dq = coef[head[m+q]]; - for (pos = 1; pos <= tcol_nnz; pos++) - { i = tcol_ind[pos]; -#ifdef GLP_DEBUG - xassert(1 <= i && i <= m); -#endif - dq += coef[head[i]] * tcol_vec[i]; - } - return dq; -} - -/*********************************************************************** -* update_cbar - update reduced costs of non-basic variables -* -* This routine updates reduced costs of all (except fixed) non-basic -* variables for the adjacent basis. */ - -static void update_cbar(struct csa *csa) -{ -#ifdef GLP_DEBUG - int n = csa->n; -#endif - double *cbar = csa->cbar; - int q = csa->q; - int trow_nnz = csa->trow_nnz; - int *trow_ind = csa->trow_ind; - double *trow_vec = csa->trow_vec; - int j, pos; - double new_dq; -#ifdef GLP_DEBUG - xassert(1 <= q && q <= n); -#endif - /* compute reduced cost of xB[p] in the adjacent basis, where it - will replace xN[q] */ -#ifdef GLP_DEBUG - xassert(trow_vec[q] != 0.0); -#endif - new_dq = (cbar[q] /= trow_vec[q]); - /* update reduced costs of other non-basic variables (except - xN[q], because it will be replaced by xB[p]) */ - for (pos = 1; pos <= trow_nnz; pos++) - { j = trow_ind[pos]; - /* skip xN[q] */ - if (j == q) continue; - cbar[j] -= trow_vec[j] * new_dq; - } - return; -} - -/*********************************************************************** -* update_gamma - update steepest edge coefficients -* -* This routine updates steepest-edge coefficients for the adjacent -* basis. */ - -static void update_gamma(struct csa *csa) -{ int m = csa->m; -#ifdef GLP_DEBUG - int n = csa->n; -#endif - char *type = csa->type; - int *A_ptr = csa->A_ptr; - int *A_ind = csa->A_ind; - double *A_val = csa->A_val; - int *head = csa->head; - char *refsp = csa->refsp; - double *gamma = csa->gamma; - int q = csa->q; - int tcol_nnz = csa->tcol_nnz; - int *tcol_ind = csa->tcol_ind; - double *tcol_vec = csa->tcol_vec; - int p = csa->p; - int trow_nnz = csa->trow_nnz; - int *trow_ind = csa->trow_ind; - double *trow_vec = csa->trow_vec; - double *u = csa->work3; - int i, j, k, pos, beg, end, ptr; - double gamma_q, delta_q, pivot, s, t, t1, t2; -#ifdef GLP_DEBUG - xassert(1 <= p && p <= m); - xassert(1 <= q && q <= n); -#endif - /* the basis changes, so decrease the count */ - xassert(csa->refct > 0); - csa->refct--; - /* recompute gamma[q] for the current basis more accurately and - compute auxiliary vector u */ - gamma_q = delta_q = (refsp[head[m+q]] ? 1.0 : 0.0); - for (i = 1; i <= m; i++) u[i] = 0.0; - for (pos = 1; pos <= tcol_nnz; pos++) - { i = tcol_ind[pos]; - if (refsp[head[i]]) - { u[i] = t = tcol_vec[i]; - gamma_q += t * t; - } - else - u[i] = 0.0; - } - xassert(csa->valid); - bfd_btran(csa->bfd, u); - /* update gamma[k] for other non-basic variables (except fixed - variables and xN[q], because it will be replaced by xB[p]) */ - pivot = trow_vec[q]; -#ifdef GLP_DEBUG - xassert(pivot != 0.0); -#endif - for (pos = 1; pos <= trow_nnz; pos++) - { j = trow_ind[pos]; - /* skip xN[q] */ - if (j == q) continue; - /* compute t */ - t = trow_vec[j] / pivot; - /* compute inner product s = N'[j] * u */ - k = head[m+j]; /* x[k] = xN[j] */ - if (k <= m) - s = u[k]; - else - { s = 0.0; - beg = A_ptr[k-m]; - end = A_ptr[k-m+1]; - for (ptr = beg; ptr < end; ptr++) - s -= A_val[ptr] * u[A_ind[ptr]]; - } - /* compute gamma[k] for the adjacent basis */ - t1 = gamma[j] + t * t * gamma_q + 2.0 * t * s; - t2 = (refsp[k] ? 1.0 : 0.0) + delta_q * t * t; - gamma[j] = (t1 >= t2 ? t1 : t2); - if (gamma[j] < DBL_EPSILON) gamma[j] = DBL_EPSILON; - } - /* compute gamma[q] for the adjacent basis */ - if (type[head[p]] == GLP_FX) - gamma[q] = 1.0; - else - { gamma[q] = gamma_q / (pivot * pivot); - if (gamma[q] < DBL_EPSILON) gamma[q] = DBL_EPSILON; - } - return; -} - -/*********************************************************************** -* err_in_bbar - compute maximal relative error in primal solution -* -* This routine returns maximal relative error: -* -* max |beta[i] - bbar[i]| / (1 + |beta[i]|), -* -* where beta and bbar are, respectively, directly computed and the -* current (updated) values of basic variables. -* -* NOTE: The routine is intended only for debugginig purposes. */ - -static double err_in_bbar(struct csa *csa) -{ int m = csa->m; - double *bbar = csa->bbar; - int i; - double e, emax, *beta; - beta = xcalloc(1+m, sizeof(double)); - eval_beta(csa, beta); - emax = 0.0; - for (i = 1; i <= m; i++) - { e = fabs(beta[i] - bbar[i]) / (1.0 + fabs(beta[i])); - if (emax < e) emax = e; - } - xfree(beta); - return emax; -} - -/*********************************************************************** -* err_in_cbar - compute maximal relative error in dual solution -* -* This routine returns maximal relative error: -* -* max |cost[j] - cbar[j]| / (1 + |cost[j]|), -* -* where cost and cbar are, respectively, directly computed and the -* current (updated) reduced costs of non-basic non-fixed variables. -* -* NOTE: The routine is intended only for debugginig purposes. */ - -static double err_in_cbar(struct csa *csa) -{ int m = csa->m; - int n = csa->n; - char *stat = csa->stat; - double *cbar = csa->cbar; - int j; - double e, emax, cost, *pi; - pi = xcalloc(1+m, sizeof(double)); - eval_pi(csa, pi); - emax = 0.0; - for (j = 1; j <= n; j++) - { if (stat[j] == GLP_NS) continue; - cost = eval_cost(csa, pi, j); - e = fabs(cost - cbar[j]) / (1.0 + fabs(cost)); - if (emax < e) emax = e; - } - xfree(pi); - return emax; -} - -/*********************************************************************** -* err_in_gamma - compute maximal relative error in steepest edge cff. -* -* This routine returns maximal relative error: -* -* max |gamma'[j] - gamma[j]| / (1 + |gamma'[j]), -* -* where gamma'[j] and gamma[j] are, respectively, directly computed -* and the current (updated) steepest edge coefficients for non-basic -* non-fixed variable x[j]. -* -* NOTE: The routine is intended only for debugginig purposes. */ - -static double err_in_gamma(struct csa *csa) -{ int n = csa->n; - char *stat = csa->stat; - double *gamma = csa->gamma; - int j; - double e, emax, temp; - emax = 0.0; - for (j = 1; j <= n; j++) - { if (stat[j] == GLP_NS) - { xassert(gamma[j] == 1.0); - continue; - } - temp = eval_gamma(csa, j); - e = fabs(temp - gamma[j]) / (1.0 + fabs(temp)); - if (emax < e) emax = e; - } - return emax; -} - -/*********************************************************************** -* change_basis - change basis header -* -* This routine changes the basis header to make it corresponding to -* the adjacent basis. */ - -static void change_basis(struct csa *csa) -{ int m = csa->m; -#ifdef GLP_DEBUG - int n = csa->n; - char *type = csa->type; -#endif - int *head = csa->head; - char *stat = csa->stat; - int q = csa->q; - int p = csa->p; - int p_stat = csa->p_stat; - int k; -#ifdef GLP_DEBUG - xassert(1 <= q && q <= n); -#endif - if (p < 0) - { /* xN[q] goes to its opposite bound */ -#ifdef GLP_DEBUG - k = head[m+q]; /* x[k] = xN[q] */ - xassert(1 <= k && k <= m+n); - xassert(type[k] == GLP_DB); -#endif - switch (stat[q]) - { case GLP_NL: - /* xN[q] increases */ - stat[q] = GLP_NU; - break; - case GLP_NU: - /* xN[q] decreases */ - stat[q] = GLP_NL; - break; - default: - xassert(stat != stat); - } - } - else - { /* xB[p] leaves the basis, xN[q] enters the basis */ -#ifdef GLP_DEBUG - xassert(1 <= p && p <= m); - k = head[p]; /* x[k] = xB[p] */ - switch (p_stat) - { case GLP_NL: - /* xB[p] goes to its lower bound */ - xassert(type[k] == GLP_LO || type[k] == GLP_DB); - break; - case GLP_NU: - /* xB[p] goes to its upper bound */ - xassert(type[k] == GLP_UP || type[k] == GLP_DB); - break; - case GLP_NS: - /* xB[p] goes to its fixed value */ - xassert(type[k] == GLP_NS); - break; - default: - xassert(p_stat != p_stat); - } -#endif - /* xB[p] <-> xN[q] */ - k = head[p], head[p] = head[m+q], head[m+q] = k; - stat[q] = (char)p_stat; - } - return; -} - -/*********************************************************************** -* set_aux_obj - construct auxiliary objective function -* -* The auxiliary objective function is a separable piecewise linear -* convex function, which is the sum of primal infeasibilities: -* -* z = t[1] + ... + t[m+n] -> minimize, -* -* where: -* -* / lb[k] - x[k], if x[k] < lb[k] -* | -* t[k] = < 0, if lb[k] <= x[k] <= ub[k] -* | -* \ x[k] - ub[k], if x[k] > ub[k] -* -* This routine computes objective coefficients for the current basis -* and returns the number of non-zero terms t[k]. */ - -static int set_aux_obj(struct csa *csa, double tol_bnd) -{ int m = csa->m; - int n = csa->n; - char *type = csa->type; - double *lb = csa->lb; - double *ub = csa->ub; - double *coef = csa->coef; - int *head = csa->head; - double *bbar = csa->bbar; - int i, k, cnt = 0; - double eps; - /* use a bit more restrictive tolerance */ - tol_bnd *= 0.90; - /* clear all objective coefficients */ - for (k = 1; k <= m+n; k++) - coef[k] = 0.0; - /* walk through the list of basic variables */ - for (i = 1; i <= m; i++) - { k = head[i]; /* x[k] = xB[i] */ - if (type[k] == GLP_LO || type[k] == GLP_DB || - type[k] == GLP_FX) - { /* x[k] has lower bound */ - eps = tol_bnd * (1.0 + kappa * fabs(lb[k])); - if (bbar[i] < lb[k] - eps) - { /* and violates it */ - coef[k] = -1.0; - cnt++; - } - } - if (type[k] == GLP_UP || type[k] == GLP_DB || - type[k] == GLP_FX) - { /* x[k] has upper bound */ - eps = tol_bnd * (1.0 + kappa * fabs(ub[k])); - if (bbar[i] > ub[k] + eps) - { /* and violates it */ - coef[k] = +1.0; - cnt++; - } - } - } - return cnt; -} - -/*********************************************************************** -* set_orig_obj - restore original objective function -* -* This routine assigns scaled original objective coefficients to the -* working objective function. */ - -static void set_orig_obj(struct csa *csa) -{ int m = csa->m; - int n = csa->n; - double *coef = csa->coef; - double *obj = csa->obj; - double zeta = csa->zeta; - int i, j; - for (i = 1; i <= m; i++) - coef[i] = 0.0; - for (j = 1; j <= n; j++) - coef[m+j] = zeta * obj[j]; - return; -} - -/*********************************************************************** -* check_stab - check numerical stability of basic solution -* -* If the current basic solution is primal feasible (or pseudo feasible -* on phase I) within a tolerance, this routine returns zero, otherwise -* it returns non-zero. */ - -static int check_stab(struct csa *csa, double tol_bnd) -{ int m = csa->m; -#ifdef GLP_DEBUG - int n = csa->n; -#endif - char *type = csa->type; - double *lb = csa->lb; - double *ub = csa->ub; - double *coef = csa->coef; - int *head = csa->head; - int phase = csa->phase; - double *bbar = csa->bbar; - int i, k; - double eps; - /* walk through the list of basic variables */ - for (i = 1; i <= m; i++) - { k = head[i]; /* x[k] = xB[i] */ -#ifdef GLP_DEBUG - xassert(1 <= k && k <= m+n); -#endif - if (phase == 1 && coef[k] < 0.0) - { /* x[k] must not be greater than its lower bound */ -#ifdef GLP_DEBUG - xassert(type[k] == GLP_LO || type[k] == GLP_DB || - type[k] == GLP_FX); -#endif - eps = tol_bnd * (1.0 + kappa * fabs(lb[k])); - if (bbar[i] > lb[k] + eps) return 1; - } - else if (phase == 1 && coef[k] > 0.0) - { /* x[k] must not be less than its upper bound */ -#ifdef GLP_DEBUG - xassert(type[k] == GLP_UP || type[k] == GLP_DB || - type[k] == GLP_FX); -#endif - eps = tol_bnd * (1.0 + kappa * fabs(ub[k])); - if (bbar[i] < ub[k] - eps) return 1; - } - else - { /* either phase = 1 and coef[k] = 0, or phase = 2 */ - if (type[k] == GLP_LO || type[k] == GLP_DB || - type[k] == GLP_FX) - { /* x[k] must not be less than its lower bound */ - eps = tol_bnd * (1.0 + kappa * fabs(lb[k])); - if (bbar[i] < lb[k] - eps) return 1; - } - if (type[k] == GLP_UP || type[k] == GLP_DB || - type[k] == GLP_FX) - { /* x[k] must not be greater then its upper bound */ - eps = tol_bnd * (1.0 + kappa * fabs(ub[k])); - if (bbar[i] > ub[k] + eps) return 1; - } - } - } - /* basic solution is primal feasible within a tolerance */ - return 0; -} - -/*********************************************************************** -* check_feas - check primal feasibility of basic solution -* -* If the current basic solution is primal feasible within a tolerance, -* this routine returns zero, otherwise it returns non-zero. */ - -static int check_feas(struct csa *csa, double tol_bnd) -{ int m = csa->m; -#ifdef GLP_DEBUG - int n = csa->n; - char *type = csa->type; -#endif - double *lb = csa->lb; - double *ub = csa->ub; - double *coef = csa->coef; - int *head = csa->head; - double *bbar = csa->bbar; - int i, k; - double eps; - xassert(csa->phase == 1); - /* walk through the list of basic variables */ - for (i = 1; i <= m; i++) - { k = head[i]; /* x[k] = xB[i] */ -#ifdef GLP_DEBUG - xassert(1 <= k && k <= m+n); -#endif - if (coef[k] < 0.0) - { /* check if x[k] still violates its lower bound */ -#ifdef GLP_DEBUG - xassert(type[k] == GLP_LO || type[k] == GLP_DB || - type[k] == GLP_FX); -#endif - eps = tol_bnd * (1.0 + kappa * fabs(lb[k])); - if (bbar[i] < lb[k] - eps) return 1; - } - else if (coef[k] > 0.0) - { /* check if x[k] still violates its upper bound */ -#ifdef GLP_DEBUG - xassert(type[k] == GLP_UP || type[k] == GLP_DB || - type[k] == GLP_FX); -#endif - eps = tol_bnd * (1.0 + kappa * fabs(ub[k])); - if (bbar[i] > ub[k] + eps) return 1; - } - } - /* basic solution is primal feasible within a tolerance */ - return 0; -} - -/*********************************************************************** -* eval_obj - compute original objective function -* -* This routine computes the current value of the original objective -* function. */ - -static double eval_obj(struct csa *csa) -{ int m = csa->m; - int n = csa->n; - double *obj = csa->obj; - int *head = csa->head; - double *bbar = csa->bbar; - int i, j, k; - double sum; - sum = obj[0]; - /* walk through the list of basic variables */ - for (i = 1; i <= m; i++) - { k = head[i]; /* x[k] = xB[i] */ -#ifdef GLP_DEBUG - xassert(1 <= k && k <= m+n); -#endif - if (k > m) - sum += obj[k-m] * bbar[i]; - } - /* walk through the list of non-basic variables */ - for (j = 1; j <= n; j++) - { k = head[m+j]; /* x[k] = xN[j] */ -#ifdef GLP_DEBUG - xassert(1 <= k && k <= m+n); -#endif - if (k > m) - sum += obj[k-m] * get_xN(csa, j); - } - return sum; -} - -/*********************************************************************** -* display - display the search progress -* -* This routine displays some information about the search progress -* that includes: -* -* the search phase; -* -* the number of simplex iterations performed by the solver; -* -* the original objective value; -* -* the sum of (scaled) primal infeasibilities; -* -* the number of basic fixed variables. */ - -static void display(struct csa *csa, const glp_smcp *parm, int spec) -{ int m = csa->m; -#ifdef GLP_DEBUG - int n = csa->n; -#endif - char *type = csa->type; - double *lb = csa->lb; - double *ub = csa->ub; - int phase = csa->phase; - int *head = csa->head; - double *bbar = csa->bbar; - int i, k, cnt; - double sum; - if (parm->msg_lev < GLP_MSG_ON) goto skip; - if (parm->out_dly > 0 && - 1000.0 * xdifftime(xtime(), csa->tm_beg) < parm->out_dly) - goto skip; - if (csa->it_cnt == csa->it_dpy) goto skip; - if (!spec && csa->it_cnt % parm->out_frq != 0) goto skip; - /* compute the sum of primal infeasibilities and determine the - number of basic fixed variables */ - sum = 0.0, cnt = 0; - for (i = 1; i <= m; i++) - { k = head[i]; /* x[k] = xB[i] */ -#ifdef GLP_DEBUG - xassert(1 <= k && k <= m+n); -#endif - if (type[k] == GLP_LO || type[k] == GLP_DB || - type[k] == GLP_FX) - { /* x[k] has lower bound */ - if (bbar[i] < lb[k]) - sum += (lb[k] - bbar[i]); - } - if (type[k] == GLP_UP || type[k] == GLP_DB || - type[k] == GLP_FX) - { /* x[k] has upper bound */ - if (bbar[i] > ub[k]) - sum += (bbar[i] - ub[k]); - } - if (type[k] == GLP_FX) cnt++; - } - xprintf("%c%6d: obj = %17.9e infeas = %10.3e (%d)\n", - phase == 1 ? ' ' : '*', csa->it_cnt, eval_obj(csa), sum, cnt); - csa->it_dpy = csa->it_cnt; -skip: return; -} - -/*********************************************************************** -* store_sol - store basic solution back to the problem object -* -* This routine stores basic solution components back to the problem -* object. */ - -static void store_sol(struct csa *csa, glp_prob *lp, int p_stat, - int d_stat, int ray) -{ int m = csa->m; - int n = csa->n; - double zeta = csa->zeta; - int *head = csa->head; - char *stat = csa->stat; - double *bbar = csa->bbar; - double *cbar = csa->cbar; - int i, j, k; -#ifdef GLP_DEBUG - xassert(lp->m == m); - xassert(lp->n == n); -#endif - /* basis factorization */ -#ifdef GLP_DEBUG - xassert(!lp->valid && lp->bfd == NULL); - xassert(csa->valid && csa->bfd != NULL); -#endif - lp->valid = 1, csa->valid = 0; - lp->bfd = csa->bfd, csa->bfd = NULL; - memcpy(&lp->head[1], &head[1], m * sizeof(int)); - /* basic solution status */ - lp->pbs_stat = p_stat; - lp->dbs_stat = d_stat; - /* objective function value */ - lp->obj_val = eval_obj(csa); - /* simplex iteration count */ - lp->it_cnt = csa->it_cnt; - /* unbounded ray */ - lp->some = ray; - /* basic variables */ - for (i = 1; i <= m; i++) - { k = head[i]; /* x[k] = xB[i] */ -#ifdef GLP_DEBUG - xassert(1 <= k && k <= m+n); -#endif - if (k <= m) - { GLPROW *row = lp->row[k]; - row->stat = GLP_BS; - row->bind = i; - row->prim = bbar[i] / row->rii; - row->dual = 0.0; - } - else - { GLPCOL *col = lp->col[k-m]; - col->stat = GLP_BS; - col->bind = i; - col->prim = bbar[i] * col->sjj; - col->dual = 0.0; - } - } - /* non-basic variables */ - for (j = 1; j <= n; j++) - { k = head[m+j]; /* x[k] = xN[j] */ -#ifdef GLP_DEBUG - xassert(1 <= k && k <= m+n); -#endif - if (k <= m) - { GLPROW *row = lp->row[k]; - row->stat = stat[j]; - row->bind = 0; -#if 0 - row->prim = get_xN(csa, j) / row->rii; -#else - switch (stat[j]) - { case GLP_NL: - row->prim = row->lb; break; - case GLP_NU: - row->prim = row->ub; break; - case GLP_NF: - row->prim = 0.0; break; - case GLP_NS: - row->prim = row->lb; break; - default: - xassert(stat != stat); - } -#endif - row->dual = (cbar[j] * row->rii) / zeta; - } - else - { GLPCOL *col = lp->col[k-m]; - col->stat = stat[j]; - col->bind = 0; -#if 0 - col->prim = get_xN(csa, j) * col->sjj; -#else - switch (stat[j]) - { case GLP_NL: - col->prim = col->lb; break; - case GLP_NU: - col->prim = col->ub; break; - case GLP_NF: - col->prim = 0.0; break; - case GLP_NS: - col->prim = col->lb; break; - default: - xassert(stat != stat); - } -#endif - col->dual = (cbar[j] / col->sjj) / zeta; - } - } - return; -} - -/*********************************************************************** -* free_csa - deallocate common storage area -* -* This routine frees all the memory allocated to arrays in the common -* storage area (CSA). */ - -static void free_csa(struct csa *csa) -{ xfree(csa->type); - xfree(csa->lb); - xfree(csa->ub); - xfree(csa->coef); - xfree(csa->obj); - xfree(csa->A_ptr); - xfree(csa->A_ind); - xfree(csa->A_val); - xfree(csa->head); - xfree(csa->stat); - xfree(csa->N_ptr); - xfree(csa->N_len); - xfree(csa->N_ind); - xfree(csa->N_val); - xfree(csa->bbar); - xfree(csa->cbar); - xfree(csa->refsp); - xfree(csa->gamma); - xfree(csa->tcol_ind); - xfree(csa->tcol_vec); - xfree(csa->trow_ind); - xfree(csa->trow_vec); - xfree(csa->work1); - xfree(csa->work2); - xfree(csa->work3); - xfree(csa->work4); - xfree(csa); - return; -} - -/*********************************************************************** -* spx_primal - core LP solver based on the primal simplex method -* -* SYNOPSIS -* -* #include "glpspx.h" -* int spx_primal(glp_prob *lp, const glp_smcp *parm); -* -* DESCRIPTION -* -* The routine spx_primal is a core LP solver based on the two-phase -* primal simplex method. -* -* RETURNS -* -* 0 LP instance has been successfully solved. -* -* GLP_EITLIM -* Iteration limit has been exhausted. -* -* GLP_ETMLIM -* Time limit has been exhausted. -* -* GLP_EFAIL -* The solver failed to solve LP instance. */ - -int spx_primal(glp_prob *lp, const glp_smcp *parm) -{ struct csa *csa; - int binv_st = 2; - /* status of basis matrix factorization: - 0 - invalid; 1 - just computed; 2 - updated */ - int bbar_st = 0; - /* status of primal values of basic variables: - 0 - invalid; 1 - just computed; 2 - updated */ - int cbar_st = 0; - /* status of reduced costs of non-basic variables: - 0 - invalid; 1 - just computed; 2 - updated */ - int rigorous = 0; - /* rigorous mode flag; this flag is used to enable iterative - refinement on computing pivot rows and columns of the simplex - table */ - int check = 0; - int p_stat, d_stat, ret; - /* allocate and initialize the common storage area */ - csa = alloc_csa(lp); - init_csa(csa, lp); - if (parm->msg_lev >= GLP_MSG_DBG) - xprintf("Objective scale factor = %g\n", csa->zeta); -loop: /* main loop starts here */ - /* compute factorization of the basis matrix */ - if (binv_st == 0) - { ret = invert_B(csa); - if (ret != 0) - { if (parm->msg_lev >= GLP_MSG_ERR) - { xprintf("Error: unable to factorize the basis matrix (%d" - ")\n", ret); - xprintf("Sorry, basis recovery procedure not implemented" - " yet\n"); - } - xassert(!lp->valid && lp->bfd == NULL); - lp->bfd = csa->bfd, csa->bfd = NULL; - lp->pbs_stat = lp->dbs_stat = GLP_UNDEF; - lp->obj_val = 0.0; - lp->it_cnt = csa->it_cnt; - lp->some = 0; - ret = GLP_EFAIL; - goto done; - } - csa->valid = 1; - binv_st = 1; /* just computed */ - /* invalidate basic solution components */ - bbar_st = cbar_st = 0; - } - /* compute primal values of basic variables */ - if (bbar_st == 0) - { eval_bbar(csa); - bbar_st = 1; /* just computed */ - /* determine the search phase, if not determined yet */ - if (csa->phase == 0) - { if (set_aux_obj(csa, parm->tol_bnd) > 0) - { /* current basic solution is primal infeasible */ - /* start to minimize the sum of infeasibilities */ - csa->phase = 1; - } - else - { /* current basic solution is primal feasible */ - /* start to minimize the original objective function */ - set_orig_obj(csa); - csa->phase = 2; - } - xassert(check_stab(csa, parm->tol_bnd) == 0); - /* working objective coefficients have been changed, so - invalidate reduced costs */ - cbar_st = 0; - display(csa, parm, 1); - } - /* make sure that the current basic solution remains primal - feasible (or pseudo feasible on phase I) */ - if (check_stab(csa, parm->tol_bnd)) - { /* there are excessive bound violations due to round-off - errors */ - if (parm->msg_lev >= GLP_MSG_ERR) - xprintf("Warning: numerical instability (primal simplex," - " phase %s)\n", csa->phase == 1 ? "I" : "II"); - /* restart the search */ - csa->phase = 0; - binv_st = 0; - rigorous = 5; - goto loop; - } - } - xassert(csa->phase == 1 || csa->phase == 2); - /* on phase I we do not need to wait until the current basic - solution becomes dual feasible; it is sufficient to make sure - that no basic variable violates its bounds */ - if (csa->phase == 1 && !check_feas(csa, parm->tol_bnd)) - { /* the current basis is primal feasible; switch to phase II */ - csa->phase = 2; - set_orig_obj(csa); - cbar_st = 0; - display(csa, parm, 1); - } - /* compute reduced costs of non-basic variables */ - if (cbar_st == 0) - { eval_cbar(csa); - cbar_st = 1; /* just computed */ - } - /* redefine the reference space, if required */ - switch (parm->pricing) - { case GLP_PT_STD: - break; - case GLP_PT_PSE: - if (csa->refct == 0) reset_refsp(csa); - break; - default: - xassert(parm != parm); - } - /* at this point the basis factorization and all basic solution - components are valid */ - xassert(binv_st && bbar_st && cbar_st); - /* check accuracy of current basic solution components (only for - debugging) */ - if (check) - { double e_bbar = err_in_bbar(csa); - double e_cbar = err_in_cbar(csa); - double e_gamma = - (parm->pricing == GLP_PT_PSE ? err_in_gamma(csa) : 0.0); - xprintf("e_bbar = %10.3e; e_cbar = %10.3e; e_gamma = %10.3e\n", - e_bbar, e_cbar, e_gamma); - xassert(e_bbar <= 1e-5 && e_cbar <= 1e-5 && e_gamma <= 1e-3); - } - /* check if the iteration limit has been exhausted */ - if (parm->it_lim < INT_MAX && - csa->it_cnt - csa->it_beg >= parm->it_lim) - { if (bbar_st != 1 || csa->phase == 2 && cbar_st != 1) - { if (bbar_st != 1) bbar_st = 0; - if (csa->phase == 2 && cbar_st != 1) cbar_st = 0; - goto loop; - } - display(csa, parm, 1); - if (parm->msg_lev >= GLP_MSG_ALL) - xprintf("ITERATION LIMIT EXCEEDED; SEARCH TERMINATED\n"); - switch (csa->phase) - { case 1: - p_stat = GLP_INFEAS; - set_orig_obj(csa); - eval_cbar(csa); - break; - case 2: - p_stat = GLP_FEAS; - break; - default: - xassert(csa != csa); - } - chuzc(csa, parm->tol_dj); - d_stat = (csa->q == 0 ? GLP_FEAS : GLP_INFEAS); - store_sol(csa, lp, p_stat, d_stat, 0); - ret = GLP_EITLIM; - goto done; - } - /* check if the time limit has been exhausted */ - if (parm->tm_lim < INT_MAX && - 1000.0 * xdifftime(xtime(), csa->tm_beg) >= parm->tm_lim) - { if (bbar_st != 1 || csa->phase == 2 && cbar_st != 1) - { if (bbar_st != 1) bbar_st = 0; - if (csa->phase == 2 && cbar_st != 1) cbar_st = 0; - goto loop; - } - display(csa, parm, 1); - if (parm->msg_lev >= GLP_MSG_ALL) - xprintf("TIME LIMIT EXCEEDED; SEARCH TERMINATED\n"); - switch (csa->phase) - { case 1: - p_stat = GLP_INFEAS; - set_orig_obj(csa); - eval_cbar(csa); - break; - case 2: - p_stat = GLP_FEAS; - break; - default: - xassert(csa != csa); - } - chuzc(csa, parm->tol_dj); - d_stat = (csa->q == 0 ? GLP_FEAS : GLP_INFEAS); - store_sol(csa, lp, p_stat, d_stat, 0); - ret = GLP_ETMLIM; - goto done; - } - /* display the search progress */ - display(csa, parm, 0); - /* choose non-basic variable xN[q] */ - chuzc(csa, parm->tol_dj); - if (csa->q == 0) - { if (bbar_st != 1 || cbar_st != 1) - { if (bbar_st != 1) bbar_st = 0; - if (cbar_st != 1) cbar_st = 0; - goto loop; - } - display(csa, parm, 1); - switch (csa->phase) - { case 1: - if (parm->msg_lev >= GLP_MSG_ALL) -#if 0 /* 13/VII-2013; suggested by Prof. Fischetti */ - xprintf("PROBLEM HAS NO FEASIBLE SOLUTION\n"); -#else - xprintf("LP HAS NO PRIMAL FEASIBLE SOLUTION\n"); -#endif - p_stat = GLP_NOFEAS; - set_orig_obj(csa); - eval_cbar(csa); - chuzc(csa, parm->tol_dj); - d_stat = (csa->q == 0 ? GLP_FEAS : GLP_INFEAS); - break; - case 2: - if (parm->msg_lev >= GLP_MSG_ALL) -#if 0 /* 13/VII-2013; suggested by Prof. Fischetti */ - xprintf("OPTIMAL SOLUTION FOUND\n"); -#else - xprintf("OPTIMAL LP SOLUTION FOUND\n"); -#endif - p_stat = d_stat = GLP_FEAS; - break; - default: - xassert(csa != csa); - } - store_sol(csa, lp, p_stat, d_stat, 0); - ret = 0; - goto done; - } - /* compute pivot column of the simplex table */ - eval_tcol(csa); - if (rigorous) refine_tcol(csa); - sort_tcol(csa, parm->tol_piv); - /* check accuracy of the reduced cost of xN[q] */ - { double d1 = csa->cbar[csa->q]; /* less accurate */ - double d2 = reeval_cost(csa); /* more accurate */ - xassert(d1 != 0.0); - if (fabs(d1 - d2) > 1e-5 * (1.0 + fabs(d2)) || - !(d1 < 0.0 && d2 < 0.0 || d1 > 0.0 && d2 > 0.0)) - { if (parm->msg_lev >= GLP_MSG_DBG) - xprintf("d1 = %.12g; d2 = %.12g\n", d1, d2); - if (cbar_st != 1 || !rigorous) - { if (cbar_st != 1) cbar_st = 0; - rigorous = 5; - goto loop; - } - } - /* replace cbar[q] by more accurate value keeping its sign */ - if (d1 > 0.0) - csa->cbar[csa->q] = (d2 > 0.0 ? d2 : +DBL_EPSILON); - else - csa->cbar[csa->q] = (d2 < 0.0 ? d2 : -DBL_EPSILON); - } - /* choose basic variable xB[p] */ - switch (parm->r_test) - { case GLP_RT_STD: - chuzr(csa, 0.0); - break; - case GLP_RT_HAR: - chuzr(csa, 0.30 * parm->tol_bnd); - break; - default: - xassert(parm != parm); - } - if (csa->p == 0) - { if (bbar_st != 1 || cbar_st != 1 || !rigorous) - { if (bbar_st != 1) bbar_st = 0; - if (cbar_st != 1) cbar_st = 0; - rigorous = 1; - goto loop; - } - display(csa, parm, 1); - switch (csa->phase) - { case 1: - if (parm->msg_lev >= GLP_MSG_ERR) - xprintf("Error: unable to choose basic variable on ph" - "ase I\n"); - xassert(!lp->valid && lp->bfd == NULL); - lp->bfd = csa->bfd, csa->bfd = NULL; - lp->pbs_stat = lp->dbs_stat = GLP_UNDEF; - lp->obj_val = 0.0; - lp->it_cnt = csa->it_cnt; - lp->some = 0; - ret = GLP_EFAIL; - break; - case 2: - if (parm->msg_lev >= GLP_MSG_ALL) -#if 0 /* 13/VII-2013; suggested by Prof. Fischetti */ - xprintf("PROBLEM HAS UNBOUNDED SOLUTION\n"); -#else - xprintf("LP HAS UNBOUNDED PRIMAL SOLUTION\n"); -#endif - store_sol(csa, lp, GLP_FEAS, GLP_NOFEAS, - csa->head[csa->m+csa->q]); - ret = 0; - break; - default: - xassert(csa != csa); - } - goto done; - } - /* check if the pivot element is acceptable */ - if (csa->p > 0) - { double piv = csa->tcol_vec[csa->p]; - double eps = 1e-5 * (1.0 + 0.01 * csa->tcol_max); - if (fabs(piv) < eps) - { if (parm->msg_lev >= GLP_MSG_DBG) - xprintf("piv = %.12g; eps = %g\n", piv, eps); - if (!rigorous) - { rigorous = 5; - goto loop; - } - } - } - /* now xN[q] and xB[p] have been chosen anyhow */ - /* compute pivot row of the simplex table */ - if (csa->p > 0) - { double *rho = csa->work4; - eval_rho(csa, rho); - if (rigorous) refine_rho(csa, rho); - eval_trow(csa, rho); - } - /* accuracy check based on the pivot element */ - if (csa->p > 0) - { double piv1 = csa->tcol_vec[csa->p]; /* more accurate */ - double piv2 = csa->trow_vec[csa->q]; /* less accurate */ - xassert(piv1 != 0.0); - if (fabs(piv1 - piv2) > 1e-8 * (1.0 + fabs(piv1)) || - !(piv1 > 0.0 && piv2 > 0.0 || piv1 < 0.0 && piv2 < 0.0)) - { if (parm->msg_lev >= GLP_MSG_DBG) - xprintf("piv1 = %.12g; piv2 = %.12g\n", piv1, piv2); - if (binv_st != 1 || !rigorous) - { if (binv_st != 1) binv_st = 0; - rigorous = 5; - goto loop; - } - /* use more accurate version in the pivot row */ - if (csa->trow_vec[csa->q] == 0.0) - { csa->trow_nnz++; - xassert(csa->trow_nnz <= csa->n); - csa->trow_ind[csa->trow_nnz] = csa->q; - } - csa->trow_vec[csa->q] = piv1; - } - } - /* update primal values of basic variables */ - update_bbar(csa); - bbar_st = 2; /* updated */ - /* update reduced costs of non-basic variables */ - if (csa->p > 0) - { update_cbar(csa); - cbar_st = 2; /* updated */ - /* on phase I objective coefficient of xB[p] in the adjacent - basis becomes zero */ - if (csa->phase == 1) - { int k = csa->head[csa->p]; /* x[k] = xB[p] -> xN[q] */ - csa->cbar[csa->q] -= csa->coef[k]; - csa->coef[k] = 0.0; - } - } - /* update steepest edge coefficients */ - if (csa->p > 0) - { switch (parm->pricing) - { case GLP_PT_STD: - break; - case GLP_PT_PSE: - if (csa->refct > 0) update_gamma(csa); - break; - default: - xassert(parm != parm); - } - } - /* update factorization of the basis matrix */ - if (csa->p > 0) - { ret = update_B(csa, csa->p, csa->head[csa->m+csa->q]); - if (ret == 0) - binv_st = 2; /* updated */ - else - { csa->valid = 0; - binv_st = 0; /* invalid */ - } - } - /* update matrix N */ - if (csa->p > 0) - { del_N_col(csa, csa->q, csa->head[csa->m+csa->q]); - if (csa->type[csa->head[csa->p]] != GLP_FX) - add_N_col(csa, csa->q, csa->head[csa->p]); - } - /* change the basis header */ - change_basis(csa); - /* iteration complete */ - csa->it_cnt++; - if (rigorous > 0) rigorous--; - goto loop; -done: /* deallocate the common storage area */ - free_csa(csa); - /* return to the calling program */ - return ret; -} - -/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpspx02.c b/resources/3rdparty/glpk-4.53/src/glpspx02.c deleted file mode 100644 index 685c221a0..000000000 --- a/resources/3rdparty/glpk-4.53/src/glpspx02.c +++ /dev/null @@ -1,3118 +0,0 @@ -/* glpspx02.c (dual simplex method) */ - -/*********************************************************************** -* This code is part of GLPK (GNU Linear Programming Kit). -* -* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, -* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied -* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights -* reserved. E-mail: . -* -* GLPK is free software: you can redistribute it and/or modify it -* under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* GLPK is distributed in the hope that it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -* License for more details. -* -* You should have received a copy of the GNU General Public License -* along with GLPK. If not, see . -***********************************************************************/ - -#include "env.h" -#include "glpspx.h" - -#define GLP_DEBUG 1 - -#if 0 -#define GLP_LONG_STEP 1 -#endif - -struct csa -{ /* common storage area */ - /*--------------------------------------------------------------*/ - /* LP data */ - int m; - /* number of rows (auxiliary variables), m > 0 */ - int n; - /* number of columns (structural variables), n > 0 */ - char *type; /* char type[1+m+n]; */ - /* type[0] is not used; - type[k], 1 <= k <= m+n, is the type of variable x[k]: - GLP_FR - free variable - GLP_LO - variable with lower bound - GLP_UP - variable with upper bound - GLP_DB - double-bounded variable - GLP_FX - fixed variable */ - double *lb; /* double lb[1+m+n]; */ - /* lb[0] is not used; - lb[k], 1 <= k <= m+n, is an lower bound of variable x[k]; - if x[k] has no lower bound, lb[k] is zero */ - double *ub; /* double ub[1+m+n]; */ - /* ub[0] is not used; - ub[k], 1 <= k <= m+n, is an upper bound of variable x[k]; - if x[k] has no upper bound, ub[k] is zero; - if x[k] is of fixed type, ub[k] is the same as lb[k] */ - double *coef; /* double coef[1+m+n]; */ - /* coef[0] is not used; - coef[k], 1 <= k <= m+n, is an objective coefficient at - variable x[k] */ - /*--------------------------------------------------------------*/ - /* original bounds of variables */ - char *orig_type; /* char orig_type[1+m+n]; */ - double *orig_lb; /* double orig_lb[1+m+n]; */ - double *orig_ub; /* double orig_ub[1+m+n]; */ - /*--------------------------------------------------------------*/ - /* original objective function */ - double *obj; /* double obj[1+n]; */ - /* obj[0] is a constant term of the original objective function; - obj[j], 1 <= j <= n, is an original objective coefficient at - structural variable x[m+j] */ - double zeta; - /* factor used to scale original objective coefficients; its - sign defines original optimization direction: zeta > 0 means - minimization, zeta < 0 means maximization */ - /*--------------------------------------------------------------*/ - /* constraint matrix A; it has m rows and n columns and is stored - by columns */ - int *A_ptr; /* int A_ptr[1+n+1]; */ - /* A_ptr[0] is not used; - A_ptr[j], 1 <= j <= n, is starting position of j-th column in - arrays A_ind and A_val; note that A_ptr[1] is always 1; - A_ptr[n+1] indicates the position after the last element in - arrays A_ind and A_val */ - int *A_ind; /* int A_ind[A_ptr[n+1]]; */ - /* row indices */ - double *A_val; /* double A_val[A_ptr[n+1]]; */ - /* non-zero element values */ -#if 1 /* 06/IV-2009 */ - /* constraint matrix A stored by rows */ - int *AT_ptr; /* int AT_ptr[1+m+1]; */ - /* AT_ptr[0] is not used; - AT_ptr[i], 1 <= i <= m, is starting position of i-th row in - arrays AT_ind and AT_val; note that AT_ptr[1] is always 1; - AT_ptr[m+1] indicates the position after the last element in - arrays AT_ind and AT_val */ - int *AT_ind; /* int AT_ind[AT_ptr[m+1]]; */ - /* column indices */ - double *AT_val; /* double AT_val[AT_ptr[m+1]]; */ - /* non-zero element values */ -#endif - /*--------------------------------------------------------------*/ - /* basis header */ - int *head; /* int head[1+m+n]; */ - /* head[0] is not used; - head[i], 1 <= i <= m, is the ordinal number of basic variable - xB[i]; head[i] = k means that xB[i] = x[k] and i-th column of - matrix B is k-th column of matrix (I|-A); - head[m+j], 1 <= j <= n, is the ordinal number of non-basic - variable xN[j]; head[m+j] = k means that xN[j] = x[k] and j-th - column of matrix N is k-th column of matrix (I|-A) */ -#if 1 /* 06/IV-2009 */ - int *bind; /* int bind[1+m+n]; */ - /* bind[0] is not used; - bind[k], 1 <= k <= m+n, is the position of k-th column of the - matrix (I|-A) in the matrix (B|N); that is, bind[k] = k' means - that head[k'] = k */ -#endif - char *stat; /* char stat[1+n]; */ - /* stat[0] is not used; - stat[j], 1 <= j <= n, is the status of non-basic variable - xN[j], which defines its active bound: - GLP_NL - lower bound is active - GLP_NU - upper bound is active - GLP_NF - free variable - GLP_NS - fixed variable */ - /*--------------------------------------------------------------*/ - /* matrix B is the basis matrix; it is composed from columns of - the augmented constraint matrix (I|-A) corresponding to basic - variables and stored in a factorized (invertable) form */ - int valid; - /* factorization is valid only if this flag is set */ - BFD *bfd; /* BFD bfd[1:m,1:m]; */ - /* factorized (invertable) form of the basis matrix */ -#if 0 /* 06/IV-2009 */ - /*--------------------------------------------------------------*/ - /* matrix N is a matrix composed from columns of the augmented - constraint matrix (I|-A) corresponding to non-basic variables - except fixed ones; it is stored by rows and changes every time - the basis changes */ - int *N_ptr; /* int N_ptr[1+m+1]; */ - /* N_ptr[0] is not used; - N_ptr[i], 1 <= i <= m, is starting position of i-th row in - arrays N_ind and N_val; note that N_ptr[1] is always 1; - N_ptr[m+1] indicates the position after the last element in - arrays N_ind and N_val */ - int *N_len; /* int N_len[1+m]; */ - /* N_len[0] is not used; - N_len[i], 1 <= i <= m, is length of i-th row (0 to n) */ - int *N_ind; /* int N_ind[N_ptr[m+1]]; */ - /* column indices */ - double *N_val; /* double N_val[N_ptr[m+1]]; */ - /* non-zero element values */ -#endif - /*--------------------------------------------------------------*/ - /* working parameters */ - int phase; - /* search phase: - 0 - not determined yet - 1 - search for dual feasible solution - 2 - search for optimal solution */ -#if 0 /* 10/VI-2013 */ - glp_long tm_beg; -#else - double tm_beg; -#endif - /* time value at the beginning of the search */ - int it_beg; - /* simplex iteration count at the beginning of the search */ - int it_cnt; - /* simplex iteration count; it increases by one every time the - basis changes */ - int it_dpy; - /* simplex iteration count at the most recent display output */ - /*--------------------------------------------------------------*/ - /* basic solution components */ - double *bbar; /* double bbar[1+m]; */ - /* bbar[0] is not used on phase I; on phase II it is the current - value of the original objective function; - bbar[i], 1 <= i <= m, is primal value of basic variable xB[i] - (if xB[i] is free, its primal value is not updated) */ - double *cbar; /* double cbar[1+n]; */ - /* cbar[0] is not used; - cbar[j], 1 <= j <= n, is reduced cost of non-basic variable - xN[j] (if xN[j] is fixed, its reduced cost is not updated) */ - /*--------------------------------------------------------------*/ - /* the following pricing technique options may be used: - GLP_PT_STD - standard ("textbook") pricing; - GLP_PT_PSE - projected steepest edge; - GLP_PT_DVX - Devex pricing (not implemented yet); - in case of GLP_PT_STD the reference space is not used, and all - steepest edge coefficients are set to 1 */ - int refct; - /* this count is set to an initial value when the reference space - is defined and decreases by one every time the basis changes; - once this count reaches zero, the reference space is redefined - again */ - char *refsp; /* char refsp[1+m+n]; */ - /* refsp[0] is not used; - refsp[k], 1 <= k <= m+n, is the flag which means that variable - x[k] belongs to the current reference space */ - double *gamma; /* double gamma[1+m]; */ - /* gamma[0] is not used; - gamma[i], 1 <= i <= n, is the steepest edge coefficient for - basic variable xB[i]; if xB[i] is free, gamma[i] is not used - and just set to 1 */ - /*--------------------------------------------------------------*/ - /* basic variable xB[p] chosen to leave the basis */ - int p; - /* index of the basic variable xB[p] chosen, 1 <= p <= m; - if the set of eligible basic variables is empty (i.e. if the - current basic solution is primal feasible within a tolerance) - and thus no variable has been chosen, p is set to 0 */ - double delta; - /* change of xB[p] in the adjacent basis; - delta > 0 means that xB[p] violates its lower bound and will - increase to achieve it in the adjacent basis; - delta < 0 means that xB[p] violates its upper bound and will - decrease to achieve it in the adjacent basis */ - /*--------------------------------------------------------------*/ - /* pivot row of the simplex table corresponding to basic variable - xB[p] chosen is the following vector: - T' * e[p] = - N' * inv(B') * e[p] = - N' * rho, - where B' is a matrix transposed to the current basis matrix, - N' is a matrix, whose rows are columns of the matrix (I|-A) - corresponding to non-basic non-fixed variables */ - int trow_nnz; - /* number of non-zero components, 0 <= nnz <= n */ - int *trow_ind; /* int trow_ind[1+n]; */ - /* trow_ind[0] is not used; - trow_ind[t], 1 <= t <= nnz, is an index of non-zero component, - i.e. trow_ind[t] = j means that trow_vec[j] != 0 */ - double *trow_vec; /* int trow_vec[1+n]; */ - /* trow_vec[0] is not used; - trow_vec[j], 1 <= j <= n, is a numeric value of j-th component - of the row */ - double trow_max; - /* infinity (maximum) norm of the row (max |trow_vec[j]|) */ - int trow_num; - /* number of significant non-zero components, which means that: - |trow_vec[j]| >= eps for j in trow_ind[1,...,num], - |tcol_vec[j]| < eps for j in trow_ind[num+1,...,nnz], - where eps is a pivot tolerance */ - /*--------------------------------------------------------------*/ -#ifdef GLP_LONG_STEP /* 07/IV-2009 */ - int nbps; - /* number of breakpoints, 0 <= nbps <= n */ - struct bkpt - { int j; - /* index of non-basic variable xN[j], 1 <= j <= n */ - double t; - /* value of dual ray parameter at breakpoint, t >= 0 */ - double dz; - /* dz = zeta(t = t[k]) - zeta(t = 0) */ - } *bkpt; /* struct bkpt bkpt[1+n]; */ - /* bkpt[0] is not used; - bkpt[k], 1 <= k <= nbps, is k-th breakpoint of the dual - objective */ -#endif - /*--------------------------------------------------------------*/ - /* non-basic variable xN[q] chosen to enter the basis */ - int q; - /* index of the non-basic variable xN[q] chosen, 1 <= q <= n; - if no variable has been chosen, q is set to 0 */ - double new_dq; - /* reduced cost of xN[q] in the adjacent basis (it is the change - of lambdaB[p]) */ - /*--------------------------------------------------------------*/ - /* pivot column of the simplex table corresponding to non-basic - variable xN[q] chosen is the following vector: - T * e[q] = - inv(B) * N * e[q] = - inv(B) * N[q], - where B is the current basis matrix, N[q] is a column of the - matrix (I|-A) corresponding to xN[q] */ - int tcol_nnz; - /* number of non-zero components, 0 <= nnz <= m */ - int *tcol_ind; /* int tcol_ind[1+m]; */ - /* tcol_ind[0] is not used; - tcol_ind[t], 1 <= t <= nnz, is an index of non-zero component, - i.e. tcol_ind[t] = i means that tcol_vec[i] != 0 */ - double *tcol_vec; /* double tcol_vec[1+m]; */ - /* tcol_vec[0] is not used; - tcol_vec[i], 1 <= i <= m, is a numeric value of i-th component - of the column */ - /*--------------------------------------------------------------*/ - /* working arrays */ - double *work1; /* double work1[1+m]; */ - double *work2; /* double work2[1+m]; */ - double *work3; /* double work3[1+m]; */ - double *work4; /* double work4[1+m]; */ -}; - -static const double kappa = 0.10; - -/*********************************************************************** -* alloc_csa - allocate common storage area -* -* This routine allocates all arrays in the common storage area (CSA) -* and returns a pointer to the CSA. */ - -static struct csa *alloc_csa(glp_prob *lp) -{ struct csa *csa; - int m = lp->m; - int n = lp->n; - int nnz = lp->nnz; - csa = xmalloc(sizeof(struct csa)); - xassert(m > 0 && n > 0); - csa->m = m; - csa->n = n; - csa->type = xcalloc(1+m+n, sizeof(char)); - csa->lb = xcalloc(1+m+n, sizeof(double)); - csa->ub = xcalloc(1+m+n, sizeof(double)); - csa->coef = xcalloc(1+m+n, sizeof(double)); - csa->orig_type = xcalloc(1+m+n, sizeof(char)); - csa->orig_lb = xcalloc(1+m+n, sizeof(double)); - csa->orig_ub = xcalloc(1+m+n, sizeof(double)); - csa->obj = xcalloc(1+n, sizeof(double)); - csa->A_ptr = xcalloc(1+n+1, sizeof(int)); - csa->A_ind = xcalloc(1+nnz, sizeof(int)); - csa->A_val = xcalloc(1+nnz, sizeof(double)); -#if 1 /* 06/IV-2009 */ - csa->AT_ptr = xcalloc(1+m+1, sizeof(int)); - csa->AT_ind = xcalloc(1+nnz, sizeof(int)); - csa->AT_val = xcalloc(1+nnz, sizeof(double)); -#endif - csa->head = xcalloc(1+m+n, sizeof(int)); -#if 1 /* 06/IV-2009 */ - csa->bind = xcalloc(1+m+n, sizeof(int)); -#endif - csa->stat = xcalloc(1+n, sizeof(char)); -#if 0 /* 06/IV-2009 */ - csa->N_ptr = xcalloc(1+m+1, sizeof(int)); - csa->N_len = xcalloc(1+m, sizeof(int)); - csa->N_ind = NULL; /* will be allocated later */ - csa->N_val = NULL; /* will be allocated later */ -#endif - csa->bbar = xcalloc(1+m, sizeof(double)); - csa->cbar = xcalloc(1+n, sizeof(double)); - csa->refsp = xcalloc(1+m+n, sizeof(char)); - csa->gamma = xcalloc(1+m, sizeof(double)); - csa->trow_ind = xcalloc(1+n, sizeof(int)); - csa->trow_vec = xcalloc(1+n, sizeof(double)); -#ifdef GLP_LONG_STEP /* 07/IV-2009 */ - csa->bkpt = xcalloc(1+n, sizeof(struct bkpt)); -#endif - csa->tcol_ind = xcalloc(1+m, sizeof(int)); - csa->tcol_vec = xcalloc(1+m, sizeof(double)); - csa->work1 = xcalloc(1+m, sizeof(double)); - csa->work2 = xcalloc(1+m, sizeof(double)); - csa->work3 = xcalloc(1+m, sizeof(double)); - csa->work4 = xcalloc(1+m, sizeof(double)); - return csa; -} - -/*********************************************************************** -* init_csa - initialize common storage area -* -* This routine initializes all data structures in the common storage -* area (CSA). */ - -static void init_csa(struct csa *csa, glp_prob *lp) -{ int m = csa->m; - int n = csa->n; - char *type = csa->type; - double *lb = csa->lb; - double *ub = csa->ub; - double *coef = csa->coef; - char *orig_type = csa->orig_type; - double *orig_lb = csa->orig_lb; - double *orig_ub = csa->orig_ub; - double *obj = csa->obj; - int *A_ptr = csa->A_ptr; - int *A_ind = csa->A_ind; - double *A_val = csa->A_val; -#if 1 /* 06/IV-2009 */ - int *AT_ptr = csa->AT_ptr; - int *AT_ind = csa->AT_ind; - double *AT_val = csa->AT_val; -#endif - int *head = csa->head; -#if 1 /* 06/IV-2009 */ - int *bind = csa->bind; -#endif - char *stat = csa->stat; - char *refsp = csa->refsp; - double *gamma = csa->gamma; - int i, j, k, loc; - double cmax; - /* auxiliary variables */ - for (i = 1; i <= m; i++) - { GLPROW *row = lp->row[i]; - type[i] = (char)row->type; - lb[i] = row->lb * row->rii; - ub[i] = row->ub * row->rii; - coef[i] = 0.0; - } - /* structural variables */ - for (j = 1; j <= n; j++) - { GLPCOL *col = lp->col[j]; - type[m+j] = (char)col->type; - lb[m+j] = col->lb / col->sjj; - ub[m+j] = col->ub / col->sjj; - coef[m+j] = col->coef * col->sjj; - } - /* original bounds of variables */ - memcpy(&orig_type[1], &type[1], (m+n) * sizeof(char)); - memcpy(&orig_lb[1], &lb[1], (m+n) * sizeof(double)); - memcpy(&orig_ub[1], &ub[1], (m+n) * sizeof(double)); - /* original objective function */ - obj[0] = lp->c0; - memcpy(&obj[1], &coef[m+1], n * sizeof(double)); - /* factor used to scale original objective coefficients */ - cmax = 0.0; - for (j = 1; j <= n; j++) - if (cmax < fabs(obj[j])) cmax = fabs(obj[j]); - if (cmax == 0.0) cmax = 1.0; - switch (lp->dir) - { case GLP_MIN: - csa->zeta = + 1.0 / cmax; - break; - case GLP_MAX: - csa->zeta = - 1.0 / cmax; - break; - default: - xassert(lp != lp); - } -#if 1 - if (fabs(csa->zeta) < 1.0) csa->zeta *= 1000.0; -#endif - /* scale working objective coefficients */ - for (j = 1; j <= n; j++) coef[m+j] *= csa->zeta; - /* matrix A (by columns) */ - loc = 1; - for (j = 1; j <= n; j++) - { GLPAIJ *aij; - A_ptr[j] = loc; - for (aij = lp->col[j]->ptr; aij != NULL; aij = aij->c_next) - { A_ind[loc] = aij->row->i; - A_val[loc] = aij->row->rii * aij->val * aij->col->sjj; - loc++; - } - } - A_ptr[n+1] = loc; - xassert(loc-1 == lp->nnz); -#if 1 /* 06/IV-2009 */ - /* matrix A (by rows) */ - loc = 1; - for (i = 1; i <= m; i++) - { GLPAIJ *aij; - AT_ptr[i] = loc; - for (aij = lp->row[i]->ptr; aij != NULL; aij = aij->r_next) - { AT_ind[loc] = aij->col->j; - AT_val[loc] = aij->row->rii * aij->val * aij->col->sjj; - loc++; - } - } - AT_ptr[m+1] = loc; - xassert(loc-1 == lp->nnz); -#endif - /* basis header */ - xassert(lp->valid); - memcpy(&head[1], &lp->head[1], m * sizeof(int)); - k = 0; - for (i = 1; i <= m; i++) - { GLPROW *row = lp->row[i]; - if (row->stat != GLP_BS) - { k++; - xassert(k <= n); - head[m+k] = i; - stat[k] = (char)row->stat; - } - } - for (j = 1; j <= n; j++) - { GLPCOL *col = lp->col[j]; - if (col->stat != GLP_BS) - { k++; - xassert(k <= n); - head[m+k] = m + j; - stat[k] = (char)col->stat; - } - } - xassert(k == n); -#if 1 /* 06/IV-2009 */ - for (k = 1; k <= m+n; k++) - bind[head[k]] = k; -#endif - /* factorization of matrix B */ - csa->valid = 1, lp->valid = 0; - csa->bfd = lp->bfd, lp->bfd = NULL; -#if 0 /* 06/IV-2009 */ - /* matrix N (by rows) */ - alloc_N(csa); - build_N(csa); -#endif - /* working parameters */ - csa->phase = 0; - csa->tm_beg = xtime(); - csa->it_beg = csa->it_cnt = lp->it_cnt; - csa->it_dpy = -1; - /* reference space and steepest edge coefficients */ - csa->refct = 0; - memset(&refsp[1], 0, (m+n) * sizeof(char)); - for (i = 1; i <= m; i++) gamma[i] = 1.0; - return; -} - -#if 1 /* copied from primal */ -/*********************************************************************** -* invert_B - compute factorization of the basis matrix -* -* This routine computes factorization of the current basis matrix B. -* -* If the operation is successful, the routine returns zero, otherwise -* non-zero. */ - -static int inv_col(void *info, int i, int ind[], double val[]) -{ /* this auxiliary routine returns row indices and numeric values - of non-zero elements of i-th column of the basis matrix */ - struct csa *csa = info; - int m = csa->m; -#ifdef GLP_DEBUG - int n = csa->n; -#endif - int *A_ptr = csa->A_ptr; - int *A_ind = csa->A_ind; - double *A_val = csa->A_val; - int *head = csa->head; - int k, len, ptr, t; -#ifdef GLP_DEBUG - xassert(1 <= i && i <= m); -#endif - k = head[i]; /* B[i] is k-th column of (I|-A) */ -#ifdef GLP_DEBUG - xassert(1 <= k && k <= m+n); -#endif - if (k <= m) - { /* B[i] is k-th column of submatrix I */ - len = 1; - ind[1] = k; - val[1] = 1.0; - } - else - { /* B[i] is (k-m)-th column of submatrix (-A) */ - ptr = A_ptr[k-m]; - len = A_ptr[k-m+1] - ptr; - memcpy(&ind[1], &A_ind[ptr], len * sizeof(int)); - memcpy(&val[1], &A_val[ptr], len * sizeof(double)); - for (t = 1; t <= len; t++) val[t] = - val[t]; - } - return len; -} - -static int invert_B(struct csa *csa) -{ int ret; - ret = bfd_factorize(csa->bfd, csa->m, NULL, inv_col, csa); - csa->valid = (ret == 0); - return ret; -} -#endif - -#if 1 /* copied from primal */ -/*********************************************************************** -* update_B - update factorization of the basis matrix -* -* This routine replaces i-th column of the basis matrix B by k-th -* column of the augmented constraint matrix (I|-A) and then updates -* the factorization of B. -* -* If the factorization has been successfully updated, the routine -* returns zero, otherwise non-zero. */ - -static int update_B(struct csa *csa, int i, int k) -{ int m = csa->m; -#ifdef GLP_DEBUG - int n = csa->n; -#endif - int ret; -#ifdef GLP_DEBUG - xassert(1 <= i && i <= m); - xassert(1 <= k && k <= m+n); -#endif - if (k <= m) - { /* new i-th column of B is k-th column of I */ - int ind[1+1]; - double val[1+1]; - ind[1] = k; - val[1] = 1.0; - xassert(csa->valid); - ret = bfd_update_it(csa->bfd, i, 0, 1, ind, val); - } - else - { /* new i-th column of B is (k-m)-th column of (-A) */ - int *A_ptr = csa->A_ptr; - int *A_ind = csa->A_ind; - double *A_val = csa->A_val; - double *val = csa->work1; - int beg, end, ptr, len; - beg = A_ptr[k-m]; - end = A_ptr[k-m+1]; - len = 0; - for (ptr = beg; ptr < end; ptr++) - val[++len] = - A_val[ptr]; - xassert(csa->valid); - ret = bfd_update_it(csa->bfd, i, 0, len, &A_ind[beg-1], val); - } - csa->valid = (ret == 0); - return ret; -} -#endif - -#if 1 /* copied from primal */ -/*********************************************************************** -* error_ftran - compute residual vector r = h - B * x -* -* This routine computes the residual vector r = h - B * x, where B is -* the current basis matrix, h is the vector of right-hand sides, x is -* the solution vector. */ - -static void error_ftran(struct csa *csa, double h[], double x[], - double r[]) -{ int m = csa->m; -#ifdef GLP_DEBUG - int n = csa->n; -#endif - int *A_ptr = csa->A_ptr; - int *A_ind = csa->A_ind; - double *A_val = csa->A_val; - int *head = csa->head; - int i, k, beg, end, ptr; - double temp; - /* compute the residual vector: - r = h - B * x = h - B[1] * x[1] - ... - B[m] * x[m], - where B[1], ..., B[m] are columns of matrix B */ - memcpy(&r[1], &h[1], m * sizeof(double)); - for (i = 1; i <= m; i++) - { temp = x[i]; - if (temp == 0.0) continue; - k = head[i]; /* B[i] is k-th column of (I|-A) */ -#ifdef GLP_DEBUG - xassert(1 <= k && k <= m+n); -#endif - if (k <= m) - { /* B[i] is k-th column of submatrix I */ - r[k] -= temp; - } - else - { /* B[i] is (k-m)-th column of submatrix (-A) */ - beg = A_ptr[k-m]; - end = A_ptr[k-m+1]; - for (ptr = beg; ptr < end; ptr++) - r[A_ind[ptr]] += A_val[ptr] * temp; - } - } - return; -} -#endif - -#if 1 /* copied from primal */ -/*********************************************************************** -* refine_ftran - refine solution of B * x = h -* -* This routine performs one iteration to refine the solution of -* the system B * x = h, where B is the current basis matrix, h is the -* vector of right-hand sides, x is the solution vector. */ - -static void refine_ftran(struct csa *csa, double h[], double x[]) -{ int m = csa->m; - double *r = csa->work1; - double *d = csa->work1; - int i; - /* compute the residual vector r = h - B * x */ - error_ftran(csa, h, x, r); - /* compute the correction vector d = inv(B) * r */ - xassert(csa->valid); - bfd_ftran(csa->bfd, d); - /* refine the solution vector (new x) = (old x) + d */ - for (i = 1; i <= m; i++) x[i] += d[i]; - return; -} -#endif - -#if 1 /* copied from primal */ -/*********************************************************************** -* error_btran - compute residual vector r = h - B'* x -* -* This routine computes the residual vector r = h - B'* x, where B' -* is a matrix transposed to the current basis matrix, h is the vector -* of right-hand sides, x is the solution vector. */ - -static void error_btran(struct csa *csa, double h[], double x[], - double r[]) -{ int m = csa->m; -#ifdef GLP_DEBUG - int n = csa->n; -#endif - int *A_ptr = csa->A_ptr; - int *A_ind = csa->A_ind; - double *A_val = csa->A_val; - int *head = csa->head; - int i, k, beg, end, ptr; - double temp; - /* compute the residual vector r = b - B'* x */ - for (i = 1; i <= m; i++) - { /* r[i] := b[i] - (i-th column of B)'* x */ - k = head[i]; /* B[i] is k-th column of (I|-A) */ -#ifdef GLP_DEBUG - xassert(1 <= k && k <= m+n); -#endif - temp = h[i]; - if (k <= m) - { /* B[i] is k-th column of submatrix I */ - temp -= x[k]; - } - else - { /* B[i] is (k-m)-th column of submatrix (-A) */ - beg = A_ptr[k-m]; - end = A_ptr[k-m+1]; - for (ptr = beg; ptr < end; ptr++) - temp += A_val[ptr] * x[A_ind[ptr]]; - } - r[i] = temp; - } - return; -} -#endif - -#if 1 /* copied from primal */ -/*********************************************************************** -* refine_btran - refine solution of B'* x = h -* -* This routine performs one iteration to refine the solution of the -* system B'* x = h, where B' is a matrix transposed to the current -* basis matrix, h is the vector of right-hand sides, x is the solution -* vector. */ - -static void refine_btran(struct csa *csa, double h[], double x[]) -{ int m = csa->m; - double *r = csa->work1; - double *d = csa->work1; - int i; - /* compute the residual vector r = h - B'* x */ - error_btran(csa, h, x, r); - /* compute the correction vector d = inv(B') * r */ - xassert(csa->valid); - bfd_btran(csa->bfd, d); - /* refine the solution vector (new x) = (old x) + d */ - for (i = 1; i <= m; i++) x[i] += d[i]; - return; -} -#endif - -#if 1 /* copied from primal */ -/*********************************************************************** -* get_xN - determine current value of non-basic variable xN[j] -* -* This routine returns the current value of non-basic variable xN[j], -* which is a value of its active bound. */ - -static double get_xN(struct csa *csa, int j) -{ int m = csa->m; -#ifdef GLP_DEBUG - int n = csa->n; -#endif - double *lb = csa->lb; - double *ub = csa->ub; - int *head = csa->head; - char *stat = csa->stat; - int k; - double xN; -#ifdef GLP_DEBUG - xassert(1 <= j && j <= n); -#endif - k = head[m+j]; /* x[k] = xN[j] */ -#ifdef GLP_DEBUG - xassert(1 <= k && k <= m+n); -#endif - switch (stat[j]) - { case GLP_NL: - /* x[k] is on its lower bound */ - xN = lb[k]; break; - case GLP_NU: - /* x[k] is on its upper bound */ - xN = ub[k]; break; - case GLP_NF: - /* x[k] is free non-basic variable */ - xN = 0.0; break; - case GLP_NS: - /* x[k] is fixed non-basic variable */ - xN = lb[k]; break; - default: - xassert(stat != stat); - } - return xN; -} -#endif - -#if 1 /* copied from primal */ -/*********************************************************************** -* eval_beta - compute primal values of basic variables -* -* This routine computes current primal values of all basic variables: -* -* beta = - inv(B) * N * xN, -* -* where B is the current basis matrix, N is a matrix built of columns -* of matrix (I|-A) corresponding to non-basic variables, and xN is the -* vector of current values of non-basic variables. */ - -static void eval_beta(struct csa *csa, double beta[]) -{ int m = csa->m; - int n = csa->n; - int *A_ptr = csa->A_ptr; - int *A_ind = csa->A_ind; - double *A_val = csa->A_val; - int *head = csa->head; - double *h = csa->work2; - int i, j, k, beg, end, ptr; - double xN; - /* compute the right-hand side vector: - h := - N * xN = - N[1] * xN[1] - ... - N[n] * xN[n], - where N[1], ..., N[n] are columns of matrix N */ - for (i = 1; i <= m; i++) - h[i] = 0.0; - for (j = 1; j <= n; j++) - { k = head[m+j]; /* x[k] = xN[j] */ -#ifdef GLP_DEBUG - xassert(1 <= k && k <= m+n); -#endif - /* determine current value of xN[j] */ - xN = get_xN(csa, j); - if (xN == 0.0) continue; - if (k <= m) - { /* N[j] is k-th column of submatrix I */ - h[k] -= xN; - } - else - { /* N[j] is (k-m)-th column of submatrix (-A) */ - beg = A_ptr[k-m]; - end = A_ptr[k-m+1]; - for (ptr = beg; ptr < end; ptr++) - h[A_ind[ptr]] += xN * A_val[ptr]; - } - } - /* solve system B * beta = h */ - memcpy(&beta[1], &h[1], m * sizeof(double)); - xassert(csa->valid); - bfd_ftran(csa->bfd, beta); - /* and refine the solution */ - refine_ftran(csa, h, beta); - return; -} -#endif - -#if 1 /* copied from primal */ -/*********************************************************************** -* eval_pi - compute vector of simplex multipliers -* -* This routine computes the vector of current simplex multipliers: -* -* pi = inv(B') * cB, -* -* where B' is a matrix transposed to the current basis matrix, cB is -* a subvector of objective coefficients at basic variables. */ - -static void eval_pi(struct csa *csa, double pi[]) -{ int m = csa->m; - double *c = csa->coef; - int *head = csa->head; - double *cB = csa->work2; - int i; - /* construct the right-hand side vector cB */ - for (i = 1; i <= m; i++) - cB[i] = c[head[i]]; - /* solve system B'* pi = cB */ - memcpy(&pi[1], &cB[1], m * sizeof(double)); - xassert(csa->valid); - bfd_btran(csa->bfd, pi); - /* and refine the solution */ - refine_btran(csa, cB, pi); - return; -} -#endif - -#if 1 /* copied from primal */ -/*********************************************************************** -* eval_cost - compute reduced cost of non-basic variable xN[j] -* -* This routine computes the current reduced cost of non-basic variable -* xN[j]: -* -* d[j] = cN[j] - N'[j] * pi, -* -* where cN[j] is the objective coefficient at variable xN[j], N[j] is -* a column of the augmented constraint matrix (I|-A) corresponding to -* xN[j], pi is the vector of simplex multipliers. */ - -static double eval_cost(struct csa *csa, double pi[], int j) -{ int m = csa->m; -#ifdef GLP_DEBUG - int n = csa->n; -#endif - double *coef = csa->coef; - int *head = csa->head; - int k; - double dj; -#ifdef GLP_DEBUG - xassert(1 <= j && j <= n); -#endif - k = head[m+j]; /* x[k] = xN[j] */ -#ifdef GLP_DEBUG - xassert(1 <= k && k <= m+n); -#endif - dj = coef[k]; - if (k <= m) - { /* N[j] is k-th column of submatrix I */ - dj -= pi[k]; - } - else - { /* N[j] is (k-m)-th column of submatrix (-A) */ - int *A_ptr = csa->A_ptr; - int *A_ind = csa->A_ind; - double *A_val = csa->A_val; - int beg, end, ptr; - beg = A_ptr[k-m]; - end = A_ptr[k-m+1]; - for (ptr = beg; ptr < end; ptr++) - dj += A_val[ptr] * pi[A_ind[ptr]]; - } - return dj; -} -#endif - -#if 1 /* copied from primal */ -/*********************************************************************** -* eval_bbar - compute and store primal values of basic variables -* -* This routine computes primal values of all basic variables and then -* stores them in the solution array. */ - -static void eval_bbar(struct csa *csa) -{ eval_beta(csa, csa->bbar); - return; -} -#endif - -#if 1 /* copied from primal */ -/*********************************************************************** -* eval_cbar - compute and store reduced costs of non-basic variables -* -* This routine computes reduced costs of all non-basic variables and -* then stores them in the solution array. */ - -static void eval_cbar(struct csa *csa) -{ -#ifdef GLP_DEBUG - int m = csa->m; -#endif - int n = csa->n; -#ifdef GLP_DEBUG - int *head = csa->head; -#endif - double *cbar = csa->cbar; - double *pi = csa->work3; - int j; -#ifdef GLP_DEBUG - int k; -#endif - /* compute simplex multipliers */ - eval_pi(csa, pi); - /* compute and store reduced costs */ - for (j = 1; j <= n; j++) - { -#ifdef GLP_DEBUG - k = head[m+j]; /* x[k] = xN[j] */ - xassert(1 <= k && k <= m+n); -#endif - cbar[j] = eval_cost(csa, pi, j); - } - return; -} -#endif - -/*********************************************************************** -* reset_refsp - reset the reference space -* -* This routine resets (redefines) the reference space used in the -* projected steepest edge pricing algorithm. */ - -static void reset_refsp(struct csa *csa) -{ int m = csa->m; - int n = csa->n; - int *head = csa->head; - char *refsp = csa->refsp; - double *gamma = csa->gamma; - int i, k; - xassert(csa->refct == 0); - csa->refct = 1000; - memset(&refsp[1], 0, (m+n) * sizeof(char)); - for (i = 1; i <= m; i++) - { k = head[i]; /* x[k] = xB[i] */ - refsp[k] = 1; - gamma[i] = 1.0; - } - return; -} - -/*********************************************************************** -* eval_gamma - compute steepest edge coefficients -* -* This routine computes the vector of steepest edge coefficients for -* all basic variables (except free ones) using its direct definition: -* -* gamma[i] = eta[i] + sum alfa[i,j]^2, i = 1,...,m, -* j in C -* -* where eta[i] = 1 means that xB[i] is in the current reference space, -* and 0 otherwise; C is a set of non-basic non-fixed variables xN[j], -* which are in the current reference space; alfa[i,j] are elements of -* the current simplex table. -* -* NOTE: The routine is intended only for debugginig purposes. */ - -static void eval_gamma(struct csa *csa, double gamma[]) -{ int m = csa->m; - int n = csa->n; - char *type = csa->type; - int *head = csa->head; - char *refsp = csa->refsp; - double *alfa = csa->work3; - double *h = csa->work3; - int i, j, k; - /* gamma[i] := eta[i] (or 1, if xB[i] is free) */ - for (i = 1; i <= m; i++) - { k = head[i]; /* x[k] = xB[i] */ -#ifdef GLP_DEBUG - xassert(1 <= k && k <= m+n); -#endif - if (type[k] == GLP_FR) - gamma[i] = 1.0; - else - gamma[i] = (refsp[k] ? 1.0 : 0.0); - } - /* compute columns of the current simplex table */ - for (j = 1; j <= n; j++) - { k = head[m+j]; /* x[k] = xN[j] */ -#ifdef GLP_DEBUG - xassert(1 <= k && k <= m+n); -#endif - /* skip column, if xN[j] is not in C */ - if (!refsp[k]) continue; -#ifdef GLP_DEBUG - /* set C must not contain fixed variables */ - xassert(type[k] != GLP_FX); -#endif - /* construct the right-hand side vector h = - N[j] */ - for (i = 1; i <= m; i++) - h[i] = 0.0; - if (k <= m) - { /* N[j] is k-th column of submatrix I */ - h[k] = -1.0; - } - else - { /* N[j] is (k-m)-th column of submatrix (-A) */ - int *A_ptr = csa->A_ptr; - int *A_ind = csa->A_ind; - double *A_val = csa->A_val; - int beg, end, ptr; - beg = A_ptr[k-m]; - end = A_ptr[k-m+1]; - for (ptr = beg; ptr < end; ptr++) - h[A_ind[ptr]] = A_val[ptr]; - } - /* solve system B * alfa = h */ - xassert(csa->valid); - bfd_ftran(csa->bfd, alfa); - /* gamma[i] := gamma[i] + alfa[i,j]^2 */ - for (i = 1; i <= m; i++) - { k = head[i]; /* x[k] = xB[i] */ - if (type[k] != GLP_FR) - gamma[i] += alfa[i] * alfa[i]; - } - } - return; -} - -/*********************************************************************** -* chuzr - choose basic variable (row of the simplex table) -* -* This routine chooses basic variable xB[p] having largest weighted -* bound violation: -* -* |r[p]| / sqrt(gamma[p]) = max |r[i]| / sqrt(gamma[i]), -* i in I -* -* / lB[i] - beta[i], if beta[i] < lB[i] -* | -* r[i] = < 0, if lB[i] <= beta[i] <= uB[i] -* | -* \ uB[i] - beta[i], if beta[i] > uB[i] -* -* where beta[i] is primal value of xB[i] in the current basis, lB[i] -* and uB[i] are lower and upper bounds of xB[i], I is a subset of -* eligible basic variables, which significantly violates their bounds, -* gamma[i] is the steepest edge coefficient. -* -* If |r[i]| is less than a specified tolerance, xB[i] is not included -* in I and therefore ignored. -* -* If I is empty and no variable has been chosen, p is set to 0. */ - -static void chuzr(struct csa *csa, double tol_bnd) -{ int m = csa->m; -#ifdef GLP_DEBUG - int n = csa->n; -#endif - char *type = csa->type; - double *lb = csa->lb; - double *ub = csa->ub; - int *head = csa->head; - double *bbar = csa->bbar; - double *gamma = csa->gamma; - int i, k, p; - double delta, best, eps, ri, temp; - /* nothing is chosen so far */ - p = 0, delta = 0.0, best = 0.0; - /* look through the list of basic variables */ - for (i = 1; i <= m; i++) - { k = head[i]; /* x[k] = xB[i] */ -#ifdef GLP_DEBUG - xassert(1 <= k && k <= m+n); -#endif - /* determine bound violation ri[i] */ - ri = 0.0; - if (type[k] == GLP_LO || type[k] == GLP_DB || - type[k] == GLP_FX) - { /* xB[i] has lower bound */ - eps = tol_bnd * (1.0 + kappa * fabs(lb[k])); - if (bbar[i] < lb[k] - eps) - { /* and significantly violates it */ - ri = lb[k] - bbar[i]; - } - } - if (type[k] == GLP_UP || type[k] == GLP_DB || - type[k] == GLP_FX) - { /* xB[i] has upper bound */ - eps = tol_bnd * (1.0 + kappa * fabs(ub[k])); - if (bbar[i] > ub[k] + eps) - { /* and significantly violates it */ - ri = ub[k] - bbar[i]; - } - } - /* if xB[i] is not eligible, skip it */ - if (ri == 0.0) continue; - /* xB[i] is eligible basic variable; choose one with largest - weighted bound violation */ -#ifdef GLP_DEBUG - xassert(gamma[i] >= 0.0); -#endif - temp = gamma[i]; - if (temp < DBL_EPSILON) temp = DBL_EPSILON; - temp = (ri * ri) / temp; - if (best < temp) - p = i, delta = ri, best = temp; - } - /* store the index of basic variable xB[p] chosen and its change - in the adjacent basis */ - csa->p = p; - csa->delta = delta; - return; -} - -#if 1 /* copied from primal */ -/*********************************************************************** -* eval_rho - compute pivot row of the inverse -* -* This routine computes the pivot (p-th) row of the inverse inv(B), -* which corresponds to basic variable xB[p] chosen: -* -* rho = inv(B') * e[p], -* -* where B' is a matrix transposed to the current basis matrix, e[p] -* is unity vector. */ - -static void eval_rho(struct csa *csa, double rho[]) -{ int m = csa->m; - int p = csa->p; - double *e = rho; - int i; -#ifdef GLP_DEBUG - xassert(1 <= p && p <= m); -#endif - /* construct the right-hand side vector e[p] */ - for (i = 1; i <= m; i++) - e[i] = 0.0; - e[p] = 1.0; - /* solve system B'* rho = e[p] */ - xassert(csa->valid); - bfd_btran(csa->bfd, rho); - return; -} -#endif - -#if 1 /* copied from primal */ -/*********************************************************************** -* refine_rho - refine pivot row of the inverse -* -* This routine refines the pivot row of the inverse inv(B) assuming -* that it was previously computed by the routine eval_rho. */ - -static void refine_rho(struct csa *csa, double rho[]) -{ int m = csa->m; - int p = csa->p; - double *e = csa->work3; - int i; -#ifdef GLP_DEBUG - xassert(1 <= p && p <= m); -#endif - /* construct the right-hand side vector e[p] */ - for (i = 1; i <= m; i++) - e[i] = 0.0; - e[p] = 1.0; - /* refine solution of B'* rho = e[p] */ - refine_btran(csa, e, rho); - return; -} -#endif - -#if 1 /* 06/IV-2009 */ -/*********************************************************************** -* eval_trow - compute pivot row of the simplex table -* -* This routine computes the pivot row of the simplex table, which -* corresponds to basic variable xB[p] chosen. -* -* The pivot row is the following vector: -* -* trow = T'* e[p] = - N'* inv(B') * e[p] = - N' * rho, -* -* where rho is the pivot row of the inverse inv(B) previously computed -* by the routine eval_rho. -* -* Note that elements of the pivot row corresponding to fixed non-basic -* variables are not computed. -* -* NOTES -* -* Computing pivot row of the simplex table is one of the most time -* consuming operations, and for some instances it may take more than -* 50% of the total solution time. -* -* In the current implementation there are two routines to compute the -* pivot row. The routine eval_trow1 computes elements of the pivot row -* as inner products of columns of the matrix N and the vector rho; it -* is used when the vector rho is relatively dense. The routine -* eval_trow2 computes the pivot row as a linear combination of rows of -* the matrix N; it is used when the vector rho is relatively sparse. */ - -static void eval_trow1(struct csa *csa, double rho[]) -{ int m = csa->m; - int n = csa->n; - int *A_ptr = csa->A_ptr; - int *A_ind = csa->A_ind; - double *A_val = csa->A_val; - int *head = csa->head; - char *stat = csa->stat; - int *trow_ind = csa->trow_ind; - double *trow_vec = csa->trow_vec; - int j, k, beg, end, ptr, nnz; - double temp; - /* compute the pivot row as inner products of columns of the - matrix N and vector rho: trow[j] = - rho * N[j] */ - nnz = 0; - for (j = 1; j <= n; j++) - { if (stat[j] == GLP_NS) - { /* xN[j] is fixed */ - trow_vec[j] = 0.0; - continue; - } - k = head[m+j]; /* x[k] = xN[j] */ - if (k <= m) - { /* N[j] is k-th column of submatrix I */ - temp = - rho[k]; - } - else - { /* N[j] is (k-m)-th column of submatrix (-A) */ - beg = A_ptr[k-m], end = A_ptr[k-m+1]; - temp = 0.0; - for (ptr = beg; ptr < end; ptr++) - temp += rho[A_ind[ptr]] * A_val[ptr]; - } - if (temp != 0.0) - trow_ind[++nnz] = j; - trow_vec[j] = temp; - } - csa->trow_nnz = nnz; - return; -} - -static void eval_trow2(struct csa *csa, double rho[]) -{ int m = csa->m; - int n = csa->n; - int *AT_ptr = csa->AT_ptr; - int *AT_ind = csa->AT_ind; - double *AT_val = csa->AT_val; - int *bind = csa->bind; - char *stat = csa->stat; - int *trow_ind = csa->trow_ind; - double *trow_vec = csa->trow_vec; - int i, j, beg, end, ptr, nnz; - double temp; - /* clear the pivot row */ - for (j = 1; j <= n; j++) - trow_vec[j] = 0.0; - /* compute the pivot row as a linear combination of rows of the - matrix N: trow = - rho[1] * N'[1] - ... - rho[m] * N'[m] */ - for (i = 1; i <= m; i++) - { temp = rho[i]; - if (temp == 0.0) continue; - /* trow := trow - rho[i] * N'[i] */ - j = bind[i] - m; /* x[i] = xN[j] */ - if (j >= 1 && stat[j] != GLP_NS) - trow_vec[j] -= temp; - beg = AT_ptr[i], end = AT_ptr[i+1]; - for (ptr = beg; ptr < end; ptr++) - { j = bind[m + AT_ind[ptr]] - m; /* x[k] = xN[j] */ - if (j >= 1 && stat[j] != GLP_NS) - trow_vec[j] += temp * AT_val[ptr]; - } - } - /* construct sparse pattern of the pivot row */ - nnz = 0; - for (j = 1; j <= n; j++) - { if (trow_vec[j] != 0.0) - trow_ind[++nnz] = j; - } - csa->trow_nnz = nnz; - return; -} - -static void eval_trow(struct csa *csa, double rho[]) -{ int m = csa->m; - int i, nnz; - double dens; - /* determine the density of the vector rho */ - nnz = 0; - for (i = 1; i <= m; i++) - if (rho[i] != 0.0) nnz++; - dens = (double)nnz / (double)m; - if (dens >= 0.20) - { /* rho is relatively dense */ - eval_trow1(csa, rho); - } - else - { /* rho is relatively sparse */ - eval_trow2(csa, rho); - } - return; -} -#endif - -/*********************************************************************** -* sort_trow - sort pivot row of the simplex table -* -* This routine reorders the list of non-zero elements of the pivot -* row to put significant elements, whose magnitude is not less than -* a specified tolerance, in front of the list, and stores the number -* of significant elements in trow_num. */ - -static void sort_trow(struct csa *csa, double tol_piv) -{ -#ifdef GLP_DEBUG - int n = csa->n; - char *stat = csa->stat; -#endif - int nnz = csa->trow_nnz; - int *trow_ind = csa->trow_ind; - double *trow_vec = csa->trow_vec; - int j, num, pos; - double big, eps, temp; - /* compute infinity (maximum) norm of the row */ - big = 0.0; - for (pos = 1; pos <= nnz; pos++) - { -#ifdef GLP_DEBUG - j = trow_ind[pos]; - xassert(1 <= j && j <= n); - xassert(stat[j] != GLP_NS); -#endif - temp = fabs(trow_vec[trow_ind[pos]]); - if (big < temp) big = temp; - } - csa->trow_max = big; - /* determine absolute pivot tolerance */ - eps = tol_piv * (1.0 + 0.01 * big); - /* move significant row components to the front of the list */ - for (num = 0; num < nnz; ) - { j = trow_ind[nnz]; - if (fabs(trow_vec[j]) < eps) - nnz--; - else - { num++; - trow_ind[nnz] = trow_ind[num]; - trow_ind[num] = j; - } - } - csa->trow_num = num; - return; -} - -#ifdef GLP_LONG_STEP /* 07/IV-2009 */ -static int ls_func(const void *p1_, const void *p2_) -{ const struct bkpt *p1 = p1_, *p2 = p2_; - if (p1->t < p2->t) return -1; - if (p1->t > p2->t) return +1; - return 0; -} - -static int ls_func1(const void *p1_, const void *p2_) -{ const struct bkpt *p1 = p1_, *p2 = p2_; - if (p1->dz < p2->dz) return -1; - if (p1->dz > p2->dz) return +1; - return 0; -} - -static void long_step(struct csa *csa) -{ int m = csa->m; -#ifdef GLP_DEBUG - int n = csa->n; -#endif - char *type = csa->type; - double *lb = csa->lb; - double *ub = csa->ub; - int *head = csa->head; - char *stat = csa->stat; - double *cbar = csa->cbar; - double delta = csa->delta; - int *trow_ind = csa->trow_ind; - double *trow_vec = csa->trow_vec; - int trow_num = csa->trow_num; - struct bkpt *bkpt = csa->bkpt; - int j, k, kk, nbps, pos; - double alfa, s, slope, dzmax; - /* delta > 0 means that xB[p] violates its lower bound, so to - increase the dual objective lambdaB[p] must increase; - delta < 0 means that xB[p] violates its upper bound, so to - increase the dual objective lambdaB[p] must decrease */ - /* s := sign(delta) */ - s = (delta > 0.0 ? +1.0 : -1.0); - /* determine breakpoints of the dual objective */ - nbps = 0; - for (pos = 1; pos <= trow_num; pos++) - { j = trow_ind[pos]; -#ifdef GLP_DEBUG - xassert(1 <= j && j <= n); - xassert(stat[j] != GLP_NS); -#endif - /* if there is free non-basic variable, switch to the standard - ratio test */ - if (stat[j] == GLP_NF) - { nbps = 0; - goto done; - } - /* lambdaN[j] = ... - alfa * t - ..., where t = s * lambdaB[i] - is the dual ray parameter, t >= 0 */ - alfa = s * trow_vec[j]; -#ifdef GLP_DEBUG - xassert(alfa != 0.0); - xassert(stat[j] == GLP_NL || stat[j] == GLP_NU); -#endif - if (alfa > 0.0 && stat[j] == GLP_NL || - alfa < 0.0 && stat[j] == GLP_NU) - { /* either lambdaN[j] >= 0 (if stat = GLP_NL) and decreases - or lambdaN[j] <= 0 (if stat = GLP_NU) and increases; in - both cases we have a breakpoint */ - nbps++; -#ifdef GLP_DEBUG - xassert(nbps <= n); -#endif - bkpt[nbps].j = j; - bkpt[nbps].t = cbar[j] / alfa; -/* -if (stat[j] == GLP_NL && cbar[j] < 0.0 || - stat[j] == GLP_NU && cbar[j] > 0.0) -xprintf("%d %g\n", stat[j], cbar[j]); -*/ - /* if t is negative, replace it by exact zero (see comments - in the routine chuzc) */ - if (bkpt[nbps].t < 0.0) bkpt[nbps].t = 0.0; - } - } - /* if there are less than two breakpoints, switch to the standard - ratio test */ - if (nbps < 2) - { nbps = 0; - goto done; - } - /* sort breakpoints by ascending the dual ray parameter, t */ - qsort(&bkpt[1], nbps, sizeof(struct bkpt), ls_func); - /* determine last breakpoint, at which the dual objective still - greater than at t = 0 */ - dzmax = 0.0; - slope = fabs(delta); /* initial slope */ - for (kk = 1; kk <= nbps; kk++) - { if (kk == 1) - bkpt[kk].dz = - 0.0 + slope * (bkpt[kk].t - 0.0); - else - bkpt[kk].dz = - bkpt[kk-1].dz + slope * (bkpt[kk].t - bkpt[kk-1].t); - if (dzmax < bkpt[kk].dz) - dzmax = bkpt[kk].dz; - else if (bkpt[kk].dz < 0.05 * (1.0 + dzmax)) - { nbps = kk - 1; - break; - } - j = bkpt[kk].j; - k = head[m+j]; /* x[k] = xN[j] */ - if (type[k] == GLP_DB) - slope -= fabs(trow_vec[j]) * (ub[k] - lb[k]); - else - { nbps = kk; - break; - } - } - /* if there are less than two breakpoints, switch to the standard - ratio test */ - if (nbps < 2) - { nbps = 0; - goto done; - } - /* sort breakpoints by ascending the dual change, dz */ - qsort(&bkpt[1], nbps, sizeof(struct bkpt), ls_func1); -/* -for (kk = 1; kk <= nbps; kk++) -xprintf("%d; t = %g; dz = %g\n", kk, bkpt[kk].t, bkpt[kk].dz); -*/ -done: csa->nbps = nbps; - return; -} -#endif - -/*********************************************************************** -* chuzc - choose non-basic variable (column of the simplex table) -* -* This routine chooses non-basic variable xN[q], which being entered -* in the basis keeps dual feasibility of the basic solution. -* -* The parameter rtol is a relative tolerance used to relax zero bounds -* of reduced costs of non-basic variables. If rtol = 0, the routine -* implements the standard ratio test. Otherwise, if rtol > 0, the -* routine implements Harris' two-pass ratio test. In the latter case -* rtol should be about three times less than a tolerance used to check -* dual feasibility. */ - -static void chuzc(struct csa *csa, double rtol) -{ -#ifdef GLP_DEBUG - int m = csa->m; - int n = csa->n; -#endif - char *stat = csa->stat; - double *cbar = csa->cbar; -#ifdef GLP_DEBUG - int p = csa->p; -#endif - double delta = csa->delta; - int *trow_ind = csa->trow_ind; - double *trow_vec = csa->trow_vec; - int trow_num = csa->trow_num; - int j, pos, q; - double alfa, big, s, t, teta, tmax; -#ifdef GLP_DEBUG - xassert(1 <= p && p <= m); -#endif - /* delta > 0 means that xB[p] violates its lower bound and goes - to it in the adjacent basis, so lambdaB[p] is increasing from - its lower zero bound; - delta < 0 means that xB[p] violates its upper bound and goes - to it in the adjacent basis, so lambdaB[p] is decreasing from - its upper zero bound */ -#ifdef GLP_DEBUG - xassert(delta != 0.0); -#endif - /* s := sign(delta) */ - s = (delta > 0.0 ? +1.0 : -1.0); - /*** FIRST PASS ***/ - /* nothing is chosen so far */ - q = 0, teta = DBL_MAX, big = 0.0; - /* walk through significant elements of the pivot row */ - for (pos = 1; pos <= trow_num; pos++) - { j = trow_ind[pos]; -#ifdef GLP_DEBUG - xassert(1 <= j && j <= n); -#endif - alfa = s * trow_vec[j]; -#ifdef GLP_DEBUG - xassert(alfa != 0.0); -#endif - /* lambdaN[j] = ... - alfa * lambdaB[p] - ..., and due to s we - need to consider only increasing lambdaB[p] */ - if (alfa > 0.0) - { /* lambdaN[j] is decreasing */ - if (stat[j] == GLP_NL || stat[j] == GLP_NF) - { /* lambdaN[j] has zero lower bound */ - t = (cbar[j] + rtol) / alfa; - } - else - { /* lambdaN[j] has no lower bound */ - continue; - } - } - else - { /* lambdaN[j] is increasing */ - if (stat[j] == GLP_NU || stat[j] == GLP_NF) - { /* lambdaN[j] has zero upper bound */ - t = (cbar[j] - rtol) / alfa; - } - else - { /* lambdaN[j] has no upper bound */ - continue; - } - } - /* t is a change of lambdaB[p], on which lambdaN[j] reaches - its zero bound (possibly relaxed); since the basic solution - is assumed to be dual feasible, t has to be non-negative by - definition; however, it may happen that lambdaN[j] slightly - (i.e. within a tolerance) violates its zero bound, that - leads to negative t; in the latter case, if xN[j] is chosen, - negative t means that lambdaB[p] changes in wrong direction - that may cause wrong results on updating reduced costs; - thus, if t is negative, we should replace it by exact zero - assuming that lambdaN[j] is exactly on its zero bound, and - violation appears due to round-off errors */ - if (t < 0.0) t = 0.0; - /* apply minimal ratio test */ - if (teta > t || teta == t && big < fabs(alfa)) - q = j, teta = t, big = fabs(alfa); - } - /* the second pass is skipped in the following cases: */ - /* if the standard ratio test is used */ - if (rtol == 0.0) goto done; - /* if no non-basic variable has been chosen on the first pass */ - if (q == 0) goto done; - /* if lambdaN[q] prevents lambdaB[p] from any change */ - if (teta == 0.0) goto done; - /*** SECOND PASS ***/ - /* here tmax is a maximal change of lambdaB[p], on which the - solution remains dual feasible within a tolerance */ -#if 0 - tmax = (1.0 + 10.0 * DBL_EPSILON) * teta; -#else - tmax = teta; -#endif - /* nothing is chosen so far */ - q = 0, teta = DBL_MAX, big = 0.0; - /* walk through significant elements of the pivot row */ - for (pos = 1; pos <= trow_num; pos++) - { j = trow_ind[pos]; -#ifdef GLP_DEBUG - xassert(1 <= j && j <= n); -#endif - alfa = s * trow_vec[j]; -#ifdef GLP_DEBUG - xassert(alfa != 0.0); -#endif - /* lambdaN[j] = ... - alfa * lambdaB[p] - ..., and due to s we - need to consider only increasing lambdaB[p] */ - if (alfa > 0.0) - { /* lambdaN[j] is decreasing */ - if (stat[j] == GLP_NL || stat[j] == GLP_NF) - { /* lambdaN[j] has zero lower bound */ - t = cbar[j] / alfa; - } - else - { /* lambdaN[j] has no lower bound */ - continue; - } - } - else - { /* lambdaN[j] is increasing */ - if (stat[j] == GLP_NU || stat[j] == GLP_NF) - { /* lambdaN[j] has zero upper bound */ - t = cbar[j] / alfa; - } - else - { /* lambdaN[j] has no upper bound */ - continue; - } - } - /* (see comments for the first pass) */ - if (t < 0.0) t = 0.0; - /* t is a change of lambdaB[p], on which lambdaN[j] reaches - its zero (lower or upper) bound; if t <= tmax, all reduced - costs can violate their zero bounds only within relaxation - tolerance rtol, so we can choose non-basic variable having - largest influence coefficient to avoid possible numerical - instability */ - if (t <= tmax && big < fabs(alfa)) - q = j, teta = t, big = fabs(alfa); - } - /* something must be chosen on the second pass */ - xassert(q != 0); -done: /* store the index of non-basic variable xN[q] chosen */ - csa->q = q; - /* store reduced cost of xN[q] in the adjacent basis */ - csa->new_dq = s * teta; - return; -} - -#if 1 /* copied from primal */ -/*********************************************************************** -* eval_tcol - compute pivot column of the simplex table -* -* This routine computes the pivot column of the simplex table, which -* corresponds to non-basic variable xN[q] chosen. -* -* The pivot column is the following vector: -* -* tcol = T * e[q] = - inv(B) * N * e[q] = - inv(B) * N[q], -* -* where B is the current basis matrix, N[q] is a column of the matrix -* (I|-A) corresponding to variable xN[q]. */ - -static void eval_tcol(struct csa *csa) -{ int m = csa->m; -#ifdef GLP_DEBUG - int n = csa->n; -#endif - int *head = csa->head; - int q = csa->q; - int *tcol_ind = csa->tcol_ind; - double *tcol_vec = csa->tcol_vec; - double *h = csa->tcol_vec; - int i, k, nnz; -#ifdef GLP_DEBUG - xassert(1 <= q && q <= n); -#endif - k = head[m+q]; /* x[k] = xN[q] */ -#ifdef GLP_DEBUG - xassert(1 <= k && k <= m+n); -#endif - /* construct the right-hand side vector h = - N[q] */ - for (i = 1; i <= m; i++) - h[i] = 0.0; - if (k <= m) - { /* N[q] is k-th column of submatrix I */ - h[k] = -1.0; - } - else - { /* N[q] is (k-m)-th column of submatrix (-A) */ - int *A_ptr = csa->A_ptr; - int *A_ind = csa->A_ind; - double *A_val = csa->A_val; - int beg, end, ptr; - beg = A_ptr[k-m]; - end = A_ptr[k-m+1]; - for (ptr = beg; ptr < end; ptr++) - h[A_ind[ptr]] = A_val[ptr]; - } - /* solve system B * tcol = h */ - xassert(csa->valid); - bfd_ftran(csa->bfd, tcol_vec); - /* construct sparse pattern of the pivot column */ - nnz = 0; - for (i = 1; i <= m; i++) - { if (tcol_vec[i] != 0.0) - tcol_ind[++nnz] = i; - } - csa->tcol_nnz = nnz; - return; -} -#endif - -#if 1 /* copied from primal */ -/*********************************************************************** -* refine_tcol - refine pivot column of the simplex table -* -* This routine refines the pivot column of the simplex table assuming -* that it was previously computed by the routine eval_tcol. */ - -static void refine_tcol(struct csa *csa) -{ int m = csa->m; -#ifdef GLP_DEBUG - int n = csa->n; -#endif - int *head = csa->head; - int q = csa->q; - int *tcol_ind = csa->tcol_ind; - double *tcol_vec = csa->tcol_vec; - double *h = csa->work3; - int i, k, nnz; -#ifdef GLP_DEBUG - xassert(1 <= q && q <= n); -#endif - k = head[m+q]; /* x[k] = xN[q] */ -#ifdef GLP_DEBUG - xassert(1 <= k && k <= m+n); -#endif - /* construct the right-hand side vector h = - N[q] */ - for (i = 1; i <= m; i++) - h[i] = 0.0; - if (k <= m) - { /* N[q] is k-th column of submatrix I */ - h[k] = -1.0; - } - else - { /* N[q] is (k-m)-th column of submatrix (-A) */ - int *A_ptr = csa->A_ptr; - int *A_ind = csa->A_ind; - double *A_val = csa->A_val; - int beg, end, ptr; - beg = A_ptr[k-m]; - end = A_ptr[k-m+1]; - for (ptr = beg; ptr < end; ptr++) - h[A_ind[ptr]] = A_val[ptr]; - } - /* refine solution of B * tcol = h */ - refine_ftran(csa, h, tcol_vec); - /* construct sparse pattern of the pivot column */ - nnz = 0; - for (i = 1; i <= m; i++) - { if (tcol_vec[i] != 0.0) - tcol_ind[++nnz] = i; - } - csa->tcol_nnz = nnz; - return; -} -#endif - -/*********************************************************************** -* update_cbar - update reduced costs of non-basic variables -* -* This routine updates reduced costs of all (except fixed) non-basic -* variables for the adjacent basis. */ - -static void update_cbar(struct csa *csa) -{ -#ifdef GLP_DEBUG - int n = csa->n; -#endif - double *cbar = csa->cbar; - int trow_nnz = csa->trow_nnz; - int *trow_ind = csa->trow_ind; - double *trow_vec = csa->trow_vec; - int q = csa->q; - double new_dq = csa->new_dq; - int j, pos; -#ifdef GLP_DEBUG - xassert(1 <= q && q <= n); -#endif - /* set new reduced cost of xN[q] */ - cbar[q] = new_dq; - /* update reduced costs of other non-basic variables */ - if (new_dq == 0.0) goto done; - for (pos = 1; pos <= trow_nnz; pos++) - { j = trow_ind[pos]; -#ifdef GLP_DEBUG - xassert(1 <= j && j <= n); -#endif - if (j != q) - cbar[j] -= trow_vec[j] * new_dq; - } -done: return; -} - -/*********************************************************************** -* update_bbar - update values of basic variables -* -* This routine updates values of all basic variables for the adjacent -* basis. */ - -static void update_bbar(struct csa *csa) -{ -#ifdef GLP_DEBUG - int m = csa->m; - int n = csa->n; -#endif - double *bbar = csa->bbar; - int p = csa->p; - double delta = csa->delta; - int q = csa->q; - int tcol_nnz = csa->tcol_nnz; - int *tcol_ind = csa->tcol_ind; - double *tcol_vec = csa->tcol_vec; - int i, pos; - double teta; -#ifdef GLP_DEBUG - xassert(1 <= p && p <= m); - xassert(1 <= q && q <= n); -#endif - /* determine the change of xN[q] in the adjacent basis */ -#ifdef GLP_DEBUG - xassert(tcol_vec[p] != 0.0); -#endif - teta = delta / tcol_vec[p]; - /* set new primal value of xN[q] */ - bbar[p] = get_xN(csa, q) + teta; - /* update primal values of other basic variables */ - if (teta == 0.0) goto done; - for (pos = 1; pos <= tcol_nnz; pos++) - { i = tcol_ind[pos]; -#ifdef GLP_DEBUG - xassert(1 <= i && i <= m); -#endif - if (i != p) - bbar[i] += tcol_vec[i] * teta; - } -done: return; -} - -/*********************************************************************** -* update_gamma - update steepest edge coefficients -* -* This routine updates steepest-edge coefficients for the adjacent -* basis. */ - -static void update_gamma(struct csa *csa) -{ int m = csa->m; -#ifdef GLP_DEBUG - int n = csa->n; -#endif - char *type = csa->type; - int *head = csa->head; - char *refsp = csa->refsp; - double *gamma = csa->gamma; - int p = csa->p; - int trow_nnz = csa->trow_nnz; - int *trow_ind = csa->trow_ind; - double *trow_vec = csa->trow_vec; - int q = csa->q; - int tcol_nnz = csa->tcol_nnz; - int *tcol_ind = csa->tcol_ind; - double *tcol_vec = csa->tcol_vec; - double *u = csa->work3; - int i, j, k,pos; - double gamma_p, eta_p, pivot, t, t1, t2; -#ifdef GLP_DEBUG - xassert(1 <= p && p <= m); - xassert(1 <= q && q <= n); -#endif - /* the basis changes, so decrease the count */ - xassert(csa->refct > 0); - csa->refct--; - /* recompute gamma[p] for the current basis more accurately and - compute auxiliary vector u */ -#ifdef GLP_DEBUG - xassert(type[head[p]] != GLP_FR); -#endif - gamma_p = eta_p = (refsp[head[p]] ? 1.0 : 0.0); - for (i = 1; i <= m; i++) u[i] = 0.0; - for (pos = 1; pos <= trow_nnz; pos++) - { j = trow_ind[pos]; -#ifdef GLP_DEBUG - xassert(1 <= j && j <= n); -#endif - k = head[m+j]; /* x[k] = xN[j] */ -#ifdef GLP_DEBUG - xassert(1 <= k && k <= m+n); - xassert(type[k] != GLP_FX); -#endif - if (!refsp[k]) continue; - t = trow_vec[j]; - gamma_p += t * t; - /* u := u + N[j] * delta[j] * trow[j] */ - if (k <= m) - { /* N[k] = k-j stolbec submatrix I */ - u[k] += t; - } - else - { /* N[k] = k-m-k stolbec (-A) */ - int *A_ptr = csa->A_ptr; - int *A_ind = csa->A_ind; - double *A_val = csa->A_val; - int beg, end, ptr; - beg = A_ptr[k-m]; - end = A_ptr[k-m+1]; - for (ptr = beg; ptr < end; ptr++) - u[A_ind[ptr]] -= t * A_val[ptr]; - } - } - xassert(csa->valid); - bfd_ftran(csa->bfd, u); - /* update gamma[i] for other basic variables (except xB[p] and - free variables) */ - pivot = tcol_vec[p]; -#ifdef GLP_DEBUG - xassert(pivot != 0.0); -#endif - for (pos = 1; pos <= tcol_nnz; pos++) - { i = tcol_ind[pos]; -#ifdef GLP_DEBUG - xassert(1 <= i && i <= m); -#endif - k = head[i]; -#ifdef GLP_DEBUG - xassert(1 <= k && k <= m+n); -#endif - /* skip xB[p] */ - if (i == p) continue; - /* skip free basic variable */ - if (type[head[i]] == GLP_FR) - { -#ifdef GLP_DEBUG - xassert(gamma[i] == 1.0); -#endif - continue; - } - /* compute gamma[i] for the adjacent basis */ - t = tcol_vec[i] / pivot; - t1 = gamma[i] + t * t * gamma_p + 2.0 * t * u[i]; - t2 = (refsp[k] ? 1.0 : 0.0) + eta_p * t * t; - gamma[i] = (t1 >= t2 ? t1 : t2); - /* (though gamma[i] can be exact zero, because the reference - space does not include non-basic fixed variables) */ - if (gamma[i] < DBL_EPSILON) gamma[i] = DBL_EPSILON; - } - /* compute gamma[p] for the adjacent basis */ - if (type[head[m+q]] == GLP_FR) - gamma[p] = 1.0; - else - { gamma[p] = gamma_p / (pivot * pivot); - if (gamma[p] < DBL_EPSILON) gamma[p] = DBL_EPSILON; - } - /* if xB[p], which becomes xN[q] in the adjacent basis, is fixed - and belongs to the reference space, remove it from there, and - change all gamma's appropriately */ - k = head[p]; - if (type[k] == GLP_FX && refsp[k]) - { refsp[k] = 0; - for (pos = 1; pos <= tcol_nnz; pos++) - { i = tcol_ind[pos]; - if (i == p) - { if (type[head[m+q]] == GLP_FR) continue; - t = 1.0 / tcol_vec[p]; - } - else - { if (type[head[i]] == GLP_FR) continue; - t = tcol_vec[i] / tcol_vec[p]; - } - gamma[i] -= t * t; - if (gamma[i] < DBL_EPSILON) gamma[i] = DBL_EPSILON; - } - } - return; -} - -#if 1 /* copied from primal */ -/*********************************************************************** -* err_in_bbar - compute maximal relative error in primal solution -* -* This routine returns maximal relative error: -* -* max |beta[i] - bbar[i]| / (1 + |beta[i]|), -* -* where beta and bbar are, respectively, directly computed and the -* current (updated) values of basic variables. -* -* NOTE: The routine is intended only for debugginig purposes. */ - -static double err_in_bbar(struct csa *csa) -{ int m = csa->m; - double *bbar = csa->bbar; - int i; - double e, emax, *beta; - beta = xcalloc(1+m, sizeof(double)); - eval_beta(csa, beta); - emax = 0.0; - for (i = 1; i <= m; i++) - { e = fabs(beta[i] - bbar[i]) / (1.0 + fabs(beta[i])); - if (emax < e) emax = e; - } - xfree(beta); - return emax; -} -#endif - -#if 1 /* copied from primal */ -/*********************************************************************** -* err_in_cbar - compute maximal relative error in dual solution -* -* This routine returns maximal relative error: -* -* max |cost[j] - cbar[j]| / (1 + |cost[j]|), -* -* where cost and cbar are, respectively, directly computed and the -* current (updated) reduced costs of non-basic non-fixed variables. -* -* NOTE: The routine is intended only for debugginig purposes. */ - -static double err_in_cbar(struct csa *csa) -{ int m = csa->m; - int n = csa->n; - char *stat = csa->stat; - double *cbar = csa->cbar; - int j; - double e, emax, cost, *pi; - pi = xcalloc(1+m, sizeof(double)); - eval_pi(csa, pi); - emax = 0.0; - for (j = 1; j <= n; j++) - { if (stat[j] == GLP_NS) continue; - cost = eval_cost(csa, pi, j); - e = fabs(cost - cbar[j]) / (1.0 + fabs(cost)); - if (emax < e) emax = e; - } - xfree(pi); - return emax; -} -#endif - -/*********************************************************************** -* err_in_gamma - compute maximal relative error in steepest edge cff. -* -* This routine returns maximal relative error: -* -* max |gamma'[j] - gamma[j]| / (1 + |gamma'[j]), -* -* where gamma'[j] and gamma[j] are, respectively, directly computed -* and the current (updated) steepest edge coefficients for non-basic -* non-fixed variable x[j]. -* -* NOTE: The routine is intended only for debugginig purposes. */ - -static double err_in_gamma(struct csa *csa) -{ int m = csa->m; - char *type = csa->type; - int *head = csa->head; - double *gamma = csa->gamma; - double *exact = csa->work4; - int i; - double e, emax, temp; - eval_gamma(csa, exact); - emax = 0.0; - for (i = 1; i <= m; i++) - { if (type[head[i]] == GLP_FR) - { xassert(gamma[i] == 1.0); - xassert(exact[i] == 1.0); - continue; - } - temp = exact[i]; - e = fabs(temp - gamma[i]) / (1.0 + fabs(temp)); - if (emax < e) emax = e; - } - return emax; -} - -/*********************************************************************** -* change_basis - change basis header -* -* This routine changes the basis header to make it corresponding to -* the adjacent basis. */ - -static void change_basis(struct csa *csa) -{ int m = csa->m; -#ifdef GLP_DEBUG - int n = csa->n; -#endif - char *type = csa->type; - int *head = csa->head; -#if 1 /* 06/IV-2009 */ - int *bind = csa->bind; -#endif - char *stat = csa->stat; - int p = csa->p; - double delta = csa->delta; - int q = csa->q; - int k; - /* xB[p] leaves the basis, xN[q] enters the basis */ -#ifdef GLP_DEBUG - xassert(1 <= p && p <= m); - xassert(1 <= q && q <= n); -#endif - /* xB[p] <-> xN[q] */ - k = head[p], head[p] = head[m+q], head[m+q] = k; -#if 1 /* 06/IV-2009 */ - bind[head[p]] = p, bind[head[m+q]] = m + q; -#endif - if (type[k] == GLP_FX) - stat[q] = GLP_NS; - else if (delta > 0.0) - { -#ifdef GLP_DEBUG - xassert(type[k] == GLP_LO || type[k] == GLP_DB); -#endif - stat[q] = GLP_NL; - } - else /* delta < 0.0 */ - { -#ifdef GLP_DEBUG - xassert(type[k] == GLP_UP || type[k] == GLP_DB); -#endif - stat[q] = GLP_NU; - } - return; -} - -/*********************************************************************** -* check_feas - check dual feasibility of basic solution -* -* If the current basic solution is dual feasible within a tolerance, -* this routine returns zero, otherwise it returns non-zero. */ - -static int check_feas(struct csa *csa, double tol_dj) -{ int m = csa->m; - int n = csa->n; - char *orig_type = csa->orig_type; - int *head = csa->head; - double *cbar = csa->cbar; - int j, k; - for (j = 1; j <= n; j++) - { k = head[m+j]; /* x[k] = xN[j] */ -#ifdef GLP_DEBUG - xassert(1 <= k && k <= m+n); -#endif - if (cbar[j] < - tol_dj) - if (orig_type[k] == GLP_LO || orig_type[k] == GLP_FR) - return 1; - if (cbar[j] > + tol_dj) - if (orig_type[k] == GLP_UP || orig_type[k] == GLP_FR) - return 1; - } - return 0; -} - -/*********************************************************************** -* set_aux_bnds - assign auxiliary bounds to variables -* -* This routine assigns auxiliary bounds to variables to construct an -* LP problem solved on phase I. */ - -static void set_aux_bnds(struct csa *csa) -{ int m = csa->m; - int n = csa->n; - char *type = csa->type; - double *lb = csa->lb; - double *ub = csa->ub; - char *orig_type = csa->orig_type; - int *head = csa->head; - char *stat = csa->stat; - double *cbar = csa->cbar; - int j, k; - for (k = 1; k <= m+n; k++) - { switch (orig_type[k]) - { case GLP_FR: -#if 0 - type[k] = GLP_DB, lb[k] = -1.0, ub[k] = +1.0; -#else - /* to force free variables to enter the basis */ - type[k] = GLP_DB, lb[k] = -1e3, ub[k] = +1e3; -#endif - break; - case GLP_LO: - type[k] = GLP_DB, lb[k] = 0.0, ub[k] = +1.0; - break; - case GLP_UP: - type[k] = GLP_DB, lb[k] = -1.0, ub[k] = 0.0; - break; - case GLP_DB: - case GLP_FX: - type[k] = GLP_FX, lb[k] = ub[k] = 0.0; - break; - default: - xassert(orig_type != orig_type); - } - } - for (j = 1; j <= n; j++) - { k = head[m+j]; /* x[k] = xN[j] */ -#ifdef GLP_DEBUG - xassert(1 <= k && k <= m+n); -#endif - if (type[k] == GLP_FX) - stat[j] = GLP_NS; - else if (cbar[j] >= 0.0) - stat[j] = GLP_NL; - else - stat[j] = GLP_NU; - } - return; -} - -/*********************************************************************** -* set_orig_bnds - restore original bounds of variables -* -* This routine restores original types and bounds of variables and -* determines statuses of non-basic variables assuming that the current -* basis is dual feasible. */ - -static void set_orig_bnds(struct csa *csa) -{ int m = csa->m; - int n = csa->n; - char *type = csa->type; - double *lb = csa->lb; - double *ub = csa->ub; - char *orig_type = csa->orig_type; - double *orig_lb = csa->orig_lb; - double *orig_ub = csa->orig_ub; - int *head = csa->head; - char *stat = csa->stat; - double *cbar = csa->cbar; - int j, k; - memcpy(&type[1], &orig_type[1], (m+n) * sizeof(char)); - memcpy(&lb[1], &orig_lb[1], (m+n) * sizeof(double)); - memcpy(&ub[1], &orig_ub[1], (m+n) * sizeof(double)); - for (j = 1; j <= n; j++) - { k = head[m+j]; /* x[k] = xN[j] */ -#ifdef GLP_DEBUG - xassert(1 <= k && k <= m+n); -#endif - switch (type[k]) - { case GLP_FR: - stat[j] = GLP_NF; - break; - case GLP_LO: - stat[j] = GLP_NL; - break; - case GLP_UP: - stat[j] = GLP_NU; - break; - case GLP_DB: - if (cbar[j] >= +DBL_EPSILON) - stat[j] = GLP_NL; - else if (cbar[j] <= -DBL_EPSILON) - stat[j] = GLP_NU; - else if (fabs(lb[k]) <= fabs(ub[k])) - stat[j] = GLP_NL; - else - stat[j] = GLP_NU; - break; - case GLP_FX: - stat[j] = GLP_NS; - break; - default: - xassert(type != type); - } - } - return; -} - -/*********************************************************************** -* check_stab - check numerical stability of basic solution -* -* If the current basic solution is dual feasible within a tolerance, -* this routine returns zero, otherwise it returns non-zero. */ - -static int check_stab(struct csa *csa, double tol_dj) -{ int n = csa->n; - char *stat = csa->stat; - double *cbar = csa->cbar; - int j; - for (j = 1; j <= n; j++) - { if (cbar[j] < - tol_dj) - if (stat[j] == GLP_NL || stat[j] == GLP_NF) return 1; - if (cbar[j] > + tol_dj) - if (stat[j] == GLP_NU || stat[j] == GLP_NF) return 1; - } - return 0; -} - -#if 1 /* copied from primal */ -/*********************************************************************** -* eval_obj - compute original objective function -* -* This routine computes the current value of the original objective -* function. */ - -static double eval_obj(struct csa *csa) -{ int m = csa->m; - int n = csa->n; - double *obj = csa->obj; - int *head = csa->head; - double *bbar = csa->bbar; - int i, j, k; - double sum; - sum = obj[0]; - /* walk through the list of basic variables */ - for (i = 1; i <= m; i++) - { k = head[i]; /* x[k] = xB[i] */ -#ifdef GLP_DEBUG - xassert(1 <= k && k <= m+n); -#endif - if (k > m) - sum += obj[k-m] * bbar[i]; - } - /* walk through the list of non-basic variables */ - for (j = 1; j <= n; j++) - { k = head[m+j]; /* x[k] = xN[j] */ -#ifdef GLP_DEBUG - xassert(1 <= k && k <= m+n); -#endif - if (k > m) - sum += obj[k-m] * get_xN(csa, j); - } - return sum; -} -#endif - -/*********************************************************************** -* display - display the search progress -* -* This routine displays some information about the search progress. */ - -static void display(struct csa *csa, const glp_smcp *parm, int spec) -{ int m = csa->m; - int n = csa->n; - double *coef = csa->coef; - char *orig_type = csa->orig_type; - int *head = csa->head; - char *stat = csa->stat; - int phase = csa->phase; - double *bbar = csa->bbar; - double *cbar = csa->cbar; - int i, j, cnt; - double sum; - if (parm->msg_lev < GLP_MSG_ON) goto skip; - if (parm->out_dly > 0 && - 1000.0 * xdifftime(xtime(), csa->tm_beg) < parm->out_dly) - goto skip; - if (csa->it_cnt == csa->it_dpy) goto skip; - if (!spec && csa->it_cnt % parm->out_frq != 0) goto skip; - /* compute the sum of dual infeasibilities */ - sum = 0.0; - if (phase == 1) - { for (i = 1; i <= m; i++) - sum -= coef[head[i]] * bbar[i]; - for (j = 1; j <= n; j++) - sum -= coef[head[m+j]] * get_xN(csa, j); - } - else - { for (j = 1; j <= n; j++) - { if (cbar[j] < 0.0) - if (stat[j] == GLP_NL || stat[j] == GLP_NF) - sum -= cbar[j]; - if (cbar[j] > 0.0) - if (stat[j] == GLP_NU || stat[j] == GLP_NF) - sum += cbar[j]; - } - } - /* determine the number of basic fixed variables */ - cnt = 0; - for (i = 1; i <= m; i++) - if (orig_type[head[i]] == GLP_FX) cnt++; - if (csa->phase == 1) - xprintf(" %6d: %24s infeas = %10.3e (%d)\n", - csa->it_cnt, "", sum, cnt); - else - xprintf("|%6d: obj = %17.9e infeas = %10.3e (%d)\n", - csa->it_cnt, eval_obj(csa), sum, cnt); - csa->it_dpy = csa->it_cnt; -skip: return; -} - -#if 1 /* copied from primal */ -/*********************************************************************** -* store_sol - store basic solution back to the problem object -* -* This routine stores basic solution components back to the problem -* object. */ - -static void store_sol(struct csa *csa, glp_prob *lp, int p_stat, - int d_stat, int ray) -{ int m = csa->m; - int n = csa->n; - double zeta = csa->zeta; - int *head = csa->head; - char *stat = csa->stat; - double *bbar = csa->bbar; - double *cbar = csa->cbar; - int i, j, k; -#ifdef GLP_DEBUG - xassert(lp->m == m); - xassert(lp->n == n); -#endif - /* basis factorization */ -#ifdef GLP_DEBUG - xassert(!lp->valid && lp->bfd == NULL); - xassert(csa->valid && csa->bfd != NULL); -#endif - lp->valid = 1, csa->valid = 0; - lp->bfd = csa->bfd, csa->bfd = NULL; - memcpy(&lp->head[1], &head[1], m * sizeof(int)); - /* basic solution status */ - lp->pbs_stat = p_stat; - lp->dbs_stat = d_stat; - /* objective function value */ - lp->obj_val = eval_obj(csa); - /* simplex iteration count */ - lp->it_cnt = csa->it_cnt; - /* unbounded ray */ - lp->some = ray; - /* basic variables */ - for (i = 1; i <= m; i++) - { k = head[i]; /* x[k] = xB[i] */ -#ifdef GLP_DEBUG - xassert(1 <= k && k <= m+n); -#endif - if (k <= m) - { GLPROW *row = lp->row[k]; - row->stat = GLP_BS; - row->bind = i; - row->prim = bbar[i] / row->rii; - row->dual = 0.0; - } - else - { GLPCOL *col = lp->col[k-m]; - col->stat = GLP_BS; - col->bind = i; - col->prim = bbar[i] * col->sjj; - col->dual = 0.0; - } - } - /* non-basic variables */ - for (j = 1; j <= n; j++) - { k = head[m+j]; /* x[k] = xN[j] */ -#ifdef GLP_DEBUG - xassert(1 <= k && k <= m+n); -#endif - if (k <= m) - { GLPROW *row = lp->row[k]; - row->stat = stat[j]; - row->bind = 0; -#if 0 - row->prim = get_xN(csa, j) / row->rii; -#else - switch (stat[j]) - { case GLP_NL: - row->prim = row->lb; break; - case GLP_NU: - row->prim = row->ub; break; - case GLP_NF: - row->prim = 0.0; break; - case GLP_NS: - row->prim = row->lb; break; - default: - xassert(stat != stat); - } -#endif - row->dual = (cbar[j] * row->rii) / zeta; - } - else - { GLPCOL *col = lp->col[k-m]; - col->stat = stat[j]; - col->bind = 0; -#if 0 - col->prim = get_xN(csa, j) * col->sjj; -#else - switch (stat[j]) - { case GLP_NL: - col->prim = col->lb; break; - case GLP_NU: - col->prim = col->ub; break; - case GLP_NF: - col->prim = 0.0; break; - case GLP_NS: - col->prim = col->lb; break; - default: - xassert(stat != stat); - } -#endif - col->dual = (cbar[j] / col->sjj) / zeta; - } - } - return; -} -#endif - -/*********************************************************************** -* free_csa - deallocate common storage area -* -* This routine frees all the memory allocated to arrays in the common -* storage area (CSA). */ - -static void free_csa(struct csa *csa) -{ xfree(csa->type); - xfree(csa->lb); - xfree(csa->ub); - xfree(csa->coef); - xfree(csa->orig_type); - xfree(csa->orig_lb); - xfree(csa->orig_ub); - xfree(csa->obj); - xfree(csa->A_ptr); - xfree(csa->A_ind); - xfree(csa->A_val); -#if 1 /* 06/IV-2009 */ - xfree(csa->AT_ptr); - xfree(csa->AT_ind); - xfree(csa->AT_val); -#endif - xfree(csa->head); -#if 1 /* 06/IV-2009 */ - xfree(csa->bind); -#endif - xfree(csa->stat); -#if 0 /* 06/IV-2009 */ - xfree(csa->N_ptr); - xfree(csa->N_len); - xfree(csa->N_ind); - xfree(csa->N_val); -#endif - xfree(csa->bbar); - xfree(csa->cbar); - xfree(csa->refsp); - xfree(csa->gamma); - xfree(csa->trow_ind); - xfree(csa->trow_vec); -#ifdef GLP_LONG_STEP /* 07/IV-2009 */ - xfree(csa->bkpt); -#endif - xfree(csa->tcol_ind); - xfree(csa->tcol_vec); - xfree(csa->work1); - xfree(csa->work2); - xfree(csa->work3); - xfree(csa->work4); - xfree(csa); - return; -} - -/*********************************************************************** -* spx_dual - core LP solver based on the dual simplex method -* -* SYNOPSIS -* -* #include "glpspx.h" -* int spx_dual(glp_prob *lp, const glp_smcp *parm); -* -* DESCRIPTION -* -* The routine spx_dual is a core LP solver based on the two-phase dual -* simplex method. -* -* RETURNS -* -* 0 LP instance has been successfully solved. -* -* GLP_EOBJLL -* Objective lower limit has been reached (maximization). -* -* GLP_EOBJUL -* Objective upper limit has been reached (minimization). -* -* GLP_EITLIM -* Iteration limit has been exhausted. -* -* GLP_ETMLIM -* Time limit has been exhausted. -* -* GLP_EFAIL -* The solver failed to solve LP instance. */ - -int spx_dual(glp_prob *lp, const glp_smcp *parm) -{ struct csa *csa; - int binv_st = 2; - /* status of basis matrix factorization: - 0 - invalid; 1 - just computed; 2 - updated */ - int bbar_st = 0; - /* status of primal values of basic variables: - 0 - invalid; 1 - just computed; 2 - updated */ - int cbar_st = 0; - /* status of reduced costs of non-basic variables: - 0 - invalid; 1 - just computed; 2 - updated */ - int rigorous = 0; - /* rigorous mode flag; this flag is used to enable iterative - refinement on computing pivot rows and columns of the simplex - table */ - int check = 0; - int p_stat, d_stat, ret; -#if 1 /* 16/VII-2013 */ - int degen = 0; - /* degenerated step count */ -#endif - /* allocate and initialize the common storage area */ - csa = alloc_csa(lp); - init_csa(csa, lp); - if (parm->msg_lev >= GLP_MSG_DBG) - xprintf("Objective scale factor = %g\n", csa->zeta); -loop: /* main loop starts here */ - /* compute factorization of the basis matrix */ - if (binv_st == 0) - { ret = invert_B(csa); - if (ret != 0) - { if (parm->msg_lev >= GLP_MSG_ERR) - { xprintf("Error: unable to factorize the basis matrix (%d" - ")\n", ret); - xprintf("Sorry, basis recovery procedure not implemented" - " yet\n"); - } - xassert(!lp->valid && lp->bfd == NULL); - lp->bfd = csa->bfd, csa->bfd = NULL; - lp->pbs_stat = lp->dbs_stat = GLP_UNDEF; - lp->obj_val = 0.0; - lp->it_cnt = csa->it_cnt; - lp->some = 0; - ret = GLP_EFAIL; - goto done; - } - csa->valid = 1; - binv_st = 1; /* just computed */ - /* invalidate basic solution components */ - bbar_st = cbar_st = 0; - } -#if 1 /* 16/VII-2013 */ - if (degen >= 5000 && parm->meth == GLP_DUALP) - { if (parm->msg_lev >= GLP_MSG_ERR) - xprintf("Warning: dual degeneracy; switching to primal simp" - "lex\n"); - store_sol(csa, lp, GLP_UNDEF, GLP_UNDEF, 0); - ret = GLP_EFAIL; - goto done; - } -#endif - /* compute reduced costs of non-basic variables */ - if (cbar_st == 0) - { eval_cbar(csa); - cbar_st = 1; /* just computed */ - /* determine the search phase, if not determined yet */ - if (csa->phase == 0) - { if (check_feas(csa, 0.90 * parm->tol_dj) != 0) - { /* current basic solution is dual infeasible */ - /* start searching for dual feasible solution */ - csa->phase = 1; - set_aux_bnds(csa); - } - else - { /* current basic solution is dual feasible */ - /* start searching for optimal solution */ - csa->phase = 2; - set_orig_bnds(csa); - } - xassert(check_stab(csa, parm->tol_dj) == 0); - /* some non-basic double-bounded variables might become - fixed (on phase I) or vice versa (on phase II) */ -#if 0 /* 06/IV-2009 */ - build_N(csa); -#endif - csa->refct = 0; - /* bounds of non-basic variables have been changed, so - invalidate primal values */ - bbar_st = 0; - } - /* make sure that the current basic solution remains dual - feasible */ - if (check_stab(csa, parm->tol_dj) != 0) - { if (parm->msg_lev >= GLP_MSG_ERR) - xprintf("Warning: numerical instability (dual simplex, p" - "hase %s)\n", csa->phase == 1 ? "I" : "II"); -#if 1 - if (parm->meth == GLP_DUALP) - { store_sol(csa, lp, GLP_UNDEF, GLP_UNDEF, 0); - ret = GLP_EFAIL; - goto done; - } -#endif - /* restart the search */ - csa->phase = 0; - binv_st = 0; - rigorous = 5; - goto loop; - } - } - xassert(csa->phase == 1 || csa->phase == 2); - /* on phase I we do not need to wait until the current basic - solution becomes primal feasible; it is sufficient to make - sure that all reduced costs have correct signs */ - if (csa->phase == 1 && check_feas(csa, parm->tol_dj) == 0) - { /* the current basis is dual feasible; switch to phase II */ - display(csa, parm, 1); - csa->phase = 2; - if (cbar_st != 1) - { eval_cbar(csa); - cbar_st = 1; - } - set_orig_bnds(csa); -#if 0 /* 06/IV-2009 */ - build_N(csa); -#endif - csa->refct = 0; - bbar_st = 0; - } - /* compute primal values of basic variables */ - if (bbar_st == 0) - { eval_bbar(csa); - if (csa->phase == 2) - csa->bbar[0] = eval_obj(csa); - bbar_st = 1; /* just computed */ - } - /* redefine the reference space, if required */ - switch (parm->pricing) - { case GLP_PT_STD: - break; - case GLP_PT_PSE: - if (csa->refct == 0) reset_refsp(csa); - break; - default: - xassert(parm != parm); - } - /* at this point the basis factorization and all basic solution - components are valid */ - xassert(binv_st && bbar_st && cbar_st); - /* check accuracy of current basic solution components (only for - debugging) */ - if (check) - { double e_bbar = err_in_bbar(csa); - double e_cbar = err_in_cbar(csa); - double e_gamma = - (parm->pricing == GLP_PT_PSE ? err_in_gamma(csa) : 0.0); - xprintf("e_bbar = %10.3e; e_cbar = %10.3e; e_gamma = %10.3e\n", - e_bbar, e_cbar, e_gamma); - xassert(e_bbar <= 1e-5 && e_cbar <= 1e-5 && e_gamma <= 1e-3); - } - /* if the objective has to be maximized, check if it has reached - its lower limit */ - if (csa->phase == 2 && csa->zeta < 0.0 && - parm->obj_ll > -DBL_MAX && csa->bbar[0] <= parm->obj_ll) - { if (bbar_st != 1 || cbar_st != 1) - { if (bbar_st != 1) bbar_st = 0; - if (cbar_st != 1) cbar_st = 0; - goto loop; - } - display(csa, parm, 1); - if (parm->msg_lev >= GLP_MSG_ALL) - xprintf("OBJECTIVE LOWER LIMIT REACHED; SEARCH TERMINATED\n" - ); - store_sol(csa, lp, GLP_INFEAS, GLP_FEAS, 0); - ret = GLP_EOBJLL; - goto done; - } - /* if the objective has to be minimized, check if it has reached - its upper limit */ - if (csa->phase == 2 && csa->zeta > 0.0 && - parm->obj_ul < +DBL_MAX && csa->bbar[0] >= parm->obj_ul) - { if (bbar_st != 1 || cbar_st != 1) - { if (bbar_st != 1) bbar_st = 0; - if (cbar_st != 1) cbar_st = 0; - goto loop; - } - display(csa, parm, 1); - if (parm->msg_lev >= GLP_MSG_ALL) - xprintf("OBJECTIVE UPPER LIMIT REACHED; SEARCH TERMINATED\n" - ); - store_sol(csa, lp, GLP_INFEAS, GLP_FEAS, 0); - ret = GLP_EOBJUL; - goto done; - } - /* check if the iteration limit has been exhausted */ - if (parm->it_lim < INT_MAX && - csa->it_cnt - csa->it_beg >= parm->it_lim) - { if (csa->phase == 2 && bbar_st != 1 || cbar_st != 1) - { if (csa->phase == 2 && bbar_st != 1) bbar_st = 0; - if (cbar_st != 1) cbar_st = 0; - goto loop; - } - display(csa, parm, 1); - if (parm->msg_lev >= GLP_MSG_ALL) - xprintf("ITERATION LIMIT EXCEEDED; SEARCH TERMINATED\n"); - switch (csa->phase) - { case 1: - d_stat = GLP_INFEAS; - set_orig_bnds(csa); - eval_bbar(csa); - break; - case 2: - d_stat = GLP_FEAS; - break; - default: - xassert(csa != csa); - } - store_sol(csa, lp, GLP_INFEAS, d_stat, 0); - ret = GLP_EITLIM; - goto done; - } - /* check if the time limit has been exhausted */ - if (parm->tm_lim < INT_MAX && - 1000.0 * xdifftime(xtime(), csa->tm_beg) >= parm->tm_lim) - { if (csa->phase == 2 && bbar_st != 1 || cbar_st != 1) - { if (csa->phase == 2 && bbar_st != 1) bbar_st = 0; - if (cbar_st != 1) cbar_st = 0; - goto loop; - } - display(csa, parm, 1); - if (parm->msg_lev >= GLP_MSG_ALL) - xprintf("TIME LIMIT EXCEEDED; SEARCH TERMINATED\n"); - switch (csa->phase) - { case 1: - d_stat = GLP_INFEAS; - set_orig_bnds(csa); - eval_bbar(csa); - break; - case 2: - d_stat = GLP_FEAS; - break; - default: - xassert(csa != csa); - } - store_sol(csa, lp, GLP_INFEAS, d_stat, 0); - ret = GLP_ETMLIM; - goto done; - } - /* display the search progress */ - display(csa, parm, 0); - /* choose basic variable xB[p] */ - chuzr(csa, parm->tol_bnd); - if (csa->p == 0) - { if (bbar_st != 1 || cbar_st != 1) - { if (bbar_st != 1) bbar_st = 0; - if (cbar_st != 1) cbar_st = 0; - goto loop; - } - display(csa, parm, 1); - switch (csa->phase) - { case 1: - if (parm->msg_lev >= GLP_MSG_ALL) -#if 0 /* 13/VII-2013; suggested by Prof. Fischetti */ - xprintf("PROBLEM HAS NO DUAL FEASIBLE SOLUTION\n"); -#else - xprintf("LP HAS NO DUAL FEASIBLE SOLUTION\n"); -#endif - set_orig_bnds(csa); - eval_bbar(csa); - p_stat = GLP_INFEAS, d_stat = GLP_NOFEAS; - break; - case 2: - if (parm->msg_lev >= GLP_MSG_ALL) -#if 0 /* 13/VII-2013; suggested by Prof. Fischetti */ - xprintf("OPTIMAL SOLUTION FOUND\n"); -#else - xprintf("OPTIMAL LP SOLUTION FOUND\n"); -#endif - p_stat = d_stat = GLP_FEAS; - break; - default: - xassert(csa != csa); - } - store_sol(csa, lp, p_stat, d_stat, 0); - ret = 0; - goto done; - } - /* compute pivot row of the simplex table */ - { double *rho = csa->work4; - eval_rho(csa, rho); - if (rigorous) refine_rho(csa, rho); - eval_trow(csa, rho); - sort_trow(csa, parm->tol_bnd); - } - /* unlike primal simplex there is no need to check accuracy of - the primal value of xB[p] (which might be computed using the - pivot row), since bbar is a result of FTRAN */ -#ifdef GLP_LONG_STEP /* 07/IV-2009 */ - long_step(csa); - if (csa->nbps > 0) - { csa->q = csa->bkpt[csa->nbps].j; - if (csa->delta > 0.0) - csa->new_dq = + csa->bkpt[csa->nbps].t; - else - csa->new_dq = - csa->bkpt[csa->nbps].t; - } - else -#endif - /* choose non-basic variable xN[q] */ - switch (parm->r_test) - { case GLP_RT_STD: - chuzc(csa, 0.0); - break; - case GLP_RT_HAR: - chuzc(csa, 0.30 * parm->tol_dj); - break; - default: - xassert(parm != parm); - } - if (csa->q == 0) - { if (bbar_st != 1 || cbar_st != 1 || !rigorous) - { if (bbar_st != 1) bbar_st = 0; - if (cbar_st != 1) cbar_st = 0; - rigorous = 1; - goto loop; - } - display(csa, parm, 1); - switch (csa->phase) - { case 1: - if (parm->msg_lev >= GLP_MSG_ERR) - xprintf("Error: unable to choose non-basic variable o" - "n phase I\n"); - xassert(!lp->valid && lp->bfd == NULL); - lp->bfd = csa->bfd, csa->bfd = NULL; - lp->pbs_stat = lp->dbs_stat = GLP_UNDEF; - lp->obj_val = 0.0; - lp->it_cnt = csa->it_cnt; - lp->some = 0; - ret = GLP_EFAIL; - break; - case 2: - if (parm->msg_lev >= GLP_MSG_ALL) -#if 0 /* 13/VII-2013; suggested by Prof. Fischetti */ - xprintf("PROBLEM HAS NO FEASIBLE SOLUTION\n"); -#else - xprintf("LP HAS UNBOUNDED DUAL SOLUTION\n"); -#endif - store_sol(csa, lp, GLP_NOFEAS, GLP_FEAS, - csa->head[csa->p]); - ret = 0; - break; - default: - xassert(csa != csa); - } - goto done; - } - /* check if the pivot element is acceptable */ - { double piv = csa->trow_vec[csa->q]; - double eps = 1e-5 * (1.0 + 0.01 * csa->trow_max); - if (fabs(piv) < eps) - { if (parm->msg_lev >= GLP_MSG_DBG) - xprintf("piv = %.12g; eps = %g\n", piv, eps); - if (!rigorous) - { rigorous = 5; - goto loop; - } - } - } - /* now xN[q] and xB[p] have been chosen anyhow */ - /* compute pivot column of the simplex table */ - eval_tcol(csa); - if (rigorous) refine_tcol(csa); - /* accuracy check based on the pivot element */ - { double piv1 = csa->tcol_vec[csa->p]; /* more accurate */ - double piv2 = csa->trow_vec[csa->q]; /* less accurate */ - xassert(piv1 != 0.0); - if (fabs(piv1 - piv2) > 1e-8 * (1.0 + fabs(piv1)) || - !(piv1 > 0.0 && piv2 > 0.0 || piv1 < 0.0 && piv2 < 0.0)) - { if (parm->msg_lev >= GLP_MSG_DBG) - xprintf("piv1 = %.12g; piv2 = %.12g\n", piv1, piv2); - if (binv_st != 1 || !rigorous) - { if (binv_st != 1) binv_st = 0; - rigorous = 5; - goto loop; - } - /* (not a good idea; should be revised later) */ - if (csa->tcol_vec[csa->p] == 0.0) - { csa->tcol_nnz++; - xassert(csa->tcol_nnz <= csa->m); - csa->tcol_ind[csa->tcol_nnz] = csa->p; - } - csa->tcol_vec[csa->p] = piv2; - } - } - /* update primal values of basic variables */ -#ifdef GLP_LONG_STEP /* 07/IV-2009 */ - if (csa->nbps > 0) - { int kk, j, k; - for (kk = 1; kk < csa->nbps; kk++) - { if (csa->bkpt[kk].t >= csa->bkpt[csa->nbps].t) continue; - j = csa->bkpt[kk].j; - k = csa->head[csa->m + j]; - xassert(csa->type[k] == GLP_DB); - if (csa->stat[j] == GLP_NL) - csa->stat[j] = GLP_NU; - else - csa->stat[j] = GLP_NL; - } - } - bbar_st = 0; -#else - update_bbar(csa); - if (csa->phase == 2) - csa->bbar[0] += (csa->cbar[csa->q] / csa->zeta) * - (csa->delta / csa->tcol_vec[csa->p]); - bbar_st = 2; /* updated */ -#endif - /* update reduced costs of non-basic variables */ - update_cbar(csa); - cbar_st = 2; /* updated */ - /* update steepest edge coefficients */ - switch (parm->pricing) - { case GLP_PT_STD: - break; - case GLP_PT_PSE: - if (csa->refct > 0) update_gamma(csa); - break; - default: - xassert(parm != parm); - } - /* update factorization of the basis matrix */ - ret = update_B(csa, csa->p, csa->head[csa->m+csa->q]); - if (ret == 0) - binv_st = 2; /* updated */ - else - { csa->valid = 0; - binv_st = 0; /* invalid */ - } -#if 0 /* 06/IV-2009 */ - /* update matrix N */ - del_N_col(csa, csa->q, csa->head[csa->m+csa->q]); - if (csa->type[csa->head[csa->p]] != GLP_FX) - add_N_col(csa, csa->q, csa->head[csa->p]); -#endif - /* change the basis header */ - change_basis(csa); - /* iteration complete */ - csa->it_cnt++; -#if 1 /* 16/VII-2013 */ - if (-1e-9 <= csa->new_dq && csa->new_dq <= +1e-9) - { /* degenerated step */ - degen++; - } - else - { /* non-degenerated step */ - degen = 0; - } -#endif - if (rigorous > 0) rigorous--; - goto loop; -done: /* deallocate the common storage area */ - free_csa(csa); - /* return to the calling program */ - return ret; -} - -/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glptsp.c b/resources/3rdparty/glpk-4.53/src/glptsp.c deleted file mode 100644 index ceb569584..000000000 --- a/resources/3rdparty/glpk-4.53/src/glptsp.c +++ /dev/null @@ -1,667 +0,0 @@ -/* glptsp.c */ - -/*********************************************************************** -* This code is part of GLPK (GNU Linear Programming Kit). -* -* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, -* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied -* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights -* reserved. E-mail: . -* -* GLPK is free software: you can redistribute it and/or modify it -* under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* GLPK is distributed in the hope that it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -* License for more details. -* -* You should have received a copy of the GNU General Public License -* along with GLPK. If not, see . -***********************************************************************/ - -#include "env.h" -#include "glptsp.h" -#include "misc.h" - -#define xfault xerror - -/*---------------------------------------------------------------------- --- tsp_read_data - read TSP instance data. --- --- *Synopsis* --- --- #include "glptsp.h" --- TSP *tsp_read_data(char *fname); --- --- *Description* --- --- The routine tsp_read_data reads a TSP (or related problem) instance --- data from the text file, whose name is the character string fname. --- --- For detailed description of the format recognized by the routine see --- the report: G.Reinelt, TSPLIB 95. --- --- *Returns* --- --- If no error occurred, the routine tsp_read_data returns a pointer to --- the TSP instance data block, which contains loaded data. In the case --- of error the routine prints an error message and returns NULL. */ - -struct dsa -{ /* dynamic storage area used by the routine tsp_read_data */ - char *fname; - /* name of the input text file */ - FILE *fp; - /* stream assigned to the input text file */ - int seqn; - /* line sequential number */ - int c; - /* current character */ - char token[255+1]; - /* current token */ -}; - -static int get_char(struct dsa *dsa) -{ dsa->c = fgetc(dsa->fp); - if (ferror(dsa->fp)) - { xprintf("%s:%d: read error - %s\n", - dsa->fname, dsa->seqn, strerror(errno)); - return 1; - } - if (feof(dsa->fp)) - dsa->c = EOF; - else if (dsa->c == '\n') - dsa->seqn++; - else if (isspace(dsa->c)) - dsa->c = ' '; - else if (iscntrl(dsa->c)) - { xprintf("%s:%d: invalid control character 0x%02X\n", - dsa->fname, dsa->seqn, dsa->c); - return 1; - } - return 0; -} - -static int skip_spaces(struct dsa *dsa, int across) -{ while (dsa->c == ' ' || (across && dsa->c == '\n')) - if (get_char(dsa)) return 1; - return 0; -} - -static int scan_keyword(struct dsa *dsa) -{ int len = 0; - if (skip_spaces(dsa, 0)) return 1; - dsa->token[0] = '\0'; - while (isalnum(dsa->c) || dsa->c == '_') - { if (len == 31) - { xprintf("%s:%d: keyword `%s...' too long\n", dsa->fname, - dsa->seqn, dsa->token); - return 1; - } - dsa->token[len++] = (char)dsa->c, dsa->token[len] = '\0'; - if (get_char(dsa)) return 1; - } - if (len == 0) - { xprintf("%s:%d: missing keyword\n", dsa->fname, dsa->seqn); - return 1; - } - return 0; -} - -static int check_colon(struct dsa *dsa) -{ if (skip_spaces(dsa, 0)) return 1; - if (dsa->c != ':') - { xprintf("%s:%d: missing colon after `%s'\n", dsa->fname, - dsa->seqn, dsa->token); - return 1; - } - if (get_char(dsa)) return 1; - return 0; -} - -static int scan_token(struct dsa *dsa, int across) -{ int len = 0; - if (skip_spaces(dsa, across)) return 1; - dsa->token[0] = '\0'; - while (!(dsa->c == EOF || dsa->c == '\n' || dsa->c == ' ')) - { if (len == 255) - { dsa->token[31] = '\0'; - xprintf("%s:%d: token `%s...' too long\n", dsa->fname, - dsa->seqn, dsa->token); - return 1; - } - dsa->token[len++] = (char)dsa->c, dsa->token[len] = '\0'; - if (get_char(dsa)) return 1; - } - return 0; -} - -static int check_newline(struct dsa *dsa) -{ if (skip_spaces(dsa, 0)) return 1; - if (!(dsa->c == EOF || dsa->c == '\n')) - { xprintf("%s:%d: extra symbols detected\n", dsa->fname, - dsa->seqn); - return 1; - } - if (get_char(dsa)) return 1; - return 0; -} - -static int scan_comment(struct dsa *dsa) -{ int len = 0; - if (skip_spaces(dsa, 0)) return 1; - dsa->token[0] = '\0'; - while (!(dsa->c == EOF || dsa->c == '\n')) - { if (len == 255) - { xprintf("%s:%d: comment too long\n", dsa->fname, dsa->seqn) - ; - return 1; - } - dsa->token[len++] = (char)dsa->c, dsa->token[len] = '\0'; - if (get_char(dsa)) return 1; - } - return 0; -} - -static int scan_integer(struct dsa *dsa, int across, int *val) -{ if (scan_token(dsa, across)) return 1; - if (strlen(dsa->token) == 0) - { xprintf("%s:%d: missing integer\n", dsa->fname, dsa->seqn); - return 1; - } - if (str2int(dsa->token, val)) - { xprintf("%s:%d: integer `%s' invalid\n", dsa->fname, dsa->seqn - , dsa->token); - return 1; - } - return 0; -} - -static int scan_number(struct dsa *dsa, int across, double *val) -{ if (scan_token(dsa, across)) return 1; - if (strlen(dsa->token) == 0) - { xprintf("%s:%d: missing number\n", dsa->fname, dsa->seqn); - return 1; - } - if (str2num(dsa->token, val)) - { xprintf("%s:%d: number `%s' invalid\n", dsa->fname, dsa->seqn, - dsa->token); - return 1; - } - return 0; -} - -TSP *tsp_read_data(char *fname) -{ struct dsa _dsa, *dsa = &_dsa; - TSP *tsp = NULL; - dsa->fname = fname; - xprintf("tsp_read_data: reading TSP data from `%s'...\n", - dsa->fname); - dsa->fp = fopen(dsa->fname, "r"); - if (dsa->fp == NULL) - { xprintf("tsp_read_data: unable to open `%s' - %s\n", - dsa->fname, strerror(errno)); - goto fail; - } - tsp = xmalloc(sizeof(TSP)); - tsp->name = NULL; - tsp->type = TSP_UNDEF; - tsp->comment = NULL; - tsp->dimension = 0; - tsp->edge_weight_type = TSP_UNDEF; - tsp->edge_weight_format = TSP_UNDEF; - tsp->display_data_type = TSP_UNDEF; - tsp->node_x_coord = NULL; - tsp->node_y_coord = NULL; - tsp->dply_x_coord = NULL; - tsp->dply_y_coord = NULL; - tsp->tour = NULL; - tsp->edge_weight = NULL; - dsa->seqn = 1; - if (get_char(dsa)) goto fail; -loop: if (scan_keyword(dsa)) goto fail; - if (strcmp(dsa->token, "NAME") == 0) - { if (tsp->name != NULL) - { xprintf("%s:%d: NAME entry multiply defined\n", dsa->fname, - dsa->seqn); - goto fail; - } - if (check_colon(dsa)) goto fail; - if (scan_token(dsa, 0)) goto fail; - if (strlen(dsa->token) == 0) - { xprintf("%s:%d: NAME entry incomplete\n", dsa->fname, - dsa->seqn); - goto fail; - } - tsp->name = xmalloc(strlen(dsa->token) + 1); - strcpy(tsp->name, dsa->token); - xprintf("tsp_read_data: NAME: %s\n", tsp->name); - if (check_newline(dsa)) goto fail; - } - else if (strcmp(dsa->token, "TYPE") == 0) - { if (tsp->type != TSP_UNDEF) - { xprintf("%s:%d: TYPE entry multiply defined\n", dsa->fname, - dsa->seqn); - goto fail; - } - if (check_colon(dsa)) goto fail; - if (scan_keyword(dsa)) goto fail; - if (strcmp(dsa->token, "TSP") == 0) - tsp->type = TSP_TSP; - else if (strcmp(dsa->token, "ATSP") == 0) - tsp->type = TSP_ATSP; - else if (strcmp(dsa->token, "TOUR") == 0) - tsp->type = TSP_TOUR; - else - { xprintf("%s:%d: data type `%s' not recognized\n", - dsa->fname, dsa->seqn, dsa->token); - goto fail; - } - xprintf("tsp_read_data: TYPE: %s\n", dsa->token); - if (check_newline(dsa)) goto fail; - } - else if (strcmp(dsa->token, "COMMENT") == 0) - { if (tsp->comment != NULL) - { xprintf("%s:%d: COMMENT entry multiply defined\n", - dsa->fname, dsa->seqn); - goto fail; - } - if (check_colon(dsa)) goto fail; - if (scan_comment(dsa)) goto fail; - tsp->comment = xmalloc(strlen(dsa->token) + 1); - strcpy(tsp->comment, dsa->token); - xprintf("tsp_read_data: COMMENT: %s\n", tsp->comment); - if (check_newline(dsa)) goto fail; - } - else if (strcmp(dsa->token, "DIMENSION") == 0) - { if (tsp->dimension != 0) - { xprintf("%s:%d: DIMENSION entry multiply defined\n", - dsa->fname, dsa->seqn); - goto fail; - } - if (check_colon(dsa)) goto fail; - if (scan_integer(dsa, 0, &tsp->dimension)) goto fail; - if (tsp->dimension < 1) - { xprintf("%s:%d: invalid dimension\n", dsa->fname, - dsa->seqn); - goto fail; - } - xprintf("tsp_read_data: DIMENSION: %d\n", tsp->dimension); - if (check_newline(dsa)) goto fail; - } - else if (strcmp(dsa->token, "EDGE_WEIGHT_TYPE") == 0) - { if (tsp->edge_weight_type != TSP_UNDEF) - { xprintf("%s:%d: EDGE_WEIGHT_TYPE entry multiply defined\n", - dsa->fname, dsa->seqn); - goto fail; - } - if (check_colon(dsa)) goto fail; - if (scan_keyword(dsa)) goto fail; - if (strcmp(dsa->token, "GEO") == 0) - tsp->edge_weight_type = TSP_GEO; - else if (strcmp(dsa->token, "EUC_2D") == 0) - tsp->edge_weight_type = TSP_EUC_2D; - else if (strcmp(dsa->token, "ATT") == 0) - tsp->edge_weight_type = TSP_ATT; - else if (strcmp(dsa->token, "EXPLICIT") == 0) - tsp->edge_weight_type = TSP_EXPLICIT; - else if (strcmp(dsa->token, "CEIL_2D") == 0) - tsp->edge_weight_type = TSP_CEIL_2D; - else - { xprintf("%s:%d: edge weight type `%s' not recognized\n", - dsa->fname, dsa->seqn, dsa->token); - goto fail; - } - xprintf("tsp_read_data: EDGE_WEIGHT_TYPE: %s\n", dsa->token); - if (check_newline(dsa)) goto fail; - } - else if (strcmp(dsa->token, "EDGE_WEIGHT_FORMAT") == 0) - { if (tsp->edge_weight_format != TSP_UNDEF) - { xprintf( - "%s:%d: EDGE_WEIGHT_FORMAT entry multiply defined\n", - dsa->fname, dsa->seqn); - goto fail; - } - if (check_colon(dsa)) goto fail; - if (scan_keyword(dsa)) goto fail; - if (strcmp(dsa->token, "UPPER_ROW") == 0) - tsp->edge_weight_format = TSP_UPPER_ROW; - else if (strcmp(dsa->token, "FULL_MATRIX") == 0) - tsp->edge_weight_format = TSP_FULL_MATRIX; - else if (strcmp(dsa->token, "FUNCTION") == 0) - tsp->edge_weight_format = TSP_FUNCTION; - else if (strcmp(dsa->token, "LOWER_DIAG_ROW") == 0) - tsp->edge_weight_format = TSP_LOWER_DIAG_ROW; - else - { xprintf("%s:%d: edge weight format `%s' not recognized\n", - dsa->fname, dsa->seqn, dsa->token); - goto fail; - } - xprintf("tsp_read_data: EDGE_WEIGHT_FORMAT: %s\n", dsa->token); - if (check_newline(dsa)) goto fail; - } - else if (strcmp(dsa->token, "DISPLAY_DATA_TYPE") == 0) - { if (tsp->display_data_type != TSP_UNDEF) - { xprintf("%s:%d: DISPLAY_DATA_TYPE entry multiply defined\n", - dsa->fname, dsa->seqn); - goto fail; - } - if (check_colon(dsa)) goto fail; - if (scan_keyword(dsa)) goto fail; - if (strcmp(dsa->token, "COORD_DISPLAY") == 0) - tsp->display_data_type = TSP_COORD_DISPLAY; - else if (strcmp(dsa->token, "TWOD_DISPLAY") == 0) - tsp->display_data_type = TSP_TWOD_DISPLAY; - else - { xprintf("%s:%d: display data type `%s' not recognized\n", - dsa->fname, dsa->seqn, dsa->token); - goto fail; - } - xprintf("tsp_read_data: DISPLAY_DATA_TYPE: %s\n", dsa->token); - if (check_newline(dsa)) goto fail; - } - else if (strcmp(dsa->token, "NODE_COORD_SECTION") == 0) - { int n = tsp->dimension, k, node; - if (n == 0) - { xprintf("%s:%d: DIMENSION entry not specified\n", - dsa->fname, dsa->seqn); - goto fail; - } - if (tsp->node_x_coord != NULL) - { xprintf("%s:%d: NODE_COORD_SECTION multiply specified\n", - dsa->fname, dsa->seqn); - goto fail; - } - if (check_newline(dsa)) goto fail; - tsp->node_x_coord = xcalloc(1+n, sizeof(double)); - tsp->node_y_coord = xcalloc(1+n, sizeof(double)); - for (node = 1; node <= n; node++) - tsp->node_x_coord[node] = tsp->node_y_coord[node] = DBL_MAX; - for (k = 1; k <= n; k++) - { if (scan_integer(dsa, 0, &node)) goto fail; - if (!(1 <= node && node <= n)) - { xprintf("%s:%d: invalid node number %d\n", dsa->fname, - dsa->seqn, node); - goto fail; - } - if (tsp->node_x_coord[node] != DBL_MAX) - { xprintf("%s:%d: node number %d multiply specified\n", - dsa->fname, dsa->seqn, node); - goto fail; - } - if (scan_number(dsa, 0, &tsp->node_x_coord[node])) - goto fail; - if (scan_number(dsa, 0, &tsp->node_y_coord[node])) - goto fail; - if (check_newline(dsa)) goto fail; - } - } - else if (strcmp(dsa->token, "DISPLAY_DATA_SECTION") == 0) - { int n = tsp->dimension, k, node; - if (n == 0) - { xprintf("%s:%d: DIMENSION entry not specified\n", - dsa->fname, dsa->seqn); - goto fail; - } - if (tsp->dply_x_coord != NULL) - { xprintf("%s:%d: DISPLAY_DATA_SECTION multiply specified\n", - dsa->fname, dsa->seqn); - goto fail; - } - if (check_newline(dsa)) goto fail; - tsp->dply_x_coord = xcalloc(1+n, sizeof(double)); - tsp->dply_y_coord = xcalloc(1+n, sizeof(double)); - for (node = 1; node <= n; node++) - tsp->dply_x_coord[node] = tsp->dply_y_coord[node] = DBL_MAX; - for (k = 1; k <= n; k++) - { if (scan_integer(dsa, 0, &node)) goto fail; - if (!(1 <= node && node <= n)) - { xprintf("%s:%d: invalid node number %d\n", dsa->fname, - dsa->seqn, node); - goto fail; - } - if (tsp->dply_x_coord[node] != DBL_MAX) - { xprintf("%s:%d: node number %d multiply specified\n", - dsa->fname, dsa->seqn, node); - goto fail; - } - if (scan_number(dsa, 0, &tsp->dply_x_coord[node])) - goto fail; - if (scan_number(dsa, 0, &tsp->dply_y_coord[node])) - goto fail; - if (check_newline(dsa)) goto fail; - } - } - else if (strcmp(dsa->token, "TOUR_SECTION") == 0) - { int n = tsp->dimension, k, node; - if (n == 0) - { xprintf("%s:%d: DIMENSION entry not specified\n", - dsa->fname, dsa->seqn); - goto fail; - } - if (tsp->tour != NULL) - { xprintf("%s:%d: TOUR_SECTION multiply specified\n", - dsa->fname, dsa->seqn); - goto fail; - } - if (check_newline(dsa)) goto fail; - tsp->tour = xcalloc(1+n, sizeof(int)); - for (k = 1; k <= n; k++) - { if (scan_integer(dsa, 1, &node)) goto fail; - if (!(1 <= node && node <= n)) - { xprintf("%s:%d: invalid node number %d\n", dsa->fname, - dsa->seqn, node); - goto fail; - } - tsp->tour[k] = node; - } - if (scan_integer(dsa, 1, &node)) goto fail; - if (node != -1) - { xprintf("%s:%d: extra node(s) detected\n", dsa->fname, - dsa->seqn); - goto fail; - } - if (check_newline(dsa)) goto fail; - } - else if (strcmp(dsa->token, "EDGE_WEIGHT_SECTION") == 0) - { int n = tsp->dimension, i, j, temp; - if (n == 0) - { xprintf("%s:%d: DIMENSION entry not specified\n", - dsa->fname, dsa->seqn); - goto fail; - } - if (tsp->edge_weight_format == TSP_UNDEF) - { xprintf("%s:%d: EDGE_WEIGHT_FORMAT entry not specified\n", - dsa->fname, dsa->seqn); - goto fail; - } - if (tsp->edge_weight != NULL) - { xprintf("%s:%d: EDGE_WEIGHT_SECTION multiply specified\n", - dsa->fname, dsa->seqn); - goto fail; - } - if (check_newline(dsa)) goto fail; - tsp->edge_weight = xcalloc(1+n*n, sizeof(int)); - switch (tsp->edge_weight_format) - { case TSP_FULL_MATRIX: - for (i = 1; i <= n; i++) - { for (j = 1; j <= n; j++) - { if (scan_integer(dsa, 1, &temp)) goto fail; - tsp->edge_weight[(i - 1) * n + j] = temp; - } - } - break; - case TSP_UPPER_ROW: - for (i = 1; i <= n; i++) - { tsp->edge_weight[(i - 1) * n + i] = 0; - for (j = i + 1; j <= n; j++) - { if (scan_integer(dsa, 1, &temp)) goto fail; - tsp->edge_weight[(i - 1) * n + j] = temp; - tsp->edge_weight[(j - 1) * n + i] = temp; - } - } - break; - case TSP_LOWER_DIAG_ROW: - for (i = 1; i <= n; i++) - { for (j = 1; j <= i; j++) - { if (scan_integer(dsa, 1, &temp)) goto fail; - tsp->edge_weight[(i - 1) * n + j] = temp; - tsp->edge_weight[(j - 1) * n + i] = temp; - } - } - break; - default: - goto fail; - } - if (check_newline(dsa)) goto fail; - } - else if (strcmp(dsa->token, "EOF") == 0) - { if (check_newline(dsa)) goto fail; - goto done; - } - else - { xprintf("%s:%d: keyword `%s' not recognized\n", dsa->fname, - dsa->seqn, dsa->token); - goto fail; - } - goto loop; -done: xprintf("tsp_read_data: %d lines were read\n", dsa->seqn-1); - fclose(dsa->fp); - return tsp; -fail: if (tsp != NULL) - { if (tsp->name != NULL) xfree(tsp->name); - if (tsp->comment != NULL) xfree(tsp->comment); - if (tsp->node_x_coord != NULL) xfree(tsp->node_x_coord); - if (tsp->node_y_coord != NULL) xfree(tsp->node_y_coord); - if (tsp->dply_x_coord != NULL) xfree(tsp->dply_x_coord); - if (tsp->dply_y_coord != NULL) xfree(tsp->dply_y_coord); - if (tsp->tour != NULL) xfree(tsp->tour); - if (tsp->edge_weight != NULL) xfree(tsp->edge_weight); - xfree(tsp); - } - if (dsa->fp != NULL) fclose(dsa->fp); - return NULL; -} - -/*---------------------------------------------------------------------- --- tsp_free_data - free TSP instance data. --- --- *Synopsis* --- --- #include "glptsp.h" --- void tsp_free_data(TSP *tsp); --- --- *Description* --- --- The routine tsp_free_data frees all the memory allocated to the TSP --- instance data block, which the parameter tsp points to. */ - -void tsp_free_data(TSP *tsp) -{ if (tsp->name != NULL) xfree(tsp->name); - if (tsp->comment != NULL) xfree(tsp->comment); - if (tsp->node_x_coord != NULL) xfree(tsp->node_x_coord); - if (tsp->node_y_coord != NULL) xfree(tsp->node_y_coord); - if (tsp->dply_x_coord != NULL) xfree(tsp->dply_x_coord); - if (tsp->dply_y_coord != NULL) xfree(tsp->dply_y_coord); - if (tsp->tour != NULL) xfree(tsp->tour); - if (tsp->edge_weight != NULL) xfree(tsp->edge_weight); - xfree(tsp); - return; -} - -/*---------------------------------------------------------------------- --- tsp_distance - compute distance between two nodes. --- --- *Synopsis* --- --- #include "glptsp.h" --- int tsp_distance(TSP *tsp, int i, int j); --- --- *Description* --- --- The routine tsp_distance computes the distance between i-th and j-th --- nodes for the TSP instance, which tsp points to. --- --- *Returns* --- --- The routine tsp_distance returns the computed distance. */ - -#define nint(x) ((int)((x) + 0.5)) - -static double rad(double x) -{ /* convert input coordinate to longitude/latitude, in radians */ - double pi = 3.141592, deg, min; - deg = (int)x; - min = x - deg; - return pi * (deg + 5.0 * min / 3.0) / 180.0; -} - -int tsp_distance(TSP *tsp, int i, int j) -{ int n = tsp->dimension, dij; - if (!(tsp->type == TSP_TSP || tsp->type == TSP_ATSP)) - xfault("tsp_distance: invalid TSP instance\n"); - if (!(1 <= i && i <= n && 1 <= j && j <= n)) - xfault("tsp_distance: node number out of range\n"); - switch (tsp->edge_weight_type) - { case TSP_UNDEF: - xfault("tsp_distance: edge weight type not specified\n"); - case TSP_EXPLICIT: - if (tsp->edge_weight == NULL) - xfault("tsp_distance: edge weights not specified\n"); - dij = tsp->edge_weight[(i - 1) * n + j]; - break; - case TSP_EUC_2D: - if (tsp->node_x_coord == NULL || tsp->node_y_coord == NULL) - xfault("tsp_distance: node coordinates not specified\n"); - { double xd, yd; - xd = tsp->node_x_coord[i] - tsp->node_x_coord[j]; - yd = tsp->node_y_coord[i] - tsp->node_y_coord[j]; - dij = nint(sqrt(xd * xd + yd * yd)); - } - break; - case TSP_CEIL_2D: - if (tsp->node_x_coord == NULL || tsp->node_y_coord == NULL) - xfault("tsp_distance: node coordinates not specified\n"); - { double xd, yd; - xd = tsp->node_x_coord[i] - tsp->node_x_coord[j]; - yd = tsp->node_y_coord[i] - tsp->node_y_coord[j]; - dij = (int)ceil(sqrt(xd * xd + yd * yd)); - } - break; - case TSP_GEO: - if (tsp->node_x_coord == NULL || tsp->node_y_coord == NULL) - xfault("tsp_distance: node coordinates not specified\n"); - { double rrr = 6378.388; - double latitude_i = rad(tsp->node_x_coord[i]); - double latitude_j = rad(tsp->node_x_coord[j]); - double longitude_i = rad(tsp->node_y_coord[i]); - double longitude_j = rad(tsp->node_y_coord[j]); - double q1 = cos(longitude_i - longitude_j); - double q2 = cos(latitude_i - latitude_j); - double q3 = cos(latitude_i + latitude_j); - dij = (int)(rrr * acos(0.5 * ((1.0 + q1) * q2 - - (1.0 - q1) *q3)) + 1.0); - } - break; - case TSP_ATT: - if (tsp->node_x_coord == NULL || tsp->node_y_coord == NULL) - xfault("tsp_distance: node coordinates not specified\n"); - { int tij; - double xd, yd, rij; - xd = tsp->node_x_coord[i] - tsp->node_x_coord[j]; - yd = tsp->node_y_coord[i] - tsp->node_y_coord[j]; - rij = sqrt((xd * xd + yd * yd) / 10.0); - tij = nint(rij); - if (tij < rij) dij = tij + 1; else dij = tij; - } - break; - default: - xassert(tsp->edge_weight_type != tsp->edge_weight_type); - } - return dij; -} - -/* eof */ diff --git a/resources/3rdparty/glpk-4.53/AUTHORS b/resources/3rdparty/glpk-4.57/AUTHORS similarity index 100% rename from resources/3rdparty/glpk-4.53/AUTHORS rename to resources/3rdparty/glpk-4.57/AUTHORS diff --git a/resources/3rdparty/glpk-4.53/COPYING b/resources/3rdparty/glpk-4.57/COPYING similarity index 100% rename from resources/3rdparty/glpk-4.53/COPYING rename to resources/3rdparty/glpk-4.57/COPYING diff --git a/resources/3rdparty/glpk-4.53/ChangeLog b/resources/3rdparty/glpk-4.57/ChangeLog similarity index 93% rename from resources/3rdparty/glpk-4.53/ChangeLog rename to resources/3rdparty/glpk-4.57/ChangeLog index 1200edce6..acf5867be 100644 --- a/resources/3rdparty/glpk-4.53/ChangeLog +++ b/resources/3rdparty/glpk-4.57/ChangeLog @@ -1,3 +1,188 @@ +Sun Nov 08 12:00:00 2015 Andrew Makhorin + + * GLPK 4.57 (38:0:2) has been released. + + * src/simplex/spy*.* + New, more efficient implementation of the dual simplex method + was included in the package. + + * src/simplex/spxprim.c + Incorrect directive #ifdef USE_AT was changed to #if USE_AT. + + * src/simplex/simplex.h + New header for simplex-based drivers was added. + + * src/glpspx02.c + Old implementation of the dual simplex method was removed from + the package. + + * src/glpspx.h + Old header for simplex-based drivers was removed. + + * src/glpapi06.c + Call to spx_dual was changed to spy_dual. + tol_piv = 1e-10 in glp_init_smcp was changed to 1e-9 (this new + tolerance seems to be more adequate for new implementations of + the primal and dual simplex methods). + + * src/glpk.h, src/glpapi09.c, src/glpios03.c + Option iocp.sr_heur to enable/disable simple rounding heuristic + was added. Thanks to Chris Matrakidis for + suggestion. + + * src/env/env.h src/env/error.c + API routine glp_at_error was added and documented. Thanks to + Jeroen Demeyer for suggestion. + + * src/glpapi19.c + Translation of MiniSat solver (src/minisat) from C++ to C is + made by a non-skilled programmer who converts pointers to ints + and vice versa, so MiniSat works on 32-bit platforms only. + Fixing this portability issue would require rewriting the code, + so currently to prevent crashing the API routine glp_minisat1 + was changed just to report failure if 64-bit version of GLPK is + used. Thanks to Heinrich Schuchardt for + bug report. + + * doc/glpk.tex, doc/gmpl.tex + Some material was added according to changes in GLPK API. + Also some minor typos were corrected. Thanks to Anton Voropaev + for typo report. + + * w32/makefiles, w64/makefiles + Option /Zi was added to pass to MSVC compiler. + + examples/tsp/*.* + An example application program TSPSOL was added. This program + is intended to solve the Symmetric Traveling Salesman Problem. + For more details see examples/tsp/README. + +Thu Oct 01 12:00:00 2015 Andrew Makhorin + + * GLPK 4.56 (37:3:1) has been released. + + * src/simplex/*.c, *.h + New, more efficient and robust implementation of the primal + simplex method was included in the package. + + * src/glpspx01.c + Old implementation of the primal simplex method was removed + from the package. + + * src/bflib/sgf.c + A bug was fixed in routine sgf_reduce_nuc. (The bug appeared if + the basis matrix was structurally singular.) Thanks to Martin + Jacob for bug report. + + * w32/*.*, w64/*.* + Scripts to build GLPK with Microsoft Visual Studio 2015 were + added. Thanks to Xypron for contribution + and testing. + +Fri Aug 22 12:00:00 2014 Andrew Makhorin + + * GLPK 4.55 (37:2:1) has been released. + + * src/bflib/luf.c, src/bflib/luf.h + Two routines luf_vt_solve1 and luf_estimate_norm were added to + estimate 1-norm of matrix inverse. + + * src/bflib/btf.c, src/bflib/btf.h + Two routines btf_at_solve1 and btf_estimate_norm were added to + estimate 1-norm of block triangular matrix inverse. + + * src/bflib/fhvint.c, src/bflib/fhvint.h + The routine fhvint_estimate was added to estimate 1-norm of the + basis matrix inverse (FHV-factorization). + + * src/bflib/scfint.c, src/bflib/scfint.h + The routine scfint_estimate was added to estimate 1-norm of the + basis matrix inverse (Schur-complement-based factorization). + + * src/bfd.c, src/bfd.c + The routine bfd_condest was added to estimate the condition of + the basis matrix. + + * src/bflib/scfint.h + The prefix '_glp' was added to keep the namespace clean. + + * src/env/stream.c + Two open modes "a" and "ab" were added. Thanks to Pedro P. Wong + for bug report. + + * src/glpapi21.c (glpsol) + Minor bug was fixed (command-line options --btf, --cbg, --cgr + didn't work properly). + + * src/bflib/sgf.c + A serious bug was fixed in a basis factorization routine used + on the dense phase. (The bug might appear only if the number of + rows exceeded sqrt(2**31) ~= 46,340 and caused access violtaion + exception because of integer overflow.) Thanks to Mark Meketon + for bug report. + + * doc/glpk.tex + Two API routines glp_alloc and glp_realloc were documented. + Thanks to Brian Gladman for suggestion. + + * doc/gmpl_es.tex, doc/gmpl_es.pdf + Translation of the document "Modeling Language GNU MathProg" + to Spanish was included (in LaTeX and pdf formats). Thanks to + Pablo Yapura for contribution. + +Fri Mar 28 12:00:00 2014 Andrew Makhorin + + * GLPK 4.54 (37:1:1) has been released. + + * src/bflib/fhvint.h, fhvint.c + Some technical changes were made. + + * src/bflib/btf.h, btf.c, btfint.h, btfint.c + The module BTF was added to the package. It implements sparse + block triangular factorization of a square non-singular matrix + and is based on LU-factorization (see the LUF module). + + * src/bflib/scf.h, scf.c, scfint.h, scfint.c + The module SCF was added to the package. It implements sparse + factorization of a square non-singular matrix based on Schur + complement and LU-factorization (plain or block triangular; see + the LUF and BTF modules). + + * src/bfd.c + LP basis factorization driver was changed to use most recent + versions of the FHV and SCF modules. + + * src/glplpf.h, glplpf.c + Old version of the Schur-complement-based factorization module + was removed from the package. + + * src/glpk.h + New flags GLP_BF_LUF, GLP_BF_BTF were added for glp_bfcp. + + * src/glpapi12.c + The API routines glp_get_bfcp, glp_set_bfcp were replaced due + to new version of the BFD module. + + * src/glpapi21.c + New command-line options --luf, --btf, --ft, --cbg, and --cgr + were added for the glpsol solver. + + * src/* + According to a new version of the GNU Coding Standards in all + messages a grave accent character (`) was replaced by a single + apostrophe character ('). + + * src/glpapi09.c mip status bug was fixed. Thanks to Remy Roy + for bug report. + + * doc/glpk.tex + Some comments about invalidating the basis factorization were + added. Thanks to Xypron for suggestion. + + * configure.ac + "iodbc-config --cflags" was added to detect iodbc flags. Thanks + to Sebastien Villemot for patch. + Thu Feb 13 12:00:00 2014 Andrew Makhorin * GLPK 4.53 (37:0:1) has been released. diff --git a/resources/3rdparty/glpk-4.53/INSTALL b/resources/3rdparty/glpk-4.57/INSTALL similarity index 100% rename from resources/3rdparty/glpk-4.53/INSTALL rename to resources/3rdparty/glpk-4.57/INSTALL diff --git a/resources/3rdparty/glpk-4.53/Makefile.am b/resources/3rdparty/glpk-4.57/Makefile.am similarity index 100% rename from resources/3rdparty/glpk-4.53/Makefile.am rename to resources/3rdparty/glpk-4.57/Makefile.am diff --git a/resources/3rdparty/glpk-4.53/Makefile.in b/resources/3rdparty/glpk-4.57/Makefile.in similarity index 100% rename from resources/3rdparty/glpk-4.53/Makefile.in rename to resources/3rdparty/glpk-4.57/Makefile.in diff --git a/resources/3rdparty/glpk-4.53/NEWS b/resources/3rdparty/glpk-4.57/NEWS similarity index 94% rename from resources/3rdparty/glpk-4.53/NEWS rename to resources/3rdparty/glpk-4.57/NEWS index 5bbadf21a..608086d1b 100644 --- a/resources/3rdparty/glpk-4.53/NEWS +++ b/resources/3rdparty/glpk-4.57/NEWS @@ -1,3 +1,103 @@ +GLPK 4.57 (release date: Nov 08, 2015) + + A new, more efficient implementation of the dual simplex method + was included in the package. This new implementation replaces + the old one, which was removed. + + Option sr_heur was added to struct glp_iocp to enable/disable + the simple rounding heuristic used by the MIP solver. Thanks to + Chris Matrakidis for suggestion. + + New API routine glp_at_error was added and documented. Thanks + to Jeroen Demeyer for suggestion. + + Some minor typos were corrected in the GLPK documentation. + Thanks to Anton Voropaev for typo + report. + + An example application program TSPSOL was added. It uses the + GLPK MIP optimizer to solve the Symmetric Traveling Salesman + Problem and illustrates "lazy" constraints generation. For more + details please see glpk/examples/tsp/README. + +GLPK 4.56 (release date: Oct 01, 2015) + + A new, more efficient and more robust implementation of the + primal simplex method was included in the package. This new + implementation replaces the old one, which was removed. + + A bug was fixed in a basis factorization routine. (The bug + appeared if the basis matrix was structurally singular having + duplicate row and/or column singletons.) Thanks to Martin Jacob + for bug report. + + Scripts to build GLPK with Microsoft Visual Studio 2015 were + added. Thanks to Xypron for contribution + and testing. + +GLPK 4.55 (release date: Aug 22, 2014) + + Some internal (non-API) routines to estimate the condition of + the basis matrix were added. These routines are mainly intended + to be used by the simplex-based solvers. + + Two open modes "a" and "ab" were added to GLPK I/O routines. + Thanks to Pedro P. Wong for bug report. + + Minor bug was fixed in the solver glpsol (command-line options + --btf, --cbg, and --cgr didn't work properly). + + A serious bug was fixed in a basis factorization routine used + on the dense phase. (The bug might appear only if the number of + rows exceeded sqrt(2**31) ~= 46,340 and caused access violation + exception because of integer overflow.) Thanks to Mark Meketon + for bug report. + + Two API routines glp_alloc and glp_realloc were documented. + Thanks to Brian Gladman for suggestion. + + Translation of the document "Modeling Language GNU MathProg" + to Spanish was included (in LaTeX and pdf formats). Thanks to + Pablo Yapura for contribution. + +GLPK 4.54 (release date: Mar 28, 2014) + + Block-triangular LU-factorization was implemented to be used + on computing an initial factorization of the basis matrix. + + A new version of the Schur-complement-based factorization + module was included in the package. Now it can be used along + with plain as well as with block-triangular LU-factorization. + + Currently the following flags can be used to specify the type + of the basis matrix factorization (glp_bfcp.type): + + GLP_BF_LUF + GLP_BF_FT LUF, Forrest-Tomlin update (default) + GLP_BF_LUF + GLP_BF_BG LUF, Schur complement, Bartels-Golub + update + GLP_BF_LUF + GLP_BF_GR LUF, Schur complement, Givens rotation + update + GLP_BF_BTF + GLP_BF_BG BTF, Schur complement, Bartels-Golub + update + GLP_BF_BTF + GLP_BF_GR BTF, Schur complement, Givens rotation + update + + In case of GLP_BF_FT the update is applied to matrix U, while + in cases of GLP_BF_BG and GLP_BF_GR the update is applied to + the Schur complement. + + Corresponding new options --luf and --btf were added to glpsol. + + For more details please see a new edition of the GLPK reference + manual included in the distribution. + + A minor bug (in reporting the mip solution status) was fixed. + Thanks to Remy Roy for bug report. + + A call to "iodbc-config --cflags" was added in configure.ac + to correctly detect iodbc flags. Thanks to Sebastien Villemot + for patch. + GLPK 4.53 (release date: Feb 13, 2014) The API routine glp_read_mps was changed to remove free rows. diff --git a/resources/3rdparty/glpk-4.53/README b/resources/3rdparty/glpk-4.57/README similarity index 85% rename from resources/3rdparty/glpk-4.53/README rename to resources/3rdparty/glpk-4.57/README index 2e7feb08b..23550ef14 100644 --- a/resources/3rdparty/glpk-4.53/README +++ b/resources/3rdparty/glpk-4.57/README @@ -1,11 +1,11 @@ Olga K. gewidmet -GLPK (GNU Linear Programming Kit) Version 4.53 +GLPK (GNU Linear Programming Kit) Version 4.57 Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, -2009, 2010, 2011, 2013, 2014 Andrew Makhorin, Department for Applied -Informatics, Moscow Aviation Institute, Moscow, Russia. All rights -reserved. E-mail: . +2009, 2010, 2011, 2013, 2014, 2015 Andrew Makhorin, Department for +Applied Informatics, Moscow Aviation Institute, Moscow, Russia. All +rights reserved. E-mail: . GLPK is part of the GNU Project released under the aegis of GNU. diff --git a/resources/3rdparty/glpk-4.53/THANKS b/resources/3rdparty/glpk-4.57/THANKS similarity index 91% rename from resources/3rdparty/glpk-4.53/THANKS rename to resources/3rdparty/glpk-4.57/THANKS index 6cbd95613..fc6fd047d 100644 --- a/resources/3rdparty/glpk-4.53/THANKS +++ b/resources/3rdparty/glpk-4.57/THANKS @@ -11,6 +11,8 @@ Andrew Hood for bug report. Anne-Laurence Putz for bug report. +Anton Voropaev for bug and typo report. + Axel Simon for bug report. Bernhard Schmidt for bug report. @@ -23,6 +25,8 @@ for bounds sensitivity analysis. Brady Hunsaker for some suggestions concerning MIP routines. +Brian Gladman for suggestion. + Cameron Kellough for bug report. Carlo Baldassi for bug report. @@ -31,6 +35,8 @@ Cedric[FR] for bug report. Charles Brixko for bug report. +Chris Matrakidis for suggestion. + Chris Rosebrugh for contribution of a new version of GLPK JNI (Java Native Interface). @@ -82,6 +88,8 @@ Jan Engelhardt for some suggestions. Jeffrey Kantor for reporting typos in the MathProg language reference. +Jeroen Demeyer for suggestion. + Jiri Spitz for bug report. Joey Rios for some suggestions. @@ -105,8 +113,12 @@ Marco Atzeri for bug report. Marco Atzeri for bug report. +Mark Meketon for bug report. + Markus Pilz for bug report. +Martin Jacob for bug report. + Minh Ha Duong for fixing doc typos. Morten Welinder for bug report. @@ -140,6 +152,11 @@ Olivier for bug report. Oscar Gustafsson for contribution of a routine to write data in OPB (pseudo boolean) format. +Pablo Yapura for translation the document +"Modeling Language GNU MathProg" to Spanish. + +Pedro P. Wong for bug report. + Peter T. Breuer for bug report. Peter A. Huegler for bug report. @@ -156,6 +173,8 @@ shared library support under GNU/Linux. Raniere Gaia Costa da Silva for bug report. +Remy Roy for bug report. + Robbie Morrison for correcting the glpk manual. Robert Wood for example model in MathProg. diff --git a/resources/3rdparty/glpk-4.53/aclocal.m4 b/resources/3rdparty/glpk-4.57/aclocal.m4 similarity index 100% rename from resources/3rdparty/glpk-4.53/aclocal.m4 rename to resources/3rdparty/glpk-4.57/aclocal.m4 diff --git a/resources/3rdparty/glpk-4.53/config.guess b/resources/3rdparty/glpk-4.57/config.guess old mode 100644 new mode 100755 similarity index 100% rename from resources/3rdparty/glpk-4.53/config.guess rename to resources/3rdparty/glpk-4.57/config.guess diff --git a/resources/3rdparty/glpk-4.53/config.h.in b/resources/3rdparty/glpk-4.57/config.h.in similarity index 100% rename from resources/3rdparty/glpk-4.53/config.h.in rename to resources/3rdparty/glpk-4.57/config.h.in diff --git a/resources/3rdparty/glpk-4.53/config.sub b/resources/3rdparty/glpk-4.57/config.sub old mode 100644 new mode 100755 similarity index 100% rename from resources/3rdparty/glpk-4.53/config.sub rename to resources/3rdparty/glpk-4.57/config.sub diff --git a/resources/3rdparty/glpk-4.53/configure b/resources/3rdparty/glpk-4.57/configure old mode 100644 new mode 100755 similarity index 99% rename from resources/3rdparty/glpk-4.53/configure rename to resources/3rdparty/glpk-4.57/configure index 049242a6b..b6b02927c --- a/resources/3rdparty/glpk-4.53/configure +++ b/resources/3rdparty/glpk-4.57/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for GLPK 4.53. +# Generated by GNU Autoconf 2.69 for GLPK 4.57. # # Report bugs to . # @@ -590,8 +590,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='GLPK' PACKAGE_TARNAME='glpk' -PACKAGE_VERSION='4.53' -PACKAGE_STRING='GLPK 4.53' +PACKAGE_VERSION='4.57' +PACKAGE_STRING='GLPK 4.57' PACKAGE_BUGREPORT='bug-glpk@gnu.org' PACKAGE_URL='' @@ -1309,7 +1309,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures GLPK 4.53 to adapt to many kinds of systems. +\`configure' configures GLPK 4.57 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1379,7 +1379,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of GLPK 4.53:";; + short | recursive ) echo "Configuration of GLPK 4.57:";; esac cat <<\_ACEOF @@ -1486,7 +1486,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -GLPK configure 4.53 +GLPK configure 4.57 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -1855,7 +1855,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by GLPK $as_me 4.53, which was +It was created by GLPK $as_me 4.57, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2684,7 +2684,7 @@ fi # Define the identity of the package. PACKAGE='glpk' - VERSION='4.53' + VERSION='4.57' cat >>confdefs.h <<_ACEOF @@ -11429,6 +11429,7 @@ if test "$enable_odbc" = "yes"; then fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } + CFLAGS="$(iodbc-config --cflags) $CFLAGS" cat >>confdefs.h <<_ACEOF #define ODBC_DLNAME "$LIBIODBC" @@ -12001,7 +12002,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by GLPK $as_me 4.53, which was +This file was extended by GLPK $as_me 4.57, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -12067,7 +12068,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -GLPK config.status 4.53 +GLPK config.status 4.57 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/resources/3rdparty/glpk-4.53/configure.ac b/resources/3rdparty/glpk-4.57/configure.ac similarity index 97% rename from resources/3rdparty/glpk-4.53/configure.ac rename to resources/3rdparty/glpk-4.57/configure.ac index 7f3de1878..e0e06cf49 100644 --- a/resources/3rdparty/glpk-4.53/configure.ac +++ b/resources/3rdparty/glpk-4.57/configure.ac @@ -1,6 +1,6 @@ dnl Process this file with autoconf to produce a configure script -AC_INIT([GLPK], [4.53], [bug-glpk@gnu.org]) +AC_INIT([GLPK], [4.57], [bug-glpk@gnu.org]) AC_CONFIG_SRCDIR([src/glpk.h]) @@ -117,6 +117,7 @@ if test "$enable_odbc" = "yes"; then AC_MSG_ERROR([--enable-odbc requires --enable-dl]) fi AC_MSG_RESULT([yes]) + CFLAGS="$(iodbc-config --cflags) $CFLAGS" AC_DEFINE_UNQUOTED([ODBC_DLNAME], ["$LIBIODBC"], [N/A]) elif test "$enable_odbc" = "unix"; then if test "$enable_dl" = "no"; then diff --git a/resources/3rdparty/glpk-4.53/depcomp b/resources/3rdparty/glpk-4.57/depcomp old mode 100644 new mode 100755 similarity index 100% rename from resources/3rdparty/glpk-4.53/depcomp rename to resources/3rdparty/glpk-4.57/depcomp diff --git a/resources/3rdparty/glpk-4.53/doc/cnfsat.pdf b/resources/3rdparty/glpk-4.57/doc/cnfsat.pdf similarity index 100% rename from resources/3rdparty/glpk-4.53/doc/cnfsat.pdf rename to resources/3rdparty/glpk-4.57/doc/cnfsat.pdf diff --git a/resources/3rdparty/glpk-4.53/doc/cnfsat.tex b/resources/3rdparty/glpk-4.57/doc/cnfsat.tex similarity index 100% rename from resources/3rdparty/glpk-4.53/doc/cnfsat.tex rename to resources/3rdparty/glpk-4.57/doc/cnfsat.tex diff --git a/resources/3rdparty/glpk-4.53/doc/glpk.pdf b/resources/3rdparty/glpk-4.57/doc/glpk.pdf similarity index 53% rename from resources/3rdparty/glpk-4.53/doc/glpk.pdf rename to resources/3rdparty/glpk-4.57/doc/glpk.pdf index 670f58b3c..51f0a4a3d 100644 Binary files a/resources/3rdparty/glpk-4.53/doc/glpk.pdf and b/resources/3rdparty/glpk-4.57/doc/glpk.pdf differ diff --git a/resources/3rdparty/glpk-4.53/doc/glpk.tex b/resources/3rdparty/glpk-4.57/doc/glpk.tex similarity index 89% rename from resources/3rdparty/glpk-4.53/doc/glpk.tex rename to resources/3rdparty/glpk-4.57/doc/glpk.tex index dbff90a66..b5f88c023 100644 --- a/resources/3rdparty/glpk-4.53/doc/glpk.tex +++ b/resources/3rdparty/glpk-4.57/doc/glpk.tex @@ -4,9 +4,9 @@ % This code is part of GLPK (GNU Linear Programming Kit). % % Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, -% 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied -% Informatics, Moscow Aviation Institute, Moscow, Russia. All rights -% reserved. E-mail: . +% 2009, 2010, 2011, 2013, 2014, 2015 Andrew Makhorin, Department for +% Applied Informatics, Moscow Aviation Institute, Moscow, Russia. All +% rights reserved. E-mail: . % % GLPK is free software: you can redistribute it and/or modify it % under the terms of the GNU General Public License as published by @@ -49,6 +49,7 @@ urlcolor=blue]{hyperref} \def\para#1{\noindent{\bf#1}} \def\synopsis{\para{Synopsis}} \def\description{\para{Description}} +\def\note{\para{Note}} \def\returns{\para{Returns}} \renewcommand\contentsname{\sf\bfseries Contents} @@ -83,12 +84,12 @@ urlcolor=blue]{hyperref} \vspace{0.5in} \begin{LARGE} -\sf for GLPK Version 4.52 +\sf for GLPK Version 4.57 \end{LARGE} \vspace{0.5in} \begin{Large} -\sf (DRAFT, July 2013) +\sf (DRAFT, November 2015) \end{Large} \end{center} @@ -104,9 +105,9 @@ GNU. \noindent Copyright \copyright{} 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, -2008, 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied -Informatics, Moscow Aviation Institute, Moscow, Russia. All rights -reserved. +2008, 2009, 2010, 2011, 2013, 2014, 2015 Andrew Makhorin, Department +for Applied Informatics, Moscow Aviation Institute, Moscow, Russia. All +rights reserved. \noindent Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA diff --git a/resources/3rdparty/glpk-4.53/doc/glpk01.tex b/resources/3rdparty/glpk-4.57/doc/glpk01.tex similarity index 100% rename from resources/3rdparty/glpk-4.53/doc/glpk01.tex rename to resources/3rdparty/glpk-4.57/doc/glpk01.tex diff --git a/resources/3rdparty/glpk-4.53/doc/glpk02.tex b/resources/3rdparty/glpk-4.57/doc/glpk02.tex similarity index 98% rename from resources/3rdparty/glpk-4.53/doc/glpk02.tex rename to resources/3rdparty/glpk-4.57/doc/glpk02.tex index c2663026e..3fa6ef7f7 100644 --- a/resources/3rdparty/glpk-4.53/doc/glpk02.tex +++ b/resources/3rdparty/glpk-4.57/doc/glpk02.tex @@ -352,6 +352,11 @@ the row list, so the ordinal numbers of existing rows are not changed. Being added each new row is initially free (unbounded) and has empty list of the constraint coefficients. +Each new row becomes a non-active (non-binding) constraint, i.e. the +corresponding auxiliary variable is marked as basic. + +If the basis factorization exists, adding row(s) invalidates it. + \returns The routine \verb|glp_add_rows| returns the ordinal number of the first @@ -375,6 +380,11 @@ columns are not changed. Being added each new column is initially fixed at zero and has empty list of the constraint coefficients. +Each new column is marked as non-basic, i.e. zero value of the +corresponding structural variable becomes an active (binding) bound. + +If the basis factorization exists, it remains valid. + \returns The routine \verb|glp_add_cols| returns the ordinal number of the first @@ -503,6 +513,8 @@ while the parameter \verb|ub| is ignored. Being added to the problem object each column is initially fixed at zero, i.e. its type is \verb|GLP_FX| and both bounds are 0. +\newpage + \subsection{glp\_set\_obj\_coef --- set (change) objective coefficient or constant term} @@ -521,8 +533,6 @@ the objective coefficient is specified by the parameter \verb|coef|. If the parameter \verb|j| is 0, the routine sets (changes) the constant term (``shift'') of the objective function. -\newpage - \subsection{glp\_set\_mat\_row --- set (replace) row of the constraint matrix} @@ -550,6 +560,11 @@ but they are not stored in the constraint matrix. If the parameter \verb|len| is 0, the parameters \verb|ind| and/or \verb|val| can be specified as \verb|NULL|. +\note + +If the basis factorization exists and changing the row changes +coefficients at basic column(s), the factorization is invalidated. + \subsection{glp\_set\_mat\_col --- set (replace) column of the constr\-aint matrix} @@ -577,6 +592,11 @@ they are not stored in the constraint matrix. If the parameter \verb|len| is 0, the parameters \verb|ind| and/or \verb|val| can be specified as \verb|NULL|. +\note + +If the basis factorization exists, changing the column corresponding +to a basic structural variable invalidates it. + \subsection{glp\_load\_matrix --- load (replace) the whole constraint matrix} @@ -606,6 +626,10 @@ however, they are not stored in the constraint matrix. If the parameter \verb|ne| is 0, the parameters \verb|ia|, \verb|ja|, and/or \verb|ar| can be specified as \verb|NULL|. +\note + +If the basis factorization exists, this operation invalidates it. + \subsection{glp\_check\_dup --- check for duplicate elements in sparse matrix} @@ -683,6 +707,11 @@ be five rows $a$, $b$, $c$, $d$, $e$ with ordinal numbers 1, 2, 3, 4, 5, and let rows $b$ and $d$ have been deleted. Then after deletion the remaining rows $a$, $c$, $e$ are assigned new oridinal numbers 1, 2, 3. +If the basis factorization exists, deleting active (binding) rows, +i.e. whose auxiliary variables are marked as non-basic, invalidates it. + +\newpage + \subsection{glp\_del\_cols --- delete columns from problem object} \synopsis @@ -707,6 +736,9 @@ ordinal numbers 1, 2, 3, 4, 5, 6, and let columns $p$, $q$, $s$ have been deleted. Then after deletion the remaining columns $r$, $t$, $u$ are assigned new ordinal numbers 1, 2, 3. +If the basis factorization exists, deleting basic columns invalidates +it. + \subsection{glp\_copy\_prob --- copy problem object content} \synopsis @@ -724,8 +756,6 @@ The parameter \verb|names| is a flag. If it is \verb|GLP_ON|, the routine also copies all symbolic names; otherwise, if it is \verb|GLP_OFF|, no symbolic names are copied. -\newpage - \subsection{glp\_erase\_prob --- erase problem object content} \synopsis @@ -742,6 +772,8 @@ problem object would be deleted with the routine \verb|glp_delete_prob| and then created anew with the routine \verb|glp_create_prob|, with the only exception that the pointer to the problem object remains valid. +\newpage + \subsection{glp\_delete\_prob --- delete problem object} \synopsis @@ -1674,8 +1706,8 @@ infeasible or non-optimal, the presolver should be disabled. \para{Terminal output} Solving large problem instances may take a long time, so the solver -reports some information about the current basic solution, which is sent -to the terminal. This information has the following format: +reports some information about the current basic solution, which is +sent to the terminal. This information has the following format: \begin{verbatim} nnn: obj = xxx infeas = yyy (ddd) @@ -1683,8 +1715,8 @@ to the terminal. This information has the following format: \noindent where: `\verb|nnn|' is the iteration number, `\verb|xxx|' is the -current value of the objective function (it is is unscaled and has -correct sign); `\verb|yyy|' is the current sum of primal or dual +current value of the objective function (it is unscaled and has correct +sign); `\verb|yyy|' is the current sum of primal or dual infeasibilities (it is scaled and therefore may be used only for visual estimating), `\verb|ddd|' is the current number of fixed basic variables. @@ -1773,7 +1805,7 @@ purpose.) \bigskip -{\tt double tol\_piv} (default: {\tt 1e-10}) +{\tt double tol\_piv} (default: {\tt 1e-9}) Tolerance used to choose eligble pivotal elements of the simplex table. (Do not change this parameter without detailed understanding its @@ -2950,6 +2982,16 @@ Preprocessing technique option: \bigskip\vspace*{-2pt} +{\tt int sr\_heur} (default: {\tt GLP\_ON}) + +Simple rounding heuristic option: + +\verb|GLP_ON | --- enable applying the simple rounding heuristic; + +\verb|GLP_OFF| --- disable applying the simple rounding heuristic. + +\newpage + {\tt int fp\_heur} (default: {\tt GLP\_OFF}) Feasibility pump heuristic option: @@ -2958,7 +3000,7 @@ Feasibility pump heuristic option: \verb|GLP_OFF| --- disable applying the feasibility pump heuristic. -\newpage +\bigskip {\tt int ps\_heur} (default: {\tt GLP\_OFF}) @@ -3019,7 +3061,7 @@ Clique cut option: \verb|GLP_OFF| --- disable generating clique cuts. -\bigskip +\newpage {\tt double tol\_int} (default: {\tt 1e-5}) @@ -3027,7 +3069,7 @@ Absolute tolerance used to check if optimal solution to the current LP relaxation is integer feasible. (Do not change this parameter without detailed understanding its purpose.) -\newpage +\bigskip {\tt double tol\_obj} (default: {\tt 1e-7}) diff --git a/resources/3rdparty/glpk-4.53/doc/glpk03.tex b/resources/3rdparty/glpk-4.57/doc/glpk03.tex similarity index 100% rename from resources/3rdparty/glpk-4.53/doc/glpk03.tex rename to resources/3rdparty/glpk-4.57/doc/glpk03.tex diff --git a/resources/3rdparty/glpk-4.53/doc/glpk04.tex b/resources/3rdparty/glpk-4.57/doc/glpk04.tex similarity index 96% rename from resources/3rdparty/glpk-4.53/doc/glpk04.tex rename to resources/3rdparty/glpk-4.57/doc/glpk04.tex index 5c5ed3073..2367db573 100644 --- a/resources/3rdparty/glpk-4.53/doc/glpk04.tex +++ b/resources/3rdparty/glpk-4.57/doc/glpk04.tex @@ -568,28 +568,36 @@ names of corresponding members in the structure \verb|glp_bfcp|. \medskip -{\tt int type} (default: {\tt GLP\_BF\_FT}) +{\tt int type} (default: {\tt GLP\_BF\_LUF + GLP\_BF\_FT}) Basis factorization type: -\verb|GLP_BF_FT|---$LU$ + Forrest--Tomlin update; +\verb~GLP_BF_LUF + GLP_BF_FT~ --- $LUF$, Forrest--Tomlin update; -\verb|GLP_BF_BG|---$LU$ + Schur complement + Bartels--Golub update; +\verb~GLP_BF_LUF + GLP_BF_BG~ --- $LUF$, Schur complement, +Bartels--Golub update; -\verb|GLP_BF_GR|---$LU$ + Schur complement + Givens rotation update. +\verb~GLP_BF_LUF + GLP_BF_GR~ --- $LUF$, Schur complement, +Givens rotation update; + +\verb~GLP_BF_BTF + GLP_BF_BG~ --- $BTF$, Schur complement, +Bartels--Golub update; + +\verb~GLP_BF_BTF + GLP_BF_GR~ --- $BTF$, Schur complement, +Givens rotation update. In case of \verb|GLP_BF_FT| the update is applied to matrix $U$, while in cases of \verb|GLP_BF_BG| and \verb|GLP_BF_GR| the update is applied to the Schur complement. -\medskip - -{\tt int lu\_size} (default: {\tt 0}) - -The initial size of the Sparse Vector Area, in non-zeros, used on -computing $LU$-factorization of the basis matrix for the first time. -If this parameter is set to 0, the initial SVA size is determined -automatically. +%\medskip +% +%{\tt int lu\_size} (default: {\tt 0}) +% +%The initial size of the Sparse Vector Area, in non-zeros, used on +%computing $LU$-factorization of the basis matrix for the first time. +%If this parameter is set to 0, the initial SVA size is determined +%automatically. \medskip @@ -635,17 +643,17 @@ $LU$-factorization of the basis matrix. If an element of the active submatrix of factor $U$ is less than \verb|eps_tol| in the magnitude, it is replaced by exact zero. -\medskip - -{\tt double max\_gro} (default: {\tt 1e+10}) - -Maximal growth of elements of factor $U$, \verb|max_gro| $\geq$ 1, -allowable on computing $LU$-factorization of the basis matrix. If on -some elimination step the ratio $u_{big}/b_{max}$ (where $u_{big}$ is -the largest magnitude of elements of factor $U$ appeared in its active -submatrix during all the factorization process, $b_{max}$ is the -largest magnitude of elements of the basis matrix to be factorized), -the basis matrix is considered as ill-conditioned. +%\medskip +% +%{\tt double max\_gro} (default: {\tt 1e+10}) +% +%Maximal growth of elements of factor $U$, \verb|max_gro| $\geq$ 1, +%allowable on computing $LU$-factorization of the basis matrix. If on +%some elimination step the ratio $u_{big}/b_{max}$ (where $u_{big}$ is +%the largest magnitude of elements of factor $U$ appeared in its active +%submatrix during all the factorization process, $b_{max}$ is the +%largest magnitude of elements of the basis matrix to be factorized), +%the basis matrix is considered as ill-conditioned. \medskip @@ -683,17 +691,15 @@ allocate working arrays. As a rule, each update adds one new row and column (however, some updates may need no addition), so this parameter limits the number of updates between refactorizations. -\medskip - -{\tt int rs\_size} (default: {\tt 0}) - -The initial size of the Sparse Vector Area, in non-zeros, used to -store non-zero elements of additional rows and columns introduced on -updating $LU$-factorization of the basis matrix with the Schur -complement technique. If this parameter is set to 0, the initial SVA -size is determined automatically. - -\newpage +%\medskip +% +%{\tt int rs\_size} (default: {\tt 0}) +% +%The initial size of the Sparse Vector Area, in non-zeros, used to +%store non-zero elements of additional rows and columns introduced on +%updating $LU$-factorization of the basis matrix with the Schur +%complement technique. If this parameter is set to 0, the initial SVA +%size is determined automatically. \subsection{glp\_get\_bhead --- retrieve the basis header information} @@ -765,8 +771,6 @@ $1\leq i\leq m$, in the current basis associated with the specified problem object, where $m$ is the number of rows. However, if $i$-th auxiliary variable is non-basic, the routine returns zero. -\newpage - \para{Comments} The routine \verb|glp_get_row_bind| is an inversion of the routine @@ -836,8 +840,6 @@ to the basis matrix $B$ associated with the specified problem object, $x$ is the vector of unknowns to be computed, $b$ is the vector of right-hand sides. -\newpage - On entry to the routine elements of the vector $b$ should be stored in locations \verb|x[1]|, \dots, \verb|x[m]|, where $m$ is the number of rows. On exit the routine stores elements of the vector $x$ in the same diff --git a/resources/3rdparty/glpk-4.53/doc/glpk05.tex b/resources/3rdparty/glpk-4.57/doc/glpk05.tex similarity index 100% rename from resources/3rdparty/glpk-4.53/doc/glpk05.tex rename to resources/3rdparty/glpk-4.57/doc/glpk05.tex diff --git a/resources/3rdparty/glpk-4.53/doc/glpk06.tex b/resources/3rdparty/glpk-4.57/doc/glpk06.tex similarity index 82% rename from resources/3rdparty/glpk-4.53/doc/glpk06.tex rename to resources/3rdparty/glpk-4.57/doc/glpk06.tex index 71eb8197d..dad96c578 100644 --- a/resources/3rdparty/glpk-4.53/doc/glpk06.tex +++ b/resources/3rdparty/glpk-4.57/doc/glpk06.tex @@ -253,6 +253,29 @@ program. \newpage +\subsection{glp\_at\_error --- check for error state} + +\synopsis + +\begin{verbatim} + int glp_at_error(void); +\end{verbatim} + +\description + +The routine \verb|glp_at_error| checks if the GLPK environment is at +error state, i.~e.~if the call to the routine is (indirectly) made from +the \verb|glp_error| routine via an user-defined hook routine. + +This routine can be used, for example, by a custom output handler +(installed with the routine \verb|glp_term_hook|) to determine whether +or not the message to be displayed is an error message. + +\returns + +If the GLPK environment is at error state, the routine returns +non-zero, otherwise zero. + \subsection{glp\_assert --- check logical condition} \synopsis @@ -303,68 +326,67 @@ terminated. To prevent abnormal termnation the hook routine may perform a global jump using the standard function \verb|longjmp|, in which case the application program {\it must} call the routine \verb|glp_free_env|. -\subsection{glp\_malloc --- allocate memory block} +\subsection{glp\_alloc --- allocate memory block} \synopsis \begin{verbatim} - void *glp_malloc(int size); + void *glp_alloc(int n, int size); \end{verbatim} \description -The routine \verb|glp_malloc| dynamically allocates a memory block of -\verb|size| bytes long. Note that: +The routine \verb|glp_alloc| dynamically allocates a memory block of +\verb|n|$\times$\verb|size| bytes long. Note that: -1) the parameter \verb|size| must be positive; +1) the parameters \verb|n| and \verb|size| must be positive; -2) being allocated the memory block contains arbitrary data, that is, -it is {\it not} initialized by binary zeros; +2) having been allocated the memory block contains arbitrary data, that +is, it is {\it not} initialized by binary zeros; 3) if the block cannot be allocated due to insufficient memory, the routine prints an error message and abnormally terminates the program. This routine is a replacement of the standard C function \verb|malloc| -and used by all GLPK routines for dynamic memory allocation. The -application program may use \verb|glp_malloc| for the same purpose. +and used by GLPK routines for dynamic memory allocation. The +application program may use \verb|glp_alloc| for the same purpose. \returns -The routine \verb|glp_malloc| returns a pointer to the memory block +The routine \verb|glp_alloc| returns a pointer to the memory block allocated. To free this block the routine \verb|glp_free| (not the -standard C function \verb|free|!) must be used. +standard C function \verb|free|!) should be used. -\subsection{glp\_calloc --- allocate memory block} +\subsection{glp\_realloc --- reallocate memory block} \synopsis \begin{verbatim} - void *glp_calloc(int n, int size); + void *glp_realloc(void *ptr, int n, int size); \end{verbatim} \description -The routine \verb|glp_calloc| dynamically allocates a memory block of -\verb|n|$\times$\verb|size| bytes long. Note that: +The routine \verb|glp_realloc| dynamically reallocates a memory block +pointed to by \verb|ptr|, which was previously allocated by the routine +\verb|glp_alloc| or reallocated by this routine. Note that the pointer +\verb|ptr| must be valid and must not be \verb|NULL|. The new size of +the memory block is \verb|n|$\times$\verb|size| bytes long. Note that: 1) both parameters \verb|n| and \verb|size| must be positive; -2) being allocated the memory block contains arbitrary data, that is, -it is {\it not} initialized by binary zeros; - -3) if the block cannot be allocated due to insufficient memory, the +2) if the block cannot be reallocated due to insufficient memory, the routine prints an error message and abnormally terminates the program. -This routine is a replacement of the standard C function \verb|calloc| -(with exception that the block is not cleaned) and used by all GLPK -routines for dynamic memory allocation. The application program may use -\verb|glp_calloc| for the same purpose. +This routine is a replacement of the standard C function \verb|realloc| +and used by GLPK routines for dynamic memory allocation. The +application program may use \verb|glp_realloc| for the same purpose. \returns -The routine \verb|glp_calloc| returns a pointer to the memory block -allocated. To free this block the routine \verb|glp_free| (not the -standard C function \verb|free|!) must be used. +The routine \verb|glp_realloc| returns a pointer to the memory block +reallocated. To free this block the routine \verb|glp_free| (not the +standard C function \verb|free|!) should be used. \subsection{glp\_free --- free memory block} @@ -378,15 +400,14 @@ standard C function \verb|free|!) must be used. The routine \verb|glp_free| deallocates a memory block pointed to by \verb|ptr|, which was previously allocated by the routine -\verb|glp_malloc| or \verb|glp_calloc|. Note that the pointer -\verb|ptr| must be valid and must not be \verb|NULL|. +\verb|glp_malloc| or reallocated by the routine \verb|glp_realloc|. +Note that the pointer \verb|ptr| must be valid and must not be +\verb|NULL|. This routine is a replacement of the standard C function \verb|free| -and used by all GLPK routines for dynamic memory allocation. The +and used by GLPK routines for dynamic memory allocation. The application program may use \verb|glp_free| for the same purpose. -\newpage - \subsection{glp\_mem\_usage --- get memory usage information} \synopsis diff --git a/resources/3rdparty/glpk-4.53/doc/glpk07.tex b/resources/3rdparty/glpk-4.57/doc/glpk07.tex similarity index 100% rename from resources/3rdparty/glpk-4.53/doc/glpk07.tex rename to resources/3rdparty/glpk-4.57/doc/glpk07.tex diff --git a/resources/3rdparty/glpk-4.53/doc/glpk08.tex b/resources/3rdparty/glpk-4.57/doc/glpk08.tex similarity index 100% rename from resources/3rdparty/glpk-4.53/doc/glpk08.tex rename to resources/3rdparty/glpk-4.57/doc/glpk08.tex diff --git a/resources/3rdparty/glpk-4.53/doc/glpk09.tex b/resources/3rdparty/glpk-4.57/doc/glpk09.tex similarity index 100% rename from resources/3rdparty/glpk-4.53/doc/glpk09.tex rename to resources/3rdparty/glpk-4.57/doc/glpk09.tex diff --git a/resources/3rdparty/glpk-4.53/doc/glpk10.tex b/resources/3rdparty/glpk-4.57/doc/glpk10.tex similarity index 95% rename from resources/3rdparty/glpk-4.53/doc/glpk10.tex rename to resources/3rdparty/glpk-4.57/doc/glpk10.tex index 3499d04bf..01c4f35d4 100644 --- a/resources/3rdparty/glpk-4.53/doc/glpk10.tex +++ b/resources/3rdparty/glpk-4.57/doc/glpk10.tex @@ -70,12 +70,11 @@ the problem, and write its solution to an output text file. \para{LP basis factorization options} \begin{verbatim} - --luf LU + Forrest-Tomlin update - (faster, less stable; default) - --cbg LU + Schur complement + Bartels-Golub update - (slower, more stable) - --cgr LU + Schur complement + Givens rotation update - (slower, more stable) + --luf plain LU factorization (default) + --btf block triangular LU factorization + --ft Forrest-Tomlin update (requires --luf; default) + --cbg Schur complement + Bartels-Golub update + --cgr Schur complement + Givens rotation update \end{verbatim} \para{Options specific to the simplex solver} diff --git a/resources/3rdparty/glpk-4.53/doc/glpk11.tex b/resources/3rdparty/glpk-4.57/doc/glpk11.tex similarity index 100% rename from resources/3rdparty/glpk-4.53/doc/glpk11.tex rename to resources/3rdparty/glpk-4.57/doc/glpk11.tex diff --git a/resources/3rdparty/glpk-4.53/doc/glpk12.tex b/resources/3rdparty/glpk-4.57/doc/glpk12.tex similarity index 100% rename from resources/3rdparty/glpk-4.53/doc/glpk12.tex rename to resources/3rdparty/glpk-4.57/doc/glpk12.tex diff --git a/resources/3rdparty/glpk-4.53/doc/gmpl.pdf b/resources/3rdparty/glpk-4.57/doc/gmpl.pdf similarity index 60% rename from resources/3rdparty/glpk-4.53/doc/gmpl.pdf rename to resources/3rdparty/glpk-4.57/doc/gmpl.pdf index dfd72fc3c..0f6833f68 100644 Binary files a/resources/3rdparty/glpk-4.53/doc/gmpl.pdf and b/resources/3rdparty/glpk-4.57/doc/gmpl.pdf differ diff --git a/resources/3rdparty/glpk-4.53/doc/gmpl.tex b/resources/3rdparty/glpk-4.57/doc/gmpl.tex similarity index 99% rename from resources/3rdparty/glpk-4.53/doc/gmpl.tex rename to resources/3rdparty/glpk-4.57/doc/gmpl.tex index 4c84fbd20..6c468603d 100644 --- a/resources/3rdparty/glpk-4.53/doc/gmpl.tex +++ b/resources/3rdparty/glpk-4.57/doc/gmpl.tex @@ -4,9 +4,9 @@ % This code is part of GLPK (GNU Linear Programming Kit). % % Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, -% 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied -% Informatics, Moscow Aviation Institute, Moscow, Russia. All rights -% reserved. E-mail: . +% 2009, 2010, 2011, 2013, 2014, 2015 Andrew Makhorin, Department for +% Applied Informatics, Moscow Aviation Institute, Moscow, Russia. All +% rights reserved. E-mail: . % % GLPK is free software: you can redistribute it and/or modify it % under the terms of the GNU General Public License as published by @@ -71,12 +71,12 @@ urlcolor=blue]{hyperref} \vspace{0.5in} \begin{LARGE} -\sf for GLPK Version 4.50 +\sf for GLPK Version 4.57 \end{LARGE} \vspace{0.5in} \begin{Large} -\sf (DRAFT, May 2013) +\sf (DRAFT, October 2015) \end{Large} \end{center} @@ -93,9 +93,9 @@ GNU. \noindent Copyright \copyright{} 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, -2008, 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied -Informatics, Moscow Aviation Institute, Moscow, Russia. All rights -reserved. +2008, 2009, 2010, 2011, 2013, 2014, 2015 Andrew Makhorin, Department +for Applied Informatics, Moscow Aviation Institute, Moscow, Russia. All +rights reserved. \noindent Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, @@ -1519,7 +1519,7 @@ expressions (see Subsection \ref{hierarchy}, page \pageref{hierarchy}). \section{Linear expressions} -An {\it linear expression} is a rule for computing so called +A {\it linear expression} is a rule for computing so called a {\it linear form} or simply a {\it formula}, which is a linear (or affine) function of elemental variables. @@ -2059,7 +2059,7 @@ the constraint. (Commae following expressions may be omitted.) s.t. r: x + y + z, >= 0, <= 1; limit{t in 1..T}: sum{j in prd} make[j,t] <= max_prd; subject to balance{i in raw, t in 1..T}: - store[i,t+1] - store[i,t] - sum{j in prd} units[i,j] * make[j,t]; + store[i,t+1] = store[i,t] - sum{j in prd} units[i,j] * make[j,t]; subject to rlim 'regular-time limit' {t in time}: sum{p in prd} pt[p] * rprd[p,t] <= 1.3 * dpp[t] * crews[t]; \end{verbatim} @@ -2283,8 +2283,8 @@ evaluated and displayed for every $n$-tuple in the domain set. In the latter case items may include dummy indices introduced in corresponding indexing expression. -An item to be displayed can be a model object (set, parameter, v -ariable, constraint, objective) or an expression. +An item to be displayed can be a model object (set, parameter, +variable, constraint, objective) or an expression. If the item is a computable object (i.e. a set or parameter provided with the assign attribute), the object is evaluated over the entire @@ -2774,7 +2774,7 @@ colon following the keyword {\tt(tr)} may be omitted.) set month := Jan Feb Mar Apr May Jun; set month "Jan", "Feb", "Mar", "Apr", "May", "Jun"; set A[3,Mar] := (1,2) (2,3) (4,2) (3,1) (2,2) (4,4) (3,4); -set A[3,'Mar'] := 1 2 2 3 4 2 3 1 2 2 4 4 2 4; +set A[3,'Mar'] := 1 2 2 3 4 2 3 1 2 2 4 4 3 4; set A[3,'Mar'] : 1 2 3 4 := 1 - + - - 2 - + + - @@ -3167,7 +3167,7 @@ following it. 2. Symbolic name $s$ may be omitted along with the colon following it. -3. All comae are optional and may be omitted. +3. All commae are optional and may be omitted. The data block in the tabbing format shown above is exactly equivalent to the following data blocks: diff --git a/resources/3rdparty/glpk-4.57/doc/gmpl_es.pdf b/resources/3rdparty/glpk-4.57/doc/gmpl_es.pdf new file mode 100644 index 000000000..2d5ca8e0c Binary files /dev/null and b/resources/3rdparty/glpk-4.57/doc/gmpl_es.pdf differ diff --git a/resources/3rdparty/glpk-4.57/doc/gmpl_es.tex b/resources/3rdparty/glpk-4.57/doc/gmpl_es.tex new file mode 100644 index 000000000..76a64485b --- /dev/null +++ b/resources/3rdparty/glpk-4.57/doc/gmpl_es.tex @@ -0,0 +1,3233 @@ +%* gmpl_es.tex *% + +%*********************************************************************** +% This code is part of GLPK (GNU Linear Programming Kit). +% +% Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, +% 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +% Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +% reserved. E-mail: . +% +% GLPK is free software: you can redistribute it and/or modify it +% under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% GLPK is distributed in the hope that it will be useful, but WITHOUT +% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +% or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +% License for more details. +% +% You should have received a copy of the GNU General Public License +% along with GLPK. If not, see . +%*********************************************************************** + +\documentclass[11pt,spanish]{report} +\usepackage[utf8]{inputenc} +\usepackage[T1]{fontenc} +\usepackage{amssymb} +\usepackage[dvipdfm,linktocpage,colorlinks,linkcolor=blue, +urlcolor=blue]{hyperref} +\usepackage{indentfirst} + +\setlength{\textwidth}{6.5in} +\setlength{\textheight}{8.5in} +\setlength{\oddsidemargin}{0in} +\setlength{\topmargin}{0in} +\setlength{\headheight}{0in} +\setlength{\headsep}{0in} +\setlength{\footskip}{0.5in} +\setlength{\parindent}{16pt} +\setlength{\parskip}{5pt} +\setlength{\topsep}{0pt} +\setlength{\partopsep}{0pt} +\setlength{\itemsep}{\parskip} +\setlength{\parsep}{0pt} +\setlength{\leftmargini}{\parindent} +\renewcommand{\labelitemi}{---} + +\def\para#1{\noindent{\bf#1}} + +\renewcommand\contentsname{\sf\bfseries Contenidos} +\renewcommand\chaptername{\sf\bfseries Capítulo} +\renewcommand\appendixname{\sf\bfseries Apéndice} + +\begin{document} + +\thispagestyle{empty} + +\begin{center} + +\vspace*{1.5in} + +\begin{huge} +\sf\bfseries Lenguaje de Modelado GNU MathProg +\end{huge} + +\vspace{0.5in} + +\begin{LARGE} +\sf Referencia del Lenguaje +\end{LARGE} + +\vspace{0.5in} + +\begin{LARGE} +\sf para GLPK Versión 4.50 +\end{LARGE} + +\vspace{0.5in} +\begin{Large} +\sf (BORRADOR, Mayo del 2013) +\end{Large} + +\end{center} + +\newpage + +\vspace*{1in} + +\vfill + +\noindent +El paquete GLPK es parte del Proyecto GNU distribuido bajo la égida de GNU + +\noindent +Copyright \copyright{} 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, +2008, 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +Informatics, Moscow Aviation Institute, Moscow, Russia. Todos los derechos +reservados. + +\noindent +Título original en inglés: Modeling Language GNU MathProg - Language Reference for GLPK Version 4.50 + +\noindent +Traducción: Pablo Yapura, Facultad de Ciencias Agrarias y Forestales, Universidad Nacional de La Plata, La Plata, Argentina. + +\noindent +Copyright \copyright{} 2013 Pablo Yapura, para esta traducción. Todos los derechos reservados. + +\noindent +Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, +MA 02110-1301, USA. + +\noindent +Se permite realizar y distribuir copias textuales de este manual siempre que se preserve este aviso de permiso y el aviso del copyright en todas las copias. + +\noindent +Se permite copiar y distribuir versiones modificadas de este manual bajo las condiciones de copias textuales, siempre que también se distribuya íntegro el trabajo derivado resultante bajo los términos de un aviso de permiso idéntico al presente. + +\noindent +Se permite copiar y distribuir traducciones de este manual en otro idioma bajo las condiciones establecidas arriba para versiones modificadas. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +{\setlength{\parskip}{0pt} +\tableofcontents +} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\chapter{Introducción} + +{\it GNU MathProg} es un lenguaje de modelado diseñado para describir modelos lineales de programación matemática.\footnote{El lenguaje GNU MathProg es un subconjunto del lenguaje AMPL. Su implementación en GLPK está basada principalmente en el paper: {\it Robert Fourer}, {\it David M. Gay} \& {\it Brian W. Kernighan}, ``A Modeling Language for Mathematical Programming.'' {\it Management Science} 36 (1990), pp.~519-554.} + +La descripción del modelo escrita en el lenguaje GNU MathProg consiste en un conjunto de sentencias y bloques de datos construidos por el usuario a partir de los elementos del lenguaje que se describen en este documento. + +En un proceso que se denomina {\it traducción}, un programa denominado {\it traductor del modelo} analiza la descripción del modelo y la traduce en una estructura interna de datos, la que puede ser usada tanto para generar una instancia de un problema de programación matemática, como para obtener directamente una solución numérica del problema mediante un programa denominado {\it solver}. + +\section{El problema de la programación lineal} +\label{problem} + +En MathProg el problema de la programación lineal (PL) se expresa como sigue: + +\medskip + +\noindent\hspace{1in}minimizar (o maximizar) +$$z=c_1x_1+c_2x_2+\dots+c_nx_n+c_0\eqno(1.1)$$ +\noindent\hspace{1in}sujeto a las restricciones lineales +$$ +\begin{array}{l@{\ }c@{\ }r@{\ }c@{\ }r@{\ }c@{\ }r@{\ }c@{\ }l} +L_1&\leq&a_{11}x_1&+&a_{12}x_2&+\dots+&a_{1n}x_n&\leq&U_1\\ +L_2&\leq&a_{21}x_1&+&a_{22}x_2&+\dots+&a_{2n}x_n&\leq&U_2\\ +\multicolumn{9}{c}{.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .}\\ +L_m&\leq&a_{m1}x_1&+&a_{m2}x_2&+\dots+&a_{mn}x_n&\leq&U_m\\ +\end{array}\eqno(1.2) +$$ +\noindent\hspace{1in}y a las cotas de las variables +$$ +\begin{array}{l@{\ }c@{\ }c@{\ }c@{\ }l} +l_1&\leq&x_1&\leq&u_1\\ +l_2&\leq&x_2&\leq&u_2\\ +\multicolumn{5}{c}{.\ \ .\ \ .\ \ .\ \ .}\\ +l_n&\leq&x_n&\leq&u_n\\ +\end{array}\eqno(1.3) +$$ + +\noindent +donde $x_1$, $x_2$, \dots, $x_n$ son variables; $z$ es la función objetivo; $c_1$, $c_2$, \dots, $c_n$ son coeficientes de la función objetivo; $c_0$ es el término constante (``de traslación'') de la función objetivo; $a_{11}$, +$a_{12}$, \dots, $a_{mn}$ son coeficientes de las restricciones; $L_1$, $L_2$, +\dots, $L_m$ son cotas inferiores de las restricciones; $U_1$, $U_2$, \dots, $U_m$ son cotas superiores de las restricciones; $l_1$, $l_2$, \dots, $l_n$ son cotas inferiores de las variables y $u_1$, $u_2$, \dots, $u_n$ son cotas superiores de las variables. + +Las cotas de las variables y las cotas de las restricciones pueden ser tanto finitas como infinitas. Además, las cotas inferiores pueden ser iguales a las correspondientes cotas superiores. Entonces, están permitidos los siguientes tipos de variables y restricciones: + +\medskip + +{\def\arraystretch{1.4} +\noindent\hspace{54pt} +\begin{tabular}{@{}r@{\ }c@{\ }c@{\ }c@{\ }l@{\hspace*{39.5pt}}l} +$-\infty$&$<$&$x$&$<$&$+\infty$&Variable libre (no acotada)\\ +$l$&$\leq$&$x$&$<$&$+\infty$&Variable con cota inferior\\ +$-\infty$&$<$&$x$&$\leq$&$u$&Variable con cota superior\\ +$l$&$\leq$&$x$&$\leq$&$u$&Variable doblemente acotada\\ +$l$&$=$&$x$&=&$u$&Variable fija\\ +\end{tabular} + +\noindent\hspace{54pt} +\begin{tabular}{@{}r@{\ }c@{\ }c@{\ }c@{\ }ll} +$-\infty$&$<$&$\sum a_jx_j$&$<$&$+\infty$&Forma lineal libre (no acotada)\\ +$L$&$\leq$&$\sum a_jx_j$&$<$&$+\infty$&Restricción de inecuación ``mayor o igual que''\\ +$-\infty$&$<$&$\sum a_jx_j$&$\leq$&$U$&Restricción de inecuación ``menor o igual que''\\ +$L$&$\leq$&$\sum a_jx_j$&$\leq$&$U$&Restricción de inecuación doblemente acotada\\ +$L$&$=$&$\sum a_jx_j$&=&$U$&Restricción de igualdad\\ +\end{tabular} +} + +\medskip + +Además de problemas puros de PL, MathProg también permite problemas de programación entera lineal mixta (PEM), en los que algunas o todas las variables se han restringido a ser enteras o binarias. + +\section{Objetos del modelo} + +En MathProg el modelo se describe mediante conjuntos, parámetros, variables, restricciones y objetivos, los que se denominan {\it objetos del modelo}. + +El usuario introduce objetos particulares del modelo usando las sentencias del lenguaje. Cada objeto del modelo está provisto de un nombre simbólico que lo identifica de manera única y está pensado con propósitos de referencia. + +\newpage + +Los objetos del modelo, incluyendo los conjuntos, pueden ser arreglos multidimensionales construidos sobre conjuntos indizantes. Formalmente, el arreglo $n$-dimensional $A$ es el mapeo $$A:\Delta\rightarrow\Xi,\eqno(1.4)$$ donde $\Delta\subseteq C_1\times\dots\times C_n$ es el subconjunto del producto cartesiano de los conjuntos indizantes, $\Xi$ es el conjunto de los miembros del arreglo. En MathProg, el conjunto $\Delta$ se denomina {\it dominio del subíndice}. Sus miembros son los $n$-tuplos $(i_1,\dots,i_n)$, donde +$i_1\in C_1$, \dots, $i_n\in C_n$. + +Si $n=0$, el producto cartesiano tiene exactamente un miembro (específicamente, un 0-tuplo), de forma tal que es conveniente pensar en los objetos escalares como arreglos 0-dimensionales que tienen un solo miembro. + +El tipo de los miembros del arreglo se determina por el tipo del objeto del modelo correspondiente como sigue: + +\medskip + +\noindent\hfil +\begin{tabular}{@{}ll@{}} +Objeto del modelo&Miembro del arreglo\\ +\hline +Conjunto&Conjunto plano elemental\\ +Parámetro&Número o símbolo\\ +Variable&Variable elemental\\ +Restricción&Restricción elemental\\ +Objetivo&Objetivo elemental\\ +\end{tabular} + +\medskip + +Para referir al miembro particular de un objeto, el mismo debe estar provisto de {\it subíndices}. Por ejemplo, si $a$ es un parámetro 2-dimensional definido sobre $I\times J$, una referencia a sus miembros particulares se puede escribir como $a[i,j]$, donde $i\in I$ y $j\in J$. Se sobreentiende que los objetos escalares no necesitan subíndices por ser 0-dimensionales. + +\section{Estructura de la descripción del modelo} + +A veces es deseable escribir un modelo que, en distintos momentos, puede requerir diferentes datos para solucionar cada instancia del problema usando el modelo. Por esta razón, en MathProg la descripción del modelo consta de dos partes: la {\it sección del modelo} y la {\it sección de los datos}. + +La sección del modelo es la parte principal de la descripción del modelo que contiene las declaraciones de los objetos del modelo; es común a todos los problemas basados en el modelo correspondiente. + +La sección de los datos es una parte opcional de la descripción del modelo que contiene los datos específicos para una instancia particular del problema. + +Dependiendo de lo que sea más conveniente, las secciones del modelo y de los datos pueden disponerse en el mismo archivo o en dos archivos separados. Esta última característica permite tener un número arbitrario de secciones con datos diferentes para ser usadas con la misma sección del modelo. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\chapter{Codificación de la descripción del modelo} +\label{coding} + +La descripción del modelo se codifica en formato de texto plano usando el juego de caracteres ASCII. Los caracteres válidos en la descripción del modelo son los siguientes: + +\begin{itemize} +\item caracteres alfabéticos:\\ +\verb|A B C D E F G H I J K L M N O P Q R S T U V W X Y Z|\\ +\verb|a b c d e f g h i j k l m n o p q r s t u v w x y z _| +\item caracteres numéricos:\\ +\verb|0 1 2 3 4 5 6 7 8 9| +\item caracteres especiales:\\ +\verb?! " # & ' ( ) * + , - . / : ; < = > [ ] ^ { | } ~? +\item caracteres no imprimibles:\\ +\verb|SP HT CR NL VT FF| +\end{itemize} + +Dentro de los literales de cadena y de los comentarios, cualquier carácter ASCII (excepto los caracteres de control) son válidos. + +Los caracteres no imprimibles no son significativos. Se pueden usar libremente entre las unidades léxicas para mejorar la legibilidad de la descripción del modelo. También se usan para separar unidades léxicas entre sí, en caso de no existir otra forma de hacerlo. + +Sintácticamente, la descripción del modelo es una secuencia de unidades léxicas de las siguientes categorías: + +\begin{itemize} +\item nombres simbólicos; +\item literales numéricos; +\item literales de cadena; +\item palabras clave; +\item delimitadores; +\item comentarios. +\end{itemize} + +Las unidades léxicas del lenguaje se discuten a continuación. + +\section{Nombres simbólicos} + +Un {\it nombre simbólico} consiste de caracteres alfabéticos y numéricos, el primero de los cuales debe ser alfabético. Todos los nombres simbólicos deben ser distintos (sensibilidad a las mayúsculas). + +\para{Ejemplos} + +\begin{verbatim} +alfa123 +Esto_es_un_nombre +_P123_abc_321 +\end{verbatim} + +Los nombres simbólicos se usan para identificar los objetos del modelo (conjuntos, parámetros, variables, restricciones y objetivos) y los índices. + +Todos los nombres simbólicos (exceptuando los nombres de los índices) deben ser únicos, {\it i.e.} la descripción del modelo no debe tener objetos distintos con el mismo nombre. Los nombres simbólicos de los índices deben ser únicos dentro del alcance en el que son válidos. + +\section{Literales numéricos} + +Un {\it literal numérico} sigue la forma {\it xx}{\tt E}{\it syy}, donde {\it xx} es un número con punto decimal optativo, {\it s} es el signo {\tt+} o {\tt-} e {\it yy} es un exponente decimal. La letra {\tt E} es insensible a las mayúsculas y se puede codificar como {\tt e}. + +\para{Ejemplos} + +\begin{verbatim} +123 +3.14159 +56.E+5 +.78 +123.456e-7 +\end{verbatim} + +Los literales numéricos se usan para representar cantidades numéricas y tienen significado fijo obvio. + +\section{Literales de cadena} + +Un {\it literal de cadena} es una secuencia arbitraria de caracteres encerrados entre comillas, tanto simples como dobles. Ambas formas son equivalentes. + +Si una comilla simple es parte de un literal de cadena encerrado entre comillas simples, se debe codificar dos veces. Análogamente, si una comilla doble es parte de un literal de cadena encerrado entre comillas dobles, se debe codificar dos veces. + +\para{Ejemplos} + +\begin{verbatim} +'Esta es una cadena' +"Esta es otra cadena" +'No debe usarse los 20''s' +"""Hola, che"" cantaba Favio." +\end{verbatim} + +Los literales de cadena se usan para representar cantidades simbólicas. + +\section{Palabras clave} + +Una {\it palabra clave} es una secuencia de caracteres alfabéticos y posiblemente algunos caracteres especiales. + +Todas la palabras clave caen en alguna de dos categorías: las {\it palabras clave reservadas}, que no pueden usarse como nombres simbólicos, y las {\it palabras clave no reservadas}, que son reconocidas por el contexto y entonces pueden usarse como nombres simbólicos. + +Las palabras clave reservadas son las siguientes: + +\noindent\hfil +\begin{tabular}{@{}p{.7in}p{.7in}p{.7in}p{.7in}@{}} +{\tt and}&{\tt else}&{\tt mod}&{\tt union}\\ +{\tt by}&{\tt if}&{\tt not}&{\tt within}\\ +{\tt cross}&{\tt in}&{\tt or}\\ +{\tt diff}&{\tt inter}&{\tt symdiff}\\ +{\tt div}&{\tt less}&{\tt then}\\ +\end{tabular} + +Las palabras clave no reservadas se describen en secciones posteriores. + +Todas las palabras clave tienen un significado fijo, el que se explicará en las discusiones de las correspondientes construcciones sintácticas donde las palabras claves sean usadas. + +\section{Delimitadores} + +Un {\it delimitador} es tanto un carácter especial individual como una secuencia de dos caracteres especiales, como sigue: + +\noindent\hfil +\begin{tabular}{@{}p{.3in}p{.3in}p{.3in}p{.3in}p{.3in}p{.3in}p{.3in} +p{.3in}p{.3in}@{}} +{\tt+}&{\tt**}&{\tt<=}&{\tt>}&{\tt\&\&}&{\tt:}&{\tt|}&{\tt[}&{\tt>}{\tt>}\\ +{\tt-}&{\tt\textasciicircum}&{\tt=}&{\tt<>}&{\tt||}&{\tt;}&{\tt\char126} +&{\tt]}&{\tt<-}\\ +{\tt*}&{\tt\&}&{\tt==}&{\tt!=}&{\tt.}&{\tt:=}&{\tt(}&{\tt\{}\\ +{\tt/}&{\tt<}&{\tt>=}&{\tt!}&{\tt,}&{\tt..}&{\tt)}&{\tt\}}\\ +\end{tabular} + +Si el delimitador está compuesto por dos caracteres, no debe haber espacios entre ellos. + +Todos los delimitadores tienen un significado fijo, el que se explicará en las discusiones de las correspondientes construcciones sintácticas donde los delimitadores sean usados. + +\section{Comentarios} + +Con propósitos de documentación, la descripción del modelo puede ser provista de {\it comentarios}, los que pueden ser de dos formas diferentes. La primera es un {\it comentario de una línea individual}, el que debe comenzar con el carácter {\tt\#} y se extiende hasta el final de la línea. La segunda forma es un {\it comentario en secuencia}, el que consiste en una secuencia de caracteres cualesquiera encerrados entre {\tt/*} y {\tt*/}. + +\para{Ejemplos} + +\begin{verbatim} +param n := 10; # Esto es un comentario +/* Esto es otro comentario */ +\end{verbatim} + +Los comentarios son ignorados por el traductor del modelo y pueden aparecer en cualquier sitio de la descripción del modelo en la que que se permitan caracteres no imprimibles. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\chapter{Expresiones} + +Una {\it expresión} es una regla para calcular un valor. En la descripción de un modelo, las expresiones se usan como constituyentes de ciertas sentencias. + +En general, las expresiones están compuestas por operandos y operadores. + +Dependiendo del tipo del valor resultante, todas las expresiones pertenecen a alguna de las siguientes categorías: + +\vspace*{-8pt} + +\begin{itemize} +\item expresiones numéricas; +\item expresiones simbólicas; +\item expresiones indizantes; +\item expresiones de conjuntos; +\item expresiones lógicas; +\item expresiones lineales. +\end{itemize} + +\vspace*{-8pt} + +\section{Expresiones numéricas} + +Una {\it expresión numérica} es una regla para calcular un valor numérico individual representado como un número de punto flotante. + +La expresión numérica primaria puede ser un literal numérico, un índice, un parámetro no-indizado, un parámetro indizado, una función interna de referencia, una expresión numérica iterada, una expresión numérica condicional u otra expresión numérica encerrada entre paréntesis. + +\newpage + +\para{Ejemplos} + +\noindent +\begin{tabular}{@{}ll@{}} +\verb|1.23|&(literal numérico)\\ +\verb|j|&(índice)\\ +\verb|tiempo|&(parámetro no-indizado)\\ +\verb|a['Mayo de 2003',j+1]|&(parámetro indizado)\\ +\verb|abs(b[i,j])|&(función de referencia)\\ +\verb|sum{i in S diff T} alfa[i] * b[i,j]|&(expresión iterada)\\ +\verb|if i in I then 2 * p else q[i+1]|&(expresión condicional)\\ +\verb|(b[i,j] + .5 * c)|&(expresión parentética)\\ +\end{tabular} + +Empleando ciertos operadores aritméticos se pueden construir expresiones numéricas más generales conteniendo dos o más expresiones numéricas primarias. + +\para{Ejemplos} + +\begin{verbatim} +j+1 +2 * a[i-1,j+1] - b[i,j] +sum{j in J} a[i,j] * x[j] + sum{k in K} b[i,k] * x[k] +(if i in I and p >= 1 then 2 * p else q[i+1]) / (a[i,j] + 1.5) +\end{verbatim} + +\subsection{Literales numéricos} + +Si la expresión numérica primaria es un literal numérico, el valor resultante es obvio. + +\subsection{Índices} + +Si la expresión numérica primaria es un índice, el valor resultante es el valor corriente asignado al índice. + +\subsection{Parámetros no-indizados} + +Si la expresión numérica primaria es un parámetro no-indizado (el que debe ser 0-dimensional), el valor resultante es el valor del parámetro. + +\subsection{Parámetros indizados} + +La expresión numérica primaria que se refiere a parámetros indizados tiene la siguiente forma sintáctica: +$$ +\mbox{{\it nombre}{\tt[}$i_1${\tt,} $i_2${\tt,} \dots{\tt,} $i_n${\tt]}} +$$ +donde {\it nombre} es el nombre simbólico del parámetro e $i_1$, $i_2$, +\dots, $i_n$ son subíndices. + +Cada subíndice debe ser una expresión numérica o simbólica. El número de subíndices en la lista de subíndices debe ser igual a la dimensión del parámetro con el cual está asociada la lista de subíndices. + +Los valores reales de las expresiones de subíndices se usan para identificar al miembro particular del parámetro que determina el valor resultante de la expresión primaria. + +\subsection{Funciones de referencia} + +En MathProg existen las siguientes funciones internas, las que se pueden usar en expresiones numéricas: + +\begin{tabular}{@{}p{112pt}p{328pt}@{}} +{\tt abs(}$x${\tt)}&$|x|$, valor absoluto de $x$\\ +{\tt atan(}$x${\tt)}&$\arctan x$, valor principal del arcotangente de +$x$ (en radianes)\\ +{\tt atan(}$y${\tt,} $x${\tt)}&$\arctan y/x$, valor principal del arcotangente de $y/x$ (en radianes). En este caso, los signos de ambos argumentos, $y$ y $x$, se usan para determinar el cuadrante del valor resultante\\ +{\tt card(}$X${\tt)}&$|X|$, el cardinal (número de elementos) del conjunto $X$\\ +{\tt ceil(}$x${\tt)}&$\lceil x\rceil$, el menor entero no menor que $x$ (``techo de $x$'')\\ +{\tt cos(}$x${\tt)}&$\cos x$, coseno de $x$ (en radianes)\\ +{\tt exp(}$x${\tt)}&$e^x$, exponencial en base $e$ de $x$\\ +{\tt floor(}$x${\tt)}&$\lfloor x\rfloor$, el mayor entero no mayor que $x$ (``piso de $x$'')\\ +{\tt gmtime()}&el número de segundos transcurridos desde las 00:00:00 del 1 de enero de 1970, Tiempo Universal Coordinado (para los detalles ver la Sección \ref{gmtime}, página \pageref{gmtime})\\ +{\tt length(}$c${\tt)}&$|c|$, longitud de la cadena de caracteres $c$\\ +{\tt log(}$x${\tt)}&$\log x$, logaritmo natural de $x$\\ +{\tt log10(}$x${\tt)}&$\log_{10}x$, logaritmo común (decimal) de $x$\\ +{\tt max(}$x_1${\tt,} $x_2${\tt,} \dots{\tt,} $x_n${\tt)}&el mayor de los valores $x_1$, $x_2$, \dots, $x_n$\\ +{\tt min(}$x_1${\tt,} $x_2${\tt,} \dots{\tt,} $x_n${\tt)}&el menor de los valores $x_1$, $x_2$, \dots, $x_n$\\ +{\tt round(}$x${\tt)}&redondeo de $x$ al entero más próximo\\ +{\tt round(}$x${\tt,} $n${\tt)}&redondeo de $x$ a $n$ dígitos decimales\\ +{\tt sin(}$x${\tt)}&$\sin x$, seno de $x$ (en radianes)\\ +{\tt sqrt(}$x${\tt)}&$\sqrt{x}$, raíz cuadrada no-negativa de $x$\\ +{\tt str2time(}$c${\tt,} $f${\tt)}&conversión de la cadena de caracteres $c$ a tiempo calendario (para los detalles ver la Sección \ref{str2time}, página \pageref{str2time})\\ +{\tt trunc(}$x${\tt)}&truncado de $x$ al entero más próximo\\ +{\tt trunc(}$x${\tt,} $n${\tt)}&truncado de $x$ a $n$ dígitos decimales\\ +{\tt Irand224()}&generación de un entero pseudo-aleatorio uniformemente distribuido en $[0,2^{24})$\\ +{\tt Uniform01()}&generación de un número pseudo-aleatorio uniformemente distribuido en $[0,1)$\\ +{\tt Uniform(}$a${\tt,} $b${\tt)}&generación de un número pseudo-aleatorio uniformemente distribuido en $[a,b)$\\ +{\tt Normal01()}&generación de una variable gaussiana pseudo-aleatoria con $\mu=0$ y $\sigma=1$\\ +{\tt Normal(}$\mu${\tt,} $\sigma${\tt)}&generación de una variable gaussiana pseudo-aleatoria con $\mu$ y $\sigma$ dadas\\ +\end{tabular} + +Los argumentos de todas la funciones internas, excepto {\tt card}, {\tt length} y {\tt str2time}, deben ser expresiones numéricas. El argumento de {\tt card} debe ser una expresión de conjunto. El argumento de {\tt length} y ambos argumentos de {\tt str2time} deben ser expresiones simbólicas. + +El valor resultante de una expresión numérica que es una función de referencia es el resultado de aplicar la función a sus argumentos. + +Se debe notar que cada función generadora pseudo-aleatoria tiene un argumento latente ({\it i.e.} algún estado interno) que cambia cada vez que se aplica la función. Así, si la función se aplica repetidamente, aún con argumentos idénticos, debido al efecto colateral siempre se producirán valores resultantes diferentes. + +\subsection{Expresiones iteradas} +\label{itexpr} + +Una {\it expresión numérica iterada} es una expresión numérica primaria que tiene la siguiente forma sintáctica: +$$\mbox{\it operador-iterado expresión-indizante integrando}$$ +donde {\it operador-iterado} es el nombre simbólico del operador iterado que se ejecutará (ver más adelante), {\it expresión-indizante} es una expresión indizante que introduce índices y controla la iteración e {\it integrando} es una expresión numérica que participa en la operación. + +En MathProg existen cuatro operadores iterados que se pueden usar en expresiones numéricas: + +{\def\arraystretch{2} +\noindent\hfil +\begin{tabular}{@{}lll@{}} +{\tt sum}&sumatoria&$\displaystyle\sum_{(i_1,\dots,i_n)\in\Delta} +f(i_1,\dots,i_n)$\\ +{\tt prod}&multiplicatoria&$\displaystyle\prod_{(i_1,\dots,i_n)\in\Delta} +f(i_1,\dots,i_n)$\\ +{\tt min}&mínimo&$\displaystyle\min_{(i_1,\dots,i_n)\in\Delta} +f(i_1,\dots,i_n)$\\ +{\tt max}&máximo&$\displaystyle\max_{(i_1,\dots,i_n)\in\Delta} +f(i_1,\dots,i_n)$\\ +\end{tabular} +} + +\noindent donde $i_1$, \dots, $i_n$ son índices introducidos en la expresión indizante, $\Delta$ es el dominio, el conjunto de los $n$-tuplos especificados en la expresión indizante que define valores particulares asignados a los índices para ejecutar la operación iterada y $f(i_1,\dots,i_n)$ es el integrando, una expresión numérica cuyo valor resultante depende de los índices. + +El valor resultante de una expresión numérica iterada es el resultado de aplicar el operador iterado a sus integrandos a través de todos los $n$-tuplos contenidos en el dominio. + +\subsection{Expresiones condicionales} +\label{ifthen} + +Una {\it expresión numérica condicional} es una expresión numérica primaria que tiene una de las dos formas sintácticas siguientes: +$$ +{\def\arraystretch{1.4} +\begin{array}{l} +\mbox{{\tt if} $b$ {\tt then} $x$ {\tt else} $y$}\\ +\mbox{{\tt if} $b$ {\tt then} $x$}\\ +\end{array} +} +$$ +donde $b$ es una expresión lógica, mientras que $x$ e $y$ son expresiones numéricas. + +El valor resultante de un expresión condicional depende del valor de la expresión lógica que sigue a la palabra clave {\tt if}. Si toma el valor {\it verdadero}, el valor de la expresión condicional es el valor de la expresión que sigue a la palabra clave {\tt then}. De otro modo, si la expresión lógica toma el valor {\it falso}, el valor de la expresión condicional es el valor de la expresión que sigue a la palabra clave {\tt else}. Si se usa la segunda forma sintáctica, la reducida, y la expresión lógica toma el valor {\it falso}, el valor resultante de la expresión condicional será cero. + +\subsection{Expresiones parentéticas} + +Cualquier expresión numérica puede ser encerrada entre paréntesis, lo que las torna sintácticamente en una expresión numérica primaria. + +Los paréntesis pueden usarse en expresiones numéricas, como en el álgebra, para especificar el orden deseado en el cual se ejecutarán las operaciones. Cuando se usan paréntesis, la expresión entre paréntesis se evalúa antes que el valor resultante sea usado. + +El valor resultante de la expresión parentética es idéntico al valor de la expresión encerrada entre paréntesis. + +\subsection{Operadores aritméticos} + +En MathProg existen los siguientes operadores aritméticos, los que se pueden usar en expresiones numéricas: + +\begin{tabular}{@{}ll@{}} +{\tt +} $x$&más unario\\ +{\tt -} $x$&menos unario\\ +$x$ {\tt +} $y$&adición\\ +$x$ {\tt -} $y$&sustracción\\ +$x$ {\tt less} $y$&diferencia positiva (si $x1$, la segunda forma es la que debe usarse. + +Si se usa la primera forma de la entrada indizante, el índice $i$ sólo puede ser un índice (ver más adelante). Si se usa la segunda forma, los índices $i_1$, $i_2$, \dots, $i_n$ pueden ser indistintamente índices o alguna expresión numérica o simbólica, siempre que al menos uno de los índices sea un índice. La tercera forma, reducida, de la entrada indizante tiene el mismo efecto que si +$i$ (si $C$ es 1-dimensional) o $i_1$, $i_2$, \dots, $i_n$ (si $C$ es $n$-dimensional) se hubieran especificado todos como índices. + +Un {\it índice} es un objeto auxiliar del modelo que actúa como una variable individual. Los valores asignados a los índices son componentes de los $n$-tuplos de conjuntos básicos, {\it i.e.} algunas cantidades numéricas y simbólicas. + +Para referenciarlos, los índices pueden ser provistos con nombres simbólicos. Sin embargo, a diferencia de otros objetos del modelo (conjuntos, parámetros, etc.), los índices no necesitan ser declarados explícitamente. Cada nombre simbólico {\it no-declarado} que se usa en una posición indizante de alguna entrada indizante es reconocido como el nombre simbólico correspondiente al índice. + +Los nombre simbólicos de los índices son válidos solamente dentro del alcance de la expresión indizante en la que se introdujo el índice. Más allá del alcance, estos índices son completamente inaccesibles, de modo que los mismos nombres simbólicos se pueden usar para diferentes propósitos, en particular para representar índices en otras expresiones indizantes. + +El alcance de la expresión indizante, en el que las declaraciones implícitas de los índices son válidas, depende del contexto en que se usa la expresión indizante: + +\vspace*{-8pt} + +\begin{itemize} +\item Si la expresión indizante se usa en un operador-iterado, su alcance se extiende hasta el final del integrando; +\item Si la expresión indizante se usa como una expresión de conjunto primaria, su alcance se extiende hasta el final de esta expresión indizante; +\item Si la expresión indizante se usa para definir el dominio del subíndice en la declaración de algún objeto del modelo, su alcance se extiende hasta el final de la correspondiente sentencia. +\end{itemize} + +\vspace*{-8pt} + +El mecanismo de indización implementado mediante las expresiones indizantes se explica mejor con algunos ejemplos que se discuten a continuación. + +Sean tres conjuntos: +$$ +{\def\arraystretch{1.4} +\begin{array}{l} +A=\{4,7,9\},\\ +B=\{(1,Ene),(1,Feb),(2,Mar),(2,Abr),(3,May),(3,Jun)\},\\ +C=\{a,b,c\},\\ +\end{array} +} +$$ +donde $A$ y $C$ consisten de 1-tuplos (singletones) y $B$ consiste de +2-tuplos (duplos). Considérese la siguiente expresión indizante: +$$\mbox{{\tt\{i in A, (j,k) in B, l in C\}}}$$ +donde {\tt i}, {\tt j}, {\tt k} y {\tt l} son índices. + +Aunque MathProg no es un lenguaje de programación por procedimientos, para cualquier expresión indizante se puede dar una descripción algorítmica equivalente. En particular, la descripción algorítmica de la expresión indizante anterior se vería como sigue: + +\noindent\hfil +\begin{tabular}{@{}l@{}} +{\bf para todo} $i\in A$ {\bf ejecutar}\\ +\hspace{16pt}{\bf para todo} $(j,k)\in B$ {\bf ejecutar}\\ +\hspace{32pt}{\bf para todo} $l\in C$ {\bf ejecutar}\\ +\hspace{48pt}{\it acción};\\ +\end{tabular} + +\noindent donde los índices $i$, $j$, $k$ y $l$ son asignados consecutivamente a los correspondientes componentes de los $n$-tuplos a partir de los conjuntos básicos $A$, $B$ y $C$ y {\it acción} es alguna acción que depende del contexto en el que se esté usando la expresión indizante. Por ejemplo, si la acción fuese imprimir los valores corrientes de los índices, la impresión se vería como sigue: + +\noindent\hfil +\begin{tabular}{@{}llll@{}} +$i=4$&$j=1$&$k=Ene$&$l=a$\\ +$i=4$&$j=1$&$k=Ene$&$l=b$\\ +$i=4$&$j=1$&$k=Ene$&$l=c$\\ +$i=4$&$j=1$&$k=Feb$&$l=a$\\ +$i=4$&$j=1$&$k=Feb$&$l=b$\\ +\multicolumn{4}{c}{.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .}\\ +$i=9$&$j=3$&$k=Jun$&$l=b$\\ +$i=9$&$j=3$&$k=Jun$&$l=c$\\ +\end{tabular} + +Sea la expresión indizante del ejemplo usada en la siguiente operación iterada: +$$\mbox{{\tt sum\{i in A, (j,k) in B, l in C\} p[i,j,k,l]}}$$ +donde {\tt p} es un parámetro numérico 4-dimensional o alguna expresión numérica cuyos valores resultantes dependan de {\tt i}, {\tt j}, {\tt k} y {\tt l}. En este caso la acción es la sumatoria, de modo que el valor resultante de la expresión numérica primaria es: +$$\sum_{i\in A,(j,k)\in B,l\in C}(p_{ijkl}).$$ + +Ahora, sea la expresión indizante del ejemplo usada como una expresión de conjunto primaria. En este caso, la acción es reunir a todos los 4-tuplos (cuádruplos) de la forma $(i,j,k,l)$ en un conjunto, de modo que el valor resultante de tal operación es simplemente el producto cartesiano de los conjuntos básicos: +$$A\times B\times C=\{(i,j,k,l):i\in A,(j,k)\in B,l\in C\}.$$ +Se debe notar que, en este caso, la misma expresión indizante podría escribirse en la forma reducida: +$$\mbox{{\tt\{A, B, C\}}}$$ +ya que los índices $i$, $j$, $k$ y $l$ no son referenciados y, consecuentemente, sus nombres simbólicos no necesitan ser especificados. + +Finalmente, sea la expresión indizante del ejemplo usada como el dominio del subíndice en la declaración de algún objeto 4-dimensional del modelo, por ejemplo un parámetro numérico: +$$\mbox{{\tt param p\{i in A, (j,k) in B, l in C\}} \dots {\tt;}}$$ + +\noindent En este caso la acción es generar los miembros del parámetro, donde cada uno de los cuales tiene la forma $p[i,j,k,l]$. + +Como se dijo anteriormente, algunos índices en la segunda forma de las entradas indizantes pueden ser expresiones numéricas o simbólicas, no solamente índices. En este caso, los valores resultantes de tales expresiones desempeñan el papel de algunas condiciones lógicas para seleccionar, solamente, aquellos $n$-tuplos del producto cartesiano de los conjuntos básicos que satisfacen estas condiciones. + +Considérese, por ejemplo, la siguiente expresión indizante: +$$\mbox{{\tt\{i in A, (i-1,k) in B, l in C\}}}$$ +donde {\tt i}, {\tt k} y {\tt l} son índices e {\tt i-1} es una expresión numérica. La descripción algorítmica de esta expresión indizante sería la siguiente: + +\noindent\hfil +\begin{tabular}{@{}l@{}} +{\bf para todo} $i\in A$ {\bf ejecutar}\\ +\hspace{16pt}{\bf para todo} $(j,k)\in B$ {\bf y} $j=i-1$ {\bf ejecutar}\\ +\hspace{32pt}{\bf para todo} $l\in C$ {\bf ejecutar}\\ +\hspace{48pt}{\it acción};\\ +\end{tabular} + +\noindent Así, si la expresión indizante se usara como una expresión de conjunto primaria, el conjunto resultante sería el siguiente: +$$\{(4,May,a),(4,May,b),(4,May,c),(4,Jun,a),(4,Jun,b),(4,Jun,c)\}.$$ +Debe notarse que, en este caso, el conjunto resultante consistirá de 3-tuplos y no de 4-tuplos, puesto que en la expresión indizante no hay un índice que corresponda al primer componente de los 2-tuplos del conjunto $B$. + +La regla general es: el número de componentes de los $n$-tuplos definido por una expresión indizante es igual al número de índices de tal expresión, en la que la correspondencia entre los índices y los componentes de los $n$-tuplos en el conjunto resultante es posicional, {\it i.e.} el primer índice se corresponde con el primer componente, el segundo índice se corresponde con el segundo componente, etc. + +En algunos casos es necesario seleccionar un subconjunto del producto cartesiano de algunos conjuntos. Esto se puede lograr mediante el empleo de un predicado lógico opcional, el que se especifica en la expresión indizante. + +Considérese, por ejemplo, la siguiente expresión indizante: +$$\mbox{{\tt\{i in A, (j,k) in B, l in C: i <= 5 and k <> 'Mar'\}}}$$ +donde la expresión lógica que sigue a los dos puntos es un predicado. La descripción algorítmica de tal expresión indizante sería la siguiente: + +\noindent\hfil +\begin{tabular}{@{}l@{}} +{\bf para todo} $i\in A$ {\bf ejecutar}\\ +\hspace{16pt}{\bf para todo} $(j,k)\in B$ {\bf ejecutar}\\ +\hspace{32pt}{\bf para todo} $l\in C$ {\bf ejecutar}\\ +\hspace{48pt}{\bf si} $i\leq 5$ {\bf y} $k\neq`Mar'$ {\bf entonces}\\ +\hspace{64pt}{\it acción};\\ +\end{tabular} + +\noindent Así, si esta expresión indizante se usara como una expresión de conjunto primaria, el conjunto resultante sería el siguiente: +$$\{(4,1,Ene,a),(4,1,Feb,a),(4,2,Abr,a),\dots,(4,3,Jun,c)\}.$$ + +Si no se especifica un predicado en la expresión indizante, se asume uno que toma el valor {\it verdadero}. + +\section{Expresiones de conjunto} + +Una {\it expresión de conjunto} es una regla para calcular un conjunto elemental, {\it i.e.} una colección de $n$-tuplos cuyos componentes son cantidades numéricas y simbólicas. + +La expresión de conjunto primaria puede ser un conjunto de literales, un conjunto no-indizado, un conjunto indizado, un conjunto ``aritmético'', una expresión indizante, una expresión de conjunto iterada, una expresión de conjunto condicional u otra expresión de conjunto encerrada entre paréntesis. + +\para{Ejemplos} + +\noindent +\begin{tabular}{@{}ll@{}} +\verb|{(123,'aaa'), (i+1,'bbb'), (j-1,'ccc')}| &(conjunto de literales)\\ +\verb|I| &(conjunto no-indizado)\\ +\verb|S[i-1,j+1]| &(conjunto indizado)\\ +\verb|1..t-1 by 2| &(conjunto ``aritmético'')\\ +\verb|{t in 1..T, (t+1,j) in S: (t,j) in F}| &(expresión indizante)\\ +\verb|setof{i in I, j in J}(i+1,j-1)| &(expresión de conjunto iterada)\\ +\verb|if i < j then S[i,j] else F diff S[i,j]| &(expresión de conjunto condicional)\\ +\verb|(1..10 union 21..30)| &(expresión de conjunto parentética)\\ +\end{tabular} + +Empleando ciertos operadores de conjunto se pueden construir expresiones de conjunto más generales conteniendo dos o más expresiones de conjunto primarias. + +\newpage + +\para{Ejemplos} + +\begin{verbatim} +(A union B) inter (I cross J) +1..10 cross (if i < j then {'a', 'b', 'c'} else {'d', 'e', 'f'}) +\end{verbatim} + +\subsection{Conjuntos de literales} + +Un {\it conjunto de literales} es una expresión de conjunto primaria que tiene las dos formas sintácticas siguientes: +$$ +{\def\arraystretch{1.4} +\begin{array}{l} +\mbox{{\tt\{}$e_1${\tt,} $e_2${\tt,} \dots{\tt,} $e_m${\tt\}}}\\ +\mbox{{\tt\{(}$e_{11}${\tt,} \dots{\tt,} $e_{1n}${\tt),} +{\tt(}$e_{21}${\tt,} \dots{\tt,} $e_{2n}${\tt),} \dots{\tt,} +{\tt(}$e_{m1}${\tt,} \dots{\tt,} $e_{mn}${\tt)\}}}\\ +\end{array} +} +$$ +donde $e_1$, \dots, $e_m$, $e_{11}$, \dots, $e_{mn}$ son expresiones numéricas o simbólicas. + +Si se usa la primera forma, el conjunto resultante consiste de 1-tuplos (singletones), enumerados entre las llaves. Se permite especificar un conjunto vacío como {\tt\{\ \}}, el que no tiene 1-tuplos. Si se usa la segunda forma, el conjunto resultante consiste de $n$-tuplos enumerados entre las llaves, donde cada $n$-tuplo particular está compuesto por los correspondientes componentes enumerados entre los paréntesis. Todos los $n$-tuplos deben tener el mismo número de componentes. + +\subsection{Conjuntos no-indizados} + +Si la expresión de conjunto primaria es un conjunto no-indizado (el que debe ser 0-dimensional), el conjunto resultante es un conjunto elemental asociado con el objeto conjunto correspondiente. + +\subsection{Conjuntos indizados} + +La expresión de conjunto primaria que se refiere a un conjunto indizado tiene la siguiente forma sintáctica: +$$\mbox{{\it nombre}{\tt[}$i_1${\tt,} $i_2${\tt,} \dots{\tt,} +$i_n${\tt]}}$$ +donde {\it nombre} es el nombre simbólico del objeto conjunto e $i_1$, $i_2$, +\dots, $i_n$ son subíndices. + +Cada subíndice debe ser una expresión numérica o simbólica. El número de subíndices en la lista de subíndices debe coincidir con la dimensión del objeto conjunto al cual está asociada la lista de subíndices. + +Los valores corrientes de las expresiones de los subíndices se usan para identificar un miembro particular del objeto conjunto que determina el conjunto resultante. + +\subsection{Conjuntos ``aritméticos''} + +La expresión de conjunto primaria que constituye un conjunto ``aritmético'' tiene las dos formas sintácticas siguientes: +$$ +{\def\arraystretch{1.4} +\begin{array}{l} +\mbox{$t_0$ {\tt..} $t_1$ {\tt by} $\delta t$}\\ +\mbox{$t_0$ {\tt..} $t_1$}\\ +\end{array} +} +$$ +donde $t_0$, $t_1$ y $\delta t$ son expresiones numéricas (el valor de +$\delta t$ no debe ser cero). La segunda forma es equivalente a la primera con $\delta t=1$. + +Si $\delta t>0$, el conjunto resultante se determina como sigue: +$$\{t:\exists k\in{\cal Z}(t=t_0+k\delta t,\ t_0\leq t\leq t_1)\}.$$ +De otro modo, si $\delta t<0$, el conjunto resultante se determina como sigue: +$$\{t:\exists k\in{\cal Z}(t=t_0+k\delta t,\ t_1\leq t\leq t_0)\}.$$ + +\subsection{Expresiones de indización} + +Si la expresión de conjunto primaria es una expresión indizante, el conjunto resultante se determina como se ha descripto anteriormente en la Sección \ref{indexing}, página \pageref{indexing}. + +\subsection{Expresiones iteradas} + +Una {\it expresión de conjunto iterada} es una expresión de conjunto primaria que tiene la siguiente forma sintáctica: +$$\mbox{{\tt setof} {\it expresión-indizante} {\it integrando}}$$ +donde {\it expresión-indizante} es una expresión indizante que introduce índices y controla la iteración e {\it integrando} es tanto una expresión numérica o simbólica individual como una lista de expresiones numéricas o simbólicas separadas por coma y encerradas entre paréntesis. + +Si el integrando es una expresión numérica o simbólica individual, el conjunto resultante está compuesto por 1-tuplos y se determina como sigue: +$$\{x:(i_1,\dots,i_n)\in\Delta\},$$ +\noindent donde $x$ es un valor del integrando, $i_1$, \dots, $i_n$ son índices introducidos en la expresión indizante y $\Delta$ es el dominio, un conjunto de $n$-tuplos especificados por la expresión indizante que define los valores particulares asignados a los índices para realizar la operación iterada. + +Si el integrando es una lista conteniendo $m$ expresiones numéricas y simbólicas, el conjunto resultante está compuesto por $m$-tuplos y se determina como sigue: +$$\{(x_1,\dots,x_m):(i_1,\dots,i_n)\in\Delta\},$$ +donde $x_1$, \dots, $x_m$ son valores de las expresiones en la lista de integrandos e $i_1$, \dots, $i_n$ y $\Delta$ tienen el mismo significado anterior. + +\subsection{Expresiones condicionales} + +Una {\it expresión de conjunto condicional} es una expresión de conjunto primaria que tiene la siguiente forma sintáctica: +$$\mbox{{\tt if} $b$ {\tt then} $X$ {\tt else} $Y$}$$ +donde $b$ es una expresión lógica y $X$ e $Y$ son expresiones de conjunto que deben definir conjuntos de igual dimensión. + +El valor resultante de la expresión condicional depende del valor de la expresión lógica que sigue a la palabra clave {\tt if}. Si toma el valor {\it verdadero}, el conjunto resultante es el valor de la expresión que sigue a la palabra clave {\tt then}. De otro modo, si la expresión lógica toma el valor {\it falso}, el conjunto resultante es el valor de la expresión que sigue a la palabra clave {\tt else}. + +\subsection{Expresiones parentéticas} + +Cualquier expresión de conjunto puede encerrarse entre paréntesis, lo que la convierte sintácticamente en una expresión de conjunto primaria. + +Los paréntesis pueden usarse en expresiones de conjunto, como en el álgebra, para especificar el orden deseado en el cual se ejecutarán las operaciones. Cuando se usan paréntesis, la expresión entre paréntesis se evalúa antes que el valor resultante sea usado. + +El valor resultante de la expresión parentética es idéntico al valor de la expresión encerrada entre paréntesis. + +\subsection{Operadores de conjunto} + +En MathProg existen los siguientes operadores de conjunto, los que se pueden usar en expresiones de conjunto: + +\begin{tabular}{@{}ll@{}} +$X$ {\tt union} $Y$&union $X\cup Y$\\ +$X$ {\tt diff} $Y$&diferencia $X\backslash Y$\\ +$X$ {\tt symdiff} $Y$&diferencia simétrica $X\oplus Y=(X\backslash Y)\cup(Y\backslash X)$\\ +$X$ {\tt inter} $Y$&intersección $X\cap Y$\\ +$X$ {\tt cross} $Y$&producto cartesiano (``cruzado'') $X\times Y$\\ +\end{tabular} + +\noindent donde $X$ e $Y$ son expresiones de conjunto que deben definir conjuntos de la misma dimensión (excepto para el producto cartesiano). + +Si la expresión incluye más de un operador de conjunto, todos los operadores se ejecutan de izquierda a derecha, de acuerdo con la jerarquía de las operaciones (ver más adelante). + +El valor resultante de la expresión que contiene operadores de conjunto es el resultado de aplicar los operadores a sus operandos. + +La dimensión del conjunto resultante, {\it i.e.} la dimensión de los $n$-tuplos de los que consiste el conjunto resultante, es la dimensión de los operandos, excepto en el producto cartesiano, en la que la dimensión del conjunto resultante es la suma de las dimensiones de sus operandos. + +\subsection{Jerarquía de las operaciones} + +La siguiente lista muestra la jerarquía de las operaciones en expresiones de conjunto: + +\noindent\hfil +\begin{tabular}{@{}ll@{}} +Operación&Jerarquía\\ +\hline +Evaluación de operaciones numéricas& +1.{\textsuperscript{\b{a}}}-7.{\textsuperscript{\b{a}}}\\ +Evaluación de operaciones simbólicas& +8.{\textsuperscript{\b{a}}}-9.{\textsuperscript{\b{a}}}\\ +Evaluación de conjuntos iterados o ``aritméticos'' ({\tt setof}, {\tt..})& +10.{\textsuperscript{\b{a}}}\\ +Producto cartesiano ({\tt cross})& +11.{\textsuperscript{\b{a}}}\\ +Intersección ({\tt inter})& +12.{\textsuperscript{\b{a}}}\\ +Unión y diferencia ({\tt union}, {\tt diff}, {\tt symdiff})& +13.{\textsuperscript{\b{a}}}\\ +Evaluación condicional ({\tt if} \dots {\tt then} \dots {\tt else})& +14.{\textsuperscript{\b{a}}}\\ +\end{tabular} + +Esta jerarquía tiene el mismo significado que se explicó anteriormente para expresiones numéricas (ver Subsección \ref{hierarchy}, página \pageref{hierarchy}). + +\section{Expresiones lógicas} + +Una {\it expresión lógica} es una regla para calcular un valor lógico individual, el que puede ser tanto {\it verdadero} como {\it falso}. + +La expresión lógica primaria puede ser una expresión numérica, una expresión relacional, una expresión lógica iterada u otra expresión lógica encerrada entre paréntesis. + +\para{Ejemplos} + +\noindent +\begin{tabular}{@{}ll@{}} +\verb|i+1| &(expresión numérica)\\ +\verb|a[i,j] < 1.5| &(expresión relacional)\\ +\verb|s[i+1,j-1] <> 'Mar' & anho | &(expresión relacional)\\ +\verb|(i+1,'Ene') not in I cross J| &(expresión relacional)\\ +\verb|S union T within A[i] inter B[j]| &(expresión relacional)\\ +\verb|forall{i in I, j in J} a[i,j] < .5 * b[i]| &(expresión lógica iterada)\\ +\verb|(a[i,j] < 1.5 or b[i] >= a[i,j])| &(expresión lógica parentética)\\ +\end{tabular} + +Empleando ciertos operadores lógicos se pueden construir expresiones lógicas más generales conteniendo dos o más expresiones lógicas primarias. + +\para{Ejemplos} + +\begin{verbatim} +not (a[i,j] < 1.5 or b[i] >= a[i,j]) and (i,j) in S +(i,j) in S or (i,j) not in T diff U +\end{verbatim} + +\vspace*{-8pt} + +\subsection{Expresiones numéricas} + +El valor resultante de una expresión lógica primaria, cuando es una expresión numérica, es {\it verdadero} si el valor resultante de la expresión numérica es distinto de cero. De otro modo, el valor resultante de la expresión lógica es {\it falso}. + +\vspace*{-8pt} + +\subsection{Operadores relacionales} + +En MathProg existen los siguientes operadores relacionales, los que se pueden usar en expresiones lógicas: + +\begin{tabular}{@{}ll@{}} +$x$ {\tt<} $y$&comprueba si $x=} $y$&comprueba si $x\geq y$\\ +$x$ {\tt>} $y$&comprueba si $x>y$\\ +$x$ {\tt<>} $y$, $x$ {\tt!=} $y$&comprueba si $x\neq y$\\ +$x$ {\tt in} $Y$&comprueba si $x\in Y$\\ +{\tt(}$x_1${\tt,}\dots{\tt,}$x_n${\tt)} {\tt in} $Y$&comprueba si +$(x_1,\dots,x_n)\in Y$\\ +$x$ {\tt not} {\tt in} $Y$, $x$ {\tt!in} $Y$&comprueba si $x\not\in Y$\\ +{\tt(}$x_1${\tt,}\dots{\tt,}$x_n${\tt)} {\tt not} {\tt in} $Y$, +{\tt(}$x_1${\tt,}\dots{\tt,}$x_n${\tt)} {\tt !in} $Y$&comprueba si +$(x_1,\dots,x_n)\not\in Y$\\ +$X$ {\tt within} $Y$&comprueba si $X\subseteq Y$\\ +$X$ {\tt not} {\tt within} $Y$, $X$ {\tt !within} $Y$&comprueba si +$X\not\subseteq Y$\\ +\end{tabular} + +\noindent donde $x$, $x_1$, \dots, $x_n$ e $y$ son expresiones numéricas o simbólicas, mientras que $X$ e $Y$ son expresiones de conjunto. + +Notas: + +1. En las operaciones {\tt in}, {\tt not in} y {\tt !in} el número de componentes del primer operando debe ser igual a la dimensión del segundo operando. + +2. En las operaciones {\tt within}, {\tt not within} y {\tt !within} ambos operandos deben tener la misma dimensión. + +Todos los operadores relacionales listados anteriormente tienen su significado matemático convencional. El valor resultante es {\it verdadero} si los operandos satisfacen la correspondiente relación, o es {\it falso} en caso contrario. (Debe notarse que los valores simbólicos se ordenan lexicográficamente y que cualquier valor numérico precede a cualquier valor simbólico.) + +\subsection{Expresiones iteradas} + +Una {\it expresión lógica iterada} es una expresión lógica primaria que tiene la siguiente forma sintáctica: +$$\mbox{{\it operador-iterado} {\it expresión-indizante} +{\it integrando}}$$ +donde {\it operador-iterado} es el nombre simbólico del operador iterado que se ejecutará (ver más adelante), {\it expresión-indizante} es una expresión indizante que introduce índices y controla la iteración e {\it integrando} es una expresión lógica que participa en la operación. + +En MathProg existen dos operadores iterados que se pueden usar en expresiones lógicas: + +{\def\arraystretch{1.4} +\noindent\hfil +\begin{tabular}{@{}lll@{}} +{\tt forall}&cuantificador-$\forall$&$\displaystyle +\forall(i_1,\dots,i_n)\in\Delta[f(i_1,\dots,i_n)],$\\ +{\tt exists}&cuantificador-$\exists$&$\displaystyle +\exists(i_1,\dots,i_n)\in\Delta[f(i_1,\dots,i_n)],$\\ +\end{tabular} +} + +\noindent donde $i_1$, \dots, $i_n$ son índices introducidos en la expresión indizante, $\Delta$ es el dominio, un conjunto de $n$-tuplos especificados por la expresión indizante que define los valores particulares asignados a los índices para ejecutar la operación iterada y $f(i_1,\dots,i_n)$ es el integrando, una expresión lógica cuyo valor resultante depende de los índices. + +Para el cuantificador-$\forall$, el valor resultante de la expresión lógica iterada es {\it verdadero} si el valor del integrando es {\it verdadero} para todos los $n$-tuplos contenidos en el dominio, de otro modo es {\it falso}. + +Para el cuantificador-$\exists$, el valor resultante de la expresión lógica iterada es {\it falso} si el valor del integrando es {\it falso} para todos los $n$-tuplos contenidos en el dominio, de otro modo es {\it verdadero}. + +\subsection{Expresiones parentéticas} + +Cualquier expresión lógica puede encerrarse entre paréntesis, lo que la convierte sintácticamente en una expresión lógica primaria. + +Los paréntesis pueden usarse en expresiones lógicas, como en el álgebra, para especificar el orden deseado en el cual se ejecutarán las operaciones. Cuando se usan paréntesis, la expresión entre paréntesis se evalúa antes que el valor resultante sea usado. + +El valor resultante de la expresión parentética es idéntico al valor de la expresión encerrada entre paréntesis. + +\subsection{Operadores lógicos} + +En MathProg existen los siguientes operadores lógicos, los que se pueden usar en expresiones lógicas: + +\begin{tabular}{@{}ll@{}} +{\tt not} $x$, {\tt!}$x$&negación $\neg\ x$\\ +$x$ {\tt and} $y$, $x$ {\tt\&\&} $y$&conjunción (``y'' lógico) +$x\;\&\;y$\\ +$x$ {\tt or} $y$, $x$ {\tt||} $y$&disyunción (``o'' lógico) +$x\vee y$\\ +\end{tabular} + +\noindent donde $x$ e $y$ son expresiones lógicas. + +Si la expresión incluye más de un operador lógico, todos los operadores se ejecutan de izquierda a derecha, de acuerdo con la jerarquía de las operaciones (ver más adelante). El valor resultante de la expresión que contiene operadores lógicos es el resultado de aplicar los operadores a sus operandos. + +\subsection{Jerarquía de las operaciones} + +La siguiente lista muestra la jerarquía de las operaciones en expresiones lógicas: + +\noindent\hfil +\begin{tabular}{@{}ll@{}} +Operación&Jerarquía\\ +\hline +Evaluación de operaciones numéricas& +1.{\textsuperscript{\b{a}}}-7.{\textsuperscript{\b{a}}}\\ +Evaluación de operaciones simbólicas& +8.{\textsuperscript{\b{a}}}-9.{\textsuperscript{\b{a}}}\\ +Evaluación de operaciones de conjuntos& +10.{\textsuperscript{\b{a}}}-14.{\textsuperscript{\b{a}}}\\ +Operaciones relacionales ({\tt<}, {\tt<=}, etc.)& +15.{\textsuperscript{\b{a}}}\\ +Negación ({\tt not}, {\tt!})& +16.{\textsuperscript{\b{a}}}\\ +Conjunción ({\tt and}, {\tt\&\&})& +17.{\textsuperscript{\b{a}}}\\ +Cuantificación-$\forall$ y -$\exists$ ({\tt forall}, {\tt exists})& +18.{\textsuperscript{\b{a}}}\\ +Disyunción ({\tt or}, {\tt||})& +19.{\textsuperscript{\b{a}}}\\ +\end{tabular} + +Esta jerarquía tiene el mismo significado que se explicó anteriormente para expresiones numéricas (ver Subsección \ref{hierarchy}, página \pageref{hierarchy}). + +\section{Expresiones lineales} + +Una {\it expresión lineal} es una regla para calcular la denominada {\it forma lineal}, que es una función lineal (o afín) de variables elementales. + +La expresión lineal primaria puede ser una variable no-indizada, una variable indizada, una expresión lineal iterada, una expresión lineal condicional u otra expresión lineal encerrada entre paréntesis. + +También está permitido usar una expresión numérica como una expresión lineal primaria, en cuyo caso el valor resultante de la expresión numérica se convierte automáticamente a una forma lineal que incluye el término constante solamente. + +\para{Ejemplos} + +\noindent +\begin{tabular}{@{}ll@{}} +\verb|z| &(variable no-indizada)\\ +\verb|x[i,j]| &(variable indizada)\\ +\verb|sum{j in J} (a[i,j] * x[i,j] + 3 * y[i-1])| & +(expresión lineal iterada)\\ +\verb|if i in I then x[i,j] else 1.5 * z + 3.25| & +(expresión lineal condicional)\\ +\verb|(a[i,j] * x[i,j] + y[i-1] + .1)| & +(expresión lineal parentética)\\ +\end{tabular} + +Empleando ciertos operadores aritméticos se pueden construir expresiones lineales más generales conteniendo dos o más expresiones lineales primarias. + +\para{Ejemplos} + +\begin{verbatim} +2 * x[i-1,j+1] + 3.5 * y[k] + .5 * z +(- x[i,j] + 3.5 * y[k]) / sum{t in T} abs(d[i,j,t]) +\end{verbatim} + +\vspace*{-5pt} + +\subsection{Variables no-indizadas} + +Si la expresión lineal primaria es una variable no-indizada (que debe ser 0-dimensional), la forma lineal resultante es aquella variable no-indizada. + +\vspace*{-5pt} + +\subsection{Variables indizadas} + +La expresión lineal primaria que se refiere a una variable indizada tiene la siguiente forma sintáctica: +$$\mbox{{\it nombre}{\tt[}$i_1${\tt,} $i_2${\tt,} \dots{\tt,} +$i_n${\tt]}}$$ +donde {\it nombre} es el nombre simbólico de la variable del modelo e $i_1$, +$i_2$, \dots, $i_n$ son subíndices. + +Cada subíndice debe ser una expresión numérica o simbólica. El número de subíndices en la lista de subíndices debe ser igual a la dimensión de la variable del modelo con la cual está asociada la lista de subíndices. + +Los valores corrientes de las expresiones de los subíndices se usan para identificar un miembro particular de la variable del modelo que determina la forma lineal resultante, la cual es una variable elemental asociada con el miembro correspondiente. + +\vspace*{-5pt} + +\subsection{Expresiones iteradas} + +Una {\it expresión lineal iterada} es una expresión lineal primaria que tiene la siguiente forma sintáctica: +$$\mbox{{\tt sum} {\it expresión-indizante} {\it integrando}}$$ +donde {\it expresión-indizante} es una expresión indizante que introduce índices y controla la iteración e {\it integrando} es una expresión lineal que participa en la operación. + +La expresión lineal iterada se evalúa exactamente de la misma manera que la expresión numérica iterada (ver Subsección \ref{itexpr}, página +\pageref{itexpr}), excepto que el integrando participante en la sumatoria es una forma lineal y no un valor numérico. + +\vspace*{-5pt} + +\subsection{Expresiones condicionales} + +Una {\it expresión lineal condicional} es una expresión lineal primaria que tiene alguna de las dos formas sintácticas siguientes: +$$ +{\def\arraystretch{1.4} +\begin{array}{l} +\mbox{{\tt if} $b$ {\tt then} $f$ {\tt else} $g$}\\ +\mbox{{\tt if} $b$ {\tt then} $f$}\\ +\end{array} +} +$$ +donde $b$ es una expresión lógica, mientras que $f$ y $g$ son expresiones lineales. + +La expresión lineal condicional se evalúa exactamente de la misma manera que la expresión numérica condicional (ver Subsección \ref{ifthen}, página \pageref{ifthen}), excepto que los operandos participantes en la operación son formas lineales y no valores numéricos. + +\subsection{Expresiones parentéticas} + +Cualquier expresión lineal puede encerrarse entre paréntesis, lo que la convierte sintácticamente en una expresión lineal primaria. + +Los paréntesis pueden usarse en expresiones lineales, como en el álgebra, para especificar el orden deseado en el cual se ejecutarán las operaciones. Cuando se usan paréntesis, la expresión entre paréntesis se evalúa antes que el valor resultante sea usado. + +El valor resultante de la expresión parentética es idéntico al valor de la expresión encerrada entre paréntesis. + +\subsection{Operadores aritméticos} + +En MathProg existen los siguientes operadores aritméticos, los que se pueden usar en expresiones lineales: + +\begin{tabular}{@{}ll@{}} +{\tt+} $f$&más unario\\ +{\tt-} $f$&menos unario\\ +$f$ {\tt+} $g$&adición\\ +$f$ {\tt-} $g$&sustracción\\ +$x$ {\tt*} $f$, $f$ {\tt*} $x$&multiplicación\\ +$f$ {\tt/} $x$&división +\end{tabular} + +\noindent donde $f$ y $g$ son expresiones lineales, mientras que $x$ es una expresión numérica (más precisamente, una expresión lineal conteniendo únicamente el término constante). + +Si la expresión incluye más de un operador aritmético, todos los operadores se ejecutan de izquierda a derecha, de acuerdo con la jerarquía de las operaciones (ver más adelante). El valor resultante de la expresión que contiene operadores aritméticos es el resultado de aplicar los operadores a sus operandos. + +\subsection{Jerarquía de las operaciones} + +La jerarquía de las operaciones aritméticas usadas en las expresiones lineales es la misma que en las expresiones numéricas (ver Subsección \ref{hierarchy}, +página \pageref{hierarchy}). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\chapter{Sentencias} + +Las {\it sentencias} son unidades básicas de la descripción del modelo. En MathProg todas las sentencias se clasifican en dos categorías: sentencias declarativas y sentencias funcionales. + +Las {\it sentencias declarativas} (sentencia {\it set}, sentencia {\it parameter}, sentencia {\it variable}, sentencia {\it constraint} y sentencia {\it objective}) se usan para declarar objetos de cierto tipo del modelo y definir ciertas propiedades de tales objetos. + +Las {\it sentencias funcionales} (sentencia {\it solve}, sentencia {\it check}, sentencia {\it display}, sentencia {\it printf}, sentencia {\it loop} y sentencia {\it table}) están ideadas para ejecutar ciertas acciones específicas. + +Debe notarse que las sentencias declarativas pueden seguir cualquier orden arbitrario, lo cual no afecta el resultado de la traducción. Sin embargo, todos los objetos del modelo deben ser declarados antes de ser referenciados en otras sentencias. + +\section{Sentencia set} + +\noindent +\framebox[468pt][l]{ +\parbox[c][24pt]{468pt}{ +\hspace{6pt} {\tt set} {\it nombre} {\it alias} {\it dominio} {\tt,} +{\it atributo} {\tt,} \dots {\tt,} {\it atributo} {\tt;} +}} + +\medskip + +\noindent +{\it nombre} es el nombre simbólico del conjunto; + +\noindent +{\it alias} es un literal de cadena opcional que especifica un alias para el conjunto; + +\noindent +{\it dominio} es una expresión-indizante opcional que especifica el dominio del subíndice del conjunto; + +\noindent +{\it atributo}, \dots, {\it atributo} son atributos opcionales del conjunto (las comas que preceden a los atributos se pueden omitir). + +\para{Atributos opcionales} + +\vspace*{-8pt} + +\begin{description} +\item[{\tt dimen} $n$]\hspace*{0pt}\\ +especifica la dimensión de los $n$-tuplos de los que consiste el conjunto; +\item[{\tt within} {\it expresión}]\hspace*{0pt}\\ +especifica un superconjunto que restringe al conjunto o a todos sus miembros (conjuntos elementales) a estar incluido en aquel superconjunto; +\item[{\tt:=} {\it expresión}]\hspace*{0pt}\\ +especifica un conjunto elemental asignado al conjunto o sus miembros; +\item[{\tt default} {\it expresión}]\hspace*{0pt}\\ +especifica un conjunto elemental asignado al conjunto o sus miembros cuando no haya datos apropiados disponibles en la sección de datos. +\end{description} + +\vspace*{-8pt} + +\para{Ejemplos} + +\begin{verbatim} +set nodos; +set arcos within nodos cross nodos; +set paso{p in 1..maxiter} dimen 2 := if p = 1 then arcos else paso[p-1] + union setof{k in nodos, (i,k) in paso[p-1], (k,j) in paso[p-1]}(i,j); +set A{i in I, j in J}, within B[i+1] cross C[j-1], within D diff E, + default {('abc',123), (321,'cba')}; +\end{verbatim} + +La sentencia set declara un conjunto. Si no se especifica el dominio del subíndice, el conjunto será simple, de otro modo será un arreglo de conjuntos elementales. + +El atributo {\tt dimen} especifica la dimensión de los $n$-tuplos de los que consiste el conjunto (si es un conjunto simple) o sus miembros (si el conjunto es un arreglo de conjuntos elementales), en la que $n$ debe ser un entero sin signo desde 1 hasta 20. Como mucho se puede especificar un atributo {\tt dimen}. Si no se especifica el atributo {\tt dimen}, la dimensión de los $n$-tuplos se determina implícitamente por otros atributos (por ejemplo, si hay una expresión de conjunto que sigue a {\tt :=} o a la palabra clave {\tt default}, se usará la dimensión de los $n$-tuplos del correspondiente conjunto elemental). Si no hay información disponible sobre la dimensión, se asume {\tt dimen 1}. + +El atributo {\tt within} especifica una expresión de conjunto cuyo valor resultante es un superconjunto usado para restringir al conjunto (si es un conjunto simple) o a sus miembros (si el conjunto es un arreglo de conjuntos elementales) a estar incluido en aquel superconjunto. Se puede especificar un número arbitrario de atributos {\tt within} en la misma sentencia set. + +El atributo de asignación ({\tt :=}) especifica una expresión de conjunto usada para evaluar conjuntos elementales asignados al conjunto (si es un conjunto simple) o sus miembros (si el conjunto es un arreglo de conjuntos elementales). Si se especifica el atributo de asignación, el conjunto es {\it calculable} y consecuentemente no es necesario proveerle datos en la sección de datos. Si no se especifica el atributo de asignación, entonces se deben proveer datos para el conjunto en la sección de datos. Como mucho, se puede especificar una asignación o un atributo {\tt default} para el mismo conjunto. + +El atributo {\tt default} especifica una expresión de conjunto usada para evaluar conjuntos elementales asignados al conjunto (si es un conjunto simple) o sus miembros (si el conjunto es un arreglo de conjuntos elementales) toda vez que no haya datos apropiados disponibles en la sección de datos. Si no se especifica una asignación o un atributo {\tt default}, la carencia de datos causará un error. + +\newpage + +\section{Sentencia parameter} + +\noindent +\framebox[468pt][l]{ +\parbox[c][24pt]{468pt}{ +\hspace{6pt} {\tt param} {\it nombre} {\it alias} {\it dominio} {\tt,} +{\it atributo} {\tt,} \dots {\tt,} {\it atributo} {\tt;} +}} + +\medskip + +\noindent +{\it nombre} es el nombre simbólico del parámetro; + +\noindent +{\it alias} es un literal de cadena opcional que especifica un alias para el parámetro; + +\noindent +{\it dominio} es una expresión indizante opcional que especifica el dominio del subíndice del parámetro; + +\noindent +{\it atributo}, \dots, {\it atributo} son atributos opcionales del parámetro (las comas que preceden a los atributos se pueden omitir). + +\para{Atributos opcionales} + +\vspace*{-8pt} + +\begin{description} +\item[{\tt integer}]\hspace*{0pt}\\ +especifica que el parámetro es entero; +\item[{\tt binary}]\hspace*{0pt}\\ +especifica que el parámetro es binario; +\item[{\tt symbolic}]\hspace*{0pt}\\ +especifica que el parámetro es simbólico; +\item[{\it relación expresión}]\hspace*{0pt}\\ +(donde {\it relación} es alguno de: {\tt<}, {\tt<=}, {\tt=}, {\tt==}, +{\tt>=}, {\tt>}, {\tt<>}, {\tt!=})\\ +especifica una condición que restringe al parámetro o a sus miembros a satisfacer aquella condición; +\item[{\tt in} {\it expresión}]\hspace*{0pt}\\ +especifica un superconjunto que restringe al parámetro o a sus miembros a estar incluidos en aquel superconjunto; +\item[{\tt:=} {\it expresión}]\hspace*{0pt}\\ +especifica un valor asignado al parámetro o a sus miembros; +\item[{\tt default} {\it expresión}]\hspace*{0pt}\\ +especifica un valor asignado al parámetro o a sus miembros cuando no haya datos apropiados disponibles en la sección de datos. +\end{description} + +\vspace*{-8pt} + +\para{Ejemplos} + +\begin{verbatim} +param unidades{insumo,producto} >= 0; +param ganancia{producto, 1..T+1}; +param N := 20 integer >= 0 <= 100; +param combinacion 'n elige k' {n in 0..N, k in 0..n} := + if k = 0 or k = n then 1 else combinacion[n-1,k-1] + combinacion[n-1,k]; +param p{i in I, j in J}, integer, >= 0, <= i+j, in A[i] symdiff B[j], + in C[i,j], default 0.5 * (i + j); +param mes symbolic default 'May' in {'Mar', 'Abr', 'May'}; +\end{verbatim} + +La sentencia parameter declara un parámetro. Si el dominio del subíndice no se especifica, el parámetro es un parámetro simple (escalar); de otro modo es un arreglo $n$-dimensional. + +Los atributos de tipo {\tt integer}, {\tt binary} y {\tt symbolic} califican el tipo de valores que se le puede asignar al parámetro como se muestra a continuación: + +\noindent\hfil +\begin{tabular}{@{}ll@{}} +Atributo de tipo&Valores asignado\\ +\hline +(no especificado)&Cualquier valor numérico\\ +{\tt integer}&Solamente valores numéricos enteros\\ +{\tt binary}&Tanto 0 como 1\\ +{\tt symbolic}&Cualquier valor numérico y simbólico\\ +\end{tabular} + +El atributo {\tt symbolic} no se puede especificar junto con otros atributos de tipo. Cuando se especifica debe preceder a todos los demás atributos. + +El atributo de condición especifica una condición opcional que restringe los valores asignados al parámetro a satisfacer esta condición. Este atributo tiene las siguientes formas sintácticas: + +\begin{tabular}{@{}ll@{}} +{\tt<} $v$&comprueba si $x=} $v$&comprueba si $x\geq v$\\ +{\tt>} $v$&comprueba si $x\geq v$\\ +{\tt<>} $v$, {\tt!=} $v$&comprueba si $x\neq v$\\ +\end{tabular} + +\noindent donde $x$ es un valor asignado al parámetro y $v$ es el valor resultante de una expresión numérica o simbólica especificada en el atributo de condición. Se puede especificar un número arbitrario de atributos de condición para el mismo parámetro. Si el valor que se está asignando al parámetro durante la evaluación del modelo viola al menos una de las condiciones especificadas, se producirá un error. (Debe notarse que los valores simbólicos se ordenan lexicográficamente y que cualquier valor numérico precede a cualquier valor simbólico.) + +El atributo {\tt in} es semejante al atributo de condición y especifica una expresión de conjunto cuyo valor resultante es un superconjunto usado para restringir los valores numéricos o simbólicos asignados al parámetro a estar incluidos en aquel superconjunto. Se puede especificar un número arbitrario de atributos {\tt in} para el mismo parámetro. Si el valor que se está asignando al parámetro durante la evaluación del modelo no pertenece al menos a uno de los superconjuntos especificados, se producirá un error. + +El atributo de asignación ({\tt:=}) especifica una expresión numérica o simbólica usada para calcular un valor asignado al parámetro (si es un parámetro simple) o a sus miembros (si el parámetro es un arreglo). Si se especifica el atributo de asignación, el parámetro es {\it calculable} y consecuentemente no es necesario proveer datos en la sección de datos. Si no se especifica el atributo de asignación, entonces se deben proveer datos para el parámetro en la sección de datos. Como mucho, se puede especificar una asignación o un atributo {\tt default} para el mismo conjunto. + +El atributo {\tt default} especifica una expresión numérica o simbólica que se usa para calcular un valor asignado al parámetro o a sus miembros, toda vez que no haya datos apropiados disponibles en la sección de datos. Si no se especifica una asignación ni un atributo {\tt default}, la carencia de datos causará un error. + +\section{Sentencia variable} + +\noindent +\framebox[468pt][l]{ +\parbox[c][24pt]{468pt}{ +\hspace{6pt} {\tt var} {\it nombre} {\it alias} {\it dominio} {\tt,} +{\it atributo} {\tt,} \dots {\tt,} {\it atributo} {\tt;} +}} + +\medskip + +\noindent +{\it nombre} es el nombre simbólico de la variable; + +\noindent +{\it alias} es un literal de cadena opcional que especifica un alias para la variable; + +\noindent +{\it dominio} es una expresión indizante opcional que especifica el dominio del subíndice de la variable; + +\noindent +{\it atributo}, \dots, {\it atributo} son atributos opcionales de la variable (las comas que preceden a los atributos se pueden omitir). + +\para{Atributos opcionales} + +\vspace*{-8pt} + +\begin{description} +\item[{\tt integer}]\hspace*{0pt}\\ +restringe la variable a ser entera; +\item[{\tt binary}]\hspace*{0pt}\\ +restringe la variable a ser binaria; +\item[{\tt>=} {\it expresión}]\hspace*{0pt}\\ +especifica una cota inferior para la variable; +\item[{\tt<=} {\it expresión}]\hspace*{0pt}\\ +especifica una cota superior para la variable; +\item[{\tt=} {\it expresión}]\hspace*{0pt}\\ +especifica un valor fijo para la variable. +\end{description} + +\vspace*{-8pt} + +\para{Ejemplos} + +\begin{verbatim} +var x >= 0; +var y{I,J}; +var elaborar{p in producto}, integer, >= compromiso[p], <= mercado[p]; +var almacenar{insumo, 1..T+1} >= 0; +var z{i in I, j in J} >= i+j; +\end{verbatim} + +La sentencia variable declara una variable. Si no se especifica el dominio del subíndice, la variable es una variable simple (escalar); de otro modo es un arreglo $n$-dimensional de variables elementales. + +Las variables elementales asociadas con una variable del modelo (si es una variable simple) o sus miembros (si es un arreglo) corresponde a las variables en la formulación del problema de PL/PEM (ver Sección \ref{problem}, página \pageref{problem}). Debe notarse que sólo variables elementales realmente referenciadas en algunas restricciones y/u objetivos se incluirán en la instancia del problema de PL/PEM que se generará. + +Los atributos de tipo {\tt integer} y {\tt binary} restringen la variable a ser entera o binaria, respectivamente. Si no se especifica un atributo de tipo, la variable será continua. Si todas las variables en el modelo son continuas, el problema correspondiente será de la clase PL. Si hay al menos una variable entera o binaria, el problema será de la clase PEM. + +El atributo de cota inferior ({\tt>=}) especifica una expresión numérica para calcular la cota inferior de la variable. Se puede especificar una cota inferior como máximo. Por defecto, todas las variables no tienen cota inferior (excepto las binarias), de modo que si se requiere que sea no-negativa, su cota inferior cero debe especificarse explícitamente. + +El atributo de cota superior ({\tt<=}) especifica una expresión numérica para calcular la cota superior de la variable. Se puede especificar una cota superior como máximo. + +El atributo de valor fijo ({\tt=}) especifica una expresión numérica para calcular el valor en el cual se fijará la variable. Este atributo no puede especificarse junto con los atributos de cota. + +\section{Sentencia constraint} + +\noindent +\framebox[468pt][l]{ +\parbox[c][106pt]{468pt}{ +\hspace{6pt} {\tt s.t.} {\it nombre} {\it alias} {\it dominio} {\tt:} +{\it expresión} {\tt,} {\tt=} {\it expresión} {\tt;} + +\medskip + +\hspace{6pt} {\tt s.t.} {\it nombre} {\it alias} {\it dominio} {\tt:} +{\it expresión} {\tt,} {\tt<=} {\it expresión} {\tt;} + +\medskip + +\hspace{6pt} {\tt s.t.} {\it nombre} {\it alias} {\it dominio} {\tt:} +{\it expresión} {\tt,} {\tt>=} {\it expresión} {\tt;} + +\medskip + +\hspace{6pt} {\tt s.t.} {\it nombre} {\it alias} {\it dominio} {\tt:} +{\it expresión} {\tt,} {\tt<=} {\it expresión} {\tt,} {\tt<=} +{\it expresión} {\tt;} + +\medskip + +\hspace{6pt} {\tt s.t.} {\it nombre} {\it alias} {\it dominio} {\tt:} +{\it expresión} {\tt,} {\tt>=} {\it expresión} {\tt,} {\tt>=} +{\it expresión} {\tt;} +}} + +\medskip + +\noindent +{\it nombre} es el nombre simbólico de la restricción; + +\noindent +{\it alias} es un literal de cadena opcional que especifica un alias para la restricción; + +\noindent +{\it dominio} es una expresión indizante opcional que especifica el dominio del subíndice de la restricción; + +\noindent +{\it expresión} es una expresión lineal usada para calcular un componente de la restricción (las comas que siguen a las expresiones pueden omitirse). + +\noindent +(La palabra clave {\tt s.t.} se puede escribir como {\tt subject to}, o como {\tt subj to} o ser completamente omitida.) + +\para{Ejemplos} + +\begin{verbatim} +s.t. r: x + y + z, >= 0, <= 1; +limite{t in 1..T}: sum{j in producto} elaborar[j,t] <= max_producto; +subject to balance{i in insumo, t in 1..T}: + almacenar[i,t+1] - almacenar[i,t] - + sum{j in producto} unidades[i,j] * elaborar[j,t]; +subject to ltn 'limite tiempo normal' {t in tiempo}: + sum{p in producto} pt[p] * rprd[p,t] <= 1.3 * dpp[t] * brigadas[t]; +\end{verbatim} + +La sentencia constraint declara una restricción. Si no se especifica el dominio del subíndice, la restricción es una restricción simple (escalar); de otro modo, es un arreglo $n$-dimensional de restricciones elementales. + +Las restricciones elementales asociadas con la restricción del modelo (si es una restricción simple) o sus miembros (si es un arreglo) corresponde a las restricciones lineales en la formulación del problema de PL/PEM (ver Sección \ref{problem}, página \pageref{problem}). + +Si la restricción tiene la forma de una igualdad o desigualdad simple, {\it i.e.} incluye dos expresiones, una de las cuales está a continuación de los dos puntos y la otra está a continuación del signo relacional {\tt=}, {\tt<=} o {\tt>=}, ambas expresiones de la sentencia pueden ser expresiones lineales. Si la restricción tiene la forma de una doble desigualdad, {\it i.e.} incluye tres expresiones, la expresión del medio puede ser una expresión lineal mientras que la de la izquierda y la de la derecha sólo pueden ser expresiones numéricas. + +Generar el modelo es, groseramente hablando, generar sus restricciones, las que son siempre evaluadas para todo el dominio del subíndice. A su vez, la evaluación de las restricciones lleva a la evaluación de otros objetos del modelo tales como los conjuntos, los parámetros y las variables. + +La construcción de una restricción lineal real incluida en la instancia del problema, la cual corresponde a una restricción elemental particular, se realiza como sigue. + +Si la restricción tiene la forma de una igualdad o desigualdad simple, la evaluación de ambas expresiones lineales resulta en dos formas lineales: +$$\begin{array}{r@{\ }c@{\ }r@{\ }c@{\ }r@{\ }c@{\ }r@{\ }c@{\ }r} +f&=&a_1x_1&+&a_2x_2&+\dots+&a_nx_n&+&a_0,\\ +g&=&b_1x_1&+&b_2x_2&+\dots+&b_nx_n&+&b_0,\\ +\end{array}$$ +donde $x_1$, $x_2$, \dots, $x_n$ son variables elementales; $a_1$, $a_2$, +\dots, $a_n$, $b_1$, $b_2$, \dots, $b_n$ son coeficientes numéricos y +$a_0$ y $b_0$ son términos constantes. Luego, todos los términos lineales de $f$ y $g$ se llevan al lado izquierdo y los términos constantes se llevan al lado derecho, para dar la restricción elemental final en forma estándar: +$$(a_1-b_1)x_1+(a_2-b_2)x_2+\dots+(a_n-b_n)x_n\left\{ +\begin{array}{@{}c@{}}=\\\leq\\\geq\\\end{array}\right\}b_0-a_0.$$ + +Si la restricción tiene la forma de una doble desigualdad, la evaluación de la expresión lineal del medio resulta en una forma lineal: +$$f=a_1x_1+a_2x_2+\dots+a_nx_n+a_0,$$ +y la evaluación de las expresiones numéricas de la izquierda y de la derecha dará dos valores numéricos $l$ y $u$, respectivamente. Luego, el término constante de la forma lineal se lleva tanto a la izquierda como a la derecha para dar la restricción elemental final en forma estándar: +$$l-a_0\leq a_1x_1+a_2x_2+\dots+a_nx_n\leq u-a_0.$$ + +\section{Sentencia objective} + +\noindent +\framebox[468pt][l]{ +\parbox[c][44pt]{468pt}{ +\hspace{6pt} {\tt minimize} {\it nombre} {\it alias} {\it dominio} {\tt:} +{\it expresión} {\tt;} + +\medskip + +\hspace{6pt} {\tt maximize} {\it nombre} {\it alias} {\it dominio} {\tt:} +{\it expresión} {\tt;} +}} + +\medskip + +\noindent +{\it nombre} es el nombre simbólico del objetivo; + +\noindent +{\it alias} es un literal de cadena opcional que especifica un alias para el objetivo; + +\noindent +{\it dominio} es una expresión indizante opcional que especifica el dominio del subíndice del objetivo; + +\noindent +{\it expresión} es una expresión lineal usada para calcular la forma lineal del objetivo. + +\para{Ejemplos} + +\begin{verbatim} +minimize objetivo: x + 1.5 * (y + z); +maximize ganancia_total: sum{p in producto} ganancia[p] * elaborar[p]; +\end{verbatim} + +La sentencia objective declara un objetivo. Si no se especifica el dominio del subíndice, el objetivo es un objetivo simple (escalar); de otro modo, es un arreglo $n$-dimensional de objetivos elementales. + +Los objetivos elementales asociados con el objetivo del modelo (si es un objetivo simple) o sus miembros (si es un arreglo) corresponden a restricciones lineales generales en la formulación del problema de PL/PEM (ver Sección \ref{problem}, página \pageref{problem}). Sin embargo, a diferencia de las restricciones, las correspondientes formas lineales son libres (no tienen cota). + +La construcción de una restricción lineal real incluida en la instancia del problema, la cual corresponde a una restricción elemental particular, se realiza como sigue. La expresión lineal especificada en la sentencia objective se evalúa para resultar en una forma lineal: +$$f=a_1x_1+a_2x_2+\dots+a_nx_n+a_0,$$ +donde $x_1$, $x_2$, \dots, $x_n$ son variables elementales; $a_1$, $a_2$, +\dots, $a_n$ son coeficientes numéricos y $a_0$ es el término constante. Luego se usa la forma lineal para construir la restricción elemental final en forma estándar: +$$-\infty= 0 and y >= 0; +check sum{i in ORIGEN} oferta[i] = sum{j in DESTINO} demanda[j]; +check{i in I, j in 1..10}: S[i,j] in U[i] union V[j]; +\end{verbatim} + +El sentencia check permite comprobar el valor resultante de una expresión lógica especificada en la sentencia. Si el valor es {\it falso} se reporta un error. + +Si el dominio del subíndice no se especifica, la comprobación se ejecuta solamente una vez. Especificar el dominio del subíndice permite ejecutar múltiples comprobaciones para cada $n$-tuplo en el conjunto dominio. En este último caso, la expresión lógica puede incluir índices introducidos en la correspondiente expresión indizante. + +\section{Sentencia display} + +\noindent +\framebox[468pt][l]{ +\parbox[c][24pt]{468pt}{ +\hspace{6pt} {\tt display} {\it dominio} {\tt:} {\it ítem} {\tt,} +\dots {\tt,} {\it ítem} {\tt;} +}} + +\medskip + +\noindent +{\it dominio} es una expresión indizante opcional que especifica el dominio del subíndice de la sentencia display; + +\noindent +{\it ítem}, \dots, {\it ítem} son ítems que se mostrarán (los dos puntos que preceden al primer ítem pueden omitirse). + +\para{Ejemplos} + +\begin{verbatim} +display: 'x =', x, 'y =', y, 'z =', z; +display sqrt(x ** 2 + y ** 2 + z ** 2); +display{i in I, j in J}: i, j, a[i,j], b[i,j]; +\end{verbatim} + +La sentencia display evalúa todos los ítems especificados en la sentencia y escribe sus valores en la salida estándar (terminal) en formato de texto plano. + +Si el dominio del subíndice no se especifica, los ítems son evaluados y mostrados solamente una vez. Especificar el dominio del subíndice produce que los ítems sean evaluados y mostrados para cada $n$-tuplo en el conjunto dominio. En este último caso, los ítems pueden incluir índices introducidos en la correspondiente expresión indizante. + +Un ítem a ser mostrado puede ser un objeto del modelo (conjunto, parámetro, variable, restricción u objetivo) o una expresión. + +Si el ítem es un objeto calculable ({\it i.e.} un conjunto o parámetro provisto con el atributo de asignación), el mismo es evaluado a través de todo su dominio y luego se muestra su contenido ({\it i.e.} el contenido del arreglo de objetos). De otro modo, si el ítem no es un objeto calculable, solamente se muestra su contenido corriente ({\it i.e.} los miembros realmente generados durante la evaluación del modelo). + +Si el ítem es una expresión, la misma se evalúa y se muestra su valor resultante. + +\section{Sentencia printf} + +\noindent +\framebox[468pt][l]{ +\parbox[c][64pt]{468pt}{ +\hspace{6pt} {\tt printf} {\it dominio} {\tt:} {\it formato} {\tt,} +{\it expresión} {\tt,} \dots {\tt,} {\it expresión} {\tt;} + +\medskip + +\hspace{6pt} {\tt printf} {\it dominio} {\tt:} {\it formato} {\tt,} +{\it expresión} {\tt,} \dots {\tt,} {\it expresión} {\tt>} +{\it archivo} {\tt;} + +\medskip + +\hspace{6pt} {\tt printf} {\it dominio} {\tt:} {\it formato} {\tt,} +{\it expresión} {\tt,} \dots {\tt,} {\it expresión} {\tt>}{\tt>} +{\it archivo} {\tt;} +}} + +\medskip + +\noindent +{\it dominio} es una expresión indizante opcional que especifica el dominio del subíndice de la sentencia printf; + +\noindent +{\it formato} es una expresión simbólica cuyo valor especifica una cadena de control de formato (los dos puntos que preceden a la expresión de formato pueden omitirse). + +\noindent +{\it expresión}, \dots, {\it expresión} son cero o más expresiones cuyos valores deben ser formateados e impresos. Cada expresión debe ser de tipo numérico, simbólico o lógico. + +\noindent +{\it archivo} es una expresión simbólica cuyo valor especifica el nombre de un archivo de texto al cual se redirigirá la salida. La señal {\tt>} significa la creación de un archivo nuevo y vacío, mientras que la señal {\tt>}{\tt>} significa anexar la salida a un archivo existente. Si no se especifica un nombre de archivo, la salida se escribe en la salida estándar (terminal). + +\para{Ejemplos} + +\begin{verbatim} +printf 'Hola, mundo!\n'; +printf: "x = %.3f; y = %.3f; z = %.3f\n", x, y, z > "resultado.txt"; +printf{i in I, j in J}: "el flujo desde %s hacia %s es %d\n", i, j, x[i,j] + >> archivo_resultados & ".txt"; +printf{i in I} 'el flujo total de %s es %g\n', i, sum{j in J} x[i,j]; +printf{k in K} "x[%s] = " & (if x[k] < 0 then "?" else "%g"), + k, x[k]; +\end{verbatim} + +La sentencia printf es semejante a la sentencia display; sin embargo, la misma permite formatear los datos que se escribirán. + +Si el dominio del subíndice no se especifica, la sentencia printf es ejecutada solamente una vez. Especificar el dominio del subíndice produce que la sentencia printf sea ejecutada para cada $n$-tuplo en el conjunto dominio. En este último caso, el formato y la expresión pueden incluir índices introducidos en la correspondiente expresión indizante. + +La cadena de control de formato es el valor de la expresión simbólica {\it formato} especificado en la sentencia printf. Se compone con cero o más directivas como sigue: caracteres ordinarios (no {\tt\%}), que son copiados sin modificación al flujo de salida, y especificaciones de conversión, cada una de las cuales provoca la evaluación de la expresión correspondiente especificada en la sentencia printf, su formateo y la escritura del valor resultante en el flujo de salida. + +Las especificaciones de conversión que se pueden usar en la cadena de control de formato son las siguientes: {\tt d}, {\tt i}, {\tt f}, {\tt F}, {\tt e}, {\tt E}, {\tt g}, {\tt G} y {\tt s}. Estas especificaciones tienen la misma semántica y sintaxis que en el lenguaje de programación C. + +\section{Sentencia for} + +\noindent +\framebox[468pt][l]{ +\parbox[c][44pt]{468pt}{ +\hspace{6pt} {\tt for} {\it dominio} {\tt:} {\it sentencia} {\tt;} + +\medskip + +\hspace{6pt} {\tt for} {\it dominio} {\tt:} {\tt\{} {\it sentencia} +\dots {\it sentencia} {\tt\}} {\tt;} +}} + +\medskip + +\noindent +{\it dominio} es una expresión indizante opcional que especifica el dominio del subíndice de la sentencia for (los dos puntos a continuación de la expresión indizante pueden omitirse); + +\noindent +{\it sentencia} es una sentencia que será ejecutada bajo el control de la sentencia for; + +\noindent +{\it sentencia}, \dots, {\it sentencia} es una secuencia de sentencias (encerrada entre llaves) que serán ejecutadas bajo el control de la sentencia for. + +Solamente se pueden usar las siguientes sentencias dentro de la sentencia for: check, display, printf y otra sentencia for. + +\para{Ejemplos} + +\begin{verbatim} +for {(i,j) in E: i != j} +{ printf "el flujo desde %s hacia %s es %g\n", i, j, x[i,j]; + check x[i,j] >= 0; +} +for {i in 1..n} +{ for {j in 1..n} printf " %s", if x[i,j] then "Q" else "."; + printf("\n"); +} +for {1..72} printf("*"); +\end{verbatim} + +La sentencia for provoca que la sentencia o secuencia de sentencias especificadas como parte de la sentencia for sea ejecutada para cada $n$-tuplo en el conjunto dominio. De modo que las sentencias dentro de la sentencia for pueden incluir índices introducidos en la correspondiente expresión indizante. + +\section{Sentencia table} + +\noindent +\framebox[468pt][l]{ +\parbox[c][80pt]{468pt}{ +\hspace{6pt} {\tt table} {\it nombre} {\it alias} {\tt IN} {\it controlador} +{\it arg} \dots {\it arg} {\tt:} + +\hspace{6pt} {\tt\ \ \ \ \ } {\it conjunto} {\tt<-} {\tt[} {\it cmp} {\tt,} +\dots {\tt,} {\it cmp} {\tt]} {\tt,} {\it par} {\tt\textasciitilde} +{\it cmp} {\tt,} \dots {\tt,} {\it par} {\tt\textasciitilde} {\it cmp} +{\tt;} + +\medskip + +\hspace{6pt} {\tt table} {\it nombre} {\it alias} {\it dominio} {\tt OUT} +{\it controlador} {\it arg} \dots {\it arg} {\tt:} + +\hspace{6pt} {\tt\ \ \ \ \ } {\it expr} {\tt\textasciitilde} {\it cmp} +{\tt,} \dots {\tt,} {\it expr} {\tt\textasciitilde} {\it cmp} {\tt;} +}} + +\medskip + +\noindent +{\it nombre} es el nombre simbólico de la tabla; + +\noindent +{\it alias} es un literal de cadena opcional que especifica un alias para la tabla; + +\noindent +{\it dominio} es una expresión indizante que especifica el dominio del subíndice de la tabla (de salida); + +\noindent +{\tt IN} significa leer datos desde la tabla de entrada; + +\noindent +{\tt OUT} significa escribir datos en la tabla de salida; + +\noindent +{\it controlador} es una expresión simbólica que especifica el controlador usado para acceder a la tabla (para más detalles, ver Apéndice \ref{drivers}, página \pageref{drivers}); + +\noindent +{\it arg} es una expresión simbólica opcional que es un argumento pasado al controlador de la tabla. Esta expresión simbólica no debe incluir índices especificados en el dominio; + +\noindent +{\it conjunto} es el nombre de un conjunto simple opcional llamado {\it conjunto de control}. Puede ser omitido junto con el delimitador {\tt<-}; + +\noindent +{\it cmp} es un nombre de campo. Entre corchetes se debe especificar al menos un campo. El nombre de campo a continuación de un nombre de parámetro o de una expresión es opcional y puede ser omitido junto con el delimitador~{\tt\textasciitilde}, en cuyo caso el nombre del objeto del modelo que corresponda se usará como el nombre de campo; + +\noindent +{\it par} es el nombre simbólico de un parámetro del modelo; + +\noindent +{\it expr} es una expresión numérica o simbólica. + +\para{Ejemplos} + +\begin{verbatim} +table datos IN "CSV" "datos.csv": M <- [DESDE,HACIA], d~DISTANCIA, + c~COSTO; +table resultado{(s,h) in M} OUT "CSV" "resultado.csv": s~DESDE, h~HACIA, + x[s,h]~FLUJO; +\end{verbatim} + +La sentencia table permite leer datos desde una tabla y asignarlos a objetos del modelo tales como conjuntos y parámetros (no escalares), al igual que escribir datos del modelo en una tabla. + +\subsection{Estructura de tablas} + +Una {\it tabla de datos} es un conjunto (desordenado) de {\it registros}, en el que cada registro consiste del mismo número de {\it campos}, y cada campo está provisto de un nombre simbólico único denominado {\it nombre de campo}. Por ejemplo: + +\bigskip + +\begin{tabular}{@{\hspace*{51mm}}c@{\hspace*{9mm}}c@{\hspace*{10mm}}c +@{\hspace*{7mm}}c} +Primer&Segundo&&Último\\ +campo&campo&.\ \ .\ \ .&campo\\ +$\downarrow$&$\downarrow$&&$\downarrow$\\ +\end{tabular} + +\begin{tabular}{ll@{}} +Encabezado de tabla&$\rightarrow$\\ +Primer registro&$\rightarrow$\\ +Segundo registro&$\rightarrow$\\ +\\ +\hfil .\ \ .\ \ .\\ +\\ +Último registro&$\rightarrow$\\ +\end{tabular} +\begin{tabular}{|l|l|c|c|} +\hline +{\tt DESDE}&{\tt HACIA}&{\tt DISTANCIA}&{\tt COSTO}\\ +\hline +{\tt Seattle} &{\tt New-York}&{\tt 2.5}&{\tt 0.12}\\ +{\tt Seattle} &{\tt Chicago} &{\tt 1.7}&{\tt 0.08}\\ +{\tt Seattle} &{\tt Topeka} &{\tt 1.8}&{\tt 0.09}\\ +{\tt San-Diego}&{\tt New-York}&{\tt 2.5}&{\tt 0.15}\\ +{\tt San-Diego}&{\tt Chicago} &{\tt 1.8}&{\tt 0.10}\\ +{\tt San-Diego}&{\tt Topeka} &{\tt 1.4}&{\tt 0.07}\\ +\hline +\end{tabular} + +\subsection{Lectura de datos desde una tabla de entrada} + +La sentencia table de entrada produce la lectura de los datos desde la tabla especificada, registro por registro. + +Una vez que se ha leído el próximo registro, los valores numéricos o simbólicos de los campos cuyos nombres se han encerrado entre corchetes en la sentencia table se reúnen en un $n$-tuplo y, si se ha especificado el conjunto de control en la sentencia table, este $n$-tuplo es agregado al mismo. Además, un valor numérico o simbólico de cada campo asociado con un parámetro del modelo se asigna al miembro del parámetro identificado por subíndices, los cuales son componentes del $n$-tuplo que se acaba de leer. + +Por ejemplo, la siguiente sentencia table de entrada: + +\noindent\hfil +\verb|table datos IN "...": M <- [DESDE,HACIA], d~DISTANCIA, c~COSTO;| + +\noindent +produce la lectura de valores de cuatro campos llamados {\tt DESDE}, {\tt HACIA}, {\tt DISTANCIA} y {\tt COSTO} de cada registro de la tabla especificada. Los valores de los campos {\tt DESDE} y {\tt HACIA} proveen un par $(s,h)$ que se agrega al conjunto de control {\tt M}. El valor del campo {\tt DISTANCIA} se asigna al miembro del parámetro ${\tt d}[s,h]$ y el valor del campo {\tt COSTO} se asigna al miembro del parámetro ${\tt c}[s,h]$. + +Debe notarse que la tabla de entrada puede contener campos adicionales cuyos nombres no sean especificados en la sentencia table, en cuyo caso los valores de estos campos serán ignorados al leer la tabla. + +\subsection{Escritura de datos en una tabla de salida} + +La sentencia table de salida produce la escritura de datos en la tabla especificada. Debe notarse que algunos controladores (concretamente CSV y xBASE) destruyen la tabla de salida antes de escribir los datos, {\it i.e.} borran todos sus registros existentes. + +Cada $n$-tuplo en el conjunto dominio especificado genera un registro escrito en la tabla de salida. Los valores de los campos son valores numéricos o simbólicos de las correspondientes expresiones especificadas en la sentencia table. Estas expresiones se evalúan para cada $n$-tuplo en el conjunto dominio y, de este modo, puede incluir índices que se introdujeron en la correspondiente expresión indizante. + +Por ejemplo, la siguiente sentencia table de salida: + +\noindent\hfil +\verb|table resultado{(s,h) in M} OUT "...": s~DESDE, h~HACIA, x[s,h]~FLUJO;| + +\noindent +produce la escritura de registros en la tabla de salida, a razón de un registro por cada par $(s,h)$ en el conjunto {\tt M}, en el que cada registro consiste de tres campos llamados {\tt DESDE}, {\tt HACIA} y {\tt FLUJO}. Los valores escritos en los campos {\tt DESDE} y {\tt HACIA} son los valores corrientes de los índices {\tt s} y {\tt h}, y el valor escrito en el campo {\tt FLUJO} es un valor del miembro ${\tt x}[s,h]$ del correspondiente parámetro o variable indexada. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\chapter{Datos del modelo} + +Los {\it datos del modelo} incluyen conjuntos elementales, los cuales son ``valores'' de los conjuntos del modelo, y valores simbólicos y numéricos de los parámetros del modelo. + +En MathProg hay dos maneras diferentes de proveer valores para los conjuntos y parámetros del modelo. Una manera es simplemente proveyendo los datos necesarios mediante el atributo de asignación. Sin embargo, en muchos casos es más práctico separar el modelo en sí mismo de los datos particulares necesarios para el modelo. Por esta última razón, en MathProg hay otra manera que consiste en separar la descripción del modelo en dos partes: la sección del modelo y la sección de los datos. + +La {\it sección del modelo} es la parte principal de la descripción del modelo que contiene las declaraciones de todos los objetos del modelo y es común a todos los problemas basados en tal modelo. + +La {\it sección de los datos} es una parte opcional de la descripción del modelo que contiene datos específicos para un problema particular. + +En MathProg las secciones del modelo y de los datos se pueden ubicar tanto en un único archivo de texto, como en dos archivos de texto separados. + +1. Si ambas secciones se ubican en un archivo, este debe componerse como sigue: + +\bigskip + +\noindent\hfil +\framebox{\begin{tabular}{l} +{\it sentencia}{\tt;}\\ +{\it sentencia}{\tt;}\\ +\hfil.\ \ .\ \ .\\ +{\it sentencia}{\tt;}\\ +{\tt data;}\\ +{\it bloque de datos}{\tt;}\\ +{\it bloque de datos}{\tt;}\\ +\hfil.\ \ .\ \ .\\ +{\it bloque de datos}{\tt;}\\ +{\tt end;} +\end{tabular}} + +\newpage + +2. Si ambas secciones se ubican en dos archivos separados, los archivos se componen como sigue: + +\bigskip + +\noindent\hfil +\begin{tabular}{@{}c@{}} +\framebox{\begin{tabular}{l} +{\it sentencia}{\tt;}\\ +{\it sentencia}{\tt;}\\ +\hfil.\ \ .\ \ .\\ +{\it sentencia}{\tt;}\\ +{\tt end;}\\ +\end{tabular}}\\ +\\\\Archivo del modelo\\ +\end{tabular} +\hspace{32pt} +\begin{tabular}{@{}c@{}} +\framebox{\begin{tabular}{l} +{\tt data;}\\ +{\it bloque de datos}{\tt;}\\ +{\it bloque de datos}{\tt;}\\ +\hfil.\ \ .\ \ .\\ +{\it bloque de datos}{\tt;}\\ +{\tt end;}\\ +\end{tabular}}\\ +\\Archivo de datos\\ +\end{tabular} + +\bigskip + +Nota: si la sección de datos se ubica en un archivo separado, la palabra clave {\tt data} es opcional y puede omitirse, al igual que el punto y coma que le sigue. + +\section{Codificación de la sección de los datos} + +La {\it sección de los datos} es una secuencia de bloques de datos en varios formatos que se discuten en las siguientes secciones. El orden que siguen los bloques de datos en la sección de los datos puede ser arbitrario, no necesariamente el mismo que se siguió en la sección del modelo para sus correspondientes objetos. + +Las reglas para codificar la sección de los datos comúnmente son las mismas reglas que para codificar la descripción del modelo (ver Sección \ref{coding}, página \pageref{coding}), {\it i.e.} los bloques de datos se componen con unidades léxicas básicas como nombres simbólicos, literales numéricos y de cadena, palabras clave, delimitadores y comentarios. Sin embargo, por conveniencia y para mejorar la legibilidad hay una desviación de la regla común: si un literal de cadena consiste únicamente de caracteres alfanuméricos (incluyendo el carácter de subrayado), los signos {\tt+} y {\tt-} y/o el punto decimal, el mismo puede codificarse sin comillas delimitadoras (simples o dobles). + +Todo el material numérico y simbólico provisto en la sección de los datos se codifica en la forma de números y símbolos, {\it i.e.} a diferencia de la sección del modelo, en la sección de los datos no se permiten expresiones. Sin embargo, los signos {\tt+} y {\tt-} pueden preceder a literales numéricos para permitir la codificación de cantidades numéricas con signo, en cuyo caso no debe haber caracteres de espacio en blanco entre el signo y el literal numérico que le sigue (si hay al menos un espacio en blanco, el signo y el literal numérico que le sigue serán reconocidos como dos unidades léxicas diferentes). + +\newpage + +\section{Bloque de datos de conjunto} + +\noindent +\framebox[468pt][l]{ +\parbox[c][44pt]{468pt}{ +\hspace{6pt} {\tt set} {\it nombre} {\tt,} {\it registro} {\tt,} \dots +{\tt,} {\it registro} {\tt;} + +\medskip + +\hspace{6pt} {\tt set} {\it nombre} {\tt[} {\it símbolo} {\tt,} \dots +{\tt,} {\it símbolo} {\tt]} {\tt,} {\it registro} {\tt,} \dots {\tt,} +{\it registro} {\tt;} +}} + +\medskip + +\noindent +{\it nombre} es el nombre simbólico del conjunto; + +\noindent +{\it símbolo}, \dots, {\it símbolo} son subíndices que especifican un miembro particular del conjunto (si el conjunto es un arreglo, {\it i.e.} un conjunto de conjuntos); + +\noindent +{\it registro}, \dots, {\it registro} son registros. + +\noindent +Las comas que preceden a los registros pueden omitirse. + +\para{Registros} + +\vspace*{-8pt} + +\begin{description} +\item[{\tt :=}]\hspace*{0pt}\\ +es un elemento de asignación de registro no-significativo que puede ser usado libremente para mejorar la legibilidad; +\item[{\tt(} {\it porción} {\tt)}]\hspace*{0pt}\\ +especifica una porción; +\item[{\it datos-simples}]\hspace*{0pt}\\ +especifica los datos del conjunto en formato simple; +\item[{\tt:} {\it datos-matriciales}]\hspace*{0pt}\\ +especifica los datos del conjunto en formato matricial; +\item[{\tt(tr)} {\tt:} {\it datos-matriciales}]\hspace*{0pt}\\ +especifica los datos del conjunto en formato matricial traspuesto (en este caso, los dos puntos que siguen a la palabra clave {\tt(tr)} pueden omitirse). +\end{description} + +\vspace*{-8pt} + +\para{Ejemplos} + +\begin{verbatim} +set mes := Ene Feb Mar Abr May Jun; +set mes "Ene", "Feb", "Mar", "Abr", "May", "Jun"; +set A[3,Mar] := (1,2) (2,3) (4,2) (3,1) (2,2) (4,4) (3,4); +set A[3,'Mar'] := 1 2 2 3 4 2 3 1 2 2 4 4 3 4; +set A[3,'Mar'] : 1 2 3 4 := + 1 - + - - + 2 - + + - + 3 + - - + + 4 - + - + ; +set B := (1,2,3) (1,3,2) (2,3,1) (2,1,3) (1,2,2) (1,1,1) (2,1,1); +set B := (*,*,*) 1 2 3, 1 3 2, 2 3 1, 2 1 3, 1 2 2, 1 1 1, 2 1 1; +set B := (1,*,2) 3 2 (2,*,1) 3 1 (1,2,3) (2,1,3) (1,1,1); +set B := (1,*,*) : 1 2 3 := + 1 + - - + 2 - + + + 3 - + - + (2,*,*) : 1 2 3 := + 1 + - + + 2 - - - + 3 + - - ; +\end{verbatim} + +\noindent(En estos ejemplos, {\tt mes} es un conjunto simple de singletones, {\tt A} es un arreglo 2-dimensional de duplos y {\tt B} es un conjunto simple de triplos. Los bloques de datos para el mismo conjunto son equivalentes en el sentido de que especifican los mismos datos en formatos distintos. + +El {\it bloque de datos del conjunto} se usa para especificar un conjunto elemental completo, el que se asigna a un conjunto (si es un conjunto simple) o a uno de sus miembros (si el conjunto es un arreglo de conjuntos).\footnote{Hay otra forma de especificar datos para un conjunto simple junto con los datos para los parámetros. Esta característica se discute en la próxima sección.} + +Los bloques de datos sólo pueden ser especificados para conjuntos no-calculables, {\it i.e.} para conjuntos que no tienen el atributo de asignación ({\tt:=}) en la correspondiente sentencia set. + +Si el conjunto es un conjunto simple, sólo se debe especificar su nombre simbólico en el encabezado del bloque de datos. De otro modo, si el conjunto es un arreglo $n$-dimensional, su nombre simbólico debe proveerse con una lista completa de subíndices separados por coma y encerrados entre corchetes para especificar un miembro particular del arreglo de conjuntos. El número de subíndices debe ser igual a la dimensión del arreglo de conjuntos, en el que cada subíndice deben ser un número o símbolo. + +Un conjunto elemental definido en el bloque de datos del conjunto se codifica como una secuencia de registros según se describe luego.\footnote{{Registro} es simplemente un término técnico. No significa que los mismos presenten algún formateo especial.} + +\subsection{Asignación de registro} + +La {\it asignación de registro} ({\tt:=}) es un elemento no-significativo. Se puede usar para mejorar la legibilidad de los bloques de datos. + +\subsection{Registro en porción} + +El {\it registro en porción} es un registro de control que especifica una {\it porción} del conjunto elemental definido en el bloque de datos. Tiene la siguiente forma sintáctica: +$$\mbox{{\tt(} $p_1$ {\tt,} $p_2$ {\tt,} \dots {\tt,} $p_n$ {\tt)}}$$ +donde $p_1$, $p_2$, \dots, $p_n$ son componentes de la porción. + +Cada componente de la porción puede ser un número o un símbolo o el asterisco ({\tt*}). El número de componentes de la porción debe coincidir con la dimensión de los $n$-tuplos del conjunto elemental que se define. Por ejemplo, si el conjunto elemental contiene 4-tuplos (cuádruplos), la porción debe tener cuatro componentes. El número de asteriscos en la porción se denomina la {\it dimensión de la porción}. + +El efecto de usar las porciones es como sigue: si se especifica una porción $m$-dimensional ({\it i.e.} una porción que tiene $m$ asteriscos) en el bloque de datos, todos los registros subsecuentes deben especificar tuplos de dimensión $m$. Cuando se encuentra un $m$-tuplo, cada asterisco en la porción se reemplaza por los correspondientes componentes del $m$-tuplo para dar el $n$-tuplo resultante, el que es incluido en el conjunto elemental que se define. Por ejemplo, si está vigente la porción $(a,*,1,2,*)$ y se encuentra el duplo $(3,b)$ en el registro subsecuente, el 5-tuplo resultante que se incluye en el conjunto elemental es $(a,3,1,2,b)$. + +Las porciones que no tienen asteriscos en si mismas, definen un $n$-tuplo completo que se incluye en el conjunto elemental. + +Una vez especificada una porción, la misma está vigente hasta que aparezca una nueva porción o bien hasta que se encuentra el final del bloque de datos. Debe notarse que si no se especifica una porción en el bloque de datos, se asume una cuyos componentes son asteriscos en todas las posiciones. + +\subsection{Registro simple} + +El {\it registro simple} define un $n$-tuplo en formato simple y tiene la siguiente forma sintáctica: +$$\mbox{$t_1$ {\tt,} $t_2$ {\tt,} \dots {\tt,} $t_n$}$$ +donde $t_1$, $t_2$, \dots, $t_n$ son componentes del $n$-tuplo. Cada componente puede ser un número o símbolo. Las comas entre componentes son opcionales y pueden omitirse. + +\subsection{Registro matricial} + +El {\it registro matricial} define varios 2-tuplos (duplos) en formato matricial y tiene la siguiente forma sintáctica: +$$\begin{array}{cccccc} +\mbox{{\tt:}}&c_1&c_2&\dots&c_n&\mbox{{\tt:=}}\\ +f_1&a_{11}&a_{12}&\dots&a_{1n}&\\ +f_2&a_{21}&a_{22}&\dots&a_{2n}&\\ +\multicolumn{5}{c}{.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .}&\\ +f_m&a_{m1}&a_{m2}&\dots&a_{mn}&\\ +\end{array}$$ +donde $f_1$, $f_2$, \dots, $f_m$ son números y/o símbolos que corresponden a filas de la matriz; $c_1$, $c_2$, \dots, $c_n$ son números y/o símbolos que corresponden a columnas de la matriz, mientras que $a_{11}$, $a_{12}$, \dots, $a_{mn}$ son los elementos de la matriz, los cuales pueden ser tanto {\tt+} como {\tt-}. (En este registro, el delimitador {\tt:} que precede a la lista de columnas y el delimitador {\tt:=} a continuación de la lista de columnas, no pueden ser omitidos.) + +Cada elemento $a_{ij}$ del bloque de datos matricial (donde $1\leq i\leq m$, +$1\leq j\leq n$) corresponde a 2-tuplos $(f_i,c_j)$. Si en $a_{ij}$ se indica el signo más ({\tt+}), el correspondiente 2-tuplo (o un $n$-tuplo más largo si se usa una porción) se incluye en el conjunto elemental. De otro modo, si en $a_{ij}$ se indica el signo menos ({\tt-}) el 2-tuplo no se incluye en el conjunto elemental. + +Puesto que el registro matricial define 2-tuplos, ya sea el conjunto elemental o bien la porción vigente en uso deben ser 2-dimensionales. + +\subsection{Registro matricial traspuesto} + +El {\it registro matricial traspuesto} tiene la siguiente forma sintáctica: +$$\begin{array}{cccccc} +\mbox{{\tt(tr) :}}&c_1&c_2&\dots&c_n&\mbox{{\tt:=}}\\ +f_1&a_{11}&a_{12}&\dots&a_{1n}&\\ +f_2&a_{21}&a_{22}&\dots&a_{2n}&\\ +\multicolumn{5}{c}{.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .}&\\ +f_m&a_{m1}&a_{m2}&\dots&a_{mn}&\\ +\end{array}$$ +(En este caso el delimitador {\tt:} a continuación de la palabra clave {\tt (tr)} es opcional y puede omitirse.) + +Este registro es completamente análogo al registro matricial (ver anteriormente) con la única excepción, en este caso, de que cada elemento $a_{ij}$ de la matriz corresponde al 2-tuplo $(c_j,f_i)$ en vez de a $(f_i,c_j)$. + +Una vez especificado, el indicador {\tt(tr)} tiene alcance en todos los registros subsecuentes hasta que se encuentra otra porción o bien el fin del bloque de datos. + +\section{Bloque de datos de parámetro} + +\noindent +\framebox[468pt][l]{ +\parbox[c][88pt]{468pt}{ +\hspace{6pt} {\tt param} {\it nombre} {\tt,} {\it registro} {\tt,} \dots +{\tt,} {\it registro} {\tt;} + +\medskip + +\hspace{6pt} {\tt param} {\it nombre} {\tt default} {\it valor} {\tt,} +{\it registro} {\tt,} \dots {\tt,} {\it registro} {\tt;} + +\medskip + +\hspace{6pt} {\tt param} {\tt:} {\it datos-tabulación} {\tt;} + +\medskip + +\hspace{6pt} {\tt param} {\tt default} {\it valor} {\tt:} +{\it datos-tabulación} {\tt;} +}} + +\medskip + +\noindent +{\it nombre} es el nombre simbólico del parámetro; + +\noindent +{\it valor} es un valor por defecto opcional del parámetro; + +\noindent +{\it registro}, \dots, {\it registro} son registros. + +\noindent +{\it datos-tabulación} especifica los datos del parámetro en el formato tabulación. + +\noindent +Las comas que preceden a los registros pueden omitirse. + +\para{Registros} + +\vspace*{-8pt} + +\begin{description} +\item[{\tt :=}]\hspace*{0pt}\\ +es un elemento de asignación de registro no-significativo que puede ser usado libremente para mejorar la legibilidad; +\item[{\tt[} {\it porción} {\tt]}]\hspace*{0pt}\\ +especifica una porción; +\item[{\it datos-planos}]\hspace*{0pt}\\ +especifica los datos del parámetro en formato plano; +\item[{\tt:} {\it datos-tabulares}]\hspace*{0pt}\\ +especifica los datos del parámetro en formato tabular; +\item[{\tt(tr)} {\tt:} {\it datos-tabulares}]\hspace*{0pt}\\ +especifica los datos del parámetro en formato matricial traspuesto (en este caso, los dos puntos que siguen a la palabra clave {\tt(tr)} pueden omitirse). +\end{description} + +\vspace*{-8pt} + +\para{Ejemplos} + +\begin{verbatim} +param T := 4; +param mes := 1 Ene 2 Feb 3 Mar 4 Abr 5 May; +param mes := [1] 'Ene', [2] 'Feb', [3] 'Mar', [4] 'Abr', [5] 'May'; +param stock_inicial := hierro 7.32 niquel 35.8; +param stock_inicial [*] hierro 7.32, niquel 35.8; +param costo [hierro] .025 [niquel] .03; +param valor := hierro -.1, niquel .02; +param : stock_inicial costo valor := + hierro 7.32 .025 -.1 + niquel 35.8 .03 .02 ; +param : insumo : stock_inicial costo valor := + hierro 7.32 .025 -.1 + niquel 35.8 .03 .02 ; +param demanda default 0 (tr) + : FRA DET LAN WIN STL FRE LAF := + laminas 300 . 100 75 . 225 250 + rollos 500 750 400 250 . 850 500 + cintas 100 . . 50 200 . 250 ; +param costo_transporte := + [*,*,laminas]: FRA DET LAN WIN STL FRE LAF := + GARY 30 10 8 10 11 71 6 + CLEV 22 7 10 7 21 82 13 + PITT 19 11 12 10 25 83 15 + [*,*,rollos]: FRA DET LAN WIN STL FRE LAF := + GARY 39 14 11 14 16 82 8 + CLEV 27 9 12 9 26 95 17 + PITT 24 14 17 13 28 99 20 + [*,*,cintas]: FRA DET LAN WIN STL FRE LAF := + GARY 41 15 12 16 17 86 8 + CLEV 29 9 13 9 28 99 18 + PITT 26 14 17 13 31 104 20 ; +\end{verbatim} + +El {\it bloque de datos del parámetro} se usa para especificar datos completos a un parámetro (o a varios parámetros si los datos se especifican en el formato tabulaciones) + +Los bloques de datos sólo pueden ser especificados para parámetros no-calculables, {\it i.e.} para parámetros que no tienen el atributo de asignación({\tt:=}) en la correspondiente sentencia parameter. + +Los datos definidos en el bloque de datos del parámetro se codifican como una secuencia de registros descriptos luego. Adicionalmente, el bloque de datos puede ser provisto con el atributo opcional {\tt default}, el cual especifica un valor numérico o simbólico por defecto para el parámetro (parámetros). Este valor por defecto se asigna al parámetro, o a sus miembros, cuando no se definen valores apropiados en el bloque de datos del parámetro. El atributo {\tt default} no se puede usar si ya se ha especificado en la correspondiente sentencia parameter. + +\subsection{Asignación de registro} + +La {\it asignación de registro} ({\tt:=}) es un elemento no-significativo. Se puede usar para mejorar la legibilidad de los bloques de datos. + +\subsection{Registro en porción} + +El {\it registro en porción} es un registro de control que especifica una {\it porción} del arreglo de parámetros. Tiene la siguiente forma sintáctica: +$$\mbox{{\tt[} $p_1$ {\tt,} $p_2$ {\tt,} \dots {\tt,} $p_n$ {\tt]}}$$ +donde $p_1$, $p_2$, \dots, $p_n$ son componentes de la porción. + +Cada componente de la porción puede ser un número o un símbolo o el asterisco ({\tt*}). El número de componentes de la porción debe coincidir con la dimensión del parámetro. Por ejemplo, si el parámetro es un arreglo 4-dimensional, la porción debe tener cuatro componentes. El número de asteriscos en la porción se denomina la {\it dimensión de la porción}. + +El efecto de usar las porciones es como sigue: si se especifica una porción $m$-dimensional ({\it i.e.} una porción que tiene $m$ asteriscos) en el bloque de datos, todos los registros subsecuentes deben especificar los subíndices de los miembros del parámetro como si el parámetro fuese $m$-dimensional y no $n$-dimensional. + +Cuando se encuentran los $m$ subíndices, cada asterisco en la porción se reemplaza por el correspondiente subíndice para dar los $n$ subíndices, los cuales definen al miembro corriente del parámetro. Por ejemplo, si está vigente la porción $(a,*,1,2,*)$ y se encuentran los subíndices 3 y $b$ en el registro subsecuente, la lista completa de subíndices que se usa para elegir un miembro del parámetro es $(a,3,1,2,b)$. + +Se permite especificar una porción que no tenga asteriscos. Tal porción, en sí misma define una lista completa de subíndices, en cuyo caso el próximo registro debe definir solamente un valor individual del correspondiente miembro del parámetro. + +Una vez especificada una porción, la misma está vigente hasta que aparezca una nueva porción o bien hasta que se encuentra el final del bloque de datos. Debe notarse que si no se especifica una porción en el bloque de datos, se asume una cuyos componentes son todos asteriscos. + +\subsection{Registro plano} + +El {\it registro plano} define la lista de subíndices y un valor individual en el formato plano. Este registro tiene la siguiente forma sintáctica: +$$\mbox{$t_1$ {\tt,} $t_2$ {\tt,} \dots {\tt,} $t_n$ {\tt,} $v$}$$ +donde $t_1$, $t_2$, \dots, $t_n$ son subíndices y $v$ es un valor. Cada subíndice, al igual que el valor, puede ser un número o un símbolo. Las comas que siguen a los subíndices son opcionales y pueden omitirse. + +En el caso de parámetros o porciones 0-dimensionales, el registro plano no tiene subíndice y consiste solamente de un valor individual. + +\subsection{Registro tabular} + +El {\it registro tabular} define varios valores, cada uno de los cuales viene provisto con dos subíndices. Este registro tiene la siguiente forma sintáctica: +$$\begin{array}{cccccc} +\mbox{{\tt:}}&c_1&c_2&\dots&c_n&\mbox{{\tt:=}}\\ +f_1&a_{11}&a_{12}&\dots&a_{1n}&\\ +f_2&a_{21}&a_{22}&\dots&a_{2n}&\\ +\multicolumn{5}{c}{.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .}&\\ +f_m&a_{m1}&a_{m2}&\dots&a_{mn}&\\ +\end{array}$$ +donde los $f_1$, $f_2$, \dots, $f_m$ son números y/o símbolos que corresponden a filas de la tabla; $c_1$, $c_2$, \dots, $c_n$ son números y/o símbolos que corresponden a columnas de la tabla; mientras que $a_{11}$, $a_{12}$, \dots, $a_{mn}$ son elementos de la tabla. Cada elemento puede ser un número o símbolo o el punto decimal ({\tt.}) solo (en este registro, el delimitador {\tt:} que precede a la lista de columnas y el delimitador {\tt:=} a continuación de la lista de columnas, no pueden ser omitidos.). + +Cada elemento $a_{ij}$ del bloque de datos tabulares ($1\leq i\leq m$, +$1\leq j\leq n$) define dos subíndices, siendo el primero $f_i$ y el segundo $c_j$. Estos subíndices se usan junto con la porción vigente para formar la lista completa de subíndices que identifica a un miembro particular del arreglo de parámetros. Si $a_{ij}$ es un número o símbolo, tal valor se asigna al miembro del parámetro. Sin embargo, si $a_{ij}$ es un punto decimal solo, el miembro recibe el valor por defecto especificado ya sea en el bloque de datos del parámetro o en la sentencia parameter, o si no hay un valor por defecto especificado, el miembro permanece indefinido. + +Puesto que el registro tabular provee dos subíndices para cada valor, ya sea el parámetro o bien la porción vigente en uso deben ser 2-dimensionales. + +\subsection{Registro tabular traspuesto} + +El {\it registro tabular traspuesto} tiene la siguiente forma sintáctica: +$$\begin{array}{cccccc} +\mbox{{\tt(tr) :}}&c_1&c_2&\dots&c_n&\mbox{{\tt:=}}\\ +f_1&a_{11}&a_{12}&\dots&a_{1n}&\\ +f_2&a_{21}&a_{22}&\dots&a_{2n}&\\ +\multicolumn{5}{c}{.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .}&\\ +f_m&a_{m1}&a_{m2}&\dots&a_{mn}&\\ +\end{array}$$ +(En este caso el delimitador {\tt:} a continuación de la palabra clave {\tt (tr)} es opcional y puede omitirse.) + +Este registro es completamente análogo al registro tabular (ver anteriormente), con la única excepción de que el primer subíndice definido por el elemento $a_{ij}$ es $c_j$ mientras que el segundo es $f_i$. + +Una vez especificado, el indicador {\tt(tr)} tiene alcance en todos los registros subsecuentes hasta que se encuentre otra porción o bien el fin del bloque de datos. + +\subsection{Formato de datos tabulación} + +El bloque de datos del parámetro en el {\it formato tabulación} tiene la siguiente forma sintáctica: +$$ +\begin{array}{*{8}{l}} +\multicolumn{4}{l} +{{\tt param}\ {\tt default}\ valor\ {\tt :}\ c\ {\tt :}}& +p_1\ \ \verb|,|&p_2\ \ \verb|,|&\dots\ \verb|,|&p_f\ \ \verb|:=|\\ +f_{11}\ \verb|,|& f_{12}\ \verb|,|& \dots\ \verb|,|& f_{1n}\ \verb|,|& +a_{11}\ \verb|,|& a_{12}\ \verb|,|& \dots\ \verb|,|& a_{1f}\ \verb|,|\\ +f_{21}\ \verb|,|& f_{22}\ \verb|,|& \dots\ \verb|,|& f_{2n}\ \verb|,|& +a_{21}\ \verb|,|& a_{22}\ \verb|,|& \dots\ \verb|,|& a_{2f}\ \verb|,|\\ +\dots & \dots & \dots & \dots & \dots & \dots & \dots & \dots \\ +f_{m1}\ \verb|,|& f_{m2}\ \verb|,|& \dots\ \verb|,|& f_{mn}\ \verb|,|& +a_{m1}\ \verb|,|& a_{m2}\ \verb|,|& \dots\ \verb|,|& a_{mf}\ \verb|;|\\ +\end{array} +$$ + +1. La palabra clave {\tt default} puede omitirse junto con el valor que le sigue. + +2. El nombre simbólico $c$ puede omitirse junto con los dos puntos que le siguen. + +3. Todas las comas son opcionales y pueden omitirse. + +El bloque de datos en el formato tabulación mostrado arriba es exactamente equivalente a los siguientes bloques de datos: + +\verb|set| $c$\ \verb|:=|\ $ +\verb|(|f_{11}\verb|,|f_{12}\verb|,|\dots\verb|,|f_{1n}\verb|) | +\verb|(|f_{21}\verb|,|f_{22}\verb|,|\dots\verb|,|f_{2n}\verb|) | +\dots +\verb| (|f_{m1}\verb|,|f_{m2}\verb|,|\dots\verb|,|f_{mn}\verb|);|$ + +\verb|param| $p_1$\ \verb|default|\ $valor$\ \verb|:=| + +$\verb| | +\verb|[|f_{11}\verb|,|f_{12}\verb|,|\dots\verb|,|f_{1n}\verb|] |a_{11} +\verb| [|f_{21}\verb|,|f_{22}\verb|,|\dots\verb|,|f_{2n}\verb|] |a_{21} +\verb| |\dots +\verb| [|f_{m1}\verb|,|f_{m2}\verb|,|\dots\verb|,|f_{mn}\verb|] |a_{m1} +\verb|;| +$ + +\verb|param| $p_2$\ \verb|default|\ $valor$\ \verb|:=| + +$\verb| | +\verb|[|f_{11}\verb|,|f_{12}\verb|,|\dots\verb|,|f_{1n}\verb|] |a_{12} +\verb| [|f_{21}\verb|,|f_{22}\verb|,|\dots\verb|,|f_{2n}\verb|] |a_{22} +\verb| |\dots +\verb| [|f_{m1}\verb|,|f_{m2}\verb|,|\dots\verb|,|f_{mn}\verb|] |a_{m2} +\verb|;| +$ + +\verb| |.\ \ \ .\ \ \ .\ \ \ .\ \ \ .\ \ \ .\ \ \ .\ \ \ .\ \ \ . + +\verb|param| $p_f$\ \verb|default|\ $valor$\ \verb|:=| + +$\verb| | +\verb|[|f_{11}\verb|,|f_{12}\verb|,|\dots\verb|,|f_{1n}\verb|] |a_{1f} +\verb| [|f_{21}\verb|,|f_{22}\verb|,|\dots\verb|,|f_{2n}\verb|] |a_{2f} +\verb| |\dots +\verb| [|f_{m1}\verb|,|f_{m2}\verb|,|\dots\verb|,|f_{mn}\verb|] |a_{mf} +\verb|;| +$ + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\appendix + +\chapter{Uso de sufijos} + +\vspace*{-12pt} + +Se pueden usar sufijos para recuperar valores adicionales relacionados con las variables, restricciones y objetivos del modelo. + +Un {\it sufijo} consiste de un punto ({\tt.}) seguido de una palabra clave no-reservada. Por ejemplo, si {\tt x} es una variable bidimensional, {\tt x[i,j].lb} es un valor numérico igual a la cota inferior de la variable elemental {\tt x[i,j]} que se puede usar como un parámetro numérico dondequiera que sea en expresiones. + +Para las variables del modelo, los sufijos tienen los siguientes significados: + +\begin{tabular}{@{}ll@{}} +{\tt.lb}&cota inferior\\ +{\tt.ub}&cota superior\\ +{\tt.status}&estatus en la solución:\\ +&0 --- indefinida\\ +&1 --- básica\\ +&2 --- no-básica en la cota inferior\\ +&3 --- no-básica en la cota superior\\ +&4 --- variable no-básica libre (no acotada)\\ +&5 --- variable no-básica fija\\ +{\tt.val}&valor primal en la solución\\ +{\tt.dual}&valor dual (costo reducido) en la solución\\ +\end{tabular} + +Para las restricciones y objetivos del modelo, los sufijos tienen los siguientes significados: + +\begin{tabular}{@{}ll@{}} +{\tt.lb}&cota inferior de la forma lineal\\ +{\tt.ub}&cota superior de la forma lineal\\ +{\tt.status}&estatus en la solución:\\ +&0 --- indefinida\\ +&1 --- no-limitante\\ +&2 --- limitante en la cota inferior\\ +&3 --- limitante en la cota superior\\ +&4 --- fila limitante libre (no-acotada)\\ +&5 --- restricción de igualdad limitante\\ +{\tt.val}&valor primal de la forma lineal en la solución\\ +{\tt.dual}&valor dual (costo reducido) de la forma lineal en la solución\\ +\end{tabular} + +Debe notarse que los sufijos {\tt.status}, {\tt.val} y {\tt.dual} solamente pueden usarse luego de la sentencia solve. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\chapter{Funciones de fecha y hora} + +\noindent\hfil +\begin{tabular}{c} +por Andrew Makhorin \verb||\\ +y Heinrich Schuchardt \verb||\\ +\end{tabular} + +\section{Obtención del tiempo calendario corriente} +\label{gmtime} + +Para obtener el tiempo calendario\footnote{N. del T.: el tiempo calendario es un punto en el {\it continuum} del tiempo, por ejemplo 4 de noviembre de 1990 a las 18:02.5 UTC. A veces se lo llama ``tiempo absoluto''. La definición está tomada de {\it Sandra Loosemore}, {\it Richard M. Stallman}, {\it Roland McGrath}, {\it Andrew Oram} \& {\it Ulrich Drepper}, ``The GNU C Library Reference Manual - for version 2.17'', Free Software Foundation, Inc, 2012.} corriente en MathProg existe la función {\tt gmtime}. No tiene argumentos y devuelve el número de segundos transcurridos desde las 00:00:00 del 1 de enero de 1970, Tiempo Universal Coordinado (UTC). Por ejemplo: + +\begin{verbatim} + param utc := gmtime(); +\end{verbatim} + +MathPro no tiene una función para convertir el tiempo UTC devuelto por la función {\tt gmtime} a tiempo calendario {\it local}. Entonces, si se necesita determinar el tiempo calendario local corriente, se debe agregar al tiempo UTC devuelto la diferencia horaria con respecto al UTC expresada en segundos. Por ejemplo, la hora en Berlín durante el invierno está una hora adelante del UTC, lo que corresponde una diferencia horaria de +1~hora~= +3600~segundos, de modo que el tiempo calendario corriente del invierno en Berlín se puede determinar como sigue: + +\begin{verbatim} + param ahora := gmtime() + 3600; +\end{verbatim} + +\noindent Análogamente, el horario de verano en Chicago (Zona Horaria Central) está cinco horas por detrás del UTC, de modo que el correspondiente tiempo calendario local corriente se puede determinar como sigue: + +\begin{verbatim} + param ahora := gmtime() - 5 * 3600; +\end{verbatim} + +Debe notarse que el valor devuelto por {\tt gmtime} es volátil, {\it i.e.} si se la invoca varias veces, esta función devolverá valores diferentes. + +\section{Conversión de una cadena de caracteres a un tiempo calendario} +\label{str2time} + +La función {\tt str2time(}{\it c}{\tt,} {\it f}{\tt)} convierte una cadena de caracteres (una {\it estampa de la fecha y hora}) especificada por su primer argumento {\it c}, la que debe ser una expresión simbólica, a un tiempo calendario apropiado para cálculos aritméticos. La conversión se controla mediante la especificación de una cadena de formato {\it f} (el segundo argumento), la que también debe ser una expresión simbólica. + +El resultado de la conversión devuelto por {\tt str2time} tiene el mismo significado que los valores devueltos por la función {\tt gmtime} (ver Subsección \ref{gmtime}, página \pageref{gmtime}). Debe notarse que {\tt str2time} {\it no corrige} el tiempo calendario devuelto para considerar la zona horaria local, {\it i.e.} si se aplica a las 00:00:00 del 1 de enero de 1970, siempre devolverá 0. + +Por ejemplo, las sentencias del modelo + +\begin{verbatim} + param c, symbolic, := "07/14/98 13:47"; + param t := str2time(c, "%m/%d/%y %H:%M"); + display t; +\end{verbatim} + +\noindent imprime lo siguiente en la salida estándar: + +\begin{verbatim} + t = 900424020 +\end{verbatim} + +\noindent donde el tiempo calendario mostrado corresponde a las 13:47:00 del 14 de julio de 1998. + +La cadena de formato que se pasa a la función {\tt str2time} consiste de especificadores de conversión y caracteres ordinarios. Cada especificador de conversión empieza con un carácter de porcentaje ({\tt\%}) seguido por una letra. + +Los siguientes especificadores de conversión se pueden usar en la cadena de formato\footnote{N. del T.: en todas las funciones de fecha y hora, nombre del mes y del día de la semana refiere a su denominación en inglés, {\it e.g.}: {\tt August}, {\tt Aug}, {\tt Wednesday}, {\tt We}.}: + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%b}&El nombre del mes abreviado (insensible a mayúsculas). Al menos las tres primeras letras del nombre del mes deben aparecer en la cadena de entrada.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%d}&El día del mes como un número decimal (rango de 1 a 31). Se permite el cero como primer dígito, aunque no es requerido.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%h}&Lo mismo que {\tt\%b}.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%H}&La hora como un número decimal, empleando un reloj de 24 horas (rango de 0 a 23). Se permite el cero como primer dígito, aunque no es requerido.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%m}&El mes como un número decimal (rango de 1 a 12). Se permite el cero como primer dígito, aunque no es requerido.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%M}&El minuto como número decimal (rango de 0 a 59). Se permite el cero como primer dígito, aunque no es requerido.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%S}&El segundo como un número decimal (rango de 0 a 59). Se permite el cero como primer dígito, aunque no es requerido.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%y}&El año sin un siglo como un número decimal (rango de 0 a 99). Se permite el cero como primer dígito, aunque no es requerido. Los valores de entrada en el rango de 0 a 68 se consideran como los años 2000 al 2068, mientras que los valores del 69 al 99 como los años 1969 a 1999.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%z}&La diferencia horaria con respecto a GMT en formato ISO 8601.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%\%}&Un carácter {\tt\%} literal.\\ +\end{tabular} + +Todos los demás caracteres (ordinarios) en la cadena de formato deben tener un carácter de coincidencia con la cadena de entrada a ser convertida. Las excepciones son los espacios en la cadena de entrada, la cual puede coincidir con cero o más caracteres de espacio en la cadena de formato. + +Si algún componente de la fecha y/u hora están ausentes en el formato y, consecuentemente, en la cadena de entrada, la función {\tt str2time} usa sus valores por defecto de las 00:00:00 del 1 de enero de 1970, es decir que el valor por defecto para el año es 1970, el valor por defecto para el mes es enero, etc. + +La función {} es aplicable a todos los tiempos calendarios en el rango desde las 00:00:00 del 1 de enero del 0001 hasta las 23:59:59 del 31 de diciembre del 4000 del calendario gregoriano. + +\section{Conversión de un tiempo calendario a una cadena de caracteres} +\label{time2str} + +La función {\tt time2str(}{\it t}{\tt,} {\it f}{\tt)} convierte el tiempo calendario especificado por su primer argumento {\it t}, el que debe ser una expresión numérica, a una cadena de caracteres (valor simbólico). La conversión se controla con la cadena de formato {\it f} especificada (el segundo argumento), la que debe ser una expresión simbólica. + +El tiempo calendario que se le pasa a {\tt time2str} tiene el mismo significado que el valor devuelto por la función {\tt gmtime} (ver Subsección \ref{gmtime}, página \pageref{gmtime}). Debe notarse que {\tt time2str} {\it no corrige} el tiempo calendario especificado para considerar la zona horaria local, {\it i.e.} el tiempo calendario 0 siempre corresponde a las 00:00:00 del 1 de enero de 1970. + +Por ejemplo, las sentencias del modelo + +\begin{verbatim} + param c, symbolic, := time2str(gmtime(), "%FT%TZ"); + display c; +\end{verbatim} + +\noindent puede producir la siguiente impresión: + +\begin{verbatim} + c = '2008-12-04T00:23:45Z' +\end{verbatim} + +\noindent que es una estampa de una fecha y hora en el formato ISO. + +La cadena de formato que se pasa a la función {\tt time2str} consiste de especificadores de conversión y caracteres ordinarios. Cada especificador de conversión empieza con un carácter de porcentaje ({\tt\%}) seguido por una letra. + +Los siguientes especificadores de conversión se pueden usar en la cadena de formato: + +\newpage + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%a}&El nombre del día de la semana abreviado (2 caracteres).\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%A}&El nombre del día de la semana completo.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%b}&El nombre del mes abreviado (3 caracteres).\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%B}&El nombre del mes completo.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%C}&El siglo del año, es decir el mayor entero no mayor que el año dividido por~100.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%d}&El día del mes como un número decimal (rango de 01 a 31).\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%D}&La fecha, usando el formato \verb|%m/%d/%y|.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%e}&El día del mes, como con \verb|%d|, pero rellenado con un espacio en blanco en vez de cero.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%F}&La fecha, usando el formato \verb|%Y-%m-%d|.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%g}&El año correspondiente al número de semana ISO, pero sin el siglo (rango de 00 a 99). Tiene el mismo formato y valor que \verb|%y|, excepto que si el número de semana ISO (ver \verb|%V|) pertenece al año previo o siguiente, se usa aquel año en su lugar.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%G}&El año correspondiente al número de semana ISO. Tiene el mismo formato y valor que \verb|%Y|, excepto que si el número de semana ISO (ver \verb|%V|) pertenece al año previo o siguiente, se usa aquel año en su lugar.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%h}&Lo mismo que \verb|%b|.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%H}&La hora como un número decimal, empleando un reloj de 24 horas (rango de 00 a 23).\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%I}&La hora como un número decimal, empleando un reloj de 12 horas (rango de 01 a 12).\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%j}&El día del año como un número decimal (rango de 001 a 366).\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%k}&La hora como un número decimal, empleando un reloj de 24 horas como con \verb|%H|, pero rellenado con un espacio en blanco en vez de cero.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%l}&La hora como un número decimal, empleando un reloj de 12 horas como con \verb|%I|, pero rellenado con un espacio en blanco en vez de cero.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%m}&El mes como un número decimal (rango de 01 a 12).\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%M}&El minuto como un número decimal (rango de 00 a 59).\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%p}&Tanto {\tt AM} como {\tt PM}, de acuerdo con el valor horario dado. La medianoche es tratada como {\tt AM} y el mediodía como {\tt PM}.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%P}&Tanto {\tt am} como {\tt pm}, de acuerdo con el valor horario dado. La medianoche es tratada como {\tt am} y el mediodía como {\tt pm}.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%R}&La hora y los minutos en números decimales, usando el formato \verb|%H:%M|.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%S}&Los segundos como un número decimal (rango de 00 a 59).\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%T}&La hora del día en números decimales, usando el formato \verb|%H:%M:%S|.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%u}&El día de la semana como un número decimal (rango de 1 a 7), siendo 1 el lunes.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%U}&El número de semana del año corriente como un número decimal (rango de 00 a 53), empezando con el primer domingo como el primer día de la primer semana. Se considera que los días del año anteriores al primer domingo son parte de la semana 00.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%V}&El número de semana ISO como un número decimal (rango 01 a 53). Las semanas de ISO empiezan los lunes y terminan los domingos. La semana 01 de un año es la primer semana que tiene la mayoría de sus días en ese año, lo cual es equivalente a la semana que contiene al 4 de enero. La semana 01 de un año puede contener días del año previo. La semana anterior a la semana 01 de un año es la última semana (52 o 53) del año previo, aún si esta contiene días del nuevo año. En otras palabras, si el 1 de enero cae en lunes, martes, miércoles o jueves, está en la semana 01; si el 1 de enero cae en viernes, sábado o domingo, está en la semana 52 o 53 del año previo.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%w}&El día de la semana como un número decimal (rango de 0 a 6), siendo 0 el domingo.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%W}&El número de semana del año corriente como un número decimal (rango de 00 a 53), empezando con el primer lunes como el primer día de la primer semana. Se considera que los días del año anteriores al primer lunes son parte de la semana 00.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%y}&El año sin el siglo como un número decimal (rango de 00 a 99), es decir año {\tt mod} 100.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%Y}&El año como un número decimal, usando el calendario gregoriano.\\ +\end{tabular} + +\begin{tabular}{@{}p{20pt}p{421.5pt}@{}} +{\tt\%\%}& Un carácter \verb|%| literal.\\ +\end{tabular} + +Todos los demás caracteres (ordinarios) en la cadena de formato simplemente se copian a la cadena resultante. + +El primer argumento (tiempo calendario) que se le pasa a la función {\tt time2str} debe están en el rango entre $-62135596800$ y $+64092211199$, lo que corresponde al período desde las 00:00:00 del 1 de enero del 0001 hasta las 23:59:59 del 31 de diciembre del 4000 del calendario gregoriano. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\chapter{Controladores de tablas} +\label{drivers} + +\noindent\hfil +\begin{tabular}{c} +por Andrew Makhorin \verb||\\ +y Heinrich Schuchardt \verb||\\ +\end{tabular} + +\bigskip\bigskip + +El {\it controlador de tablas} es un módulo del programa que permite la trasmisión de datos entre objetos de un modelo MathProg y tablas de datos. + +Actualmente, el paquete GLPK tiene cuatro controladores de tablas: + +\vspace*{-8pt} + +\begin{itemize} +\item controlador interno de tablas CSV; +\item controlador interno de tablas xBASE; +\item controlador de tablas ODBC; +\item controlador de tablas MySQL. +\end{itemize} + +\vspace*{-8pt} + +\section{Controlador de tablas CSV} + +El controlador de tablas CSV asume que la tabla de datos está representada en la forma de un archivo de texto plano, en el formato de archivo CSV (valores separados por coma) como se describe más adelante. + +Para elegir el controlador de tablas CSV, su nombre en la sentencia table debe especificarse como \verb|"CSV"| y el único argumento debe especificar el nombre de un archivo de texto plano conteniendo la tabla. Por ejemplo: + +\begin{verbatim} + table datos IN "CSV" "datos.csv": ... ; +\end{verbatim} + +El sufijo del nombre de archivo puede ser arbitrario; sin embargo, se recomienda usar el sufijo `\verb|.csv|'. + +\newpage + +Al leer tablas de entrada, el controlador de tablas CSV provee un campo implícito llamado \verb|RECNO|, el cual contiene el número del registro corriente. Este campo puede especificarse en la sentencia table de entrada, como si existiera un verdadero campo llamado \verb|RECNO| en el archivo CSV. Por ejemplo: + +\begin{verbatim} + table lista IN "CSV" "lista.csv": num <- [RECNO], ... ; +\end{verbatim} + +\subsection*{Formato CSV\footnote{Este material está basado en el documento RFC 4180.}} + +El formato CSV (valores separados por coma) es un formato de archivo de texto plano definido como sigue: + +1. Cada registro se ubica en una línea separada, delimitada por un salto de línea. Por ejemplo: + +\begin{verbatim} + aaa,bbb,ccc\n + xxx,yyy,zzz\n +\end{verbatim} + +\noindent +donde \verb|\n| significa el carácter de control \verb|LF| ({\tt 0x0A}). + +2. El último registro en el archivo puede tener un salto de línea final o no. Por ejemplo: + +\begin{verbatim} + aaa,bbb,ccc\n + xxx,yyy,zzz +\end{verbatim} + +3. Debería haber una línea de encabezado que aparezca en la primera línea del archivo, en el mismo formato que las líneas de registro normales. Este encabezado debería contener nombres que correspondan a los campos en el archivo. El número de nombres de campo en la línea de encabezado debe ser igual al número de campos de los registros en el archivo. Por ejemplo: + +\begin{verbatim} + nombre1,nombre2,nombre3\n + aaa,bbb,ccc\n + xxx,yyy,zzz\n +\end{verbatim} + +4. Dentro del encabezado y de cada registro puede haber uno o más campos separados por comas. Cada línea debe contener el mismo número de campos a través de todo el archivo. Los espacios se consideran parte del campo y, consecuentemente, no son ignorados. El último campo en el registro no debe estar seguido de una coma. Por ejemplo: + +\begin{verbatim} + aaa,bbb,ccc\n +\end{verbatim} + +5. Los campos pueden estar encerrados entre comillas dobles o no. Por ejemplo: + +\begin{verbatim} + "aaa","bbb","ccc"\n + zzz,yyy,xxx\n +\end{verbatim} + +6. Si el campo se encierra entre comillas dobles, cada comilla doble que sea parte del campo debe codificarse dos veces. Por ejemplo: + +\begin{verbatim} + "aaa","b""bb","ccc"\n +\end{verbatim} + +\newpage + +\para{Ejemplo} + +\begin{verbatim} +DESDE,HACIA,DISTANCIA,COSTO +Seattle,New-York,2.5,0.12 +Seattle,Chicago,1.7,0.08 +Seattle,Topeka,1.8,0.09 +San-Diego,New-York,2.5,0.15 +San-Diego,Chicago,1.8,0.10 +San-Diego,Topeka,1.4,0.07 +\end{verbatim} + +\section{Controlador de tablas xBASE} + +El controlador de tablas xBASE asume que la tabla de datos se almacenó en formato de archivo .dbf. + +Para elegir el controlador de tablas xBASE, su nombre en la sentencia table debe especificarse como \verb|"xBASE"| y el primer argumento debe especificar el nombre de un archivo .dbf que contenga la tabla. Para la tabla de salida, debe haber un segundo argumento definiendo el formato de la tabla en la forma \verb|"FF...F"|, donde \verb|F| es tanto {\tt C({\it n})}, el cual especifica un campo de caracteres de longitud $n$, como + {\tt N({\it n}{\rm [},{\it p}{\rm ]})}, el cual especifica un campo numérico de longitud $n$ y precisión $p$ (por defecto, $p$ es 0). + +El siguiente es un ejemplo simple que ilustra la creación y lectura de un archivo .dbf: + +\begin{verbatim} +table tab1{i in 1..10} OUT "xBASE" "foo.dbf" + "N(5)N(10,4)C(1)C(10)": 2*i+1 ~ B, Uniform(-20,+20) ~ A, + "?" ~ FOO, "[" & i & "]" ~ C; +set M, dimen 4; +table tab2 IN "xBASE" "foo.dbf": M <- [B, C, RECNO, A]; +display M; +end; +\end{verbatim} + +\section{Controlador de tablas ODBC} + +El controlador de tablas ODBC permite conexiones con bases de datos SQL usando una implementación de la interfaz ODBC basada en la Call Level Interface (CLI).\footnote{La norma de software correspondiente se define en ISO/IEC 9075-3:2003.} + +\para{Debian GNU/Linux.} +Bajo Debian GNU/Linux, el controlador de tablas ODBC usa el paquete iODBC,\footnote{Ver {\tt}.} el cual debe estar instalado antes de compilar el paquete GLPK. La instalación se puede efectuar con el siguiente comando: + +\begin{verbatim} + sudo apt-get install libiodbc2-dev +\end{verbatim} + +Debe notarse que para la configuración del paquete GLPK para activar el uso de la librería iODBC, se debe pasar la opción `\verb|--enable-odbc|' al script de configuración. + +Para su uso en todo el sistema, las bases de datos individuales deben ingresarse en \verb|/etc/odbc.ini| y \verb|/etc/odbcinst.ini|. Las conexiones de las bases de datos usadas por un usuario individual se especifican mediante archivos en el directorio home (\verb|.odbc.ini| y \verb|.odbcinst.ini|). + +\para{Microsoft Windows.} +Bajo Microsoft Windows, el controlador de tablas ODBC usa la librería ODBC de Microsoft. Para activar esta característica, el símbolo: + +\begin{verbatim} + #define ODBC_DLNAME "odbc32.dll" +\end{verbatim} + +\noindent +debe definirse en el archivo de configuración de GLPK `\verb|config.h|'. + +Las fuentes de datos pueden crearse por intermedio de las Herramientas Administrativas del Panel de Control. + +Para elegir el controlador de tablas ODBC, su nombre en la sentencia table debe especificarse como \verb|'ODBC'| o \verb|'iODBC'|. + +La lista de argumentos se especifica como sigue. + +El primer argumento es la cadena de conexión que se pasa a la librería ODBC, por ejemplo: + +\verb|'DSN=glpk;UID=user;PWD=password'|, o + +\verb|'DRIVER=MySQL;DATABASE=glpkdb;UID=user;PWD=password'|. + +Las diferentes partes de la cadena se separan con punto y coma. Cada parte consiste de un par {\it nombre de campo} y {\it valor} separados por el signo igual. Los nombres de campo permitidos dependen de la librería ODBC. Típicamente, se permiten los siguientes nombres de campo: + +\verb|DATABASE | base de datos; + +\verb|DRIVER | controlador ODBC; + +\verb|DSN | nombre de una fuente de datos; + +\verb|FILEDSN | nombre de un archivo de fuente de datos; + +\verb|PWD | clave de usuario; + +\verb|SERVER | base de datos; + +\verb|UID | nombre de usuario. + +El segundo argumento, y todos los siguientes, son considerados como sentencias SQL. + +Las sentencias SQL se pueden extender sobre múltiples argumentos. Si el último carácter de un argumento es un punto y coma, este indica el final de una sentencia SQL. + +Los argumentos de una sentencia SQL se concatenan separados por espacios. El eventual punto y coma final será removido. + +Todas las sentencias SQL, excepto la última, se ejecutarán directamente. + +Para table-IN, la última sentencia SQL puede ser un comando SELECT que empieza con \verb|'SELECT '| en letras mayúsculas. Si la cadena no se inicia con \verb|'SELECT '|, se considera que es un nombre de tabla y automáticamente se genera una sentencia SELECT. + +Para table-OUT, la última sentencia SQL puede contener uno o múltiples signos de interrogación. Si contiene un signo de interrogación, se considera como una plantilla para la rutina de escritura. De otro modo, la cadena es considerada un nombre de tabla y se genera automáticamente una plantilla INSERT. + +La rutina de escritura usa la plantilla con el signo de interrogación y reemplaza al primer signo de interrogación con el primer parámetro de salida, el segundo signo de interrogación con el segundo parámetro de salida, y así sucesivamente. Luego se emite el comando SQL. + +El siguiente es un ejemplo de la sentencia table de salida: + +\begin{verbatim} +table ta { l in LOCALIDADES } OUT + 'ODBC' + 'DSN=glpkdb;UID=glpkuser;PWD=glpkpassword' + 'DROP TABLE IF EXISTS resultados;' + 'CREATE TABLE resultados ( ID INT, LOC VARCHAR(255), CANT DOUBLE );' + 'INSERT INTO resultados 'VALUES ( 4, ?, ? )' : + l ~ LOC, cantidad[l] ~ CANT; +\end{verbatim} + +\noindent +Alternativamente, se puede escribir como sigue: + +\begin{verbatim} +table ta { l in LOCALIDADES } OUT + 'ODBC' + 'DSN=glpkdb;UID=glpkuser;PWD=glpkpassword' + 'DROP TABLE IF EXISTS resultados;' + 'CREATE TABLE resultados ( ID INT, LOC VARCHAR(255), CANT DOUBLE );' + 'resultados' : + l ~ LOC, cantidad[l] ~ CANT, 4 ~ ID; +\end{verbatim} + +El uso de plantillas con `\verb|?|' no sólo permite INSERT, sino también UPDATE, DELETE, etc. Por ejemplo: + +\begin{verbatim} +table ta { l in LOCALIDADES } OUT + 'ODBC' + 'DSN=glpkdb;UID=glpkuser;PWD=glpkpassword' + 'UPDATE resultados SET FECHA = ' & fecha & ' WHERE ID = 4;' + 'UPDATE resultados SET CANT = ? WHERE LOC = ? AND ID = 4' : + cantidad[l], l; +\end{verbatim} + +\section{Controlador de tablas MySQL} + +El controlador de tablas permite conexiones con bases de datos MySQL. + +\para{Debian GNU/Linux.} +Bajo Debian GNU/Linux, el controlador de tablas MySQL usa el paquete MySQL,\footnote{Para descargar los archivos de desarrollo, ver +{\tt}.} el cual debe estar instalado antes de compilar el paquete GLPK. La instalación se puede efectuar con el siguiente comando: + +\begin{verbatim} + sudo apt-get install libmysqlclient15-dev +\end{verbatim} + +Debe notarse que para la configuración del paquete GLPK para activar el uso de la librería MySQL, se debe pasar la opción `\verb|--enable-mysql|' al script de configuración. + +\para{Microsoft Windows.} +Bajo Microsoft Windows, el controlador de tablas MySQL también usa la librería MySQL. Para activar esta característica, el símbolo: + +\begin{verbatim} + #define MYSQL_DLNAME "libmysql.dll" +\end{verbatim} + +\noindent +debe definirse en el archivo de configuración de GLPK `\verb|config.h|'. + +Para elegir el controlador de tablas MySQL, su nombre en la sentencia table debe especificarse como \verb|'MySQL'|. + +La lista de argumentos se especifica como sigue. + +El primer argumento especifica como conectar la base de datos en el estilo DSN, por ejemplo: + +\verb|'Database=glpk;UID=glpk;PWD=gnu'|. + +Las diferentes partes de la cadena se separan con punto y coma. Cada parte consiste de un par {\it nombre de campo} y {\it valor} separados por el signo igual. Se permiten los siguientes nombres de campo: + +\verb|Server | servidor corriendo la base de datos (localhost por defecto); + +\verb|Database | nombre de la base de datos; + +\verb|UID | nombre de usuario; + +\verb|PWD | clave de usuario; + +\verb|Port | puerto usado por el servidor (3306 por defecto). + +El segundo argumento, y todos los siguientes, son considerados como sentencias SQL. + +Las sentencias SQL se pueden extender sobre múltiples argumentos. Si el último carácter de un argumento es un punto y coma, este indica el final de una sentencia SQL. + +Los argumentos de una sentencia SQL se concatenan separados por espacios. El eventual punto y coma final será removido. + +Todas las sentencias SQL, excepto la última, se ejecutarán directamente. + +Para table-IN, la última sentencia SQL puede ser un comando SELECT que empieza con \verb|'SELECT '| en letras mayúsculas. Si la cadena no se inicia con \verb|'SELECT '|, se considera que es un nombre de tabla y automáticamente se genera una sentencia SELECT. + +Para table-OUT, la última sentencia SQL puede contener uno o múltiples signos de interrogación. Si contiene un signo de interrogación, se considera como una plantilla para la rutina de escritura. De otro modo, la cadena es considerada un nombre de tabla y se genera automáticamente una plantilla INSERT. + +La rutina de escritura usa la plantilla con el signo de interrogación y reemplaza al primer signo de interrogación con el primer parámetro de salida, el segundo signo de interrogación con el segundo parámetro de salida y así sucesivamente. Luego se emite el comando SQL. + +El siguiente es un ejemplo de la sentencia table de salida: + +\newpage + +\begin{verbatim} +table ta { l in LOCALIDADES } OUT + 'MySQL' + 'Database=glpkdb;UID=glpkuser;PWD=glpkpassword' + 'DROP TABLE IF EXISTS resultados;' + 'CREATE TABLE resultados ( ID INT, LOC VARCHAR(255), CANT DOUBLE );' + 'INSERT INTO resultados VALUES ( 4, ?, ? )' : + l ~ LOC, cantidad[l] ~ CANT; +\end{verbatim} + +\noindent +Alternativamente, se puede escribir como sigue: + +\begin{verbatim} +table ta { l in LOCALIDADES } OUT + 'MySQL' + 'Database=glpkdb;UID=glpkuser;PWD=glpkpassword' + 'DROP TABLE IF EXISTS resultados;' + 'CREATE TABLE resultados ( ID INT, LOC VARCHAR(255), CANT DOUBLE );' + 'resultados' : + l ~ LOC, cantidad[l] ~ CANT, 4 ~ ID; +\end{verbatim} + +El uso de plantillas con `\verb|?|' no sólo permite INSERT, sino también UPDATE, DELETE, etc. Por ejemplo: + +\begin{verbatim} +table ta { l in LOCALIDADES } OUT + 'MySQL' + 'Database=glpkdb;UID=glpkuser;PWD=glpkpassword' + 'UPDATE resultados SET FECHA = ' & fecha & ' WHERE ID = 4;' + 'UPDATE resultados SET CANT = ? WHERE LOC = ? AND ID = 4' : + cantidad[l], l; +\end{verbatim} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\chapter{Solución de modelos con glpsol} + +El paquete GLPK\footnote{{\tt http://www.gnu.org/software/glpk/}} incluye el programa {\tt glpsol}, un {\it solver} autónomo de PL/PEM. Este programa puede ser invocado desde la línea de comando o desde el {\it shell} para resolver modelos escritos en el lenguaje de modelado GNU MathProg. + +Para comunicarle al solver que el archivo de entrada contiene una descripción del modelo, es necesario especificar la opción \verb|--model| en la línea de comando. Por ejemplo: + +\begin{verbatim} + glpsol --model foo.mod +\end{verbatim} + +A veces es necesario usar la sección de datos colocada en un archivo separado, en cuyo caso se debe usar el siguiente comando: + +\begin{verbatim} + glpsol --model foo.mod --data foo.dat +\end{verbatim} + +\noindent Debe notarse que, si el archivo del modelo también contiene una sección de datos, esta sección será ignorada. + +También se permite especificar más de un archivo conteniendo la sección de datos, por ejemplo: + +\begin{verbatim} + glpsol --model foo.mod --data foo1.dat --data foo2.dat +\end{verbatim} + +Si la descripción del modelo contiene algunas sentencias display y/o printf, por defecto la salida es enviada a la terminal. Si se necesita redirigir la salida a un archivo, se puede usar el siguiente comando: + +\begin{verbatim} + glpsol --model foo.mod --display foo.out +\end{verbatim} + +Si se necesita inspeccionar el problema, el cual ha sido generado por el traductor del modelo, se puede usar la opción \verb|--wlp| como sigue: + +\begin{verbatim} + glpsol --model foo.mod --wlp foo.lp +\end{verbatim} + +\noindent En este caso el problema se escribe en el archivo \verb|foo.lp|, en formato CPLEX LP apropiado para el análisis visual. + +\newpage + +A veces sólo se necesita chequear la descripción del modelo, sin resolver la instancia generada del problema. En este caso, se debe especificar la opción \verb|--check|, por ejemplo: + +\begin{verbatim} + glpsol --check --model foo.mod --wlp foo.lp +\end{verbatim} + +Si se necesita escribir una solución numérica obtenida por el solver en un archivo, se puede usar el siguiente comando: + +\begin{verbatim} + glpsol --model foo.mod --output foo.sol +\end{verbatim} + +\noindent en cuyo caso la solución se escribe en el archivo \verb|foo.sol| en formato de texto plano apropiado para el análisis visual. + +La lista completa de opciones de \verb|glpsol| se puede encontrar en el manual de referencia de GLPK incluido en la distribución de GLPK. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\chapter{Ejemplo de descripción del modelo} + +\section{Descripción del modelo escrita en MathProg} + +Abajo hay un ejemplo completo de la descripción de un modelo escrito en el lenguaje de modelado GNU MathProg. + +\bigskip + +\begin{verbatim} +# UN PROBLEMA DE TRANSPORTE +# +# Este problema encuentra la logística de costo mínimo de flete +# que cumple los requerimientos en los mercados y en las fábricas +# de suministro. +# +# Referencia: +# Dantzig G B. 1963. Linear Programming and Extensions. +# Princeton University Press, Princeton, New Jersey. +# Sección 3-3. + +set I; +/* plantas de enlatado */ + +set J; +/* mercados */ + +param a{i in I}; +/* producción de la planta i, en cajas */ + +param b{j in J}; +/* demanda en el mercado j, en cajas */ + +param d{i in I, j in J}; +/* distancia, en miles de millas */ + +param f; +/* flete, en dólares por caja cada mil millas */ + +param c{i in I, j in J} := f * d[i,j] / 1000; +/* costo de transporte, en miles de dólares por caja */ + +var x{i in I, j in J} >= 0; +/* cantidades despachadas, en cajas */ + +minimize costo: sum{i in I, j in J} c[i,j] * x[i,j]; +/* costo total de transporte, en miles de dólares */ + +s.t. suministro{i in I}: sum{j in J} x[i,j] <= a[i]; +/* observar el límite de suministro de la planta i */ + +s.t. demanda{j in J}: sum{i in I} x[i,j] >= b[j]; +/* satisfacer la demanda del mercado j */ + +data; + +set I := Seattle San-Diego; + +set J := New-York Chicago Topeka; + +param a := Seattle 350 + San-Diego 600; + +param b := New-York 325 + Chicago 300 + Topeka 275; + +param d : New-York Chicago Topeka := + Seattle 2.5 1.7 1.8 + San-Diego 2.5 1.8 1.4 ; + +param f := 90; + +end; +\end{verbatim} + +%\newpage + +\section{Instancia generada del problema de PL} + +Abajo está el resultado de la traducción del modelo de ejemplo producido por el solver \verb|glpsol|, con la opción \verb|--wlp| y escrita en el formato CPLEX LP. + +\medskip + +\begin{verbatim} +\* Problem: transporte *\ + +Minimize + costo: + 0.225 x(Seattle,New~York) + 0.153 x(Seattle,Chicago) + + 0.162 x(Seattle,Topeka) + 0.225 x(San~Diego,New~York) + + 0.162 x(San~Diego,Chicago) + 0.126 x(San~Diego,Topeka) + +Subject To + suministro(Seattle): + x(Seattle,New~York) + x(Seattle,Chicago) + + x(Seattle,Topeka) <= 350 + suministro(San~Diego): + x(San~Diego,New~York) + x(San~Diego,Chicago) + + x(San~Diego,Topeka) <= 600 + demanda(New~York): + x(Seattle,New~York) + x(San~Diego,New~York) >= 325 + demanda(Chicago): + x(Seattle,Chicago) + x(San~Diego,Chicago) >= 300 + demanda(Topeka): + x(Seattle,Topeka) + x(San~Diego,Topeka) >= 275 + +End +\end{verbatim} + +\section{Solución óptima del problema de PL} + +Abajo está la solución óptima de la instancia generada del problema de PL encontrada por el solver \verb|glpsol|, con la opción \verb|--output| y escrita en formato de texto plano. + +\medskip + +%\begin{footnotesize} +\begin{verbatim} +Problem: transporte +Rows: 6 +Columns: 6 +Non-zeros: 18 +Status: OPTIMAL +Objective: costo = 153.675 (MINimum) + + No. Row name St Activity Lower bound Upper bound Marginal +------ ------------ -- ------------- ------------- ------------- ------------- + 1 costo B 153.675 + 2 suministro[Seattle] + NU 350 350 < eps + 3 suministro[San-Diego] + B 550 600 + 4 demanda[New-York] + NL 325 325 0.225 + 5 demanda[Chicago] + NL 300 300 0.153 + 6 demanda[Topeka] + NL 275 275 0.126 + + No. Column name St Activity Lower bound Upper bound Marginal +------ ------------ -- ------------- ------------- ------------- ------------- + 1 x[Seattle,New-York] + B 50 0 + 2 x[Seattle,Chicago] + B 300 0 + 3 x[Seattle,Topeka] + NL 0 0 0.036 + 4 x[San-Diego,New-York] + B 275 0 + 5 x[San-Diego,Chicago] + NL 0 0 0.009 + 6 x[San-Diego,Topeka] + B 275 0 + +End of output +\end{verbatim} +%\end{footnotesize} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newpage + +\section*{Reconocimientos} +\addcontentsline{toc}{chapter}{Reconocimientos} + +Los autores desean agradecer a las siguientes personas, quienes amablemente leyeron, comentaron y corrigieron el borrador de este documento: + +\noindent Juan Carlos Borrás \verb|| + +\noindent Harley Mackenzie \verb|| + +\noindent Robbie Morrison \verb|| + +\end{document} diff --git a/resources/3rdparty/glpk-4.53/doc/graphs.pdf b/resources/3rdparty/glpk-4.57/doc/graphs.pdf similarity index 100% rename from resources/3rdparty/glpk-4.53/doc/graphs.pdf rename to resources/3rdparty/glpk-4.57/doc/graphs.pdf diff --git a/resources/3rdparty/glpk-4.53/doc/graphs.tex b/resources/3rdparty/glpk-4.57/doc/graphs.tex similarity index 100% rename from resources/3rdparty/glpk-4.53/doc/graphs.tex rename to resources/3rdparty/glpk-4.57/doc/graphs.tex diff --git a/resources/3rdparty/glpk-4.53/doc/miplib2.txt b/resources/3rdparty/glpk-4.57/doc/miplib2.txt similarity index 100% rename from resources/3rdparty/glpk-4.53/doc/miplib2.txt rename to resources/3rdparty/glpk-4.57/doc/miplib2.txt diff --git a/resources/3rdparty/glpk-4.53/doc/miplib3.txt b/resources/3rdparty/glpk-4.57/doc/miplib3.txt similarity index 100% rename from resources/3rdparty/glpk-4.53/doc/miplib3.txt rename to resources/3rdparty/glpk-4.57/doc/miplib3.txt diff --git a/resources/3rdparty/glpk-4.53/doc/netlib.txt b/resources/3rdparty/glpk-4.57/doc/netlib.txt similarity index 100% rename from resources/3rdparty/glpk-4.53/doc/netlib.txt rename to resources/3rdparty/glpk-4.57/doc/netlib.txt diff --git a/resources/3rdparty/glpk-4.53/doc/notes/dfeas.pdf b/resources/3rdparty/glpk-4.57/doc/notes/dfeas.pdf similarity index 100% rename from resources/3rdparty/glpk-4.53/doc/notes/dfeas.pdf rename to resources/3rdparty/glpk-4.57/doc/notes/dfeas.pdf diff --git a/resources/3rdparty/glpk-4.53/doc/notes/gomory.pdf b/resources/3rdparty/glpk-4.57/doc/notes/gomory.pdf similarity index 100% rename from resources/3rdparty/glpk-4.53/doc/notes/gomory.pdf rename to resources/3rdparty/glpk-4.57/doc/notes/gomory.pdf diff --git a/resources/3rdparty/glpk-4.53/doc/notes/keller.pdf b/resources/3rdparty/glpk-4.57/doc/notes/keller.pdf similarity index 100% rename from resources/3rdparty/glpk-4.53/doc/notes/keller.pdf rename to resources/3rdparty/glpk-4.57/doc/notes/keller.pdf diff --git a/resources/3rdparty/glpk-4.57/doc/notes/scf.pdf b/resources/3rdparty/glpk-4.57/doc/notes/scf.pdf new file mode 100644 index 000000000..da324f27f Binary files /dev/null and b/resources/3rdparty/glpk-4.57/doc/notes/scf.pdf differ diff --git a/resources/3rdparty/glpk-4.57/doc/notes/simplex1.pdf b/resources/3rdparty/glpk-4.57/doc/notes/simplex1.pdf new file mode 100644 index 000000000..828ad9970 Binary files /dev/null and b/resources/3rdparty/glpk-4.57/doc/notes/simplex1.pdf differ diff --git a/resources/3rdparty/glpk-4.57/doc/notes/simplex2.pdf b/resources/3rdparty/glpk-4.57/doc/notes/simplex2.pdf new file mode 100644 index 000000000..a9c2878d6 Binary files /dev/null and b/resources/3rdparty/glpk-4.57/doc/notes/simplex2.pdf differ diff --git a/resources/3rdparty/glpk-4.53/examples/INDEX b/resources/3rdparty/glpk-4.57/examples/INDEX similarity index 86% rename from resources/3rdparty/glpk-4.53/examples/INDEX rename to resources/3rdparty/glpk-4.57/examples/INDEX index 9647c7bc8..2eadbcd97 100644 --- a/resources/3rdparty/glpk-4.53/examples/INDEX +++ b/resources/3rdparty/glpk-4.57/examples/INDEX @@ -1,3 +1,4 @@ +alloy.mps Aluminium alloy blending assign.mod Assignment problem bpp.mod Bin packing problem cal.mod Print an ASCII calendar of the given year @@ -14,10 +15,12 @@ egypt.mod A static model for fertilizer production fctp.mod Fixed-charge transportation problem food.mod Food manufacture model food2.mod Food manufacture model +furnace.mps Electric-arc furnace steelmaking gap.mod Generalized assignment problem graph.mod Graph visualization hashi.mod A solver for the Japanese number-puzzle Hashiwokakero huge.mod Arithmetic mean of a large number of integers +icecream.mps Ice cream blending jssp.mod Job-shop scheduling problem magic.mod Magic square maxcut.mod Maximum cut problem @@ -27,15 +30,18 @@ mfvsp.mod Minimum feedback vertex set problem min01ks.mod Finding minimal equivalent 0-1 knapsack inequality misp.mod Maximum independent set problem money.mod A crypto-arithmetic puzzle +murtagh.mps Oil refinery model mvcp.mod Minimum vertex cover problem numbrix.mod Number placement puzzle pbn/*.* Paint-by-numbers puzzle -plan.mod A simple LP problem +plan.lp A simple LP problem (CPLEX LP format) +plan.mod A simple LP problem (MathProg format) +plan.mps A simple LP problem (MPS format) prod.mod A multiperiod production model qfit.mod Quadratic curve fitting solution queens.mod A classic combinatorial optimization problem sat.mod Satisfiability problem -shiftcover.mod Workforce shift coverage assignment problem +shiftcov.mod Workforce shift coverage assignment problem shikaku.mod A solver for the logic puzzle Shikaku sorting.mod How to sort arrays in MathProg spp.mod Shortest path problem diff --git a/resources/3rdparty/glpk-4.53/examples/Makefile.am b/resources/3rdparty/glpk-4.57/examples/Makefile.am similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/Makefile.am rename to resources/3rdparty/glpk-4.57/examples/Makefile.am diff --git a/resources/3rdparty/glpk-4.53/examples/Makefile.in b/resources/3rdparty/glpk-4.57/examples/Makefile.in similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/Makefile.in rename to resources/3rdparty/glpk-4.57/examples/Makefile.in diff --git a/resources/3rdparty/glpk-4.57/examples/alloy.mps b/resources/3rdparty/glpk-4.57/examples/alloy.mps new file mode 100644 index 000000000..9f774f165 --- /dev/null +++ b/resources/3rdparty/glpk-4.57/examples/alloy.mps @@ -0,0 +1,282 @@ +*NAME: ALLOY +*ROWS: 22 +*COLUMNS: 20 +*NONZERO: 203 +*OPT SOLN: 2149.247891 +*SOURCE: Linear Programming--Aluminium Alloy Blending +* Data Processing Application. N.Y.: IBM Corp. +*APPLICATION: Aluminium Alloy Blending +*COMMENTS: fixed MPS format +* encoded by Andrew Makhorin +* +NAME ALLOY +ROWS + N COST $ Cost $ + G ZN $ Zinc Minimum lbs + L ZX $ Zinc Maximum lbs + G CN $ Copper Minimum lbs + L CX $ Copper Maximum lbs + G MN $ Magnesium Minimum lbs + L MX $ Magnesium Maximum lbs + G CHN $ Chromium Minimum lbs + L CHX $ Chromium Maximum lbs + G BN $ Beryllium Minimum lbs + L BX $ Beryllium Maximum lbs + L IX $ Iron Maximum lbs + L SX $ Silicon Maximum lbs + L MGX $ Manganese Maximum lbs + L NX $ Nickel Maximum lbs + L TX $ Titanium Maximum lbs + L LX $ Lead Maximum lbs + L TNX $ Tin Maximum lbs + L BIX $ Bismuth Maximum lbs + L GX $ General Impurities lbs + L SCX $ Scrap 1 Limit lbs + G FL $ Furnance Load lbs +COLUMNS +* Pure Aluminium 1 + A1 COST .28 + IX .0004 + SX .0005 + FL 1.0 +* Pure Aluminium 2 + A2 COST .26 + IX .0006 + SX .0006 + FL 1.0 +* Pure Aluminium 3 + A3 COST .25 + IX .0011 + SX .0007 + FL 1.0 +* Pure Aluminium 4 + A4 COST .23 + IX .0026 + SX .0012 + FL 1.0 +* Pure Copper + C COST .31 + CN 1.00 + CX 1.00 + FL 1.0 +* Pure Magnesium + M COST .38 + MN 1.00 + MX 1.00 + FL 1.0 +* Beryllium/Aluminium Alloy + B/A COST 3.60 + BN 0.0600 + BX 0.0600 + FL 1.0 +* Pure Zinc + Z COST .22 + ZN .95 + ZX .95 + FL 1.0 +* Chromium Aluminium Alloy + C/A COST .27 + CHN .0300 + CHX .0300 + FL 1.0 +* Scrap 1 + SC1 COST .21 + ZN .0009 + ZX .0009 + CN .0444 + CX .0444 + MN .0042 + MX .0042 + CHN .0001 + CHX .0001 + IX .0024 + SX .0101 + MGX .0079 + NX .0001 + TX .0004 + LX .0001 + TNX .0001 + GX .0001 + SCX 1.00 + FL 1.0 +* Scrap 2 + SC2 COST .20 + ZN .0012 + ZX .0012 + CN .0026 + CX .0026 + MN .0060 + MX .0060 + CHN .0018 + CHX .0018 + IX .0026 + SX .0106 + MGX .0003 + NX .0002 + TX .0004 + LX .0001 + TNX .0001 + GX .0002 + FL 1.0 +* Scrap 3 + SC3 COST .21 + ZN .0568 + ZX .0568 + CN .0152 + CX .0152 + MN .0248 + MX .0248 + CHN .0020 + CHX .0020 + IX .0016 + SX .0013 + MGX .0005 + TX .0004 + LX .0003 + TNX .0003 + FL 1.0 +* Scrap 4 + SC4 COST .20 + ZN .0563 + ZX .0563 + CN .0149 + CX .0149 + MN .0238 + MX .0238 + CHN .0019 + CHX .0019 + IX .0019 + SX .0011 + MGX .0004 + TX .0004 + LX .0003 + TNX .0003 + FL 1.0 +* Scrap 5 + SC5 COST .21 + ZN .0460 + ZX .0460 + CN .0071 + CX .0071 + MN .0343 + MX .0343 + CHN .0013 + CHX .0013 + IX .0017 + SX .0013 + MGX .0018 + TX .0002 + LX .0002 + TNX .0002 + FL 1.0 +* Scrap 6 + SC6 COST .20 + ZN .0455 + ZX .0455 + CN .0071 + CX .0071 + MN .0343 + MX .0343 + IX .0016 + SX .0011 + MGX .0017 + TX .0002 + LX .0002 + TNX .0002 + FL 1.0 +* Scrap 7 + SC7 COST .21 + ZN .0009 + ZX .0009 + CN .0447 + CX .0447 + MN .0143 + MX .0143 + IX .0026 + SX .0013 + MGX .0052 + TX .0003 + LX .0001 + TNX .0001 + FL 1.0 +* Scrap 8 + SC8 COST .20 + ZN .0006 + ZX .0006 + CN .0623 + CX .0623 + IX .0017 + SX .0010 + MGX .0025 + TX .0005 + LX .0001 + TNX .0001 + GX .0025 + FL 1.0 +* Scrap 9 + SC9 COST .21 + ZN .0009 + ZX .0009 + CN .0034 + CX .0034 + MN .0093 + MX .0093 + CHN .0019 + CHX .0019 + IX .0030 + SX .0062 + MGX .0002 + TX .0003 + BIX .0005 + FL 1.0 +* Scrap 10 + SC10 COST .20 + ZN .0008 + ZX .0008 + CN .0003 + CX .0003 + MN .0249 + MX .0249 + CHN .0016 + CHX .0016 + IX .0015 + SX .0011 + MGX .0002 + FL 1.0 +* Scrap 11 + SC11 COST .21 + ZN .0675 + ZX .0675 + CN .0195 + CX .0195 + MN .0265 + MX .0265 + CHN .0020 + CHX .0020 + IX .0014 + SX .0008 + MGX .0002 + FL 1.0 +RHS + ZN 555. + ZX 590. + CN 140.0 + CX 190.0 + MN 245.0 + MX 275.0 + CHN 19.0 + CHX 22.0 + BN 2.0 + BX 4.0 + IX 15.0 + SX 10.0 + MGX 3.0 + NX 2.0 + TX 2.0 + LX 2.0 + TNX 2.0 + BIX 8.0 + GX 8.0 + SCX 900.0 + FL 10000. +ENDATA diff --git a/resources/3rdparty/glpk-4.53/examples/assign.mod b/resources/3rdparty/glpk-4.57/examples/assign.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/assign.mod rename to resources/3rdparty/glpk-4.57/examples/assign.mod diff --git a/resources/3rdparty/glpk-4.53/examples/bpp.mod b/resources/3rdparty/glpk-4.57/examples/bpp.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/bpp.mod rename to resources/3rdparty/glpk-4.57/examples/bpp.mod diff --git a/resources/3rdparty/glpk-4.53/examples/cal.mod b/resources/3rdparty/glpk-4.57/examples/cal.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/cal.mod rename to resources/3rdparty/glpk-4.57/examples/cal.mod diff --git a/resources/3rdparty/glpk-4.53/examples/cf12a.mod b/resources/3rdparty/glpk-4.57/examples/cf12a.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/cf12a.mod rename to resources/3rdparty/glpk-4.57/examples/cf12a.mod diff --git a/resources/3rdparty/glpk-4.53/examples/cf12b.mod b/resources/3rdparty/glpk-4.57/examples/cf12b.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/cf12b.mod rename to resources/3rdparty/glpk-4.57/examples/cf12b.mod diff --git a/resources/3rdparty/glpk-4.53/examples/cflsq.mod b/resources/3rdparty/glpk-4.57/examples/cflsq.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/cflsq.mod rename to resources/3rdparty/glpk-4.57/examples/cflsq.mod diff --git a/resources/3rdparty/glpk-4.53/examples/color.mod b/resources/3rdparty/glpk-4.57/examples/color.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/color.mod rename to resources/3rdparty/glpk-4.57/examples/color.mod diff --git a/resources/3rdparty/glpk-4.53/examples/cplex/README b/resources/3rdparty/glpk-4.57/examples/cplex/README similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/cplex/README rename to resources/3rdparty/glpk-4.57/examples/cplex/README diff --git a/resources/3rdparty/glpk-4.53/examples/cplex/concorde.txt b/resources/3rdparty/glpk-4.57/examples/cplex/concorde.txt similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/cplex/concorde.txt rename to resources/3rdparty/glpk-4.57/examples/cplex/concorde.txt diff --git a/resources/3rdparty/glpk-4.53/examples/cplex/cplex.c b/resources/3rdparty/glpk-4.57/examples/cplex/cplex.c similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/cplex/cplex.c rename to resources/3rdparty/glpk-4.57/examples/cplex/cplex.c diff --git a/resources/3rdparty/glpk-4.53/examples/cplex/cplex.h b/resources/3rdparty/glpk-4.57/examples/cplex/cplex.h similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/cplex/cplex.h rename to resources/3rdparty/glpk-4.57/examples/cplex/cplex.h diff --git a/resources/3rdparty/glpk-4.53/examples/cpp.mod b/resources/3rdparty/glpk-4.57/examples/cpp.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/cpp.mod rename to resources/3rdparty/glpk-4.57/examples/cpp.mod diff --git a/resources/3rdparty/glpk-4.53/examples/crypto.mod b/resources/3rdparty/glpk-4.57/examples/crypto.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/crypto.mod rename to resources/3rdparty/glpk-4.57/examples/crypto.mod diff --git a/resources/3rdparty/glpk-4.53/examples/csv/distances.csv b/resources/3rdparty/glpk-4.57/examples/csv/distances.csv similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/csv/distances.csv rename to resources/3rdparty/glpk-4.57/examples/csv/distances.csv diff --git a/resources/3rdparty/glpk-4.53/examples/csv/markets.csv b/resources/3rdparty/glpk-4.57/examples/csv/markets.csv similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/csv/markets.csv rename to resources/3rdparty/glpk-4.57/examples/csv/markets.csv diff --git a/resources/3rdparty/glpk-4.53/examples/csv/parameters.csv b/resources/3rdparty/glpk-4.57/examples/csv/parameters.csv similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/csv/parameters.csv rename to resources/3rdparty/glpk-4.57/examples/csv/parameters.csv diff --git a/resources/3rdparty/glpk-4.53/examples/csv/plants.csv b/resources/3rdparty/glpk-4.57/examples/csv/plants.csv similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/csv/plants.csv rename to resources/3rdparty/glpk-4.57/examples/csv/plants.csv diff --git a/resources/3rdparty/glpk-4.53/examples/csv/transp_csv.mod b/resources/3rdparty/glpk-4.57/examples/csv/transp_csv.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/csv/transp_csv.mod rename to resources/3rdparty/glpk-4.57/examples/csv/transp_csv.mod diff --git a/resources/3rdparty/glpk-4.53/examples/dbf/ForestMgt_Model_I_GIS_dbf.mod b/resources/3rdparty/glpk-4.57/examples/dbf/ForestMgt_Model_I_GIS_dbf.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/dbf/ForestMgt_Model_I_GIS_dbf.mod rename to resources/3rdparty/glpk-4.57/examples/dbf/ForestMgt_Model_I_GIS_dbf.mod diff --git a/resources/3rdparty/glpk-4.53/examples/dbf/Forest_Cost.dbf b/resources/3rdparty/glpk-4.57/examples/dbf/Forest_Cost.dbf similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/dbf/Forest_Cost.dbf rename to resources/3rdparty/glpk-4.57/examples/dbf/Forest_Cost.dbf diff --git a/resources/3rdparty/glpk-4.53/examples/dbf/NetRev_Table.dbf b/resources/3rdparty/glpk-4.57/examples/dbf/NetRev_Table.dbf similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/dbf/NetRev_Table.dbf rename to resources/3rdparty/glpk-4.57/examples/dbf/NetRev_Table.dbf diff --git a/resources/3rdparty/glpk-4.53/examples/dbf/README b/resources/3rdparty/glpk-4.57/examples/dbf/README similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/dbf/README rename to resources/3rdparty/glpk-4.57/examples/dbf/README diff --git a/resources/3rdparty/glpk-4.53/examples/dbf/TCost_Table.dbf b/resources/3rdparty/glpk-4.57/examples/dbf/TCost_Table.dbf similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/dbf/TCost_Table.dbf rename to resources/3rdparty/glpk-4.57/examples/dbf/TCost_Table.dbf diff --git a/resources/3rdparty/glpk-4.53/examples/dbf/Yield_Table_Vol.dbf b/resources/3rdparty/glpk-4.57/examples/dbf/Yield_Table_Vol.dbf similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/dbf/Yield_Table_Vol.dbf rename to resources/3rdparty/glpk-4.57/examples/dbf/Yield_Table_Vol.dbf diff --git a/resources/3rdparty/glpk-4.53/examples/dbf/cultural_pres.dbf b/resources/3rdparty/glpk-4.57/examples/dbf/cultural_pres.dbf similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/dbf/cultural_pres.dbf rename to resources/3rdparty/glpk-4.57/examples/dbf/cultural_pres.dbf diff --git a/resources/3rdparty/glpk-4.53/examples/dbf/mgt_year.dbf b/resources/3rdparty/glpk-4.57/examples/dbf/mgt_year.dbf similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/dbf/mgt_year.dbf rename to resources/3rdparty/glpk-4.57/examples/dbf/mgt_year.dbf diff --git a/resources/3rdparty/glpk-4.53/examples/dbf/stands.dbf b/resources/3rdparty/glpk-4.57/examples/dbf/stands.dbf similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/dbf/stands.dbf rename to resources/3rdparty/glpk-4.57/examples/dbf/stands.dbf diff --git a/resources/3rdparty/glpk-4.53/examples/dbf/standtype.dbf b/resources/3rdparty/glpk-4.57/examples/dbf/standtype.dbf similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/dbf/standtype.dbf rename to resources/3rdparty/glpk-4.57/examples/dbf/standtype.dbf diff --git a/resources/3rdparty/glpk-4.53/examples/dea.mod b/resources/3rdparty/glpk-4.57/examples/dea.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/dea.mod rename to resources/3rdparty/glpk-4.57/examples/dea.mod diff --git a/resources/3rdparty/glpk-4.53/examples/diet.mod b/resources/3rdparty/glpk-4.57/examples/diet.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/diet.mod rename to resources/3rdparty/glpk-4.57/examples/diet.mod diff --git a/resources/3rdparty/glpk-4.53/examples/dist.mod b/resources/3rdparty/glpk-4.57/examples/dist.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/dist.mod rename to resources/3rdparty/glpk-4.57/examples/dist.mod diff --git a/resources/3rdparty/glpk-4.53/examples/egypt.mod b/resources/3rdparty/glpk-4.57/examples/egypt.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/egypt.mod rename to resources/3rdparty/glpk-4.57/examples/egypt.mod diff --git a/resources/3rdparty/glpk-4.53/examples/fctp.mod b/resources/3rdparty/glpk-4.57/examples/fctp.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/fctp.mod rename to resources/3rdparty/glpk-4.57/examples/fctp.mod diff --git a/resources/3rdparty/glpk-4.53/examples/food.mod b/resources/3rdparty/glpk-4.57/examples/food.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/food.mod rename to resources/3rdparty/glpk-4.57/examples/food.mod diff --git a/resources/3rdparty/glpk-4.53/examples/food2.mod b/resources/3rdparty/glpk-4.57/examples/food2.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/food2.mod rename to resources/3rdparty/glpk-4.57/examples/food2.mod diff --git a/resources/3rdparty/glpk-4.57/examples/furnace.mps b/resources/3rdparty/glpk-4.57/examples/furnace.mps new file mode 100644 index 000000000..b89b7acbd --- /dev/null +++ b/resources/3rdparty/glpk-4.57/examples/furnace.mps @@ -0,0 +1,164 @@ +*NAME: FURNACE +*ROWS: 18 +*COLUMNS: 18 +*NONZERO: 90 +*OPT SOLN: 2141.923551 +*SOURCE: Linear Programming--Electric-Arc Furnace Steelmaking +* Data Processing Application. N.Y.: IBM Corp. +*APPLICATION: Electric-Arc Furnace Steelmaking +*COMMENTS: fixed MPS format +* encoded by Andrew Makhorin +* +NAME FURNACE +ROWS + N VALUE $ Price per pound (of initial charge materials) + E CR $ Chromium + E MN $ Manganese + E SI $ Silicon + E C $ Carbon + E FE $ Iron + E TOTCHG $ Total elements charged + E CRSLAG $ Chromium-oxidized-to-slag relationship + E TOTCRS $ Total modified chromium specification constraint + E MN/CR $ Total manganese specification constraint + E FESLAG $ Iron-oxidized-to-slag relationship + G ENDFE $ Total iron specification constraint + L CSPEC $ Total carbon specification constraint + E BASE $ Basicity relationship + L SISPEC $ Total silicon specification constraint + G TOTAL $ Total end metal + L TOTRS4 $ Inventory limitation on 430 grade scrap + L TOTRCF $ Inventory limitation on low-carbon ferrochrome +COLUMNS +* Steel scrap + STSCP VALUE .02 + CR 0 + MN .01 + SI .002 + C .006 + FE .982 +* 430 grade scrap + SP430 VALUE .075 + CR .16 + MN .01 + SI .0095 + C .0012 + FE .8143 + TOTRS4 1 +* High-carbon ferrochrome + HCFCR VALUE .27 + CR .556 + MN 0 + SI .02 + C .08 + FE .334 +* Low-carbon ferrochrome + LCFCR VALUE .40 + CR .65 + MN 0 + SI .01 + C .0009 + FE .3391 + TOTRCF 1 +* Chromium initially charged + CRIT VALUE 0 + CR -1 + TOTCHG 1 + CRSLAG 1 +* Manganese initially charged + MNIT VALUE 0 + MN -1 + TOTCHG 1 + CRSLAG 1 + MN/CR .98 +* Silicon initially charged + SIIT VALUE 0 + SI -1 + TOTCHG 1 + CSPEC -5 + BASE 2.14 + TOTAL -1 +* Carbon initially charged + CEIT VALUE 0 + C -1 + TOTCHG 1 + TOTAL -1 +* Iron initially charged + FEIT VALUE 0 + FE -1 + TOTCHG 1 + ENDFE 1 +* Total initial charge weight + TICW VALUE 0 + TOTCHG -1 + CRSLAG -.074 + TOTCRS .074 + FESLAG .075 + CSPEC 5 + TOTAL 1 +* Modified chromium in the slag + ISCR VALUE 0 + CRSLAG -1 + TOTCRS .95 + FESLAG -1 + CSPEC -.25 + SISPEC -.395 + TOTAL -.05 +* Chrome silicide additive at refining stage + CRSI VALUE .27 + TOTCRS .39 + ENDFE .18 + BASE 2.7606 + SISPEC .43 + TOTAL .57 +* 430 grade scrap at refining stage + RS430 VALUE .075 + TOTCRS .17 + MN/CR .01 + ENDFE .8143 + CSPEC 12 + SISPEC .0095 + TOTAL 1 + TOTRS4 1 +* Low-carbon ferrochrome at refining stage + RCFCR VALUE .40 + TOTCRS .65 + ENDFE .3391 + CSPEC 9 + SISPEC .01 + TOTAL 1 + TOTRCF 1 +* Iron in the slag + ISFE VALUE 0 + FESLAG -1 + ENDFE -.05 + CSPEC -.25 + SISPEC -.238 + TOTAL -.05 +* Lime at refining stage + LIME VALUE .01 + BASE -2 +* Low-carbon ferrochrome at finishing stage + FCFCR VALUE .40 + TOTCRS .65 + ENDFE .3391 + CSPEC 9 + SISPEC .01 + TOTAL 1 + TOTRCF 1 +* Slack in the chromium and manganese specifications + SIS VALUE 0 + TOTCRS 1 + MN/CR 1 +RHS + TOTCRS 3400 + MN/CR 200 + ENDFE 16200 + CSPEC 100000 + SISPEC 200 + TOTAL 20000 + TOTRS4 2000 + TOTRCF 2000 +BOUNDS + UP HCFCR 2000 +ENDATA diff --git a/resources/3rdparty/glpk-4.53/examples/gap.mod b/resources/3rdparty/glpk-4.57/examples/gap.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/gap.mod rename to resources/3rdparty/glpk-4.57/examples/gap.mod diff --git a/resources/3rdparty/glpk-4.53/examples/glpsol.c b/resources/3rdparty/glpk-4.57/examples/glpsol.c similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/glpsol.c rename to resources/3rdparty/glpk-4.57/examples/glpsol.c diff --git a/resources/3rdparty/glpk-4.53/examples/graph.mod b/resources/3rdparty/glpk-4.57/examples/graph.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/graph.mod rename to resources/3rdparty/glpk-4.57/examples/graph.mod diff --git a/resources/3rdparty/glpk-4.53/examples/hashi.mod b/resources/3rdparty/glpk-4.57/examples/hashi.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/hashi.mod rename to resources/3rdparty/glpk-4.57/examples/hashi.mod diff --git a/resources/3rdparty/glpk-4.53/examples/huge.mod b/resources/3rdparty/glpk-4.57/examples/huge.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/huge.mod rename to resources/3rdparty/glpk-4.57/examples/huge.mod diff --git a/resources/3rdparty/glpk-4.57/examples/icecream.mps b/resources/3rdparty/glpk-4.57/examples/icecream.mps new file mode 100644 index 000000000..5d741306d --- /dev/null +++ b/resources/3rdparty/glpk-4.57/examples/icecream.mps @@ -0,0 +1,345 @@ +*NAME: ICECREAM +*ROWS: 17 +*COLUMNS: 27 +*NONZERO: 264 +*OPT SOLN: 962.8214691 +*SOURCE: Linear Programming--Ice Cream Blending +* Data Processing Application. N.Y.: IBM Corp. +*APPLICATION: Ice Cream Blending +*COMMENTS: fixed MPS format +* encoded by Andrew Makhorin +* +NAME ICECREAM +ROWS + N COST $ Minimum cost $ + G MIN.BF $ Butterfat lbs + L MAX.BF + G MIN.MSNF $ Milk solids (nonfat) lbs + L MAX.MSNF + G MIN.TMS $ Total milk solids lbs + L MAX.TMS + G MIN.SUG $ Sweetness lbs + L MAX.SUG + L CSS $ Corn syrup solids lbs + G MIN.TS $ Total solids lbs + L MAX.TS + G MIN.H2O $ Water lbs + L MAX.H2O + E STAB $ Stabilizer lbs + E EMUL $ Emulsifier lbs + E YIELD $ Amount to be made lbs +COLUMNS +* Cream (40%) + I1 COST 27.9 + MIN.BF .40 + MAX.BF .40 + MIN.MSNF .054 + MAX.MSNF .054 + MIN.TMS .454 + MAX.TMS .454 + MIN.TS .454 + MAX.TS .454 + MIN.H2O .546 + MAX.H2O .546 + YIELD 1 +* Cream (38%) + I2 COST 26.3 + MIN.BF .38 + MAX.BF .38 + MIN.MSNF .056 + MAX.MSNF .056 + MIN.TMS .436 + MAX.TMS .436 + MIN.TS .436 + MAX.TS .436 + MIN.H2O .564 + MAX.H2O .564 + YIELD 1 +* Milk (3.2%) + I3 COST 3.2 + MIN.BF .032 + MAX.BF .032 + MIN.MSNF .087 + MAX.MSNF .087 + MIN.TMS .119 + MAX.TMS .119 + MIN.TS .119 + MAX.TS .119 + MIN.H2O .881 + MAX.H2O .881 + YIELD 1 +* Milk (3.4%) + I4 COST 3.2 + MIN.BF .034 + MAX.BF .034 + MIN.MSNF .087 + MAX.MSNF .087 + MIN.TMS .121 + MAX.TMS .121 + MIN.TS .121 + MAX.TS .121 + MIN.H2O .879 + MAX.H2O .879 + YIELD 1 +* Milk (3.5%) + I5 COST 3.3 + MIN.BF .035 + MAX.BF .035 + MIN.MSNF .087 + MAX.MSNF .087 + MIN.TMS .122 + MAX.TMS .122 + MIN.TS .122 + MAX.TS .122 + MIN.H2O .879 + MAX.H2O .879 + YIELD 1 +* Milk (3.6%) + I6 COST 3.3 + MIN.BF .036 + MAX.BF .036 + MIN.MSNF .087 + MAX.MSNF .087 + MIN.TMS .123 + MAX.TMS .123 + MIN.TS .123 + MAX.TS .123 + MIN.H2O .877 + MAX.H2O .877 + YIELD 1 +* Milk (3.7%) + I7 COST 3.4 + MIN.BF .037 + MAX.BF .037 + MIN.MSNF .087 + MAX.MSNF .087 + MIN.TMS .124 + MAX.TMS .124 + MIN.TS .124 + MAX.TS .124 + MIN.H2O .876 + MAX.H2O .876 + YIELD 1 +* Milk (3.8%) + I8 COST 3.5 + MIN.BF .038 + MAX.BF .038 + MIN.MSNF .087 + MAX.MSNF .087 + MIN.TMS .125 + MAX.TMS .125 + MIN.TS .125 + MAX.TS .125 + MIN.H2O .875 + MAX.H2O .875 + YIELD 1 +* Milk (3.9%) + I9 COST 3.5 + MIN.BF .039 + MAX.BF .039 + MIN.MSNF .086 + MAX.MSNF .086 + MIN.TMS .125 + MAX.TMS .125 + MIN.TS .125 + MAX.TS .125 + MIN.H2O .875 + MAX.H2O .875 + YIELD 1 +* Milk (4.0%) + I10 COST 3.6 + MIN.BF .040 + MAX.BF .040 + MIN.MSNF .086 + MAX.MSNF .086 + MIN.TMS .126 + MAX.TMS .126 + MIN.TS .126 + MAX.TS .126 + MIN.H2O .874 + MAX.H2O .874 + YIELD 1 +* Milk (4.2%) + I11 COST 3.7 + MIN.BF .042 + MAX.BF .042 + MIN.MSNF .086 + MAX.MSNF .086 + MIN.TMS .128 + MAX.TMS .128 + MIN.TS .128 + MAX.TS .128 + MIN.H2O .872 + MAX.H2O .872 + YIELD 1 +* Skim Milk + I12 COST 1.8 + MIN.MSNF .09 + MAX.MSNF .09 + MIN.TMS .09 + MAX.TMS .09 + MIN.TS .09 + MAX.TS .09 + MIN.H2O .91 + MAX.H2O .91 + YIELD 1 +* Condensed Whole Milk + I13 COST 7.6 + MIN.BF .08 + MAX.BF .08 + MIN.MSNF .2 + MAX.MSNF .2 + MIN.TMS .28 + MAX.TMS .28 + MIN.TS .28 + MAX.TS .28 + MIN.H2O .72 + MAX.H2O .72 + YIELD 1 +* Condensed Skim Milk (28%) + I14 COST 3.9 + MIN.MSNF .28 + MAX.MSNF .28 + MIN.TMS .28 + MAX.TMS .28 + MIN.TS .28 + MAX.TS .28 + MIN.H2O .72 + MAX.H2O .72 + YIELD 1 +* Condensed Skim Milk (30%) + I15 COST 4.9 + MIN.MSNF .3 + MAX.MSNF .3 + MIN.TMS .3 + MAX.TMS .3 + MIN.TS .3 + MAX.TS .3 + MIN.H2O .7 + MAX.H2O .7 + YIELD 1 +* Condensed Skim Milk (32%) + I16 COST 4.5 + MIN.MSNF .32 + MAX.MSNF .32 + MIN.TMS .32 + MAX.TMS .32 + MIN.TS .32 + MAX.TS .32 + MIN.H2O .68 + MAX.H2O .68 + YIELD 1 +* Dry Skim Milk + I17 COST 14.8 + MIN.BF .01 + MAX.BF .01 + MIN.MSNF .96 + MAX.MSNF .96 + MIN.TMS .97 + MAX.TMS .97 + MIN.TS .97 + MAX.TS .97 + MIN.H2O .03 + MAX.H2O .03 + YIELD 1 +* Dry Buttermilk + I18 COST 15.0 + MIN.BF .05 + MAX.BF .05 + MIN.MSNF .92 + MAX.MSNF .92 + MIN.TMS .97 + MAX.TMS .97 + MIN.TS .97 + MAX.TS .97 + MIN.H2O .03 + MAX.H2O .03 + YIELD 1 +* Dry Whey Solids + I19 COST 10.7 + MIN.MSNF .95 + MAX.MSNF .95 + MIN.TMS .95 + MAX.TMS .95 + MIN.TS .95 + MAX.TS .95 + MIN.H2O .05 + MAX.H2O .05 + YIELD 1 +* Dry Sucrose + I20 COST 10.2 + MIN.SUG 1.0 + MAX.SUG 1.0 + MIN.TS 1.0 + MAX.TS 1.0 + YIELD 1 +* Cane Syrup + I21 COST 9.9 + MIN.SUG .67 + MAX.SUG .67 + MIN.TS .67 + MAX.TS .67 + MIN.H2O .33 + MAX.H2O .33 + YIELD 1 +* Corn Sgr. Solids (50% Sweetness) + I22 COST 7.0 + MIN.SUG .5 + MAX.SUG .5 + CSS 1.0 + MIN.TS 1.0 + MAX.TS 1.0 + YIELD 1 +* Corn Sgr. Solids (45% Sweetness) + I23 COST 9.0 + MIN.SUG .45 + MAX.SUG .45 + CSS 1.0 + MIN.TS 1.0 + MAX.TS 1.0 + YIELD 1 +* Corn Syrup + I24 COST 6.6 + MIN.SUG .4 + MAX.SUG .4 + CSS .8 + MIN.TS .8 + MAX.TS .8 + MIN.H2O .2 + MAX.H2O .2 + YIELD 1 +* Stabilizer + I25 COST 55.0 + STAB 1.0 + YIELD 1 +* Emulsifier + I26 COST 78.0 + EMUL 1.0 + YIELD 1 +* Water + I27 COST 0 + MIN.H2O 1.0 + MAX.H2O 1.0 + YIELD 1 +RHS + MIN.BF 10 + MAX.BF 16 + MIN.MSNF 10.5 + MAX.MSNF 13 + MIN.TMS 20.5 + MAX.TMS 25 + MIN.SUG 11 + MAX.SUG 17 + CSS 6 + MIN.TS 37.5 + MAX.TS 41.5 + MIN.H2O 58.5 + MAX.H2O 62.5 + STAB .37 + EMUL .01 + YIELD 100 +BOUNDS + UP I1 10 + LO I6 40 + UP I19 4 +ENDATA diff --git a/resources/3rdparty/glpk-4.53/examples/iptsamp.c b/resources/3rdparty/glpk-4.57/examples/iptsamp.c similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/iptsamp.c rename to resources/3rdparty/glpk-4.57/examples/iptsamp.c diff --git a/resources/3rdparty/glpk-4.53/examples/jssp.mod b/resources/3rdparty/glpk-4.57/examples/jssp.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/jssp.mod rename to resources/3rdparty/glpk-4.57/examples/jssp.mod diff --git a/resources/3rdparty/glpk-4.53/examples/magic.mod b/resources/3rdparty/glpk-4.57/examples/magic.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/magic.mod rename to resources/3rdparty/glpk-4.57/examples/magic.mod diff --git a/resources/3rdparty/glpk-4.53/examples/maxcut.mod b/resources/3rdparty/glpk-4.57/examples/maxcut.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/maxcut.mod rename to resources/3rdparty/glpk-4.57/examples/maxcut.mod diff --git a/resources/3rdparty/glpk-4.53/examples/maxflow.mod b/resources/3rdparty/glpk-4.57/examples/maxflow.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/maxflow.mod rename to resources/3rdparty/glpk-4.57/examples/maxflow.mod diff --git a/resources/3rdparty/glpk-4.53/examples/mfasp.mod b/resources/3rdparty/glpk-4.57/examples/mfasp.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/mfasp.mod rename to resources/3rdparty/glpk-4.57/examples/mfasp.mod diff --git a/resources/3rdparty/glpk-4.53/examples/mfvsp.mod b/resources/3rdparty/glpk-4.57/examples/mfvsp.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/mfvsp.mod rename to resources/3rdparty/glpk-4.57/examples/mfvsp.mod diff --git a/resources/3rdparty/glpk-4.53/examples/min01ks.mod b/resources/3rdparty/glpk-4.57/examples/min01ks.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/min01ks.mod rename to resources/3rdparty/glpk-4.57/examples/min01ks.mod diff --git a/resources/3rdparty/glpk-4.53/examples/misp.mod b/resources/3rdparty/glpk-4.57/examples/misp.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/misp.mod rename to resources/3rdparty/glpk-4.57/examples/misp.mod diff --git a/resources/3rdparty/glpk-4.53/examples/misp1.dat b/resources/3rdparty/glpk-4.57/examples/misp1.dat similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/misp1.dat rename to resources/3rdparty/glpk-4.57/examples/misp1.dat diff --git a/resources/3rdparty/glpk-4.53/examples/misp2.dat b/resources/3rdparty/glpk-4.57/examples/misp2.dat similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/misp2.dat rename to resources/3rdparty/glpk-4.57/examples/misp2.dat diff --git a/resources/3rdparty/glpk-4.53/examples/money.mod b/resources/3rdparty/glpk-4.57/examples/money.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/money.mod rename to resources/3rdparty/glpk-4.57/examples/money.mod diff --git a/resources/3rdparty/glpk-4.53/examples/mplsamp1.c b/resources/3rdparty/glpk-4.57/examples/mplsamp1.c similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/mplsamp1.c rename to resources/3rdparty/glpk-4.57/examples/mplsamp1.c diff --git a/resources/3rdparty/glpk-4.53/examples/mplsamp2.c b/resources/3rdparty/glpk-4.57/examples/mplsamp2.c similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/mplsamp2.c rename to resources/3rdparty/glpk-4.57/examples/mplsamp2.c diff --git a/resources/3rdparty/glpk-4.53/examples/murtagh.mps b/resources/3rdparty/glpk-4.57/examples/murtagh.mps similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/murtagh.mps rename to resources/3rdparty/glpk-4.57/examples/murtagh.mps diff --git a/resources/3rdparty/glpk-4.53/examples/mvcp.mod b/resources/3rdparty/glpk-4.57/examples/mvcp.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/mvcp.mod rename to resources/3rdparty/glpk-4.57/examples/mvcp.mod diff --git a/resources/3rdparty/glpk-4.53/examples/netgen.c b/resources/3rdparty/glpk-4.57/examples/netgen.c similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/netgen.c rename to resources/3rdparty/glpk-4.57/examples/netgen.c diff --git a/resources/3rdparty/glpk-4.53/examples/numbrix.mod b/resources/3rdparty/glpk-4.57/examples/numbrix.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/numbrix.mod rename to resources/3rdparty/glpk-4.57/examples/numbrix.mod diff --git a/resources/3rdparty/glpk-4.53/examples/oldapi/README b/resources/3rdparty/glpk-4.57/examples/oldapi/README similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/oldapi/README rename to resources/3rdparty/glpk-4.57/examples/oldapi/README diff --git a/resources/3rdparty/glpk-4.53/examples/oldapi/lpx.c b/resources/3rdparty/glpk-4.57/examples/oldapi/lpx.c similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/oldapi/lpx.c rename to resources/3rdparty/glpk-4.57/examples/oldapi/lpx.c diff --git a/resources/3rdparty/glpk-4.53/examples/oldapi/lpx.h b/resources/3rdparty/glpk-4.57/examples/oldapi/lpx.h similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/oldapi/lpx.h rename to resources/3rdparty/glpk-4.57/examples/oldapi/lpx.h diff --git a/resources/3rdparty/glpk-4.53/examples/oldapi/lpxsamp.c b/resources/3rdparty/glpk-4.57/examples/oldapi/lpxsamp.c similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/oldapi/lpxsamp.c rename to resources/3rdparty/glpk-4.57/examples/oldapi/lpxsamp.c diff --git a/resources/3rdparty/glpk-4.53/examples/pbn/9dom.dat b/resources/3rdparty/glpk-4.57/examples/pbn/9dom.dat similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/pbn/9dom.dat rename to resources/3rdparty/glpk-4.57/examples/pbn/9dom.dat diff --git a/resources/3rdparty/glpk-4.53/examples/pbn/README b/resources/3rdparty/glpk-4.57/examples/pbn/README similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/pbn/README rename to resources/3rdparty/glpk-4.57/examples/pbn/README diff --git a/resources/3rdparty/glpk-4.53/examples/pbn/bucks.dat b/resources/3rdparty/glpk-4.57/examples/pbn/bucks.dat similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/pbn/bucks.dat rename to resources/3rdparty/glpk-4.57/examples/pbn/bucks.dat diff --git a/resources/3rdparty/glpk-4.53/examples/pbn/cat.dat b/resources/3rdparty/glpk-4.57/examples/pbn/cat.dat similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/pbn/cat.dat rename to resources/3rdparty/glpk-4.57/examples/pbn/cat.dat diff --git a/resources/3rdparty/glpk-4.53/examples/pbn/dancer.dat b/resources/3rdparty/glpk-4.57/examples/pbn/dancer.dat similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/pbn/dancer.dat rename to resources/3rdparty/glpk-4.57/examples/pbn/dancer.dat diff --git a/resources/3rdparty/glpk-4.57/examples/pbn/disney.dat b/resources/3rdparty/glpk-4.57/examples/pbn/disney.dat new file mode 100644 index 000000000..2eab1fe2d --- /dev/null +++ b/resources/3rdparty/glpk-4.57/examples/pbn/disney.dat @@ -0,0 +1,115 @@ +/* disney.dat */ + +data; + +param m := 50; + +param n := 50; + +param row : 1 2 3 4 5 6 7 := + 1 8 . . . . . . + 2 7 15 . . . . . + 3 2 2 19 . . . . + 4 1 2 16 1 2 . . + 5 1 5 14 1 . . . + 6 2 4 13 1 1 . . + 7 6 12 5 . . . . + 8 1 5 6 11 . . . + 9 1 4 5 4 8 . . + 10 1 4 1 18 . . . + 11 1 5 2 11 4 . . + 12 1 8 2 6 3 . . + 13 1 7 1 3 2 . . + 14 1 13 2 . . . . + 15 1 12 1 . . . . + 16 1 2 7 4 2 . . + 17 2 3 4 2 . . . + 18 5 4 3 1 . . . + 19 8 4 3 1 . . . + 20 10 3 2 1 . . . + 21 12 1 1 . . . . + 22 13 1 1 1 . . . + 23 15 1 1 3 . . . + 24 3 5 5 1 2 1 . + 25 4 5 5 2 4 2 . + 26 3 3 5 1 1 2 1 + 27 3 3 2 4 2 2 . + 28 2 3 2 3 3 2 . + 29 2 4 3 3 5 . . + 30 2 7 4 1 4 3 . + 31 3 13 1 4 5 . . + 32 9 4 1 4 7 6 1 + 33 8 1 1 2 1 15 . + 34 6 6 3 1 1 6 6 + 35 6 3 8 1 2 6 6 + 36 2 5 13 3 1 . . + 37 5 1 11 3 4 . . + 38 9 8 4 3 . . . + 39 9 6 3 10 3 . . + 40 10 5 3 2 2 3 . + 41 10 6 3 2 10 . . + 42 10 4 2 1 9 . . + 43 11 3 2 2 4 . . + 44 11 2 2 1 1 2 3 + 45 8 2 2 2 8 . . + 46 5 1 2 2 4 4 . + 47 6 2 2 2 3 4 . + 48 8 2 2 2 3 3 . + 49 10 2 4 3 1 5 4 + 50 12 7 7 4 7 . . +; + +param col : 1 2 3 4 5 6 7 8 9 10 := + 1 14 . . . . . . . . . + 2 9 15 . . . . . . . . + 3 28 . . . . . . . . . + 4 7 5 14 . . . . . . . + 5 6 4 14 . . . . . . . + 6 5 5 8 4 . . . . . . + 7 7 6 8 3 . . . . . . + 8 19 8 3 . . . . . . . + 9 16 9 2 . . . . . . . + 10 15 2 5 2 . . . . . . + 11 8 3 1 3 1 . . . . . + 12 4 7 2 2 3 1 . . . . + 13 2 12 6 3 1 2 . . . . + 14 1 1 12 1 2 . . . . . + 15 1 4 9 2 1 2 . . . . + 16 1 6 5 6 1 . . . . . + 17 1 7 5 3 5 1 1 . . . + 18 1 8 8 6 2 1 . . . . + 19 2 1 7 5 9 1 . . . . + 20 2 2 7 6 9 1 . . . . + 21 6 15 9 2 . . . . . . + 22 7 5 4 14 1 . . . . . + 23 8 4 4 3 6 1 1 . . . + 24 9 5 2 7 3 2 3 . . . + 25 9 7 4 10 1 2 1 . . . + 26 8 2 4 2 5 2 2 2 1 . + 27 7 2 6 2 3 5 2 1 . . + 28 7 4 4 2 5 2 2 1 . . + 29 7 3 4 1 1 2 1 . . . + 30 7 3 4 1 2 2 2 . . . + 31 8 6 1 1 2 1 . . . . + 32 6 1 3 1 2 1 2 . . . + 33 4 1 3 2 2 1 2 2 . . + 34 4 1 3 1 3 1 2 2 2 . + 35 3 5 1 1 1 2 1 1 1 2 + 36 2 6 1 1 3 1 1 3 . . + 37 2 5 1 5 6 1 3 . . . + 38 2 6 2 6 3 2 . . . . + 39 1 4 2 6 2 2 1 . . . + 40 2 5 3 4 1 2 2 . . . + 41 3 7 3 1 10 . . . . . + 42 5 2 1 9 . . . . . . + 43 3 2 2 2 6 . . . . . + 44 2 1 1 2 3 2 . . . . + 45 4 2 2 2 1 . . . . . + 46 4 1 2 3 1 . . . . . + 47 4 1 1 2 3 2 . . . . + 48 6 4 6 . . . . . . . + 49 3 3 5 . . . . . . . + 50 3 2 3 . . . . . . . +; + +end; diff --git a/resources/3rdparty/glpk-4.53/examples/pbn/dragon.dat b/resources/3rdparty/glpk-4.57/examples/pbn/dragon.dat similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/pbn/dragon.dat rename to resources/3rdparty/glpk-4.57/examples/pbn/dragon.dat diff --git a/resources/3rdparty/glpk-4.53/examples/pbn/edge.dat b/resources/3rdparty/glpk-4.57/examples/pbn/edge.dat similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/pbn/edge.dat rename to resources/3rdparty/glpk-4.57/examples/pbn/edge.dat diff --git a/resources/3rdparty/glpk-4.53/examples/pbn/forever.dat b/resources/3rdparty/glpk-4.57/examples/pbn/forever.dat similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/pbn/forever.dat rename to resources/3rdparty/glpk-4.57/examples/pbn/forever.dat diff --git a/resources/3rdparty/glpk-4.53/examples/pbn/knot.dat b/resources/3rdparty/glpk-4.57/examples/pbn/knot.dat similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/pbn/knot.dat rename to resources/3rdparty/glpk-4.57/examples/pbn/knot.dat diff --git a/resources/3rdparty/glpk-4.53/examples/pbn/light.dat b/resources/3rdparty/glpk-4.57/examples/pbn/light.dat similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/pbn/light.dat rename to resources/3rdparty/glpk-4.57/examples/pbn/light.dat diff --git a/resources/3rdparty/glpk-4.53/examples/pbn/mum.dat b/resources/3rdparty/glpk-4.57/examples/pbn/mum.dat similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/pbn/mum.dat rename to resources/3rdparty/glpk-4.57/examples/pbn/mum.dat diff --git a/resources/3rdparty/glpk-4.53/examples/pbn/pbn.mod b/resources/3rdparty/glpk-4.57/examples/pbn/pbn.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/pbn/pbn.mod rename to resources/3rdparty/glpk-4.57/examples/pbn/pbn.mod diff --git a/resources/3rdparty/glpk-4.53/examples/pbn/pbn.pdf b/resources/3rdparty/glpk-4.57/examples/pbn/pbn.pdf similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/pbn/pbn.pdf rename to resources/3rdparty/glpk-4.57/examples/pbn/pbn.pdf diff --git a/resources/3rdparty/glpk-4.53/examples/pbn/pbn.tex b/resources/3rdparty/glpk-4.57/examples/pbn/pbn.tex similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/pbn/pbn.tex rename to resources/3rdparty/glpk-4.57/examples/pbn/pbn.tex diff --git a/resources/3rdparty/glpk-4.53/examples/pbn/petro.dat b/resources/3rdparty/glpk-4.57/examples/pbn/petro.dat similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/pbn/petro.dat rename to resources/3rdparty/glpk-4.57/examples/pbn/petro.dat diff --git a/resources/3rdparty/glpk-4.53/examples/pbn/skid.dat b/resources/3rdparty/glpk-4.57/examples/pbn/skid.dat similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/pbn/skid.dat rename to resources/3rdparty/glpk-4.57/examples/pbn/skid.dat diff --git a/resources/3rdparty/glpk-4.53/examples/pbn/swing.dat b/resources/3rdparty/glpk-4.57/examples/pbn/swing.dat similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/pbn/swing.dat rename to resources/3rdparty/glpk-4.57/examples/pbn/swing.dat diff --git a/resources/3rdparty/glpk-4.53/examples/plan.lp b/resources/3rdparty/glpk-4.57/examples/plan.lp similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/plan.lp rename to resources/3rdparty/glpk-4.57/examples/plan.lp diff --git a/resources/3rdparty/glpk-4.53/examples/plan.mod b/resources/3rdparty/glpk-4.57/examples/plan.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/plan.mod rename to resources/3rdparty/glpk-4.57/examples/plan.mod diff --git a/resources/3rdparty/glpk-4.53/examples/plan.mps b/resources/3rdparty/glpk-4.57/examples/plan.mps similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/plan.mps rename to resources/3rdparty/glpk-4.57/examples/plan.mps diff --git a/resources/3rdparty/glpk-4.53/examples/prod.mod b/resources/3rdparty/glpk-4.57/examples/prod.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/prod.mod rename to resources/3rdparty/glpk-4.57/examples/prod.mod diff --git a/resources/3rdparty/glpk-4.53/examples/qfit.mod b/resources/3rdparty/glpk-4.57/examples/qfit.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/qfit.mod rename to resources/3rdparty/glpk-4.57/examples/qfit.mod diff --git a/resources/3rdparty/glpk-4.53/examples/queens.mod b/resources/3rdparty/glpk-4.57/examples/queens.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/queens.mod rename to resources/3rdparty/glpk-4.57/examples/queens.mod diff --git a/resources/3rdparty/glpk-4.53/examples/samp1.mps b/resources/3rdparty/glpk-4.57/examples/samp1.mps similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/samp1.mps rename to resources/3rdparty/glpk-4.57/examples/samp1.mps diff --git a/resources/3rdparty/glpk-4.53/examples/samp2.mps b/resources/3rdparty/glpk-4.57/examples/samp2.mps similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/samp2.mps rename to resources/3rdparty/glpk-4.57/examples/samp2.mps diff --git a/resources/3rdparty/glpk-4.53/examples/sample.asn b/resources/3rdparty/glpk-4.57/examples/sample.asn similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/sample.asn rename to resources/3rdparty/glpk-4.57/examples/sample.asn diff --git a/resources/3rdparty/glpk-4.53/examples/sample.c b/resources/3rdparty/glpk-4.57/examples/sample.c similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/sample.c rename to resources/3rdparty/glpk-4.57/examples/sample.c diff --git a/resources/3rdparty/glpk-4.53/examples/sample.clq b/resources/3rdparty/glpk-4.57/examples/sample.clq similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/sample.clq rename to resources/3rdparty/glpk-4.57/examples/sample.clq diff --git a/resources/3rdparty/glpk-4.53/examples/sample.cnf b/resources/3rdparty/glpk-4.57/examples/sample.cnf similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/sample.cnf rename to resources/3rdparty/glpk-4.57/examples/sample.cnf diff --git a/resources/3rdparty/glpk-4.53/examples/sample.col b/resources/3rdparty/glpk-4.57/examples/sample.col similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/sample.col rename to resources/3rdparty/glpk-4.57/examples/sample.col diff --git a/resources/3rdparty/glpk-4.53/examples/sample.max b/resources/3rdparty/glpk-4.57/examples/sample.max similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/sample.max rename to resources/3rdparty/glpk-4.57/examples/sample.max diff --git a/resources/3rdparty/glpk-4.53/examples/sample.min b/resources/3rdparty/glpk-4.57/examples/sample.min similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/sample.min rename to resources/3rdparty/glpk-4.57/examples/sample.min diff --git a/resources/3rdparty/glpk-4.53/examples/sat.mod b/resources/3rdparty/glpk-4.57/examples/sat.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/sat.mod rename to resources/3rdparty/glpk-4.57/examples/sat.mod diff --git a/resources/3rdparty/glpk-4.53/examples/shiftcover.mod b/resources/3rdparty/glpk-4.57/examples/shiftcov.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/shiftcover.mod rename to resources/3rdparty/glpk-4.57/examples/shiftcov.mod diff --git a/resources/3rdparty/glpk-4.53/examples/shikaku.mod b/resources/3rdparty/glpk-4.57/examples/shikaku.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/shikaku.mod rename to resources/3rdparty/glpk-4.57/examples/shikaku.mod diff --git a/resources/3rdparty/glpk-4.53/examples/sorting.mod b/resources/3rdparty/glpk-4.57/examples/sorting.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/sorting.mod rename to resources/3rdparty/glpk-4.57/examples/sorting.mod diff --git a/resources/3rdparty/glpk-4.53/examples/spp.mod b/resources/3rdparty/glpk-4.57/examples/spp.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/spp.mod rename to resources/3rdparty/glpk-4.57/examples/spp.mod diff --git a/resources/3rdparty/glpk-4.53/examples/spxsamp1.c b/resources/3rdparty/glpk-4.57/examples/spxsamp1.c similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/spxsamp1.c rename to resources/3rdparty/glpk-4.57/examples/spxsamp1.c diff --git a/resources/3rdparty/glpk-4.53/examples/spxsamp2.c b/resources/3rdparty/glpk-4.57/examples/spxsamp2.c similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/spxsamp2.c rename to resources/3rdparty/glpk-4.57/examples/spxsamp2.c diff --git a/resources/3rdparty/glpk-4.53/examples/sql/README b/resources/3rdparty/glpk-4.57/examples/sql/README similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/sql/README rename to resources/3rdparty/glpk-4.57/examples/sql/README diff --git a/resources/3rdparty/glpk-4.53/examples/sql/mysql_setup.sh b/resources/3rdparty/glpk-4.57/examples/sql/mysql_setup.sh old mode 100644 new mode 100755 similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/sql/mysql_setup.sh rename to resources/3rdparty/glpk-4.57/examples/sql/mysql_setup.sh diff --git a/resources/3rdparty/glpk-4.53/examples/sql/sudoku.sql b/resources/3rdparty/glpk-4.57/examples/sql/sudoku.sql similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/sql/sudoku.sql rename to resources/3rdparty/glpk-4.57/examples/sql/sudoku.sql diff --git a/resources/3rdparty/glpk-4.53/examples/sql/sudoku_mysql.mod b/resources/3rdparty/glpk-4.57/examples/sql/sudoku_mysql.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/sql/sudoku_mysql.mod rename to resources/3rdparty/glpk-4.57/examples/sql/sudoku_mysql.mod diff --git a/resources/3rdparty/glpk-4.53/examples/sql/sudoku_odbc.mod b/resources/3rdparty/glpk-4.57/examples/sql/sudoku_odbc.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/sql/sudoku_odbc.mod rename to resources/3rdparty/glpk-4.57/examples/sql/sudoku_odbc.mod diff --git a/resources/3rdparty/glpk-4.53/examples/sql/transp.sql b/resources/3rdparty/glpk-4.57/examples/sql/transp.sql similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/sql/transp.sql rename to resources/3rdparty/glpk-4.57/examples/sql/transp.sql diff --git a/resources/3rdparty/glpk-4.53/examples/sql/transp_mysql.mod b/resources/3rdparty/glpk-4.57/examples/sql/transp_mysql.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/sql/transp_mysql.mod rename to resources/3rdparty/glpk-4.57/examples/sql/transp_mysql.mod diff --git a/resources/3rdparty/glpk-4.53/examples/sql/transp_odbc.mod b/resources/3rdparty/glpk-4.57/examples/sql/transp_odbc.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/sql/transp_odbc.mod rename to resources/3rdparty/glpk-4.57/examples/sql/transp_odbc.mod diff --git a/resources/3rdparty/glpk-4.53/examples/stigler.mod b/resources/3rdparty/glpk-4.57/examples/stigler.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/stigler.mod rename to resources/3rdparty/glpk-4.57/examples/stigler.mod diff --git a/resources/3rdparty/glpk-4.53/examples/sudoku.dat b/resources/3rdparty/glpk-4.57/examples/sudoku.dat similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/sudoku.dat rename to resources/3rdparty/glpk-4.57/examples/sudoku.dat diff --git a/resources/3rdparty/glpk-4.53/examples/sudoku.mod b/resources/3rdparty/glpk-4.57/examples/sudoku.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/sudoku.mod rename to resources/3rdparty/glpk-4.57/examples/sudoku.mod diff --git a/resources/3rdparty/glpk-4.53/examples/t1.cs b/resources/3rdparty/glpk-4.57/examples/t1.cs similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/t1.cs rename to resources/3rdparty/glpk-4.57/examples/t1.cs diff --git a/resources/3rdparty/glpk-4.53/examples/tas.mod b/resources/3rdparty/glpk-4.57/examples/tas.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/tas.mod rename to resources/3rdparty/glpk-4.57/examples/tas.mod diff --git a/resources/3rdparty/glpk-4.53/examples/todd.mod b/resources/3rdparty/glpk-4.57/examples/todd.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/todd.mod rename to resources/3rdparty/glpk-4.57/examples/todd.mod diff --git a/resources/3rdparty/glpk-4.53/examples/train.mod b/resources/3rdparty/glpk-4.57/examples/train.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/train.mod rename to resources/3rdparty/glpk-4.57/examples/train.mod diff --git a/resources/3rdparty/glpk-4.53/examples/transp.mod b/resources/3rdparty/glpk-4.57/examples/transp.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/transp.mod rename to resources/3rdparty/glpk-4.57/examples/transp.mod diff --git a/resources/3rdparty/glpk-4.53/examples/trick.mod b/resources/3rdparty/glpk-4.57/examples/trick.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/trick.mod rename to resources/3rdparty/glpk-4.57/examples/trick.mod diff --git a/resources/3rdparty/glpk-4.53/examples/tsp.mod b/resources/3rdparty/glpk-4.57/examples/tsp.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/tsp.mod rename to resources/3rdparty/glpk-4.57/examples/tsp.mod diff --git a/resources/3rdparty/glpk-4.57/examples/tsp/README b/resources/3rdparty/glpk-4.57/examples/tsp/README new file mode 100644 index 000000000..7d497e58f --- /dev/null +++ b/resources/3rdparty/glpk-4.57/examples/tsp/README @@ -0,0 +1,37 @@ +This subdirectory contains an example application program, TSPSOL, +which is a stand-alone solver intended to solve the Symmetric Traveling +Salesman Problem (TSP) with the GLPK integer optimizer. + +Please note that this program is only an illustrative example that +illustrates generating "lazy" constraints during the branch-and-bound +search. It is *not* a state-of-the-art code, so only small-sized TSP +instances (perhaps, having up to 150-200 nodes) can be solved with this +program in a reasonable time. For more details see comments in the +source code. + +To build TSPSOL executable you need to run 'build.sh' script. Note that +you should have the GLPK library properly installed. + +To run the TSPSOL program use the following command: + + tspsol tsp-file + +where tsp-file specifies an input text file containing TSP data in +TSPLIB 95 format. + +Detailed description of the input format recognized by TSPSOL is given +in the report: Gerhard Reinelt, "TSPLIB 95". This report as well as +TSPLIB, a library of sample TSP instances, are freely available for +research purposes; see: +. + +This subdirectory also includes the following example TSP instances: + +dantzig42.tsp 42 cities (Dantzig) [from TSPLIB] +gr120.tsp 120 cities in Germany (Groetschel) [from TSPLIB] +moscow.tsp 68 cities in Moscow region (Makhorin) +sample.tsp small example from D.Phillips and A.Garcia-Diaz +ulysses16.tsp Odyssey of Ulysses (Groetschel/Padberg) [from TSPLIB] +ulysses22.tsp Odyssey of Ulysses (Groetschel/Padberg) [from TSPLIB] + +Please send comments to the mailing list. diff --git a/resources/3rdparty/glpk-4.57/examples/tsp/bench.txt b/resources/3rdparty/glpk-4.57/examples/tsp/bench.txt new file mode 100644 index 000000000..4596b2e39 --- /dev/null +++ b/resources/3rdparty/glpk-4.57/examples/tsp/bench.txt @@ -0,0 +1,56 @@ +Solver: TSPSOL for GLPK 4.56 +Computer: Intel Celeron J1800 2.41 GHz +OS: Debian GNU/Linux 8.1.0 "Jessie" +Compiler: GCC 4.7.2 (options used: -O2) +Test set: TSPLIB 95 + +Instance N Solution Lower Bound Nodes Iters Time,s Mem,MB +------------ --- ------------ ------------ -------- ------- ------ ------ +att48 48 10628 opt 1 336 < 1 1.2 +bayg29 29 1610 opt 1 173 < 1 0.3 +bays29 29 2020 opt 1 166 < 1 0.3 +berlin52 52 7542 opt 1 253 < 1 0.7 +bier127 127 118282 opt 29 1330 14 19.1 +brazil58 58 25395 opt 1 458 1 2.0 +brg180 180 1950 opt 131 20012 83 52.0 +burma14 14 3323 opt 1 55 < 1 0.1 +ch130 130 6110 opt 45 2212 38 24.2 +ch150 150 6528 opt 271 4967 138 27.5 +d198 98 15780 opt 259 11371 719 92.3 +dantzig42 42 699 opt 1 171 < 1 0.8 +eil51 51 426 opt 115 1368 2 2.4 +eil76 76 538 opt 1 517 < 1 2.2 +eil101 101 629 opt 1 838 4 9.9 +fri26 26 937 opt 1 125 < 1 0.2 +gr17 17 2085 opt 1 93 < 1 0.1 +gr21 21 2707 opt 1 82 < 1 0.1 +gr24 24 1272 opt 1 137 < 1 0.2 +gr48 48 5046 opt 3 407 1 2.3 +gr96 96 55209 opt 367 5564 63 12.4 +gr120 120 6942 opt 121 2940 46 14.7 +gr137 137 69853 opt 97 1934 27 16.2 +gr202 202 40160 opt 183 4176 287 88.4 +hk48 48 11461 opt 1 322 < 1 1.1 +kroA100 100 21282 opt 57 2227 23 13.2 +kroB100 100 22141 opt 71 1891 27 15.6 +kroC100 100 20749 opt 9 1035 5 9.4 +kroD100 100 21294 opt 9 1203 10 12.3 +kroE100 100 22068 opt 323 5055 100 13.4 +kroA150 150 26524 opt 431 8069 487 50.2 +kroB150 150 26130 opt 309 12599 610 43.1 +lin105 105 14379 opt 5 910 4 7.3 +lin318 318 42029 opt 1527 25885 4972 286.4 +pr76 76 108159 opt 20537 636616 9218 128.7 * +pr107 107 44303 opt 1 3692 38 33.2 +pr124 124 59030 opt 19 1306 23 25.6 +pr136 136 96772 opt 93 2799 60 27.7 +pr144 144 58537 opt 11 1948 37 32.2 +pr152 152 73682 opt 125 3269 99 46.0 +pr226 226 80369 opt 1 6699 240 163.8 +rat99 99 1211 opt 11 467 2 5,6 +rd100 100 7910 opt 1 868 3 7.2 +st70 70 675 opt 1 688 1 3.2 +swiss42 42 1273 opt 1 231 < 1 0.8 +u159 159 42080 opt 9 1356 15 30.0 +ulysses16 16 6859 opt 1 72 < 1 0.1 +ulysses22 22 7013 opt 1 110 < 1 0.2 diff --git a/resources/3rdparty/glpk-4.57/examples/tsp/build.sh b/resources/3rdparty/glpk-4.57/examples/tsp/build.sh new file mode 100755 index 000000000..ab6abc1fb --- /dev/null +++ b/resources/3rdparty/glpk-4.57/examples/tsp/build.sh @@ -0,0 +1,8 @@ +#!/bin/sh +# +# Run this script to build TSPSOL executable. +# +# NOTE: you need to have GLPK properly installed. +# +gcc -O2 -otspsol main.c maxflow.c mincut.c misc.c tsplib.c -lglpk -lm +./tspsol sample.tsp diff --git a/resources/3rdparty/glpk-4.57/examples/tsp/dantzig42.tsp b/resources/3rdparty/glpk-4.57/examples/tsp/dantzig42.tsp new file mode 100644 index 000000000..15567bff1 --- /dev/null +++ b/resources/3rdparty/glpk-4.57/examples/tsp/dantzig42.tsp @@ -0,0 +1,103 @@ +NAME : dantzig42 +TYPE : TSP +COMMENT : 42 cities (Dantzig) +DIMENSION : 42 +EDGE_WEIGHT_TYPE : EXPLICIT +EDGE_WEIGHT_FORMAT : LOWER_DIAG_ROW +DISPLAY_DATA_TYPE : TWOD_DISPLAY +EDGE_WEIGHT_SECTION + 0 8 0 39 45 0 37 47 9 0 50 49 21 15 0 61 62 21 + 20 17 0 58 60 16 17 18 6 0 59 60 15 20 26 17 10 0 + 62 66 20 25 31 22 15 5 0 81 81 40 44 50 41 35 24 20 + 0 103 107 62 67 72 63 57 46 41 23 0 108 117 66 71 77 68 + 61 51 46 26 11 0 145 149 104 108 114 106 99 88 84 63 49 40 + 0 181 185 140 144 150 142 135 124 120 99 85 76 35 0 187 191 146 + 150 156 142 137 130 125 105 90 81 41 10 0 161 170 120 124 130 115 + 110 104 105 90 72 62 34 31 27 0 142 146 101 104 111 97 91 85 + 86 75 51 59 29 53 48 21 0 174 178 133 138 143 129 123 117 118 + 107 83 84 54 46 35 26 31 0 185 186 142 143 140 130 126 124 128 + 118 93 101 72 69 58 58 43 26 0 164 165 120 123 124 106 106 105 + 110 104 86 97 71 93 82 62 42 45 22 0 137 139 94 96 94 80 + 78 77 84 77 56 64 65 90 87 58 36 68 50 30 0 117 122 77 + 80 83 68 62 60 61 50 34 42 49 82 77 60 30 62 70 49 21 + 0 114 118 73 78 84 69 63 57 59 48 28 36 43 77 72 45 27 + 59 69 55 27 5 0 85 89 44 48 53 41 34 28 29 22 23 35 + 69 105 102 74 56 88 99 81 54 32 29 0 77 80 36 40 46 34 + 27 19 21 14 29 40 77 114 111 84 64 96 107 87 60 40 37 8 + 0 87 89 44 46 46 30 28 29 32 27 36 47 78 116 112 84 66 + 98 95 75 47 36 39 12 11 0 91 93 48 50 48 34 32 33 36 + 30 34 45 77 115 110 83 63 97 91 72 44 32 36 9 15 3 0 + 105 106 62 63 64 47 46 49 54 48 46 59 85 119 115 88 66 98 + 79 59 31 36 42 28 33 21 20 0 111 113 69 71 66 51 53 56 + 61 57 59 71 96 130 126 98 75 98 85 62 38 47 53 39 42 29 + 30 12 0 91 92 50 51 46 30 34 38 43 49 60 71 103 141 136 + 109 90 115 99 81 53 61 62 36 34 24 28 20 20 0 83 85 42 + 43 38 22 26 32 36 51 63 75 106 142 140 112 93 126 108 88 60 + 64 66 39 36 27 31 28 28 8 0 89 91 55 55 50 34 39 44 + 49 63 76 87 120 155 150 123 100 123 109 86 62 71 78 52 49 39 + 44 35 24 15 12 0 95 97 64 63 56 42 49 56 60 75 86 97 + 126 160 155 128 104 128 113 90 67 76 82 62 59 49 53 40 29 25 + 23 11 0 74 81 44 43 35 23 30 39 44 62 78 89 121 159 155 + 127 108 136 124 101 75 79 81 54 50 42 46 43 39 23 14 14 21 + 0 67 69 42 41 31 25 32 41 46 64 83 90 130 164 160 133 114 + 146 134 111 85 84 86 59 52 47 51 53 49 32 24 24 30 9 0 + 74 76 61 60 42 44 51 60 66 83 102 110 147 185 179 155 133 159 + 146 122 98 105 107 79 71 66 70 70 60 48 40 36 33 25 18 0 + 57 59 46 41 25 30 36 47 52 71 93 98 136 172 172 148 126 158 + 147 124 121 97 99 71 65 59 63 67 62 46 38 37 43 23 13 17 + 0 45 46 41 34 20 34 38 48 53 73 96 99 137 176 178 151 131 + 163 159 135 108 102 103 73 67 64 69 75 72 54 46 49 54 34 24 + 29 12 0 35 37 35 26 18 34 36 46 51 70 93 97 134 171 176 + 151 129 161 163 139 118 102 101 71 65 65 70 84 78 58 50 56 62 + 41 32 38 21 9 0 29 33 30 21 18 35 33 40 45 65 87 91 + 117 166 171 144 125 157 156 139 113 95 97 67 60 62 67 79 82 62 + 53 59 66 45 38 45 27 15 6 0 3 11 41 37 47 57 55 58 + 63 83 105 109 147 186 188 164 144 176 182 161 134 119 116 86 78 84 + 88 101 108 88 80 86 92 71 64 71 54 41 32 25 0 5 12 55 + 41 53 64 61 61 66 84 111 113 150 186 192 166 147 180 188 167 140 + 124 119 90 87 90 94 107 114 77 86 92 98 80 74 77 60 48 38 + 32 6 0 +DISPLAY_DATA_SECTION + 1 170.0 85.0 + 2 166.0 88.0 + 3 133.0 73.0 + 4 140.0 70.0 + 5 142.0 55.0 + 6 126.0 53.0 + 7 125.0 60.0 + 8 119.0 68.0 + 9 117.0 74.0 + 10 99.0 83.0 + 11 73.0 79.0 + 12 72.0 91.0 + 13 37.0 94.0 + 14 6.0 106.0 + 15 3.0 97.0 + 16 21.0 82.0 + 17 33.0 67.0 + 18 4.0 66.0 + 19 3.0 42.0 + 20 27.0 33.0 + 21 52.0 41.0 + 22 57.0 59.0 + 23 58.0 66.0 + 24 88.0 65.0 + 25 99.0 67.0 + 26 95.0 55.0 + 27 89.0 55.0 + 28 83.0 38.0 + 29 85.0 25.0 + 30 104.0 35.0 + 31 112.0 37.0 + 32 112.0 24.0 + 33 113.0 13.0 + 34 125.0 30.0 + 35 135.0 32.0 + 36 147.0 18.0 + 37 147.5 36.0 + 38 154.5 45.0 + 39 157.0 54.0 + 40 158.0 61.0 + 41 172.0 82.0 + 42 174.0 87.0 +EOF diff --git a/resources/3rdparty/glpk-4.57/examples/tsp/gr120.tsp b/resources/3rdparty/glpk-4.57/examples/tsp/gr120.tsp new file mode 100644 index 000000000..632248922 --- /dev/null +++ b/resources/3rdparty/glpk-4.57/examples/tsp/gr120.tsp @@ -0,0 +1,534 @@ +NAME: gr120 +TYPE: TSP +COMMENT: 120 cities in Germany (Groetschel) +DIMENSION: 120 +EDGE_WEIGHT_TYPE: EXPLICIT +EDGE_WEIGHT_FORMAT: LOWER_DIAG_ROW +DISPLAY_DATA_TYPE: TWOD_DISPLAY +EDGE_WEIGHT_SECTION + 0 534 0 434 107 0 294 241 148 0 593 190 137 374 0 409 351 240 + 190 258 0 332 320 232 139 494 310 0 232 354 261 113 372 188 208 0 + 464 124 88 171 202 328 188 284 0 566 508 397 347 331 171 467 345 485 + 0 552 80 127 259 234 365 249 372 61 522 0 802 316 336 509 222 470 + 588 584 392 502 386 0 633 432 479 552 586 723 417 621 411 874 354 738 + 0 257 641 541 407 706 522 184 391 372 679 433 915 390 0 187 577 477 + 337 636 452 375 321 507 609 595 845 572 196 0 91 450 357 210 509 325 + 248 141 380 482 468 718 661 228 158 0 412 624 531 384 690 506 210 408 + 398 663 459 892 227 169 351 383 0 400 752 659 512 818 634 338 536 526 + 791 587 1020 524 151 270 371 167 0 472 805 712 565 871 687 391 589 579 + 844 640 1073 413 257 342 443 220 57 0 389 665 572 425 731 547 251 449 + 439 704 500 933 274 146 328 360 53 112 165 0 610 76 183 317 192 442 + 396 430 202 515 141 233 492 723 653 526 700 828 881 741 0 340 730 630 + 490 789 605 394 474 582 762 643 998 444 125 185 311 223 67 139 168 806 + 0 510 152 134 217 248 370 175 330 46 527 72 438 380 359 553 426 385 + 513 566 426 213 569 0 153 447 354 207 470 280 246 113 377 437 465 715 + 659 345 275 98 500 488 560 477 523 428 423 0 511 844 751 604 910 726 + 430 628 618 883 679 1112 407 296 381 482 259 96 39 204 920 178 605 599 + 0 269 283 190 42 332 148 169 63 213 305 301 544 582 382 312 185 365 + 493 546 406 359 465 259 170 585 0 525 157 95 232 42 257 316 355 160 + 330 167 254 521 638 568 441 615 743 796 656 188 721 206 438 835 274 0 + 150 539 446 299 598 414 279 283 469 571 557 807 488 112 96 120 267 255 + 327 244 615 195 515 237 366 274 530 0 80 507 414 267 566 382 305 251 + 437 539 525 775 572 196 88 77 351 339 411 328 583 279 483 205 450 242 + 498 63 0 130 520 427 280 579 395 318 264 450 552 538 788 543 167 59 + 101 322 310 382 299 596 250 496 218 412 255 511 56 25 0 401 791 691 + 551 850 666 474 535 662 823 723 1059 524 238 238 372 303 138 126 248 867 + 101 649 489 165 526 782 256 340 311 0 134 524 431 284 583 399 314 268 + 454 556 542 792 530 154 63 105 309 297 369 286 600 237 500 222 408 259 + 515 34 29 22 298 0 666 942 849 702 1008 824 528 726 716 981 777 1210 + 446 423 605 637 357 280 217 279 1018 336 703 754 194 683 933 521 605 576 + 416 563 0 259 281 188 40 364 180 142 72 211 337 299 549 555 372 302 + 175 338 466 519 379 357 455 257 172 558 27 272 264 232 245 516 249 656 + 0 505 447 336 286 354 110 406 284 424 70 461 566 819 618 548 421 602 + 730 783 643 538 701 466 376 822 244 353 509 478 491 762 494 920 276 0 + 453 358 247 234 265 59 354 232 335 182 372 477 767 566 496 369 550 678 + 731 591 449 649 377 324 770 192 264 458 426 439 710 443 868 224 95 0 + 627 334 251 408 168 239 528 406 300 166 348 331 700 740 670 504 724 852 + 905 765 360 823 346 504 944 366 179 632 600 613 884 617 1042 398 162 177 + 0 339 275 187 94 313 281 45 184 143 438 204 543 458 229 382 250 255 + 350 436 296 351 439 130 248 475 136 271 286 312 325 519 321 573 102 377 + 325 425 0 710 283 254 491 117 375 611 489 319 354 351 202 679 823 753 + 626 807 935 988 848 272 906 365 587 1027 449 159 715 683 696 967 700 1125 + 481 345 337 183 430 0 243 353 260 113 419 235 89 133 283 392 368 621 + 502 209 286 159 285 413 466 326 429 439 226 157 505 94 344 190 216 229 + 500 225 603 67 331 279 453 96 536 0 376 520 427 280 586 402 106 300 + 294 559 355 788 340 146 322 306 112 240 293 153 596 296 281 338 332 261 + 511 220 322 293 376 253 430 234 498 446 620 151 703 181 0 449 594 501 + 354 660 476 180 378 368 633 429 862 256 206 388 420 45 204 257 101 670 + 260 355 537 296 335 585 304 388 359 340 346 394 308 572 520 694 225 777 + 255 82 0 505 781 688 541 847 663 367 565 555 820 616 1049 289 262 444 + 476 196 119 136 118 857 175 542 593 129 522 772 360 444 415 255 402 161 + 495 759 707 881 412 964 442 269 233 0 322 611 518 371 677 493 197 395 + 372 650 446 879 359 69 261 293 94 142 224 84 687 146 372 410 263 352 + 602 177 261 232 247 219 361 325 589 537 711 242 794 272 99 106 200 0 + 185 575 482 335 634 450 231 319 419 607 480 843 462 86 124 156 241 226 + 298 218 651 166 406 273 337 310 566 40 124 95 227 82 495 300 546 494 + 668 276 751 207 212 278 334 151 0 353 638 545 398 704 520 224 422 412 + 677 473 906 282 110 292 324 61 125 178 38 714 181 399 441 217 379 629 + 208 292 263 261 250 315 352 616 564 738 269 821 299 126 82 154 46 182 + 0 324 314 191 106 275 91 225 104 244 248 332 487 638 437 367 240 421 + 549 602 462 390 520 290 238 641 64 227 329 297 310 581 314 739 95 187 + 135 309 196 392 150 317 391 578 408 365 435 0 388 234 127 124 219 113 + 289 168 215 270 254 431 606 501 431 304 485 613 666 526 310 584 232 302 + 705 128 163 393 361 374 645 378 803 159 209 120 219 229 336 214 381 455 + 642 472 429 499 64 0 447 664 571 424 730 546 250 448 438 703 499 932 + 188 204 386 418 36 202 255 88 740 258 425 535 294 405 655 302 386 357 + 338 344 392 378 642 590 764 295 847 325 152 68 231 130 276 96 461 525 + 0 360 606 513 366 672 488 192 390 380 645 441 874 273 117 299 331 46 + 150 203 63 682 206 367 448 242 347 597 215 299 270 286 257 340 320 584 + 532 706 237 789 267 94 58 179 48 189 31 403 467 82 0 605 133 180 + 312 287 418 264 425 112 575 55 439 313 448 648 520 474 602 655 515 193 + 658 89 517 694 354 220 610 577 591 738 595 792 352 514 425 401 219 404 + 421 370 444 631 461 495 488 385 307 514 456 0 656 932 839 692 998 814 + 518 716 706 971 767 1200 444 413 595 627 347 270 200 269 1008 326 693 744 + 177 673 923 511 595 566 406 553 42 646 910 858 1032 563 1115 593 420 384 + 151 351 485 305 729 793 382 330 782 0 573 113 101 280 79 329 359 403 + 163 402 157 235 509 686 616 489 663 791 844 704 131 769 209 486 883 322 + 57 578 546 559 830 563 981 320 425 336 236 314 176 392 559 633 820 650 + 614 677 353 220 603 645 210 971 0 293 384 274 143 319 129 262 60 314 + 286 402 531 675 451 381 201 458 586 639 499 460 534 360 151 678 101 318 + 343 311 324 595 328 776 132 225 173 353 233 436 187 354 428 615 445 379 + 472 83 147 498 440 455 766 375 0 372 283 199 153 229 39 273 151 324 + 196 324 441 686 485 415 288 469 597 650 510 413 568 370 241 689 111 228 + 377 345 358 629 362 787 143 135 83 263 244 346 198 365 439 626 456 413 + 483 54 72 509 451 377 777 300 90 0 330 479 386 239 545 361 65 259 + 253 518 314 747 378 119 276 260 150 278 331 191 555 334 240 297 370 220 + 470 174 276 247 414 207 468 193 457 405 579 110 662 140 46 120 307 126 + 166 164 276 340 190 132 329 458 518 313 324 0 610 297 234 391 107 275 + 511 389 322 248 331 254 693 723 653 526 707 835 888 748 302 806 368 487 + 927 349 149 615 583 596 867 600 1025 381 239 231 77 408 106 436 603 677 + 864 694 651 721 292 236 747 689 384 1015 186 336 246 562 0 598 874 781 + 634 940 756 460 658 648 913 709 1142 370 355 537 569 289 212 197 211 950 + 268 635 686 157 615 865 453 537 508 348 495 84 588 852 800 974 505 1057 + 535 362 326 93 293 427 247 671 735 324 272 724 85 913 708 719 400 957 + 0 214 604 504 364 663 479 402 348 534 636 622 872 599 223 49 185 378 + 319 391 355 680 234 580 302 430 339 595 123 115 86 287 90 632 329 575 + 523 697 409 780 313 349 415 471 288 151 319 394 458 413 326 675 622 643 + 408 442 303 680 564 0 154 401 308 161 460 276 199 78 331 433 419 669 + 612 298 228 63 453 441 513 430 477 381 377 47 552 136 392 190 158 171 + 442 175 707 126 372 320 494 201 577 110 291 490 546 363 226 396 191 255 + 488 401 471 697 440 138 239 250 477 639 255 0 70 464 371 224 523 339 + 262 208 394 496 482 732 567 191 121 27 346 334 406 323 540 274 440 162 + 445 199 455 83 47 64 335 68 600 189 435 383 557 269 640 173 295 383 + 439 256 119 287 254 378 381 294 534 590 503 268 302 249 540 532 148 115 + 0 606 349 266 387 183 216 507 385 354 147 363 357 715 719 649 522 703 + 831 884 744 375 802 400 483 923 345 194 611 579 592 863 596 1021 377 139 + 154 22 447 209 432 599 673 860 690 647 717 288 232 743 685 416 1011 262 + 332 242 558 103 953 676 473 536 0 631 228 175 412 38 296 532 410 240 + 306 272 210 640 744 674 547 728 856 909 769 233 827 286 508 948 370 80 + 636 604 617 888 621 1046 402 293 261 138 351 79 457 624 698 885 715 672 + 742 313 257 768 710 325 1036 117 357 267 583 69 978 701 498 561 153 0 + 642 129 176 349 121 369 428 472 232 428 226 187 578 755 685 558 732 860 + 913 773 98 838 278 555 952 391 132 647 615 628 899 632 1050 389 465 376 + 260 383 161 461 628 702 889 719 683 746 422 330 772 714 279 1040 75 430 + 340 587 191 982 712 509 572 275 122 0 503 779 686 539 845 661 365 563 + 553 818 614 1047 245 260 442 474 141 151 168 116 855 207 540 591 162 520 + 770 358 442 413 287 400 201 493 757 705 879 410 962 440 267 231 44 198 + 332 152 576 640 174 177 629 199 818 613 624 305 862 125 469 544 437 858 + 883 887 0 372 762 662 522 821 637 456 506 644 794 705 1030 506 209 209 + 343 285 120 108 230 838 72 631 460 147 497 753 227 311 282 29 269 398 + 487 733 681 855 501 938 471 354 322 237 218 198 243 552 616 320 268 720 + 388 801 566 600 396 838 330 258 413 306 834 859 870 269 0 641 348 265 + 422 152 262 542 420 314 189 362 313 714 754 684 557 738 866 919 779 344 + 837 360 518 958 380 193 646 614 627 898 631 1056 412 185 200 23 439 165 + 467 634 708 895 725 682 752 323 233 778 720 415 1046 231 367 277 593 59 + 988 711 508 571 45 122 244 893 869 0 561 837 744 597 903 719 423 621 + 611 876 672 1105 311 318 500 532 252 175 192 174 913 231 598 649 186 578 + 828 416 500 471 311 458 154 551 815 763 937 468 1020 498 325 289 65 256 + 390 210 634 698 287 235 687 152 876 671 682 363 920 77 527 602 495 916 + 941 945 66 293 951 0 478 754 661 514 820 636 340 538 528 793 589 1022 + 261 235 417 449 116 132 149 91 830 188 515 566 159 495 745 333 417 388 + 268 375 226 468 732 680 854 385 937 415 242 206 55 173 307 127 551 615 + 149 152 604 224 793 588 599 280 837 150 444 519 412 833 858 862 25 250 + 868 91 0 247 316 223 76 360 176 170 39 246 333 334 572 583 360 290 + 163 366 494 547 407 392 443 292 133 586 37 307 252 220 233 504 237 684 + 34 272 220 394 146 477 95 262 336 523 353 288 380 92 156 406 348 387 + 674 355 83 139 221 377 616 317 92 177 373 398 424 521 475 408 579 496 + 0 317 336 212 95 289 105 218 79 266 262 354 501 631 430 360 233 414 + 542 595 455 412 513 312 213 634 53 248 397 290 378 574 382 732 88 201 + 149 323 189 406 143 310 384 571 401 358 428 21 85 454 396 407 722 375 + 62 68 269 306 664 387 184 247 302 327 444 569 545 337 627 544 70 0 + 272 382 289 142 448 264 84 162 234 421 295 650 497 180 315 188 280 408 + 461 321 458 464 221 186 500 123 373 193 245 258 544 228 598 96 360 308 + 482 91 565 29 142 250 437 267 159 294 179 243 320 262 310 588 421 216 + 227 96 465 530 342 139 209 461 486 490 435 526 496 493 410 124 172 0 + 575 276 199 356 86 240 476 354 287 250 296 266 672 688 618 491 672 800 + 853 713 289 771 333 452 892 314 127 580 548 561 832 565 990 346 237 205 + 82 373 141 401 568 642 829 659 616 686 257 201 712 654 349 980 165 301 + 211 527 35 922 645 442 505 97 56 178 827 803 66 885 802 342 271 430 + 0 219 479 386 239 545 361 167 259 317 518 378 747 474 83 172 149 253 + 235 339 230 555 228 304 263 378 220 470 79 139 134 289 112 507 193 457 + 405 579 174 662 126 154 290 346 136 621 194 276 340 288 201 393 497 518 + 313 324 108 562 439 199 216 153 558 583 587 344 260 593 402 319 221 269 + 97 527 0 293 683 583 443 742 558 238 427 426 715 487 951 352 50 232 + 264 131 101 174 108 759 105 413 381 213 418 674 148 232 203 206 190 385 + 408 654 602 776 283 859 248 140 168 224 41 122 72 473 537 166 89 502 + 375 722 487 521 167 759 317 259 334 227 755 780 791 222 177 790 280 197 + 396 466 219 724 134 0 54 529 429 289 588 404 327 273 459 561 547 797 + 595 219 92 82 374 362 434 351 605 302 505 227 473 264 520 119 31 43 + 363 58 628 254 500 448 622 334 705 238 327 411 467 284 147 315 319 383 + 409 322 600 618 568 333 367 281 605 560 84 180 53 601 626 637 465 334 + 636 523 440 242 312 267 570 170 255 0 648 188 182 355 68 316 434 430 + 238 362 232 154 584 761 691 564 738 866 919 779 177 844 284 561 958 390 + 100 653 621 634 905 638 1056 395 412 323 194 389 95 467 634 708 895 725 + 689 752 333 277 778 720 285 1046 81 377 287 593 125 988 718 515 578 209 + 56 66 893 876 178 951 868 418 347 496 112 593 797 643 0 211 601 501 + 361 660 476 231 345 479 633 480 869 466 74 81 182 243 189 261 220 677 + 129 406 299 300 336 592 105 150 121 190 108 497 326 572 520 694 276 777 + 310 204 280 336 143 37 184 391 455 278 191 495 487 640 405 439 166 677 + 429 160 252 145 673 698 709 334 161 708 392 309 314 384 196 642 99 125 + 173 715 0 568 844 751 604 910 726 430 628 618 883 679 1112 348 325 507 + 539 259 182 150 181 920 238 605 656 127 585 835 423 507 478 318 465 98 + 558 822 770 944 475 1027 505 332 296 63 263 397 217 641 705 294 242 694 + 96 883 678 689 370 927 30 534 609 502 923 948 952 103 300 958 56 120 + 586 634 500 892 409 287 530 958 399 0 497 150 67 204 70 257 288 327 + 155 335 164 282 516 610 540 413 587 715 768 628 216 693 201 410 807 246 + 28 502 470 483 754 487 905 244 353 264 184 243 187 316 483 557 744 574 + 538 601 199 135 627 569 217 895 85 292 228 442 167 837 567 364 427 199 + 108 160 742 725 198 800 717 279 220 345 132 442 646 492 128 564 807 0 + 290 680 580 440 739 555 317 424 505 712 566 948 506 139 98 261 285 155 + 227 229 756 88 492 378 266 415 671 144 176 164 140 136 424 405 651 599 + 773 362 856 389 290 322 263 195 116 226 470 534 320 243 581 414 719 484 + 518 252 756 356 147 331 224 752 777 788 295 111 787 319 276 393 463 275 + 721 178 154 190 794 79 326 643 0 475 65 42 182 137 282 261 295 65 + 439 85 321 437 588 518 391 565 693 746 606 141 671 111 388 785 224 95 + 480 448 461 732 465 883 222 378 289 272 216 254 294 461 535 722 552 516 + 579 255 169 605 547 138 873 92 325 241 420 255 815 545 342 405 287 175 + 161 720 703 286 778 695 257 277 323 220 420 624 470 167 542 785 88 621 + 0 654 341 278 435 151 319 555 433 366 266 375 298 755 767 697 570 751 + 879 932 792 346 850 412 531 971 393 193 659 627 640 911 644 1069 425 262 + 254 100 452 103 480 647 721 908 738 695 765 336 280 791 733 428 1059 230 + 380 290 606 44 1001 724 521 584 122 113 235 906 882 77 964 881 421 350 + 509 79 606 803 649 169 721 971 211 800 299 0 445 387 276 226 294 50 + 346 224 364 125 410 506 759 558 488 361 542 670 723 583 478 641 406 316 + 762 184 293 450 418 431 702 435 860 216 64 57 193 317 411 271 438 512 + 699 529 486 556 127 149 582 524 454 850 365 165 75 397 311 792 515 312 + 375 170 332 405 697 673 216 755 672 212 141 300 276 397 594 440 352 512 + 762 293 591 318 355 0 375 765 665 525 824 640 384 509 572 797 633 1033 + 434 160 245 346 213 48 59 158 841 42 559 463 98 500 756 230 314 285 + 90 272 326 490 736 684 858 429 941 474 286 250 165 169 201 171 555 619 + 248 196 648 316 804 569 603 324 841 258 294 416 309 837 862 873 197 72 + 872 221 178 478 548 454 832 263 128 337 879 164 228 728 130 706 885 676 + 0 268 658 558 418 717 533 231 402 419 690 480 926 420 53 138 239 199 + 132 204 202 734 72 406 356 243 393 649 123 207 178 185 165 401 383 629 + 577 751 276 834 367 204 236 240 109 86 140 448 512 234 157 495 391 697 + 462 496 166 734 333 187 309 202 730 755 766 272 156 765 296 253 371 441 + 227 699 130 68 230 772 57 303 627 86 599 778 569 107 0 261 519 426 + 279 585 401 141 299 329 558 390 787 422 43 200 232 211 183 294 178 595 + 162 316 342 333 260 510 98 200 171 275 131 455 233 497 445 619 186 702 + 166 114 248 294 67 90 142 316 380 246 159 405 445 558 353 364 76 602 + 387 227 295 195 598 623 627 292 246 633 350 267 261 309 137 567 69 82 + 223 633 90 357 482 176 460 646 437 197 90 0 710 184 271 417 239 487 + 496 530 300 546 249 168 616 823 753 626 800 928 981 841 108 906 321 623 +1020 459 241 715 683 696 967 700 1118 457 583 494 378 451 279 529 696 770 + 957 787 751 814 490 448 840 782 310 1108 184 560 458 655 309 1050 780 577 + 640 393 240 118 955 938 362 1013 930 492 512 558 296 655 859 705 179 777 +1020 269 856 229 353 523 941 834 695 0 396 291 180 177 198 53 297 175 + 268 218 305 410 710 509 439 312 493 621 674 534 382 592 310 273 713 135 + 197 401 369 382 653 386 811 167 157 67 215 268 315 222 389 463 650 480 + 437 507 78 53 533 475 358 801 269 122 32 348 215 743 466 263 326 206 + 236 309 648 624 238 706 623 163 92 251 180 348 545 391 256 463 713 197 + 542 222 259 97 627 520 388 427 0 295 424 278 183 308 118 302 100 354 + 275 442 520 715 491 421 241 498 626 679 539 500 574 400 191 718 141 307 + 383 351 364 635 368 816 172 214 162 342 273 425 227 394 468 655 485 419 + 512 114 151 538 480 495 806 364 40 79 353 325 748 448 178 308 321 346 + 419 653 606 356 711 628 123 93 256 290 353 527 373 366 445 718 281 524 + 365 369 154 609 502 393 537 111 0 651 927 834 687 993 809 513 711 701 + 966 762 1195 407 408 590 622 342 265 282 264 1003 321 688 739 276 668 918 + 506 590 561 401 548 174 641 905 853 1027 558 1110 588 415 379 155 346 480 + 300 724 788 377 325 777 173 966 761 772 453 1010 90 617 692 585 1006 1031 +1035 162 383 1041 96 187 669 717 583 975 492 370 613 1041 482 112 890 409 + 868 1054 845 311 386 440 1103 796 801 0 175 565 472 325 624 440 311 309 + 495 597 583 833 504 128 76 146 283 271 343 260 641 211 541 263 382 300 + 556 32 76 47 272 30 537 290 536 484 658 318 741 222 256 320 376 193 + 56 224 355 419 318 231 636 527 604 369 403 210 641 469 103 216 109 637 + 662 673 374 243 672 432 349 278 423 225 606 104 164 99 679 57 439 528 + 112 506 685 476 246 114 134 741 427 409 522 0 585 67 146 292 135 385 + 371 405 175 458 147 249 499 698 628 501 675 803 856 716 57 781 221 498 + 895 334 131 590 558 571 842 575 993 332 481 392 303 326 215 404 571 645 + 832 662 626 689 365 261 715 657 200 983 74 435 356 530 245 925 655 452 + 515 318 176 62 830 813 287 888 805 367 387 433 232 530 734 580 120 652 + 895 159 731 104 289 421 816 709 570 121 325 438 978 616 0 250 640 540 + 400 699 515 277 384 465 672 526 908 466 99 89 221 245 178 250 220 716 + 96 452 338 289 375 631 105 189 160 151 147 447 365 611 559 733 322 816 + 349 250 282 286 155 76 186 430 494 280 203 541 437 679 444 478 212 716 + 379 138 291 184 712 737 748 318 122 747 342 299 353 423 235 681 138 114 + 212 754 39 349 603 40 581 760 551 138 46 136 816 502 484 432 96 691 + 0 717 221 251 424 137 385 503 499 307 417 301 95 653 830 760 633 807 + 935 988 848 190 913 353 631 1027 459 169 722 690 703 974 707 1125 464 481 + 392 246 458 117 536 703 777 964 794 758 821 402 346 847 789 354 1115 150 + 446 356 662 169 1057 787 584 647 272 125 92 962 945 228 1020 937 487 416 + 565 181 662 866 712 69 784 1027 197 863 236 213 421 948 841 702 162 325 + 435 1110 748 154 823 0 246 454 361 213 373 183 332 130 384 340 472 585 + 745 472 402 237 528 656 709 569 530 555 430 167 748 171 372 364 332 345 + 616 349 846 202 279 227 407 303 490 257 424 498 685 515 400 542 157 221 + 568 510 525 836 429 70 144 383 390 778 429 174 289 386 411 484 683 587 + 421 741 658 153 132 286 355 383 508 354 431 426 748 346 505 395 434 219 + 590 483 423 630 176 65 831 390 505 465 500 0 788 302 322 495 208 456 + 574 570 378 488 372 23 724 901 831 704 818 1006 1059 919 203 984 424 701 +1098 530 240 793 761 774 1045 778 1196 535 552 463 317 529 188 607 774 848 +1035 865 829 892 473 417 918 860 425 1186 221 517 427 733 240 1128 858 655 + 718 343 196 173 1033 1016 299 1091 1008 558 487 636 252 733 937 783 154 855 +1098 268 934 307 284 492 1019 912 773 138 396 506 1181 819 235 894 81 571 + 0 426 596 503 356 662 478 182 380 370 635 431 864 253 183 365 397 27 + 181 234 82 672 237 357 514 273 337 587 281 365 336 317 323 371 310 574 + 522 696 227 779 257 84 19 210 83 255 67 393 457 65 35 446 361 635 + 430 441 122 679 303 392 467 360 675 700 704 208 299 710 266 183 338 386 + 252 644 267 145 388 710 257 273 559 299 537 723 514 227 213 225 772 465 + 470 355 297 647 259 779 500 850 0 596 575 330 377 237 179 497 375 552 + 100 589 407 941 709 639 512 693 821 874 734 421 792 460 467 913 335 236 + 601 569 582 853 586 1011 367 91 117 72 468 259 422 589 663 850 680 637 + 707 278 221 733 675 642 1001 308 316 212 548 153 943 666 463 526 47 212 + 334 848 824 95 906 823 363 292 451 156 548 745 591 268 663 913 241 742 + 506 172 133 827 720 588 452 185 305 996 627 364 702 322 370 393 665 0 + 634 910 817 670 976 792 496 694 684 949 745 1178 414 391 573 605 325 248 + 185 247 986 304 671 722 162 651 901 489 573 544 384 531 32 624 888 836 +1010 541 1093 571 398 362 129 329 463 283 707 771 360 308 760 33 949 744 + 755 436 983 52 600 675 568 989 1014 1018 169 366 1024 122 194 652 700 566 + 958 475 353 596 1024 465 66 873 392 851 1037 828 294 369 423 1086 779 784 + 142 505 961 415 1003 814 1164 339 979 0 507 209 111 201 139 172 408 286 + 213 329 223 351 575 620 550 423 604 732 785 645 275 703 259 384 824 202 + 87 512 480 493 764 497 922 278 268 141 173 252 256 333 500 574 761 591 + 548 618 138 74 644 586 276 912 144 233 143 459 156 854 577 374 437 208 + 177 219 759 735 187 817 734 274 159 362 121 459 656 502 197 574 824 59 + 653 147 200 208 738 631 499 328 112 222 907 538 218 613 266 287 337 576 + 208 890 0 463 186 79 155 157 161 251 216 167 318 206 369 558 576 506 + 379 553 681 734 594 262 659 213 376 773 176 115 468 436 449 720 453 871 + 210 257 168 219 206 274 282 449 523 710 540 504 567 112 48 593 535 259 + 861 172 195 120 408 202 803 533 330 393 254 195 247 708 691 233 766 683 + 204 133 311 167 408 612 458 215 530 773 87 609 121 246 197 694 587 448 + 350 101 199 856 494 225 569 284 269 355 525 251 839 46 0 408 169 105 + 116 242 298 131 229 57 455 118 437 468 315 451 325 341 469 522 382 245 + 525 72 322 561 158 200 413 382 394 605 398 659 155 394 305 344 86 359 + 228 237 311 498 328 362 355 188 160 381 323 169 649 208 259 269 196 327 + 591 478 276 339 391 280 277 496 587 358 554 471 191 211 177 292 260 369 + 403 283 362 561 172 448 110 371 334 515 362 272 345 238 299 644 439 220 + 408 352 329 423 313 388 627 183 137 0 529 389 278 310 236 127 430 308 + 366 125 403 447 755 642 572 445 626 754 807 667 420 725 408 400 846 268 + 235 534 502 515 786 519 944 300 80 68 112 401 299 355 522 596 783 613 + 570 640 211 169 666 608 456 934 307 249 225 481 193 876 599 396 459 89 + 231 353 781 757 135 839 756 296 225 384 175 481 678 524 287 596 846 240 + 675 320 212 84 760 653 521 471 133 238 929 560 363 635 362 303 433 598 + 52 912 156 199 336 0 192 412 319 172 477 293 160 154 342 450 430 680 + 573 228 235 108 383 371 443 360 488 311 388 167 482 153 403 119 165 178 + 372 154 637 126 389 337 511 162 594 71 207 420 476 232 136 324 209 273 + 418 331 482 627 451 246 256 161 494 569 262 120 110 490 515 590 474 343 + 525 532 449 127 202 74 459 96 264 187 526 182 539 375 261 353 538 329 + 346 239 165 588 280 286 622 151 463 221 595 294 666 397 480 605 391 341 + 287 413 0 529 286 231 310 177 165 430 308 319 182 328 379 680 642 572 + 445 626 754 807 667 344 725 365 406 846 268 159 534 502 515 786 519 944 + 300 137 106 75 370 231 355 522 596 783 613 570 640 211 155 666 608 381 + 934 231 255 165 481 125 876 599 396 459 77 155 247 781 757 89 839 756 + 296 225 384 99 481 678 524 211 596 846 164 675 252 148 168 760 653 521 + 365 137 244 929 560 287 635 294 309 365 598 80 912 131 177 314 87 413 + 0 434 710 617 470 776 592 296 494 484 749 545 978 346 191 373 405 125 + 82 142 47 786 145 471 522 145 451 701 289 373 344 225 331 238 424 688 + 636 810 341 893 371 198 162 77 129 263 83 507 571 160 108 560 228 749 + 544 555 236 793 170 400 475 368 789 814 818 76 207 824 133 51 452 500 + 366 758 275 153 396 824 265 140 673 233 651 837 628 135 210 223 886 579 + 584 223 305 761 241 893 614 964 139 779 206 690 639 427 712 405 712 0 + 535 811 718 571 877 693 397 595 585 850 646 1079 336 292 474 506 226 94 + 76 129 887 154 572 623 75 552 802 390 474 445 202 432 175 525 789 737 + 911 442 994 472 299 263 58 230 364 184 608 672 261 209 661 160 850 645 + 656 337 894 140 501 576 469 890 915 919 91 184 925 113 88 553 601 467 + 859 376 176 497 925 276 110 774 242 752 938 729 123 219 324 987 680 685 + 205 406 862 265 994 715 1065 240 880 143 791 740 528 813 506 813 82 0 + 630 108 191 337 165 424 416 450 220 483 188 190 540 743 673 546 720 848 + 901 761 43 826 266 543 940 379 161 635 603 616 887 620 1038 877 520 431 + 315 371 216 449 616 690 877 707 671 734 410 306 760 702 241 1028 104 480 + 395 575 246 970 700 497 560 348 177 55 875 858 299 933 850 412 432 478 + 233 575 779 625 121 697 940 189 776 149 290 460 861 754 615 80 364 474 +1023 661 41 736 147 550 160 692 394 1006 248 270 265 393 508 317 806 907 + 0 446 252 145 227 162 111 347 225 233 268 272 374 624 559 489 362 543 + 671 724 584 346 642 279 323 763 185 161 451 419 432 703 436 861 217 207 + 141 162 272 279 272 439 513 700 530 487 557 128 50 583 525 325 851 233 + 172 82 398 179 793 516 313 376 175 200 273 698 674 176 756 673 213 142 + 301 144 398 595 441 220 513 763 108 592 187 223 147 677 570 438 391 51 + 161 846 477 289 552 289 226 360 515 167 829 49 66 203 115 330 98 629 + 730 319 0 166 518 425 277 437 247 336 114 448 404 536 649 749 435 365 + 150 590 578 650 567 594 518 494 90 689 235 436 402 295 383 579 387 844 + 189 343 291 471 295 554 247 428 627 683 500 363 531 221 285 625 538 589 + 834 493 134 208 372 454 776 392 137 252 450 475 548 681 550 485 739 656 + 150 196 276 419 353 471 317 495 389 746 410 468 459 498 283 553 446 432 + 694 240 129 829 353 569 428 564 80 635 604 434 812 351 333 393 367 257 + 373 612 713 614 290 0 471 313 202 252 166 99 372 250 290 210 358 378 + 679 584 514 387 568 696 749 609 350 667 332 348 788 210 165 476 444 457 + 728 461 886 242 156 61 135 311 276 297 464 538 725 555 512 582 153 93 + 608 550 380 876 237 197 107 423 170 818 541 338 401 147 191 277 723 699 + 149 781 698 238 167 326 135 423 620 466 224 538 788 139 617 244 214 118 + 702 595 462 395 67 186 871 502 293 577 293 251 364 540 128 854 80 123 + 260 76 355 70 654 755 323 39 315 0 442 718 625 478 784 600 304 502 + 492 757 553 986 300 199 381 413 81 137 184 53 794 209 479 530 194 459 + 709 297 381 352 285 339 261 432 696 644 818 349 901 379 206 126 90 137 + 271 91 515 579 111 116 568 259 757 552 563 244 801 185 408 483 376 797 + 822 826 60 267 832 126 35 460 508 374 766 283 161 404 832 273 155 681 + 293 659 845 636 195 270 231 894 587 592 222 313 769 301 901 622 972 108 + 787 229 698 647 435 720 413 720 55 123 814 637 620 662 0 523 230 147 + 304 81 188 424 302 235 255 174 293 596 636 566 439 620 748 801 661 265 + 719 281 400 840 262 75 528 496 509 780 513 938 294 284 195 104 321 193 + 349 516 590 777 607 564 634 205 149 660 602 297 928 147 249 159 475 87 + 870 593 390 453 119 108 192 775 751 118 833 750 290 219 378 52 475 672 + 518 139 590 840 80 669 168 131 224 754 647 515 310 128 238 923 554 208 + 629 208 303 279 592 161 906 69 115 240 160 407 84 706 807 238 92 367 + 87 714 0 566 45 139 273 228 383 352 386 121 540 60 314 411 679 609 + 482 656 784 837 697 81 762 132 479 876 315 189 571 539 552 823 556 974 + 313 479 390 366 307 308 385 552 626 813 643 607 670 346 266 696 638 112 + 964 158 416 342 511 335 906 636 433 496 381 266 155 811 794 380 869 786 + 348 368 414 314 511 715 561 213 633 876 182 712 97 379 419 797 690 551 + 189 323 456 959 597 93 672 247 486 284 628 607 942 244 218 178 421 444 + 346 742 843 124 284 550 345 750 262 0 235 313 220 73 371 187 168 43 + 243 344 331 583 581 348 278 151 364 492 545 405 389 431 289 137 584 48 + 304 240 208 221 492 225 682 32 283 231 405 144 488 93 260 334 521 351 + 276 378 103 167 404 346 384 672 352 95 150 219 388 614 305 94 165 384 + 409 421 519 463 419 577 494 12 92 122 353 219 384 230 429 302 584 276 + 381 254 432 223 466 359 259 489 174 135 667 266 364 341 498 165 569 336 + 374 650 285 215 188 307 115 307 450 551 409 224 154 249 458 301 345 0 + 432 822 722 582 881 697 441 566 629 854 690 1090 491 217 302 403 270 105 + 69 215 898 99 616 520 108 557 813 287 371 342 77 329 383 547 793 741 + 915 486 998 531 343 307 222 226 258 228 612 676 305 253 705 373 861 626 + 660 381 898 315 351 473 366 894 919 930 254 66 929 278 235 535 605 511 + 863 320 185 394 936 221 285 785 177 763 942 733 57 164 254 998 684 666 + 368 303 873 195 1005 647 1076 284 884 351 795 751 572 817 403 817 192 145 + 819 734 610 759 252 811 854 523 0 435 653 560 413 719 535 239 437 427 + 692 488 921 220 192 374 406 29 190 243 64 729 246 414 523 282 394 644 + 290 374 345 326 332 380 367 631 579 753 284 836 314 141 78 219 123 264 + 84 450 514 34 75 503 370 692 487 498 179 736 312 401 476 369 732 757 + 761 137 308 767 275 112 395 443 309 701 276 154 397 767 266 282 616 308 + 594 780 571 236 222 234 829 522 527 365 306 704 268 836 557 907 56 722 + 348 633 582 370 655 406 655 148 249 749 572 613 597 77 649 685 393 293 + 0 369 167 79 77 205 259 153 190 97 416 185 435 537 482 412 286 459 + 587 640 500 243 555 111 283 679 119 163 375 343 356 626 360 777 116 355 + 266 305 108 322 189 356 429 616 446 411 473 149 121 499 441 238 767 206 + 220 230 315 288 709 439 237 300 352 243 275 614 587 319 672 589 152 172 + 218 253 315 518 364 281 436 679 135 515 108 332 295 600 493 355 343 199 + 260 762 401 218 475 350 290 421 431 349 745 144 98 39 297 248 275 545 + 646 263 164 354 221 553 201 199 149 657 488 0 121 511 418 271 570 386 + 309 255 441 543 529 779 518 142 99 84 297 285 357 274 587 225 487 209 + 396 246 502 35 29 42 286 36 551 236 482 430 604 316 687 220 268 334 + 390 207 70 238 301 365 332 245 581 541 550 315 349 222 587 483 126 162 + 55 583 608 619 388 257 618 446 363 224 294 249 552 104 178 60 625 96 + 453 474 175 452 631 422 260 153 146 687 373 355 536 47 562 135 694 336 + 765 311 573 519 484 440 386 506 169 506 319 520 607 423 299 448 327 500 + 543 212 317 320 347 0 +DISPLAY_DATA_SECTION + 1 8.0 124.0 + 2 125.0 80.0 + 3 97.0 74.0 + 4 69.0 96.0 + 5 106.0 46.0 + 6 49.0 57.0 + 7 80.0 125.0 + 8 42.0 93.0 + 9 104.0 94.0 + 10 35.0 17.0 + 11 118.0 96.0 + 12 151.0 22.0 + 13 154.0 182.0 + 14 57.0 165.0 + 15 18.0 159.0 + 16 27.0 123.0 + 17 96.0 170.0 + 18 63.0 198.0 + 19 59.0 211.0 + 20 88.0 182.0 + 21 142.0 72.0 + 22 48.0 190.0 + 23 106.0 106.0 + 24 28.0 102.0 + 25 63.0 224.0 + 26 58.0 93.0 + 27 103.0 56.0 + 28 38.0 149.0 + 29 23.0 138.0 + 30 22.0 146.0 + 31 32.0 208.0 + 32 27.0 144.0 + 33 75.0 258.0 + 34 59.0 101.0 + 35 41.0 32.0 + 36 53.0 46.0 + 37 76.0 19.0 + 38 79.0 115.0 + 39 109.0 13.0 + 40 59.0 118.0 + 41 84.0 147.0 + 42 95.0 160.0 + 43 87.0 213.0 + 44 73.0 166.0 + 45 43.0 153.0 + 46 81.0 175.0 + 47 59.0 77.0 + 48 70.0 68.0 + 49 106.0 169.0 + 50 86.0 168.0 + 51 127.0 109.0 + 52 68.0 243.0 + 53 116.0 57.0 + 54 39.0 78.0 + 55 54.0 65.0 + 56 77.0 141.0 + 57 95.0 24.0 + 58 89.0 238.0 + 59 9.0 158.0 + 60 39.0 109.0 + 61 25.0 129.0 + 62 69.0 20.0 + 63 104.0 34.0 + 64 132.0 51.0 + 65 98.0 207.0 + 66 37.0 203.0 + 67 80.0 16.0 + 68 103.0 224.0 + 69 94.0 202.0 + 70 49.0 96.0 + 71 55.0 80.0 + 72 62.0 123.0 + 73 91.0 31.0 + 74 51.0 142.0 + 75 64.0 172.0 + 76 14.0 138.0 + 77 120.0 37.0 + 78 38.0 160.0 + 79 86.0 230.0 + 80 96.0 59.0 + 81 33.0 177.0 + 82 108.0 78.0 + 83 93.0 12.0 + 84 43.0 47.0 + 85 52.0 200.0 + 86 48.0 171.0 + 87 62.0 153.0 + 88 159.0 53.0 + 89 60.0 60.0 + 90 36.0 73.0 + 91 111.0 243.0 + 92 31.0 150.0 + 93 130.0 67.0 + 94 36.0 172.0 + 95 132.0 28.0 + 96 29.0 73.0 + 97 150.0 28.0 + 98 89.0 166.0 + 99 58.0 21.0 + 100 78.0 244.0 + 101 82.0 58.0 + 102 81.0 68.0 + 103 92.0 98.0 + 104 56.0 33.0 + 105 47.0 126.0 + 106 70.0 34.0 + 107 78.0 195.0 + 108 77.0 215.0 + 109 140.0 62.0 + 110 70.0 57.0 + 111 16.0 89.0 + 112 66.0 50.0 + 113 98.0 194.0 + 114 87.0 45.0 + 115 132.0 87.0 + 116 52.0 99.0 + 117 50.0 212.0 + 118 103.0 176.0 + 119 84.0 91.0 + 120 31.0 140.0 +EOF diff --git a/resources/3rdparty/glpk-4.57/examples/tsp/main.c b/resources/3rdparty/glpk-4.57/examples/tsp/main.c new file mode 100644 index 000000000..822af324a --- /dev/null +++ b/resources/3rdparty/glpk-4.57/examples/tsp/main.c @@ -0,0 +1,535 @@ +/* main.c */ + +/* Written by Andrew Makhorin , October 2015. */ + +/*********************************************************************** +* This program is a stand-alone solver intended for solving Symmetric +* Traveling Salesman Problem (TSP) with the branch-and-bound method. +* +* Please note that this program is only an illustrative example. It is +* *not* a state-of-the-art code, so only small TSP instances (perhaps, +* having up to 150-200 nodes) can be solved with this code. +* +* To run this program use the following command: +* +* tspsol tsp-file +* +* where tsp-file specifies an input text file containing TSP data in +* TSPLIB 95 format. +* +* Detailed description of the input format recognized by this program +* is given in the report: Gerhard Reinelt, "TSPLIB 95". This report as +* well as TSPLIB, a library of sample TSP instances (and other related +* problems), are freely available for research purposes at the webpage +* . +* +* Symmetric Traveling Salesman Problem +* ------------------------------------ +* Let a complete undirected graph be given: +* +* K = (V, E), (1) +* +* where V = {1, ..., n} is a set of nodes, E = V cross V is a set of +* edges. Let also each edge e = (i,j) be assigned a positive number +* c[i,j], which is the length of e. The Symmetric Traveling Salesman +* Problem (TSP) is to find a tour in K of minimal length. +* +* Integer programming formulation of TSP +* -------------------------------------- +* For a set of nodes W within V introduce the following notation: +* +* d(W) = {(i,j):i in W and j not in W or i not in W and j in W}, (2) +* +* i.e. d(W) is the set of edges which have exactly one endnode in W. +* If W = {v}, i.e. W consists of the only node, we write simply d(v). +* +* The integer programming formulation of TSP is the following: +* +* minimize sum c[i,j] * x[i,j] (3) +* i,j +* +* subject to sum x[i,j] = 2 for all v in V (4) +* (i,j) in d(v) +* +* sum x[i,j] >= 2 for all W within V, (5) +* (i,j) in d(W) W != empty, W != V +* +* x[i,j] in {0, 1} for all i, j (6) +* +* The binary variables x[i,j] have conventional meaning: if x[i,j] = 1, +* the edge (i,j) is included in the tour, otherwise, if x[i,j] = 0, the +* edge is not included in the tour. +* +* The constraints (4) are called degree constraints. They require that +* for each node v in V there must be exactly two edges included in the +* tour which are incident to v. +* +* The constraints (5) are called subtour elimination constraints. They +* are used to forbid subtours. Note that the number of the subtour +* elimination constraints grows exponentially on the size of the TSP +* instance, so these constraints are not included explicitly in the +* IP, but generated dynamically during the B&B search. +***********************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include +#include "maxflow.h" +#include "mincut.h" +#include "misc.h" +#include "tsplib.h" + +int n; +/* number of nodes in the problem, n >= 2 */ + +int *c; /* int c[1+n*(n-1)/2]; */ +/* upper triangle (without diagonal entries) of the (symmetric) matrix + * C = (c[i,j]) in row-wise format, where c[i,j] specifies a length of + * edge e = (i,j), 1 <= i < j <= n */ + +int *tour; /* int tour[1+n]; */ +/* solution to TSP, which is a tour specified by the list of node + * numbers tour[1] -> ... -> tour[nn] -> tour[1] in the order the nodes + * are visited; note that any tour is a permutation of node numbers */ + +glp_prob *P; +/* integer programming problem object */ + +/*********************************************************************** +* loc - determine reduced index of element of symmetric matrix +* +* Given indices i and j of an element of a symmetric nxn-matrix, +* 1 <= i, j <= n, i != j, this routine returns the index of that +* element in an array, which is the upper triangle (without diagonal +* entries) of the matrix in row-wise format. */ + +int loc(int i, int j) +{ xassert(1 <= i && i <= n); + xassert(1 <= j && j <= n); + xassert(i != j); + if (i < j) + return ((n - 1) + (n - i + 1)) * (i - 1) / 2 + (j - i); + else + return loc(j, i); +} + +/*********************************************************************** +* read_data - read TSP data +* +* This routine reads TSP data from a specified text file in TSPLIB 95 +* format. */ + +void read_data(const char *fname) +{ TSP *tsp; + int i, j; + tsp = tsp_read_data(fname); + if (tsp == NULL) + { xprintf("TSP data file processing error\n"); + exit(EXIT_FAILURE); + } + if (tsp->type != TSP_TSP) + { xprintf("Invalid TSP data type\n"); + exit(EXIT_FAILURE); + } + n = tsp->dimension; + xassert(n >= 2); + if (n > 32768) + { xprintf("TSP instance too large\n"); + exit(EXIT_FAILURE); + } + c = xalloc(1+loc(n-1, n), sizeof(int)); + for (i = 1; i <= n; i++) + { for (j = i+1; j <= n; j++) + c[loc(i, j)] = tsp_distance(tsp, i, j); + } + tsp_free_data(tsp); + return; +} + +/*********************************************************************** +* build_prob - build initial integer programming problem +* +* This routine builds the initial integer programming problem, which +* includes all variables (6), objective (3) and all degree constraints +* (4). Subtour elimination constraints (5) are considered "lazy" and +* not included in the initial problem. */ + +void build_prob(void) +{ int i, j, k, *ind; + double *val; + char name[50]; + /* create problem object */ + P = glp_create_prob(); + /* add all binary variables (6) */ + for (i = 1; i <= n; i++) + { for (j = i+1; j <= n; j++) + { k = glp_add_cols(P, 1); + xassert(k == loc(i,j)); + sprintf(name, "x[%d,%d]", i, j); + glp_set_col_name(P, k, name); + glp_set_col_kind(P, k, GLP_BV); + /* set objective coefficient (3) */ + glp_set_obj_coef(P, k, c[k]); + } + } + /* add all degree constraints (4) */ + ind = xalloc(1+n, sizeof(int)); + val = xalloc(1+n, sizeof(double)); + for (i = 1; i <= n; i++) + { k = glp_add_rows(P, 1); + xassert(k == i); + sprintf(name, "v[%d]", i); + glp_set_row_name(P, i, name); + glp_set_row_bnds(P, i, GLP_FX, 2, 2); + k = 0; + for (j = 1; j <= n; j++) + { if (i != j) + k++, ind[k] = loc(i,j), val[k] = 1; + } + xassert(k == n-1); + glp_set_mat_row(P, i, n-1, ind, val); + } + xfree(ind); + xfree(val); + return; +} + +/*********************************************************************** +* build_tour - build tour for corresponding solution to IP +* +* Given a feasible solution to IP (3)-(6) this routine builds the +* corresponding solution to TSP, which is a tour specified by the list +* of node numbers tour[1] -> ... -> tour[nn] -> tour[1] in the order +* the nodes are to be visited */ + +void build_tour(void) +{ int i, j, k, kk, *beg, *end; + /* solution to MIP should be feasible */ + switch (glp_mip_status(P)) + { case GLP_FEAS: + case GLP_OPT: + break; + default: + xassert(P != P); + } + /* build the list of edges included in the tour */ + beg = xalloc(1+n, sizeof(int)); + end = xalloc(1+n, sizeof(int)); + k = 0; + for (i = 1; i <= n; i++) + { for (j = i+1; j <= n; j++) + { double x; + x = glp_mip_col_val(P, loc(i,j)); + xassert(x == 0 || x == 1); + if (x) + { k++; + xassert(k <= n); + beg[k] = i, end[k] = j; + } + } + } + xassert(k == n); + /* reorder edges in the list as they follow in the tour */ + for (k = 1; k <= n; k++) + { /* find k-th edge of the tour */ + j = (k == 1 ? 1 : end[k-1]); + for (kk = k; kk <= n; kk++) + { if (beg[kk] == j) + break; + if (end[kk] == j) + { end[kk] = beg[kk], beg[kk] = j; + break; + } + } + xassert(kk <= n); + /* put the edge to k-th position in the list */ + i = beg[k], beg[k] = beg[kk], beg[kk] = i; + j = end[k], end[k] = end[kk], end[kk] = j; + } + /* build the tour starting from node 1 */ + xassert(beg[1] == 1); + for (k = 1; k <= n; k++) + { if (k > 1) + xassert(end[k-1] == beg[k]); + tour[k] = beg[k]; + } + xassert(end[n] == 1); + xfree(beg); + xfree(end); + return; +} + +/*********************************************************************** +* tour_length - calculate tour length +* +* This routine calculates the length of the specified tour, which is +* a sum of corresponding edge length. */ + +int tour_length(const int tour[/*1+n*/]) +{ int i, j, sum; + sum = 0; + for (i = 1; i <= n; i++) + { j = (i < n ? i+1 : 1); + sum += c[loc(tour[i], tour[j])]; + } + return sum; +} + +/*********************************************************************** +* write_tour - write tour to text file in TSPLIB format +* +* This routine writes the specified tour to a text file in TSPLIB +* format. */ + +void write_tour(const char *fname, const int tour[/*1+n*/]) +{ FILE *fp; + int i; + xprintf("Writing TSP solution to '%s'...\n", fname); + fp = fopen(fname, "w"); + if (fp == NULL) + { xprintf("Unable to create '%s' - %s\n", fname, + strerror(errno)); + return; + } + fprintf(fp, "NAME : %s\n", fname); + fprintf(fp, "COMMENT : Tour length is %d\n", tour_length(tour)); + fprintf(fp, "TYPE : TOUR\n"); + fprintf(fp, "DIMENSION : %d\n", n); + fprintf(fp, "TOUR_SECTION\n"); + for (i = 1; i <= n; i++) + fprintf(fp, "%d\n", tour[i]); + fprintf(fp, "-1\n"); + fprintf(fp, "EOF\n"); + fclose(fp); + return; +} + +/*********************************************************************** +* gen_subt_row - generate violated subtour elimination constraint +* +* This routine is called from the MIP solver to generate a violated +* subtour elimination constraint (5). +* +* Constraints of this class has the form: +* +* sum x[i,j] >= 2, i in W, j in V \ W, +* +* for all W, where W is a proper nonempty subset of V, V is the set of +* nodes of the given graph. +* +* In order to find a violated constraint of this class this routine +* finds a min cut in a capacitated network, which has the same sets of +* nodes and edges as the original graph, and where capacities of edges +* are values of variables x[i,j] in a basic solution to LP relaxation +* of the current subproblem. */ + +void gen_subt(glp_tree *T) +{ int i, j, ne, nz, *beg, *end, *cap, *cut, *ind; + double sum, *val; + /* MIP preprocessor should not be used */ + xassert(glp_ios_get_prob(T) == P); + /* if some variable x[i,j] is zero in basic solution, then the + * capacity of corresponding edge in the associated network is + * zero, so we may not include such edge in the network */ + /* count number of edges having non-zero capacity */ + ne = 0; + for (i = 1; i <= n; i++) + { for (j = i+1; j <= n; j++) + { if (glp_get_col_prim(P, loc(i,j)) >= .001) + ne++; + } + } + /* build the capacitated network */ + beg = xalloc(1+ne, sizeof(int)); + end = xalloc(1+ne, sizeof(int)); + cap = xalloc(1+ne, sizeof(int)); + nz = 0; + for (i = 1; i <= n; i++) + { for (j = i+1; j <= n; j++) + { if (glp_get_col_prim(P, loc(i,j)) >= .001) + { nz++; + xassert(nz <= ne); + beg[nz] = i, end[nz] = j; + /* scale all edge capacities to make them integral */ + cap[nz] = ceil(1000 * glp_get_col_prim(P, loc(i,j))); + } + } + } + xassert(nz == ne); + /* find minimal cut in the capacitated network */ + cut = xalloc(1+n, sizeof(int)); + min_cut(n, ne, beg, end, cap, cut); + /* determine the number of non-zero coefficients in the subtour + * elimination constraint and calculate its left-hand side which + * is the (unscaled) capacity of corresponding min cut */ + ne = 0, sum = 0; + for (i = 1; i <= n; i++) + { for (j = i+1; j <= n; j++) + { if (cut[i] && !cut[j] || !cut[i] && cut[j]) + { ne++; + sum += glp_get_col_prim(P, loc(i,j)); + } + } + } + /* if the (unscaled) capacity of min cut is less than 2, the + * corresponding subtour elimination constraint is violated */ + if (sum <= 1.999) + { /* build the list of non-zero coefficients */ + ind = xalloc(1+ne, sizeof(int)); + val = xalloc(1+ne, sizeof(double)); + nz = 0; + for (i = 1; i <= n; i++) + { for (j = i+1; j <= n; j++) + { if (cut[i] && !cut[j] || !cut[i] && cut[j]) + { nz++; + xassert(nz <= ne); + ind[nz] = loc(i,j); + val[nz] = 1; + } + } + } + xassert(nz == ne); + /* add violated tour elimination constraint to the current + * subproblem */ + i = glp_add_rows(P, 1); + glp_set_row_bnds(P, i, GLP_LO, 2, 0); + glp_set_mat_row(P, i, nz, ind, val); + xfree(ind); + xfree(val); + } + /* free working arrays */ + xfree(beg); + xfree(end); + xfree(cap); + xfree(cut); + return; +} + +/*********************************************************************** +* cb_func - application callback routine +* +* This routine is called from the MIP solver at various points of +* the branch-and-cut algorithm. */ + +void cb_func(glp_tree *T, void *info) +{ xassert(info == info); + switch (glp_ios_reason(T)) + { case GLP_IROWGEN: + /* generate one violated subtour elimination constraint */ + gen_subt(T); + break; + } + return; +} + +/*********************************************************************** +* main - TSP solver main program +* +* This main program parses command-line arguments, reads specified TSP +* instance from a text file, and calls the MIP solver to solve it. */ + +int main(int argc, char *argv[]) +{ int j; + char *in_file = NULL, *out_file = NULL; + time_t start; + glp_iocp iocp; + /* parse command-line arguments */ +# define p(str) (strcmp(argv[j], str) == 0) + for (j = 1; j < argc; j++) + { if (p("--output") || p("-o")) + { j++; + if (j == argc || argv[j][0] == '\0' || argv[j][0] == '-') + { xprintf("No solution output file specified\n"); + exit(EXIT_FAILURE); + } + if (out_file != NULL) + { xprintf("Only one solution output file allowed\n"); + exit(EXIT_FAILURE); + } + out_file = argv[j]; + } + else if (p("--help") || p("-h")) + { xprintf("Usage: %s [options...] tsp-file\n", argv[0]); + xprintf("\n"); + xprintf("Options:\n"); + xprintf(" -o filename, --output filename\n"); + xprintf(" write solution to filename\n") + ; + xprintf(" -h, --help display this help information" + " and exit\n"); + exit(EXIT_SUCCESS); + } + else if (argv[j][0] == '-' || + (argv[j][0] == '-' && argv[j][1] == '-')) + { xprintf("Invalid option '%s'; try %s --help\n", argv[j], + argv[0]); + exit(EXIT_FAILURE); + } + else + { if (in_file != NULL) + { xprintf("Only one input file allowed\n"); + exit(EXIT_FAILURE); + } + in_file = argv[j]; + } + } + if (in_file == NULL) + { xprintf("No input file specified; try %s --help\n", argv[0]); + exit(EXIT_FAILURE); + } +# undef p + /* display program banner */ + xprintf("TSP Solver for GLPK %s\n", glp_version()); + /* remove output solution file specified in command-line */ + if (out_file != NULL) + remove(out_file); + /* read TSP instance from input data file */ + read_data(in_file); + /* build initial IP problem */ + start = time(NULL); + build_prob(); + tour = xalloc(1+n, sizeof(int)); + /* solve LP relaxation of initial IP problem */ + xprintf("Solving initial LP relaxation...\n"); + xassert(glp_simplex(P, NULL) == 0); + xassert(glp_get_status(P) == GLP_OPT); + /* solve IP problem with "lazy" constraints */ + glp_init_iocp(&iocp); + iocp.br_tech = GLP_BR_MFV; /* most fractional variable */ + iocp.bt_tech = GLP_BT_BLB; /* best local bound */ + iocp.sr_heur = GLP_OFF; /* disable simple rounding heuristic */ + iocp.gmi_cuts = GLP_ON; /* enable Gomory cuts */ + iocp.cb_func = cb_func; + glp_intopt(P, &iocp); + build_tour(); + /* display some statistics */ + xprintf("Time used: %.1f secs\n", difftime(time(NULL), start)); + { size_t tpeak; + glp_mem_usage(NULL, NULL, NULL, &tpeak); + xprintf("Memory used: %.1f Mb (%.0f bytes)\n", + (double)tpeak / 1048576.0, (double)tpeak); + } + /* write solution to output file, if required */ + if (out_file != NULL) + write_tour(out_file, tour); + /* deallocate working objects */ + xfree(c); + xfree(tour); + glp_delete_prob(P); + /* check that no memory blocks are still allocated */ + { int count; + size_t total; + glp_mem_usage(&count, NULL, &total, NULL); + if (count != 0) + xerror("Error: %d memory block(s) were lost\n", count); + xassert(total == 0); + } + return 0; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.57/examples/tsp/maxflow.c b/resources/3rdparty/glpk-4.57/examples/tsp/maxflow.c new file mode 100644 index 000000000..c28f5274d --- /dev/null +++ b/resources/3rdparty/glpk-4.57/examples/tsp/maxflow.c @@ -0,0 +1,170 @@ +/* maxflow.c */ + +/* Written by Andrew Makhorin , October 2015. */ + +#include + +#include +#include "maxflow.h" +#include "misc.h" + +/*********************************************************************** +* NAME +* +* max_flow - find max flow in undirected capacitated network +* +* SYNOPSIS +* +* #include "maxflow.h" +* int max_flow(int nn, int ne, const int beg[], const int end[], +* const int cap[], int s, int t, int x[]); +* +* DESCRIPTION +* +* This routine finds max flow in a given undirected network. +* +* The undirected capacitated network is specified by the parameters +* nn, ne, beg, end, and cap. The parameter nn specifies the number of +* vertices (nodes), nn >= 2, and the parameter ne specifies the number +* of edges, ne >= 0. The network edges are specified by triplets +* (beg[k], end[k], cap[k]) for k = 1, ..., ne, where beg[k] < end[k] +* are numbers of the first and second nodes of k-th edge, and +* cap[k] > 0 is a capacity of k-th edge. Loops and multiple edges are +* not allowed. +* +* The parameter s is the number of a source node, and the parameter t +* is the number of a sink node, s != t. +* +* On exit the routine computes elementary flows thru edges and stores +* their values to locations x[1], ..., x[ne]. Positive value of x[k] +* means that the elementary flow goes from node beg[k] to node end[k], +* and negative value means that the flow goes in opposite direction. +* +* RETURNS +* +* The routine returns the total maximum flow through the network. */ + +int max_flow(int nn, int ne, const int beg[/*1+ne*/], + const int end[/*1+ne*/], const int cap[/*1+ne*/], int s, int t, + int x[/*1+ne*/]) +{ int k; + /* sanity checks */ + xassert(nn >= 2); + xassert(ne >= 0); + xassert(1 <= s && s <= nn); + xassert(1 <= t && t <= nn); + xassert(s != t); + for (k = 1; k <= ne; k++) + { xassert(1 <= beg[k] && beg[k] < end[k] && end[k] <= nn); + xassert(cap[k] > 0); + } + /* find max flow */ + return max_flow_lp(nn, ne, beg, end, cap, s, t, x); +} + +/*********************************************************************** +* NAME +* +* max_flow_lp - find max flow with simplex method +* +* SYNOPSIS +* +* #include "maxflow.h" +* int max_flow_lp(int nn, int ne, const int beg[], const int end[], +* const int cap[], int s, int t, int x[]); +* +* DESCRIPTION +* +* This routine finds max flow in a given undirected network with the +* simplex method. +* +* Parameters of this routine have the same meaning as for the routine +* max_flow (see above). +* +* RETURNS +* +* The routine returns the total maximum flow through the network. */ + +int max_flow_lp(int nn, int ne, const int beg[/*1+ne*/], + const int end[/*1+ne*/], const int cap[/*1+ne*/], int s, int t, + int x[/*1+ne*/]) +{ glp_prob *lp; + glp_smcp smcp; + int i, k, nz, flow, *rn, *cn; + double temp, *aa; + /* create LP problem instance */ + lp = glp_create_prob(); + /* create LP rows; i-th row is the conservation condition of the + * flow at i-th node, i = 1, ..., nn */ + glp_add_rows(lp, nn); + for (i = 1; i <= nn; i++) + glp_set_row_bnds(lp, i, GLP_FX, 0.0, 0.0); + /* create LP columns; k-th column is the elementary flow thru + * k-th edge, k = 1, ..., ne; the last column with the number + * ne+1 is the total flow through the network, which goes along + * a dummy feedback edge from the sink to the source */ + glp_add_cols(lp, ne+1); + for (k = 1; k <= ne; k++) + { xassert(cap[k] > 0); + glp_set_col_bnds(lp, k, GLP_DB, -cap[k], +cap[k]); + } + glp_set_col_bnds(lp, ne+1, GLP_FR, 0.0, 0.0); + /* build the constraint matrix; structurally this matrix is the + * incidence matrix of the network, so each its column (including + * the last column for the dummy edge) has exactly two non-zero + * entries */ + rn = xalloc(1+2*(ne+1), sizeof(int)); + cn = xalloc(1+2*(ne+1), sizeof(int)); + aa = xalloc(1+2*(ne+1), sizeof(double)); + nz = 0; + for (k = 1; k <= ne; k++) + { /* x[k] > 0 means the elementary flow thru k-th edge goes from + * node beg[k] to node end[k] */ + nz++, rn[nz] = beg[k], cn[nz] = k, aa[nz] = -1.0; + nz++, rn[nz] = end[k], cn[nz] = k, aa[nz] = +1.0; + } + /* total flow thru the network goes from the sink to the source + * along the dummy feedback edge */ + nz++, rn[nz] = t, cn[nz] = ne+1, aa[nz] = -1.0; + nz++, rn[nz] = s, cn[nz] = ne+1, aa[nz] = +1.0; + /* check the number of non-zero entries */ + xassert(nz == 2*(ne+1)); + /* load the constraint matrix into the LP problem object */ + glp_load_matrix(lp, nz, rn, cn, aa); + xfree(rn); + xfree(cn); + xfree(aa); + /* objective function is the total flow through the network to + * be maximized */ + glp_set_obj_dir(lp, GLP_MAX); + glp_set_obj_coef(lp, ne + 1, 1.0); + /* solve LP instance with the (primal) simplex method */ + glp_term_out(0); + glp_adv_basis(lp, 0); + glp_term_out(1); + glp_init_smcp(&smcp); + smcp.msg_lev = GLP_MSG_ON; + smcp.out_dly = 5000; + xassert(glp_simplex(lp, &smcp) == 0); + xassert(glp_get_status(lp) == GLP_OPT); + /* obtain optimal elementary flows thru edges of the network */ + /* (note that the constraint matrix is unimodular and the data + * are integral, so all elementary flows in basic solution should + * also be integral) */ + for (k = 1; k <= ne; k++) + { temp = glp_get_col_prim(lp, k); + x[k] = (int)floor(temp + .5); + xassert(fabs(x[k] - temp) <= 1e-6); + } + /* obtain the maximum flow thru the original network which is the + * flow thru the dummy feedback edge */ + temp = glp_get_col_prim(lp, ne+1); + flow = (int)floor(temp + .5); + xassert(fabs(flow - temp) <= 1e-6); + /* delete LP problem instance */ + glp_delete_prob(lp); + /* return to the calling program */ + return flow; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.57/examples/tsp/maxflow.h b/resources/3rdparty/glpk-4.57/examples/tsp/maxflow.h new file mode 100644 index 000000000..245c5ec12 --- /dev/null +++ b/resources/3rdparty/glpk-4.57/examples/tsp/maxflow.h @@ -0,0 +1,20 @@ +/* maxflow.h */ + +/* Written by Andrew Makhorin , October 2015. */ + +#ifndef MAXFLOW_H +#define MAXFLOW_H + +int max_flow(int nn, int ne, const int beg[/*1+ne*/], + const int end[/*1+ne*/], const int cap[/*1+ne*/], int s, int t, + int x[/*1+ne*/]); +/* find max flow in undirected capacitated network */ + +int max_flow_lp(int nn, int ne, const int beg[/*1+ne*/], + const int end[/*1+ne*/], const int cap[/*1+ne*/], int s, int t, + int x[/*1+ne*/]); +/* find max flow with simplex method */ + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.57/examples/tsp/mincut.c b/resources/3rdparty/glpk-4.57/examples/tsp/mincut.c new file mode 100644 index 000000000..46905aa0e --- /dev/null +++ b/resources/3rdparty/glpk-4.57/examples/tsp/mincut.c @@ -0,0 +1,392 @@ +/* mincut.c */ + +/* Written by Andrew Makhorin , October 2015. */ + +#include + +#include "maxflow.h" +#include "mincut.h" +#include "misc.h" + +/*********************************************************************** +* NAME +* +* min_cut - find min cut in undirected capacitated network +* +* SYNOPSIS +* +* #include "mincut.h" +* int min_cut(int nn, int ne, const int beg[], const int end[], +* const cap[], int cut[]); +* +* DESCRIPTION +* +* This routine find min cut in a given undirected network. +* +* The undirected capacitated network is specified by the parameters +* nn, ne, beg, end, and cap. The parameter nn specifies the number of +* vertices (nodes), nn >= 2, and the parameter ne specifies the number +* of edges, ne >= 0. The network edges are specified by triplets +* (beg[k], end[k], cap[k]) for k = 1, ..., ne, where beg[k] < end[k] +* are numbers of the first and second nodes of k-th edge, and +* cap[k] > 0 is a capacity of k-th edge. Loops and multiple edges are +* not allowed. +* +* Let V be the set of nodes of the network and let W be an arbitrary +* non-empty proper subset of V. A cut associated with the subset W is +* a subset of all the edges, one node of which belongs to W and other +* node belongs to V \ W. The capacity of a cut (W, V \ W) is the sum +* of the capacities of all the edges, which belong to the cut. Minimal +* cut is a cut, whose capacity is minimal. +* +* On exit the routine stores flags of nodes v[i], i = 1, ..., nn, to +* locations cut[i], where cut[i] = 1 means that v[i] belongs to W and +* cut[i] = 0 means that v[i] belongs to V \ W, where W corresponds to +* the minimal cut found. +* +* RETURNS +* +* The routine returns the capacity of the min cut found. */ + +int min_cut(int nn, int ne, const int beg[/*1+ne*/], + const int end[/*1+ne*/], const cap[/*1+ne*/], int cut[/*1+nn*/]) +{ int k; + /* sanity checks */ + xassert(nn >= 2); + xassert(ne >= 0); + for (k = 1; k <= ne; k++) + { xassert(1 <= beg[k] && beg[k] < end[k] && end[k] <= nn); + xassert(cap[k] > 0); + } + /* find min cut */ + return min_cut_sw(nn, ne, beg, end, cap, cut); +} + +/*********************************************************************** +* NAME +* +* min_st_cut - find min (s,t)-cut for known max flow +* +* SYNOPSIS +* +* #include "mincut.h" +* +* DESCRIPTION +* +* This routine finds min (s,t)-cut in a given undirected network that +* corresponds to a known max flow from s to t in the network. +* +* Parameters nn, ne, beg, end, and cap specify the network in the same +* way as for the routine min_cut (see above). +* +* Parameters s and t specify, resp., the number of the source node +* and the number of the sink node, s != t, for which the min (s,t)-cut +* has to be found. +* +* Parameter x specifies the known max flow from s to t in the network, +* where locations x[1], ..., x[ne] contains elementary flow thru edges +* of the network (positive value of x[k] means that the elementary +* flow goes from node beg[k] to node end[k], and negative value means +* that the flow goes in opposite direction). +* +* This routine splits the set of nodes V of the network into two +* non-empty subsets V(s) and V(t) = V \ V(s), where the source node s +* belongs to V(s), the sink node t belongs to V(t), and all edges, one +* node of which belongs to V(s) and other one belongs to V(t), are +* saturated (that is, x[k] = +cap[k] or x[k] = -cap[k]). +* +* On exit the routine stores flags of the nodes v[i], i = 1, ..., nn, +* to locations cut[i], where cut[i] = 1 means that v[i] belongs to V(s) +* and cut[i] = 0 means that v[i] belongs to V(t) = V \ V(s). +* +* RETURNS +* +* The routine returns the capacity of min (s,t)-cut, which is the sum +* of the capacities of all the edges, which belong to the cut. (Note +* that due to theorem by Ford and Fulkerson this value is always equal +* to corresponding max flow.) +* +* ALGORITHM +* +* To determine the set V(s) the routine simply finds all nodes, which +* can be reached from the source node s via non-saturated edges. The +* set V(t) is determined as the complement V \ V(s). */ + +int min_st_cut(int nn, int ne, const int beg[/*1+ne*/], + const int end[/*1+ne*/], const int cap[/*1+ne*/], int s, int t, + const int x[/*1+ne*/], int cut[/*1+nn*/]) +{ int i, j, k, p, q, temp, *head1, *next1, *head2, *next2, *list; + /* head1[i] points to the first edge with beg[k] = i + * next1[k] points to the next edge with the same beg[k] + * head2[i] points to the first edge with end[k] = i + * next2[k] points to the next edge with the same end[k] */ + head1 = xalloc(1+nn, sizeof(int)); + head2 = xalloc(1+nn, sizeof(int)); + next1 = xalloc(1+ne, sizeof(int)); + next2 = xalloc(1+ne, sizeof(int)); + for (i = 1; i <= nn; i++) + head1[i] = head2[i] = 0; + for (k = 1; k <= ne; k++) + { i = beg[k], next1[k] = head1[i], head1[i] = k; + j = end[k], next2[k] = head2[j], head2[j] = k; + } + /* on constructing the set V(s) list[1], ..., list[p-1] contain + * nodes, which can be reached from source node and have been + * visited, and list[p], ..., list[q] contain nodes, which can be + * reached from source node but havn't been visited yet */ + list = xalloc(1+nn, sizeof(int)); + for (i = 1; i <= nn; i++) + cut[i] = 0; + p = q = 1, list[1] = s, cut[s] = 1; + while (p <= q) + { /* pick next node, which is reachable from the source node and + * has not visited yet, and visit it */ + i = list[p++]; + /* walk through edges with beg[k] = i */ + for (k = head1[i]; k != 0; k = next1[k]) + { j = end[k]; + xassert(beg[k] == i); + /* from v[i] we can reach v[j], if the elementary flow from + * v[i] to v[j] is non-saturated */ + if (cut[j] == 0 && x[k] < +cap[k]) + list[++q] = j, cut[j] = 1; + } + /* walk through edges with end[k] = i */ + for (k = head2[i]; k != 0; k = next2[k]) + { j = beg[k]; + xassert(end[k] == i); + /* from v[i] we can reach v[j], if the elementary flow from + * v[i] to v[j] is non-saturated */ + if (cut[j] == 0 && x[k] > -cap[k]) + list[++q] = j, cut[j] = 1; + } + } + /* sink cannot belong to V(s) */ + xassert(!cut[t]); + /* free working arrays */ + xfree(head1); + xfree(head2); + xfree(next1); + xfree(next2); + xfree(list); + /* compute capacity of the minimal (s,t)-cut found */ + temp = 0; + for (k = 1; k <= ne; k++) + { i = beg[k], j = end[k]; + if (cut[i] && !cut[j] || !cut[i] && cut[j]) + temp += cap[k]; + } + /* return to the calling program */ + return temp; +} + +/*********************************************************************** +* NAME +* +* min_cut_sw - find min cut with Stoer and Wagner algorithm +* +* SYNOPSIS +* +* #include "mincut.h" +* int min_cut_sw(int nn, int ne, const int beg[], const int end[], +* const cap[], int cut[]); +* +* DESCRIPTION +* +* This routine find min cut in a given undirected network with the +* algorithm proposed by Stoer and Wagner (see references below). +* +* Parameters of this routine have the same meaning as for the routine +* min_cut (see above). +* +* RETURNS +* +* The routine returns the capacity of the min cut found. +* +* ALGORITHM +* +* The basic idea of Stoer&Wagner algorithm is the following. Let G be +* a capacitated network, and G(s,t) be a network, in which the nodes s +* and t are merged into one new node, loops are deleted, but multuple +* edges are retained. It is obvious that a minimum cut in G is the +* minimum of two quantities: the minimum cut in G(s,t) and a minimum +* cut that separates s and t. This allows to find a minimum cut in the +* original network solving at most nn max flow problems. +* +* REFERENCES +* +* M. Stoer, F. Wagner. A Simple Min Cut Algorithm. Algorithms, ESA'94 +* LNCS 855 (1994), pp. 141-47. +* +* J. Cheriyan, R. Ravi. Approximation Algorithms for Network Problems. +* Univ. of Waterloo (1998), p. 147. */ + +int min_cut_sw(int nn, int ne, const int beg[/*1+ne*/], + const int end[/*1+ne*/], const cap[/*1+ne*/], int cut[/*1+nn*/]) +{ int i, j, k, min_cut, flow, temp, *head1, *next1, *head2, *next2; + int I, J, K, S, T, DEG, NV, NE, *HEAD, *NEXT, *NUMB, *BEG, *END, + *CAP, *X, *ADJ, *SUM, *CUT; + /* head1[i] points to the first edge with beg[k] = i + * next1[k] points to the next edge with the same beg[k] + * head2[i] points to the first edge with end[k] = i + * next2[k] points to the next edge with the same end[k] */ + head1 = xalloc(1+nn, sizeof(int)); + head2 = xalloc(1+nn, sizeof(int)); + next1 = xalloc(1+ne, sizeof(int)); + next2 = xalloc(1+ne, sizeof(int)); + for (i = 1; i <= nn; i++) + head1[i] = head2[i] = 0; + for (k = 1; k <= ne; k++) + { i = beg[k], next1[k] = head1[i], head1[i] = k; + j = end[k], next2[k] = head2[j], head2[j] = k; + } + /* an auxiliary network used in the algorithm is resulted from + * the original network by merging some nodes into one supernode; + * all variables and arrays related to this auxiliary network are + * denoted in CAPS */ + /* HEAD[I] points to the first node of the original network that + * belongs to the I-th supernode + * NEXT[i] points to the next node of the original network that + * belongs to the same supernode as the i-th node + * NUMB[i] is a supernode, which the i-th node belongs to */ + /* initially the auxiliary network is equivalent to the original + * network, i.e. each supernode consists of one node */ + NV = nn; + HEAD = xalloc(1+nn, sizeof(int)); + NEXT = xalloc(1+nn, sizeof(int)); + NUMB = xalloc(1+nn, sizeof(int)); + for (i = 1; i <= nn; i++) + HEAD[i] = i, NEXT[i] = 0, NUMB[i] = i; + /* number of edges in the auxiliary network is never greater than + * in the original one */ + BEG = xalloc(1+ne, sizeof(int)); + END = xalloc(1+ne, sizeof(int)); + CAP = xalloc(1+ne, sizeof(int)); + X = xalloc(1+ne, sizeof(int)); + /* allocate some auxiliary arrays */ + ADJ = xalloc(1+nn, sizeof(int)); + SUM = xalloc(1+nn, sizeof(int)); + CUT = xalloc(1+nn, sizeof(int)); + /* currently no min cut is found so far */ + min_cut = INT_MAX; + /* main loop starts here */ + while (NV > 1) + { /* build the set of edges of the auxiliary network */ + NE = 0; + /* multiple edges are not allowed in the max flow algorithm, + * so we can replace each multiple edge, which is the result + * of merging nodes into supernodes, by a single edge, whose + * capacity is the sum of capacities of particular edges; + * these summary capacities will be stored in the array SUM */ + for (I = 1; I <= NV; I++) + SUM[I] = 0.0; + for (I = 1; I <= NV; I++) + { /* DEG is number of single edges, which connects I-th + * supernode and some J-th supernode, where I < J */ + DEG = 0; + /* walk thru nodes that belong to I-th supernode */ + for (i = HEAD[I]; i != 0; i = NEXT[i]) + { /* i-th node belongs to I-th supernode */ + /* walk through edges with beg[k] = i */ + for (k = head1[i]; k != 0; k = next1[k]) + { j = end[k]; + /* j-th node belongs to J-th supernode */ + J = NUMB[j]; + /* ignore loops and edges with I > J */ + if (I >= J) + continue; + /* add an edge that connects I-th and J-th supernodes + * (if not added yet) */ + if (SUM[J] == 0.0) + ADJ[++DEG] = J; + /* sum up the capacity of the original edge */ + xassert(cap[k] > 0.0); + SUM[J] += cap[k]; + } + /* walk through edges with end[k] = i */ + for (k = head2[i]; k != 0; k = next2[k]) + { j = beg[k]; + /* j-th node belongs to J-th supernode */ + J = NUMB[j]; + /* ignore loops and edges with I > J */ + if (I >= J) + continue; + /* add an edge that connects I-th and J-th supernodes + * (if not added yet) */ + if (SUM[J] == 0.0) + ADJ[++DEG] = J; + /* sum up the capacity of the original edge */ + xassert(cap[k] > 0.0); + SUM[J] += cap[k]; + } + } + /* add single edges connecting I-th supernode with other + * supernodes to the auxiliary network; restore the array + * SUM for subsequent use */ + for (K = 1; K <= DEG; K++) + { NE++; + xassert(NE <= ne); + J = ADJ[K]; + BEG[NE] = I, END[NE] = J, CAP[NE] = SUM[J]; + SUM[J] = 0.0; + } + } + /* choose two arbitrary supernodes of the auxiliary network, + * one of which is the source and other is the sink */ + S = 1, T = NV; + /* determine max flow from S to T */ + flow = max_flow(NV, NE, BEG, END, CAP, S, T, X); + /* if the min cut that separates supernodes S and T is less + * than the currently known, remember it */ + if (min_cut > flow) + { min_cut = flow; + /* find min (s,t)-cut in the auxiliary network */ + temp = min_st_cut(NV, NE, BEG, END, CAP, S, T, X, CUT); + /* (Ford and Fulkerson insist on this) */ + xassert(flow == temp); + /* build corresponding min cut in the original network */ + for (i = 1; i <= nn; i++) cut[i] = CUT[NUMB[i]]; + /* if the min cut capacity is zero (i.e. the network has + * unconnected components), the search can be prematurely + * terminated */ + if (min_cut == 0) + break; + } + /* now merge all nodes of the original network, which belong + * to the supernodes S and T, into one new supernode; this is + * attained by carrying all nodes from T to S (for the sake of + * convenience T should be the last supernode) */ + xassert(T == NV); + /* assign new references to nodes from T */ + for (i = HEAD[T]; i != 0; i = NEXT[i]) + NUMB[i] = S; + /* find last entry in the node list of S */ + i = HEAD[S]; + xassert(i != 0); + while (NEXT[i] != 0) + i = NEXT[i]; + /* and attach to it the node list of T */ + NEXT[i] = HEAD[T]; + /* decrease number of nodes in the auxiliary network */ + NV--; + } + /* free working arrays */ + xfree(HEAD); + xfree(NEXT); + xfree(NUMB); + xfree(BEG); + xfree(END); + xfree(CAP); + xfree(X); + xfree(ADJ); + xfree(SUM); + xfree(CUT); + xfree(head1); + xfree(head2); + xfree(next1); + xfree(next2); + /* return to the calling program */ + return min_cut; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.57/examples/tsp/mincut.h b/resources/3rdparty/glpk-4.57/examples/tsp/mincut.h new file mode 100644 index 000000000..aefdbb7dd --- /dev/null +++ b/resources/3rdparty/glpk-4.57/examples/tsp/mincut.h @@ -0,0 +1,23 @@ +/* mincut.c */ + +/* Written by Andrew Makhorin , October 2015. */ + +#ifndef MINCUT_H +#define MINCUT_H + +int min_cut(int nn, int ne, const int beg[/*1+ne*/], + const int end[/*1+ne*/], const cap[/*1+ne*/], int cut[/*1+nn*/]); +/* find min cut in undirected capacitated network */ + +int min_st_cut(int nn, int ne, const int beg[/*1+ne*/], + const int end[/*1+ne*/], const int cap[/*1+ne*/], int s, int t, + const int x[/*1+ne*/], int cut[/*1+nn*/]); +/* find min (s,t)-cut for known max flow */ + +int min_cut_sw(int nn, int ne, const int beg[/*1+ne*/], + const int end[/*1+ne*/], const cap[/*1+ne*/], int cut[/*1+nn*/]); +/* find min cut with Stoer and Wagner algorithm */ + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.57/examples/tsp/misc.c b/resources/3rdparty/glpk-4.57/examples/tsp/misc.c new file mode 100644 index 000000000..e0b08fb5b --- /dev/null +++ b/resources/3rdparty/glpk-4.57/examples/tsp/misc.c @@ -0,0 +1,159 @@ +/* misc.c */ + +/* Written by Andrew Makhorin , October 2015. */ + +#include +#include +#include +#include +#include "misc.h" + +/*********************************************************************** +* NAME +* +* str2int - convert character string to value of int type +* +* SYNOPSIS +* +* #include "misc.h" +* int str2int(const char *str, int *val); +* +* DESCRIPTION +* +* The routine str2int converts the character string str to a value of +* integer type and stores the value into location, which the parameter +* val points to (in the case of error content of this location is not +* changed). +* +* RETURNS +* +* The routine returns one of the following error codes: +* +* 0 - no error; +* 1 - value out of range; +* 2 - character string is syntactically incorrect. */ + +int str2int(const char *str, int *val_) +{ int d, k, s, val = 0; + /* scan optional sign */ + if (str[0] == '+') + s = +1, k = 1; + else if (str[0] == '-') + s = -1, k = 1; + else + s = +1, k = 0; + /* check for the first digit */ + if (!isdigit((unsigned char)str[k])) + return 2; + /* scan digits */ + while (isdigit((unsigned char)str[k])) + { d = str[k++] - '0'; + if (s > 0) + { if (val > INT_MAX / 10) + return 1; + val *= 10; + if (val > INT_MAX - d) + return 1; + val += d; + } + else /* s < 0 */ + { if (val < INT_MIN / 10) + return 1; + val *= 10; + if (val < INT_MIN + d) + return 1; + val -= d; + } + } + /* check for terminator */ + if (str[k] != '\0') + return 2; + /* conversion has been done */ + *val_ = val; + return 0; +} + +/*********************************************************************** +* NAME +* +* str2num - convert character string to value of double type +* +* SYNOPSIS +* +* #include "misc.h" +* int str2num(const char *str, double *val); +* +* DESCRIPTION +* +* The routine str2num converts the character string str to a value of +* double type and stores the value into location, which the parameter +* val points to (in the case of error content of this location is not +* changed). +* +* RETURNS +* +* The routine returns one of the following error codes: +* +* 0 - no error; +* 1 - value out of range; +* 2 - character string is syntactically incorrect. */ + +int str2num(const char *str, double *val_) +{ int k; + double val; + /* scan optional sign */ + k = (str[0] == '+' || str[0] == '-' ? 1 : 0); + /* check for decimal point */ + if (str[k] == '.') + { k++; + /* a digit should follow it */ + if (!isdigit((unsigned char)str[k])) + return 2; + k++; + goto frac; + } + /* integer part should start with a digit */ + if (!isdigit((unsigned char)str[k])) + return 2; + /* scan integer part */ + while (isdigit((unsigned char)str[k])) + k++; + /* check for decimal point */ + if (str[k] == '.') k++; +frac: /* scan optional fraction part */ + while (isdigit((unsigned char)str[k])) + k++; + /* check for decimal exponent */ + if (str[k] == 'E' || str[k] == 'e') + { k++; + /* scan optional sign */ + if (str[k] == '+' || str[k] == '-') + k++; + /* a digit should follow E, E+ or E- */ + if (!isdigit((unsigned char)str[k])) + return 2; + } + /* scan optional exponent part */ + while (isdigit((unsigned char)str[k])) + k++; + /* check for terminator */ + if (str[k] != '\0') + return 2; + /* perform conversion */ + { char *endptr; + val = strtod(str, &endptr); + if (*endptr != '\0') + return 2; + } + /* check for overflow */ + if (!(-DBL_MAX <= val && val <= +DBL_MAX)) + return 1; + /* check for underflow */ + if (-DBL_MIN < val && val < +DBL_MIN) + val = 0.0; + /* conversion has been done */ + *val_ = val; + return 0; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.57/examples/tsp/misc.h b/resources/3rdparty/glpk-4.57/examples/tsp/misc.h new file mode 100644 index 000000000..097383157 --- /dev/null +++ b/resources/3rdparty/glpk-4.57/examples/tsp/misc.h @@ -0,0 +1,24 @@ +/* misc.h */ + +/* Written by Andrew Makhorin , October 2015. */ + +#ifndef MISC_H +#define MISC_H + +#include + +#define xprintf glp_printf +#define xerror glp_error +#define xassert glp_assert +#define xalloc glp_alloc +#define xfree glp_free + +int str2int(const char *str, int *val); +/* convert character string to value of int type */ + +int str2num(const char *str, double *val); +/* convert character string to value of double type */ + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.57/examples/tsp/moscow.tsp b/resources/3rdparty/glpk-4.57/examples/tsp/moscow.tsp new file mode 100644 index 000000000..a2d4ea2fa --- /dev/null +++ b/resources/3rdparty/glpk-4.57/examples/tsp/moscow.tsp @@ -0,0 +1,200 @@ +NAME: MOSCOW +TYPE: TSP +COMMENT: 68 cities in Moscow region (Andrew Makhorin ) +DIMENSION: 68 +EDGE_WEIGHT_TYPE: EXPLICIT +EDGE_WEIGHT_FORMAT: LOWER_DIAG_ROW +EDGE_WEIGHT_SECTION +0 +80 0 +99 66 0 +73 153 156 0 +118 156 205 116 0 +136 103 37 190 242 0 +134 128 180 141 90 217 0 +72 75 127 126 81 164 86 0 +131 94 146 184 133 183 67 91 0 +75 38 90 136 126 127 94 45 56 0 +67 52 46 124 169 83 165 88 132 76 0 +134 66 69 207 219 68 189 138 136 101 106 0 +179 142 194 204 153 231 87 139 52 104 180 188 0 +145 98 63 216 240 26 212 159 178 122 109 53 226 0 +83 7 69 156 159 106 131 78 97 41 55 60 145 95 0 +85 38 68 158 180 105 152 99 118 62 57 74 166 100 41 0 +188 163 97 222 294 77 277 223 243 187 135 145 291 93 166 165 0 +38 101 125 92 80 162 96 34 101 71 93 164 149 176 104 116 214 0 +88 66 118 142 97 155 62 40 67 36 103 129 115 150 69 90 215 50 0 +113 50 102 174 164 139 136 83 92 46 88 94 140 134 53 74 199 109 74 0 +67 94 146 113 62 183 81 19 86 64 107 157 134 178 97 118 242 29 35 102 0 +133 132 96 167 239 91 245 168 212 156 80 159 260 117 135 137 55 159 183 + 168 187 0 +51 64 54 108 157 91 159 82 139 83 25 118 187 117 67 69 143 77 97 100 101 + 88 0 +122 116 168 129 78 205 12 74 55 82 153 177 75 200 119 140 265 84 50 124 + 69 233 147 0 +148 115 49 202 254 29 229 176 195 139 95 97 243 45 118 117 48 174 167 + 151 195 83 103 217 0 +95 32 84 156 146 121 118 65 84 28 70 95 132 116 35 56 181 91 56 18 84 + 150 82 106 133 0 +133 70 122 194 184 159 156 103 112 66 108 99 160 148 73 94 219 129 94 25 + 122 188 120 144 171 38 0 +57 58 110 118 98 147 103 17 84 28 71 121 132 142 61 82 206 43 42 66 36 + 151 65 91 159 48 86 0 +164 101 142 225 188 167 122 134 55 97 139 109 107 152 104 125 239 150 + 116 67 135 219 151 110 191 69 87 117 0 +145 93 78 218 240 41 212 159 153 122 117 27 205 26 87 100 118 176 150 + 121 178 132 129 200 70 116 126 142 126 0 +142 74 77 215 227 60 197 146 134 109 114 8 186 45 68 82 137 172 137 102 + 165 151 126 185 89 103 107 129 107 19 0 +85 48 100 146 119 137 84 55 63 10 86 111 111 132 51 72 197 72 38 56 57 + 166 93 72 149 38 76 38 107 132 119 0 +106 26 73 179 182 110 154 101 120 64 78 48 168 97 30 62 170 127 92 76 + 120 158 90 142 122 58 84 84 102 75 56 74 0 +171 138 72 225 277 52 252 199 218 162 118 120 266 68 141 140 25 197 190 + 174 218 80 126 240 23 156 194 182 214 93 112 172 145 0 +65 18 48 138 160 85 132 79 98 42 37 69 146 80 21 20 145 96 70 54 98 117 + 49 120 97 36 74 62 105 80 77 52 44 120 0 +90 163 173 17 99 207 124 111 167 138 141 217 187 228 166 168 239 77 127 + 176 96 184 125 112 219 158 196 120 222 228 225 148 189 242 148 0 +47 22 67 116 121 104 106 40 80 24 44 85 128 99 25 39 164 66 44 46 59 124 + 46 94 116 28 66 23 97 99 93 34 48 139 19 118 0 +89 26 78 150 140 115 112 59 78 22 64 89 126 110 29 50 175 85 50 24 78 + 144 76 100 127 6 44 42 75 110 97 32 52 150 30 152 22 0 +31 111 118 42 134 155 153 91 157 101 86 165 205 176 114 116 207 57 107 + 139 86 152 70 141 167 121 159 83 190 176 173 111 137 190 96 59 78 115 0 +115 35 56 188 191 93 158 110 111 73 87 31 159 80 42 45 153 136 101 63 + 129 152 99 146 105 65 68 93 86 58 39 83 17 128 53 198 57 61 146 0 +37 70 103 91 121 140 121 44 101 45 62 124 149 135 73 75 197 41 59 83 63 + 142 56 109 152 65 103 27 134 135 132 55 96 175 55 93 25 59 56 105 0 +143 142 106 177 249 101 255 178 222 166 90 169 270 127 145 147 65 169 + 193 178 197 10 98 243 93 160 198 161 229 142 161 176 168 90 127 194 134 + 154 162 162 152 0 +152 151 115 186 258 110 264 187 231 175 99 178 279 136 154 156 100 178 + 202 187 206 45 107 252 98 169 207 170 238 151 170 185 177 121 136 203 + 143 163 171 171 161 55 0 +146 74 81 219 230 70 191 149 124 112 118 12 176 55 72 84 147 175 140 102 + 168 161 130 179 99 104 107 132 97 29 10 122 56 122 81 229 96 100 177 39 + 136 171 180 0 +118 50 53 191 203 84 173 122 126 85 90 16 174 69 44 58 150 148 113 78 + 141 149 102 161 102 79 83 105 101 43 24 95 32 125 53 201 69 73 149 15 + 108 159 168 28 0 +50 56 62 107 155 99 151 74 131 75 17 110 179 121 59 61 151 76 89 92 93 + 96 8 139 111 74 112 57 143 121 118 85 82 134 41 124 38 68 69 91 48 106 + 115 122 94 0 +107 126 110 113 209 117 221 144 201 145 87 179 249 143 129 131 149 133 + 159 162 162 94 62 209 129 144 182 127 213 158 177 155 152 152 111 130 + 108 138 98 161 118 104 113 187 163 70 0 +105 42 94 166 156 131 128 75 84 38 80 86 132 126 45 66 191 101 66 8 94 + 160 92 116 143 10 28 58 59 113 94 48 68 166 46 168 38 16 131 55 75 170 + 179 94 70 84 154 0 +114 133 117 120 216 124 228 151 208 152 94 186 256 150 136 138 156 140 + 166 169 169 101 69 216 136 151 189 134 220 165 184 162 159 159 118 137 + 115 145 105 168 125 111 120 194 170 77 35 161 0 +89 42 72 162 184 109 156 103 122 66 61 70 170 104 45 4 169 120 94 78 122 + 141 73 144 121 60 98 86 127 97 78 76 58 144 24 172 43 54 120 41 79 151 + 160 80 54 65 135 70 142 0 +218 166 151 291 313 114 285 232 226 195 190 100 278 99 160 173 191 249 + 223 194 251 205 202 273 143 189 199 215 199 73 92 205 148 166 153 301 + 172 183 249 131 208 215 224 102 116 194 231 186 238 170 0 +81 147 168 48 68 205 93 80 136 117 136 208 156 219 150 159 250 46 96 155 + 65 195 120 81 217 137 175 89 191 219 216 118 173 240 139 31 109 131 66 + 182 84 205 214 220 192 119 141 147 148 163 292 0 +147 84 125 208 180 160 115 117 48 80 122 100 100 145 87 108 222 133 99 + 50 118 202 134 103 174 52 70 100 17 119 100 90 85 197 88 210 80 58 173 + 69 117 212 221 90 84 126 196 42 203 110 192 179 0 +93 112 96 99 195 103 207 130 187 131 73 165 235 129 115 117 135 119 145 + 148 148 80 48 195 115 130 168 113 199 144 163 141 138 138 97 116 94 124 + 84 147 104 90 99 173 149 56 14 140 21 121 217 127 182 0 +97 91 143 151 103 180 37 49 76 57 128 152 100 175 94 115 240 59 25 99 44 + 208 122 25 192 81 119 66 125 175 160 47 117 215 95 136 69 75 116 121 84 + 218 227 160 136 114 184 91 191 119 248 105 108 170 0 +122 121 85 156 228 80 234 157 201 145 69 148 249 106 124 126 70 148 172 + 157 176 15 77 222 68 139 177 140 208 121 140 155 147 91 106 173 113 133 + 141 141 131 25 30 150 138 85 83 149 90 130 194 184 191 69 197 0 +179 142 194 232 181 222 115 139 48 104 180 164 38 207 145 166 291 149 + 115 126 134 260 187 103 243 128 146 132 83 181 162 111 161 266 146 215 + 128 126 205 145 149 270 279 152 160 179 249 118 256 170 254 184 76 235 + 124 249 0 +38 67 82 99 144 119 146 69 126 70 50 121 174 132 70 72 171 64 84 103 88 + 116 34 134 131 85 123 52 154 132 129 80 93 154 52 116 40 79 57 102 43 + 126 135 133 105 33 90 95 97 76 205 107 137 76 109 105 174 0 +100 34 86 173 168 123 140 87 100 50 72 70 148 118 37 58 183 113 78 52 + 106 152 84 128 135 44 57 70 75 97 78 60 27 158 38 180 39 38 131 39 87 + 162 171 78 54 76 146 44 153 62 170 159 58 132 103 141 134 87 0 +69 46 98 130 117 135 82 39 72 16 83 109 120 130 49 70 195 65 20 54 55 + 163 77 70 147 36 74 22 105 130 117 26 72 170 50 132 24 30 95 81 39 173 + 182 120 93 69 139 46 146 74 203 111 88 125 45 152 120 64 58 0 +160 97 138 219 168 173 102 126 35 91 135 113 87 158 100 121 235 136 102 + 63 121 215 147 90 187 65 83 113 30 132 113 98 98 210 101 202 93 71 186 + 82 130 225 234 103 97 139 209 55 216 123 205 171 13 195 111 204 83 150 + 71 101 0 +70 89 73 110 176 104 184 107 164 108 50 142 212 130 92 94 136 96 122 125 + 125 81 25 172 116 107 145 90 176 145 150 118 115 139 74 127 71 101 89 + 124 81 91 100 154 126 33 37 117 44 98 218 138 159 23 147 70 212 53 109 + 102 172 0 +188 136 121 261 283 84 255 202 196 165 160 70 248 69 130 143 161 219 193 + 164 221 175 172 243 113 159 169 185 169 43 62 175 118 136 123 271 142 + 153 219 101 178 185 194 72 86 164 201 156 208 140 30 262 162 187 218 + 164 224 175 140 173 175 188 0 +94 28 80 167 162 117 134 81 100 44 66 69 148 112 31 52 177 107 72 56 100 + 146 78 122 129 38 63 64 81 96 77 54 21 152 32 174 33 32 125 38 81 156 + 165 77 53 70 140 48 147 56 169 153 64 126 97 135 140 81 6 52 77 103 139 + 0 +45 43 75 118 142 112 138 61 118 62 30 97 166 108 46 48 164 76 76 79 80 + 109 21 126 124 61 99 44 130 108 105 72 69 147 28 128 25 55 76 78 35 119 + 128 109 81 13 83 71 90 52 181 119 113 69 101 98 166 32 63 56 126 46 151 + 57 0 +113 35 48 186 191 85 163 110 119 73 85 37 167 72 39 37 145 136 101 71 + 129 144 97 151 97 67 76 93 94 64 45 83 25 120 48 196 57 61 144 8 103 + 154 163 47 21 89 158 63 165 33 137 182 77 144 126 133 153 100 47 81 90 + 121 107 46 76 0 +97 21 57 170 173 94 145 92 111 55 69 46 159 81 14 55 154 118 83 67 111 + 149 81 133 106 49 87 75 118 73 54 65 18 129 35 180 39 43 128 33 87 159 + 168 58 30 73 143 59 150 58 146 164 101 129 108 138 159 84 45 63 114 106 + 116 39 60 25 0 +116 79 131 177 133 168 98 76 51 41 117 127 63 163 82 103 228 86 52 77 71 + 197 124 86 180 69 97 69 100 154 135 48 105 203 83 163 65 63 142 96 86 + 207 216 135 111 116 186 69 193 107 227 132 83 172 61 186 63 111 85 57 + 86 149 197 85 103 104 96 0 +EOF + +Vertices of the graph: + 1 Aprelevka 35 Lyubertsy + 2 Balashikha 36 Mozhaysk + 3 Bronnitsy 37 Moskva + 4 Vereya 38 Mytischi + 5 Volokolamsk 39 Naro-Fominsk + 6 Voskresensk 40 Noginsk + 7 Vysokovsk 41 Odintsovo + 8 Dedovsk 42 Ozherel'ye + 9 Dmitrov 43 Ozyory +10 Dolgoprudny 44 Orekhovo-Zuevo +11 Domodedovo 45 Pavlovsky Posad +12 Drezna 46 Podol'sk +13 Dubna 47 Protvino +14 Egor'yevsk 48 Pushkino +15 Zheleznodorozhny 49 Puschino +16 Zhukovsky 50 Ramenskoye +17 Zaraysk 51 Roshal +18 Zvenigorod 52 Ruza +19 Zelenograd 53 Sergiyev Posad +20 Ivanteyevka 54 Serpukhov +21 Istra 55 Solnechnogorsk +22 Kashira 56 Stupino +23 Klimovsk 57 Taldom +24 Klin 58 Troitsk +25 Kolomna 59 Fryazino +26 Korolyov (Podlipki) 60 Khimki +27 Krasnoarmeysk 61 Khot'kovo +28 Krasnogorsk 62 Chekhov +29 Krasnozavodsk 63 Shatura +30 Kurovskoye 64 Schyolkovo +31 Likino-Dulyovo 65 Scherbinka +32 Lobnya 66 Elektrostal +33 Losino-Petrovsky 67 Elektrougli +34 Lukhovitsy 68 Yakhroma + +Optimal tour length is 1994 kilometers (obtained by glpk tspsol): +1 39 4 36 52 5 7 24 55 19 60 10 32 68 13 57 9 61 53 29 27 20 48 26 38 +59 64 33 67 15 2 35 16 50 66 40 45 12 44 31 63 51 30 14 6 3 25 34 17 22 +42 56 43 47 49 54 62 23 46 11 65 58 41 37 28 8 21 18 1 diff --git a/resources/3rdparty/glpk-4.57/examples/tsp/sample.tsp b/resources/3rdparty/glpk-4.57/examples/tsp/sample.tsp new file mode 100644 index 000000000..9e1367a33 --- /dev/null +++ b/resources/3rdparty/glpk-4.57/examples/tsp/sample.tsp @@ -0,0 +1,16 @@ +NAME: SAMPLE +TYPE: TSP +COMMENT: Example from D.Phillips, A.Garcia-Diaz, p.124 +DIMENSION: 8 +EDGE_WEIGHT_TYPE: EXPLICIT +EDGE_WEIGHT_FORMAT: LOWER_DIAG_ROW +EDGE_WEIGHT_SECTION +0 +190 0 +210 380 0 +680 760 890 0 +690 790 900 480 0 +460 610 340 760 890 0 +780 670 410 510 490 720 0 +750 450 600 250 560 600 500 0 +EOF diff --git a/resources/3rdparty/glpk-4.57/examples/tsp/tsplib.c b/resources/3rdparty/glpk-4.57/examples/tsp/tsplib.c new file mode 100644 index 000000000..189ff8aa5 --- /dev/null +++ b/resources/3rdparty/glpk-4.57/examples/tsp/tsplib.c @@ -0,0 +1,730 @@ +/* tsplib.c */ + +/* Written by Andrew Makhorin , October 2015. */ + +#include +#include +#include +#include +#include +#include +#include + +#include "misc.h" +#include "tsplib.h" + +/*********************************************************************** +* NAME +* +* tsp_read_data - read TSP instance data +* +* SYNOPSIS +* +* #include "tsplib.h" +* TSP *tsp_read_data(const char *fname); +* +* DESCRIPTION +* +* The routine tsp_read_data reads a TSP (or related problem) instance +* data from a text file, whose name is the character string fname. +* +* For detailed description of the format recognized by the routine see +* the report: G.Reinelt, TSPLIB 95. +* +* RETURNS +* +* If no error occurred, the routine tsp_read_data returns a pointer to +* the TSP instance data block, which contains loaded data. In the case +* of error the routine prints an error message and returns NULL. */ + +struct csa +{ /* common storage area used by the routine tsp_read_data */ + const char *fname; + /* name of the input text file */ + FILE *fp; + /* stream assigned to the input text file */ + int seqn; + /* line sequential number */ + int c; + /* current character */ + char token[255+1]; + /* current token */ +}; + +static int get_char(struct csa *csa) +{ csa->c = fgetc(csa->fp); + if (ferror(csa->fp)) + { xprintf("%s:%d: read error - %s\n", csa->fname, csa->seqn, + strerror(errno)); + return 1; + } + if (feof(csa->fp)) + csa->c = EOF; + else if (csa->c == '\n') + csa->seqn++; + else if (isspace(csa->c)) + csa->c = ' '; + else if (iscntrl(csa->c)) + { xprintf("%s:%d: invalid control character 0x%02X\n", + csa->fname, csa->seqn, csa->c); + return 1; + } + return 0; +} + +static int skip_spaces(struct csa *csa, int across) +{ while (csa->c == ' ' || (across && csa->c == '\n')) + if (get_char(csa)) return 1; + return 0; +} + +static int scan_keyword(struct csa *csa) +{ int len = 0; + if (skip_spaces(csa, 0)) + return 1; + if (csa->c == EOF) + { xprintf("%s:%d: warning: missing EOF inserted\n", csa->fname, + csa->seqn); + strcpy(csa->token, "EOF"); + return 0; + } + csa->token[0] = '\0'; + while (isalnum(csa->c) || csa->c == '_') + { if (len == 31) + { xprintf("%s:%d: keyword '%s...' too long\n", csa->fname, + csa->seqn, csa->token); + return 1; + } + csa->token[len++] = (char)csa->c, csa->token[len] = '\0'; + if (get_char(csa)) + return 1; + } + if (len == 0) + { xprintf("%s:%d: missing keyword\n", csa->fname, csa->seqn); + return 1; + } + return 0; +} + +static int check_colon(struct csa *csa) +{ if (skip_spaces(csa, 0)) + return 1; + if (csa->c != ':') + { xprintf("%s:%d: missing colon after '%s'\n", csa->fname, + csa->seqn, csa->token); + return 1; + } + if (get_char(csa)) + return 1; + return 0; +} + +static int scan_token(struct csa *csa, int across) +{ int len = 0; + if (skip_spaces(csa, across)) + return 1; + csa->token[0] = '\0'; + while (!(csa->c == EOF || csa->c == '\n' || csa->c == ' ')) + { if (len == 255) + { csa->token[31] = '\0'; + xprintf("%s:%d: token '%s...' too long\n", csa->fname, + csa->seqn, csa->token); + return 1; + } + csa->token[len++] = (char)csa->c, csa->token[len] = '\0'; + if (get_char(csa)) + return 1; + } + return 0; +} + +static int check_newline(struct csa *csa) +{ if (skip_spaces(csa, 0)) + return 1; + if (!(csa->c == EOF || csa->c == '\n')) + { xprintf("%s:%d: extra symbols detected\n", csa->fname, + csa->seqn); + return 1; + } + if (get_char(csa)) + return 1; + return 0; +} + +static int scan_comment(struct csa *csa) +{ int len = 0; + if (skip_spaces(csa, 0)) + return 1; + csa->token[0] = '\0'; + while (!(csa->c == EOF || csa->c == '\n')) + { if (len == 255) + { xprintf("%s:%d: comment too long\n", csa->fname, csa->seqn); + return 1; + } + csa->token[len++] = (char)csa->c, csa->token[len] = '\0'; + if (get_char(csa)) + return 1; + } + return 0; +} + +static int scan_integer(struct csa *csa, int across, int *val) +{ if (scan_token(csa, across)) + return 1; + if (strlen(csa->token) == 0) + { xprintf("%s:%d: missing integer\n", csa->fname, csa->seqn); + return 1; + } + if (str2int(csa->token, val)) + { xprintf("%s:%d: integer '%s' invalid\n", csa->fname, csa->seqn, + csa->token); + return 1; + } + return 0; +} + +static int scan_number(struct csa *csa, int across, double *val) +{ if (scan_token(csa, across)) + return 1; + if (strlen(csa->token) == 0) + { xprintf("%s:%d: missing number\n", csa->fname, csa->seqn); + return 1; + } + if (str2num(csa->token, val)) + { xprintf("%s:%d: number '%s' invalid\n", csa->fname, csa->seqn, + csa->token); + return 1; + } + return 0; +} + +TSP *tsp_read_data(const char *fname) +{ struct csa _dsa, *csa = &_dsa; + TSP *tsp = NULL; + csa->fname = fname; + xprintf("Reading TSP data from '%s'...\n", csa->fname); + csa->fp = fopen(csa->fname, "r"); + if (csa->fp == NULL) + { xprintf("Unable to open '%s' - %s\n", csa->fname, + strerror(errno)); + goto fail; + } + tsp = xalloc(1, sizeof(TSP)); + tsp->name = NULL; + tsp->type = TSP_UNDEF; + tsp->comment = NULL; + tsp->dimension = 0; + tsp->edge_weight_type = TSP_UNDEF; + tsp->edge_weight_format = TSP_UNDEF; + tsp->display_data_type = TSP_UNDEF; + tsp->node_x_coord = NULL; + tsp->node_y_coord = NULL; + tsp->dply_x_coord = NULL; + tsp->dply_y_coord = NULL; + tsp->tour = NULL; + tsp->edge_weight = NULL; + csa->seqn = 1; + if (get_char(csa)) + goto fail; +loop: if (scan_keyword(csa)) + goto fail; + if (strcmp(csa->token, "NAME") == 0) + { if (tsp->name != NULL) + { xprintf("%s:%d: NAME entry multiply defined\n", csa->fname, + csa->seqn); + goto fail; + } + if (check_colon(csa)) + goto fail; + if (scan_token(csa, 0)) + goto fail; + if (strlen(csa->token) == 0) + { xprintf("%s:%d: NAME entry incomplete\n", csa->fname, + csa->seqn); + goto fail; + } + tsp->name = xalloc(strlen(csa->token)+1, sizeof(char)); + strcpy(tsp->name, csa->token); + xprintf("NAME: %s\n", tsp->name); + if (check_newline(csa)) + goto fail; + } + else if (strcmp(csa->token, "TYPE") == 0) + { if (tsp->type != TSP_UNDEF) + { xprintf("%s:%d: TYPE entry multiply defined\n", csa->fname, + csa->seqn); + goto fail; + } + if (check_colon(csa)) + goto fail; + if (scan_keyword(csa)) + goto fail; + if (strcmp(csa->token, "TSP") == 0) + tsp->type = TSP_TSP; + else if (strcmp(csa->token, "ATSP") == 0) + tsp->type = TSP_ATSP; + else if (strcmp(csa->token, "TOUR") == 0) + tsp->type = TSP_TOUR; + else + { xprintf("%s:%d: data type '%s' not recognized\n", + csa->fname, csa->seqn, csa->token); + goto fail; + } + xprintf("TYPE: %s\n", csa->token); + if (check_newline(csa)) + goto fail; + } + else if (strcmp(csa->token, "COMMENT") == 0) + { if (check_colon(csa)) + goto fail; + if (scan_comment(csa)) + goto fail; + xprintf("COMMENT: %s\n", csa->token); + if (tsp->comment == NULL) + { tsp->comment = xalloc(strlen(csa->token)+1, sizeof(char)); + strcpy(tsp->comment, csa->token); + } + else + { xprintf("%s:%d: warning: extra COMMENT entry ignored\n", + csa->fname, csa->seqn); + } + if (check_newline(csa)) + goto fail; + } + else if (strcmp(csa->token, "DIMENSION") == 0) + { if (tsp->dimension != 0) + { xprintf("%s:%d: DIMENSION entry multiply defined\n", + csa->fname, csa->seqn); + goto fail; + } + if (check_colon(csa)) + goto fail; + if (scan_integer(csa, 0, &tsp->dimension)) + goto fail; + if (tsp->dimension < 1) + { xprintf("%s:%d: invalid dimension\n", csa->fname, + csa->seqn); + goto fail; + } + xprintf("DIMENSION: %d\n", tsp->dimension); + if (check_newline(csa)) + goto fail; + } + else if (strcmp(csa->token, "EDGE_WEIGHT_TYPE") == 0) + { if (tsp->edge_weight_type != TSP_UNDEF) + { xprintf("%s:%d: EDGE_WEIGHT_TYPE entry multiply defined\n", + csa->fname, csa->seqn); + goto fail; + } + if (check_colon(csa)) + goto fail; + if (scan_keyword(csa)) + goto fail; + if (strcmp(csa->token, "GEO") == 0) + tsp->edge_weight_type = TSP_GEO; + else if (strcmp(csa->token, "EUC_2D") == 0) + tsp->edge_weight_type = TSP_EUC_2D; + else if (strcmp(csa->token, "ATT") == 0) + tsp->edge_weight_type = TSP_ATT; + else if (strcmp(csa->token, "EXPLICIT") == 0) + tsp->edge_weight_type = TSP_EXPLICIT; + else if (strcmp(csa->token, "CEIL_2D") == 0) + tsp->edge_weight_type = TSP_CEIL_2D; + else + { xprintf("%s:%d: edge weight type '%s' not recognized\n", + csa->fname, csa->seqn, csa->token); + goto fail; + } + xprintf("EDGE_WEIGHT_TYPE: %s\n", csa->token); + if (check_newline(csa)) + goto fail; + } + else if (strcmp(csa->token, "EDGE_WEIGHT_FORMAT") == 0) + { if (tsp->edge_weight_format != TSP_UNDEF) + { xprintf("%s:%d: EDGE_WEIGHT_FORMAT entry multiply defined\n" + , csa->fname, csa->seqn); + goto fail; + } + if (check_colon(csa)) + goto fail; + if (scan_keyword(csa)) + goto fail; + if (strcmp(csa->token, "UPPER_ROW") == 0) + tsp->edge_weight_format = TSP_UPPER_ROW; + else if (strcmp(csa->token, "FULL_MATRIX") == 0) + tsp->edge_weight_format = TSP_FULL_MATRIX; + else if (strcmp(csa->token, "FUNCTION") == 0) + tsp->edge_weight_format = TSP_FUNCTION; + else if (strcmp(csa->token, "LOWER_DIAG_ROW") == 0) + tsp->edge_weight_format = TSP_LOWER_DIAG_ROW; + else + { xprintf("%s:%d: edge weight format '%s' not recognized\n", + csa->fname, csa->seqn, csa->token); + goto fail; + } + xprintf("EDGE_WEIGHT_FORMAT: %s\n", csa->token); + if (check_newline(csa)) + goto fail; + } + else if (strcmp(csa->token, "DISPLAY_DATA_TYPE") == 0) + { if (tsp->display_data_type != TSP_UNDEF) + { xprintf("%s:%d: DISPLAY_DATA_TYPE entry multiply defined\n", + csa->fname, csa->seqn); + goto fail; + } + if (check_colon(csa)) + goto fail; + if (scan_keyword(csa)) + goto fail; + if (strcmp(csa->token, "COORD_DISPLAY") == 0) + tsp->display_data_type = TSP_COORD_DISPLAY; + else if (strcmp(csa->token, "TWOD_DISPLAY") == 0) + tsp->display_data_type = TSP_TWOD_DISPLAY; + else + { xprintf("%s:%d: display data type '%s' not recognized\n", + csa->fname, csa->seqn, csa->token); + goto fail; + } + xprintf("DISPLAY_DATA_TYPE: %s\n", csa->token); + if (check_newline(csa)) + goto fail; + } + else if (strcmp(csa->token, "NODE_COORD_SECTION") == 0) + { int n = tsp->dimension, k, node; + if (n == 0) + { xprintf("%s:%d: DIMENSION entry not specified\n", + csa->fname, csa->seqn); + goto fail; + } + if (tsp->node_x_coord != NULL) + { xprintf("%s:%d: NODE_COORD_SECTION multiply specified\n", + csa->fname, csa->seqn); + goto fail; + } + if (check_newline(csa)) + goto fail; + tsp->node_x_coord = xalloc(1+n, sizeof(double)); + tsp->node_y_coord = xalloc(1+n, sizeof(double)); + for (node = 1; node <= n; node++) + tsp->node_x_coord[node] = tsp->node_y_coord[node] = DBL_MAX; + for (k = 1; k <= n; k++) + { if (scan_integer(csa, 0, &node)) + goto fail; + if (!(1 <= node && node <= n)) + { xprintf("%s:%d: invalid node number %d\n", csa->fname, + csa->seqn, node); + goto fail; + } + if (tsp->node_x_coord[node] != DBL_MAX) + { xprintf("%s:%d: node number %d multiply specified\n", + csa->fname, csa->seqn, node); + goto fail; + } + if (scan_number(csa, 0, &tsp->node_x_coord[node])) + goto fail; + if (scan_number(csa, 0, &tsp->node_y_coord[node])) + goto fail; + if (check_newline(csa)) + goto fail; + } + } + else if (strcmp(csa->token, "DISPLAY_DATA_SECTION") == 0) + { int n = tsp->dimension, k, node; + if (n == 0) + { xprintf("%s:%d: DIMENSION entry not specified\n", + csa->fname, csa->seqn); + goto fail; + } + if (tsp->dply_x_coord != NULL) + { xprintf("%s:%d: DISPLAY_DATA_SECTION multiply specified\n", + csa->fname, csa->seqn); + goto fail; + } + if (check_newline(csa)) + goto fail; + tsp->dply_x_coord = xalloc(1+n, sizeof(double)); + tsp->dply_y_coord = xalloc(1+n, sizeof(double)); + for (node = 1; node <= n; node++) + tsp->dply_x_coord[node] = tsp->dply_y_coord[node] = DBL_MAX; + for (k = 1; k <= n; k++) + { if (scan_integer(csa, 0, &node)) + goto fail; + if (!(1 <= node && node <= n)) + { xprintf("%s:%d: invalid node number %d\n", csa->fname, + csa->seqn, node); + goto fail; + } + if (tsp->dply_x_coord[node] != DBL_MAX) + { xprintf("%s:%d: node number %d multiply specified\n", + csa->fname, csa->seqn, node); + goto fail; + } + if (scan_number(csa, 0, &tsp->dply_x_coord[node])) + goto fail; + if (scan_number(csa, 0, &tsp->dply_y_coord[node])) + goto fail; + if (check_newline(csa)) + goto fail; + } + } + else if (strcmp(csa->token, "TOUR_SECTION") == 0) + { int n = tsp->dimension, k, node; + if (n == 0) + { xprintf("%s:%d: DIMENSION entry not specified\n", + csa->fname, csa->seqn); + goto fail; + } + if (tsp->tour != NULL) + { xprintf("%s:%d: TOUR_SECTION multiply specified\n", + csa->fname, csa->seqn); + goto fail; + } + if (check_newline(csa)) + goto fail; + tsp->tour = xalloc(1+n, sizeof(int)); + for (k = 1; k <= n; k++) + { if (scan_integer(csa, 1, &node)) + goto fail; + if (!(1 <= node && node <= n)) + { xprintf("%s:%d: invalid node number %d\n", csa->fname, + csa->seqn, node); + goto fail; + } + tsp->tour[k] = node; + } + if (scan_integer(csa, 1, &node)) + goto fail; + if (node != -1) + { xprintf("%s:%d: extra node(s) detected\n", csa->fname, + csa->seqn); + goto fail; + } + if (check_newline(csa)) + goto fail; + } + else if (strcmp(csa->token, "EDGE_WEIGHT_SECTION") == 0) + { int n = tsp->dimension, i, j, temp; + if (n == 0) + { xprintf("%s:%d: DIMENSION entry not specified\n", + csa->fname, csa->seqn); + goto fail; + } + if (tsp->edge_weight_format == TSP_UNDEF) + { xprintf("%s:%d: EDGE_WEIGHT_FORMAT entry not specified\n", + csa->fname, csa->seqn); + goto fail; + } + if (tsp->edge_weight != NULL) + { xprintf("%s:%d: EDGE_WEIGHT_SECTION multiply specified\n", + csa->fname, csa->seqn); + goto fail; + } + if (check_newline(csa)) + goto fail; + tsp->edge_weight = xalloc(1+n*n, sizeof(int)); + switch (tsp->edge_weight_format) + { case TSP_FULL_MATRIX: + for (i = 1; i <= n; i++) + { for (j = 1; j <= n; j++) + { if (scan_integer(csa, 1, &temp)) + goto fail; + tsp->edge_weight[(i - 1) * n + j] = temp; + } + } + break; + case TSP_UPPER_ROW: + for (i = 1; i <= n; i++) + { tsp->edge_weight[(i - 1) * n + i] = 0; + for (j = i + 1; j <= n; j++) + { if (scan_integer(csa, 1, &temp)) + goto fail; + tsp->edge_weight[(i - 1) * n + j] = temp; + tsp->edge_weight[(j - 1) * n + i] = temp; + } + } + break; + case TSP_LOWER_DIAG_ROW: + for (i = 1; i <= n; i++) + { for (j = 1; j <= i; j++) + { if (scan_integer(csa, 1, &temp)) + goto fail; + tsp->edge_weight[(i - 1) * n + j] = temp; + tsp->edge_weight[(j - 1) * n + i] = temp; + } + } + break; + default: + goto fail; + } + if (check_newline(csa)) + goto fail; + } + else if (strcmp(csa->token, "EOF") == 0) + { if (check_newline(csa)) + goto fail; + goto done; + } + else + { xprintf("%s:%d: keyword '%s' not recognized\n", csa->fname, + csa->seqn, csa->token); + goto fail; + } + goto loop; +done: xprintf("%d lines were read\n", csa->seqn-1); + fclose(csa->fp); + return tsp; +fail: if (tsp != NULL) + { if (tsp->name != NULL) + xfree(tsp->name); + if (tsp->comment != NULL) + xfree(tsp->comment); + if (tsp->node_x_coord != NULL) + xfree(tsp->node_x_coord); + if (tsp->node_y_coord != NULL) + xfree(tsp->node_y_coord); + if (tsp->dply_x_coord != NULL) + xfree(tsp->dply_x_coord); + if (tsp->dply_y_coord != NULL) + xfree(tsp->dply_y_coord); + if (tsp->tour != NULL) + xfree(tsp->tour); + if (tsp->edge_weight != NULL) + xfree(tsp->edge_weight); + xfree(tsp); + } + if (csa->fp != NULL) + fclose(csa->fp); + return NULL; +} + +/*********************************************************************** +* NAME +* +* tsp_distance - compute distance between two nodes +* +* SYNOPSIS +* +* #include "tsplib.h" +* int tsp_distance(TSP *tsp, int i, int j); +* +* DESCRIPTION +* +* The routine tsp_distance computes the distance between i-th and j-th +* nodes for the TSP instance, which tsp points to. +* +* RETURNS +* +* The routine tsp_distance returns the computed distance. */ + +#define nint(x) ((int)((x) + 0.5)) + +static double rad(double x) +{ /* convert input coordinate to longitude/latitude, in radians */ + double pi = 3.141592, deg, min; + deg = (int)x; + min = x - deg; + return pi * (deg + 5.0 * min / 3.0) / 180.0; +} + +int tsp_distance(const TSP *tsp, int i, int j) +{ int n = tsp->dimension, dij; + if (!(tsp->type == TSP_TSP || tsp->type == TSP_ATSP)) + xerror("tsp_distance: invalid TSP instance\n"); + if (!(1 <= i && i <= n && 1 <= j && j <= n)) + xerror("tsp_distance: node number out of range\n"); + switch (tsp->edge_weight_type) + { case TSP_UNDEF: + xerror("tsp_distance: edge weight type not specified\n"); + case TSP_EXPLICIT: + if (tsp->edge_weight == NULL) + xerror("tsp_distance: edge weights not specified\n"); + dij = tsp->edge_weight[(i - 1) * n + j]; + break; + case TSP_EUC_2D: + if (tsp->node_x_coord == NULL || tsp->node_y_coord == NULL) + xerror("tsp_distance: node coordinates not specified\n"); + { double xd, yd; + xd = tsp->node_x_coord[i] - tsp->node_x_coord[j]; + yd = tsp->node_y_coord[i] - tsp->node_y_coord[j]; + dij = nint(sqrt(xd * xd + yd * yd)); + } + break; + case TSP_CEIL_2D: + if (tsp->node_x_coord == NULL || tsp->node_y_coord == NULL) + xerror("tsp_distance: node coordinates not specified\n"); + { double xd, yd; + xd = tsp->node_x_coord[i] - tsp->node_x_coord[j]; + yd = tsp->node_y_coord[i] - tsp->node_y_coord[j]; + dij = (int)ceil(sqrt(xd * xd + yd * yd)); + } + break; + case TSP_GEO: + if (tsp->node_x_coord == NULL || tsp->node_y_coord == NULL) + xerror("tsp_distance: node coordinates not specified\n"); + { double rrr = 6378.388; + double latitude_i = rad(tsp->node_x_coord[i]); + double latitude_j = rad(tsp->node_x_coord[j]); + double longitude_i = rad(tsp->node_y_coord[i]); + double longitude_j = rad(tsp->node_y_coord[j]); + double q1 = cos(longitude_i - longitude_j); + double q2 = cos(latitude_i - latitude_j); + double q3 = cos(latitude_i + latitude_j); + dij = (int)(rrr * acos(0.5 * ((1.0 + q1) * q2 - + (1.0 - q1) *q3)) + 1.0); + } + break; + case TSP_ATT: + if (tsp->node_x_coord == NULL || tsp->node_y_coord == NULL) + xerror("tsp_distance: node coordinates not specified\n"); + { int tij; + double xd, yd, rij; + xd = tsp->node_x_coord[i] - tsp->node_x_coord[j]; + yd = tsp->node_y_coord[i] - tsp->node_y_coord[j]; + rij = sqrt((xd * xd + yd * yd) / 10.0); + tij = nint(rij); + if (tij < rij) dij = tij + 1; else dij = tij; + } + break; + default: + xassert(tsp->edge_weight_type != tsp->edge_weight_type); + } + return dij; +} + +/*********************************************************************** +* NAME +* +* tsp_free_data - free TSP instance data +* +* SYNOPSIS +* +* #include "tsplib.h" +* void tsp_free_data(TSP *tsp); +* +* DESCRIPTION +* +* The routine tsp_free_data frees all the memory allocated to the TSP +* instance data block, which the parameter tsp points to. */ + +void tsp_free_data(TSP *tsp) +{ if (tsp->name != NULL) + xfree(tsp->name); + if (tsp->comment != NULL) + xfree(tsp->comment); + if (tsp->node_x_coord != NULL) + xfree(tsp->node_x_coord); + if (tsp->node_y_coord != NULL) + xfree(tsp->node_y_coord); + if (tsp->dply_x_coord != NULL) + xfree(tsp->dply_x_coord); + if (tsp->dply_y_coord != NULL) + xfree(tsp->dply_y_coord); + if (tsp->tour != NULL) + xfree(tsp->tour); + if (tsp->edge_weight != NULL) + xfree(tsp->edge_weight); + xfree(tsp); + return; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glptsp.h b/resources/3rdparty/glpk-4.57/examples/tsp/tsplib.h similarity index 58% rename from resources/3rdparty/glpk-4.53/src/glptsp.h rename to resources/3rdparty/glpk-4.57/examples/tsp/tsplib.h index 6b82ee5e5..efadaef88 100644 --- a/resources/3rdparty/glpk-4.53/src/glptsp.h +++ b/resources/3rdparty/glpk-4.57/examples/tsp/tsplib.h @@ -1,37 +1,17 @@ -/* glptsp.h (TSP format) */ +/* tsplib.h */ -/*********************************************************************** -* This code is part of GLPK (GNU Linear Programming Kit). -* -* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, -* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied -* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights -* reserved. E-mail: . -* -* GLPK is free software: you can redistribute it and/or modify it -* under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* GLPK is distributed in the hope that it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public -* License for more details. -* -* You should have received a copy of the GNU General Public License -* along with GLPK. If not, see . -***********************************************************************/ +/* Written by Andrew Makhorin , October 2015. */ -#ifndef GLPTSP_H -#define GLPTSP_H +#ifndef TSPLIB_H +#define TSPLIB_H typedef struct TSP TSP; struct TSP { /* TSP (or related problem) instance in the format described in - the report [G.Reinelt, TSPLIB 95] */ + * [G.Reinelt, TSPLIB 95] */ /*--------------------------------------------------------------*/ - /* the specification part */ + /* specification part */ char *name; /* identifies the data file */ int type; @@ -42,10 +22,10 @@ struct TSP #define TSP_TOUR 3 /* collection of tours */ char *comment; /* additional comments (usually the name of the contributor or - creator of the problem instance is given here) */ + * creator of the problem instance is given here) */ int dimension; /* for a TSP or ATSP, the dimension is the number of its nodes - for a TOUR it is the dimension of the corresponding problem */ + * for a TOUR it is the dimension of the corresponding problem */ int edge_weight_type; /* specifies how the edge weights (or distances) are given: */ #define TSP_UNDEF 0 /* undefined */ @@ -56,22 +36,22 @@ struct TSP #define TSP_ATT 5 /* special distance function */ int edge_weight_format; /* describes the format of the edge weights if they are given - explicitly: */ + * explicitly: */ #define TSP_UNDEF 0 /* undefined */ #define TSP_FUNCTION 1 /* given by a function */ #define TSP_FULL_MATRIX 2 /* given by a full matrix */ #define TSP_UPPER_ROW 3 /* upper triangulat matrix (row-wise - without diagonal entries) */ + * without diagonal entries) */ #define TSP_LOWER_DIAG_ROW 4 /* lower triangular matrix (row-wise - including diagonal entries) */ + * including diagonal entries) */ int display_data_type; /* specifies how a graphical display of the nodes can be - obtained: */ + * obtained: */ #define TSP_UNDEF 0 /* undefined */ #define TSP_COORD_DISPLAY 1 /* display is generated from the node - coordinates */ + * coordinates */ #define TSP_TWOD_DISPLAY 2 /* explicit coordinates in 2-D are - given */ + * given */ /*--------------------------------------------------------------*/ /* data part */ /* NODE_COORD_SECTION: */ @@ -86,19 +66,15 @@ struct TSP int *edge_weight; /* int edge_weight[1+dimension*dimension]; */ }; -#define tsp_read_data _glp_tsp_read_data -#define tsp_free_data _glp_tsp_free_data -#define tsp_distance _glp_tsp_distance - -TSP *tsp_read_data(char *fname); +TSP *tsp_read_data(const char *fname); /* read TSP instance data */ +int tsp_distance(const TSP *tsp, int i, int j); +/* compute distance between two nodes */ + void tsp_free_data(TSP *tsp); /* free TSP instance data */ -int tsp_distance(TSP *tsp, int i, int j); -/* compute distance between two nodes */ - #endif /* eof */ diff --git a/resources/3rdparty/glpk-4.57/examples/tsp/ulysses16.tsp b/resources/3rdparty/glpk-4.57/examples/tsp/ulysses16.tsp new file mode 100644 index 000000000..4ce24a60e --- /dev/null +++ b/resources/3rdparty/glpk-4.57/examples/tsp/ulysses16.tsp @@ -0,0 +1,24 @@ +NAME: ulysses16.tsp +TYPE: TSP +COMMENT: Odyssey of Ulysses (Groetschel/Padberg) +DIMENSION: 16 +EDGE_WEIGHT_TYPE: GEO +DISPLAY_DATA_TYPE: COORD_DISPLAY +NODE_COORD_SECTION + 1 38.24 20.42 + 2 39.57 26.15 + 3 40.56 25.32 + 4 36.26 23.12 + 5 33.48 10.54 + 6 37.56 12.19 + 7 38.42 13.11 + 8 37.52 20.44 + 9 41.23 9.10 + 10 41.17 13.05 + 11 36.08 -5.21 + 12 38.47 15.13 + 13 38.15 15.35 + 14 37.51 15.17 + 15 35.49 14.32 + 16 39.36 19.56 + EOF diff --git a/resources/3rdparty/glpk-4.57/examples/tsp/ulysses22.tsp b/resources/3rdparty/glpk-4.57/examples/tsp/ulysses22.tsp new file mode 100644 index 000000000..9e95fb826 --- /dev/null +++ b/resources/3rdparty/glpk-4.57/examples/tsp/ulysses22.tsp @@ -0,0 +1,30 @@ +NAME: ulysses22.tsp +TYPE: TSP +COMMENT: Odyssey of Ulysses (Groetschel/Padberg) +DIMENSION: 22 +EDGE_WEIGHT_TYPE: GEO +DISPLAY_DATA_TYPE: COORD_DISPLAY +NODE_COORD_SECTION + 1 38.24 20.42 + 2 39.57 26.15 + 3 40.56 25.32 + 4 36.26 23.12 + 5 33.48 10.54 + 6 37.56 12.19 + 7 38.42 13.11 + 8 37.52 20.44 + 9 41.23 9.10 + 10 41.17 13.05 + 11 36.08 -5.21 + 12 38.47 15.13 + 13 38.15 15.35 + 14 37.51 15.17 + 15 35.49 14.32 + 16 39.36 19.56 + 17 38.09 24.36 + 18 36.09 23.00 + 19 40.44 13.57 + 20 40.33 14.15 + 21 40.37 14.23 + 22 37.57 22.56 +EOF diff --git a/resources/3rdparty/glpk-4.53/examples/xyacfs.mod b/resources/3rdparty/glpk-4.57/examples/xyacfs.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/xyacfs.mod rename to resources/3rdparty/glpk-4.57/examples/xyacfs.mod diff --git a/resources/3rdparty/glpk-4.53/examples/yacfs.mod b/resources/3rdparty/glpk-4.57/examples/yacfs.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/yacfs.mod rename to resources/3rdparty/glpk-4.57/examples/yacfs.mod diff --git a/resources/3rdparty/glpk-4.53/examples/zebra.mod b/resources/3rdparty/glpk-4.57/examples/zebra.mod similarity index 100% rename from resources/3rdparty/glpk-4.53/examples/zebra.mod rename to resources/3rdparty/glpk-4.57/examples/zebra.mod diff --git a/resources/3rdparty/glpk-4.53/install-sh b/resources/3rdparty/glpk-4.57/install-sh old mode 100644 new mode 100755 similarity index 100% rename from resources/3rdparty/glpk-4.53/install-sh rename to resources/3rdparty/glpk-4.57/install-sh diff --git a/resources/3rdparty/glpk-4.53/ltmain.sh b/resources/3rdparty/glpk-4.57/ltmain.sh old mode 100644 new mode 100755 similarity index 100% rename from resources/3rdparty/glpk-4.53/ltmain.sh rename to resources/3rdparty/glpk-4.57/ltmain.sh diff --git a/resources/3rdparty/glpk-4.53/m4/libtool.m4 b/resources/3rdparty/glpk-4.57/m4/libtool.m4 similarity index 100% rename from resources/3rdparty/glpk-4.53/m4/libtool.m4 rename to resources/3rdparty/glpk-4.57/m4/libtool.m4 diff --git a/resources/3rdparty/glpk-4.53/m4/ltoptions.m4 b/resources/3rdparty/glpk-4.57/m4/ltoptions.m4 similarity index 100% rename from resources/3rdparty/glpk-4.53/m4/ltoptions.m4 rename to resources/3rdparty/glpk-4.57/m4/ltoptions.m4 diff --git a/resources/3rdparty/glpk-4.53/m4/ltsugar.m4 b/resources/3rdparty/glpk-4.57/m4/ltsugar.m4 similarity index 100% rename from resources/3rdparty/glpk-4.53/m4/ltsugar.m4 rename to resources/3rdparty/glpk-4.57/m4/ltsugar.m4 diff --git a/resources/3rdparty/glpk-4.53/m4/ltversion.m4 b/resources/3rdparty/glpk-4.57/m4/ltversion.m4 similarity index 100% rename from resources/3rdparty/glpk-4.53/m4/ltversion.m4 rename to resources/3rdparty/glpk-4.57/m4/ltversion.m4 diff --git a/resources/3rdparty/glpk-4.53/m4/lt~obsolete.m4 b/resources/3rdparty/glpk-4.57/m4/lt~obsolete.m4 similarity index 100% rename from resources/3rdparty/glpk-4.53/m4/lt~obsolete.m4 rename to resources/3rdparty/glpk-4.57/m4/lt~obsolete.m4 diff --git a/resources/3rdparty/glpk-4.53/missing b/resources/3rdparty/glpk-4.57/missing old mode 100644 new mode 100755 similarity index 100% rename from resources/3rdparty/glpk-4.53/missing rename to resources/3rdparty/glpk-4.57/missing diff --git a/resources/3rdparty/glpk-4.53/src/Makefile.am b/resources/3rdparty/glpk-4.57/src/Makefile.am similarity index 88% rename from resources/3rdparty/glpk-4.53/src/Makefile.am rename to resources/3rdparty/glpk-4.57/src/Makefile.am index b4f050f71..836ef11bd 100644 --- a/resources/3rdparty/glpk-4.53/src/Makefile.am +++ b/resources/3rdparty/glpk-4.57/src/Makefile.am @@ -14,10 +14,11 @@ libglpk_la_CPPFLAGS = \ -I$(srcdir)/minisat \ -I$(srcdir)/misc \ -I$(srcdir)/proxy \ +-I$(srcdir)/simplex \ -I$(srcdir)/zlib libglpk_la_LDFLAGS = \ --version-info 37:0:1 \ +-version-info 38:0:2 \ -export-symbols-regex '^glp_*' libglpk_la_SOURCES = \ @@ -64,7 +65,6 @@ glpios10.c \ glpios11.c \ glpios12.c \ glpipm.c \ -glplpf.c \ glpmat.c \ glpmpl01.c \ glpmpl02.c \ @@ -86,12 +86,9 @@ glprgr.c \ glpscl.c \ glpsdf.c \ glpspm.c \ -glpspx01.c \ -glpspx02.c \ glpsql.c \ glpssx01.c \ glpssx02.c \ -glptsp.c \ lux.c \ amd/amd_1.c \ amd/amd_2.c \ @@ -105,11 +102,15 @@ amd/amd_post_tree.c \ amd/amd_postorder.c \ amd/amd_preprocess.c \ amd/amd_valid.c \ +bflib/btf.c \ +bflib/btfint.c \ bflib/fhv.c \ bflib/fhvint.c \ bflib/ifu.c \ bflib/luf.c \ bflib/lufint.c \ +bflib/scf.c \ +bflib/scfint.c \ bflib/sgf.c \ bflib/sva.c \ cglib/cfg.c \ @@ -148,6 +149,16 @@ misc/wclique.c \ misc/wclique1.c \ proxy/proxy.c \ proxy/proxy1.c \ +simplex/spxat.c \ +simplex/spxchuzc.c \ +simplex/spxchuzr.c \ +simplex/spxlp.c \ +simplex/spxnt.c \ +simplex/spxprim.c \ +simplex/spxprob.c \ +simplex/spychuzc.c \ +simplex/spychuzr.c \ +simplex/spydual.c \ zlib/adler32.c \ zlib/compress.c \ zlib/crc32.c \ diff --git a/resources/3rdparty/glpk-4.53/src/Makefile.in b/resources/3rdparty/glpk-4.57/src/Makefile.in similarity index 91% rename from resources/3rdparty/glpk-4.53/src/Makefile.in rename to resources/3rdparty/glpk-4.57/src/Makefile.in index caab6d29a..cf9f95ae2 100644 --- a/resources/3rdparty/glpk-4.53/src/Makefile.in +++ b/resources/3rdparty/glpk-4.57/src/Makefile.in @@ -116,47 +116,52 @@ am_libglpk_la_OBJECTS = libglpk_la-avl.lo libglpk_la-bfd.lo \ libglpk_la-glpios08.lo libglpk_la-glpios09.lo \ libglpk_la-glpios10.lo libglpk_la-glpios11.lo \ libglpk_la-glpios12.lo libglpk_la-glpipm.lo \ - libglpk_la-glplpf.lo libglpk_la-glpmat.lo \ - libglpk_la-glpmpl01.lo libglpk_la-glpmpl02.lo \ - libglpk_la-glpmpl03.lo libglpk_la-glpmpl04.lo \ - libglpk_la-glpmpl05.lo libglpk_la-glpmpl06.lo \ - libglpk_la-glpmps.lo libglpk_la-glpnet03.lo \ - libglpk_la-glpnet04.lo libglpk_la-glpnet05.lo \ - libglpk_la-glpnpp01.lo libglpk_la-glpnpp02.lo \ - libglpk_la-glpnpp03.lo libglpk_la-glpnpp04.lo \ - libglpk_la-glpnpp05.lo libglpk_la-glpnpp06.lo \ - libglpk_la-glprgr.lo libglpk_la-glpscl.lo libglpk_la-glpsdf.lo \ - libglpk_la-glpspm.lo libglpk_la-glpspx01.lo \ - libglpk_la-glpspx02.lo libglpk_la-glpsql.lo \ - libglpk_la-glpssx01.lo libglpk_la-glpssx02.lo \ - libglpk_la-glptsp.lo libglpk_la-lux.lo libglpk_la-amd_1.lo \ + libglpk_la-glpmat.lo libglpk_la-glpmpl01.lo \ + libglpk_la-glpmpl02.lo libglpk_la-glpmpl03.lo \ + libglpk_la-glpmpl04.lo libglpk_la-glpmpl05.lo \ + libglpk_la-glpmpl06.lo libglpk_la-glpmps.lo \ + libglpk_la-glpnet03.lo libglpk_la-glpnet04.lo \ + libglpk_la-glpnet05.lo libglpk_la-glpnpp01.lo \ + libglpk_la-glpnpp02.lo libglpk_la-glpnpp03.lo \ + libglpk_la-glpnpp04.lo libglpk_la-glpnpp05.lo \ + libglpk_la-glpnpp06.lo libglpk_la-glprgr.lo \ + libglpk_la-glpscl.lo libglpk_la-glpsdf.lo libglpk_la-glpspm.lo \ + libglpk_la-glpsql.lo libglpk_la-glpssx01.lo \ + libglpk_la-glpssx02.lo libglpk_la-lux.lo libglpk_la-amd_1.lo \ libglpk_la-amd_2.lo libglpk_la-amd_aat.lo \ libglpk_la-amd_control.lo libglpk_la-amd_defaults.lo \ libglpk_la-amd_dump.lo libglpk_la-amd_info.lo \ libglpk_la-amd_order.lo libglpk_la-amd_post_tree.lo \ libglpk_la-amd_postorder.lo libglpk_la-amd_preprocess.lo \ - libglpk_la-amd_valid.lo libglpk_la-fhv.lo libglpk_la-fhvint.lo \ - libglpk_la-ifu.lo libglpk_la-luf.lo libglpk_la-lufint.lo \ - libglpk_la-sgf.lo libglpk_la-sva.lo libglpk_la-cfg.lo \ - libglpk_la-cfg1.lo libglpk_la-colamd.lo libglpk_la-alloc.lo \ - libglpk_la-dlsup.lo libglpk_la-env.lo libglpk_la-error.lo \ - libglpk_la-stdout.lo libglpk_la-stream.lo libglpk_la-time.lo \ - libglpk_la-tls.lo libglpk_la-minisat.lo libglpk_la-bignum.lo \ - libglpk_la-dmp.lo libglpk_la-ffalg.lo libglpk_la-fp2rat.lo \ - libglpk_la-gcd.lo libglpk_la-jd.lo libglpk_la-keller.lo \ - libglpk_la-mc13d.lo libglpk_la-mc21a.lo libglpk_la-okalg.lo \ - libglpk_la-qmd.lo libglpk_la-relax4.lo libglpk_la-rng.lo \ - libglpk_la-rng1.lo libglpk_la-round2n.lo libglpk_la-str2int.lo \ - libglpk_la-str2num.lo libglpk_la-strspx.lo \ - libglpk_la-strtrim.lo libglpk_la-triang.lo \ - libglpk_la-wclique.lo libglpk_la-wclique1.lo \ - libglpk_la-proxy.lo libglpk_la-proxy1.lo libglpk_la-adler32.lo \ - libglpk_la-compress.lo libglpk_la-crc32.lo \ - libglpk_la-deflate.lo libglpk_la-gzclose.lo \ - libglpk_la-gzlib.lo libglpk_la-gzread.lo libglpk_la-gzwrite.lo \ - libglpk_la-inffast.lo libglpk_la-inflate.lo \ - libglpk_la-inftrees.lo libglpk_la-trees.lo \ - libglpk_la-uncompr.lo libglpk_la-zio.lo libglpk_la-zutil.lo + libglpk_la-amd_valid.lo libglpk_la-btf.lo libglpk_la-btfint.lo \ + libglpk_la-fhv.lo libglpk_la-fhvint.lo libglpk_la-ifu.lo \ + libglpk_la-luf.lo libglpk_la-lufint.lo libglpk_la-scf.lo \ + libglpk_la-scfint.lo libglpk_la-sgf.lo libglpk_la-sva.lo \ + libglpk_la-cfg.lo libglpk_la-cfg1.lo libglpk_la-colamd.lo \ + libglpk_la-alloc.lo libglpk_la-dlsup.lo libglpk_la-env.lo \ + libglpk_la-error.lo libglpk_la-stdout.lo libglpk_la-stream.lo \ + libglpk_la-time.lo libglpk_la-tls.lo libglpk_la-minisat.lo \ + libglpk_la-bignum.lo libglpk_la-dmp.lo libglpk_la-ffalg.lo \ + libglpk_la-fp2rat.lo libglpk_la-gcd.lo libglpk_la-jd.lo \ + libglpk_la-keller.lo libglpk_la-mc13d.lo libglpk_la-mc21a.lo \ + libglpk_la-okalg.lo libglpk_la-qmd.lo libglpk_la-relax4.lo \ + libglpk_la-rng.lo libglpk_la-rng1.lo libglpk_la-round2n.lo \ + libglpk_la-str2int.lo libglpk_la-str2num.lo \ + libglpk_la-strspx.lo libglpk_la-strtrim.lo \ + libglpk_la-triang.lo libglpk_la-wclique.lo \ + libglpk_la-wclique1.lo libglpk_la-proxy.lo \ + libglpk_la-proxy1.lo libglpk_la-spxat.lo \ + libglpk_la-spxchuzc.lo libglpk_la-spxchuzr.lo \ + libglpk_la-spxlp.lo libglpk_la-spxnt.lo libglpk_la-spxprim.lo \ + libglpk_la-spxprob.lo libglpk_la-spychuzc.lo \ + libglpk_la-spychuzr.lo libglpk_la-spydual.lo \ + libglpk_la-adler32.lo libglpk_la-compress.lo \ + libglpk_la-crc32.lo libglpk_la-deflate.lo \ + libglpk_la-gzclose.lo libglpk_la-gzlib.lo libglpk_la-gzread.lo \ + libglpk_la-gzwrite.lo libglpk_la-inffast.lo \ + libglpk_la-inflate.lo libglpk_la-inftrees.lo \ + libglpk_la-trees.lo libglpk_la-uncompr.lo libglpk_la-zio.lo \ + libglpk_la-zutil.lo libglpk_la_OBJECTS = $(am_libglpk_la_OBJECTS) libglpk_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ @@ -310,10 +315,11 @@ libglpk_la_CPPFLAGS = \ -I$(srcdir)/minisat \ -I$(srcdir)/misc \ -I$(srcdir)/proxy \ +-I$(srcdir)/simplex \ -I$(srcdir)/zlib libglpk_la_LDFLAGS = \ --version-info 37:0:1 \ +-version-info 38:0:2 \ -export-symbols-regex '^glp_*' libglpk_la_SOURCES = \ @@ -360,7 +366,6 @@ glpios10.c \ glpios11.c \ glpios12.c \ glpipm.c \ -glplpf.c \ glpmat.c \ glpmpl01.c \ glpmpl02.c \ @@ -382,12 +387,9 @@ glprgr.c \ glpscl.c \ glpsdf.c \ glpspm.c \ -glpspx01.c \ -glpspx02.c \ glpsql.c \ glpssx01.c \ glpssx02.c \ -glptsp.c \ lux.c \ amd/amd_1.c \ amd/amd_2.c \ @@ -401,11 +403,15 @@ amd/amd_post_tree.c \ amd/amd_postorder.c \ amd/amd_preprocess.c \ amd/amd_valid.c \ +bflib/btf.c \ +bflib/btfint.c \ bflib/fhv.c \ bflib/fhvint.c \ bflib/ifu.c \ bflib/luf.c \ bflib/lufint.c \ +bflib/scf.c \ +bflib/scfint.c \ bflib/sgf.c \ bflib/sva.c \ cglib/cfg.c \ @@ -444,6 +450,16 @@ misc/wclique.c \ misc/wclique1.c \ proxy/proxy.c \ proxy/proxy1.c \ +simplex/spxat.c \ +simplex/spxchuzc.c \ +simplex/spxchuzr.c \ +simplex/spxlp.c \ +simplex/spxnt.c \ +simplex/spxprim.c \ +simplex/spxprob.c \ +simplex/spychuzc.c \ +simplex/spychuzr.c \ +simplex/spydual.c \ zlib/adler32.c \ zlib/compress.c \ zlib/crc32.c \ @@ -555,6 +571,8 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-bfd.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-bfx.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-bignum.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-btf.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-btfint.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-cfg.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-cfg1.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-colamd.Plo@am__quote@ @@ -610,7 +628,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpios11.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpios12.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpipm.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glplpf.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpmat.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpmpl01.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpmpl02.Plo@am__quote@ @@ -632,12 +649,9 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpscl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpsdf.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpspm.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpspx01.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpspx02.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpsql.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpssx01.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpssx02.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glptsp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-gzclose.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-gzlib.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-gzread.Plo@am__quote@ @@ -662,7 +676,19 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-rng.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-rng1.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-round2n.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-scf.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-scfint.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-sgf.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-spxat.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-spxchuzc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-spxchuzr.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-spxlp.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-spxnt.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-spxprim.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-spxprob.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-spychuzc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-spychuzr.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-spydual.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-stdout.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-str2int.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-str2num.Plo@am__quote@ @@ -1002,13 +1028,6 @@ libglpk_la-glpipm.lo: glpipm.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpipm.lo `test -f 'glpipm.c' || echo '$(srcdir)/'`glpipm.c -libglpk_la-glplpf.lo: glplpf.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glplpf.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glplpf.Tpo -c -o libglpk_la-glplpf.lo `test -f 'glplpf.c' || echo '$(srcdir)/'`glplpf.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glplpf.Tpo $(DEPDIR)/libglpk_la-glplpf.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glplpf.c' object='libglpk_la-glplpf.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glplpf.lo `test -f 'glplpf.c' || echo '$(srcdir)/'`glplpf.c - libglpk_la-glpmat.lo: glpmat.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpmat.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpmat.Tpo -c -o libglpk_la-glpmat.lo `test -f 'glpmat.c' || echo '$(srcdir)/'`glpmat.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpmat.Tpo $(DEPDIR)/libglpk_la-glpmat.Plo @@ -1156,20 +1175,6 @@ libglpk_la-glpspm.lo: glpspm.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpspm.lo `test -f 'glpspm.c' || echo '$(srcdir)/'`glpspm.c -libglpk_la-glpspx01.lo: glpspx01.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpspx01.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpspx01.Tpo -c -o libglpk_la-glpspx01.lo `test -f 'glpspx01.c' || echo '$(srcdir)/'`glpspx01.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpspx01.Tpo $(DEPDIR)/libglpk_la-glpspx01.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpspx01.c' object='libglpk_la-glpspx01.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpspx01.lo `test -f 'glpspx01.c' || echo '$(srcdir)/'`glpspx01.c - -libglpk_la-glpspx02.lo: glpspx02.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpspx02.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpspx02.Tpo -c -o libglpk_la-glpspx02.lo `test -f 'glpspx02.c' || echo '$(srcdir)/'`glpspx02.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpspx02.Tpo $(DEPDIR)/libglpk_la-glpspx02.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpspx02.c' object='libglpk_la-glpspx02.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpspx02.lo `test -f 'glpspx02.c' || echo '$(srcdir)/'`glpspx02.c - libglpk_la-glpsql.lo: glpsql.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpsql.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpsql.Tpo -c -o libglpk_la-glpsql.lo `test -f 'glpsql.c' || echo '$(srcdir)/'`glpsql.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpsql.Tpo $(DEPDIR)/libglpk_la-glpsql.Plo @@ -1191,13 +1196,6 @@ libglpk_la-glpssx02.lo: glpssx02.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpssx02.lo `test -f 'glpssx02.c' || echo '$(srcdir)/'`glpssx02.c -libglpk_la-glptsp.lo: glptsp.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glptsp.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glptsp.Tpo -c -o libglpk_la-glptsp.lo `test -f 'glptsp.c' || echo '$(srcdir)/'`glptsp.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glptsp.Tpo $(DEPDIR)/libglpk_la-glptsp.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glptsp.c' object='libglpk_la-glptsp.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glptsp.lo `test -f 'glptsp.c' || echo '$(srcdir)/'`glptsp.c - libglpk_la-lux.lo: lux.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-lux.lo -MD -MP -MF $(DEPDIR)/libglpk_la-lux.Tpo -c -o libglpk_la-lux.lo `test -f 'lux.c' || echo '$(srcdir)/'`lux.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-lux.Tpo $(DEPDIR)/libglpk_la-lux.Plo @@ -1289,6 +1287,20 @@ libglpk_la-amd_valid.lo: amd/amd_valid.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-amd_valid.lo `test -f 'amd/amd_valid.c' || echo '$(srcdir)/'`amd/amd_valid.c +libglpk_la-btf.lo: bflib/btf.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-btf.lo -MD -MP -MF $(DEPDIR)/libglpk_la-btf.Tpo -c -o libglpk_la-btf.lo `test -f 'bflib/btf.c' || echo '$(srcdir)/'`bflib/btf.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-btf.Tpo $(DEPDIR)/libglpk_la-btf.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bflib/btf.c' object='libglpk_la-btf.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-btf.lo `test -f 'bflib/btf.c' || echo '$(srcdir)/'`bflib/btf.c + +libglpk_la-btfint.lo: bflib/btfint.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-btfint.lo -MD -MP -MF $(DEPDIR)/libglpk_la-btfint.Tpo -c -o libglpk_la-btfint.lo `test -f 'bflib/btfint.c' || echo '$(srcdir)/'`bflib/btfint.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-btfint.Tpo $(DEPDIR)/libglpk_la-btfint.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bflib/btfint.c' object='libglpk_la-btfint.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-btfint.lo `test -f 'bflib/btfint.c' || echo '$(srcdir)/'`bflib/btfint.c + libglpk_la-fhv.lo: bflib/fhv.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-fhv.lo -MD -MP -MF $(DEPDIR)/libglpk_la-fhv.Tpo -c -o libglpk_la-fhv.lo `test -f 'bflib/fhv.c' || echo '$(srcdir)/'`bflib/fhv.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-fhv.Tpo $(DEPDIR)/libglpk_la-fhv.Plo @@ -1324,6 +1336,20 @@ libglpk_la-lufint.lo: bflib/lufint.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-lufint.lo `test -f 'bflib/lufint.c' || echo '$(srcdir)/'`bflib/lufint.c +libglpk_la-scf.lo: bflib/scf.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-scf.lo -MD -MP -MF $(DEPDIR)/libglpk_la-scf.Tpo -c -o libglpk_la-scf.lo `test -f 'bflib/scf.c' || echo '$(srcdir)/'`bflib/scf.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-scf.Tpo $(DEPDIR)/libglpk_la-scf.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bflib/scf.c' object='libglpk_la-scf.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-scf.lo `test -f 'bflib/scf.c' || echo '$(srcdir)/'`bflib/scf.c + +libglpk_la-scfint.lo: bflib/scfint.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-scfint.lo -MD -MP -MF $(DEPDIR)/libglpk_la-scfint.Tpo -c -o libglpk_la-scfint.lo `test -f 'bflib/scfint.c' || echo '$(srcdir)/'`bflib/scfint.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-scfint.Tpo $(DEPDIR)/libglpk_la-scfint.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bflib/scfint.c' object='libglpk_la-scfint.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-scfint.lo `test -f 'bflib/scfint.c' || echo '$(srcdir)/'`bflib/scfint.c + libglpk_la-sgf.lo: bflib/sgf.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-sgf.lo -MD -MP -MF $(DEPDIR)/libglpk_la-sgf.Tpo -c -o libglpk_la-sgf.lo `test -f 'bflib/sgf.c' || echo '$(srcdir)/'`bflib/sgf.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-sgf.Tpo $(DEPDIR)/libglpk_la-sgf.Plo @@ -1590,6 +1616,76 @@ libglpk_la-proxy1.lo: proxy/proxy1.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-proxy1.lo `test -f 'proxy/proxy1.c' || echo '$(srcdir)/'`proxy/proxy1.c +libglpk_la-spxat.lo: simplex/spxat.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-spxat.lo -MD -MP -MF $(DEPDIR)/libglpk_la-spxat.Tpo -c -o libglpk_la-spxat.lo `test -f 'simplex/spxat.c' || echo '$(srcdir)/'`simplex/spxat.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-spxat.Tpo $(DEPDIR)/libglpk_la-spxat.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='simplex/spxat.c' object='libglpk_la-spxat.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-spxat.lo `test -f 'simplex/spxat.c' || echo '$(srcdir)/'`simplex/spxat.c + +libglpk_la-spxchuzc.lo: simplex/spxchuzc.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-spxchuzc.lo -MD -MP -MF $(DEPDIR)/libglpk_la-spxchuzc.Tpo -c -o libglpk_la-spxchuzc.lo `test -f 'simplex/spxchuzc.c' || echo '$(srcdir)/'`simplex/spxchuzc.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-spxchuzc.Tpo $(DEPDIR)/libglpk_la-spxchuzc.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='simplex/spxchuzc.c' object='libglpk_la-spxchuzc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-spxchuzc.lo `test -f 'simplex/spxchuzc.c' || echo '$(srcdir)/'`simplex/spxchuzc.c + +libglpk_la-spxchuzr.lo: simplex/spxchuzr.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-spxchuzr.lo -MD -MP -MF $(DEPDIR)/libglpk_la-spxchuzr.Tpo -c -o libglpk_la-spxchuzr.lo `test -f 'simplex/spxchuzr.c' || echo '$(srcdir)/'`simplex/spxchuzr.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-spxchuzr.Tpo $(DEPDIR)/libglpk_la-spxchuzr.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='simplex/spxchuzr.c' object='libglpk_la-spxchuzr.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-spxchuzr.lo `test -f 'simplex/spxchuzr.c' || echo '$(srcdir)/'`simplex/spxchuzr.c + +libglpk_la-spxlp.lo: simplex/spxlp.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-spxlp.lo -MD -MP -MF $(DEPDIR)/libglpk_la-spxlp.Tpo -c -o libglpk_la-spxlp.lo `test -f 'simplex/spxlp.c' || echo '$(srcdir)/'`simplex/spxlp.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-spxlp.Tpo $(DEPDIR)/libglpk_la-spxlp.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='simplex/spxlp.c' object='libglpk_la-spxlp.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-spxlp.lo `test -f 'simplex/spxlp.c' || echo '$(srcdir)/'`simplex/spxlp.c + +libglpk_la-spxnt.lo: simplex/spxnt.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-spxnt.lo -MD -MP -MF $(DEPDIR)/libglpk_la-spxnt.Tpo -c -o libglpk_la-spxnt.lo `test -f 'simplex/spxnt.c' || echo '$(srcdir)/'`simplex/spxnt.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-spxnt.Tpo $(DEPDIR)/libglpk_la-spxnt.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='simplex/spxnt.c' object='libglpk_la-spxnt.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-spxnt.lo `test -f 'simplex/spxnt.c' || echo '$(srcdir)/'`simplex/spxnt.c + +libglpk_la-spxprim.lo: simplex/spxprim.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-spxprim.lo -MD -MP -MF $(DEPDIR)/libglpk_la-spxprim.Tpo -c -o libglpk_la-spxprim.lo `test -f 'simplex/spxprim.c' || echo '$(srcdir)/'`simplex/spxprim.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-spxprim.Tpo $(DEPDIR)/libglpk_la-spxprim.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='simplex/spxprim.c' object='libglpk_la-spxprim.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-spxprim.lo `test -f 'simplex/spxprim.c' || echo '$(srcdir)/'`simplex/spxprim.c + +libglpk_la-spxprob.lo: simplex/spxprob.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-spxprob.lo -MD -MP -MF $(DEPDIR)/libglpk_la-spxprob.Tpo -c -o libglpk_la-spxprob.lo `test -f 'simplex/spxprob.c' || echo '$(srcdir)/'`simplex/spxprob.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-spxprob.Tpo $(DEPDIR)/libglpk_la-spxprob.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='simplex/spxprob.c' object='libglpk_la-spxprob.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-spxprob.lo `test -f 'simplex/spxprob.c' || echo '$(srcdir)/'`simplex/spxprob.c + +libglpk_la-spychuzc.lo: simplex/spychuzc.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-spychuzc.lo -MD -MP -MF $(DEPDIR)/libglpk_la-spychuzc.Tpo -c -o libglpk_la-spychuzc.lo `test -f 'simplex/spychuzc.c' || echo '$(srcdir)/'`simplex/spychuzc.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-spychuzc.Tpo $(DEPDIR)/libglpk_la-spychuzc.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='simplex/spychuzc.c' object='libglpk_la-spychuzc.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-spychuzc.lo `test -f 'simplex/spychuzc.c' || echo '$(srcdir)/'`simplex/spychuzc.c + +libglpk_la-spychuzr.lo: simplex/spychuzr.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-spychuzr.lo -MD -MP -MF $(DEPDIR)/libglpk_la-spychuzr.Tpo -c -o libglpk_la-spychuzr.lo `test -f 'simplex/spychuzr.c' || echo '$(srcdir)/'`simplex/spychuzr.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-spychuzr.Tpo $(DEPDIR)/libglpk_la-spychuzr.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='simplex/spychuzr.c' object='libglpk_la-spychuzr.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-spychuzr.lo `test -f 'simplex/spychuzr.c' || echo '$(srcdir)/'`simplex/spychuzr.c + +libglpk_la-spydual.lo: simplex/spydual.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-spydual.lo -MD -MP -MF $(DEPDIR)/libglpk_la-spydual.Tpo -c -o libglpk_la-spydual.lo `test -f 'simplex/spydual.c' || echo '$(srcdir)/'`simplex/spydual.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-spydual.Tpo $(DEPDIR)/libglpk_la-spydual.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='simplex/spydual.c' object='libglpk_la-spydual.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-spydual.lo `test -f 'simplex/spydual.c' || echo '$(srcdir)/'`simplex/spydual.c + libglpk_la-adler32.lo: zlib/adler32.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-adler32.lo -MD -MP -MF $(DEPDIR)/libglpk_la-adler32.Tpo -c -o libglpk_la-adler32.lo `test -f 'zlib/adler32.c' || echo '$(srcdir)/'`zlib/adler32.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-adler32.Tpo $(DEPDIR)/libglpk_la-adler32.Plo diff --git a/resources/3rdparty/glpk-4.53/src/amd/COPYING b/resources/3rdparty/glpk-4.57/src/amd/COPYING similarity index 100% rename from resources/3rdparty/glpk-4.53/src/amd/COPYING rename to resources/3rdparty/glpk-4.57/src/amd/COPYING diff --git a/resources/3rdparty/glpk-4.53/src/amd/README b/resources/3rdparty/glpk-4.57/src/amd/README similarity index 100% rename from resources/3rdparty/glpk-4.53/src/amd/README rename to resources/3rdparty/glpk-4.57/src/amd/README diff --git a/resources/3rdparty/glpk-4.53/src/amd/amd.h b/resources/3rdparty/glpk-4.57/src/amd/amd.h similarity index 100% rename from resources/3rdparty/glpk-4.53/src/amd/amd.h rename to resources/3rdparty/glpk-4.57/src/amd/amd.h diff --git a/resources/3rdparty/glpk-4.53/src/amd/amd_1.c b/resources/3rdparty/glpk-4.57/src/amd/amd_1.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/amd/amd_1.c rename to resources/3rdparty/glpk-4.57/src/amd/amd_1.c diff --git a/resources/3rdparty/glpk-4.53/src/amd/amd_2.c b/resources/3rdparty/glpk-4.57/src/amd/amd_2.c similarity index 99% rename from resources/3rdparty/glpk-4.53/src/amd/amd_2.c rename to resources/3rdparty/glpk-4.57/src/amd/amd_2.c index b448fc93c..36ae828ab 100644 --- a/resources/3rdparty/glpk-4.53/src/amd/amd_2.c +++ b/resources/3rdparty/glpk-4.57/src/amd/amd_2.c @@ -546,7 +546,7 @@ GLOBAL void AMD_2 * p1: Pe [i] for some variable i (start of element list) * p2: Pe [i] + Elen [i] - 1 for some variable i * p3: index of first supervariable in clean list - * p4: + * p4: * pdst: destination pointer, for compression * pend: end of memory to compress * pj: pointer into an element or variable diff --git a/resources/3rdparty/glpk-4.53/src/amd/amd_aat.c b/resources/3rdparty/glpk-4.57/src/amd/amd_aat.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/amd/amd_aat.c rename to resources/3rdparty/glpk-4.57/src/amd/amd_aat.c diff --git a/resources/3rdparty/glpk-4.53/src/amd/amd_control.c b/resources/3rdparty/glpk-4.57/src/amd/amd_control.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/amd/amd_control.c rename to resources/3rdparty/glpk-4.57/src/amd/amd_control.c diff --git a/resources/3rdparty/glpk-4.53/src/amd/amd_defaults.c b/resources/3rdparty/glpk-4.57/src/amd/amd_defaults.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/amd/amd_defaults.c rename to resources/3rdparty/glpk-4.57/src/amd/amd_defaults.c diff --git a/resources/3rdparty/glpk-4.53/src/amd/amd_dump.c b/resources/3rdparty/glpk-4.57/src/amd/amd_dump.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/amd/amd_dump.c rename to resources/3rdparty/glpk-4.57/src/amd/amd_dump.c diff --git a/resources/3rdparty/glpk-4.53/src/amd/amd_info.c b/resources/3rdparty/glpk-4.57/src/amd/amd_info.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/amd/amd_info.c rename to resources/3rdparty/glpk-4.57/src/amd/amd_info.c diff --git a/resources/3rdparty/glpk-4.53/src/amd/amd_internal.h b/resources/3rdparty/glpk-4.57/src/amd/amd_internal.h similarity index 100% rename from resources/3rdparty/glpk-4.53/src/amd/amd_internal.h rename to resources/3rdparty/glpk-4.57/src/amd/amd_internal.h diff --git a/resources/3rdparty/glpk-4.53/src/amd/amd_order.c b/resources/3rdparty/glpk-4.57/src/amd/amd_order.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/amd/amd_order.c rename to resources/3rdparty/glpk-4.57/src/amd/amd_order.c diff --git a/resources/3rdparty/glpk-4.53/src/amd/amd_post_tree.c b/resources/3rdparty/glpk-4.57/src/amd/amd_post_tree.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/amd/amd_post_tree.c rename to resources/3rdparty/glpk-4.57/src/amd/amd_post_tree.c diff --git a/resources/3rdparty/glpk-4.53/src/amd/amd_postorder.c b/resources/3rdparty/glpk-4.57/src/amd/amd_postorder.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/amd/amd_postorder.c rename to resources/3rdparty/glpk-4.57/src/amd/amd_postorder.c diff --git a/resources/3rdparty/glpk-4.53/src/amd/amd_preprocess.c b/resources/3rdparty/glpk-4.57/src/amd/amd_preprocess.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/amd/amd_preprocess.c rename to resources/3rdparty/glpk-4.57/src/amd/amd_preprocess.c diff --git a/resources/3rdparty/glpk-4.53/src/amd/amd_valid.c b/resources/3rdparty/glpk-4.57/src/amd/amd_valid.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/amd/amd_valid.c rename to resources/3rdparty/glpk-4.57/src/amd/amd_valid.c diff --git a/resources/3rdparty/glpk-4.53/src/avl.c b/resources/3rdparty/glpk-4.57/src/avl.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/avl.c rename to resources/3rdparty/glpk-4.57/src/avl.c diff --git a/resources/3rdparty/glpk-4.53/src/avl.h b/resources/3rdparty/glpk-4.57/src/avl.h similarity index 100% rename from resources/3rdparty/glpk-4.53/src/avl.h rename to resources/3rdparty/glpk-4.57/src/avl.h diff --git a/resources/3rdparty/glpk-4.57/src/bfd.c b/resources/3rdparty/glpk-4.57/src/bfd.c new file mode 100644 index 000000000..9e70619dc --- /dev/null +++ b/resources/3rdparty/glpk-4.57/src/bfd.c @@ -0,0 +1,508 @@ +/* bfd.c (LP basis factorization driver) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2007, 2014 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "glpk.h" +#include "env.h" +#include "bfd.h" +#include "fhvint.h" +#include "scfint.h" +#ifdef GLP_DEBUG +#include "glpspm.h" +#endif + +struct BFD +{ /* LP basis factorization driver */ + int valid; + /* factorization is valid only if this flag is set */ + int type; + /* type of factorization used: + 0 - interface not established yet + 1 - FHV-factorization + 2 - Schur-complement-based factorization */ + union + { void *none; /* type = 0 */ + FHVINT *fhvi; /* type = 1 */ + SCFINT *scfi; /* type = 2 */ + } u; + /* interface to factorization of LP basis */ + glp_bfcp parm; + /* factorization control parameters */ +#ifdef GLP_DEBUG + SPM *B; + /* current basis (for testing/debugging only) */ +#endif + int upd_cnt; + /* factorization update count */ +#if 1 /* 21/IV-2014 */ + double b_norm; + /* 1-norm of matrix B */ + double i_norm; + /* estimated 1-norm of matrix inv(B) */ +#endif +}; + +BFD *bfd_create_it(void) +{ /* create LP basis factorization */ + BFD *bfd; +#ifdef GLP_DEBUG + xprintf("bfd_create_it: warning: debugging version used\n"); +#endif + bfd = talloc(1, BFD); + bfd->valid = 0; + bfd->type = 0; + bfd->u.none = NULL; + bfd_set_bfcp(bfd, NULL); +#ifdef GLP_DEBUG + bfd->B = NULL; +#endif + bfd->upd_cnt = 0; + return bfd; +} + +#if 0 /* 08/III-2014 */ +void bfd_set_parm(BFD *bfd, const void *parm) +{ /* change LP basis factorization control parameters */ + memcpy(&bfd->parm, parm, sizeof(glp_bfcp)); + return; +} +#endif + +void bfd_get_bfcp(BFD *bfd, void /* glp_bfcp */ *parm) +{ /* retrieve LP basis factorization control parameters */ + memcpy(parm, &bfd->parm, sizeof(glp_bfcp)); + return; +} + +void bfd_set_bfcp(BFD *bfd, const void /* glp_bfcp */ *parm) +{ /* change LP basis factorization control parameters */ + if (parm == NULL) + { /* reset to default */ + memset(&bfd->parm, 0, sizeof(glp_bfcp)); + bfd->parm.type = GLP_BF_LUF + GLP_BF_FT; + bfd->parm.piv_tol = 0.10; + bfd->parm.piv_lim = 4; + bfd->parm.suhl = 1; + bfd->parm.eps_tol = DBL_EPSILON; + bfd->parm.nfs_max = 100; + bfd->parm.nrs_max = 70; + } + else + memcpy(&bfd->parm, parm, sizeof(glp_bfcp)); + return; +} + +#if 1 /* 21/IV-2014 */ +struct bfd_info +{ BFD *bfd; + int (*col)(void *info, int j, int ind[], double val[]); + void *info; +}; + +static int bfd_col(void *info_, int j, int ind[], double val[]) +{ struct bfd_info *info = info_; + int t, len; + double sum; + len = info->col(info->info, j, ind, val); + sum = 0.0; + for (t = 1; t <= len; t++) + { if (val[t] >= 0.0) + sum += val[t]; + else + sum -= val[t]; + } + if (info->bfd->b_norm < sum) + info->bfd->b_norm = sum; + return len; +} +#endif + +int bfd_factorize(BFD *bfd, int m, /*const int bh[],*/ int (*col1) + (void *info, int j, int ind[], double val[]), void *info1) +{ /* compute LP basis factorization */ +#if 1 /* 21/IV-2014 */ + struct bfd_info info; +#endif + int type, ret; + /*xassert(bh == bh);*/ + /* invalidate current factorization */ + bfd->valid = 0; + /* determine required factorization type */ + switch (bfd->parm.type) + { case GLP_BF_LUF + GLP_BF_FT: + type = 1; + break; + case GLP_BF_LUF + GLP_BF_BG: + case GLP_BF_LUF + GLP_BF_GR: + case GLP_BF_BTF + GLP_BF_BG: + case GLP_BF_BTF + GLP_BF_GR: + type = 2; + break; + default: + xassert(bfd != bfd); + } + /* delete factorization interface, if necessary */ + switch (bfd->type) + { case 0: + break; + case 1: + if (type != 1) + { bfd->type = 0; + fhvint_delete(bfd->u.fhvi); + bfd->u.fhvi = NULL; + } + break; + case 2: + if (type != 2) + { bfd->type = 0; + scfint_delete(bfd->u.scfi); + bfd->u.scfi = NULL; + } + break; + default: + xassert(bfd != bfd); + } + /* establish factorization interface, if necessary */ + if (bfd->type == 0) + { switch (type) + { case 1: + bfd->type = 1; + xassert(bfd->u.fhvi == NULL); + bfd->u.fhvi = fhvint_create(); + break; + case 2: + bfd->type = 2; + xassert(bfd->u.scfi == NULL); + if (!(bfd->parm.type & GLP_BF_BTF)) + bfd->u.scfi = scfint_create(1); + else + bfd->u.scfi = scfint_create(2); + break; + default: + xassert(type != type); + } + } + /* try to compute factorization */ +#if 1 /* 21/IV-2014 */ + bfd->b_norm = bfd->i_norm = 0.0; + info.bfd = bfd; + info.col = col1; + info.info = info1; +#endif + switch (bfd->type) + { case 1: + bfd->u.fhvi->lufi->sgf_piv_tol = bfd->parm.piv_tol; + bfd->u.fhvi->lufi->sgf_piv_lim = bfd->parm.piv_lim; + bfd->u.fhvi->lufi->sgf_suhl = bfd->parm.suhl; + bfd->u.fhvi->lufi->sgf_eps_tol = bfd->parm.eps_tol; + bfd->u.fhvi->nfs_max = bfd->parm.nfs_max; + ret = fhvint_factorize(bfd->u.fhvi, m, bfd_col, &info); +#if 1 /* FIXME */ + if (ret == 0) + bfd->i_norm = fhvint_estimate(bfd->u.fhvi); + else + ret = BFD_ESING; +#endif + break; + case 2: + if (bfd->u.scfi->scf.type == 1) + { bfd->u.scfi->u.lufi->sgf_piv_tol = bfd->parm.piv_tol; + bfd->u.scfi->u.lufi->sgf_piv_lim = bfd->parm.piv_lim; + bfd->u.scfi->u.lufi->sgf_suhl = bfd->parm.suhl; + bfd->u.scfi->u.lufi->sgf_eps_tol = bfd->parm.eps_tol; + } + else if (bfd->u.scfi->scf.type == 2) + { bfd->u.scfi->u.btfi->sgf_piv_tol = bfd->parm.piv_tol; + bfd->u.scfi->u.btfi->sgf_piv_lim = bfd->parm.piv_lim; + bfd->u.scfi->u.btfi->sgf_suhl = bfd->parm.suhl; + bfd->u.scfi->u.btfi->sgf_eps_tol = bfd->parm.eps_tol; + } + else + xassert(bfd != bfd); + bfd->u.scfi->nn_max = bfd->parm.nrs_max; + ret = scfint_factorize(bfd->u.scfi, m, bfd_col, &info); +#if 1 /* FIXME */ + if (ret == 0) + bfd->i_norm = scfint_estimate(bfd->u.scfi); + else + ret = BFD_ESING; +#endif + break; + default: + xassert(bfd != bfd); + } +#ifdef GLP_DEBUG + /* save specified LP basis */ + if (bfd->B != NULL) + spm_delete_mat(bfd->B); + bfd->B = spm_create_mat(m, m); + { int *ind = talloc(1+m, int); + double *val = talloc(1+m, double); + int j, k, len; + for (j = 1; j <= m; j++) + { len = col(info, j, ind, val); + for (k = 1; k <= len; k++) + spm_new_elem(bfd->B, ind[k], j, val[k]); + } + tfree(ind); + tfree(val); + } +#endif + if (ret == 0) + { /* factorization has been successfully computed */ + double cond; + bfd->valid = 1; +#ifdef GLP_DEBUG + cond = bfd_condest(bfd); + if (cond > 1e9) + xprintf("bfd_factorize: warning: cond(B) = %g\n", cond); +#endif + } +#ifdef GLP_DEBUG + xprintf("bfd_factorize: m = %d; ret = %d\n", m, ret); +#endif + bfd->upd_cnt = 0; + return ret; +} + +#if 0 /* 21/IV-2014 */ +double bfd_estimate(BFD *bfd) +{ /* estimate 1-norm of inv(B) */ + double norm; + xassert(bfd->valid); + xassert(bfd->upd_cnt == 0); + switch (bfd->type) + { case 1: + norm = fhvint_estimate(bfd->u.fhvi); + break; + case 2: + norm = scfint_estimate(bfd->u.scfi); + break; + default: + xassert(bfd != bfd); + } + return norm; +} +#endif + +#if 1 /* 21/IV-2014 */ +double bfd_condest(BFD *bfd) +{ /* estimate condition of B */ + double cond; + xassert(bfd->valid); + /*xassert(bfd->upd_cnt == 0);*/ + cond = bfd->b_norm * bfd->i_norm; + if (cond < 1.0) + cond = 1.0; + return cond; +} +#endif + +void bfd_ftran(BFD *bfd, double x[]) +{ /* perform forward transformation (solve system B * x = b) */ +#ifdef GLP_DEBUG + SPM *B = bfd->B; + int m = B->m; + double *b = talloc(1+m, double); + SPME *e; + int k; + double s, relerr, maxerr; + for (k = 1; k <= m; k++) + b[k] = x[k]; +#endif + xassert(bfd->valid); + switch (bfd->type) + { case 1: + fhvint_ftran(bfd->u.fhvi, x); + break; + case 2: + scfint_ftran(bfd->u.scfi, x); + break; + default: + xassert(bfd != bfd); + } +#ifdef GLP_DEBUG + maxerr = 0.0; + for (k = 1; k <= m; k++) + { s = 0.0; + for (e = B->row[k]; e != NULL; e = e->r_next) + s += e->val * x[e->j]; + relerr = (b[k] - s) / (1.0 + fabs(b[k])); + if (maxerr < relerr) + maxerr = relerr; + } + if (maxerr > 1e-8) + xprintf("bfd_ftran: maxerr = %g; relative error too large\n", + maxerr); + tfree(b); +#endif + return; +} + +void bfd_btran(BFD *bfd, double x[]) +{ /* perform backward transformation (solve system B'* x = b) */ +#ifdef GLP_DEBUG + SPM *B = bfd->B; + int m = B->m; + double *b = talloc(1+m, double); + SPME *e; + int k; + double s, relerr, maxerr; + for (k = 1; k <= m; k++) + b[k] = x[k]; +#endif + xassert(bfd->valid); + switch (bfd->type) + { case 1: + fhvint_btran(bfd->u.fhvi, x); + break; + case 2: + scfint_btran(bfd->u.scfi, x); + break; + default: + xassert(bfd != bfd); + } +#ifdef GLP_DEBUG + maxerr = 0.0; + for (k = 1; k <= m; k++) + { s = 0.0; + for (e = B->col[k]; e != NULL; e = e->c_next) + s += e->val * x[e->i]; + relerr = (b[k] - s) / (1.0 + fabs(b[k])); + if (maxerr < relerr) + maxerr = relerr; + } + if (maxerr > 1e-8) + xprintf("bfd_btran: maxerr = %g; relative error too large\n", + maxerr); + tfree(b); +#endif + return; +} + +int bfd_update(BFD *bfd, int j, int len, const int ind[], const double + val[]) +{ /* update LP basis factorization */ + int ret; + xassert(bfd->valid); + switch (bfd->type) + { case 1: + ret = fhvint_update(bfd->u.fhvi, j, len, ind, val); +#if 1 /* FIXME */ + switch (ret) + { case 0: + break; + case 1: + ret = BFD_ESING; + break; + case 2: + case 3: + ret = BFD_ECOND; + break; + case 4: + ret = BFD_ELIMIT; + break; + case 5: + ret = BFD_ECHECK; + break; + default: + xassert(ret != ret); + } +#endif + break; + case 2: + switch (bfd->parm.type & 0x0F) + { case GLP_BF_BG: + ret = scfint_update(bfd->u.scfi, 1, j, len, ind, val); + break; + case GLP_BF_GR: + ret = scfint_update(bfd->u.scfi, 2, j, len, ind, val); + break; + default: + xassert(bfd != bfd); + } +#if 1 /* FIXME */ + switch (ret) + { case 0: + break; + case 1: + ret = BFD_ELIMIT; + break; + case 2: + ret = BFD_ECOND; + break; + default: + xassert(ret != ret); + } +#endif + break; + default: + xassert(bfd != bfd); + } + if (ret != 0) + { /* updating factorization failed */ + bfd->valid = 0; + } +#ifdef GLP_DEBUG + /* save updated LP basis */ + { SPME *e; + int k; + for (e = bfd->B->col[j]; e != NULL; e = e->c_next) + e->val = 0.0; + spm_drop_zeros(bfd->B, 0.0); + for (k = 1; k <= len; k++) + spm_new_elem(bfd->B, ind[k], j, val[k]); + } +#endif + if (ret == 0) + bfd->upd_cnt++; + return ret; +} + +int bfd_get_count(BFD *bfd) +{ /* determine factorization update count */ + return bfd->upd_cnt; +} + +void bfd_delete_it(BFD *bfd) +{ /* delete LP basis factorization */ + switch (bfd->type) + { case 0: + break; + case 1: + fhvint_delete(bfd->u.fhvi); + break; + case 2: + scfint_delete(bfd->u.scfi); + break; + default: + xassert(bfd != bfd); + } +#ifdef GLP_DEBUG + if (bfd->B != NULL) + spm_delete_mat(bfd->B); +#endif + tfree(bfd); + return; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/bfd.h b/resources/3rdparty/glpk-4.57/src/bfd.h similarity index 77% rename from resources/3rdparty/glpk-4.53/src/bfd.h rename to resources/3rdparty/glpk-4.57/src/bfd.h index 98f7e44b4..1e18e561d 100644 --- a/resources/3rdparty/glpk-4.53/src/bfd.h +++ b/resources/3rdparty/glpk-4.57/src/bfd.h @@ -32,21 +32,39 @@ typedef struct BFD BFD; #define BFD_ECOND 2 /* ill-conditioned matrix */ #define BFD_ECHECK 3 /* insufficient accuracy */ #define BFD_ELIMIT 4 /* update limit reached */ +#if 0 /* 05/III-2014 */ #define BFD_EROOM 5 /* SVA overflow */ +#endif #define bfd_create_it _glp_bfd_create_it BFD *bfd_create_it(void); /* create LP basis factorization */ +#if 0 /* 08/III-2014 */ #define bfd_set_parm _glp_bfd_set_parm void bfd_set_parm(BFD *bfd, const void *parm); /* change LP basis factorization control parameters */ +#endif + +#define bfd_get_bfcp _glp_bfd_get_bfcp +void bfd_get_bfcp(BFD *bfd, void /* glp_bfcp */ *parm); +/* retrieve LP basis factorization control parameters */ + +#define bfd_set_bfcp _glp_bfd_set_bfcp +void bfd_set_bfcp(BFD *bfd, const void /* glp_bfcp */ *parm); +/* change LP basis factorization control parameters */ #define bfd_factorize _glp_bfd_factorize -int bfd_factorize(BFD *bfd, int m, const int bh[], int (*col) +int bfd_factorize(BFD *bfd, int m, /*const int bh[],*/ int (*col) (void *info, int j, int ind[], double val[]), void *info); /* compute LP basis factorization */ +#if 1 /* 21/IV-2014 */ +#define bfd_condest _glp_bfd_condest +double bfd_condest(BFD *bfd); +/* estimate condition of B */ +#endif + #define bfd_ftran _glp_bfd_ftran void bfd_ftran(BFD *bfd, double x[]); /* perform forward transformation (solve system B*x = b) */ @@ -55,9 +73,9 @@ void bfd_ftran(BFD *bfd, double x[]); void bfd_btran(BFD *bfd, double x[]); /* perform backward transformation (solve system B'*x = b) */ -#define bfd_update_it _glp_bfd_update_it -int bfd_update_it(BFD *bfd, int j, int bh, int len, const int ind[], - const double val[]); +#define bfd_update _glp_bfd_update +int bfd_update(BFD *bfd, int j, int len, const int ind[], const double + val[]); /* update LP basis factorization */ #define bfd_get_count _glp_bfd_get_count diff --git a/resources/3rdparty/glpk-4.57/src/bflib/btf.c b/resources/3rdparty/glpk-4.57/src/bflib/btf.c new file mode 100644 index 000000000..993c9ca17 --- /dev/null +++ b/resources/3rdparty/glpk-4.57/src/bflib/btf.c @@ -0,0 +1,569 @@ +/* btf.c (sparse block triangular LU-factorization) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2013-2014 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "btf.h" +#include "env.h" +#include "luf.h" +#include "mc13d.h" +#include "mc21a.h" + +/*********************************************************************** +* btf_store_a_cols - store pattern of matrix A in column-wise format +* +* This routine stores the pattern (that is, only indices of non-zero +* elements) of the original matrix A in column-wise format. +* +* On exit the routine returns the number of non-zeros in matrix A. */ + +int btf_store_a_cols(BTF *btf, int (*col)(void *info, int j, int ind[], + double val[]), void *info, int ind[], double val[]) +{ int n = btf->n; + SVA *sva = btf->sva; + int *sv_ind = sva->ind; + int ac_ref = btf->ac_ref; + int *ac_ptr = &sva->ptr[ac_ref-1]; + int *ac_len = &sva->len[ac_ref-1]; + int j, len, ptr, nnz; + nnz = 0; + for (j = 1; j <= n; j++) + { /* get j-th column */ + len = col(info, j, ind, val); + xassert(0 <= len && len <= n); + /* reserve locations for j-th column */ + if (len > 0) + { if (sva->r_ptr - sva->m_ptr < len) + { sva_more_space(sva, len); + sv_ind = sva->ind; + } + sva_reserve_cap(sva, ac_ref+(j-1), len); + } + /* store pattern of j-th column */ + ptr = ac_ptr[j]; + memcpy(&sv_ind[ptr], &ind[1], len * sizeof(int)); + ac_len[j] = len; + nnz += len; + } + return nnz; +} + +/*********************************************************************** +* btf_make_blocks - permutations to block triangular form +* +* This routine analyzes the pattern of the original matrix A and +* determines permutation matrices P and Q such that A = P * A~* Q, +* where A~ is an upper block triangular matrix. +* +* On exit the routine returns symbolic rank of matrix A. */ + +int btf_make_blocks(BTF *btf) +{ int n = btf->n; + SVA *sva = btf->sva; + int *sv_ind = sva->ind; + int *pp_ind = btf->pp_ind; + int *pp_inv = btf->pp_inv; + int *qq_ind = btf->qq_ind; + int *qq_inv = btf->qq_inv; + int *beg = btf->beg; + int ac_ref = btf->ac_ref; + int *ac_ptr = &sva->ptr[ac_ref-1]; + int *ac_len = &sva->len[ac_ref-1]; + int i, j, rank, *iperm, *pr, *arp, *cv, *out, *ip, *lenr, *lowl, + *numb, *prev; + /* determine column permutation matrix M such that matrix A * M + * has zero-free diagonal */ + iperm = qq_inv; /* matrix M */ + pr = btf->p1_ind; /* working array */ + arp = btf->p1_inv; /* working array */ + cv = btf->q1_ind; /* working array */ + out = btf->q1_inv; /* working array */ + rank = mc21a(n, sv_ind, ac_ptr, ac_len, iperm, pr, arp, cv, out); + xassert(0 <= rank && rank <= n); + if (rank < n) + { /* A is structurally singular (rank is its symbolic rank) */ + goto done; + } + /* build pattern of matrix A * M */ + ip = pp_ind; /* working array */ + lenr = qq_ind; /* working array */ + for (j = 1; j <= n; j++) + { ip[j] = ac_ptr[iperm[j]]; + lenr[j] = ac_len[iperm[j]]; + } + /* determine symmetric permutation matrix S such that matrix + * S * (A * M) * S' = A~ is upper block triangular */ + lowl = btf->p1_ind; /* working array */ + numb = btf->p1_inv; /* working array */ + prev = btf->q1_ind; /* working array */ + btf->num = + mc13d(n, sv_ind, ip, lenr, pp_inv, beg, lowl, numb, prev); + xassert(beg[1] == 1); + beg[btf->num+1] = n+1; + /* A * M = S' * A~ * S ==> A = S' * A~ * (S * M') */ + /* determine permutation matrix P = S' */ + for (j = 1; j <= n; j++) + pp_ind[pp_inv[j]] = j; + /* determine permutation matrix Q = S * M' = P' * M' */ + for (i = 1; i <= n; i++) + qq_ind[i] = iperm[pp_inv[i]]; + for (i = 1; i <= n; i++) + qq_inv[qq_ind[i]] = i; +done: return rank; +} + +/*********************************************************************** +* btf_check_blocks - check structure of matrix A~ +* +* This routine checks that structure of upper block triangular matrix +* A~ is correct. +* +* NOTE: For testing/debugging only. */ + +void btf_check_blocks(BTF *btf) +{ int n = btf->n; + SVA *sva = btf->sva; + int *sv_ind = sva->ind; + int *pp_ind = btf->pp_ind; + int *pp_inv = btf->pp_inv; + int *qq_ind = btf->qq_ind; + int *qq_inv = btf->qq_inv; + int num = btf->num; + int *beg = btf->beg; + int ac_ref = btf->ac_ref; + int *ac_ptr = &sva->ptr[ac_ref-1]; + int *ac_len = &sva->len[ac_ref-1]; + int i, ii, j, jj, k, size, ptr, end, diag; + xassert(n > 0); + /* check permutation matrices P and Q */ + for (k = 1; k <= n; k++) + { xassert(1 <= pp_ind[k] && pp_ind[k] <= n); + xassert(pp_inv[pp_ind[k]] == k); + xassert(1 <= qq_ind[k] && qq_ind[k] <= n); + xassert(qq_inv[qq_ind[k]] == k); + } + /* check that matrix A~ is upper block triangular with non-zero + * diagonal */ + xassert(1 <= num && num <= n); + xassert(beg[1] == 1); + xassert(beg[num+1] == n+1); + /* walk thru blocks of A~ */ + for (k = 1; k <= num; k++) + { /* determine size of k-th block */ + size = beg[k+1] - beg[k]; + xassert(size >= 1); + /* walk thru columns of k-th block */ + for (jj = beg[k]; jj < beg[k+1]; jj++) + { diag = 0; + /* jj-th column of A~ = j-th column of A */ + j = qq_ind[jj]; + /* walk thru elements of j-th column of A */ + ptr = ac_ptr[j]; + end = ptr + ac_len[j]; + for (; ptr < end; ptr++) + { /* determine row index of a[i,j] */ + i = sv_ind[ptr]; + /* i-th row of A = ii-th row of A~ */ + ii = pp_ind[i]; + /* a~[ii,jj] should not be below k-th block */ + xassert(ii < beg[k+1]); + if (ii == jj) + { /* non-zero diagonal element of A~ encountered */ + diag = 1; + } + } + xassert(diag); + } + } + return; +} + +/*********************************************************************** +* btf_build_a_rows - build matrix A in row-wise format +* +* This routine builds the row-wise representation of matrix A in the +* right part of SVA using its column-wise representation. +* +* The working array len should have at least 1+n elements (len[0] is +* not used). */ + +void btf_build_a_rows(BTF *btf, int len[/*1+n*/]) +{ int n = btf->n; + SVA *sva = btf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + int ar_ref = btf->ar_ref; + int *ar_ptr = &sva->ptr[ar_ref-1]; + int *ar_len = &sva->len[ar_ref-1]; + int ac_ref = btf->ac_ref; + int *ac_ptr = &sva->ptr[ac_ref-1]; + int *ac_len = &sva->len[ac_ref-1]; + int i, j, end, nnz, ptr, ptr1; + /* calculate the number of non-zeros in each row of matrix A and + * the total number of non-zeros */ + nnz = 0; + for (i = 1; i <= n; i++) + len[i] = 0; + for (j = 1; j <= n; j++) + { nnz += ac_len[j]; + for (end = (ptr = ac_ptr[j]) + ac_len[j]; ptr < end; ptr++) + len[sv_ind[ptr]]++; + } + /* we need at least nnz free locations in SVA */ + if (sva->r_ptr - sva->m_ptr < nnz) + { sva_more_space(sva, nnz); + sv_ind = sva->ind; + sv_val = sva->val; + } + /* reserve locations for rows of matrix A */ + for (i = 1; i <= n; i++) + { if (len[i] > 0) + sva_reserve_cap(sva, ar_ref-1+i, len[i]); + ar_len[i] = len[i]; + } + /* walk thru columns of matrix A and build its rows */ + for (j = 1; j <= n; j++) + { for (end = (ptr = ac_ptr[j]) + ac_len[j]; ptr < end; ptr++) + { i = sv_ind[ptr]; + sv_ind[ptr1 = ar_ptr[i] + (--len[i])] = j; + sv_val[ptr1] = sv_val[ptr]; + } + } + return; +} + +/*********************************************************************** +* btf_a_solve - solve system A * x = b +* +* This routine solves the system A * x = b, where A is the original +* matrix. +* +* On entry the array b should contain elements of the right-hand size +* vector b in locations b[1], ..., b[n], where n is the order of the +* matrix A. On exit the array x will contain elements of the solution +* vector in locations x[1], ..., x[n]. Note that the array b will be +* clobbered on exit. +* +* The routine also uses locations [1], ..., [max_size] of two working +* arrays w1 and w2, where max_size is the maximal size of diagonal +* blocks in BT-factorization (max_size <= n). */ + +void btf_a_solve(BTF *btf, double b[/*1+n*/], double x[/*1+n*/], + double w1[/*1+n*/], double w2[/*1+n*/]) +{ SVA *sva = btf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + int *pp_inv = btf->pp_inv; + int *qq_ind = btf->qq_ind; + int num = btf->num; + int *beg = btf->beg; + int ac_ref = btf->ac_ref; + int *ac_ptr = &sva->ptr[ac_ref-1]; + int *ac_len = &sva->len[ac_ref-1]; + double *bb = w1; + double *xx = w2; + LUF luf; + int i, j, jj, k, beg_k, flag; + double t; + for (k = num; k >= 1; k--) + { /* determine order of diagonal block A~[k,k] */ + luf.n = beg[k+1] - (beg_k = beg[k]); + if (luf.n == 1) + { /* trivial case */ + /* solve system A~[k,k] * X[k] = B[k] */ + t = x[qq_ind[beg_k]] = + b[pp_inv[beg_k]] / btf->vr_piv[beg_k]; + /* substitute X[k] into other equations */ + if (t != 0.0) + { int ptr = ac_ptr[qq_ind[beg_k]]; + int end = ptr + ac_len[qq_ind[beg_k]]; + for (; ptr < end; ptr++) + b[sv_ind[ptr]] -= sv_val[ptr] * t; + } + } + else + { /* general case */ + /* construct B[k] */ + flag = 0; + for (i = 1; i <= luf.n; i++) + { if ((bb[i] = b[pp_inv[i + (beg_k-1)]]) != 0.0) + flag = 1; + } + /* solve system A~[k,k] * X[k] = B[k] */ + if (!flag) + { /* B[k] = 0, so X[k] = 0 */ + for (j = 1; j <= luf.n; j++) + x[qq_ind[j + (beg_k-1)]] = 0.0; + continue; + } + luf.sva = sva; + luf.fr_ref = btf->fr_ref + (beg_k-1); + luf.fc_ref = btf->fc_ref + (beg_k-1); + luf.vr_ref = btf->vr_ref + (beg_k-1); + luf.vr_piv = btf->vr_piv + (beg_k-1); + luf.vc_ref = btf->vc_ref + (beg_k-1); + luf.pp_ind = btf->p1_ind + (beg_k-1); + luf.pp_inv = btf->p1_inv + (beg_k-1); + luf.qq_ind = btf->q1_ind + (beg_k-1); + luf.qq_inv = btf->q1_inv + (beg_k-1); + luf_f_solve(&luf, bb); + luf_v_solve(&luf, bb, xx); + /* store X[k] and substitute it into other equations */ + for (j = 1; j <= luf.n; j++) + { jj = j + (beg_k-1); + t = x[qq_ind[jj]] = xx[j]; + if (t != 0.0) + { int ptr = ac_ptr[qq_ind[jj]]; + int end = ptr + ac_len[qq_ind[jj]]; + for (; ptr < end; ptr++) + b[sv_ind[ptr]] -= sv_val[ptr] * t; + } + } + } + } + return; +} + +/*********************************************************************** +* btf_at_solve - solve system A'* x = b +* +* This routine solves the system A'* x = b, where A' is a matrix +* transposed to the original matrix A. +* +* On entry the array b should contain elements of the right-hand size +* vector b in locations b[1], ..., b[n], where n is the order of the +* matrix A. On exit the array x will contain elements of the solution +* vector in locations x[1], ..., x[n]. Note that the array b will be +* clobbered on exit. +* +* The routine also uses locations [1], ..., [max_size] of two working +* arrays w1 and w2, where max_size is the maximal size of diagonal +* blocks in BT-factorization (max_size <= n). */ + +void btf_at_solve(BTF *btf, double b[/*1+n*/], double x[/*1+n*/], + double w1[/*1+n*/], double w2[/*1+n*/]) +{ SVA *sva = btf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + int *pp_inv = btf->pp_inv; + int *qq_ind = btf->qq_ind; + int num = btf->num; + int *beg = btf->beg; + int ar_ref = btf->ar_ref; + int *ar_ptr = &sva->ptr[ar_ref-1]; + int *ar_len = &sva->len[ar_ref-1]; + double *bb = w1; + double *xx = w2; + LUF luf; + int i, j, jj, k, beg_k, flag; + double t; + for (k = 1; k <= num; k++) + { /* determine order of diagonal block A~[k,k] */ + luf.n = beg[k+1] - (beg_k = beg[k]); + if (luf.n == 1) + { /* trivial case */ + /* solve system A~'[k,k] * X[k] = B[k] */ + t = x[pp_inv[beg_k]] = + b[qq_ind[beg_k]] / btf->vr_piv[beg_k]; + /* substitute X[k] into other equations */ + if (t != 0.0) + { int ptr = ar_ptr[pp_inv[beg_k]]; + int end = ptr + ar_len[pp_inv[beg_k]]; + for (; ptr < end; ptr++) + b[sv_ind[ptr]] -= sv_val[ptr] * t; + } + } + else + { /* general case */ + /* construct B[k] */ + flag = 0; + for (i = 1; i <= luf.n; i++) + { if ((bb[i] = b[qq_ind[i + (beg_k-1)]]) != 0.0) + flag = 1; + } + /* solve system A~'[k,k] * X[k] = B[k] */ + if (!flag) + { /* B[k] = 0, so X[k] = 0 */ + for (j = 1; j <= luf.n; j++) + x[pp_inv[j + (beg_k-1)]] = 0.0; + continue; + } + luf.sva = sva; + luf.fr_ref = btf->fr_ref + (beg_k-1); + luf.fc_ref = btf->fc_ref + (beg_k-1); + luf.vr_ref = btf->vr_ref + (beg_k-1); + luf.vr_piv = btf->vr_piv + (beg_k-1); + luf.vc_ref = btf->vc_ref + (beg_k-1); + luf.pp_ind = btf->p1_ind + (beg_k-1); + luf.pp_inv = btf->p1_inv + (beg_k-1); + luf.qq_ind = btf->q1_ind + (beg_k-1); + luf.qq_inv = btf->q1_inv + (beg_k-1); + luf_vt_solve(&luf, bb, xx); + luf_ft_solve(&luf, xx); + /* store X[k] and substitute it into other equations */ + for (j = 1; j <= luf.n; j++) + { jj = j + (beg_k-1); + t = x[pp_inv[jj]] = xx[j]; + if (t != 0.0) + { int ptr = ar_ptr[pp_inv[jj]]; + int end = ptr + ar_len[pp_inv[jj]]; + for (; ptr < end; ptr++) + b[sv_ind[ptr]] -= sv_val[ptr] * t; + } + } + } + } + return; +} + +/*********************************************************************** +* btf_at_solve1 - solve system A'* y = e' to cause growth in y +* +* This routine is a special version of btf_at_solve. It solves the +* system A'* y = e' = e + delta e, where A' is a matrix transposed to +* the original matrix A, e is the specified right-hand side vector, +* and delta e is a vector of +1 and -1 chosen to cause growth in the +* solution vector y. +* +* On entry the array e should contain elements of the right-hand size +* vector e in locations e[1], ..., e[n], where n is the order of the +* matrix A. On exit the array y will contain elements of the solution +* vector in locations y[1], ..., y[n]. Note that the array e will be +* clobbered on exit. +* +* The routine also uses locations [1], ..., [max_size] of two working +* arrays w1 and w2, where max_size is the maximal size of diagonal +* blocks in BT-factorization (max_size <= n). */ + +void btf_at_solve1(BTF *btf, double e[/*1+n*/], double y[/*1+n*/], + double w1[/*1+n*/], double w2[/*1+n*/]) +{ SVA *sva = btf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + int *pp_inv = btf->pp_inv; + int *qq_ind = btf->qq_ind; + int num = btf->num; + int *beg = btf->beg; + int ar_ref = btf->ar_ref; + int *ar_ptr = &sva->ptr[ar_ref-1]; + int *ar_len = &sva->len[ar_ref-1]; + double *ee = w1; + double *yy = w2; + LUF luf; + int i, j, jj, k, beg_k, ptr, end; + double e_k, y_k; + for (k = 1; k <= num; k++) + { /* determine order of diagonal block A~[k,k] */ + luf.n = beg[k+1] - (beg_k = beg[k]); + if (luf.n == 1) + { /* trivial case */ + /* determine E'[k] = E[k] + delta E[k] */ + e_k = e[qq_ind[beg_k]]; + e_k = (e_k >= 0.0 ? e_k + 1.0 : e_k - 1.0); + /* solve system A~'[k,k] * Y[k] = E[k] */ + y_k = y[pp_inv[beg_k]] = e_k / btf->vr_piv[beg_k]; + /* substitute Y[k] into other equations */ + ptr = ar_ptr[pp_inv[beg_k]]; + end = ptr + ar_len[pp_inv[beg_k]]; + for (; ptr < end; ptr++) + e[sv_ind[ptr]] -= sv_val[ptr] * y_k; + } + else + { /* general case */ + /* construct E[k] */ + for (i = 1; i <= luf.n; i++) + ee[i] = e[qq_ind[i + (beg_k-1)]]; + /* solve system A~'[k,k] * Y[k] = E[k] + delta E[k] */ + luf.sva = sva; + luf.fr_ref = btf->fr_ref + (beg_k-1); + luf.fc_ref = btf->fc_ref + (beg_k-1); + luf.vr_ref = btf->vr_ref + (beg_k-1); + luf.vr_piv = btf->vr_piv + (beg_k-1); + luf.vc_ref = btf->vc_ref + (beg_k-1); + luf.pp_ind = btf->p1_ind + (beg_k-1); + luf.pp_inv = btf->p1_inv + (beg_k-1); + luf.qq_ind = btf->q1_ind + (beg_k-1); + luf.qq_inv = btf->q1_inv + (beg_k-1); + luf_vt_solve1(&luf, ee, yy); + luf_ft_solve(&luf, yy); + /* store Y[k] and substitute it into other equations */ + for (j = 1; j <= luf.n; j++) + { jj = j + (beg_k-1); + y_k = y[pp_inv[jj]] = yy[j]; + ptr = ar_ptr[pp_inv[jj]]; + end = ptr + ar_len[pp_inv[jj]]; + for (; ptr < end; ptr++) + e[sv_ind[ptr]] -= sv_val[ptr] * y_k; + } + } + } + return; +} + +/*********************************************************************** +* btf_estimate_norm - estimate 1-norm of inv(A) +* +* This routine estimates 1-norm of inv(A) by one step of inverse +* iteration for the small singular vector as described in [1]. This +* involves solving two systems of equations: +* +* A'* y = e, +* +* A * z = y, +* +* where A' is a matrix transposed to A, and e is a vector of +1 and -1 +* chosen to cause growth in y. Then +* +* estimate 1-norm of inv(A) = (1-norm of z) / (1-norm of y) +* +* REFERENCES +* +* 1. G.E.Forsythe, M.A.Malcolm, C.B.Moler. Computer Methods for +* Mathematical Computations. Prentice-Hall, Englewood Cliffs, N.J., +* pp. 30-62 (subroutines DECOMP and SOLVE). */ + +double btf_estimate_norm(BTF *btf, double w1[/*1+n*/], double + w2[/*1+n*/], double w3[/*1+n*/], double w4[/*1+n*/]) +{ int n = btf->n; + double *e = w1; + double *y = w2; + double *z = w1; + int i; + double y_norm, z_norm; + /* compute y = inv(A') * e to cause growth in y */ + for (i = 1; i <= n; i++) + e[i] = 0.0; + btf_at_solve1(btf, e, y, w3, w4); + /* compute 1-norm of y = sum |y[i]| */ + y_norm = 0.0; + for (i = 1; i <= n; i++) + y_norm += (y[i] >= 0.0 ? +y[i] : -y[i]); + /* compute z = inv(A) * y */ + btf_a_solve(btf, y, z, w3, w4); + /* compute 1-norm of z = sum |z[i]| */ + z_norm = 0.0; + for (i = 1; i <= n; i++) + z_norm += (z[i] >= 0.0 ? +z[i] : -z[i]); + /* estimate 1-norm of inv(A) = (1-norm of z) / (1-norm of y) */ + return z_norm / y_norm; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.57/src/bflib/btf.h b/resources/3rdparty/glpk-4.57/src/bflib/btf.h new file mode 100644 index 000000000..3f1b59265 --- /dev/null +++ b/resources/3rdparty/glpk-4.57/src/bflib/btf.h @@ -0,0 +1,207 @@ +/* btf.h (sparse block triangular LU-factorization) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2013-2014 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef BTF_H +#define BTF_H + +#include "sva.h" + +/*********************************************************************** +* The structure BTF describes BT-factorization, which is sparse block +* triangular LU-factorization. +* +* The BT-factorization has the following format: +* +* A = P * A~ * Q, (1) +* +* where A is a given (unsymmetric) square matrix, A~ is an upper block +* triangular matrix (see below), P and Q are permutation matrices. All +* the matrices have the same order n. +* +* The matrix A~, which is a permuted version of the original matrix A, +* has the following structure: +* +* A~[1,1] A~[1,2] ... A~[1,num-1] A~[1,num] +* +* A~[2,2] ... A~[2,num-1] A~[2,num] +* +* . . . . . . . . . (2) +* +* A~[num-1,num-1] A~[num-1,num] +* +* A~[num,num] +* +* where A~[i,j] is a submatrix called a "block," num is the number of +* blocks. Each diagonal block A~[k,k] is a non-singular square matrix, +* and each subdiagonal block A~[i,j], i > j, is a zero submatrix, thus +* A~ is an upper block triangular matrix. +* +* Permutation matrices P and Q are stored in ordinary arrays in both +* row- and column-like formats. +* +* The original matrix A is stored in both row- and column-wise sparse +* formats in the associated sparse vector area (SVA). Should note that +* elements of all diagonal blocks A~[k,k] in matrix A are set to zero +* (i.e. removed), so only elements of non-diagonal blocks are stored. +* +* Each diagonal block A~[k,k], 1 <= k <= num, is stored in the form of +* LU-factorization (see the module LUF). */ + +typedef struct BTF BTF; + +struct BTF +{ /* sparse block triangular LU-factorization */ + int n; + /* order of matrices A, A~, P, Q */ + SVA *sva; + /* associated sparse vector area used to store rows and columns + * of matrix A as well as sparse vectors for LU-factorizations of + * all diagonal blocks A~[k,k] */ + /*--------------------------------------------------------------*/ + /* matrix P */ + int *pp_ind; /* int pp_ind[1+n]; */ + /* pp_ind[i] = j means that P[i,j] = 1 */ + int *pp_inv; /* int pp_inv[1+n]; */ + /* pp_inv[j] = i means that P[i,j] = 1 */ + /* if i-th row of matrix A is i'-th row of matrix A~, then + * pp_ind[i] = i' and pp_inv[i'] = i */ + /*--------------------------------------------------------------*/ + /* matrix Q */ + int *qq_ind; /* int qq_ind[1+n]; */ + /* qq_ind[i] = j means that Q[i,j] = 1 */ + int *qq_inv; /* int qq_inv[1+n]; */ + /* qq_inv[j] = i means that Q[i,j] = 1 */ + /* if j-th column of matrix A is j'-th column of matrix A~, then + * qq_ind[j'] = j and qq_inv[j] = j' */ + /*--------------------------------------------------------------*/ + /* block triangular structure of matrix A~ */ + int num; + /* number of diagonal blocks, 1 <= num <= n */ + int *beg; /* int beg[1+num+1]; */ + /* beg[0] is not used; + * beg[k], 1 <= k <= num, is index of first row/column of k-th + * block of matrix A~; + * beg[num+1] is always n+1; + * note that order (size) of k-th diagonal block can be computed + * as beg[k+1] - beg[k] */ + /*--------------------------------------------------------------*/ + /* original matrix A in row-wise format */ + /* NOTE: elements of all diagonal blocks A~[k,k] are removed */ + int ar_ref; + /* reference number of sparse vector in SVA, which is the first + * row of matrix A */ +#if 0 + 0 + int *ar_ptr = &sva->ptr[ar_ref-1]; + /* ar_ptr[0] is not used; + * ar_ptr[i], 1 <= i <= n, is pointer to i-th row in SVA */ + int *ar_len = &sva->ptr[ar_ref-1]; + /* ar_len[0] is not used; + * ar_len[i], 1 <= i <= n, is length of i-th row */ +#endif + /*--------------------------------------------------------------*/ + /* original matrix A in column-wise format */ + /* NOTE: elements of all diagonal blocks A~[k,k] are removed */ + int ac_ref; + /* reference number of sparse vector in SVA, which is the first + * column of matrix A */ +#if 0 + 0 + int *ac_ptr = &sva->ptr[ac_ref-1]; + /* ac_ptr[0] is not used; + * ac_ptr[j], 1 <= j <= n, is pointer to j-th column in SVA */ + int *ac_len = &sva->ptr[ac_ref-1]; + /* ac_len[0] is not used; + * ac_len[j], 1 <= j <= n, is length of j-th column */ +#endif + /*--------------------------------------------------------------*/ + /* LU-factorizations of diagonal blocks A~[k,k] */ + /* to decrease overhead expenses similar arrays for all LUFs are + * packed into a single array; for example, elements fr_ptr[1], + * ..., fr_ptr[n1], where n1 = beg[2] - beg[1], are related to + * LUF for first diagonal block A~[1,1], elements fr_ptr[n1+1], + * ..., fr_ptr[n1+n2], where n2 = beg[3] - beg[2], are related to + * LUF for second diagonal block A~[2,2], etc.; in other words, + * elements related to LUF for k-th diagonal block A~[k,k] have + * indices beg[k], beg[k]+1, ..., beg[k+1]-1 */ + /* for details about LUF see description of the LUF module */ + int fr_ref; + /* reference number of sparse vector in SVA, which is the first + row of matrix F for first diagonal block A~[1,1] */ + int fc_ref; + /* reference number of sparse vector in SVA, which is the first + column of matrix F for first diagonal block A~[1,1] */ + int vr_ref; + /* reference number of sparse vector in SVA, which is the first + row of matrix V for first diagonal block A~[1,1] */ + double *vr_piv; /* double vr_piv[1+n]; */ + /* vr_piv[0] is not used; + vr_piv[1,...,n] are pivot elements for all diagonal blocks */ + int vc_ref; + /* reference number of sparse vector in SVA, which is the first + column of matrix V for first diagonal block A~[1,1] */ + int *p1_ind; /* int p1_ind[1+n]; */ + int *p1_inv; /* int p1_inv[1+n]; */ + int *q1_ind; /* int q1_ind[1+n]; */ + int *q1_inv; /* int q1_inv[1+n]; */ + /* permutation matrices P and Q for all diagonal blocks */ +}; + +#define btf_store_a_cols _glp_btf_store_a_cols +int btf_store_a_cols(BTF *btf, int (*col)(void *info, int j, int ind[], + double val[]), void *info, int ind[], double val[]); +/* store pattern of matrix A in column-wise format */ + +#define btf_make_blocks _glp_btf_make_blocks +int btf_make_blocks(BTF *btf); +/* permutations to block triangular form */ + +#define btf_check_blocks _glp_btf_check_blocks +void btf_check_blocks(BTF *btf); +/* check structure of matrix A~ */ + +#define btf_build_a_rows _glp_btf_build_a_rows +void btf_build_a_rows(BTF *btf, int len[/*1+n*/]); +/* build matrix A in row-wise format */ + +#define btf_a_solve _glp_btf_a_solve +void btf_a_solve(BTF *btf, double b[/*1+n*/], double x[/*1+n*/], + double w1[/*1+n*/], double w2[/*1+n*/]); +/* solve system A * x = b */ + +#define btf_at_solve _glp_btf_at_solve +void btf_at_solve(BTF *btf, double b[/*1+n*/], double x[/*1+n*/], + double w1[/*1+n*/], double w2[/*1+n*/]); +/* solve system A'* x = b */ + +#define btf_at_solve1 _glp_btf_at_solve1 +void btf_at_solve1(BTF *btf, double e[/*1+n*/], double y[/*1+n*/], + double w1[/*1+n*/], double w2[/*1+n*/]); +/* solve system A'* y = e' to cause growth in y */ + +#define btf_estimate_norm _glp_btf_estimate_norm +double btf_estimate_norm(BTF *btf, double w1[/*1+n*/], double + w2[/*1+n*/], double w3[/*1+n*/], double w4[/*1+n*/]); +/* estimate 1-norm of inv(A) */ + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.57/src/bflib/btfint.c b/resources/3rdparty/glpk-4.57/src/bflib/btfint.c new file mode 100644 index 000000000..378d3a816 --- /dev/null +++ b/resources/3rdparty/glpk-4.57/src/bflib/btfint.c @@ -0,0 +1,407 @@ +/* btfint.c (interface to BT-factorization) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2013-2014 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "btfint.h" + +BTFINT *btfint_create(void) +{ /* create interface to BT-factorization */ + BTFINT *fi; + fi = talloc(1, BTFINT); + fi->n_max = 0; + fi->valid = 0; + fi->sva = NULL; + fi->btf = NULL; + fi->sgf = NULL; + fi->sva_n_max = fi->sva_size = 0; + fi->delta_n0 = fi->delta_n = 0; + fi->sgf_piv_tol = 0.10; + fi->sgf_piv_lim = 4; + fi->sgf_suhl = 1; + fi->sgf_eps_tol = DBL_EPSILON; + return fi; +} + +static void factorize_triv(BTFINT *fi, int k, int (*col)(void *info, + int j, int ind[], double val[]), void *info) +{ /* compute LU-factorization of diagonal block A~[k,k] and store + * corresponding columns of matrix A except elements of A~[k,k] + * (trivial case when the block has unity size) */ + SVA *sva = fi->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + BTF *btf = fi->btf; + int *pp_inv = btf->pp_inv; + int *qq_ind = btf->qq_ind; + int *beg = btf->beg; + int ac_ref = btf->ac_ref; + int *ac_ptr = &sva->ptr[ac_ref-1]; + int *ac_len = &sva->len[ac_ref-1]; + SGF *sgf = fi->sgf; + int *ind = (int *)sgf->vr_max; /* working array */ + double *val = sgf->work; /* working array */ + int i, j, t, len, ptr, beg_k; + /* diagonal block A~[k,k] has the only element in matrix A~, + * which is a~[beg[k],beg[k]] = a[i,j] */ + beg_k = beg[k]; + i = pp_inv[beg_k]; + j = qq_ind[beg_k]; + /* get j-th column of A */ + len = col(info, j, ind, val); + /* find element a[i,j] = a~[beg[k],beg[k]] in j-th column */ + for (t = 1; t <= len; t++) + { if (ind[t] == i) + break; + } + xassert(t <= len); + /* compute LU-factorization of diagonal block A~[k,k], where + * F = (1), V = (a[i,j]), P = Q = (1) (see the module LUF) */ +#if 1 /* FIXME */ + xassert(val[t] != 0.0); +#endif + btf->vr_piv[beg_k] = val[t]; + btf->p1_ind[beg_k] = btf->p1_inv[beg_k] = 1; + btf->q1_ind[beg_k] = btf->q1_inv[beg_k] = 1; + /* remove element a[i,j] = a~[beg[k],beg[k]] from j-th column */ + memmove(&ind[t], &ind[t+1], (len-t) * sizeof(int)); + memmove(&val[t], &val[t+1], (len-t) * sizeof(double)); + len--; + /* and store resulting j-th column of A into BTF */ + if (len > 0) + { /* reserve locations for j-th column of A */ + if (sva->r_ptr - sva->m_ptr < len) + { sva_more_space(sva, len); + sv_ind = sva->ind; + sv_val = sva->val; + } + sva_reserve_cap(sva, ac_ref+(j-1), len); + /* store j-th column of A (except elements of A~[k,k]) */ + ptr = ac_ptr[j]; + memcpy(&sv_ind[ptr], &ind[1], len * sizeof(int)); + memcpy(&sv_val[ptr], &val[1], len * sizeof(double)); + ac_len[j] = len; + } + return; +} + +static int factorize_block(BTFINT *fi, int k, int (*col)(void *info, + int j, int ind[], double val[]), void *info) +{ /* compute LU-factorization of diagonal block A~[k,k] and store + * corresponding columns of matrix A except elements of A~[k,k] + * (general case) */ + SVA *sva = fi->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + BTF *btf = fi->btf; + int *pp_ind = btf->pp_ind; + int *qq_ind = btf->qq_ind; + int *beg = btf->beg; + int ac_ref = btf->ac_ref; + int *ac_ptr = &sva->ptr[ac_ref-1]; + int *ac_len = &sva->len[ac_ref-1]; + SGF *sgf = fi->sgf; + int *ind = (int *)sgf->vr_max; /* working array */ + double *val = sgf->work; /* working array */ + LUF luf; + int *vc_ptr, *vc_len, *vc_cap; + int i, ii, j, jj, t, len, cnt, ptr, beg_k; + /* construct fake LUF for LU-factorization of A~[k,k] */ + sgf->luf = &luf; + luf.n = beg[k+1] - (beg_k = beg[k]); + luf.sva = sva; + luf.fr_ref = btf->fr_ref + (beg_k-1); + luf.fc_ref = btf->fc_ref + (beg_k-1); + luf.vr_ref = btf->vr_ref + (beg_k-1); + luf.vr_piv = btf->vr_piv + (beg_k-1); + luf.vc_ref = btf->vc_ref + (beg_k-1); + luf.pp_ind = btf->p1_ind + (beg_k-1); + luf.pp_inv = btf->p1_inv + (beg_k-1); + luf.qq_ind = btf->q1_ind + (beg_k-1); + luf.qq_inv = btf->q1_inv + (beg_k-1); + /* process columns of k-th block of matrix A~ */ + vc_ptr = &sva->ptr[luf.vc_ref-1]; + vc_len = &sva->len[luf.vc_ref-1]; + vc_cap = &sva->cap[luf.vc_ref-1]; + for (jj = 1; jj <= luf.n; jj++) + { /* jj-th column of A~ = j-th column of A */ + j = qq_ind[jj + (beg_k-1)]; + /* get j-th column of A */ + len = col(info, j, ind, val); + /* move elements of diagonal block A~[k,k] to the beginning of + * the column list */ + cnt = 0; + for (t = 1; t <= len; t++) + { /* i = row index of element a[i,j] */ + i = ind[t]; + /* i-th row of A = ii-th row of A~ */ + ii = pp_ind[i]; + if (ii >= beg_k) + { /* a~[ii,jj] = a[i,j] is in diagonal block A~[k,k] */ + double temp; + cnt++; + ind[t] = ind[cnt]; + ind[cnt] = ii - (beg_k-1); /* local index */ + temp = val[t], val[t] = val[cnt], val[cnt] = temp; + } + } + /* first cnt elements in the column list give jj-th column of + * diagonal block A~[k,k], which is initial matrix V in LUF */ + /* enlarge capacity of jj-th column of V = A~[k,k] */ + if (vc_cap[jj] < cnt) + { if (sva->r_ptr - sva->m_ptr < cnt) + { sva_more_space(sva, cnt); + sv_ind = sva->ind; + sv_val = sva->val; + } + sva_enlarge_cap(sva, luf.vc_ref+(jj-1), cnt, 0); + } + /* store jj-th column of V = A~[k,k] */ + ptr = vc_ptr[jj]; + memcpy(&sv_ind[ptr], &ind[1], cnt * sizeof(int)); + memcpy(&sv_val[ptr], &val[1], cnt * sizeof(double)); + vc_len[jj] = cnt; + /* other (len-cnt) elements in the column list are stored in + * j-th column of the original matrix A */ + len -= cnt; + if (len > 0) + { /* reserve locations for j-th column of A */ + if (sva->r_ptr - sva->m_ptr < len) + { sva_more_space(sva, len); + sv_ind = sva->ind; + sv_val = sva->val; + } + sva_reserve_cap(sva, ac_ref-1+j, len); + /* store j-th column of A (except elements of A~[k,k]) */ + ptr = ac_ptr[j]; + memcpy(&sv_ind[ptr], &ind[cnt+1], len * sizeof(int)); + memcpy(&sv_val[ptr], &val[cnt+1], len * sizeof(double)); + ac_len[j] = len; + } + } + /* compute LU-factorization of diagonal block A~[k,k]; may note + * that A~[k,k] is irreducible (strongly connected), so singleton + * phase will have no effect */ + k = sgf_factorize(sgf, 0 /* disable singleton phase */); + /* now left (dynamic) part of SVA should be empty (wichtig!) */ + xassert(sva->m_ptr == 1); + return k; +} + +int btfint_factorize(BTFINT *fi, int n, int (*col)(void *info, int j, + int ind[], double val[]), void *info) +{ /* compute BT-factorization of specified matrix A */ + SVA *sva; + BTF *btf; + SGF *sgf; + int k, rank; + xassert(n > 0); + fi->valid = 0; + /* create sparse vector area (SVA), if necessary */ + sva = fi->sva; + if (sva == NULL) + { int sva_n_max = fi->sva_n_max; + int sva_size = fi->sva_size; + if (sva_n_max == 0) + sva_n_max = 6 * n; + if (sva_size == 0) + sva_size = 10 * n; + sva = fi->sva = sva_create_area(sva_n_max, sva_size); + } + /* allocate/reallocate underlying objects, if necessary */ + if (fi->n_max < n) + { int n_max = fi->n_max; + if (n_max == 0) + n_max = fi->n_max = n + fi->delta_n0; + else + n_max = fi->n_max = n + fi->delta_n; + xassert(n_max >= n); + /* allocate/reallocate block triangular factorization (BTF) */ + btf = fi->btf; + if (btf == NULL) + { btf = fi->btf = talloc(1, BTF); + memset(btf, 0, sizeof(BTF)); + btf->sva = sva; + } + else + { tfree(btf->pp_ind); + tfree(btf->pp_inv); + tfree(btf->qq_ind); + tfree(btf->qq_inv); + tfree(btf->beg); + tfree(btf->vr_piv); + tfree(btf->p1_ind); + tfree(btf->p1_inv); + tfree(btf->q1_ind); + tfree(btf->q1_inv); + } + btf->pp_ind = talloc(1+n_max, int); + btf->pp_inv = talloc(1+n_max, int); + btf->qq_ind = talloc(1+n_max, int); + btf->qq_inv = talloc(1+n_max, int); + btf->beg = talloc(1+n_max+1, int); + btf->vr_piv = talloc(1+n_max, double); + btf->p1_ind = talloc(1+n_max, int); + btf->p1_inv = talloc(1+n_max, int); + btf->q1_ind = talloc(1+n_max, int); + btf->q1_inv = talloc(1+n_max, int); + /* allocate/reallocate factorizer workspace (SGF) */ + /* (note that for SGF we could use the size of largest block + * rather than n_max) */ + sgf = fi->sgf; + sgf = fi->sgf; + if (sgf == NULL) + { sgf = fi->sgf = talloc(1, SGF); + memset(sgf, 0, sizeof(SGF)); + } + else + { tfree(sgf->rs_head); + tfree(sgf->rs_prev); + tfree(sgf->rs_next); + tfree(sgf->cs_head); + tfree(sgf->cs_prev); + tfree(sgf->cs_next); + tfree(sgf->vr_max); + tfree(sgf->flag); + tfree(sgf->work); + } + sgf->rs_head = talloc(1+n_max, int); + sgf->rs_prev = talloc(1+n_max, int); + sgf->rs_next = talloc(1+n_max, int); + sgf->cs_head = talloc(1+n_max, int); + sgf->cs_prev = talloc(1+n_max, int); + sgf->cs_next = talloc(1+n_max, int); + sgf->vr_max = talloc(1+n_max, double); + sgf->flag = talloc(1+n_max, char); + sgf->work = talloc(1+n_max, double); + } + btf = fi->btf; + btf->n = n; + sgf = fi->sgf; +#if 1 /* FIXME */ + /* initialize SVA */ + sva->n = 0; + sva->m_ptr = 1; + sva->r_ptr = sva->size + 1; + sva->head = sva->tail = 0; +#endif + /* store pattern of original matrix A in column-wise format */ + btf->ac_ref = sva_alloc_vecs(btf->sva, btf->n); + btf_store_a_cols(btf, col, info, btf->pp_ind, btf->vr_piv); +#ifdef GLP_DEBUG + sva_check_area(sva); +#endif + /* analyze pattern of original matrix A and determine permutation + * matrices P and Q such that A = P * A~* Q, where A~ is an upper + * block triangular matrix */ + rank = btf_make_blocks(btf); + if (rank != n) + { /* original matrix A is structurally singular */ + return 1; + } +#ifdef GLP_DEBUG + btf_check_blocks(btf); +#endif +#if 1 /* FIXME */ + /* initialize SVA */ + sva->n = 0; + sva->m_ptr = 1; + sva->r_ptr = sva->size + 1; + sva->head = sva->tail = 0; +#endif + /* allocate sparse vectors in SVA */ + btf->ar_ref = sva_alloc_vecs(btf->sva, btf->n); + btf->ac_ref = sva_alloc_vecs(btf->sva, btf->n); + btf->fr_ref = sva_alloc_vecs(btf->sva, btf->n); + btf->fc_ref = sva_alloc_vecs(btf->sva, btf->n); + btf->vr_ref = sva_alloc_vecs(btf->sva, btf->n); + btf->vc_ref = sva_alloc_vecs(btf->sva, btf->n); + /* setup factorizer control parameters */ + sgf->updat = 0; /* wichtig! */ + sgf->piv_tol = fi->sgf_piv_tol; + sgf->piv_lim = fi->sgf_piv_lim; + sgf->suhl = fi->sgf_suhl; + sgf->eps_tol = fi->sgf_eps_tol; + /* compute LU-factorizations of diagonal blocks A~[k,k] and also + * store corresponding columns of matrix A except elements of all + * blocks A~[k,k] */ + for (k = 1; k <= btf->num; k++) + { if (btf->beg[k+1] - btf->beg[k] == 1) + { /* trivial case (A~[k,k] has unity order) */ + factorize_triv(fi, k, col, info); + } + else + { /* general case */ + if (factorize_block(fi, k, col, info) != 0) + return 2; /* factorization of A~[k,k] failed */ + } + } +#ifdef GLP_DEBUG + sva_check_area(sva); +#endif + /* build row-wise representation of matrix A */ + btf_build_a_rows(fi->btf, fi->sgf->rs_head); +#ifdef GLP_DEBUG + sva_check_area(sva); +#endif + /* BT-factorization has been successfully computed */ + fi->valid = 1; + return 0; +} + +void btfint_delete(BTFINT *fi) +{ /* delete interface to BT-factorization */ + SVA *sva = fi->sva; + BTF *btf = fi->btf; + SGF *sgf = fi->sgf; + if (sva != NULL) + sva_delete_area(sva); + if (btf != NULL) + { tfree(btf->pp_ind); + tfree(btf->pp_inv); + tfree(btf->qq_ind); + tfree(btf->qq_inv); + tfree(btf->beg); + tfree(btf->vr_piv); + tfree(btf->p1_ind); + tfree(btf->p1_inv); + tfree(btf->q1_ind); + tfree(btf->q1_inv); + tfree(btf); + } + if (sgf != NULL) + { tfree(sgf->rs_head); + tfree(sgf->rs_prev); + tfree(sgf->rs_next); + tfree(sgf->cs_head); + tfree(sgf->cs_prev); + tfree(sgf->cs_next); + tfree(sgf->vr_max); + tfree(sgf->flag); + tfree(sgf->work); + tfree(sgf); + } + tfree(fi); + return; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.57/src/bflib/btfint.h b/resources/3rdparty/glpk-4.57/src/bflib/btfint.h new file mode 100644 index 000000000..8d0e70e21 --- /dev/null +++ b/resources/3rdparty/glpk-4.57/src/bflib/btfint.h @@ -0,0 +1,73 @@ +/* btfint.h (interface to BT-factorization) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2013-2014 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef BTFINT_H +#define BTFINT_H + +#include "btf.h" +#include "sgf.h" + +typedef struct BTFINT BTFINT; + +struct BTFINT +{ /* interface to BT-factorization */ + int n_max; + /* maximal value of n (increased automatically) */ + int valid; + /* factorization is valid only if this flag is set */ + SVA *sva; + /* sparse vector area (SVA) */ + BTF *btf; + /* sparse block triangular LU-factorization */ + SGF *sgf; + /* sparse Gaussian factorizer workspace */ + /*--------------------------------------------------------------*/ + /* control parameters */ + int sva_n_max, sva_size; + /* parameters passed to sva_create_area */ + int delta_n0, delta_n; + /* if n_max = 0, set n_max = n + delta_n0 + * if n_max < n, set n_max = n + delta_n */ + double sgf_piv_tol; + int sgf_piv_lim; + int sgf_suhl; + double sgf_eps_tol; + /* factorizer control parameters */ +}; + +#define btfint_create _glp_btfint_create +BTFINT *btfint_create(void); +/* create interface to BT-factorization */ + +#define btfint_factorize _glp_btfint_factorize +int btfint_factorize(BTFINT *fi, int n, int (*col)(void *info, int j, + int ind[], double val[]), void *info); +/* compute BT-factorization of specified matrix A */ + +#define btfint_delete _glp_btfint_delete +void btfint_delete(BTFINT *fi); +/* delete interface to BT-factorization */ + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/bflib/fhv.c b/resources/3rdparty/glpk-4.57/src/bflib/fhv.c similarity index 99% rename from resources/3rdparty/glpk-4.53/src/bflib/fhv.c rename to resources/3rdparty/glpk-4.57/src/bflib/fhv.c index 271460657..e4bdf8552 100644 --- a/resources/3rdparty/glpk-4.53/src/bflib/fhv.c +++ b/resources/3rdparty/glpk-4.57/src/bflib/fhv.c @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2012-2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * diff --git a/resources/3rdparty/glpk-4.53/src/bflib/fhv.h b/resources/3rdparty/glpk-4.57/src/bflib/fhv.h similarity index 98% rename from resources/3rdparty/glpk-4.53/src/bflib/fhv.h rename to resources/3rdparty/glpk-4.57/src/bflib/fhv.h index 992ca311d..df39ca5cb 100644 --- a/resources/3rdparty/glpk-4.53/src/bflib/fhv.h +++ b/resources/3rdparty/glpk-4.57/src/bflib/fhv.h @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2012-2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * diff --git a/resources/3rdparty/glpk-4.53/src/bflib/fhvint.c b/resources/3rdparty/glpk-4.57/src/bflib/fhvint.c similarity index 62% rename from resources/3rdparty/glpk-4.53/src/bflib/fhvint.c rename to resources/3rdparty/glpk-4.57/src/bflib/fhvint.c index 9d2b25938..a21b71c67 100644 --- a/resources/3rdparty/glpk-4.53/src/bflib/fhvint.c +++ b/resources/3rdparty/glpk-4.57/src/bflib/fhvint.c @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2012-2014 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * @@ -28,18 +28,14 @@ FHVINT *fhvint_create(void) { /* create interface to FHV-factorization */ FHVINT *fi; fi = talloc(1, FHVINT); - fi->valid = 0; - fi->fhv = NULL; - fi->lufint = NULL; - fi->nfs_max = 0; + memset(fi, 0, sizeof(FHVINT)); + fi->lufi = lufint_create(); return fi; } int fhvint_factorize(FHVINT *fi, int n, int (*col)(void *info, int j, int ind[], double val[]), void *info) { /* compute FHV-factorization of specified matrix A */ - FHV *fhv; - LUFINT *lufint; int nfs_max, old_n_max, n_max, k, ret; xassert(n > 0); fi->valid = 0; @@ -48,52 +44,36 @@ int fhvint_factorize(FHVINT *fi, int n, int (*col)(void *info, int j, if (nfs_max == 0) nfs_max = 100; xassert(nfs_max > 0); - /* create interface to LU-factorization, if necessary */ - lufint = fi->lufint; - if (lufint == NULL) - { lufint = fi->lufint = lufint_create(); - lufint->sva_n_max = 4 * n + nfs_max; - lufint->sva_size = 10 * n; - lufint->delta_n0 = 0; - lufint->delta_n = 100; - lufint->sgf_updat = 1; - } - /* compute LU-factorization of specified matrix A */ - old_n_max = lufint->n_max; - ret = lufint_factorize(lufint, n, col, info); - n_max = lufint->n_max; - /* create FHV-factorization, if necessary */ - fhv = fi->fhv; - if (fhv == NULL) - { fhv = fi->fhv = talloc(1, FHV); - fhv->luf = lufint->luf; - fhv->nfs_max = 0; - fhv->hh_ind = NULL; - fhv->p0_ind = NULL; - fhv->p0_inv = NULL; - } - /* allocate/reallocate FHV-factorization, if necessary */ - if (fhv->nfs_max != nfs_max) - { fhv->nfs_max = nfs_max; - if (fhv->hh_ind != NULL) - tfree(fhv->hh_ind); - fhv->hh_ind = talloc(1+nfs_max, int); + /* compute factorization of specified matrix A */ + old_n_max = fi->lufi->n_max; + fi->lufi->sva_n_max = 4 * n + nfs_max; + fi->lufi->sgf_updat = 1; + ret = lufint_factorize(fi->lufi, n, col, info); + n_max = fi->lufi->n_max; + /* allocate/reallocate arrays, if necessary */ + if (fi->fhv.nfs_max != nfs_max) + { if (fi->fhv.hh_ind != NULL) + tfree(fi->fhv.hh_ind); + fi->fhv.hh_ind = talloc(1+nfs_max, int); } if (old_n_max < n_max) - { if (fhv->p0_ind != NULL) - tfree(fhv->p0_ind); - if (fhv->p0_inv != NULL) - tfree(fhv->p0_inv); - fhv->p0_ind = talloc(1+n_max, int); - fhv->p0_inv = talloc(1+n_max, int); + { if (fi->fhv.p0_ind != NULL) + tfree(fi->fhv.p0_ind); + if (fi->fhv.p0_inv != NULL) + tfree(fi->fhv.p0_inv); + fi->fhv.p0_ind = talloc(1+n_max, int); + fi->fhv.p0_inv = talloc(1+n_max, int); } + /* initialize FHV-factorization */ + fi->fhv.luf = fi->lufi->luf; + fi->fhv.nfs_max = nfs_max; /* H := I */ - fhv->nfs = 0; - fhv->hh_ref = sva_alloc_vecs(fi->lufint->sva, nfs_max); + fi->fhv.nfs = 0; + fi->fhv.hh_ref = sva_alloc_vecs(fi->lufi->sva, nfs_max); /* P0 := P */ for (k = 1; k <= n; k++) - { fhv->p0_ind[k] = fi->lufint->luf->pp_ind[k]; - fhv->p0_inv[k] = fi->lufint->luf->pp_inv[k]; + { fi->fhv.p0_ind[k] = fi->fhv.luf->pp_ind[k]; + fi->fhv.p0_inv[k] = fi->fhv.luf->pp_inv[k]; } /* set validation flag */ if (ret == 0) @@ -104,13 +84,13 @@ int fhvint_factorize(FHVINT *fi, int n, int (*col)(void *info, int j, int fhvint_update(FHVINT *fi, int j, int len, const int ind[], const double val[]) { /* update FHV-factorization after replacing j-th column of A */ - SGF *sgf = fi->lufint->sgf; + SGF *sgf = fi->lufi->sgf; int *ind1 = sgf->rs_next; double *val1 = sgf->vr_max; double *work = sgf->work; int ret; xassert(fi->valid); - ret = fhv_ft_update(fi->fhv, j, len, ind, val, ind1, val1, work); + ret = fhv_ft_update(&fi->fhv, j, len, ind, val, ind1, val1, work); if (ret != 0) fi->valid = 0; return ret; @@ -118,12 +98,12 @@ int fhvint_update(FHVINT *fi, int j, int len, const int ind[], void fhvint_ftran(FHVINT *fi, double x[]) { /* solve system A * x = b */ - FHV *fhv = fi->fhv; + FHV *fhv = &fi->fhv; LUF *luf = fhv->luf; int n = luf->n; int *pp_ind = luf->pp_ind; int *pp_inv = luf->pp_inv; - SGF *sgf = fi->lufint->sgf; + SGF *sgf = fi->lufi->sgf; double *work = sgf->work; xassert(fi->valid); /* A = F * H * V */ @@ -141,12 +121,12 @@ void fhvint_ftran(FHVINT *fi, double x[]) void fhvint_btran(FHVINT *fi, double x[]) { /* solve system A'* x = b */ - FHV *fhv = fi->fhv; + FHV *fhv = &fi->fhv; LUF *luf = fhv->luf; int n = luf->n; int *pp_ind = luf->pp_ind; int *pp_inv = luf->pp_inv; - SGF *sgf = fi->lufint->sgf; + SGF *sgf = fi->lufi->sgf; double *work = sgf->work; xassert(fi->valid); /* A' = (F * H * V)' = V'* H'* F' */ @@ -162,18 +142,25 @@ void fhvint_btran(FHVINT *fi, double x[]) return; } +double fhvint_estimate(FHVINT *fi) +{ /* estimate 1-norm of inv(A) */ + double norm; + xassert(fi->valid); + xassert(fi->fhv.nfs == 0); + norm = luf_estimate_norm(fi->fhv.luf, fi->lufi->sgf->vr_max, + fi->lufi->sgf->work); + return norm; +} + void fhvint_delete(FHVINT *fi) { /* delete interface to FHV-factorization */ - FHV *fhv = fi->fhv; - LUFINT *lufint = fi->lufint; - if (fhv != NULL) - { tfree(fhv->hh_ind); - tfree(fhv->p0_ind); - tfree(fhv->p0_inv); - tfree(fhv); - } - if (lufint != NULL) - lufint_delete(fi->lufint); + lufint_delete(fi->lufi); + if (fi->fhv.hh_ind != NULL) + tfree(fi->fhv.hh_ind); + if (fi->fhv.p0_ind != NULL) + tfree(fi->fhv.p0_ind); + if (fi->fhv.p0_inv != NULL) + tfree(fi->fhv.p0_inv); tfree(fi); return; } diff --git a/resources/3rdparty/glpk-4.53/src/bflib/fhvint.h b/resources/3rdparty/glpk-4.57/src/bflib/fhvint.h similarity index 91% rename from resources/3rdparty/glpk-4.53/src/bflib/fhvint.h rename to resources/3rdparty/glpk-4.57/src/bflib/fhvint.h index 1363a9230..000829c6f 100644 --- a/resources/3rdparty/glpk-4.53/src/bflib/fhvint.h +++ b/resources/3rdparty/glpk-4.57/src/bflib/fhvint.h @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2012-2014 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * @@ -33,9 +33,9 @@ struct FHVINT { /* interface to FHV-factorization */ int valid; /* factorization is valid only if this flag is set */ - FHV *fhv; + FHV fhv; /* FHV-factorization */ - LUFINT *lufint; + LUFINT *lufi; /* interface to underlying LU-factorization */ /*--------------------------------------------------------------*/ /* control parameters */ @@ -65,6 +65,10 @@ void fhvint_ftran(FHVINT *fi, double x[]); void fhvint_btran(FHVINT *fi, double x[]); /* solve system A'* x = b */ +#define fhvint_estimate _glp_fhvint_estimate +double fhvint_estimate(FHVINT *fi); +/* estimate 1-norm of inv(A) */ + #define fhvint_delete _glp_fhvint_delete void fhvint_delete(FHVINT *fi); /* delete interface to FHV-factorization */ diff --git a/resources/3rdparty/glpk-4.53/src/bflib/ifu.c b/resources/3rdparty/glpk-4.57/src/bflib/ifu.c similarity index 99% rename from resources/3rdparty/glpk-4.53/src/bflib/ifu.c rename to resources/3rdparty/glpk-4.57/src/bflib/ifu.c index 9e4adc7f8..aa47fb092 100644 --- a/resources/3rdparty/glpk-4.53/src/bflib/ifu.c +++ b/resources/3rdparty/glpk-4.57/src/bflib/ifu.c @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2012-2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * diff --git a/resources/3rdparty/glpk-4.53/src/bflib/ifu.h b/resources/3rdparty/glpk-4.57/src/bflib/ifu.h similarity index 98% rename from resources/3rdparty/glpk-4.53/src/bflib/ifu.h rename to resources/3rdparty/glpk-4.57/src/bflib/ifu.h index 0d53f78f6..1c67a8015 100644 --- a/resources/3rdparty/glpk-4.53/src/bflib/ifu.h +++ b/resources/3rdparty/glpk-4.57/src/bflib/ifu.h @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2012-2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * diff --git a/resources/3rdparty/glpk-4.53/src/bflib/luf.c b/resources/3rdparty/glpk-4.57/src/bflib/luf.c similarity index 78% rename from resources/3rdparty/glpk-4.53/src/bflib/luf.c rename to resources/3rdparty/glpk-4.57/src/bflib/luf.c index adbf10451..2797407d9 100644 --- a/resources/3rdparty/glpk-4.53/src/bflib/luf.c +++ b/resources/3rdparty/glpk-4.57/src/bflib/luf.c @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2012-2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * @@ -24,6 +24,49 @@ #include "env.h" #include "luf.h" +/*********************************************************************** +* luf_store_v_cols - store matrix V = A in column-wise format +* +* This routine stores matrix V = A in column-wise format, where A is +* the original matrix to be factorized. +* +* On exit the routine returns the number of non-zeros in matrix V. */ + +int luf_store_v_cols(LUF *luf, int (*col)(void *info, int j, int ind[], + double val[]), void *info, int ind[], double val[]) +{ int n = luf->n; + SVA *sva = luf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + int vc_ref = luf->vc_ref; + int *vc_ptr = &sva->ptr[vc_ref-1]; + int *vc_len = &sva->len[vc_ref-1]; + int *vc_cap = &sva->cap[vc_ref-1]; + int j, len, ptr, nnz; + nnz = 0; + for (j = 1; j <= n; j++) + { /* get j-th column */ + len = col(info, j, ind, val); + xassert(0 <= len && len <= n); + /* enlarge j-th column capacity */ + if (vc_cap[j] < len) + { if (sva->r_ptr - sva->m_ptr < len) + { sva_more_space(sva, len); + sv_ind = sva->ind; + sv_val = sva->val; + } + sva_enlarge_cap(sva, vc_ref-1+j, len, 0); + } + /* store j-th column */ + ptr = vc_ptr[j]; + memcpy(&sv_ind[ptr], &ind[1], len * sizeof(int)); + memcpy(&sv_val[ptr], &val[1], len * sizeof(double)); + vc_len[j] = len; + nnz += len; + } + return nnz; +} + /*********************************************************************** * luf_check_all - check LU-factorization before k-th elimination step * @@ -441,8 +484,7 @@ void luf_f_solve(LUF *luf, double x[/*1+n*/]) /* walk thru j-th column of matrix F and substitute x[j] into * other equations */ if ((x_j = x[j]) != 0.0) - { for (end = (ptr = fc_ptr[j]) + fc_len[j]; - ptr < end; ptr++) + { for (end = (ptr = fc_ptr[j]) + fc_len[j]; ptr < end; ptr++) x[sv_ind[ptr]] -= sv_val[ptr] * x_j; } } @@ -479,8 +521,7 @@ void luf_ft_solve(LUF *luf, double x[/*1+n*/]) /* walk thru i-th row of matrix F and substitute x[i] into * other equations */ if ((x_i = x[i]) != 0.0) - { for (end = (ptr = fr_ptr[i]) + fr_len[i]; - ptr < end; ptr++) + { for (end = (ptr = fr_ptr[i]) + fr_len[i]; ptr < end; ptr++) x[sv_ind[ptr]] -= sv_val[ptr] * x_i; } } @@ -521,8 +562,7 @@ void luf_v_solve(LUF *luf, double b[/*1+n*/], double x[/*1+n*/]) * walk through j-th column of matrix V and substitute x[j] * into other equations */ if ((x_j = x[j] = b[i] / vr_piv[i]) != 0.0) - { for (end = (ptr = vc_ptr[j]) + vc_len[j]; - ptr < end; ptr++) + { for (end = (ptr = vc_ptr[j]) + vc_len[j]; ptr < end; ptr++) b[sv_ind[ptr]] -= sv_val[ptr] * x_j; } } @@ -564,12 +604,110 @@ void luf_vt_solve(LUF *luf, double b[/*1+n*/], double x[/*1+n*/]) * walk through i-th row of matrix V and substitute x[i] into * other equations */ if ((x_i = x[i] = b[j] / vr_piv[i]) != 0.0) - { for (end = (ptr = vr_ptr[i]) + vr_len[i]; - ptr < end; ptr++) + { for (end = (ptr = vr_ptr[i]) + vr_len[i]; ptr < end; ptr++) b[sv_ind[ptr]] -= sv_val[ptr] * x_i; } } return; } +/*********************************************************************** +* luf_vt_solve1 - solve system V' * y = e' to cause growth in y +* +* This routine is a special version of luf_vt_solve. It solves the +* system V'* y = e' = e + delta e, where V' is a matrix transposed to +* the matrix V, e is the specified right-hand side vector, and delta e +* is a vector of +1 and -1 chosen to cause growth in the solution +* vector y. +* +* On entry the array e should contain elements of the right-hand side +* vector e in locations e[1], ..., e[n], where n is the order of the +* matrix V. On exit the array y will contain elements of the solution +* vector y in locations y[1], ..., y[n]. Note that the array e will be +* clobbered on exit. */ + +void luf_vt_solve1(LUF *luf, double e[/*1+n*/], double y[/*1+n*/]) +{ int n = luf->n; + SVA *sva = luf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + double *vr_piv = luf->vr_piv; + int vr_ref = luf->vr_ref; + int *vr_ptr = &sva->ptr[vr_ref-1]; + int *vr_len = &sva->len[vr_ref-1]; + int *pp_inv = luf->pp_inv; + int *qq_ind = luf->qq_ind; + int i, j, k, ptr, end; + double e_j, y_i; + for (k = 1; k <= n; k++) + { /* k-th row of U' = j-th column of V */ + /* k-th column of U' = i-th row of V */ + i = pp_inv[k]; + j = qq_ind[k]; + /* determine e'[j] = e[j] + delta e[j] */ + e_j = (e[j] >= 0.0 ? e[j] + 1.0 : e[j] - 1.0); + /* compute y[i] = e'[j] / u'[k,k], where u'[k,k] = v[i,j] */ + y_i = y[i] = e_j / vr_piv[i]; + /* walk through i-th row of matrix V and substitute y[i] into + * other equations */ + for (end = (ptr = vr_ptr[i]) + vr_len[i]; ptr < end; ptr++) + e[sv_ind[ptr]] -= sv_val[ptr] * y_i; + } + return; +} + +/*********************************************************************** +* luf_estimate_norm - estimate 1-norm of inv(A) +* +* This routine estimates 1-norm of inv(A) by one step of inverse +* iteration for the small singular vector as described in [1]. This +* involves solving two systems of equations: +* +* A'* y = e, +* +* A * z = y, +* +* where A' is a matrix transposed to A, and e is a vector of +1 and -1 +* chosen to cause growth in y. Then +* +* estimate 1-norm of inv(A) = (1-norm of z) / (1-norm of y) +* +* REFERENCES +* +* 1. G.E.Forsythe, M.A.Malcolm, C.B.Moler. Computer Methods for +* Mathematical Computations. Prentice-Hall, Englewood Cliffs, N.J., +* pp. 30-62 (subroutines DECOMP and SOLVE). */ + +double luf_estimate_norm(LUF *luf, double w1[/*1+n*/], double + w2[/*1+n*/]) +{ int n = luf->n; + double *e = w1; + double *y = w2; + double *z = w1; + int i; + double y_norm, z_norm; + /* y = inv(A') * e = inv(F') * inv(V') * e */ + /* compute y' = inv(V') * e to cause growth in y' */ + for (i = 1; i <= n; i++) + e[i] = 0.0; + luf_vt_solve1(luf, e, y); + /* compute y = inv(F') * y' */ + luf_ft_solve(luf, y); + /* compute 1-norm of y = sum |y[i]| */ + y_norm = 0.0; + for (i = 1; i <= n; i++) + y_norm += (y[i] >= 0.0 ? +y[i] : -y[i]); + /* z = inv(A) * y = inv(V) * inv(F) * y */ + /* compute z' = inv(F) * y */ + luf_f_solve(luf, y); + /* compute z = inv(V) * z' */ + luf_v_solve(luf, y, z); + /* compute 1-norm of z = sum |z[i]| */ + z_norm = 0.0; + for (i = 1; i <= n; i++) + z_norm += (z[i] >= 0.0 ? +z[i] : -z[i]); + /* estimate 1-norm of inv(A) = (1-norm of z) / (1-norm of y) */ + return z_norm / y_norm; +} + /* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/bflib/luf.h b/resources/3rdparty/glpk-4.57/src/bflib/luf.h similarity index 91% rename from resources/3rdparty/glpk-4.53/src/bflib/luf.h rename to resources/3rdparty/glpk-4.57/src/bflib/luf.h index d5b0bd3c8..d9264095a 100644 --- a/resources/3rdparty/glpk-4.53/src/bflib/luf.h +++ b/resources/3rdparty/glpk-4.57/src/bflib/luf.h @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2012-2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * @@ -168,6 +168,11 @@ struct LUF } while (0) /* swap columns j1 and j2 of matrix U = P'* V * Q' */ +#define luf_store_v_cols _glp_luf_store_v_cols +int luf_store_v_cols(LUF *luf, int (*col)(void *info, int j, int ind[], + double val[]), void *info, int ind[], double val[]); +/* store matrix V = A in column-wise format */ + #define luf_check_all _glp_luf_check_all void luf_check_all(LUF *luf, int k); /* check LU-factorization before k-th elimination step */ @@ -192,22 +197,31 @@ void luf_check_f_rc(LUF *luf); void luf_check_v_rc(LUF *luf); /* check rows and columns of matrix V */ -#define luf_f_solve _glp_luf_f_solve1 +#define luf_f_solve _glp_luf_f_solve void luf_f_solve(LUF *luf, double x[/*1+n*/]); /* solve system F * x = b */ -#define luf_ft_solve _glp_luf_ft_solve1 +#define luf_ft_solve _glp_luf_ft_solve void luf_ft_solve(LUF *luf, double x[/*1+n*/]); /* solve system F' * x = b */ -#define luf_v_solve _glp_luf_v_solve1 +#define luf_v_solve _glp_luf_v_solve void luf_v_solve(LUF *luf, double b[/*1+n*/], double x[/*1+n*/]); /* solve system V * x = b */ -#define luf_vt_solve _glp_luf_vt_solve1 +#define luf_vt_solve _glp_luf_vt_solve void luf_vt_solve(LUF *luf, double b[/*1+n*/], double x[/*1+n*/]); /* solve system V' * x = b */ +#define luf_vt_solve1 _glp_luf_vt_solve1 +void luf_vt_solve1(LUF *luf, double e[/*1+n*/], double y[/*1+n*/]); +/* solve system V' * y = e' to cause growth in y */ + +#define luf_estimate_norm _glp_luf_estimate_norm +double luf_estimate_norm(LUF *luf, double w1[/*1+n*/], double + w2[/*1+n*/]); +/* estimate 1-norm of inv(A) */ + #endif /* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/bflib/lufint.c b/resources/3rdparty/glpk-4.57/src/bflib/lufint.c similarity index 80% rename from resources/3rdparty/glpk-4.53/src/bflib/lufint.c rename to resources/3rdparty/glpk-4.57/src/bflib/lufint.c index 56f83e32f..7cd00924f 100644 --- a/resources/3rdparty/glpk-4.53/src/bflib/lufint.c +++ b/resources/3rdparty/glpk-4.57/src/bflib/lufint.c @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2012-2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * @@ -43,42 +43,6 @@ LUFINT *lufint_create(void) return fi; } -static int setup_v_cols(LUF *luf, int (*col)(void *info, int j, - int ind[], double val[]), void *info, int ind[], double val[]) -{ /* setup matrix V = A in column-wise format */ - int n = luf->n; - SVA *sva = luf->sva; - int *sv_ind = sva->ind; - double *sv_val = sva->val; - int vc_ref = luf->vc_ref; - int *vc_ptr = &sva->ptr[vc_ref-1]; - int *vc_len = &sva->len[vc_ref-1]; - int *vc_cap = &sva->cap[vc_ref-1]; - int j, len, ptr, nnz; - nnz = 0; - for (j = 1; j <= n; j++) - { /* get j-th column */ - len = col(info, j, ind, val); - xassert(0 <= len && len <= n); - /* enlarge j-th column capacity */ - if (vc_cap[j] < len) - { if (sva->r_ptr - sva->m_ptr < len) - { sva_more_space(sva, len); - sv_ind = sva->ind; - sv_val = sva->val; - } - sva_enlarge_cap(sva, vc_ref-1+j, len, 0); - } - /* store j-th column */ - ptr = vc_ptr[j]; - memcpy(&sv_ind[ptr], &ind[1], len * sizeof(int)); - memcpy(&sv_val[ptr], &val[1], len * sizeof(double)); - vc_len[j] = len; - nnz += len; - } - return nnz; -} - int lufint_factorize(LUFINT *fi, int n, int (*col)(void *info, int j, int ind[], double val[]), void *info) { /* compute LU-factorization of specified matrix A */ @@ -169,8 +133,8 @@ int lufint_factorize(LUFINT *fi, int n, int (*col)(void *info, int j, luf->fc_ref = sva_alloc_vecs(sva, n); luf->vr_ref = sva_alloc_vecs(sva, n); luf->vc_ref = sva_alloc_vecs(sva, n); - /* setup matrix V = A in column-wise format */ - setup_v_cols(luf, col, info, sgf->rs_prev, sgf->work); + /* store matrix V = A in column-wise format */ + luf_store_v_cols(luf, col, info, sgf->rs_prev, sgf->work); /* setup factorizer control parameters */ sgf->updat = fi->sgf_updat; sgf->piv_tol = fi->sgf_piv_tol; diff --git a/resources/3rdparty/glpk-4.53/src/bflib/lufint.h b/resources/3rdparty/glpk-4.57/src/bflib/lufint.h similarity index 97% rename from resources/3rdparty/glpk-4.53/src/bflib/lufint.h rename to resources/3rdparty/glpk-4.57/src/bflib/lufint.h index 6ec6cf073..b3ad5b646 100644 --- a/resources/3rdparty/glpk-4.53/src/bflib/lufint.h +++ b/resources/3rdparty/glpk-4.57/src/bflib/lufint.h @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2012-2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * diff --git a/resources/3rdparty/glpk-4.57/src/bflib/scf.c b/resources/3rdparty/glpk-4.57/src/bflib/scf.c new file mode 100644 index 000000000..556b19114 --- /dev/null +++ b/resources/3rdparty/glpk-4.57/src/bflib/scf.c @@ -0,0 +1,523 @@ +/* scf.c (sparse updatable Schur-complement-based factorization) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2013-2014 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "scf.h" + +/*********************************************************************** +* scf_r0_solve - solve system R0 * x = b or R0'* x = b +* +* This routine solves the system R0 * x = b (if tr is zero) or the +* system R0'* x = b (if tr is non-zero), where R0 is the left factor +* of the initial matrix A0 = R0 * S0. +* +* On entry the array x should contain elements of the right-hand side +* vector b in locations x[1], ..., x[n0], where n0 is the order of the +* matrix R0. On exit the array x will contain elements of the solution +* vector in the same locations. */ + +void scf_r0_solve(SCF *scf, int tr, double x[/*1+n0*/]) +{ switch (scf->type) + { case 1: + /* A0 = F0 * V0, so R0 = F0 */ + if (!tr) + luf_f_solve(scf->a0.luf, x); + else + luf_ft_solve(scf->a0.luf, x); + break; + case 2: + /* A0 = I * A0, so R0 = I */ + break; + default: + xassert(scf != scf); + } + return; +} + +/*********************************************************************** +* scf_s0_solve - solve system S0 * x = b or S0'* x = b +* +* This routine solves the system S0 * x = b (if tr is zero) or the +* system S0'* x = b (if tr is non-zero), where S0 is the right factor +* of the initial matrix A0 = R0 * S0. +* +* On entry the array x should contain elements of the right-hand side +* vector b in locations x[1], ..., x[n0], where n0 is the order of the +* matrix S0. On exit the array x will contain elements of the solution +* vector in the same locations. +* +* The routine uses locations [1], ..., [n0] of three working arrays +* w1, w2, and w3. (In case of type = 1 arrays w2 and w3 are not used +* and can be specified as NULL.) */ + +void scf_s0_solve(SCF *scf, int tr, double x[/*1+n0*/], + double w1[/*1+n0*/], double w2[/*1+n0*/], double w3[/*1+n0*/]) +{ int n0 = scf->n0; + switch (scf->type) + { case 1: + /* A0 = F0 * V0, so S0 = V0 */ + if (!tr) + luf_v_solve(scf->a0.luf, x, w1); + else + luf_vt_solve(scf->a0.luf, x, w1); + break; + case 2: + /* A0 = I * A0, so S0 = A0 */ + if (!tr) + btf_a_solve(scf->a0.btf, x, w1, w2, w3); + else + btf_at_solve(scf->a0.btf, x, w1, w2, w3); + break; + default: + xassert(scf != scf); + } + memcpy(&x[1], &w1[1], n0 * sizeof(double)); + return; +} + +/*********************************************************************** +* scf_r_prod - compute product y := y + alpha * R * x +* +* This routine computes the product y := y + alpha * R * x, where +* x is a n0-vector, alpha is a scalar, y is a nn-vector. +* +* Since matrix R is available by rows, the product components are +* computed as inner products: +* +* y[i] = y[i] + alpha * (i-th row of R) * x +* +* for i = 1, 2, ..., nn. */ + +void scf_r_prod(SCF *scf, double y[/*1+nn*/], double a, const double + x[/*1+n0*/]) +{ int nn = scf->nn; + SVA *sva = scf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + int rr_ref = scf->rr_ref; + int *rr_ptr = &sva->ptr[rr_ref-1]; + int *rr_len = &sva->len[rr_ref-1]; + int i, ptr, end; + double t; + for (i = 1; i <= nn; i++) + { /* t := (i-th row of R) * x */ + t = 0.0; + for (end = (ptr = rr_ptr[i]) + rr_len[i]; ptr < end; ptr++) + t += sv_val[ptr] * x[sv_ind[ptr]]; + /* y[i] := y[i] + alpha * t */ + y[i] += a * t; + } + return; +} + +/*********************************************************************** +* scf_rt_prod - compute product y := y + alpha * R'* x +* +* This routine computes the product y := y + alpha * R'* x, where +* R' is a matrix transposed to R, x is a nn-vector, alpha is a scalar, +* y is a n0-vector. +* +* Since matrix R is available by rows, the product is computed as a +* linear combination: +* +* y := y + alpha * (R'[1] * x[1] + ... + R'[nn] * x[nn]), +* +* where R'[i] is i-th row of R. */ + +void scf_rt_prod(SCF *scf, double y[/*1+n0*/], double a, const double + x[/*1+nn*/]) +{ int nn = scf->nn; + SVA *sva = scf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + int rr_ref = scf->rr_ref; + int *rr_ptr = &sva->ptr[rr_ref-1]; + int *rr_len = &sva->len[rr_ref-1]; + int i, ptr, end; + double t; + for (i = 1; i <= nn; i++) + { if (x[i] == 0.0) + continue; + /* y := y + alpha * R'[i] * x[i] */ + t = a * x[i]; + for (end = (ptr = rr_ptr[i]) + rr_len[i]; ptr < end; ptr++) + y[sv_ind[ptr]] += sv_val[ptr] * t; + } + return; +} + +/*********************************************************************** +* scf_s_prod - compute product y := y + alpha * S * x +* +* This routine computes the product y := y + alpha * S * x, where +* x is a nn-vector, alpha is a scalar, y is a n0 vector. +* +* Since matrix S is available by columns, the product is computed as +* a linear combination: +* +* y := y + alpha * (S[1] * x[1] + ... + S[nn] * x[nn]), +* +* where S[j] is j-th column of S. */ + +void scf_s_prod(SCF *scf, double y[/*1+n0*/], double a, const double + x[/*1+nn*/]) +{ int nn = scf->nn; + SVA *sva = scf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + int ss_ref = scf->ss_ref; + int *ss_ptr = &sva->ptr[ss_ref-1]; + int *ss_len = &sva->len[ss_ref-1]; + int j, ptr, end; + double t; + for (j = 1; j <= nn; j++) + { if (x[j] == 0.0) + continue; + /* y := y + alpha * S[j] * x[j] */ + t = a * x[j]; + for (end = (ptr = ss_ptr[j]) + ss_len[j]; ptr < end; ptr++) + y[sv_ind[ptr]] += sv_val[ptr] * t; + } + return; +} + +/*********************************************************************** +* scf_st_prod - compute product y := y + alpha * S'* x +* +* This routine computes the product y := y + alpha * S'* x, where +* S' is a matrix transposed to S, x is a n0-vector, alpha is a scalar, +* y is a nn-vector. +* +* Since matrix S is available by columns, the product components are +* computed as inner products: +* +* y[j] := y[j] + alpha * (j-th column of S) * x +* +* for j = 1, 2, ..., nn. */ + +void scf_st_prod(SCF *scf, double y[/*1+nn*/], double a, const double + x[/*1+n0*/]) +{ int nn = scf->nn; + SVA *sva = scf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + int ss_ref = scf->ss_ref; + int *ss_ptr = &sva->ptr[ss_ref-1]; + int *ss_len = &sva->len[ss_ref-1]; + int j, ptr, end; + double t; + for (j = 1; j <= nn; j++) + { /* t := (j-th column of S) * x */ + t = 0.0; + for (end = (ptr = ss_ptr[j]) + ss_len[j]; ptr < end; ptr++) + t += sv_val[ptr] * x[sv_ind[ptr]]; + /* y[j] := y[j] + alpha * t */ + y[j] += a * t; + } + return; +} + +/*********************************************************************** +* scf_a_solve - solve system A * x = b +* +* This routine solves the system A * x = b, where A is the current +* matrix. +* +* On entry the array x should contain elements of the right-hand side +* vector b in locations x[1], ..., x[n], where n is the order of the +* matrix A. On exit the array x will contain elements of the solution +* vector in the same locations. +* +* For details see the program documentation. */ + +void scf_a_solve(SCF *scf, double x[/*1+n*/], + double w[/*1+n0+nn*/], double work1[/*1+max(n0,nn)*/], + double work2[/*1+n*/], double work3[/*1+n*/]) +{ int n = scf->n; + int n0 = scf->n0; + int nn = scf->nn; + int *pp_ind = scf->pp_ind; + int *qq_inv = scf->qq_inv; + int i, ii; + /* (u1, u2) := inv(P) * (b, 0) */ + for (ii = 1; ii <= n0+nn; ii++) + { i = pp_ind[ii]; +#if 1 /* FIXME: currently P = I */ + xassert(i == ii); +#endif + w[ii] = (i <= n ? x[i] : 0.0); + } + /* v1 := inv(R0) * u1 */ + scf_r0_solve(scf, 0, &w[0]); + /* v2 := u2 - R * v1 */ + scf_r_prod(scf, &w[n0], -1.0, &w[0]); + /* w2 := inv(C) * v2 */ + ifu_a_solve(&scf->ifu, &w[n0], work1); + /* w1 := inv(S0) * (v1 - S * w2) */ + scf_s_prod(scf, &w[0], -1.0, &w[n0]); + scf_s0_solve(scf, 0, &w[0], work1, work2, work3); + /* (x, x~) := inv(Q) * (w1, w2); x~ is not needed */ + for (i = 1; i <= n; i++) + x[i] = w[qq_inv[i]]; + return; +} + +/*********************************************************************** +* scf_at_solve - solve system A'* x = b +* +* This routine solves the system A'* x = b, where A' is a matrix +* transposed to the current matrix A. +* +* On entry the array x should contain elements of the right-hand side +* vector b in locations x[1], ..., x[n], where n is the order of the +* matrix A. On exit the array x will contain elements of the solution +* vector in the same locations. +* +* For details see the program documentation. */ + +void scf_at_solve(SCF *scf, double x[/*1+n*/], + double w[/*1+n0+nn*/], double work1[/*1+max(n0,nn)*/], + double work2[/*1+n*/], double work3[/*1+n*/]) +{ int n = scf->n; + int n0 = scf->n0; + int nn = scf->nn; + int *pp_inv = scf->pp_inv; + int *qq_ind = scf->qq_ind; + int i, ii; + /* (u1, u2) := Q * (b, 0) */ + for (ii = 1; ii <= n0+nn; ii++) + { i = qq_ind[ii]; + w[ii] = (i <= n ? x[i] : 0.0); + } + /* v1 := inv(S0') * u1 */ + scf_s0_solve(scf, 1, &w[0], work1, work2, work3); + /* v2 := inv(C') * (u2 - S'* v1) */ + scf_st_prod(scf, &w[n0], -1.0, &w[0]); + ifu_at_solve(&scf->ifu, &w[n0], work1); + /* w2 := v2 */ + /* nop */ + /* w1 := inv(R0') * (v1 - R'* w2) */ + scf_rt_prod(scf, &w[0], -1.0, &w[n0]); + scf_r0_solve(scf, 1, &w[0]); + /* compute (x, x~) := P * (w1, w2); x~ is not needed */ + for (i = 1; i <= n; i++) + { +#if 1 /* FIXME: currently P = I */ + xassert(pp_inv[i] == i); +#endif + x[i] = w[pp_inv[i]]; + } + return; +} + +/*********************************************************************** +* scf_add_r_row - add new row to matrix R +* +* This routine adds new (nn+1)-th row to matrix R, whose elements are +* specified in locations w[1,...,n0]. */ + +void scf_add_r_row(SCF *scf, const double w[/*1+n0*/]) +{ int n0 = scf->n0; + int nn = scf->nn; + SVA *sva = scf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + int rr_ref = scf->rr_ref; + int *rr_ptr = &sva->ptr[rr_ref-1]; + int *rr_len = &sva->len[rr_ref-1]; + int j, len, ptr; + xassert(0 <= nn && nn < scf->nn_max); + /* determine length of new row */ + len = 0; + for (j = 1; j <= n0; j++) + { if (w[j] != 0.0) + len++; + } + /* reserve locations for new row in static part of SVA */ + if (len > 0) + { if (sva->r_ptr - sva->m_ptr < len) + { sva_more_space(sva, len); + sv_ind = sva->ind; + sv_val = sva->val; + } + sva_reserve_cap(sva, rr_ref + nn, len); + } + /* store new row in sparse format */ + ptr = rr_ptr[nn+1]; + for (j = 1; j <= n0; j++) + { if (w[j] != 0.0) + { sv_ind[ptr] = j; + sv_val[ptr] = w[j]; + ptr++; + } + } + xassert(ptr - rr_ptr[nn+1] == len); + rr_len[nn+1] = len; +#ifdef GLP_DEBUG + sva_check_area(sva); +#endif + return; +} + +/*********************************************************************** +* scf_add_s_col - add new column to matrix S +* +* This routine adds new (nn+1)-th column to matrix S, whose elements +* are specified in locations v[1,...,n0]. */ + +void scf_add_s_col(SCF *scf, const double v[/*1+n0*/]) +{ int n0 = scf->n0; + int nn = scf->nn; + SVA *sva = scf->sva; + int *sv_ind = sva->ind; + double *sv_val = sva->val; + int ss_ref = scf->ss_ref; + int *ss_ptr = &sva->ptr[ss_ref-1]; + int *ss_len = &sva->len[ss_ref-1]; + int i, len, ptr; + xassert(0 <= nn && nn < scf->nn_max); + /* determine length of new column */ + len = 0; + for (i = 1; i <= n0; i++) + { if (v[i] != 0.0) + len++; + } + /* reserve locations for new column in static part of SVA */ + if (len > 0) + { if (sva->r_ptr - sva->m_ptr < len) + { sva_more_space(sva, len); + sv_ind = sva->ind; + sv_val = sva->val; + } + sva_reserve_cap(sva, ss_ref + nn, len); + } + /* store new column in sparse format */ + ptr = ss_ptr[nn+1]; + for (i = 1; i <= n0; i++) + { if (v[i] != 0.0) + { sv_ind[ptr] = i; + sv_val[ptr] = v[i]; + ptr++; + } + } + xassert(ptr - ss_ptr[nn+1] == len); + ss_len[nn+1] = len; +#ifdef GLP_DEBUG + sva_check_area(sva); +#endif + return; +} + +/*********************************************************************** +* scf_update_aug - update factorization of augmented matrix +* +* Given factorization of the current augmented matrix: +* +* ( A0 A1 ) ( R0 ) ( S0 S ) +* ( ) = ( ) ( ), +* ( A2 A3 ) ( R I ) ( C ) +* +* this routine computes factorization of the new augmented matrix: +* +* ( A0 | A1 b ) +* ( ---+------ ) ( A0 A1^ ) ( R0 ) ( S0 S^ ) +* ( A2 | A3 f ) = ( ) = ( ) ( ), +* ( | ) ( A2^ A3^ ) ( R^ I ) ( C^ ) +* ( d' | g' h ) +* +* where b and d are specified n0-vectors, f and g are specified +* nn-vectors, and h is a specified scalar. (Note that corresponding +* arrays are clobbered on exit.) +* +* The parameter upd specifies how to update factorization of the Schur +* complement C: +* +* 1 Bartels-Golub updating. +* +* 2 Givens rotations updating. +* +* The working arrays w1, w2, and w3 are used in the same way as in the +* routine scf_s0_solve. +* +* RETURNS +* +* 0 Factorization has been successfully updated. +* +* 1 Updating limit has been reached. +* +* 2 Updating IFU-factorization of matrix C failed. +* +* For details see the program documentation. */ + +int scf_update_aug(SCF *scf, double b[/*1+n0*/], double d[/*1+n0*/], + double f[/*1+nn*/], double g[/*1+nn*/], double h, int upd, + double w1[/*1+n0*/], double w2[/*1+n0*/], double w3[/*1+n0*/]) +{ int n0 = scf->n0; + int k, ret; + double *v, *w, *x, *y, z; + if (scf->nn == scf->nn_max) + { /* updating limit has been reached */ + return 1; + } + /* v := inv(R0) * b */ + scf_r0_solve(scf, 0, (v = b)); + /* w := inv(S0') * d */ + scf_s0_solve(scf, 1, (w = d), w1, w2, w3); + /* x := f - R * v */ + scf_r_prod(scf, (x = f), -1.0, v); + /* y := g - S'* w */ + scf_st_prod(scf, (y = g), -1.0, w); + /* z := h - v'* w */ + z = h; + for (k = 1; k <= n0; k++) + z -= v[k] * w[k]; + /* new R := R with row w added */ + scf_add_r_row(scf, w); + /* new S := S with column v added */ + scf_add_s_col(scf, v); + /* update IFU-factorization of C */ + switch (upd) + { case 1: + ret = ifu_bg_update(&scf->ifu, x, y, z); + break; + case 2: + ret = ifu_gr_update(&scf->ifu, x, y, z); + break; + default: + xassert(upd != upd); + } + if (ret != 0) + { /* updating IFU-factorization failed */ + return 2; + } + /* increase number of additional rows and columns */ + scf->nn++; + /* expand P and Q */ + k = n0 + scf->nn; + scf->pp_ind[k] = scf->pp_inv[k] = k; + scf->qq_ind[k] = scf->qq_inv[k] = k; + /* factorization has been successfully updated */ + return 0; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.57/src/bflib/scf.h b/resources/3rdparty/glpk-4.57/src/bflib/scf.h new file mode 100644 index 000000000..69d8cfc2a --- /dev/null +++ b/resources/3rdparty/glpk-4.57/src/bflib/scf.h @@ -0,0 +1,211 @@ +/* scf.h (sparse updatable Schur-complement-based factorization) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2013-2014 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef SCF_H +#define SCF_H + +#include "btf.h" +#include "ifu.h" +#include "luf.h" + +/*********************************************************************** +* The structure SCF describes sparse updatable factorization based on +* Schur complement. +* +* The SCF-factorization has the following format: +* +* ( A A1~ ) ( A0 A1 ) ( R0 ) ( S0 S ) +* ( ) = P ( ) Q = P ( ) ( ) Q, (1) +* ( A2~ A3~ ) ( A2 A3 ) ( R I ) ( C ) +* +* where: +* +* A is current (unsymmetric) square matrix (not stored); +* +* A1~, A2~, A3~ are some additional matrices (not stored); +* +* A0 is initial (unsymmetric) square matrix (not stored); +* +* A1, A2, A3 are some additional matrices (not stored); +* +* R0 and S0 are matrices that define factorization of the initial +* matrix A0 = R0 * S0 (stored in an invertable form); +* +* R is a matrix defined from R * S0 = A2, so R = A2 * inv(S0) (stored +* in row-wise sparse format); +* +* S is a matrix defined from R0 * S = A1, so S = inv(R0) * A1 (stored +* in column-wise sparse format); +* +* C is Schur complement (to matrix A0) defined from R * S + C = A3, +* so C = A3 - R * S = A3 - A2 * inv(A0) * A1 (stored in an invertable +* form). +* +* P, Q are permutation matrices (stored in both row- and column-like +* formats). */ + +typedef struct SCF SCF; + +struct SCF +{ /* Schur-complement-based factorization */ + int n; + /* order of current matrix A */ + /*--------------------------------------------------------------*/ + /* initial matrix A0 = R0 * S0 of order n0 in invertable form */ + int n0; + /* order of matrix A0 */ + int type; + /* type of factorization used: + * 1 - LU-factorization (R0 = F0, S0 = V0) + * 2 - BT-factorization (R0 = I, S0 = A0) */ + union + { LUF *luf; /* type = 1 */ + BTF *btf; /* type = 2 */ + } a0; + /* factorization of matrix A0 */ + /*--------------------------------------------------------------*/ + /* augmented matrix (A0, A1; A2, A3) of order n0+nn */ + int nn_max; + /* maximal number of additional rows and columns in the augmented + * matrix (this limits the number of updates) */ + int nn; + /* current number of additional rows and columns in the augmented + * matrix, 0 <= nn <= nn_max */ + SVA *sva; + /* associated sparse vector area (SVA) used to store rows of + * matrix R and columns of matrix S */ + /*--------------------------------------------------------------*/ + /* nn*n0-matrix R in row-wise format */ + int rr_ref; + /* reference number of sparse vector in SVA, which is the first + * row of matrix R */ +#if 0 + 0 + int *rr_ptr = &sva->ptr[rr_ref-1]; + /* rr_ptr[0] is not used; + * rr_ptr[i], 1 <= i <= nn, is pointer to i-th row in SVA; + * rr_ptr[nn+1,...,nn_max] are reserved locations */ + int *rr_len = &sva->len[rr_ref-1]; + /* rr_len[0] is not used; + * rr_len[i], 1 <= i <= nn, is length of i-th row; + * rr_len[nn+1,...,nn_max] are reserved locations */ +#endif + /*--------------------------------------------------------------*/ + /* n0*nn-matrix S in column-wise format */ + int ss_ref; + /* reference number of sparse vector in SVA, which is the first + * column of matrix S */ +#if 0 + 0 + int *ss_ptr = &sva->ptr[ss_ref-1]; + /* ss_ptr[0] is not used; + * ss_ptr[j], 1 <= j <= nn, is pointer to j-th column in SVA; + * ss_ptr[nn+1,...,nn_max] are reserved locations */ + int *ss_len = &sva->len[ss_ref-1]; + /* ss_len[0] is not used; + * ss_len[j], 1 <= j <= nn, is length of j-th column; + * ss_len[nn+1,...,nn_max] are reserved locations */ +#endif + /*--------------------------------------------------------------*/ + /* Schur complement C of order nn in invertable form */ + IFU ifu; + /* IFU-factorization of matrix C */ + /*--------------------------------------------------------------*/ + /* permutation matrix P of order n0+nn */ + int *pp_ind; /* int pp_ind[1+n0+nn_max]; */ + /* pp_ind[i] = j means that P[i,j] = 1 */ + int *pp_inv; /* int pp_inv[1+n0+nn_max]; */ + /* pp_inv[j] = i means that P[i,j] = 1 */ + /*--------------------------------------------------------------*/ + /* permutation matrix Q of order n0+nn */ + int *qq_ind; /* int qq_ind[1+n0+nn_max]; */ + /* qq_ind[i] = j means that Q[i,j] = 1 */ + int *qq_inv; /* int qq_inv[1+n0+nn_max]; */ + /* qq_inv[j] = i means that Q[i,j] = 1 */ +}; + +#define scf_swap_q_cols(j1, j2) \ + do \ + { int i1, i2; \ + i1 = qq_inv[j1], i2 = qq_inv[j2]; \ + qq_ind[i1] = j2, qq_inv[j2] = i1; \ + qq_ind[i2] = j1, qq_inv[j1] = i2; \ + } while (0) +/* swap columns j1 and j2 of permutation matrix Q */ + +#define scf_r0_solve _glp_scf_r0_solve +void scf_r0_solve(SCF *scf, int tr, double x[/*1+n0*/]); +/* solve system R0 * x = b or R0'* x = b */ + +#define scf_s0_solve _glp_scf_s0_solve +void scf_s0_solve(SCF *scf, int tr, double x[/*1+n0*/], + double w1[/*1+n0*/], double w2[/*1+n0*/], double w3[/*1+n0*/]); +/* solve system S0 * x = b or S0'* x = b */ + +#define scf_r_prod _glp_scf_r_prod +void scf_r_prod(SCF *scf, double y[/*1+nn*/], double a, const double + x[/*1+n0*/]); +/* compute product y := y + alpha * R * x */ + +#define scf_rt_prod _glp_scf_rt_prod +void scf_rt_prod(SCF *scf, double y[/*1+n0*/], double a, const double + x[/*1+nn*/]); +/* compute product y := y + alpha * R'* x */ + +#define scf_s_prod _glp_scf_s_prod +void scf_s_prod(SCF *scf, double y[/*1+n0*/], double a, const double + x[/*1+nn*/]); +/* compute product y := y + alpha * S * x */ + +#define scf_st_prod _glp_scf_st_prod +void scf_st_prod(SCF *scf, double y[/*1+nn*/], double a, const double + x[/*1+n0*/]); +/* compute product y := y + alpha * S'* x */ + +#define scf_a_solve _glp_scf_a_solve +void scf_a_solve(SCF *scf, double x[/*1+n*/], + double w[/*1+n0+nn*/], double work1[/*1+max(n0,nn)*/], + double work2[/*1+n*/], double work3[/*1+n*/]); +/* solve system A * x = b */ + +#define scf_at_solve _glp_scf_at_solve +void scf_at_solve(SCF *scf, double x[/*1+n*/], + double w[/*1+n0+nn*/], double work1[/*1+max(n0,nn)*/], + double work2[/*1+n*/], double work3[/*1+n*/]); +/* solve system A'* x = b */ + +#define scf_add_r_row _glp_scf_add_r_row +void scf_add_r_row(SCF *scf, const double w[/*1+n0*/]); +/* add new row to matrix R */ + +#define scf_add_s_col _glp_scf_add_s_col +void scf_add_s_col(SCF *scf, const double v[/*1+n0*/]); +/* add new column to matrix S */ + +#define scf_update_aug _glp_scf_update_aug +int scf_update_aug(SCF *scf, double b[/*1+n0*/], double d[/*1+n0*/], + double f[/*1+nn*/], double g[/*1+nn*/], double h, int upd, + double w1[/*1+n0*/], double w2[/*1+n0*/], double w3[/*1+n0*/]); +/* update factorization of augmented matrix */ + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.57/src/bflib/scfint.c b/resources/3rdparty/glpk-4.57/src/bflib/scfint.c new file mode 100644 index 000000000..06aa8f7d4 --- /dev/null +++ b/resources/3rdparty/glpk-4.57/src/bflib/scfint.c @@ -0,0 +1,255 @@ +/* scfint.c (interface to Schur-complement-based factorization) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2013-2014 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "scfint.h" + +SCFINT *scfint_create(int type) +{ /* create interface to SC-factorization */ + SCFINT *fi; + fi = talloc(1, SCFINT); + memset(fi, 0, sizeof(SCFINT)); + switch ((fi->scf.type = type)) + { case 1: + fi->u.lufi = lufint_create(); + break; + case 2: + fi->u.btfi = btfint_create(); + break; + default: + xassert(type != type); + } + return fi; +} + +int scfint_factorize(SCFINT *fi, int n, int (*col)(void *info, int j, + int ind[], double val[]), void *info) +{ /* compute SC-factorization of specified matrix A */ + int nn_max, old_n0_max, n0_max, k, ret; + xassert(n > 0); + fi->valid = 0; + /* get required value of nn_max */ + nn_max = fi->nn_max; + if (nn_max == 0) + nn_max = 100; + xassert(nn_max > 0); + /* compute factorization of specified matrix A */ + switch (fi->scf.type) + { case 1: + old_n0_max = fi->u.lufi->n_max; + fi->u.lufi->sva_n_max = 4 * n + 2 * nn_max; + ret = lufint_factorize(fi->u.lufi, n, col, info); + n0_max = fi->u.lufi->n_max; + fi->scf.sva = fi->u.lufi->sva; + fi->scf.a0.luf = fi->u.lufi->luf; + break; + case 2: + old_n0_max = fi->u.btfi->n_max; + fi->u.btfi->sva_n_max = 6 * n + 2 * nn_max; + ret = btfint_factorize(fi->u.btfi, n, col, info); + n0_max = fi->u.btfi->n_max; + fi->scf.sva = fi->u.btfi->sva; + fi->scf.a0.btf = fi->u.btfi->btf; + break; + default: + xassert(fi != fi); + } + /* allocate/reallocate arrays, if necessary */ + if (old_n0_max < n0_max) + { if (fi->w1 != NULL) + tfree(fi->w1); + if (fi->w2 != NULL) + tfree(fi->w2); + if (fi->w3 != NULL) + tfree(fi->w3); + fi->w1 = talloc(1+n0_max, double); + fi->w2 = talloc(1+n0_max, double); + fi->w3 = talloc(1+n0_max, double); + } + if (fi->scf.nn_max != nn_max) + { if (fi->scf.ifu.f != NULL) + tfree(fi->scf.ifu.f); + if (fi->scf.ifu.u != NULL) + tfree(fi->scf.ifu.u); + fi->scf.ifu.f = talloc(nn_max * nn_max, double); + fi->scf.ifu.u = talloc(nn_max * nn_max, double); + } + if (old_n0_max < n0_max || fi->scf.nn_max != nn_max) + { if (fi->scf.pp_ind != NULL) + tfree(fi->scf.pp_ind); + if (fi->scf.pp_inv != NULL) + tfree(fi->scf.pp_inv); + if (fi->scf.qq_ind != NULL) + tfree(fi->scf.qq_ind); + if (fi->scf.qq_inv != NULL) + tfree(fi->scf.qq_inv); + if (fi->w4 != NULL) + tfree(fi->w4); + if (fi->w5 != NULL) + tfree(fi->w5); + fi->scf.pp_ind = talloc(1+n0_max+nn_max, int); + fi->scf.pp_inv = talloc(1+n0_max+nn_max, int); + fi->scf.qq_ind = talloc(1+n0_max+nn_max, int); + fi->scf.qq_inv = talloc(1+n0_max+nn_max, int); + fi->w4 = talloc(1+n0_max+nn_max, double); + fi->w5 = talloc(1+n0_max+nn_max, double); + } + /* initialize SC-factorization */ + fi->scf.n = n; + fi->scf.n0 = n; + fi->scf.nn_max = nn_max; + fi->scf.nn = 0; + fi->scf.rr_ref = sva_alloc_vecs(fi->scf.sva, nn_max); + fi->scf.ss_ref = sva_alloc_vecs(fi->scf.sva, nn_max); + fi->scf.ifu.n_max = nn_max; + fi->scf.ifu.n = 0; + for (k = 1; k <= n; k++) + { fi->scf.pp_ind[k] = k; + fi->scf.pp_inv[k] = k; + fi->scf.qq_ind[k] = k; + fi->scf.qq_inv[k] = k; + } + /* set validation flag */ + if (ret == 0) + fi->valid = 1; + return ret; +} + +int scfint_update(SCFINT *fi, int upd, int j, int len, const int ind[], + const double val[]) +{ /* update SC-factorization after replacing j-th column of A */ + int n = fi->scf.n; + int n0 = fi->scf.n0; + int nn = fi->scf.nn; + int *pp_ind = fi->scf.pp_ind; + int *qq_ind = fi->scf.qq_ind; + int *qq_inv = fi->scf.qq_inv; + double *bf = fi->w4; + double *dg = fi->w5; + int k, t, ret; + xassert(fi->valid); + xassert(0 <= n && n <= n0+nn); + /* (b, f) := inv(P) * (beta, 0) */ + for (k = 1; k <= n0+nn; k++) + bf[k] = 0.0; + for (t = 1; t <= len; t++) + { k = ind[t]; + xassert(1 <= k && k <= n); +#if 1 /* FIXME: currently P = I */ + xassert(pp_ind[k] == k); +#endif + xassert(bf[k] == 0.0); + xassert(val[t] != 0.0); + bf[k] = val[t]; + } + /* (d, g) := Q * (cj, 0) */ + for (k = 1; k <= n0+nn; k++) + dg[k] = 0.0; + xassert(1 <= j && j <= n); + dg[fi->scf.qq_inv[j]] = 1; + /* update factorization of augmented matrix */ + ret = scf_update_aug(&fi->scf, &bf[0], &dg[0], &bf[n0], &dg[n0], + 0.0, upd, fi->w1, fi->w2, fi->w3); + if (ret == 0) + { /* swap j-th and last columns of new matrix Q */ + scf_swap_q_cols(j, n0+nn+1); + } + else + { /* updating failed */ + fi->valid = 0; + } + return ret; +} + +void scfint_ftran(SCFINT *fi, double x[]) +{ /* solve system A * x = b */ + xassert(fi->valid); + scf_a_solve(&fi->scf, x, fi->w4, fi->w5, fi->w1, fi->w2); + return; +} + +void scfint_btran(SCFINT *fi, double x[]) +{ /* solve system A'* x = b */ + xassert(fi->valid); + scf_at_solve(&fi->scf, x, fi->w4, fi->w5, fi->w1, fi->w2); + return; +} + +double scfint_estimate(SCFINT *fi) +{ /* estimate 1-norm of inv(A) */ + double norm; + xassert(fi->valid); + xassert(fi->scf.n == fi->scf.n0); + switch (fi->scf.type) + { case 1: + norm = luf_estimate_norm(fi->scf.a0.luf, fi->w1, fi->w2); + break; + case 2: + norm = btf_estimate_norm(fi->scf.a0.btf, fi->w1, fi->w2, + fi->w3, fi->w4); + break; + default: + xassert(fi != fi); + } + return norm; +} + +void scfint_delete(SCFINT *fi) +{ /* delete interface to SC-factorization */ + switch (fi->scf.type) + { case 1: + lufint_delete(fi->u.lufi); + break; + case 2: + btfint_delete(fi->u.btfi); + break; + default: + xassert(fi != fi); + } + if (fi->scf.ifu.f != NULL) + tfree(fi->scf.ifu.f); + if (fi->scf.ifu.u != NULL) + tfree(fi->scf.ifu.u); + if (fi->scf.pp_ind != NULL) + tfree(fi->scf.pp_ind); + if (fi->scf.pp_inv != NULL) + tfree(fi->scf.pp_inv); + if (fi->scf.qq_ind != NULL) + tfree(fi->scf.qq_ind); + if (fi->scf.qq_inv != NULL) + tfree(fi->scf.qq_inv); + if (fi->w1 != NULL) + tfree(fi->w1); + if (fi->w2 != NULL) + tfree(fi->w2); + if (fi->w3 != NULL) + tfree(fi->w3); + if (fi->w4 != NULL) + tfree(fi->w4); + if (fi->w5 != NULL) + tfree(fi->w5); + tfree(fi); + return; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.57/src/bflib/scfint.h b/resources/3rdparty/glpk-4.57/src/bflib/scfint.h new file mode 100644 index 000000000..3e56355ba --- /dev/null +++ b/resources/3rdparty/glpk-4.57/src/bflib/scfint.h @@ -0,0 +1,89 @@ +/* scfint.h (interface to Schur-complement-based factorization) */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2013-2014 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef SCFINT_H +#define SCFINT_H + +#include "scf.h" +#include "lufint.h" +#include "btfint.h" + +typedef struct SCFINT SCFINT; + +struct SCFINT +{ /* interface to SC-factorization */ + int valid; + /* factorization is valid only if this flag is set */ + SCF scf; + /* Schur-complement based factorization */ + union + { LUFINT *lufi; /* scf.type = 1 */ + BTFINT *btfi; /* scf.type = 2 */ + } u; + /* interface to factorize initial matrix A0 */ + /*--------------------------------------------------------------*/ + /* working arrays */ + double *w1; /* double w1[1+n0_max]; */ + double *w2; /* double w2[1+n0_max]; */ + double *w3; /* double w3[1+n0_max]; */ + double *w4; /* double w4[1+n0_max+nn_max]; */ + double *w5; /* double w5[1+n0_max+nn_max]; */ + /*--------------------------------------------------------------*/ + /* control parameters */ + int nn_max; + /* required maximal number of updates */ +}; + +#define scfint_create _glp_scfint_create +SCFINT *scfint_create(int type); +/* create interface to SC-factorization */ + +#define scfint_factorize _glp_scfint_factorize +int scfint_factorize(SCFINT *fi, int n, int (*col)(void *info, int j, + int ind[], double val[]), void *info); +/* compute SC-factorization of specified matrix A */ + +#define scfint_update _glp_scfint_update +int scfint_update(SCFINT *fi, int upd, int j, int len, const int ind[], + const double val[]); +/* update SC-factorization after replacing j-th column of A */ + +#define scfint_ftran _glp_scfint_ftran +void scfint_ftran(SCFINT *fi, double x[]); +/* solve system A * x = b */ + +#define scfint_btran _glp_scfint_btran +void scfint_btran(SCFINT *fi, double x[]); +/* solve system A'* x = b */ + +#define scfint_estimate _glp_scfint_estimate +double scfint_estimate(SCFINT *fi); +/* estimate 1-norm of inv(A) */ + +#define scfint_delete _glp_scfint_delete +void scfint_delete(SCFINT *fi); +/* delete interface to SC-factorization */ + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/bflib/sgf.c b/resources/3rdparty/glpk-4.57/src/bflib/sgf.c similarity index 98% rename from resources/3rdparty/glpk-4.53/src/bflib/sgf.c rename to resources/3rdparty/glpk-4.57/src/bflib/sgf.c index 462ac10ac..4000c8a55 100644 --- a/resources/3rdparty/glpk-4.53/src/bflib/sgf.c +++ b/resources/3rdparty/glpk-4.57/src/bflib/sgf.c @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2012-2015 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * @@ -91,6 +91,17 @@ void sgf_reduce_nuc(LUF *luf, int *k1_, int *k2_, int cnt[/*1+n*/], while (ns > 0) { /* column singleton is in j-th column of V */ j = list[ns--]; +#if 1 /* 25/IX-2015 */ + if (cnt[j] == 0) + { /* j-th column in the current nucleus is actually empty */ + /* this happened because on a previous step in the nucleus + * there were two or more identical column singletons (that + * means structural singularity), so removing one of them + * from the nucleus made other columns empty */ + /* do not remove empty column from the nucleus */ + continue; + } +#endif /* find i-th row of V containing column singleton */ ptr = vc_ptr[j]; end = ptr + vc_len[j]; @@ -138,6 +149,14 @@ void sgf_reduce_nuc(LUF *luf, int *k1_, int *k2_, int cnt[/*1+n*/], while (ns > 0) { /* row singleton is in i-th row of V */ i = list[ns--]; +#if 1 /* 25/IX-2015 */ + if (cnt[i] == 0) + { /* i-th row in the current nucleus is actually empty */ + /* (see comments above for similar case of empty column) */ + /* do not remove empty row from the nucleus */ + continue; + } +#endif /* find j-th column of V containing row singleton */ ptr = vr_ptr[i]; end = ptr + vr_len[i]; @@ -1351,7 +1370,11 @@ int sgf_factorize(SGF *sgf, int singl) double den; /* calculate density of active submatrix */ na = n - k + 1; /* order of active submatrix */ +#if 0 /* 21/VIII-2014 */ den = (double)nnz / (double)(na * na); +#else + den = (double)nnz / ((double)(na) * (double)(na)); +#endif /* if active submatrix is relatively dense, switch to dense * phase */ #if 1 /* FIXME */ diff --git a/resources/3rdparty/glpk-4.53/src/bflib/sgf.h b/resources/3rdparty/glpk-4.57/src/bflib/sgf.h similarity index 99% rename from resources/3rdparty/glpk-4.53/src/bflib/sgf.h rename to resources/3rdparty/glpk-4.57/src/bflib/sgf.h index dc64f957c..04d528cb7 100644 --- a/resources/3rdparty/glpk-4.53/src/bflib/sgf.h +++ b/resources/3rdparty/glpk-4.57/src/bflib/sgf.h @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2012-2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * diff --git a/resources/3rdparty/glpk-4.53/src/bflib/sva.c b/resources/3rdparty/glpk-4.57/src/bflib/sva.c similarity index 99% rename from resources/3rdparty/glpk-4.53/src/bflib/sva.c rename to resources/3rdparty/glpk-4.57/src/bflib/sva.c index 264f9e15f..e6a675ccb 100644 --- a/resources/3rdparty/glpk-4.53/src/bflib/sva.c +++ b/resources/3rdparty/glpk-4.57/src/bflib/sva.c @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2012-2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * @@ -501,7 +501,11 @@ void sva_check_area(SVA *sva) int *prev = sva->prev; int *next = sva->next; int k; +#if 0 /* 16/II-2004; SVA may be empty */ xassert(1 <= n && n <= n_max); +#else + xassert(0 <= n && n <= n_max); +#endif xassert(1 <= m_ptr && m_ptr <= r_ptr && r_ptr <= size+1); /* all vectors included the linked list should have non-zero * capacity and be stored in the left part */ diff --git a/resources/3rdparty/glpk-4.53/src/bflib/sva.h b/resources/3rdparty/glpk-4.57/src/bflib/sva.h similarity index 98% rename from resources/3rdparty/glpk-4.53/src/bflib/sva.h rename to resources/3rdparty/glpk-4.57/src/bflib/sva.h index ad3959ba5..0eab317b5 100644 --- a/resources/3rdparty/glpk-4.53/src/bflib/sva.h +++ b/resources/3rdparty/glpk-4.57/src/bflib/sva.h @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2012-2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * diff --git a/resources/3rdparty/glpk-4.53/src/bfx.c b/resources/3rdparty/glpk-4.57/src/bfx.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/bfx.c rename to resources/3rdparty/glpk-4.57/src/bfx.c diff --git a/resources/3rdparty/glpk-4.53/src/bfx.h b/resources/3rdparty/glpk-4.57/src/bfx.h similarity index 100% rename from resources/3rdparty/glpk-4.53/src/bfx.h rename to resources/3rdparty/glpk-4.57/src/bfx.h diff --git a/resources/3rdparty/glpk-4.53/src/cglib/cfg.c b/resources/3rdparty/glpk-4.57/src/cglib/cfg.c similarity index 99% rename from resources/3rdparty/glpk-4.53/src/cglib/cfg.c rename to resources/3rdparty/glpk-4.57/src/cglib/cfg.c index 92738b415..ab73b2da1 100644 --- a/resources/3rdparty/glpk-4.53/src/cglib/cfg.c +++ b/resources/3rdparty/glpk-4.57/src/cglib/cfg.c @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2012-2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * diff --git a/resources/3rdparty/glpk-4.53/src/cglib/cfg.h b/resources/3rdparty/glpk-4.57/src/cglib/cfg.h similarity index 98% rename from resources/3rdparty/glpk-4.53/src/cglib/cfg.h rename to resources/3rdparty/glpk-4.57/src/cglib/cfg.h index 87b61c738..bbf2454ca 100644 --- a/resources/3rdparty/glpk-4.53/src/cglib/cfg.h +++ b/resources/3rdparty/glpk-4.57/src/cglib/cfg.h @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2012-2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * diff --git a/resources/3rdparty/glpk-4.53/src/cglib/cfg1.c b/resources/3rdparty/glpk-4.57/src/cglib/cfg1.c similarity index 99% rename from resources/3rdparty/glpk-4.53/src/cglib/cfg1.c rename to resources/3rdparty/glpk-4.57/src/cglib/cfg1.c index 02317bffb..0dbfbeb06 100644 --- a/resources/3rdparty/glpk-4.53/src/cglib/cfg1.c +++ b/resources/3rdparty/glpk-4.57/src/cglib/cfg1.c @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2012-2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * diff --git a/resources/3rdparty/glpk-4.53/src/colamd/COPYING b/resources/3rdparty/glpk-4.57/src/colamd/COPYING similarity index 100% rename from resources/3rdparty/glpk-4.53/src/colamd/COPYING rename to resources/3rdparty/glpk-4.57/src/colamd/COPYING diff --git a/resources/3rdparty/glpk-4.53/src/colamd/README b/resources/3rdparty/glpk-4.57/src/colamd/README similarity index 100% rename from resources/3rdparty/glpk-4.53/src/colamd/README rename to resources/3rdparty/glpk-4.57/src/colamd/README diff --git a/resources/3rdparty/glpk-4.53/src/colamd/colamd.c b/resources/3rdparty/glpk-4.57/src/colamd/colamd.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/colamd/colamd.c rename to resources/3rdparty/glpk-4.57/src/colamd/colamd.c diff --git a/resources/3rdparty/glpk-4.53/src/colamd/colamd.h b/resources/3rdparty/glpk-4.57/src/colamd/colamd.h similarity index 100% rename from resources/3rdparty/glpk-4.53/src/colamd/colamd.h rename to resources/3rdparty/glpk-4.57/src/colamd/colamd.h diff --git a/resources/3rdparty/glpk-4.53/src/draft.h b/resources/3rdparty/glpk-4.57/src/draft.h similarity index 100% rename from resources/3rdparty/glpk-4.53/src/draft.h rename to resources/3rdparty/glpk-4.57/src/draft.h diff --git a/resources/3rdparty/glpk-4.53/src/env/alloc.c b/resources/3rdparty/glpk-4.57/src/env/alloc.c similarity index 99% rename from resources/3rdparty/glpk-4.53/src/env/alloc.c rename to resources/3rdparty/glpk-4.57/src/env/alloc.c index 5a9d5b766..8e2d613de 100644 --- a/resources/3rdparty/glpk-4.53/src/env/alloc.c +++ b/resources/3rdparty/glpk-4.57/src/env/alloc.c @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2000, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * diff --git a/resources/3rdparty/glpk-4.53/src/env/dlsup.c b/resources/3rdparty/glpk-4.57/src/env/dlsup.c similarity index 98% rename from resources/3rdparty/glpk-4.53/src/env/dlsup.c rename to resources/3rdparty/glpk-4.57/src/env/dlsup.c index 0987bd5cf..54c56c6dd 100644 --- a/resources/3rdparty/glpk-4.53/src/env/dlsup.c +++ b/resources/3rdparty/glpk-4.57/src/env/dlsup.c @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2008, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2008-2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * diff --git a/resources/3rdparty/glpk-4.53/src/env/env.c b/resources/3rdparty/glpk-4.57/src/env/env.c similarity index 99% rename from resources/3rdparty/glpk-4.53/src/env/env.c rename to resources/3rdparty/glpk-4.57/src/env/env.c index 56bd7540b..2cc67a3b9 100644 --- a/resources/3rdparty/glpk-4.53/src/env/env.c +++ b/resources/3rdparty/glpk-4.57/src/env/env.c @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2000, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * diff --git a/resources/3rdparty/glpk-4.53/src/env/env.h b/resources/3rdparty/glpk-4.57/src/env/env.h similarity index 97% rename from resources/3rdparty/glpk-4.53/src/env/env.h rename to resources/3rdparty/glpk-4.57/src/env/env.h index 2c013dce7..7d26a21ee 100644 --- a/resources/3rdparty/glpk-4.53/src/env/env.h +++ b/resources/3rdparty/glpk-4.57/src/env/env.h @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2000, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2000-2015 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * @@ -62,6 +62,10 @@ struct ENV /* output stream used to copy terminal output */ /*--------------------------------------------------------------*/ /* error handling */ +#if 1 /* 07/XI-2015 */ + int err_st; + /* error state flag; set on entry to glp_error */ +#endif const char *err_file; /* value of the __FILE__ macro passed to glp_error */ int err_line; diff --git a/resources/3rdparty/glpk-4.53/src/env/error.c b/resources/3rdparty/glpk-4.57/src/env/error.c similarity index 86% rename from resources/3rdparty/glpk-4.53/src/env/error.c rename to resources/3rdparty/glpk-4.57/src/env/error.c index 3dec72125..a898b7687 100644 --- a/resources/3rdparty/glpk-4.53/src/env/error.c +++ b/resources/3rdparty/glpk-4.57/src/env/error.c @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2000, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2000-2015 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * @@ -41,6 +41,9 @@ static void errfunc(const char *fmt, ...) { ENV *env = get_env_ptr(); va_list arg; +#if 1 /* 07/XI-2015 */ + env->err_st = 1; +#endif env->term_out = GLP_ON; va_start(arg, fmt); xvprintf(fmt, arg); @@ -61,6 +64,33 @@ glp_errfunc glp_error_(const char *file, int line) return errfunc; } +#if 1 /* 07/XI-2015 */ +/*********************************************************************** +* NAME +* +* glp_at_error - check for error state +* +* SYNOPSIS +* +* int glp_at_error(void); +* +* DESCRIPTION +* +* The routine glp_at_error checks if the GLPK environment is at error +* state, i.e. if the call to the routine is (indirectly) made from the +* glp_error routine via an user-defined hook routine. +* +* RETURNS +* +* If the GLPK environment is at error state, the routine glp_at_error +* returns non-zero, otherwise zero. */ + +int glp_at_error(void) +{ ENV *env = get_env_ptr(); + return env->err_st; +} +#endif + /*********************************************************************** * NAME * diff --git a/resources/3rdparty/glpk-4.53/src/env/stdc.h b/resources/3rdparty/glpk-4.57/src/env/stdc.h similarity index 94% rename from resources/3rdparty/glpk-4.53/src/env/stdc.h rename to resources/3rdparty/glpk-4.57/src/env/stdc.h index 2d0416370..9ffdcd942 100644 --- a/resources/3rdparty/glpk-4.53/src/env/stdc.h +++ b/resources/3rdparty/glpk-4.57/src/env/stdc.h @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2000, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * diff --git a/resources/3rdparty/glpk-4.53/src/env/stdout.c b/resources/3rdparty/glpk-4.57/src/env/stdout.c similarity index 99% rename from resources/3rdparty/glpk-4.53/src/env/stdout.c rename to resources/3rdparty/glpk-4.57/src/env/stdout.c index fc44e1218..94eee02a4 100644 --- a/resources/3rdparty/glpk-4.53/src/env/stdout.c +++ b/resources/3rdparty/glpk-4.57/src/env/stdout.c @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2000, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * diff --git a/resources/3rdparty/glpk-4.53/src/env/stream.c b/resources/3rdparty/glpk-4.57/src/env/stream.c similarity index 96% rename from resources/3rdparty/glpk-4.53/src/env/stream.c rename to resources/3rdparty/glpk-4.57/src/env/stream.c index d290c116e..8879616e2 100644 --- a/resources/3rdparty/glpk-4.53/src/env/stream.c +++ b/resources/3rdparty/glpk-4.57/src/env/stream.c @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2008, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2008-2014 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * @@ -77,8 +77,10 @@ struct glp_file * * "r" open text file for reading; * "w" truncate to zero length or create text file for writing; +* "a" append, open or create text file for writing at end-of-file; * "rb" open binary file for reading; -* "wb" truncate to zero length or create binary file for writing. +* "wb" truncate to zero length or create binary file for writing; +* "ab" append, open or create binary file for writing at end-of-file. * * RETURNS * @@ -93,6 +95,10 @@ glp_file *glp_open(const char *name, const char *mode) flag = 0; else if (strcmp(mode, "w") == 0 || strcmp(mode, "wb") == 0) flag = IOWRT; +#if 1 /* 08/V-2014 */ + else if (strcmp(mode, "a") == 0 || strcmp(mode, "ab") == 0) + flag = IOWRT; +#endif else xerror("glp_open: invalid mode string\n"); if (strcmp(name, "/dev/null") == 0) @@ -126,6 +132,10 @@ glp_file *glp_open(const char *name, const char *mode) mode = "rb"; else if (strcmp(mode, "w") == 0) mode = "wb"; +#if 1 /* 08/V-2014; this mode seems not to work */ + else if (strcmp(mode, "a") == 0) + mode = "ab"; +#endif file = gzopen(name, mode); if (file == NULL) { put_err_msg(strerror(errno)); diff --git a/resources/3rdparty/glpk-4.53/src/env/time.c b/resources/3rdparty/glpk-4.57/src/env/time.c similarity index 98% rename from resources/3rdparty/glpk-4.53/src/env/time.c rename to resources/3rdparty/glpk-4.57/src/env/time.c index 01956ce7f..e5aac0b0b 100644 --- a/resources/3rdparty/glpk-4.53/src/env/time.c +++ b/resources/3rdparty/glpk-4.57/src/env/time.c @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2000, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * diff --git a/resources/3rdparty/glpk-4.53/src/env/tls.c b/resources/3rdparty/glpk-4.57/src/env/tls.c similarity index 96% rename from resources/3rdparty/glpk-4.53/src/env/tls.c rename to resources/3rdparty/glpk-4.57/src/env/tls.c index b414e3b32..3ffa11437 100644 --- a/resources/3rdparty/glpk-4.53/src/env/tls.c +++ b/resources/3rdparty/glpk-4.57/src/env/tls.c @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2001, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2001-2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * diff --git a/resources/3rdparty/glpk-4.53/src/glpapi01.c b/resources/3rdparty/glpk-4.57/src/glpapi01.c similarity index 99% rename from resources/3rdparty/glpk-4.53/src/glpapi01.c rename to resources/3rdparty/glpk-4.57/src/glpapi01.c index a7010b4e3..376d98c47 100644 --- a/resources/3rdparty/glpk-4.53/src/glpapi01.c +++ b/resources/3rdparty/glpk-4.57/src/glpapi01.c @@ -58,11 +58,13 @@ static void create_prob(glp_prob *lp) { lp->magic = GLP_PROB_MAGIC; lp->pool = dmp_create_pool(); +#if 0 /* 08/III-2014 */ #if 0 /* 17/XI-2009 */ lp->cps = xmalloc(sizeof(struct LPXCPS)); lpx_reset_parms(lp); #else lp->parms = NULL; +#endif #endif lp->tree = NULL; #if 0 @@ -84,7 +86,9 @@ static void create_prob(glp_prob *lp) /* basis factorization */ lp->valid = 0; lp->head = xcalloc(1+lp->m_max, sizeof(int)); +#if 0 /* 08/III-2014 */ lp->bfcp = NULL; +#endif lp->bfd = NULL; /* basic solution (LP) */ lp->pbs_stat = lp->dbs_stat = GLP_UNDEF; @@ -1540,10 +1544,12 @@ void glp_erase_prob(glp_prob *lp) static void delete_prob(glp_prob *lp) { lp->magic = 0x3F3F3F3F; dmp_delete_pool(lp->pool); +#if 0 /* 08/III-2014 */ #if 0 /* 17/XI-2009 */ xfree(lp->cps); #else if (lp->parms != NULL) xfree(lp->parms); +#endif #endif xassert(lp->tree == NULL); #if 0 @@ -1554,7 +1560,9 @@ static void delete_prob(glp_prob *lp) if (lp->r_tree != NULL) avl_delete_tree(lp->r_tree); if (lp->c_tree != NULL) avl_delete_tree(lp->c_tree); xfree(lp->head); +#if 0 /* 08/III-2014 */ if (lp->bfcp != NULL) xfree(lp->bfcp); +#endif if (lp->bfd != NULL) bfd_delete_it(lp->bfd); return; } diff --git a/resources/3rdparty/glpk-4.53/src/glpapi02.c b/resources/3rdparty/glpk-4.57/src/glpapi02.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glpapi02.c rename to resources/3rdparty/glpk-4.57/src/glpapi02.c diff --git a/resources/3rdparty/glpk-4.53/src/glpapi03.c b/resources/3rdparty/glpk-4.57/src/glpapi03.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glpapi03.c rename to resources/3rdparty/glpk-4.57/src/glpapi03.c diff --git a/resources/3rdparty/glpk-4.53/src/glpapi04.c b/resources/3rdparty/glpk-4.57/src/glpapi04.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glpapi04.c rename to resources/3rdparty/glpk-4.57/src/glpapi04.c diff --git a/resources/3rdparty/glpk-4.53/src/glpapi05.c b/resources/3rdparty/glpk-4.57/src/glpapi05.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glpapi05.c rename to resources/3rdparty/glpk-4.57/src/glpapi05.c diff --git a/resources/3rdparty/glpk-4.53/src/glpapi06.c b/resources/3rdparty/glpk-4.57/src/glpapi06.c similarity index 99% rename from resources/3rdparty/glpk-4.53/src/glpapi06.c rename to resources/3rdparty/glpk-4.57/src/glpapi06.c index 53a2f9340..715e1954e 100644 --- a/resources/3rdparty/glpk-4.53/src/glpapi06.c +++ b/resources/3rdparty/glpk-4.57/src/glpapi06.c @@ -25,7 +25,12 @@ #include "env.h" #include "glpios.h" #include "glpnpp.h" +#if 0 /* 07/XI-2015 */ #include "glpspx.h" +#else +#include "simplex.h" +#define spx_dual spy_dual +#endif /*********************************************************************** * NAME @@ -481,7 +486,11 @@ void glp_init_smcp(glp_smcp *parm) parm->r_test = GLP_RT_HAR; parm->tol_bnd = 1e-7; parm->tol_dj = 1e-7; +#if 0 /* 07/XI-2015 */ parm->tol_piv = 1e-10; +#else + parm->tol_piv = 1e-9; +#endif parm->obj_ll = -DBL_MAX; parm->obj_ul = +DBL_MAX; parm->it_lim = INT_MAX; @@ -812,7 +821,7 @@ int glp_get_it_cnt(glp_prob *P) #endif #if 1 /* 08/VIII-2013 */ -int glp_set_it_cnt(glp_prob *P, int it_cnt) +void glp_set_it_cnt(glp_prob *P, int it_cnt) { /* set simplex solver iteration count */ P->it_cnt = it_cnt; return; diff --git a/resources/3rdparty/glpk-4.53/src/glpapi07.c b/resources/3rdparty/glpk-4.57/src/glpapi07.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glpapi07.c rename to resources/3rdparty/glpk-4.57/src/glpapi07.c diff --git a/resources/3rdparty/glpk-4.53/src/glpapi08.c b/resources/3rdparty/glpk-4.57/src/glpapi08.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glpapi08.c rename to resources/3rdparty/glpk-4.57/src/glpapi08.c diff --git a/resources/3rdparty/glpk-4.53/src/glpapi09.c b/resources/3rdparty/glpk-4.57/src/glpapi09.c similarity index 99% rename from resources/3rdparty/glpk-4.53/src/glpapi09.c rename to resources/3rdparty/glpk-4.57/src/glpapi09.c index a24f3fdb6..a864e9b18 100644 --- a/resources/3rdparty/glpk-4.53/src/glpapi09.c +++ b/resources/3rdparty/glpk-4.57/src/glpapi09.c @@ -626,6 +626,10 @@ int glp_intopt(glp_prob *P, const glp_iocp *parm) #endif else ret = preprocess_and_solve_mip(P, parm); +#if 1 /* 12/III-2013 */ + if (ret == GLP_ENOPFS) + P->mip_stat = GLP_NOFEAS; +#endif done: /* return to the application program */ return ret; } @@ -668,17 +672,12 @@ void glp_init_iocp(glp_iocp *parm) parm->presolve = GLP_OFF; parm->binarize = GLP_OFF; parm->fp_heur = GLP_OFF; -#if 1 /* 25/V-2013 */ parm->ps_heur = GLP_OFF; -#endif -#if 1 /* 29/VI-2013 */ parm->ps_tm_lim = 60000; /* 1 minute */ -#endif -#if 1 /* 11/VII-2013 */ + parm->sr_heur = GLP_ON; +#if 1 /* 24/X-2015; not documented--should not be used */ parm->use_sol = GLP_OFF; parm->save_sol = NULL; -#endif -#if 1 /* 28/V-2010 */ parm->alien = GLP_OFF; #endif return; diff --git a/resources/3rdparty/glpk-4.53/src/glpapi10.c b/resources/3rdparty/glpk-4.57/src/glpapi10.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glpapi10.c rename to resources/3rdparty/glpk-4.57/src/glpapi10.c diff --git a/resources/3rdparty/glpk-4.53/src/glpapi11.c b/resources/3rdparty/glpk-4.57/src/glpapi11.c similarity index 96% rename from resources/3rdparty/glpk-4.53/src/glpapi11.c rename to resources/3rdparty/glpk-4.57/src/glpapi11.c index 29876da23..7bc528172 100644 --- a/resources/3rdparty/glpk-4.53/src/glpapi11.c +++ b/resources/3rdparty/glpk-4.57/src/glpapi11.c @@ -35,10 +35,10 @@ int glp_print_sol(glp_prob *P, const char *fname) GLPCOL *col; int i, j, t, ae_ind, re_ind, ret; double ae_max, re_max; - xprintf("Writing basic solution to `%s'...\n", fname); + xprintf("Writing basic solution to '%s'...\n", fname); fp = glp_open(fname, "w"); if (fp == NULL) - { xprintf("Unable to create `%s' - %s\n", fname, get_err_msg()); + { xprintf("Unable to create '%s' - %s\n", fname, get_err_msg()); ret = 1; goto done; } @@ -192,7 +192,7 @@ int glp_print_sol(glp_prob *P, const char *fname) xfflush(fp); #endif if (glp_ioerr(fp)) - { xprintf("Write error on `%s' - %s\n", fname, get_err_msg()); + { xprintf("Write error on '%s' - %s\n", fname, get_err_msg()); ret = 1; goto done; } @@ -225,7 +225,7 @@ int glp_read_sol(glp_prob *lp, const char *fname) { glp_data *data; jmp_buf jump; int i, j, k, ret = 0; - xprintf("Reading basic solution from `%s'...\n", fname); + xprintf("Reading basic solution from '%s'...\n", fname); data = glp_sdf_open_file(fname); if (data == NULL) { ret = 1; @@ -338,10 +338,10 @@ done: if (ret) lp->pbs_stat = lp->dbs_stat = GLP_UNDEF; int glp_write_sol(glp_prob *lp, const char *fname) { glp_file *fp; int i, j, ret = 0; - xprintf("Writing basic solution to `%s'...\n", fname); + xprintf("Writing basic solution to '%s'...\n", fname); fp = glp_open(fname, "w"); if (fp == NULL) - { xprintf("Unable to create `%s' - %s\n", fname, get_err_msg()); + { xprintf("Unable to create '%s' - %s\n", fname, get_err_msg()); ret = 1; goto done; } @@ -368,7 +368,7 @@ int glp_write_sol(glp_prob *lp, const char *fname) xfflush(fp); #endif if (glp_ioerr(fp)) - { xprintf("Write error on `%s' - %s\n", fname, get_err_msg()); + { xprintf("Write error on '%s' - %s\n", fname, get_err_msg()); ret = 1; goto done; } @@ -450,10 +450,10 @@ int glp_print_ranges(glp_prob *P, int len, const int list[], goto done; } /* start reporting */ - xprintf("Write sensitivity analysis report to `%s'...\n", fname); + xprintf("Write sensitivity analysis report to '%s'...\n", fname); fp = glp_open(fname, "w"); if (fp == NULL) - { xprintf("Unable to create `%s' - %s\n", fname, get_err_msg()); + { xprintf("Unable to create '%s' - %s\n", fname, get_err_msg()); ret = 3; goto done; } @@ -641,7 +641,7 @@ int glp_print_ranges(glp_prob *P, int len, const int list[], xfflush(fp); #endif if (glp_ioerr(fp)) - { xprintf("Write error on `%s' - %s\n", fname, get_err_msg()); + { xprintf("Write error on '%s' - %s\n", fname, get_err_msg()); ret = 4; goto done; } @@ -659,10 +659,10 @@ int glp_print_ipt(glp_prob *P, const char *fname) GLPCOL *col; int i, j, t, ae_ind, re_ind, ret; double ae_max, re_max; - xprintf("Writing interior-point solution to `%s'...\n", fname); + xprintf("Writing interior-point solution to '%s'...\n", fname); fp = glp_open(fname, "w"); if (fp == NULL) - { xprintf("Unable to create `%s' - %s\n", fname, get_err_msg()); + { xprintf("Unable to create '%s' - %s\n", fname, get_err_msg()); ret = 1; goto done; } @@ -800,7 +800,7 @@ int glp_print_ipt(glp_prob *P, const char *fname) xfflush(fp); #endif if (glp_ioerr(fp)) - { xprintf("Write error on `%s' - %s\n", fname, get_err_msg()); + { xprintf("Write error on '%s' - %s\n", fname, get_err_msg()); ret = 1; goto done; } @@ -834,7 +834,7 @@ int glp_read_ipt(glp_prob *lp, const char *fname) { glp_data *data; jmp_buf jump; int i, j, k, ret = 0; - xprintf("Reading interior-point solution from `%s'...\n", fname); + xprintf("Reading interior-point solution from '%s'...\n", fname); data = glp_sdf_open_file(fname); if (data == NULL) { ret = 1; @@ -924,10 +924,10 @@ done: if (ret) lp->ipt_stat = GLP_UNDEF; int glp_write_ipt(glp_prob *lp, const char *fname) { glp_file *fp; int i, j, ret = 0; - xprintf("Writing interior-point solution to `%s'...\n", fname); + xprintf("Writing interior-point solution to '%s'...\n", fname); fp = glp_open(fname, "w"); if (fp == NULL) - { xprintf("Unable to create `%s' - %s\n", fname, get_err_msg()); + { xprintf("Unable to create '%s' - %s\n", fname, get_err_msg()); ret = 1; goto done; } @@ -953,7 +953,7 @@ int glp_write_ipt(glp_prob *lp, const char *fname) xfflush(fp); #endif if (glp_ioerr(fp)) - { xprintf("Write error on `%s' - %s\n", fname, get_err_msg()); + { xprintf("Write error on '%s' - %s\n", fname, get_err_msg()); ret = 1; goto done; } @@ -971,10 +971,10 @@ int glp_print_mip(glp_prob *P, const char *fname) GLPCOL *col; int i, j, t, ae_ind, re_ind, ret; double ae_max, re_max; - xprintf("Writing MIP solution to `%s'...\n", fname); + xprintf("Writing MIP solution to '%s'...\n", fname); fp = glp_open(fname, "w"); if (fp == NULL) - { xprintf("Unable to create `%s' - %s\n", fname, get_err_msg()); + { xprintf("Unable to create '%s' - %s\n", fname, get_err_msg()); ret = 1; goto done; } @@ -1081,7 +1081,7 @@ int glp_print_mip(glp_prob *P, const char *fname) xfflush(fp); #endif if (glp_ioerr(fp)) - { xprintf("Write error on `%s' - %s\n", fname, get_err_msg()); + { xprintf("Write error on '%s' - %s\n", fname, get_err_msg()); ret = 1; goto done; } @@ -1114,7 +1114,7 @@ int glp_read_mip(glp_prob *mip, const char *fname) { glp_data *data; jmp_buf jump; int i, j, k, ret = 0; - xprintf("Reading MIP solution from `%s'...\n", fname); + xprintf("Reading MIP solution from '%s'...\n", fname); data = glp_sdf_open_file(fname); if (data == NULL) { ret = 1; @@ -1202,10 +1202,10 @@ done: if (ret) mip->mip_stat = GLP_UNDEF; int glp_write_mip(glp_prob *mip, const char *fname) { glp_file *fp; int i, j, ret = 0; - xprintf("Writing MIP solution to `%s'...\n", fname); + xprintf("Writing MIP solution to '%s'...\n", fname); fp = glp_open(fname, "w"); if (fp == NULL) - { xprintf("Unable to create `%s' - %s\n", fname, get_err_msg()); + { xprintf("Unable to create '%s' - %s\n", fname, get_err_msg()); ret = 1; goto done; } @@ -1223,7 +1223,7 @@ int glp_write_mip(glp_prob *mip, const char *fname) xfflush(fp); #endif if (glp_ioerr(fp)) - { xprintf("Write error on `%s' - %s\n", fname, get_err_msg()); + { xprintf("Write error on '%s' - %s\n", fname, get_err_msg()); ret = 1; goto done; } diff --git a/resources/3rdparty/glpk-4.53/src/glpapi12.c b/resources/3rdparty/glpk-4.57/src/glpapi12.c similarity index 96% rename from resources/3rdparty/glpk-4.53/src/glpapi12.c rename to resources/3rdparty/glpk-4.57/src/glpapi12.c index 8c2ff9073..120953048 100644 --- a/resources/3rdparty/glpk-4.53/src/glpapi12.c +++ b/resources/3rdparty/glpk-4.57/src/glpapi12.c @@ -106,8 +106,6 @@ static int b_col(void *info, int j, int ind[], double val[]) return len; } -static void copy_bfcp(glp_prob *lp); - int glp_factorize(glp_prob *lp) { int m = lp->m; int n = lp->n; @@ -151,9 +149,11 @@ int glp_factorize(glp_prob *lp) if (m > 0) { if (lp->bfd == NULL) { lp->bfd = bfd_create_it(); +#if 0 /* 08/III-2014 */ copy_bfcp(lp); +#endif } - switch (bfd_factorize(lp->bfd, m, lp->head, b_col, lp)) + switch (bfd_factorize(lp->bfd, m, /*lp->head,*/ b_col, lp)) { case 0: /* ok */ break; @@ -221,25 +221,14 @@ int glp_bf_updated(glp_prob *lp) * Current values of control parameters are stored by the routine in * a glp_bfcp structure, which the parameter parm points to. */ -void glp_get_bfcp(glp_prob *lp, glp_bfcp *parm) -{ glp_bfcp *bfcp = lp->bfcp; - if (bfcp == NULL) - { parm->type = GLP_BF_FT; - parm->lu_size = 0; - parm->piv_tol = 0.10; - parm->piv_lim = 4; - parm->suhl = GLP_ON; - parm->eps_tol = 1e-15; - parm->max_gro = 1e+10; - parm->nfs_max = 100; - parm->upd_tol = 1e-6; - parm->nrs_max = 100; - parm->rs_size = 0; - } - else - memcpy(parm, bfcp, sizeof(glp_bfcp)); +#if 1 /* 08/III-2014 */ +void glp_get_bfcp(glp_prob *P, glp_bfcp *parm) +{ if (P->bfd == NULL) + P->bfd = bfd_create_it(); + bfd_get_bfcp(P->bfd, parm); return; } +#endif /*********************************************************************** * NAME @@ -262,86 +251,41 @@ void glp_get_bfcp(glp_prob *lp, glp_bfcp *parm) * The parameter parm can be specified as NULL, in which case all * control parameters are reset to their default values. */ -#if 0 /* 15/XI-2009 */ -static void copy_bfcp(glp_prob *lp) -{ glp_bfcp _parm, *parm = &_parm; - BFD *bfd = lp->bfd; - glp_get_bfcp(lp, parm); - xassert(bfd != NULL); - bfd->type = parm->type; - bfd->lu_size = parm->lu_size; - bfd->piv_tol = parm->piv_tol; - bfd->piv_lim = parm->piv_lim; - bfd->suhl = parm->suhl; - bfd->eps_tol = parm->eps_tol; - bfd->max_gro = parm->max_gro; - bfd->nfs_max = parm->nfs_max; - bfd->upd_tol = parm->upd_tol; - bfd->nrs_max = parm->nrs_max; - bfd->rs_size = parm->rs_size; - return; -} -#else -static void copy_bfcp(glp_prob *lp) -{ glp_bfcp _parm, *parm = &_parm; - glp_get_bfcp(lp, parm); - bfd_set_parm(lp->bfd, parm); - return; -} -#endif - -void glp_set_bfcp(glp_prob *lp, const glp_bfcp *parm) -{ glp_bfcp *bfcp = lp->bfcp; - if (parm == NULL) - { /* reset to default values */ - if (bfcp != NULL) - xfree(bfcp), lp->bfcp = NULL; - } - else - { /* set to specified values */ - if (bfcp == NULL) - bfcp = lp->bfcp = xmalloc(sizeof(glp_bfcp)); - memcpy(bfcp, parm, sizeof(glp_bfcp)); - if (!(bfcp->type == GLP_BF_FT || bfcp->type == GLP_BF_BG || - bfcp->type == GLP_BF_GR)) - xerror("glp_set_bfcp: type = %d; invalid parameter\n", - bfcp->type); - if (bfcp->lu_size < 0) - xerror("glp_set_bfcp: lu_size = %d; invalid parameter\n", - bfcp->lu_size); - if (!(0.0 < bfcp->piv_tol && bfcp->piv_tol < 1.0)) +#if 1 /* 08/III-2014 */ +void glp_set_bfcp(glp_prob *P, const glp_bfcp *parm) +{ if (P->bfd == NULL) + P->bfd = bfd_create_it(); + if (parm != NULL) + { if (!(parm->type == GLP_BF_LUF + GLP_BF_FT || + parm->type == GLP_BF_LUF + GLP_BF_BG || + parm->type == GLP_BF_LUF + GLP_BF_GR || + parm->type == GLP_BF_BTF + GLP_BF_BG || + parm->type == GLP_BF_BTF + GLP_BF_GR)) + xerror("glp_set_bfcp: type = 0x%02X; invalid parameter\n", + parm->type); + if (!(0.0 < parm->piv_tol && parm->piv_tol < 1.0)) xerror("glp_set_bfcp: piv_tol = %g; invalid parameter\n", - bfcp->piv_tol); - if (bfcp->piv_lim < 1) + parm->piv_tol); + if (parm->piv_lim < 1) xerror("glp_set_bfcp: piv_lim = %d; invalid parameter\n", - bfcp->piv_lim); - if (!(bfcp->suhl == GLP_ON || bfcp->suhl == GLP_OFF)) + parm->piv_lim); + if (!(parm->suhl == GLP_ON || parm->suhl == GLP_OFF)) xerror("glp_set_bfcp: suhl = %d; invalid parameter\n", - bfcp->suhl); - if (!(0.0 <= bfcp->eps_tol && bfcp->eps_tol <= 1e-6)) + parm->suhl); + if (!(0.0 <= parm->eps_tol && parm->eps_tol <= 1e-6)) xerror("glp_set_bfcp: eps_tol = %g; invalid parameter\n", - bfcp->eps_tol); - if (bfcp->max_gro < 1.0) - xerror("glp_set_bfcp: max_gro = %g; invalid parameter\n", - bfcp->max_gro); - if (!(1 <= bfcp->nfs_max && bfcp->nfs_max <= 32767)) + parm->eps_tol); + if (!(1 <= parm->nfs_max && parm->nfs_max <= 32767)) xerror("glp_set_bfcp: nfs_max = %d; invalid parameter\n", - bfcp->nfs_max); - if (!(0.0 < bfcp->upd_tol && bfcp->upd_tol < 1.0)) - xerror("glp_set_bfcp: upd_tol = %g; invalid parameter\n", - bfcp->upd_tol); - if (!(1 <= bfcp->nrs_max && bfcp->nrs_max <= 32767)) + parm->nfs_max); + if (!(1 <= parm->nrs_max && parm->nrs_max <= 32767)) xerror("glp_set_bfcp: nrs_max = %d; invalid parameter\n", - bfcp->nrs_max); - if (bfcp->rs_size < 0) - xerror("glp_set_bfcp: rs_size = %d; invalid parameter\n", - bfcp->nrs_max); - if (bfcp->rs_size == 0) - bfcp->rs_size = 20 * bfcp->nrs_max; + parm->nrs_max); } - if (lp->bfd != NULL) copy_bfcp(lp); + bfd_set_bfcp(P->bfd, parm); return; } +#endif /*********************************************************************** * NAME diff --git a/resources/3rdparty/glpk-4.53/src/glpapi13.c b/resources/3rdparty/glpk-4.57/src/glpapi13.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glpapi13.c rename to resources/3rdparty/glpk-4.57/src/glpapi13.c diff --git a/resources/3rdparty/glpk-4.53/src/glpapi14.c b/resources/3rdparty/glpk-4.57/src/glpapi14.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glpapi14.c rename to resources/3rdparty/glpk-4.57/src/glpapi14.c diff --git a/resources/3rdparty/glpk-4.53/src/glpapi15.c b/resources/3rdparty/glpk-4.57/src/glpapi15.c similarity index 98% rename from resources/3rdparty/glpk-4.53/src/glpapi15.c rename to resources/3rdparty/glpk-4.57/src/glpapi15.c index ecc6c32d3..be1248c57 100644 --- a/resources/3rdparty/glpk-4.53/src/glpapi15.c +++ b/resources/3rdparty/glpk-4.57/src/glpapi15.c @@ -526,7 +526,7 @@ int glp_read_graph(glp_graph *G, const char *fname) jmp_buf jump; int nv, na, i, j, k, ret; glp_erase_graph(G, G->v_size, G->a_size); - xprintf("Reading graph from `%s'...\n", fname); + xprintf("Reading graph from '%s'...\n", fname); data = glp_sdf_open_file(fname); if (data == NULL) { ret = 1; @@ -585,10 +585,10 @@ int glp_write_graph(glp_graph *G, const char *fname) glp_vertex *v; glp_arc *a; int i, count, ret; - xprintf("Writing graph to `%s'...\n", fname); + xprintf("Writing graph to '%s'...\n", fname); fp = glp_open(fname, "w"), count = 0; if (fp == NULL) - { xprintf("Unable to create `%s' - %s\n", fname, get_err_msg()); + { xprintf("Unable to create '%s' - %s\n", fname, get_err_msg()); ret = 1; goto done; } @@ -602,7 +602,7 @@ int glp_write_graph(glp_graph *G, const char *fname) xfflush(fp); #endif if (glp_ioerr(fp)) - { xprintf("Write error on `%s' - %s\n", fname, get_err_msg()); + { xprintf("Write error on '%s' - %s\n", fname, get_err_msg()); ret = 1; goto done; } diff --git a/resources/3rdparty/glpk-4.53/src/glpapi16.c b/resources/3rdparty/glpk-4.57/src/glpapi16.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glpapi16.c rename to resources/3rdparty/glpk-4.57/src/glpapi16.c diff --git a/resources/3rdparty/glpk-4.53/src/glpapi17.c b/resources/3rdparty/glpk-4.57/src/glpapi17.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glpapi17.c rename to resources/3rdparty/glpk-4.57/src/glpapi17.c diff --git a/resources/3rdparty/glpk-4.53/src/glpapi18.c b/resources/3rdparty/glpk-4.57/src/glpapi18.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glpapi18.c rename to resources/3rdparty/glpk-4.57/src/glpapi18.c diff --git a/resources/3rdparty/glpk-4.53/src/glpapi19.c b/resources/3rdparty/glpk-4.57/src/glpapi19.c similarity index 95% rename from resources/3rdparty/glpk-4.53/src/glpapi19.c rename to resources/3rdparty/glpk-4.57/src/glpapi19.c index 49fee3898..eda96a946 100644 --- a/resources/3rdparty/glpk-4.53/src/glpapi19.c +++ b/resources/3rdparty/glpk-4.57/src/glpapi19.c @@ -48,6 +48,14 @@ int glp_minisat1(glp_prob *P) ret = GLP_EDATA; goto done; } +#if 1 /* 07/XI-2015 */ + if (sizeof(void *) != sizeof(int)) + { xprintf("glp_minisat1: sorry, MiniSat solver is not supported " + "on 64-bit platforms\n"); + ret = GLP_EFAIL; + goto done; + } +#endif /* solve CNF-SAT problem */ xprintf("Solving CNF-SAT problem...\n"); xprintf("Instance has %d variable%s, %d clause%s, and %d literal%" diff --git a/resources/3rdparty/glpk-4.53/src/glpapi20.c b/resources/3rdparty/glpk-4.57/src/glpapi20.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glpapi20.c rename to resources/3rdparty/glpk-4.57/src/glpapi20.c diff --git a/resources/3rdparty/glpk-4.53/src/glpapi21.c b/resources/3rdparty/glpk-4.57/src/glpapi21.c similarity index 97% rename from resources/3rdparty/glpk-4.53/src/glpapi21.c rename to resources/3rdparty/glpk-4.57/src/glpapi21.c index 3b54a0dfb..30866310a 100644 --- a/resources/3rdparty/glpk-4.53/src/glpapi21.c +++ b/resources/3rdparty/glpk-4.57/src/glpapi21.c @@ -241,6 +241,7 @@ static void print_help(const char *my_name) ; xprintf("\n"); xprintf("LP basis factorization options:\n"); +#if 0 /* 08/III-2014 */ xprintf(" --luf LU + Forrest-Tomlin update\n"); xprintf(" (faster, less stable; default)\n"); xprintf(" --cbg LU + Schur complement + Bartels-Gol" @@ -249,6 +250,18 @@ static void print_help(const char *my_name) xprintf(" --cgr LU + Schur complement + Givens rota" "tion update\n"); xprintf(" (slower, more stable)\n"); +#else + xprintf(" --luf plain LU-factorization (default)\n") + ; + xprintf(" --btf block triangular LU-factorization\n" + ); + xprintf(" --ft Forrest-Tomlin update (requires --l" + "uf; default)\n"); + xprintf(" --cbg Schur complement + Bartels-Golub up" + "date\n"); + xprintf(" --cgr Schur complement + Givens rotation " + "update\n"); +#endif xprintf("\n"); xprintf("Options specific to simplex solver:\n"); xprintf(" --primal use primal simplex (default)\n"); @@ -362,10 +375,8 @@ static void print_version(int briefly) xprintf("GLPSOL: GLPK LP/MIP Solver, v%s\n", glp_version()); if (briefly) goto done; xprintf("\n"); - xprintf("Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, " - "2007, 2008,\n"); - xprintf("2009, 2010, 2011, 2013, 2014 Andrew Makhorin, Department" - " for Applied\n"); + xprintf("Copyright (C) 2000-2015 Andrew Makhorin, Department for " + "Applied\n"); xprintf("Informatics, Moscow Aviation Institute, Moscow, Russia. " "All rights\n"); xprintf("reserved. E-mail: .\n"); @@ -657,12 +668,35 @@ static int parse_cmdline(struct csa *csa, int argc, const char *argv[]) { print_version(0); return -1; } +#if 0 /* 08/III-2014 */ else if (p("--luf")) csa->bfcp.type = GLP_BF_FT; else if (p("--cbg")) csa->bfcp.type = GLP_BF_BG; else if (p("--cgr")) csa->bfcp.type = GLP_BF_GR; +#else + else if (p("--luf")) + { csa->bfcp.type &= 0x0F; + csa->bfcp.type |= GLP_BF_LUF; + } + else if (p("--btf")) + { csa->bfcp.type &= 0x0F; + csa->bfcp.type |= GLP_BF_BTF; + } + else if (p("--ft")) + { csa->bfcp.type &= 0xF0; + csa->bfcp.type |= GLP_BF_FT; + } + else if (p("--cbg")) + { csa->bfcp.type &= 0xF0; + csa->bfcp.type |= GLP_BF_BG; + } + else if (p("--cgr")) + { csa->bfcp.type &= 0xF0; + csa->bfcp.type |= GLP_BF_GR; + } +#endif else if (p("--primal")) csa->smcp.meth = GLP_PRIMAL; else if (p("--dual")) diff --git a/resources/3rdparty/glpk-4.53/src/glpcpx.c b/resources/3rdparty/glpk-4.57/src/glpcpx.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glpcpx.c rename to resources/3rdparty/glpk-4.57/src/glpcpx.c diff --git a/resources/3rdparty/glpk-4.53/src/glpdmx.c b/resources/3rdparty/glpk-4.57/src/glpdmx.c similarity index 95% rename from resources/3rdparty/glpk-4.53/src/glpdmx.c rename to resources/3rdparty/glpk-4.57/src/glpdmx.c index 329baaf69..e8a323da9 100644 --- a/resources/3rdparty/glpk-4.53/src/glpdmx.c +++ b/resources/3rdparty/glpk-4.57/src/glpdmx.c @@ -142,7 +142,7 @@ static void read_field(struct csa *csa) error(csa, "unexpected end of line"); while (!(csa->c == ' ' || csa->c == '\n')) { if (len == sizeof(csa->field)-1) - error(csa, "data field `%.15s...' too long", csa->field); + error(csa, "data field '%.15s...' too long", csa->field); csa->field[len++] = (char)csa->c; read_char(csa); } @@ -219,11 +219,11 @@ int glp_read_mincost(glp_graph *G, int v_rhs, int a_low, int a_cap, csa->c = '\n'; csa->field[0] = '\0'; csa->empty = csa->nonint = 0; - xprintf("Reading min-cost flow problem data from `%s'...\n", + xprintf("Reading min-cost flow problem data from '%s'...\n", fname); csa->fp = glp_open(fname, "r"); if (csa->fp == NULL) - { xprintf("Unable to open `%s' - %s\n", fname, get_err_msg()); + { xprintf("Unable to open '%s' - %s\n", fname, get_err_msg()); longjmp(csa->jump, 1); } /* read problem line */ @@ -232,7 +232,7 @@ int glp_read_mincost(glp_graph *G, int v_rhs, int a_low, int a_cap, error(csa, "problem line missing or invalid"); read_field(csa); if (strcmp(csa->field, "min") != 0) - error(csa, "wrong problem designator; `min' expected"); + error(csa, "wrong problem designator; 'min' expected"); read_field(csa); if (!(str2int(csa->field, &nv) == 0 && nv >= 0)) error(csa, "number of nodes missing or invalid"); @@ -279,7 +279,7 @@ int glp_read_mincost(glp_graph *G, int v_rhs, int a_low, int a_cap, for (k = 1; k <= na; k++) { if (k > 1) read_designator(csa); if (strcmp(csa->field, "a") != 0) - error(csa, "wrong line designator; `a' expected"); + error(csa, "wrong line designator; 'a' expected"); read_field(csa); if (str2int(csa->field, &i) != 0) error(csa, "starting node number missing or invalid"); @@ -357,11 +357,11 @@ int glp_write_mincost(glp_graph *G, int v_rhs, int a_low, int a_cap, if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double)) xerror("glp_write_mincost: a_cost = %d; invalid offset\n", a_cost); - xprintf("Writing min-cost flow problem data to `%s'...\n", + xprintf("Writing min-cost flow problem data to '%s'...\n", fname); fp = glp_open(fname, "w"); if (fp == NULL) - { xprintf("Unable to create `%s' - %s\n", fname, get_err_msg()); + { xprintf("Unable to create '%s' - %s\n", fname, get_err_msg()); ret = 1; goto done; } @@ -401,7 +401,7 @@ int glp_write_mincost(glp_graph *G, int v_rhs, int a_low, int a_cap, xfflush(fp); #endif if (glp_ioerr(fp)) - { xprintf("Write error on `%s' - %s\n", fname, get_err_msg()); + { xprintf("Write error on '%s' - %s\n", fname, get_err_msg()); ret = 1; goto done; } @@ -451,11 +451,11 @@ int glp_read_maxflow(glp_graph *G, int *_s, int *_t, int a_cap, csa->c = '\n'; csa->field[0] = '\0'; csa->empty = csa->nonint = 0; - xprintf("Reading maximum flow problem data from `%s'...\n", + xprintf("Reading maximum flow problem data from '%s'...\n", fname); csa->fp = glp_open(fname, "r"); if (csa->fp == NULL) - { xprintf("Unable to open `%s' - %s\n", fname, get_err_msg()); + { xprintf("Unable to open '%s' - %s\n", fname, get_err_msg()); longjmp(csa->jump, 1); } /* read problem line */ @@ -464,7 +464,7 @@ int glp_read_maxflow(glp_graph *G, int *_s, int *_t, int a_cap, error(csa, "problem line missing or invalid"); read_field(csa); if (strcmp(csa->field, "max") != 0) - error(csa, "wrong problem designator; `max' expected"); + error(csa, "wrong problem designator; 'max' expected"); read_field(csa); if (!(str2int(csa->field, &nv) == 0 && nv >= 2)) error(csa, "number of nodes missing or invalid"); @@ -497,7 +497,7 @@ int glp_read_maxflow(glp_graph *G, int *_s, int *_t, int a_cap, t = i; } else - error(csa, "wrong node designator; `s' or `t' expected"); + error(csa, "wrong node designator; 's' or 't' expected"); if (s > 0 && s == t) error(csa, "source and sink nodes must be distinct"); end_of_line(csa); @@ -512,7 +512,7 @@ int glp_read_maxflow(glp_graph *G, int *_s, int *_t, int a_cap, for (k = 1; k <= na; k++) { if (k > 1) read_designator(csa); if (strcmp(csa->field, "a") != 0) - error(csa, "wrong line designator; `a' expected"); + error(csa, "wrong line designator; 'a' expected"); read_field(csa); if (str2int(csa->field, &i) != 0) error(csa, "starting node number missing or invalid"); @@ -574,11 +574,11 @@ int glp_write_maxflow(glp_graph *G, int s, int t, int a_cap, if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double)) xerror("glp_write_mincost: a_cap = %d; invalid offset\n", a_cap); - xprintf("Writing maximum flow problem data to `%s'...\n", + xprintf("Writing maximum flow problem data to '%s'...\n", fname); fp = glp_open(fname, "w"); if (fp == NULL) - { xprintf("Unable to create `%s' - %s\n", fname, get_err_msg()); + { xprintf("Unable to create '%s' - %s\n", fname, get_err_msg()); ret = 1; goto done; } @@ -603,7 +603,7 @@ int glp_write_maxflow(glp_graph *G, int s, int t, int a_cap, xfflush(fp); #endif if (glp_ioerr(fp)) - { xprintf("Write error on `%s' - %s\n", fname, get_err_msg()); + { xprintf("Write error on '%s' - %s\n", fname, get_err_msg()); ret = 1; goto done; } @@ -658,10 +658,10 @@ int glp_read_asnprob(glp_graph *G, int v_set, int a_cost, const char csa->c = '\n'; csa->field[0] = '\0'; csa->empty = csa->nonint = 0; - xprintf("Reading assignment problem data from `%s'...\n", fname); + xprintf("Reading assignment problem data from '%s'...\n", fname); csa->fp = glp_open(fname, "r"); if (csa->fp == NULL) - { xprintf("Unable to open `%s' - %s\n", fname, get_err_msg()); + { xprintf("Unable to open '%s' - %s\n", fname, get_err_msg()); longjmp(csa->jump, 1); } /* read problem line */ @@ -670,7 +670,7 @@ int glp_read_asnprob(glp_graph *G, int v_set, int a_cost, const char error(csa, "problem line missing or invalid"); read_field(csa); if (strcmp(csa->field, "asn") != 0) - error(csa, "wrong problem designator; `asn' expected"); + error(csa, "wrong problem designator; 'asn' expected"); read_field(csa); if (!(str2int(csa->field, &nv) == 0 && nv >= 0)) error(csa, "number of nodes missing or invalid"); @@ -710,7 +710,7 @@ int glp_read_asnprob(glp_graph *G, int v_set, int a_cost, const char for (k = 1; k <= na; k++) { if (k > 1) read_designator(csa); if (strcmp(csa->field, "a") != 0) - error(csa, "wrong line designator; `a' expected"); + error(csa, "wrong line designator; 'a' expected"); read_field(csa); if (str2int(csa->field, &i) != 0) error(csa, "starting node number missing or invalid"); @@ -774,10 +774,10 @@ int glp_write_asnprob(glp_graph *G, int v_set, int a_cost, const char if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double)) xerror("glp_write_asnprob: a_cost = %d; invalid offset\n", a_cost); - xprintf("Writing assignment problem data to `%s'...\n", fname); + xprintf("Writing assignment problem data to '%s'...\n", fname); fp = glp_open(fname, "w"); if (fp == NULL) - { xprintf("Unable to create `%s' - %s\n", fname, get_err_msg()); + { xprintf("Unable to create '%s' - %s\n", fname, get_err_msg()); ret = 1; goto done; } @@ -809,7 +809,7 @@ int glp_write_asnprob(glp_graph *G, int v_set, int a_cost, const char xfflush(fp); #endif if (glp_ioerr(fp)) - { xprintf("Write error on `%s' - %s\n", fname, get_err_msg()); + { xprintf("Write error on '%s' - %s\n", fname, get_err_msg()); ret = 1; goto done; } @@ -858,10 +858,10 @@ int glp_read_ccdata(glp_graph *G, int v_wgt, const char *fname) csa->c = '\n'; csa->field[0] = '\0'; csa->empty = csa->nonint = 0; - xprintf("Reading graph from `%s'...\n", fname); + xprintf("Reading graph from '%s'...\n", fname); csa->fp = glp_open(fname, "r"); if (csa->fp == NULL) - { xprintf("Unable to open `%s' - %s\n", fname, get_err_msg()); + { xprintf("Unable to open '%s' - %s\n", fname, get_err_msg()); longjmp(csa->jump, 1); } /* read problem line */ @@ -870,7 +870,7 @@ int glp_read_ccdata(glp_graph *G, int v_wgt, const char *fname) error(csa, "problem line missing or invalid"); read_field(csa); if (strcmp(csa->field, "edge") != 0) - error(csa, "wrong problem designator; `edge' expected"); + error(csa, "wrong problem designator; 'edge' expected"); read_field(csa); if (!(str2int(csa->field, &nv) == 0 && nv >= 0)) error(csa, "number of vertices missing or invalid"); @@ -917,7 +917,7 @@ int glp_read_ccdata(glp_graph *G, int v_wgt, const char *fname) for (k = 1; k <= ne; k++) { if (k > 1) read_designator(csa); if (strcmp(csa->field, "e") != 0) - error(csa, "wrong line designator; `e' expected"); + error(csa, "wrong line designator; 'e' expected"); read_field(csa); if (str2int(csa->field, &i) != 0) error(csa, "first vertex number missing or invalid"); @@ -966,10 +966,10 @@ int glp_write_ccdata(glp_graph *G, int v_wgt, const char *fname) if (v_wgt >= 0 && v_wgt > G->v_size - (int)sizeof(double)) xerror("glp_write_ccdata: v_wgt = %d; invalid offset\n", v_wgt); - xprintf("Writing graph to `%s'\n", fname); + xprintf("Writing graph to '%s'\n", fname); fp = glp_open(fname, "w"); if (fp == NULL) - { xprintf("Unable to create `%s' - %s\n", fname, get_err_msg()); + { xprintf("Unable to create '%s' - %s\n", fname, get_err_msg()); ret = 1; goto done; } @@ -994,7 +994,7 @@ int glp_write_ccdata(glp_graph *G, int v_wgt, const char *fname) xfflush(fp); #endif if (glp_ioerr(fp)) - { xprintf("Write error on `%s' - %s\n", fname, get_err_msg()); + { xprintf("Write error on '%s' - %s\n", fname, get_err_msg()); ret = 1; goto done; } @@ -1047,10 +1047,10 @@ int glp_read_prob(glp_prob *P, int flags, const char *fname) csa->c = '\n'; csa->field[0] = '\0'; csa->empty = csa->nonint = 0; - xprintf("Reading problem data from `%s'...\n", fname); + xprintf("Reading problem data from '%s'...\n", fname); csa->fp = glp_open(fname, "r"); if (csa->fp == NULL) - { xprintf("Unable to open `%s' - %s\n", fname, get_err_msg()); + { xprintf("Unable to open '%s' - %s\n", fname, get_err_msg()); longjmp(csa->jump, 1); } /* read problem line */ @@ -1063,7 +1063,7 @@ int glp_read_prob(glp_prob *P, int flags, const char *fname) else if (strcmp(csa->field, "mip") == 0) mip = 1; else - error(csa, "wrong problem designator; `lp' or `mip' expected\n" + error(csa, "wrong problem designator; 'lp' or 'mip' expected\n" ); read_field(csa); if (strcmp(csa->field, "min") == 0) @@ -1375,10 +1375,10 @@ int glp_write_prob(glp_prob *P, int flags, const char *fname) if (fname == NULL) xerror("glp_write_prob: fname = %d; invalid parameter\n", fname); - xprintf("Writing problem data to `%s'...\n", fname); + xprintf("Writing problem data to '%s'...\n", fname); fp = glp_open(fname, "w"), count = 0; if (fp == NULL) - { xprintf("Unable to create `%s' - %s\n", fname, get_err_msg()); + { xprintf("Unable to create '%s' - %s\n", fname, get_err_msg()); ret = 1; goto done; } @@ -1468,7 +1468,7 @@ skip2: if (col->name != NULL) xfflush(fp); #endif if (glp_ioerr(fp)) - { xprintf("Write error on `%s' - %s\n", fname, get_err_msg()); + { xprintf("Write error on '%s' - %s\n", fname, get_err_msg()); ret = 1; goto done; } @@ -1503,10 +1503,10 @@ int glp_read_cnfsat(glp_prob *P, const char *fname) csa->c = '\n'; csa->field[0] = '\0'; csa->empty = csa->nonint = 0; - xprintf("Reading CNF-SAT problem data from `%s'...\n", fname); + xprintf("Reading CNF-SAT problem data from '%s'...\n", fname); csa->fp = glp_open(fname, "r"); if (csa->fp == NULL) - { xprintf("Unable to open `%s' - %s\n", fname, get_err_msg()); + { xprintf("Unable to open '%s' - %s\n", fname, get_err_msg()); longjmp(csa->jump, 1); } /* read problem line */ @@ -1515,7 +1515,7 @@ int glp_read_cnfsat(glp_prob *P, const char *fname) error(csa, "problem line missing or invalid"); read_field(csa); if (strcmp(csa->field, "cnf") != 0) - error(csa, "wrong problem designator; `cnf' expected\n"); + error(csa, "wrong problem designator; 'cnf' expected\n"); read_field(csa); if (!(str2int(csa->field, &n) == 0 && n >= 0)) error(csa, "number of variables missing or invalid\n"); @@ -1649,10 +1649,10 @@ int glp_write_cnfsat(glp_prob *P, const char *fname) ret = 1; goto done; } - xprintf("Writing CNF-SAT problem data to `%s'...\n", fname); + xprintf("Writing CNF-SAT problem data to '%s'...\n", fname); fp = glp_open(fname, "w"); if (fp == NULL) - { xprintf("Unable to create `%s' - %s\n", fname, get_err_msg()); + { xprintf("Unable to create '%s' - %s\n", fname, get_err_msg()); ret = 1; goto done; } @@ -1680,7 +1680,7 @@ int glp_write_cnfsat(glp_prob *P, const char *fname) xfflush(fp); #endif if (glp_ioerr(fp)) - { xprintf("Write error on `%s' - %s\n", fname, get_err_msg()); + { xprintf("Write error on '%s' - %s\n", fname, get_err_msg()); ret = 1; goto done; } diff --git a/resources/3rdparty/glpk-4.53/src/glpgmp.c b/resources/3rdparty/glpk-4.57/src/glpgmp.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glpgmp.c rename to resources/3rdparty/glpk-4.57/src/glpgmp.c diff --git a/resources/3rdparty/glpk-4.53/src/glpgmp.h b/resources/3rdparty/glpk-4.57/src/glpgmp.h similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glpgmp.h rename to resources/3rdparty/glpk-4.57/src/glpgmp.h diff --git a/resources/3rdparty/glpk-4.53/src/glphbm.c b/resources/3rdparty/glpk-4.57/src/glphbm.c similarity index 96% rename from resources/3rdparty/glpk-4.53/src/glphbm.c rename to resources/3rdparty/glpk-4.57/src/glphbm.c index 07f4107d9..100ece6e2 100644 --- a/resources/3rdparty/glpk-4.53/src/glphbm.c +++ b/resources/3rdparty/glpk-4.57/src/glphbm.c @@ -146,7 +146,7 @@ static int scan_int(struct dsa *dsa, char *fld, int pos, int width, xassert(1 <= width && width <= 80); memcpy(str, dsa->card + pos, width), str[width] = '\0'; if (str2int(strspx(str), val)) - { xprintf("%s:%d: field `%s' contains invalid value `%s'\n", + { xprintf("%s:%d: field '%s' contains invalid value '%s'\n", dsa->fname, dsa->seqn, fld, str); return 1; } @@ -167,7 +167,7 @@ static int parse_fmt(struct dsa *dsa, char *fmt) char str[80+1]; /* first character should be left parenthesis */ if (fmt[0] != '(') -fail: { xprintf("hbm_read_mat: format `%s' not recognised\n", fmt); +fail: { xprintf("hbm_read_mat: format '%s' not recognised\n", fmt); return 1; } k = 1; @@ -251,7 +251,7 @@ static int read_int_array(struct dsa *dsa, char *name, char *fmt, if (!(dsa->fmt_f == 'I' && dsa->fmt_w <= 80 && dsa->fmt_k * dsa->fmt_w <= 80)) { xprintf( - "%s:%d: can't read array `%s' - invalid format `%s'\n", + "%s:%d: can't read array '%s' - invalid format '%s'\n", dsa->fname, dsa->seqn, name, fmt); return 1; } @@ -265,7 +265,7 @@ static int read_int_array(struct dsa *dsa, char *name, char *fmt, strspx(str); if (str2int(str, &val[k])) { xprintf( - "%s:%d: can't read array `%s' - invalid value `%s'\n", + "%s:%d: can't read array '%s' - invalid value '%s'\n", dsa->fname, dsa->seqn, name, str); return 1; } @@ -290,7 +290,7 @@ static int read_real_array(struct dsa *dsa, char *name, char *fmt, if (!(dsa->fmt_f != 'I' && dsa->fmt_w <= 80 && dsa->fmt_k * dsa->fmt_w <= 80)) { xprintf( - "%s:%d: can't read array `%s' - invalid format `%s'\n", + "%s:%d: can't read array '%s' - invalid format '%s'\n", dsa->fname, dsa->seqn, name, fmt); return 1; } @@ -303,7 +303,7 @@ static int read_real_array(struct dsa *dsa, char *name, char *fmt, str[dsa->fmt_w] = '\0'; strspx(str); if (strchr(str, '.') == NULL && strcmp(str, "0")) - { xprintf("%s(%d): can't read array `%s' - value `%s' has no " + { xprintf("%s(%d): can't read array '%s' - value '%s' has no " "decimal point\n", dsa->fname, dsa->seqn, name, str); return 1; } @@ -324,7 +324,7 @@ static int read_real_array(struct dsa *dsa, char *name, char *fmt, } if (str2num(str, &val[k])) { xprintf( - "%s:%d: can't read array `%s' - invalid value `%s'\n", + "%s:%d: can't read array '%s' - invalid value '%s'\n", dsa->fname, dsa->seqn, name, str); return 1; } @@ -336,11 +336,11 @@ HBM *hbm_read_mat(const char *fname) { struct dsa _dsa, *dsa = &_dsa; HBM *hbm = NULL; dsa->fname = fname; - xprintf("hbm_read_mat: reading matrix from `%s'...\n", + xprintf("hbm_read_mat: reading matrix from '%s'...\n", dsa->fname); dsa->fp = fopen(dsa->fname, "r"); if (dsa->fp == NULL) - { xprintf("hbm_read_mat: unable to open `%s' - %s\n", + { xprintf("hbm_read_mat: unable to open '%s' - %s\n", dsa->fname, strerror(errno)); goto fail; } @@ -371,7 +371,7 @@ HBM *hbm_read_mat(const char *fname) if (strchr("RCP", hbm->mxtype[0]) == NULL || strchr("SUHZR", hbm->mxtype[1]) == NULL || strchr("AE", hbm->mxtype[2]) == NULL) - { xprintf("%s:%d: matrix type `%s' not recognised\n", + { xprintf("%s:%d: matrix type '%s' not recognised\n", dsa->fname, dsa->seqn, hbm->mxtype); goto fail; } @@ -405,7 +405,7 @@ HBM *hbm_read_mat(const char *fname) memcpy(hbm->rhstyp, dsa->card, 3), hbm->rhstyp[3] = '\0'; if (scan_int(dsa, "nrhs", 14, 14, &hbm->nrhs)) goto fail; if (scan_int(dsa, "nrhsix", 28, 14, &hbm->nrhsix)) goto fail; - xprintf("rhstyp = `%s'; nrhs = %d; nrhsix = %d\n", + xprintf("rhstyp = '%s'; nrhs = %d; nrhsix = %d\n", hbm->rhstyp, hbm->nrhs, hbm->nrhsix); } /* read matrix structure */ @@ -460,7 +460,7 @@ HBM *hbm_read_mat(const char *fname) hbm->rhsval)) goto fail; } else - { xprintf("%s:%d: right-hand side type `%c' not recognised\n", + { xprintf("%s:%d: right-hand side type '%c' not recognised\n", dsa->fname, dsa->seqn, hbm->rhstyp[0]); goto fail; } diff --git a/resources/3rdparty/glpk-4.53/src/glphbm.h b/resources/3rdparty/glpk-4.57/src/glphbm.h similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glphbm.h rename to resources/3rdparty/glpk-4.57/src/glphbm.h diff --git a/resources/3rdparty/glpk-4.53/src/glpini01.c b/resources/3rdparty/glpk-4.57/src/glpini01.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glpini01.c rename to resources/3rdparty/glpk-4.57/src/glpini01.c diff --git a/resources/3rdparty/glpk-4.53/src/glpini02.c b/resources/3rdparty/glpk-4.57/src/glpini02.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glpini02.c rename to resources/3rdparty/glpk-4.57/src/glpini02.c diff --git a/resources/3rdparty/glpk-4.53/src/glpios.h b/resources/3rdparty/glpk-4.57/src/glpios.h similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glpios.h rename to resources/3rdparty/glpk-4.57/src/glpios.h diff --git a/resources/3rdparty/glpk-4.53/src/glpios01.c b/resources/3rdparty/glpk-4.57/src/glpios01.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glpios01.c rename to resources/3rdparty/glpk-4.57/src/glpios01.c diff --git a/resources/3rdparty/glpk-4.53/src/glpios02.c b/resources/3rdparty/glpk-4.57/src/glpios02.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glpios02.c rename to resources/3rdparty/glpk-4.57/src/glpios02.c diff --git a/resources/3rdparty/glpk-4.53/src/glpios03.c b/resources/3rdparty/glpk-4.57/src/glpios03.c similarity index 95% rename from resources/3rdparty/glpk-4.53/src/glpios03.c rename to resources/3rdparty/glpk-4.57/src/glpios03.c index 3ee79ee04..29ea32e2c 100644 --- a/resources/3rdparty/glpk-4.53/src/glpios03.c +++ b/resources/3rdparty/glpk-4.57/src/glpios03.c @@ -561,80 +561,6 @@ static void cleanup_the_tree(glp_tree *T) return; } -#if 0 /* 09/VII-2013 */ -/*********************************************************************** -* round_heur - simple rounding heuristic -* -* This routine attempts to guess an integer feasible solution by -* simple rounding values of all integer variables in basic solution to -* nearest integers. */ - -static int round_heur(glp_tree *T) -{ glp_prob *P = T->mip; - int m = P->m; - int n = P->n; - int i, j, ret; - double *x; - /* compute rounded values of variables */ - x = talloc(1+n, double); - for (j = 1; j <= n; j++) - { GLPCOL *col = P->col[j]; - if (col->kind == GLP_IV) - { /* integer variable */ - x[j] = floor(col->prim + 0.5); - } - else if (col->type == GLP_FX) - { /* fixed variable */ - x[j] = col->prim; - } - else - { /* non-integer non-fixed variable */ - ret = 3; - goto done; - } - } - /* check that no constraints are violated */ - for (i = 1; i <= m; i++) - { GLPROW *row = P->row[i]; - int type = row->type; - GLPAIJ *aij; - double sum; - if (type == GLP_FR) - continue; - /* compute value of linear form */ - sum = 0.0; - for (aij = row->ptr; aij != NULL; aij = aij->r_next) - sum += aij->val * x[aij->col->j]; - /* check lower bound */ - if (type == GLP_LO || type == GLP_DB || type == GLP_FX) - { if (sum < row->lb - 1e-9) - { /* lower bound is violated */ - ret = 2; - goto done; - } - } - /* check upper bound */ - if (type == GLP_UP || type == GLP_DB || type == GLP_FX) - { if (sum > row->ub + 1e-9) - { /* upper bound is violated */ - ret = 2; - goto done; - } - } - } - /* rounded solution is integer feasible */ - if (glp_ios_heur_sol(T, x) == 0) - { /* solution is accepted */ - ret = 0; - } - else - { /* solution is rejected */ - ret = 1; - } -done: tfree(x); - return ret; -} -#else /*********************************************************************** * round_heur - simple rounding heuristic * @@ -706,7 +632,6 @@ static int round_heur(glp_tree *T) done: tfree(x); return ret; } -#endif #if 0 #define round_heur round_heur2 @@ -995,6 +920,14 @@ loop: /* main loop starts here */ #if 0 if (p == 1) glp_write_lp(T->mip, NULL, "root.lp"); +#endif +#if 1 /* 24/X-2015 */ + if (p == 1) + { if (T->parm->sr_heur == GLP_OFF) + { if (T->parm->msg_lev >= GLP_MSG_ALL) + xprintf("Simple rounding heuristic disabled\n"); + } + } #endif /* if it is the root subproblem, initialize cut generators */ if (p == 1) @@ -1289,8 +1222,9 @@ more: /* minor loop starts here */ } } #endif -#if 1 /* 09/VII-2013 */ +#if 1 /* 24/X-2015 */ /* try to find solution with a simple rounding heuristic */ + if (T->parm->sr_heur) { xassert(T->reason == 0); T->reason = GLP_IHEUR; round_heur(T); diff --git a/resources/3rdparty/glpk-4.53/src/glpios04.c b/resources/3rdparty/glpk-4.57/src/glpios04.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glpios04.c rename to resources/3rdparty/glpk-4.57/src/glpios04.c diff --git a/resources/3rdparty/glpk-4.53/src/glpios05.c b/resources/3rdparty/glpk-4.57/src/glpios05.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glpios05.c rename to resources/3rdparty/glpk-4.57/src/glpios05.c diff --git a/resources/3rdparty/glpk-4.53/src/glpios06.c b/resources/3rdparty/glpk-4.57/src/glpios06.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glpios06.c rename to resources/3rdparty/glpk-4.57/src/glpios06.c diff --git a/resources/3rdparty/glpk-4.53/src/glpios07.c b/resources/3rdparty/glpk-4.57/src/glpios07.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glpios07.c rename to resources/3rdparty/glpk-4.57/src/glpios07.c diff --git a/resources/3rdparty/glpk-4.53/src/glpios08.c b/resources/3rdparty/glpk-4.57/src/glpios08.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glpios08.c rename to resources/3rdparty/glpk-4.57/src/glpios08.c diff --git a/resources/3rdparty/glpk-4.53/src/glpios09.c b/resources/3rdparty/glpk-4.57/src/glpios09.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glpios09.c rename to resources/3rdparty/glpk-4.57/src/glpios09.c diff --git a/resources/3rdparty/glpk-4.53/src/glpios10.c b/resources/3rdparty/glpk-4.57/src/glpios10.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glpios10.c rename to resources/3rdparty/glpk-4.57/src/glpios10.c diff --git a/resources/3rdparty/glpk-4.53/src/glpios11.c b/resources/3rdparty/glpk-4.57/src/glpios11.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glpios11.c rename to resources/3rdparty/glpk-4.57/src/glpios11.c diff --git a/resources/3rdparty/glpk-4.53/src/glpios12.c b/resources/3rdparty/glpk-4.57/src/glpios12.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glpios12.c rename to resources/3rdparty/glpk-4.57/src/glpios12.c diff --git a/resources/3rdparty/glpk-4.53/src/glpipm.c b/resources/3rdparty/glpk-4.57/src/glpipm.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glpipm.c rename to resources/3rdparty/glpk-4.57/src/glpipm.c diff --git a/resources/3rdparty/glpk-4.53/src/glpipm.h b/resources/3rdparty/glpk-4.57/src/glpipm.h similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glpipm.h rename to resources/3rdparty/glpk-4.57/src/glpipm.h diff --git a/resources/3rdparty/glpk-4.53/src/glpk.h b/resources/3rdparty/glpk-4.57/src/glpk.h similarity index 95% rename from resources/3rdparty/glpk-4.53/src/glpk.h rename to resources/3rdparty/glpk-4.57/src/glpk.h index 86b8b913b..ed5be77fc 100644 --- a/resources/3rdparty/glpk-4.53/src/glpk.h +++ b/resources/3rdparty/glpk-4.57/src/glpk.h @@ -4,9 +4,9 @@ * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, -* 2009, 2010, 2011, 2013, 2014 Andrew Makhorin, Department for Applied -* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights -* reserved. E-mail: . +* 2009, 2010, 2011, 2013, 2014, 2015 Andrew Makhorin, Department for +* Applied Informatics, Moscow Aviation Institute, Moscow, Russia. All +* rights reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by @@ -34,7 +34,7 @@ extern "C" { /* library version numbers: */ #define GLP_MAJOR_VERSION 4 -#define GLP_MINOR_VERSION 53 +#define GLP_MINOR_VERSION 57 typedef struct glp_prob glp_prob; /* LP/MIP problem object */ @@ -84,21 +84,25 @@ typedef struct glp_prob glp_prob; typedef struct { /* basis factorization control parameters */ - int msg_lev; /* (reserved) */ + int msg_lev; /* (not used) */ int type; /* factorization type: */ -#define GLP_BF_FT 1 /* LUF + Forrest-Tomlin */ -#define GLP_BF_BG 2 /* LUF + Schur compl. + Bartels-Golub */ -#define GLP_BF_GR 3 /* LUF + Schur compl. + Givens rotation */ - int lu_size; /* luf.sv_size */ - double piv_tol; /* luf.piv_tol */ - int piv_lim; /* luf.piv_lim */ - int suhl; /* luf.suhl */ - double eps_tol; /* luf.eps_tol */ - double max_gro; /* luf.max_gro */ - int nfs_max; /* fhv.hh_max */ - double upd_tol; /* fhv.upd_tol */ - int nrs_max; /* lpf.n_max */ - int rs_size; /* lpf.v_size */ +#if 1 /* 05/III-2014 */ +#define GLP_BF_LUF 0x00 /* plain LU-factorization */ +#define GLP_BF_BTF 0x10 /* block triangular LU-factorization */ +#endif +#define GLP_BF_FT 0x01 /* Forrest-Tomlin (LUF only) */ +#define GLP_BF_BG 0x02 /* Schur compl. + Bartels-Golub */ +#define GLP_BF_GR 0x03 /* Schur compl. + Givens rotation */ + int lu_size; /* (not used) */ + double piv_tol; /* sgf_piv_tol */ + int piv_lim; /* sgf_piv_lim */ + int suhl; /* sgf_suhl */ + double eps_tol; /* sgf_eps_tol */ + double max_gro; /* (not used) */ + int nfs_max; /* fhvint.nfs_max */ + double upd_tol; /* (not used) */ + int nrs_max; /* scfint.nn_max */ + int rs_size; /* (not used) */ double foo_bar[38]; /* (reserved) */ } glp_bfcp; @@ -115,11 +119,11 @@ typedef struct #define GLP_DUALP 2 /* use dual; if it fails, use primal */ #define GLP_DUAL 3 /* use dual simplex */ int pricing; /* pricing technique: */ -#define GLP_PT_STD 0x11 /* standard (Dantzig rule) */ +#define GLP_PT_STD 0x11 /* standard (Dantzig's rule) */ #define GLP_PT_PSE 0x22 /* projected steepest edge */ int r_test; /* ratio test technique: */ #define GLP_RT_STD 0x11 /* standard (textbook) */ -#define GLP_RT_HAR 0x22 /* two-pass Harris' ratio test */ +#define GLP_RT_HAR 0x22 /* Harris' two-pass ratio test */ double tol_bnd; /* spx.tol_bnd */ double tol_dj; /* spx.tol_dj */ double tol_piv; /* spx.tol_piv */ @@ -182,20 +186,15 @@ typedef struct int presolve; /* enable/disable using MIP presolver */ int binarize; /* try to binarize integer variables */ int fp_heur; /* feasibility pump heuristic */ -#if 1 /* 25/V-2013 */ int ps_heur; /* proximity search heuristic */ -#endif -#if 1 /* 29/VI-2013 */ int ps_tm_lim; /* proxy time limit, milliseconds */ -#endif -#if 1 /* 11/VII-2013 */ + int sr_heur; /* simple rounding heuristic */ +#if 1 /* 24/X-2015; not documented--should not be used */ int use_sol; /* use existing solution */ const char *save_sol; /* filename to save every new solution */ -#endif -#if 1 /* 28/V-2010 */ int alien; /* use alien solver */ #endif - double foo_bar[25]; /* (reserved) */ + double foo_bar[24]; /* (reserved) */ } glp_iocp; typedef struct @@ -500,7 +499,7 @@ int glp_get_it_cnt(glp_prob *P); #endif #if 1 /* 08/VIII-2013; not documented yet */ -int glp_set_it_cnt(glp_prob *P, int it_cnt); +void glp_set_it_cnt(glp_prob *P, int it_cnt); /* set simplex solver iteration count */ #endif @@ -594,22 +593,22 @@ int glp_write_mip(glp_prob *P, const char *fname); /* write MIP solution to text file */ int glp_bf_exists(glp_prob *P); -/* check if the basis factorization exists */ +/* check if LP basis factorization exists */ int glp_factorize(glp_prob *P); -/* compute the basis factorization */ +/* compute LP basis factorization */ int glp_bf_updated(glp_prob *P); -/* check if the basis factorization has been updated */ +/* check if LP basis factorization has been updated */ void glp_get_bfcp(glp_prob *P, glp_bfcp *parm); -/* retrieve basis factorization control parameters */ +/* retrieve LP basis factorization control parameters */ void glp_set_bfcp(glp_prob *P, const glp_bfcp *parm); -/* change basis factorization control parameters */ +/* change LP basis factorization control parameters */ int glp_get_bhead(glp_prob *P, int k); -/* retrieve the basis header information */ +/* retrieve LP basis header information */ int glp_get_row_bind(glp_prob *P, int i); /* retrieve row index in the basis header */ @@ -827,6 +826,11 @@ typedef void (*glp_errfunc)(const char *fmt, ...); glp_errfunc glp_error_(const char *file, int line); /* display fatal error message and terminate execution */ +#if 1 /* 07/XI-2015 */ +int glp_at_error(void); +/* check for error state */ +#endif + #define glp_assert(expr) \ ((void)((expr) || (glp_assert_(#expr, __FILE__, __LINE__), 1))) void glp_assert_(const char *expr, const char *file, int line); diff --git a/resources/3rdparty/glpk-4.53/src/glpmat.c b/resources/3rdparty/glpk-4.57/src/glpmat.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glpmat.c rename to resources/3rdparty/glpk-4.57/src/glpmat.c diff --git a/resources/3rdparty/glpk-4.53/src/glpmat.h b/resources/3rdparty/glpk-4.57/src/glpmat.h similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glpmat.h rename to resources/3rdparty/glpk-4.57/src/glpmat.h diff --git a/resources/3rdparty/glpk-4.53/src/glpmpl.h b/resources/3rdparty/glpk-4.57/src/glpmpl.h similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glpmpl.h rename to resources/3rdparty/glpk-4.57/src/glpmpl.h diff --git a/resources/3rdparty/glpk-4.53/src/glpmpl01.c b/resources/3rdparty/glpk-4.57/src/glpmpl01.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glpmpl01.c rename to resources/3rdparty/glpk-4.57/src/glpmpl01.c diff --git a/resources/3rdparty/glpk-4.53/src/glpmpl02.c b/resources/3rdparty/glpk-4.57/src/glpmpl02.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glpmpl02.c rename to resources/3rdparty/glpk-4.57/src/glpmpl02.c diff --git a/resources/3rdparty/glpk-4.53/src/glpmpl03.c b/resources/3rdparty/glpk-4.57/src/glpmpl03.c similarity index 99% rename from resources/3rdparty/glpk-4.53/src/glpmpl03.c rename to resources/3rdparty/glpk-4.57/src/glpmpl03.c index b84dd7ccf..ddc3b583e 100644 --- a/resources/3rdparty/glpk-4.53/src/glpmpl03.c +++ b/resources/3rdparty/glpk-4.57/src/glpmpl03.c @@ -5913,7 +5913,7 @@ void execute_printf(MPL *mpl, PRINTF *prt) if (mpl->prt_fp == NULL) { mpl->prt_fp = glp_open(fname, prt->app ? "a" : "w"); if (mpl->prt_fp == NULL) - error(mpl, "unable to open `%s' for writing - %s", + error(mpl, "unable to open '%s' for writing - %s", fname, get_err_msg()); mpl->prt_file = xmalloc(strlen(fname)+1); strcpy(mpl->prt_file, fname); @@ -5926,7 +5926,7 @@ void execute_printf(MPL *mpl, PRINTF *prt) xfflush(mpl->prt_fp); #endif if (glp_ioerr(mpl->prt_fp)) - error(mpl, "writing error to `%s' - %s", mpl->prt_file, + error(mpl, "writing error to '%s' - %s", mpl->prt_file, get_err_msg()); } return; diff --git a/resources/3rdparty/glpk-4.53/src/glpmpl04.c b/resources/3rdparty/glpk-4.57/src/glpmpl04.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glpmpl04.c rename to resources/3rdparty/glpk-4.57/src/glpmpl04.c diff --git a/resources/3rdparty/glpk-4.53/src/glpmpl05.c b/resources/3rdparty/glpk-4.57/src/glpmpl05.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glpmpl05.c rename to resources/3rdparty/glpk-4.57/src/glpmpl05.c diff --git a/resources/3rdparty/glpk-4.53/src/glpmpl06.c b/resources/3rdparty/glpk-4.57/src/glpmpl06.c similarity index 99% rename from resources/3rdparty/glpk-4.53/src/glpmpl06.c rename to resources/3rdparty/glpk-4.57/src/glpmpl06.c index 8ab122a75..67c5aa05e 100644 --- a/resources/3rdparty/glpk-4.53/src/glpmpl06.c +++ b/resources/3rdparty/glpk-4.57/src/glpmpl06.c @@ -913,7 +913,7 @@ void mpl_tab_drv_open(MPL *mpl, int mode) dca->link = db_mysql_open(dca, mode); } else - xprintf("Invalid table driver `%s'\n", dca->arg[1]); + xprintf("Invalid table driver '%s'\n", dca->arg[1]); if (dca->link == NULL) error(mpl, "error on opening table %s", mpl->stmt->u.tab->name); diff --git a/resources/3rdparty/glpk-4.53/src/glpmps.c b/resources/3rdparty/glpk-4.57/src/glpmps.c similarity index 97% rename from resources/3rdparty/glpk-4.53/src/glpmps.c rename to resources/3rdparty/glpk-4.57/src/glpmps.c index 7b45ff77f..69be984c5 100644 --- a/resources/3rdparty/glpk-4.53/src/glpmps.c +++ b/resources/3rdparty/glpk-4.57/src/glpmps.c @@ -377,7 +377,7 @@ static double read_number(struct csa *csa) for (s = csa->field; *s == ' '; s++); /* perform conversion */ if (str2num(s, &x) != 0) - error(csa, "cannot convert `%s' to floating-point number\n", + error(csa, "cannot convert '%s' to floating-point number\n", s); return x; } @@ -432,7 +432,7 @@ loop: if (indicator(csa, 0)) goto done; if (csa->field[0] == '\0') error(csa, "missing row name in field 2\n"); if (glp_find_row(csa->P, csa->field) != 0) - error(csa, "row `%s' multiply specified\n", csa->field); + error(csa, "row '%s' multiply specified\n", csa->field); i = glp_add_rows(csa->P, 1); glp_set_row_name(csa->P, i, csa->field); glp_set_row_bnds(csa->P, i, type, 0.0, 0.0); @@ -513,7 +513,7 @@ loop: if (indicator(csa, 0)) goto done; } /* create new column */ if (glp_find_col(csa->P, name) != 0) - error(csa, "column `%s' multiply specified\n", name); + error(csa, "column '%s' multiply specified\n", name); j = glp_add_cols(csa->P, 1); glp_set_col_name(csa->P, j, name); glp_set_col_kind(csa->P, j, kind); @@ -541,9 +541,9 @@ loop: if (indicator(csa, 0)) goto done; } i = glp_find_row(csa->P, csa->field); if (i == 0) - error(csa, "row `%s' not found\n", csa->field); + error(csa, "row '%s' not found\n", csa->field); if (flag[i]) - error(csa, "duplicate coefficient in row `%s'\n", + error(csa, "duplicate coefficient in row '%s'\n", csa->field); /* field 4 or 6: coefficient value */ aij = read_number(csa); @@ -616,9 +616,9 @@ blnk: { /* new RHS vector */ } i = glp_find_row(csa->P, csa->field); if (i == 0) - error(csa, "row `%s' not found\n", csa->field); + error(csa, "row '%s' not found\n", csa->field); if (flag[i]) - error(csa, "duplicate right-hand side for row `%s'\n", + error(csa, "duplicate right-hand side for row '%s'\n", csa->field); /* field 4 or 6: right-hand side value */ rhs = read_number(csa); @@ -628,7 +628,7 @@ blnk: { /* new RHS vector */ { if (i == csa->obj_row) glp_set_obj_coef(csa->P, 0, rhs); else if (rhs != 0.0) - warning(csa, "non-zero right-hand side for free row `%s'" + warning(csa, "non-zero right-hand side for free row '%s'" " ignored\n", csa->P->row[i]->name); } else @@ -696,15 +696,15 @@ blnk: { /* new RANGES vector */ } i = glp_find_row(csa->P, csa->field); if (i == 0) - error(csa, "row `%s' not found\n", csa->field); + error(csa, "row '%s' not found\n", csa->field); if (flag[i]) - error(csa, "duplicate range for row `%s'\n", csa->field); + error(csa, "duplicate range for row '%s'\n", csa->field); /* field 4 or 6: range value */ rng = read_number(csa); if (fabs(rng) < csa->parm->tol_mps) rng = 0.0; type = csa->P->row[i]->type; if (type == GLP_FR) - warning(csa, "range for free row `%s' ignored\n", + warning(csa, "range for free row '%s' ignored\n", csa->P->row[i]->name); else if (type == GLP_LO) { rhs = csa->P->row[i]->lb; @@ -797,12 +797,12 @@ blnk: { /* new BOUNDS vector */ error(csa, "missing column name in field 3\n"); j = glp_find_col(csa->P, csa->field); if (j == 0) - error(csa, "column `%s' not found\n", csa->field); + error(csa, "column '%s' not found\n", csa->field); if ((flag[j] & mask) == 0x01) - error(csa, "duplicate lower bound for column `%s'\n", + error(csa, "duplicate lower bound for column '%s'\n", csa->field); if ((flag[j] & mask) == 0x10) - error(csa, "duplicate upper bound for column `%s'\n", + error(csa, "duplicate upper bound for column '%s'\n", csa->field); xassert((flag[j] & mask) == 0x00); /* field 4: bound value */ @@ -887,7 +887,7 @@ int glp_read_mps(glp_prob *P, int fmt, const glp_mpscp *parm, glp_mpscp _parm; struct csa _csa, *csa = &_csa; int ret; - xprintf("Reading problem data from `%s'...\n", fname); + xprintf("Reading problem data from '%s'...\n", fname); if (!(fmt == GLP_MPS_DECK || fmt == GLP_MPS_FILE)) xerror("glp_read_mps: fmt = %d; invalid parameter\n", fmt); if (parm == NULL) @@ -917,7 +917,7 @@ int glp_read_mps(glp_prob *P, int fmt, const glp_mpscp *parm, /* open input MPS file */ csa->fp = glp_open(fname, "r"); if (csa->fp == NULL) - { xprintf("Unable to open `%s' - %s\n", fname, get_err_msg()); + { xprintf("Unable to open '%s' - %s\n", fname, get_err_msg()); ret = 1; goto done; } @@ -953,7 +953,7 @@ int glp_read_mps(glp_prob *P, int fmt, const glp_mpscp *parm, } } if (csa->obj_row == 0) - error(csa, "objective row `%s' not found\n", + error(csa, "objective row '%s' not found\n", parm->obj_name); } if (csa->obj_row != 0) @@ -983,25 +983,6 @@ int glp_read_mps(glp_prob *P, int fmt, const glp_mpscp *parm, if (strcmp(csa->field, "ENDATA") != 0) error(csa, "invalid use of %s indicator record\n", csa->field); -#if 1 /* 08/VIII-2013 */ - /* remove free rows */ - { int i, nrs, *num; - num = talloc(1+P->m, int); - nrs = 0; - for (i = 1; i <= P->m; i++) - { if (P->row[i]->type == GLP_FR) - num[++nrs] = i; - } - if (nrs > 0) - { glp_del_rows(P, nrs, num); - if (nrs == 1) - xprintf("One free row was removed\n"); - else - xprintf("%d free rows were removed\n", nrs); - } - tfree(num); - } -#endif /* print some statistics */ xprintf("%d row%s, %d column%s, %d non-zero%s\n", P->m, P->m == 1 ? "" : "s", P->n, P->n == 1 ? "" : "s", @@ -1029,6 +1010,25 @@ int glp_read_mps(glp_prob *P, int fmt, const glp_mpscp *parm, } } xprintf("%d records were read\n", csa->recno); +#if 1 /* 08/VIII-2013 */ + /* remove free rows */ + { int i, nrs, *num; + num = talloc(1+P->m, int); + nrs = 0; + for (i = 1; i <= P->m; i++) + { if (P->row[i]->type == GLP_FR) + num[++nrs] = i; + } + if (nrs > 0) + { glp_del_rows(P, nrs, num); + if (nrs == 1) + xprintf("One free row was removed\n"); + else + xprintf("%d free rows were removed\n", nrs); + } + tfree(num); + } +#endif /* problem data has been successfully read */ glp_delete_index(P); glp_sort_matrix(P); @@ -1159,7 +1159,7 @@ int glp_write_mps(glp_prob *P, int fmt, const glp_mpscp *parm, glp_file *fp; int out_obj, one_col = 0, empty = 0; int i, j, recno, marker, count, gap, ret; - xprintf("Writing problem data to `%s'...\n", fname); + xprintf("Writing problem data to '%s'...\n", fname); if (!(fmt == GLP_MPS_DECK || fmt == GLP_MPS_FILE)) xerror("glp_write_mps: fmt = %d; invalid parameter\n", fmt); if (parm == NULL) @@ -1173,7 +1173,7 @@ int glp_write_mps(glp_prob *P, int fmt, const glp_mpscp *parm, /* create output MPS file */ fp = glp_open(fname, "w"), recno = 0; if (fp == NULL) - { xprintf("Unable to create `%s' - %s\n", fname, get_err_msg()); + { xprintf("Unable to create '%s' - %s\n", fname, get_err_msg()); ret = 1; goto done; } @@ -1419,7 +1419,7 @@ endt: /* write ENDATA indicator record */ xfflush(fp); #endif if (glp_ioerr(fp)) - { xprintf("Write error on `%s' - %s\n", fname, get_err_msg()); + { xprintf("Write error on '%s' - %s\n", fname, get_err_msg()); ret = 1; goto done; } diff --git a/resources/3rdparty/glpk-4.53/src/glpnet03.c b/resources/3rdparty/glpk-4.57/src/glpnet03.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glpnet03.c rename to resources/3rdparty/glpk-4.57/src/glpnet03.c diff --git a/resources/3rdparty/glpk-4.53/src/glpnet04.c b/resources/3rdparty/glpk-4.57/src/glpnet04.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glpnet04.c rename to resources/3rdparty/glpk-4.57/src/glpnet04.c diff --git a/resources/3rdparty/glpk-4.53/src/glpnet05.c b/resources/3rdparty/glpk-4.57/src/glpnet05.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glpnet05.c rename to resources/3rdparty/glpk-4.57/src/glpnet05.c diff --git a/resources/3rdparty/glpk-4.53/src/glpnpp.h b/resources/3rdparty/glpk-4.57/src/glpnpp.h similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glpnpp.h rename to resources/3rdparty/glpk-4.57/src/glpnpp.h diff --git a/resources/3rdparty/glpk-4.53/src/glpnpp01.c b/resources/3rdparty/glpk-4.57/src/glpnpp01.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glpnpp01.c rename to resources/3rdparty/glpk-4.57/src/glpnpp01.c diff --git a/resources/3rdparty/glpk-4.53/src/glpnpp02.c b/resources/3rdparty/glpk-4.57/src/glpnpp02.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glpnpp02.c rename to resources/3rdparty/glpk-4.57/src/glpnpp02.c diff --git a/resources/3rdparty/glpk-4.53/src/glpnpp03.c b/resources/3rdparty/glpk-4.57/src/glpnpp03.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glpnpp03.c rename to resources/3rdparty/glpk-4.57/src/glpnpp03.c diff --git a/resources/3rdparty/glpk-4.53/src/glpnpp04.c b/resources/3rdparty/glpk-4.57/src/glpnpp04.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glpnpp04.c rename to resources/3rdparty/glpk-4.57/src/glpnpp04.c diff --git a/resources/3rdparty/glpk-4.53/src/glpnpp05.c b/resources/3rdparty/glpk-4.57/src/glpnpp05.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glpnpp05.c rename to resources/3rdparty/glpk-4.57/src/glpnpp05.c diff --git a/resources/3rdparty/glpk-4.53/src/glpnpp06.c b/resources/3rdparty/glpk-4.57/src/glpnpp06.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glpnpp06.c rename to resources/3rdparty/glpk-4.57/src/glpnpp06.c diff --git a/resources/3rdparty/glpk-4.53/src/glprgr.c b/resources/3rdparty/glpk-4.57/src/glprgr.c similarity index 97% rename from resources/3rdparty/glpk-4.53/src/glprgr.c rename to resources/3rdparty/glpk-4.57/src/glprgr.c index 382a932ca..b4b616b1b 100644 --- a/resources/3rdparty/glpk-4.53/src/glprgr.c +++ b/resources/3rdparty/glpk-4.57/src/glprgr.c @@ -100,7 +100,7 @@ int rgr_write_bmp16(const char *fname, int m, int n, const char map[]) xfault("rgr_write_bmp16: n = %d; invalid width\n", n); fp = fopen(fname, "wb"); if (fp == NULL) - { xprintf("rgr_write_bmp16: unable to create `%s' - %s\n", + { xprintf("rgr_write_bmp16: unable to create '%s' - %s\n", fname, strerror(errno)); ret = 1; goto fini; @@ -154,7 +154,7 @@ int rgr_write_bmp16(const char *fname, int m, int n, const char map[]) } fflush(fp); if (ferror(fp)) - { xprintf("rgr_write_bmp16: write error on `%s' - %s\n", + { xprintf("rgr_write_bmp16: write error on '%s' - %s\n", fname, strerror(errno)); ret = 1; } diff --git a/resources/3rdparty/glpk-4.53/src/glprgr.h b/resources/3rdparty/glpk-4.57/src/glprgr.h similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glprgr.h rename to resources/3rdparty/glpk-4.57/src/glprgr.h diff --git a/resources/3rdparty/glpk-4.53/src/glpscl.c b/resources/3rdparty/glpk-4.57/src/glpscl.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glpscl.c rename to resources/3rdparty/glpk-4.57/src/glpscl.c diff --git a/resources/3rdparty/glpk-4.53/src/glpsdf.c b/resources/3rdparty/glpk-4.57/src/glpsdf.c similarity index 94% rename from resources/3rdparty/glpk-4.53/src/glpsdf.c rename to resources/3rdparty/glpk-4.57/src/glpsdf.c index bd167f2dd..e14bd0662 100644 --- a/resources/3rdparty/glpk-4.53/src/glpsdf.c +++ b/resources/3rdparty/glpk-4.57/src/glpsdf.c @@ -51,7 +51,7 @@ glp_data *glp_sdf_open_file(const char *fname) jmp_buf jump; fp = glp_open(fname, "r"); if (fp == NULL) - { xprintf("Unable to open `%s' - %s\n", fname, get_err_msg()); + { xprintf("Unable to open '%s' - %s\n", fname, get_err_msg()); goto done; } data = xmalloc(sizeof(glp_data)); @@ -164,7 +164,7 @@ static void next_item(glp_data *data) while (!(data->c == ' ' || data->c == '\n')) { data->item[len++] = (char)data->c; if (len == sizeof(data->item)) - glp_sdf_error(data, "data item `%.31s...' too long\n", + glp_sdf_error(data, "data item '%.31s...' too long\n", data->item); next_char(data); } @@ -180,10 +180,10 @@ int glp_sdf_read_int(glp_data *data) { case 0: break; case 1: - glp_sdf_error(data, "integer `%s' out of range\n", + glp_sdf_error(data, "integer '%s' out of range\n", data->item); case 2: - glp_sdf_error(data, "cannot convert `%s' to integer\n", + glp_sdf_error(data, "cannot convert '%s' to integer\n", data->item); default: xassert(data != data); @@ -199,10 +199,10 @@ double glp_sdf_read_num(glp_data *data) { case 0: break; case 1: - glp_sdf_error(data, "number `%s' out of range\n", + glp_sdf_error(data, "number '%s' out of range\n", data->item); case 2: - glp_sdf_error(data, "cannot convert `%s' to number\n", + glp_sdf_error(data, "cannot convert '%s' to number\n", data->item); default: xassert(data != data); diff --git a/resources/3rdparty/glpk-4.53/src/glpsdf.h b/resources/3rdparty/glpk-4.57/src/glpsdf.h similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glpsdf.h rename to resources/3rdparty/glpk-4.57/src/glpsdf.h diff --git a/resources/3rdparty/glpk-4.53/src/glpspm.c b/resources/3rdparty/glpk-4.57/src/glpspm.c similarity index 98% rename from resources/3rdparty/glpk-4.53/src/glpspm.c rename to resources/3rdparty/glpk-4.57/src/glpspm.c index c05b3ac18..c6cfd25dd 100644 --- a/resources/3rdparty/glpk-4.53/src/glpspm.c +++ b/resources/3rdparty/glpk-4.57/src/glpspm.c @@ -266,7 +266,7 @@ int spm_show_mat(const SPM *A, const char *fname) int n = A->n; int i, j, k, ret; char *map; - xprintf("spm_show_mat: writing matrix pattern to `%s'...\n", + xprintf("spm_show_mat: writing matrix pattern to '%s'...\n", fname); xassert(1 <= m && m <= 32767); xassert(1 <= n && n <= 32767); @@ -346,7 +346,7 @@ SPM *spm_read_hbm(const char *fname) if (!(strcmp(mxtype, "RSA") == 0 || strcmp(mxtype, "PSA") == 0 || strcmp(mxtype, "RUA") == 0 || strcmp(mxtype, "PUA") == 0 || strcmp(mxtype, "RRA") == 0 || strcmp(mxtype, "PRA") == 0)) - { xprintf("spm_read_hbm: matrix type `%s' not supported\n", + { xprintf("spm_read_hbm: matrix type '%s' not supported\n", mxtype); goto fini; } @@ -486,10 +486,10 @@ SPM *spm_read_mat(const char *fname) jmp_buf jump; int i, j, k, m, n, nnz, fail = 0; double val; - xprintf("spm_read_mat: reading matrix from `%s'...\n", fname); + xprintf("spm_read_mat: reading matrix from '%s'...\n", fname); pds = pds_open_file(fname); if (pds == NULL) - { xprintf("spm_read_mat: unable to open `%s' - %s\n", fname, + { xprintf("spm_read_mat: unable to open '%s' - %s\n", fname, strerror(errno)); fail = 1; goto done; @@ -582,10 +582,10 @@ int spm_write_mat(const SPM *A, const char *fname) int spm_write_mat(const SPM *A, const char *fname) { FILE *fp; int i, nnz, ret = 0; - xprintf("spm_write_mat: writing matrix to `%s'...\n", fname); + xprintf("spm_write_mat: writing matrix to '%s'...\n", fname); fp = fopen(fname, "w"); if (fp == NULL) - { xprintf("spm_write_mat: unable to create `%s' - %s\n", fname, + { xprintf("spm_write_mat: unable to create '%s' - %s\n", fname, strerror(errno)); ret = 1; goto done; @@ -604,7 +604,7 @@ int spm_write_mat(const SPM *A, const char *fname) } fflush(fp); if (ferror(fp)) - { xprintf("spm_write_mat: writing error on `%s' - %s\n", fname, + { xprintf("spm_write_mat: writing error on '%s' - %s\n", fname, strerror(errno)); ret = 1; goto done; diff --git a/resources/3rdparty/glpk-4.53/src/glpspm.h b/resources/3rdparty/glpk-4.57/src/glpspm.h similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glpspm.h rename to resources/3rdparty/glpk-4.57/src/glpspm.h diff --git a/resources/3rdparty/glpk-4.53/src/glpsql.c b/resources/3rdparty/glpk-4.57/src/glpsql.c similarity index 99% rename from resources/3rdparty/glpk-4.53/src/glpsql.c rename to resources/3rdparty/glpk-4.57/src/glpsql.c index 8cd5cd08b..9c664dbc5 100644 --- a/resources/3rdparty/glpk-4.53/src/glpsql.c +++ b/resources/3rdparty/glpk-4.57/src/glpsql.c @@ -86,11 +86,10 @@ static char **args_concat(TABDCA *dca) int j; int j0; int j1; - int len; + size_t len; int lentot; int narg; int nline = 0; - void *ret; char **sqllines = NULL; narg = mpl_tab_num_args(dca); @@ -184,12 +183,12 @@ static int db_escaped_string_length(const char* from) return count; } -static int db_escape_string (char *to, const char *from) +static void db_escape_string (char *to, const char *from) /* escape string*/ { const char *source = from; char *target = to; - unsigned int remaining; + size_t remaining; remaining = strlen(from); @@ -216,8 +215,6 @@ static int db_escape_string (char *to, const char *from) /* Write the terminating NUL character. */ *target = '\0'; - - return target - to; } static char *db_generate_select_stmt(TABDCA *dca) diff --git a/resources/3rdparty/glpk-4.53/src/glpsql.h b/resources/3rdparty/glpk-4.57/src/glpsql.h similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glpsql.h rename to resources/3rdparty/glpk-4.57/src/glpsql.h diff --git a/resources/3rdparty/glpk-4.53/src/glpssx.h b/resources/3rdparty/glpk-4.57/src/glpssx.h similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glpssx.h rename to resources/3rdparty/glpk-4.57/src/glpssx.h diff --git a/resources/3rdparty/glpk-4.53/src/glpssx01.c b/resources/3rdparty/glpk-4.57/src/glpssx01.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glpssx01.c rename to resources/3rdparty/glpk-4.57/src/glpssx01.c diff --git a/resources/3rdparty/glpk-4.53/src/glpssx02.c b/resources/3rdparty/glpk-4.57/src/glpssx02.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/glpssx02.c rename to resources/3rdparty/glpk-4.57/src/glpssx02.c diff --git a/resources/3rdparty/glpk-4.53/src/lux.c b/resources/3rdparty/glpk-4.57/src/lux.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/lux.c rename to resources/3rdparty/glpk-4.57/src/lux.c diff --git a/resources/3rdparty/glpk-4.53/src/lux.h b/resources/3rdparty/glpk-4.57/src/lux.h similarity index 100% rename from resources/3rdparty/glpk-4.53/src/lux.h rename to resources/3rdparty/glpk-4.57/src/lux.h diff --git a/resources/3rdparty/glpk-4.53/src/minisat/LICENSE b/resources/3rdparty/glpk-4.57/src/minisat/LICENSE similarity index 100% rename from resources/3rdparty/glpk-4.53/src/minisat/LICENSE rename to resources/3rdparty/glpk-4.57/src/minisat/LICENSE diff --git a/resources/3rdparty/glpk-4.53/src/minisat/README b/resources/3rdparty/glpk-4.57/src/minisat/README similarity index 100% rename from resources/3rdparty/glpk-4.53/src/minisat/README rename to resources/3rdparty/glpk-4.57/src/minisat/README diff --git a/resources/3rdparty/glpk-4.53/src/minisat/minisat.c b/resources/3rdparty/glpk-4.57/src/minisat/minisat.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/minisat/minisat.c rename to resources/3rdparty/glpk-4.57/src/minisat/minisat.c diff --git a/resources/3rdparty/glpk-4.53/src/minisat/minisat.h b/resources/3rdparty/glpk-4.57/src/minisat/minisat.h similarity index 100% rename from resources/3rdparty/glpk-4.53/src/minisat/minisat.h rename to resources/3rdparty/glpk-4.57/src/minisat/minisat.h diff --git a/resources/3rdparty/glpk-4.53/src/misc/bignum.c b/resources/3rdparty/glpk-4.57/src/misc/bignum.c similarity index 99% rename from resources/3rdparty/glpk-4.53/src/misc/bignum.c rename to resources/3rdparty/glpk-4.57/src/misc/bignum.c index f91df5fd0..540dd9fdd 100644 --- a/resources/3rdparty/glpk-4.53/src/misc/bignum.c +++ b/resources/3rdparty/glpk-4.57/src/misc/bignum.c @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2006, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2006-2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * diff --git a/resources/3rdparty/glpk-4.53/src/misc/bignum.h b/resources/3rdparty/glpk-4.57/src/misc/bignum.h similarity index 95% rename from resources/3rdparty/glpk-4.53/src/misc/bignum.h rename to resources/3rdparty/glpk-4.57/src/misc/bignum.h index b6361d2bc..aebac374d 100644 --- a/resources/3rdparty/glpk-4.53/src/misc/bignum.h +++ b/resources/3rdparty/glpk-4.57/src/misc/bignum.h @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2006, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2006-2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * diff --git a/resources/3rdparty/glpk-4.53/src/misc/dmp.c b/resources/3rdparty/glpk-4.57/src/misc/dmp.c similarity index 99% rename from resources/3rdparty/glpk-4.53/src/misc/dmp.c rename to resources/3rdparty/glpk-4.57/src/misc/dmp.c index e92b3e90e..a4882c861 100644 --- a/resources/3rdparty/glpk-4.53/src/misc/dmp.c +++ b/resources/3rdparty/glpk-4.57/src/misc/dmp.c @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2000, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * diff --git a/resources/3rdparty/glpk-4.53/src/misc/dmp.h b/resources/3rdparty/glpk-4.57/src/misc/dmp.h similarity index 96% rename from resources/3rdparty/glpk-4.53/src/misc/dmp.h rename to resources/3rdparty/glpk-4.57/src/misc/dmp.h index e2ef01a89..85fe7176a 100644 --- a/resources/3rdparty/glpk-4.53/src/misc/dmp.h +++ b/resources/3rdparty/glpk-4.57/src/misc/dmp.h @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2000, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * diff --git a/resources/3rdparty/glpk-4.53/src/misc/ffalg.c b/resources/3rdparty/glpk-4.57/src/misc/ffalg.c similarity index 99% rename from resources/3rdparty/glpk-4.53/src/misc/ffalg.c rename to resources/3rdparty/glpk-4.57/src/misc/ffalg.c index c55d8d4a2..4ea2913db 100644 --- a/resources/3rdparty/glpk-4.53/src/misc/ffalg.c +++ b/resources/3rdparty/glpk-4.57/src/misc/ffalg.c @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2009, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2009-2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * diff --git a/resources/3rdparty/glpk-4.53/src/misc/ffalg.h b/resources/3rdparty/glpk-4.57/src/misc/ffalg.h similarity index 94% rename from resources/3rdparty/glpk-4.53/src/misc/ffalg.h rename to resources/3rdparty/glpk-4.57/src/misc/ffalg.h index 662b747f3..7016f8fa6 100644 --- a/resources/3rdparty/glpk-4.53/src/misc/ffalg.h +++ b/resources/3rdparty/glpk-4.57/src/misc/ffalg.h @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2009, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2009-2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * diff --git a/resources/3rdparty/glpk-4.53/src/misc/fp2rat.c b/resources/3rdparty/glpk-4.57/src/misc/fp2rat.c similarity index 98% rename from resources/3rdparty/glpk-4.53/src/misc/fp2rat.c rename to resources/3rdparty/glpk-4.57/src/misc/fp2rat.c index 1e462b9cb..4699bbd16 100644 --- a/resources/3rdparty/glpk-4.53/src/misc/fp2rat.c +++ b/resources/3rdparty/glpk-4.57/src/misc/fp2rat.c @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2000, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * diff --git a/resources/3rdparty/glpk-4.53/src/misc/gcd.c b/resources/3rdparty/glpk-4.57/src/misc/gcd.c similarity index 97% rename from resources/3rdparty/glpk-4.53/src/misc/gcd.c rename to resources/3rdparty/glpk-4.57/src/misc/gcd.c index b5c596209..95c48cc04 100644 --- a/resources/3rdparty/glpk-4.53/src/misc/gcd.c +++ b/resources/3rdparty/glpk-4.57/src/misc/gcd.c @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2000, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * diff --git a/resources/3rdparty/glpk-4.53/src/misc/jd.c b/resources/3rdparty/glpk-4.57/src/misc/jd.c similarity index 98% rename from resources/3rdparty/glpk-4.53/src/misc/jd.c rename to resources/3rdparty/glpk-4.57/src/misc/jd.c index e678a1ee9..c9d631719 100644 --- a/resources/3rdparty/glpk-4.53/src/misc/jd.c +++ b/resources/3rdparty/glpk-4.57/src/misc/jd.c @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2000, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * diff --git a/resources/3rdparty/glpk-4.53/src/misc/jd.h b/resources/3rdparty/glpk-4.57/src/misc/jd.h similarity index 94% rename from resources/3rdparty/glpk-4.53/src/misc/jd.h rename to resources/3rdparty/glpk-4.57/src/misc/jd.h index daaa85894..009d2daad 100644 --- a/resources/3rdparty/glpk-4.53/src/misc/jd.h +++ b/resources/3rdparty/glpk-4.57/src/misc/jd.h @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2000, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * diff --git a/resources/3rdparty/glpk-4.53/src/misc/keller.c b/resources/3rdparty/glpk-4.57/src/misc/keller.c similarity index 99% rename from resources/3rdparty/glpk-4.53/src/misc/keller.c rename to resources/3rdparty/glpk-4.57/src/misc/keller.c index 2c4849d7d..d64d3c1e2 100644 --- a/resources/3rdparty/glpk-4.53/src/misc/keller.c +++ b/resources/3rdparty/glpk-4.57/src/misc/keller.c @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2009, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2009-2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * diff --git a/resources/3rdparty/glpk-4.53/src/misc/keller.h b/resources/3rdparty/glpk-4.57/src/misc/keller.h similarity index 94% rename from resources/3rdparty/glpk-4.53/src/misc/keller.h rename to resources/3rdparty/glpk-4.57/src/misc/keller.h index 77dfbf67c..d7a5b3431 100644 --- a/resources/3rdparty/glpk-4.53/src/misc/keller.h +++ b/resources/3rdparty/glpk-4.57/src/misc/keller.h @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2009, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2009-2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * diff --git a/resources/3rdparty/glpk-4.53/src/misc/mc13d.c b/resources/3rdparty/glpk-4.57/src/misc/mc13d.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/misc/mc13d.c rename to resources/3rdparty/glpk-4.57/src/misc/mc13d.c diff --git a/resources/3rdparty/glpk-4.53/src/misc/mc13d.h b/resources/3rdparty/glpk-4.57/src/misc/mc13d.h similarity index 94% rename from resources/3rdparty/glpk-4.53/src/misc/mc13d.h rename to resources/3rdparty/glpk-4.57/src/misc/mc13d.h index b260fcd60..bdd57a19a 100644 --- a/resources/3rdparty/glpk-4.53/src/misc/mc13d.h +++ b/resources/3rdparty/glpk-4.57/src/misc/mc13d.h @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2009, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2009-2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * diff --git a/resources/3rdparty/glpk-4.53/src/misc/mc21a.c b/resources/3rdparty/glpk-4.57/src/misc/mc21a.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/misc/mc21a.c rename to resources/3rdparty/glpk-4.57/src/misc/mc21a.c diff --git a/resources/3rdparty/glpk-4.53/src/misc/mc21a.h b/resources/3rdparty/glpk-4.57/src/misc/mc21a.h similarity index 94% rename from resources/3rdparty/glpk-4.53/src/misc/mc21a.h rename to resources/3rdparty/glpk-4.57/src/misc/mc21a.h index e0de53a15..755f28b22 100644 --- a/resources/3rdparty/glpk-4.53/src/misc/mc21a.h +++ b/resources/3rdparty/glpk-4.57/src/misc/mc21a.h @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2009, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2009-2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * diff --git a/resources/3rdparty/glpk-4.53/src/misc/misc.h b/resources/3rdparty/glpk-4.57/src/misc/misc.h similarity index 96% rename from resources/3rdparty/glpk-4.53/src/misc/misc.h rename to resources/3rdparty/glpk-4.57/src/misc/misc.h index cf6c0481c..1ba1dc505 100644 --- a/resources/3rdparty/glpk-4.53/src/misc/misc.h +++ b/resources/3rdparty/glpk-4.57/src/misc/misc.h @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2000, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * diff --git a/resources/3rdparty/glpk-4.53/src/misc/okalg.c b/resources/3rdparty/glpk-4.57/src/misc/okalg.c similarity index 99% rename from resources/3rdparty/glpk-4.53/src/misc/okalg.c rename to resources/3rdparty/glpk-4.57/src/misc/okalg.c index 5fa6ac37e..8eecd6df8 100644 --- a/resources/3rdparty/glpk-4.53/src/misc/okalg.c +++ b/resources/3rdparty/glpk-4.57/src/misc/okalg.c @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2009, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2009-2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * diff --git a/resources/3rdparty/glpk-4.53/src/misc/okalg.h b/resources/3rdparty/glpk-4.57/src/misc/okalg.h similarity index 94% rename from resources/3rdparty/glpk-4.53/src/misc/okalg.h rename to resources/3rdparty/glpk-4.57/src/misc/okalg.h index 71a4a0df7..2f2d97403 100644 --- a/resources/3rdparty/glpk-4.53/src/misc/okalg.h +++ b/resources/3rdparty/glpk-4.57/src/misc/okalg.h @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2009, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2009-2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * diff --git a/resources/3rdparty/glpk-4.53/src/misc/qmd.c b/resources/3rdparty/glpk-4.57/src/misc/qmd.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/misc/qmd.c rename to resources/3rdparty/glpk-4.57/src/misc/qmd.c diff --git a/resources/3rdparty/glpk-4.53/src/misc/qmd.h b/resources/3rdparty/glpk-4.57/src/misc/qmd.h similarity index 96% rename from resources/3rdparty/glpk-4.53/src/misc/qmd.h rename to resources/3rdparty/glpk-4.57/src/misc/qmd.h index 4c5a089ab..e55d50f52 100644 --- a/resources/3rdparty/glpk-4.53/src/misc/qmd.h +++ b/resources/3rdparty/glpk-4.57/src/misc/qmd.h @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2001, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2001-2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * diff --git a/resources/3rdparty/glpk-4.53/src/misc/relax4.c b/resources/3rdparty/glpk-4.57/src/misc/relax4.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/misc/relax4.c rename to resources/3rdparty/glpk-4.57/src/misc/relax4.c diff --git a/resources/3rdparty/glpk-4.53/src/misc/relax4.h b/resources/3rdparty/glpk-4.57/src/misc/relax4.h similarity index 98% rename from resources/3rdparty/glpk-4.53/src/misc/relax4.h rename to resources/3rdparty/glpk-4.57/src/misc/relax4.h index 44991fc55..f48b8508c 100644 --- a/resources/3rdparty/glpk-4.53/src/misc/relax4.h +++ b/resources/3rdparty/glpk-4.57/src/misc/relax4.h @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2012-2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * diff --git a/resources/3rdparty/glpk-4.53/src/misc/rng.c b/resources/3rdparty/glpk-4.57/src/misc/rng.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/misc/rng.c rename to resources/3rdparty/glpk-4.57/src/misc/rng.c diff --git a/resources/3rdparty/glpk-4.53/src/misc/rng.h b/resources/3rdparty/glpk-4.57/src/misc/rng.h similarity index 96% rename from resources/3rdparty/glpk-4.53/src/misc/rng.h rename to resources/3rdparty/glpk-4.57/src/misc/rng.h index 9747b4490..49725e057 100644 --- a/resources/3rdparty/glpk-4.53/src/misc/rng.h +++ b/resources/3rdparty/glpk-4.57/src/misc/rng.h @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2003, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2003-2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * diff --git a/resources/3rdparty/glpk-4.53/src/misc/rng1.c b/resources/3rdparty/glpk-4.57/src/misc/rng1.c similarity index 96% rename from resources/3rdparty/glpk-4.53/src/misc/rng1.c rename to resources/3rdparty/glpk-4.57/src/misc/rng1.c index 567c79eb8..b89f676f2 100644 --- a/resources/3rdparty/glpk-4.53/src/misc/rng1.c +++ b/resources/3rdparty/glpk-4.57/src/misc/rng1.c @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2003, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2003-2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * diff --git a/resources/3rdparty/glpk-4.53/src/misc/round2n.c b/resources/3rdparty/glpk-4.57/src/misc/round2n.c similarity index 96% rename from resources/3rdparty/glpk-4.53/src/misc/round2n.c rename to resources/3rdparty/glpk-4.57/src/misc/round2n.c index 126d638c1..8a94c6162 100644 --- a/resources/3rdparty/glpk-4.53/src/misc/round2n.c +++ b/resources/3rdparty/glpk-4.57/src/misc/round2n.c @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2000, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * diff --git a/resources/3rdparty/glpk-4.53/src/misc/str2int.c b/resources/3rdparty/glpk-4.57/src/misc/str2int.c similarity index 97% rename from resources/3rdparty/glpk-4.53/src/misc/str2int.c rename to resources/3rdparty/glpk-4.57/src/misc/str2int.c index 5d8117a55..cbd6e953f 100644 --- a/resources/3rdparty/glpk-4.53/src/misc/str2int.c +++ b/resources/3rdparty/glpk-4.57/src/misc/str2int.c @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2000, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * diff --git a/resources/3rdparty/glpk-4.53/src/misc/str2num.c b/resources/3rdparty/glpk-4.57/src/misc/str2num.c similarity index 98% rename from resources/3rdparty/glpk-4.53/src/misc/str2num.c rename to resources/3rdparty/glpk-4.57/src/misc/str2num.c index f67c2fc17..26c2f68f1 100644 --- a/resources/3rdparty/glpk-4.53/src/misc/str2num.c +++ b/resources/3rdparty/glpk-4.57/src/misc/str2num.c @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2000, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * diff --git a/resources/3rdparty/glpk-4.53/src/misc/strspx.c b/resources/3rdparty/glpk-4.57/src/misc/strspx.c similarity index 96% rename from resources/3rdparty/glpk-4.53/src/misc/strspx.c rename to resources/3rdparty/glpk-4.57/src/misc/strspx.c index f0702f9ce..fe8a2a101 100644 --- a/resources/3rdparty/glpk-4.53/src/misc/strspx.c +++ b/resources/3rdparty/glpk-4.57/src/misc/strspx.c @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2000, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * diff --git a/resources/3rdparty/glpk-4.53/src/misc/strtrim.c b/resources/3rdparty/glpk-4.57/src/misc/strtrim.c similarity index 96% rename from resources/3rdparty/glpk-4.53/src/misc/strtrim.c rename to resources/3rdparty/glpk-4.57/src/misc/strtrim.c index a9b782359..9992c4b0c 100644 --- a/resources/3rdparty/glpk-4.53/src/misc/strtrim.c +++ b/resources/3rdparty/glpk-4.57/src/misc/strtrim.c @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2000, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2000-2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * diff --git a/resources/3rdparty/glpk-4.53/src/misc/triang.c b/resources/3rdparty/glpk-4.57/src/misc/triang.c similarity index 99% rename from resources/3rdparty/glpk-4.53/src/misc/triang.c rename to resources/3rdparty/glpk-4.57/src/misc/triang.c index bb95ecc3a..99ba4d604 100644 --- a/resources/3rdparty/glpk-4.53/src/misc/triang.c +++ b/resources/3rdparty/glpk-4.57/src/misc/triang.c @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2012-2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * diff --git a/resources/3rdparty/glpk-4.53/src/misc/triang.h b/resources/3rdparty/glpk-4.57/src/misc/triang.h similarity index 94% rename from resources/3rdparty/glpk-4.53/src/misc/triang.h rename to resources/3rdparty/glpk-4.57/src/misc/triang.h index 1d5f484d7..1e50d44dc 100644 --- a/resources/3rdparty/glpk-4.53/src/misc/triang.h +++ b/resources/3rdparty/glpk-4.57/src/misc/triang.h @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2012-2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * diff --git a/resources/3rdparty/glpk-4.53/src/misc/wclique.c b/resources/3rdparty/glpk-4.57/src/misc/wclique.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/misc/wclique.c rename to resources/3rdparty/glpk-4.57/src/misc/wclique.c diff --git a/resources/3rdparty/glpk-4.53/src/misc/wclique.h b/resources/3rdparty/glpk-4.57/src/misc/wclique.h similarity index 94% rename from resources/3rdparty/glpk-4.53/src/misc/wclique.h rename to resources/3rdparty/glpk-4.57/src/misc/wclique.h index bc6853899..d52dc8052 100644 --- a/resources/3rdparty/glpk-4.53/src/misc/wclique.h +++ b/resources/3rdparty/glpk-4.57/src/misc/wclique.h @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2009, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2009-2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * diff --git a/resources/3rdparty/glpk-4.53/src/misc/wclique1.c b/resources/3rdparty/glpk-4.57/src/misc/wclique1.c similarity index 99% rename from resources/3rdparty/glpk-4.53/src/misc/wclique1.c rename to resources/3rdparty/glpk-4.57/src/misc/wclique1.c index ea36ddd73..c263a5e5a 100644 --- a/resources/3rdparty/glpk-4.53/src/misc/wclique1.c +++ b/resources/3rdparty/glpk-4.57/src/misc/wclique1.c @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2012-2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * diff --git a/resources/3rdparty/glpk-4.53/src/misc/wclique1.h b/resources/3rdparty/glpk-4.57/src/misc/wclique1.h similarity index 94% rename from resources/3rdparty/glpk-4.53/src/misc/wclique1.h rename to resources/3rdparty/glpk-4.57/src/misc/wclique1.h index 14e10cba5..588f32571 100644 --- a/resources/3rdparty/glpk-4.53/src/misc/wclique1.h +++ b/resources/3rdparty/glpk-4.57/src/misc/wclique1.h @@ -3,7 +3,7 @@ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2012-2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * diff --git a/resources/3rdparty/glpk-4.53/src/prob.h b/resources/3rdparty/glpk-4.57/src/prob.h similarity index 98% rename from resources/3rdparty/glpk-4.53/src/prob.h rename to resources/3rdparty/glpk-4.57/src/prob.h index 1b9236114..69dea0eb8 100644 --- a/resources/3rdparty/glpk-4.53/src/prob.h +++ b/resources/3rdparty/glpk-4.57/src/prob.h @@ -45,8 +45,10 @@ struct glp_prob glp_tree *tree; /* pointer to the search tree; set by the MIP solver when this object is used in the tree as a core MIP object */ +#if 0 /* 08/III-2014 */ void *parms; /* reserved for backward compatibility */ +#endif /*--------------------------------------------------------------*/ /* LP/MIP data */ char *name; @@ -90,8 +92,10 @@ struct glp_prob head[i] = k is the ordinal number of auxiliary (1 <= k <= m) or structural (m+1 <= k <= m+n) variable which corresponds to i-th basic variable xB[i], 1 <= i <= m */ +#if 0 /* 08/III-2014 */ glp_bfcp *bfcp; /* basis factorization control parameters; may be NULL */ +#endif BFD *bfd; /* BFD bfd[1:m,1:m]; */ /* basis factorization driver; may be NULL */ /*--------------------------------------------------------------*/ @@ -111,7 +115,7 @@ struct glp_prob double obj_val; /* objective function value */ int it_cnt; - /* simplex method iteration count; increased by one on performing + /* simplex method iteration count; increases by one on performing one simplex iteration */ int some; /* ordinal number of some auxiliary or structural variable having diff --git a/resources/3rdparty/glpk-4.53/src/proxy/main.c b/resources/3rdparty/glpk-4.57/src/proxy/main.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/proxy/main.c rename to resources/3rdparty/glpk-4.57/src/proxy/main.c diff --git a/resources/3rdparty/glpk-4.53/src/proxy/proxy.c b/resources/3rdparty/glpk-4.57/src/proxy/proxy.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/proxy/proxy.c rename to resources/3rdparty/glpk-4.57/src/proxy/proxy.c diff --git a/resources/3rdparty/glpk-4.53/src/proxy/proxy.h b/resources/3rdparty/glpk-4.57/src/proxy/proxy.h similarity index 100% rename from resources/3rdparty/glpk-4.53/src/proxy/proxy.h rename to resources/3rdparty/glpk-4.57/src/proxy/proxy.h diff --git a/resources/3rdparty/glpk-4.53/src/proxy/proxy1.c b/resources/3rdparty/glpk-4.57/src/proxy/proxy1.c similarity index 51% rename from resources/3rdparty/glpk-4.53/src/proxy/proxy1.c rename to resources/3rdparty/glpk-4.57/src/proxy/proxy1.c index ce96d9e80..b05fe8e4f 100644 --- a/resources/3rdparty/glpk-4.53/src/proxy/proxy1.c +++ b/resources/3rdparty/glpk-4.57/src/proxy/proxy1.c @@ -1,6 +1,25 @@ /* proxy1.c */ -/* (reserved for copyright notice) */ +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2013 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ #include "env.h" #include "glpios.h" diff --git a/resources/3rdparty/glpk-4.57/src/simplex/simplex.h b/resources/3rdparty/glpk-4.57/src/simplex/simplex.h new file mode 100644 index 000000000..48205881d --- /dev/null +++ b/resources/3rdparty/glpk-4.57/src/simplex/simplex.h @@ -0,0 +1,39 @@ +/* simplex.h */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2015 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef SIMPLEX_H +#define SIMPLEX_H + +#include "prob.h" + +#define spx_primal _glp_spx_primal +int spx_primal(glp_prob *P, const glp_smcp *parm); +/* driver to primal simplex method */ + +#define spy_dual _glp_spy_dual +int spy_dual(glp_prob *P, const glp_smcp *parm); +/* driver to dual simplex method */ + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.57/src/simplex/spxat.c b/resources/3rdparty/glpk-4.57/src/simplex/spxat.c new file mode 100644 index 000000000..3570a18c9 --- /dev/null +++ b/resources/3rdparty/glpk-4.57/src/simplex/spxat.c @@ -0,0 +1,265 @@ +/* spxat.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2015 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "spxat.h" + +/*********************************************************************** +* spx_alloc_at - allocate constraint matrix in sparse row-wise format +* +* This routine allocates the memory for arrays needed to represent the +* constraint matrix in sparse row-wise format. */ + +void spx_alloc_at(SPXLP *lp, SPXAT *at) +{ int m = lp->m; + int n = lp->n; + int nnz = lp->nnz; + at->ptr = talloc(1+m+1, int); + at->ind = talloc(1+nnz, int); + at->val = talloc(1+nnz, double); + at->work = talloc(1+n, double); + return; +} + +/*********************************************************************** +* spx_build_at - build constraint matrix in sparse row-wise format +* +* This routine builds sparse row-wise representation of the constraint +* matrix A using its sparse column-wise representation stored in the +* lp object, and stores the result in the at object. */ + +void spx_build_at(SPXLP *lp, SPXAT *at) +{ int m = lp->m; + int n = lp->n; + int nnz = lp->nnz; + int *A_ptr = lp->A_ptr; + int *A_ind = lp->A_ind; + double *A_val = lp->A_val; + int *AT_ptr = at->ptr; + int *AT_ind = at->ind; + double *AT_val = at->val; + int i, k, ptr, end, pos; + /* calculate AT_ptr[i] = number of non-zeros in i-th row */ + memset(&AT_ptr[1], 0, m * sizeof(int)); + for (k = 1; k <= n; k++) + { ptr = A_ptr[k]; + end = A_ptr[k+1]; + for (; ptr < end; ptr++) + AT_ptr[A_ind[ptr]]++; + } + /* set AT_ptr[i] to position after last element in i-th row */ + AT_ptr[1]++; + for (i = 2; i <= m; i++) + AT_ptr[i] += AT_ptr[i-1]; + xassert(AT_ptr[m] == nnz+1); + AT_ptr[m+1] = nnz+1; + /* build row-wise representation and re-arrange AT_ptr[i] */ + for (k = n; k >= 1; k--) + { /* copy elements from k-th column to corresponding rows */ + ptr = A_ptr[k]; + end = A_ptr[k+1]; + for (; ptr < end; ptr++) + { pos = --AT_ptr[A_ind[ptr]]; + AT_ind[pos] = k; + AT_val[pos] = A_val[ptr]; + } + } + xassert(AT_ptr[1] == 1); + return; +} + +/*********************************************************************** +* spx_at_prod - compute product y := y + s * A'* x +* +* This routine computes the product: +* +* y := y + s * A'* x, +* +* where A' is a matrix transposed to the mxn-matrix A of constraint +* coefficients, x is a m-vector, s is a scalar, y is a n-vector. +* +* The routine uses the row-wise representation of the matrix A and +* computes the product as a linear combination: +* +* y := y + s * (A'[1] * x[1] + ... + A'[m] * x[m]), +* +* where A'[i] is i-th row of A, 1 <= i <= m. */ + +void spx_at_prod(SPXLP *lp, SPXAT *at, double y[/*1+n*/], double s, + const double x[/*1+m*/]) +{ int m = lp->m; + int *AT_ptr = at->ptr; + int *AT_ind = at->ind; + double *AT_val = at->val; + int i, ptr, end; + double t; + for (i = 1; i <= m; i++) + { if (x[i] != 0.0) + { /* y := y + s * (i-th row of A) * x[i] */ + t = s * x[i]; + ptr = AT_ptr[i]; + end = AT_ptr[i+1]; + for (; ptr < end; ptr++) + y[AT_ind[ptr]] += AT_val[ptr] * t; + } + } + return; +} + +/*********************************************************************** +* spx_nt_prod1 - compute product y := y + s * N'* x +* +* This routine computes the product: +* +* y := y + s * N'* x, +* +* where N' is a matrix transposed to the mx(n-m)-matrix N composed +* from non-basic columns of the constraint matrix A, x is a m-vector, +* s is a scalar, y is (n-m)-vector. +* +* If the flag ign is non-zero, the routine ignores the input content +* of the array y assuming that y = 0. */ + +void spx_nt_prod1(SPXLP *lp, SPXAT *at, double y[/*1+n-m*/], int ign, + double s, const double x[/*1+m*/]) +{ int m = lp->m; + int n = lp->n; + int *head = lp->head; + double *work = at->work; + int j, k; + for (k = 1; k <= n; k++) + work[k] = 0.0; + if (!ign) + { for (j = 1; j <= n-m; j++) + work[head[m+j]] = y[j]; + } + spx_at_prod(lp, at, work, s, x); + for (j = 1; j <= n-m; j++) + y[j] = work[head[m+j]]; + return; +} + +/*********************************************************************** +* spx_eval_trow1 - compute i-th row of simplex table +* +* This routine computes i-th row of the current simplex table +* T = (T[i,j]) = - inv(B) * N, 1 <= i <= m, using representation of +* the constraint matrix A in row-wise format. +* +* The vector rho = (rho[j]), which is i-th row of the basis inverse +* inv(B), should be previously computed with the routine spx_eval_rho. +* It is assumed that elements of this vector are stored in the array +* locations rho[1], ..., rho[m]. +* +* There exist two ways to compute the simplex table row. +* +* 1. T[i,j], j = 1,...,n-m, is computed as inner product: +* +* m +* T[i,j] = - sum a[i,k] * rho[i], +* i=1 +* +* where N[j] = A[k] is a column of the constraint matrix corresponding +* to non-basic variable xN[j]. The estimated number of operations in +* this case is: +* +* n1 = (n - m) * (nnz(A) / n), +* +* (n - m) is the number of columns of N, nnz(A) / n is the average +* number of non-zeros in one column of A and, therefore, of N. +* +* 2. The simplex table row is computed as part of a linear combination +* of rows of A with coefficients rho[i] != 0. The estimated number +* of operations in this case is: +* +* n2 = nnz(rho) * (nnz(A) / m), +* +* where nnz(rho) is the number of non-zeros in the vector rho, +* nnz(A) / m is the average number of non-zeros in one row of A. +* +* If n1 < n2, the routine computes the simples table row using the +* first way (like the routine spx_eval_trow). Otherwise, the routine +* uses the second way calling the routine spx_nt_prod1. +* +* On exit components of the simplex table row are stored in the array +* locations trow[1], ... trow[n-m]. */ + +void spx_eval_trow1(SPXLP *lp, SPXAT *at, const double rho[/*1+m*/], + double trow[/*1+n-m*/]) +{ int m = lp->m; + int n = lp->n; + int nnz = lp->nnz; + int i, j, nnz_rho; + double cnt1, cnt2; + /* determine nnz(rho) */ + nnz_rho = 0; + for (i = 1; i <= m; i++) + { if (rho[i] != 0.0) + nnz_rho++; + } + /* estimate the number of operations for both ways */ + cnt1 = (double)(n - m) * ((double)nnz / (double)n); + cnt2 = (double)nnz_rho * ((double)nnz / (double)m); + /* compute i-th row of simplex table */ + if (cnt1 < cnt2) + { /* as inner products */ + int *A_ptr = lp->A_ptr; + int *A_ind = lp->A_ind; + double *A_val = lp->A_val; + int *head = lp->head; + int k, ptr, end; + double tij; + for (j = 1; j <= n-m; j++) + { k = head[m+j]; /* x[k] = xN[j] */ + /* compute t[i,j] = - N'[j] * pi */ + tij = 0.0; + ptr = A_ptr[k]; + end = A_ptr[k+1]; + for (; ptr < end; ptr++) + tij -= A_val[ptr] * rho[A_ind[ptr]]; + trow[j] = tij; + } + } + else + { /* as linear combination */ + spx_nt_prod1(lp, at, trow, 1, -1.0, rho); + } + return; +} + +/*********************************************************************** +* spx_free_at - deallocate constraint matrix in sparse row-wise format +* +* This routine deallocates the memory used for arrays of the program +* object at. */ + +void spx_free_at(SPXLP *lp, SPXAT *at) +{ xassert(lp == lp); + tfree(at->ptr); + tfree(at->ind); + tfree(at->val); + tfree(at->work); + return; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.57/src/simplex/spxat.h b/resources/3rdparty/glpk-4.57/src/simplex/spxat.h new file mode 100644 index 000000000..98d5b0033 --- /dev/null +++ b/resources/3rdparty/glpk-4.57/src/simplex/spxat.h @@ -0,0 +1,80 @@ +/* spxat.h */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2015 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef SPXAT_H +#define SPXAT_H + +#include "spxlp.h" + +typedef struct SPXAT SPXAT; + +struct SPXAT +{ /* mxn-matrix A of constraint coefficients in sparse row-wise + * format */ + int *ptr; /* int ptr[1+m+1]; */ + /* ptr[0] is not used; + * ptr[i], 1 <= i <= m, is starting position of i-th row in + * arrays ind and val; note that ptr[1] is always 1; + * ptr[m+1] indicates the position after the last element in + * arrays ind and val, i.e. ptr[m+1] = nnz+1, where nnz is the + * number of non-zero elements in matrix A; + * the length of i-th row (the number of non-zero elements in + * that row) can be calculated as ptr[i+1] - ptr[i] */ + int *ind; /* int ind[1+nnz]; */ + /* column indices */ + double *val; /* double val[1+nnz]; */ + /* non-zero element values */ + double *work; /* double work[1+n]; */ + /* working array */ +}; + +#define spx_alloc_at _glp_spx_alloc_at +void spx_alloc_at(SPXLP *lp, SPXAT *at); +/* allocate constraint matrix in sparse row-wise format */ + +#define spx_build_at _glp_spx_build_at +void spx_build_at(SPXLP *lp, SPXAT *at); +/* build constraint matrix in sparse row-wise format */ + +#define spx_at_prod _glp_spx_at_prod +void spx_at_prod(SPXLP *lp, SPXAT *at, double y[/*1+n*/], double s, + const double x[/*1+m*/]); +/* compute product y := y + s * A'* x */ + +#define spx_nt_prod1 _glp_spx_nt_prod1 +void spx_nt_prod1(SPXLP *lp, SPXAT *at, double y[/*1+n-m*/], int ign, + double s, const double x[/*1+m*/]); +/* compute product y := y + s * N'* x */ + +#define spx_eval_trow1 _glp_spx_eval_trow1 +void spx_eval_trow1(SPXLP *lp, SPXAT *at, const double rho[/*1+m*/], + double trow[/*1+n-m*/]); +/* compute i-th row of simplex table */ + +#define spx_free_at _glp_spx_free_at +void spx_free_at(SPXLP *lp, SPXAT *at); +/* deallocate constraint matrix in sparse row-wise format */ + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.57/src/simplex/spxchuzc.c b/resources/3rdparty/glpk-4.57/src/simplex/spxchuzc.c new file mode 100644 index 000000000..c60ccabc9 --- /dev/null +++ b/resources/3rdparty/glpk-4.57/src/simplex/spxchuzc.c @@ -0,0 +1,381 @@ +/* spxchuzc.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2015 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "spxchuzc.h" + +/*********************************************************************** +* spx_chuzc_sel - select eligible non-basic variables +* +* This routine selects eligible non-basic variables xN[j], whose +* reduced costs d[j] have "wrong" sign, i.e. changing such xN[j] in +* feasible direction improves (decreases) the objective function. +* +* Reduced costs of non-basic variables should be placed in the array +* locations d[1], ..., d[n-m]. +* +* Non-basic variable xN[j] is considered eligible if: +* +* d[j] <= -eps[j] and xN[j] can increase +* +* d[j] >= +eps[j] and xN[j] can decrease +* +* for +* +* eps[j] = tol + tol1 * |cN[j]|, +* +* where cN[j] is the objective coefficient at xN[j], tol and tol1 are +* specified tolerances. +* +* On exit the routine stores indices j of eligible non-basic variables +* xN[j] to the array locations list[1], ..., list[num] and returns the +* number of such variables 0 <= num <= n-m. (If the parameter list is +* specified as NULL, no indices are stored.) */ + +int spx_chuzc_sel(SPXLP *lp, const double d[/*1+n-m*/], double tol, + double tol1, int list[/*1+n-m*/]) +{ int m = lp->m; + int n = lp->n; + double *c = lp->c; + double *l = lp->l; + double *u = lp->u; + int *head = lp->head; + char *flag = lp->flag; + int j, k, num; + double ck, eps; + num = 0; + /* walk thru list of non-basic variables */ + for (j = 1; j <= n-m; j++) + { k = head[m+j]; /* x[k] = xN[j] */ + if (l[k] == u[k]) + { /* xN[j] is fixed variable; skip it */ + continue; + } + /* determine absolute tolerance eps[j] */ + ck = c[k]; + eps = tol + tol1 * (ck >= 0.0 ? +ck : -ck); + /* check if xN[j] is eligible */ + if (d[j] <= -eps) + { /* xN[j] should be able to increase */ + if (flag[j]) + { /* but its upper bound is active */ + continue; + } + } + else if (d[j] >= +eps) + { /* xN[j] should be able to decrease */ + if (!flag[j] && l[k] != -DBL_MAX) + { /* but its lower bound is active */ + continue; + } + } + else /* -eps < d[j] < +eps */ + { /* xN[j] does not affect the objective function within the + * specified tolerance */ + continue; + } + /* xN[j] is eligible non-basic variable */ + num++; + if (list != NULL) + list[num] = j; + } + return num; +} + +/*********************************************************************** +* spx_chuzc_std - choose non-basic variable (Dantzig's rule) +* +* This routine chooses most eligible non-basic variable xN[q] +* according to Dantzig's ("standard") rule: +* +* d[q] = max |d[j]|, +* j in J +* +* where J <= {1, ..., n-m} is the set of indices of eligible non-basic +* variables, d[j] is the reduced cost of non-basic variable xN[j] in +* the current basis. +* +* Reduced costs of non-basic variables should be placed in the array +* locations d[1], ..., d[n-m]. +* +* Indices of eligible non-basic variables j in J should be placed in +* the array locations list[1], ..., list[num], where num = |J| > 0 is +* the total number of such variables. +* +* On exit the routine returns q, the index of the non-basic variable +* xN[q] chosen. */ + +int spx_chuzc_std(SPXLP *lp, const double d[/*1+n-m*/], int num, + const int list[]) +{ int m = lp->m; + int n = lp->n; + int j, q, t; + double abs_dj, abs_dq; + xassert(0 < num && num <= n-m); + q = 0, abs_dq = -1.0; + for (t = 1; t <= num; t++) + { j = list[t]; + abs_dj = (d[j] >= 0.0 ? +d[j] : -d[j]); + if (abs_dq < abs_dj) + q = j, abs_dq = abs_dj; + } + xassert(q != 0); + return q; +} + +/*********************************************************************** +* spx_alloc_se - allocate pricing data block +* +* This routine allocates the memory for arrays used in the pricing +* data block. */ + +void spx_alloc_se(SPXLP *lp, SPXSE *se) +{ int m = lp->m; + int n = lp->n; + se->valid = 0; + se->refsp = talloc(1+n, char); + se->gamma = talloc(1+n-m, double); + se->work = talloc(1+m, double); + return; +} + +/*********************************************************************** +* spx_reset_refsp - reset reference space +* +* This routine resets (re-initializes) the reference space composing +* it from variables which are non-basic in the current basis, and sets +* all weights gamma[j] to 1. */ + +void spx_reset_refsp(SPXLP *lp, SPXSE *se) +{ int m = lp->m; + int n = lp->n; + int *head = lp->head; + char *refsp = se->refsp; + double *gamma = se->gamma; + int j, k; + se->valid = 1; + memset(&refsp[1], 0, n * sizeof(char)); + for (j = 1; j <= n-m; j++) + { k = head[m+j]; /* x[k] = xN[j] */ + refsp[k] = 1; + gamma[j] = 1.0; + } + return; +} + +/*********************************************************************** +* spx_eval_gamma_j - compute projected steepest edge weight directly +* +* This routine computes projected steepest edge weight gamma[j], +* 1 <= j <= n-m, for the current basis directly with the formula: +* +* m +* gamma[j] = delta[j] + sum eta[i] * T[i,j]**2, +* i=1 +* +* where T[i,j] is element of the current simplex table, and +* +* ( 1, if xB[i] is in the reference space +* eta[i] = { +* ( 0, otherwise +* +* ( 1, if xN[j] is in the reference space +* delta[j] = { +* ( 0, otherwise +* +* NOTE: For testing/debugging only. */ + +double spx_eval_gamma_j(SPXLP *lp, SPXSE *se, int j) +{ int m = lp->m; + int n = lp->n; + int *head = lp->head; + char *refsp = se->refsp; + double *tcol = se->work; + int i, k; + double gamma_j; + xassert(se->valid); + xassert(1 <= j && j <= n-m); + k = head[m+j]; /* x[k] = xN[j] */ + gamma_j = (refsp[k] ? 1.0 : 0.0); + spx_eval_tcol(lp, j, tcol); + for (i = 1; i <= m; i++) + { k = head[i]; /* x[k] = xB[i] */ + if (refsp[k]) + gamma_j += tcol[i] * tcol[i]; + } + return gamma_j; +} + +/*********************************************************************** +* spx_chuzc_pse - choose non-basic variable (projected steepest edge) +* +* This routine chooses most eligible non-basic variable xN[q] +* according to the projected steepest edge method: +* +* d[q]**2 d[j]**2 +* -------- = max -------- , +* gamma[q] j in J gamma[j] +* +* where J <= {1, ..., n-m} is the set of indices of eligible non-basic +* variable, d[j] is the reduced cost of non-basic variable xN[j] in +* the current basis, gamma[j] is the projected steepest edge weight. +* +* Reduced costs of non-basic variables should be placed in the array +* locations d[1], ..., d[n-m]. +* +* Indices of eligible non-basic variables j in J should be placed in +* the array locations list[1], ..., list[num], where num = |J| > 0 is +* the total number of such variables. +* +* On exit the routine returns q, the index of the non-basic variable +* xN[q] chosen. */ + +int spx_chuzc_pse(SPXLP *lp, SPXSE *se, const double d[/*1+n-m*/], + int num, const int list[]) +{ int m = lp->m; + int n = lp->n; + double *gamma = se->gamma; + int j, q, t; + double best, temp; + xassert(se->valid); + xassert(0 < num && num <= n-m); + q = 0, best = -1.0; + for (t = 1; t <= num; t++) + { j = list[t]; + /* FIXME */ + if (gamma[j] < DBL_EPSILON) + temp = 0.0; + else + temp = (d[j] * d[j]) / gamma[j]; + if (best < temp) + q = j, best = temp; + } + xassert(q != 0); + return q; +} + +/*********************************************************************** +* spx_update_gamma - update projected steepest edge weights exactly +* +* This routine updates the vector gamma = (gamma[j]) of projected +* steepest edge weights exactly, for the adjacent basis. +* +* On entry to the routine the content of the se object should be valid +* and should correspond to the current basis. +* +* The parameter 1 <= p <= m specifies basic variable xB[p] which +* becomes non-basic variable xN[q] in the adjacent basis. +* +* The parameter 1 <= q <= n-m specified non-basic variable xN[q] which +* becomes basic variable xB[p] in the adjacent basis. +* +* It is assumed that the array trow contains elements of p-th (pivot) +* row T'[p] of the simplex table in locations trow[1], ..., trow[n-m]. +* It is also assumed that the array tcol contains elements of q-th +* (pivot) column T[q] of the simple table in locations tcol[1], ..., +* tcol[m]. (These row and column should be computed for the current +* basis.) +* +* For details about the formulae used see the program documentation. +* +* The routine also computes the relative error: +* +* e = |gamma[q] - gamma'[q]| / (1 + |gamma[q]|), +* +* where gamma'[q] is the weight for xN[q] on entry to the routine, +* and returns e on exit. (If e happens to be large enough, the calling +* program may reset the reference space, since other weights also may +* be inaccurate.) */ + +double spx_update_gamma(SPXLP *lp, SPXSE *se, int p, int q, + const double trow[/*1+n-m*/], const double tcol[/*1+m*/]) +{ int m = lp->m; + int n = lp->n; + int *head = lp->head; + char *refsp = se->refsp; + double *gamma = se->gamma; + double *u = se->work; + int i, j, k, ptr, end; + double gamma_q, delta_q, e, r, s, t1, t2; + xassert(se->valid); + xassert(1 <= p && p <= m); + xassert(1 <= q && q <= n-m); + /* compute gamma[q] in current basis more accurately; also + * compute auxiliary vector u */ + k = head[m+q]; /* x[k] = xN[q] */ + gamma_q = delta_q = (refsp[k] ? 1.0 : 0.0); + for (i = 1; i <= m; i++) + { k = head[i]; /* x[k] = xB[i] */ + if (refsp[k]) + { gamma_q += tcol[i] * tcol[i]; + u[i] = tcol[i]; + } + else + u[i] = 0.0; + } + bfd_btran(lp->bfd, u); + /* compute relative error in gamma[q] */ + e = fabs(gamma_q - gamma[q]) / (1.0 + gamma_q); + /* compute new gamma[q] */ + gamma[q] = gamma_q / (tcol[p] * tcol[p]); + /* compute new gamma[j] for all j != q */ + for (j = 1; j <= n-m; j++) + { if (j == q) + continue; + if (-1e-9 < trow[j] && trow[j] < +1e-9) + { /* T[p,j] is close to zero; gamma[j] is not changed */ + continue; + } + /* compute r[j] = T[p,j] / T[p,q] */ + r = trow[j] / tcol[p]; + /* compute inner product s[j] = N'[j] * u, where N[j] = A[k] + * is constraint matrix column corresponding to xN[j] */ + s = 0.0; + k = head[m+j]; /* x[k] = xN[j] */ + ptr = lp->A_ptr[k]; + end = lp->A_ptr[k+1]; + for (; ptr < end; ptr++) + s += lp->A_val[ptr] * u[lp->A_ind[ptr]]; + /* compute new gamma[j] */ + t1 = gamma[j] + r * (r * gamma_q + s + s); + t2 = (refsp[k] ? 1.0 : 0.0) + delta_q * r * r; + gamma[j] = (t1 >= t2 ? t1 : t2); + } + return e; +} + +/*********************************************************************** +* spx_free_se - deallocate pricing data block +* +* This routine deallocates the memory used for arrays in the pricing +* data block. */ + +void spx_free_se(SPXLP *lp, SPXSE *se) +{ xassert(lp == lp); + tfree(se->refsp); + tfree(se->gamma); + tfree(se->work); + return; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.57/src/simplex/spxchuzc.h b/resources/3rdparty/glpk-4.57/src/simplex/spxchuzc.h new file mode 100644 index 000000000..c09cca9aa --- /dev/null +++ b/resources/3rdparty/glpk-4.57/src/simplex/spxchuzc.h @@ -0,0 +1,85 @@ +/* spxchuzc.h */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2015 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef SPXCHUZC_H +#define SPXCHUZC_H + +#include "spxlp.h" + +#define spx_chuzc_sel _glp_spx_chuzc_sel +int spx_chuzc_sel(SPXLP *lp, const double d[/*1+n-m*/], double tol, + double tol1, int list[/*1+n-m*/]); +/* select eligible non-basic variables */ + +#define spx_chuzc_std _glp_spx_chuzc_std +int spx_chuzc_std(SPXLP *lp, const double d[/*1+n-m*/], int num, + const int list[]); +/* choose non-basic variable (Dantzig's rule) */ + +typedef struct SPXSE SPXSE; + +struct SPXSE +{ /* projected steepest edge and Devex pricing data block */ + int valid; + /* content validity flag */ + char *refsp; /* char refsp[1+n]; */ + /* refsp[0] is not used; + * refsp[k], 1 <= k <= n, is the flag meaning that variable x[k] + * is in the reference space */ + double *gamma; /* double gamma[1+n-m]; */ + /* gamma[0] is not used; + * gamma[j], 1 <= j <= n-m, is the weight for reduced cost d[j] + * of non-basic variable xN[j] in the current basis */ + double *work; /* double work[1+m]; */ + /* working array */ +}; + +#define spx_alloc_se _glp_spx_alloc_se +void spx_alloc_se(SPXLP *lp, SPXSE *se); +/* allocate pricing data block */ + +#define spx_reset_refsp _glp_spx_reset_refsp +void spx_reset_refsp(SPXLP *lp, SPXSE *se); +/* reset reference space */ + +#define spx_eval_gamma_j _glp_spx_eval_gamma_j +double spx_eval_gamma_j(SPXLP *lp, SPXSE *se, int j); +/* compute projeted steepest edge weight directly */ + +#define spx_chuzc_pse _glp_spx_chuzc_pse +int spx_chuzc_pse(SPXLP *lp, SPXSE *se, const double d[/*1+n-m*/], + int num, const int list[]); +/* choose non-basic variable (projected steepest edge) */ + +#define spx_update_gamma _glp_spx_update_gamma +double spx_update_gamma(SPXLP *lp, SPXSE *se, int p, int q, + const double trow[/*1+n-m*/], const double tcol[/*1+m*/]); +/* update projected steepest edge weights exactly */ + +#define spx_free_se _glp_spx_free_se +void spx_free_se(SPXLP *lp, SPXSE *se); +/* deallocate pricing data block */ + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.57/src/simplex/spxchuzr.c b/resources/3rdparty/glpk-4.57/src/simplex/spxchuzr.c new file mode 100644 index 000000000..49db8bd14 --- /dev/null +++ b/resources/3rdparty/glpk-4.57/src/simplex/spxchuzr.c @@ -0,0 +1,388 @@ +/* spxchuzr.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2015 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "spxchuzr.h" + +/*********************************************************************** +* spx_chuzr_std - choose basic variable (textbook ratio test) +* +* This routine implements an improved textbook ratio test to choose +* basic variable xB[p]. +* +* The parameter phase specifies the search phase: +* +* 1 - searching for feasible basic solution. In this case the routine +* uses artificial bounds of basic variables that correspond to +* breakpoints of the penalty function: +* +* ( lB[i], if cB[i] = 0 +* ( +* lB'[i] = { uB[i], if cB[i] > 0 +* ( +* ( -inf, if cB[i] < 0 +* +* ( uB[i], if cB[i] = 0 +* ( +* uB'[i] = { +inf, if cB[i] > 0 +* ( +* ( lB[i], if cB[i] < 0 +* +* where lB[i] and uB[i] are original bounds of variable xB[i], +* cB[i] is the penalty (objective) coefficient of that variable. +* +* 2 - searching for optimal basic solution. In this case the routine +* uses original bounds of basic variables. +* +* Current values of basic variables should be placed in the array +* locations beta[1], ..., beta[m]. +* +* The parameter 1 <= q <= n-m specifies the index of non-basic +* variable xN[q] chosen. +* +* The parameter s specifies the direction in which xN[q] changes: +* s = +1.0 means xN[q] increases, and s = -1.0 means xN[q] decreases. +* (Thus, the corresponding ray parameter is theta = s (xN[q] - f[q]), +* where f[q] is the active bound of xN[q] in the current basis.) +* +* Elements of q-th simplex table column T[q] = (t[i,q]) corresponding +* to non-basic variable xN[q] should be placed in the array locations +* tcol[1], ..., tcol[m]. +* +* The parameter tol_piv specifies a tolerance for elements of the +* simplex table column T[q]. If |t[i,q]| < tol_piv, basic variable +* xB[i] is skipped, i.e. it is assumed that it does not depend on the +* ray parameter theta. +* +* The parameters tol and tol1 specify tolerances used to increase the +* choice freedom by simulating an artificial degeneracy as follows. +* If beta[i] <= lB[i] + delta[i], where delta[i] = tol + tol1 |lB[i]|, +* it is assumed that beta[i] is exactly the same as lB[i]. Similarly, +* if beta[i] >= uB[i] - delta[i], where delta[i] = tol + tol1 |uB[i]|, +* it is assumed that beta[i] is exactly the same as uB[i]. +* +* The routine determines the index 1 <= p <= m of basic variable xB[p] +* that reaches its (lower or upper) bound first on increasing the ray +* parameter theta, stores the bound flag (0 - lower bound or fixed +* value, 1 - upper bound) to the location pointed to by the pointer +* p_flag, and returns the index p. If non-basic variable xN[q] is +* double-bounded and reaches its opposite bound first, the routine +* returns (-1). And if the ray parameter may increase unlimitedly, the +* routine returns zero. +* +* Should note that the bound flag stored to the location pointed to by +* p_flag corresponds to the original (not artficial) bound of variable +* xB[p] and defines the active bound flag lp->flag[q] to be set in the +* adjacent basis for that basic variable. */ + +int spx_chuzr_std(SPXLP *lp, int phase, const double beta[/*1+m*/], + int q, double s, const double tcol[/*1+m*/], int *p_flag, + double tol_piv, double tol, double tol1) +{ int m = lp->m; + int n = lp->n; + double *c = lp->c; + double *l = lp->l; + double *u = lp->u; + int *head = lp->head; + int i, i_flag, k, p; + double alfa, biga, delta, lk, uk, teta, teta_min; + xassert(phase == 1 || phase == 2); + xassert(1 <= q && q <= n-m); + xassert(s == +1.0 || s == -1.0); + /* determine initial teta_min */ + k = head[m+q]; /* x[k] = xN[q] */ + if (l[k] == -DBL_MAX || u[k] == +DBL_MAX) + { /* xN[q] has no opposite bound */ + p = 0, *p_flag = 0, teta_min = DBL_MAX, biga = 0.0; + } + else + { /* xN[q] have both lower and upper bounds */ + p = -1, *p_flag = 0, teta_min = fabs(l[k] - u[k]), biga = 1.0; + } + /* walk thru the list of basic variables */ + for (i = 1; i <= m; i++) + { k = head[i]; /* x[k] = xB[i] */ + /* determine alfa such that delta xB[i] = alfa * teta */ + alfa = s * tcol[i]; + if (alfa <= -tol_piv) + { /* xB[i] decreases */ + /* determine actual lower bound of xB[i] */ + if (phase == 1 && c[k] < 0.0) + { /* xB[i] has no actual lower bound */ + continue; + } + else if (phase == 1 && c[k] > 0.0) + { /* actual lower bound of xB[i] is its upper bound */ + lk = u[k]; + xassert(lk != +DBL_MAX); + i_flag = 1; + } + else + { /* actual lower bound of xB[i] is its original bound */ + lk = l[k]; + if (lk == -DBL_MAX) + continue; + i_flag = 0; + } + /* determine teta on which xB[i] reaches its lower bound */ + delta = tol + tol1 * (lk >= 0.0 ? +lk : -lk); + if (beta[i] <= lk + delta) + teta = 0.0; + else + teta = (lk - beta[i]) / alfa; + } + else if (alfa >= +tol_piv) + { /* xB[i] increases */ + /* determine actual upper bound of xB[i] */ + if (phase == 1 && c[k] < 0.0) + { /* actual upper bound of xB[i] is its lower bound */ + uk = l[k]; + xassert(uk != -DBL_MAX); + i_flag = 0; + } + else if (phase == 1 && c[k] > 0.0) + { /* xB[i] has no actual upper bound */ + continue; + } + else + { /* actual upper bound of xB[i] is its original bound */ + uk = u[k]; + if (uk == +DBL_MAX) + continue; + i_flag = 1; + } + /* determine teta on which xB[i] reaches its upper bound */ + delta = tol + tol1 * (uk >= 0.0 ? +uk : -uk); + if (beta[i] >= uk - delta) + teta = 0.0; + else + teta = (uk - beta[i]) / alfa; + } + else + { /* xB[i] does not depend on teta */ + continue; + } + /* choose basic variable xB[p] for which teta is minimal */ + xassert(teta >= 0.0); + alfa = (alfa >= 0.0 ? +alfa : -alfa); + if (teta_min > teta || (teta_min == teta && biga < alfa)) + p = i, *p_flag = i_flag, teta_min = teta, biga = alfa; + } + /* if xB[p] is fixed variable, adjust its bound flag */ + if (p > 0) + { k = head[p]; + if (l[k] == u[k]) + *p_flag = 0; + } + return p; +} + +/*********************************************************************** +* spx_chuzr_harris - choose basic variable (Harris' ratio test) +* +* This routine implements Harris' ratio test to choose basic variable +* xB[p]. +* +* All the parameters, except tol and tol1, as well as the returned +* value have the same meaning as for the routine spx_chuzr_std (see +* above). +* +* The parameters tol and tol1 specify tolerances on bound violations +* for basic variables. For the lower bound of basic variable xB[i] the +* tolerance is delta[i] = tol + tol1 |lB[i]|, and for the upper bound +* the tolerance is delta[i] = tol + tol1 |uB[i]|. */ + +int spx_chuzr_harris(SPXLP *lp, int phase, const double beta[/*1+m*/], + int q, double s, const double tcol[/*1+m*/], int *p_flag, + double tol_piv, double tol, double tol1) +{ int m = lp->m; + int n = lp->n; + double *c = lp->c; + double *l = lp->l; + double *u = lp->u; + int *head = lp->head; + int i, i_flag, k, p; + double alfa, biga, delta, lk, uk, teta, teta_min; + xassert(phase == 1 || phase == 2); + xassert(1 <= q && q <= n-m); + xassert(s == +1.0 || s == -1.0); + /*--------------------------------------------------------------*/ + /* first pass: determine teta_min for relaxed bounds */ + /*--------------------------------------------------------------*/ + teta_min = DBL_MAX; + /* walk thru the list of basic variables */ + for (i = 1; i <= m; i++) + { k = head[i]; /* x[k] = xB[i] */ + /* determine alfa such that delta xB[i] = alfa * teta */ + alfa = s * tcol[i]; + if (alfa <= -tol_piv) + { /* xB[i] decreases */ + /* determine actual lower bound of xB[i] */ + if (phase == 1 && c[k] < 0.0) + { /* xB[i] has no actual lower bound */ + continue; + } + else if (phase == 1 && c[k] > 0.0) + { /* actual lower bound of xB[i] is its upper bound */ + lk = u[k]; + xassert(lk != +DBL_MAX); + } + else + { /* actual lower bound of xB[i] is its original bound */ + lk = l[k]; + if (lk == -DBL_MAX) + continue; + } + /* determine teta on which xB[i] reaches its relaxed lower + * bound */ + delta = tol + tol1 * (lk >= 0.0 ? +lk : -lk); + if (beta[i] < lk) + teta = - delta / alfa; + else + teta = ((lk - delta) - beta[i]) / alfa; + } + else if (alfa >= +tol_piv) + { /* xB[i] increases */ + /* determine actual upper bound of xB[i] */ + if (phase == 1 && c[k] < 0.0) + { /* actual upper bound of xB[i] is its lower bound */ + uk = l[k]; + xassert(uk != -DBL_MAX); + } + else if (phase == 1 && c[k] > 0.0) + { /* xB[i] has no actual upper bound */ + continue; + } + else + { /* actual upper bound of xB[i] is its original bound */ + uk = u[k]; + if (uk == +DBL_MAX) + continue; + } + /* determine teta on which xB[i] reaches its relaxed upper + * bound */ + delta = tol + tol1 * (uk >= 0.0 ? +uk : -uk); + if (beta[i] > uk) + teta = + delta / alfa; + else + teta = ((uk + delta) - beta[i]) / alfa; + } + else + { /* xB[i] does not depend on teta */ + continue; + } + xassert(teta >= 0.0); + if (teta_min > teta) + teta_min = teta; + } + /*--------------------------------------------------------------*/ + /* second pass: choose basic variable xB[p] */ + /*--------------------------------------------------------------*/ + k = head[m+q]; /* x[k] = xN[q] */ + if (l[k] != -DBL_MAX && u[k] != +DBL_MAX) + { /* xN[q] has both lower and upper bounds */ + if (fabs(l[k] - u[k]) <= teta_min) + { /* and reaches its opposite bound */ + p = -1, *p_flag = 0; + goto done; + } + } + if (teta_min == DBL_MAX) + { /* teta may increase unlimitedly */ + p = 0, *p_flag = 0; + goto done; + } + /* nothing is chosen so far */ + p = 0, *p_flag = 0, biga = 0.0; + /* walk thru the list of basic variables */ + for (i = 1; i <= m; i++) + { k = head[i]; /* x[k] = xB[i] */ + /* determine alfa such that delta xB[i] = alfa * teta */ + alfa = s * tcol[i]; + if (alfa <= -tol_piv) + { /* xB[i] decreases */ + /* determine actual lower bound of xB[i] */ + if (phase == 1 && c[k] < 0.0) + { /* xB[i] has no actual lower bound */ + continue; + } + else if (phase == 1 && c[k] > 0.0) + { /* actual lower bound of xB[i] is its upper bound */ + lk = u[k]; + xassert(lk != +DBL_MAX); + i_flag = 1; + } + else + { /* actual lower bound of xB[i] is its original bound */ + lk = l[k]; + if (lk == -DBL_MAX) + continue; + i_flag = 0; + } + /* determine teta on which xB[i] reaches its lower bound */ + teta = (lk - beta[i]) / alfa; + } + else if (alfa >= +tol_piv) + { /* xB[i] increases */ + /* determine actual upper bound of xB[i] */ + if (phase == 1 && c[k] < 0.0) + { /* actual upper bound of xB[i] is its lower bound */ + uk = l[k]; + xassert(uk != -DBL_MAX); + i_flag = 0; + } + else if (phase == 1 && c[k] > 0.0) + { /* xB[i] has no actual upper bound */ + continue; + } + else + { /* actual upper bound of xB[i] is its original bound */ + uk = u[k]; + if (uk == +DBL_MAX) + continue; + i_flag = 1; + } + /* determine teta on which xB[i] reaches its upper bound */ + teta = (uk - beta[i]) / alfa; + } + else + { /* xB[i] does not depend on teta */ + continue; + } + /* choose basic variable for which teta is not greater than + * teta_min determined for relaxed bounds and which has best + * (largest in magnitude) pivot */ + alfa = (alfa >= 0.0 ? +alfa : -alfa); + if (teta <= teta_min && biga < alfa) + p = i, *p_flag = i_flag, biga = alfa; + } + /* something must be chosen */ + xassert(1 <= p && p <= m); + /* if xB[p] is fixed variable, adjust its bound flag */ + k = head[p]; + if (l[k] == u[k]) + *p_flag = 0; +done: return p; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.57/src/simplex/spxchuzr.h b/resources/3rdparty/glpk-4.57/src/simplex/spxchuzr.h new file mode 100644 index 000000000..74f6e444a --- /dev/null +++ b/resources/3rdparty/glpk-4.57/src/simplex/spxchuzr.h @@ -0,0 +1,43 @@ +/* spxchuzr.h */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2015 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef SPXCHUZR_H +#define SPXCHUZR_H + +#include "spxlp.h" + +#define spx_chuzr_std _glp_spx_chuzr_std +int spx_chuzr_std(SPXLP *lp, int phase, const double beta[/*1+m*/], + int q, double s, const double tcol[/*1+m*/], int *p_flag, + double tol_piv, double tol, double tol1); +/* choose basic variable (textbook ratio test) */ + +#define spx_chuzr_harris _glp_spx_chuzr_harris +int spx_chuzr_harris(SPXLP *lp, int phase, const double beta[/*1+m*/], + int q, double s, const double tcol[/*1+m*/], int *p_flag, + double tol_piv, double tol, double tol1); +/* choose basic variable (Harris' ratio test) */ + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.57/src/simplex/spxlp.c b/resources/3rdparty/glpk-4.57/src/simplex/spxlp.c new file mode 100644 index 000000000..fe788d84d --- /dev/null +++ b/resources/3rdparty/glpk-4.57/src/simplex/spxlp.c @@ -0,0 +1,674 @@ +/* spxlp.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2015 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "spxlp.h" + +/*********************************************************************** +* spx_factorize - compute factorization of current basis matrix +* +* This routine computes factorization of the current basis matrix B. +* +* If the factorization has been successfully computed, the routine +* validates it and returns zero. Otherwise, the routine invalidates +* the factorization and returns the code provided by the factorization +* driver (bfd_factorize). */ + +static int jth_col(void *info, int j, int ind[], double val[]) +{ /* provide column B[j] */ + SPXLP *lp = info; + int m = lp->m; + int *A_ptr = lp->A_ptr; + int *head = lp->head; + int k, ptr, len; + xassert(1 <= j && j <= m); + k = head[j]; /* x[k] = xB[j] */ + ptr = A_ptr[k]; + len = A_ptr[k+1] - ptr; + memcpy(&ind[1], &lp->A_ind[ptr], len * sizeof(int)); + memcpy(&val[1], &lp->A_val[ptr], len * sizeof(double)); + return len; +} + +int spx_factorize(SPXLP *lp) +{ int ret; + ret = bfd_factorize(lp->bfd, lp->m, jth_col, lp); + lp->valid = (ret == 0); + return ret; +} + +/*********************************************************************** +* spx_eval_beta - compute current values of basic variables +* +* This routine computes vector beta = (beta[i]) of current values of +* basic variables xB = (xB[i]). (Factorization of the current basis +* matrix should be valid.) +* +* First the routine computes a modified vector of right-hand sides: +* +* n-m +* y = b - N * f = b - sum N[j] * f[j], +* j=1 +* +* where b = (b[i]) is the original vector of right-hand sides, N is +* a matrix composed from columns of the original constraint matrix A, +* which (columns) correspond to non-basic variables, f = (f[j]) is the +* vector of active bounds of non-basic variables xN = (xN[j]), +* N[j] = A[k] is a column of matrix A corresponding to non-basic +* variable xN[j] = x[k], f[j] is current active bound lN[j] = l[k] or +* uN[j] = u[k] of non-basic variable xN[j] = x[k]. The matrix-vector +* product N * f is computed as a linear combination of columns of N, +* so if f[j] = 0, column N[j] can be skipped. +* +* Then the routine performs FTRAN to compute the vector beta: +* +* beta = inv(B) * y. +* +* On exit the routine stores components of the vector beta to array +* locations beta[1], ..., beta[m]. */ + +void spx_eval_beta(SPXLP *lp, double beta[/*1+m*/]) +{ int m = lp->m; + int n = lp->n; + int *A_ptr = lp->A_ptr; + int *A_ind = lp->A_ind; + double *A_val = lp->A_val; + double *b = lp->b; + double *l = lp->l; + double *u = lp->u; + int *head = lp->head; + char *flag = lp->flag; + int j, k, ptr, end; + double fj, *y; + /* compute y = b - N * xN */ + /* y := b */ + y = beta; + memcpy(&y[1], &b[1], m * sizeof(double)); + /* y := y - N * f */ + for (j = 1; j <= n-m; j++) + { k = head[m+j]; /* x[k] = xN[j] */ + /* f[j] := active bound of xN[j] */ + fj = flag[j] ? u[k] : l[k]; + if (fj == 0.0 || fj == -DBL_MAX) + { /* either xN[j] has zero active bound or it is unbounded; + * in the latter case its value is assumed to be zero */ + continue; + } + /* y := y - N[j] * f[j] */ + ptr = A_ptr[k]; + end = A_ptr[k+1]; + for (; ptr < end; ptr++) + y[A_ind[ptr]] -= A_val[ptr] * fj; + } + /* compute beta = inv(B) * y */ + xassert(lp->valid); + bfd_ftran(lp->bfd, beta); + return; +} + +/*********************************************************************** +* spx_eval_obj - compute current value of objective function +* +* This routine computes the value of the objective function in the +* current basic solution: +* +* z = cB'* beta + cN'* f + c[0] = +* +* m n-m +* = sum cB[i] * beta[i] + sum cN[j] * f[j] + c[0], +* i=1 j=1 +* +* where cB = (cB[i]) is the vector of objective coefficients at basic +* variables, beta = (beta[i]) is the vector of current values of basic +* variables, cN = (cN[j]) is the vector of objective coefficients at +* non-basic variables, f = (f[j]) is the vector of current active +* bounds of non-basic variables, c[0] is the constant term of the +* objective function. +* +* It as assumed that components of the vector beta are stored in the +* array locations beta[1], ..., beta[m]. */ + +double spx_eval_obj(SPXLP *lp, const double beta[/*1+m*/]) +{ int m = lp->m; + int n = lp->n; + double *c = lp->c; + double *l = lp->l; + double *u = lp->u; + int *head = lp->head; + char *flag = lp->flag; + int i, j, k; + double fj, z; + /* compute z = cB'* beta + cN'* f + c0 */ + /* z := c0 */ + z = c[0]; + /* z := z + cB'* beta */ + for (i = 1; i <= m; i++) + { k = head[i]; /* x[k] = xB[i] */ + z += c[k] * beta[i]; + } + /* z := z + cN'* f */ + for (j = 1; j <= n-m; j++) + { k = head[m+j]; /* x[k] = xN[j] */ + /* f[j] := active bound of xN[j] */ + fj = flag[j] ? u[k] : l[k]; + if (fj == 0.0 || fj == -DBL_MAX) + { /* either xN[j] has zero active bound or it is unbounded; + * in the latter case its value is assumed to be zero */ + continue; + } + z += c[k] * fj; + } + return z; +} + +/*********************************************************************** +* spx_eval_pi - compute simplex multipliers in current basis +* +* This routine computes vector pi = (pi[i]) of simplex multipliers in +* the current basis. (Factorization of the current basis matrix should +* be valid.) +* +* The vector pi is computed by performing BTRAN: +* +* pi = inv(B') * cB, +* +* where cB = (cB[i]) is the vector of objective coefficients at basic +* variables xB = (xB[i]). +* +* On exit components of vector pi are stored in the array locations +* pi[1], ..., pi[m]. */ + +void spx_eval_pi(SPXLP *lp, double pi[/*1+m*/]) +{ int m = lp->m; + double *c = lp->c; + int *head = lp->head; + int i; + double *cB; + /* construct cB */ + cB = pi; + for (i = 1; i <= m; i++) + cB[i] = c[head[i]]; + /* compute pi = inv(B) * cB */ + bfd_btran(lp->bfd, pi); + return; +} + +/*********************************************************************** +* spx_eval_dj - compute reduced cost of j-th non-basic variable +* +* This routine computes reduced cost d[j] of non-basic variable +* xN[j] = x[k], 1 <= j <= n-m, in the current basic solution: +* +* d[j] = c[k] - A'[k] * pi, +* +* where c[k] is the objective coefficient at x[k], A[k] is k-th column +* of the constraint matrix, pi is the vector of simplex multipliers in +* the current basis. +* +* It as assumed that components of the vector pi are stored in the +* array locations pi[1], ..., pi[m]. */ + +double spx_eval_dj(SPXLP *lp, const double pi[/*1+m*/], int j) +{ int m = lp->m; + int n = lp->n; + int *A_ptr = lp->A_ptr; + int *A_ind = lp->A_ind; + double *A_val = lp->A_val; + int k, ptr, end; + double dj; + xassert(1 <= j && j <= n-m); + k = lp->head[m+j]; /* x[k] = xN[j] */ + /* dj := c[k] */ + dj = lp->c[k]; + /* dj := dj - A'[k] * pi */ + ptr = A_ptr[k]; + end = A_ptr[k+1]; + for (; ptr < end; ptr++) + dj -= A_val[ptr] * pi[A_ind[ptr]]; + return dj; +} + +/*********************************************************************** +* spx_eval_tcol - compute j-th column of simplex table +* +* This routine computes j-th column of the current simplex table +* T = (T[i,j]) = - inv(B) * N, 1 <= j <= n-m. (Factorization of the +* current basis matrix should be valid.) +* +* The simplex table column is computed by performing FTRAN: +* +* tcol = - inv(B) * N[j], +* +* where B is the current basis matrix, N[j] = A[k] is a column of the +* constraint matrix corresponding to non-basic variable xN[j] = x[k]. +* +* On exit components of the simplex table column are stored in the +* array locations tcol[1], ... tcol[m]. */ + +void spx_eval_tcol(SPXLP *lp, int j, double tcol[/*1+m*/]) +{ int m = lp->m; + int n = lp->n; + int *A_ptr = lp->A_ptr; + int *A_ind = lp->A_ind; + double *A_val = lp->A_val; + int *head = lp->head; + int i, k, ptr, end; + xassert(1 <= j && j <= n-m); + k = head[m+j]; /* x[k] = xN[j] */ + /* compute tcol = - inv(B) * N[j] */ + for (i = 1; i <= m; i++) + tcol[i] = 0.0; + ptr = A_ptr[k]; + end = A_ptr[k+1]; + for (; ptr < end; ptr++) + tcol[A_ind[ptr]] = -A_val[ptr]; + bfd_ftran(lp->bfd, tcol); + return; +} + +/*********************************************************************** +* spx_eval_rho - compute i-th row of basis matrix inverse +* +* This routine computes i-th row of the matrix inv(B), where B is +* the current basis matrix, 1 <= i <= m. (Factorization of the current +* basis matrix should be valid.) +* +* The inverse row is computed by performing BTRAN: +* +* rho = inv(B') * e[i], +* +* where e[i] is i-th column of unity matrix. +* +* On exit components of the row are stored in the array locations +* row[1], ..., row[m]. */ + +void spx_eval_rho(SPXLP *lp, int i, double rho[/*1+m*/]) +{ int m = lp->m; + int j; + xassert(1 <= i && i <= m); + /* compute rho = inv(B') * e[i] */ + for (j = 1; j <= m; j++) + rho[j] = 0.0; + rho[i] = 1.0; + bfd_btran(lp->bfd, rho); + return; +} + +/*********************************************************************** +* spx_eval_tij - compute element T[i,j] of simplex table +* +* This routine computes element T[i,j] of the current simplex table +* T = - inv(B) * N, 1 <= i <= m, 1 <= j <= n-m, with the following +* formula: +* +* T[i,j] = - N'[j] * rho, (1) +* +* where N[j] = A[k] is a column of the constraint matrix corresponding +* to non-basic variable xN[j] = x[k], rho is i-th row of the inverse +* matrix inv(B). +* +* It as assumed that components of the inverse row rho = (rho[j]) are +* stored in the array locations rho[1], ..., rho[m]. */ + +double spx_eval_tij(SPXLP *lp, const double rho[/*1+m*/], int j) +{ int m = lp->m; + int n = lp->n; + int *A_ptr = lp->A_ptr; + int *A_ind = lp->A_ind; + double *A_val = lp->A_val; + int k, ptr, end; + double tij; + xassert(1 <= j && j <= n-m); + k = lp->head[m+j]; /* x[k] = xN[j] */ + /* compute t[i,j] = - N'[j] * pi */ + tij = 0.0; + ptr = A_ptr[k]; + end = A_ptr[k+1]; + for (; ptr < end; ptr++) + tij -= A_val[ptr] * rho[A_ind[ptr]]; + return tij; +} + +/*********************************************************************** +* spx_eval_trow - compute i-th row of simplex table +* +* This routine computes i-th row of the current simplex table +* T = (T[i,j]) = - inv(B) * N, 1 <= i <= m. +* +* Elements of the row T[i] = (T[i,j]), j = 1, ..., n-m, are computed +* directly with the routine spx_eval_tij. +* +* The vector rho = (rho[j]), which is i-th row of the basis inverse +* inv(B), should be previously computed with the routine spx_eval_rho. +* It is assumed that elements of this vector are stored in the array +* locations rho[1], ..., rho[m]. +* +* On exit components of the simplex table row are stored in the array +* locations trow[1], ... trow[n-m]. +* +* NOTE: For testing/debugging only. */ + +void spx_eval_trow(SPXLP *lp, const double rho[/*1+m*/], double + trow[/*1+n-m*/]) +{ int m = lp->m; + int n = lp->n; + int j; + for (j = 1; j <= n-m; j++) + trow[j] = spx_eval_tij(lp, rho, j); + return; +} + +/*********************************************************************** +* spx_update_beta - update values of basic variables +* +* This routine updates the vector beta = (beta[i]) of values of basic +* variables xB = (xB[i]) for the adjacent basis. +* +* On entry to the routine components of the vector beta in the current +* basis should be placed in array locations beta[1], ..., beta[m]. +* +* The parameter 1 <= p <= m specifies basic variable xB[p] which +* becomes non-basic variable xN[q] in the adjacent basis. The special +* case p < 0 means that non-basic variable xN[q] goes from its current +* active bound to opposite one in the adjacent basis. +* +* If the flag p_flag is set, the active bound of xB[p] in the adjacent +* basis is set to its upper bound. (In this case xB[p] should have its +* upper bound and should not be fixed.) +* +* The parameter 1 <= q <= n-m specifies non-basic variable xN[q] which +* becomes basic variable xB[p] in the adjacent basis (if 1 <= p <= m), +* or goes to its opposite bound (if p < 0). (In the latter case xN[q] +* should have both lower and upper bounds and should not be fixed.) +* +* It is assumed that the array tcol contains elements of q-th (pivot) +* column T[q] of the simple table in locations tcol[1], ..., tcol[m]. +* (This column should be computed for the current basis.) +* +* First, the routine determines the increment of basic variable xB[p] +* in the adjacent basis (but only if 1 <= p <= m): +* +* ( - beta[p], if -inf < xB[p] < +inf +* ( +* delta xB[p] = { lB[p] - beta[p], if p_flag = 0 +* ( +* ( uB[p] - beta[p], if p_flag = 1 +* +* where beta[p] is the value of xB[p] in the current basis, lB[p] and +* uB[p] are its lower and upper bounds. Then, the routine determines +* the increment of non-basic variable xN[q] in the adjacent basis: +* +* ( delta xB[p] / T[p,q], if 1 <= p <= m +* ( +* delta xN[q] = { uN[q] - lN[q], if p < 0 and f[q] = lN[q] +* ( +* ( lN[q] - uN[q], if p < 0 and f[q] = uN[q] +* +* where T[p,q] is the pivot element of the simplex table, f[q] is the +* active bound of xN[q] in the current basis. +* +* If 1 <= p <= m, in the adjacent basis xN[q] becomes xB[p], so: +* +* new beta[p] = f[q] + delta xN[q]. +* +* Values of other basic variables xB[i] for 1 <= i <= m, i != p, are +* updated as follows: +* +* new beta[i] = beta[i] + T[i,q] * delta xN[q]. +* +* On exit the routine stores updated components of the vector beta to +* the same locations, where the input vector beta was stored. */ + +void spx_update_beta(SPXLP *lp, double beta[/*1+m*/], int p, + int p_flag, int q, const double tcol[/*1+m*/]) +{ int m = lp->m; + int n = lp->n; + double *l = lp->l; + double *u = lp->u; + int *head = lp->head; + char *flag = lp->flag; + int i, k; + double delta_p, delta_q; + if (p < 0) + { /* special case: xN[q] goes to its opposite bound */ + xassert(1 <= q && q <= n-m); + /* xN[q] should be double-bounded variable */ + k = head[m+q]; /* x[k] = xN[q] */ + xassert(l[k] != -DBL_MAX && u[k] != +DBL_MAX && l[k] != u[k]); + /* determine delta xN[q] */ + if (flag[q]) + { /* xN[q] goes from its upper bound to its lower bound */ + delta_q = l[k] - u[k]; + } + else + { /* xN[q] goes from its lower bound to its upper bound */ + delta_q = u[k] - l[k]; + } + } + else + { /* xB[p] leaves the basis, xN[q] enters the basis */ + xassert(1 <= p && p <= m); + xassert(1 <= q && q <= n-m); + /* determine delta xB[p] */ + k = head[p]; /* x[k] = xB[p] */ + if (p_flag) + { /* xB[p] goes to its upper bound */ + xassert(l[k] != u[k] && u[k] != +DBL_MAX); + delta_p = u[k] - beta[p]; + } + else if (l[k] == -DBL_MAX) + { /* unbounded xB[p] becomes non-basic (unusual case) */ + xassert(u[k] == +DBL_MAX); + delta_p = 0.0 - beta[p]; + } + else + { /* xB[p] goes to its lower bound or becomes fixed */ + delta_p = l[k] - beta[p]; + } + /* determine delta xN[q] */ + delta_q = delta_p / tcol[p]; + /* compute new beta[p], which is the value of xN[q] in the + * adjacent basis */ + k = head[m+q]; /* x[k] = xN[q] */ + if (flag[q]) + { /* xN[q] has its upper bound active */ + xassert(l[k] != u[k] && u[k] != +DBL_MAX); + beta[p] = u[k] + delta_q; + } + else if (l[k] == -DBL_MAX) + { /* xN[q] is non-basic unbounded variable */ + xassert(u[k] == +DBL_MAX); + beta[p] = 0.0 + delta_q; + } + else + { /* xN[q] has its lower bound active or is fixed (latter + * case is unusual) */ + beta[p] = l[k] + delta_q; + } + } + /* compute new beta[i] for all i != p */ + for (i = 1; i <= m; i++) + { if (i != p) + beta[i] += tcol[i] * delta_q; + } + return; +} + +/*********************************************************************** +* spx_update_d - update reduced costs of non-basic variables +* +* This routine updates the vector d = (d[j]) of reduced costs of +* non-basic variables xN = (xN[j]) for the adjacent basis. +* +* On entry to the routine components of the vector d in the current +* basis should be placed in locations d[1], ..., d[n-m]. +* +* The parameter 1 <= p <= m specifies basic variable xB[p] which +* becomes non-basic variable xN[q] in the adjacent basis. +* +* The parameter 1 <= q <= n-m specified non-basic variable xN[q] which +* becomes basic variable xB[p] in the adjacent basis. +* +* It is assumed that the array trow contains elements of p-th (pivot) +* row T'[p] of the simplex table in locations trow[1], ..., trow[n-m]. +* It is also assumed that the array tcol contains elements of q-th +* (pivot) column T[q] of the simple table in locations tcol[1], ..., +* tcol[m]. (These row and column should be computed for the current +* basis.) +* +* First, the routine computes more accurate reduced cost d[q] in the +* current basis using q-th column of the simplex table: +* +* n-m +* d[q] = cN[q] + sum t[i,q] * cB[i], +* i=1 +* +* where cN[q] and cB[i] are objective coefficients at variables xN[q] +* and xB[i], resp. The routine also computes the relative error: +* +* e = |d[q] - d'[q]| / (1 + |d[q]|), +* +* where d'[q] is the reduced cost of xN[q] on entry to the routine, +* and returns e on exit. (If e happens to be large enough, the calling +* program may compute the reduced costs directly, since other reduced +* costs also may be inaccurate.) +* +* In the adjacent basis xB[p] becomes xN[q], so: +* +* new d[q] = d[q] / T[p,q], +* +* where T[p,q] is the pivot element of the simplex table (it is taken +* from column T[q] as more accurate). Reduced costs of other non-basic +* variables xN[j] for 1 <= j <= n-m, j != q, are updated as follows: +* +* new d[j] = d[j] + T[p,j] * new d[q]. +* +* On exit the routine stores updated components of the vector d to the +* same locations, where the input vector d was stored. */ + +double spx_update_d(SPXLP *lp, double d[/*1+n-m*/], int p, int q, + const double trow[/*1+n-m*/], const double tcol[/*1+m*/]) +{ int m = lp->m; + int n = lp->n; + double *c = lp->c; + int *head = lp->head; + int i, j, k; + double dq, e; + xassert(1 <= p && p <= m); + xassert(1 <= q && q <= n); + /* compute d[q] in current basis more accurately */ + k = head[m+q]; /* x[k] = xN[q] */ + dq = c[k]; + for (i = 1; i <= m; i++) + dq += tcol[i] * c[head[i]]; + /* compute relative error in d[q] */ + e = fabs(dq - d[q]) / (1.0 + fabs(dq)); + /* compute new d[q], which is the reduced cost of xB[p] in the + * adjacent basis */ + d[q] = (dq /= tcol[p]); + /* compute new d[j] for all j != q */ + for (j = 1; j <= n-m; j++) + { if (j != q) + d[j] -= trow[j] * dq; + } + return e; +} + +/*********************************************************************** +* spx_change_basis - change current basis to adjacent one +* +* This routine changes the current basis to the adjacent one making +* necessary changes in lp->head and lp->flag members. +* +* The parameters p, p_flag, and q have the same meaning as for the +* routine spx_update_beta. */ + +void spx_change_basis(SPXLP *lp, int p, int p_flag, int q) +{ int m = lp->m; + int n = lp->n; + double *l = lp->l; + double *u = lp->u; + int *head = lp->head; + char *flag = lp->flag; + int k; + if (p < 0) + { /* special case: xN[q] goes to its opposite bound */ + xassert(1 <= q && q <= n-m); + /* xN[q] should be double-bounded variable */ + k = head[m+q]; /* x[k] = xN[q] */ + xassert(l[k] != -DBL_MAX && u[k] != +DBL_MAX && l[k] != u[k]); + /* change active bound flag */ + flag[q] = 1 - flag[q]; + } + else + { /* xB[p] leaves the basis, xN[q] enters the basis */ + xassert(1 <= p && p <= m); + xassert(p_flag == 0 || p_flag == 1); + xassert(1 <= q && q <= n-m); + k = head[p]; /* xB[p] = x[k] */ + if (p_flag) + { /* xB[p] goes to its upper bound */ + xassert(l[k] != u[k] && u[k] != +DBL_MAX); + } + /* swap xB[p] and xN[q] in the basis */ + head[p] = head[m+q], head[m+q] = k; + /* and set active bound flag for new xN[q] */ + lp->flag[q] = p_flag; + } + return; +} + +/*********************************************************************** +* spx_update_invb - update factorization of basis matrix +* +* This routine updates factorization of the basis matrix B when i-th +* column of B is replaced by k-th column of the constraint matrix A. +* +* The parameter 1 <= i <= m specifies the number of column of matrix B +* to be replaced by a new column. +* +* The parameter 1 <= k <= n specifies the number of column of matrix A +* to be used for replacement. +* +* If the factorization has been successfully updated, the routine +* validates it and returns zero. Otherwise, the routine invalidates +* the factorization and returns the code provided by the factorization +* driver (bfd_update). */ + +int spx_update_invb(SPXLP *lp, int i, int k) +{ int m = lp->m; + int n = lp->n; + int *A_ptr = lp->A_ptr; + int *A_ind = lp->A_ind; + double *A_val = lp->A_val; + int ptr, len, ret; + xassert(1 <= i && i <= m); + xassert(1 <= k && k <= n); + ptr = A_ptr[k]; + len = A_ptr[k+1] - ptr; + ret = bfd_update(lp->bfd, i, len, &A_ind[ptr-1], &A_val[ptr-1]); + lp->valid = (ret == 0); + return ret; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.57/src/simplex/spxlp.h b/resources/3rdparty/glpk-4.57/src/simplex/spxlp.h new file mode 100644 index 000000000..e13528c4c --- /dev/null +++ b/resources/3rdparty/glpk-4.57/src/simplex/spxlp.h @@ -0,0 +1,214 @@ +/* spxlp.h */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2015 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef SPXLP_H +#define SPXLP_H + +#include "bfd.h" + +/*********************************************************************** +* The structure SPXLP describes LP problem and its current basis. +* +* It is assumed that LP problem has the following formulation (this is +* so called "working format"): +* +* z = c'* x + c0 -> min (1) +* +* A * x = b (2) +* +* l <= x <= u (3) +* +* where: +* +* x = (x[k]) is a n-vector of variables; +* +* z is an objective function; +* +* c = (c[k]) is a n-vector of objective coefficients; +* +* c0 is a constant term of the objective function; +* +* A = (a[i,k]) is a mxn-matrix of constraint coefficients; +* +* b = (b[i]) is a m-vector of right-hand sides; +* +* l = (l[k]) is a n-vector of lower bounds of variables; +* +* u = (u[k]) is a n-vector of upper bounds of variables. +* +* If variable x[k] has no lower (upper) bound, it is formally assumed +* that l[k] = -inf (u[k] = +inf). Variable having no bounds is called +* free (unbounded) variable. If l[k] = u[k], variable x[k] is assumed +* to be fixed. +* +* It is also assumed that matrix A has full row rank: rank(A) = m, +* i.e. all its rows are linearly independent, so m <= n. +* +* The (current) basis is defined by an appropriate permutation matrix +* P of order n such that: +* +* ( xB ) +* P * x = ( ), (4) +* ( xN ) +* +* where xB = (xB[i]) is a m-vector of basic variables, xN = (xN[j]) is +* a (n-m)-vector of non-basic variables. If a non-basic variable xN[j] +* has both lower and upper bounds, there is used an additional flag to +* indicate which bound is active. +* +* From (2) and (4) it follows that: +* +* A * P'* P * x = b <=> B * xB + N * xN = b, (5) +* +* where P' is a matrix transposed to P, and +* +* A * P' = (B | N). (6) +* +* Here B is the basis matrix, which is a square non-singular matrix +* of order m composed from columns of matrix A that correspond to +* basic variables xB, and N is a mx(n-m) matrix composed from columns +* of matrix A that correspond to non-basic variables xN. */ + +typedef struct SPXLP SPXLP; + +struct SPXLP +{ /* LP problem data and its (current) basis */ + int m; + /* number of equality constraints, m > 0 */ + int n; + /* number of variables, n >= m */ + int nnz; + /* number of non-zeros in constraint matrix A */ + /*--------------------------------------------------------------*/ + /* mxn-matrix A of constraint coefficients in sparse column-wise + * format */ + int *A_ptr; /* int A_ptr[1+n+1]; */ + /* A_ptr[0] is not used; + * A_ptr[k], 1 <= k <= n, is starting position of k-th column in + * arrays A_ind and A_val; note that A_ptr[1] is always 1; + * A_ptr[n+1] indicates the position after the last element in + * arrays A_ind and A_val, i.e. A_ptr[n+1] = nnz+1, where nnz is + * the number of non-zero elements in matrix A; + * the length of k-th column (the number of non-zero elements in + * that column) can be calculated as A_ptr[k+1] - A_ptr[k] */ + int *A_ind; /* int A_ind[1+nnz]; */ + /* row indices */ + double *A_val; /* double A_val[1+nnz]; */ + /* non-zero element values (constraint coefficients) */ + /*--------------------------------------------------------------*/ + /* principal vectors of LP formulation */ + double *b; /* double b[1+m]; */ + /* b[0] is not used; + * b[i], 1 <= i <= m, is the right-hand side of i-th equality + * constraint */ + double *c; /* double c[1+n]; */ + /* c[0] is the constant term of the objective function; + * c[k], 1 <= k <= n, is the objective function coefficient at + * variable x[k] */ + double *l; /* double l[1+n]; */ + /* l[0] is not used; + * l[k], 1 <= k <= n, is the lower bound of variable x[k]; + * if x[k] has no lower bound, l[k] = -DBL_MAX */ + double *u; /* double u[1+n]; */ + /* u[0] is not used; + * u[k], 1 <= k <= n, is the upper bound of variable u[k]; + * if x[k] has no upper bound, u[k] = +DBL_MAX; + * note that l[k] = u[k] means that x[k] is fixed variable */ + /*--------------------------------------------------------------*/ + /* LP basis */ + int *head; /* int head[1+n]; */ + /* basis header, which is permutation matrix P (4): + * head[0] is not used; + * head[i] = k means that xB[i] = x[k], 1 <= i <= m; + * head[m+j] = k, means that xN[j] = x[k], 1 <= j <= n-m */ + char *flag; /* char flag[1+n-m]; */ + /* flags of non-basic variables: + * flag[0] is not used; + * flag[j], 1 <= j <= n-m, indicates that non-basic variable + * xN[j] is non-fixed and has its upper bound active */ + /*--------------------------------------------------------------*/ + /* basis matrix B of order m stored in factorized form */ + int valid; + /* factorization validity flag */ + BFD *bfd; + /* driver to factorization of the basis matrix */ +}; + +#define spx_factorize _glp_spx_factorize +int spx_factorize(SPXLP *lp); +/* compute factorization of current basis matrix */ + +#define spx_eval_beta _glp_spx_eval_beta +void spx_eval_beta(SPXLP *lp, double beta[/*1+m*/]); +/* compute values of basic variables */ + +#define spx_eval_obj _glp_spx_eval_obj +double spx_eval_obj(SPXLP *lp, const double beta[/*1+m*/]); +/* compute value of objective function */ + +#define spx_eval_pi _glp_spx_eval_pi +void spx_eval_pi(SPXLP *lp, double pi[/*1+m*/]); +/* compute simplex multipliers */ + +#define spx_eval_dj _glp_spx_eval_dj +double spx_eval_dj(SPXLP *lp, const double pi[/*1+m*/], int j); +/* compute reduced cost of j-th non-basic variable */ + +#define spx_eval_tcol _glp_spx_eval_tcol +void spx_eval_tcol(SPXLP *lp, int j, double tcol[/*1+m*/]); +/* compute j-th column of simplex table */ + +#define spx_eval_rho _glp_spx_eval_rho +void spx_eval_rho(SPXLP *lp, int i, double rho[/*1+m*/]); +/* compute i-th row of basis matrix inverse */ + +#define spx_eval_tij _glp_spx_eval_tij +double spx_eval_tij(SPXLP *lp, const double rho[/*1+m*/], int j); +/* compute element T[i,j] of simplex table */ + +#define spx_eval_trow _glp_spx_eval_trow +void spx_eval_trow(SPXLP *lp, const double rho[/*1+m*/], double + trow[/*1+n-m*/]); +/* compute i-th row of simplex table */ + +#define spx_update_beta _glp_spx_update_beta +void spx_update_beta(SPXLP *lp, double beta[/*1+m*/], int p, + int p_flag, int q, const double tcol[/*1+m*/]); +/* update values of basic variables */ + +#define spx_update_d _glp_spx_update_d +double spx_update_d(SPXLP *lp, double d[/*1+n-m*/], int p, int q, + const double trow[/*1+n-m*/], const double tcol[/*1+m*/]); +/* update reduced costs of non-basic variables */ + +#define spx_change_basis _glp_spx_change_basis +void spx_change_basis(SPXLP *lp, int p, int p_flag, int q); +/* change current basis to adjacent one */ + +#define spx_update_invb _glp_spx_update_invb +int spx_update_invb(SPXLP *lp, int i, int k); +/* update factorization of basis matrix */ + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.57/src/simplex/spxnt.c b/resources/3rdparty/glpk-4.57/src/simplex/spxnt.c new file mode 100644 index 000000000..cf3e1f2be --- /dev/null +++ b/resources/3rdparty/glpk-4.57/src/simplex/spxnt.c @@ -0,0 +1,260 @@ +/* spxnt.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2015 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "spxnt.h" + +/*********************************************************************** +* spx_alloc_nt - allocate matrix N in sparse row-wise format +* +* This routine allocates the memory for arrays needed to represent the +* matrix N composed of non-basic columns of the constraint matrix A. */ + +void spx_alloc_nt(SPXLP *lp, SPXNT *nt) +{ int m = lp->m; + int nnz = lp->nnz; + nt->ptr = talloc(1+m, int); + nt->len = talloc(1+m, int); + nt->ind = talloc(1+nnz, int); + nt->val = talloc(1+nnz, double); + return; +} + +/*********************************************************************** +* spx_init_nt - initialize row pointers for matrix N +* +* This routine initializes (sets up) row pointers for the matrix N +* using column-wise representation of the constraint matrix A. +* +* This routine needs to be called only once. */ + +void spx_init_nt(SPXLP *lp, SPXNT *nt) +{ int m = lp->m; + int n = lp->n; + int nnz = lp->nnz; + int *A_ptr = lp->A_ptr; + int *A_ind = lp->A_ind; + int *NT_ptr = nt->ptr; + int *NT_len = nt->len; + int i, k, ptr, end; + /* calculate NT_len[i] = maximal number of non-zeros in i-th row + * of N = number of non-zeros in i-th row of A */ + memset(&NT_len[1], 0, m * sizeof(int)); + for (k = 1; k <= n; k++) + { ptr = A_ptr[k]; + end = A_ptr[k+1]; + for (; ptr < end; ptr++) + NT_len[A_ind[ptr]]++; + } + /* initialize row pointers NT_ptr[i], i = 1,...,n-m */ + NT_ptr[1] = 1; + for (i = 2; i <= m; i++) + NT_ptr[i] = NT_ptr[i-1] + NT_len[i-1]; + xassert(NT_ptr[m] + NT_len[m] == nnz+1); + return; +} + +/*********************************************************************** +* spx_nt_add_col - add column N[j] = A[k] to matrix N +* +* This routine adds elements of column N[j] = A[k], 1 <= j <= n-m, +* 1 <= k <= n, to the row-wise represntation of the matrix N. It is +* assumed (with no check) that elements of the specified column are +* missing in the row-wise represntation of N. */ + +void spx_nt_add_col(SPXLP *lp, SPXNT *nt, int j, int k) +{ int m = lp->m; + int n = lp->n; + int nnz = lp->nnz; + int *A_ptr = lp->A_ptr; + int *A_ind = lp->A_ind; + double *A_val = lp->A_val; + int *NT_ptr = nt->ptr; + int *NT_len = nt->len; + int *NT_ind = nt->ind; + double *NT_val = nt->val; + int i, ptr, end, pos; + xassert(1 <= j && j <= n-m); + xassert(1 <= k && k <= n); + ptr = A_ptr[k]; + end = A_ptr[k+1]; + for (; ptr < end; ptr++) + { i = A_ind[ptr]; + /* add element N[i,j] = A[i,k] to i-th row of matrix N */ + pos = NT_ptr[i] + (NT_len[i]++); + if (i < m) + xassert(pos < NT_ptr[i+1]); + else + xassert(pos <= nnz); + NT_ind[pos] = j; + NT_val[pos] = A_val[ptr]; + } + return; +} + +/*********************************************************************** +* spx_build_nt - build matrix N for current basis +* +* This routine builds the row-wise represntation of the matrix N +* for the current basis by adding columns of the constraint matrix A +* corresponding to non-basic variables. */ + +void spx_build_nt(SPXLP *lp, SPXNT *nt) +{ int m = lp->m; + int n = lp->n; + int *head = lp->head; + int *NT_len = nt->len; + int j, k; + /* N := 0 */ + memset(&NT_len[1], 0, m * sizeof(int)); + /* add non-basic columns N[j] = A[k] */ + for (j = 1; j <= n-m; j++) + { k = head[m+j]; /* x[k] = xN[j] */ + spx_nt_add_col(lp, nt, j, k); + } + return; +} + +/*********************************************************************** +* spx_nt_del_col - remove column N[j] = A[k] from matrix N +* +* This routine removes elements of column N[j] = A[k], 1 <= j <= n-m, +* 1 <= k <= n, from the row-wise representation of the matrix N. It is +* assumed (with no check) that elements of the specified column are +* present in the row-wise representation of N. */ + +void spx_nt_del_col(SPXLP *lp, SPXNT *nt, int j, int k) +{ int m = lp->m; + int n = lp->n; + int *A_ptr = lp->A_ptr; + int *A_ind = lp->A_ind; + int *NT_ptr = nt->ptr; + int *NT_len = nt->len; + int *NT_ind = nt->ind; + double *NT_val = nt->val; + int i, ptr, end, ptr1, end1; + xassert(1 <= j && j <= n-m); + xassert(1 <= k && k <= n); + ptr = A_ptr[k]; + end = A_ptr[k+1]; + for (; ptr < end; ptr++) + { i = A_ind[ptr]; + /* find element N[i,j] = A[i,k] in i-th row of matrix N */ + ptr1 = NT_ptr[i]; + end1 = ptr1 + NT_len[i]; + for (; NT_ind[ptr1] != j; ptr1++) + /* nop */; + xassert(ptr1 < end1); + /* and remove it from i-th row element list */ + NT_len[i]--; + NT_ind[ptr1] = NT_ind[end1-1]; + NT_val[ptr1] = NT_val[end1-1]; + } + return; +} + +/*********************************************************************** +* spx_update_nt - update matrix N for adjacent basis +* +* This routine updates the row-wise represntation of matrix N for +* the adjacent basis, where column N[q], 1 <= q <= n-m, is replaced by +* column B[p], 1 <= p <= m, of the current basis matrix B. */ + +void spx_update_nt(SPXLP *lp, SPXNT *nt, int p, int q) +{ int m = lp->m; + int n = lp->n; + int *head = lp->head; + xassert(1 <= p && p <= m); + xassert(1 <= q && q <= n-m); + /* remove old column N[q] corresponding to variable xN[q] */ + spx_nt_del_col(lp, nt, q, head[m+q]); + /* add new column N[q] corresponding to variable xB[p] */ + spx_nt_add_col(lp, nt, q, head[p]); + return; +} + +/*********************************************************************** +* spx_nt_prod - compute product y := y + s * N'* x +* +* This routine computes the product: +* +* y := y + s * N'* x, +* +* where N' is a matrix transposed to the mx(n-m)-matrix N composed +* from non-basic columns of the constraint matrix A, x is a m-vector, +* s is a scalar, y is (n-m)-vector. +* +* If the flag ign is non-zero, the routine ignores the input content +* of the array y assuming that y = 0. +* +* The routine uses the row-wise representation of the matrix N and +* computes the product as a linear combination: +* +* y := y + s * (N'[1] * x[1] + ... + N'[m] * x[m]), +* +* where N'[i] is i-th row of N, 1 <= i <= m. */ + +void spx_nt_prod(SPXLP *lp, SPXNT *nt, double y[/*1+n-m*/], int ign, + double s, const double x[/*1+m*/]) +{ int m = lp->m; + int n = lp->n; + int *NT_ptr = nt->ptr; + int *NT_len = nt->len; + int *NT_ind = nt->ind; + double *NT_val = nt->val; + int i, j, ptr, end; + double t; + if (ign) + { /* y := 0 */ + for (j = 1; j <= n-m; j++) + y[j] = 0.0; + } + for (i = 1; i <= m; i++) + { if (x[i] != 0.0) + { /* y := y + s * (i-th row of N) * x[i] */ + t = s * x[i]; + ptr = NT_ptr[i]; + end = ptr + NT_len[i]; + for (; ptr < end; ptr++) + y[NT_ind[ptr]] += NT_val[ptr] * t; + } + } + return; +} + +/*********************************************************************** +* spx_free_nt - deallocate matrix N in sparse row-wise format +* +* This routine deallocates the memory used for arrays of the program +* object nt. */ + +void spx_free_nt(SPXLP *lp, SPXNT *nt) +{ xassert(lp == lp); + tfree(nt->ptr); + tfree(nt->len); + tfree(nt->ind); + tfree(nt->val); + return; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.57/src/simplex/spxnt.h b/resources/3rdparty/glpk-4.57/src/simplex/spxnt.h new file mode 100644 index 000000000..d2622404c --- /dev/null +++ b/resources/3rdparty/glpk-4.57/src/simplex/spxnt.h @@ -0,0 +1,89 @@ +/* spxnt.h */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2015 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef SPXNT_H +#define SPXNT_H + +#include "spxlp.h" + +typedef struct SPXNT SPXNT; + +struct SPXNT +{ /* mx(n-m)-matrix N composed of non-basic columns of constraint + * matrix A, in sparse row-wise format */ + int *ptr; /* int ptr[1+m]; */ + /* ptr[0] is not used; + * ptr[i], 1 <= i <= m, is starting position of i-th row in + * arrays ind and val; note that ptr[1] is always 1; + * these starting positions are set up *once* as if they would + * correspond to rows of matrix A stored without gaps, i.e. + * ptr[i+1] - ptr[i] is the number of non-zeros in i-th (i < m) + * row of matrix A, and (nnz+1) - ptr[m] is the number of + * non-zero in m-th (last) row of matrix A, where nnz is the + * total number of non-zeros in matrix A */ + int *len; /* int len[1+m]; */ + /* len[0] is not used; + * len[i], 1 <= i <= m, is the number of non-zeros in i-th row + * of current matrix N */ + int *ind; /* int ind[1+nnz]; */ + /* column indices */ + double *val; /* double val[1+nnz]; */ + /* non-zero element values */ +}; + +#define spx_alloc_nt _glp_spx_alloc_nt +void spx_alloc_nt(SPXLP *lp, SPXNT *nt); +/* allocate matrix N in sparse row-wise format */ + +#define spx_init_nt _glp_spx_init_nt +void spx_init_nt(SPXLP *lp, SPXNT *nt); +/* initialize row pointers for matrix N */ + +#define spx_nt_add_col _glp_spx_nt_add_col +void spx_nt_add_col(SPXLP *lp, SPXNT *nt, int j, int k); +/* add column N[j] = A[k] */ + +#define spx_build_nt _glp_spx_build_nt +void spx_build_nt(SPXLP *lp, SPXNT *nt); +/* build matrix N for current basis */ + +#define spx_nt_del_col _glp_spx_nt_del_col +void spx_nt_del_col(SPXLP *lp, SPXNT *nt, int j, int k); +/* remove column N[j] = A[k] from matrix N */ + +#define spx_update_nt _glp_spx_update_nt +void spx_update_nt(SPXLP *lp, SPXNT *nt, int p, int q); +/* update matrix N for adjacent basis */ + +#define spx_nt_prod _glp_spx_nt_prod +void spx_nt_prod(SPXLP *lp, SPXNT *nt, double y[/*1+n-m*/], int ign, + double s, const double x[/*1+m*/]); +/* compute product y := y + s * N'* x */ + +#define spx_free_nt _glp_spx_free_nt +void spx_free_nt(SPXLP *lp, SPXNT *nt); +/* deallocate matrix N in sparse row-wise format */ + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.57/src/simplex/spxprim.c b/resources/3rdparty/glpk-4.57/src/simplex/spxprim.c new file mode 100644 index 000000000..b22133ff0 --- /dev/null +++ b/resources/3rdparty/glpk-4.57/src/simplex/spxprim.c @@ -0,0 +1,1139 @@ +/* spxprim.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2015 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "simplex.h" +#include "spxat.h" +#include "spxnt.h" +#include "spxchuzc.h" +#include "spxchuzr.h" +#include "spxprob.h" + +#define USE_AT 0 +/* 1 - use A in row-wise format + * 0 - use N in row-wise format */ + +#define EXCL 1 +/* 1 - exclude fixed non-basic variables + * 0 - don't exclude variables */ + +#define SHIFT 1 +/* 1 - shift bounds of variables toward zero + * 0 - don't shift bounds of variables */ + +#define CHECK_ACCURACY 0 +/* (for debugging) */ + +struct csa +{ /* common storage area */ + SPXLP *lp; + /* LP problem data and its (current) basis; this LP has m rows + * and n columns */ + int dir; + /* original optimization direction: + * +1 - minimization + * -1 - maximization */ + double *c; /* double c[1+n]; */ + /* copy of original objective coefficients */ + SPXAT *at; + /* mxn-matrix A of constraint coefficients, in sparse row-wise + * format (NULL if not used) */ + SPXNT *nt; + /* mx(n-m)-matrix N composed of non-basic columns of constraint + * matrix A, in sparse row-wise format (NULL if not used) */ + int phase; + /* search phase: + * 0 - not determined yet + * 1 - searching for primal feasible solution + * 2 - searching for optimal solution */ + double *beta; /* double beta[1+m]; */ + /* beta[i] is primal value of basic variable xB[i] */ + int beta_st; + /* status of the vector beta: + * 0 - undefined + * 1 - just computed + * 2 - updated */ + double *d; /* double d[1+n-m]; */ + /* d[j] is reduced cost of non-basic variable xN[j] */ + int d_st; + /* status of the vector d: + * 0 - undefined + * 1 - just computed + * 2 - updated */ + SPXSE *se; + /* projected steepest edge and Devex pricing data block (NULL if + * not used) */ + int num; + /* number of eligible non-basic variables */ + int *list; /* int list[1+n-m]; */ + /* list[1], ..., list[num] are indices j of eligible non-basic + * variables xN[j] */ + int q; + /* xN[q] is a non-basic variable chosen to enter the basis */ + double *tcol; /* double tcol[1+m]; */ + /* q-th (pivot) column of the simplex table */ + int p; + /* xB[p] is a basic variable chosen to leave the basis; + * p = 0 means that no basic variable reaches its bound; + * p < 0 means that non-basic variable xN[q] reaches its opposite + * bound before any basic variable */ + int p_flag; + /* if this flag is set, the active bound of xB[p] in the adjacent + * basis should be set to the upper bound */ + double *trow; /* double trow[1+n-m]; */ + /* p-th (pivot) row of the simplex table */ + double *work; /* double work[1+m]; */ + /* working array */ + int p_stat, d_stat; + /* primal and dual solution statuses */ + /*--------------------------------------------------------------*/ + /* control parameters (see struct glp_smcp) */ + int msg_lev; + /* message level */ + int harris; + /* ratio test technique: + * 0 - textbook ratio test + * 1 - Harris' two pass ratio test */ + double tol_bnd, tol_bnd1; + /* primal feasibility tolerances */ + double tol_dj, tol_dj1; + /* dual feasibility tolerances */ + double tol_piv; + /* pivot tolerance */ + int it_lim; + /* iteration limit */ + int tm_lim; + /* time limit, milliseconds */ + int out_frq; + /* display output frequency, iterations */ + int out_dly; + /* display output delay, milliseconds */ + /*--------------------------------------------------------------*/ + /* working parameters */ + double tm_beg; + /* time value at the beginning of the search */ + int it_beg; + /* simplex iteration count at the beginning of the search */ + int it_cnt; + /* simplex iteration count; it increases by one every time the + * basis changes (including the case when a non-basic variable + * jumps to its opposite bound) */ + int it_dpy; + /* simplex iteration count at most recent display output */ + int inv_cnt; + /* basis factorization count since most recent display output */ +}; + +/*********************************************************************** +* set_penalty - set penalty function coefficients +* +* This routine sets up objective coefficients of the penalty function, +* which is the sum of primal infeasibilities, as follows: +* +* if beta[i] < l[k] - eps1, set c[k] = -1, +* +* if beta[i] > u[k] + eps2, set c[k] = +1, +* +* otherwise, set c[k] = 0, +* +* where beta[i] is current value of basic variable xB[i] = x[k], l[k] +* and u[k] are original bounds of x[k], and +* +* eps1 = tol + tol1 * |l[k]|, +* +* eps2 = tol + tol1 * |u[k]|. +* +* The routine returns the number of non-zero objective coefficients, +* which is the number of basic variables violating their bounds. Thus, +* if the value returned is zero, the current basis is primal feasible +* within the specified tolerances. */ + +static int set_penalty(struct csa *csa, double tol, double tol1) +{ SPXLP *lp = csa->lp; + int m = lp->m; + int n = lp->n; + double *c = lp->c; + double *l = lp->l; + double *u = lp->u; + int *head = lp->head; + double *beta = csa->beta; + int i, k, count = 0; + double t, eps; + /* reset objective coefficients */ + for (k = 0; k <= n; k++) + c[k] = 0.0; + /* walk thru the list of basic variables */ + for (i = 1; i <= m; i++) + { k = head[i]; /* x[k] = xB[i] */ + /* check lower bound */ + if ((t = l[k]) != -DBL_MAX) + { eps = tol + tol1 * (t >= 0.0 ? +t : -t); + if (beta[i] < t - eps) + { /* lower bound is violated */ + c[k] = -1.0, count++; + } + } + /* check upper bound */ + if ((t = u[k]) != +DBL_MAX) + { eps = tol + tol1 * (t >= 0.0 ? +t : -t); + if (beta[i] > t + eps) + { /* upper bound is violated */ + c[k] = +1.0, count++; + } + } + } + return count; +} + +/*********************************************************************** +* check_feas - check primal feasibility of basic solution +* +* This routine checks if the specified values of all basic variables +* beta = (beta[i]) are within their bounds. +* +* Let l[k] and u[k] be original bounds of basic variable xB[i] = x[k]. +* The actual bounds of x[k] are determined as follows: +* +* 1) if phase = 1 and c[k] < 0, x[k] violates its lower bound, so its +* actual bounds are artificial: -inf < x[k] <= l[k]; +* +* 2) if phase = 1 and c[k] > 0, x[k] violates its upper bound, so its +* actual bounds are artificial: u[k] <= x[k] < +inf; +* +* 3) in all other cases (if phase = 1 and c[k] = 0, or if phase = 2) +* actual bounds are original: l[k] <= x[k] <= u[k]. +* +* The parameters tol and tol1 are bound violation tolerances. The +* actual bounds l'[k] and u'[k] are considered as non-violated within +* the specified tolerance if +* +* l'[k] - eps1 <= beta[i] <= u'[k] + eps2, +* +* where eps1 = tol + tol1 * |l'[k]|, eps2 = tol + tol1 * |u'[k]|. +* +* The routine returns one of the following codes: +* +* 0 - solution is feasible (no actual bounds are violated); +* +* 1 - solution is infeasible, however, only artificial bounds are +* violated (this is possible only if phase = 1); +* +* 2 - solution is infeasible and at least one original bound is +* violated. */ + +static int check_feas(struct csa *csa, int phase, double tol, double + tol1) +{ SPXLP *lp = csa->lp; + int m = lp->m; + double *c = lp->c; + double *l = lp->l; + double *u = lp->u; + int *head = lp->head; + double *beta = csa->beta; + int i, k, orig, ret = 0; + double lk, uk, eps; + xassert(phase == 1 || phase == 2); + /* walk thru the list of basic variables */ + for (i = 1; i <= m; i++) + { k = head[i]; /* x[k] = xB[i] */ + /* determine actual bounds of x[k] */ + if (phase == 1 && c[k] < 0.0) + { /* -inf < x[k] <= l[k] */ + lk = -DBL_MAX, uk = l[k]; + orig = 0; /* artificial bounds */ + } + else if (phase == 1 && c[k] > 0.0) + { /* u[k] <= x[k] < +inf */ + lk = u[k], uk = +DBL_MAX; + orig = 0; /* artificial bounds */ + } + else + { /* l[k] <= x[k] <= u[k] */ + lk = l[k], uk = u[k]; + orig = 1; /* original bounds */ + } + /* check actual lower bound */ + if (lk != -DBL_MAX) + { eps = tol + tol1 * (lk >= 0.0 ? +lk : -lk); + if (beta[i] < lk - eps) + { /* actual lower bound is violated */ + if (orig) + { ret = 2; + break; + } + ret = 1; + } + } + /* check actual upper bound */ + if (uk != +DBL_MAX) + { eps = tol + tol1 * (uk >= 0.0 ? +uk : -uk); + if (beta[i] > uk + eps) + { /* actual upper bound is violated */ + if (orig) + { ret = 2; + break; + } + ret = 1; + } + } + } + return ret; +} + +/*********************************************************************** +* adjust_penalty - adjust penalty function coefficients +* +* On searching for primal feasible solution it may happen that some +* basic variable xB[i] = x[k] has non-zero objective coefficient c[k] +* indicating that xB[i] violates its lower (if c[k] < 0) or upper (if +* c[k] > 0) original bound, but due to primal degenarcy the violation +* is close to zero. +* +* This routine identifies such basic variables and sets objective +* coefficients at these variables to zero that allows avoiding zero- +* step simplex iterations. +* +* The parameters tol and tol1 are bound violation tolerances. The +* original bounds l[k] and u[k] are considered as non-violated within +* the specified tolerance if +* +* l[k] - eps1 <= beta[i] <= u[k] + eps2, +* +* where beta[i] is value of basic variable xB[i] = x[k] in the current +* basis, eps1 = tol + tol1 * |l[k]|, eps2 = tol + tol1 * |u[k]|. +* +* The routine returns the number of objective coefficients which were +* set to zero. */ + +static int adjust_penalty(struct csa *csa, double tol, double tol1) +{ SPXLP *lp = csa->lp; + int m = lp->m; + double *c = lp->c; + double *l = lp->l; + double *u = lp->u; + int *head = lp->head; + double *beta = csa->beta; + int i, k, count = 0; + double t, eps; + xassert(csa->phase == 1); + /* walk thru the list of basic variables */ + for (i = 1; i <= m; i++) + { k = head[i]; /* x[k] = xB[i] */ + if (c[k] < 0.0) + { /* x[k] violates its original lower bound l[k] */ + xassert((t = l[k]) != -DBL_MAX); + eps = tol + tol1 * (t >= 0.0 ? +t : -t); + if (beta[i] >= t - eps) + { /* however, violation is close to zero */ + c[k] = 0.0, count++; + } + } + else if (c[k] > 0.0) + { /* x[k] violates its original upper bound u[k] */ + xassert((t = u[k]) != +DBL_MAX); + eps = tol + tol1 * (t >= 0.0 ? +t : -t); + if (beta[i] <= t + eps) + { /* however, violation is close to zero */ + c[k] = 0.0, count++; + } + } + } + return count; +} + +#if CHECK_ACCURACY +/*********************************************************************** +* err_in_vec - compute maximal relative error between two vectors +* +* This routine computes and returns maximal relative error between +* n-vectors x and y: +* +* err_max = max |x[i] - y[i]| / (1 + |x[i]|). +* +* NOTE: This routine is intended only for debugginig purposes. */ + +static double err_in_vec(int n, const double x[], const double y[]) +{ int i; + double err, err_max; + err_max = 0.0; + for (i = 1; i <= n; i++) + { err = fabs(x[i] - y[i]) / (1.0 + fabs(x[i])); + if (err_max < err) + err_max = err; + } + return err_max; +} +#endif + +#if CHECK_ACCURACY +/*********************************************************************** +* err_in_beta - compute maximal relative error in vector beta +* +* This routine computes and returns maximal relative error in vector +* of values of basic variables beta = (beta[i]). +* +* NOTE: This routine is intended only for debugginig purposes. */ + +static double err_in_beta(struct csa *csa) +{ SPXLP *lp = csa->lp; + int m = lp->m; + double err, *beta; + beta = talloc(1+m, double); + spx_eval_beta(lp, beta); + err = err_in_vec(m, beta, csa->beta); + tfree(beta); + return err; +} +#endif + +#if CHECK_ACCURACY +/*********************************************************************** +* err_in_d - compute maximal relative error in vector d +* +* This routine computes and returns maximal relative error in vector +* of reduced costs of non-basic variables d = (d[j]). +* +* NOTE: This routine is intended only for debugginig purposes. */ + +static double err_in_d(struct csa *csa) +{ SPXLP *lp = csa->lp; + int m = lp->m; + int n = lp->n; + int j; + double err, *pi, *d; + pi = talloc(1+m, double); + d = talloc(1+n-m, double); + spx_eval_pi(lp, pi); + for (j = 1; j <= n-m; j++) + d[j] = spx_eval_dj(lp, pi, j); + err = err_in_vec(n-m, d, csa->d); + tfree(pi); + tfree(d); + return err; +} +#endif + +#if CHECK_ACCURACY +/*********************************************************************** +* err_in_gamma - compute maximal relative error in vector gamma +* +* This routine computes and returns maximal relative error in vector +* of projected steepest edge weights gamma = (gamma[j]). +* +* NOTE: This routine is intended only for debugginig purposes. */ + +static double err_in_gamma(struct csa *csa) +{ SPXLP *lp = csa->lp; + int m = lp->m; + int n = lp->n; + SPXSE *se = csa->se; + int j; + double err, *gamma; + xassert(se != NULL); + gamma = talloc(1+n-m, double); + for (j = 1; j <= n-m; j++) + gamma[j] = spx_eval_gamma_j(lp, se, j); + err = err_in_vec(n-m, gamma, se->gamma); + tfree(gamma); + return err; +} +#endif + +#if CHECK_ACCURACY +/*********************************************************************** +* check_accuracy - check accuracy of basic solution components +* +* This routine checks accuracy of current basic solution components. +* +* NOTE: This routine is intended only for debugginig purposes. */ + +static void check_accuracy(struct csa *csa) +{ double e_beta, e_d, e_gamma; + e_beta = err_in_beta(csa); + e_d = err_in_d(csa); + if (csa->se == NULL) + e_gamma = 0.; + else + e_gamma = err_in_gamma(csa); + xprintf("e_beta = %10.3e; e_d = %10.3e; e_gamma = %10.3e\n", + e_beta, e_d, e_gamma); + xassert(e_beta <= 1e-5 && e_d <= 1e-5 && e_gamma <= 1e-3); + return; +} +#endif + +/*********************************************************************** +* choose_pivot - choose xN[q] and xB[p] +* +* Given the list of eligible non-basic variables this routine first +* chooses non-basic variable xN[q]. This choice is always possible, +* because the list is assumed to be non-empty. Then the routine +* computes q-th column T[*,q] of the simplex table T[i,j] and chooses +* basic variable xB[p]. If the pivot T[p,q] is small in magnitude, +* the routine attempts to choose another xN[q] and xB[p] in order to +* avoid badly conditioned adjacent bases. */ + +static void choose_pivot(struct csa *csa) +{ SPXLP *lp = csa->lp; + int m = lp->m; + int n = lp->n; + double *beta = csa->beta; + double *d = csa->d; + SPXSE *se = csa->se; + int *list = csa->list; + int nnn, try, q, t, p_flag, p; + double *tcol = csa->work; + /* initial number of eligible non-basic variables */ + nnn = csa->num; + /* nothing has been chosen so far */ + csa->q = 0; + try = 0; +try: /* choose non-basic variable xN[q] */ + xassert(nnn > 0); + try++; + if (se == NULL) + { /* Dantzig's rule */ + q = spx_chuzc_std(lp, d, nnn, list); + } + else + { /* projected steepest edge */ + q = spx_chuzc_pse(lp, se, d, nnn, list); + } + xassert(1 <= q && q <= n-m); + /* compute q-th column of the simplex table */ + spx_eval_tcol(lp, q, tcol); + /* choose basic variable xB[p] */ + if (!csa->harris) + { /* textbook ratio test */ + p = spx_chuzr_std(lp, csa->phase, beta, q, + d[q] < 0.0 ? +1. : -1., tcol, &p_flag, csa->tol_piv, + .30 * csa->tol_bnd, .30 * csa->tol_bnd1); + } + else + { /* Harris' two-pass ratio test */ + p = spx_chuzr_harris(lp, csa->phase, beta, q, + d[q] < 0.0 ? +1. : -1., tcol, &p_flag , csa->tol_piv, + .50 * csa->tol_bnd, .50 * csa->tol_bnd1); + } + /* either keep previous choice or accept new choice depending on + * which one is better */ + if (csa->q == 0 || p <= 0 || + fabs(tcol[p]) > fabs(csa->tcol[csa->p])) + { csa->q = q; + memcpy(&csa->tcol[1], &tcol[1], m * sizeof(double)); + csa->p = p; + csa->p_flag = p_flag; + } + /* check if current choice is acceptable */ + if (csa->p <= 0 || fabs(csa->tcol[csa->p]) >= 0.001) + goto done; + if (nnn == 1) + goto done; + if (try == 5) + goto done; + /* try to choose other xN[q] and xB[p] */ + /* find xN[q] in the list */ + for (t = 1; t <= nnn; t++) + if (list[t] == q) break; + xassert(t <= nnn); + /* move xN[q] to the end of the list */ + list[t] = list[nnn], list[nnn] = q; + /* and exclude it from consideration */ + nnn--; + /* repeat the choice */ + goto try; +done: /* the choice has been made */ + return; +} + +/*********************************************************************** +* sum_infeas - compute sum of primal infeasibilities +* +* This routine compute the sum of primal infeasibilities, which is the +* current penalty function value. */ + +static double sum_infeas(SPXLP *lp, const double beta[/*1+m*/]) +{ int m = lp->m; + double *l = lp->l; + double *u = lp->u; + int *head = lp->head; + int i, k; + double sum = 0.0; + for (i = 1; i <= m; i++) + { k = head[i]; /* x[k] = xB[i] */ + if (l[k] != -DBL_MAX && beta[i] < l[k]) + sum += l[k] - beta[i]; + if (u[k] != +DBL_MAX && beta[i] > u[k]) + sum += beta[i] - u[k]; + } + return sum; +} + +/*********************************************************************** +* display - display search progress +* +* This routine displays some information about the search progress +* that includes: +* +* search phase; +* +* number of simplex iterations performed by the solver; +* +* original objective value; +* +* sum of (scaled) primal infeasibilities; +* +* number of infeasibilities (phase I) or non-optimalities (phase II); +* +* number of basic factorizations since last display output. */ + +static void display(struct csa *csa, int spec) +{ int nnn, k; + double obj, sum, *save; + /* check if the display output should be skipped */ + if (csa->msg_lev < GLP_MSG_ON) goto skip; + if (csa->out_dly > 0 && + 1000.0 * xdifftime(xtime(), csa->tm_beg) < csa->out_dly) + goto skip; + if (csa->it_cnt == csa->it_dpy) goto skip; + if (!spec && csa->it_cnt % csa->out_frq != 0) goto skip; + /* compute original objective value */ + save = csa->lp->c; + csa->lp->c = csa->c; + obj = csa->dir * spx_eval_obj(csa->lp, csa->beta); + csa->lp->c = save; + /* compute sum of (scaled) primal infeasibilities */ + sum = sum_infeas(csa->lp, csa->beta); + /* compute number of infeasibilities/non-optimalities */ + switch (csa->phase) + { case 1: + nnn = 0; + for (k = 1; k <= csa->lp->n; k++) + if (csa->lp->c[k] != 0.0) nnn++; + break; + case 2: + xassert(csa->d_st); + nnn = spx_chuzc_sel(csa->lp, csa->d, csa->tol_dj, + csa->tol_dj1, NULL); + break; + default: + xassert(csa != csa); + } + /* display search progress */ + xprintf("%c%6d: obj = %17.9e inf = %11.3e (%d)", + csa->phase == 2 ? '*' : ' ', csa->it_cnt, obj, sum, nnn); + if (csa->inv_cnt) + { /* number of basis factorizations performed */ + xprintf(" %d", csa->inv_cnt); + csa->inv_cnt = 0; + } + xprintf("\n"); + csa->it_dpy = csa->it_cnt; +skip: return; +} + +/*********************************************************************** +* spx_primal - driver to primal simplex method +* +* This routine is a driver to the two-phase primal simplex method. +* +* On exit this routine returns one of the following codes: +* +* 0 LP instance has been successfully solved. +* +* GLP_EITLIM +* Iteration limit has been exhausted. +* +* GLP_ETMLIM +* Time limit has been exhausted. +* +* GLP_EFAIL +* The solver failed to solve LP instance. */ + +static int primal_simplex(struct csa *csa) +{ /* primal simplex method main logic routine */ + SPXLP *lp = csa->lp; + int m = lp->m; + int n = lp->n; + double *c = lp->c; + int *head = lp->head; + SPXAT *at = csa->at; + SPXNT *nt = csa->nt; + double *beta = csa->beta; + double *d = csa->d; + SPXSE *se = csa->se; + int *list = csa->list; + double *tcol = csa->tcol; + double *trow = csa->trow; + double *pi = csa->work; + double *rho = csa->work; + int msg_lev = csa->msg_lev; + double tol_bnd = csa->tol_bnd; + double tol_bnd1 = csa->tol_bnd1; + double tol_dj = csa->tol_dj; + double tol_dj1 = csa->tol_dj1; + int j, refct, ret; +loop: /* main loop starts here */ + /* compute factorization of the basis matrix */ + if (!lp->valid) + { double cond; + ret = spx_factorize(lp); + csa->inv_cnt++; + if (ret != 0) + { if (msg_lev >= GLP_MSG_ERR) + xprintf("Error: unable to factorize the basis matrix (%d" + ")\n", ret); + csa->p_stat = csa->d_stat = GLP_UNDEF; + ret = GLP_EFAIL; + goto fini; + } + /* check condition of the basis matrix */ + cond = bfd_condest(lp->bfd); + if (cond > 1.0 / DBL_EPSILON) + { if (msg_lev >= GLP_MSG_ERR) + xprintf("Error: basis matrix is singular to working prec" + "ision (cond = %.3g)\n", cond); + csa->p_stat = csa->d_stat = GLP_UNDEF; + ret = GLP_EFAIL; + goto fini; + } + if (cond > 0.001 / DBL_EPSILON) + { if (msg_lev >= GLP_MSG_ERR) + xprintf("Warning: basis matrix is ill-conditioned (cond " + "= %.3g)\n", cond); + } + /* invalidate basic solution components */ + csa->beta_st = csa->d_st = 0; + } + /* compute values of basic variables beta = (beta[i]) */ + if (!csa->beta_st) + { spx_eval_beta(lp, beta); + csa->beta_st = 1; /* just computed */ + /* determine the search phase, if not determined yet */ + if (!csa->phase) + { if (set_penalty(csa, 0.97 * tol_bnd, 0.97 * tol_bnd1)) + { /* current basic solution is primal infeasible */ + /* start to minimize the sum of infeasibilities */ + csa->phase = 1; + } + else + { /* current basic solution is primal feasible */ + /* start to minimize the original objective function */ + csa->phase = 2; + memcpy(c, csa->c, (1+n) * sizeof(double)); + } + /* working objective coefficients have been changed, so + * invalidate reduced costs */ + csa->d_st = 0; + } + /* make sure that the current basic solution remains primal + * feasible (or pseudo-feasible on phase I) */ + if (check_feas(csa, csa->phase, tol_bnd, tol_bnd1)) + { /* excessive bound violations due to round-off errors */ + if (msg_lev >= GLP_MSG_ERR) + xprintf("Warning: numerical instability (primal simplex," + " phase %s)\n", csa->phase == 1 ? "I" : "II"); + /* restart the search */ + lp->valid = 0; + csa->phase = 0; + goto loop; + } + } + /* at this point the search phase is determined */ + xassert(csa->phase == 1 || csa->phase == 2); + if (csa->phase == 1) + { /* adjust penalty function coefficients */ + if (adjust_penalty(csa, tol_bnd, tol_bnd1)) + { /* some coefficients were changed, so invalidate reduced + * costs of non-basic variables */ + csa->d_st = 0; + } + } + /* compute reduced costs of non-basic variables d = (d[j]) */ + if (!csa->d_st) + { spx_eval_pi(lp, pi); + for (j = 1; j <= n-m; j++) + d[j] = spx_eval_dj(lp, pi, j); + csa->d_st = 1; /* just computed */ + } + /* reset the reference space, if necessary */ + if (se != NULL && !se->valid) + spx_reset_refsp(lp, se), refct = 1000; + /* at this point the basis factorization and all basic solution + * components are valid */ + xassert(lp->valid && csa->beta_st && csa->d_st); +#if CHECK_ACCURACY + /* check accuracy of current basic solution components (only for + * debugging) */ + check_accuracy(csa); +#endif + /* check if the iteration limit has been exhausted */ + if (csa->it_cnt - csa->it_beg >= csa->it_lim) + { if (csa->beta_st != 1) + csa->beta_st = 0; + if (csa->d_st != 1) + csa->d_st = 0; + if (!(csa->beta_st && csa->d_st)) + goto loop; + display(csa, 1); + if (msg_lev >= GLP_MSG_ALL) + xprintf("ITERATION LIMIT EXCEEDED; SEARCH TERMINATED\n"); + csa->p_stat = (csa->phase == 2 ? GLP_FEAS : GLP_INFEAS); + csa->d_stat = GLP_UNDEF; /* will be set below */ + ret = GLP_EITLIM; + goto fini; + } + /* check if the time limit has been exhausted */ + if (1000.0 * xdifftime(xtime(), csa->tm_beg) >= csa->tm_lim) + { if (csa->beta_st != 1) + csa->beta_st = 0; + if (csa->d_st != 1) + csa->d_st = 0; + if (!(csa->beta_st && csa->d_st)) + goto loop; + display(csa, 1); + if (msg_lev >= GLP_MSG_ALL) + xprintf("TIME LIMIT EXCEEDED; SEARCH TERMINATED\n"); + csa->p_stat = (csa->phase == 2 ? GLP_FEAS : GLP_INFEAS); + csa->d_stat = GLP_UNDEF; /* will be set below */ + ret = GLP_ETMLIM; + goto fini; + } + /* display the search progress */ + display(csa, 0); + /* select eligible non-basic variables */ + switch (csa->phase) + { case 1: + csa->num = spx_chuzc_sel(lp, d, 1e-8, 0.0, list); + break; + case 2: + csa->num = spx_chuzc_sel(lp, d, tol_dj, tol_dj1, list); + break; + default: + xassert(csa != csa); + } + /* check for optimality */ + if (csa->num == 0) + { if (csa->beta_st != 1) + csa->beta_st = 0; + if (csa->d_st != 1) + csa->d_st = 0; + if (!(csa->beta_st && csa->d_st)) + goto loop; + /* current basis is optimal */ + display(csa, 1); + switch (csa->phase) + { case 1: + /* check for primal feasibility */ + if (!check_feas(csa, 2, tol_bnd, tol_bnd1)) + { /* feasible solution found; switch to phase II */ + memcpy(c, csa->c, (1+n) * sizeof(double)); + csa->phase = 2; + csa->d_st = 0; + goto loop; + } + /* no feasible solution exists */ + if (msg_lev >= GLP_MSG_ALL) + xprintf("LP HAS NO PRIMAL FEASIBLE SOLUTION\n"); + csa->p_stat = GLP_NOFEAS; + csa->d_stat = GLP_UNDEF; /* will be set below */ + ret = 0; + goto fini; + case 2: + /* optimal solution found */ + if (msg_lev >= GLP_MSG_ALL) + xprintf("OPTIMAL LP SOLUTION FOUND\n"); + csa->p_stat = csa->d_stat = GLP_FEAS; + ret = 0; + goto fini; + default: + xassert(csa != csa); + } + } + /* choose xN[q] and xB[p] */ + choose_pivot(csa); + /* check for unboundedness */ + if (csa->p == 0) + { if (csa->beta_st != 1) + csa->beta_st = 0; + if (csa->d_st != 1) + csa->d_st = 0; + if (!(csa->beta_st && csa->d_st)) + goto loop; + display(csa, 1); + switch (csa->phase) + { case 1: + /* this should never happen */ + if (msg_lev >= GLP_MSG_ERR) + xprintf("Error: primal simplex failed\n"); + csa->p_stat = csa->d_stat = GLP_UNDEF; + ret = GLP_EFAIL; + goto fini; + case 2: + /* primal unboundedness detected */ + if (msg_lev >= GLP_MSG_ALL) + xprintf("LP HAS UNBOUNDED PRIMAL SOLUTION\n"); + csa->p_stat = GLP_FEAS; + csa->d_stat = GLP_NOFEAS; + ret = 0; + goto fini; + default: + xassert(csa != csa); + } + } + /* update values of basic variables for adjacent basis */ + spx_update_beta(lp, beta, csa->p, csa->p_flag, csa->q, tcol); + csa->beta_st = 2; + /* p < 0 means that xN[q] jumps to its opposite bound */ + if (csa->p < 0) + goto skip; + /* xN[q] enters and xB[p] leaves the basis */ + /* compute p-th row of inv(B) */ + spx_eval_rho(lp, csa->p, rho); + /* compute p-th (pivot) row of the simplex table */ + if (at != NULL) + spx_eval_trow1(lp, at, rho, trow); + else + spx_nt_prod(lp, nt, trow, 1, -1.0, rho); + /* FIXME: tcol[p] and trow[q] should be close to each other */ + xassert(trow[csa->q] != 0.0); + /* update reduced costs of non-basic variables for adjacent + * basis */ + if (spx_update_d(lp, d, csa->p, csa->q, trow, tcol) <= 1e-9) + { /* successful updating */ + csa->d_st = 2; + if (csa->phase == 1) + { /* adjust reduced cost of xN[q] in adjacent basis, since + * its penalty coefficient changes (see below) */ + d[csa->q] -= c[head[csa->p]]; + } + } + else + { /* new reduced costs are inaccurate */ + csa->d_st = 0; + } + if (csa->phase == 1) + { /* xB[p] leaves the basis replacing xN[q], so set its penalty + * coefficient to zero */ + c[head[csa->p]] = 0.0; + } + /* update steepest edge weights for adjacent basis, if used */ + if (se != NULL) + { if (refct > 0) + { if (spx_update_gamma(lp, se, csa->p, csa->q, trow, tcol) + <= 1e-3) + { /* successful updating */ + refct--; + } + else + { /* new weights are inaccurate; reset reference space */ + se->valid = 0; + } + } + else + { /* too many updates; reset reference space */ + se->valid = 0; + } + } + /* update matrix N for adjacent basis, if used */ + if (nt != NULL) + spx_update_nt(lp, nt, csa->p, csa->q); +skip: /* change current basis header to adjacent one */ + spx_change_basis(lp, csa->p, csa->p_flag, csa->q); + /* and update factorization of the basis matrix */ + if (csa->p > 0) + spx_update_invb(lp, csa->p, head[csa->p]); + /* simplex iteration complete */ + csa->it_cnt++; + goto loop; +fini: /* restore original objective function */ + memcpy(c, csa->c, (1+n) * sizeof(double)); + /* compute reduced costs of non-basic variables and determine + * solution dual status, if necessary */ + if (csa->p_stat != GLP_UNDEF && csa->d_stat == GLP_UNDEF) + { xassert(ret != GLP_EFAIL); + spx_eval_pi(lp, pi); + for (j = 1; j <= n-m; j++) + d[j] = spx_eval_dj(lp, pi, j); + csa->num = spx_chuzc_sel(lp, d, tol_dj, tol_dj1, NULL); + csa->d_stat = (csa->num == 0 ? GLP_FEAS : GLP_INFEAS); + } + return ret; +} + +int spx_primal(glp_prob *P, const glp_smcp *parm) +{ /* driver to primal simplex method */ + struct csa csa_, *csa = &csa_; + SPXLP lp; +#if USE_AT + SPXAT at; +#else + SPXNT nt; +#endif + SPXSE se; + int ret, *map, *daeh; + /* build working LP and its initial basis */ + memset(csa, 0, sizeof(struct csa)); + csa->lp = &lp; + spx_init_lp(csa->lp, P, EXCL); + spx_alloc_lp(csa->lp); + map = talloc(1+P->m+P->n, int); + spx_build_lp(csa->lp, P, EXCL, SHIFT, map); + spx_build_basis(csa->lp, P, map); + switch (P->dir) + { case GLP_MIN: + csa->dir = +1; + break; + case GLP_MAX: + csa->dir = -1; + break; + default: + xassert(P != P); + } + csa->c = talloc(1+csa->lp->n, double); + memcpy(csa->c, csa->lp->c, (1+csa->lp->n) * sizeof(double)); +#if USE_AT + /* build matrix A in row-wise format */ + csa->at = &at; + csa->nt = NULL; + spx_alloc_at(csa->lp, csa->at); + spx_build_at(csa->lp, csa->at); +#else + /* build matrix N in row-wise format for initial basis */ + csa->at = NULL; + csa->nt = &nt; + spx_alloc_nt(csa->lp, csa->nt); + spx_init_nt(csa->lp, csa->nt); + spx_build_nt(csa->lp, csa->nt); +#endif + /* allocate and initialize working components */ + csa->phase = 0; + csa->beta = talloc(1+csa->lp->m, double); + csa->beta_st = 0; + csa->d = talloc(1+csa->lp->n-csa->lp->m, double); + csa->d_st = 0; + switch (parm->pricing) + { case GLP_PT_STD: + csa->se = NULL; + break; + case GLP_PT_PSE: + csa->se = &se; + spx_alloc_se(csa->lp, csa->se); + break; + default: + xassert(parm != parm); + } + csa->list = talloc(1+csa->lp->n-csa->lp->m, int); + csa->tcol = talloc(1+csa->lp->m, double); + csa->trow = talloc(1+csa->lp->n-csa->lp->m, double); + csa->work = talloc(1+csa->lp->m, double); + /* initialize control parameters */ + csa->msg_lev = parm->msg_lev; + switch (parm->r_test) + { case GLP_RT_STD: + csa->harris = 0; + break; + case GLP_RT_HAR: + csa->harris = 1; + break; + default: + xassert(parm != parm); + } + csa->tol_bnd = parm->tol_bnd; + csa->tol_bnd1 = .001 * parm->tol_bnd; + csa->tol_dj = parm->tol_dj; + csa->tol_dj1 = .001 * parm->tol_dj; + csa->tol_piv = parm->tol_piv; + csa->it_lim = parm->it_lim; + csa->tm_lim = parm->tm_lim; + csa->out_frq = parm->out_frq; + csa->out_dly = parm->out_dly; + /* initialize working parameters */ + csa->tm_beg = xtime(); + csa->it_beg = csa->it_cnt = P->it_cnt; + csa->it_dpy = -1; + csa->inv_cnt = 0; + /* try to solve working LP */ + ret = primal_simplex(csa); + /* return basis factorization back to problem object */ + P->valid = csa->lp->valid; + P->bfd = csa->lp->bfd; + /* set solution status */ + P->pbs_stat = csa->p_stat; + P->dbs_stat = csa->d_stat; + /* if the solver failed, do not store basis header and basic + * solution components to problem object */ + if (ret == GLP_EFAIL) + goto skip; + /* convert working LP basis to original LP basis and store it to + * problem object */ + daeh = talloc(1+csa->lp->n, int); + spx_store_basis(csa->lp, P, map, daeh); + /* compute simplex multipliers for final basic solution found by + * the solver */ + spx_eval_pi(csa->lp, csa->work); + /* convert working LP solution to original LP solution and store + * it to problem object */ + spx_store_sol(csa->lp, P, SHIFT, map, daeh, csa->beta, csa->work, + csa->d); + tfree(daeh); + /* save simplex iteration count */ + P->it_cnt = csa->it_cnt; + /* report auxiliary/structural variable causing unboundedness */ + P->some = 0; + if (csa->p_stat == GLP_FEAS && csa->d_stat == GLP_NOFEAS) + { int k, kk; + /* xN[q] = x[k] causes unboundedness */ + xassert(1 <= csa->q && csa->q <= csa->lp->n - csa->lp->m); + k = csa->lp->head[csa->lp->m + csa->q]; + xassert(1 <= k && k <= csa->lp->n); + /* convert to number of original variable */ + for (kk = 1; kk <= P->m + P->n; kk++) + { if (abs(map[kk]) == k) + { P->some = kk; + break; + } + } + xassert(P->some != 0); + } +skip: /* deallocate working objects and arrays */ + spx_free_lp(csa->lp); + tfree(map); + tfree(csa->c); + if (csa->at != NULL) + spx_free_at(csa->lp, csa->at); + if (csa->nt != NULL) + spx_free_nt(csa->lp, csa->nt); + tfree(csa->beta); + tfree(csa->d); + if (csa->se != NULL) + spx_free_se(csa->lp, csa->se); + tfree(csa->list); + tfree(csa->tcol); + tfree(csa->trow); + tfree(csa->work); + /* return to calling program */ + return ret; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.57/src/simplex/spxprob.c b/resources/3rdparty/glpk-4.57/src/simplex/spxprob.c new file mode 100644 index 000000000..4bebe2e74 --- /dev/null +++ b/resources/3rdparty/glpk-4.57/src/simplex/spxprob.c @@ -0,0 +1,679 @@ +/* spxprob.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2015 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "spxprob.h" + +/*********************************************************************** +* spx_init_lp - initialize working LP object +* +* This routine determines the number of equality constraints m, the +* number of variables n, and the number of non-zero elements nnz in +* the constraint matrix for the working LP, which corresponds to the +* original LP, and stores these dimensions to the working LP object. +* (The working LP object should be allocated by the calling routine.) +* +* If the flag excl is set, the routine assumes that non-basic fixed +* variables will be excluded from the working LP. */ + +void spx_init_lp(SPXLP *lp, glp_prob *P, int excl) +{ int i, j, m, n, nnz; + m = P->m; + xassert(m > 0); + n = 0; + nnz = P->nnz; + xassert(P->valid); + /* scan rows of original LP */ + for (i = 1; i <= m; i++) + { GLPROW *row = P->row[i]; + if (excl && row->stat == GLP_NS) + { /* skip non-basic fixed auxiliary variable */ + /* nop */ + } + else + { /* include auxiliary variable in working LP */ + n++; + nnz++; /* unity column */ + } + } + /* scan columns of original LP */ + for (j = 1; j <= P->n; j++) + { GLPCOL *col = P->col[j]; + if (excl && col->stat == GLP_NS) + { /* skip non-basic fixed structural variable */ + GLPAIJ *aij; + for (aij = col->ptr; aij != NULL; aij = aij->c_next) + nnz--; + } + else + { /* include structural variable in working LP */ + n++; + } + } + /* initialize working LP data block */ + memset(lp, 0, sizeof(SPXLP)); + lp->m = m; + xassert(n > 0); + lp->n = n; + lp->nnz = nnz; + return; +} + +/*********************************************************************** +* spx_alloc_lp - allocate working LP arrays +* +* This routine allocates the memory for all arrays in the working LP +* object. */ + +void spx_alloc_lp(SPXLP *lp) +{ int m = lp->m; + int n = lp->n; + int nnz = lp->nnz; + lp->A_ptr = talloc(1+n+1, int); + lp->A_ind = talloc(1+nnz, int); + lp->A_val = talloc(1+nnz, double); + lp->b = talloc(1+m, double); + lp->c = talloc(1+n, double); + lp->l = talloc(1+n, double); + lp->u = talloc(1+n, double); + lp->head = talloc(1+n, int); + lp->flag = talloc(1+n-m, char); + return; +} + +/*********************************************************************** +* spx_build_lp - convert original LP to working LP +* +* This routine converts components (except the current basis) of the +* original LP to components of the working LP and perform scaling of +* these components. Also, if the original LP is maximization, the +* routine changes the signs of the objective coefficients and constant +* term to opposite ones. +* +* If the flag excl is set, original non-basic fixed variables are +* *not* included in the working LP. Otherwise, all (auxiliary and +* structural) original variables are included in the working LP. Note +* that this flag should have the same value as it has in a call to the +* routine spx_init_lp. +* +* If the flag shift is set, the routine shift bounds of variables +* included in the working LP to make at least one bound to be zero. +* If a variable has both lower and upper bounds, the bound having +* smaller magnitude is shifted to zero. +* +* On exit the routine stores information about correspondence between +* numbers of variables in the original and working LPs to the array +* map, which should have 1+P->m+P->n locations (location [0] is not +* used), where P->m is the numbers of rows and P->n is the number of +* columns in the original LP: +* +* map[i] = +k, 1 <= i <= P->m, means that i-th auxiliary variable of +* the original LP corresponds to variable x[k] of the working LP; +* +* map[i] = -k, 1 <= i <= P->m, means that i-th auxiliary variable of +* the original LP corresponds to variable x[k] of the working LP, and +* the upper bound of that variable was shifted to zero; +* +* map[i] = 0, 1 <= i <= P->m, means that i-th auxiliary variable of +* the original LP was excluded from the working LP; +* +* map[P->m+j], 1 <= j <= P->n, has the same sense as above, however, +* for j-th structural variable of the original LP. */ + +void spx_build_lp(SPXLP *lp, glp_prob *P, int excl, int shift, + int map[/*1+P->m+P->n*/]) +{ int m = lp->m; + int n = lp->n; + int nnz = lp->nnz; + int *A_ptr = lp->A_ptr; + int *A_ind = lp->A_ind; + double *A_val = lp->A_val; + double *b = lp->b; + double *c = lp->c; + double *l = lp->l; + double *u = lp->u; + int i, j, k, kk, ptr, end; + double dir, delta; + /* working LP is always minimization */ + switch (P->dir) + { case GLP_MIN: + dir = +1.0; + break; + case GLP_MAX: + dir = -1.0; + break; + default: + xassert(P != P); + } + /* initialize constant term of the objective */ + c[0] = dir * P->c0; + k = 0; /* number of variable in working LP */ + ptr = 1; /* current available position in A_ind/A_val */ + /* process rows of original LP */ + xassert(P->m == m); + for (i = 1; i <= m; i++) + { GLPROW *row = P->row[i]; + if (excl && row->stat == GLP_NS) + { /* i-th auxiliary variable is non-basic and fixed */ + /* substitute its scaled value in working LP */ + xassert(row->type == GLP_FX); + map[i] = 0; + b[i] = - row->lb * row->rii; + } + else + { /* include i-th auxiliary variable in working LP */ + map[i] = ++k; + /* setup k-th column of working constraint matrix which is + * i-th column of unity matrix */ + A_ptr[k] = ptr; + A_ind[ptr] = i; + A_val[ptr] = 1.0; + ptr++; + /* initialize right-hand side of i-th equality constraint + * and setup zero objective coefficient at variable x[k] */ + b[i] = c[k] = 0.0; + /* setup scaled bounds of variable x[k] */ + switch (row->type) + { case GLP_FR: + l[k] = -DBL_MAX, u[k] = +DBL_MAX; + break; + case GLP_LO: + l[k] = row->lb * row->rii, u[k] = +DBL_MAX; + break; + case GLP_UP: + l[k] = -DBL_MAX, u[k] = row->ub * row->rii; + break; + case GLP_DB: + l[k] = row->lb * row->rii, u[k] = row->ub * row->rii; + xassert(l[k] != u[k]); + break; + case GLP_FX: + l[k] = u[k] = row->lb * row->rii; + break; + default: + xassert(row != row); + } + } + } + /* process columns of original LP */ + for (j = 1; j <= P->n; j++) + { GLPCOL *col = P->col[j]; + GLPAIJ *aij; + if (excl && col->stat == GLP_NS) + { /* j-th structural variable is non-basic and fixed */ + /* substitute its scaled value in working LP */ + xassert(col->type == GLP_FX); + map[m+j] = 0; + if (col->lb != 0.0) + { /* (note that sjj scale factor is cancelled) */ + for (aij = col->ptr; aij != NULL; aij = aij->c_next) + b[aij->row->i] += + (aij->row->rii * aij->val) * col->lb; + c[0] += (dir * col->coef) * col->lb; + } + } + else + { /* include j-th structural variable in working LP */ + map[m+j] = ++k; + /* setup k-th column of working constraint matrix which is + * scaled j-th column of original constraint matrix (-A) */ + A_ptr[k] = ptr; + for (aij = col->ptr; aij != NULL; aij = aij->c_next) + { A_ind[ptr] = aij->row->i; + A_val[ptr] = - aij->row->rii * aij->val * col->sjj; + ptr++; + } + /* setup scaled objective coefficient at variable x[k] */ + c[k] = dir * col->coef * col->sjj; + /* setup scaled bounds of variable x[k] */ + switch (col->type) + { case GLP_FR: + l[k] = -DBL_MAX, u[k] = +DBL_MAX; + break; + case GLP_LO: + l[k] = col->lb / col->sjj, u[k] = +DBL_MAX; + break; + case GLP_UP: + l[k] = -DBL_MAX, u[k] = col->ub / col->sjj; + break; + case GLP_DB: + l[k] = col->lb / col->sjj, u[k] = col->ub / col->sjj; + xassert(l[k] != u[k]); + break; + case GLP_FX: + l[k] = u[k] = col->lb / col->sjj; + break; + default: + xassert(col != col); + } + } + } + xassert(k == n); + xassert(ptr == nnz+1); + A_ptr[n+1] = ptr; + /* shift bounds of all variables of working LP (optionally) */ + if (shift) + { for (kk = 1; kk <= m+P->n; kk++) + { k = map[kk]; + if (k == 0) + { /* corresponding original variable was excluded */ + continue; + } + /* shift bounds of variable x[k] */ + if (l[k] == -DBL_MAX && u[k] == +DBL_MAX) + { /* x[k] is unbounded variable */ + delta = 0.0; + } + else if (l[k] != -DBL_MAX && u[k] == +DBL_MAX) + { /* shift lower bound to zero */ + delta = l[k]; + l[k] = 0.0; + } + else if (l[k] == -DBL_MAX && u[k] != +DBL_MAX) + { /* shift upper bound to zero */ + map[kk] = -k; + delta = u[k]; + u[k] = 0.0; + } + else if (l[k] != u[k]) + { /* x[k] is double bounded variable */ + if (fabs(l[k]) <= fabs(u[k])) + { /* shift lower bound to zero */ + delta = l[k]; + l[k] = 0.0, u[k] -= delta; + } + else + { /* shift upper bound to zero */ + map[kk] = -k; + delta = u[k]; + l[k] -= delta, u[k] = 0.0; + } + xassert(l[k] != u[k]); + } + else + { /* shift fixed value to zero */ + delta = l[k]; + l[k] = u[k] = 0.0; + } + /* substitute x[k] = x'[k] + delta into all constraints + * and the objective function of working LP */ + if (delta != 0.0) + { ptr = A_ptr[k]; + end = A_ptr[k+1]; + for (; ptr < end; ptr++) + b[A_ind[ptr]] -= A_val[ptr] * delta; + c[0] += c[k] * delta; + } + } + } + return; +} + +/*********************************************************************** +* spx_build_basis - convert original LP basis to working LP basis +* +* This routine converts the current basis of the original LP to +* corresponding initial basis of the working LP, and moves the basis +* factorization driver from the original LP object to the working LP +* object. +* +* The array map should contain information provided by the routine +* spx_build_lp. */ + +void spx_build_basis(SPXLP *lp, glp_prob *P, const int map[]) +{ int m = lp->m; + int n = lp->n; + int *head = lp->head; + char *flag = lp->flag; + int i, j, k, ii, jj; + /* original basis factorization should be valid that guarantees + * the basis is correct */ + xassert(P->m == m); + xassert(P->valid); + /* initialize basis header for working LP */ + memset(&head[1], 0, m * sizeof(int)); + jj = 0; + /* scan rows of original LP */ + xassert(P->m == m); + for (i = 1; i <= m; i++) + { GLPROW *row = P->row[i]; + /* determine ordinal number of x[k] in working LP */ + if ((k = map[i]) < 0) + k = -k; + if (k == 0) + { /* corresponding original variable was excluded */ + continue; + } + xassert(1 <= k && k <= n); + if (row->stat == GLP_BS) + { /* x[k] is basic variable xB[ii] */ + ii = row->bind; + xassert(1 <= ii && ii <= m); + xassert(head[ii] == 0); + head[ii] = k; + } + else + { /* x[k] is non-basic variable xN[jj] */ + jj++; + head[m+jj] = k; + flag[jj] = (row->stat == GLP_NU); + } + } + /* scan columns of original LP */ + for (j = 1; j <= P->n; j++) + { GLPCOL *col = P->col[j]; + /* determine ordinal number of x[k] in working LP */ + if ((k = map[m+j]) < 0) + k = -k; + if (k == 0) + { /* corresponding original variable was excluded */ + continue; + } + xassert(1 <= k && k <= n); + if (col->stat == GLP_BS) + { /* x[k] is basic variable xB[ii] */ + ii = col->bind; + xassert(1 <= ii && ii <= m); + xassert(head[ii] == 0); + head[ii] = k; + } + else + { /* x[k] is non-basic variable xN[jj] */ + jj++; + head[m+jj] = k; + flag[jj] = (col->stat == GLP_NU); + } + } + xassert(m+jj == n); + /* acquire basis factorization */ + lp->valid = 1; + lp->bfd = P->bfd; + P->valid = 0; + P->bfd = NULL; + return; +} + +/*********************************************************************** +* spx_store_basis - convert working LP basis to original LP basis +* +* This routine converts the current working LP basis to corresponding +* original LP basis. This operations includes determining and setting +* statuses of all rows (auxiliary variables) and columns (structural +* variables), and building the basis header. +* +* The array map should contain information provided by the routine +* spx_build_lp. +* +* On exit the routine fills the array daeh. This array should have +* 1+lp->n locations (location [0] is not used) and contain the inverse +* of the working basis header lp->head, i.e. head[k'] = k means that +* daeh[k] = k'. */ + +void spx_store_basis(SPXLP *lp, glp_prob *P, const int map[], + int daeh[/*1+n*/]) +{ int m = lp->m; + int n = lp->n; + int *head = lp->head; + char *flag = lp->flag; + int i, j, k, kk; + /* determine inverse of working basis header */ + for (kk = 1; kk <= n; kk++) + daeh[head[kk]] = kk; + /* set row statuses */ + xassert(P->m == m); + for (i = 1; i <= m; i++) + { GLPROW *row = P->row[i]; + if ((k = map[i]) < 0) + k = -k; + if (k == 0) + { /* non-basic fixed auxiliary variable was excluded */ + xassert(row->type == GLP_FX); + row->stat = GLP_NS; + row->bind = 0; + } + else + { /* auxiliary variable corresponds to variable x[k] */ + kk = daeh[k]; + if (kk <= m) + { /* x[k] = xB[kk] */ + P->head[kk] = i; + row->stat = GLP_BS; + row->bind = kk; + } + else + { /* x[k] = xN[kk-m] */ + switch (row->type) + { case GLP_FR: + row->stat = GLP_NF; + break; + case GLP_LO: + row->stat = GLP_NL; + break; + case GLP_UP: + row->stat = GLP_NU; + break; + case GLP_DB: + row->stat = (flag[kk-m] ? GLP_NU : GLP_NL); + break; + case GLP_FX: + row->stat = GLP_NS; + break; + default: + xassert(row != row); + } + row->bind = 0; + } + } + } + /* set column statuses */ + for (j = 1; j <= P->n; j++) + { GLPCOL *col = P->col[j]; + if ((k = map[m+j]) < 0) + k = -k; + if (k == 0) + { /* non-basic fixed structural variable was excluded */ + xassert(col->type == GLP_FX); + col->stat = GLP_NS; + col->bind = 0; + } + else + { /* structural variable corresponds to variable x[k] */ + kk = daeh[k]; + if (kk <= m) + { /* x[k] = xB[kk] */ + P->head[kk] = m+j; + col->stat = GLP_BS; + col->bind = kk; + } + else + { /* x[k] = xN[kk-m] */ + switch (col->type) + { case GLP_FR: + col->stat = GLP_NF; + break; + case GLP_LO: + col->stat = GLP_NL; + break; + case GLP_UP: + col->stat = GLP_NU; + break; + case GLP_DB: + col->stat = (flag[kk-m] ? GLP_NU : GLP_NL); + break; + case GLP_FX: + col->stat = GLP_NS; + break; + default: + xassert(col != col); + } + col->bind = 0; + } + } + } + return; +} + +/*********************************************************************** +* spx_store_sol - convert working LP solution to original LP solution +* +* This routine converts the current basic solution of the working LP +* (values of basic variables, simplex multipliers, reduced costs of +* non-basic variables) to corresponding basic solution of the original +* LP (values and reduced costs of auxiliary and structural variables). +* This conversion includes unscaling all basic solution components, +* computing reduced costs of excluded non-basic variables, recovering +* unshifted values of basic variables, changing the signs of reduced +* costs (if the original LP is maximization), and computing the value +* of the objective function. +* +* The flag shift should have the same value as it has in a call to the +* routine spx_build_lp. +* +* The array map should contain information provided by the routine +* spx_build_lp. +* +* The array daeh should contain information provided by the routine +* spx_store_basis. +* +* The arrays beta, pi, and d should contain basic solution components +* for the working LP: +* +* array locations beta[1], ..., beta[m] should contain values of basic +* variables beta = (beta[i]); +* +* array locations pi[1], ..., pi[m] should contain simplex multipliers +* pi = (pi[i]); +* +* array locations d[1], ..., d[n-m] should contain reduced costs of +* non-basic variables d = (d[j]). */ + +void spx_store_sol(SPXLP *lp, glp_prob *P, int shift, + const int map[], const int daeh[], const double beta[], + const double pi[], const double d[]) +{ int m = lp->m; + char *flag = lp->flag; + int i, j, k, kk; + double dir; + /* working LP is always minimization */ + switch (P->dir) + { case GLP_MIN: + dir = +1.0; + break; + case GLP_MAX: + dir = -1.0; + break; + default: + xassert(P != P); + } + /* compute row solution components */ + xassert(P->m == m); + for (i = 1; i <= m; i++) + { GLPROW *row = P->row[i]; + if ((k = map[i]) < 0) + k = -k; + if (k == 0) + { /* non-basic fixed auxiliary variable was excluded */ + xassert(row->type == GLP_FX); + row->prim = row->lb; + /* compute reduced cost d[k] = c[k] - A'[k] * pi as if x[k] + * would be non-basic in working LP */ + row->dual = - dir * pi[i] * row->rii; + } + else + { /* auxiliary variable corresponds to variable x[k] */ + kk = daeh[k]; + if (kk <= m) + { /* x[k] = xB[kk] */ + row->prim = beta[kk] / row->rii; + if (shift) + row->prim += (map[i] < 0 ? row->ub : row->lb); + row->dual = 0.0; + } + else + { /* x[k] = xN[kk-m] */ + row->prim = (flag[kk-m] ? row->ub : row->lb); + row->dual = (dir * d[kk-m]) * row->rii; + } + } + } + /* compute column solution components and objective value */ + P->obj_val = P->c0; + for (j = 1; j <= P->n; j++) + { GLPCOL *col = P->col[j]; + if ((k = map[m+j]) < 0) + k = -k; + if (k == 0) + { /* non-basic fixed structural variable was excluded */ + GLPAIJ *aij; + double dk; + xassert(col->type == GLP_FX); + col->prim = col->lb; + /* compute reduced cost d[k] = c[k] - A'[k] * pi as if x[k] + * would be non-basic in working LP */ + /* (note that sjj scale factor is cancelled) */ + dk = dir * col->coef; + for (aij = col->ptr; aij != NULL; aij = aij->c_next) + dk += (aij->row->rii * aij->val) * pi[aij->row->i]; + col->dual = dir * dk; + } + else + { /* structural variable corresponds to variable x[k] */ + kk = daeh[k]; + if (kk <= m) + { /* x[k] = xB[kk] */ + col->prim = beta[kk] * col->sjj; + if (shift) + col->prim += (map[m+j] < 0 ? col->ub : col->lb); + col->dual = 0.0; + } + else + { /* x[k] = xN[kk-m] */ + col->prim = (flag[kk-m] ? col->ub : col->lb); + col->dual = (dir * d[kk-m]) / col->sjj; + } + } + P->obj_val += col->coef * col->prim; + } + return; +} + +/*********************************************************************** +* spx_free_lp - deallocate working LP arrays +* +* This routine deallocates the memory used for arrays of the working +* LP object. */ + +void spx_free_lp(SPXLP *lp) +{ tfree(lp->A_ptr); + tfree(lp->A_ind); + tfree(lp->A_val); + tfree(lp->b); + tfree(lp->c); + tfree(lp->l); + tfree(lp->u); + tfree(lp->head); + tfree(lp->flag); + return; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.57/src/simplex/spxprob.h b/resources/3rdparty/glpk-4.57/src/simplex/spxprob.h new file mode 100644 index 000000000..b7d87fa72 --- /dev/null +++ b/resources/3rdparty/glpk-4.57/src/simplex/spxprob.h @@ -0,0 +1,64 @@ +/* spxprob.h */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2015 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef SPXPROB_H +#define SPXPROB_H + +#include "prob.h" +#include "spxlp.h" + +#define spx_init_lp _glp_spx_init_lp +void spx_init_lp(SPXLP *lp, glp_prob *P, int excl); +/* initialize working LP object */ + +#define spx_alloc_lp _glp_spx_alloc_lp +void spx_alloc_lp(SPXLP *lp); +/* allocate working LP arrays */ + +#define spx_build_lp _glp_spx_build_lp +void spx_build_lp(SPXLP *lp, glp_prob *P, int excl, int shift, + int map[/*1+P->m+P->n*/]); +/* convert original LP to working LP */ + +#define spx_build_basis _glp_spx_build_basis +void spx_build_basis(SPXLP *lp, glp_prob *P, const int map[]); +/* convert original LP basis to working LP basis */ + +#define spx_store_basis _glp_spx_store_basis +void spx_store_basis(SPXLP *lp, glp_prob *P, const int map[], + int daeh[/*1+n*/]); +/* convert working LP basis to original LP basis */ + +#define spx_store_sol _glp_spx_store_sol +void spx_store_sol(SPXLP *lp, glp_prob *P, int shift, + const int map[], const int daeh[], const double beta[], + const double pi[], const double d[]); +/* convert working LP solution to original LP solution */ + +#define spx_free_lp _glp_spx_free_lp +void spx_free_lp(SPXLP *lp); +/* deallocate working LP arrays */ + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.57/src/simplex/spychuzc.c b/resources/3rdparty/glpk-4.57/src/simplex/spychuzc.c new file mode 100644 index 000000000..dbf8029bb --- /dev/null +++ b/resources/3rdparty/glpk-4.57/src/simplex/spychuzc.c @@ -0,0 +1,222 @@ +/* spychuzc.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2015 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "spychuzc.h" + +/*********************************************************************** +* spy_chuzc_std - choose non-basic variable (dual textbook ratio test) +* +* This routine implements an improved dual textbook ratio test to +* choose non-basic variable xN[q]. +* +* Current reduced costs of non-basic variables should be placed in the +* array locations d[1], ..., d[n-m]. Note that d[j] is a value of dual +* basic variable lambdaN[j] in the current basis. +* +* The parameter s specifies the sign of bound violation for basic +* variable xB[p] chosen: s = +1.0 means that xB[p] violates its lower +* bound, so dual non-basic variable lambdaB[p] = lambda^+B[p] +* increases, and s = -1.0 means that xB[p] violates its upper bound, +* so dual non-basic variable lambdaB[p] = lambda^-B[p] decreases. +* (Thus, the dual ray parameter theta = s * lambdaB[p] >= 0.) +* +* Elements of p-th simplex table row t[p] = (t[p,j]) corresponding +* to basic variable xB[p] should be placed in the array locations +* trow[1], ..., trow[n-m]. +* +* The parameter tol_piv specifies a tolerance for elements of the +* simplex table row t[p]. If |t[p,j]| < tol_piv, dual basic variable +* lambdaN[j] is skipped, i.e. it is assumed that it does not depend on +* the dual ray parameter theta. +* +* The parameters tol and tol1 specify tolerances used to increase the +* choice freedom by simulating an artificial degeneracy as follows. +* If lambdaN[j] = lambda^+N[j] >= 0 and d[j] <= +delta[j], or if +* lambdaN[j] = lambda^-N[j] <= 0 and d[j] >= -delta[j], where +* delta[j] = tol + tol1 * |cN[j]|, cN[j] is objective coefficient at +* xN[j], then it is assumed that reduced cost d[j] is equal to zero. +* +* The routine determines the index 1 <= q <= n-m of non-basic variable +* xN[q], for which corresponding dual basic variable lambda^+N[j] or +* lambda^-N[j] reaches its zero bound first on increasing the dual ray +* parameter theta, and returns p on exit. And if theta may increase +* unlimitedly, the routine returns zero. */ + +int spy_chuzc_std(SPXLP *lp, const double d[/*1+n-m*/], + double s, const double trow[/*1+n-m*/], double tol_piv, + double tol, double tol1) +{ int m = lp->m; + int n = lp->n; + double *c = lp->c; + double *l = lp->l; + double *u = lp->u; + int *head = lp->head; + char *flag = lp->flag; + int j, k, q; + double alfa, biga, delta, teta, teta_min; + xassert(s == +1.0 || s == -1.0); + /* nothing is chosen so far */ + q = 0, teta_min = DBL_MAX, biga = 0.0; + /* walk thru the list of non-basic variables */ + for (j = 1; j <= n-m; j++) + { k = head[m+j]; /* x[k] = xN[j] */ + /* if xN[j] is fixed variable, skip it */ + if (l[k] == u[k]) + continue; + alfa = s * trow[j]; + if (alfa >= +tol_piv && !flag[j]) + { /* xN[j] is either free or has its lower bound active, so + * lambdaN[j] = d[j] >= 0 decreases down to zero */ + delta = tol + tol1 * (c[k] >= 0.0 ? +c[k] : -c[k]); + /* determine theta on which lambdaN[j] reaches zero */ + teta = (d[j] < +delta ? 0.0 : d[j] / alfa); + } + else if (alfa <= -tol_piv && (l[k] == -DBL_MAX || flag[j])) + { /* xN[j] is either free or has its upper bound active, so + * lambdaN[j] = d[j] <= 0 increases up to zero */ + delta = tol + tol1 * (c[k] >= 0.0 ? +c[k] : -c[k]); + /* determine theta on which lambdaN[j] reaches zero */ + teta = (d[j] > -delta ? 0.0 : d[j] / alfa); + } + else + { /* lambdaN[j] cannot reach zero on increasing theta */ + continue; + } + /* choose non-basic variable xN[q] by corresponding dual basic + * variable lambdaN[q] for which theta is minimal */ + xassert(teta >= 0.0); + alfa = (alfa >= 0.0 ? +alfa : -alfa); + if (teta_min > teta || (teta_min == teta && biga < alfa)) + q = j, teta_min = teta, biga = alfa; + } + return q; +} + +/*********************************************************************** +* spy_chuzc_harris - choose non-basic var. (dual Harris' ratio test) +* +* This routine implements dual Harris' ratio test to choose non-basic +* variable xN[q]. +* +* All the parameters, except tol and tol1, as well as the returned +* value have the same meaning as for the routine spx_chuzr_std (see +* above). +* +* The parameters tol and tol1 specify tolerances on zero bound +* violations for reduced costs of non-basic variables. For reduced +* cost d[j] the tolerance is delta[j] = tol + tol1 |cN[j]|, where +* cN[j] is objective coefficient at non-basic variable xN[j]. */ + +int spy_chuzc_harris(SPXLP *lp, const double d[/*1+n-m*/], + double s, const double trow[/*1+n-m*/], double tol_piv, + double tol, double tol1) +{ int m = lp->m; + int n = lp->n; + double *c = lp->c; + double *l = lp->l; + double *u = lp->u; + int *head = lp->head; + char *flag = lp->flag; + int j, k, q; + double alfa, biga, delta, teta, teta_min; + xassert(s == +1.0 || s == -1.0); + /*--------------------------------------------------------------*/ + /* first pass: determine teta_min for relaxed bounds */ + /*--------------------------------------------------------------*/ + teta_min = DBL_MAX; + /* walk thru the list of non-basic variables */ + for (j = 1; j <= n-m; j++) + { k = head[m+j]; /* x[k] = xN[j] */ + /* if xN[j] is fixed variable, skip it */ + if (l[k] == u[k]) + continue; + alfa = s * trow[j]; + if (alfa >= +tol_piv && !flag[j]) + { /* xN[j] is either free or has its lower bound active, so + * lambdaN[j] = d[j] >= 0 decreases down to zero */ + delta = tol + tol1 * (c[k] >= 0.0 ? +c[k] : -c[k]); + /* determine theta on which lambdaN[j] reaches -delta */ + teta = ((d[j] < 0.0 ? 0.0 : d[j]) + delta) / alfa; + } + else if (alfa <= -tol_piv && (l[k] == -DBL_MAX || flag[j])) + { /* xN[j] is either free or has its upper bound active, so + * lambdaN[j] = d[j] <= 0 increases up to zero */ + delta = tol + tol1 * (c[k] >= 0.0 ? +c[k] : -c[k]); + /* determine theta on which lambdaN[j] reaches +delta */ + teta = ((d[j] > 0.0 ? 0.0 : d[j]) - delta) / alfa; + } + else + { /* lambdaN[j] cannot reach zero on increasing theta */ + continue; + } + xassert(teta >= 0.0); + if (teta_min > teta) + teta_min = teta; + } + /*--------------------------------------------------------------*/ + /* second pass: choose non-basic variable xN[q] */ + /*--------------------------------------------------------------*/ + if (teta_min == DBL_MAX) + { /* theta may increase unlimitedly */ + q = 0; + goto done; + } + /* nothing is chosen so far */ + q = 0, biga = 0.0; + /* walk thru the list of non-basic variables */ + for (j = 1; j <= n-m; j++) + { k = head[m+j]; /* x[k] = xN[j] */ + /* if xN[j] is fixed variable, skip it */ + if (l[k] == u[k]) + continue; + alfa = s * trow[j]; + if (alfa >= +tol_piv && !flag[j]) + { /* xN[j] is either free or has its lower bound active, so + * lambdaN[j] = d[j] >= 0 decreases down to zero */ + /* determine theta on which lambdaN[j] reaches zero */ + teta = d[j] / alfa; + } + else if (alfa <= -tol_piv && (l[k] == -DBL_MAX || flag[j])) + { /* xN[j] is either free or has its upper bound active, so + * lambdaN[j] = d[j] <= 0 increases up to zero */ + /* determine theta on which lambdaN[j] reaches zero */ + teta = d[j] / alfa; + } + else + { /* lambdaN[j] cannot reach zero on increasing theta */ + continue; + } + /* choose non-basic variable for which theta is not greater + * than theta_min determined for relaxed bounds and which has + * best (largest in magnitude) pivot */ + alfa = (alfa >= 0.0 ? +alfa : -alfa); + if (teta <= teta_min && biga < alfa) + q = j, biga = alfa; + } + /* something must be chosen */ + xassert(1 <= q && q <= n-m); +done: return q; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/glpspx.h b/resources/3rdparty/glpk-4.57/src/simplex/spychuzc.h similarity index 59% rename from resources/3rdparty/glpk-4.53/src/glpspx.h rename to resources/3rdparty/glpk-4.57/src/simplex/spychuzc.h index e62687a6c..751e64dda 100644 --- a/resources/3rdparty/glpk-4.53/src/glpspx.h +++ b/resources/3rdparty/glpk-4.57/src/simplex/spychuzc.h @@ -1,10 +1,9 @@ -/* glpspx.h (core simplex solvers) */ +/* spychuzc.h */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * -* Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, -* 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied +* Copyright (C) 2015 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * @@ -22,18 +21,22 @@ * along with GLPK. If not, see . ***********************************************************************/ -#ifndef GLPSPX_H -#define GLPSPX_H +#ifndef SPYCHUZC_H +#define SPYCHUZC_H -#include "prob.h" +#include "spxlp.h" -#define spx_primal _glp_spx_primal -int spx_primal(glp_prob *lp, const glp_smcp *parm); -/* core LP solver based on the primal simplex method */ +#define spy_chuzc_std _glp_spy_chuzc_std +int spy_chuzc_std(SPXLP *lp, const double d[/*1+n-m*/], + double s, const double trow[/*1+n-m*/], double tol_piv, + double tol, double tol1); +/* choose non-basic variable (dual textbook ratio test) */ -#define spx_dual _glp_spx_dual -int spx_dual(glp_prob *lp, const glp_smcp *parm); -/* core LP solver based on the dual simplex method */ +#define spy_chuzc_harris _glp_spy_chuzc_harris +int spy_chuzc_harris(SPXLP *lp, const double d[/*1+n-m*/], + double s, const double trow[/*1+n-m*/], double tol_piv, + double tol, double tol1); +/* choose non-basic variable (dual Harris' ratio test) */ #endif diff --git a/resources/3rdparty/glpk-4.57/src/simplex/spychuzr.c b/resources/3rdparty/glpk-4.57/src/simplex/spychuzr.c new file mode 100644 index 000000000..756ce3e6a --- /dev/null +++ b/resources/3rdparty/glpk-4.57/src/simplex/spychuzr.c @@ -0,0 +1,406 @@ +/* spychuzr.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2015 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "spychuzr.h" + +/*********************************************************************** +* spy_chuzr_sel - select eligible basic variables +* +* This routine selects eligible basic variables xB[i], whose value +* beta[i] violates corresponding lower lB[i] or upper uB[i] bound. +* Positive bound violation rp[i] = lb[i] - beta[i] > 0 is the reduced +* cost of non-basic dual variable lambda^+B[i] >= 0, so increasing it +* increases the dual objective. Similarly, negative bound violation +* rn[i] = ub[i] - beta[i] < 0 is the reduced cost of non-basic dual +* variable lambda^-B[i] <= 0, so decreasing it also increases the dual +* objective. +* +* Current values of basic variables should be placed in the array +* locations beta[1], ..., beta[m]. +* +* Basic variable xB[i] is considered eligible, if: +* +* beta[i] <= lB[i] - eps1[i], or +* +* beta[i] >= uB[i] + eps2[i], +* +* for +* +* eps1[i] = tol + tol1 * |lB[i]|, +* +* eps2[i] = tol + tol2 * |uB[i]|, +* +* where lB[i] and uB[i] are, resp., lower and upper bounds of xB[i], +* tol and tol1 are specified tolerances. +* +* On exit the routine stores indices i of eligible basic variables +* xB[i] to the array locations list[1], ..., list[num] and returns the +* number of such variables 0 <= num <= m. (If the parameter list is +* specified as NULL, no indices are stored.) */ + +int spy_chuzr_sel(SPXLP *lp, const double beta[/*1+m*/], double tol, + double tol1, int list[/*1+m*/]) +{ int m = lp->m; + double *l = lp->l; + double *u = lp->u; + int *head = lp->head; + int i, k, num; + double lk, uk, eps; + num = 0; + /* walk thru list of basic variables */ + for (i = 1; i <= m; i++) + { k = head[i]; /* x[k] = xB[i] */ + lk = l[k], uk = u[k]; + /* check if xB[i] is eligible */ + if (beta[i] < lk) + { /* determine absolute tolerance eps1[i] */ + eps = tol + tol1 * (lk >= 0.0 ? +lk : -lk); + if (beta[i] < lk - eps) + { /* lower bound is violated */ + num++; + if (list != NULL) + list[num] = i; + } + } + else if (beta[i] > uk) + { /* determine absolute tolerance eps2[i] */ + eps = tol + tol1 * (uk >= 0.0 ? +uk : -uk); + if (beta[i] > uk + eps) + { /* upper bound is violated */ + num++; + if (list != NULL) + list[num] = i; + } + } + } + return num; +} + +/*********************************************************************** +* spy_chuzr_std - choose basic variable (dual Dantzig's rule) +* +* This routine chooses most eligible basic variable xB[p] according +* to dual Dantzig's ("standard") rule: +* +* r[p] = max |r[i]|, +* i in I +* +* ( lB[i] - beta[i], if beta[i] < lB[i] +* ( +* r[i] = { 0, if lB[i] <= beta[i] <= uB[i] +* ( +* ( uB[i] - beta[i], if beta[i] > uB[i] +* +* where I <= {1, ..., m} is the set of indices of eligible basic +* variables, beta[i] is current value of xB[i], lB[i] and uB[i] are, +* resp., lower and upper bounds of xB[i], r[i] is bound violation. +* +* Current values of basic variables should be placed in the array +* locations beta[1], ..., beta[m]. +* +* Indices of eligible basic variables i in I should be placed in the +* array locations list[1], ..., list[num], where num = |J| > 0 is the +* total number of such variables. +* +* On exit the routine returns p, the index of the basic variable xB[p] +* chosen. */ + +int spy_chuzr_std(SPXLP *lp, const double beta[/*1+m*/], int num, + const int list[]) +{ int m = lp->m; + double *l = lp->l; + double *u = lp->u; + int *head = lp->head; + int i, k, p, t; + double abs_ri, abs_rp; + xassert(0 < num && num <= m); + p = 0, abs_rp = -1.0; + for (t = 1; t <= num; t++) + { i = list[t]; + k = head[i]; /* x[k] = xB[i] */ + if (beta[i] < l[k]) + abs_ri = l[k] - beta[i]; + else if (beta[i] > u[k]) + abs_ri = beta[i] - u[k]; + else + xassert(t != t); + if (abs_rp < abs_ri) + p = i, abs_rp = abs_ri; + } + xassert(p != 0); + return p; +} + +/*********************************************************************** +* spy_alloc_se - allocate dual pricing data block +* +* This routine allocates the memory for arrays used in the dual +* pricing data block. */ + +void spy_alloc_se(SPXLP *lp, SPYSE *se) +{ int m = lp->m; + int n = lp->n; + se->valid = 0; + se->refsp = talloc(1+n, char); + se->gamma = talloc(1+m, double); + se->work = talloc(1+m, double); + return; +} + +/*********************************************************************** +* spy_reset_refsp - reset dual reference space +* +* This routine resets (re-initializes) the dual reference space +* composing it from dual variables which are non-basic (corresponding +* to basic primal variables) in the current basis, and sets all +* weights gamma[i] to 1. */ + +void spy_reset_refsp(SPXLP *lp, SPYSE *se) +{ int m = lp->m; + int n = lp->n; + int *head = lp->head; + char *refsp = se->refsp; + double *gamma = se->gamma; + int i, k; + se->valid = 1; + memset(&refsp[1], 0, n * sizeof(char)); + for (i = 1; i <= m; i++) + { k = head[i]; /* x[k] = xB[i] */ + refsp[k] = 1; + gamma[i] = 1.0; + } + return; +} + +/*********************************************************************** +* spy_eval_gamma_i - compute dual proj. steepest edge weight directly +* +* This routine computes dual projected steepest edge weight gamma[i], +* 1 <= i <= m, for the current basis directly with the formula: +* +* n-m +* gamma[i] = delta[i] + sum eta[j] * T[i,j]**2, +* j=1 +* +* where T[i,j] is element of the current simplex table, and +* +* ( 1, if lambdaN[j] is in the reference space +* eta[j] = { +* ( 0, otherwise +* +* ( 1, if lambdaB[i] is in the reference space +* delta[i] = { +* ( 0, otherwise +* +* Dual basic variable lambdaN[j] corresponds to primal non-basic +* variable xN[j], and dual non-basic variable lambdaB[j] corresponds +* to primal basic variable xB[i]. +* +* NOTE: For testing/debugging only. */ + +double spy_eval_gamma_i(SPXLP *lp, SPYSE *se, int i) +{ int m = lp->m; + int n = lp->n; + int *head = lp->head; + char *refsp = se->refsp; + double *rho = se->work; + int j, k; + double gamma_i, t_ij; + xassert(se->valid); + xassert(1 <= i && i <= m); + k = head[i]; /* x[k] = xB[i] */ + gamma_i = (refsp[k] ? 1.0 : 0.0); + spx_eval_rho(lp, i, rho); + for (j = 1; j <= n-m; j++) + { k = head[m+j]; /* x[k] = xN[j] */ + if (refsp[k]) + { t_ij = spx_eval_tij(lp, rho, j); + gamma_i += t_ij * t_ij; + } + } + return gamma_i; +} + +/*********************************************************************** +* spy_chuzr_pse - choose basic variable (dual projected steepest edge) +* +* This routine chooses most eligible basic variable xB[p] according +* to the dual projected steepest edge method: +* +* r[p]**2 r[i]**2 +* -------- = max -------- , +* gamma[p] i in I gamma[i] +* +* ( lB[i] - beta[i], if beta[i] < lB[i] +* ( +* r[i] = { 0, if lB[i] <= beta[i] <= uB[i] +* ( +* ( uB[i] - beta[i], if beta[i] > uB[i] +* +* where I <= {1, ..., m} is the set of indices of eligible basic +* variables, beta[i] is current value of xB[i], lB[i] and uB[i] are, +* resp., lower and upper bounds of xB[i], r[i] is bound violation. +* +* Current values of basic variables should be placed in the array +* locations beta[1], ..., beta[m]. +* +* Indices of eligible basic variables i in I should be placed in the +* array locations list[1], ..., list[num], where num = |J| > 0 is the +* total number of such variables. +* +* On exit the routine returns p, the index of the basic variable xB[p] +* chosen. */ + +int spy_chuzr_pse(SPXLP *lp, SPYSE *se, const double beta[/*1+m*/], + int num, const int list[]) +{ int m = lp->m; + double *l = lp->l; + double *u = lp->u; + int *head = lp->head; + double *gamma = se->gamma; + int i, k, p, t; + double best, ri, temp; + xassert(0 < num && num <= m); + p = 0, best = -1.0; + for (t = 1; t <= num; t++) + { i = list[t]; + k = head[i]; /* x[k] = xB[i] */ + if (beta[i] < l[k]) + ri = l[k] - beta[i]; + else if (beta[i] > u[k]) + ri = u[k] - beta[i]; + else + xassert(t != t); + /* FIXME */ + if (gamma[i] < DBL_EPSILON) + temp = 0.0; + else + temp = (ri * ri) / gamma[i]; + if (best < temp) + p = i, best = temp; + } + xassert(p != 0); + return p; +} + +/*********************************************************************** +* spy_update_gamma - update dual proj. steepest edge weights exactly +* +* This routine updates the vector gamma = (gamma[i]) of dual projected +* steepest edge weights exactly, for the adjacent basis. +* +* On entry to the routine the content of the se object should be valid +* and should correspond to the current basis. +* +* The parameter 1 <= p <= m specifies basic variable xB[p] which +* becomes non-basic variable xN[q] in the adjacent basis. +* +* The parameter 1 <= q <= n-m specified non-basic variable xN[q] which +* becomes basic variable xB[p] in the adjacent basis. +* +* It is assumed that the array trow contains elements of p-th (pivot) +* row T'[p] of the simplex table in locations trow[1], ..., trow[n-m]. +* It is also assumed that the array tcol contains elements of q-th +* (pivot) column T[q] of the simple table in locations tcol[1], ..., +* tcol[m]. (These row and column should be computed for the current +* basis.) +* +* For details about the formulae used see the program documentation. +* +* The routine also computes the relative error: +* +* e = |gamma[p] - gamma'[p]| / (1 + |gamma[p]|), +* +* where gamma'[p] is the weight for lambdaB[p] (which is dual +* non-basic variable corresponding to xB[p]) on entry to the routine, +* and returns e on exit. (If e happens to be large enough, the calling +* program may reset the reference space, since other weights also may +* be inaccurate.) */ + +double spy_update_gamma(SPXLP *lp, SPYSE *se, int p, int q, + const double trow[/*1+n-m*/], const double tcol[/*1+m*/]) +{ int m = lp->m; + int n = lp->n; + int *head = lp->head; + char *refsp = se->refsp; + double *gamma = se->gamma; + double *u = se->work; + int i, j, k, ptr, end; + double gamma_p, delta_p, e, r, t1, t2; + xassert(se->valid); + xassert(1 <= p && p <= m); + xassert(1 <= q && q <= n-m); + /* compute gamma[p] in current basis more accurately; also + * compute auxiliary vector u */ + k = head[p]; /* x[k] = xB[p] */ + gamma_p = delta_p = (refsp[k] ? 1.0 : 0.0); + for (i = 1; i <= m; i++) + u[i] = 0.0; + for (j = 1; j <= n-m; j++) + { k = head[m+j]; /* x[k] = xN[j] */ + if (refsp[k] && trow[j] != 0.0) + { gamma_p += trow[j] * trow[j]; + /* u := u + T[p,j] * N[j], where N[j] = A[k] is constraint + * matrix column corresponding to xN[j] */ + ptr = lp->A_ptr[k]; + end = lp->A_ptr[k+1]; + for (; ptr < end; ptr++) + u[lp->A_ind[ptr]] += trow[j] * lp->A_val[ptr]; + } + } + bfd_ftran(lp->bfd, u); + /* compute relative error in gamma[p] */ + e = fabs(gamma_p - gamma[p]) / (1.0 + gamma_p); + /* compute new gamma[p] */ + gamma[p] = gamma_p / (tcol[p] * tcol[p]); + /* compute new gamma[i] for all i != p */ + for (i = 1; i <= m; i++) + { if (i == p) + continue; + /* compute r[i] = T[i,q] / T[p,q] */ + r = tcol[i] / tcol[p]; + /* compute new gamma[i] */ + t1 = gamma[i] + r * (r * gamma_p + u[i] + u[i]); + k = head[i]; /* x[k] = xB[i] */ + t2 = (refsp[k] ? 1.0 : 0.0) + delta_p * r * r; + gamma[i] = (t1 >= t2 ? t1 : t2); + } + return e; +} + +/*********************************************************************** +* spy_free_se - deallocate dual pricing data block +* +* This routine deallocates the memory used for arrays in the dual +* pricing data block. */ + +void spy_free_se(SPXLP *lp, SPYSE *se) +{ xassert(lp == lp); + tfree(se->refsp); + tfree(se->gamma); + tfree(se->work); + return; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.57/src/simplex/spychuzr.h b/resources/3rdparty/glpk-4.57/src/simplex/spychuzr.h new file mode 100644 index 000000000..5be8192ef --- /dev/null +++ b/resources/3rdparty/glpk-4.57/src/simplex/spychuzr.h @@ -0,0 +1,86 @@ +/* spychuzr.h */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2015 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#ifndef SPYCHUZR_H +#define SPYCHUZR_H + +#include "spxlp.h" + +#define spy_chuzr_sel _glp_spy_chuzr_sel +int spy_chuzr_sel(SPXLP *lp, const double beta[/*1+m*/], double tol, + double tol1, int list[/*1+m*/]); +/* select eligible basic variables */ + +#define spy_chuzr_std _glp_spy_chuzr_std +int spy_chuzr_std(SPXLP *lp, const double beta[/*1+m*/], int num, + const int list[]); +/* choose basic variable (dual Dantzig's rule) */ + +typedef struct SPYSE SPYSE; + +struct SPYSE +{ /* dual projected steepest edge and Devex pricing data block */ + int valid; + /* content validity flag */ + char *refsp; /* char refsp[1+n]; */ + /* refsp[0] is not used; + * refsp[k], 1 <= k <= n, is the flag meaning that dual variable + * lambda[k] is in the dual reference space */ + double *gamma; /* double gamma[1+m]; */ + /* gamma[0] is not used; + * gamma[i], 1 <= i <= m, is the weight for reduced cost r[i] + * of dual non-basic variable lambdaB[j] in the current basis + * (r[i] is bound violation for basic variable xB[i]) */ + double *work; /* double work[1+m]; */ + /* working array */ +}; + +#define spy_alloc_se _glp_spy_alloc_se +void spy_alloc_se(SPXLP *lp, SPYSE *se); +/* allocate dual pricing data block */ + +#define spy_reset_refsp _glp_spy_reset_refsp +void spy_reset_refsp(SPXLP *lp, SPYSE *se); +/* reset dual reference space */ + +#define spy_eval_gamma_i _glp_spy_eval_gamma_i +double spy_eval_gamma_i(SPXLP *lp, SPYSE *se, int i); +/* compute dual projected steepest edge weight directly */ + +#define spy_chuzr_pse _glp_spy_chuzr_pse +int spy_chuzr_pse(SPXLP *lp, SPYSE *se, const double beta[/*1+m*/], + int num, const int list[]); +/* choose basic variable (dual projected steepest edge) */ + +#define spy_update_gamma _glp_spy_update_gamma +double spy_update_gamma(SPXLP *lp, SPYSE *se, int p, int q, + const double trow[/*1+n-m*/], const double tcol[/*1+m*/]); +/* update dual projected steepest edge weights exactly */ + +#define spy_free_se _glp_spy_free_se +void spy_free_se(SPXLP *lp, SPYSE *se); +/* deallocate dual pricing data block */ + +#endif + +/* eof */ diff --git a/resources/3rdparty/glpk-4.57/src/simplex/spydual.c b/resources/3rdparty/glpk-4.57/src/simplex/spydual.c new file mode 100644 index 000000000..9d08fbdc9 --- /dev/null +++ b/resources/3rdparty/glpk-4.57/src/simplex/spydual.c @@ -0,0 +1,1221 @@ +/* spydual.c */ + +/*********************************************************************** +* This code is part of GLPK (GNU Linear Programming Kit). +* +* Copyright (C) 2015 Andrew Makhorin, Department for Applied +* Informatics, Moscow Aviation Institute, Moscow, Russia. All rights +* reserved. E-mail: . +* +* GLPK is free software: you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* GLPK is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +* License for more details. +* +* You should have received a copy of the GNU General Public License +* along with GLPK. If not, see . +***********************************************************************/ + +#include "env.h" +#include "simplex.h" +#include "spxat.h" +#include "spxnt.h" +#include "spxprob.h" +#include "spychuzc.h" +#include "spychuzr.h" + +#define USE_AT 1 +/* 1 - use A in row-wise format + * 0 - use N in row-wise format */ +/* (Looks like using A' provide more accuracy for dual simplex.) */ + +#define EXCL 1 +/* 1 - exclude fixed non-basic variables + * 0 - don't exclude variables */ + +#define SHIFT 1 +/* 1 - shift bounds of variables toward zero + * 0 - don't shift bounds of variables */ + +#define CHECK_ACCURACY 0 +/* (for debugging) */ + +struct csa +{ /* common storage area */ + SPXLP *lp; + /* LP problem data and its (current) basis; this LP has m rows + * and n columns */ + int dir; + /* original optimization direction: + * +1 - minimization + * -1 - maximization */ + double *b; /* double b[1+m]; */ + /* copy of original right-hand sides */ + double *l; /* double l[1+n]; */ + /* copy of original lower bounds */ + double *u; /* double u[1+n]; */ + /* copy of original upper bounds */ + SPXAT *at; + /* mxn-matrix A of constraint coefficients, in sparse row-wise + * format (NULL if not used) */ + SPXNT *nt; + /* mx(n-m)-matrix N composed of non-basic columns of constraint + * matrix A, in sparse row-wise format (NULL if not used) */ + int phase; + /* search phase: + * 0 - not determined yet + * 1 - searching for dual feasible solution + * 2 - searching for optimal solution */ + double *beta; /* double beta[1+m]; */ + /* beta[i] is primal value of basic variable xB[i] */ + int beta_st; + /* status of the vector beta: + * 0 - undefined + * 1 - just computed + * 2 - updated */ + double *d; /* double d[1+n-m]; */ + /* d[j] is reduced cost of non-basic variable xN[j] */ + int d_st; + /* status of the vector d: + * 0 - undefined + * 1 - just computed + * 2 - updated */ + SPYSE *se; + /* dual projected steepest edge and Devex pricing data block + * (NULL if not used) */ + int num; + /* number of eligible basic variables */ + int *list; /* int list[1+m]; */ + /* list[1], ..., list[num] are indices i of eligible basic + * variables xB[i] */ + int p; + /* xB[p] is a basic variable chosen to leave the basis */ + double *trow; /* double trow[1+n-m]; */ + /* p-th (pivot) row of the simplex table */ + int q; + /* xN[q] is a non-basic variable chosen to enter the basis */ + double *tcol; /* double tcol[1+m]; */ + /* q-th (pivot) column of the simplex table */ + double *work; /* double work[1+m]; */ + /* working array */ + double *work1; /* double work1[1+n-m]; */ + /* another working array */ + int p_stat, d_stat; + /* primal and dual solution statuses */ + /*--------------------------------------------------------------*/ + /* control parameters (see struct glp_smcp) */ + int msg_lev; + /* message level */ + int dualp; + /* if this flag is set, report failure in case of instability */ + int harris; + /* dual ratio test technique: + * 0 - textbook ratio test + * 1 - Harris' two pass ratio test */ + double tol_bnd, tol_bnd1; + /* primal feasibility tolerances */ + double tol_dj, tol_dj1; + /* dual feasibility tolerances */ + double tol_piv; + /* pivot tolerance */ + double obj_lim; + /* objective limit */ + int it_lim; + /* iteration limit */ + int tm_lim; + /* time limit, milliseconds */ + int out_frq; + /* display output frequency, iterations */ + int out_dly; + /* display output delay, milliseconds */ + /*--------------------------------------------------------------*/ + /* working parameters */ + double tm_beg; + /* time value at the beginning of the search */ + int it_beg; + /* simplex iteration count at the beginning of the search */ + int it_cnt; + /* simplex iteration count; it increases by one every time the + * basis changes */ + int it_dpy; + /* simplex iteration count at most recent display output */ + int inv_cnt; + /* basis factorization count since most recent display output */ +}; + +/*********************************************************************** +* check_flags - check correctness of active bound flags +* +* This routine checks that flags specifying active bounds of all +* non-basic variables are correct. +* +* NOTE: It is important to note that if bounds of variables have been +* changed, active bound flags should be corrected accordingly. */ + +static void check_flags(struct csa *csa) +{ SPXLP *lp = csa->lp; + int m = lp->m; + int n = lp->n; + double *l = lp->l; + double *u = lp->u; + int *head = lp->head; + char *flag = lp->flag; + int j, k; + for (j = 1; j <= n-m; j++) + { k = head[m+j]; /* x[k] = xN[j] */ + if (l[k] == -DBL_MAX && u[k] == +DBL_MAX) + xassert(!flag[j]); + else if (l[k] != -DBL_MAX && u[k] == +DBL_MAX) + xassert(!flag[j]); + else if (l[k] == -DBL_MAX && u[k] != +DBL_MAX) + xassert(flag[j]); + else if (l[k] == u[k]) + xassert(!flag[j]); + } + return; +} + +/*********************************************************************** +* set_art_bounds - set artificial right-hand sides and bounds +* +* This routine sets artificial right-hand sides and artificial bounds +* for all variables to minimize the sum of dual infeasibilities on +* phase I. Given current reduced costs d = (d[j]) this routine also +* sets active artificial bounds of non-basic variables to provide dual +* feasibility (this is always possible because all variables have both +* lower and upper artificial bounds). */ + +static void set_art_bounds(struct csa *csa) +{ SPXLP *lp = csa->lp; + int m = lp->m; + int n = lp->n; + double *b = lp->b; + double *l = lp->l; + double *u = lp->u; + int *head = lp->head; + char *flag = lp->flag; + double *d = csa->d; + int i, j, k; + /* set artificial right-hand sides */ + for (i = 1; i <= m; i++) + b[i] = 0.0; + /* set artificial bounds depending on types of variables */ + for (k = 1; k <= n; k++) + { if (csa->l[k] == -DBL_MAX && csa->u[k] == +DBL_MAX) + { /* force free variables to enter the basis */ + l[k] = -1e3, u[k] = +1e3; + } + else if (csa->l[k] != -DBL_MAX && csa->u[k] == +DBL_MAX) + l[k] = 0.0, u[k] = +1.0; + else if (csa->l[k] == -DBL_MAX && csa->u[k] != +DBL_MAX) + l[k] = -1.0, u[k] = 0.0; + else + l[k] = u[k] = 0.0; + } + /* set active artificial bounds for non-basic variables */ + xassert(csa->d_st == 1); + for (j = 1; j <= n-m; j++) + { k = head[m+j]; /* x[k] = xN[j] */ + flag[j] = (l[k] != u[k] && d[j] < 0.0); + } + /* invalidate values of basic variables, since active bounds of + * non-basic variables have been changed */ + csa->beta_st = 0; + return; +} + +/*********************************************************************** +* set_orig_bounds - restore original right-hand sides and bounds +* +* This routine restores original right-hand sides and original bounds +* for all variables. This routine also sets active original bounds for +* non-basic variables; for double-bounded non-basic variables current +* reduced costs d = (d[j]) are used to decide which bound (lower or +* upper) should be made active. */ + +void set_orig_bounds(struct csa *csa) +{ SPXLP *lp = csa->lp; + int m = lp->m; + int n = lp->n; + double *b = lp->b; + double *l = lp->l; + double *u = lp->u; + int *head = lp->head; + char *flag = lp->flag; + double *d = csa->d; + int j, k; + /* restore original right-hand sides */ + memcpy(b, csa->b, (1+m) * sizeof(double)); + /* restore original bounds of all variables */ + memcpy(l, csa->l, (1+n) * sizeof(double)); + memcpy(u, csa->u, (1+n) * sizeof(double)); + /* set active original bounds for non-basic variables */ + xassert(csa->d_st == 1); + for (j = 1; j <= n-m; j++) + { k = head[m+j]; /* x[k] = xN[j] */ + if (l[k] == -DBL_MAX && u[k] == +DBL_MAX) + flag[j] = 0; + else if (l[k] != -DBL_MAX && u[k] == +DBL_MAX) + flag[j] = 0; + else if (l[k] == -DBL_MAX && u[k] != +DBL_MAX) + flag[j] = 1; + else if (l[k] != u[k]) + flag[j] = (d[j] < 0.0); + else + flag[j] = 0; + } + /* invalidate values of basic variables, since active bounds of + * non-basic variables have been changed */ + csa->beta_st = 0; + return; +} + +/*********************************************************************** +* check_feas - check dual feasibility of basic solution +* +* This routine checks that reduced costs of all non-basic variables +* d = (d[j]) have correct signs. +* +* Reduced cost d[j] is considered as having correct sign within the +* specified tolerance depending on status of non-basic variable xN[j] +* if one of the following conditions is met: +* +* xN[j] is free -eps <= d[j] <= +eps +* +* xN[j] has its lower bound active d[j] >= -eps +* +* xN[j] has its upper bound active d[j] <= +eps +* +* xN[j] is fixed d[j] has any value +* +* where eps = tol + tol1 * |cN[j]|, cN[j] is the objective coefficient +* at xN[j]. (See also the routine spx_chuzc_sel.) +* +* The flag recov allows the routine to recover dual feasibility by +* changing active bounds of non-basic variables. (For example, if +* xN[j] has its lower bound active and d[j] < -eps, the feasibility +* can be recovered by making xN[j] active on its upper bound.) +* +* If the basic solution is dual feasible, the routine returns zero. +* If the basic solution is dual infeasible, but its dual feasibility +* can be recovered (or has been recovered, if the flag recov is set), +* the routine returns a negative value. Otherwise, the routine returns +* the number j of some non-basic variable xN[j], whose reduced cost +* d[j] is dual infeasible and cannot be recovered. */ + +static int check_feas(struct csa *csa, double tol, double tol1, + int recov) +{ SPXLP *lp = csa->lp; + int m = lp->m; + int n = lp->n; + double *c = lp->c; + double *l = lp->l; + double *u = lp->u; + int *head = lp->head; + char *flag = lp->flag; + double *d = csa->d; + int j, k, ret = 0; + double eps; + /* reduced costs should be just computed */ + xassert(csa->d_st == 1); + /* walk thru list of non-basic variables */ + for (j = 1; j <= n-m; j++) + { k = head[m+j]; /* x[k] = xN[j] */ + if (l[k] == u[k]) + { /* xN[j] is fixed variable; skip it */ + continue; + } + /* determine absolute tolerance eps[j] */ + eps = tol + tol1 * (c[k] >= 0.0 ? +c[k] : -c[k]); + /* check dual feasibility of xN[j] */ + if (d[j] > +eps) + { /* xN[j] should have its lower bound active */ + if (l[k] == -DBL_MAX || flag[j]) + { /* but it either has no lower bound or its lower bound + * is inactive */ + if (l[k] == -DBL_MAX) + { /* cannot recover, since xN[j] has no lower bound */ + ret = j; + break; + } + /* recovering is possible */ + if (recov) + flag[j] = 0; + ret = -1; + } + } + else if (d[j] < -eps) + { /* xN[j] should have its upper bound active */ + if (!flag[j]) + { /* but it either has no upper bound or its upper bound + * is inactive */ + if (u[k] == +DBL_MAX) + { /* cannot recover, since xN[j] has no upper bound */ + ret = j; + break; + } + /* recovering is possible */ + if (recov) + flag[j] = 1; + ret = -1; + } + } + } + if (recov && ret) + { /* invalidate values of basic variables, since active bounds + * of non-basic variables have been changed */ + csa->beta_st = 0; + } + return ret; +} + +#if CHECK_ACCURACY +/*********************************************************************** +* err_in_vec - compute maximal relative error between two vectors +* +* This routine computes and returns maximal relative error between +* n-vectors x and y: +* +* err_max = max |x[i] - y[i]| / (1 + |x[i]|). +* +* NOTE: This routine is intended only for debugginig purposes. */ + +static double err_in_vec(int n, const double x[], const double y[]) +{ int i; + double err, err_max; + err_max = 0.0; + for (i = 1; i <= n; i++) + { err = fabs(x[i] - y[i]) / (1.0 + fabs(x[i])); + if (err_max < err) + err_max = err; + } + return err_max; +} +#endif + +#if CHECK_ACCURACY +/*********************************************************************** +* err_in_beta - compute maximal relative error in vector beta +* +* This routine computes and returns maximal relative error in vector +* of values of basic variables beta = (beta[i]). +* +* NOTE: This routine is intended only for debugginig purposes. */ + +static double err_in_beta(struct csa *csa) +{ SPXLP *lp = csa->lp; + int m = lp->m; + double err, *beta; + beta = talloc(1+m, double); + spx_eval_beta(lp, beta); + err = err_in_vec(m, beta, csa->beta); + tfree(beta); + return err; +} +#endif + +#if CHECK_ACCURACY +/*********************************************************************** +* err_in_d - compute maximal relative error in vector d +* +* This routine computes and returns maximal relative error in vector +* of reduced costs of non-basic variables d = (d[j]). +* +* NOTE: This routine is intended only for debugginig purposes. */ + +static double err_in_d(struct csa *csa) +{ SPXLP *lp = csa->lp; + int m = lp->m; + int n = lp->n; + int j; + double err, *pi, *d; + pi = talloc(1+m, double); + d = talloc(1+n-m, double); + spx_eval_pi(lp, pi); + for (j = 1; j <= n-m; j++) + d[j] = spx_eval_dj(lp, pi, j); + err = err_in_vec(n-m, d, csa->d); + tfree(pi); + tfree(d); + return err; +} +#endif + +#if CHECK_ACCURACY +/*********************************************************************** +* err_in_gamma - compute maximal relative error in vector gamma +* +* This routine computes and returns maximal relative error in vector +* of projected steepest edge weights gamma = (gamma[j]). +* +* NOTE: This routine is intended only for debugginig purposes. */ + +static double err_in_gamma(struct csa *csa) +{ SPXLP *lp = csa->lp; + int m = lp->m; + int n = lp->n; + SPYSE *se = csa->se; + int i; + double err, *gamma; + xassert(se != NULL); +gamma = talloc(1+m, double); + for (i = 1; i <= m; i++) + gamma[i] = spy_eval_gamma_i(lp, se, i); + err = err_in_vec(m, gamma, se->gamma); + tfree(gamma); + return err; +} +#endif + +#if CHECK_ACCURACY +/*********************************************************************** +* check_accuracy - check accuracy of basic solution components +* +* This routine checks accuracy of current basic solution components. +* +* NOTE: This routine is intended only for debugginig purposes. */ + +static void check_accuracy(struct csa *csa) +{ double e_beta, e_d, e_gamma; + e_beta = err_in_beta(csa); + e_d = err_in_d(csa); + if (csa->se == NULL) + e_gamma = 0.; + else + e_gamma = err_in_gamma(csa); + xprintf("e_beta = %10.3e; e_d = %10.3e; e_gamma = %10.3e\n", + e_beta, e_d, e_gamma); + xassert(e_beta <= 1e-5 && e_d <= 1e-5 && e_gamma <= 1e-3); + return; +} +#endif + +/*********************************************************************** +* choose_pivot - choose xB[p] and xN[q] +* +* Given the list of eligible basic variables this routine first +* chooses basic variable xB[p]. This choice is always possible, +* because the list is assumed to be non-empty. Then the routine +* computes p-th row T[p,*] of the simplex table T[i,j] and chooses +* non-basic variable xN[q]. If the pivot T[p,q] is small in magnitude, +* the routine attempts to choose another xB[p] and xN[q] in order to +* avoid badly conditioned adjacent bases. */ + +static void choose_pivot(struct csa *csa) +{ SPXLP *lp = csa->lp; + int m = lp->m; + int n = lp->n; + double *l = lp->l; + int *head = lp->head; + SPXAT *at = csa->at; + SPXNT *nt = csa->nt; + double *beta = csa->beta; + double *d = csa->d; + SPYSE *se = csa->se; + int *list = csa->list; + double *rho = csa->work; + double *trow = csa->work1; + int nnn, try, k, p, q, t; + xassert(csa->beta_st); + xassert(csa->d_st); + /* initial number of eligible basic variables */ + nnn = csa->num; + /* nothing has been chosen so far */ + csa->p = 0; + try = 0; +try: /* choose basic variable xB[p] */ + xassert(nnn > 0); + try++; + if (se == NULL) + { /* dual Dantzig's rule */ + p = spy_chuzr_std(lp, beta, nnn, list); + } + else + { /* dual projected steepest edge */ + p = spy_chuzr_pse(lp, se, beta, nnn, list); + } + xassert(1 <= p && p <= m); + /* compute p-th row of inv(B) */ + spx_eval_rho(lp, p, rho); + /* compute p-th row of the simplex table */ + if (at != NULL) + spx_eval_trow1(lp, at, rho, trow); + else + spx_nt_prod(lp, nt, trow, 1, -1.0, rho); + /* choose non-basic variable xN[q] */ + k = head[p]; /* x[k] = xB[p] */ + if (!csa->harris) + q = spy_chuzc_std(lp, d, beta[p] < l[k] ? +1. : -1., trow, + csa->tol_piv, .30 * csa->tol_dj, .30 * csa->tol_dj1); + else + q = spy_chuzc_harris(lp, d, beta[p] < l[k] ? +1. : -1., trow, + csa->tol_piv, .35 * csa->tol_dj, .35 * csa->tol_dj1); + /* either keep previous choice or accept new choice depending on + * which one is better */ + if (csa->p == 0 || q == 0 || + fabs(trow[q]) > fabs(csa->trow[csa->q])) + { csa->p = p; + memcpy(&csa->trow[1], &trow[1], (n-m) * sizeof(double)); + csa->q = q; + } + /* check if current choice is acceptable */ + if (csa->q == 0 || fabs(csa->trow[csa->q]) >= 0.001) + goto done; + if (nnn == 1) + goto done; + if (try == 5) + goto done; + /* try to choose other xB[p] and xN[q] */ + /* find xB[p] in the list */ + for (t = 1; t <= nnn; t++) + if (list[t] == p) break; + xassert(t <= nnn); + /* move xB[p] to the end of the list */ + list[t] = list[nnn], list[nnn] = p; + /* and exclude it from consideration */ + nnn--; + /* repeat the choice */ + goto try; +done: /* the choice has been made */ + return; +} + +/*********************************************************************** +* display - display search progress +* +* This routine displays some information about the search progress +* that includes: +* +* search phase; +* +* number of simplex iterations performed by the solver; +* +* original objective value (only on phase II); +* +* sum of (scaled) dual infeasibilities for original bounds; +* +* number of dual infeasibilities (phase I) or primal infeasibilities +* (phase II); +* +* number of basic factorizations since last display output. */ + +static void display(struct csa *csa, int spec) +{ SPXLP *lp = csa->lp; + int m = lp->m; + int n = lp->n; + int *head = lp->head; + char *flag = lp->flag; + double *l = csa->l; /* original lower bounds */ + double *u = csa->u; /* original upper bounds */ + double *beta = csa->beta; + double *d = csa->d; + int j, k, nnn; + double sum; + /* check if the display output should be skipped */ + if (csa->msg_lev < GLP_MSG_ON) goto skip; + if (csa->out_dly > 0 && + 1000.0 * xdifftime(xtime(), csa->tm_beg) < csa->out_dly) + goto skip; + if (csa->it_cnt == csa->it_dpy) goto skip; + if (!spec && csa->it_cnt % csa->out_frq != 0) goto skip; + /* display search progress depending on search phase */ + switch (csa->phase) + { case 1: + /* compute sum and number of (scaled) dual infeasibilities + * for original bounds */ + sum = 0.0, nnn = 0; + for (j = 1; j <= n-m; j++) + { k = head[m+j]; /* x[k] = xN[j] */ + if (d[j] > 0.0) + { /* xN[j] should have lower bound */ + if (l[k] == -DBL_MAX) + { sum += d[j]; + if (d[j] > +1e-7) + nnn++; + } + } + else if (d[j] < 0.0) + { /* xN[j] should have upper bound */ + if (u[k] == +DBL_MAX) + { sum -= d[j]; + if (d[j] < -1e-7) + nnn++; + } + } + } + /* on phase I variables have artificial bounds which are + * meaningless for original LP, so corresponding objective + * function value is also meaningless */ + xprintf(" %6d: %23s inf = %11.3e (%d)", + csa->it_cnt, "", sum, nnn); + break; + case 2: + /* compute sum of (scaled) dual infeasibilities */ + sum = 0.0, nnn = 0; + for (j = 1; j <= n-m; j++) + { k = head[m+j]; /* x[k] = xN[j] */ + if (d[j] > 0.0) + { /* xN[j] should have its lower bound active */ + if (l[k] == -DBL_MAX || flag[j]) + sum += d[j]; + } + else if (d[j] < 0.0) + { /* xN[j] should have its upper bound active */ + if (l[k] != u[k] && !flag[j]) + sum -= d[j]; + } + } + /* compute number of primal infeasibilities */ + nnn = spy_chuzr_sel(lp, beta, csa->tol_bnd, csa->tol_bnd1, + NULL); + xprintf("#%6d: obj = %17.9e inf = %11.3e (%d)", + csa->it_cnt, (double)csa->dir * spx_eval_obj(lp, beta), + sum, nnn); + break; + default: + xassert(csa != csa); + } + if (csa->inv_cnt) + { /* number of basis factorizations performed */ + xprintf(" %d", csa->inv_cnt); + csa->inv_cnt = 0; + } + xprintf("\n"); + csa->it_dpy = csa->it_cnt; +skip: return; +} + +/*********************************************************************** +* spy_dual - driver to dual simplex method +* +* This routine is a driver to the two-phase dual simplex method. +* +* On exit this routine returns one of the following codes: +* +* 0 LP instance has been successfully solved. +* +* GLP_EOBJLL +* Objective lower limit has been reached (maximization). +* +* GLP_EOBJUL +* Objective upper limit has been reached (minimization). +* +* GLP_EITLIM +* Iteration limit has been exhausted. +* +* GLP_ETMLIM +* Time limit has been exhausted. +* +* GLP_EFAIL +* The solver failed to solve LP instance. */ + +static int dual_simplex(struct csa *csa) +{ /* dual simplex method main logic routine */ + SPXLP *lp = csa->lp; + int m = lp->m; + int n = lp->n; + double *l = lp->l; + double *u = lp->u; + int *head = lp->head; + SPXNT *nt = csa->nt; + double *beta = csa->beta; + double *d = csa->d; + SPYSE *se = csa->se; + int *list = csa->list; + double *trow = csa->trow; + double *tcol = csa->tcol; + double *pi = csa->work; + int msg_lev = csa->msg_lev; + double tol_bnd = csa->tol_bnd; + double tol_bnd1 = csa->tol_bnd1; + double tol_dj = csa->tol_dj; + double tol_dj1 = csa->tol_dj1; + int j, k, p_flag, refct, ret; + check_flags(csa); +loop: /* main loop starts here */ + /* compute factorization of the basis matrix */ + if (!lp->valid) + { double cond; + ret = spx_factorize(lp); + csa->inv_cnt++; + if (ret != 0) + { if (msg_lev >= GLP_MSG_ERR) + xprintf("Error: unable to factorize the basis matrix (%d" + ")\n", ret); + csa->p_stat = csa->d_stat = GLP_UNDEF; + ret = GLP_EFAIL; + goto fini; + } + /* check condition of the basis matrix */ + cond = bfd_condest(lp->bfd); + if (cond > 1.0 / DBL_EPSILON) + { if (msg_lev >= GLP_MSG_ERR) + xprintf("Error: basis matrix is singular to working prec" + "ision (cond = %.3g)\n", cond); + csa->p_stat = csa->d_stat = GLP_UNDEF; + ret = GLP_EFAIL; + goto fini; + } + if (cond > 0.001 / DBL_EPSILON) + { if (msg_lev >= GLP_MSG_ERR) + xprintf("Warning: basis matrix is ill-conditioned (cond " + "= %.3g)\n", cond); + } + /* invalidate basic solution components */ + csa->beta_st = csa->d_st = 0; + } + /* compute reduced costs of non-basic variables d = (d[j]) */ + if (!csa->d_st) + { spx_eval_pi(lp, pi); + for (j = 1; j <= n-m; j++) + d[j] = spx_eval_dj(lp, pi, j); + csa->d_st = 1; /* just computed */ + /* determine the search phase, if not determined yet (this is + * performed only once at the beginning of the search for the + * original bounds) */ + if (!csa->phase) + { j = check_feas(csa, 0.97 * tol_dj, 0.97 * tol_dj1, 1); + if (j > 0) + { /* initial basic solution is dual infeasible and cannot + * be recovered */ + /* start to search for dual feasible solution */ + set_art_bounds(csa); + csa->phase = 1; + } + else + { /* initial basic solution is either dual feasible or its + * dual feasibility has been recovered */ + /* start to search for optimal solution */ + csa->phase = 2; + } + } + /* make sure that current basic solution is dual feasible */ + j = check_feas(csa, tol_dj, tol_dj1, 0); + if (j) + { /* dual feasibility is broken due to excessive round-off + * errors */ + if (bfd_get_count(lp->bfd)) + { /* try to provide more accuracy */ + lp->valid = 0; + goto loop; + } + if (msg_lev >= GLP_MSG_ERR) + xprintf("Warning: numerical instability (dual simplex, p" + "hase %s)\n", csa->phase == 1 ? "I" : "II"); + if (csa->dualp) + { /* do not continue the search; report failure */ + csa->p_stat = csa->d_stat = GLP_UNDEF; + ret = -1; /* special case of GLP_EFAIL */ + goto fini; + } + /* try to recover dual feasibility */ + j = check_feas(csa, 0.97 * tol_dj, 0.97 * tol_dj1, 1); + if (j > 0) + { /* dual feasibility cannot be recovered (this may happen + * only on phase II) */ + xassert(csa->phase == 2); + /* restart to search for dual feasible solution */ + set_art_bounds(csa); + csa->phase = 1; + } + } + } + /* at this point the search phase is determined */ + xassert(csa->phase == 1 || csa->phase == 2); + /* compute values of basic variables beta = (beta[i]) */ + if (!csa->beta_st) + { spx_eval_beta(lp, beta); + csa->beta_st = 1; /* just computed */ + } + /* reset the dual reference space, if necessary */ + if (se != NULL && !se->valid) + spy_reset_refsp(lp, se), refct = 1000; + /* at this point the basis factorization and all basic solution + * components are valid */ + xassert(lp->valid && csa->beta_st && csa->d_st); + check_flags(csa); +#if CHECK_ACCURACY + /* check accuracy of current basic solution components (only for + * debugging) */ + check_accuracy(csa); +#endif + /* check if the objective limit has been reached */ + if (csa->phase == 2 && csa->obj_lim != DBL_MAX + && spx_eval_obj(lp, beta) >= csa->obj_lim) + { if (csa->beta_st != 1) + csa->beta_st = 0; + if (csa->d_st != 1) + csa->d_st = 0; + if (!(csa->beta_st && csa->d_st)) + goto loop; + display(csa, 1); + if (msg_lev >= GLP_MSG_ALL) + xprintf("OBJECTIVE %s LIMIT REACHED; SEARCH TERMINATED\n", + csa->dir > 0 ? "UPPER" : "LOWER"); + csa->num = spy_chuzr_sel(lp, beta, tol_bnd, tol_bnd1, list); + csa->p_stat = (csa->num == 0 ? GLP_FEAS : GLP_INFEAS); + csa->d_stat = GLP_FEAS; + ret = (csa->dir > 0 ? GLP_EOBJUL : GLP_EOBJLL); + goto fini; + } + /* check if the iteration limit has been exhausted */ + if (csa->it_cnt - csa->it_beg >= csa->it_lim) + { if (csa->beta_st != 1) + csa->beta_st = 0; + if (csa->d_st != 1) + csa->d_st = 0; + if (!(csa->beta_st && csa->d_st)) + goto loop; + display(csa, 1); + if (msg_lev >= GLP_MSG_ALL) + xprintf("ITERATION LIMIT EXCEEDED; SEARCH TERMINATED\n"); + if (csa->phase == 1) + { set_orig_bounds(csa); + check_flags(csa); + spx_eval_beta(lp, beta); + } + csa->num = spy_chuzr_sel(lp, beta, tol_bnd, tol_bnd1, list); + csa->p_stat = (csa->num == 0 ? GLP_FEAS : GLP_INFEAS); + csa->d_stat = (csa->phase == 1 ? GLP_INFEAS : GLP_FEAS); + ret = GLP_EITLIM; + goto fini; + } + /* check if the time limit has been exhausted */ + if (1000.0 * xdifftime(xtime(), csa->tm_beg) >= csa->tm_lim) + { if (csa->beta_st != 1) + csa->beta_st = 0; + if (csa->d_st != 1) + csa->d_st = 0; + if (!(csa->beta_st && csa->d_st)) + goto loop; + display(csa, 1); + if (msg_lev >= GLP_MSG_ALL) + xprintf("TIME LIMIT EXCEEDED; SEARCH TERMINATED\n"); + if (csa->phase == 1) + { set_orig_bounds(csa); + check_flags(csa); + spx_eval_beta(lp, beta); + } + csa->num = spy_chuzr_sel(lp, beta, tol_bnd, tol_bnd1, list); + csa->p_stat = (csa->num == 0 ? GLP_FEAS : GLP_INFEAS); + csa->d_stat = (csa->phase == 1 ? GLP_INFEAS : GLP_FEAS); + ret = GLP_EITLIM; + goto fini; + } + /* display the search progress */ + display(csa, 0); + /* select eligible basic variables */ + switch (csa->phase) + { case 1: + csa->num = spy_chuzr_sel(lp, beta, 1e-8, 0.0, list); + break; + case 2: + csa->num = spy_chuzr_sel(lp, beta, tol_bnd, tol_bnd1, list); + break; + default: + xassert(csa != csa); + } + /* check for optimality */ + if (csa->num == 0) + { if (csa->beta_st != 1) + csa->beta_st = 0; + if (csa->d_st != 1) + csa->d_st = 0; + if (!(csa->beta_st && csa->d_st)) + goto loop; + /* current basis is optimal */ + display(csa, 1); + switch (csa->phase) + { case 1: + /* check for dual feasibility */ + set_orig_bounds(csa); + check_flags(csa); + if (check_feas(csa, tol_dj, tol_dj1, 0) == 0) + { /* dual feasible solution found; switch to phase II */ + csa->phase = 2; + xassert(!csa->beta_st); + goto loop; + } + /* no dual feasible solution exists */ + if (msg_lev >= GLP_MSG_ALL) + xprintf("LP HAS NO DUAL FEASIBLE SOLUTION\n"); + spx_eval_beta(lp, beta); + csa->num = spy_chuzr_sel(lp, beta, tol_bnd, tol_bnd1, + list); + csa->p_stat = (csa->num == 0 ? GLP_FEAS : GLP_INFEAS); + csa->d_stat = GLP_NOFEAS; + ret = 0; + goto fini; + case 2: + /* optimal solution found */ + if (msg_lev >= GLP_MSG_ALL) + xprintf("OPTIMAL LP SOLUTION FOUND\n"); + csa->p_stat = csa->d_stat = GLP_FEAS; + ret = 0; + goto fini; + default: + xassert(csa != csa); + } + } + /* choose xB[p] and xN[q] */ + choose_pivot(csa); + /* check for dual unboundedness */ + if (csa->q == 0) + { if (csa->beta_st != 1) + csa->beta_st = 0; + if (csa->d_st != 1) + csa->d_st = 0; + if (!(csa->beta_st && csa->d_st)) + goto loop; + display(csa, 1); + switch (csa->phase) + { case 1: + /* this should never happen */ + if (msg_lev >= GLP_MSG_ERR) + xprintf("Error: dual simplex failed\n"); + csa->p_stat = csa->d_stat = GLP_UNDEF; + ret = GLP_EFAIL; + goto fini; + case 2: + /* dual unboundedness detected */ + if (msg_lev >= GLP_MSG_ALL) + xprintf("LP HAS NO PRIMAL FEASIBLE SOLUTION\n"); + csa->p_stat = GLP_NOFEAS; + csa->d_stat = GLP_FEAS; + ret = 0; + goto fini; + default: + xassert(csa != csa); + } + } + /* compute q-th column of the simplex table */ + spx_eval_tcol(lp, csa->q, tcol); + /* FIXME: tcol[p] and trow[q] should be close to each other */ + xassert(tcol[csa->p] != 0.0); + /* update values of basic variables for adjacent basis */ + k = head[csa->p]; /* x[k] = xB[p] */ + p_flag = (l[k] != u[k] && beta[csa->p] > u[k]); + spx_update_beta(lp, beta, csa->p, p_flag, csa->q, tcol); + csa->beta_st = 2; + /* update reduced costs of non-basic variables for adjacent + * basis */ + if (spx_update_d(lp, d, csa->p, csa->q, trow, tcol) <= 1e-9) + { /* successful updating */ + csa->d_st = 2; + } + else + { /* new reduced costs are inaccurate */ + csa->d_st = 0; + } + /* update steepest edge weights for adjacent basis, if used */ + if (se != NULL) + { if (refct > 0) + { if (spy_update_gamma(lp, se, csa->p, csa->q, trow, tcol) + <= 1e-3) + { /* successful updating */ + refct--; + } + else + { /* new weights are inaccurate; reset reference space */ + se->valid = 0; + } + } + else + { /* too many updates; reset reference space */ + se->valid = 0; + } + } + /* update matrix N for adjacent basis, if used */ + if (nt != NULL) + spx_update_nt(lp, nt, csa->p, csa->q); + /* change current basis header to adjacent one */ + spx_change_basis(lp, csa->p, p_flag, csa->q); + /* and update factorization of the basis matrix */ + if (csa->p > 0) + spx_update_invb(lp, csa->p, head[csa->p]); + /* dual simplex iteration complete */ + csa->it_cnt++; + goto loop; +fini: return ret; +} + +int spy_dual(glp_prob *P, const glp_smcp *parm) +{ /* driver to dual simplex method */ + struct csa csa_, *csa = &csa_; + SPXLP lp; +#if USE_AT + SPXAT at; +#else + SPXNT nt; +#endif + SPYSE se; + int ret, *map, *daeh; + /* build working LP and its initial basis */ + memset(csa, 0, sizeof(struct csa)); + csa->lp = &lp; + spx_init_lp(csa->lp, P, EXCL); + spx_alloc_lp(csa->lp); + map = talloc(1+P->m+P->n, int); + spx_build_lp(csa->lp, P, EXCL, SHIFT, map); + spx_build_basis(csa->lp, P, map); + switch (P->dir) + { case GLP_MIN: + csa->dir = +1; + break; + case GLP_MAX: + csa->dir = -1; + break; + default: + xassert(P != P); + } + csa->b = talloc(1+csa->lp->m, double); + memcpy(csa->b, csa->lp->b, (1+csa->lp->m) * sizeof(double)); + csa->l = talloc(1+csa->lp->n, double); + memcpy(csa->l, csa->lp->l, (1+csa->lp->n) * sizeof(double)); + csa->u = talloc(1+csa->lp->n, double); + memcpy(csa->u, csa->lp->u, (1+csa->lp->n) * sizeof(double)); +#if USE_AT + /* build matrix A in row-wise format */ + csa->at = &at; + csa->nt = NULL; + spx_alloc_at(csa->lp, csa->at); + spx_build_at(csa->lp, csa->at); +#else + /* build matrix N in row-wise format for initial basis */ + csa->at = NULL; + csa->nt = &nt; + spx_alloc_nt(csa->lp, csa->nt); + spx_init_nt(csa->lp, csa->nt); + spx_build_nt(csa->lp, csa->nt); +#endif + /* allocate and initialize working components */ + csa->phase = 0; + csa->beta = talloc(1+csa->lp->m, double); + csa->beta_st = 0; + csa->d = talloc(1+csa->lp->n-csa->lp->m, double); + csa->d_st = 0; + switch (parm->pricing) + { case GLP_PT_STD: + csa->se = NULL; + break; + case GLP_PT_PSE: + csa->se = &se; + spy_alloc_se(csa->lp, csa->se); + break; + default: + xassert(parm != parm); + } + csa->list = talloc(1+csa->lp->m, int); + csa->trow = talloc(1+csa->lp->n-csa->lp->m, double); + csa->tcol = talloc(1+csa->lp->m, double); + csa->work = talloc(1+csa->lp->m, double); + csa->work1 = talloc(1+csa->lp->n-csa->lp->m, double); + /* initialize control parameters */ + csa->msg_lev = parm->msg_lev; + csa->dualp = (parm->meth == GLP_DUALP); + switch (parm->r_test) + { case GLP_RT_STD: + csa->harris = 0; + break; + case GLP_RT_HAR: + csa->harris = 1; + break; + default: + xassert(parm != parm); + } + csa->tol_bnd = parm->tol_bnd; + csa->tol_bnd1 = .001 * parm->tol_bnd; + csa->tol_dj = parm->tol_dj; + csa->tol_dj1 = .001 * parm->tol_dj; + csa->tol_piv = parm->tol_piv; + switch (P->dir) + { case GLP_MIN: + csa->obj_lim = + parm->obj_ul; + break; + case GLP_MAX: + csa->obj_lim = - parm->obj_ll; + break; + default: + xassert(parm != parm); + } + csa->it_lim = parm->it_lim; + csa->tm_lim = parm->tm_lim; + csa->out_frq = parm->out_frq; + csa->out_dly = parm->out_dly; + /* initialize working parameters */ + csa->tm_beg = xtime(); + csa->it_beg = csa->it_cnt = P->it_cnt; + csa->it_dpy = -1; + csa->inv_cnt = 0; + /* try to solve working LP */ + ret = dual_simplex(csa); + /* return basis factorization back to problem object */ + P->valid = csa->lp->valid; + P->bfd = csa->lp->bfd; + /* set solution status */ + P->pbs_stat = csa->p_stat; + P->dbs_stat = csa->d_stat; + /* if the solver failed, do not store basis header and basic + * solution components to problem object */ + if (ret == GLP_EFAIL) + goto skip; + /* convert working LP basis to original LP basis and store it to + * problem object */ + daeh = talloc(1+csa->lp->n, int); + spx_store_basis(csa->lp, P, map, daeh); + /* compute simplex multipliers for final basic solution found by + * the solver */ + spx_eval_pi(csa->lp, csa->work); + /* convert working LP solution to original LP solution and store + * it to problem object */ + spx_store_sol(csa->lp, P, SHIFT, map, daeh, csa->beta, csa->work, + csa->d); + tfree(daeh); + /* save simplex iteration count */ + P->it_cnt = csa->it_cnt; + /* report auxiliary/structural variable causing unboundedness */ + P->some = 0; + if (csa->p_stat == GLP_NOFEAS && csa->d_stat == GLP_FEAS) + { int k, kk; + /* xB[p] = x[k] causes dual unboundedness */ + xassert(1 <= csa->p && csa->p <= csa->lp->m); + k = csa->lp->head[csa->p]; + xassert(1 <= k && k <= csa->lp->n); + /* convert to number of original variable */ + for (kk = 1; kk <= P->m + P->n; kk++) + { if (abs(map[kk]) == k) + { P->some = kk; + break; + } + } + xassert(P->some != 0); + } +skip: /* deallocate working objects and arrays */ + spx_free_lp(csa->lp); + tfree(map); + tfree(csa->b); + tfree(csa->l); + tfree(csa->u); + if (csa->at != NULL) + spx_free_at(csa->lp, csa->at); + if (csa->nt != NULL) + spx_free_nt(csa->lp, csa->nt); + tfree(csa->beta); + tfree(csa->d); + if (csa->se != NULL) + spy_free_se(csa->lp, csa->se); + tfree(csa->list); + tfree(csa->trow); + tfree(csa->tcol); + tfree(csa->work); + tfree(csa->work1); + /* return to calling program */ + return ret >= 0 ? ret : GLP_EFAIL; +} + +/* eof */ diff --git a/resources/3rdparty/glpk-4.53/src/zlib/README b/resources/3rdparty/glpk-4.57/src/zlib/README similarity index 100% rename from resources/3rdparty/glpk-4.53/src/zlib/README rename to resources/3rdparty/glpk-4.57/src/zlib/README diff --git a/resources/3rdparty/glpk-4.53/src/zlib/adler32.c b/resources/3rdparty/glpk-4.57/src/zlib/adler32.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/zlib/adler32.c rename to resources/3rdparty/glpk-4.57/src/zlib/adler32.c diff --git a/resources/3rdparty/glpk-4.53/src/zlib/compress.c b/resources/3rdparty/glpk-4.57/src/zlib/compress.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/zlib/compress.c rename to resources/3rdparty/glpk-4.57/src/zlib/compress.c diff --git a/resources/3rdparty/glpk-4.53/src/zlib/crc32.c b/resources/3rdparty/glpk-4.57/src/zlib/crc32.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/zlib/crc32.c rename to resources/3rdparty/glpk-4.57/src/zlib/crc32.c diff --git a/resources/3rdparty/glpk-4.53/src/zlib/crc32.h b/resources/3rdparty/glpk-4.57/src/zlib/crc32.h similarity index 100% rename from resources/3rdparty/glpk-4.53/src/zlib/crc32.h rename to resources/3rdparty/glpk-4.57/src/zlib/crc32.h diff --git a/resources/3rdparty/glpk-4.53/src/zlib/deflate.c b/resources/3rdparty/glpk-4.57/src/zlib/deflate.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/zlib/deflate.c rename to resources/3rdparty/glpk-4.57/src/zlib/deflate.c diff --git a/resources/3rdparty/glpk-4.53/src/zlib/deflate.h b/resources/3rdparty/glpk-4.57/src/zlib/deflate.h similarity index 100% rename from resources/3rdparty/glpk-4.53/src/zlib/deflate.h rename to resources/3rdparty/glpk-4.57/src/zlib/deflate.h diff --git a/resources/3rdparty/glpk-4.53/src/zlib/gzclose.c b/resources/3rdparty/glpk-4.57/src/zlib/gzclose.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/zlib/gzclose.c rename to resources/3rdparty/glpk-4.57/src/zlib/gzclose.c diff --git a/resources/3rdparty/glpk-4.53/src/zlib/gzguts.h b/resources/3rdparty/glpk-4.57/src/zlib/gzguts.h similarity index 100% rename from resources/3rdparty/glpk-4.53/src/zlib/gzguts.h rename to resources/3rdparty/glpk-4.57/src/zlib/gzguts.h diff --git a/resources/3rdparty/glpk-4.53/src/zlib/gzlib.c b/resources/3rdparty/glpk-4.57/src/zlib/gzlib.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/zlib/gzlib.c rename to resources/3rdparty/glpk-4.57/src/zlib/gzlib.c diff --git a/resources/3rdparty/glpk-4.53/src/zlib/gzread.c b/resources/3rdparty/glpk-4.57/src/zlib/gzread.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/zlib/gzread.c rename to resources/3rdparty/glpk-4.57/src/zlib/gzread.c diff --git a/resources/3rdparty/glpk-4.53/src/zlib/gzwrite.c b/resources/3rdparty/glpk-4.57/src/zlib/gzwrite.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/zlib/gzwrite.c rename to resources/3rdparty/glpk-4.57/src/zlib/gzwrite.c diff --git a/resources/3rdparty/glpk-4.53/src/zlib/inffast.c b/resources/3rdparty/glpk-4.57/src/zlib/inffast.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/zlib/inffast.c rename to resources/3rdparty/glpk-4.57/src/zlib/inffast.c diff --git a/resources/3rdparty/glpk-4.53/src/zlib/inffast.h b/resources/3rdparty/glpk-4.57/src/zlib/inffast.h similarity index 100% rename from resources/3rdparty/glpk-4.53/src/zlib/inffast.h rename to resources/3rdparty/glpk-4.57/src/zlib/inffast.h diff --git a/resources/3rdparty/glpk-4.53/src/zlib/inffixed.h b/resources/3rdparty/glpk-4.57/src/zlib/inffixed.h similarity index 100% rename from resources/3rdparty/glpk-4.53/src/zlib/inffixed.h rename to resources/3rdparty/glpk-4.57/src/zlib/inffixed.h diff --git a/resources/3rdparty/glpk-4.53/src/zlib/inflate.c b/resources/3rdparty/glpk-4.57/src/zlib/inflate.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/zlib/inflate.c rename to resources/3rdparty/glpk-4.57/src/zlib/inflate.c diff --git a/resources/3rdparty/glpk-4.53/src/zlib/inflate.h b/resources/3rdparty/glpk-4.57/src/zlib/inflate.h similarity index 100% rename from resources/3rdparty/glpk-4.53/src/zlib/inflate.h rename to resources/3rdparty/glpk-4.57/src/zlib/inflate.h diff --git a/resources/3rdparty/glpk-4.53/src/zlib/inftrees.c b/resources/3rdparty/glpk-4.57/src/zlib/inftrees.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/zlib/inftrees.c rename to resources/3rdparty/glpk-4.57/src/zlib/inftrees.c diff --git a/resources/3rdparty/glpk-4.53/src/zlib/inftrees.h b/resources/3rdparty/glpk-4.57/src/zlib/inftrees.h similarity index 100% rename from resources/3rdparty/glpk-4.53/src/zlib/inftrees.h rename to resources/3rdparty/glpk-4.57/src/zlib/inftrees.h diff --git a/resources/3rdparty/glpk-4.53/src/zlib/trees.c b/resources/3rdparty/glpk-4.57/src/zlib/trees.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/zlib/trees.c rename to resources/3rdparty/glpk-4.57/src/zlib/trees.c diff --git a/resources/3rdparty/glpk-4.53/src/zlib/trees.h b/resources/3rdparty/glpk-4.57/src/zlib/trees.h similarity index 100% rename from resources/3rdparty/glpk-4.53/src/zlib/trees.h rename to resources/3rdparty/glpk-4.57/src/zlib/trees.h diff --git a/resources/3rdparty/glpk-4.53/src/zlib/uncompr.c b/resources/3rdparty/glpk-4.57/src/zlib/uncompr.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/zlib/uncompr.c rename to resources/3rdparty/glpk-4.57/src/zlib/uncompr.c diff --git a/resources/3rdparty/glpk-4.53/src/zlib/zconf.h b/resources/3rdparty/glpk-4.57/src/zlib/zconf.h similarity index 100% rename from resources/3rdparty/glpk-4.53/src/zlib/zconf.h rename to resources/3rdparty/glpk-4.57/src/zlib/zconf.h diff --git a/resources/3rdparty/glpk-4.53/src/zlib/zio.c b/resources/3rdparty/glpk-4.57/src/zlib/zio.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/zlib/zio.c rename to resources/3rdparty/glpk-4.57/src/zlib/zio.c diff --git a/resources/3rdparty/glpk-4.53/src/zlib/zio.h b/resources/3rdparty/glpk-4.57/src/zlib/zio.h similarity index 100% rename from resources/3rdparty/glpk-4.53/src/zlib/zio.h rename to resources/3rdparty/glpk-4.57/src/zlib/zio.h diff --git a/resources/3rdparty/glpk-4.53/src/zlib/zlib.h b/resources/3rdparty/glpk-4.57/src/zlib/zlib.h similarity index 100% rename from resources/3rdparty/glpk-4.53/src/zlib/zlib.h rename to resources/3rdparty/glpk-4.57/src/zlib/zlib.h diff --git a/resources/3rdparty/glpk-4.53/src/zlib/zutil.c b/resources/3rdparty/glpk-4.57/src/zlib/zutil.c similarity index 100% rename from resources/3rdparty/glpk-4.53/src/zlib/zutil.c rename to resources/3rdparty/glpk-4.57/src/zlib/zutil.c diff --git a/resources/3rdparty/glpk-4.53/src/zlib/zutil.h b/resources/3rdparty/glpk-4.57/src/zlib/zutil.h similarity index 100% rename from resources/3rdparty/glpk-4.53/src/zlib/zutil.h rename to resources/3rdparty/glpk-4.57/src/zlib/zutil.h diff --git a/resources/3rdparty/glpk-4.53/w32/Build_GLPK_with_VC10.bat b/resources/3rdparty/glpk-4.57/w32/Build_GLPK_with_VC10.bat old mode 100644 new mode 100755 similarity index 100% rename from resources/3rdparty/glpk-4.53/w32/Build_GLPK_with_VC10.bat rename to resources/3rdparty/glpk-4.57/w32/Build_GLPK_with_VC10.bat diff --git a/resources/3rdparty/glpk-4.53/w32/Build_GLPK_with_VC10_DLL.bat b/resources/3rdparty/glpk-4.57/w32/Build_GLPK_with_VC10_DLL.bat old mode 100644 new mode 100755 similarity index 100% rename from resources/3rdparty/glpk-4.53/w32/Build_GLPK_with_VC10_DLL.bat rename to resources/3rdparty/glpk-4.57/w32/Build_GLPK_with_VC10_DLL.bat diff --git a/resources/3rdparty/glpk-4.57/w32/Build_GLPK_with_VC14.bat b/resources/3rdparty/glpk-4.57/w32/Build_GLPK_with_VC14.bat new file mode 100755 index 000000000..02bb9add3 --- /dev/null +++ b/resources/3rdparty/glpk-4.57/w32/Build_GLPK_with_VC14.bat @@ -0,0 +1,11 @@ +rem Build GLPK with Microsoft Visual Studio Community 2015 + +rem NOTE: Make sure that HOME variable specifies correct path +set HOME="C:\Program Files\Microsoft Visual Studio 14.0\VC" + +call %HOME%\vcvarsall.bat x86 +copy config_VC config.h +%HOME%\bin\nmake.exe /f Makefile_VC +%HOME%\bin\nmake.exe /f Makefile_VC check + +pause diff --git a/resources/3rdparty/glpk-4.57/w32/Build_GLPK_with_VC14_DLL.bat b/resources/3rdparty/glpk-4.57/w32/Build_GLPK_with_VC14_DLL.bat new file mode 100755 index 000000000..baf4b112b --- /dev/null +++ b/resources/3rdparty/glpk-4.57/w32/Build_GLPK_with_VC14_DLL.bat @@ -0,0 +1,11 @@ +rem Build GLPK DLL with Microsoft Visual Studio Community 2015 + +rem NOTE: Make sure that HOME variable specifies correct path +set HOME="C:\Program Files\Microsoft Visual Studio 14.0\VC" + +call %HOME%\vcvarsall.bat x86 +copy config_VC config.h +%HOME%\bin\nmake.exe /f Makefile_VC_DLL +%HOME%\bin\nmake.exe /f Makefile_VC_DLL check + +pause diff --git a/resources/3rdparty/glpk-4.53/w32/Build_GLPK_with_VC9.bat b/resources/3rdparty/glpk-4.57/w32/Build_GLPK_with_VC9.bat old mode 100644 new mode 100755 similarity index 100% rename from resources/3rdparty/glpk-4.53/w32/Build_GLPK_with_VC9.bat rename to resources/3rdparty/glpk-4.57/w32/Build_GLPK_with_VC9.bat diff --git a/resources/3rdparty/glpk-4.53/w32/Build_GLPK_with_VC9_DLL.bat b/resources/3rdparty/glpk-4.57/w32/Build_GLPK_with_VC9_DLL.bat old mode 100644 new mode 100755 similarity index 100% rename from resources/3rdparty/glpk-4.53/w32/Build_GLPK_with_VC9_DLL.bat rename to resources/3rdparty/glpk-4.57/w32/Build_GLPK_with_VC9_DLL.bat diff --git a/resources/3rdparty/glpk-4.53/w32/Makefile_VC b/resources/3rdparty/glpk-4.57/w32/Makefile_VC similarity index 90% rename from resources/3rdparty/glpk-4.53/w32/Makefile_VC rename to resources/3rdparty/glpk-4.57/w32/Makefile_VC index c0c257ea2..e4853f789 100644 --- a/resources/3rdparty/glpk-4.53/w32/Makefile_VC +++ b/resources/3rdparty/glpk-4.57/w32/Makefile_VC @@ -11,12 +11,14 @@ CFLAGS = \ /I..\src\minisat \ /I..\src\misc \ /I..\src\proxy \ +/I..\src\simplex \ /I..\src\zlib \ /DHAVE_CONFIG_H=1 \ /D_CRT_SECURE_NO_WARNINGS=1 \ /nologo \ /W3 \ -/O2 +/O2 \ +/Zi OBJSET = \ ..\src\avl.obj \ @@ -62,7 +64,6 @@ OBJSET = \ ..\src\glpios11.obj \ ..\src\glpios12.obj \ ..\src\glpipm.obj \ -..\src\glplpf.obj \ ..\src\glpmat.obj \ ..\src\glpmpl01.obj \ ..\src\glpmpl02.obj \ @@ -84,12 +85,9 @@ OBJSET = \ ..\src\glpscl.obj \ ..\src\glpsdf.obj \ ..\src\glpspm.obj \ -..\src\glpspx01.obj \ -..\src\glpspx02.obj \ ..\src\glpsql.obj \ ..\src\glpssx01.obj \ ..\src\glpssx02.obj \ -..\src\glptsp.obj \ ..\src\lux.obj \ ..\src\amd\amd_1.obj \ ..\src\amd\amd_2.obj \ @@ -103,11 +101,15 @@ OBJSET = \ ..\src\amd\amd_postorder.obj \ ..\src\amd\amd_preprocess.obj \ ..\src\amd\amd_valid.obj \ +..\src\bflib\btf.obj \ +..\src\bflib\btfint.obj \ ..\src\bflib\fhv.obj \ ..\src\bflib\fhvint.obj \ ..\src\bflib\ifu.obj \ ..\src\bflib\luf.obj \ ..\src\bflib\lufint.obj \ +..\src\bflib\scf.obj \ +..\src\bflib\scfint.obj \ ..\src\bflib\sgf.obj \ ..\src\bflib\sva.obj \ ..\src\cglib\cfg.obj \ @@ -146,6 +148,16 @@ OBJSET = \ ..\src\misc\wclique1.obj \ ..\src\proxy\proxy.obj \ ..\src\proxy\proxy1.obj \ +..\src\simplex\spxat.obj \ +..\src\simplex\spxchuzc.obj \ +..\src\simplex\spxchuzr.obj \ +..\src\simplex\spxlp.obj \ +..\src\simplex\spxnt.obj \ +..\src\simplex\spxprim.obj \ +..\src\simplex\spxprob.obj \ +..\src\simplex\spychuzc.obj \ +..\src\simplex\spychuzr.obj \ +..\src\simplex\spydual.obj \ ..\src\zlib\adler32.obj \ ..\src\zlib\compress.obj \ ..\src\zlib\crc32.obj \ @@ -178,6 +190,7 @@ glpk.lib: $(OBJSET) ..\src\minisat\*.obj \ ..\src\misc\*.obj \ ..\src\proxy\*.obj \ + ..\src\simplex\*.obj \ ..\src\zlib\*.obj glpsol.exe: ..\examples\glpsol.obj glpk.lib diff --git a/resources/3rdparty/glpk-4.53/w32/Makefile_VC_DLL b/resources/3rdparty/glpk-4.57/w32/Makefile_VC_DLL similarity index 85% rename from resources/3rdparty/glpk-4.53/w32/Makefile_VC_DLL rename to resources/3rdparty/glpk-4.57/w32/Makefile_VC_DLL index 9eb7a6586..53467e0b5 100644 --- a/resources/3rdparty/glpk-4.53/w32/Makefile_VC_DLL +++ b/resources/3rdparty/glpk-4.57/w32/Makefile_VC_DLL @@ -11,12 +11,14 @@ CFLAGS = \ /I..\src\minisat \ /I..\src\misc \ /I..\src\proxy \ +/I..\src\simplex \ /I..\src\zlib \ /DHAVE_CONFIG_H=1 \ /D_CRT_SECURE_NO_WARNINGS=1 \ /nologo \ /W3 \ -/O2 +/O2 \ +/Zi OBJSET = \ ..\src\avl.obj \ @@ -62,7 +64,6 @@ OBJSET = \ ..\src\glpios11.obj \ ..\src\glpios12.obj \ ..\src\glpipm.obj \ -..\src\glplpf.obj \ ..\src\glpmat.obj \ ..\src\glpmpl01.obj \ ..\src\glpmpl02.obj \ @@ -84,12 +85,9 @@ OBJSET = \ ..\src\glpscl.obj \ ..\src\glpsdf.obj \ ..\src\glpspm.obj \ -..\src\glpspx01.obj \ -..\src\glpspx02.obj \ ..\src\glpsql.obj \ ..\src\glpssx01.obj \ ..\src\glpssx02.obj \ -..\src\glptsp.obj \ ..\src\lux.obj \ ..\src\amd\amd_1.obj \ ..\src\amd\amd_2.obj \ @@ -103,11 +101,15 @@ OBJSET = \ ..\src\amd\amd_postorder.obj \ ..\src\amd\amd_preprocess.obj \ ..\src\amd\amd_valid.obj \ +..\src\bflib\btf.obj \ +..\src\bflib\btfint.obj \ ..\src\bflib\fhv.obj \ ..\src\bflib\fhvint.obj \ ..\src\bflib\ifu.obj \ ..\src\bflib\luf.obj \ ..\src\bflib\lufint.obj \ +..\src\bflib\scf.obj \ +..\src\bflib\scfint.obj \ ..\src\bflib\sgf.obj \ ..\src\bflib\sva.obj \ ..\src\cglib\cfg.obj \ @@ -146,6 +148,16 @@ OBJSET = \ ..\src\misc\wclique1.obj \ ..\src\proxy\proxy.obj \ ..\src\proxy\proxy1.obj \ +..\src\simplex\spxat.obj \ +..\src\simplex\spxchuzc.obj \ +..\src\simplex\spxchuzr.obj \ +..\src\simplex\spxlp.obj \ +..\src\simplex\spxnt.obj \ +..\src\simplex\spxprim.obj \ +..\src\simplex\spxprob.obj \ +..\src\simplex\spychuzc.obj \ +..\src\simplex\spychuzr.obj \ +..\src\simplex\spydual.obj \ ..\src\zlib\adler32.obj \ ..\src\zlib\compress.obj \ ..\src\zlib\crc32.obj \ @@ -165,10 +177,10 @@ OBJSET = \ .c.obj: cl.exe $(CFLAGS) /Fo$*.obj /c $*.c -all: glpk_4_53.dll glpsol.exe +all: glpk_4_57.dll glpsol.exe -glpk_4_53.dll: $(OBJSET) - cl.exe $(CFLAGS) /LD /Feglpk_4_53.dll \ +glpk_4_57.dll: $(OBJSET) + cl.exe $(CFLAGS) /LD /Feglpk_4_57.dll \ ..\src\*.obj \ ..\src\amd\*.obj \ ..\src\bflib\*.obj \ @@ -178,12 +190,13 @@ glpk_4_53.dll: $(OBJSET) ..\src\minisat\*.obj \ ..\src\misc\*.obj \ ..\src\proxy\*.obj \ + ..\src\simplex\*.obj \ ..\src\zlib\*.obj \ - glpk_4_53.def + glpk_4_57.def -glpsol.exe: ..\examples\glpsol.obj glpk_4_53.dll +glpsol.exe: ..\examples\glpsol.obj glpk_4_57.dll cl.exe $(CFLAGS) /Feglpsol.exe \ - ..\examples\glpsol.obj glpk_4_53.lib + ..\examples\glpsol.obj glpk_4_57.lib check: glpsol.exe .\glpsol.exe --version diff --git a/resources/3rdparty/glpk-4.53/w32/config_VC b/resources/3rdparty/glpk-4.57/w32/config_VC similarity index 100% rename from resources/3rdparty/glpk-4.53/w32/config_VC rename to resources/3rdparty/glpk-4.57/w32/config_VC diff --git a/resources/3rdparty/glpk-4.53/w32/glpk_4_53.def b/resources/3rdparty/glpk-4.57/w32/glpk_4_57.def similarity index 99% rename from resources/3rdparty/glpk-4.53/w32/glpk_4_53.def rename to resources/3rdparty/glpk-4.57/w32/glpk_4_57.def index dc5ed7595..61076961c 100644 --- a/resources/3rdparty/glpk-4.53/w32/glpk_4_53.def +++ b/resources/3rdparty/glpk-4.57/w32/glpk_4_57.def @@ -1,5 +1,5 @@ -LIBRARY glpk_4_53 -VERSION 4.53 +LIBRARY glpk_4_57 +VERSION 4.57 DESCRIPTION "GNU Linear Programming Kit" EXPORTS glp_create_prob diff --git a/resources/3rdparty/glpk-4.53/w32/readme.txt b/resources/3rdparty/glpk-4.57/w32/readme.txt similarity index 100% rename from resources/3rdparty/glpk-4.53/w32/readme.txt rename to resources/3rdparty/glpk-4.57/w32/readme.txt diff --git a/resources/3rdparty/glpk-4.53/w64/Build_GLPK_with_VC10.bat b/resources/3rdparty/glpk-4.57/w64/Build_GLPK_with_VC10.bat old mode 100644 new mode 100755 similarity index 100% rename from resources/3rdparty/glpk-4.53/w64/Build_GLPK_with_VC10.bat rename to resources/3rdparty/glpk-4.57/w64/Build_GLPK_with_VC10.bat diff --git a/resources/3rdparty/glpk-4.53/w64/Build_GLPK_with_VC10_DLL.bat b/resources/3rdparty/glpk-4.57/w64/Build_GLPK_with_VC10_DLL.bat old mode 100644 new mode 100755 similarity index 100% rename from resources/3rdparty/glpk-4.53/w64/Build_GLPK_with_VC10_DLL.bat rename to resources/3rdparty/glpk-4.57/w64/Build_GLPK_with_VC10_DLL.bat diff --git a/resources/3rdparty/glpk-4.57/w64/Build_GLPK_with_VC14.bat b/resources/3rdparty/glpk-4.57/w64/Build_GLPK_with_VC14.bat new file mode 100755 index 000000000..33bdaeaa2 --- /dev/null +++ b/resources/3rdparty/glpk-4.57/w64/Build_GLPK_with_VC14.bat @@ -0,0 +1,11 @@ +rem Build GLPK with Microsoft Visual Studio Community 2015 + +rem NOTE: Make sure that HOME variable specifies correct path +set HOME="C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC" + +call %HOME%\vcvarsall.bat x64 +copy config_VC config.h +%HOME%\bin\nmake.exe /f Makefile_VC +%HOME%\bin\nmake.exe /f Makefile_VC check + +pause diff --git a/resources/3rdparty/glpk-4.57/w64/Build_GLPK_with_VC14_DLL.bat b/resources/3rdparty/glpk-4.57/w64/Build_GLPK_with_VC14_DLL.bat new file mode 100755 index 000000000..25a6a87d8 --- /dev/null +++ b/resources/3rdparty/glpk-4.57/w64/Build_GLPK_with_VC14_DLL.bat @@ -0,0 +1,11 @@ +rem Build GLPK DLL with Microsoft Visual Studio Community 2015 + +rem NOTE: Make sure that HOME variable specifies correct path +set HOME="C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC" + +call %HOME%\vcvarsall.bat x64 +copy config_VC config.h +%HOME%\bin\nmake.exe /f Makefile_VC_DLL +%HOME%\bin\nmake.exe /f Makefile_VC_DLL check + +pause diff --git a/resources/3rdparty/glpk-4.53/w64/Build_GLPK_with_VC9.bat b/resources/3rdparty/glpk-4.57/w64/Build_GLPK_with_VC9.bat old mode 100644 new mode 100755 similarity index 100% rename from resources/3rdparty/glpk-4.53/w64/Build_GLPK_with_VC9.bat rename to resources/3rdparty/glpk-4.57/w64/Build_GLPK_with_VC9.bat diff --git a/resources/3rdparty/glpk-4.53/w64/Build_GLPK_with_VC9_DLL.bat b/resources/3rdparty/glpk-4.57/w64/Build_GLPK_with_VC9_DLL.bat old mode 100644 new mode 100755 similarity index 100% rename from resources/3rdparty/glpk-4.53/w64/Build_GLPK_with_VC9_DLL.bat rename to resources/3rdparty/glpk-4.57/w64/Build_GLPK_with_VC9_DLL.bat diff --git a/resources/3rdparty/glpk-4.53/w64/config_VC b/resources/3rdparty/glpk-4.57/w64/config_VC similarity index 100% rename from resources/3rdparty/glpk-4.53/w64/config_VC rename to resources/3rdparty/glpk-4.57/w64/config_VC diff --git a/resources/3rdparty/glpk-4.53/w64/glpk_4_53.def b/resources/3rdparty/glpk-4.57/w64/glpk_4_57.def similarity index 99% rename from resources/3rdparty/glpk-4.53/w64/glpk_4_53.def rename to resources/3rdparty/glpk-4.57/w64/glpk_4_57.def index dc5ed7595..61076961c 100644 --- a/resources/3rdparty/glpk-4.53/w64/glpk_4_53.def +++ b/resources/3rdparty/glpk-4.57/w64/glpk_4_57.def @@ -1,5 +1,5 @@ -LIBRARY glpk_4_53 -VERSION 4.53 +LIBRARY glpk_4_57 +VERSION 4.57 DESCRIPTION "GNU Linear Programming Kit" EXPORTS glp_create_prob diff --git a/resources/3rdparty/glpk-4.53/w64/makefile_VC b/resources/3rdparty/glpk-4.57/w64/makefile_VC similarity index 90% rename from resources/3rdparty/glpk-4.53/w64/makefile_VC rename to resources/3rdparty/glpk-4.57/w64/makefile_VC index c0c257ea2..e4853f789 100644 --- a/resources/3rdparty/glpk-4.53/w64/makefile_VC +++ b/resources/3rdparty/glpk-4.57/w64/makefile_VC @@ -11,12 +11,14 @@ CFLAGS = \ /I..\src\minisat \ /I..\src\misc \ /I..\src\proxy \ +/I..\src\simplex \ /I..\src\zlib \ /DHAVE_CONFIG_H=1 \ /D_CRT_SECURE_NO_WARNINGS=1 \ /nologo \ /W3 \ -/O2 +/O2 \ +/Zi OBJSET = \ ..\src\avl.obj \ @@ -62,7 +64,6 @@ OBJSET = \ ..\src\glpios11.obj \ ..\src\glpios12.obj \ ..\src\glpipm.obj \ -..\src\glplpf.obj \ ..\src\glpmat.obj \ ..\src\glpmpl01.obj \ ..\src\glpmpl02.obj \ @@ -84,12 +85,9 @@ OBJSET = \ ..\src\glpscl.obj \ ..\src\glpsdf.obj \ ..\src\glpspm.obj \ -..\src\glpspx01.obj \ -..\src\glpspx02.obj \ ..\src\glpsql.obj \ ..\src\glpssx01.obj \ ..\src\glpssx02.obj \ -..\src\glptsp.obj \ ..\src\lux.obj \ ..\src\amd\amd_1.obj \ ..\src\amd\amd_2.obj \ @@ -103,11 +101,15 @@ OBJSET = \ ..\src\amd\amd_postorder.obj \ ..\src\amd\amd_preprocess.obj \ ..\src\amd\amd_valid.obj \ +..\src\bflib\btf.obj \ +..\src\bflib\btfint.obj \ ..\src\bflib\fhv.obj \ ..\src\bflib\fhvint.obj \ ..\src\bflib\ifu.obj \ ..\src\bflib\luf.obj \ ..\src\bflib\lufint.obj \ +..\src\bflib\scf.obj \ +..\src\bflib\scfint.obj \ ..\src\bflib\sgf.obj \ ..\src\bflib\sva.obj \ ..\src\cglib\cfg.obj \ @@ -146,6 +148,16 @@ OBJSET = \ ..\src\misc\wclique1.obj \ ..\src\proxy\proxy.obj \ ..\src\proxy\proxy1.obj \ +..\src\simplex\spxat.obj \ +..\src\simplex\spxchuzc.obj \ +..\src\simplex\spxchuzr.obj \ +..\src\simplex\spxlp.obj \ +..\src\simplex\spxnt.obj \ +..\src\simplex\spxprim.obj \ +..\src\simplex\spxprob.obj \ +..\src\simplex\spychuzc.obj \ +..\src\simplex\spychuzr.obj \ +..\src\simplex\spydual.obj \ ..\src\zlib\adler32.obj \ ..\src\zlib\compress.obj \ ..\src\zlib\crc32.obj \ @@ -178,6 +190,7 @@ glpk.lib: $(OBJSET) ..\src\minisat\*.obj \ ..\src\misc\*.obj \ ..\src\proxy\*.obj \ + ..\src\simplex\*.obj \ ..\src\zlib\*.obj glpsol.exe: ..\examples\glpsol.obj glpk.lib diff --git a/resources/3rdparty/glpk-4.53/w64/makefile_VC_DLL b/resources/3rdparty/glpk-4.57/w64/makefile_VC_DLL similarity index 85% rename from resources/3rdparty/glpk-4.53/w64/makefile_VC_DLL rename to resources/3rdparty/glpk-4.57/w64/makefile_VC_DLL index 9eb7a6586..53467e0b5 100644 --- a/resources/3rdparty/glpk-4.53/w64/makefile_VC_DLL +++ b/resources/3rdparty/glpk-4.57/w64/makefile_VC_DLL @@ -11,12 +11,14 @@ CFLAGS = \ /I..\src\minisat \ /I..\src\misc \ /I..\src\proxy \ +/I..\src\simplex \ /I..\src\zlib \ /DHAVE_CONFIG_H=1 \ /D_CRT_SECURE_NO_WARNINGS=1 \ /nologo \ /W3 \ -/O2 +/O2 \ +/Zi OBJSET = \ ..\src\avl.obj \ @@ -62,7 +64,6 @@ OBJSET = \ ..\src\glpios11.obj \ ..\src\glpios12.obj \ ..\src\glpipm.obj \ -..\src\glplpf.obj \ ..\src\glpmat.obj \ ..\src\glpmpl01.obj \ ..\src\glpmpl02.obj \ @@ -84,12 +85,9 @@ OBJSET = \ ..\src\glpscl.obj \ ..\src\glpsdf.obj \ ..\src\glpspm.obj \ -..\src\glpspx01.obj \ -..\src\glpspx02.obj \ ..\src\glpsql.obj \ ..\src\glpssx01.obj \ ..\src\glpssx02.obj \ -..\src\glptsp.obj \ ..\src\lux.obj \ ..\src\amd\amd_1.obj \ ..\src\amd\amd_2.obj \ @@ -103,11 +101,15 @@ OBJSET = \ ..\src\amd\amd_postorder.obj \ ..\src\amd\amd_preprocess.obj \ ..\src\amd\amd_valid.obj \ +..\src\bflib\btf.obj \ +..\src\bflib\btfint.obj \ ..\src\bflib\fhv.obj \ ..\src\bflib\fhvint.obj \ ..\src\bflib\ifu.obj \ ..\src\bflib\luf.obj \ ..\src\bflib\lufint.obj \ +..\src\bflib\scf.obj \ +..\src\bflib\scfint.obj \ ..\src\bflib\sgf.obj \ ..\src\bflib\sva.obj \ ..\src\cglib\cfg.obj \ @@ -146,6 +148,16 @@ OBJSET = \ ..\src\misc\wclique1.obj \ ..\src\proxy\proxy.obj \ ..\src\proxy\proxy1.obj \ +..\src\simplex\spxat.obj \ +..\src\simplex\spxchuzc.obj \ +..\src\simplex\spxchuzr.obj \ +..\src\simplex\spxlp.obj \ +..\src\simplex\spxnt.obj \ +..\src\simplex\spxprim.obj \ +..\src\simplex\spxprob.obj \ +..\src\simplex\spychuzc.obj \ +..\src\simplex\spychuzr.obj \ +..\src\simplex\spydual.obj \ ..\src\zlib\adler32.obj \ ..\src\zlib\compress.obj \ ..\src\zlib\crc32.obj \ @@ -165,10 +177,10 @@ OBJSET = \ .c.obj: cl.exe $(CFLAGS) /Fo$*.obj /c $*.c -all: glpk_4_53.dll glpsol.exe +all: glpk_4_57.dll glpsol.exe -glpk_4_53.dll: $(OBJSET) - cl.exe $(CFLAGS) /LD /Feglpk_4_53.dll \ +glpk_4_57.dll: $(OBJSET) + cl.exe $(CFLAGS) /LD /Feglpk_4_57.dll \ ..\src\*.obj \ ..\src\amd\*.obj \ ..\src\bflib\*.obj \ @@ -178,12 +190,13 @@ glpk_4_53.dll: $(OBJSET) ..\src\minisat\*.obj \ ..\src\misc\*.obj \ ..\src\proxy\*.obj \ + ..\src\simplex\*.obj \ ..\src\zlib\*.obj \ - glpk_4_53.def + glpk_4_57.def -glpsol.exe: ..\examples\glpsol.obj glpk_4_53.dll +glpsol.exe: ..\examples\glpsol.obj glpk_4_57.dll cl.exe $(CFLAGS) /Feglpsol.exe \ - ..\examples\glpsol.obj glpk_4_53.lib + ..\examples\glpsol.obj glpk_4_57.lib check: glpsol.exe .\glpsol.exe --version diff --git a/resources/3rdparty/glpk-4.53/w64/readme.txt b/resources/3rdparty/glpk-4.57/w64/readme.txt similarity index 100% rename from resources/3rdparty/glpk-4.53/w64/readme.txt rename to resources/3rdparty/glpk-4.57/w64/readme.txt diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 874eee2dc..b234ac88b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -111,6 +111,7 @@ endif(ADDITIONAL_LINK_DIRS) add_library(storm SHARED ${STORM_LIB_SOURCES} ${STORM_LIB_HEADERS} ${STORM_GENERATED_SOURCES}) # Adding headers for xcode add_dependencies(storm xercesc) add_dependencies(storm sylvan) +add_dependencies(storm glpk) add_executable(storm-main ${STORM_MAIN_SOURCES} ${STORM_MAIN_HEADERS}) target_link_libraries(storm-main storm) # Adding headers for xcode set_target_properties(storm-main PROPERTIES OUTPUT_NAME "storm") diff --git a/src/builder/ExplicitPrismModelBuilder.cpp b/src/builder/ExplicitPrismModelBuilder.cpp index ed0f43d3b..d345d9f05 100644 --- a/src/builder/ExplicitPrismModelBuilder.cpp +++ b/src/builder/ExplicitPrismModelBuilder.cpp @@ -264,7 +264,7 @@ namespace storm { STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException, "The program contains undefined constants that appear in some places other than update probabilities and reward value expressions, which is not admitted."); #endif } - + // If the set of labels we are supposed to built is restricted, we need to remove the other labels from the program. if (options.labelsToBuild) { if (!options.buildAllLabels) { diff --git a/src/cli/cli.cpp b/src/cli/cli.cpp index 0909b25de..758ac9a2a 100644 --- a/src/cli/cli.cpp +++ b/src/cli/cli.cpp @@ -236,15 +236,15 @@ namespace storm { if (settings.isSymbolicSet()) { #ifdef STORM_HAVE_CARL if (settings.isParametricSet()) { - buildAndCheckSymbolicModel(program.get(), formulas); + buildAndCheckSymbolicModel(program.get(), formulas, true); } else { #endif - buildAndCheckSymbolicModel(program.get(), formulas); + buildAndCheckSymbolicModel(program.get(), formulas, true); #ifdef STORM_HAVE_CARL } #endif } else if (settings.isExplicitSet()) { - buildAndCheckExplicitModel(formulas); + buildAndCheckExplicitModel(formulas, true); } else { STORM_LOG_THROW(false, storm::exceptions::InvalidSettingsException, "No input model."); } diff --git a/src/cli/entrypoints.h b/src/cli/entrypoints.h index cddebdf7f..bbb9d6404 100644 --- a/src/cli/entrypoints.h +++ b/src/cli/entrypoints.h @@ -9,10 +9,10 @@ namespace storm { namespace cli { template - void verifySparseModel(std::shared_ptr> model, std::vector> const& formulas) { + void verifySparseModel(std::shared_ptr> model, std::vector> const& formulas, bool onlyInitialStatesRelevant = false) { for (auto const& formula : formulas) { std::cout << std::endl << "Model checking property: " << *formula << " ..."; - std::unique_ptr result(storm::verifySparseModel(model, formula)); + std::unique_ptr result(storm::verifySparseModel(model, formula, onlyInitialStatesRelevant)); if (result) { std::cout << " done." << std::endl; std::cout << "Result (initial states): "; @@ -26,12 +26,12 @@ namespace storm { #ifdef STORM_HAVE_CARL template<> - inline void verifySparseModel(std::shared_ptr> model, std::vector> const& formulas) { + inline void verifySparseModel(std::shared_ptr> model, std::vector> const& formulas, bool onlyInitialStatesRelevant) { for (auto const& formula : formulas) { STORM_LOG_THROW(model->getType() == storm::models::ModelType::Dtmc, storm::exceptions::InvalidSettingsException, "Currently parametric verification is only available for DTMCs."); std::cout << std::endl << "Model checking property: " << *formula << " ..."; - std::unique_ptr result(storm::verifySparseModel(model, formula)); + std::unique_ptr result(storm::verifySparseModel(model, formula, onlyInitialStatesRelevant)); if (result) { std::cout << " done." << std::endl; std::cout << "Result (initial states): "; @@ -50,15 +50,15 @@ namespace storm { #endif template - void verifySymbolicModelWithAbstractionRefinementEngine(storm::prism::Program const& program, std::vector> const& formulas) { + void verifySymbolicModelWithAbstractionRefinementEngine(storm::prism::Program const& program, std::vector> const& formulas, bool onlyInitialStatesRelevant = false) { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Abstraction Refinement is not yet implemented."); } template - void verifySymbolicModelWithHybridEngine(std::shared_ptr> model, std::vector> const& formulas) { + void verifySymbolicModelWithHybridEngine(std::shared_ptr> model, std::vector> const& formulas, bool onlyInitialStatesRelevant = false) { for (auto const& formula : formulas) { std::cout << std::endl << "Model checking property: " << *formula << " ..."; - std::unique_ptr result(storm::verifySymbolicModelWithHybridEngine(model, formula)); + std::unique_ptr result(storm::verifySymbolicModelWithHybridEngine(model, formula, onlyInitialStatesRelevant)); if (result) { std::cout << " done." << std::endl; @@ -72,10 +72,10 @@ namespace storm { } template - void verifySymbolicModelWithSymbolicEngine(std::shared_ptr> model, std::vector> const& formulas) { + void verifySymbolicModelWithSymbolicEngine(std::shared_ptr> model, std::vector> const& formulas, bool onlyInitialStatesRelevant = false) { for (auto const& formula : formulas) { std::cout << std::endl << "Model checking property: " << *formula << " ..."; - std::unique_ptr result(storm::verifySymbolicModelWithDdEngine(model, formula)); + std::unique_ptr result(storm::verifySymbolicModelWithDdEngine(model, formula, onlyInitialStatesRelevant)); if (result) { std::cout << " done." << std::endl; std::cout << "Result (initial states): "; @@ -114,12 +114,12 @@ namespace storm { } template - void buildAndCheckSymbolicModel(storm::prism::Program const& program, std::vector> const& formulas) { + void buildAndCheckSymbolicModel(storm::prism::Program const& program, std::vector> const& formulas, bool onlyInitialStatesRelevant = false) { storm::settings::modules::GeneralSettings const& settings = storm::settings::generalSettings(); if (settings.getEngine() == storm::settings::modules::GeneralSettings::Engine::AbstractionRefinement) { - verifySymbolicModelWithAbstractionRefinementEngine(program, formulas); + verifySymbolicModelWithAbstractionRefinementEngine(program, formulas, onlyInitialStatesRelevant); } else { storm::storage::ModelFormulasPair modelFormulasPair = buildSymbolicModel(program, formulas); STORM_LOG_THROW(modelFormulasPair.model != nullptr, storm::exceptions::InvalidStateException, @@ -133,7 +133,6 @@ namespace storm { // Verify the model, if a formula was given. if (!formulas.empty()) { - if (modelFormulasPair.model->isSparseModel()) { if (storm::settings::generalSettings().isCounterexampleSet()) { // If we were requested to generate a counterexample, we now do so for each formula. @@ -141,15 +140,15 @@ namespace storm { generateCounterexample(program, modelFormulasPair.model->as>(), formula); } } else { - verifySparseModel(modelFormulasPair.model->as>(), modelFormulasPair.formulas); + verifySparseModel(modelFormulasPair.model->as>(), modelFormulasPair.formulas, onlyInitialStatesRelevant); } } else if (modelFormulasPair.model->isSymbolicModel()) { if (storm::settings::generalSettings().getEngine() == storm::settings::modules::GeneralSettings::Engine::Hybrid) { verifySymbolicModelWithHybridEngine(modelFormulasPair.model->as>(), - modelFormulasPair.formulas); + modelFormulasPair.formulas, onlyInitialStatesRelevant); } else { verifySymbolicModelWithSymbolicEngine(modelFormulasPair.model->as>(), - modelFormulasPair.formulas); + modelFormulasPair.formulas, onlyInitialStatesRelevant); } } else { STORM_LOG_THROW(false, storm::exceptions::InvalidSettingsException, "Invalid input model type."); @@ -159,20 +158,20 @@ namespace storm { } template - void buildAndCheckSymbolicModel(storm::prism::Program const& program, std::vector> const& formulas) { + void buildAndCheckSymbolicModel(storm::prism::Program const& program, std::vector> const& formulas, bool onlyInitialStatesRelevant = false) { if (storm::settings::generalSettings().getDdLibraryType() == storm::dd::DdType::CUDD) { - buildAndCheckSymbolicModel(program, formulas); + buildAndCheckSymbolicModel(program, formulas, onlyInitialStatesRelevant); } else if (storm::settings::generalSettings().getDdLibraryType() == storm::dd::DdType::Sylvan) { - buildAndCheckSymbolicModel(program, formulas); + buildAndCheckSymbolicModel(program, formulas, onlyInitialStatesRelevant); } } template - void buildAndCheckExplicitModel(std::vector> const& formulas) { + void buildAndCheckExplicitModel(std::vector> const& formulas, bool onlyInitialStatesRelevant = false) { storm::settings::modules::GeneralSettings const& settings = storm::settings::generalSettings(); STORM_LOG_THROW(settings.isExplicitSet(), storm::exceptions::InvalidStateException, "Unable to build explicit model without model files."); - std::shared_ptr model = buildExplicitModel(settings.getTransitionFilename(), settings.getLabelingFilename(), settings.isStateRewardsSet() ? settings.getStateRewardsFilename() : boost::optional(), settings.isTransitionRewardsSet() ? settings.getTransitionRewardsFilename() : boost::optional(), settings.isChoiceLabelingSet() ? settings.getChoiceLabelingFilename() : boost::optional()); + std::shared_ptr model = buildExplicitModel(settings.getTransitionFilename(), settings.getLabelingFilename(), settings.isStateRewardsSet() ? boost::optional(settings.getStateRewardsFilename()) : boost::none, settings.isTransitionRewardsSet() ? boost::optional(settings.getTransitionRewardsFilename()) : boost::none, settings.isChoiceLabelingSet() ? boost::optional(settings.getChoiceLabelingFilename()) : boost::none); // Preprocess the model if needed. BRANCH_ON_MODELTYPE(model, model, ValueType, storm::dd::DdType::CUDD, preprocessModel, formulas); @@ -183,7 +182,7 @@ namespace storm { // Verify the model, if a formula was given. if (!formulas.empty()) { STORM_LOG_THROW(model->isSparseModel(), storm::exceptions::InvalidStateException, "Expected sparse model."); - verifySparseModel(model->as>(), formulas); + verifySparseModel(model->as>(), formulas, onlyInitialStatesRelevant); } } } diff --git a/src/counterexamples/MILPMinimalLabelSetGenerator.h b/src/counterexamples/MILPMinimalLabelSetGenerator.h index bc5be2111..17825b23d 100644 --- a/src/counterexamples/MILPMinimalLabelSetGenerator.h +++ b/src/counterexamples/MILPMinimalLabelSetGenerator.h @@ -957,8 +957,6 @@ namespace storm { // (4.2) Construct constraint system. buildConstraintSystem(*solver, labeledMdp, psiStates, stateInformation, choiceInformation, variableInformation, probabilityThreshold, strictBound, includeSchedulerCuts); - solver->writeModelToFile("model.lp"); - // (4.3) Optimize the model. solver->optimize(); diff --git a/src/logic/Formula.cpp b/src/logic/Formula.cpp index babf9edfc..5ba068af9 100644 --- a/src/logic/Formula.cpp +++ b/src/logic/Formula.cpp @@ -115,6 +115,10 @@ namespace storm { return false; } + bool Formula::isOperatorFormula() const { + return false; + } + bool Formula::isPctlPathFormula() const { return false; } @@ -379,6 +383,14 @@ namespace storm { return dynamic_cast(*this); } + OperatorFormula& Formula::asOperatorFormula() { + return dynamic_cast(*this); + } + + OperatorFormula const& Formula::asOperatorFormula() const { + return dynamic_cast(*this); + } + std::vector> Formula::getAtomicExpressionFormulas() const { std::vector> result; this->gatherAtomicExpressionFormulas(result); diff --git a/src/logic/Formula.h b/src/logic/Formula.h index 1a6933703..31ee7744a 100644 --- a/src/logic/Formula.h +++ b/src/logic/Formula.h @@ -38,6 +38,7 @@ namespace storm { class LongRunAverageRewardFormula; class ProbabilityOperatorFormula; class RewardOperatorFormula; + class OperatorFormula; // Also foward-declare base model checker class. class ModelChecker; @@ -80,6 +81,7 @@ namespace storm { virtual bool isLongRunAverageRewardFormula() const; virtual bool isProbabilityOperatorFormula() const; virtual bool isRewardOperatorFormula() const; + virtual bool isOperatorFormula() const; virtual bool isPctlPathFormula() const; virtual bool isPctlStateFormula() const; @@ -175,6 +177,9 @@ namespace storm { RewardOperatorFormula& asRewardOperatorFormula(); RewardOperatorFormula const& asRewardOperatorFormula() const; + OperatorFormula& asOperatorFormula(); + OperatorFormula const& asOperatorFormula() const; + std::vector> getAtomicExpressionFormulas() const; std::vector> getAtomicLabelFormulas() const; std::set getReferencedRewardModels() const; diff --git a/src/logic/Formulas.h b/src/logic/Formulas.h index faf4ca164..3671b2859 100644 --- a/src/logic/Formulas.h +++ b/src/logic/Formulas.h @@ -13,6 +13,7 @@ #include "src/logic/NextFormula.h" #include "src/logic/PathFormula.h" #include "src/logic/RewardPathFormula.h" +#include "src/logic/OperatorFormula.h" #include "src/logic/ProbabilityOperatorFormula.h" #include "src/logic/ReachabilityRewardFormula.h" #include "src/logic/LongRunAverageRewardFormula.h" diff --git a/src/logic/OperatorFormula.cpp b/src/logic/OperatorFormula.cpp index 39fad071d..768b6b3d0 100644 --- a/src/logic/OperatorFormula.cpp +++ b/src/logic/OperatorFormula.cpp @@ -34,6 +34,10 @@ namespace storm { return optimalityType.get(); } + bool OperatorFormula::isOperatorFormula() const { + return true; + } + std::ostream& OperatorFormula::writeToStream(std::ostream& out) const { if (hasOptimalityType()) { out << (getOptimalityType() == OptimizationDirection::Minimize ? "min" : "max"); diff --git a/src/logic/OperatorFormula.h b/src/logic/OperatorFormula.h index a059ddb8b..5c120bf2f 100644 --- a/src/logic/OperatorFormula.h +++ b/src/logic/OperatorFormula.h @@ -24,6 +24,7 @@ namespace storm { void setBound(double); bool hasOptimalityType() const; OptimizationDirection const& getOptimalityType() const; + virtual bool isOperatorFormula() const override; virtual std::ostream& writeToStream(std::ostream& out) const override; diff --git a/src/modelchecker/AbstractModelChecker.cpp b/src/modelchecker/AbstractModelChecker.cpp index 2b840d83c..764b02427 100644 --- a/src/modelchecker/AbstractModelChecker.cpp +++ b/src/modelchecker/AbstractModelChecker.cpp @@ -11,137 +11,144 @@ namespace storm { namespace modelchecker { - std::unique_ptr AbstractModelChecker::check(storm::logic::Formula const& formula) { + std::unique_ptr AbstractModelChecker::check(CheckTask const& checkTask) { + storm::logic::Formula const& formula = checkTask.getFormula(); STORM_LOG_THROW(this->canHandle(formula), storm::exceptions::InvalidArgumentException, "The model checker is not able to check the formula '" << formula << "'."); if (formula.isStateFormula()) { - return this->checkStateFormula(formula.asStateFormula()); + return this->checkStateFormula(checkTask.replaceFormula(formula.asStateFormula())); } else if (formula.isPathFormula()) { - return this->computeProbabilities(formula.asPathFormula()); + return this->computeProbabilities(checkTask.replaceFormula(formula.asPathFormula())); } else if (formula.isRewardPathFormula()) { - return this->computeRewards(formula.asRewardPathFormula()); + return this->computeRewards(checkTask.replaceFormula(formula.asRewardPathFormula())); } STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException, "The given formula '" << formula << "' is invalid."); } - std::unique_ptr AbstractModelChecker::computeProbabilities(storm::logic::PathFormula const& pathFormula, bool qualitative, boost::optional const& optimalityType) { + std::unique_ptr AbstractModelChecker::computeProbabilities(CheckTask const& checkTask) { + storm::logic::PathFormula const& pathFormula = checkTask.getFormula(); if (pathFormula.isBoundedUntilFormula()) { - return this->computeBoundedUntilProbabilities(pathFormula.asBoundedUntilFormula(), qualitative, optimalityType); + return this->computeBoundedUntilProbabilities(checkTask.replaceFormula(pathFormula.asBoundedUntilFormula())); } else if (pathFormula.isConditionalPathFormula()) { - return this->computeConditionalProbabilities(pathFormula.asConditionalPathFormula(), qualitative, optimalityType); + return this->computeConditionalProbabilities(checkTask.replaceFormula(pathFormula.asConditionalPathFormula())); } else if (pathFormula.isEventuallyFormula()) { - return this->computeEventuallyProbabilities(pathFormula.asEventuallyFormula(), qualitative, optimalityType); + return this->computeEventuallyProbabilities(checkTask.replaceFormula(pathFormula.asEventuallyFormula())); } else if (pathFormula.isGloballyFormula()) { - return this->computeGloballyProbabilities(pathFormula.asGloballyFormula(), qualitative, optimalityType); + return this->computeGloballyProbabilities(checkTask.replaceFormula(pathFormula.asGloballyFormula())); } else if (pathFormula.isUntilFormula()) { - return this->computeUntilProbabilities(pathFormula.asUntilFormula(), qualitative, optimalityType); + return this->computeUntilProbabilities(checkTask.replaceFormula(pathFormula.asUntilFormula())); } else if (pathFormula.isNextFormula()) { - return this->computeNextProbabilities(pathFormula.asNextFormula(), qualitative, optimalityType); + return this->computeNextProbabilities(checkTask.replaceFormula(pathFormula.asNextFormula())); } STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException, "The given formula '" << pathFormula << "' is invalid."); } - std::unique_ptr AbstractModelChecker::computeBoundedUntilProbabilities(storm::logic::BoundedUntilFormula const& pathFormula, bool qualitative, boost::optional const& optimalityType) { - STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "This model checker does not support the formula: " << pathFormula << "."); + std::unique_ptr AbstractModelChecker::computeBoundedUntilProbabilities(CheckTask const& checkTask) { + STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "This model checker does not support the formula: " << checkTask.getFormula() << "."); } - std::unique_ptr AbstractModelChecker::computeConditionalProbabilities(storm::logic::ConditionalPathFormula const& pathFormula, bool qualitative, boost::optional const& optimalityType) { - STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "This model checker does not support the formula: " << pathFormula << "."); + std::unique_ptr AbstractModelChecker::computeConditionalProbabilities(CheckTask const& checkTask) { + STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "This model checker does not support the formula: " << checkTask.getFormula() << "."); } - std::unique_ptr AbstractModelChecker::computeEventuallyProbabilities(storm::logic::EventuallyFormula const& pathFormula, bool qualitative, boost::optional const& optimalityType) { + std::unique_ptr AbstractModelChecker::computeEventuallyProbabilities(CheckTask const& checkTask) { + storm::logic::EventuallyFormula const& pathFormula = checkTask.getFormula(); storm::logic::UntilFormula newFormula(storm::logic::Formula::getTrueFormula(), pathFormula.getSubformula().asSharedPointer()); - return this->computeUntilProbabilities(newFormula, qualitative, optimalityType); + return this->computeUntilProbabilities(checkTask.replaceFormula(newFormula)); } - std::unique_ptr AbstractModelChecker::computeGloballyProbabilities(storm::logic::GloballyFormula const& pathFormula, bool qualitative, boost::optional const& optimalityType) { - STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "This model checker does not support the formula: " << pathFormula << "."); + std::unique_ptr AbstractModelChecker::computeGloballyProbabilities(CheckTask const& checkTask) { + STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "This model checker does not support the formula: " << checkTask.getFormula() << "."); } - std::unique_ptr AbstractModelChecker::computeNextProbabilities(storm::logic::NextFormula const& pathFormula, bool qualitative, boost::optional const& optimalityType) { - STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "This model checker does not support the formula: " << pathFormula << "."); + std::unique_ptr AbstractModelChecker::computeNextProbabilities(CheckTask const& checkTask) { + STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "This model checker does not support the formula: " << checkTask.getFormula() << "."); } - std::unique_ptr AbstractModelChecker::computeUntilProbabilities(storm::logic::UntilFormula const& pathFormula, bool qualitative, boost::optional const& optimalityType) { - STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "This model checker does not support the formula: " << pathFormula << "."); + std::unique_ptr AbstractModelChecker::computeUntilProbabilities(CheckTask const& checkTask) { + STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "This model checker does not support the formula: " << checkTask.getFormula() << "."); } - std::unique_ptr AbstractModelChecker::computeRewards(storm::logic::RewardPathFormula const& rewardPathFormula, boost::optional const& rewardModelName, bool qualitative, boost::optional const& optimalityType) { + std::unique_ptr AbstractModelChecker::computeRewards(CheckTask const& checkTask) { + storm::logic::RewardPathFormula const& rewardPathFormula = checkTask.getFormula(); if (rewardPathFormula.isCumulativeRewardFormula()) { - return this->computeCumulativeRewards(rewardPathFormula.asCumulativeRewardFormula(), rewardModelName, qualitative, optimalityType); + return this->computeCumulativeRewards(checkTask.replaceFormula(rewardPathFormula.asCumulativeRewardFormula())); } else if (rewardPathFormula.isInstantaneousRewardFormula()) { - return this->computeInstantaneousRewards(rewardPathFormula.asInstantaneousRewardFormula(), rewardModelName, qualitative, optimalityType); + return this->computeInstantaneousRewards(checkTask.replaceFormula(rewardPathFormula.asInstantaneousRewardFormula())); } else if (rewardPathFormula.isReachabilityRewardFormula()) { - return this->computeReachabilityRewards(rewardPathFormula.asReachabilityRewardFormula(), rewardModelName, qualitative, optimalityType); + return this->computeReachabilityRewards(checkTask.replaceFormula(rewardPathFormula.asReachabilityRewardFormula())); } else if (rewardPathFormula.isLongRunAverageRewardFormula()) { - return this->computeLongRunAverageRewards(rewardPathFormula.asLongRunAverageRewardFormula(), rewardModelName, qualitative, optimalityType); + return this->computeLongRunAverageRewards(checkTask.replaceFormula(rewardPathFormula.asLongRunAverageRewardFormula())); } STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException, "The given formula '" << rewardPathFormula << "' is invalid."); } - std::unique_ptr AbstractModelChecker::computeCumulativeRewards(storm::logic::CumulativeRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName, bool qualitative, boost::optional const& optimalityType) { - STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "This model checker does not support the formula: " << rewardPathFormula << "."); + std::unique_ptr AbstractModelChecker::computeCumulativeRewards(CheckTask const& checkTask) { + STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "This model checker does not support the formula: " << checkTask.getFormula() << "."); } - std::unique_ptr AbstractModelChecker::computeInstantaneousRewards(storm::logic::InstantaneousRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName, bool qualitative, boost::optional const& optimalityType) { - STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "This model checker does not support the formula: " << rewardPathFormula << "."); + std::unique_ptr AbstractModelChecker::computeInstantaneousRewards(CheckTask const& checkTask) { + STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "This model checker does not support the formula: " << checkTask.getFormula() << "."); } - std::unique_ptr AbstractModelChecker::computeReachabilityRewards(storm::logic::ReachabilityRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName, bool qualitative, boost::optional const& optimalityType) { - STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "This model checker does not support the formula: " << rewardPathFormula << "."); + std::unique_ptr AbstractModelChecker::computeReachabilityRewards(CheckTask const& checkTask) { + STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "This model checker does not support the formula: " << checkTask.getFormula() << "."); } - std::unique_ptr AbstractModelChecker::computeLongRunAverageRewards(storm::logic::LongRunAverageRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName, bool qualitative, boost::optional const& optimalityType) { - STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "This model checker does not support the formula: " << rewardPathFormula << "."); + std::unique_ptr AbstractModelChecker::computeLongRunAverageRewards(CheckTask const& checkTask) { + STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "This model checker does not support the formula: " << checkTask.getFormula() << "."); } - std::unique_ptr AbstractModelChecker::computeLongRunAverageProbabilities(storm::logic::StateFormula const& eventuallyFormula, bool qualitative, boost::optional const& optimalityType) { - STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "This model checker does not support the computation of long-run averages."); + std::unique_ptr AbstractModelChecker::computeLongRunAverageProbabilities(CheckTask const& checkTask) { + STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "This model checker does not support the formula: " << checkTask.getFormula() << "."); } - std::unique_ptr AbstractModelChecker::computeExpectedTimes(storm::logic::EventuallyFormula const& eventuallyFormula, bool qualitative, boost::optional const& optimalityType) { - STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "This model checker does not support the computation of expected times."); + std::unique_ptr AbstractModelChecker::computeExpectedTimes(CheckTask const& checkTask) { + STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "This model checker does not support the formula: " << checkTask.getFormula() << "."); } - std::unique_ptr AbstractModelChecker::checkStateFormula(storm::logic::StateFormula const& stateFormula) { + std::unique_ptr AbstractModelChecker::checkStateFormula(CheckTask const& checkTask) { + storm::logic::StateFormula const& stateFormula = checkTask.getFormula(); if (stateFormula.isBinaryBooleanStateFormula()) { - return this->checkBinaryBooleanStateFormula(stateFormula.asBinaryBooleanStateFormula()); + return this->checkBinaryBooleanStateFormula(checkTask.replaceFormula(stateFormula.asBinaryBooleanStateFormula())); } else if (stateFormula.isUnaryBooleanStateFormula()) { - return this->checkUnaryBooleanStateFormula(stateFormula.asUnaryBooleanStateFormula()); + return this->checkUnaryBooleanStateFormula(checkTask.replaceFormula(stateFormula.asUnaryBooleanStateFormula())); } else if (stateFormula.isBooleanLiteralFormula()) { - return this->checkBooleanLiteralFormula(stateFormula.asBooleanLiteralFormula()); + return this->checkBooleanLiteralFormula(checkTask.replaceFormula(stateFormula.asBooleanLiteralFormula())); } else if (stateFormula.isProbabilityOperatorFormula()) { - return this->checkProbabilityOperatorFormula(stateFormula.asProbabilityOperatorFormula()); + return this->checkProbabilityOperatorFormula(checkTask.replaceFormula(stateFormula.asProbabilityOperatorFormula())); } else if (stateFormula.isRewardOperatorFormula()) { - return this->checkRewardOperatorFormula(stateFormula.asRewardOperatorFormula()); + return this->checkRewardOperatorFormula(checkTask.replaceFormula(stateFormula.asRewardOperatorFormula())); } else if (stateFormula.isExpectedTimeOperatorFormula()) { - return this->checkExpectedTimeOperatorFormula(stateFormula.asExpectedTimeOperatorFormula()); + return this->checkExpectedTimeOperatorFormula(checkTask.replaceFormula(stateFormula.asExpectedTimeOperatorFormula())); } else if (stateFormula.isLongRunAverageOperatorFormula()) { - return this->checkLongRunAverageOperatorFormula(stateFormula.asLongRunAverageOperatorFormula()); + return this->checkLongRunAverageOperatorFormula(checkTask.replaceFormula(stateFormula.asLongRunAverageOperatorFormula())); } else if (stateFormula.isAtomicExpressionFormula()) { - return this->checkAtomicExpressionFormula(stateFormula.asAtomicExpressionFormula()); + return this->checkAtomicExpressionFormula(checkTask.replaceFormula(stateFormula.asAtomicExpressionFormula())); } else if (stateFormula.isAtomicLabelFormula()) { - return this->checkAtomicLabelFormula(stateFormula.asAtomicLabelFormula()); + return this->checkAtomicLabelFormula(checkTask.replaceFormula(stateFormula.asAtomicLabelFormula())); } else if (stateFormula.isBooleanLiteralFormula()) { - return this->checkBooleanLiteralFormula(stateFormula.asBooleanLiteralFormula()); + return this->checkBooleanLiteralFormula(checkTask.replaceFormula(stateFormula.asBooleanLiteralFormula())); } STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException, "The given formula '" << stateFormula << "' is invalid."); } - std::unique_ptr AbstractModelChecker::checkAtomicExpressionFormula(storm::logic::AtomicExpressionFormula const& stateFormula) { + std::unique_ptr AbstractModelChecker::checkAtomicExpressionFormula(CheckTask const& checkTask) { + storm::logic::AtomicExpressionFormula const& stateFormula = checkTask.getFormula(); std::stringstream stream; stream << stateFormula.getExpression(); - return this->checkAtomicLabelFormula(storm::logic::AtomicLabelFormula(stream.str())); + return this->checkAtomicLabelFormula(checkTask.replaceFormula(storm::logic::AtomicLabelFormula(stream.str()))); } - std::unique_ptr AbstractModelChecker::checkAtomicLabelFormula(storm::logic::AtomicLabelFormula const& stateFormula) { - STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "This model checker does not support the formula: " << stateFormula << "."); + std::unique_ptr AbstractModelChecker::checkAtomicLabelFormula(CheckTask const& checkTask) { + STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "This model checker does not support the formula: " << checkTask.getFormula() << "."); } - std::unique_ptr AbstractModelChecker::checkBinaryBooleanStateFormula(storm::logic::BinaryBooleanStateFormula const& stateFormula) { + std::unique_ptr AbstractModelChecker::checkBinaryBooleanStateFormula(CheckTask const& checkTask) { + storm::logic::BinaryBooleanStateFormula const& stateFormula = checkTask.getFormula(); STORM_LOG_THROW(stateFormula.getLeftSubformula().isStateFormula() && stateFormula.getRightSubformula().isStateFormula(), storm::exceptions::InvalidArgumentException, "The given formula is invalid."); - std::unique_ptr leftResult = this->check(stateFormula.getLeftSubformula().asStateFormula()); - std::unique_ptr rightResult = this->check(stateFormula.getRightSubformula().asStateFormula()); + std::unique_ptr leftResult = this->check(checkTask.replaceFormula(stateFormula.getLeftSubformula().asStateFormula())); + std::unique_ptr rightResult = this->check(checkTask.replaceFormula(stateFormula.getRightSubformula().asStateFormula())); STORM_LOG_THROW(leftResult->isQualitative() && rightResult->isQualitative(), storm::exceptions::InternalTypeErrorException, "Expected qualitative results."); @@ -156,33 +163,15 @@ namespace storm { return leftResult; } - std::unique_ptr AbstractModelChecker::checkBooleanLiteralFormula(storm::logic::BooleanLiteralFormula const& stateFormula) { - STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "This model checker does not support the formula: " << stateFormula << "."); + std::unique_ptr AbstractModelChecker::checkBooleanLiteralFormula(CheckTask const& checkTask) { + STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "This model checker does not support the formula: " << checkTask.getFormula() << "."); } - std::unique_ptr AbstractModelChecker::checkProbabilityOperatorFormula(storm::logic::ProbabilityOperatorFormula const& stateFormula) { + std::unique_ptr AbstractModelChecker::checkProbabilityOperatorFormula(CheckTask const& checkTask) { + storm::logic::ProbabilityOperatorFormula const& stateFormula = checkTask.getFormula(); STORM_LOG_THROW(stateFormula.getSubformula().isPathFormula(), storm::exceptions::InvalidArgumentException, "The given formula is invalid."); - // If the probability bound is 0 or 1, is suffices to do qualitative model checking. - bool qualitative = false; - if (stateFormula.hasBound()) { - if (storm::utility::isZero(stateFormula.getBound()) || storm::utility::isOne(stateFormula.getBound())) { - qualitative = true; - } - } - - std::unique_ptr result; - if (stateFormula.hasOptimalityType()) { - result = this->computeProbabilities(stateFormula.getSubformula().asPathFormula(), qualitative, stateFormula.getOptimalityType()); - } else if (stateFormula.hasBound()) { - if (stateFormula.getComparisonType() == storm::logic::ComparisonType::Less || stateFormula.getComparisonType() == storm::logic::ComparisonType::LessEqual) { - result = this->computeProbabilities(stateFormula.getSubformula().asPathFormula(), qualitative, OptimizationDirection::Maximize); - } else { - result = this->computeProbabilities(stateFormula.getSubformula().asPathFormula(), qualitative, OptimizationDirection::Minimize); - } - } else { - result = this->computeProbabilities(stateFormula.getSubformula().asPathFormula(), qualitative); - } + std::unique_ptr result = this->computeProbabilities(checkTask.replaceFormula(stateFormula.getSubformula().asPathFormula())); if (stateFormula.hasBound()) { STORM_LOG_THROW(result->isQuantitative(), storm::exceptions::InvalidOperationException, "Unable to perform comparison operation on non-quantitative result."); @@ -192,95 +181,51 @@ namespace storm { } } - std::unique_ptr AbstractModelChecker::checkRewardOperatorFormula(storm::logic::RewardOperatorFormula const& stateFormula) { + std::unique_ptr AbstractModelChecker::checkRewardOperatorFormula(CheckTask const& checkTask) { + storm::logic::RewardOperatorFormula const& stateFormula = checkTask.getFormula(); STORM_LOG_THROW(stateFormula.getSubformula().isRewardPathFormula(), storm::exceptions::InvalidArgumentException, "The given formula is invalid."); - // If the reward bound is 0, is suffices to do qualitative model checking. - bool qualitative = false; - if (stateFormula.hasBound()) { - if (storm::utility::isZero(stateFormula.getBound())) { - qualitative = true; - } - } - - std::unique_ptr result; - if (stateFormula.hasOptimalityType()) { - result = this->computeRewards(stateFormula.getSubformula().asRewardPathFormula(), stateFormula.getOptionalRewardModelName(), qualitative, stateFormula.getOptimalityType()); - } else if (stateFormula.hasBound()) { - if (stateFormula.getComparisonType() == storm::logic::ComparisonType::Less || stateFormula.getComparisonType() == storm::logic::ComparisonType::LessEqual) { - result = this->computeRewards(stateFormula.getSubformula().asRewardPathFormula(), stateFormula.getOptionalRewardModelName(), qualitative, OptimizationDirection::Maximize); - } else { - result = this->computeRewards(stateFormula.getSubformula().asRewardPathFormula(), stateFormula.getOptionalRewardModelName(), qualitative, OptimizationDirection::Minimize); - } - } else { - result = this->computeRewards(stateFormula.getSubformula().asRewardPathFormula(), stateFormula.getOptionalRewardModelName(), qualitative); - } + std::unique_ptr result = this->computeRewards(checkTask.replaceFormula(stateFormula.getSubformula().asRewardPathFormula())); - if (stateFormula.hasBound()) { + if (checkTask.isBoundSet()) { STORM_LOG_THROW(result->isQuantitative(), storm::exceptions::InvalidOperationException, "Unable to perform comparison operation on non-quantitative result."); - return result->asQuantitativeCheckResult().compareAgainstBound(stateFormula.getComparisonType(), stateFormula.getBound()); + return result->asQuantitativeCheckResult().compareAgainstBound(checkTask.getBoundComparisonType(), checkTask.getBoundValue()); } else { return result; } } - std::unique_ptr AbstractModelChecker::checkExpectedTimeOperatorFormula(storm::logic::ExpectedTimeOperatorFormula const& stateFormula) { + std::unique_ptr AbstractModelChecker::checkExpectedTimeOperatorFormula(CheckTask const& checkTask) { + storm::logic::ExpectedTimeOperatorFormula const& stateFormula = checkTask.getFormula(); STORM_LOG_THROW(stateFormula.getSubformula().isEventuallyFormula(), storm::exceptions::InvalidArgumentException, "The given formula is invalid."); - // If the reward bound is 0, is suffices to do qualitative model checking. - bool qualitative = false; - if (stateFormula.hasBound()) { - if (storm::utility::isZero(stateFormula.getBound())) { - qualitative = true; - } - } - - std::unique_ptr result; - if (stateFormula.hasOptimalityType()) { - result = this->computeExpectedTimes(stateFormula.getSubformula().asEventuallyFormula(), qualitative, stateFormula.getOptimalityType()); - } else if (stateFormula.hasBound()) { - if (stateFormula.getComparisonType() == storm::logic::ComparisonType::Less || stateFormula.getComparisonType() == storm::logic::ComparisonType::LessEqual) { - result = this->computeExpectedTimes(stateFormula.getSubformula().asEventuallyFormula(), qualitative, OptimizationDirection::Maximize); - } else { - result = this->computeExpectedTimes(stateFormula.getSubformula().asEventuallyFormula(), qualitative, OptimizationDirection::Minimize); - } - } else { - result = this->computeExpectedTimes(stateFormula.getSubformula().asEventuallyFormula(), qualitative); - } + std::unique_ptr result = this->computeExpectedTimes(checkTask.replaceFormula(stateFormula.getSubformula().asEventuallyFormula())); - if (stateFormula.hasBound()) { + if (checkTask.isBoundSet()) { STORM_LOG_THROW(result->isQuantitative(), storm::exceptions::InvalidOperationException, "Unable to perform comparison operation on non-quantitative result."); - return result->asQuantitativeCheckResult().compareAgainstBound(stateFormula.getComparisonType(), stateFormula.getBound()); + return result->asQuantitativeCheckResult().compareAgainstBound(checkTask.getBoundComparisonType(), checkTask.getBoundValue()); } else { return result; } } - std::unique_ptr AbstractModelChecker::checkLongRunAverageOperatorFormula(storm::logic::LongRunAverageOperatorFormula const& stateFormula) { + std::unique_ptr AbstractModelChecker::checkLongRunAverageOperatorFormula(CheckTask const& checkTask) { + storm::logic::LongRunAverageOperatorFormula const& stateFormula = checkTask.getFormula(); STORM_LOG_THROW(stateFormula.getSubformula().isStateFormula(), storm::exceptions::InvalidArgumentException, "The given formula is invalid."); - std::unique_ptr result; - if (stateFormula.hasOptimalityType()) { - result = this->computeLongRunAverageProbabilities(stateFormula.getSubformula().asStateFormula(), false, stateFormula.getOptimalityType()); - } else if (stateFormula.hasBound()) { - if (stateFormula.getComparisonType() == storm::logic::ComparisonType::Less || stateFormula.getComparisonType() == storm::logic::ComparisonType::LessEqual) { - result = this->computeLongRunAverageProbabilities(stateFormula.getSubformula().asStateFormula(), false, OptimizationDirection::Maximize); - } else { - result = this->computeLongRunAverageProbabilities(stateFormula.getSubformula().asStateFormula(), false, OptimizationDirection::Minimize); - } - } else { - result = this->computeLongRunAverageProbabilities(stateFormula.getSubformula().asStateFormula(), false); - } + std::unique_ptr result = this->computeLongRunAverageProbabilities(checkTask.replaceFormula(stateFormula.getSubformula().asStateFormula())); - if (stateFormula.hasBound()) { - return result->asQuantitativeCheckResult().compareAgainstBound(stateFormula.getComparisonType(), stateFormula.getBound()); + if (checkTask.isBoundSet()) { + STORM_LOG_THROW(result->isQuantitative(), storm::exceptions::InvalidOperationException, "Unable to perform comparison operation on non-quantitative result."); + return result->asQuantitativeCheckResult().compareAgainstBound(checkTask.getBoundComparisonType(), checkTask.getBoundValue()); } else { return result; } } - std::unique_ptr AbstractModelChecker::checkUnaryBooleanStateFormula(storm::logic::UnaryBooleanStateFormula const& stateFormula) { - std::unique_ptr subResult = this->check(stateFormula.getSubformula()); + std::unique_ptr AbstractModelChecker::checkUnaryBooleanStateFormula(CheckTask const& checkTask) { + storm::logic::UnaryBooleanStateFormula const& stateFormula = checkTask.getFormula(); + std::unique_ptr subResult = this->check(checkTask.replaceFormula(stateFormula.getSubformula())); STORM_LOG_THROW(subResult->isQualitative(), storm::exceptions::InternalTypeErrorException, "Expected qualitative result."); if (stateFormula.isNot()) { subResult->asQualitativeCheckResult().complement(); diff --git a/src/modelchecker/AbstractModelChecker.h b/src/modelchecker/AbstractModelChecker.h index 5fca10010..a4ad1b6ac 100644 --- a/src/modelchecker/AbstractModelChecker.h +++ b/src/modelchecker/AbstractModelChecker.h @@ -3,6 +3,7 @@ #include +#include "src/modelchecker/CheckTask.h" #include "src/logic/Formulas.h" #include "src/solver/OptimizationDirection.h" @@ -17,53 +18,53 @@ namespace storm { } /*! - * Determines whether the model checker can handle the formula. If this method returns false, the formula - * must not be checked using the model checker. + * Determines whether the model checker can handle the given verification task. If this method returns + * false, the task must not be checked using this model checker. * - * @param formula The formula for which to check whether the model checker can handle it. - * @return True iff the model checker can check the given formula. + * @param checkTask The task for which to check whether the model checker can handle it. + * @return True iff the model checker can check the given task. */ - virtual bool canHandle(storm::logic::Formula const& formula) const = 0; + virtual bool canHandle(CheckTask const& checkTask) const = 0; /*! * Checks the provided formula. * - * @param formula The formula to check. + * @param checkTask The verification task to pursue. * @return The verification result. */ - virtual std::unique_ptr check(storm::logic::Formula const& formula); + virtual std::unique_ptr check(CheckTask const& checkTask); // The methods to compute probabilities for path formulas. - virtual std::unique_ptr computeProbabilities(storm::logic::PathFormula const& pathFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()); - virtual std::unique_ptr computeBoundedUntilProbabilities(storm::logic::BoundedUntilFormula const& pathFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()); - virtual std::unique_ptr computeConditionalProbabilities(storm::logic::ConditionalPathFormula const& pathFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()); - virtual std::unique_ptr computeEventuallyProbabilities(storm::logic::EventuallyFormula const& pathFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()); - virtual std::unique_ptr computeGloballyProbabilities(storm::logic::GloballyFormula const& pathFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()); - virtual std::unique_ptr computeNextProbabilities(storm::logic::NextFormula const& pathFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()); - virtual std::unique_ptr computeUntilProbabilities(storm::logic::UntilFormula const& pathFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()); + virtual std::unique_ptr computeProbabilities(CheckTask const& checkTask); + virtual std::unique_ptr computeBoundedUntilProbabilities(CheckTask const& checkTask); + virtual std::unique_ptr computeConditionalProbabilities(CheckTask const& checkTask); + virtual std::unique_ptr computeEventuallyProbabilities(CheckTask const& checkTask); + virtual std::unique_ptr computeGloballyProbabilities(CheckTask const& checkTask); + virtual std::unique_ptr computeNextProbabilities(CheckTask const& checkTask); + virtual std::unique_ptr computeUntilProbabilities(CheckTask const& checkTask); // The methods to compute the rewards for path formulas. - virtual std::unique_ptr computeRewards(storm::logic::RewardPathFormula const& rewardPathFormula, boost::optional const& rewardModelName = boost::optional(), bool qualitative = false, boost::optional const& optimalityType = boost::optional()); - virtual std::unique_ptr computeCumulativeRewards(storm::logic::CumulativeRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName = boost::optional(), bool qualitative = false, boost::optional const& optimalityType = boost::optional()); - virtual std::unique_ptr computeInstantaneousRewards(storm::logic::InstantaneousRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName = boost::optional(), bool qualitative = false, boost::optional const& optimalityType = boost::optional()); - virtual std::unique_ptr computeReachabilityRewards(storm::logic::ReachabilityRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName = boost::optional(), bool qualitative = false, boost::optional const& optimalityType = boost::optional()); - virtual std::unique_ptr computeLongRunAverageRewards(storm::logic::LongRunAverageRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName = boost::optional(), bool qualitative = false, boost::optional const& optimalityType = boost::optional()); + virtual std::unique_ptr computeRewards(CheckTask const& checkTask); + virtual std::unique_ptr computeCumulativeRewards(CheckTask const& checkTask); + virtual std::unique_ptr computeInstantaneousRewards(CheckTask const& checkTask); + virtual std::unique_ptr computeReachabilityRewards(CheckTask const& checkTask); + virtual std::unique_ptr computeLongRunAverageRewards(CheckTask const& checkTask); // The methods to compute the long-run average and expected time. - virtual std::unique_ptr computeLongRunAverageProbabilities(storm::logic::StateFormula const& stateFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()); - virtual std::unique_ptr computeExpectedTimes(storm::logic::EventuallyFormula const& eventuallyFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()); + virtual std::unique_ptr computeLongRunAverageProbabilities(CheckTask const& checkTask); + virtual std::unique_ptr computeExpectedTimes(CheckTask const& checkTask); // The methods to check state formulas. - virtual std::unique_ptr checkStateFormula(storm::logic::StateFormula const& stateFormula); - virtual std::unique_ptr checkAtomicExpressionFormula(storm::logic::AtomicExpressionFormula const& stateFormula); - virtual std::unique_ptr checkAtomicLabelFormula(storm::logic::AtomicLabelFormula const& stateFormula); - virtual std::unique_ptr checkBinaryBooleanStateFormula(storm::logic::BinaryBooleanStateFormula const& stateFormula); - virtual std::unique_ptr checkBooleanLiteralFormula(storm::logic::BooleanLiteralFormula const& stateFormula); - virtual std::unique_ptr checkProbabilityOperatorFormula(storm::logic::ProbabilityOperatorFormula const& stateFormula); - virtual std::unique_ptr checkRewardOperatorFormula(storm::logic::RewardOperatorFormula const& stateFormula); - virtual std::unique_ptr checkExpectedTimeOperatorFormula(storm::logic::ExpectedTimeOperatorFormula const& stateFormula); - virtual std::unique_ptr checkLongRunAverageOperatorFormula(storm::logic::LongRunAverageOperatorFormula const& stateFormula); - virtual std::unique_ptr checkUnaryBooleanStateFormula(storm::logic::UnaryBooleanStateFormula const& stateFormula); + virtual std::unique_ptr checkStateFormula(CheckTask const& stateFormula); + virtual std::unique_ptr checkAtomicExpressionFormula(CheckTask const& checkTask); + virtual std::unique_ptr checkAtomicLabelFormula(CheckTask const& checkTask); + virtual std::unique_ptr checkBinaryBooleanStateFormula(CheckTask const& checkTask); + virtual std::unique_ptr checkBooleanLiteralFormula(CheckTask const& checkTask); + virtual std::unique_ptr checkProbabilityOperatorFormula(CheckTask const& checkTask); + virtual std::unique_ptr checkRewardOperatorFormula(CheckTask const& checkTask); + virtual std::unique_ptr checkExpectedTimeOperatorFormula(CheckTask const& checkTask); + virtual std::unique_ptr checkLongRunAverageOperatorFormula(CheckTask const& checkTask); + virtual std::unique_ptr checkUnaryBooleanStateFormula(CheckTask const& checkTask); }; } } diff --git a/src/modelchecker/CheckTask.h b/src/modelchecker/CheckTask.h new file mode 100644 index 000000000..cf66f4f06 --- /dev/null +++ b/src/modelchecker/CheckTask.h @@ -0,0 +1,221 @@ +#ifndef STORM_MODELCHECKER_CHECKTASK_H_ +#define STORM_MODELCHECKER_CHECKTASK_H_ + +#include + +#include "src/logic/Formulas.h" +#include "src/utility/constants.h" + +#include "src/solver/OptimizationDirection.h" +#include "src/logic/ComparisonType.h" + +namespace storm { + namespace logic { + class Formula; + } + + namespace modelchecker { + + /* + * This class is used to customize the checking process of a formula. + */ + template + class CheckTask { + public: + template + friend class CheckTask; + + /*! + * Creates a task object with the default options for the given formula. + */ + CheckTask(FormulaType const& formula, bool onlyInitialStatesRelevant = false) : formula(formula) { + this->onlyInitialStatesRelevant = onlyInitialStatesRelevant; + this->produceStrategies = true; + this->qualitative = false; + + if (formula.isOperatorFormula()) { + storm::logic::OperatorFormula const& operatorFormula = formula.asOperatorFormula(); + if (operatorFormula.hasOptimalityType()) { + this->optimizationDirection = operatorFormula.getOptimalityType(); + } + + if (operatorFormula.hasBound()) { + if (onlyInitialStatesRelevant) { + this->bound = std::make_pair(operatorFormula.getComparisonType(), static_cast(operatorFormula.getBound())); + } + + if (!optimizationDirection) { + this->optimizationDirection = operatorFormula.getComparisonType() == storm::logic::ComparisonType::Less || operatorFormula.getComparisonType() == storm::logic::ComparisonType::LessEqual ? OptimizationDirection::Maximize : OptimizationDirection::Minimize; + } + } + } + + if (formula.isProbabilityOperatorFormula()) { + storm::logic::ProbabilityOperatorFormula const& probabilityOperatorFormula = formula.asProbabilityOperatorFormula(); + + if (probabilityOperatorFormula.hasBound()) { + if (probabilityOperatorFormula.getBound() == storm::utility::zero() || probabilityOperatorFormula.getBound() == storm::utility::one()) { + this->qualitative = true; + } + } + } else if (formula.isRewardOperatorFormula()) { + storm::logic::RewardOperatorFormula const& rewardOperatorFormula = formula.asRewardOperatorFormula(); + this->rewardModel = rewardOperatorFormula.getOptionalRewardModelName(); + + if (rewardOperatorFormula.hasBound()) { + if (rewardOperatorFormula.getBound() == storm::utility::zero()) { + this->qualitative = true; + } + } + } + } + + /*! + * Copies the check task from the source while replacing the formula with the new one. In particular, this + * changes the formula type of the check task object. + */ + template + CheckTask replaceFormula(NewFormulaType const& newFormula) const { + return CheckTask(newFormula, this->optimizationDirection, this->rewardModel, this->onlyInitialStatesRelevant, this->bound, this->qualitative, this->produceStrategies); + } + + /*! + * Retrieves the formula from this task. + */ + FormulaType const& getFormula() const { + return formula.get(); + } + + /*! + * Retrieves whether an optimization direction was set. + */ + bool isOptimizationDirectionSet() const { + return static_cast(optimizationDirection); + } + + /*! + * Retrieves the optimization direction (if set). + */ + storm::OptimizationDirection const& getOptimizationDirection() const { + return optimizationDirection.get(); + } + + /*! + * Retrieves whether a reward model was set. + */ + bool isRewardModelSet() const { + return static_cast(rewardModel); + } + + /*! + * Retrieves the reward model over which to perform the checking (if set). + */ + std::string const& getRewardModel() const { + return rewardModel.get(); + } + + /*! + * Retrieves whether only the initial states are relevant in the computation. + */ + bool isOnlyInitialStatesRelevantSet() const { + return onlyInitialStatesRelevant; + } + + /*! + * Sets whether only initial states are relevant. + */ + CheckTask& setOnlyInitialStatesRelevant(bool value = true) { + this->onlyInitialStatesRelevant = value; + return *this; + } + + /*! + * Retrieves whether there is a bound with which the values for the states will be compared. + */ + bool isBoundSet() const { + return static_cast(bound); + } + + /*! + * Retrieves the value of the bound (if set). + */ + ValueType const& getBoundValue() const { + return bound.get().second; + } + + /*! + * Retrieves the comparison type of the bound (if set). + */ + storm::logic::ComparisonType const& getBoundComparisonType() const { + return bound.get().first; + } + + /*! + * Retrieves the bound for the initial states (if set). + */ + std::pair const& getBound() const { + return bound.get(); + } + + /*! + * Retrieves whether the computation only needs to be performed qualitatively, because the values will only + * be compared to 0/1. + */ + bool isQualitativeSet() const { + return qualitative; + } + + /*! + * Retrieves whether strategies are to be produced (if supported). + */ + bool isProduceStrategiesSet() const { + return produceStrategies; + } + + private: + /*! + * Creates a task object with the given options. + * + * @param formula The formula to attach to the task. + * @param optimizationDirection If set, the probabilities will be minimized/maximized. + * @param rewardModelName If given, the checking has to be done wrt. to this reward model. + * @param onlyInitialStatesRelevant If set to true, the model checker may decide to only compute the values + * for the initial states. + * @param initialStatesBound The bound with which the initial states will be compared. This may only be set + * together with the flag that indicates only initial states of the model are relevant. + * @param qualitative A flag specifying whether the property needs to be checked qualitatively, i.e. compared + * with bounds 0/1. + * @param produceStrategies If supported by the model checker and the model formalism, strategies to achieve + * a value will be produced if this flag is set. + */ + CheckTask(std::reference_wrapper const& formula, boost::optional const& optimizationDirection, boost::optional const& rewardModel, bool onlyInitialStatesRelevant, boost::optional> const& bound, bool qualitative, bool produceStrategies) : formula(formula), optimizationDirection(optimizationDirection), rewardModel(rewardModel), onlyInitialStatesRelevant(onlyInitialStatesRelevant), bound(bound), qualitative(qualitative), produceStrategies(produceStrategies) { + // Intentionally left empty. + } + + // The formula that is to be checked. + std::reference_wrapper formula; + + // If set, the probabilities will be minimized/maximized. + boost::optional optimizationDirection; + + // If set, the reward property has to be interpreted over this model. + boost::optional rewardModel; + + // If set to true, the model checker may decide to only compute the values for the initial states. + bool onlyInitialStatesRelevant; + + // The bound with which the initial states will be compared. + boost::optional> bound; + + // A flag specifying whether the property needs to be checked qualitatively, i.e. compared with bounds 0/1. + bool qualitative; + + // If supported by the model checker and the model formalism, strategies to achieve a value will be produced + // if this flag is set. + bool produceStrategies; + }; + + } +} + +#endif /* STORM_MODELCHECKER_CHECKTASK_H_ */ \ No newline at end of file diff --git a/src/modelchecker/csl/HybridCtmcCslModelChecker.cpp b/src/modelchecker/csl/HybridCtmcCslModelChecker.cpp index 42c9466d1..a5eb27b27 100644 --- a/src/modelchecker/csl/HybridCtmcCslModelChecker.cpp +++ b/src/modelchecker/csl/HybridCtmcCslModelChecker.cpp @@ -23,22 +23,25 @@ namespace storm { } template - bool HybridCtmcCslModelChecker::canHandle(storm::logic::Formula const& formula) const { + bool HybridCtmcCslModelChecker::canHandle(CheckTask const& checkTask) const { + storm::logic::Formula const& formula = checkTask.getFormula(); return formula.isCslStateFormula() || formula.isCslPathFormula() || formula.isRewardPathFormula(); } template - std::unique_ptr HybridCtmcCslModelChecker::computeUntilProbabilities(storm::logic::UntilFormula const& pathFormula, bool qualitative, boost::optional const& optimalityType) { + std::unique_ptr HybridCtmcCslModelChecker::computeUntilProbabilities(CheckTask const& checkTask) { + storm::logic::UntilFormula const& pathFormula = checkTask.getFormula(); std::unique_ptr leftResultPointer = this->check(pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(pathFormula.getRightSubformula()); SymbolicQualitativeCheckResult const& leftResult = leftResultPointer->asSymbolicQualitativeCheckResult(); SymbolicQualitativeCheckResult const& rightResult = rightResultPointer->asSymbolicQualitativeCheckResult(); - return storm::modelchecker::helper::HybridCtmcCslHelper::computeUntilProbabilities(this->getModel(), this->getModel().getTransitionMatrix(), this->getModel().getExitRateVector(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), qualitative, *this->linearEquationSolverFactory); + return storm::modelchecker::helper::HybridCtmcCslHelper::computeUntilProbabilities(this->getModel(), this->getModel().getTransitionMatrix(), this->getModel().getExitRateVector(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), checkTask.isQualitativeSet(), *this->linearEquationSolverFactory); } template - std::unique_ptr HybridCtmcCslModelChecker::computeNextProbabilities(storm::logic::NextFormula const& pathFormula, bool qualitative, boost::optional const& optimalityType) { + std::unique_ptr HybridCtmcCslModelChecker::computeNextProbabilities(CheckTask const& checkTask) { + storm::logic::NextFormula const& pathFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(pathFormula.getSubformula()); SymbolicQualitativeCheckResult const& subResult = subResultPointer->asSymbolicQualitativeCheckResult(); @@ -51,15 +54,17 @@ namespace storm { } template - std::unique_ptr HybridCtmcCslModelChecker::computeReachabilityRewards(storm::logic::ReachabilityRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName, bool qualitative, boost::optional const& optimalityType) { + std::unique_ptr HybridCtmcCslModelChecker::computeReachabilityRewards(CheckTask const& checkTask) { + storm::logic::ReachabilityRewardFormula const& rewardPathFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(rewardPathFormula.getSubformula()); SymbolicQualitativeCheckResult const& subResult = subResultPointer->asSymbolicQualitativeCheckResult(); - return storm::modelchecker::helper::HybridCtmcCslHelper::computeReachabilityRewards(this->getModel(), this->getModel().getTransitionMatrix(), this->getModel().getExitRateVector(), rewardModelName ? this->getModel().getRewardModel(rewardModelName.get()) : this->getModel().getRewardModel(""), subResult.getTruthValuesVector(), qualitative, *linearEquationSolverFactory); + return storm::modelchecker::helper::HybridCtmcCslHelper::computeReachabilityRewards(this->getModel(), this->getModel().getTransitionMatrix(), this->getModel().getExitRateVector(), checkTask.isRewardModelSet() ? this->getModel().getRewardModel(checkTask.getRewardModel()) : this->getModel().getRewardModel(""), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), *linearEquationSolverFactory); } template - std::unique_ptr HybridCtmcCslModelChecker::computeBoundedUntilProbabilities(storm::logic::BoundedUntilFormula const& pathFormula, bool qualitative, boost::optional const& optimalityType) { + std::unique_ptr HybridCtmcCslModelChecker::computeBoundedUntilProbabilities(CheckTask const& checkTask) { + storm::logic::BoundedUntilFormula const& pathFormula = checkTask.getFormula(); std::unique_ptr leftResultPointer = this->check(pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(pathFormula.getRightSubformula()); SymbolicQualitativeCheckResult const& leftResult = leftResultPointer->asSymbolicQualitativeCheckResult(); @@ -74,25 +79,28 @@ namespace storm { upperBound = pathFormula.getDiscreteTimeBound(); } - return storm::modelchecker::helper::HybridCtmcCslHelper::computeBoundedUntilProbabilities(this->getModel(), this->getModel().getTransitionMatrix(), this->getModel().getExitRateVector(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), qualitative, lowerBound, upperBound, *linearEquationSolverFactory); + return storm::modelchecker::helper::HybridCtmcCslHelper::computeBoundedUntilProbabilities(this->getModel(), this->getModel().getTransitionMatrix(), this->getModel().getExitRateVector(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), checkTask.isQualitativeSet(), lowerBound, upperBound, *linearEquationSolverFactory); } template - std::unique_ptr HybridCtmcCslModelChecker::computeInstantaneousRewards(storm::logic::InstantaneousRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName, bool qualitative, boost::optional const& optimalityType) { - return storm::modelchecker::helper::HybridCtmcCslHelper::computeInstantaneousRewards(this->getModel(), this->getModel().getTransitionMatrix(), this->getModel().getExitRateVector(), rewardModelName ? this->getModel().getRewardModel(rewardModelName.get()) : this->getModel().getRewardModel(""), rewardPathFormula.getContinuousTimeBound(), *linearEquationSolverFactory); + std::unique_ptr HybridCtmcCslModelChecker::computeInstantaneousRewards(CheckTask const& checkTask) { + storm::logic::InstantaneousRewardFormula const& rewardPathFormula = checkTask.getFormula(); + return storm::modelchecker::helper::HybridCtmcCslHelper::computeInstantaneousRewards(this->getModel(), this->getModel().getTransitionMatrix(), this->getModel().getExitRateVector(), checkTask.isRewardModelSet() ? this->getModel().getRewardModel(checkTask.getRewardModel()) : this->getModel().getRewardModel(""), rewardPathFormula.getContinuousTimeBound(), *linearEquationSolverFactory); } template - std::unique_ptr HybridCtmcCslModelChecker::computeCumulativeRewards(storm::logic::CumulativeRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName, bool qualitative, boost::optional const& optimalityType) { - return storm::modelchecker::helper::HybridCtmcCslHelper::computeCumulativeRewards(this->getModel(), this->getModel().getTransitionMatrix(), this->getModel().getExitRateVector(), rewardModelName ? this->getModel().getRewardModel(rewardModelName.get()) : this->getModel().getRewardModel(""), rewardPathFormula.getContinuousTimeBound(), *linearEquationSolverFactory); + std::unique_ptr HybridCtmcCslModelChecker::computeCumulativeRewards(CheckTask const& checkTask) { + storm::logic::CumulativeRewardFormula const& rewardPathFormula = checkTask.getFormula(); + return storm::modelchecker::helper::HybridCtmcCslHelper::computeCumulativeRewards(this->getModel(), this->getModel().getTransitionMatrix(), this->getModel().getExitRateVector(), checkTask.isRewardModelSet() ? this->getModel().getRewardModel(checkTask.getRewardModel()) : this->getModel().getRewardModel(""), rewardPathFormula.getContinuousTimeBound(), *linearEquationSolverFactory); } template - std::unique_ptr HybridCtmcCslModelChecker::computeLongRunAverageProbabilities(storm::logic::StateFormula const& stateFormula, bool qualitative, boost::optional const& optimalityType) { + std::unique_ptr HybridCtmcCslModelChecker::computeLongRunAverageProbabilities(CheckTask const& checkTask) { + storm::logic::StateFormula const& stateFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(stateFormula); SymbolicQualitativeCheckResult const& subResult = subResultPointer->asSymbolicQualitativeCheckResult(); - return storm::modelchecker::helper::HybridCtmcCslHelper::computeLongRunAverageProbabilities(this->getModel(), this->getModel().getTransitionMatrix(), this->getModel().getExitRateVector(), subResult.getTruthValuesVector(), qualitative, *linearEquationSolverFactory); + return storm::modelchecker::helper::HybridCtmcCslHelper::computeLongRunAverageProbabilities(this->getModel(), this->getModel().getTransitionMatrix(), this->getModel().getExitRateVector(), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), *linearEquationSolverFactory); } // Explicitly instantiate the model checker. diff --git a/src/modelchecker/csl/HybridCtmcCslModelChecker.h b/src/modelchecker/csl/HybridCtmcCslModelChecker.h index ed4125c7e..ace5b420b 100644 --- a/src/modelchecker/csl/HybridCtmcCslModelChecker.h +++ b/src/modelchecker/csl/HybridCtmcCslModelChecker.h @@ -17,14 +17,14 @@ namespace storm { explicit HybridCtmcCslModelChecker(storm::models::symbolic::Ctmc const& model, std::unique_ptr>&& linearEquationSolverFactory); // The implemented methods of the AbstractModelChecker interface. - virtual bool canHandle(storm::logic::Formula const& formula) const override; - virtual std::unique_ptr computeBoundedUntilProbabilities(storm::logic::BoundedUntilFormula const& pathFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeNextProbabilities(storm::logic::NextFormula const& pathFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeUntilProbabilities(storm::logic::UntilFormula const& pathFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeInstantaneousRewards(storm::logic::InstantaneousRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName = boost::optional(), bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeCumulativeRewards(storm::logic::CumulativeRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName = boost::optional(), bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeReachabilityRewards(storm::logic::ReachabilityRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName = boost::optional(), bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeLongRunAverageProbabilities(storm::logic::StateFormula const& stateFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; + virtual bool canHandle(CheckTask const& checkTask) const override; + virtual std::unique_ptr computeBoundedUntilProbabilities(CheckTask const& checkTask) override; + virtual std::unique_ptr computeNextProbabilities(CheckTask const& checkTask) override; + virtual std::unique_ptr computeUntilProbabilities(CheckTask const& checkTask) override; + virtual std::unique_ptr computeInstantaneousRewards(CheckTask const& checkTask) override; + virtual std::unique_ptr computeCumulativeRewards(CheckTask const& checkTask) override; + virtual std::unique_ptr computeReachabilityRewards(CheckTask const& checkTask) override; + virtual std::unique_ptr computeLongRunAverageProbabilities(CheckTask const& checkTask) override; protected: storm::models::symbolic::Ctmc const& getModel() const override; diff --git a/src/modelchecker/csl/SparseCtmcCslModelChecker.cpp b/src/modelchecker/csl/SparseCtmcCslModelChecker.cpp index 3648f8bb4..b06cc2a54 100644 --- a/src/modelchecker/csl/SparseCtmcCslModelChecker.cpp +++ b/src/modelchecker/csl/SparseCtmcCslModelChecker.cpp @@ -30,12 +30,14 @@ namespace storm { } template - bool SparseCtmcCslModelChecker::canHandle(storm::logic::Formula const& formula) const { + bool SparseCtmcCslModelChecker::canHandle(CheckTask const& checkTask) const { + storm::logic::Formula const& formula = checkTask.getFormula(); return formula.isCslStateFormula() || formula.isCslPathFormula() || formula.isRewardPathFormula(); } template - std::unique_ptr SparseCtmcCslModelChecker::computeBoundedUntilProbabilities(storm::logic::BoundedUntilFormula const& pathFormula, bool qualitative, boost::optional const& optimalityType) { + std::unique_ptr SparseCtmcCslModelChecker::computeBoundedUntilProbabilities(CheckTask const& checkTask) { + storm::logic::BoundedUntilFormula const& pathFormula = checkTask.getFormula(); std::unique_ptr leftResultPointer = this->check(pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(pathFormula.getRightSubformula()); ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult();; @@ -50,12 +52,13 @@ namespace storm { upperBound = pathFormula.getDiscreteTimeBound(); } - std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeBoundedUntilProbabilities(this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), this->getModel().getExitRateVector(), qualitative, lowerBound, upperBound, *linearEquationSolverFactory); + std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeBoundedUntilProbabilities(this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), this->getModel().getExitRateVector(), checkTask.isQualitativeSet(), lowerBound, upperBound, *linearEquationSolverFactory); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); } template - std::unique_ptr SparseCtmcCslModelChecker::computeNextProbabilities(storm::logic::NextFormula const& pathFormula, bool qualitative, boost::optional const& optimalityType) { + std::unique_ptr SparseCtmcCslModelChecker::computeNextProbabilities(CheckTask const& checkTask) { + storm::logic::NextFormula const& pathFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(pathFormula.getSubformula()); ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeNextProbabilities(this->getModel().getTransitionMatrix(), this->getModel().getExitRateVector(), subResult.getTruthValuesVector(), *linearEquationSolverFactory); @@ -63,43 +66,48 @@ namespace storm { } template - std::unique_ptr SparseCtmcCslModelChecker::computeUntilProbabilities(storm::logic::UntilFormula const& pathFormula, bool qualitative, boost::optional const& optimalityType) { + std::unique_ptr SparseCtmcCslModelChecker::computeUntilProbabilities(CheckTask const& checkTask) { + storm::logic::UntilFormula const& pathFormula = checkTask.getFormula(); std::unique_ptr leftResultPointer = this->check(pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(pathFormula.getRightSubformula()); ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); - std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeUntilProbabilities(this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), this->getModel().getExitRateVector(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), qualitative, *this->linearEquationSolverFactory); + std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeUntilProbabilities(this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), this->getModel().getExitRateVector(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), checkTask.isQualitativeSet(), *this->linearEquationSolverFactory); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); } template - std::unique_ptr SparseCtmcCslModelChecker::computeInstantaneousRewards(storm::logic::InstantaneousRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName, bool qualitative, boost::optional const& optimalityType) { - std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeInstantaneousRewards(this->getModel().getTransitionMatrix(), this->getModel().getExitRateVector(), rewardModelName ? this->getModel().getRewardModel(rewardModelName.get()) : this->getModel().getRewardModel(""), rewardPathFormula.getContinuousTimeBound(), *linearEquationSolverFactory); + std::unique_ptr SparseCtmcCslModelChecker::computeInstantaneousRewards(CheckTask const& checkTask) { + storm::logic::InstantaneousRewardFormula const& rewardPathFormula = checkTask.getFormula(); + std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeInstantaneousRewards(this->getModel().getTransitionMatrix(), this->getModel().getExitRateVector(), checkTask.isRewardModelSet() ? this->getModel().getRewardModel(checkTask.getRewardModel()) : this->getModel().getRewardModel(""), rewardPathFormula.getContinuousTimeBound(), *linearEquationSolverFactory); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); } template - std::unique_ptr SparseCtmcCslModelChecker::computeCumulativeRewards(storm::logic::CumulativeRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName, bool qualitative, boost::optional const& optimalityType) { - std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeCumulativeRewards(this->getModel().getTransitionMatrix(), this->getModel().getExitRateVector(), rewardModelName ? this->getModel().getRewardModel(rewardModelName.get()) : this->getModel().getRewardModel(""), rewardPathFormula.getContinuousTimeBound(), *linearEquationSolverFactory); + std::unique_ptr SparseCtmcCslModelChecker::computeCumulativeRewards(CheckTask const& checkTask) { + storm::logic::CumulativeRewardFormula const& rewardPathFormula = checkTask.getFormula(); + std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeCumulativeRewards(this->getModel().getTransitionMatrix(), this->getModel().getExitRateVector(), checkTask.isRewardModelSet() ? this->getModel().getRewardModel(checkTask.getRewardModel()) : this->getModel().getRewardModel(""), rewardPathFormula.getContinuousTimeBound(), *linearEquationSolverFactory); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); } template - std::unique_ptr SparseCtmcCslModelChecker::computeReachabilityRewards(storm::logic::ReachabilityRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName, bool qualitative, boost::optional const& optimalityType) { + std::unique_ptr SparseCtmcCslModelChecker::computeReachabilityRewards(CheckTask const& checkTask) { + storm::logic::ReachabilityRewardFormula const& rewardPathFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(rewardPathFormula.getSubformula()); ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); - std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeReachabilityRewards(this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), this->getModel().getExitRateVector(), rewardModelName ? this->getModel().getRewardModel(rewardModelName.get()) : this->getModel().getRewardModel(""), subResult.getTruthValuesVector(), qualitative, *linearEquationSolverFactory); + std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeReachabilityRewards(this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), this->getModel().getExitRateVector(), checkTask.isRewardModelSet() ? this->getModel().getRewardModel(checkTask.getRewardModel()) : this->getModel().getRewardModel(""), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), *linearEquationSolverFactory); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); } template - std::unique_ptr SparseCtmcCslModelChecker::computeLongRunAverageProbabilities(storm::logic::StateFormula const& stateFormula, bool qualitative, boost::optional const& optimalityType) { + std::unique_ptr SparseCtmcCslModelChecker::computeLongRunAverageProbabilities(CheckTask const& checkTask) { + storm::logic::StateFormula const& stateFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(stateFormula); ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); storm::storage::SparseMatrix probabilityMatrix = storm::modelchecker::helper::SparseCtmcCslHelper::computeProbabilityMatrix(this->getModel().getTransitionMatrix(), this->getModel().getExitRateVector()); - std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeLongRunAverageProbabilities(probabilityMatrix, subResult.getTruthValuesVector(), &this->getModel().getExitRateVector(), qualitative, *linearEquationSolverFactory); + std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeLongRunAverageProbabilities(probabilityMatrix, subResult.getTruthValuesVector(), &this->getModel().getExitRateVector(), checkTask.isQualitativeSet(), *linearEquationSolverFactory); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); } diff --git a/src/modelchecker/csl/SparseCtmcCslModelChecker.h b/src/modelchecker/csl/SparseCtmcCslModelChecker.h index 78e2fd91f..d4e36071a 100644 --- a/src/modelchecker/csl/SparseCtmcCslModelChecker.h +++ b/src/modelchecker/csl/SparseCtmcCslModelChecker.h @@ -20,14 +20,14 @@ namespace storm { explicit SparseCtmcCslModelChecker(SparseCtmcModelType const& model, std::unique_ptr>&& linearEquationSolverFactory); // The implemented methods of the AbstractModelChecker interface. - virtual bool canHandle(storm::logic::Formula const& formula) const override; - virtual std::unique_ptr computeBoundedUntilProbabilities(storm::logic::BoundedUntilFormula const& pathFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeNextProbabilities(storm::logic::NextFormula const& pathFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeUntilProbabilities(storm::logic::UntilFormula const& pathFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeCumulativeRewards(storm::logic::CumulativeRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName = boost::optional(), bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeInstantaneousRewards(storm::logic::InstantaneousRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName = boost::optional(), bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeReachabilityRewards(storm::logic::ReachabilityRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName = boost::optional(), bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeLongRunAverageProbabilities(storm::logic::StateFormula const& stateFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; + virtual bool canHandle(CheckTask const& checkTask) const override; + virtual std::unique_ptr computeBoundedUntilProbabilities(CheckTask const& checkTask) override; + virtual std::unique_ptr computeNextProbabilities(CheckTask const& checkTask) override; + virtual std::unique_ptr computeUntilProbabilities(CheckTask const& checkTask) override; + virtual std::unique_ptr computeCumulativeRewards(CheckTask const& checkTask) override; + virtual std::unique_ptr computeInstantaneousRewards(CheckTask const& checkTask) override; + virtual std::unique_ptr computeReachabilityRewards(CheckTask const& checkTask) override; + virtual std::unique_ptr computeLongRunAverageProbabilities(CheckTask const& checkTask) override; private: // An object that is used for solving linear equations and performing matrix-vector multiplication. diff --git a/src/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.cpp b/src/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.cpp index b93643d62..b33b01436 100644 --- a/src/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.cpp +++ b/src/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.cpp @@ -28,64 +28,70 @@ namespace storm { } template - bool SparseMarkovAutomatonCslModelChecker::canHandle(storm::logic::Formula const& formula) const { + bool SparseMarkovAutomatonCslModelChecker::canHandle(CheckTask const& checkTask) const { + storm::logic::Formula const& formula = checkTask.getFormula(); return formula.isCslStateFormula() || formula.isCslPathFormula() || (formula.isRewardPathFormula() && formula.isReachabilityRewardFormula()); } template - std::unique_ptr SparseMarkovAutomatonCslModelChecker::computeBoundedUntilProbabilities(storm::logic::BoundedUntilFormula const& pathFormula, bool qualitative, boost::optional const& optimalityType) { - STORM_LOG_THROW(optimalityType, storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); + std::unique_ptr SparseMarkovAutomatonCslModelChecker::computeBoundedUntilProbabilities(CheckTask const& checkTask) { + storm::logic::BoundedUntilFormula const& pathFormula = checkTask.getFormula(); + STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); STORM_LOG_THROW(pathFormula.getLeftSubformula().isTrueFormula(), storm::exceptions::NotImplementedException, "Only bounded properties of the form 'true U[t1, t2] phi' are currently supported."); STORM_LOG_THROW(this->getModel().isClosed(), storm::exceptions::InvalidPropertyException, "Unable to compute time-bounded reachability probabilities in non-closed Markov automaton."); std::unique_ptr rightResultPointer = this->check(pathFormula.getRightSubformula()); ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); - std::vector result = storm::modelchecker::helper::SparseMarkovAutomatonCslHelper::computeBoundedUntilProbabilities(optimalityType.get(), this->getModel().getTransitionMatrix(), this->getModel().getExitRates(), this->getModel().getMarkovianStates(), rightResult.getTruthValuesVector(), pathFormula.getIntervalBounds(), *minMaxLinearEquationSolverFactory); + std::vector result = storm::modelchecker::helper::SparseMarkovAutomatonCslHelper::computeBoundedUntilProbabilities(checkTask.getOptimizationDirection(), this->getModel().getTransitionMatrix(), this->getModel().getExitRates(), this->getModel().getMarkovianStates(), rightResult.getTruthValuesVector(), pathFormula.getIntervalBounds(), *minMaxLinearEquationSolverFactory); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(result))); } template - std::unique_ptr SparseMarkovAutomatonCslModelChecker::computeUntilProbabilities(storm::logic::UntilFormula const& pathFormula, bool qualitative, boost::optional const& optimalityType) { - STORM_LOG_THROW(optimalityType, storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); + std::unique_ptr SparseMarkovAutomatonCslModelChecker::computeUntilProbabilities(CheckTask const& checkTask) { + storm::logic::UntilFormula const& pathFormula = checkTask.getFormula(); + STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); std::unique_ptr leftResultPointer = this->check(pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(pathFormula.getRightSubformula()); ExplicitQualitativeCheckResult& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); ExplicitQualitativeCheckResult& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); - std::vector result = storm::modelchecker::helper::SparseMarkovAutomatonCslHelper::computeUntilProbabilities(optimalityType.get(), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), qualitative, *minMaxLinearEquationSolverFactory); + std::vector result = storm::modelchecker::helper::SparseMarkovAutomatonCslHelper::computeUntilProbabilities(checkTask.getOptimizationDirection(), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), checkTask.isQualitativeSet(), *minMaxLinearEquationSolverFactory); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(result))); } template - std::unique_ptr SparseMarkovAutomatonCslModelChecker::computeReachabilityRewards(storm::logic::ReachabilityRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName, bool qualitative, boost::optional const& optimalityType) { - STORM_LOG_THROW(optimalityType, storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); + std::unique_ptr SparseMarkovAutomatonCslModelChecker::computeReachabilityRewards(CheckTask const& checkTask) { + storm::logic::ReachabilityRewardFormula const& rewardPathFormula = checkTask.getFormula(); + STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); STORM_LOG_THROW(this->getModel().isClosed(), storm::exceptions::InvalidPropertyException, "Unable to compute reachability rewards in non-closed Markov automaton."); std::unique_ptr subResultPointer = this->check(rewardPathFormula.getSubformula()); ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); - std::vector result = storm::modelchecker::helper::SparseMarkovAutomatonCslHelper::computeReachabilityRewards(optimalityType.get(), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), this->getModel().getExitRates(), this->getModel().getMarkovianStates(), rewardModelName ? this->getModel().getRewardModel(rewardModelName.get()) : this->getModel().getRewardModel(""), subResult.getTruthValuesVector(), qualitative, *minMaxLinearEquationSolverFactory); + std::vector result = storm::modelchecker::helper::SparseMarkovAutomatonCslHelper::computeReachabilityRewards(checkTask.getOptimizationDirection(), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), this->getModel().getExitRates(), this->getModel().getMarkovianStates(), checkTask.isRewardModelSet() ? this->getModel().getRewardModel(checkTask.getRewardModel()) : this->getModel().getRewardModel(""), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), *minMaxLinearEquationSolverFactory); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(result))); } template - std::unique_ptr SparseMarkovAutomatonCslModelChecker::computeLongRunAverageProbabilities(storm::logic::StateFormula const& stateFormula, bool qualitative, boost::optional const& optimalityType) { - STORM_LOG_THROW(optimalityType, storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); + std::unique_ptr SparseMarkovAutomatonCslModelChecker::computeLongRunAverageProbabilities(CheckTask const& checkTask) { + storm::logic::StateFormula const& stateFormula = checkTask.getFormula(); + STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); STORM_LOG_THROW(this->getModel().isClosed(), storm::exceptions::InvalidPropertyException, "Unable to compute long-run average in non-closed Markov automaton."); std::unique_ptr subResultPointer = this->check(stateFormula); ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); - std::vector result = storm::modelchecker::helper::SparseMarkovAutomatonCslHelper::computeLongRunAverageProbabilities(optimalityType.get(), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), this->getModel().getExitRates(), this->getModel().getMarkovianStates(), subResult.getTruthValuesVector(), qualitative, *minMaxLinearEquationSolverFactory); + std::vector result = storm::modelchecker::helper::SparseMarkovAutomatonCslHelper::computeLongRunAverageProbabilities(checkTask.getOptimizationDirection(), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), this->getModel().getExitRates(), this->getModel().getMarkovianStates(), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), *minMaxLinearEquationSolverFactory); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(result))); } template - std::unique_ptr SparseMarkovAutomatonCslModelChecker::computeExpectedTimes(storm::logic::EventuallyFormula const& eventuallyFormula, bool qualitative, boost::optional const& optimalityType) { - STORM_LOG_THROW(optimalityType, storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); + std::unique_ptr SparseMarkovAutomatonCslModelChecker::computeExpectedTimes(CheckTask const& checkTask) { + storm::logic::EventuallyFormula const& eventuallyFormula = checkTask.getFormula(); + STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); STORM_LOG_THROW(this->getModel().isClosed(), storm::exceptions::InvalidPropertyException, "Unable to compute expected times in non-closed Markov automaton."); std::unique_ptr subResultPointer = this->check(eventuallyFormula.getSubformula()); ExplicitQualitativeCheckResult& subResult = subResultPointer->asExplicitQualitativeCheckResult(); - std::vector result = storm::modelchecker::helper::SparseMarkovAutomatonCslHelper::computeExpectedTimes(optimalityType.get(), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), this->getModel().getExitRates(), this->getModel().getMarkovianStates(), subResult.getTruthValuesVector(), qualitative, *minMaxLinearEquationSolverFactory); + std::vector result = storm::modelchecker::helper::SparseMarkovAutomatonCslHelper::computeExpectedTimes(checkTask.getOptimizationDirection(), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), this->getModel().getExitRates(), this->getModel().getMarkovianStates(), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), *minMaxLinearEquationSolverFactory); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(result))); } diff --git a/src/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.h b/src/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.h index a3d0fc1fb..e57f9d3e5 100644 --- a/src/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.h +++ b/src/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.h @@ -20,12 +20,12 @@ namespace storm { explicit SparseMarkovAutomatonCslModelChecker(SparseMarkovAutomatonModelType const& model); // The implemented methods of the AbstractModelChecker interface. - virtual bool canHandle(storm::logic::Formula const& formula) const override; - virtual std::unique_ptr computeBoundedUntilProbabilities(storm::logic::BoundedUntilFormula const& pathFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeUntilProbabilities(storm::logic::UntilFormula const& pathFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeReachabilityRewards(storm::logic::ReachabilityRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName = boost::optional(), bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeLongRunAverageProbabilities(storm::logic::StateFormula const& stateFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeExpectedTimes(storm::logic::EventuallyFormula const& eventuallyFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; + virtual bool canHandle(CheckTask const& checkTask) const override; + virtual std::unique_ptr computeBoundedUntilProbabilities(CheckTask const& checkTask) override; + virtual std::unique_ptr computeUntilProbabilities(CheckTask const& checkTask) override; + virtual std::unique_ptr computeReachabilityRewards(CheckTask const& checkTask) override; + virtual std::unique_ptr computeLongRunAverageProbabilities(CheckTask const& checkTask) override; + virtual std::unique_ptr computeExpectedTimes(CheckTask const& checkTask) override; private: // An object that is used for retrieving solvers for systems of linear equations that are the result of nondeterministic choices. diff --git a/src/modelchecker/prctl/HybridDtmcPrctlModelChecker.cpp b/src/modelchecker/prctl/HybridDtmcPrctlModelChecker.cpp index 6614bf8e7..c5e2225aa 100644 --- a/src/modelchecker/prctl/HybridDtmcPrctlModelChecker.cpp +++ b/src/modelchecker/prctl/HybridDtmcPrctlModelChecker.cpp @@ -34,35 +34,40 @@ namespace storm { } template - bool HybridDtmcPrctlModelChecker::canHandle(storm::logic::Formula const& formula) const { + bool HybridDtmcPrctlModelChecker::canHandle(CheckTask const& checkTask) const { + storm::logic::Formula const& formula = checkTask.getFormula(); return formula.isPctlStateFormula() || formula.isPctlPathFormula() || formula.isRewardPathFormula(); } template - std::unique_ptr HybridDtmcPrctlModelChecker::computeUntilProbabilities(storm::logic::UntilFormula const& pathFormula, bool qualitative, boost::optional const& optimalityType) { + std::unique_ptr HybridDtmcPrctlModelChecker::computeUntilProbabilities(CheckTask const& checkTask) { + storm::logic::UntilFormula const& pathFormula = checkTask.getFormula(); std::unique_ptr leftResultPointer = this->check(pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(pathFormula.getRightSubformula()); SymbolicQualitativeCheckResult const& leftResult = leftResultPointer->asSymbolicQualitativeCheckResult(); SymbolicQualitativeCheckResult const& rightResult = rightResultPointer->asSymbolicQualitativeCheckResult(); - return storm::modelchecker::helper::HybridDtmcPrctlHelper::computeUntilProbabilities(this->getModel(), this->getModel().getTransitionMatrix(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), qualitative, *this->linearEquationSolverFactory); + return storm::modelchecker::helper::HybridDtmcPrctlHelper::computeUntilProbabilities(this->getModel(), this->getModel().getTransitionMatrix(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), checkTask.isQualitativeSet(), *this->linearEquationSolverFactory); } template - std::unique_ptr HybridDtmcPrctlModelChecker::computeGloballyProbabilities(storm::logic::GloballyFormula const& pathFormula, bool qualitative, boost::optional const& optimalityType) { + std::unique_ptr HybridDtmcPrctlModelChecker::computeGloballyProbabilities(CheckTask const& checkTask) { + storm::logic::GloballyFormula const& pathFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(pathFormula.getSubformula()); SymbolicQualitativeCheckResult const& subResult = subResultPointer->asSymbolicQualitativeCheckResult(); - return storm::modelchecker::helper::HybridDtmcPrctlHelper::computeGloballyProbabilities(this->getModel(), this->getModel().getTransitionMatrix(), subResult.getTruthValuesVector(), qualitative, *this->linearEquationSolverFactory); + return storm::modelchecker::helper::HybridDtmcPrctlHelper::computeGloballyProbabilities(this->getModel(), this->getModel().getTransitionMatrix(), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), *this->linearEquationSolverFactory); } template - std::unique_ptr HybridDtmcPrctlModelChecker::computeNextProbabilities(storm::logic::NextFormula const& pathFormula, bool qualitative, boost::optional const& optimalityType) { + std::unique_ptr HybridDtmcPrctlModelChecker::computeNextProbabilities(CheckTask const& checkTask) { + storm::logic::NextFormula const& pathFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(pathFormula.getSubformula()); SymbolicQualitativeCheckResult const& subResult = subResultPointer->asSymbolicQualitativeCheckResult(); return storm::modelchecker::helper::HybridDtmcPrctlHelper::computeNextProbabilities(this->getModel(), this->getModel().getTransitionMatrix(), subResult.getTruthValuesVector()); } template - std::unique_ptr HybridDtmcPrctlModelChecker::computeBoundedUntilProbabilities(storm::logic::BoundedUntilFormula const& pathFormula, bool qualitative, boost::optional const& optimalityType) { + std::unique_ptr HybridDtmcPrctlModelChecker::computeBoundedUntilProbabilities(CheckTask const& checkTask) { + storm::logic::BoundedUntilFormula const& pathFormula = checkTask.getFormula(); STORM_LOG_THROW(pathFormula.hasDiscreteTimeBound(), storm::exceptions::InvalidArgumentException, "Formula needs to have a discrete time bound."); std::unique_ptr leftResultPointer = this->check(pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(pathFormula.getRightSubformula()); @@ -72,22 +77,25 @@ namespace storm { } template - std::unique_ptr HybridDtmcPrctlModelChecker::computeCumulativeRewards(storm::logic::CumulativeRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName, bool qualitative, boost::optional const& optimalityType) { + std::unique_ptr HybridDtmcPrctlModelChecker::computeCumulativeRewards(CheckTask const& checkTask) { + storm::logic::CumulativeRewardFormula const& rewardPathFormula = checkTask.getFormula(); STORM_LOG_THROW(rewardPathFormula.hasDiscreteTimeBound(), storm::exceptions::InvalidArgumentException, "Formula needs to have a discrete time bound."); - return storm::modelchecker::helper::HybridDtmcPrctlHelper::computeCumulativeRewards(this->getModel(), this->getModel().getTransitionMatrix(), rewardModelName ? this->getModel().getRewardModel(rewardModelName.get()) : this->getModel().getRewardModel(""), rewardPathFormula.getDiscreteTimeBound(), *this->linearEquationSolverFactory); + return storm::modelchecker::helper::HybridDtmcPrctlHelper::computeCumulativeRewards(this->getModel(), this->getModel().getTransitionMatrix(), checkTask.isRewardModelSet() ? this->getModel().getRewardModel(checkTask.getRewardModel()) : this->getModel().getRewardModel(""), rewardPathFormula.getDiscreteTimeBound(), *this->linearEquationSolverFactory); } template - std::unique_ptr HybridDtmcPrctlModelChecker::computeInstantaneousRewards(storm::logic::InstantaneousRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName, bool qualitative, boost::optional const& optimalityType) { + std::unique_ptr HybridDtmcPrctlModelChecker::computeInstantaneousRewards(CheckTask const& checkTask) { + storm::logic::InstantaneousRewardFormula const& rewardPathFormula = checkTask.getFormula(); STORM_LOG_THROW(rewardPathFormula.hasDiscreteTimeBound(), storm::exceptions::InvalidArgumentException, "Formula needs to have a discrete time bound."); - return storm::modelchecker::helper::HybridDtmcPrctlHelper::computeInstantaneousRewards(this->getModel(), this->getModel().getTransitionMatrix(), rewardModelName ? this->getModel().getRewardModel(rewardModelName.get()) : this->getModel().getRewardModel(""), rewardPathFormula.getDiscreteTimeBound(), *this->linearEquationSolverFactory); + return storm::modelchecker::helper::HybridDtmcPrctlHelper::computeInstantaneousRewards(this->getModel(), this->getModel().getTransitionMatrix(), checkTask.isRewardModelSet() ? this->getModel().getRewardModel(checkTask.getRewardModel()) : this->getModel().getRewardModel(""), rewardPathFormula.getDiscreteTimeBound(), *this->linearEquationSolverFactory); } template - std::unique_ptr HybridDtmcPrctlModelChecker::computeReachabilityRewards(storm::logic::ReachabilityRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName, bool qualitative, boost::optional const& optimalityType) { + std::unique_ptr HybridDtmcPrctlModelChecker::computeReachabilityRewards(CheckTask const& checkTask) { + storm::logic::ReachabilityRewardFormula const& rewardPathFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(rewardPathFormula.getSubformula()); SymbolicQualitativeCheckResult const& subResult = subResultPointer->asSymbolicQualitativeCheckResult(); - return storm::modelchecker::helper::HybridDtmcPrctlHelper::computeReachabilityRewards(this->getModel(), this->getModel().getTransitionMatrix(), rewardModelName ? this->getModel().getRewardModel(rewardModelName.get()) : this->getModel().getRewardModel(""), subResult.getTruthValuesVector(), qualitative, *this->linearEquationSolverFactory); + return storm::modelchecker::helper::HybridDtmcPrctlHelper::computeReachabilityRewards(this->getModel(), this->getModel().getTransitionMatrix(), checkTask.isRewardModelSet() ? this->getModel().getRewardModel(checkTask.getRewardModel()) : this->getModel().getRewardModel(""), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), *this->linearEquationSolverFactory); } template @@ -96,7 +104,8 @@ namespace storm { } template - std::unique_ptr HybridDtmcPrctlModelChecker::computeLongRunAverageProbabilities(storm::logic::StateFormula const& stateFormula, bool qualitative, boost::optional const& optimalityType) { + std::unique_ptr HybridDtmcPrctlModelChecker::computeLongRunAverageProbabilities(CheckTask const& checkTask) { + storm::logic::StateFormula const& stateFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(stateFormula); SymbolicQualitativeCheckResult const& subResult = subResultPointer->asSymbolicQualitativeCheckResult(); @@ -105,7 +114,7 @@ namespace storm { storm::storage::SparseMatrix explicitProbabilityMatrix = this->getModel().getTransitionMatrix().toMatrix(odd, odd); - std::vector result = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeLongRunAverageProbabilities(explicitProbabilityMatrix, subResult.getTruthValuesVector().toVector(odd), qualitative, *this->linearEquationSolverFactory); + std::vector result = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeLongRunAverageProbabilities(explicitProbabilityMatrix, subResult.getTruthValuesVector().toVector(odd), checkTask.isQualitativeSet(), *this->linearEquationSolverFactory); return std::unique_ptr(new HybridQuantitativeCheckResult(this->getModel().getReachableStates(), this->getModel().getManager().getBddZero(), this->getModel().getManager().template getAddZero(), this->getModel().getReachableStates(), std::move(odd), std::move(result))); } diff --git a/src/modelchecker/prctl/HybridDtmcPrctlModelChecker.h b/src/modelchecker/prctl/HybridDtmcPrctlModelChecker.h index 5d68a8785..4d64f6f17 100644 --- a/src/modelchecker/prctl/HybridDtmcPrctlModelChecker.h +++ b/src/modelchecker/prctl/HybridDtmcPrctlModelChecker.h @@ -17,15 +17,15 @@ namespace storm { explicit HybridDtmcPrctlModelChecker(storm::models::symbolic::Dtmc const& model, std::unique_ptr>&& linearEquationSolverFactory); // The implemented methods of the AbstractModelChecker interface. - virtual bool canHandle(storm::logic::Formula const& formula) const override; - virtual std::unique_ptr computeBoundedUntilProbabilities(storm::logic::BoundedUntilFormula const& pathFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeNextProbabilities(storm::logic::NextFormula const& pathFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeUntilProbabilities(storm::logic::UntilFormula const& pathFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeGloballyProbabilities(storm::logic::GloballyFormula const& pathFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeCumulativeRewards(storm::logic::CumulativeRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName = boost::optional(), bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeInstantaneousRewards(storm::logic::InstantaneousRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName = boost::optional(), bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeReachabilityRewards(storm::logic::ReachabilityRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName = boost::optional(), bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeLongRunAverageProbabilities(storm::logic::StateFormula const& stateFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; + virtual bool canHandle(CheckTask const& checkTask) const override; + virtual std::unique_ptr computeBoundedUntilProbabilities(CheckTask const& checkTask) override; + virtual std::unique_ptr computeNextProbabilities(CheckTask const& checkTask) override; + virtual std::unique_ptr computeUntilProbabilities(CheckTask const& checkTask) override; + virtual std::unique_ptr computeGloballyProbabilities(CheckTask const& checkTask) override; + virtual std::unique_ptr computeCumulativeRewards(CheckTask const& checkTask) override; + virtual std::unique_ptr computeInstantaneousRewards(CheckTask const& checkTask) override; + virtual std::unique_ptr computeReachabilityRewards(CheckTask const& checkTask) override; + virtual std::unique_ptr computeLongRunAverageProbabilities(CheckTask const& checkTask) override; protected: storm::models::symbolic::Dtmc const& getModel() const override; diff --git a/src/modelchecker/prctl/HybridMdpPrctlModelChecker.cpp b/src/modelchecker/prctl/HybridMdpPrctlModelChecker.cpp index f7b44adcb..6dfd0d83b 100644 --- a/src/modelchecker/prctl/HybridMdpPrctlModelChecker.cpp +++ b/src/modelchecker/prctl/HybridMdpPrctlModelChecker.cpp @@ -28,12 +28,13 @@ namespace storm { } template - bool HybridMdpPrctlModelChecker::canHandle(storm::logic::Formula const& formula) const { + bool HybridMdpPrctlModelChecker::canHandle(CheckTask const& checkTask) const { + storm::logic::Formula const& formula = checkTask.getFormula(); if (formula.isPctlStateFormula() || formula.isPctlPathFormula() || formula.isRewardPathFormula()) { return true; } if (formula.isProbabilityOperatorFormula()) { - return this->canHandle(formula.asProbabilityOperatorFormula().getSubformula()); + return this->canHandle(checkTask.replaceFormula(formula.asProbabilityOperatorFormula().getSubformula())); } if (formula.isGloballyFormula()) { return true; @@ -42,62 +43,69 @@ namespace storm { } template - std::unique_ptr HybridMdpPrctlModelChecker::computeUntilProbabilities(storm::logic::UntilFormula const& pathFormula, bool qualitative, boost::optional const& optimalityType) { - STORM_LOG_THROW(optimalityType, storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); + std::unique_ptr HybridMdpPrctlModelChecker::computeUntilProbabilities(CheckTask const& checkTask) { + storm::logic::UntilFormula const& pathFormula = checkTask.getFormula(); + STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); std::unique_ptr leftResultPointer = this->check(pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(pathFormula.getRightSubformula()); SymbolicQualitativeCheckResult const& leftResult = leftResultPointer->asSymbolicQualitativeCheckResult(); SymbolicQualitativeCheckResult const& rightResult = rightResultPointer->asSymbolicQualitativeCheckResult(); - return storm::modelchecker::helper::HybridMdpPrctlHelper::computeUntilProbabilities(optimalityType.get(), this->getModel(), this->getModel().getTransitionMatrix(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), qualitative, *this->linearEquationSolverFactory); + return storm::modelchecker::helper::HybridMdpPrctlHelper::computeUntilProbabilities(checkTask.getOptimizationDirection(), this->getModel(), this->getModel().getTransitionMatrix(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), checkTask.isQualitativeSet(), *this->linearEquationSolverFactory); } template - std::unique_ptr HybridMdpPrctlModelChecker::computeGloballyProbabilities(storm::logic::GloballyFormula const& pathFormula, bool qualitative, boost::optional const& optimalityType) { - STORM_LOG_THROW(optimalityType, storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); + std::unique_ptr HybridMdpPrctlModelChecker::computeGloballyProbabilities(CheckTask const& checkTask) { + storm::logic::GloballyFormula const& pathFormula = checkTask.getFormula(); + STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); std::unique_ptr subResultPointer = this->check(pathFormula.getSubformula()); SymbolicQualitativeCheckResult const& subResult = subResultPointer->asSymbolicQualitativeCheckResult(); - return storm::modelchecker::helper::HybridMdpPrctlHelper::computeGloballyProbabilities(optimalityType.get(), this->getModel(), this->getModel().getTransitionMatrix(), subResult.getTruthValuesVector(), qualitative, *this->linearEquationSolverFactory); + return storm::modelchecker::helper::HybridMdpPrctlHelper::computeGloballyProbabilities(checkTask.getOptimizationDirection(), this->getModel(), this->getModel().getTransitionMatrix(), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), *this->linearEquationSolverFactory); } template - std::unique_ptr HybridMdpPrctlModelChecker::computeNextProbabilities(storm::logic::NextFormula const& pathFormula, bool qualitative, boost::optional const& optimalityType) { - STORM_LOG_THROW(optimalityType, storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); + std::unique_ptr HybridMdpPrctlModelChecker::computeNextProbabilities(CheckTask const& checkTask) { + storm::logic::NextFormula const& pathFormula = checkTask.getFormula(); + STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); std::unique_ptr subResultPointer = this->check(pathFormula.getSubformula()); SymbolicQualitativeCheckResult const& subResult = subResultPointer->asSymbolicQualitativeCheckResult(); - return storm::modelchecker::helper::HybridMdpPrctlHelper::computeNextProbabilities(optimalityType.get(), this->getModel(), this->getModel().getTransitionMatrix(), subResult.getTruthValuesVector()); + return storm::modelchecker::helper::HybridMdpPrctlHelper::computeNextProbabilities(checkTask.getOptimizationDirection(), this->getModel(), this->getModel().getTransitionMatrix(), subResult.getTruthValuesVector()); } template - std::unique_ptr HybridMdpPrctlModelChecker::computeBoundedUntilProbabilities(storm::logic::BoundedUntilFormula const& pathFormula, bool qualitative, boost::optional const& optimalityType) { - STORM_LOG_THROW(optimalityType, storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); + std::unique_ptr HybridMdpPrctlModelChecker::computeBoundedUntilProbabilities(CheckTask const& checkTask) { + storm::logic::BoundedUntilFormula const& pathFormula = checkTask.getFormula(); + STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); STORM_LOG_THROW(pathFormula.hasDiscreteTimeBound(), storm::exceptions::InvalidPropertyException, "Formula needs to have a discrete time bound."); std::unique_ptr leftResultPointer = this->check(pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(pathFormula.getRightSubformula()); SymbolicQualitativeCheckResult const& leftResult = leftResultPointer->asSymbolicQualitativeCheckResult(); SymbolicQualitativeCheckResult const& rightResult = rightResultPointer->asSymbolicQualitativeCheckResult(); - return storm::modelchecker::helper::HybridMdpPrctlHelper::computeBoundedUntilProbabilities(optimalityType.get(), this->getModel(), this->getModel().getTransitionMatrix(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), pathFormula.getDiscreteTimeBound(), *this->linearEquationSolverFactory); + return storm::modelchecker::helper::HybridMdpPrctlHelper::computeBoundedUntilProbabilities(checkTask.getOptimizationDirection(), this->getModel(), this->getModel().getTransitionMatrix(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), pathFormula.getDiscreteTimeBound(), *this->linearEquationSolverFactory); } template - std::unique_ptr HybridMdpPrctlModelChecker::computeCumulativeRewards(storm::logic::CumulativeRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName, bool qualitative, boost::optional const& optimalityType) { - STORM_LOG_THROW(optimalityType, storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); + std::unique_ptr HybridMdpPrctlModelChecker::computeCumulativeRewards(CheckTask const& checkTask) { + storm::logic::CumulativeRewardFormula const& rewardPathFormula = checkTask.getFormula(); + STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); STORM_LOG_THROW(rewardPathFormula.hasDiscreteTimeBound(), storm::exceptions::InvalidPropertyException, "Formula needs to have a discrete time bound."); - return storm::modelchecker::helper::HybridMdpPrctlHelper::computeCumulativeRewards(optimalityType.get(), this->getModel(), this->getModel().getTransitionMatrix(), rewardModelName ? this->getModel().getRewardModel(rewardModelName.get()) : this->getModel().getRewardModel(""), rewardPathFormula.getDiscreteTimeBound(), *this->linearEquationSolverFactory); + return storm::modelchecker::helper::HybridMdpPrctlHelper::computeCumulativeRewards(checkTask.getOptimizationDirection(), this->getModel(), this->getModel().getTransitionMatrix(), checkTask.isRewardModelSet() ? this->getModel().getRewardModel(checkTask.getRewardModel()) : this->getModel().getRewardModel(""), rewardPathFormula.getDiscreteTimeBound(), *this->linearEquationSolverFactory); } template - std::unique_ptr HybridMdpPrctlModelChecker::computeInstantaneousRewards(storm::logic::InstantaneousRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName, bool qualitative, boost::optional const& optimalityType) { - STORM_LOG_THROW(optimalityType, storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); + std::unique_ptr HybridMdpPrctlModelChecker::computeInstantaneousRewards(CheckTask const& checkTask) { + storm::logic::InstantaneousRewardFormula const& rewardPathFormula = checkTask.getFormula(); + STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); STORM_LOG_THROW(rewardPathFormula.hasDiscreteTimeBound(), storm::exceptions::InvalidPropertyException, "Formula needs to have a discrete time bound."); - return storm::modelchecker::helper::HybridMdpPrctlHelper::computeInstantaneousRewards(optimalityType.get(), this->getModel(), this->getModel().getTransitionMatrix(), rewardModelName ? this->getModel().getRewardModel(rewardModelName.get()) : this->getModel().getRewardModel(""), rewardPathFormula.getDiscreteTimeBound(), *this->linearEquationSolverFactory); + return storm::modelchecker::helper::HybridMdpPrctlHelper::computeInstantaneousRewards(checkTask.getOptimizationDirection(), this->getModel(), this->getModel().getTransitionMatrix(), checkTask.isRewardModelSet() ? this->getModel().getRewardModel(checkTask.getRewardModel()) : this->getModel().getRewardModel(""), rewardPathFormula.getDiscreteTimeBound(), *this->linearEquationSolverFactory); } template - std::unique_ptr HybridMdpPrctlModelChecker::computeReachabilityRewards(storm::logic::ReachabilityRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName, bool qualitative, boost::optional const& optimalityType) { - STORM_LOG_THROW(optimalityType, storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); + std::unique_ptr HybridMdpPrctlModelChecker::computeReachabilityRewards(CheckTask const& checkTask) { + storm::logic::ReachabilityRewardFormula const& rewardPathFormula = checkTask.getFormula(); + STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); std::unique_ptr subResultPointer = this->check(rewardPathFormula.getSubformula()); SymbolicQualitativeCheckResult const& subResult = subResultPointer->asSymbolicQualitativeCheckResult(); - return storm::modelchecker::helper::HybridMdpPrctlHelper::computeReachabilityRewards(optimalityType.get(), this->getModel(), this->getModel().getTransitionMatrix(), rewardModelName ? this->getModel().getRewardModel(rewardModelName.get()) : this->getModel().getRewardModel(""), subResult.getTruthValuesVector(), qualitative, *this->linearEquationSolverFactory); + return storm::modelchecker::helper::HybridMdpPrctlHelper::computeReachabilityRewards(checkTask.getOptimizationDirection(), this->getModel(), this->getModel().getTransitionMatrix(), checkTask.isRewardModelSet() ? this->getModel().getRewardModel(checkTask.getRewardModel()) : this->getModel().getRewardModel(""), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), *this->linearEquationSolverFactory); } template diff --git a/src/modelchecker/prctl/HybridMdpPrctlModelChecker.h b/src/modelchecker/prctl/HybridMdpPrctlModelChecker.h index 4cd1d6e27..78612a378 100644 --- a/src/modelchecker/prctl/HybridMdpPrctlModelChecker.h +++ b/src/modelchecker/prctl/HybridMdpPrctlModelChecker.h @@ -24,14 +24,14 @@ namespace storm { explicit HybridMdpPrctlModelChecker(storm::models::symbolic::Mdp const& model, std::unique_ptr>&& linearEquationSolverFactory); // The implemented methods of the AbstractModelChecker interface. - virtual bool canHandle(storm::logic::Formula const& formula) const override; - virtual std::unique_ptr computeBoundedUntilProbabilities(storm::logic::BoundedUntilFormula const& pathFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeNextProbabilities(storm::logic::NextFormula const& pathFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeUntilProbabilities(storm::logic::UntilFormula const& pathFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeGloballyProbabilities(storm::logic::GloballyFormula const& pathFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeCumulativeRewards(storm::logic::CumulativeRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName = boost::optional(), bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeInstantaneousRewards(storm::logic::InstantaneousRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName = boost::optional(), bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeReachabilityRewards(storm::logic::ReachabilityRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName = boost::optional(), bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; + virtual bool canHandle(CheckTask const& checkTask) const override; + virtual std::unique_ptr computeBoundedUntilProbabilities(CheckTask const& checkTask) override; + virtual std::unique_ptr computeNextProbabilities(CheckTask const& checkTask) override; + virtual std::unique_ptr computeUntilProbabilities(CheckTask const& checkTask) override; + virtual std::unique_ptr computeGloballyProbabilities(CheckTask const& checkTask) override; + virtual std::unique_ptr computeCumulativeRewards(CheckTask const& checkTask) override; + virtual std::unique_ptr computeInstantaneousRewards(CheckTask const& checkTask) override; + virtual std::unique_ptr computeReachabilityRewards(CheckTask const& checkTask) override; protected: storm::models::symbolic::Mdp const& getModel() const override; diff --git a/src/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp b/src/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp index 5103fc3a0..d4bb73950 100644 --- a/src/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp +++ b/src/modelchecker/prctl/SparseDtmcPrctlModelChecker.cpp @@ -32,7 +32,8 @@ namespace storm { } template - bool SparseDtmcPrctlModelChecker::canHandle(storm::logic::Formula const& formula) const { + bool SparseDtmcPrctlModelChecker::canHandle(CheckTask const& checkTask) const { + storm::logic::Formula const& formula = checkTask.getFormula(); if (formula.isPctlStateFormula() || formula.isPctlPathFormula() || formula.isRewardPathFormula()) { return true; } @@ -40,7 +41,7 @@ namespace storm { return true; } if (formula.isProbabilityOperatorFormula()) { - return this->canHandle(formula.asProbabilityOperatorFormula().getSubformula()); + return this->canHandle(checkTask.replaceFormula(formula.asProbabilityOperatorFormula().getSubformula())); } if (formula.isConditionalPathFormula()) { storm::logic::ConditionalPathFormula const& conditionalPathFormula = formula.asConditionalPathFormula(); @@ -52,7 +53,8 @@ namespace storm { } template - std::unique_ptr SparseDtmcPrctlModelChecker::computeBoundedUntilProbabilities(storm::logic::BoundedUntilFormula const& pathFormula, bool qualitative, boost::optional const& optimalityType) { + std::unique_ptr SparseDtmcPrctlModelChecker::computeBoundedUntilProbabilities(CheckTask const& checkTask) { + storm::logic::BoundedUntilFormula const& pathFormula = checkTask.getFormula(); STORM_LOG_THROW(pathFormula.hasDiscreteTimeBound(), storm::exceptions::InvalidPropertyException, "Formula needs to have a discrete time bound."); std::unique_ptr leftResultPointer = this->check(pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(pathFormula.getRightSubformula()); @@ -64,7 +66,8 @@ namespace storm { } template - std::unique_ptr SparseDtmcPrctlModelChecker::computeNextProbabilities(storm::logic::NextFormula const& pathFormula, bool qualitative, boost::optional const& optimalityType) { + std::unique_ptr SparseDtmcPrctlModelChecker::computeNextProbabilities(CheckTask const& checkTask) { + storm::logic::NextFormula const& pathFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(pathFormula.getSubformula()); ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeNextProbabilities(this->getModel().getTransitionMatrix(), subResult.getTruthValuesVector(), *linearEquationSolverFactory); @@ -72,55 +75,62 @@ namespace storm { } template - std::unique_ptr SparseDtmcPrctlModelChecker::computeUntilProbabilities(storm::logic::UntilFormula const& pathFormula, bool qualitative, boost::optional const& optimalityType) { + std::unique_ptr SparseDtmcPrctlModelChecker::computeUntilProbabilities(CheckTask const& checkTask) { + storm::logic::UntilFormula const& pathFormula = checkTask.getFormula(); std::unique_ptr leftResultPointer = this->check(pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(pathFormula.getRightSubformula()); ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); - std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeUntilProbabilities(this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), qualitative, *linearEquationSolverFactory); + std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeUntilProbabilities(this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), checkTask.isQualitativeSet(), *linearEquationSolverFactory); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); } template - std::unique_ptr SparseDtmcPrctlModelChecker::computeGloballyProbabilities(storm::logic::GloballyFormula const& pathFormula, bool qualitative, boost::optional const& optimalityType) { + std::unique_ptr SparseDtmcPrctlModelChecker::computeGloballyProbabilities(CheckTask const& checkTask) { + storm::logic::GloballyFormula const& pathFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(pathFormula.getSubformula()); ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); - std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeGloballyProbabilities(this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), subResult.getTruthValuesVector(), qualitative, *linearEquationSolverFactory); + std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeGloballyProbabilities(this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), *linearEquationSolverFactory); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); } template - std::unique_ptr SparseDtmcPrctlModelChecker::computeCumulativeRewards(storm::logic::CumulativeRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName, bool qualitative, boost::optional const& optimalityType) { + std::unique_ptr SparseDtmcPrctlModelChecker::computeCumulativeRewards(CheckTask const& checkTask) { + storm::logic::CumulativeRewardFormula const& rewardPathFormula = checkTask.getFormula(); STORM_LOG_THROW(rewardPathFormula.hasDiscreteTimeBound(), storm::exceptions::InvalidPropertyException, "Formula needs to have a discrete time bound."); - std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeCumulativeRewards(this->getModel().getTransitionMatrix(), rewardModelName ? this->getModel().getRewardModel(rewardModelName.get()) : this->getModel().getRewardModel(""), rewardPathFormula.getDiscreteTimeBound(), *linearEquationSolverFactory); + std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeCumulativeRewards(this->getModel().getTransitionMatrix(), checkTask.isRewardModelSet() ? this->getModel().getRewardModel(checkTask.getRewardModel()) : this->getModel().getRewardModel(""), rewardPathFormula.getDiscreteTimeBound(), *linearEquationSolverFactory); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); } template - std::unique_ptr SparseDtmcPrctlModelChecker::computeInstantaneousRewards(storm::logic::InstantaneousRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName, bool qualitative, boost::optional const& optimalityType) { + std::unique_ptr SparseDtmcPrctlModelChecker::computeInstantaneousRewards(CheckTask const& checkTask) { + storm::logic::InstantaneousRewardFormula const& rewardPathFormula = checkTask.getFormula(); STORM_LOG_THROW(rewardPathFormula.hasDiscreteTimeBound(), storm::exceptions::InvalidPropertyException, "Formula needs to have a discrete time bound."); - std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeInstantaneousRewards(this->getModel().getTransitionMatrix(), rewardModelName ? this->getModel().getRewardModel(rewardModelName.get()) : this->getModel().getRewardModel(""), rewardPathFormula.getDiscreteTimeBound(), *linearEquationSolverFactory); + std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeInstantaneousRewards(this->getModel().getTransitionMatrix(), checkTask.isRewardModelSet() ? this->getModel().getRewardModel(checkTask.getRewardModel()) : this->getModel().getRewardModel(""), rewardPathFormula.getDiscreteTimeBound(), *linearEquationSolverFactory); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); } template - std::unique_ptr SparseDtmcPrctlModelChecker::computeReachabilityRewards(storm::logic::ReachabilityRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName, bool qualitative, boost::optional const& optimalityType) { + std::unique_ptr SparseDtmcPrctlModelChecker::computeReachabilityRewards(CheckTask const& checkTask) { + storm::logic::ReachabilityRewardFormula const& rewardPathFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(rewardPathFormula.getSubformula()); ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); - std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeReachabilityRewards(this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), rewardModelName ? this->getModel().getRewardModel(rewardModelName.get()) : this->getModel().getRewardModel(""), subResult.getTruthValuesVector(), qualitative, *linearEquationSolverFactory); + std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeReachabilityRewards(this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), checkTask.isRewardModelSet() ? this->getModel().getRewardModel(checkTask.getRewardModel()) : this->getModel().getRewardModel(""), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), *linearEquationSolverFactory); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); } template - std::unique_ptr SparseDtmcPrctlModelChecker::computeLongRunAverageProbabilities(storm::logic::StateFormula const& stateFormula, bool qualitative, boost::optional const& optimalityType) { + std::unique_ptr SparseDtmcPrctlModelChecker::computeLongRunAverageProbabilities(CheckTask const& checkTask) { + storm::logic::StateFormula const& stateFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(stateFormula); ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); - std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeLongRunAverageProbabilities(this->getModel().getTransitionMatrix(), subResult.getTruthValuesVector(), nullptr, qualitative, *linearEquationSolverFactory); + std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeLongRunAverageProbabilities(this->getModel().getTransitionMatrix(), subResult.getTruthValuesVector(), nullptr, checkTask.isQualitativeSet(), *linearEquationSolverFactory); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); } template - std::unique_ptr SparseDtmcPrctlModelChecker::computeConditionalProbabilities(storm::logic::ConditionalPathFormula const& pathFormula, bool qualitative , boost::optional const& optimalityType) { + std::unique_ptr SparseDtmcPrctlModelChecker::computeConditionalProbabilities(CheckTask const& checkTask) { + storm::logic::ConditionalPathFormula const& pathFormula = checkTask.getFormula(); STORM_LOG_THROW(pathFormula.getLeftSubformula().isEventuallyFormula(), storm::exceptions::InvalidPropertyException, "Illegal conditional probability formula."); STORM_LOG_THROW(pathFormula.getRightSubformula().isEventuallyFormula(), storm::exceptions::InvalidPropertyException, "Illegal conditional probability formula."); @@ -129,7 +139,7 @@ namespace storm { ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); - std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeConditionalProbabilities(this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), qualitative, *linearEquationSolverFactory); + std::vector numericResult = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeConditionalProbabilities(this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), checkTask.isQualitativeSet(), *linearEquationSolverFactory); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); } diff --git a/src/modelchecker/prctl/SparseDtmcPrctlModelChecker.h b/src/modelchecker/prctl/SparseDtmcPrctlModelChecker.h index 384130263..77217a3ac 100644 --- a/src/modelchecker/prctl/SparseDtmcPrctlModelChecker.h +++ b/src/modelchecker/prctl/SparseDtmcPrctlModelChecker.h @@ -19,16 +19,16 @@ namespace storm { explicit SparseDtmcPrctlModelChecker(SparseDtmcModelType const& model, std::unique_ptr>&& linearEquationSolverFactory); // The implemented methods of the AbstractModelChecker interface. - virtual bool canHandle(storm::logic::Formula const& formula) const override; - virtual std::unique_ptr computeBoundedUntilProbabilities(storm::logic::BoundedUntilFormula const& pathFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeNextProbabilities(storm::logic::NextFormula const& pathFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeUntilProbabilities(storm::logic::UntilFormula const& pathFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeGloballyProbabilities(storm::logic::GloballyFormula const& pathFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeConditionalProbabilities(storm::logic::ConditionalPathFormula const& pathFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeCumulativeRewards(storm::logic::CumulativeRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName = boost::optional(), bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeInstantaneousRewards(storm::logic::InstantaneousRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName = boost::optional(), bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeReachabilityRewards(storm::logic::ReachabilityRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName = boost::optional(), bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeLongRunAverageProbabilities(storm::logic::StateFormula const& stateFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; + virtual bool canHandle(CheckTask const& checkTask) const override; + virtual std::unique_ptr computeBoundedUntilProbabilities(CheckTask const& checkTask) override; + virtual std::unique_ptr computeNextProbabilities(CheckTask const& checkTask) override; + virtual std::unique_ptr computeUntilProbabilities(CheckTask const& checkTask) override; + virtual std::unique_ptr computeGloballyProbabilities(CheckTask const& checkTask) override; + virtual std::unique_ptr computeConditionalProbabilities(CheckTask const& checkTask) override; + virtual std::unique_ptr computeCumulativeRewards(CheckTask const& checkTask) override; + virtual std::unique_ptr computeInstantaneousRewards(CheckTask const& checkTask) override; + virtual std::unique_ptr computeReachabilityRewards(CheckTask const& checkTask) override; + virtual std::unique_ptr computeLongRunAverageProbabilities(CheckTask const& checkTask) override; private: // An object that is used for retrieving linear equation solvers. diff --git a/src/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp b/src/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp index eabe827f3..eb4025551 100644 --- a/src/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp +++ b/src/modelchecker/prctl/SparseMdpPrctlModelChecker.cpp @@ -37,12 +37,13 @@ namespace storm { } template - bool SparseMdpPrctlModelChecker::canHandle(storm::logic::Formula const& formula) const { + bool SparseMdpPrctlModelChecker::canHandle(CheckTask const& checkTask) const { + storm::logic::Formula const& formula = checkTask.getFormula(); if (formula.isPctlStateFormula() || formula.isPctlPathFormula() || formula.isRewardPathFormula()) { return true; } if (formula.isProbabilityOperatorFormula()) { - return this->canHandle(formula.asProbabilityOperatorFormula().getSubformula()); + return this->canHandle(checkTask.replaceFormula(formula.asProbabilityOperatorFormula().getSubformula())); } if (formula.isGloballyFormula()) { return true; @@ -57,48 +58,53 @@ namespace storm { } template - std::unique_ptr SparseMdpPrctlModelChecker::computeBoundedUntilProbabilities(storm::logic::BoundedUntilFormula const& pathFormula, bool qualitative, boost::optional const& optimalityType) { - STORM_LOG_THROW(optimalityType, storm::exceptions::InvalidArgumentException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); + std::unique_ptr SparseMdpPrctlModelChecker::computeBoundedUntilProbabilities(CheckTask const& checkTask) { + storm::logic::BoundedUntilFormula const& pathFormula = checkTask.getFormula(); + STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidArgumentException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); std::unique_ptr leftResultPointer = this->check(pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(pathFormula.getRightSubformula()); ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); - std::vector numericResult = storm::modelchecker::helper::SparseMdpPrctlHelper::computeBoundedUntilProbabilities(optimalityType.get(), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), pathFormula.getDiscreteTimeBound(), *minMaxLinearEquationSolverFactory); + std::vector numericResult = storm::modelchecker::helper::SparseMdpPrctlHelper::computeBoundedUntilProbabilities(checkTask.getOptimizationDirection(), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), pathFormula.getDiscreteTimeBound(), *minMaxLinearEquationSolverFactory); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); } template - std::unique_ptr SparseMdpPrctlModelChecker::computeNextProbabilities(storm::logic::NextFormula const& pathFormula, bool qualitative, boost::optional const& optimalityType) { - STORM_LOG_THROW(optimalityType, storm::exceptions::InvalidArgumentException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); + std::unique_ptr SparseMdpPrctlModelChecker::computeNextProbabilities(CheckTask const& checkTask) { + storm::logic::NextFormula const& pathFormula = checkTask.getFormula(); + STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidArgumentException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); std::unique_ptr subResultPointer = this->check(pathFormula.getSubformula()); ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); - std::vector numericResult = storm::modelchecker::helper::SparseMdpPrctlHelper::computeNextProbabilities(optimalityType.get(), this->getModel().getTransitionMatrix(), subResult.getTruthValuesVector(), *minMaxLinearEquationSolverFactory); + std::vector numericResult = storm::modelchecker::helper::SparseMdpPrctlHelper::computeNextProbabilities(checkTask.getOptimizationDirection(), this->getModel().getTransitionMatrix(), subResult.getTruthValuesVector(), *minMaxLinearEquationSolverFactory); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); } template - std::unique_ptr SparseMdpPrctlModelChecker::computeUntilProbabilities(storm::logic::UntilFormula const& pathFormula, bool qualitative, boost::optional const& optimalityType) { - STORM_LOG_THROW(optimalityType, storm::exceptions::InvalidArgumentException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); + std::unique_ptr SparseMdpPrctlModelChecker::computeUntilProbabilities(CheckTask const& checkTask) { + storm::logic::UntilFormula const& pathFormula = checkTask.getFormula(); + STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidArgumentException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); std::unique_ptr leftResultPointer = this->check(pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(pathFormula.getRightSubformula()); ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); - auto ret = storm::modelchecker::helper::SparseMdpPrctlHelper::computeUntilProbabilities(optimalityType.get(), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), qualitative, false, *minMaxLinearEquationSolverFactory); + auto ret = storm::modelchecker::helper::SparseMdpPrctlHelper::computeUntilProbabilities(checkTask.getOptimizationDirection(), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), checkTask.isQualitativeSet(), false, *minMaxLinearEquationSolverFactory); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(ret.result))); } template - std::unique_ptr SparseMdpPrctlModelChecker::computeGloballyProbabilities(storm::logic::GloballyFormula const& pathFormula, bool qualitative, boost::optional const& optimalityType) { - STORM_LOG_THROW(optimalityType, storm::exceptions::InvalidArgumentException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); + std::unique_ptr SparseMdpPrctlModelChecker::computeGloballyProbabilities(CheckTask const& checkTask) { + storm::logic::GloballyFormula const& pathFormula = checkTask.getFormula(); + STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidArgumentException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); std::unique_ptr subResultPointer = this->check(pathFormula.getSubformula()); ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); - auto ret = storm::modelchecker::helper::SparseMdpPrctlHelper::computeGloballyProbabilities(optimalityType.get(), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), subResult.getTruthValuesVector(), qualitative, *minMaxLinearEquationSolverFactory); + auto ret = storm::modelchecker::helper::SparseMdpPrctlHelper::computeGloballyProbabilities(checkTask.getOptimizationDirection(), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), *minMaxLinearEquationSolverFactory); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(ret))); } template - std::unique_ptr SparseMdpPrctlModelChecker::computeConditionalProbabilities(storm::logic::ConditionalPathFormula const& pathFormula, bool qualitative, boost::optional const& optimalityType) { - STORM_LOG_THROW(optimalityType, storm::exceptions::InvalidArgumentException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); + std::unique_ptr SparseMdpPrctlModelChecker::computeConditionalProbabilities(CheckTask const& checkTask) { + storm::logic::ConditionalPathFormula const& pathFormula = checkTask.getFormula(); + STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidArgumentException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); STORM_LOG_THROW(this->getModel().getInitialStates().getNumberOfSetBits() == 1, storm::exceptions::InvalidPropertyException, "Cannot compute conditional probabilities on MDPs with more than one initial state."); STORM_LOG_THROW(pathFormula.getLeftSubformula().isEventuallyFormula(), storm::exceptions::InvalidPropertyException, "Illegal conditional probability formula."); STORM_LOG_THROW(pathFormula.getRightSubformula().isEventuallyFormula(), storm::exceptions::InvalidPropertyException, "Illegal conditional probability formula."); @@ -108,60 +114,44 @@ namespace storm { ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); - return storm::modelchecker::helper::SparseMdpPrctlHelper::computeConditionalProbabilities(optimalityType.get(), *this->getModel().getInitialStates().begin(), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), qualitative, *minMaxLinearEquationSolverFactory); + return storm::modelchecker::helper::SparseMdpPrctlHelper::computeConditionalProbabilities(checkTask.getOptimizationDirection(), *this->getModel().getInitialStates().begin(), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), checkTask.isQualitativeSet(), *minMaxLinearEquationSolverFactory); } template - std::unique_ptr SparseMdpPrctlModelChecker::computeUntilProbabilitiesForInitialStates(storm::logic::UntilFormula const& pathFormula, bool qualitative, boost::optional const& optimalityType, boost::optional> const& bound) { - STORM_LOG_THROW(optimalityType, storm::exceptions::InvalidArgumentException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); - std::unique_ptr leftResultPointer = this->check(pathFormula.getLeftSubformula()); - std::unique_ptr rightResultPointer = this->check(pathFormula.getRightSubformula()); - ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult(); - ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); - if(qualitative | !bound) { - // For qualitative checks, or if the , we use the standard approach. - auto ret = storm::modelchecker::helper::SparseMdpPrctlHelper::computeUntilProbabilities(optimalityType.get(), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), qualitative, false, *minMaxLinearEquationSolverFactory); - return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(ret.result))); - } else { - // With a given bound, we only iterate until we pass the bound. - storm::solver::BoundedGoal boundedGoal(optimalityType.get(), bound.get(), this->getModel().getInitialStates() ); - auto ret = storm::modelchecker::helper::SparseMdpPrctlHelper::computeUntilProbabilities(boundedGoal, this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), qualitative, false, *minMaxLinearEquationSolverFactory); - return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(ret.result))); - } - - } - - template - std::unique_ptr SparseMdpPrctlModelChecker::computeCumulativeRewards(storm::logic::CumulativeRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName, bool qualitative, boost::optional const& optimalityType) { - STORM_LOG_THROW(optimalityType, storm::exceptions::InvalidArgumentException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); + std::unique_ptr SparseMdpPrctlModelChecker::computeCumulativeRewards(CheckTask const& checkTask) { + storm::logic::CumulativeRewardFormula const& rewardPathFormula = checkTask.getFormula(); + STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidArgumentException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); STORM_LOG_THROW(rewardPathFormula.hasDiscreteTimeBound(), storm::exceptions::InvalidArgumentException, "Formula needs to have a discrete time bound."); - std::vector numericResult = storm::modelchecker::helper::SparseMdpPrctlHelper::computeCumulativeRewards(optimalityType.get(), this->getModel().getTransitionMatrix(), rewardModelName ? this->getModel().getRewardModel(rewardModelName.get()) : this->getModel().getRewardModel(""), rewardPathFormula.getDiscreteTimeBound(), *minMaxLinearEquationSolverFactory); + std::vector numericResult = storm::modelchecker::helper::SparseMdpPrctlHelper::computeCumulativeRewards(checkTask.getOptimizationDirection(), this->getModel().getTransitionMatrix(), checkTask.isRewardModelSet() ? this->getModel().getRewardModel(checkTask.getRewardModel()) : this->getModel().getRewardModel(""), rewardPathFormula.getDiscreteTimeBound(), *minMaxLinearEquationSolverFactory); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); } template - std::unique_ptr SparseMdpPrctlModelChecker::computeInstantaneousRewards(storm::logic::InstantaneousRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName, bool qualitative, boost::optional const& optimalityType) { - STORM_LOG_THROW(optimalityType, storm::exceptions::InvalidArgumentException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); + std::unique_ptr SparseMdpPrctlModelChecker::computeInstantaneousRewards(CheckTask const& checkTask) { + storm::logic::InstantaneousRewardFormula const& rewardPathFormula = checkTask.getFormula(); + STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidArgumentException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); STORM_LOG_THROW(rewardPathFormula.hasDiscreteTimeBound(), storm::exceptions::InvalidArgumentException, "Formula needs to have a discrete time bound."); - std::vector numericResult = storm::modelchecker::helper::SparseMdpPrctlHelper::computeInstantaneousRewards(optimalityType.get(), this->getModel().getTransitionMatrix(), rewardModelName ? this->getModel().getRewardModel(rewardModelName.get()) : this->getModel().getRewardModel(""), rewardPathFormula.getDiscreteTimeBound(), *minMaxLinearEquationSolverFactory); + std::vector numericResult = storm::modelchecker::helper::SparseMdpPrctlHelper::computeInstantaneousRewards(checkTask.getOptimizationDirection(), this->getModel().getTransitionMatrix(), checkTask.isRewardModelSet() ? this->getModel().getRewardModel(checkTask.getRewardModel()) : this->getModel().getRewardModel(""), rewardPathFormula.getDiscreteTimeBound(), *minMaxLinearEquationSolverFactory); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); } template - std::unique_ptr SparseMdpPrctlModelChecker::computeReachabilityRewards(storm::logic::ReachabilityRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName, bool qualitative, boost::optional const& optimalityType) { - STORM_LOG_THROW(optimalityType, storm::exceptions::InvalidArgumentException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); + std::unique_ptr SparseMdpPrctlModelChecker::computeReachabilityRewards(CheckTask const& checkTask) { + storm::logic::ReachabilityRewardFormula const& rewardPathFormula = checkTask.getFormula(); + STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidArgumentException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); std::unique_ptr subResultPointer = this->check(rewardPathFormula.getSubformula()); ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); - std::vector numericResult = storm::modelchecker::helper::SparseMdpPrctlHelper::computeReachabilityRewards(optimalityType.get(), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), rewardModelName ? this->getModel().getRewardModel(rewardModelName.get()) : this->getModel().getRewardModel(""), subResult.getTruthValuesVector(), qualitative, *minMaxLinearEquationSolverFactory); + std::vector numericResult = storm::modelchecker::helper::SparseMdpPrctlHelper::computeReachabilityRewards(checkTask.getOptimizationDirection(), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), checkTask.isRewardModelSet() ? this->getModel().getRewardModel(checkTask.getRewardModel()) : this->getModel().getRewardModel(""), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), *minMaxLinearEquationSolverFactory); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); } template - std::unique_ptr SparseMdpPrctlModelChecker::computeLongRunAverageProbabilities(storm::logic::StateFormula const& stateFormula, bool qualitative, boost::optional const& optimalityType) { - STORM_LOG_THROW(optimalityType, storm::exceptions::InvalidArgumentException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); + std::unique_ptr SparseMdpPrctlModelChecker::computeLongRunAverageProbabilities(CheckTask const& checkTask) { + storm::logic::StateFormula const& stateFormula = checkTask.getFormula(); + STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidArgumentException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); std::unique_ptr subResultPointer = this->check(stateFormula); ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult(); - std::vector numericResult = storm::modelchecker::helper::SparseMdpPrctlHelper::computeLongRunAverageProbabilities(optimalityType.get(), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), subResult.getTruthValuesVector(), qualitative, *minMaxLinearEquationSolverFactory); + std::vector numericResult = storm::modelchecker::helper::SparseMdpPrctlHelper::computeLongRunAverageProbabilities(checkTask.getOptimizationDirection(), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), *minMaxLinearEquationSolverFactory); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); } diff --git a/src/modelchecker/prctl/SparseMdpPrctlModelChecker.h b/src/modelchecker/prctl/SparseMdpPrctlModelChecker.h index d36bdcec1..340b5f33a 100644 --- a/src/modelchecker/prctl/SparseMdpPrctlModelChecker.h +++ b/src/modelchecker/prctl/SparseMdpPrctlModelChecker.h @@ -8,16 +8,6 @@ #include "src/solver/MinMaxLinearEquationSolver.h" namespace storm { - namespace counterexamples { - template - class SMTMinimalCommandSetGenerator; - - template - class MILPMinimalLabelSetGenerator; - } - - - namespace modelchecker { template class SparseMdpPrctlModelChecker : public SparsePropositionalModelChecker { @@ -25,24 +15,20 @@ namespace storm { typedef typename SparseMdpModelType::ValueType ValueType; typedef typename SparseMdpModelType::RewardModelType RewardModelType; - friend class storm::counterexamples::SMTMinimalCommandSetGenerator; - friend class storm::counterexamples::MILPMinimalLabelSetGenerator; - explicit SparseMdpPrctlModelChecker(SparseMdpModelType const& model); explicit SparseMdpPrctlModelChecker(SparseMdpModelType const& model, std::unique_ptr>&& MinMaxLinearEquationSolverFactory); // The implemented methods of the AbstractModelChecker interface. - virtual bool canHandle(storm::logic::Formula const& formula) const override; - virtual std::unique_ptr computeBoundedUntilProbabilities(storm::logic::BoundedUntilFormula const& pathFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeNextProbabilities(storm::logic::NextFormula const& pathFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeUntilProbabilities(storm::logic::UntilFormula const& pathFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeGloballyProbabilities(storm::logic::GloballyFormula const& pathFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeConditionalProbabilities(storm::logic::ConditionalPathFormula const& pathFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeUntilProbabilitiesForInitialStates(storm::logic::UntilFormula const& pathFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional(), boost::optional> const& bound =boost::optional>()); - virtual std::unique_ptr computeCumulativeRewards(storm::logic::CumulativeRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName = boost::optional(), bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeInstantaneousRewards(storm::logic::InstantaneousRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName = boost::optional(), bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeReachabilityRewards(storm::logic::ReachabilityRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName = boost::optional(), bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeLongRunAverageProbabilities(storm::logic::StateFormula const& stateFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; + virtual bool canHandle(CheckTask const& checkTask) const override; + virtual std::unique_ptr computeBoundedUntilProbabilities(CheckTask const& checkTask) override; + virtual std::unique_ptr computeNextProbabilities(CheckTask const& checkTask) override; + virtual std::unique_ptr computeUntilProbabilities(CheckTask const& checkTask) override; + virtual std::unique_ptr computeGloballyProbabilities(CheckTask const& checkTask) override; + virtual std::unique_ptr computeConditionalProbabilities(CheckTask const& checkTask) override; + virtual std::unique_ptr computeCumulativeRewards(CheckTask const& checkTask) override; + virtual std::unique_ptr computeInstantaneousRewards(CheckTask const& checkTask) override; + virtual std::unique_ptr computeReachabilityRewards(CheckTask const& checkTask) override; + virtual std::unique_ptr computeLongRunAverageProbabilities(CheckTask const& checkTask) override; private: // An object that is used for retrieving solvers for systems of linear equations that are the result of nondeterministic choices. diff --git a/src/modelchecker/prctl/SymbolicDtmcPrctlModelChecker.cpp b/src/modelchecker/prctl/SymbolicDtmcPrctlModelChecker.cpp index 920102389..0053d6b77 100644 --- a/src/modelchecker/prctl/SymbolicDtmcPrctlModelChecker.cpp +++ b/src/modelchecker/prctl/SymbolicDtmcPrctlModelChecker.cpp @@ -30,12 +30,13 @@ namespace storm { } template - bool SymbolicDtmcPrctlModelChecker::canHandle(storm::logic::Formula const& formula) const { + bool SymbolicDtmcPrctlModelChecker::canHandle(CheckTask const& checkTask) const { + storm::logic::Formula const& formula = checkTask.getFormula(); if (formula.isPctlStateFormula() || formula.isPctlPathFormula() || formula.isRewardPathFormula()) { return true; } if (formula.isProbabilityOperatorFormula()) { - return this->canHandle(formula.asProbabilityOperatorFormula().getSubformula()); + return this->canHandle(checkTask.replaceFormula(formula.asProbabilityOperatorFormula().getSubformula())); } if (formula.isGloballyFormula()) { return true; @@ -44,25 +45,28 @@ namespace storm { } template - std::unique_ptr SymbolicDtmcPrctlModelChecker::computeUntilProbabilities(storm::logic::UntilFormula const& pathFormula, bool qualitative, boost::optional const& optimalityType) { + std::unique_ptr SymbolicDtmcPrctlModelChecker::computeUntilProbabilities(CheckTask const& checkTask) { + storm::logic::UntilFormula const& pathFormula = checkTask.getFormula(); std::unique_ptr leftResultPointer = this->check(pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(pathFormula.getRightSubformula()); SymbolicQualitativeCheckResult const& leftResult = leftResultPointer->asSymbolicQualitativeCheckResult(); SymbolicQualitativeCheckResult const& rightResult = rightResultPointer->asSymbolicQualitativeCheckResult(); - storm::dd::Add numericResult = storm::modelchecker::helper::SymbolicDtmcPrctlHelper::computeUntilProbabilities(this->getModel(), this->getModel().getTransitionMatrix(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), qualitative, *this->linearEquationSolverFactory); + storm::dd::Add numericResult = storm::modelchecker::helper::SymbolicDtmcPrctlHelper::computeUntilProbabilities(this->getModel(), this->getModel().getTransitionMatrix(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), checkTask.isQualitativeSet(), *this->linearEquationSolverFactory); return std::unique_ptr>(new SymbolicQuantitativeCheckResult(this->getModel().getReachableStates(), numericResult)); } template - std::unique_ptr SymbolicDtmcPrctlModelChecker::computeGloballyProbabilities(storm::logic::GloballyFormula const& pathFormula, bool qualitative, boost::optional const& optimalityType) { + std::unique_ptr SymbolicDtmcPrctlModelChecker::computeGloballyProbabilities(CheckTask const& checkTask) { + storm::logic::GloballyFormula const& pathFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(pathFormula.getSubformula()); SymbolicQualitativeCheckResult const& subResult = subResultPointer->asSymbolicQualitativeCheckResult(); - storm::dd::Add numericResult = storm::modelchecker::helper::SymbolicDtmcPrctlHelper::computeGloballyProbabilities(this->getModel(), this->getModel().getTransitionMatrix(), subResult.getTruthValuesVector(), qualitative, *this->linearEquationSolverFactory); + storm::dd::Add numericResult = storm::modelchecker::helper::SymbolicDtmcPrctlHelper::computeGloballyProbabilities(this->getModel(), this->getModel().getTransitionMatrix(), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), *this->linearEquationSolverFactory); return std::unique_ptr>(new SymbolicQuantitativeCheckResult(this->getModel().getReachableStates(), numericResult)); } template - std::unique_ptr SymbolicDtmcPrctlModelChecker::computeNextProbabilities(storm::logic::NextFormula const& pathFormula, bool qualitative, boost::optional const& optimalityType) { + std::unique_ptr SymbolicDtmcPrctlModelChecker::computeNextProbabilities(CheckTask const& checkTask) { + storm::logic::NextFormula const& pathFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(pathFormula.getSubformula()); SymbolicQualitativeCheckResult const& subResult = subResultPointer->asSymbolicQualitativeCheckResult(); storm::dd::Add numericResult = storm::modelchecker::helper::SymbolicDtmcPrctlHelper::computeNextProbabilities(this->getModel(), this->getModel().getTransitionMatrix(), subResult.getTruthValuesVector()); @@ -70,7 +74,8 @@ namespace storm { } template - std::unique_ptr SymbolicDtmcPrctlModelChecker::computeBoundedUntilProbabilities(storm::logic::BoundedUntilFormula const& pathFormula, bool qualitative, boost::optional const& optimalityType) { + std::unique_ptr SymbolicDtmcPrctlModelChecker::computeBoundedUntilProbabilities(CheckTask const& checkTask) { + storm::logic::BoundedUntilFormula const& pathFormula = checkTask.getFormula(); STORM_LOG_THROW(pathFormula.hasDiscreteTimeBound(), storm::exceptions::InvalidPropertyException, "Formula needs to have a discrete time bound."); std::unique_ptr leftResultPointer = this->check(pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(pathFormula.getRightSubformula()); @@ -81,24 +86,27 @@ namespace storm { } template - std::unique_ptr SymbolicDtmcPrctlModelChecker::computeCumulativeRewards(storm::logic::CumulativeRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName, bool qualitative, boost::optional const& optimalityType) { + std::unique_ptr SymbolicDtmcPrctlModelChecker::computeCumulativeRewards(CheckTask const& checkTask) { + storm::logic::CumulativeRewardFormula const& rewardPathFormula = checkTask.getFormula(); STORM_LOG_THROW(rewardPathFormula.hasDiscreteTimeBound(), storm::exceptions::InvalidPropertyException, "Formula needs to have a discrete time bound."); - storm::dd::Add numericResult = storm::modelchecker::helper::SymbolicDtmcPrctlHelper::computeCumulativeRewards(this->getModel(), this->getModel().getTransitionMatrix(), rewardModelName ? this->getModel().getRewardModel(rewardModelName.get()) : this->getModel().getRewardModel(""), rewardPathFormula.getDiscreteTimeBound(), *this->linearEquationSolverFactory); + storm::dd::Add numericResult = storm::modelchecker::helper::SymbolicDtmcPrctlHelper::computeCumulativeRewards(this->getModel(), this->getModel().getTransitionMatrix(), checkTask.isRewardModelSet() ? this->getModel().getRewardModel(checkTask.getRewardModel()) : this->getModel().getRewardModel(""), rewardPathFormula.getDiscreteTimeBound(), *this->linearEquationSolverFactory); return std::unique_ptr>(new SymbolicQuantitativeCheckResult(this->getModel().getReachableStates(), numericResult)); } template - std::unique_ptr SymbolicDtmcPrctlModelChecker::computeInstantaneousRewards(storm::logic::InstantaneousRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName, bool qualitative, boost::optional const& optimalityType) { + std::unique_ptr SymbolicDtmcPrctlModelChecker::computeInstantaneousRewards(CheckTask const& checkTask) { + storm::logic::InstantaneousRewardFormula const& rewardPathFormula = checkTask.getFormula(); STORM_LOG_THROW(rewardPathFormula.hasDiscreteTimeBound(), storm::exceptions::InvalidPropertyException, "Formula needs to have a discrete time bound."); - storm::dd::Add numericResult = storm::modelchecker::helper::SymbolicDtmcPrctlHelper::computeInstantaneousRewards(this->getModel(), this->getModel().getTransitionMatrix(), rewardModelName ? this->getModel().getRewardModel(rewardModelName.get()) : this->getModel().getRewardModel(""), rewardPathFormula.getDiscreteTimeBound(), *this->linearEquationSolverFactory); + storm::dd::Add numericResult = storm::modelchecker::helper::SymbolicDtmcPrctlHelper::computeInstantaneousRewards(this->getModel(), this->getModel().getTransitionMatrix(), checkTask.isRewardModelSet() ? this->getModel().getRewardModel(checkTask.getRewardModel()) : this->getModel().getRewardModel(""), rewardPathFormula.getDiscreteTimeBound(), *this->linearEquationSolverFactory); return std::unique_ptr>(new SymbolicQuantitativeCheckResult(this->getModel().getReachableStates(), numericResult)); } template - std::unique_ptr SymbolicDtmcPrctlModelChecker::computeReachabilityRewards(storm::logic::ReachabilityRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName, bool qualitative, boost::optional const& optimalityType) { + std::unique_ptr SymbolicDtmcPrctlModelChecker::computeReachabilityRewards(CheckTask const& checkTask) { + storm::logic::ReachabilityRewardFormula const& rewardPathFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(rewardPathFormula.getSubformula()); SymbolicQualitativeCheckResult const& subResult = subResultPointer->asSymbolicQualitativeCheckResult(); - storm::dd::Add numericResult = storm::modelchecker::helper::SymbolicDtmcPrctlHelper::computeReachabilityRewards(this->getModel(), this->getModel().getTransitionMatrix(), rewardModelName ? this->getModel().getRewardModel(rewardModelName.get()) : this->getModel().getRewardModel(""), subResult.getTruthValuesVector(), qualitative, *this->linearEquationSolverFactory); + storm::dd::Add numericResult = storm::modelchecker::helper::SymbolicDtmcPrctlHelper::computeReachabilityRewards(this->getModel(), this->getModel().getTransitionMatrix(), checkTask.isRewardModelSet() ? this->getModel().getRewardModel(checkTask.getRewardModel()) : this->getModel().getRewardModel(""), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), *this->linearEquationSolverFactory); return std::unique_ptr>(new SymbolicQuantitativeCheckResult(this->getModel().getReachableStates(), numericResult)); } diff --git a/src/modelchecker/prctl/SymbolicDtmcPrctlModelChecker.h b/src/modelchecker/prctl/SymbolicDtmcPrctlModelChecker.h index 8c8d4140d..a7968a56a 100644 --- a/src/modelchecker/prctl/SymbolicDtmcPrctlModelChecker.h +++ b/src/modelchecker/prctl/SymbolicDtmcPrctlModelChecker.h @@ -14,14 +14,14 @@ namespace storm { explicit SymbolicDtmcPrctlModelChecker(storm::models::symbolic::Dtmc const& model, std::unique_ptr>&& linearEquationSolverFactory); // The implemented methods of the AbstractModelChecker interface. - virtual bool canHandle(storm::logic::Formula const& formula) const override; - virtual std::unique_ptr computeBoundedUntilProbabilities(storm::logic::BoundedUntilFormula const& pathFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeNextProbabilities(storm::logic::NextFormula const& pathFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeUntilProbabilities(storm::logic::UntilFormula const& pathFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeGloballyProbabilities(storm::logic::GloballyFormula const& pathFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeCumulativeRewards(storm::logic::CumulativeRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName = boost::optional(), bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeInstantaneousRewards(storm::logic::InstantaneousRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName = boost::optional(), bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeReachabilityRewards(storm::logic::ReachabilityRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName = boost::optional(), bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; + virtual bool canHandle(CheckTask const& checkTask) const override; + virtual std::unique_ptr computeBoundedUntilProbabilities(CheckTask const& checkTask) override; + virtual std::unique_ptr computeNextProbabilities(CheckTask const& checkTask) override; + virtual std::unique_ptr computeUntilProbabilities(CheckTask const& checkTask) override; + virtual std::unique_ptr computeGloballyProbabilities(CheckTask const& checkTask) override; + virtual std::unique_ptr computeCumulativeRewards(CheckTask const& checkTask) override; + virtual std::unique_ptr computeInstantaneousRewards(CheckTask const& checkTask) override; + virtual std::unique_ptr computeReachabilityRewards(CheckTask const& checkTask) override; protected: storm::models::symbolic::Dtmc const& getModel() const override; diff --git a/src/modelchecker/prctl/SymbolicMdpPrctlModelChecker.cpp b/src/modelchecker/prctl/SymbolicMdpPrctlModelChecker.cpp index 296236f07..30891afdf 100644 --- a/src/modelchecker/prctl/SymbolicMdpPrctlModelChecker.cpp +++ b/src/modelchecker/prctl/SymbolicMdpPrctlModelChecker.cpp @@ -30,12 +30,13 @@ namespace storm { } template - bool SymbolicMdpPrctlModelChecker::canHandle(storm::logic::Formula const& formula) const { + bool SymbolicMdpPrctlModelChecker::canHandle(CheckTask const& checkTask) const { + storm::logic::Formula const& formula = checkTask.getFormula(); if (formula.isPctlStateFormula() || formula.isPctlPathFormula() || formula.isRewardPathFormula()) { return true; } if (formula.isProbabilityOperatorFormula()) { - return this->canHandle(formula.asProbabilityOperatorFormula().getSubformula()); + return this->canHandle(checkTask.replaceFormula(formula.asProbabilityOperatorFormula().getSubformula())); } if (formula.isGloballyFormula()) { return true; @@ -44,62 +45,69 @@ namespace storm { } template - std::unique_ptr SymbolicMdpPrctlModelChecker::computeUntilProbabilities(storm::logic::UntilFormula const& pathFormula, bool qualitative, boost::optional const& optimalityType) { - STORM_LOG_THROW(optimalityType, storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); + std::unique_ptr SymbolicMdpPrctlModelChecker::computeUntilProbabilities(CheckTask const& checkTask) { + storm::logic::UntilFormula const& pathFormula = checkTask.getFormula(); + STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); std::unique_ptr leftResultPointer = this->check(pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(pathFormula.getRightSubformula()); SymbolicQualitativeCheckResult const& leftResult = leftResultPointer->asSymbolicQualitativeCheckResult(); SymbolicQualitativeCheckResult const& rightResult = rightResultPointer->asSymbolicQualitativeCheckResult(); - return storm::modelchecker::helper::SymbolicMdpPrctlHelper::computeUntilProbabilities(optimalityType.get() == OptimizationDirection::Minimize, this->getModel(), this->getModel().getTransitionMatrix(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), qualitative, *this->linearEquationSolverFactory); + return storm::modelchecker::helper::SymbolicMdpPrctlHelper::computeUntilProbabilities(checkTask.getOptimizationDirection(), this->getModel(), this->getModel().getTransitionMatrix(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), checkTask.isQualitativeSet(), *this->linearEquationSolverFactory); } template - std::unique_ptr SymbolicMdpPrctlModelChecker::computeGloballyProbabilities(storm::logic::GloballyFormula const& pathFormula, bool qualitative, boost::optional const& optimalityType) { - STORM_LOG_THROW(optimalityType, storm::exceptions::InvalidArgumentException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); + std::unique_ptr SymbolicMdpPrctlModelChecker::computeGloballyProbabilities(CheckTask const& checkTask) { + storm::logic::GloballyFormula const& pathFormula = checkTask.getFormula(); + STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidArgumentException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); std::unique_ptr subResultPointer = this->check(pathFormula.getSubformula()); SymbolicQualitativeCheckResult const& subResult = subResultPointer->asSymbolicQualitativeCheckResult(); - return storm::modelchecker::helper::SymbolicMdpPrctlHelper::computeGloballyProbabilities(optimalityType.get() == OptimizationDirection::Minimize, this->getModel(), this->getModel().getTransitionMatrix(), subResult.getTruthValuesVector(), qualitative, *this->linearEquationSolverFactory); + return storm::modelchecker::helper::SymbolicMdpPrctlHelper::computeGloballyProbabilities(checkTask.getOptimizationDirection(), this->getModel(), this->getModel().getTransitionMatrix(), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), *this->linearEquationSolverFactory); } template - std::unique_ptr SymbolicMdpPrctlModelChecker::computeNextProbabilities(storm::logic::NextFormula const& pathFormula, bool qualitative, boost::optional const& optimalityType) { - STORM_LOG_THROW(optimalityType, storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); + std::unique_ptr SymbolicMdpPrctlModelChecker::computeNextProbabilities(CheckTask const& checkTask) { + storm::logic::NextFormula const& pathFormula = checkTask.getFormula(); + STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); std::unique_ptr subResultPointer = this->check(pathFormula.getSubformula()); SymbolicQualitativeCheckResult const& subResult = subResultPointer->asSymbolicQualitativeCheckResult(); - return storm::modelchecker::helper::SymbolicMdpPrctlHelper::computeNextProbabilities(optimalityType.get() == OptimizationDirection::Minimize, this->getModel(), this->getModel().getTransitionMatrix(), subResult.getTruthValuesVector()); + return storm::modelchecker::helper::SymbolicMdpPrctlHelper::computeNextProbabilities(checkTask.getOptimizationDirection(), this->getModel(), this->getModel().getTransitionMatrix(), subResult.getTruthValuesVector()); } template - std::unique_ptr SymbolicMdpPrctlModelChecker::computeBoundedUntilProbabilities(storm::logic::BoundedUntilFormula const& pathFormula, bool qualitative, boost::optional const& optimalityType) { - STORM_LOG_THROW(optimalityType, storm::exceptions::InvalidArgumentException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); + std::unique_ptr SymbolicMdpPrctlModelChecker::computeBoundedUntilProbabilities(CheckTask const& checkTask) { + storm::logic::BoundedUntilFormula const& pathFormula = checkTask.getFormula(); + STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidArgumentException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); STORM_LOG_THROW(pathFormula.hasDiscreteTimeBound(), storm::exceptions::InvalidPropertyException, "Formula needs to have a discrete time bound."); std::unique_ptr leftResultPointer = this->check(pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(pathFormula.getRightSubformula()); SymbolicQualitativeCheckResult const& leftResult = leftResultPointer->asSymbolicQualitativeCheckResult(); SymbolicQualitativeCheckResult const& rightResult = rightResultPointer->asSymbolicQualitativeCheckResult(); - return storm::modelchecker::helper::SymbolicMdpPrctlHelper::computeBoundedUntilProbabilities(optimalityType.get() == OptimizationDirection::Minimize, this->getModel(), this->getModel().getTransitionMatrix(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), pathFormula.getDiscreteTimeBound(), *this->linearEquationSolverFactory); + return storm::modelchecker::helper::SymbolicMdpPrctlHelper::computeBoundedUntilProbabilities(checkTask.getOptimizationDirection(), this->getModel(), this->getModel().getTransitionMatrix(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), pathFormula.getDiscreteTimeBound(), *this->linearEquationSolverFactory); } template - std::unique_ptr SymbolicMdpPrctlModelChecker::computeCumulativeRewards(storm::logic::CumulativeRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName, bool qualitative, boost::optional const& optimalityType) { - STORM_LOG_THROW(optimalityType, storm::exceptions::InvalidArgumentException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); + std::unique_ptr SymbolicMdpPrctlModelChecker::computeCumulativeRewards(CheckTask const& checkTask) { + storm::logic::CumulativeRewardFormula const& rewardPathFormula = checkTask.getFormula(); + STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidArgumentException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); STORM_LOG_THROW(rewardPathFormula.hasDiscreteTimeBound(), storm::exceptions::InvalidPropertyException, "Formula needs to have a discrete time bound."); - return storm::modelchecker::helper::SymbolicMdpPrctlHelper::computeCumulativeRewards(optimalityType.get() == OptimizationDirection::Minimize, this->getModel(), this->getModel().getTransitionMatrix(), rewardModelName ? this->getModel().getRewardModel(rewardModelName.get()) : this->getModel().getRewardModel(""), rewardPathFormula.getDiscreteTimeBound(), *this->linearEquationSolverFactory); + return storm::modelchecker::helper::SymbolicMdpPrctlHelper::computeCumulativeRewards(checkTask.getOptimizationDirection(), this->getModel(), this->getModel().getTransitionMatrix(), checkTask.isRewardModelSet() ? this->getModel().getRewardModel(checkTask.getRewardModel()) : this->getModel().getRewardModel(""), rewardPathFormula.getDiscreteTimeBound(), *this->linearEquationSolverFactory); } template - std::unique_ptr SymbolicMdpPrctlModelChecker::computeInstantaneousRewards(storm::logic::InstantaneousRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName, bool qualitative, boost::optional const& optimalityType) { - STORM_LOG_THROW(optimalityType, storm::exceptions::InvalidArgumentException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); + std::unique_ptr SymbolicMdpPrctlModelChecker::computeInstantaneousRewards(CheckTask const& checkTask) { + storm::logic::InstantaneousRewardFormula const& rewardPathFormula = checkTask.getFormula(); + STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidArgumentException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); STORM_LOG_THROW(rewardPathFormula.hasDiscreteTimeBound(), storm::exceptions::InvalidPropertyException, "Formula needs to have a discrete time bound."); - return storm::modelchecker::helper::SymbolicMdpPrctlHelper::computeInstantaneousRewards(optimalityType.get() == OptimizationDirection::Minimize, this->getModel(), this->getModel().getTransitionMatrix(), rewardModelName ? this->getModel().getRewardModel(rewardModelName.get()) : this->getModel().getRewardModel(""), rewardPathFormula.getDiscreteTimeBound(), *this->linearEquationSolverFactory); + return storm::modelchecker::helper::SymbolicMdpPrctlHelper::computeInstantaneousRewards(checkTask.getOptimizationDirection(), this->getModel(), this->getModel().getTransitionMatrix(), checkTask.isRewardModelSet() ? this->getModel().getRewardModel(checkTask.getRewardModel()) : this->getModel().getRewardModel(""), rewardPathFormula.getDiscreteTimeBound(), *this->linearEquationSolverFactory); } template - std::unique_ptr SymbolicMdpPrctlModelChecker::computeReachabilityRewards(storm::logic::ReachabilityRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName, bool qualitative, boost::optional const& optimalityType) { - STORM_LOG_THROW(optimalityType, storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); + std::unique_ptr SymbolicMdpPrctlModelChecker::computeReachabilityRewards(CheckTask const& checkTask) { + storm::logic::ReachabilityRewardFormula const& rewardPathFormula = checkTask.getFormula(); + STORM_LOG_THROW(checkTask.isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException, "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model."); std::unique_ptr subResultPointer = this->check(rewardPathFormula.getSubformula()); SymbolicQualitativeCheckResult const& subResult = subResultPointer->asSymbolicQualitativeCheckResult(); - return storm::modelchecker::helper::SymbolicMdpPrctlHelper::computeReachabilityRewards(optimalityType.get() == OptimizationDirection::Minimize, this->getModel(), this->getModel().getTransitionMatrix(), rewardModelName ? this->getModel().getRewardModel(rewardModelName.get()) : this->getModel().getRewardModel(""), subResult.getTruthValuesVector(), qualitative, *this->linearEquationSolverFactory); + return storm::modelchecker::helper::SymbolicMdpPrctlHelper::computeReachabilityRewards(checkTask.getOptimizationDirection(), this->getModel(), this->getModel().getTransitionMatrix(), checkTask.isRewardModelSet() ? this->getModel().getRewardModel(checkTask.getRewardModel()) : this->getModel().getRewardModel(""), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), *this->linearEquationSolverFactory); } template diff --git a/src/modelchecker/prctl/SymbolicMdpPrctlModelChecker.h b/src/modelchecker/prctl/SymbolicMdpPrctlModelChecker.h index e5160faa8..1baca69da 100644 --- a/src/modelchecker/prctl/SymbolicMdpPrctlModelChecker.h +++ b/src/modelchecker/prctl/SymbolicMdpPrctlModelChecker.h @@ -16,14 +16,14 @@ namespace storm { explicit SymbolicMdpPrctlModelChecker(storm::models::symbolic::Mdp const& model, std::unique_ptr>&& linearEquationSolverFactory); // The implemented methods of the AbstractModelChecker interface. - virtual bool canHandle(storm::logic::Formula const& formula) const override; - virtual std::unique_ptr computeBoundedUntilProbabilities(storm::logic::BoundedUntilFormula const& pathFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeNextProbabilities(storm::logic::NextFormula const& pathFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeUntilProbabilities(storm::logic::UntilFormula const& pathFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeGloballyProbabilities(storm::logic::GloballyFormula const& pathFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeCumulativeRewards(storm::logic::CumulativeRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName = boost::optional(), bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeInstantaneousRewards(storm::logic::InstantaneousRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName = boost::optional(), bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeReachabilityRewards(storm::logic::ReachabilityRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName = boost::optional(), bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; + virtual bool canHandle(CheckTask const& checkTask) const override; + virtual std::unique_ptr computeBoundedUntilProbabilities(CheckTask const& checkTask) override; + virtual std::unique_ptr computeNextProbabilities(CheckTask const& checkTask) override; + virtual std::unique_ptr computeUntilProbabilities(CheckTask const& checkTask) override; + virtual std::unique_ptr computeGloballyProbabilities(CheckTask const& checkTask) override; + virtual std::unique_ptr computeCumulativeRewards(CheckTask const& checkTask) override; + virtual std::unique_ptr computeInstantaneousRewards(CheckTask const& checkTask) override; + virtual std::unique_ptr computeReachabilityRewards(CheckTask const& checkTask) override; protected: storm::models::symbolic::Mdp const& getModel() const override; diff --git a/src/modelchecker/prctl/helper/SymbolicMdpPrctlHelper.cpp b/src/modelchecker/prctl/helper/SymbolicMdpPrctlHelper.cpp index 17705fdbb..52447c289 100644 --- a/src/modelchecker/prctl/helper/SymbolicMdpPrctlHelper.cpp +++ b/src/modelchecker/prctl/helper/SymbolicMdpPrctlHelper.cpp @@ -23,11 +23,11 @@ namespace storm { namespace helper { template - std::unique_ptr SymbolicMdpPrctlHelper::computeUntilProbabilities(bool minimize, storm::models::symbolic::NondeterministicModel const& model, storm::dd::Add const& transitionMatrix, storm::dd::Bdd const& phiStates, storm::dd::Bdd const& psiStates, bool qualitative, storm::utility::solver::SymbolicMinMaxLinearEquationSolverFactory const& linearEquationSolverFactory) { + std::unique_ptr SymbolicMdpPrctlHelper::computeUntilProbabilities(OptimizationDirection dir, storm::models::symbolic::NondeterministicModel const& model, storm::dd::Add const& transitionMatrix, storm::dd::Bdd const& phiStates, storm::dd::Bdd const& psiStates, bool qualitative, storm::utility::solver::SymbolicMinMaxLinearEquationSolverFactory const& linearEquationSolverFactory) { // We need to identify the states which have to be taken out of the matrix, i.e. all states that have // probability 0 and 1 of satisfying the until-formula. std::pair, storm::dd::Bdd> statesWithProbability01; - if (minimize) { + if (dir == OptimizationDirection::Minimize) { statesWithProbability01 = storm::utility::graph::performProb01Min(model, phiStates, psiStates); } else { statesWithProbability01 = storm::utility::graph::performProb01Max(model, phiStates, psiStates); @@ -66,7 +66,7 @@ namespace storm { // Now solve the resulting equation system. std::unique_ptr> solver = linearEquationSolverFactory.create(submatrix, maybeStates, model.getIllegalMask() && maybeStates, model.getRowVariables(), model.getColumnVariables(), model.getNondeterminismVariables(), model.getRowColumnMetaVariablePairs()); - storm::dd::Add result = solver->solveEquationSystem(minimize, model.getManager().template getAddZero(), subvector); + storm::dd::Add result = solver->solveEquationSystem(dir == OptimizationDirection::Minimize, model.getManager().template getAddZero(), subvector); return std::unique_ptr(new storm::modelchecker::SymbolicQuantitativeCheckResult(model.getReachableStates(), statesWithProbability01.second.template toAdd() + result)); } else { @@ -76,24 +76,24 @@ namespace storm { } template - std::unique_ptr SymbolicMdpPrctlHelper::computeGloballyProbabilities(bool minimize, storm::models::symbolic::NondeterministicModel const& model, storm::dd::Add const& transitionMatrix, storm::dd::Bdd const& psiStates, bool qualitative, storm::utility::solver::SymbolicMinMaxLinearEquationSolverFactory const& linearEquationSolverFactory) { - std::unique_ptr result = computeUntilProbabilities(!minimize, model, transitionMatrix, model.getReachableStates(), !psiStates && model.getReachableStates(), qualitative, linearEquationSolverFactory); + std::unique_ptr SymbolicMdpPrctlHelper::computeGloballyProbabilities(OptimizationDirection dir, storm::models::symbolic::NondeterministicModel const& model, storm::dd::Add const& transitionMatrix, storm::dd::Bdd const& psiStates, bool qualitative, storm::utility::solver::SymbolicMinMaxLinearEquationSolverFactory const& linearEquationSolverFactory) { + std::unique_ptr result = computeUntilProbabilities(dir == OptimizationDirection::Minimize ? OptimizationDirection::Maximize : OptimizationDirection::Minimize, model, transitionMatrix, model.getReachableStates(), !psiStates && model.getReachableStates(), qualitative, linearEquationSolverFactory); result->asQuantitativeCheckResult().oneMinus(); return result; } template - std::unique_ptr SymbolicMdpPrctlHelper::computeNextProbabilities(bool minimize, storm::models::symbolic::NondeterministicModel const& model, storm::dd::Add const& transitionMatrix, storm::dd::Bdd const& nextStates) { + std::unique_ptr SymbolicMdpPrctlHelper::computeNextProbabilities(OptimizationDirection dir, storm::models::symbolic::NondeterministicModel const& model, storm::dd::Add const& transitionMatrix, storm::dd::Bdd const& nextStates) { storm::dd::Add result = transitionMatrix * nextStates.swapVariables(model.getRowColumnMetaVariablePairs()).template toAdd(); return std::unique_ptr(new SymbolicQuantitativeCheckResult(model.getReachableStates(), result.sumAbstract(model.getColumnVariables()))); } template - std::unique_ptr SymbolicMdpPrctlHelper::computeBoundedUntilProbabilities(bool minimize, storm::models::symbolic::NondeterministicModel const& model, storm::dd::Add const& transitionMatrix, storm::dd::Bdd const& phiStates, storm::dd::Bdd const& psiStates, uint_fast64_t stepBound, storm::utility::solver::SymbolicMinMaxLinearEquationSolverFactory const& linearEquationSolverFactory) { + std::unique_ptr SymbolicMdpPrctlHelper::computeBoundedUntilProbabilities(OptimizationDirection dir, storm::models::symbolic::NondeterministicModel const& model, storm::dd::Add const& transitionMatrix, storm::dd::Bdd const& phiStates, storm::dd::Bdd const& psiStates, uint_fast64_t stepBound, storm::utility::solver::SymbolicMinMaxLinearEquationSolverFactory const& linearEquationSolverFactory) { // We need to identify the states which have to be taken out of the matrix, i.e. all states that have // probability 0 or 1 of satisfying the until-formula. storm::dd::Bdd statesWithProbabilityGreater0; - if (minimize) { + if (dir == OptimizationDirection::Minimize) { statesWithProbabilityGreater0 = storm::utility::graph::performProbGreater0A(model, transitionMatrix.notZero(), phiStates, psiStates); } else { statesWithProbabilityGreater0 = storm::utility::graph::performProbGreater0E(model, transitionMatrix.notZero(), phiStates, psiStates); @@ -118,7 +118,7 @@ namespace storm { submatrix *= maybeStatesAdd.swapVariables(model.getRowColumnMetaVariablePairs()); std::unique_ptr> solver = linearEquationSolverFactory.create(submatrix, maybeStates, model.getIllegalMask() && maybeStates, model.getRowVariables(), model.getColumnVariables(), model.getNondeterminismVariables(), model.getRowColumnMetaVariablePairs()); - storm::dd::Add result = solver->performMatrixVectorMultiplication(minimize, model.getManager().template getAddZero(), &subvector, stepBound); + storm::dd::Add result = solver->performMatrixVectorMultiplication(dir == OptimizationDirection::Minimize, model.getManager().template getAddZero(), &subvector, stepBound); return std::unique_ptr(new storm::modelchecker::SymbolicQuantitativeCheckResult(model.getReachableStates(), psiStates.template toAdd() + result)); } else { @@ -127,19 +127,19 @@ namespace storm { } template - std::unique_ptr SymbolicMdpPrctlHelper::computeInstantaneousRewards(bool minimize, storm::models::symbolic::NondeterministicModel const& model, storm::dd::Add const& transitionMatrix, RewardModelType const& rewardModel, uint_fast64_t stepBound, storm::utility::solver::SymbolicMinMaxLinearEquationSolverFactory const& linearEquationSolverFactory) { + std::unique_ptr SymbolicMdpPrctlHelper::computeInstantaneousRewards(OptimizationDirection dir, storm::models::symbolic::NondeterministicModel const& model, storm::dd::Add const& transitionMatrix, RewardModelType const& rewardModel, uint_fast64_t stepBound, storm::utility::solver::SymbolicMinMaxLinearEquationSolverFactory const& linearEquationSolverFactory) { // Only compute the result if the model has at least one reward this->getModel(). STORM_LOG_THROW(rewardModel.hasStateRewards(), storm::exceptions::InvalidPropertyException, "Missing reward model for formula. Skipping formula."); // Perform the matrix-vector multiplication. std::unique_ptr> solver = linearEquationSolverFactory.create(model.getTransitionMatrix(), model.getReachableStates(), model.getIllegalMask(), model.getRowVariables(), model.getColumnVariables(), model.getNondeterminismVariables(), model.getRowColumnMetaVariablePairs()); - storm::dd::Add result = solver->performMatrixVectorMultiplication(minimize, rewardModel.getStateRewardVector(), nullptr, stepBound); + storm::dd::Add result = solver->performMatrixVectorMultiplication(dir == OptimizationDirection::Minimize, rewardModel.getStateRewardVector(), nullptr, stepBound); return std::unique_ptr(new SymbolicQuantitativeCheckResult(model.getReachableStates(), result)); } template - std::unique_ptr SymbolicMdpPrctlHelper::computeCumulativeRewards(bool minimize, storm::models::symbolic::NondeterministicModel const& model, storm::dd::Add const& transitionMatrix, RewardModelType const& rewardModel, uint_fast64_t stepBound, storm::utility::solver::SymbolicMinMaxLinearEquationSolverFactory const& linearEquationSolverFactory) { + std::unique_ptr SymbolicMdpPrctlHelper::computeCumulativeRewards(OptimizationDirection dir, storm::models::symbolic::NondeterministicModel const& model, storm::dd::Add const& transitionMatrix, RewardModelType const& rewardModel, uint_fast64_t stepBound, storm::utility::solver::SymbolicMinMaxLinearEquationSolverFactory const& linearEquationSolverFactory) { // Only compute the result if the model has at least one reward this->getModel(). STORM_LOG_THROW(!rewardModel.empty(), storm::exceptions::InvalidPropertyException, "Missing reward model for formula. Skipping formula."); @@ -148,13 +148,13 @@ namespace storm { // Perform the matrix-vector multiplication. std::unique_ptr> solver = linearEquationSolverFactory.create(model.getTransitionMatrix(), model.getReachableStates(), model.getIllegalMask(), model.getRowVariables(), model.getColumnVariables(), model.getNondeterminismVariables(), model.getRowColumnMetaVariablePairs()); - storm::dd::Add result = solver->performMatrixVectorMultiplication(minimize, model.getManager().template getAddZero(), &totalRewardVector, stepBound); + storm::dd::Add result = solver->performMatrixVectorMultiplication(dir == OptimizationDirection::Minimize, model.getManager().template getAddZero(), &totalRewardVector, stepBound); return std::unique_ptr(new SymbolicQuantitativeCheckResult(model.getReachableStates(), result)); } template - std::unique_ptr SymbolicMdpPrctlHelper::computeReachabilityRewards(bool minimize, storm::models::symbolic::NondeterministicModel const& model, storm::dd::Add const& transitionMatrix, RewardModelType const& rewardModel, storm::dd::Bdd const& targetStates, bool qualitative, storm::utility::solver::SymbolicMinMaxLinearEquationSolverFactory const& linearEquationSolverFactory) { + std::unique_ptr SymbolicMdpPrctlHelper::computeReachabilityRewards(OptimizationDirection dir, storm::models::symbolic::NondeterministicModel const& model, storm::dd::Add const& transitionMatrix, RewardModelType const& rewardModel, storm::dd::Bdd const& targetStates, bool qualitative, storm::utility::solver::SymbolicMinMaxLinearEquationSolverFactory const& linearEquationSolverFactory) { // Only compute the result if there is at least one reward model. STORM_LOG_THROW(!rewardModel.empty(), storm::exceptions::InvalidPropertyException, "Missing reward model for formula. Skipping formula."); @@ -162,7 +162,7 @@ namespace storm { // Determine which states have a reward of infinity by definition. storm::dd::Bdd infinityStates; storm::dd::Bdd transitionMatrixBdd = transitionMatrix.notZero(); - if (minimize) { + if (dir == OptimizationDirection::Minimize) { infinityStates = storm::utility::graph::performProb1E(model, transitionMatrixBdd, model.getReachableStates(), targetStates, storm::utility::graph::performProbGreater0E(model, transitionMatrixBdd, model.getReachableStates(), targetStates)); } else { infinityStates = storm::utility::graph::performProb1A(model, transitionMatrixBdd, model.getReachableStates(), targetStates, storm::utility::graph::performProbGreater0A(model, transitionMatrixBdd, model.getReachableStates(), targetStates)); @@ -197,7 +197,7 @@ namespace storm { // Now solve the resulting equation system. std::unique_ptr> solver = linearEquationSolverFactory.create(submatrix, maybeStates, model.getIllegalMask() && maybeStates, model.getRowVariables(), model.getColumnVariables(), model.getNondeterminismVariables(), model.getRowColumnMetaVariablePairs()); - storm::dd::Add result = solver->solveEquationSystem(minimize, model.getManager().template getAddZero(), subvector); + storm::dd::Add result = solver->solveEquationSystem(dir == OptimizationDirection::Minimize, model.getManager().template getAddZero(), subvector); return std::unique_ptr(new storm::modelchecker::SymbolicQuantitativeCheckResult(model.getReachableStates(), infinityStates.ite(model.getManager().getConstant(storm::utility::infinity()), result))); } else { diff --git a/src/modelchecker/prctl/helper/SymbolicMdpPrctlHelper.h b/src/modelchecker/prctl/helper/SymbolicMdpPrctlHelper.h index 25b01d449..083840a00 100644 --- a/src/modelchecker/prctl/helper/SymbolicMdpPrctlHelper.h +++ b/src/modelchecker/prctl/helper/SymbolicMdpPrctlHelper.h @@ -7,6 +7,7 @@ #include "src/storage/dd/Bdd.h" #include "src/utility/solver.h" +#include "src/solver/SolveGoal.h" namespace storm { namespace modelchecker { @@ -20,19 +21,19 @@ namespace storm { public: typedef typename storm::models::symbolic::NondeterministicModel::RewardModelType RewardModelType; - static std::unique_ptr computeBoundedUntilProbabilities(bool minimize, storm::models::symbolic::NondeterministicModel const& model, storm::dd::Add const& transitionMatrix, storm::dd::Bdd const& phiStates, storm::dd::Bdd const& psiStates, uint_fast64_t stepBound, storm::utility::solver::SymbolicMinMaxLinearEquationSolverFactory const& linearEquationSolverFactory); + static std::unique_ptr computeBoundedUntilProbabilities(OptimizationDirection dir, storm::models::symbolic::NondeterministicModel const& model, storm::dd::Add const& transitionMatrix, storm::dd::Bdd const& phiStates, storm::dd::Bdd const& psiStates, uint_fast64_t stepBound, storm::utility::solver::SymbolicMinMaxLinearEquationSolverFactory const& linearEquationSolverFactory); - static std::unique_ptr computeNextProbabilities(bool minimize, storm::models::symbolic::NondeterministicModel const& model, storm::dd::Add const& transitionMatrix, storm::dd::Bdd const& nextStates); + static std::unique_ptr computeNextProbabilities(OptimizationDirection dir, storm::models::symbolic::NondeterministicModel const& model, storm::dd::Add const& transitionMatrix, storm::dd::Bdd const& nextStates); - static std::unique_ptr computeUntilProbabilities(bool minimize, storm::models::symbolic::NondeterministicModel const& model, storm::dd::Add const& transitionMatrix, storm::dd::Bdd const& phiStates, storm::dd::Bdd const& psiStates, bool qualitative, storm::utility::solver::SymbolicMinMaxLinearEquationSolverFactory const& linearEquationSolverFactory); + static std::unique_ptr computeUntilProbabilities(OptimizationDirection dir, storm::models::symbolic::NondeterministicModel const& model, storm::dd::Add const& transitionMatrix, storm::dd::Bdd const& phiStates, storm::dd::Bdd const& psiStates, bool qualitative, storm::utility::solver::SymbolicMinMaxLinearEquationSolverFactory const& linearEquationSolverFactory); - static std::unique_ptr computeGloballyProbabilities(bool minimize, storm::models::symbolic::NondeterministicModel const& model, storm::dd::Add const& transitionMatrix, storm::dd::Bdd const& psiStates, bool qualitative, storm::utility::solver::SymbolicMinMaxLinearEquationSolverFactory const& linearEquationSolverFactory); + static std::unique_ptr computeGloballyProbabilities(OptimizationDirection dir, storm::models::symbolic::NondeterministicModel const& model, storm::dd::Add const& transitionMatrix, storm::dd::Bdd const& psiStates, bool qualitative, storm::utility::solver::SymbolicMinMaxLinearEquationSolverFactory const& linearEquationSolverFactory); - static std::unique_ptr computeCumulativeRewards(bool minimize, storm::models::symbolic::NondeterministicModel const& model, storm::dd::Add const& transitionMatrix, RewardModelType const& rewardModel, uint_fast64_t stepBound, storm::utility::solver::SymbolicMinMaxLinearEquationSolverFactory const& linearEquationSolverFactory); + static std::unique_ptr computeCumulativeRewards(OptimizationDirection dir, storm::models::symbolic::NondeterministicModel const& model, storm::dd::Add const& transitionMatrix, RewardModelType const& rewardModel, uint_fast64_t stepBound, storm::utility::solver::SymbolicMinMaxLinearEquationSolverFactory const& linearEquationSolverFactory); - static std::unique_ptr computeInstantaneousRewards(bool minimize, storm::models::symbolic::NondeterministicModel const& model, storm::dd::Add const& transitionMatrix, RewardModelType const& rewardModel, uint_fast64_t stepBound, storm::utility::solver::SymbolicMinMaxLinearEquationSolverFactory const& linearEquationSolverFactory); + static std::unique_ptr computeInstantaneousRewards(OptimizationDirection dir, storm::models::symbolic::NondeterministicModel const& model, storm::dd::Add const& transitionMatrix, RewardModelType const& rewardModel, uint_fast64_t stepBound, storm::utility::solver::SymbolicMinMaxLinearEquationSolverFactory const& linearEquationSolverFactory); - static std::unique_ptr computeReachabilityRewards(bool minimize, storm::models::symbolic::NondeterministicModel const& model, storm::dd::Add const& transitionMatrix, RewardModelType const& rewardModel, storm::dd::Bdd const& targetStates, bool qualitative, storm::utility::solver::SymbolicMinMaxLinearEquationSolverFactory const& linearEquationSolverFactory); + static std::unique_ptr computeReachabilityRewards(OptimizationDirection dir, storm::models::symbolic::NondeterministicModel const& model, storm::dd::Add const& transitionMatrix, RewardModelType const& rewardModel, storm::dd::Bdd const& targetStates, bool qualitative, storm::utility::solver::SymbolicMinMaxLinearEquationSolverFactory const& linearEquationSolverFactory); }; } diff --git a/src/modelchecker/propositional/SparsePropositionalModelChecker.cpp b/src/modelchecker/propositional/SparsePropositionalModelChecker.cpp index b9384d9dc..f56843aef 100644 --- a/src/modelchecker/propositional/SparsePropositionalModelChecker.cpp +++ b/src/modelchecker/propositional/SparsePropositionalModelChecker.cpp @@ -21,12 +21,14 @@ namespace storm { } template - bool SparsePropositionalModelChecker::canHandle(storm::logic::Formula const& formula) const { + bool SparsePropositionalModelChecker::canHandle(CheckTask const& checkTask) const { + storm::logic::Formula const& formula = checkTask.getFormula(); return formula.isPropositionalFormula(); } template - std::unique_ptr SparsePropositionalModelChecker::checkBooleanLiteralFormula(storm::logic::BooleanLiteralFormula const& stateFormula) { + std::unique_ptr SparsePropositionalModelChecker::checkBooleanLiteralFormula(CheckTask const& checkTask) { + storm::logic::BooleanLiteralFormula const& stateFormula = checkTask.getFormula(); if (stateFormula.isTrueFormula()) { return std::unique_ptr(new ExplicitQualitativeCheckResult(storm::storage::BitVector(model.getNumberOfStates(), true))); } else { @@ -35,7 +37,8 @@ namespace storm { } template - std::unique_ptr SparsePropositionalModelChecker::checkAtomicLabelFormula(storm::logic::AtomicLabelFormula const& stateFormula) { + std::unique_ptr SparsePropositionalModelChecker::checkAtomicLabelFormula(CheckTask const& checkTask) { + storm::logic::AtomicLabelFormula const& stateFormula = checkTask.getFormula(); STORM_LOG_THROW(model.hasLabel(stateFormula.getLabel()), storm::exceptions::InvalidPropertyException, "The property refers to unknown label '" << stateFormula.getLabel() << "'."); return std::unique_ptr(new ExplicitQualitativeCheckResult(model.getStates(stateFormula.getLabel()))); } diff --git a/src/modelchecker/propositional/SparsePropositionalModelChecker.h b/src/modelchecker/propositional/SparsePropositionalModelChecker.h index 9565a4bc9..e0bd83bff 100644 --- a/src/modelchecker/propositional/SparsePropositionalModelChecker.h +++ b/src/modelchecker/propositional/SparsePropositionalModelChecker.h @@ -16,9 +16,9 @@ namespace storm { explicit SparsePropositionalModelChecker(SparseModelType const& model); // The implemented methods of the AbstractModelChecker interface. - virtual bool canHandle(storm::logic::Formula const& formula) const override; - virtual std::unique_ptr checkBooleanLiteralFormula(storm::logic::BooleanLiteralFormula const& stateFormula) override; - virtual std::unique_ptr checkAtomicLabelFormula(storm::logic::AtomicLabelFormula const& stateFormula) override; + virtual bool canHandle(CheckTask const& checkTask) const override; + virtual std::unique_ptr checkBooleanLiteralFormula(CheckTask const& checkTask) override; + virtual std::unique_ptr checkAtomicLabelFormula(CheckTask const& checkTask) override; protected: /*! diff --git a/src/modelchecker/propositional/SymbolicPropositionalModelChecker.cpp b/src/modelchecker/propositional/SymbolicPropositionalModelChecker.cpp index 328c0f109..943ecf7db 100644 --- a/src/modelchecker/propositional/SymbolicPropositionalModelChecker.cpp +++ b/src/modelchecker/propositional/SymbolicPropositionalModelChecker.cpp @@ -21,12 +21,14 @@ namespace storm { } template - bool SymbolicPropositionalModelChecker::canHandle(storm::logic::Formula const& formula) const { + bool SymbolicPropositionalModelChecker::canHandle(CheckTask const& checkTask) const { + storm::logic::Formula const& formula = checkTask.getFormula(); return formula.isPropositionalFormula(); } template - std::unique_ptr SymbolicPropositionalModelChecker::checkBooleanLiteralFormula(storm::logic::BooleanLiteralFormula const& stateFormula) { + std::unique_ptr SymbolicPropositionalModelChecker::checkBooleanLiteralFormula(CheckTask const& checkTask) { + storm::logic::BooleanLiteralFormula const& stateFormula = checkTask.getFormula(); if (stateFormula.isTrueFormula()) { return std::unique_ptr(new SymbolicQualitativeCheckResult(model.getReachableStates(), model.getReachableStates())); } else { @@ -35,13 +37,15 @@ namespace storm { } template - std::unique_ptr SymbolicPropositionalModelChecker::checkAtomicLabelFormula(storm::logic::AtomicLabelFormula const& stateFormula) { + std::unique_ptr SymbolicPropositionalModelChecker::checkAtomicLabelFormula(CheckTask const& checkTask) { + storm::logic::AtomicLabelFormula const& stateFormula = checkTask.getFormula(); STORM_LOG_THROW(model.hasLabel(stateFormula.getLabel()), storm::exceptions::InvalidPropertyException, "The property refers to unknown label '" << stateFormula.getLabel() << "'."); return std::unique_ptr(new SymbolicQualitativeCheckResult(model.getReachableStates(), model.getStates(stateFormula.getLabel()))); } template - std::unique_ptr SymbolicPropositionalModelChecker::checkAtomicExpressionFormula(storm::logic::AtomicExpressionFormula const& stateFormula) { + std::unique_ptr SymbolicPropositionalModelChecker::checkAtomicExpressionFormula(CheckTask const& checkTask) { + storm::logic::AtomicExpressionFormula const& stateFormula = checkTask.getFormula(); return std::unique_ptr(new SymbolicQualitativeCheckResult(model.getReachableStates(), model.getStates(stateFormula.getExpression()))); } diff --git a/src/modelchecker/propositional/SymbolicPropositionalModelChecker.h b/src/modelchecker/propositional/SymbolicPropositionalModelChecker.h index 539fbff8d..d11896900 100644 --- a/src/modelchecker/propositional/SymbolicPropositionalModelChecker.h +++ b/src/modelchecker/propositional/SymbolicPropositionalModelChecker.h @@ -21,10 +21,10 @@ namespace storm { explicit SymbolicPropositionalModelChecker(storm::models::symbolic::Model const& model); // The implemented methods of the AbstractModelChecker interface. - virtual bool canHandle(storm::logic::Formula const& formula) const override; - virtual std::unique_ptr checkBooleanLiteralFormula(storm::logic::BooleanLiteralFormula const& stateFormula) override; - virtual std::unique_ptr checkAtomicLabelFormula(storm::logic::AtomicLabelFormula const& stateFormula) override; - virtual std::unique_ptr checkAtomicExpressionFormula(storm::logic::AtomicExpressionFormula const& stateFormula) override; + virtual bool canHandle(CheckTask const& checkTask) const override; + virtual std::unique_ptr checkBooleanLiteralFormula(CheckTask const& checkTask) override; + virtual std::unique_ptr checkAtomicLabelFormula(CheckTask const& checkTask) override; + virtual std::unique_ptr checkAtomicExpressionFormula(CheckTask const& checkTask) override; protected: /*! diff --git a/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp b/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp index 6ec1e6d86..554eba5e3 100644 --- a/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp +++ b/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp @@ -75,18 +75,17 @@ namespace storm { } template - SparseDtmcEliminationModelChecker::SparseDtmcEliminationModelChecker(storm::models::sparse::Dtmc const& model, bool computeResultsForInitialStatesOnly) : SparsePropositionalModelChecker(model), computeResultsForInitialStatesOnly(computeResultsForInitialStatesOnly) { + SparseDtmcEliminationModelChecker::SparseDtmcEliminationModelChecker(storm::models::sparse::Dtmc const& model) : SparsePropositionalModelChecker(model) { // Intentionally left empty. } template - bool SparseDtmcEliminationModelChecker::canHandle(storm::logic::Formula const& formula) const { + bool SparseDtmcEliminationModelChecker::canHandle(CheckTask const& checkTask) const { + storm::logic::Formula const& formula = checkTask.getFormula(); if (formula.isProbabilityOperatorFormula()) { - storm::logic::ProbabilityOperatorFormula const& probabilityOperatorFormula = formula.asProbabilityOperatorFormula(); - return this->canHandle(probabilityOperatorFormula.getSubformula()); + return this->canHandle(checkTask.replaceFormula(formula.asProbabilityOperatorFormula().getSubformula())); } else if (formula.isRewardOperatorFormula()) { - storm::logic::RewardOperatorFormula const& rewardOperatorFormula = formula.asRewardOperatorFormula(); - return this->canHandle(rewardOperatorFormula.getSubformula()); + return this->canHandle(checkTask.replaceFormula(formula.asRewardOperatorFormula().getSubformula())); } else if (formula.isUntilFormula() || formula.isEventuallyFormula()) { if (formula.isUntilFormula()) { storm::logic::UntilFormula const& untilFormula = formula.asUntilFormula(); @@ -130,7 +129,8 @@ namespace storm { } template - std::unique_ptr SparseDtmcEliminationModelChecker::computeLongRunAverageProbabilities(storm::logic::StateFormula const& stateFormula, bool qualitative, boost::optional const& optimalityType) { + std::unique_ptr SparseDtmcEliminationModelChecker::computeLongRunAverageProbabilities(CheckTask const& checkTask) { + storm::logic::StateFormula const& stateFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(stateFormula); storm::storage::BitVector const& psiStates = subResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector(); @@ -145,7 +145,7 @@ namespace storm { storm::storage::BitVector const& initialStates = this->getModel().getInitialStates(); STORM_LOG_THROW(initialStates.getNumberOfSetBits() == 1, storm::exceptions::IllegalArgumentException, "Input model is required to have exactly one initial state."); - STORM_LOG_THROW(this->computeResultsForInitialStatesOnly, storm::exceptions::IllegalArgumentException, "Cannot compute long-run probabilities for all states."); + STORM_LOG_THROW(checkTask.isOnlyInitialStatesRelevantSet(), storm::exceptions::IllegalArgumentException, "Cannot compute long-run probabilities for all states."); storm::storage::SparseMatrix backwardTransitions = this->getModel().getBackwardTransitions(); storm::storage::BitVector maybeStates = storm::utility::graph::performProbGreater0(backwardTransitions, storm::storage::BitVector(transitionMatrix.getRowCount(), true), psiStates); @@ -154,7 +154,7 @@ namespace storm { // Determine whether we need to perform some further computation. bool furtherComputationNeeded = true; - if (computeResultsForInitialStatesOnly && initialStates.isDisjointFrom(maybeStates)) { + if (checkTask.isOnlyInitialStatesRelevantSet() && initialStates.isDisjointFrom(maybeStates)) { STORM_LOG_DEBUG("The long-run probability for all initial states was found in a preprocessing step."); furtherComputationNeeded = false; } @@ -164,7 +164,7 @@ namespace storm { } if (furtherComputationNeeded) { - if (computeResultsForInitialStatesOnly) { + if (checkTask.isOnlyInitialStatesRelevantSet()) { // Determine the set of states that is reachable from the initial state without jumping over a target state. storm::storage::BitVector reachableStates = storm::utility::graph::getReachableStates(transitionMatrix, initialStates, storm::storage::BitVector(numberOfStates, true), storm::storage::BitVector(numberOfStates, false)); @@ -174,12 +174,12 @@ namespace storm { std::vector stateValues(maybeStates.size(), storm::utility::zero()); storm::utility::vector::setVectorValues(stateValues, psiStates, storm::utility::one()); - result = computeLongRunValues(transitionMatrix, backwardTransitions, initialStates, maybeStates, computeResultsForInitialStatesOnly, stateValues); + result = computeLongRunValues(transitionMatrix, backwardTransitions, initialStates, maybeStates, checkTask.isOnlyInitialStatesRelevantSet(), stateValues); } // Construct check result based on whether we have computed values for all states or just the initial states. std::unique_ptr checkResult(new ExplicitQuantitativeCheckResult(result)); - if (computeResultsForInitialStatesOnly) { + if (checkTask.isOnlyInitialStatesRelevantSet()) { // If we computed the results for the initial states only, we need to filter the result to only // communicate these results. checkResult->filter(ExplicitQualitativeCheckResult(initialStates)); @@ -188,14 +188,14 @@ namespace storm { } template - std::unique_ptr SparseDtmcEliminationModelChecker::computeLongRunAverageRewards(storm::logic::LongRunAverageRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName, bool qualitative, boost::optional const& optimalityType) { + std::unique_ptr SparseDtmcEliminationModelChecker::computeLongRunAverageRewards(CheckTask const& checkTask) { // Do some sanity checks to establish some required properties. - RewardModelType const& rewardModel = this->getModel().getRewardModel(rewardModelName ? rewardModelName.get() : ""); + RewardModelType const& rewardModel = this->getModel().getRewardModel(checkTask.isRewardModelSet() ? checkTask.getRewardModel() : ""); STORM_LOG_THROW(!rewardModel.empty(), storm::exceptions::IllegalArgumentException, "Input model does not have a reward model."); storm::storage::BitVector const& initialStates = this->getModel().getInitialStates(); STORM_LOG_THROW(initialStates.getNumberOfSetBits() == 1, storm::exceptions::IllegalArgumentException, "Input model is required to have exactly one initial state."); - STORM_LOG_THROW(this->computeResultsForInitialStatesOnly, storm::exceptions::IllegalArgumentException, "Cannot compute long-run probabilities for all states."); + STORM_LOG_THROW(checkTask.isOnlyInitialStatesRelevantSet(), storm::exceptions::IllegalArgumentException, "Cannot compute long-run probabilities for all states."); storm::storage::SparseMatrix const& transitionMatrix = this->getModel().getTransitionMatrix(); uint_fast64_t numberOfStates = transitionMatrix.getRowCount(); @@ -221,12 +221,12 @@ namespace storm { // Determine whether we need to perform some further computation. bool furtherComputationNeeded = true; - if (computeResultsForInitialStatesOnly && initialStates.isDisjointFrom(maybeStates)) { + if (checkTask.isOnlyInitialStatesRelevantSet() && initialStates.isDisjointFrom(maybeStates)) { furtherComputationNeeded = false; } if (furtherComputationNeeded) { - if (computeResultsForInitialStatesOnly) { + if (checkTask.isOnlyInitialStatesRelevantSet()) { // Determine the set of states that is reachable from the initial state without jumping over a target state. storm::storage::BitVector reachableStates = storm::utility::graph::getReachableStates(transitionMatrix, initialStates, storm::storage::BitVector(numberOfStates, true), storm::storage::BitVector(numberOfStates, false)); @@ -234,12 +234,12 @@ namespace storm { maybeStates &= reachableStates; } - result = computeLongRunValues(transitionMatrix, backwardTransitions, initialStates, maybeStates, computeResultsForInitialStatesOnly, stateRewardValues); + result = computeLongRunValues(transitionMatrix, backwardTransitions, initialStates, maybeStates, checkTask.isOnlyInitialStatesRelevantSet(), stateRewardValues); } // Construct check result based on whether we have computed values for all states or just the initial states. std::unique_ptr checkResult(new ExplicitQuantitativeCheckResult(result)); - if (computeResultsForInitialStatesOnly) { + if (checkTask.isOnlyInitialStatesRelevantSet()) { // If we computed the results for the initial states only, we need to filter the result to only // communicate these results. checkResult->filter(ExplicitQualitativeCheckResult(initialStates)); @@ -410,7 +410,9 @@ namespace storm { } template - std::unique_ptr SparseDtmcEliminationModelChecker::computeBoundedUntilProbabilities(storm::logic::BoundedUntilFormula const& pathFormula, bool qualitative, boost::optional const& optimalityType) { + std::unique_ptr SparseDtmcEliminationModelChecker::computeBoundedUntilProbabilities(CheckTask const& checkTask) { + storm::logic::BoundedUntilFormula const& pathFormula = checkTask.getFormula(); + // Retrieve the appropriate bitvectors by model checking the subformulas. std::unique_ptr leftResultPointer = this->check(pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(pathFormula.getRightSubformula()); @@ -424,7 +426,7 @@ namespace storm { // Determine whether we need to perform some further computation. bool furtherComputationNeeded = true; - if (computeResultsForInitialStatesOnly && this->getModel().getInitialStates().isDisjointFrom(statesWithProbabilityGreater0)) { + if (checkTask.isOnlyInitialStatesRelevantSet() && this->getModel().getInitialStates().isDisjointFrom(statesWithProbabilityGreater0)) { STORM_LOG_DEBUG("The probability for all initial states was found in a preprocessing step."); furtherComputationNeeded = false; } else if (statesWithProbabilityGreater0.empty()) { @@ -440,7 +442,7 @@ namespace storm { if (furtherComputationNeeded) { uint_fast64_t timeBound = pathFormula.getDiscreteTimeBound(); - if (computeResultsForInitialStatesOnly) { + if (checkTask.isOnlyInitialStatesRelevantSet()) { // Determine the set of states that is reachable from the initial state without jumping over a target state. storm::storage::BitVector reachableStates = storm::utility::graph::getReachableStates(transitionMatrix, initialStates, phiStates, psiStates, true, timeBound); @@ -453,7 +455,7 @@ namespace storm { std::vector distancesFromInitialStates; storm::storage::BitVector relevantStates; - if (computeResultsForInitialStatesOnly) { + if (checkTask.isOnlyInitialStatesRelevantSet()) { // Determine the set of initial states of the sub-model. storm::storage::BitVector subInitialStates = this->getModel().getInitialStates() % statesWithProbabilityGreater0; @@ -482,7 +484,7 @@ namespace storm { // If we are computing the results for the initial states only, we can use the minimal distance from // each state to the initial states to determine whether we still need to consider the values for // these states. If not, we can null-out all their probabilities. - if (computeResultsForInitialStatesOnly) { + if (checkTask.isOnlyInitialStatesRelevantSet()) { for (auto state : relevantStates) { if (distancesFromInitialStates[state] > (timeBound - timeStep)) { for (auto& element : submatrix.getRow(state)) { @@ -502,7 +504,7 @@ namespace storm { // Construct check result based on whether we have computed values for all states or just the initial states. std::unique_ptr checkResult(new ExplicitQuantitativeCheckResult(result)); - if (computeResultsForInitialStatesOnly) { + if (checkTask.isOnlyInitialStatesRelevantSet()) { // If we computed the results for the initial (and prob 0 and prob1) states only, we need to filter the // result to only communicate these results. checkResult->filter(ExplicitQualitativeCheckResult(this->getModel().getInitialStates() | psiStates)); @@ -511,7 +513,9 @@ namespace storm { } template - std::unique_ptr SparseDtmcEliminationModelChecker::computeUntilProbabilities(storm::logic::UntilFormula const& pathFormula, bool qualitative, boost::optional const& optimalityType) { + std::unique_ptr SparseDtmcEliminationModelChecker::computeUntilProbabilities(CheckTask const& checkTask) { + storm::logic::UntilFormula const& pathFormula = checkTask.getFormula(); + // Retrieve the appropriate bitvectors by model checking the subformulas. std::unique_ptr leftResultPointer = this->check(pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(pathFormula.getRightSubformula()); @@ -526,7 +530,7 @@ namespace storm { // Determine whether we need to perform some further computation. bool furtherComputationNeeded = true; - if (computeResultsForInitialStatesOnly && this->getModel().getInitialStates().isDisjointFrom(maybeStates)) { + if (checkTask.isOnlyInitialStatesRelevantSet() && this->getModel().getInitialStates().isDisjointFrom(maybeStates)) { STORM_LOG_DEBUG("The probability for all initial states was found in a preprocessing step."); furtherComputationNeeded = false; } else if (maybeStates.empty()) { @@ -538,7 +542,7 @@ namespace storm { if (furtherComputationNeeded) { // If we compute the results for the initial states only, we can cut off all maybe state that are not // reachable from them. - if (computeResultsForInitialStatesOnly) { + if (checkTask.isOnlyInitialStatesRelevantSet()) { // Determine the set of states that is reachable from the initial state without jumping over a target state. storm::storage::BitVector reachableStates = storm::utility::graph::getReachableStates(this->getModel().getTransitionMatrix(), this->getModel().getInitialStates(), maybeStates, statesWithProbability1); @@ -556,7 +560,7 @@ namespace storm { storm::storage::SparseMatrix submatrix = this->getModel().getTransitionMatrix().getSubmatrix(false, maybeStates, maybeStates); storm::storage::SparseMatrix submatrixTransposed = submatrix.transpose(); - std::vector subresult = computeReachabilityValues(submatrix, oneStepProbabilities, submatrixTransposed, newInitialStates, computeResultsForInitialStatesOnly, phiStates, psiStates, oneStepProbabilities); + std::vector subresult = computeReachabilityValues(submatrix, oneStepProbabilities, submatrixTransposed, newInitialStates, checkTask.isOnlyInitialStatesRelevantSet(), phiStates, psiStates, oneStepProbabilities); storm::utility::vector::setVectorValues(result, maybeStates, subresult); } @@ -566,7 +570,7 @@ namespace storm { // Construct check result based on whether we have computed values for all states or just the initial states. std::unique_ptr checkResult(new ExplicitQuantitativeCheckResult(result)); - if (computeResultsForInitialStatesOnly) { + if (checkTask.isOnlyInitialStatesRelevantSet()) { // If we computed the results for the initial (and prob 0 and prob1) states only, we need to filter the // result to only communicate these results. checkResult->filter(ExplicitQualitativeCheckResult(~maybeStates | this->getModel().getInitialStates())); @@ -575,14 +579,16 @@ namespace storm { } template - std::unique_ptr SparseDtmcEliminationModelChecker::computeReachabilityRewards(storm::logic::ReachabilityRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName, bool qualitative, boost::optional const& optimalityType) { + std::unique_ptr SparseDtmcEliminationModelChecker::computeReachabilityRewards(CheckTask const& checkTask) { + storm::logic::ReachabilityRewardFormula const& rewardPathFormula = checkTask.getFormula(); + // Retrieve the appropriate bitvectors by model checking the subformulas. std::unique_ptr subResultPointer = this->check(rewardPathFormula.getSubformula()); storm::storage::BitVector phiStates(this->getModel().getNumberOfStates(), true); storm::storage::BitVector const& psiStates = subResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector(); // Do some sanity checks to establish some required properties. - RewardModelType const& rewardModel = this->getModel().getRewardModel(rewardModelName ? rewardModelName.get() : ""); + RewardModelType const& rewardModel = this->getModel().getRewardModel(checkTask.isRewardModelSet() ? checkTask.getRewardModel() : ""); STORM_LOG_THROW(!rewardModel.empty(), storm::exceptions::IllegalArgumentException, "Input model does not have a reward model."); // Then, compute the subset of states that has a reachability reward less than infinity. @@ -593,7 +599,7 @@ namespace storm { // Determine whether we need to perform some further computation. bool furtherComputationNeeded = true; - if (computeResultsForInitialStatesOnly) { + if (checkTask.isOnlyInitialStatesRelevantSet()) { if (this->getModel().getInitialStates().isSubsetOf(infinityStates)) { STORM_LOG_DEBUG("The reward of all initial states was found in a preprocessing step."); furtherComputationNeeded = false; @@ -608,7 +614,7 @@ namespace storm { if (furtherComputationNeeded) { // If we compute the results for the initial states only, we can cut off all maybe state that are not // reachable from them. - if (computeResultsForInitialStatesOnly) { + if (checkTask.isOnlyInitialStatesRelevantSet()) { // Determine the set of states that is reachable from the initial state without jumping over a target state. storm::storage::BitVector reachableStates = storm::utility::graph::getReachableStates(this->getModel().getTransitionMatrix(), this->getModel().getInitialStates(), maybeStates, psiStates); @@ -626,7 +632,7 @@ namespace storm { // Project the state reward vector to all maybe-states. std::vector stateRewardValues = rewardModel.getTotalRewardVector(maybeStates.getNumberOfSetBits(), this->getModel().getTransitionMatrix(), maybeStates); - std::vector subresult = computeReachabilityValues(submatrix, stateRewardValues, submatrixTransposed, newInitialStates, computeResultsForInitialStatesOnly, phiStates, psiStates, this->getModel().getTransitionMatrix().getConstrainedRowSumVector(maybeStates, psiStates)); + std::vector subresult = computeReachabilityValues(submatrix, stateRewardValues, submatrixTransposed, newInitialStates, checkTask.isOnlyInitialStatesRelevantSet(), phiStates, psiStates, this->getModel().getTransitionMatrix().getConstrainedRowSumVector(maybeStates, psiStates)); storm::utility::vector::setVectorValues(result, maybeStates, subresult); } @@ -636,7 +642,7 @@ namespace storm { // Construct check result based on whether we have computed values for all states or just the initial states. std::unique_ptr checkResult(new ExplicitQuantitativeCheckResult(result)); - if (computeResultsForInitialStatesOnly) { + if (checkTask.isOnlyInitialStatesRelevantSet()) { // If we computed the results for the initial (and inf) states only, we need to filter the result to // only communicate these results. checkResult->filter(ExplicitQualitativeCheckResult(~maybeStates | this->getModel().getInitialStates())); @@ -645,8 +651,8 @@ namespace storm { } template - std::unique_ptr SparseDtmcEliminationModelChecker::computeConditionalProbabilities(storm::logic::ConditionalPathFormula const& pathFormula, bool qualitative, boost::optional const& optimalityType) { - std::chrono::high_resolution_clock::time_point totalTimeStart = std::chrono::high_resolution_clock::now(); + std::unique_ptr SparseDtmcEliminationModelChecker::computeConditionalProbabilities(CheckTask const& checkTask) { + storm::logic::ConditionalPathFormula const& pathFormula = checkTask.getFormula(); // Retrieve the appropriate bitvectors by model checking the subformulas. STORM_LOG_THROW(pathFormula.getLeftSubformula().isEventuallyFormula(), storm::exceptions::InvalidPropertyException, "Expected 'eventually' formula."); @@ -661,7 +667,7 @@ namespace storm { // Do some sanity checks to establish some required properties. // STORM_LOG_WARN_COND(storm::settings::sparseDtmcEliminationModelCheckerSettings().getEliminationMethod() == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationMethod::State, "The chosen elimination method is not available for computing conditional probabilities. Falling back to regular state elimination."); STORM_LOG_THROW(this->getModel().getInitialStates().getNumberOfSetBits() == 1, storm::exceptions::IllegalArgumentException, "Input model is required to have exactly one initial state."); - STORM_LOG_THROW(this->computeResultsForInitialStatesOnly, storm::exceptions::IllegalArgumentException, "Cannot compute conditional probabilities for all states."); + STORM_LOG_THROW(checkTask.isOnlyInitialStatesRelevantSet(), storm::exceptions::IllegalArgumentException, "Cannot compute conditional probabilities for all states."); storm::storage::sparse::state_type initialState = *this->getModel().getInitialStates().begin(); storm::storage::SparseMatrix backwardTransitions = this->getModel().getBackwardTransitions(); @@ -690,18 +696,10 @@ namespace storm { storm::storage::BitVector statesReachingPhi = storm::utility::graph::performProbGreater0(backwardTransitions, trueStates, phiStates); // The set of states we need to consider are those that have a non-zero probability to satisfy the condition or are on some path that has a psi state in it. - STORM_LOG_TRACE("Initial state: " << this->getModel().getInitialStates()); - STORM_LOG_TRACE("Phi states: " << phiStates); - STORM_LOG_TRACE("Psi state: " << psiStates); - STORM_LOG_TRACE("States with probability greater 0 of satisfying the condition: " << statesWithProbabilityGreater0); - STORM_LOG_TRACE("States with psi predecessor: " << statesWithPsiPredecessor); - STORM_LOG_TRACE("States reaching phi: " << statesReachingPhi); storm::storage::BitVector maybeStates = statesWithProbabilityGreater0 | (statesWithPsiPredecessor & statesReachingPhi); - STORM_LOG_TRACE("Found " << maybeStates.getNumberOfSetBits() << " relevant states: " << maybeStates); // Determine the set of initial states of the sub-DTMC. storm::storage::BitVector newInitialStates = this->getModel().getInitialStates() % maybeStates; - STORM_LOG_TRACE("Found new initial states: " << newInitialStates << " (old: " << this->getModel().getInitialStates() << ")"); // Create a dummy vector for the one-step probabilities. std::vector oneStepProbabilities(maybeStates.getNumberOfSetBits(), storm::utility::zero()); @@ -723,10 +721,7 @@ namespace storm { // Keep only the states that we do not eliminate in the maybe states. maybeStates = phiStates | psiStates; - STORM_LOG_TRACE("Phi states in reduced model " << phiStates); - STORM_LOG_TRACE("Psi states in reduced model " << psiStates); storm::storage::BitVector statesToEliminate = ~maybeStates & ~newInitialStates; - STORM_LOG_TRACE("Eliminating the states " << statesToEliminate); // Before starting the model checking process, we assign priorities to states so we can use them to // impose ordering constraints later. @@ -738,19 +733,11 @@ namespace storm { eliminationOrderNeedsReversedDistances(order)); } - std::chrono::high_resolution_clock::time_point conversionStart = std::chrono::high_resolution_clock::now(); FlexibleSparseMatrix flexibleMatrix = getFlexibleSparseMatrix(submatrix); FlexibleSparseMatrix flexibleBackwardTransitions = getFlexibleSparseMatrix(submatrixTransposed, true); - std::chrono::high_resolution_clock::time_point conversionEnd = std::chrono::high_resolution_clock::now(); std::unique_ptr statePriorities = createStatePriorityQueue(distanceBasedPriorities, flexibleMatrix, flexibleBackwardTransitions, oneStepProbabilities, statesToEliminate); - - STORM_LOG_INFO("Computing conditional probilities." << std::endl); - std::chrono::high_resolution_clock::time_point modelCheckingStart = std::chrono::high_resolution_clock::now(); - uint_fast64_t numberOfStatesToEliminate = statePriorities->size(); - STORM_LOG_INFO("Eliminating " << numberOfStatesToEliminate << " states using the state elimination technique." << std::endl); performPrioritizedStateElimination(statePriorities, flexibleMatrix, flexibleBackwardTransitions, oneStepProbabilities, this->getModel().getInitialStates(), true); - STORM_LOG_INFO("Eliminated " << numberOfStatesToEliminate << " states." << std::endl); // Prepare some callbacks for the elimination procedure. ValueUpdateCallback valueUpdateCallback = [&oneStepProbabilities] (storm::storage::sparse::state_type const& state, ValueType const& loopProbability) { oneStepProbabilities[state] = storm::utility::simplify(loopProbability * oneStepProbabilities[state]); }; @@ -866,25 +853,6 @@ namespace storm { numerator += trans1.getValue() * additiveTerm; } } - std::chrono::high_resolution_clock::time_point modelCheckingEnd = std::chrono::high_resolution_clock::now(); - std::chrono::high_resolution_clock::time_point totalTimeEnd = std::chrono::high_resolution_clock::now(); - - if (storm::settings::generalSettings().isShowStatisticsSet()) { - std::chrono::high_resolution_clock::duration conversionTime = conversionEnd - conversionStart; - std::chrono::milliseconds conversionTimeInMilliseconds = std::chrono::duration_cast(conversionTime); - std::chrono::high_resolution_clock::duration modelCheckingTime = modelCheckingEnd - modelCheckingStart; - std::chrono::milliseconds modelCheckingTimeInMilliseconds = std::chrono::duration_cast(modelCheckingTime); - std::chrono::high_resolution_clock::duration totalTime = totalTimeEnd - totalTimeStart; - std::chrono::milliseconds totalTimeInMilliseconds = std::chrono::duration_cast(totalTime); - - STORM_PRINT_AND_LOG(std::endl); - STORM_PRINT_AND_LOG("Time breakdown:" << std::endl); - STORM_PRINT_AND_LOG(" * time for conversion: " << conversionTimeInMilliseconds.count() << "ms" << std::endl); - STORM_PRINT_AND_LOG(" * time for checking: " << modelCheckingTimeInMilliseconds.count() << "ms" << std::endl); - STORM_PRINT_AND_LOG("------------------------------------------" << std::endl); - STORM_PRINT_AND_LOG(" * total time: " << totalTimeInMilliseconds.count() << "ms" << std::endl); - STORM_PRINT_AND_LOG(std::endl); - } return std::unique_ptr(new ExplicitQuantitativeCheckResult(initialState, numerator / denominator)); } @@ -988,15 +956,9 @@ namespace storm { template std::vector::ValueType> SparseDtmcEliminationModelChecker::computeReachabilityValues(storm::storage::SparseMatrix const& transitionMatrix, std::vector& values, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, std::vector const& oneStepProbabilitiesToTarget) { - std::chrono::high_resolution_clock::time_point totalTimeStart = std::chrono::high_resolution_clock::now(); - - std::chrono::high_resolution_clock::time_point conversionStart = std::chrono::high_resolution_clock::now(); // Then, we convert the reduced matrix to a more flexible format to be able to perform state elimination more easily. FlexibleSparseMatrix flexibleMatrix = getFlexibleSparseMatrix(transitionMatrix); FlexibleSparseMatrix flexibleBackwardTransitions = getFlexibleSparseMatrix(backwardTransitions); - auto conversionEnd = std::chrono::high_resolution_clock::now(); - - std::chrono::high_resolution_clock::time_point modelCheckingStart = std::chrono::high_resolution_clock::now(); storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder order = storm::settings::sparseDtmcEliminationModelCheckerSettings().getEliminationOrder(); boost::optional> distanceBasedPriorities; @@ -1018,31 +980,6 @@ namespace storm { STORM_LOG_ASSERT(flexibleMatrix.empty(), "Not all transitions were eliminated."); STORM_LOG_ASSERT(flexibleBackwardTransitions.empty(), "Not all transitions were eliminated."); - std::chrono::high_resolution_clock::time_point modelCheckingEnd = std::chrono::high_resolution_clock::now(); - std::chrono::high_resolution_clock::time_point totalTimeEnd = std::chrono::high_resolution_clock::now(); - - if (storm::settings::generalSettings().isShowStatisticsSet()) { - std::chrono::high_resolution_clock::duration conversionTime = conversionEnd - conversionStart; - std::chrono::milliseconds conversionTimeInMilliseconds = std::chrono::duration_cast(conversionTime); - std::chrono::high_resolution_clock::duration modelCheckingTime = modelCheckingEnd - modelCheckingStart; - std::chrono::milliseconds modelCheckingTimeInMilliseconds = std::chrono::duration_cast(modelCheckingTime); - std::chrono::high_resolution_clock::duration totalTime = totalTimeEnd - totalTimeStart; - std::chrono::milliseconds totalTimeInMilliseconds = std::chrono::duration_cast(totalTime); - - STORM_PRINT_AND_LOG(std::endl); - STORM_PRINT_AND_LOG("Time breakdown:" << std::endl); - STORM_PRINT_AND_LOG(" * time for conversion: " << conversionTimeInMilliseconds.count() << "ms" << std::endl); - STORM_PRINT_AND_LOG(" * time for checking: " << modelCheckingTimeInMilliseconds.count() << "ms" << std::endl); - STORM_PRINT_AND_LOG("------------------------------------------" << std::endl); - STORM_PRINT_AND_LOG(" * total time: " << totalTimeInMilliseconds.count() << "ms" << std::endl); - STORM_PRINT_AND_LOG(std::endl); - STORM_PRINT_AND_LOG("Other:" << std::endl); - STORM_PRINT_AND_LOG(" * number of states eliminated: " << transitionMatrix.getRowCount() << std::endl); - if (storm::settings::sparseDtmcEliminationModelCheckerSettings().getEliminationMethod() == storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationMethod::Hybrid) { - STORM_PRINT_AND_LOG(" * maximal depth of SCC decomposition: " << maximalDepth << std::endl); - } - } - // Now, we return the value for the only initial state. STORM_LOG_DEBUG("Simplifying and returning result."); for (auto& value : values) { @@ -1243,7 +1180,6 @@ namespace storm { auto successorEntry = storm::utility::simplify(std::move(*first2 * multiplyFactor)); *result = successorEntry; newBackwardProbabilities[successorOffsetInNewBackwardTransitions].emplace_back(predecessor, successorEntry.getValue()); -// std::cout << "(1) adding " << first2->getColumn() << " -> " << newBackwardProbabilities[successorOffsetInNewBackwardTransitions].back() << "[" << successorOffsetInNewBackwardTransitions << "]" << std::endl; ++first2; ++successorOffsetInNewBackwardTransitions; } else if (first1->getColumn() < first2->getColumn()) { @@ -1253,7 +1189,6 @@ namespace storm { auto probability = storm::utility::simplify(first1->getValue() + storm::utility::simplify(multiplyFactor * first2->getValue())); *result = storm::storage::MatrixEntry(first1->getColumn(), probability); newBackwardProbabilities[successorOffsetInNewBackwardTransitions].emplace_back(predecessor, probability); -// std::cout << "(2) adding " << first2->getColumn() << " -> " << newBackwardProbabilities[successorOffsetInNewBackwardTransitions].back() << "[" << successorOffsetInNewBackwardTransitions << "]" << std::endl; ++first1; ++first2; ++successorOffsetInNewBackwardTransitions; @@ -1264,7 +1199,6 @@ namespace storm { auto stateProbability = storm::utility::simplify(std::move(*first2 * multiplyFactor)); *result = stateProbability; newBackwardProbabilities[successorOffsetInNewBackwardTransitions].emplace_back(predecessor, stateProbability.getValue()); -// std::cout << "(3) adding " << first2->getColumn() << " -> " << newBackwardProbabilities[successorOffsetInNewBackwardTransitions].back() << "[" << successorOffsetInNewBackwardTransitions << "]" << std::endl; ++successorOffsetInNewBackwardTransitions; } } @@ -1289,10 +1223,6 @@ namespace storm { } typename FlexibleSparseMatrix::row_type& successorBackwardTransitions = backwardTransitions.getRow(successorEntry.getColumn()); -// std::cout << "old backward trans of " << successorEntry.getColumn() << std::endl; -// for (auto const& trans : successorBackwardTransitions) { -// std::cout << trans << std::endl; -// } // Delete the current state as a predecessor of the successor state only if we are going to remove the // current state's forward transitions. @@ -1307,11 +1237,6 @@ namespace storm { typename FlexibleSparseMatrix::row_type::iterator first2 = newBackwardProbabilities[successorOffsetInNewBackwardTransitions].begin(); typename FlexibleSparseMatrix::row_type::iterator last2 = newBackwardProbabilities[successorOffsetInNewBackwardTransitions].end(); -// std::cout << "adding backward trans " << successorEntry.getColumn() << "[" << successorOffsetInNewBackwardTransitions << "]" << std::endl; -// for (auto const& trans : newBackwardProbabilities[successorOffsetInNewBackwardTransitions]) { -// std::cout << trans << std::endl; -// } - typename FlexibleSparseMatrix::row_type newPredecessors; newPredecessors.reserve((last1 - first1) + (last2 - first2)); std::insert_iterator result(newPredecessors, newPredecessors.end()); @@ -1347,10 +1272,6 @@ namespace storm { // Now move the new predecessors in place. successorBackwardTransitions = std::move(newPredecessors); -// std::cout << "new backward trans of " << successorEntry.getColumn() << std::endl; -// for (auto const& trans : successorBackwardTransitions) { -// std::cout << trans << std::endl; -// } ++successorOffsetInNewBackwardTransitions; } STORM_LOG_TRACE("Fixed predecessor lists of successor states."); @@ -1649,9 +1570,6 @@ namespace storm { } if (!foundCorrespondingElement) { -// std::cout << "forward entry: " << forwardIndex << " -> " << forwardEntry << std::endl; -// transitionMatrix.print(); -// backwardTransitions.print(); return false; } } diff --git a/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.h b/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.h index 692a6be57..809522260 100644 --- a/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.h +++ b/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.h @@ -19,18 +19,17 @@ namespace storm { * Creates an elimination-based model checker for the given model. * * @param model The model to analyze. - * @param computeResultsForInitialStatesOnly If set to true, the results are only computed for */ - explicit SparseDtmcEliminationModelChecker(storm::models::sparse::Dtmc const& model, bool computeResultsForInitialStatesOnly = true); + explicit SparseDtmcEliminationModelChecker(storm::models::sparse::Dtmc const& model); // The implemented methods of the AbstractModelChecker interface. - virtual bool canHandle(storm::logic::Formula const& formula) const override; - virtual std::unique_ptr computeBoundedUntilProbabilities(storm::logic::BoundedUntilFormula const& pathFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeUntilProbabilities(storm::logic::UntilFormula const& pathFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeReachabilityRewards(storm::logic::ReachabilityRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName = boost::optional(), bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeLongRunAverageRewards(storm::logic::LongRunAverageRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName = boost::optional(), bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeConditionalProbabilities(storm::logic::ConditionalPathFormula const& pathFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - virtual std::unique_ptr computeLongRunAverageProbabilities(storm::logic::StateFormula const& stateFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; + virtual bool canHandle(CheckTask const& checkTask) const override; + virtual std::unique_ptr computeBoundedUntilProbabilities(CheckTask const& checkTask) override; + virtual std::unique_ptr computeUntilProbabilities(CheckTask const& checkTask) override; + virtual std::unique_ptr computeReachabilityRewards(CheckTask const& checkTask) override; + virtual std::unique_ptr computeLongRunAverageRewards(CheckTask const& checkTask) override; + virtual std::unique_ptr computeConditionalProbabilities(CheckTask const& checkTask) override; + virtual std::unique_ptr computeLongRunAverageProbabilities(CheckTask const& checkTask) override; private: class FlexibleSparseMatrix { @@ -150,9 +149,6 @@ namespace storm { static bool checkConsistent(FlexibleSparseMatrix& transitionMatrix, FlexibleSparseMatrix& backwardTransitions); - // A flag that indicates whether this model checker is supposed to produce results for all states or just for the initial states. - bool computeResultsForInitialStatesOnly; - }; } // namespace modelchecker diff --git a/src/parser/SpiritErrorHandler.h b/src/parser/SpiritErrorHandler.h index cd2a35b06..949ad9b12 100644 --- a/src/parser/SpiritErrorHandler.h +++ b/src/parser/SpiritErrorHandler.h @@ -16,7 +16,7 @@ namespace storm { qi::error_handler_result operator()(T1 b, T2 e, T3 where, T4 const& what) const { auto lineStart = boost::spirit::get_line_start(b, where); auto lineEnd = std::find(where, e, '\n'); - std::string line(++lineStart, lineEnd); + std::string line(lineStart, lineEnd); std::stringstream stream; stream << "Parsing error at " << get_line(where) << ":" << boost::spirit::get_column(lineStart, where) << ": " << " expecting " << what << ", here:" << std::endl; diff --git a/src/utility/storm.h b/src/utility/storm.h index 7ffba8c85..d4a042bc6 100644 --- a/src/utility/storm.h +++ b/src/utility/storm.h @@ -76,7 +76,7 @@ namespace storm { template - std::shared_ptr> buildExplicitModel(std::string const& transitionsFile, std::string const& labelingFile, boost::optional const& stateRewardsFile = boost::optional(), boost::optional const& transitionRewardsFile = boost::optional(), boost::optional const& choiceLabelingFile = boost::optional()) { + std::shared_ptr> buildExplicitModel(std::string const& transitionsFile, std::string const& labelingFile, boost::optional const& stateRewardsFile = boost::none, boost::optional const& transitionRewardsFile = boost::none, boost::optional const& choiceLabelingFile = boost::none) { return storm::parser::AutoParser<>::parseModel(transitionsFile, labelingFile, stateRewardsFile ? stateRewardsFile.get() : "", transitionRewardsFile ? transitionRewardsFile.get() : "", choiceLabelingFile ? choiceLabelingFile.get() : "" ); } @@ -236,23 +236,23 @@ namespace storm { #endif template - std::unique_ptr verifyModel(std::shared_ptr model, std::shared_ptr const& formula) { + std::unique_ptr verifyModel(std::shared_ptr model, std::shared_ptr const& formula, bool onlyInitialStatesRelevant) { storm::settings::modules::GeneralSettings const& settings = storm::settings::generalSettings(); switch(settings.getEngine()) { case storm::settings::modules::GeneralSettings::Engine::Sparse: { std::shared_ptr> sparseModel = model->template as>(); STORM_LOG_THROW(sparseModel != nullptr, storm::exceptions::InvalidArgumentException, "Sparse engine requires a sparse input model"); - return verifySparseModel(sparseModel, formula); + return verifySparseModel(sparseModel, formula, onlyInitialStatesRelevant); } case storm::settings::modules::GeneralSettings::Engine::Hybrid: { std::shared_ptr> ddModel = model->template as>(); STORM_LOG_THROW(ddModel != nullptr, storm::exceptions::InvalidArgumentException, "Hybrid engine requires a dd input model"); - return verifySymbolicModelWithHybridEngine(ddModel, formula); + return verifySymbolicModelWithHybridEngine(ddModel, formula, onlyInitialStatesRelevant); } case storm::settings::modules::GeneralSettings::Engine::Dd: { std::shared_ptr> ddModel = model->template as>(); STORM_LOG_THROW(ddModel != nullptr, storm::exceptions::InvalidArgumentException, "Dd engine requires a dd input model"); - return verifySymbolicModelWithDdEngine(ddModel, formula); + return verifySymbolicModelWithDdEngine(ddModel, formula, onlyInitialStatesRelevant); } case storm::settings::modules::GeneralSettings::Engine::AbstractionRefinement: { STORM_LOG_ASSERT(false, "This position should not be reached, as at this point no model has been built."); @@ -261,18 +261,19 @@ namespace storm { } template - std::unique_ptr verifySparseModel(std::shared_ptr> model, std::shared_ptr const& formula) { + std::unique_ptr verifySparseModel(std::shared_ptr> model, std::shared_ptr const& formula, bool onlyInitialStatesRelevant = false) { std::unique_ptr result; + storm::modelchecker::CheckTask task(*formula, onlyInitialStatesRelevant); if (model->getType() == storm::models::ModelType::Dtmc) { std::shared_ptr> dtmc = model->template as>(); storm::modelchecker::SparseDtmcPrctlModelChecker> modelchecker(*dtmc); - if (modelchecker.canHandle(*formula)) { - result = modelchecker.check(*formula); + if (modelchecker.canHandle(task)) { + result = modelchecker.check(task); } else { storm::modelchecker::SparseDtmcEliminationModelChecker> modelchecker2(*dtmc); - if (modelchecker2.canHandle(*formula)) { - result = modelchecker2.check(*formula); + if (modelchecker2.canHandle(task)) { + result = modelchecker2.check(task); } } } else if (model->getType() == storm::models::ModelType::Mdp) { @@ -280,20 +281,20 @@ namespace storm { #ifdef STORM_HAVE_CUDA if (settings.isCudaSet()) { storm::modelchecker::TopologicalValueIterationMdpPrctlModelChecker modelchecker(*mdp); - result = modelchecker.check(*formula); + result = modelchecker.check(task); } else { storm::modelchecker::SparseMdpPrctlModelChecker> modelchecker(*mdp); - result = modelchecker.check(*formula); + result = modelchecker.check(task); } #else storm::modelchecker::SparseMdpPrctlModelChecker> modelchecker(*mdp); - result = modelchecker.check(*formula); + result = modelchecker.check(task); #endif } else if (model->getType() == storm::models::ModelType::Ctmc) { std::shared_ptr> ctmc = model->template as>(); storm::modelchecker::SparseCtmcCslModelChecker> modelchecker(*ctmc); - result = modelchecker.check(*formula); + result = modelchecker.check(task); } return result; @@ -317,13 +318,14 @@ namespace storm { } template<> - inline std::unique_ptr verifySparseModel(std::shared_ptr> model, std::shared_ptr const& formula) { + inline std::unique_ptr verifySparseModel(std::shared_ptr> model, std::shared_ptr const& formula, bool onlyInitialStatesRelevant) { std::unique_ptr result; std::shared_ptr> dtmc = model->template as>(); storm::modelchecker::SparseDtmcEliminationModelChecker> modelchecker(*dtmc); - if (modelchecker.canHandle(*formula)) { - result = modelchecker.check(*formula); + storm::modelchecker::CheckTask task(*formula, onlyInitialStatesRelevant); + if (modelchecker.canHandle(task)) { + result = modelchecker.check(task); } else { STORM_LOG_THROW(false, storm::exceptions::InvalidSettingsException, "The parametric engine currently does not support this property."); } @@ -333,25 +335,26 @@ namespace storm { #endif template - std::unique_ptr verifySymbolicModelWithHybridEngine(std::shared_ptr> model, std::shared_ptr const& formula) { + std::unique_ptr verifySymbolicModelWithHybridEngine(std::shared_ptr> model, std::shared_ptr const& formula, bool onlyInitialStatesRelevant = false) { std::unique_ptr result; + storm::modelchecker::CheckTask task(*formula, onlyInitialStatesRelevant); if (model->getType() == storm::models::ModelType::Dtmc) { std::shared_ptr> dtmc = model->template as>(); storm::modelchecker::HybridDtmcPrctlModelChecker modelchecker(*dtmc); - if (modelchecker.canHandle(*formula)) { - result = modelchecker.check(*formula); + if (modelchecker.canHandle(task)) { + result = modelchecker.check(task); } } else if (model->getType() == storm::models::ModelType::Ctmc) { std::shared_ptr> ctmc = model->template as>(); storm::modelchecker::HybridCtmcCslModelChecker modelchecker(*ctmc); - if (modelchecker.canHandle(*formula)) { - result = modelchecker.check(*formula); + if (modelchecker.canHandle(task)) { + result = modelchecker.check(task); } } else if (model->getType() == storm::models::ModelType::Mdp) { std::shared_ptr> mdp = model->template as>(); storm::modelchecker::HybridMdpPrctlModelChecker modelchecker(*mdp); - if (modelchecker.canHandle(*formula)) { - result = modelchecker.check(*formula); + if (modelchecker.canHandle(task)) { + result = modelchecker.check(task); } } else { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "This functionality is not yet implemented."); @@ -361,19 +364,20 @@ namespace storm { template - std::unique_ptr verifySymbolicModelWithDdEngine(std::shared_ptr> model, std::shared_ptr const& formula) { + std::unique_ptr verifySymbolicModelWithDdEngine(std::shared_ptr> model, std::shared_ptr const& formula, bool onlyInitialStatesRelevant) { std::unique_ptr result; + storm::modelchecker::CheckTask task(*formula, onlyInitialStatesRelevant); if (model->getType() == storm::models::ModelType::Dtmc) { std::shared_ptr> dtmc = model->template as>(); storm::modelchecker::SymbolicDtmcPrctlModelChecker modelchecker(*dtmc); - if (modelchecker.canHandle(*formula)) { - result = modelchecker.check(*formula); + if (modelchecker.canHandle(task)) { + result = modelchecker.check(task); } } else if (model->getType() == storm::models::ModelType::Mdp) { std::shared_ptr> mdp = model->template as>(); storm::modelchecker::SymbolicMdpPrctlModelChecker modelchecker(*mdp); - if (modelchecker.canHandle(*formula)) { - result = modelchecker.check(*formula); + if (modelchecker.canHandle(task)) { + result = modelchecker.check(task); } } else { STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "This functionality is not yet implemented."); diff --git a/test/functional/modelchecker/SparseDtmcEliminationModelCheckerTest.cpp b/test/functional/modelchecker/SparseDtmcEliminationModelCheckerTest.cpp index 7ce394070..ad4d9ab3d 100644 --- a/test/functional/modelchecker/SparseDtmcEliminationModelCheckerTest.cpp +++ b/test/functional/modelchecker/SparseDtmcEliminationModelCheckerTest.cpp @@ -94,14 +94,14 @@ TEST(SparseDtmcEliminationModelCheckerTest, Crowds) { formula = formulaParser.parseSingleFormulaFromString("P=? [F \"observe0Greater1\" || F \"observeIGreater1\"]"); - result = checker.check(*formula); + result = checker.check(storm::modelchecker::CheckTask(*formula).setOnlyInitialStatesRelevant(true)); storm::modelchecker::ExplicitQuantitativeCheckResult& quantitativeResult4 = result->asExplicitQuantitativeCheckResult(); EXPECT_NEAR(0.15330064292476167, quantitativeResult4[0], storm::settings::generalSettings().getPrecision()); formula = formulaParser.parseSingleFormulaFromString("P=? [F \"observeOnlyTrueSender\" || F \"observe0Greater1\"]"); - result = checker.check(*formula); + result = checker.check(storm::modelchecker::CheckTask(*formula).setOnlyInitialStatesRelevant(true)); storm::modelchecker::ExplicitQuantitativeCheckResult& quantitativeResult5 = result->asExplicitQuantitativeCheckResult(); EXPECT_NEAR(0.96592521978041668, quantitativeResult5[0], storm::settings::generalSettings().getPrecision()); diff --git a/test/performance/builder/leader5.nm b/test/performance/builder/leader5.nm index c48a255bb..26316affa 100644 --- a/test/performance/builder/leader5.nm +++ b/test/performance/builder/leader5.nm @@ -1,4 +1,3 @@ -<<<<<<< HEAD // asynchronous leader election // 4 processes // gxn/dxp 29/01/01 @@ -96,104 +95,3 @@ endrewards //---------------------------------------------------------------------------------------------------------------------------- formula leaders = (s1=4?1:0)+(s2=4?1:0)+(s3=4?1:0)+(s4=4?1:0)+(s5=4?1:0); label "elected" = s1=4|s2=4|s3=4|s4=4|s5=4; - -======= -// asynchronous leader election -// 4 processes -// gxn/dxp 29/01/01 - -mdp - -const int N= 5; // number of processes - -//---------------------------------------------------------------------------------------------------------------------------- -module process1 - - // COUNTER - c1 : [0..5-1]; - - // STATES - s1 : [0..4]; - // 0 make choice - // 1 have not received neighbours choice - // 2 active - // 3 inactive - // 4 leader - - // PREFERENCE - p1 : [0..1]; - - // VARIABLES FOR SENDING AND RECEIVING - receive1 : [0..2]; - // not received anything - // received choice - // received counter - sent1 : [0..2]; - // not send anything - // sent choice - // sent counter - - // pick value - [] (s1=0) -> 0.5 : (s1'=1) & (p1'=0) + 0.5 : (s1'=1) & (p1'=1); - - // send preference - [p12] (s1=1) & (sent1=0) -> (sent1'=1); - // receive preference - // stay active - [p51] (s1=1) & (receive1=0) & !( (p1=0) & (p5=1) ) -> (s1'=2) & (receive1'=1); - // become inactive - [p51] (s1=1) & (receive1=0) & (p1=0) & (p5=1) -> (s1'=3) & (receive1'=1); - - // send preference (can now reset preference) - [p12] (s1=2) & (sent1=0) -> (sent1'=1) & (p1'=0); - // send counter (already sent preference) - // not received counter yet - [c12] (s1=2) & (sent1=1) & (receive1=1) -> (sent1'=2); - // received counter (pick again) - [c12] (s1=2) & (sent1=1) & (receive1=2) -> (s1'=0) & (p1'=0) & (c1'=0) & (sent1'=0) & (receive1'=0); - - // receive counter and not sent yet (note in this case do not pass it on as will send own counter) - [c51] (s1=2) & (receive1=1) & (sent1<2) -> (receive1'=2); - // receive counter and sent counter - // only active process (decide) - [c51] (s1=2) & (receive1=1) & (sent1=2) & (c5=N-1) -> (s1'=4) & (p1'=0) & (c1'=0) & (sent1'=0) & (receive1'=0); - // other active process (pick again) - [c51] (s1=2) & (receive1=1) & (sent1=2) & (c5 (s1'=0) & (p1'=0) & (c1'=0) & (sent1'=0) & (receive1'=0); - - // send preference (must have received preference) and can now reset - [p12] (s1=3) & (receive1>0) & (sent1=0) -> (sent1'=1) & (p1'=0); - // send counter (must have received counter first) and can now reset - [c12] (s1=3) & (receive1=2) & (sent1=1) -> (s1'=3) & (p1'=0) & (c1'=0) & (sent1'=0) & (receive1'=0); - - // receive preference - [p51] (s1=3) & (receive1=0) -> (p1'=p5) & (receive1'=1); - // receive counter - [c51] (s1=3) & (receive1=1) & (c5 (c1'=c5+1) & (receive1'=2); - - // done - [done] (s1=4) -> (s1'=s1); - // add loop for processes who are inactive - [done] (s1=3) -> (s1'=s1); - -endmodule - -//---------------------------------------------------------------------------------------------------------------------------- - -// construct further stations through renaming -module process2=process1[s1=s2,p1=p2,c1=c2,sent1=sent2,receive1=receive2,p12=p23,p51=p12,c12=c23,c51=c12,p5=p1,c5=c1] endmodule -module process3=process1[s1=s3,p1=p3,c1=c3,sent1=sent3,receive1=receive3,p12=p34,p51=p23,c12=c34,c51=c23,p5=p2,c5=c2] endmodule -module process4=process1[s1=s4,p1=p4,c1=c4,sent1=sent4,receive1=receive4,p12=p45,p51=p34,c12=c45,c51=c34,p5=p3,c5=c3] endmodule -module process5=process1[s1=s5,p1=p5,c1=c5,sent1=sent5,receive1=receive5,p12=p51,p51=p45,c12=c51,c51=c45,p5=p4,c5=c4] endmodule - -//---------------------------------------------------------------------------------------------------------------------------- - -// reward - expected number of rounds (equals the number of times a process receives a counter) -rewards "rounds" - [c12] true : 1; -endrewards - -//---------------------------------------------------------------------------------------------------------------------------- -formula leaders = (s1=4?1:0)+(s2=4?1:0)+(s3=4?1:0)+(s4=4?1:0)+(s5=4?1:0); -label "elected" = s1=4|s2=4|s3=4|s4=4|s5=4; - ->>>>>>> 90d2b218a044edca8062084ee89d171695149c1e diff --git a/test/performance/builder/leader5_8.pm b/test/performance/builder/leader5_8.pm index e6cfc2106..eb7dd9fd7 100644 --- a/test/performance/builder/leader5_8.pm +++ b/test/performance/builder/leader5_8.pm @@ -1,4 +1,3 @@ -<<<<<<< HEAD // synchronous leader election protocol (itai & Rodeh) // dxp/gxn 25/01/01 @@ -88,96 +87,3 @@ endrewards // labels label "elected" = s1=3&s2=3&s3=3&s4=3&s5=3; - -======= -// synchronous leader election protocol (itai & Rodeh) -// dxp/gxn 25/01/01 - -dtmc - -// CONSTANTS -const int N = 5; // number of processes -const int K = 8; // range of probabilistic choice - -// counter module used to count the number of processes that have been read -// and to know when a process has decided -module counter - - // counter (c=i means process j reading process (i-1)+j next) - c : [1..N-1]; - - // reading - [read] c (c'=c+1); - // finished reading - [read] c=N-1 -> (c'=c); - //decide - [done] u1|u2|u3|u4|u5 -> (c'=c); - // pick again reset counter - [retry] !(u1|u2|u3|u4|u5) -> (c'=1); - // loop (when finished to avoid deadlocks) - [loop] s1=3 -> (c'=c); - -endmodule - -// processes form a ring and suppose: -// process 1 reads process 2 -// process 2 reads process 3 -// process 3 reads process 1 -module process1 - - // local state - s1 : [0..3]; - // s1=0 make random choice - // s1=1 reading - // s1=2 deciding - // s1=3 finished - - // has a unique id so far (initially true) - u1 : bool; - - // value to be sent to next process in the ring (initially sets this to its own value) - v1 : [0..K-1]; - - // random choice - p1 : [0..K-1]; - - // pick value - [pick] s1=0 -> 1/K : (s1'=1) & (p1'=0) & (v1'=0) & (u1'=true) - + 1/K : (s1'=1) & (p1'=1) & (v1'=1) & (u1'=true) - + 1/K : (s1'=1) & (p1'=2) & (v1'=2) & (u1'=true) - + 1/K : (s1'=1) & (p1'=3) & (v1'=3) & (u1'=true) - + 1/K : (s1'=1) & (p1'=4) & (v1'=4) & (u1'=true) - + 1/K : (s1'=1) & (p1'=5) & (v1'=5) & (u1'=true) - + 1/K : (s1'=1) & (p1'=6) & (v1'=6) & (u1'=true) - + 1/K : (s1'=1) & (p1'=7) & (v1'=7) & (u1'=true); - // read - [read] s1=1 & u1 & c (u1'=(p1!=v2)) & (v1'=v2); - [read] s1=1 & !u1 & c (u1'=false) & (v1'=v2) & (p1'=0); - // read and move to decide - [read] s1=1 & u1 & c=N-1 -> (s1'=2) & (u1'=(p1!=v2)) & (v1'=0) & (p1'=0); - [read] s1=1 & !u1 & c=N-1 -> (s1'=2) & (u1'=false) & (v1'=0); - // deciding - // done - [done] s1=2 -> (s1'=3) & (u1'=false) & (v1'=0) & (p1'=0); - //retry - [retry] s1=2 -> (s1'=0) & (u1'=false) & (v1'=0) & (p1'=0); - // loop (when finished to avoid deadlocks) - [loop] s1=3 -> (s1'=3); - -endmodule - -// construct remaining processes through renaming -module process2 = process1 [ s1=s2,p1=p2,v1=v2,u1=u2,v2=v3 ] endmodule -module process3 = process1 [ s1=s3,p1=p3,v1=v3,u1=u3,v2=v4 ] endmodule -module process4 = process1 [ s1=s4,p1=p4,v1=v4,u1=u4,v2=v5 ] endmodule -module process5 = process1 [ s1=s5,p1=p5,v1=v5,u1=u5,v2=v1 ] endmodule - -// expected number of rounds -rewards "num_rounds" - [pick] true : 1; -endrewards - -// labels -label "elected" = s1=3&s2=3&s3=3&s4=3&s5=3; - ->>>>>>> 90d2b218a044edca8062084ee89d171695149c1e