diff --git a/.bazelrc b/.bazelrc index 710c4d81ab..e69de29bb2 100644 --- a/.bazelrc +++ b/.bazelrc @@ -1 +0,0 @@ -common --noenable_bzlmod diff --git a/.github/workflows/build-bazel.yml b/.github/workflows/build-bazel.yml index 3bf734f973..c020350be2 100644 --- a/.github/workflows/build-bazel.yml +++ b/.github/workflows/build-bazel.yml @@ -18,10 +18,10 @@ jobs: run: bazel clean - name: build bazel - run: bazel build --enable_bzlmod //... + run: bazel build //... - name: test all - run: bazel test --enable_bzlmod //... + run: bazel test //... - name: test example run: ./bazel-bin/call-highs-example \ No newline at end of file diff --git a/.github/workflows/build-python-package.yml b/.github/workflows/build-python-package.yml index 0b6c32f2fe..df73a2e47a 100644 --- a/.github/workflows/build-python-package.yml +++ b/.github/workflows/build-python-package.yml @@ -75,26 +75,23 @@ jobs: python -m pytest build_wheel_linux: - # ubuntu 22 has a latest version of cmake, but setup-python - # does not seem to provide all necessary modules to find python - # from cmake. works on my machine, test the wheels manually - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 + strategy: + matrix: + python: [3.11] steps: - uses: actions/checkout@v4 - # strategy: - # matrix: - # python: [3.12] - name: Install correct python version uses: actions/setup-python@v5 - # with: - # python-version: ${{ matrix.python }} + with: + python-version: ${{ matrix.python }} - name: Build wheel run: | python3 --version python3 -m pip install cibuildwheel - python3 -m cibuildwheel --only cp310-manylinux_x86_64 $GITHUB_WORKSPACE + python3 -m cibuildwheel --only cp311-manylinux_x86_64 $GITHUB_WORKSPACE - name: Install wheel run: | @@ -105,7 +102,36 @@ jobs: run: | python3 -m pip install pytest python3 -m pytest $GITHUB_WORKSPACE - + + build_wheel_linux_arm: + runs-on: ubuntu-24.04-arm + strategy: + matrix: + python: [3.11] + steps: + - uses: actions/checkout@v4 + + - name: Install python + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python }} + + - name: Build wheel + run: | + python3 --version + python3 -m pip install cibuildwheel + python3 -m cibuildwheel --only cp311-manylinux_aarch64 $GITHUB_WORKSPACE + + - name: Install wheel + run: | + ls wheelhouse + python3 -m pip install wheelhouse/*.whl + + - name: Test highspy + run: | + python3 -m pip install pytest + python3 -m pytest $GITHUB_WORKSPACE + # macos 13 is Intel build_wheel_macos_13: runs-on: macos-13 diff --git a/.github/workflows/build-wheels-push.yml b/.github/workflows/build-wheels-push.yml index 899d865c9a..19851951d7 100644 --- a/.github/workflows/build-wheels-push.yml +++ b/.github/workflows/build-wheels-push.yml @@ -1,12 +1,12 @@ name: build-wheels-push -on: [] +# on: [] # on: push -# on: -# release: -# types: -# - published +on: + release: + types: + - published concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -43,12 +43,12 @@ jobs: # Github Actions doesn't support pairing matrix values together, let's improvise # https://github.com/github/feedback/discussions/7835#discussioncomment-1769026 buildplat: - - [ubuntu-20.04, manylinux_x86_64] - - [ubuntu-20.04, manylinux_i686] - - [ubuntu-20.04, manylinux_aarch64] - - [ubuntu-20.04, musllinux_x86_64] # No OpenBlas, no test - - [ubuntu-20.04, musllinux_i686] - - [ubuntu-20.04, musllinux_aarch64] + - [ubuntu-24.04, manylinux_x86_64] + - [ubuntu-24.04, manylinux_i686] + - [ubuntu-24.04-arm, manylinux_aarch64] + - [ubuntu-24.04, musllinux_x86_64] # No OpenBlas, no test + - [ubuntu-24.04, musllinux_i686] + - [ubuntu-24.04-arm, musllinux_aarch64] - [macos-13, macosx_x86_64] - [macos-14, macosx_arm64] - [windows-2019, win_amd64] @@ -58,21 +58,7 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Set up QEMU # Required for aarch64 builds - if: ${{ contains(matrix.buildplat[1], 'aarch64') }} - uses: docker/setup-qemu-action@v3 - with: - platforms: all - - - name: Build wheels (aarch64) - if: ${{ contains(matrix.buildplat[1], 'aarch64') }} - uses: pypa/cibuildwheel@v2.21 - env: - CIBW_BUILD: ${{ matrix.python }}-${{ matrix.buildplat[1] }} - CIBW_ARCHS_LINUX: aarch64 - - - name: Build wheels (not aarch64) - if: ${{ !contains(matrix.buildplat[1], 'aarch64') }} + - name: Build wheels uses: pypa/cibuildwheel@v2.21 env: CIBW_BUILD: ${{ matrix.python }}-${{ matrix.buildplat[1] }} @@ -82,51 +68,22 @@ jobs: name: cibw-wheels-${{ matrix.python }}-${{ matrix.buildplat[1] }} path: wheelhouse/*.whl - upload_testpypi: - name: >- - Publish highspy to TestPyPI - runs-on: ubuntu-latest - needs: [build_wheels, build_sdist] - # needs: [build_sdist] - - # upload to PyPI on every tag starting with 'v' - # if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') - - environment: - name: testpypi - url: https://test.pypi.org/p/highspy - - permissions: - id-token: write # IMPORTANT: mandatory for trusted publishing - steps: - - uses: actions/download-artifact@v4 - with: - pattern: cibw-* - path: dist - merge-multiple: true - - - name: Download all - uses: pypa/gh-action-pypi-publish@release/v1 - with: - repository-url: https://test.pypi.org/legacy/ - verbose: true - - # upload_pypi: + # upload_testpypi: # name: >- - # Publish highspy to PyPI + # Publish highspy to TestPyPI # runs-on: ubuntu-latest # needs: [build_wheels, build_sdist] + # # needs: [build_sdist] # # upload to PyPI on every tag starting with 'v' # # if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') # environment: - # name: pypi - # url: https://pypi.org/p/highspy + # name: testpypi + # url: https://test.pypi.org/p/highspy # permissions: # id-token: write # IMPORTANT: mandatory for trusted publishing - # steps: # - uses: actions/download-artifact@v4 # with: @@ -136,3 +93,32 @@ jobs: # - name: Download all # uses: pypa/gh-action-pypi-publish@release/v1 + # with: + # repository-url: https://test.pypi.org/legacy/ + # verbose: true + + upload_pypi: + name: >- + Publish highspy to PyPI + runs-on: ubuntu-latest + needs: [build_wheels, build_sdist] + + # upload to PyPI on every tag starting with 'v' + # if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') + + environment: + name: pypi + url: https://pypi.org/p/highspy + + permissions: + id-token: write # IMPORTANT: mandatory for trusted publishing + + steps: + - uses: actions/download-artifact@v4 + with: + pattern: cibw-* + path: dist + merge-multiple: true + + - name: Download all + uses: pypa/gh-action-pypi-publish@release/v1 diff --git a/.github/workflows/build-wheels.yml b/.github/workflows/build-wheels.yml index 25819ad7e0..02ad4908c8 100644 --- a/.github/workflows/build-wheels.yml +++ b/.github/workflows/build-wheels.yml @@ -32,12 +32,12 @@ jobs: # Github Actions doesn't support pairing matrix values together, let's improvise # https://github.com/github/feedback/discussions/7835#discussioncomment-1769026 buildplat: - - [ubuntu-20.04, manylinux_x86_64] - - [ubuntu-20.04, manylinux_i686] - - [ubuntu-20.04, manylinux_aarch64] - - [ubuntu-20.04, musllinux_x86_64] # No OpenBlas, no test - - [ubuntu-20.04, musllinux_i686] - - [ubuntu-20.04, musllinux_aarch64] + - [ubuntu-24.04, manylinux_x86_64] + - [ubuntu-24.04, manylinux_i686] + - [ubuntu-24.04-arm, manylinux_aarch64] + - [ubuntu-24.04, musllinux_x86_64] # No OpenBlas, no test + - [ubuntu-24.04, musllinux_i686] + - [ubuntu-24.04-arm, musllinux_aarch64] - [macos-13, macosx_x86_64] - [macos-14, macosx_arm64] - [windows-2019, win_amd64] @@ -46,21 +46,7 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Set up QEMU # Required for aarch64 builds - if: ${{ contains(matrix.buildplat[1], 'aarch64') }} - uses: docker/setup-qemu-action@v3 - with: - platforms: all - - - name: Build wheels (aarch64) - if: ${{ contains(matrix.buildplat[1], 'aarch64') }} - uses: pypa/cibuildwheel@v2.21 - env: - CIBW_BUILD: ${{ matrix.python }}-${{ matrix.buildplat[1] }} - CIBW_ARCHS_LINUX: aarch64 - - - name: Build wheels (not aarch64) - if: ${{ !contains(matrix.buildplat[1], 'aarch64') }} + - name: Build wheels uses: pypa/cibuildwheel@v2.21 env: CIBW_BUILD: ${{ matrix.python }}-${{ matrix.buildplat[1] }} diff --git a/.github/workflows/code-coverage.yml b/.github/workflows/code-coverage.yml new file mode 100644 index 0000000000..ab8d51dc6d --- /dev/null +++ b/.github/workflows/code-coverage.yml @@ -0,0 +1,68 @@ +name: code-coverage + +on: [pull_request] + +jobs: + debug: + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest] + + steps: + - uses: actions/checkout@v4 + + - name: install + run: sudo apt-get update && sudo apt-get install lcov + + - name: Create Build Environment + run: cmake -E make_directory ${{runner.workspace}}/build + + - name: Configure CMake + shell: bash + working-directory: ${{runner.workspace}}/build + run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=Debug -DHIGHS_COVERAGE=ON -DALL_TESTS=ON -DBUILD_SHARED_LIBS=OFF -D CMAKE_C_COMPILER=gcc -D CMAKE_CXX_COMPILER=g++ + + - name: Build + working-directory: ${{runner.workspace}}/build + shell: bash + run: | + cmake --build . --parallel --config Debug + + - name: Test + working-directory: ${{runner.workspace}}/build + shell: bash + run: ctest --parallel --timeout 300 --output-on-failure + + - name: Generate Report + working-directory: ${{runner.workspace}}/build + shell: bash + run: | + lcov -d . -c -o cov.info --ignore-errors empty + lcov --remove cov.info "/usr/include/*" -o cov.info + lcov --remove cov.info "/usr/lib/*" -o cov.info + lcov --remove cov.info "extern/pdqsort/*" -o cov.info + lcov --remove cov.info "extern/zstr/*" -o cov.info + lcov --remove cov.info "extern/catch*" -o cov.info + lcov --remove cov.info "app/cxxopts*" -o cov.info + lcov --remove cov.info "src/test*" -o cov.info + lcov --list cov.info + mv cov.info coverage.info + + - name: Genhtml Results Summary + working-directory: ${{runner.workspace}}/build + shell: bash + run: | + genhtml -o coverage coverage.info + + # Made it past the first token issue. + # May need some more time to porpagate on the codecov side. + - name: Upload coverage reports to Codecov + uses: codecov/codecov-action@v5 + with: + token: ${{ secrets.CODECOV_TOKEN }} + slug: ERGO-Code/HiGHS + fail_ci_if_error: true # optional (default = false) + files: ${{runner.workspace}}/build/coverage.info # optional + # name: codecov-umbrella # optional + verbose: true # optional (default = false) \ No newline at end of file diff --git a/.gitignore b/.gitignore index 096bc893e1..c36222e48d 100644 --- a/.gitignore +++ b/.gitignore @@ -230,6 +230,7 @@ pip-log.txt # Unit test / coverage reports .coverage +cov.info .tox #Translations diff --git a/CMakeLists.txt b/CMakeLists.txt index d27135425b..bc5ca6b65a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -103,6 +103,8 @@ if (PYTHON_BUILD_SETUP) set(ZLIB OFF) endif() +option(HIGHS_COVERAGE "Activate the code coverage compilation" OFF) + # Address | Thread | Leak # Linux atm # Only Debug is theted atm @@ -187,6 +189,14 @@ if (BUILD_CXX) option(STDCALL "Build highs with the __stdcall convention" OFF) endif() + if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR + CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR + CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + elseif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++11") + endif() + # Basic type include(CMakePushCheckState) cmake_push_check_state(RESET) @@ -320,16 +330,18 @@ if(NOT FAST_BUILD) endif() include(CheckCXXCompilerFlag) -if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(ppc64|powerpc64)" AND NOT APPLE) - check_cxx_compiler_flag("-mpopcntd" COMPILER_SUPPORTS_POPCNTD) - if(COMPILER_SUPPORTS_POPCNTD) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mpopcntd") - endif() -else() - check_cxx_compiler_flag("-mpopcnt" COMPILER_SUPPORTS_POPCNT) - if(COMPILER_SUPPORTS_POPCNT) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mpopcnt") - endif() +if (NOT HIGHS_COVERAGE AND NOT APPLE) + if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(ppc64|powerpc64)") + check_cxx_compiler_flag("-mpopcntd" COMPILER_SUPPORTS_POPCNTD) + if(COMPILER_SUPPORTS_POPCNTD) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mpopcntd") + endif() + else() + check_cxx_compiler_flag("-mpopcnt" COMPILER_SUPPORTS_POPCNT) + if(COMPILER_SUPPORTS_POPCNT) + add_compile_options(-mpopcnt) + endif() + endif() endif() option(DEBUGSOL "check the debug solution" OFF) @@ -465,6 +477,58 @@ elseif (DEBUG_MEMORY STREQUAL "Leak") -fno-omit-frame-pointer ") endif() +# HiGHS coverage update in progress +if(FAST_BUILD AND HIGHS_COVERAGE) + if(WIN32) + message(FATAL_ERROR "Error: code coverage analysis is only available under Linux for now.") + endif() + + if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug") + message(FATAL_ERROR "Warning: to enable coverage, you must compile in Debug mode") + endif() + + # Disable IPO + set(CMAKE_INTERPROCEDURAL_OPTIMIZATION OFF) + message(STATUS "Building in coverage mode") + + # Enable coverage flags + add_compile_options(-O0) + add_compile_options(--coverage) + add_compile_options(-fprofile-update=atomic) + + add_link_options(-O0) + add_link_options(--coverage) # Ensure coverage data is linked correctly + + find_program(GCOV_PATH gcov) + find_program(LCOV_PATH lcov) + find_program(GENHTML_PATH genhtml) + + if(NOT GCOV_PATH) + message(FATAL_ERROR "gcov not found! Please install lcov and gcov. Aborting...") + endif() + + if(NOT LCOV_PATH) + message(FATAL_ERROR "lcov not found! Please install lcov and gcov. Aborting...") + endif() + + if(NOT GENHTML_PATH) + message(FATAL_ERROR "genhtml not found! Please install lcov and gcov. Aborting...") + endif() + + # add_custom_target(coverage + # COMMAND ${LCOV_PATH} -d bin -c -o cov.info --ignore-errors empty + # COMMAND ${LCOV_PATH} --remove "*/usr/include/*" -o ${CMAKE_BINARY_DIR}/cov.info.cleaned + # COMMAND ${LCOV_PATH} --remove "*/usr/lib/*" -o ${CMAKE_BINARY_DIR}/cov.info.cleaned + # COMMAND ${LCOV_PATH} --remove "extern/pdqsort/*" -o ${CMAKE_BINARY_DIR}/cov.info.cleaned + # COMMAND ${LCOV_PATH} --remove "extern/zstr/*" -o ${CMAKE_BINARY_DIR}/cov.info.cleaned + # COMMAND ${LCOV_PATH} --remove "app/cxxopts*" -o ${CMAKE_BINARY_DIR}/cov.info.cleaned + # COMMAND ${GENHTML_PATH} ${CMAKE_BINARY_DIR}/cov.info.cleaned -o ${CMAKE_BINARY_DIR}/cov_report + # VERBATIM + # WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + # COMMENT "Generating code coverage report v2025.") + +endif() + if(NOT FAST_BUILD) # For the moment keep above coverage part in case we are testing at CI. option(CI "CI extended tests" ON) @@ -487,7 +551,7 @@ if(NOT FAST_BUILD) endif() if(HIGHS_COVERAGE) - if(NOT CMAKE_BUILD_TYPE STREQUAL "DEBUG") + if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug" AND NOT CMAKE_BUILD_TYPE STREQUAL "DEBUG") message(FATAL_ERROR "Warning: to enable coverage, you must compile in DEBUG mode") endif() endif() diff --git a/FEATURES.md b/FEATURES.md index 40d6292050..b3d184e3e8 100644 --- a/FEATURES.md +++ b/FEATURES.md @@ -1,16 +1,33 @@ ## Build changes -Python: Source Distribution update, added to PyPI +Added code coverage report ## Code changes -HiGHS now handles multiple linear objectives by either blending using weights, or performing lexicographic optimization: see https://ergo-code.github.io/HiGHS/stable/guide/further/#guide-multi-objective-optimization +Any LP offset is communicated to the IPM solver, and used in logging and primal/dual objective calculations. -Fixed minor bug in bound checking in presolve +If there is a valid basis when Highs::run() is called, presolve isn't skipped unless the solver option is "simplex" or "choose" (when simplex will always be chosen if there is an advanced basis). -Fixed bug in `floor(HighsCDouble x)` and `ceil(HighsCDouble x)` when argument is small +Added basis solve methods to highspy + +Added methods to get primal/dual ray and dual unboundedness direction to highspy + +When a presolved LP has model status kUnknown, rather than returning this to the user, it performs postsolve and then uses the basis to solve the original LP + +Fixed bug in presolve when pointers stored in HighsMatrixSlice get invalidated when the coefficient matrix is reallocated (e.g. when non-zeros are added in HPresolve::addToMatrix) + +Primal and dual residual tolerances - applied following IPM or PDLP solution - now documented as options + +Highs::getCols (Highs::getRows) now runs in linear time if the internal constraint matrix is stored column-wise (row-wise). Added ensureColwise/Rowwise to the Highs class, the C API and highspy so that users can set the internal constraint matrix storage orientation + +When columns and rows are deleted from the incumbent LP after a basic solution has been found, HiGHS no longer invalidates the basis. Now it maintains the basic and nonbasic status of the remaining variables and constraints. When the model is re-solved, this information is used to construct a starting basis. + +Fixed bugs in presolve + +When running from the command lin, changes to default option values are reported + +Added callback to allow users to supply integer feasible solutions to the MIP solver during execution -Added some sanity checks to Highs::writeLocalModel to prevent segfaults if called directly by a user diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index 78a96e4d12..e26139c4bd 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -54,10 +54,6 @@ else() target_link_libraries(highs libhighs) - if(EMSCRIPTEN AND EMSCRIPTEN_HTML) - set(CMAKE_EXECUTABLE_SUFFIX ".html") - set_target_properties(highs PROPERTIES LINK_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/highs_webdemo_shell.html) - endif() target_include_directories(highs PRIVATE $ @@ -66,4 +62,10 @@ else() # install the binary install(TARGETS highs EXPORT highs-targets RUNTIME) +endif() + +# Add demo to FAST_BUILD as well. +if(EMSCRIPTEN AND EMSCRIPTEN_HTML) + set(CMAKE_EXECUTABLE_SUFFIX ".html") + set_target_properties(highs PROPERTIES LINK_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/highs_webdemo_shell.html) endif() \ No newline at end of file diff --git a/app/HighsRuntimeOptions.h b/app/HighsRuntimeOptions.h index 04d3133e4b..2892a2fa86 100644 --- a/app/HighsRuntimeOptions.h +++ b/app/HighsRuntimeOptions.h @@ -145,7 +145,7 @@ bool loadOptions(const HighsLogOptions& report_log_options, int argc, case HighsLoadOptionsStatus::kError: return false; case HighsLoadOptionsStatus::kEmpty: - writeOptionsToFile(stdout, options.records); + writeOptionsToFile(stdout, options.log_options, options.records); return false; default: break; diff --git a/app/RunHighs.cpp b/app/RunHighs.cpp index 8813755b4c..b5830bc370 100644 --- a/app/RunHighs.cpp +++ b/app/RunHighs.cpp @@ -47,6 +47,7 @@ int main(int argc, char** argv) { // settings defined in any options file. highs.passOptions(loaded_options); // highs.writeOptions("Options.md"); + highs.writeOptions("", true); // Load the model from model_file HighsStatus read_status = highs.readModel(model_file); diff --git a/app/cxxopts.hpp b/app/cxxopts.hpp index 30575e4659..5bef619c8f 100644 --- a/app/cxxopts.hpp +++ b/app/cxxopts.hpp @@ -2875,4 +2875,4 @@ Options::group_help(const std::string& group) const } // namespace cxxopts -#endif //CXXOPTS_HPP_INCLUDED \ No newline at end of file +#endif //CXXOPTS_HPP_INCLUDED diff --git a/check/Avgas.cpp b/check/Avgas.cpp index fb64f348fd..256321063d 100644 --- a/check/Avgas.cpp +++ b/check/Avgas.cpp @@ -15,324 +15,231 @@ #include #include // For printf +#include "lp_data/HConst.h" + const bool dev_run = false; -void Avgas::row(HighsInt row, HighsInt& num_row, HighsInt& num_row_nz, - std::vector& rowLower, std::vector& rowUpper, - std::vector& ARstart, std::vector& ARindex, - std::vector& ARvalue) { - rowLower.resize(num_row + 1); - rowUpper.resize(num_row + 1); - ARstart.resize(num_row + 1); - ARstart[num_row] = num_row_nz; +void Avgas::addRow(const HighsInt row, HighsInt& num_row, HighsInt& num_row_nz, + std::vector& rowLower, std::vector& rowUpper, + std::vector& ARstart, + std::vector& ARindex, + std::vector& ARvalue) { + double lower; + double upper; + std::vector index; + std::vector value; + getRow(row, lower, upper, index, value); + rowLower.push_back(lower); + rowUpper.push_back(upper); + HighsInt num_nz = index.size(); + ARstart.push_back(num_row_nz); + assert(HighsInt(ARstart.size()) == num_row + 1); + for (HighsInt iEl = 0; iEl < num_nz; iEl++) { + ARvalue.push_back(value[iEl]); + ARindex.push_back(index[iEl]); + } + num_row++; + num_row_nz += num_nz; +} + +void Avgas::getRow(const HighsInt row, double& lower, double& upper, + std::vector& index, std::vector& value) { + index.clear(); + value.clear(); + upper = kHighsInf; if (row == 0) { - rowLower[num_row] = -1; - rowUpper[num_row] = 1e31; - HighsInt num_new_nz = 2; - ARindex.resize(num_row_nz + num_new_nz); - ARvalue.resize(num_row_nz + num_new_nz); - ARindex[num_row_nz] = 0; - ARvalue[num_row_nz] = -1; - num_row_nz++; - ARindex[num_row_nz] = 1; - ARvalue[num_row_nz] = -1; - num_row_nz++; + lower = -1; + index.push_back(0); + value.push_back(-1); + index.push_back(1); + value.push_back(-1); } else if (row == 1) { - rowLower[num_row] = -1; - rowUpper[num_row] = 1e31; - HighsInt num_new_nz = 2; - ARindex.resize(num_row_nz + num_new_nz); - ARvalue.resize(num_row_nz + num_new_nz); - ARindex[num_row_nz] = 2; - ARvalue[num_row_nz] = -1; - num_row_nz++; - ARindex[num_row_nz] = 3; - ARvalue[num_row_nz] = -1; - num_row_nz++; + lower = -1; + index.push_back(2); + value.push_back(-1); + index.push_back(3); + value.push_back(-1); } else if (row == 2) { - rowLower[num_row] = -1; - rowUpper[num_row] = 1e31; - HighsInt num_new_nz = 2; - ARindex.resize(num_row_nz + num_new_nz); - ARvalue.resize(num_row_nz + num_new_nz); - ARindex[num_row_nz] = 4; - ARvalue[num_row_nz] = -1; - num_row_nz++; - ARindex[num_row_nz] = 5; - ARvalue[num_row_nz] = -1; - num_row_nz++; + lower = -1; + index.push_back(4); + value.push_back(-1); + index.push_back(5); + value.push_back(-1); } else if (row == 3) { - rowLower[num_row] = -1; - rowUpper[num_row] = 1e31; - HighsInt num_new_nz = 2; - ARindex.resize(num_row_nz + num_new_nz); - ARvalue.resize(num_row_nz + num_new_nz); - ARindex[num_row_nz] = 6; - ARvalue[num_row_nz] = -1; - num_row_nz++; - ARindex[num_row_nz] = 7; - ARvalue[num_row_nz] = -1; - num_row_nz++; + lower = -1; + index.push_back(6); + value.push_back(-1); + index.push_back(7); + value.push_back(-1); } else if (row == 4) { - rowLower[num_row] = -2; - rowUpper[num_row] = 1e31; - HighsInt num_new_nz = 4; - ARindex.resize(num_row_nz + num_new_nz); - ARvalue.resize(num_row_nz + num_new_nz); - ARindex[num_row_nz] = 0; - ARvalue[num_row_nz] = -1; - num_row_nz++; - ARindex[num_row_nz] = 2; - ARvalue[num_row_nz] = -1; - num_row_nz++; - ARindex[num_row_nz] = 4; - ARvalue[num_row_nz] = -1; - num_row_nz++; - ARindex[num_row_nz] = 6; - ARvalue[num_row_nz] = -1; - num_row_nz++; + lower = -2; + index.push_back(0); + value.push_back(-1); + index.push_back(2); + value.push_back(-1); + index.push_back(4); + value.push_back(-1); + index.push_back(6); + value.push_back(-1); } else if (row == 5) { - rowLower[num_row] = -2; - rowUpper[num_row] = 1e31; - HighsInt num_new_nz = 4; - ARindex.resize(num_row_nz + num_new_nz); - ARvalue.resize(num_row_nz + num_new_nz); - ARindex[num_row_nz] = 1; - ARvalue[num_row_nz] = -1; - num_row_nz++; - ARindex[num_row_nz] = 3; - ARvalue[num_row_nz] = -1; - num_row_nz++; - ARindex[num_row_nz] = 5; - ARvalue[num_row_nz] = -1; - num_row_nz++; - ARindex[num_row_nz] = 7; - ARvalue[num_row_nz] = -1; - num_row_nz++; + lower = -2; + index.push_back(1); + value.push_back(-1); + index.push_back(3); + value.push_back(-1); + index.push_back(5); + value.push_back(-1); + index.push_back(7); + value.push_back(-1); } else if (row == 6) { - rowLower[num_row] = 0; - rowUpper[num_row] = 1e31; - HighsInt num_new_nz = 3; - ARindex.resize(num_row_nz + num_new_nz); - ARvalue.resize(num_row_nz + num_new_nz); - ARindex[num_row_nz] = 0; - ARvalue[num_row_nz] = 2; - num_row_nz++; - ARindex[num_row_nz] = 2; - ARvalue[num_row_nz] = 1; - num_row_nz++; - ARindex[num_row_nz] = 6; - ARvalue[num_row_nz] = -1; - num_row_nz++; + lower = 0; + index.push_back(0); + value.push_back(2); + index.push_back(2); + value.push_back(1); + index.push_back(6); + value.push_back(-1); } else if (row == 7) { - rowLower[num_row] = 0; - rowUpper[num_row] = 1e31; - HighsInt num_new_nz = 4; - ARindex.resize(num_row_nz + num_new_nz); - ARvalue.resize(num_row_nz + num_new_nz); - ARindex[num_row_nz] = 0; - ARvalue[num_row_nz] = 5; - num_row_nz++; - ARindex[num_row_nz] = 2; - ARvalue[num_row_nz] = 3; - num_row_nz++; - ARindex[num_row_nz] = 4; - ARvalue[num_row_nz] = -3; - num_row_nz++; - ARindex[num_row_nz] = 6; - ARvalue[num_row_nz] = -1; - num_row_nz++; + lower = 0; + index.push_back(0); + value.push_back(5); + index.push_back(2); + value.push_back(3); + index.push_back(4); + value.push_back(-3); + index.push_back(6); + value.push_back(-1); } else if (row == 8) { - rowLower[num_row] = 0; - rowUpper[num_row] = 1e31; - HighsInt num_new_nz = 4; - ARindex.resize(num_row_nz + num_new_nz); - ARvalue.resize(num_row_nz + num_new_nz); - ARindex[num_row_nz] = 1; - ARvalue[num_row_nz] = 1; - num_row_nz++; - ARindex[num_row_nz] = 3; - ARvalue[num_row_nz] = -1; - num_row_nz++; - ARindex[num_row_nz] = 5; - ARvalue[num_row_nz] = -3; - num_row_nz++; - ARindex[num_row_nz] = 7; - ARvalue[num_row_nz] = -5; - num_row_nz++; + lower = 0; + index.push_back(1); + value.push_back(1); + index.push_back(3); + value.push_back(-1); + index.push_back(5); + value.push_back(-3); + index.push_back(7); + value.push_back(-5); } else if (row == 9) { - rowLower[num_row] = 0; - rowUpper[num_row] = 1e31; - HighsInt num_new_nz = 3; - ARindex.resize(num_row_nz + num_new_nz); - ARvalue.resize(num_row_nz + num_new_nz); - ARindex[num_row_nz] = 1; - ARvalue[num_row_nz] = 1; - num_row_nz++; - ARindex[num_row_nz] = 5; - ARvalue[num_row_nz] = -3; - num_row_nz++; - ARindex[num_row_nz] = 7; - ARvalue[num_row_nz] = -2; - num_row_nz++; + lower = 0; + index.push_back(1); + value.push_back(1); + index.push_back(5); + value.push_back(-3); + index.push_back(7); + value.push_back(-2); } else { - if (dev_run) printf("Avgas: row %" HIGHSINT_FORMAT " out of range\n", row); + if (dev_run) printf("Avgas: row %d out of range\n", static_cast(row)); } - num_row++; } -void Avgas::col(HighsInt col, HighsInt& num_col, HighsInt& num_col_nz, - std::vector& colCost, std::vector& colLower, - std::vector& colUpper, std::vector& Astart, - std::vector& Aindex, std::vector& Avalue) { - colCost.resize(num_col + 1); - colLower.resize(num_col + 1); - colUpper.resize(num_col + 1); - Astart.resize(num_col + 1); - Astart[num_col] = num_col_nz; - HighsInt num_new_nz = 4; +void Avgas::addCol(HighsInt col, HighsInt& num_col, HighsInt& num_col_nz, + std::vector& colCost, std::vector& colLower, + std::vector& colUpper, std::vector& Astart, + std::vector& Aindex, std::vector& Avalue) { + double cost; + double lower; + double upper; + std::vector index; + std::vector value; + getCol(col, cost, lower, upper, index, value); + colCost.push_back(cost); + colLower.push_back(lower); + colUpper.push_back(upper); + HighsInt num_nz = index.size(); + Astart.push_back(num_col_nz); + assert(HighsInt(Astart.size()) == num_col + 1); + for (HighsInt iEl = 0; iEl < num_nz; iEl++) { + Avalue.push_back(value[iEl]); + Aindex.push_back(index[iEl]); + } + num_col++; + num_col_nz += num_nz; +} + +void Avgas::getCol(const HighsInt col, double& cost, double& lower, + double& upper, std::vector& index, + std::vector& value) { + index.clear(); + value.clear(); + lower = 0; + upper = 1; if (col == 0) { - colCost[num_col] = 0; - colLower[num_col] = 0; - colUpper[num_col] = 1; - Aindex.resize(num_col_nz + num_new_nz); - Avalue.resize(num_col_nz + num_new_nz); - Aindex[num_col_nz] = 0; - Avalue[num_col_nz] = -1; - num_col_nz++; - Aindex[num_col_nz] = 4; - Avalue[num_col_nz] = -1; - num_col_nz++; - Aindex[num_col_nz] = 6; - Avalue[num_col_nz] = 2; - num_col_nz++; - Aindex[num_col_nz] = 7; - Avalue[num_col_nz] = 5; - num_col_nz++; + cost = 0; + index.push_back(0); + value.push_back(-1); + index.push_back(4); + value.push_back(-1); + index.push_back(6); + value.push_back(2); + index.push_back(7); + value.push_back(5); } else if (col == 1) { - colCost[num_col] = -2; - colLower[num_col] = 0; - colUpper[num_col] = 1; - Aindex.resize(num_col_nz + num_new_nz); - Avalue.resize(num_col_nz + num_new_nz); - Aindex[num_col_nz] = 0; - Avalue[num_col_nz] = -1; - num_col_nz++; - Aindex[num_col_nz] = 5; - Avalue[num_col_nz] = -1; - num_col_nz++; - Aindex[num_col_nz] = 8; - Avalue[num_col_nz] = 1; - num_col_nz++; - Aindex[num_col_nz] = 9; - Avalue[num_col_nz] = 1; - num_col_nz++; + cost = -2; + index.push_back(0); + value.push_back(-1); + index.push_back(5); + value.push_back(-1); + index.push_back(8); + value.push_back(1); + index.push_back(9); + value.push_back(1); } else if (col == 2) { - colCost[num_col] = -1; - colLower[num_col] = 0; - colUpper[num_col] = 1; - Aindex.resize(num_col_nz + num_new_nz); - Avalue.resize(num_col_nz + num_new_nz); - Aindex[num_col_nz] = 1; - Avalue[num_col_nz] = -1; - num_col_nz++; - Aindex[num_col_nz] = 4; - Avalue[num_col_nz] = -1; - num_col_nz++; - Aindex[num_col_nz] = 6; - Avalue[num_col_nz] = 1; - num_col_nz++; - Aindex[num_col_nz] = 7; - Avalue[num_col_nz] = 3; - num_col_nz++; + cost = -1; + index.push_back(1); + value.push_back(-1); + index.push_back(4); + value.push_back(-1); + index.push_back(6); + value.push_back(1); + index.push_back(7); + value.push_back(3); } else if (col == 3) { - num_new_nz = 3; - colCost[num_col] = -3; - colLower[num_col] = 0; - colUpper[num_col] = 1; - Aindex.resize(num_col_nz + num_new_nz); - Avalue.resize(num_col_nz + num_new_nz); - Aindex[num_col_nz] = 1; - Avalue[num_col_nz] = -1; - num_col_nz++; - Aindex[num_col_nz] = 5; - Avalue[num_col_nz] = -1; - num_col_nz++; - Aindex[num_col_nz] = 8; - Avalue[num_col_nz] = -1; - num_col_nz++; + cost = -3; + index.push_back(1); + value.push_back(-1); + index.push_back(5); + value.push_back(-1); + index.push_back(8); + value.push_back(-1); } else if (col == 4) { - num_new_nz = 3; - colCost[num_col] = -2; - colLower[num_col] = 0; - colUpper[num_col] = 1; - Aindex.resize(num_col_nz + num_new_nz); - Avalue.resize(num_col_nz + num_new_nz); - Aindex[num_col_nz] = 2; - Avalue[num_col_nz] = -1; - num_col_nz++; - Aindex[num_col_nz] = 4; - Avalue[num_col_nz] = -1; - num_col_nz++; - Aindex[num_col_nz] = 7; - Avalue[num_col_nz] = -3; - num_col_nz++; + cost = -2; + index.push_back(2); + value.push_back(-1); + index.push_back(4); + value.push_back(-1); + index.push_back(7); + value.push_back(-3); } else if (col == 5) { - colCost[num_col] = -4; - colLower[num_col] = 0; - colUpper[num_col] = 1; - Aindex.resize(num_col_nz + num_new_nz); - Avalue.resize(num_col_nz + num_new_nz); - Aindex[num_col_nz] = 2; - Avalue[num_col_nz] = -1; - num_col_nz++; - Aindex[num_col_nz] = 5; - Avalue[num_col_nz] = -1; - num_col_nz++; - Aindex[num_col_nz] = 8; - Avalue[num_col_nz] = -3; - num_col_nz++; - Aindex[num_col_nz] = 9; - Avalue[num_col_nz] = -3; - num_col_nz++; + cost = -4; + index.push_back(2); + value.push_back(-1); + index.push_back(5); + value.push_back(-1); + index.push_back(8); + value.push_back(-3); + index.push_back(9); + value.push_back(-3); } else if (col == 6) { - colCost[num_col] = -3; - colLower[num_col] = 0; - colUpper[num_col] = 1; - Aindex.resize(num_col_nz + num_new_nz); - Avalue.resize(num_col_nz + num_new_nz); - Aindex[num_col_nz] = 3; - Avalue[num_col_nz] = -1; - num_col_nz++; - Aindex[num_col_nz] = 4; - Avalue[num_col_nz] = -1; - num_col_nz++; - Aindex[num_col_nz] = 6; - Avalue[num_col_nz] = -1; - num_col_nz++; - Aindex[num_col_nz] = 7; - Avalue[num_col_nz] = -1; - num_col_nz++; + cost = -3; + index.push_back(3); + value.push_back(-1); + index.push_back(4); + value.push_back(-1); + index.push_back(6); + value.push_back(-1); + index.push_back(7); + value.push_back(-1); } else if (col == 7) { - colCost[num_col] = -5; - colLower[num_col] = 0; - colUpper[num_col] = 1; - Aindex.resize(num_col_nz + num_new_nz); - Avalue.resize(num_col_nz + num_new_nz); - Aindex[num_col_nz] = 3; - Avalue[num_col_nz] = -1; - num_col_nz++; - Aindex[num_col_nz] = 5; - Avalue[num_col_nz] = -1; - num_col_nz++; - Aindex[num_col_nz] = 8; - Avalue[num_col_nz] = -5; - num_col_nz++; - Aindex[num_col_nz] = 9; - Avalue[num_col_nz] = -2; - num_col_nz++; + cost = -5; + index.push_back(3); + value.push_back(-1); + index.push_back(5); + value.push_back(-1); + index.push_back(8); + value.push_back(-5); + index.push_back(9); + value.push_back(-2); } else { - if (dev_run) printf("Avgas: col %" HIGHSINT_FORMAT " out of range\n", col); + if (dev_run) printf("Avgas: col %d out of range\n", static_cast(col)); } - num_col++; } diff --git a/check/Avgas.h b/check/Avgas.h index e34bbb1b61..6e7154cfc2 100644 --- a/check/Avgas.h +++ b/check/Avgas.h @@ -17,19 +17,28 @@ #include "util/HighsInt.h" +const HighsInt avgas_num_col = 8; +const HighsInt avgas_num_row = 10; + /** * @brief Utilities for tests with AVGAS */ class Avgas { public: - void row(HighsInt row, HighsInt& num_row, HighsInt& num_row_nz, - std::vector& rowLower, std::vector& rowUpper, - std::vector& ARstart, std::vector& ARindex, - std::vector& ARvalue); + void addRow(const HighsInt row, HighsInt& num_row, HighsInt& num_row_nz, + std::vector& rowLower, std::vector& rowUpper, + std::vector& ARstart, std::vector& ARindex, + std::vector& ARvalue); + + void getRow(const HighsInt row, double& lower, double& upper, + std::vector& index, std::vector& value); + + void addCol(const HighsInt col, HighsInt& num_col, HighsInt& num_col_nz, + std::vector& colCost, std::vector& colLower, + std::vector& colUpper, std::vector& Astart, + std::vector& Aindex, std::vector& Avalue); - void col(HighsInt col, HighsInt& num_col, HighsInt& num_col_nz, - std::vector& colCost, std::vector& colLower, - std::vector& colUpper, std::vector& Astart, - std::vector& Aindex, std::vector& Avalue); + void getCol(const HighsInt col, double& cost, double& lower, double& upper, + std::vector& index, std::vector& value); }; #endif /* SIMPLEX_AVGAS_H_ */ diff --git a/check/CMakeLists.txt b/check/CMakeLists.txt index b1076e1825..4ba1f995eb 100644 --- a/check/CMakeLists.txt +++ b/check/CMakeLists.txt @@ -129,25 +129,29 @@ if ((NOT FAST_BUILD OR ALL_TESTS) AND NOT (BUILD_EXTRA_UNIT_ONLY)) add_test(NAME capi_unit_tests COMMAND capi_unit_tests) # Check whether test executable builds OK. - add_test(NAME unit-test-build - COMMAND ${CMAKE_COMMAND} - --build ${HIGHS_BINARY_DIR} - --target unit_tests - # --config ${CMAKE_BUILD_TYPE} - ) - + if (NOT HIGHS_COVERAGE) + add_test(NAME unit-test-build + COMMAND ${CMAKE_COMMAND} + --build ${HIGHS_BINARY_DIR} + --target unit_tests + # --config ${CMAKE_BUILD_TYPE} + ) - # Avoid that several build jobs try to concurretly build. - set_tests_properties(unit-test-build - PROPERTIES - RESOURCE_LOCK unittestbin) + # Avoid that several build jobs try to concurretly build. + set_tests_properties(unit-test-build + PROPERTIES + RESOURCE_LOCK unittestbin) - # create a binary running all the tests in the executable - add_test(NAME unit_tests_all COMMAND unit_tests --success) - set_tests_properties(unit_tests_all - PROPERTIES - DEPENDS unit-test-build) - set_tests_properties(unit_tests_all PROPERTIES TIMEOUT 10000) + # create a binary running all the tests in the executable + add_test(NAME unit_tests_all COMMAND unit_tests --success) + set_tests_properties(unit_tests_all + PROPERTIES + DEPENDS unit-test-build) + set_tests_properties(unit_tests_all PROPERTIES TIMEOUT 10000) + else() + add_test(NAME unit_tests_all COMMAND unit_tests --success) + set_tests_properties(unit_tests_all PROPERTIES TIMEOUT 10000) + endif() # An individual test can be added with the command below but the approach # above with a single add_test for all the unit tests automatically detects all diff --git a/check/TestCallbacks.cpp b/check/TestCallbacks.cpp index d97bc0d271..6a23fd51c1 100644 --- a/check/TestCallbacks.cpp +++ b/check/TestCallbacks.cpp @@ -1,3 +1,4 @@ +// #include #include #include @@ -6,7 +7,7 @@ #include "catch.hpp" #include "lp_data/HighsCallback.h" -const bool dev_run = false; +const bool dev_run = false; // true;// const double egout_optimal_objective = 568.1007; const double egout_objective_target = 610; @@ -31,6 +32,12 @@ struct MipData { HighsVarType* integrality; }; +struct UserMipSolution { + double optimal_objective_value; + double* optimal_solution; + HighsInt require_user_solution_callback_origin; +}; + // Callback that saves message for comparison HighsCallbackFunctionType myLogCallback = [](int callback_type, const std::string& message, @@ -179,6 +186,30 @@ HighsCallbackFunctionType userMipCutPoolCallback = } }; +HighsCallbackFunctionType userkMipUserSolution = + [](int callback_type, const std::string& message, + const HighsCallbackDataOut* data_out, HighsCallbackDataIn* data_in, + void* user_callback_data) { + UserMipSolution callback_data = + *(static_cast(user_callback_data)); + if (data_out->user_solution_callback_origin == + callback_data.require_user_solution_callback_origin) { + if (data_out->mip_primal_bound > + callback_data.optimal_objective_value) { + // If current objective value is not optimal, pass the + // optimal solution as a user solution + if (dev_run) + printf( + "userkMipUserSolution: origin = %d; %g = mip_primal_bound > " + "optimal_objective_value = %g\n", + int(data_out->user_solution_callback_origin), + data_out->mip_primal_bound, + callback_data.optimal_objective_value); + data_in->user_solution = callback_data.optimal_solution; + } + } + }; + std::function userDataCallback = [](int callback_type, const std::string& message, @@ -375,8 +406,49 @@ TEST_CASE("highs-callback-mip-cut-pool", "[highs-callback]") { Highs highs; highs.setOptionValue("output_flag", dev_run); highs.readModel(filename); - // MipData user_callback_data; - highs.setCallback(userMipCutPoolCallback); //, p_user_callback_data); + highs.setCallback(userMipCutPoolCallback); highs.startCallback(kCallbackMipGetCutPool); highs.run(); } + +TEST_CASE("highs-callback-mip-user-solution", "[highs-callback]") { + // const std::vector model = {"rgn", "flugpl", "gt2", "egout", + // "bell5", "lseu", "sp150x300d"};//, "p0548", "dcmulti"}; const + // std::vector require_origin = {0, 1, 2, 3, 4, 5, 6}; + const std::vector model = {"p0548", "flugpl", "gt2", "egout", + "sp150x300d"}; + const std::vector require_origin = {0, 1, 2, 3, 4}; //, 4, 5, 6}; + assert(model.size() == require_origin.size()); + Highs highs; + highs.setOptionValue("output_flag", dev_run); + highs.setOptionValue("mip_rel_gap", 0); + HighsInt from_model = 0; + HighsInt to_model = HighsInt(model.size()); + for (HighsInt iModel = from_model; iModel < to_model; iModel++) { + const std::string filename = + std::string(HIGHS_DIR) + "/check/instances/" + model[iModel] + ".mps"; + highs.readModel(filename); + highs.run(); + std::vector optimal_solution = highs.getSolution().col_value; + double objective_function_value0 = highs.getInfo().objective_function_value; + highs.clearSolver(); + + UserMipSolution user_callback_data; + user_callback_data.optimal_objective_value = objective_function_value0; + user_callback_data.optimal_solution = optimal_solution.data(); + user_callback_data.require_user_solution_callback_origin = + require_origin[iModel]; + void* p_user_callback_data = (void*)(&user_callback_data); + + // highs.setOptionValue("presolve", kHighsOffString); + highs.setCallback(userkMipUserSolution, p_user_callback_data); + highs.startCallback(kCallbackMipUserSolution); + highs.run(); + highs.stopCallback(kCallbackMipUserSolution); + double objective_function_value1 = highs.getInfo().objective_function_value; + double objective_diff = + std::fabs(objective_function_value1 - objective_function_value0) / + std::max(1.0, std::fabs(objective_function_value0)); + REQUIRE(objective_diff < 1e-12); + } +} diff --git a/check/TestEkk.cpp b/check/TestEkk.cpp index 02a15eb47f..d5566b02ed 100644 --- a/check/TestEkk.cpp +++ b/check/TestEkk.cpp @@ -30,6 +30,7 @@ void ekk_solve(Highs& highs, std::string presolve, } REQUIRE(highs.resetOptions() == HighsStatus::kOk); + highs.setOptionValue("output_flag", dev_run); } void ekk_distillation(Highs& highs) { diff --git a/check/TestFilereader.cpp b/check/TestFilereader.cpp index 63fe50e8a2..e08eced444 100644 --- a/check/TestFilereader.cpp +++ b/check/TestFilereader.cpp @@ -416,3 +416,26 @@ TEST_CASE("writeLocalModel", "[highs_filereader]") { std::remove(write_model_file.c_str()); } + +TEST_CASE("write-MI-bound-model", "[highs_filereader]") { + std::string write_model_file = "temp.mps"; + Highs h; + h.setOptionValue("output_flag", dev_run); + h.addCol(1, -kHighsInf, 1, 0, nullptr, nullptr); + h.changeColIntegrality(0, HighsVarType::kInteger); + h.passColName(0, "x"); + std::vector index = {0}; + std::vector value = {1}; + h.addRow(-10, kHighsInf, 1, index.data(), value.data()); + h.passRowName(0, "r"); + h.run(); + double required_objective_value = h.getInfo().objective_function_value; + // writeModel must ensure that there is a line + // + // MI BOUND x + h.writeModel(write_model_file); + h.readModel(write_model_file); + h.run(); + REQUIRE(required_objective_value == h.getInfo().objective_function_value); + std::remove(write_model_file.c_str()); +} diff --git a/check/TestIpm.cpp b/check/TestIpm.cpp index cb2d1a3419..dd59b96aea 100644 --- a/check/TestIpm.cpp +++ b/check/TestIpm.cpp @@ -134,3 +134,22 @@ TEST_CASE("test-1966", "[highs_ipm]") { printf("Sum dual infeasibilities = %g\n", info.sum_dual_infeasibilities); } } + +TEST_CASE("test-2087", "[highs_ipm]") { + // Make sure that presolve is performed when re-solving using IPM, + // since optimal basis cannot be used, and ensure that the offset is + // used in IPX + Highs h; + h.setOptionValue("output_flag", dev_run); + // Use shell since it yields an offset after presolve + std::string model = "shell.mps"; + std::string filename = std::string(HIGHS_DIR) + "/check/instances/" + model; + h.readModel(filename); + + h.setOptionValue("solver", kIpmString); + h.run(); + const HighsInt first_ipm_iteration_count = h.getInfo().ipm_iteration_count; + + h.run(); + REQUIRE(first_ipm_iteration_count == h.getInfo().ipm_iteration_count); +} diff --git a/check/TestIpx.cpp b/check/TestIpx.cpp index 4866c746d3..a53a199710 100644 --- a/check/TestIpx.cpp +++ b/check/TestIpx.cpp @@ -22,6 +22,7 @@ using Int = ipxint; constexpr HighsInt num_var = 12; constexpr HighsInt num_constr = 9; +const double offset = 0; const double obj[] = {-0.2194, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.32, -0.5564, 0.6, -0.48}; const double lb[num_var] = {0.0}; @@ -47,8 +48,8 @@ TEST_CASE("test-ipx", "[highs_ipx]") { lps.SetParameters(parameters); // Solve the LP. - Int load_status = lps.LoadModel(num_var, obj, lb, ub, num_constr, Ap, Ai, Ax, - rhs, constr_type); + Int load_status = lps.LoadModel(num_var, offset, obj, lb, ub, num_constr, Ap, + Ai, Ax, rhs, constr_type); REQUIRE(load_status == 0); highs::parallel::initialize_scheduler(); diff --git a/check/TestLpModification.cpp b/check/TestLpModification.cpp index ea55d16264..9a443ea43f 100644 --- a/check/TestLpModification.cpp +++ b/check/TestLpModification.cpp @@ -5,6 +5,7 @@ #include "catch.hpp" #include "lp_data/HighsLpUtils.h" #include "util/HighsRandom.h" +#include "util/HighsTimer.h" #include "util/HighsUtils.h" const bool dev_run = false; @@ -38,6 +39,11 @@ bool areLpRowEqual(const HighsInt num_row0, const double* rowLower0, bool areLpEqual(const HighsLp lp0, const HighsLp lp1, const double infinite_bound); +bool equalSparseVectors(const HighsInt dim, const HighsInt num_nz0, + const HighsInt* index0, const double* value0, + const HighsInt num_nz1, const HighsInt* index1, + const double* value1); + void testDeleteKeep(const HighsIndexCollection& index_collection); bool testAllDeleteKeep(HighsInt num_row); @@ -425,8 +431,6 @@ TEST_CASE("LP-modification", "[highs_data]") { // options.log_dev_level = kHighsLogDevLevelVerbose; Avgas avgas; - const HighsInt avgas_num_col = 8; - const HighsInt avgas_num_row = 10; HighsInt num_row = 0; HighsInt num_row_nz = 0; std::vector rowLower; @@ -436,8 +440,8 @@ TEST_CASE("LP-modification", "[highs_data]") { std::vector ARvalue; for (HighsInt row = 0; row < avgas_num_row; row++) { - avgas.row(row, num_row, num_row_nz, rowLower, rowUpper, ARstart, ARindex, - ARvalue); + avgas.addRow(row, num_row, num_row_nz, rowLower, rowUpper, ARstart, ARindex, + ARvalue); } HighsInt num_col = 0; @@ -449,8 +453,8 @@ TEST_CASE("LP-modification", "[highs_data]") { std::vector Aindex; std::vector Avalue; for (HighsInt col = 0; col < avgas_num_col; col++) { - avgas.col(col, num_col, num_col_nz, colCost, colLower, colUpper, Astart, - Aindex, Avalue); + avgas.addCol(col, num_col, num_col_nz, colCost, colLower, colUpper, Astart, + Aindex, Avalue); } HighsStatus return_status; @@ -1876,6 +1880,39 @@ TEST_CASE("mod-duplicate-indices", "[highs_data]") { REQUIRE(objective0 == -7.75); } +bool equalSparseVectors(const HighsInt dim, const HighsInt num_nz0, + const HighsInt* index0, const double* value0, + const HighsInt num_nz1, const HighsInt* index1, + const double* value1) { + if (num_nz0 != num_nz1) { + if (dev_run) printf("num_nz0 != num_nz1\n"); + return false; + } + std::vector full_vector; + full_vector.assign(dim, 0); + for (HighsInt iEl = 0; iEl < num_nz0; iEl++) + full_vector[index0[iEl]] = value0[iEl]; + for (HighsInt iEl = 0; iEl < num_nz1; iEl++) { + HighsInt iRow = index1[iEl]; + if (full_vector[iRow] != value1[iEl]) { + if (dev_run) + printf("vector0[%d] = %g <> %g = vector1[%d]\n", int(iRow), + full_vector[iRow], value1[iEl], int(iRow)); + return false; + } + + full_vector[iRow] = 0; + } + for (HighsInt iRow = 0; iRow < dim; iRow++) + if (full_vector[iRow]) { + if (dev_run) + printf("Full vector[%d] = %g, not zero\n", int(iRow), + full_vector[iRow]); + return false; + } + return true; +} + TEST_CASE("resize-integrality", "[highs_data]") { Highs highs; highs.setOptionValue("output_flag", dev_run); @@ -1954,3 +1991,487 @@ TEST_CASE("zero-matrix-entries", "[highs_data]") { lp.a_matrix_.value_ = {1, 0, 0, 1}; REQUIRE(highs.passModel(lp) == HighsStatus::kOk); } + +void testAvgasGetRow(Highs& h) { + Avgas avgas; + double cost; + double lower; + double upper; + std::vector index; + std::vector value; + HighsInt get_num; + HighsInt lp_nnz; + std::vector lp_cost(1); + std::vector lp_lower(1); + std::vector lp_upper(1); + std::vector lp_start(1); + std::vector lp_index(avgas_num_col); + std::vector lp_value(avgas_num_col); + std::vector set(1); + std::vector mask(avgas_num_row); + for (HighsInt row = 0; row < avgas_num_row; row++) { + avgas.getRow(row, lower, upper, index, value); + HighsInt avgas_nnz = index.size(); + h.getRows(row, row, get_num, lp_lower.data(), lp_upper.data(), lp_nnz, + lp_start.data(), lp_index.data(), lp_value.data()); + REQUIRE(lp_lower[0] == lower); + REQUIRE(lp_upper[0] == upper); + REQUIRE(equalSparseVectors(avgas_num_col, avgas_nnz, index.data(), + value.data(), lp_nnz, lp_index.data(), + lp_value.data())); + } + HighsInt from_row = 2; + HighsInt to_row = 5; + HighsInt num_row = to_row - from_row + 1; + lp_lower.resize(num_row); + lp_upper.resize(num_row); + lp_start.resize(num_row); + lp_index.resize(num_row * avgas_num_col); + lp_value.resize(num_row * avgas_num_col); + h.getRows(from_row, to_row, get_num, lp_lower.data(), lp_upper.data(), lp_nnz, + lp_start.data(), lp_index.data(), lp_value.data()); + REQUIRE(get_num == num_row); + for (HighsInt row = 0; row < num_row; row++) { + HighsInt avgas_row = from_row + row; + avgas.getRow(avgas_row, lower, upper, index, value); + HighsInt avgas_nnz = index.size(); + REQUIRE(lp_lower[row] == lower); + REQUIRE(lp_upper[row] == upper); + HighsInt from_el = lp_start[row]; + HighsInt lp_col_nnz = + row < num_row - 1 ? lp_start[row + 1] - from_el : lp_nnz - from_el; + REQUIRE(equalSparseVectors(avgas_num_col, avgas_nnz, index.data(), + value.data(), lp_col_nnz, &lp_index[from_el], + &lp_value[from_el])); + } + set = {1, 2, 3, 6, 7}; + num_row = set.size(); + lp_lower.resize(num_row); + lp_upper.resize(num_row); + lp_start.resize(num_row); + lp_index.resize(num_row * avgas_num_col); + lp_value.resize(num_row * avgas_num_col); + h.getRows(num_row, set.data(), get_num, lp_lower.data(), lp_upper.data(), + lp_nnz, lp_start.data(), lp_index.data(), lp_value.data()); + REQUIRE(get_num == num_row); + for (HighsInt row = 0; row < num_row; row++) { + HighsInt avgas_row = set[row]; + avgas.getRow(avgas_row, lower, upper, index, value); + HighsInt avgas_nnz = index.size(); + REQUIRE(lp_lower[row] == lower); + REQUIRE(lp_upper[row] == upper); + HighsInt from_el = lp_start[row]; + HighsInt lp_col_nnz = + row < num_row - 1 ? lp_start[row + 1] - from_el : lp_nnz - from_el; + REQUIRE(equalSparseVectors(avgas_num_col, avgas_nnz, index.data(), + value.data(), lp_col_nnz, &lp_index[from_el], + &lp_value[from_el])); + } + mask[0] = 1; + mask[1] = 1; + mask[4] = 1; + mask[6] = 1; + mask[7] = 1; + num_row = 5; + lp_lower.resize(num_row); + lp_upper.resize(num_row); + lp_start.resize(num_row); + lp_index.resize(num_row * avgas_num_col); + lp_value.resize(num_row * avgas_num_col); + h.getRows(mask.data(), get_num, lp_lower.data(), lp_upper.data(), lp_nnz, + lp_start.data(), lp_index.data(), lp_value.data()); + REQUIRE(get_num == num_row); + HighsInt row = 0; + for (HighsInt iRow = 0; iRow < avgas_num_row; iRow++) { + if (!mask[iRow]) continue; + HighsInt avgas_row = iRow; + avgas.getRow(avgas_row, lower, upper, index, value); + HighsInt avgas_nnz = index.size(); + REQUIRE(lp_lower[row] == lower); + REQUIRE(lp_upper[row] == upper); + HighsInt from_el = lp_start[row]; + HighsInt lp_col_nnz = + row < num_row - 1 ? lp_start[row + 1] - from_el : lp_nnz - from_el; + REQUIRE(equalSparseVectors(avgas_num_col, avgas_nnz, index.data(), + value.data(), lp_col_nnz, &lp_index[from_el], + &lp_value[from_el])); + row++; + } +} + +void testAvgasGetCol(Highs& h) { + Avgas avgas; + double cost; + double lower; + double upper; + std::vector index; + std::vector value; + HighsInt get_num; + HighsInt lp_nnz; + std::vector lp_cost(1); + std::vector lp_lower(1); + std::vector lp_upper(1); + std::vector lp_start(1); + std::vector lp_index(avgas_num_row); + std::vector lp_value(avgas_num_row); + std::vector set(1); + std::vector mask(avgas_num_col); + mask.assign(avgas_num_col, 0); + for (HighsInt col = 0; col < avgas_num_col; col++) { + avgas.getCol(col, cost, lower, upper, index, value); + HighsInt avgas_nnz = index.size(); + h.getCols(col, col, get_num, lp_cost.data(), lp_lower.data(), + lp_upper.data(), lp_nnz, lp_start.data(), lp_index.data(), + lp_value.data()); + REQUIRE(lp_cost[0] == cost); + REQUIRE(lp_lower[0] == lower); + REQUIRE(lp_upper[0] == upper); + REQUIRE(equalSparseVectors(avgas_num_row, avgas_nnz, index.data(), + value.data(), lp_nnz, lp_index.data(), + lp_value.data())); + set[0] = col; + h.getCols(1, set.data(), get_num, lp_cost.data(), lp_lower.data(), + lp_upper.data(), lp_nnz, lp_start.data(), lp_index.data(), + lp_value.data()); + REQUIRE(lp_cost[0] == cost); + REQUIRE(lp_lower[0] == lower); + REQUIRE(lp_upper[0] == upper); + REQUIRE(equalSparseVectors(avgas_num_row, avgas_nnz, index.data(), + value.data(), lp_nnz, lp_index.data(), + lp_value.data())); + mask[col] = 1; + h.getCols(mask.data(), get_num, lp_cost.data(), lp_lower.data(), + lp_upper.data(), lp_nnz, lp_start.data(), lp_index.data(), + lp_value.data()); + REQUIRE(lp_cost[0] == cost); + REQUIRE(lp_lower[0] == lower); + REQUIRE(lp_upper[0] == upper); + REQUIRE(equalSparseVectors(avgas_num_row, avgas_nnz, index.data(), + value.data(), lp_nnz, lp_index.data(), + lp_value.data())); + mask[col] = 0; + } + HighsInt from_col = 2; + HighsInt to_col = 5; + HighsInt num_col = to_col - from_col + 1; + lp_cost.resize(num_col); + lp_lower.resize(num_col); + lp_upper.resize(num_col); + lp_start.resize(num_col); + lp_index.resize(num_col * avgas_num_row); + lp_value.resize(num_col * avgas_num_row); + h.getCols(from_col, to_col, get_num, lp_cost.data(), lp_lower.data(), + lp_upper.data(), lp_nnz, lp_start.data(), lp_index.data(), + lp_value.data()); + REQUIRE(get_num == num_col); + for (HighsInt col = 0; col < num_col; col++) { + HighsInt avgas_col = from_col + col; + avgas.getCol(avgas_col, cost, lower, upper, index, value); + HighsInt avgas_nnz = index.size(); + REQUIRE(lp_cost[col] == cost); + REQUIRE(lp_lower[col] == lower); + REQUIRE(lp_upper[col] == upper); + HighsInt from_el = lp_start[col]; + HighsInt lp_row_nnz = + col < num_col - 1 ? lp_start[col + 1] - from_el : lp_nnz - from_el; + REQUIRE(equalSparseVectors(avgas_num_row, avgas_nnz, index.data(), + value.data(), lp_row_nnz, &lp_index[from_el], + &lp_value[from_el])); + } + set = {1, 2, 3, 6, 7}; + num_col = set.size(); + lp_cost.resize(num_col); + lp_lower.resize(num_col); + lp_upper.resize(num_col); + lp_start.resize(num_col); + lp_index.resize(num_col * avgas_num_row); + lp_value.resize(num_col * avgas_num_row); + h.getCols(num_col, set.data(), get_num, lp_cost.data(), lp_lower.data(), + lp_upper.data(), lp_nnz, lp_start.data(), lp_index.data(), + lp_value.data()); + REQUIRE(get_num == num_col); + for (HighsInt col = 0; col < num_col; col++) { + HighsInt avgas_col = set[col]; + avgas.getCol(avgas_col, cost, lower, upper, index, value); + HighsInt avgas_nnz = index.size(); + REQUIRE(lp_cost[col] == cost); + REQUIRE(lp_lower[col] == lower); + REQUIRE(lp_upper[col] == upper); + HighsInt from_el = lp_start[col]; + HighsInt lp_row_nnz = + col < num_col - 1 ? lp_start[col + 1] - from_el : lp_nnz - from_el; + REQUIRE(equalSparseVectors(avgas_num_row, avgas_nnz, index.data(), + value.data(), lp_row_nnz, &lp_index[from_el], + &lp_value[from_el])); + } + mask[0] = 1; + mask[1] = 1; + mask[4] = 1; + mask[6] = 1; + mask[7] = 1; + num_col = 5; + lp_cost.resize(num_col); + lp_lower.resize(num_col); + lp_upper.resize(num_col); + lp_start.resize(num_col); + lp_index.resize(num_col * avgas_num_row); + lp_value.resize(num_col * avgas_num_row); + h.getCols(mask.data(), get_num, lp_cost.data(), lp_lower.data(), + lp_upper.data(), lp_nnz, lp_start.data(), lp_index.data(), + lp_value.data()); + REQUIRE(get_num == num_col); + HighsInt col = 0; + for (HighsInt iCol = 0; iCol < avgas_num_col; iCol++) { + if (!mask[iCol]) continue; + HighsInt avgas_col = iCol; + avgas.getCol(avgas_col, cost, lower, upper, index, value); + HighsInt avgas_nnz = index.size(); + REQUIRE(lp_cost[col] == cost); + REQUIRE(lp_lower[col] == lower); + REQUIRE(lp_upper[col] == upper); + HighsInt from_el = lp_start[col]; + HighsInt lp_row_nnz = + col < num_col - 1 ? lp_start[col + 1] - from_el : lp_nnz - from_el; + REQUIRE(equalSparseVectors(avgas_num_row, avgas_nnz, index.data(), + value.data(), lp_row_nnz, &lp_index[from_el], + &lp_value[from_el])); + col++; + } +} + +TEST_CASE("row-wise-get-row-avgas", "[highs_data]") { + Avgas avgas; + const HighsInt avgas_num_col = 8; + const HighsInt avgas_num_row = 10; + + Highs h; + h.setOptionValue("output_flag", dev_run); + double cost; + double lower; + double upper; + std::vector index; + std::vector value; + + for (HighsInt col = 0; col < avgas_num_col; col++) { + avgas.getCol(col, cost, lower, upper, index, value); + REQUIRE(h.addCol(cost, lower, upper, 0, nullptr, nullptr) == + HighsStatus::kOk); + } + for (HighsInt row = 0; row < avgas_num_row; row++) { + avgas.getRow(row, lower, upper, index, value); + HighsInt avgas_nnz = index.size(); + REQUIRE(h.addRow(lower, upper, avgas_nnz, index.data(), value.data()) == + HighsStatus::kOk); + } + + // Test extraction of rows and columns, with rowwise and colwise + // internal storage + h.ensureRowwise(); + testAvgasGetRow(h); + testAvgasGetCol(h); + + h.ensureColwise(); + testAvgasGetRow(h); + testAvgasGetCol(h); +} + +TEST_CASE("hot-start-after-delete", "[highs_data]") { + Highs h; + h.setOptionValue("output_flag", dev_run); + const HighsLp& lp = h.getLp(); + const HighsInfo& info = h.getInfo(); + const HighsBasis& basis = h.getBasis(); + const HighsSolution& solution = h.getSolution(); + std::string model = "avgas"; + std::string model_file = + std::string(HIGHS_DIR) + "/check/instances/" + model + ".mps"; + h.readModel(model_file); + h.run(); + HighsInt ieration_count0 = info.simplex_iteration_count; + if (dev_run) + printf("Initial solve takes %d iterations and yields objective = %g\n", + int(info.simplex_iteration_count), info.objective_function_value); + + HighsInt max_dim = std::max(lp.num_col_, lp.num_row_); + std::vector cost(1); + std::vector lower(1); + std::vector upper(1); + HighsInt nnz; + std::vector start(1); + std::vector index(max_dim); + std::vector value(max_dim); + HighsInt get_num; + HighsInt use_col, use_row; + for (HighsInt k = 0; k < 2; k++) { + if (dev_run) { + for (HighsInt iCol = 0; iCol < lp.num_col_; iCol++) + printf("Col %2d is %s\n", int(iCol), + basis.col_status[iCol] == HighsBasisStatus::kBasic ? "basic" + : "nonbasic"); + printf("\n"); + } + if (k == 0) { + use_col = 1; // Nonbasic + } else { + use_col = 4; // Basic + } + if (dev_run) + printf( + "\nDeleting and adding column %1d with status \"%s\" and value %g\n", + int(use_col), + h.basisStatusToString(basis.col_status[use_col]).c_str(), + solution.col_value[use_col]); + + h.getCols(use_col, use_col, get_num, cost.data(), lower.data(), + upper.data(), nnz, start.data(), index.data(), value.data()); + + h.deleteCols(use_col, use_col); + if (dev_run) basis.printScalars(); + + h.addCol(cost[0], lower[0], upper[0], nnz, index.data(), value.data()); + + h.run(); + if (dev_run) + printf( + "After deleting and adding column %1d, solve takes %d iterations and " + "yields objective = %g\n", + int(use_col), int(info.simplex_iteration_count), + info.objective_function_value); + REQUIRE(info.simplex_iteration_count < ieration_count0); + } + + for (HighsInt k = 0; k < 2; k++) { + if (dev_run) { + for (HighsInt iRow = 0; iRow < lp.num_row_; iRow++) + printf("Row %2d is %s\n", int(iRow), + basis.row_status[iRow] == HighsBasisStatus::kBasic ? "basic" + : "nonbasic"); + } + if (k == 0) { + use_row = 1; // Nonbasic + } else { + use_row = 8; // Basic + } + if (dev_run) + printf("\nDeleting and adding row %1d with status \"%s\" and value %g\n", + int(use_row), + h.basisStatusToString(basis.row_status[use_row]).c_str(), + solution.row_value[use_row]); + + h.getRows(use_row, use_row, get_num, lower.data(), upper.data(), nnz, + start.data(), index.data(), value.data()); + + h.deleteRows(use_row, use_row); + if (dev_run) basis.printScalars(); + + h.addRow(lower[0], upper[0], nnz, index.data(), value.data()); + + h.run(); + if (dev_run) + printf( + "After deleting and adding row %1d, solve takes %d iterations and " + "yields objective = %g\n", + int(use_row), int(info.simplex_iteration_count), + info.objective_function_value); + REQUIRE(info.simplex_iteration_count < ieration_count0); + } + std::vector set = {1, 3, 4}; + HighsInt num_set_en = set.size(); + cost.resize(num_set_en); + lower.resize(num_set_en); + upper.resize(num_set_en); + start.resize(num_set_en); + index.resize(num_set_en * max_dim); + value.resize(num_set_en * max_dim); + + h.getCols(num_set_en, set.data(), get_num, cost.data(), lower.data(), + upper.data(), nnz, start.data(), index.data(), value.data()); + + h.deleteCols(num_set_en, set.data()); + if (dev_run) basis.printScalars(); + + h.addCols(get_num, cost.data(), lower.data(), upper.data(), nnz, start.data(), + index.data(), value.data()); + + h.run(); + if (dev_run) + printf( + "After deleting and adding %d columns in set, solve takes %d " + "iterations and yields objective = %g\n", + int(get_num), int(info.simplex_iteration_count), + info.objective_function_value); + // REQUIRE(info.simplex_iteration_count < ieration_count0); + + h.getRows(num_set_en, set.data(), get_num, lower.data(), upper.data(), nnz, + start.data(), index.data(), value.data()); + + h.deleteRows(num_set_en, set.data()); + if (dev_run) basis.printScalars(); + + h.addRows(get_num, lower.data(), upper.data(), nnz, start.data(), + index.data(), value.data()); + + h.run(); + if (dev_run) + printf( + "After deleting and adding %d rows in set, solve takes %d iterations " + "and yields objective = %g\n", + int(get_num), int(info.simplex_iteration_count), + info.objective_function_value); + // REQUIRE(info.simplex_iteration_count < ieration_count0); + std::vector mask; + mask.assign(max_dim, 0); + mask[1] = 1; + mask[4] = 1; + mask[5] = 1; + + h.getCols(mask.data(), get_num, cost.data(), lower.data(), upper.data(), nnz, + start.data(), index.data(), value.data()); + + h.deleteCols(mask.data()); + if (dev_run) basis.printScalars(); + + h.addCols(get_num, cost.data(), lower.data(), upper.data(), nnz, start.data(), + index.data(), value.data()); + + h.run(); + if (dev_run) + printf( + "After deleting and adding %d columns in mask, solve takes %d " + "iterations and yields objective = %g\n", + int(get_num), int(info.simplex_iteration_count), + info.objective_function_value); + // REQUIRE(info.simplex_iteration_count < ieration_count0); + + mask.assign(max_dim, 0); + mask[1] = 1; + mask[4] = 1; + mask[5] = 1; + mask[8] = 1; + mask[9] = 1; + HighsInt num_mask_en = mask.size(); + cost.resize(num_mask_en); + lower.resize(num_mask_en); + upper.resize(num_mask_en); + start.resize(num_mask_en); + index.resize(num_mask_en * max_dim); + value.resize(num_mask_en * max_dim); + + h.getRows(mask.data(), get_num, lower.data(), upper.data(), nnz, start.data(), + index.data(), value.data()); + + h.deleteRows(mask.data()); + if (dev_run) basis.printScalars(); + + h.addRows(get_num, lower.data(), upper.data(), nnz, start.data(), + index.data(), value.data()); + + h.run(); + if (dev_run) + printf( + "After deleting and adding %d rows in mask, solve takes %d iterations " + "and yields objective = %g\n", + int(get_num), int(info.simplex_iteration_count), + info.objective_function_value); + // REQUIRE(info.simplex_iteration_count < ieration_count0); +} diff --git a/check/TestLpOrientation.cpp b/check/TestLpOrientation.cpp index e94297b9bc..a43a6d5b20 100644 --- a/check/TestLpOrientation.cpp +++ b/check/TestLpOrientation.cpp @@ -10,8 +10,6 @@ const bool dev_run = false; // No commas in test case name. TEST_CASE("LP-orientation", "[lp_orientation]") { Avgas avgas; - const HighsInt avgas_num_col = 8; - const HighsInt avgas_num_row = 10; HighsInt num_row = 0; HighsInt num_row_nz = 0; vector rowLower; @@ -21,11 +19,10 @@ TEST_CASE("LP-orientation", "[lp_orientation]") { vector ARvalue; for (HighsInt row = 0; row < avgas_num_row; row++) - avgas.row(row, num_row, num_row_nz, rowLower, rowUpper, ARstart, ARindex, - ARvalue); + avgas.addRow(row, num_row, num_row_nz, rowLower, rowUpper, ARstart, ARindex, + ARvalue); - ARstart.resize(num_row + 1); - ARstart[num_row] = num_row_nz; + ARstart.push_back(num_row_nz); HighsInt num_col = 0; HighsInt num_col_nz = 0; @@ -36,10 +33,10 @@ TEST_CASE("LP-orientation", "[lp_orientation]") { vector Aindex; vector Avalue; for (HighsInt col = 0; col < avgas_num_col; col++) - avgas.col(col, num_col, num_col_nz, colCost, colLower, colUpper, Astart, - Aindex, Avalue); - Astart.resize(num_col + 1); - Astart[num_col] = num_col_nz; + avgas.addCol(col, num_col, num_col_nz, colCost, colLower, colUpper, Astart, + Aindex, Avalue); + Astart.push_back(num_col_nz); + assert(num_col_nz == num_row_nz); double optimal_objective_function_value = -7.75; @@ -102,20 +99,18 @@ TEST_CASE("LP-orientation", "[lp_orientation]") { highs.clearModel(); highs.addCols(num_col, colCost.data(), colLower.data(), colUpper.data(), 0, NULL, NULL, NULL); - vector one_row_Lower; - vector one_row_Upper; - vector one_row_start; + double one_row_lower; + double one_row_upper; vector one_row_index; vector one_row_value; + HighsInt one_row_num_nz; for (HighsInt row = 0; row < avgas_num_row; row++) { - HighsInt one_row_numnz = 0; - HighsInt one_row_numrow = 0; - avgas.row(row, one_row_numrow, one_row_numnz, one_row_Lower, one_row_Upper, - one_row_start, one_row_index, one_row_value); - REQUIRE(highs.addRows(1, one_row_Lower.data(), one_row_Upper.data(), - one_row_numnz, one_row_start.data(), - one_row_index.data(), - one_row_value.data()) == HighsStatus::kOk); + avgas.getRow(row, one_row_lower, one_row_upper, one_row_index, + one_row_value); + one_row_num_nz = one_row_index.size(); + REQUIRE(highs.addRow(one_row_lower, one_row_upper, one_row_num_nz, + one_row_index.data(), + one_row_value.data()) == HighsStatus::kOk); } highs.run(); REQUIRE(info.objective_function_value == optimal_objective_function_value); diff --git a/check/TestLpValidation.cpp b/check/TestLpValidation.cpp index 473fdeb681..f048d505ed 100644 --- a/check/TestLpValidation.cpp +++ b/check/TestLpValidation.cpp @@ -171,10 +171,9 @@ TEST_CASE("LP-validation", "[highs_data]") { vector ARstart; vector ARindex; vector ARvalue; - for (HighsInt row = 0; row < avgas_num_row; row++) { - avgas.row(row, num_row, num_row_nz, rowLower, rowUpper, ARstart, ARindex, - ARvalue); + avgas.addRow(row, num_row, num_row_nz, rowLower, rowUpper, ARstart, ARindex, + ARvalue); } HighsInt num_col = 0; @@ -186,8 +185,8 @@ TEST_CASE("LP-validation", "[highs_data]") { vector Aindex; vector Avalue; for (HighsInt col = 0; col < avgas_num_col; col++) { - avgas.col(col, num_col, num_col_nz, colCost, colLower, colUpper, Astart, - Aindex, Avalue); + avgas.addCol(col, num_col, num_col_nz, colCost, colLower, colUpper, Astart, + Aindex, Avalue); } return_status = assessLp(lp, options); diff --git a/check/TestMipSolver.cpp b/check/TestMipSolver.cpp index ecb3502316..c4ea7f584a 100644 --- a/check/TestMipSolver.cpp +++ b/check/TestMipSolver.cpp @@ -701,7 +701,7 @@ TEST_CASE("IP-with-fract-bounds-no-presolve", "[highs_test_mip_solver]") { Highs highs; // No presolve highs.setOptionValue("output_flag", dev_run); - highs.setOptionValue("presolve", "off"); + highs.setOptionValue("presolve", kHighsOffString); // IP without constraints and fractional bounds on variables HighsLp lp; @@ -772,7 +772,7 @@ void distillationMIP(Highs& highs) { special_lps.distillationMip(lp, require_model_status, optimal_objective); REQUIRE(highs.passModel(lp) == HighsStatus::kOk); // Presolve doesn't reduce the LP - solve(highs, "on", require_model_status, optimal_objective); + solve(highs, kHighsOnString, require_model_status, optimal_objective); } void rowlessMIP(Highs& highs) { @@ -793,6 +793,29 @@ void rowlessMIP(Highs& highs) { optimal_objective = -1.0; REQUIRE(highs.passModel(lp) == HighsStatus::kOk); // Presolve reduces the LP to empty - solve(highs, "on", require_model_status, optimal_objective); - solve(highs, "off", require_model_status, optimal_objective); + solve(highs, kHighsOnString, require_model_status, optimal_objective); + solve(highs, kHighsOffString, require_model_status, optimal_objective); +} + +TEST_CASE("issue-2122", "[highs_test_mip_solver]") { + std::string filename = std::string(HIGHS_DIR) + "/check/instances/2122.lp"; + Highs highs; + highs.setOptionValue("output_flag", dev_run); + highs.setOptionValue("mip_rel_gap", 0); + highs.setOptionValue("mip_abs_gap", 0); + highs.readModel(filename); + const HighsModelStatus require_model_status = HighsModelStatus::kOptimal; + const double optimal_objective = -187612.944194; + solve(highs, kHighsOnString, require_model_status, optimal_objective); +} + +TEST_CASE("issue-2171", "[highs_test_mip_solver]") { + std::string filename = std::string(HIGHS_DIR) + "/check/instances/2171.mps"; + Highs highs; + highs.setOptionValue("mip_rel_gap", 0); + highs.setOptionValue("mip_abs_gap", 0); + highs.readModel(filename); + const HighsModelStatus require_model_status = HighsModelStatus::kOptimal; + const double optimal_objective = -22375.7585461; + solve(highs, kHighsOnString, require_model_status, optimal_objective); } diff --git a/check/TestOptions.cpp b/check/TestOptions.cpp index f511f8caef..b2a4142710 100644 --- a/check/TestOptions.cpp +++ b/check/TestOptions.cpp @@ -95,7 +95,7 @@ TEST_CASE("internal-options", "[highs_options]") { REQUIRE(options.small_matrix_value == 0.001); REQUIRE(options.mps_parser_type_free); - if (dev_run) reportOptions(stdout, options.records, true); + if (dev_run) reportOptions(stdout, report_log_options, options.records, true); return_status = checkOptions(report_log_options, options.records); REQUIRE(return_status == OptionStatus::kOk); @@ -157,7 +157,7 @@ TEST_CASE("internal-options", "[highs_options]") { if (dev_run) { printf("\nAfter setting allowed_matrix_scale_factor to 1\n"); - reportOptions(stdout, options.records); + reportOptions(stdout, report_log_options, options.records); } double allowed_matrix_scale_factor_double = 1e-7; @@ -174,7 +174,7 @@ TEST_CASE("internal-options", "[highs_options]") { if (dev_run) { printf("\nAfter testing HighsInt options\n"); - reportOptions(stdout, options.records); + reportOptions(stdout, report_log_options, options.records); } // Check setting double options @@ -231,7 +231,7 @@ TEST_CASE("internal-options", "[highs_options]") { options.log_options, options.records, model_file); REQUIRE(return_status == OptionStatus::kUnknownOption); - if (dev_run) reportOptions(stdout, options.records); + if (dev_run) reportOptions(stdout, report_log_options, options.records); bool get_mps_parser_type_free; return_status = diff --git a/check/TestPresolve.cpp b/check/TestPresolve.cpp index 7d2e5d9604..1055cdbaeb 100644 --- a/check/TestPresolve.cpp +++ b/check/TestPresolve.cpp @@ -639,3 +639,25 @@ TEST_CASE("presolve-slacks", "[highs_test_presolve]") { REQUIRE(h.getPresolvedLp().num_col_ == 2); REQUIRE(h.getPresolvedLp().num_row_ == 2); } + +TEST_CASE("presolve-issue-2095", "[highs_test_presolve]") { + std::string model_file = + std::string(HIGHS_DIR) + "/check/instances/issue-2095.mps"; + Highs highs; + highs.setOptionValue("output_flag", dev_run); + highs.readModel(model_file); + REQUIRE(highs.presolve() == HighsStatus::kOk); + REQUIRE(highs.getModelPresolveStatus() == HighsPresolveStatus::kReduced); +} + +TEST_CASE("presolve-only-at-root", "[highs_test_presolve]") { + std::string model_file = + std::string(HIGHS_DIR) + "/check/instances/gesa2.mps"; + + Highs highs; + highs.setOptionValue("output_flag", dev_run); + // Allow only presolve at root node + highs.setOptionValue("mip_root_presolve_only", true); + highs.readModel(model_file); + REQUIRE(highs.run() == HighsStatus::kOk); +} diff --git a/check/TestSpecialLps.cpp b/check/TestSpecialLps.cpp index 66d99ed304..32ddd4fe3a 100644 --- a/check/TestSpecialLps.cpp +++ b/check/TestSpecialLps.cpp @@ -47,6 +47,7 @@ void solve(Highs& highs, std::string presolve, std::string solver, REQUIRE(iteration_count == require_iteration_count); } REQUIRE(highs.resetOptions() == HighsStatus::kOk); + highs.setOptionValue("output_flag", dev_run); } void distillation(Highs& highs) { @@ -591,6 +592,7 @@ void singularStartingBasis(Highs& highs) { optimal_objective, dev_run)); REQUIRE(highs.resetOptions() == HighsStatus::kOk); + highs.setOptionValue("output_flag", dev_run); special_lps.reportSolution(highs, dev_run); } diff --git a/check/instances/2122.lp b/check/instances/2122.lp new file mode 100644 index 0000000000..e408f2da38 --- /dev/null +++ b/check/instances/2122.lp @@ -0,0 +1,1822 @@ +\ File written by HiGHS .lp file handler +max + obj: -1050.09490748148 x1 +0.077 x2 +0.068 x3 +0.05912 x4 +0.07261 x5 +0.05721 x6 +0.05509 x7 +0.05085 x8 +0.05085 x9 +0.06442 x10 +0.07947 x11 +0.08693 x12 +0.09921 x13 +0.09671 x14 +0.10135 x15 +0.09307 x16 +0.08284 x17 +0.07707 x18 +0.05433 x19 +0.07567 x20 +0.03881 x21 +0.06258 x22 +0.02425 x23 +0.04996 x24 +0.02532 x25 -0.077 x26 -0.068 x27 -0.05912 x28 -0.07261 x29 -0.05721 x30 -0.05509 x31 -0.05085 x32 -0.05085 x33 -0.06442 x34 -0.07947 x35 -0.08693 x36 -0.09921 x37 -0.09671 x38 -0.10135 x39 -0.09307 x40 -0.08284 x41 -0.07707 x42 -0.05433 x43 + -0.07567 x44 -0.03881 x45 -0.06258 x46 -0.02425 x47 -0.04996 x48 -0.02532 x49 +0.02532 x50 -0.02532 x51 -0.00042330288 x52 -0.00042330288 x53 -0.00042330288 x54 -0.00042330288 x55 -0.00042330288 x56 -0.00042330288 x57 -0.00042330288 x58 -0.00042330288 x59 -0.00042330288 x60 -0.00042330288 x61 -0.00042330288 x62 -0.00042330288 x63 -0.00042330288 x64 -0.00042330288 x65 -0.00042330288 x66 -0.00042330288 x67 -0.00042330288 x68 -0.00042330288 x69 -0.00042330288 x70 -0.00042330288 x71 -0.00042330288 x72 -0.00042330288 x73 -0.00042330288 x74 -0.00042330288 + x75 -0.00042330288 x76 -0.00042330288 x77 -0.00042330288 x78 -10 x79 -10 x80 -10 x81 -10 x82 -10 x83 -10 x84 -10 x85 -10 x86 -10 x87 -10 x88 -10 x89 -10 x90 -10 x91 -10 x92 -10 x93 -10 x94 -10 x95 -10 x96 -10 x97 -10 x98 -10 x99 -10 x100 -10 x101 -10 x102 -10 x103 -10 x104 -10 x105 -10 x106 -10 x107 -10 x108 -10 x109 -10 x110 -10 x111 -10 x112 -10 x113 -10 x114 -10 x115 -10 x116 -10 x117 -10 x118 -10 x119 -10 x120 -10 x121 -10 x122 -10 x123 -10 x124 -10 x125 -10 x126 -10 x127 -10 x128 -10 x129 -10 x130 -10 x131 -10 x132 -10 x133 -10 x134 -0.01 x135 + -0.01 x136 -0.01 x137 -0.01 x138 -0.01 x139 -0.01 x140 -0.01 x141 -0.01 x142 -0.01 x143 -0.01 x144 -0.01 x145 -0.01 x146 -0.01 x147 -0.01 x148 -0.01 x149 -0.01 x150 -0.01 x151 -0.01 x152 -0.01 x153 -0.01 x154 -0.01 x155 -0.01 x156 -0.01 x157 -0.01 x158 +st + con1: +1 x159 -0.5 x160 -0.00833333333333333 x161 +0.00833333333333333 x162 +0.00833333333333333 x163 = +0 + con2: +1 x164 -0.5 x165 -0.00833333333333333 x166 +0.00833333333333333 x167 +0.00833333333333333 x168 = +0 + con3: +1 x169 -0.5 x170 +0.00833333333333333 x171 +0.00833333333333333 x172 = +0 + con4: +1 x173 -0.5 x174 +0.00833333333333333 x175 +0.00833333333333333 x176 = +0 + con5: +1 x177 -0.5 x178 +0.00833333333333333 x179 +0.00833333333333333 x180 = +0 + con6: +1 x181 -0.5 x182 +0.00833333333333333 x183 +0.00833333333333333 x184 = +0 + con7: +1 x185 -0.5 x186 +0.00833333333333333 x187 +0.00833333333333333 x188 = +0 + con8: +1 x189 -0.5 x190 +0.00833333333333333 x191 +0.00833333333333333 x192 = +0 + con9: +1 x193 -0.5 x194 +0.00833333333333333 x195 +0.00833333333333333 x196 = +0 + con10: +1 x197 -0.5 x198 +0.00833333333333333 x199 +0.00833333333333333 x200 = +0 + con11: +1 x201 -0.5 x202 +0.00833333333333333 x203 +0.00833333333333333 x204 = +0 + con12: +1 x205 -0.5 x206 +0.00833333333333333 x207 +0.00833333333333333 x208 = +0 + con13: +1 x209 -0.5 x210 +0.00833333333333333 x211 +0.00833333333333333 x212 = +0 + con14: +1 x213 -0.5 x214 +0.00833333333333333 x215 +0.00833333333333333 x216 = +0 + con15: +1 x217 -0.5 x218 +0.00833333333333333 x219 +0.00833333333333333 x220 = +0 + con16: +1 x221 -0.5 x222 +0.00833333333333333 x223 +0.00833333333333333 x224 = +0 + con17: +1 x225 -0.5 x226 +0.00833333333333333 x227 +0.00833333333333333 x228 = +0 + con18: +1 x229 -0.5 x230 +0.00833333333333333 x231 +0.00833333333333333 x232 = +0 + con19: +1 x233 -0.5 x234 +0.00833333333333333 x235 +0.00833333333333333 x236 = +0 + con20: +1 x237 -0.5 x238 +0.00833333333333333 x239 +0.00833333333333333 x240 = +0 + con21: +1 x241 -0.5 x242 +0.00833333333333333 x243 +0.00833333333333333 x244 = +0 + con22: +1 x245 -0.5 x246 +0.00833333333333333 x247 +0.00833333333333333 x248 = +0 + con23: +1 x249 -0.5 x250 +0.00833333333333333 x251 +0.00833333333333333 x252 = +0 + con24: +1 x253 -0.5 x254 +0.00833333333333333 x255 +0.00833333333333333 x256 = +0 + con25: -12000 x257 <= -12000 + con26: +8000 x257 <= +8000 + con27: +1 x160 -12000 x258 <= +0 + con28: +1 x165 +7000 x258 <= +7000 + con29: +1 x170 -12000 x259 <= +0 + con30: +1 x174 +7000 x259 <= +7000 + con31: +1 x178 -12000 x260 <= +0 + con32: +1 x182 +7000 x260 <= +7000 + con33: +1 x186 -12000 x261 <= +0 + con34: +1 x190 +7000 x261 <= +7000 + con35: +1 x194 -12000 x262 <= +0 + con36: +1 x198 +7000 x262 <= +7000 + con37: +1 x202 -12000 x263 <= +0 + con38: +1 x206 +7000 x263 <= +7000 + con39: +1 x210 -12000 x264 <= +0 + con40: +1 x214 +7000 x264 <= +7000 + con41: +1 x218 -12000 x265 <= +0 + con42: +1 x222 +7000 x265 <= +7000 + con43: +1 x226 -12000 x266 <= +0 + con44: +1 x230 +8000 x266 <= +8000 + con45: +1 x234 -12000 x267 <= +0 + con46: +1 x238 +8000 x267 <= +8000 + con47: +1 x242 -12000 x268 <= +0 + con48: +1 x246 +8000 x268 <= +8000 + con49: +1 x250 -12000 x269 <= +0 + con50: +1 x254 +8000 x269 <= +8000 + con51: +1 x270 -12000 x271 <= +0 + con52: +8000 x271 +1 x272 <= +8000 + con53: +1 x163 -12000 x273 <= +0 + con54: +1 x161 +12000 x273 <= +12000 + con55: +1 x168 -8000 x274 <= +0 + con56: +1 x166 +8000 x274 <= +8000 + con57: +1 x172 -12000 x275 <= +0 + con58: +1 x162 +12000 x275 <= +12000 + con59: +1 x176 -7000 x276 <= +0 + con60: +1 x167 +7000 x276 <= +7000 + con61: +1 x180 -12000 x277 <= +0 + con62: +1 x171 +12000 x277 <= +12000 + con63: +1 x184 -7000 x278 <= +0 + con64: +1 x175 +7000 x278 <= +7000 + con65: +1 x188 -12000 x279 <= +0 + con66: +1 x179 +12000 x279 <= +12000 + con67: +1 x192 -7000 x280 <= +0 + con68: +1 x183 +7000 x280 <= +7000 + con69: +1 x196 -12000 x281 <= +0 + con70: +1 x187 +12000 x281 <= +12000 + con71: +1 x200 -7000 x282 <= +0 + con72: +1 x191 +7000 x282 <= +7000 + con73: +1 x204 -12000 x283 <= +0 + con74: +1 x195 +12000 x283 <= +12000 + con75: +1 x208 -7000 x284 <= +0 + con76: +1 x199 +7000 x284 <= +7000 + con77: +1 x212 -12000 x285 <= +0 + con78: +1 x203 +12000 x285 <= +12000 + con79: +1 x216 -7000 x286 <= +0 + con80: +1 x207 +7000 x286 <= +7000 + con81: +1 x220 -12000 x287 <= +0 + con82: +1 x211 +12000 x287 <= +12000 + con83: +1 x224 -7000 x288 <= +0 + con84: +1 x215 +7000 x288 <= +7000 + con85: +1 x228 -12000 x289 <= +0 + con86: +1 x219 +12000 x289 <= +12000 + con87: +1 x232 -8000 x290 <= +0 + con88: +1 x223 +8000 x290 <= +8000 + con89: +1 x236 -12000 x291 <= +0 + con90: +1 x227 +12000 x291 <= +12000 + con91: +1 x240 -8000 x292 <= +0 + con92: +1 x231 +8000 x292 <= +8000 + con93: +1 x244 -12000 x293 <= +0 + con94: +1 x235 +12000 x293 <= +12000 + con95: +1 x248 -8000 x294 <= +0 + con96: +1 x239 +8000 x294 <= +8000 + con97: +1 x252 -12000 x295 <= +0 + con98: +1 x243 +12000 x295 <= +12000 + con99: +1 x256 -8000 x296 <= +0 + con100: +1 x247 +8000 x296 <= +8000 + con101: -12000 x297 <= +0 + con102: +1 x251 +12000 x297 <= +12000 + con103: -8000 x298 <= +0 + con104: +1 x255 +8000 x298 <= +8000 + con105: +1 x160 +1 x161 -1 x163 = +12000 + con106: +1 x165 +1 x166 -1 x168 = +0 + con107: -1 x160 +1 x162 +1 x170 -1 x172 = +0 + con108: -1 x165 +1 x167 +1 x174 -1 x176 = +0 + con109: -1 x170 +1 x171 +1 x178 -1 x180 = +0 + con110: -1 x174 +1 x175 +1 x182 -1 x184 = +0 + con111: -1 x178 +1 x179 +1 x186 -1 x188 = +0 + con112: -1 x182 +1 x183 +1 x190 -1 x192 = +0 + con113: -1 x186 +1 x187 +1 x194 -1 x196 = +0 + con114: -1 x190 +1 x191 +1 x198 -1 x200 = +0 + con115: -1 x194 +1 x195 +1 x202 -1 x204 = +0 + con116: -1 x198 +1 x199 +1 x206 -1 x208 = +0 + con117: -1 x202 +1 x203 +1 x210 -1 x212 = +0 + con118: -1 x206 +1 x207 +1 x214 -1 x216 = +0 + con119: -1 x210 +1 x211 +1 x218 -1 x220 = +0 + con120: -1 x214 +1 x215 +1 x222 -1 x224 = +0 + con121: -1 x218 +1 x219 +1 x226 -1 x228 = +0 + con122: -1 x222 +1 x223 +1 x230 -1 x232 = +0 + con123: -1 x226 +1 x227 +1 x234 -1 x236 = +0 + con124: -1 x230 +1 x231 +1 x238 -1 x240 = +0 + con125: -1 x234 +1 x235 +1 x242 -1 x244 = +0 + con126: -1 x238 +1 x239 +1 x246 -1 x248 = +0 + con127: -1 x242 +1 x243 +1 x250 -1 x252 = +0 + con128: -1 x246 +1 x247 +1 x254 -1 x256 = +0 + con129: -1 x250 +1 x251 +1 x270 = +0 + con130: -1 x254 +1 x255 +1 x272 = +0 + con131: -1000 x299 = -12000 + con132: -1000 x300 = +0 + con133: +1 x160 -1000 x301 = +0 + con134: +1 x165 -1000 x302 = +0 + con135: +1 x170 -1000 x303 = +0 + con136: +1 x174 -1000 x304 = +0 + con137: +1 x178 -1000 x305 = +0 + con138: +1 x182 -1000 x306 = +0 + con139: +1 x186 -1000 x307 = +0 + con140: +1 x190 -1000 x308 = +0 + con141: +1 x194 -1000 x309 = +0 + con142: +1 x198 -1000 x310 = +0 + con143: +1 x202 -1000 x311 = +0 + con144: +1 x206 -1000 x312 = +0 + con145: +1 x210 -1000 x313 = +0 + con146: +1 x214 -1000 x314 = +0 + con147: +1 x218 -1000 x315 = +0 + con148: +1 x222 -1000 x316 = +0 + con149: +1 x226 -1000 x317 = +0 + con150: +1 x230 -1000 x318 = +0 + con151: +1 x234 -1000 x319 = +0 + con152: +1 x238 -1000 x320 = +0 + con153: +1 x242 -1000 x321 = +0 + con154: +1 x246 -1000 x322 = +0 + con155: +1 x250 -1000 x323 = +0 + con156: +1 x254 -1000 x324 = +0 + con157: +1 x270 -1000 x325 = +0 + con158: +1 x272 -1000 x326 = +0 + con159: +1 x160 +1 x161 <= +12000 + con160: +1 x165 +1 x166 <= +7000 + con161: -1 x257 +1 x258 = +0 + con162: +1 x327 -1 x328 = -222.34033333 + con163: +1 x329 -1 x330 = +4423.87633333333 + con164: +1 x331 -1 x332 = +4490.543 + con165: +1 x135 +1 x333 -1 x334 -1 x335 = -1583.939 + con166: +1 x136 +1 x336 -1 x337 -1 x338 = -1583.939 + con167: +1 x137 +1 x339 -1 x340 -1 x341 = -1583.939 + con168: +1 x138 +1 x342 -1 x343 -1 x344 = -1583.939 + con169: +1 x139 +1 x345 -1 x346 -1 x347 = -1583.939 + con170: +1 x140 +1 x348 -1 x349 -1 x350 = -1583.939 + con171: +1 x141 +1 x351 -1 x352 -1 x353 = -1583.939 + con172: +1 x142 +1 x354 -1 x355 -1 x356 = -1583.939 + con173: +1 x143 +1 x357 -1 x358 -1 x359 = -1509.457 + con174: +1 x144 +1 x360 -1 x361 -1 x362 = -1509.457 + con175: +1 x145 +1 x363 -1 x364 -1 x365 = -1509.457 + con176: +1 x146 +1 x366 -1 x367 -1 x368 = -1509.457 + con177: +1 x147 +1 x369 -1 x370 -1 x371 = -1509.457 + con178: +1 x148 +1 x372 -1 x373 -1 x374 = -1509.457 + con179: +1 x149 +1 x375 -1 x376 -1 x377 = -1509.457 + con180: +1 x150 +1 x378 -1 x379 -1 x380 = -1509.457 + con181: +1 x151 +1 x381 -1 x382 -1 x383 = -1583.939 + con182: +1 x152 +1 x384 -1 x385 -1 x386 = -1583.939 + con183: +1 x153 +1 x387 -1 x388 -1 x389 = -1583.939 + con184: +1 x154 +1 x390 -1 x391 -1 x392 = -1583.939 + con185: +1 x155 +1 x393 -1 x394 -1 x395 = -1583.939 + con186: +1 x156 +1 x396 -1 x397 -1 x398 = -1583.939 + con187: +1 x157 +1 x399 -1 x400 -1 x401 = -1583.939 + con188: +1 x158 +1 x402 -1 x403 -1 x404 = -1583.939 + con189: -17400 x405 <= -1491.66666667 + con190: +17400 x405 <= +17400 + con191: -29000 x406 <= -5933.33333333333 + con192: +29000 x406 <= +29000 + con193: -29000 x407 <= -6000 + con194: +29000 x407 <= +29000 + con195: +1 x335 -29000 x408 <= +0 + con196: +1 x135 +29000 x408 <= +29000 + con197: +1 x338 -29000 x409 <= +0 + con198: +1 x136 +29000 x409 <= +29000 + con199: +1 x341 -29000 x410 <= +0 + con200: +1 x137 +29000 x410 <= +29000 + con201: +1 x344 -29000 x411 <= +0 + con202: +1 x138 +29000 x411 <= +29000 + con203: +1 x347 -29000 x412 <= +0 + con204: +1 x139 +29000 x412 <= +29000 + con205: +1 x350 -29000 x413 <= +0 + con206: +1 x140 +29000 x413 <= +29000 + con207: +1 x353 -29000 x414 <= +0 + con208: +1 x141 +29000 x414 <= +29000 + con209: +1 x356 -29000 x415 <= +0 + con210: +1 x142 +29000 x415 <= +29000 + con211: +1 x359 -29000 x416 <= +0 + con212: +1 x143 +29000 x416 <= +29000 + con213: +1 x362 -29000 x417 <= +0 + con214: +1 x144 +29000 x417 <= +29000 + con215: +1 x365 -29000 x418 <= +0 + con216: +1 x145 +29000 x418 <= +29000 + con217: +1 x368 -29000 x419 <= +0 + con218: +1 x146 +29000 x419 <= +29000 + con219: +1 x371 -29000 x420 <= +0 + con220: +1 x147 +29000 x420 <= +29000 + con221: +1 x374 -29000 x421 <= +0 + con222: +1 x148 +29000 x421 <= +29000 + con223: +1 x377 -29000 x422 <= +0 + con224: +1 x149 +29000 x422 <= +29000 + con225: +1 x380 -29000 x423 <= +0 + con226: +1 x150 +29000 x423 <= +29000 + con227: +1 x383 -29000 x424 <= +0 + con228: +1 x151 +29000 x424 <= +29000 + con229: +1 x386 -29000 x425 <= +0 + con230: +1 x152 +29000 x425 <= +29000 + con231: +1 x389 -29000 x426 <= +0 + con232: +1 x153 +29000 x426 <= +29000 + con233: +1 x392 -29000 x427 <= +0 + con234: +1 x154 +29000 x427 <= +29000 + con235: +1 x395 -29000 x428 <= +0 + con236: +1 x155 +29000 x428 <= +29000 + con237: +1 x398 -29000 x429 <= +0 + con238: +1 x156 +29000 x429 <= +29000 + con239: +1 x401 -29000 x430 <= +0 + con240: +1 x157 +29000 x430 <= +29000 + con241: +1 x404 -29000 x431 <= +0 + con242: +1 x158 +29000 x431 <= +29000 + con243: -0.9 x327 +1 x432 = +0 + con244: +1 x328 -1 x433 = +0 + con245: -0.9 x329 +1 x434 = +0 + con246: +1 x330 -1 x435 = +0 + con247: -0.9 x331 +1 x436 = +0 + con248: +1 x332 -1 x437 = +0 + con249: -0.9 x333 +1 x438 = +0 + con250: +1 x334 -1 x439 = +0 + con251: -0.9 x336 +1 x440 = +0 + con252: +1 x337 -1 x441 = +0 + con253: -0.9 x339 +1 x442 = +0 + con254: +1 x340 -1 x443 = +0 + con255: -0.9 x342 +1 x444 = +0 + con256: +1 x343 -1 x445 = +0 + con257: -0.9 x345 +1 x446 = +0 + con258: +1 x346 -1 x447 = +0 + con259: -0.9 x348 +1 x448 = +0 + con260: +1 x349 -1 x449 = +0 + con261: -0.9 x351 +1 x450 = +0 + con262: +1 x352 -1 x451 = +0 + con263: -0.9 x354 +1 x452 = +0 + con264: +1 x355 -1 x453 = +0 + con265: -0.9 x357 +1 x454 = +0 + con266: +1 x358 -1 x455 = +0 + con267: -0.9 x360 +1 x456 = +0 + con268: +1 x361 -1 x457 = +0 + con269: -0.9 x363 +1 x458 = +0 + con270: +1 x364 -1 x459 = +0 + con271: -0.9 x366 +1 x460 = +0 + con272: +1 x367 -1 x461 = +0 + con273: -0.9 x369 +1 x462 = +0 + con274: +1 x370 -1 x463 = +0 + con275: -0.9 x372 +1 x464 = +0 + con276: +1 x373 -1 x465 = +0 + con277: -0.9 x375 +1 x466 = +0 + con278: +1 x376 -1 x467 = +0 + con279: -0.9 x378 +1 x468 = +0 + con280: +1 x379 -1 x469 = +0 + con281: -0.9 x381 +1 x470 = +0 + con282: +1 x382 -1 x471 = +0 + con283: -0.9 x384 +1 x472 = +0 + con284: +1 x385 -1 x473 = +0 + con285: -0.9 x387 +1 x474 = +0 + con286: +1 x388 -1 x475 = +0 + con287: -0.9 x390 +1 x476 = +0 + con288: +1 x391 -1 x477 = +0 + con289: -0.9 x393 +1 x478 = +0 + con290: +1 x394 -1 x479 = +0 + con291: -0.9 x396 +1 x480 = +0 + con292: +1 x397 -1 x481 = +0 + con293: -0.9 x399 +1 x482 = +0 + con294: +1 x400 -1 x483 = +0 + con295: -0.9 x402 +1 x484 = +0 + con296: +1 x403 -1 x485 = +0 + con297: -1 x135 -1 x159 +1 x164 +1 x335 = +0 + con298: -1 x136 -1 x169 +1 x173 +1 x338 = +0 + con299: -1 x137 -1 x177 +1 x181 +1 x341 = +0 + con300: -1 x138 -1 x185 +1 x189 +1 x344 = +0 + con301: -1 x139 -1 x193 +1 x197 +1 x347 = +0 + con302: -1 x140 -1 x201 +1 x205 +1 x350 = +0 + con303: -1 x141 -1 x209 +1 x213 +1 x353 = +0 + con304: -1 x142 -1 x217 +1 x221 +1 x356 = +0 + con305: -1 x143 -1 x225 +1 x229 +1 x359 = +0 + con306: -1 x144 -1 x233 +1 x237 +1 x362 = +0 + con307: -1 x145 -1 x241 +1 x245 +1 x365 = +0 + con308: -1 x146 -1 x249 +1 x253 +1 x368 = +0 + con309: +1 x486 = +0 + con310: +1 x487 = +0 + con311: +1 x488 = +0 + con312: +1 x489 = +0 + con313: +1 x490 = +0 + con314: +1 x491 = +0 + con315: +1 x492 = +0 + con316: +1 x493 = +0 + con317: +1 x494 = +0 + con318: +1 x495 = +0 + con319: +1 x496 = +0 + con320: +1 x497 = +0 + con321: +1 x498 = +0 + con322: +1 x499 = +0 + con323: +1 x500 = +0 + con324: +1 x501 = +0 + con325: +1 x502 = +0 + con326: +1 x503 = +0 + con327: +1 x504 = +0 + con328: +1 x505 = +0 + con329: +1 x506 = +0 + con330: +1 x507 = +0 + con331: +1 x508 = +0 + con332: +1 x509 = +0 + con333: +1 x510 = +0 + con334: +1 x511 = +0 + con335: +1 x512 = +0 + con336: +1 x513 = +0 + con337: +1 x514 = +0 + con338: +1 x515 = +0 + con339: +1 x516 = +0 + con340: +1 x517 = +0 + con341: +1 x518 = +0 + con342: +1 x519 = +0 + con343: +1 x520 = +0 + con344: +1 x521 = +0 + con345: +1 x522 = +0 + con346: +1 x523 = +0 + con347: +1 x524 = +0 + con348: +1 x525 = +0 + con349: +1 x526 = +0 + con350: +1 x527 = +0 + con351: +1 x528 = +0 + con352: +1 x529 = +0 + con353: +1 x530 = +0 + con354: +1 x531 = +0 + con355: +1 x532 = +0 + con356: +1 x533 = +0 + con357: +1 x534 = +0 + con358: +1 x535 = +0 + con359: +1 x536 = +0 + con360: +1 x537 = +0 + con361: +1 x538 = +0 + con362: +1 x539 = +0 + con363: +1 x327 <= +8700 + con364: +1 x329 <= +14500 + con365: +1 x331 <= +14500 + con366: +1 x333 <= +14500 + con367: +1 x336 <= +14500 + con368: +1 x339 <= +14500 + con369: +1 x342 <= +14500 + con370: +1 x345 <= +14500 + con371: +1 x348 <= +14500 + con372: +1 x351 <= +14500 + con373: +1 x354 <= +14500 + con374: +1 x357 <= +14500 + con375: +1 x360 <= +14500 + con376: +1 x363 <= +14500 + con377: +1 x366 <= +14500 + con378: +1 x369 <= +14500 + con379: +1 x372 <= +14500 + con380: +1 x375 <= +14500 + con381: +1 x378 <= +14500 + con382: +1 x381 <= +14500 + con383: +1 x384 <= +14500 + con384: +1 x387 <= +14500 + con385: +1 x390 <= +14500 + con386: +1 x393 <= +14500 + con387: +1 x396 <= +14500 + con388: +1 x399 <= +14500 + con389: +1 x402 <= +14500 + con390: +1 x328 <= +8700 + con391: +1 x330 <= +14500 + con392: +1 x332 <= +14500 + con393: +1 x334 <= +14500 + con394: +1 x337 <= +14500 + con395: +1 x340 <= +14500 + con396: +1 x343 <= +14500 + con397: +1 x346 <= +14500 + con398: +1 x349 <= +14500 + con399: +1 x352 <= +14500 + con400: +1 x355 <= +14500 + con401: +1 x358 <= +14500 + con402: +1 x361 <= +14500 + con403: +1 x364 <= +14500 + con404: +1 x367 <= +14500 + con405: +1 x370 <= +14500 + con406: +1 x373 <= +14500 + con407: +1 x376 <= +14500 + con408: +1 x379 <= +14500 + con409: +1 x382 <= +14500 + con410: +1 x385 <= +14500 + con411: +1 x388 <= +14500 + con412: +1 x391 <= +14500 + con413: +1 x394 <= +14500 + con414: +1 x397 <= +14500 + con415: +1 x400 <= +14500 + con416: +1 x403 <= +14500 + con417: +1 x327 -14501 x540 <= +0 + con418: +1 x328 +14501 x540 <= +14501 + con419: +1 x329 -14501 x541 <= +0 + con420: +1 x330 +14501 x541 <= +14501 + con421: +1 x331 -14501 x542 <= +0 + con422: +1 x332 +14501 x542 <= +14501 + con423: +1 x333 -14501 x543 <= +0 + con424: +1 x334 +14501 x543 <= +14501 + con425: +1 x336 -14501 x544 <= +0 + con426: +1 x337 +14501 x544 <= +14501 + con427: +1 x339 -14501 x545 <= +0 + con428: +1 x340 +14501 x545 <= +14501 + con429: +1 x342 -14501 x546 <= +0 + con430: +1 x343 +14501 x546 <= +14501 + con431: +1 x345 -14501 x547 <= +0 + con432: +1 x346 +14501 x547 <= +14501 + con433: +1 x348 -14501 x548 <= +0 + con434: +1 x349 +14501 x548 <= +14501 + con435: +1 x351 -14501 x549 <= +0 + con436: +1 x352 +14501 x549 <= +14501 + con437: +1 x354 -14501 x550 <= +0 + con438: +1 x355 +14501 x550 <= +14501 + con439: +1 x357 -14501 x551 <= +0 + con440: +1 x358 +14501 x551 <= +14501 + con441: +1 x360 -14501 x552 <= +0 + con442: +1 x361 +14501 x552 <= +14501 + con443: +1 x363 -14501 x553 <= +0 + con444: +1 x364 +14501 x553 <= +14501 + con445: +1 x366 -14501 x554 <= +0 + con446: +1 x367 +14501 x554 <= +14501 + con447: +1 x369 -14501 x555 <= +0 + con448: +1 x370 +14501 x555 <= +14501 + con449: +1 x372 -14501 x556 <= +0 + con450: +1 x373 +14501 x556 <= +14501 + con451: +1 x375 -14501 x557 <= +0 + con452: +1 x376 +14501 x557 <= +14501 + con453: +1 x378 -14501 x558 <= +0 + con454: +1 x379 +14501 x558 <= +14501 + con455: +1 x381 -14501 x559 <= +0 + con456: +1 x382 +14501 x559 <= +14501 + con457: +1 x384 -14501 x560 <= +0 + con458: +1 x385 +14501 x560 <= +14501 + con459: +1 x387 -14501 x561 <= +0 + con460: +1 x388 +14501 x561 <= +14501 + con461: +1 x390 -14501 x562 <= +0 + con462: +1 x391 +14501 x562 <= +14501 + con463: +1 x393 -14501 x563 <= +0 + con464: +1 x394 +14501 x563 <= +14501 + con465: +1 x396 -14501 x564 <= +0 + con466: +1 x397 +14501 x564 <= +14501 + con467: +1 x399 -14501 x565 <= +0 + con468: +1 x400 +14501 x565 <= +14501 + con469: +1 x402 -14501 x566 <= +0 + con470: +1 x403 +14501 x566 <= +14501 + con471: -1 x432 +1 x433 +1 x486 +1 x513 +1 x567 = +3776 + con472: -1 x434 +1 x435 +1 x487 +1 x514 -1 x567 +1 x568 = +0 + con473: -1 x436 +1 x437 +1 x488 +1 x515 -1 x568 +1 x569 = +0 + con474: -1 x438 +1 x439 +1 x489 +1 x516 -1 x569 +1 x570 = +0 + con475: -1 x440 +1 x441 +1 x490 +1 x517 -1 x570 +1 x571 = +0 + con476: -1 x442 +1 x443 +1 x491 +1 x518 -1 x571 +1 x572 = +0 + con477: -1 x444 +1 x445 +1 x492 +1 x519 -1 x572 +1 x573 = +0 + con478: -1 x446 +1 x447 +1 x493 +1 x520 -1 x573 +1 x574 = +0 + con479: -1 x448 +1 x449 +1 x494 +1 x521 -1 x574 +1 x575 = +0 + con480: -1 x450 +1 x451 +1 x495 +1 x522 -1 x575 +1 x576 = +0 + con481: -1 x452 +1 x453 +1 x496 +1 x523 -1 x576 +1 x577 = +0 + con482: -1 x454 +1 x455 +1 x497 +1 x524 -1 x577 +1 x578 = +0 + con483: -1 x456 +1 x457 +1 x498 +1 x525 -1 x578 +1 x579 = +0 + con484: -1 x458 +1 x459 +1 x499 +1 x526 -1 x579 +1 x580 = +0 + con485: -1 x460 +1 x461 +1 x500 +1 x527 -1 x580 +1 x581 = +0 + con486: -1 x462 +1 x463 +1 x501 +1 x528 -1 x581 +1 x582 = +0 + con487: -1 x464 +1 x465 +1 x502 +1 x529 -1 x582 +1 x583 = +0 + con488: -1 x466 +1 x467 +1 x503 +1 x530 -1 x583 +1 x584 = +0 + con489: -1 x468 +1 x469 +1 x504 +1 x531 -1 x584 +1 x585 = +0 + con490: -1 x470 +1 x471 +1 x505 +1 x532 -1 x585 +1 x586 = +0 + con491: -1 x472 +1 x473 +1 x506 +1 x533 -1 x586 +1 x587 = +0 + con492: -1 x474 +1 x475 +1 x507 +1 x534 -1 x587 +1 x588 = +0 + con493: -1 x476 +1 x477 +1 x508 +1 x535 -1 x588 +1 x589 = +0 + con494: -1 x478 +1 x479 +1 x509 +1 x536 -1 x589 +1 x590 = +0 + con495: -1 x480 +1 x481 +1 x510 +1 x537 -1 x590 +1 x591 = +0 + con496: -1 x482 +1 x483 +1 x511 +1 x538 -1 x591 +1 x592 = +0 + con497: -1 x484 +1 x485 +1 x512 +1 x539 -1 x592 +1 x593 = +0 + con498: -1 x79 <= +0 + con499: -1 x80 -1 x567 <= -13507.000312 + con500: -1 x81 -1 x568 <= -13507.000312 + con501: -1 x82 -1 x569 <= -14081.143184 + con502: -1 x83 -1 x570 <= -14081.143184 + con503: -1 x84 -1 x571 <= -14081.143184 + con504: -1 x85 -1 x572 <= -14081.143184 + con505: -1 x86 -1 x573 <= -14081.143184 + con506: -1 x87 -1 x574 <= -14081.143184 + con507: -1 x88 -1 x575 <= -14081.143184 + con508: -1 x89 -1 x576 <= -14081.143184 + con509: -1 x90 -1 x577 <= -14081.143184 + con510: -1 x91 -1 x578 <= -13507.000312 + con511: -1 x92 -1 x579 <= -13507.000312 + con512: -1 x93 -1 x580 <= -13507.000312 + con513: -1 x94 -1 x581 <= -13507.000312 + con514: -1 x95 -1 x582 <= -13507.000312 + con515: -1 x96 -1 x583 <= -13507.000312 + con516: -1 x97 -1 x584 <= -13507.000312 + con517: -1 x98 -1 x585 <= -14081.143184 + con518: -1 x99 -1 x586 <= -14081.143184 + con519: -1 x100 -1 x587 <= -14081.143184 + con520: -1 x101 -1 x588 <= -14081.143184 + con521: -1 x102 -1 x589 <= -14081.143184 + con522: -1 x103 -1 x590 <= -14081.143184 + con523: -1 x104 -1 x591 <= -14081.143184 + con524: -1 x105 -1 x592 <= -14081.143184 + con525: -1 x106 -1 x593 <= -14081.143184 + con526: -1 x107 <= +0 + con527: -1 x108 +1 x567 <= +22857.628918 + con528: -1 x109 +1 x568 <= +22857.628918 + con529: -1 x110 +1 x569 <= +22634.182676 + con530: -1 x111 +1 x570 <= +22634.182676 + con531: -1 x112 +1 x571 <= +22634.182676 + con532: -1 x113 +1 x572 <= +22634.182676 + con533: -1 x114 +1 x573 <= +22634.182676 + con534: -1 x115 +1 x574 <= +22634.182676 + con535: -1 x116 +1 x575 <= +22634.182676 + con536: -1 x117 +1 x576 <= +22634.182676 + con537: -1 x118 +1 x577 <= +22634.182676 + con538: -1 x119 +1 x578 <= +22857.628918 + con539: -1 x120 +1 x579 <= +22857.628918 + con540: -1 x121 +1 x580 <= +22857.628918 + con541: -1 x122 +1 x581 <= +22857.628918 + con542: -1 x123 +1 x582 <= +22857.628918 + con543: -1 x124 +1 x583 <= +22857.628918 + con544: -1 x125 +1 x584 <= +22857.628918 + con545: -1 x126 +1 x585 <= +22634.182676 + con546: -1 x127 +1 x586 <= +22634.182676 + con547: -1 x128 +1 x587 <= +22634.182676 + con548: -1 x129 +1 x588 <= +22634.182676 + con549: -1 x130 +1 x589 <= +22634.182676 + con550: -1 x131 +1 x590 <= +22634.182676 + con551: -1 x132 +1 x591 <= +22634.182676 + con552: -1 x133 +1 x592 <= +22634.182676 + con553: -1 x134 +1 x593 <= +14081.143184 + con554: -1 x594 = -1714.007 + con555: -1 x595 = -1509.457 + con556: -1 x596 = -1509.457 + con557: -1 x597 = -1583.939 + con558: -1 x598 = -1583.939 + con559: -1 x599 = -1583.939 + con560: -1 x600 = -1583.939 + con561: -1 x601 = -1583.939 + con562: -1 x602 = -1583.939 + con563: -1 x603 = -1583.939 + con564: -1 x604 = -1583.939 + con565: -1 x605 = -1509.457 + con566: -1 x606 = -1509.457 + con567: -1 x607 = -1509.457 + con568: -1 x608 = -1509.457 + con569: -1 x609 = -1509.457 + con570: -1 x610 = -1509.457 + con571: -1 x611 = -1509.457 + con572: -1 x612 = -1509.457 + con573: -1 x613 = -1583.939 + con574: -1 x614 = -1583.939 + con575: -1 x615 = -1583.939 + con576: -1 x616 = -1583.939 + con577: -1 x617 = -1583.939 + con578: -1 x618 = -1583.939 + con579: -1 x619 = -1583.939 + con580: -1 x620 = -1583.939 + con581: -1 x621 = +0 + con582: -1 x622 = +0 + con583: -1 x623 = +0 + con584: -1 x624 = +0 + con585: -1 x625 = +0 + con586: -1 x626 = +0 + con587: -1 x627 = +0 + con588: -1 x628 = +0 + con589: -1 x629 = +0 + con590: -1 x630 = +0 + con591: -1 x631 = +0 + con592: -1 x632 = +0 + con593: -1 x633 = +0 + con594: -1 x634 = +0 + con595: -1 x635 = +0 + con596: -1 x636 = +0 + con597: -1 x637 = +0 + con598: -1 x638 = +0 + con599: -1 x639 = +0 + con600: -1 x640 = +0 + con601: -1 x641 = +0 + con602: -1 x642 = +0 + con603: -1 x643 = +0 + con604: -1 x644 = +0 + con605: -1 x645 = +0 + con606: -1 x646 = +0 + con607: -1 x647 = +0 + con608: +1 x52 <= +8700 + con609: +1 x53 <= +14500 + con610: +1 x54 <= +14500 + con611: +1 x55 <= +14500 + con612: +1 x56 <= +14500 + con613: +1 x57 <= +14500 + con614: +1 x58 <= +14500 + con615: +1 x59 <= +14500 + con616: +1 x60 <= +14500 + con617: +1 x61 <= +14500 + con618: +1 x62 <= +14500 + con619: +1 x63 <= +14500 + con620: +1 x64 <= +14500 + con621: +1 x65 <= +14500 + con622: +1 x66 <= +14500 + con623: +1 x67 <= +14500 + con624: +1 x68 <= +14500 + con625: +1 x69 <= +14500 + con626: +1 x70 <= +14500 + con627: +1 x71 <= +14500 + con628: +1 x72 <= +14500 + con629: +1 x73 <= +14500 + con630: +1 x74 <= +14500 + con631: +1 x75 <= +14500 + con632: +1 x76 <= +14500 + con633: +1 x77 <= +14500 + con634: +1 x78 <= +14500 + con635: +1 x648 <= +8700 + con636: +1 x649 <= +14500 + con637: +1 x650 <= +14500 + con638: +1 x651 <= +14500 + con639: +1 x652 <= +14500 + con640: +1 x653 <= +14500 + con641: +1 x654 <= +14500 + con642: +1 x655 <= +14500 + con643: +1 x656 <= +14500 + con644: +1 x657 <= +14500 + con645: +1 x658 <= +14500 + con646: +1 x659 <= +14500 + con647: +1 x660 <= +14500 + con648: +1 x661 <= +14500 + con649: +1 x662 <= +14500 + con650: +1 x663 <= +14500 + con651: +1 x664 <= +14500 + con652: +1 x665 <= +14500 + con653: +1 x666 <= +14500 + con654: +1 x667 <= +14500 + con655: +1 x668 <= +14500 + con656: +1 x669 <= +14500 + con657: +1 x670 <= +14500 + con658: +1 x671 <= +14500 + con659: +1 x672 <= +14500 + con660: +1 x673 <= +14500 + con661: +1 x674 <= +14500 + con662: +1 x52 -14501 x675 <= +0 + con663: +1 x648 +14501 x675 <= +14501 + con664: +1 x53 -14501 x676 <= +0 + con665: +1 x649 +14501 x676 <= +14501 + con666: +1 x54 -14501 x677 <= +0 + con667: +1 x650 +14501 x677 <= +14501 + con668: +1 x55 -14501 x678 <= +0 + con669: +1 x651 +14501 x678 <= +14501 + con670: +1 x56 -14501 x679 <= +0 + con671: +1 x652 +14501 x679 <= +14501 + con672: +1 x57 -14501 x680 <= +0 + con673: +1 x653 +14501 x680 <= +14501 + con674: +1 x58 -14501 x681 <= +0 + con675: +1 x654 +14501 x681 <= +14501 + con676: +1 x59 -14501 x682 <= +0 + con677: +1 x655 +14501 x682 <= +14501 + con678: +1 x60 -14501 x683 <= +0 + con679: +1 x656 +14501 x683 <= +14501 + con680: +1 x61 -14501 x684 <= +0 + con681: +1 x657 +14501 x684 <= +14501 + con682: +1 x62 -14501 x685 <= +0 + con683: +1 x658 +14501 x685 <= +14501 + con684: +1 x63 -14501 x686 <= +0 + con685: +1 x659 +14501 x686 <= +14501 + con686: +1 x64 -14501 x687 <= +0 + con687: +1 x660 +14501 x687 <= +14501 + con688: +1 x65 -14501 x688 <= +0 + con689: +1 x661 +14501 x688 <= +14501 + con690: +1 x66 -14501 x689 <= +0 + con691: +1 x662 +14501 x689 <= +14501 + con692: +1 x67 -14501 x690 <= +0 + con693: +1 x663 +14501 x690 <= +14501 + con694: +1 x68 -14501 x691 <= +0 + con695: +1 x664 +14501 x691 <= +14501 + con696: +1 x69 -14501 x692 <= +0 + con697: +1 x665 +14501 x692 <= +14501 + con698: +1 x70 -14501 x693 <= +0 + con699: +1 x666 +14501 x693 <= +14501 + con700: +1 x71 -14501 x694 <= +0 + con701: +1 x667 +14501 x694 <= +14501 + con702: +1 x72 -14501 x695 <= +0 + con703: +1 x668 +14501 x695 <= +14501 + con704: +1 x73 -14501 x696 <= +0 + con705: +1 x669 +14501 x696 <= +14501 + con706: +1 x74 -14501 x697 <= +0 + con707: +1 x670 +14501 x697 <= +14501 + con708: +1 x75 -14501 x698 <= +0 + con709: +1 x671 +14501 x698 <= +14501 + con710: +1 x76 -14501 x699 <= +0 + con711: +1 x672 +14501 x699 <= +14501 + con712: +1 x77 -14501 x700 <= +0 + con713: +1 x673 +14501 x700 <= +14501 + con714: +1 x78 -14501 x701 <= +0 + con715: +1 x674 +14501 x701 <= +14501 + con716: +1 x52 -1 x327 +1 x328 -1 x648 = +0 + con717: +1 x53 -1 x329 +1 x330 -1 x649 = +0 + con718: +1 x54 -1 x331 +1 x332 -1 x650 = +0 + con719: +1 x55 -1 x333 +1 x334 -1 x651 = +0 + con720: +1 x56 -1 x336 +1 x337 -1 x652 = +0 + con721: +1 x57 -1 x339 +1 x340 -1 x653 = +0 + con722: +1 x58 -1 x342 +1 x343 -1 x654 = +0 + con723: +1 x59 -1 x345 +1 x346 -1 x655 = +0 + con724: +1 x60 -1 x348 +1 x349 -1 x656 = +0 + con725: +1 x61 -1 x351 +1 x352 -1 x657 = +0 + con726: +1 x62 -1 x354 +1 x355 -1 x658 = +0 + con727: +1 x63 -1 x357 +1 x358 -1 x659 = +0 + con728: +1 x64 -1 x360 +1 x361 -1 x660 = +0 + con729: +1 x65 -1 x363 +1 x364 -1 x661 = +0 + con730: +1 x66 -1 x366 +1 x367 -1 x662 = +0 + con731: +1 x67 -1 x369 +1 x370 -1 x663 = +0 + con732: +1 x68 -1 x372 +1 x373 -1 x664 = +0 + con733: +1 x69 -1 x375 +1 x376 -1 x665 = +0 + con734: +1 x70 -1 x378 +1 x379 -1 x666 = +0 + con735: +1 x71 -1 x381 +1 x382 -1 x667 = +0 + con736: +1 x72 -1 x384 +1 x385 -1 x668 = +0 + con737: +1 x73 -1 x387 +1 x388 -1 x669 = +0 + con738: +1 x74 -1 x390 +1 x391 -1 x670 = +0 + con739: +1 x75 -1 x393 +1 x394 -1 x671 = +0 + con740: +1 x76 -1 x396 +1 x397 -1 x672 = +0 + con741: +1 x77 -1 x399 +1 x400 -1 x673 = +0 + con742: +1 x78 -1 x402 +1 x403 -1 x674 = +0 + con743: -1.01333353535354 x52 -1.01333353535354 x594 +1.01333353535354 x621 +1.01333353535354 x648 = -1511.55585690236 + con744: -1.02286483146067 x53 -1.02286483146067 x595 +1.02286483146067 x622 +1.02286483146067 x649 = -6068.998 + con745: -1.02294058333333 x54 -1.02294058333333 x596 +1.02294058333333 x623 +1.02294058333333 x650 = -6137.6435 + con746: -1 x2 +1 x26 -1.029686 x55 -1.002874 x597 +1.029686 x624 +1.002874 x651 -1 x702 +1 x703 = +0 + con747: -1 x3 +1 x27 -1.029686 x56 -1.002874 x598 +1.029686 x625 +1.002874 x652 -1 x704 +1 x705 = +0 + con748: -1 x4 +1 x28 -1.029686 x57 -1.002874 x599 +1.029686 x626 +1.002874 x653 -1 x706 +1 x707 = +0 + con749: -1 x5 +1 x29 -1.029686 x58 -1.002874 x600 +1.029686 x627 +1.002874 x654 -1 x708 +1 x709 = +0 + con750: -1 x6 +1 x30 -1.029686 x59 -1.002874 x601 +1.029686 x628 +1.002874 x655 -1 x710 +1 x711 = +0 + con751: -1 x7 +1 x31 -1.029686 x60 -1.002874 x602 +1.029686 x629 +1.002874 x656 -1 x712 +1 x713 = +0 + con752: -1 x8 +1 x32 -1.029686 x61 -1.002874 x603 +1.029686 x630 +1.002874 x657 -1 x714 +1 x715 = +0 + con753: -1 x9 +1 x33 -1.029686 x62 -1.002874 x604 +1.029686 x631 +1.002874 x658 -1 x716 +1 x717 = +0 + con754: -1 x10 +1 x34 -1.029686 x63 -1.002874 x605 +1.029686 x632 +1.002874 x659 -1 x718 +1 x719 = +0 + con755: -1 x11 +1 x35 -1.029686 x64 -1.002874 x606 +1.029686 x633 +1.002874 x660 -1 x720 +1 x721 = +0 + con756: -1 x12 +1 x36 -1.029686 x65 -1.002874 x607 +1.029686 x634 +1.002874 x661 -1 x722 +1 x723 = +0 + con757: -1 x13 +1 x37 -1.029686 x66 -1.002874 x608 +1.029686 x635 +1.002874 x662 -1 x724 +1 x725 = +0 + con758: -1 x14 +1 x38 -1.029686 x67 -1.002874 x609 +1.029686 x636 +1.002874 x663 -1 x726 +1 x727 = +0 + con759: -1 x15 +1 x39 -1.029686 x68 -1.002874 x610 +1.029686 x637 +1.002874 x664 -1 x728 +1 x729 = +0 + con760: -1 x16 +1 x40 -1.029686 x69 -1.002874 x611 +1.029686 x638 +1.002874 x665 -1 x730 +1 x731 = +0 + con761: -1 x17 +1 x41 -1.029686 x70 -1.002874 x612 +1.029686 x639 +1.002874 x666 -1 x732 +1 x733 = +0 + con762: -1 x18 +1 x42 -1.029686 x71 -1.002874 x613 +1.029686 x640 +1.002874 x667 -1 x734 +1 x735 = +0 + con763: -1 x19 +1 x43 -1.029686 x72 -1.002874 x614 +1.029686 x641 +1.002874 x668 -1 x736 +1 x737 = +0 + con764: -1 x20 +1 x44 -1.029686 x73 -1.002874 x615 +1.029686 x642 +1.002874 x669 -1 x738 +1 x739 = +0 + con765: -1 x21 +1 x45 -1.029686 x74 -1.002874 x616 +1.029686 x643 +1.002874 x670 -1 x740 +1 x741 = +0 + con766: -1 x22 +1 x46 -1.029686 x75 -1.002874 x617 +1.029686 x644 +1.002874 x671 -1 x742 +1 x743 = +0 + con767: -1 x23 +1 x47 -1.029686 x76 -1.002874 x618 +1.029686 x645 +1.002874 x672 -1 x744 +1 x745 = +0 + con768: -1 x24 +1 x48 -1.029686 x77 -1.002874 x619 +1.029686 x646 +1.002874 x673 -1 x746 +1 x747 = +0 + con769: -1 x25 +1 x49 -1 x50 +1 x51 -1.029686 x78 -1.002874 x620 +1.029686 x647 +1.002874 x674 = +0 + con770: -17400 x748 <= -1511.55585690236 + con771: +17400 x748 <= +17400 + con772: -17400 x749 <= -1511.55585690236 + con773: -29000 x750 <= -6068.998 + con774: +29000 x750 <= +29000 + con775: -29000 x751 <= -6068.998 + con776: -29000 x752 <= -6137.6435 + con777: +29000 x752 <= +29000 + con778: -29000 x753 <= -6137.6435 + con779: +1 x26 -29000 x754 <= +0 + con780: +1 x2 +29000 x754 <= +29000 + con781: +1 x2 +1 x26 -29000 x755 <= +0 + con782: +1 x27 -29000 x756 <= +0 + con783: +1 x3 +29000 x756 <= +29000 + con784: +1 x3 +1 x27 -29000 x757 <= +0 + con785: +1 x28 -29000 x758 <= +0 + con786: +1 x4 +29000 x758 <= +29000 + con787: +1 x4 +1 x28 -29000 x759 <= +0 + con788: +1 x29 -29000 x760 <= +0 + con789: +1 x5 +29000 x760 <= +29000 + con790: +1 x5 +1 x29 -29000 x761 <= +0 + con791: +1 x30 -29000 x762 <= +0 + con792: +1 x6 +29000 x762 <= +29000 + con793: +1 x6 +1 x30 -29000 x763 <= +0 + con794: +1 x31 -29000 x764 <= +0 + con795: +1 x7 +29000 x764 <= +29000 + con796: +1 x7 +1 x31 -29000 x765 <= +0 + con797: +1 x32 -29000 x766 <= +0 + con798: +1 x8 +29000 x766 <= +29000 + con799: +1 x8 +1 x32 -29000 x767 <= +0 + con800: +1 x33 -29000 x768 <= +0 + con801: +1 x9 +29000 x768 <= +29000 + con802: +1 x9 +1 x33 -29000 x769 <= +0 + con803: +1 x34 -29000 x770 <= +0 + con804: +1 x10 +29000 x770 <= +29000 + con805: +1 x10 +1 x34 -29000 x771 <= +0 + con806: +1 x35 -29000 x772 <= +0 + con807: +1 x11 +29000 x772 <= +29000 + con808: +1 x11 +1 x35 -29000 x773 <= +0 + con809: +1 x36 -29000 x774 <= +0 + con810: +1 x12 +29000 x774 <= +29000 + con811: +1 x12 +1 x36 -29000 x775 <= +0 + con812: +1 x37 -29000 x776 <= +0 + con813: +1 x13 +29000 x776 <= +29000 + con814: +1 x13 +1 x37 -29000 x777 <= +0 + con815: +1 x38 -29000 x778 <= +0 + con816: +1 x14 +29000 x778 <= +29000 + con817: +1 x14 +1 x38 -29000 x779 <= +0 + con818: +1 x39 -29000 x780 <= +0 + con819: +1 x15 +29000 x780 <= +29000 + con820: +1 x15 +1 x39 -29000 x781 <= +0 + con821: +1 x40 -29000 x782 <= +0 + con822: +1 x16 +29000 x782 <= +29000 + con823: +1 x16 +1 x40 -29000 x783 <= +0 + con824: +1 x41 -29000 x784 <= +0 + con825: +1 x17 +29000 x784 <= +29000 + con826: +1 x17 +1 x41 -29000 x785 <= +0 + con827: +1 x42 -29000 x786 <= +0 + con828: +1 x18 +29000 x786 <= +29000 + con829: +1 x18 +1 x42 -29000 x787 <= +0 + con830: +1 x43 -29000 x788 <= +0 + con831: +1 x19 +29000 x788 <= +29000 + con832: +1 x19 +1 x43 -29000 x789 <= +0 + con833: +1 x44 -29000 x790 <= +0 + con834: +1 x20 +29000 x790 <= +29000 + con835: +1 x20 +1 x44 -29000 x791 <= +0 + con836: +1 x45 -29000 x792 <= +0 + con837: +1 x21 +29000 x792 <= +29000 + con838: +1 x21 +1 x45 -29000 x793 <= +0 + con839: +1 x46 -29000 x794 <= +0 + con840: +1 x22 +29000 x794 <= +29000 + con841: +1 x22 +1 x46 -29000 x795 <= +0 + con842: +1 x47 -29000 x796 <= +0 + con843: +1 x23 +29000 x796 <= +29000 + con844: +1 x23 +1 x47 -29000 x797 <= +0 + con845: +1 x48 -29000 x798 <= +0 + con846: +1 x24 +29000 x798 <= +29000 + con847: +1 x24 +1 x48 -29000 x799 <= +0 + con848: +1 x49 -29000 x800 <= +0 + con849: +1 x25 +29000 x800 <= +29000 + con850: +1 x25 +1 x49 -29000 x801 <= +0 + con851: -17400 x802 <= +0 + con852: +17400 x802 <= +17400 + con853: -17400 x803 <= +0 + con854: -29000 x804 <= +0 + con855: +29000 x804 <= +29000 + con856: -29000 x805 <= +0 + con857: -29000 x806 <= +0 + con858: +29000 x806 <= +29000 + con859: -29000 x807 <= +0 + con860: +1 x703 -29000 x808 <= +0 + con861: +1 x702 +29000 x808 <= +29000 + con862: +1 x702 +1 x703 -29000 x809 <= +0 + con863: +1 x705 -29000 x810 <= +0 + con864: +1 x704 +29000 x810 <= +29000 + con865: +1 x704 +1 x705 -29000 x811 <= +0 + con866: +1 x707 -29000 x812 <= +0 + con867: +1 x706 +29000 x812 <= +29000 + con868: +1 x706 +1 x707 -29000 x813 <= +0 + con869: +1 x709 -29000 x814 <= +0 + con870: +1 x708 +29000 x814 <= +29000 + con871: +1 x708 +1 x709 -29000 x815 <= +0 + con872: +1 x711 -29000 x816 <= +0 + con873: +1 x710 +29000 x816 <= +29000 + con874: +1 x710 +1 x711 -29000 x817 <= +0 + con875: +1 x713 -29000 x818 <= +0 + con876: +1 x712 +29000 x818 <= +29000 + con877: +1 x712 +1 x713 -29000 x819 <= +0 + con878: +1 x715 -29000 x820 <= +0 + con879: +1 x714 +29000 x820 <= +29000 + con880: +1 x714 +1 x715 -29000 x821 <= +0 + con881: +1 x717 -29000 x822 <= +0 + con882: +1 x716 +29000 x822 <= +29000 + con883: +1 x716 +1 x717 -29000 x823 <= +0 + con884: +1 x719 -29000 x824 <= +0 + con885: +1 x718 +29000 x824 <= +29000 + con886: +1 x718 +1 x719 -29000 x825 <= +0 + con887: +1 x721 -29000 x826 <= +0 + con888: +1 x720 +29000 x826 <= +29000 + con889: +1 x720 +1 x721 -29000 x827 <= +0 + con890: +1 x723 -29000 x828 <= +0 + con891: +1 x722 +29000 x828 <= +29000 + con892: +1 x722 +1 x723 -29000 x829 <= +0 + con893: +1 x725 -29000 x830 <= +0 + con894: +1 x724 +29000 x830 <= +29000 + con895: +1 x724 +1 x725 -29000 x831 <= +0 + con896: +1 x727 -29000 x832 <= +0 + con897: +1 x726 +29000 x832 <= +29000 + con898: +1 x726 +1 x727 -29000 x833 <= +0 + con899: +1 x729 -29000 x834 <= +0 + con900: +1 x728 +29000 x834 <= +29000 + con901: +1 x728 +1 x729 -29000 x835 <= +0 + con902: +1 x731 -29000 x836 <= +0 + con903: +1 x730 +29000 x836 <= +29000 + con904: +1 x730 +1 x731 -29000 x837 <= +0 + con905: +1 x733 -29000 x838 <= +0 + con906: +1 x732 +29000 x838 <= +29000 + con907: +1 x732 +1 x733 -29000 x839 <= +0 + con908: +1 x735 -29000 x840 <= +0 + con909: +1 x734 +29000 x840 <= +29000 + con910: +1 x734 +1 x735 -29000 x841 <= +0 + con911: +1 x737 -29000 x842 <= +0 + con912: +1 x736 +29000 x842 <= +29000 + con913: +1 x736 +1 x737 -29000 x843 <= +0 + con914: +1 x739 -29000 x844 <= +0 + con915: +1 x738 +29000 x844 <= +29000 + con916: +1 x738 +1 x739 -29000 x845 <= +0 + con917: +1 x741 -29000 x846 <= +0 + con918: +1 x740 +29000 x846 <= +29000 + con919: +1 x740 +1 x741 -29000 x847 <= +0 + con920: +1 x743 -29000 x848 <= +0 + con921: +1 x742 +29000 x848 <= +29000 + con922: +1 x742 +1 x743 -29000 x849 <= +0 + con923: +1 x745 -29000 x850 <= +0 + con924: +1 x744 +29000 x850 <= +29000 + con925: +1 x744 +1 x745 -29000 x851 <= +0 + con926: +1 x747 -29000 x852 <= +0 + con927: +1 x746 +29000 x852 <= +29000 + con928: +1 x746 +1 x747 -29000 x853 <= +0 + con929: +1 x51 -29000 x854 <= +0 + con930: +1 x50 +29000 x854 <= +29000 + con931: +1 x50 +1 x51 -29000 x855 <= +0 + con932: = +0 + con933: = +0 + con934: = +0 + con935: +1 x703 = +0 + con936: +1 x705 = +0 + con937: +1 x707 = +0 + con938: +1 x709 = +0 + con939: +1 x711 = +0 + con940: +1 x713 = +0 + con941: +1 x715 = +0 + con942: +1 x717 = +0 + con943: +1 x719 = +0 + con944: +1 x721 = +0 + con945: +1 x723 = +0 + con946: +1 x725 = +0 + con947: +1 x727 = +0 + con948: +1 x729 = +0 + con949: +1 x731 = +0 + con950: +1 x733 = +0 + con951: +1 x735 = +0 + con952: +1 x737 = +0 + con953: +1 x739 = +0 + con954: +1 x741 = +0 + con955: +1 x743 = +0 + con956: +1 x745 = +0 + con957: +1 x747 = +0 + con958: = +0 + con959: = +0 + con960: = +0 + con961: +1 x702 = +0 + con962: +1 x704 = +0 + con963: +1 x706 = +0 + con964: +1 x708 = +0 + con965: +1 x710 = +0 + con966: +1 x712 = +0 + con967: +1 x714 = +0 + con968: +1 x716 = +0 + con969: +1 x718 = +0 + con970: +1 x720 = +0 + con971: +1 x722 = +0 + con972: +1 x724 = +0 + con973: +1 x726 = +0 + con974: +1 x728 = +0 + con975: +1 x730 = +0 + con976: +1 x732 = +0 + con977: +1 x734 = +0 + con978: +1 x736 = +0 + con979: +1 x738 = +0 + con980: +1 x740 = +0 + con981: +1 x742 = +0 + con982: +1 x744 = +0 + con983: +1 x746 = +0 + con984: +1 x328 +1 x330 +1 x332 +1 x334 +1 x337 +1 x340 +1 x343 +1 x346 +1 x349 +1 x352 +1 x355 +1 x358 +1 x361 +1 x364 +1 x367 +1 x370 +1 x373 +1 x376 +1 x379 +1 x382 +1 x385 +1 x388 +1 x391 +1 x394 +1 x397 +1 x400 +1 x403 <= +20970.557 + con985: +1 x135 +1 x136 +1 x137 +1 x138 +1 x139 +1 x140 +1 x141 +1 x142 +1 x143 +1 x144 +1 x145 +1 x146 +1 x147 +1 x148 +1 x149 +1 x150 +1 x151 +1 x152 +1 x153 +1 x154 +1 x155 +1 x156 +1 x157 +1 x158 <= +20970.557 + con986: +1 x335 <= +6000 + con987: +1 x338 <= +6000 + con988: +1 x341 <= +6000 + con989: +1 x344 <= +6000 + con990: +1 x347 <= +6000 + con991: +1 x350 <= +6000 + con992: +1 x353 <= +6000 + con993: +1 x356 <= +6000 + con994: +1 x359 <= +6000 + con995: +1 x362 <= +6000 + con996: +1 x365 <= +6000 + con997: +1 x368 <= +6000 + con998: +1 x371 <= +6000 + con999: +1 x374 <= +6000 + con1000: +1 x377 <= +6000 + con1001: +1 x380 <= +6000 + con1002: +1 x383 <= +6000 + con1003: +1 x386 <= +6000 + con1004: +1 x389 <= +6000 + con1005: +1 x392 <= +6000 + con1006: +1 x395 <= +6000 + con1007: +1 x398 <= +6000 + con1008: +1 x401 <= +6000 + con1009: +1 x404 <= +6000 + con1010: +1 x135 <= +3500 + con1011: +1 x136 <= +3500 + con1012: +1 x137 <= +3500 + con1013: +1 x138 <= +3500 + con1014: +1 x139 <= +3500 + con1015: +1 x140 <= +3500 + con1016: +1 x141 <= +3500 + con1017: +1 x142 <= +3500 + con1018: +1 x143 <= +4000 + con1019: +1 x144 <= +4000 + con1020: +1 x145 <= +4000 + con1021: +1 x146 <= +4000 + con1022: +1 x147 <= +4000 + con1023: +1 x148 <= +4000 + con1024: +1 x149 <= +4000 + con1025: +1 x150 <= +4000 + con1026: +1 x151 <= +3500 + con1027: +1 x152 <= +3500 + con1028: +1 x153 <= +3500 + con1029: +1 x154 <= +3500 + con1030: +1 x155 <= +3500 + con1031: +1 x156 <= +3500 + con1032: +1 x157 <= +3500 + con1033: +1 x158 <= +3500 + con1034: +1 x749 +1 x803 <= +2 + con1035: +1 x751 +1 x805 <= +2 + con1036: +1 x753 +1 x807 <= +2 + con1037: +1 x755 +1 x809 <= +1 + con1038: +1 x757 +1 x811 <= +1 + con1039: +1 x759 +1 x813 <= +1 + con1040: +1 x761 +1 x815 <= +1 + con1041: +1 x763 +1 x817 <= +1 + con1042: +1 x765 +1 x819 <= +1 + con1043: +1 x767 +1 x821 <= +1 + con1044: +1 x769 +1 x823 <= +1 + con1045: +1 x771 +1 x825 <= +1 + con1046: +1 x773 +1 x827 <= +1 + con1047: +1 x775 +1 x829 <= +1 + con1048: +1 x777 +1 x831 <= +1 + con1049: +1 x779 +1 x833 <= +1 + con1050: +1 x781 +1 x835 <= +1 + con1051: +1 x783 +1 x837 <= +1 + con1052: +1 x785 +1 x839 <= +1 + con1053: +1 x787 +1 x841 <= +1 + con1054: +1 x789 +1 x843 <= +1 + con1055: +1 x791 +1 x845 <= +1 + con1056: +1 x793 +1 x847 <= +1 + con1057: +1 x795 +1 x849 <= +1 + con1058: +1 x797 +1 x851 <= +1 + con1059: +1 x799 +1 x853 <= +1 + con1060: +1 x801 +1 x855 <= +1 +bounds + x1 = 1 + x52 <= 8700 + x53 <= 14500 + x54 <= 14500 + x55 <= 14500 + x56 <= 14500 + x57 <= 14500 + x58 <= 14500 + x59 <= 14500 + x60 <= 14500 + x61 <= 14500 + x62 <= 14500 + x63 <= 14500 + x64 <= 14500 + x65 <= 14500 + x66 <= 14500 + x67 <= 14500 + x68 <= 14500 + x69 <= 14500 + x70 <= 14500 + x71 <= 14500 + x72 <= 14500 + x73 <= 14500 + x74 <= 14500 + x75 <= 14500 + x76 <= 14500 + x77 <= 14500 + x78 <= 14500 + x159 <= 6000 + x160 <= 12000 + x161 <= 12000 + x162 <= 12000 + x163 <= 12000 + x164 <= 3500 + x165 <= 7000 + x166 <= 8000 + x167 <= 7000 + x168 <= 8000 + x169 <= 6000 + x170 <= 12000 + x171 <= 12000 + x172 <= 12000 + x173 <= 3500 + x174 <= 7000 + x175 <= 7000 + x176 <= 7000 + x177 <= 6000 + x178 <= 12000 + x179 <= 12000 + x180 <= 12000 + x181 <= 3500 + x182 <= 7000 + x183 <= 7000 + x184 <= 7000 + x185 <= 6000 + x186 <= 12000 + x187 <= 12000 + x188 <= 12000 + x189 <= 3500 + x190 <= 7000 + x191 <= 7000 + x192 <= 7000 + x193 <= 6000 + x194 <= 12000 + x195 <= 12000 + x196 <= 12000 + x197 <= 3500 + x198 <= 7000 + x199 <= 7000 + x200 <= 7000 + x201 <= 6000 + x202 <= 12000 + x203 <= 12000 + x204 <= 12000 + x205 <= 3500 + x206 <= 7000 + x207 <= 7000 + x208 <= 7000 + x209 <= 6000 + x210 <= 12000 + x211 <= 12000 + x212 <= 12000 + x213 <= 3500 + x214 <= 7000 + x215 <= 7000 + x216 <= 7000 + x217 <= 6000 + x218 <= 12000 + x219 <= 12000 + x220 <= 12000 + x221 <= 3500 + x222 <= 7000 + x223 <= 8000 + x224 <= 7000 + x225 <= 6000 + x226 <= 12000 + x227 <= 12000 + x228 <= 12000 + x229 <= 4000 + x230 <= 8000 + x231 <= 8000 + x232 <= 8000 + x233 <= 6000 + x234 <= 12000 + x235 <= 12000 + x236 <= 12000 + x237 <= 4000 + x238 <= 8000 + x239 <= 8000 + x240 <= 8000 + x241 <= 6000 + x242 <= 12000 + x243 <= 12000 + x244 <= 12000 + x245 <= 4000 + x246 <= 8000 + x247 <= 8000 + x248 <= 8000 + x249 <= 6000 + x250 <= 12000 + x251 <= 12000 + x252 <= 12000 + x253 <= 4000 + x254 <= 8000 + x255 <= 8000 + x256 <= 8000 + x257 <= 1 + x258 <= 1 + x259 <= 1 + x260 <= 1 + x261 <= 1 + x262 <= 1 + x263 <= 1 + x264 <= 1 + x265 <= 1 + x266 <= 1 + x267 <= 1 + x268 <= 1 + x269 <= 1 + x270 <= 12000 + x271 <= 1 + x272 <= 8000 + x273 <= 1 + x274 <= 1 + x275 <= 1 + x276 <= 1 + x277 <= 1 + x278 <= 1 + x279 <= 1 + x280 <= 1 + x281 <= 1 + x282 <= 1 + x283 <= 1 + x284 <= 1 + x285 <= 1 + x286 <= 1 + x287 <= 1 + x288 <= 1 + x289 <= 1 + x290 <= 1 + x291 <= 1 + x292 <= 1 + x293 <= 1 + x294 <= 1 + x295 <= 1 + x296 <= 1 + x297 <= 1 + x298 <= 1 + x299 <= 12 + x300 <= 8 + x301 <= 12 + x302 <= 7 + x303 <= 12 + x304 <= 7 + x305 <= 12 + x306 <= 7 + x307 <= 12 + x308 <= 7 + x309 <= 12 + x310 <= 7 + x311 <= 12 + x312 <= 7 + x313 <= 12 + x314 <= 7 + x315 <= 12 + x316 <= 7 + x317 <= 12 + x318 <= 8 + x319 <= 12 + x320 <= 8 + x321 <= 12 + x322 <= 8 + x323 <= 12 + x324 <= 8 + x325 <= 12 + x326 <= 8 + x327 <= 8700 + x328 <= 8700 + x329 <= 14500 + x330 <= 14500 + x331 <= 14500 + x332 <= 14500 + x333 <= 14500 + x334 <= 14500 + x336 <= 14500 + x337 <= 14500 + x339 <= 14500 + x340 <= 14500 + x342 <= 14500 + x343 <= 14500 + x345 <= 14500 + x346 <= 14500 + x348 <= 14500 + x349 <= 14500 + x351 <= 14500 + x352 <= 14500 + x354 <= 14500 + x355 <= 14500 + x357 <= 14500 + x358 <= 14500 + x360 <= 14500 + x361 <= 14500 + x363 <= 14500 + x364 <= 14500 + x366 <= 14500 + x367 <= 14500 + x369 <= 14500 + x370 <= 14500 + x372 <= 14500 + x373 <= 14500 + x375 <= 14500 + x376 <= 14500 + x378 <= 14500 + x379 <= 14500 + x381 <= 14500 + x382 <= 14500 + x384 <= 14500 + x385 <= 14500 + x387 <= 14500 + x388 <= 14500 + x390 <= 14500 + x391 <= 14500 + x393 <= 14500 + x394 <= 14500 + x396 <= 14500 + x397 <= 14500 + x399 <= 14500 + x400 <= 14500 + x402 <= 14500 + x403 <= 14500 + x405 <= 1 + x406 <= 1 + x407 <= 1 + x408 <= 1 + x409 <= 1 + x410 <= 1 + x411 <= 1 + x412 <= 1 + x413 <= 1 + x414 <= 1 + x415 <= 1 + x416 <= 1 + x417 <= 1 + x418 <= 1 + x419 <= 1 + x420 <= 1 + x421 <= 1 + x422 <= 1 + x423 <= 1 + x424 <= 1 + x425 <= 1 + x426 <= 1 + x427 <= 1 + x428 <= 1 + x429 <= 1 + x430 <= 1 + x431 <= 1 + x540 <= 1 + x541 <= 1 + x542 <= 1 + x543 <= 1 + x544 <= 1 + x545 <= 1 + x546 <= 1 + x547 <= 1 + x548 <= 1 + x549 <= 1 + x550 <= 1 + x551 <= 1 + x552 <= 1 + x553 <= 1 + x554 <= 1 + x555 <= 1 + x556 <= 1 + x557 <= 1 + x558 <= 1 + x559 <= 1 + x560 <= 1 + x561 <= 1 + x562 <= 1 + x563 <= 1 + x564 <= 1 + x565 <= 1 + x566 <= 1 + x567 <= 29000 + x568 <= 29000 + x569 <= 29000 + x570 <= 29000 + x571 <= 29000 + x572 <= 29000 + x573 <= 29000 + x574 <= 29000 + x575 <= 29000 + x576 <= 29000 + x577 <= 29000 + x578 <= 29000 + x579 <= 29000 + x580 <= 29000 + x581 <= 29000 + x582 <= 29000 + x583 <= 29000 + x584 <= 29000 + x585 <= 29000 + x586 <= 29000 + x587 <= 29000 + x588 <= 29000 + x589 <= 29000 + x590 <= 29000 + x591 <= 29000 + x592 <= 29000 + x593 <= 29000 + x648 <= 8700 + x649 <= 14500 + x650 <= 14500 + x651 <= 14500 + x652 <= 14500 + x653 <= 14500 + x654 <= 14500 + x655 <= 14500 + x656 <= 14500 + x657 <= 14500 + x658 <= 14500 + x659 <= 14500 + x660 <= 14500 + x661 <= 14500 + x662 <= 14500 + x663 <= 14500 + x664 <= 14500 + x665 <= 14500 + x666 <= 14500 + x667 <= 14500 + x668 <= 14500 + x669 <= 14500 + x670 <= 14500 + x671 <= 14500 + x672 <= 14500 + x673 <= 14500 + x674 <= 14500 + x675 <= 1 + x676 <= 1 + x677 <= 1 + x678 <= 1 + x679 <= 1 + x680 <= 1 + x681 <= 1 + x682 <= 1 + x683 <= 1 + x684 <= 1 + x685 <= 1 + x686 <= 1 + x687 <= 1 + x688 <= 1 + x689 <= 1 + x690 <= 1 + x691 <= 1 + x692 <= 1 + x693 <= 1 + x694 <= 1 + x695 <= 1 + x696 <= 1 + x697 <= 1 + x698 <= 1 + x699 <= 1 + x700 <= 1 + x701 <= 1 + x748 <= 1 + x749 <= 1 + x750 <= 1 + x751 <= 1 + x752 <= 1 + x753 <= 1 + x754 <= 1 + x755 <= 1 + x756 <= 1 + x757 <= 1 + x758 <= 1 + x759 <= 1 + x760 <= 1 + x761 <= 1 + x762 <= 1 + x763 <= 1 + x764 <= 1 + x765 <= 1 + x766 <= 1 + x767 <= 1 + x768 <= 1 + x769 <= 1 + x770 <= 1 + x771 <= 1 + x772 <= 1 + x773 <= 1 + x774 <= 1 + x775 <= 1 + x776 <= 1 + x777 <= 1 + x778 <= 1 + x779 <= 1 + x780 <= 1 + x781 <= 1 + x782 <= 1 + x783 <= 1 + x784 <= 1 + x785 <= 1 + x786 <= 1 + x787 <= 1 + x788 <= 1 + x789 <= 1 + x790 <= 1 + x791 <= 1 + x792 <= 1 + x793 <= 1 + x794 <= 1 + x795 <= 1 + x796 <= 1 + x797 <= 1 + x798 <= 1 + x799 <= 1 + x800 <= 1 + x801 <= 1 + x802 <= 1 + x803 <= 1 + x804 <= 1 + x805 <= 1 + x806 <= 1 + x807 <= 1 + x808 <= 1 + x809 <= 1 + x810 <= 1 + x811 <= 1 + x812 <= 1 + x813 <= 1 + x814 <= 1 + x815 <= 1 + x816 <= 1 + x817 <= 1 + x818 <= 1 + x819 <= 1 + x820 <= 1 + x821 <= 1 + x822 <= 1 + x823 <= 1 + x824 <= 1 + x825 <= 1 + x826 <= 1 + x827 <= 1 + x828 <= 1 + x829 <= 1 + x830 <= 1 + x831 <= 1 + x832 <= 1 + x833 <= 1 + x834 <= 1 + x835 <= 1 + x836 <= 1 + x837 <= 1 + x838 <= 1 + x839 <= 1 + x840 <= 1 + x841 <= 1 + x842 <= 1 + x843 <= 1 + x844 <= 1 + x845 <= 1 + x846 <= 1 + x847 <= 1 + x848 <= 1 + x849 <= 1 + x850 <= 1 + x851 <= 1 + x852 <= 1 + x853 <= 1 + x854 <= 1 + x855 <= 1 +bin + x257 + x258 + x259 + x260 + x261 + x262 + x263 + x264 + x265 + x266 + x267 + x268 + x269 + x271 + x273 + x274 + x275 + x276 + x277 + x278 + x279 + x280 + x281 + x282 + x283 + x284 + x285 + x286 + x287 + x288 + x289 + x290 + x291 + x292 + x293 + x294 + x295 + x296 + x297 + x298 + x405 + x406 + x407 + x408 + x409 + x410 + x411 + x412 + x413 + x414 + x415 + x416 + x417 + x418 + x419 + x420 + x421 + x422 + x423 + x424 + x425 + x426 + x427 + x428 + x429 + x430 + x431 + x540 + x541 + x542 + x543 + x544 + x545 + x546 + x547 + x548 + x549 + x550 + x551 + x552 + x553 + x554 + x555 + x556 + x557 + x558 + x559 + x560 + x561 + x562 + x563 + x564 + x565 + x566 + x675 + x676 + x677 + x678 + x679 + x680 + x681 + x682 + x683 + x684 + x685 + x686 + x687 + x688 + x689 + x690 + x691 + x692 + x693 + x694 + x695 + x696 + x697 + x698 + x699 + x700 + x701 + x748 + x749 + x750 + x751 + x752 + x753 + x754 + x755 + x756 + x757 + x758 + x759 + x760 + x761 + x762 + x763 + x764 + x765 + x766 + x767 + x768 + x769 + x770 + x771 + x772 + x773 + x774 + x775 + x776 + x777 + x778 + x779 + x780 + x781 + x782 + x783 + x784 + x785 + x786 + x787 + x788 + x789 + x790 + x791 + x792 + x793 + x794 + x795 + x796 + x797 + x798 + x799 + x800 + x801 + x802 + x803 + x804 + x805 + x806 + x807 + x808 + x809 + x810 + x811 + x812 + x813 + x814 + x815 + x816 + x817 + x818 + x819 + x820 + x821 + x822 + x823 + x824 + x825 + x826 + x827 + x828 + x829 + x830 + x831 + x832 + x833 + x834 + x835 + x836 + x837 + x838 + x839 + x840 + x841 + x842 + x843 + x844 + x845 + x846 + x847 + x848 + x849 + x850 + x851 + x852 + x853 + x854 + x855 +gen + x299 + x300 + x301 + x302 + x303 + x304 + x305 + x306 + x307 + x308 + x309 + x310 + x311 + x312 + x313 + x314 + x315 + x316 + x317 + x318 + x319 + x320 + x321 + x322 + x323 + x324 + x325 + x326 +semi +end diff --git a/check/instances/2171.mps b/check/instances/2171.mps new file mode 100644 index 0000000000..2a3e3e96db --- /dev/null +++ b/check/instances/2171.mps @@ -0,0 +1,717 @@ +*SENSE:Minimize +NAME seed +ROWS + N OBJ + G _C1 + L _C2 + G _C3 + L _C4 + G _C5 + G _C6 + L _C7 + G _C8 + G _C9 + L _C10 + G _C11 + G _C12 + L _C13 + G _C14 + G _C15 + G _C16 + L _C17 + G _C18 + L _C19 + G _C20 + G _C21 + G _C22 + L _C23 + L _C24 + G _C25 + G _C26 + G _C27 + L _C28 + L _C29 + L _C30 + L _C31 + L _C32 + L _C33 + G _C34 + L _C35 + L _C36 + L _C37 + G _C38 + L _C39 + G _C40 + G _C41 + G _C42 + L _C43 + L _C44 + G _C45 + L _C46 + L _C47 + L _C48 + G _C49 + L _C50 + G _C51 + L _C52 + L _C53 + G _C54 + L _C55 + L _C56 + L _C57 + L _C58 + G _C59 + L _C60 + L _C61 + G _C62 + G _C63 + L _C64 + G _C65 + G _C66 + L _C67 + G _C68 + L _C69 + G _C70 + L _C71 + L _C72 + G _C73 + G _C74 + L _C75 + L _C76 + G _C77 + L _C78 + L _C79 + L _C80 + L _C81 + L _C82 + G _C83 + G _C84 + L _C85 + L _C86 + L _C87 + L _C88 + L _C89 + L _C90 + G _C91 + G _C92 + G _C93 + L _C94 + G _C95 + L _C96 + L _C97 + L _C98 +COLUMNS + MARK 'MARKER' 'INTORG' + x0 _C1 1.340000000000e+01 + x0 _C2 -2.760000000000e+00 + x0 _C3 5.100000000000e+00 + x0 _C4 1.152000000000e+01 + x0 _C5 8.180000000000e+00 + x0 _C6 -7.650000000000e+00 + x0 _C7 -1.804000000000e+01 + x0 _C8 1.074000000000e+01 + x0 _C9 -1.290000000000e+00 + x0 _C10 4.710000000000e+00 + x0 _C11 -5.250000000000e+00 + x0 _C12 -1.226000000000e+01 + x0 _C13 -8.890000000000e+00 + x0 _C14 1.504000000000e+01 + x0 _C15 1.280000000000e+00 + x0 _C16 1.159000000000e+01 + x0 _C17 1.544000000000e+01 + x0 _C18 1.772000000000e+01 + x0 _C19 3.640000000000e+00 + x0 _C20 -4.060000000000e+00 + x0 _C21 4.460000000000e+00 + x0 _C22 1.956000000000e+01 + x0 _C23 1.569000000000e+01 + x0 _C24 2.820000000000e+00 + x0 _C25 -1.269000000000e+01 + x0 _C26 -2.150000000000e+00 + x0 _C27 -8.480000000000e+00 + x0 _C28 -1.337000000000e+01 + x0 _C29 -1.955000000000e+01 + x0 _C30 1.436000000000e+01 + x0 _C31 1.324000000000e+01 + x0 _C32 1.875000000000e+01 + x0 _C33 -5.800000000000e+00 + x0 _C34 -1.870000000000e+01 + x0 _C35 1.912000000000e+01 + x0 _C36 -1.093000000000e+01 + x0 _C37 -1.607000000000e+01 + x0 _C38 -1.501000000000e+01 + x0 _C39 -1.180000000000e+01 + x0 _C40 7.850000000000e+00 + x0 _C41 -2.990000000000e+00 + x0 _C42 -2.560000000000e+00 + x0 _C43 -3.160000000000e+00 + x0 _C44 -1.572000000000e+01 + x0 _C45 -1.987000000000e+01 + x0 _C46 -2.710000000000e+00 + x0 _C47 -1.862000000000e+01 + x0 _C48 8.510000000000e+00 + x0 _C49 -1.876000000000e+01 + x0 _C50 -9.260000000000e+00 + x0 _C51 6.340000000000e+00 + x0 _C52 -8.050000000000e+00 + x0 _C53 -3.200000000000e+00 + x0 _C54 -1.610000000000e+01 + x0 _C55 1.545000000000e+01 + x0 _C56 1.140000000000e+00 + x0 _C57 8.090000000000e+00 + x0 _C58 1.640000000000e+00 + x0 _C59 -4.870000000000e+00 + x0 _C60 1.505000000000e+01 + x0 _C61 -1.969000000000e+01 + x0 _C62 -1.210000000000e+00 + x0 _C63 4.000000000000e-02 + x0 _C64 -3.370000000000e+00 + x0 _C65 -1.870000000000e+01 + x0 _C66 9.000000000000e-02 + x0 _C67 4.380000000000e+00 + x0 _C68 5.920000000000e+00 + x0 _C69 -8.280000000000e+00 + x0 _C70 1.511000000000e+01 + x0 _C71 1.936000000000e+01 + x0 _C72 8.850000000000e+00 + x0 _C73 -9.110000000000e+00 + x0 _C74 -1.670000000000e+01 + x0 _C75 1.800000000000e+00 + x0 _C76 -1.536000000000e+01 + x0 _C77 1.426000000000e+01 + x0 _C78 -1.222000000000e+01 + x0 _C79 -5.660000000000e+00 + x0 _C80 1.860000000000e+00 + x0 _C81 -5.870000000000e+00 + x0 _C82 1.893000000000e+01 + x0 _C83 1.061000000000e+01 + x0 _C84 1.028000000000e+01 + x0 _C85 1.674000000000e+01 + x0 _C86 1.297000000000e+01 + x0 _C87 -1.448000000000e+01 + x0 _C88 -2.460000000000e+00 + x0 _C89 9.730000000000e+00 + x0 _C90 2.240000000000e+00 + x0 _C91 -1.416000000000e+01 + x0 _C92 1.572000000000e+01 + x0 _C93 -1.233000000000e+01 + x0 _C94 -7.080000000000e+00 + x0 _C95 7.940000000000e+00 + x0 _C96 -9.240000000000e+00 + x0 _C97 1.146000000000e+01 + x0 _C98 -8.090000000000e+00 + x0 OBJ 9.260000000000e+01 + MARK 'MARKER' 'INTEND' + MARK 'MARKER' 'INTORG' + x1 _C1 -6.810000000000e+00 + x1 _C2 6.840000000000e+00 + x1 _C3 2.400000000000e+00 + x1 _C4 1.833000000000e+01 + x1 _C5 -5.200000000000e-01 + x1 _C6 8.370000000000e+00 + x1 _C7 1.711000000000e+01 + x1 _C8 -1.300000000000e+01 + x1 _C9 -1.417000000000e+01 + x1 _C10 -5.700000000000e+00 + x1 _C11 -1.775000000000e+01 + x1 _C12 -5.930000000000e+00 + x1 _C13 -1.298000000000e+01 + x1 _C14 -3.140000000000e+00 + x1 _C15 -1.700000000000e+00 + x1 _C16 -1.325000000000e+01 + x1 _C17 1.566000000000e+01 + x1 _C18 -9.560000000000e+00 + x1 _C19 1.712000000000e+01 + x1 _C20 -6.100000000000e+00 + x1 _C21 -8.400000000000e+00 + x1 _C22 -1.632000000000e+01 + x1 _C23 6.600000000000e+00 + x1 _C24 1.699000000000e+01 + x1 _C25 -1.220000000000e+01 + x1 _C26 -7.300000000000e-01 + x1 _C27 -1.624000000000e+01 + x1 _C28 1.866000000000e+01 + x1 _C29 1.603000000000e+01 + x1 _C30 1.436000000000e+01 + x1 _C31 1.488000000000e+01 + x1 _C32 1.915000000000e+01 + x1 _C33 1.328000000000e+01 + x1 _C34 -1.010000000000e+01 + x1 _C35 1.850000000000e+01 + x1 _C36 4.220000000000e+00 + x1 _C37 1.310000000000e+01 + x1 _C38 -1.066000000000e+01 + x1 _C39 1.475000000000e+01 + x1 _C40 1.350000000000e+01 + x1 _C41 -1.653000000000e+01 + x1 _C42 -4.710000000000e+00 + x1 _C43 -4.880000000000e+00 + x1 _C44 1.442000000000e+01 + x1 _C45 -5.590000000000e+00 + x1 _C46 1.569000000000e+01 + x1 _C47 -4.240000000000e+00 + x1 _C48 9.880000000000e+00 + x1 _C49 -7.340000000000e+00 + x1 _C50 7.660000000000e+00 + x1 _C51 -1.339000000000e+01 + x1 _C52 9.800000000000e+00 + x1 _C53 -1.900000000000e+00 + x1 _C54 1.309000000000e+01 + x1 _C55 -4.140000000000e+00 + x1 _C56 7.800000000000e+00 + x1 _C57 1.903000000000e+01 + x1 _C58 -6.070000000000e+00 + x1 _C59 -1.667000000000e+01 + x1 _C60 1.449000000000e+01 + x1 _C61 7.790000000000e+00 + x1 _C62 -1.874000000000e+01 + x1 _C63 -1.723000000000e+01 + x1 _C64 -1.500000000000e+00 + x1 _C65 -1.342000000000e+01 + x1 _C66 -1.278000000000e+01 + x1 _C67 4.790000000000e+00 + x1 _C68 -5.100000000000e-01 + x1 _C69 1.400000000000e+01 + x1 _C70 1.222000000000e+01 + x1 _C71 1.909000000000e+01 + x1 _C72 1.730000000000e+01 + x1 _C73 -6.140000000000e+00 + x1 _C74 -6.570000000000e+00 + x1 _C75 1.240000000000e+00 + x1 _C76 1.273000000000e+01 + x1 _C77 -1.753000000000e+01 + x1 _C78 1.795000000000e+01 + x1 _C79 -6.210000000000e+00 + x1 _C80 -1.094000000000e+01 + x1 _C81 1.400000000000e+01 + x1 _C82 -5.790000000000e+00 + x1 _C83 -1.975000000000e+01 + x1 _C84 -2.800000000000e-01 + x1 _C85 3.360000000000e+00 + x1 _C86 4.710000000000e+00 + x1 _C87 -3.000000000000e-01 + x1 _C88 -6.790000000000e+00 + x1 _C89 -5.440000000000e+00 + x1 _C90 -7.650000000000e+00 + x1 _C91 -2.580000000000e+00 + x1 _C92 -4.600000000000e+00 + x1 _C93 3.030000000000e+00 + x1 _C94 1.149000000000e+01 + x1 _C95 -1.040000000000e+01 + x1 _C96 1.382000000000e+01 + x1 _C97 -1.402000000000e+01 + x1 _C98 -8.600000000000e+00 + x1 OBJ 8.100000000000e-01 + MARK 'MARKER' 'INTEND' + x2 _C1 -4.140000000000e+00 + x2 _C2 -1.465000000000e+01 + x2 _C3 1.629000000000e+01 + x2 _C4 -1.327000000000e+01 + x2 _C5 -6.640000000000e+00 + x2 _C6 1.569000000000e+01 + x2 _C7 8.810000000000e+00 + x2 _C8 1.003000000000e+01 + x2 _C9 1.979000000000e+01 + x2 _C10 -1.145000000000e+01 + x2 _C11 -1.139000000000e+01 + x2 _C12 6.140000000000e+00 + x2 _C13 -1.324000000000e+01 + x2 _C14 1.631000000000e+01 + x2 _C15 -7.050000000000e+00 + x2 _C16 -1.740000000000e+01 + x2 _C17 1.532000000000e+01 + x2 _C18 4.870000000000e+00 + x2 _C19 1.695000000000e+01 + x2 _C20 1.570000000000e+01 + x2 _C21 8.200000000000e-01 + x2 _C22 5.210000000000e+00 + x2 _C23 -6.600000000000e+00 + x2 _C24 -5.310000000000e+00 + x2 _C25 -1.139000000000e+01 + x2 _C26 1.026000000000e+01 + x2 _C27 -1.507000000000e+01 + x2 _C28 7.050000000000e+00 + x2 _C29 -1.160000000000e+01 + x2 _C30 -1.833000000000e+01 + x2 _C31 -7.800000000000e+00 + x2 _C32 1.505000000000e+01 + x2 _C33 1.841000000000e+01 + x2 _C34 -7.100000000000e+00 + x2 _C35 9.190000000000e+00 + x2 _C36 -1.640000000000e+01 + x2 _C37 -6.230000000000e+00 + x2 _C38 -2.170000000000e+00 + x2 _C39 3.010000000000e+00 + x2 _C40 -1.292000000000e+01 + x2 _C41 8.450000000000e+00 + x2 _C42 1.781000000000e+01 + x2 _C43 1.038000000000e+01 + x2 _C44 9.380000000000e+00 + x2 _C45 1.762000000000e+01 + x2 _C46 -1.538000000000e+01 + x2 _C47 1.215000000000e+01 + x2 _C48 1.950000000000e+00 + x2 _C49 -1.264000000000e+01 + x2 _C50 -1.285000000000e+01 + x2 _C51 -2.720000000000e+00 + x2 _C52 -1.383000000000e+01 + x2 _C53 -1.822000000000e+01 + x2 _C54 3.580000000000e+00 + x2 _C55 1.912000000000e+01 + x2 _C56 -1.760000000000e+01 + x2 _C57 -1.684000000000e+01 + x2 _C58 -7.450000000000e+00 + x2 _C59 1.955000000000e+01 + x2 _C60 7.200000000000e-01 + x2 _C61 -4.250000000000e+00 + x2 _C62 1.070000000000e+01 + x2 _C63 1.980000000000e+01 + x2 _C64 9.040000000000e+00 + x2 _C65 1.647000000000e+01 + x2 _C66 -2.550000000000e+00 + x2 _C67 -1.448000000000e+01 + x2 _C68 1.058000000000e+01 + x2 _C69 -1.275000000000e+01 + x2 _C70 1.840000000000e+00 + x2 _C71 3.540000000000e+00 + x2 _C72 -3.590000000000e+00 + x2 _C73 -3.560000000000e+00 + x2 _C74 -1.826000000000e+01 + x2 _C75 -1.708000000000e+01 + x2 _C76 1.986000000000e+01 + x2 _C77 1.352000000000e+01 + x2 _C78 4.930000000000e+00 + x2 _C79 -2.280000000000e+00 + x2 _C80 2.800000000000e-01 + x2 _C81 -1.860000000000e+00 + x2 _C82 8.470000000000e+00 + x2 _C83 9.890000000000e+00 + x2 _C84 8.050000000000e+00 + x2 _C85 6.000000000000e-02 + x2 _C86 2.000000000000e-02 + x2 _C87 8.620000000000e+00 + x2 _C88 -8.130000000000e+00 + x2 _C89 -3.920000000000e+00 + x2 _C90 7.840000000000e+00 + x2 _C91 5.010000000000e+00 + x2 _C92 3.430000000000e+00 + x2 _C93 -2.870000000000e+00 + x2 _C94 7.550000000000e+00 + x2 _C95 1.557000000000e+01 + x2 _C96 -2.900000000000e-01 + x2 _C97 -3.310000000000e+00 + x2 _C98 -9.320000000000e+00 + x2 OBJ 7.437000000000e+01 + MARK 'MARKER' 'INTORG' + x3 _C1 1.764000000000e+01 + x3 _C2 2.710000000000e+00 + x3 _C3 -6.100000000000e+00 + x3 _C4 -1.784000000000e+01 + x3 _C5 1.790000000000e+01 + x3 _C6 -1.309000000000e+01 + x3 _C7 -1.333000000000e+01 + x3 _C8 -5.710000000000e+00 + x3 _C9 -2.000000000000e-02 + x3 _C10 -1.067000000000e+01 + x3 _C11 2.000000000000e+00 + x3 _C12 8.630000000000e+00 + x3 _C13 -1.980000000000e+00 + x3 _C14 8.490000000000e+00 + x3 _C15 1.025000000000e+01 + x3 _C16 8.190000000000e+00 + x3 _C17 -1.681000000000e+01 + x3 _C18 1.614000000000e+01 + x3 _C19 4.100000000000e-01 + x3 _C20 2.520000000000e+00 + x3 _C21 1.930000000000e+01 + x3 _C22 -2.400000000000e-01 + x3 _C23 8.530000000000e+00 + x3 _C24 -1.052000000000e+01 + x3 _C25 1.771000000000e+01 + x3 _C26 7.330000000000e+00 + x3 _C27 8.200000000000e-01 + x3 _C28 -1.120000000000e+00 + x3 _C29 -1.303000000000e+01 + x3 _C30 3.880000000000e+00 + x3 _C31 -1.736000000000e+01 + x3 _C32 -5.860000000000e+00 + x3 _C33 -5.260000000000e+00 + x3 _C34 1.108000000000e+01 + x3 _C35 6.720000000000e+00 + x3 _C36 -5.150000000000e+00 + x3 _C37 -1.021000000000e+01 + x3 _C38 -1.606000000000e+01 + x3 _C39 -5.980000000000e+00 + x3 _C40 1.902000000000e+01 + x3 _C41 1.190000000000e+00 + x3 _C42 -7.440000000000e+00 + x3 _C43 -7.170000000000e+00 + x3 _C44 -1.461000000000e+01 + x3 _C45 1.540000000000e+00 + x3 _C46 -6.140000000000e+00 + x3 _C47 -1.483000000000e+01 + x3 _C48 4.790000000000e+00 + x3 _C49 -3.340000000000e+00 + x3 _C50 -1.911000000000e+01 + x3 _C51 -3.940000000000e+00 + x3 _C52 -2.690000000000e+00 + x3 _C53 -7.390000000000e+00 + x3 _C54 1.307000000000e+01 + x3 _C55 -1.950000000000e+01 + x3 _C56 1.062000000000e+01 + x3 _C57 1.740000000000e+01 + x3 _C58 -1.852000000000e+01 + x3 _C59 1.547000000000e+01 + x3 _C60 1.176000000000e+01 + x3 _C61 1.710000000000e+00 + x3 _C62 8.030000000000e+00 + x3 _C63 -6.480000000000e+00 + x3 _C64 -8.030000000000e+00 + x3 _C65 -8.130000000000e+00 + x3 _C66 1.476000000000e+01 + x3 _C67 -6.810000000000e+00 + x3 _C68 1.010000000000e+01 + x3 _C69 -1.694000000000e+01 + x3 _C70 1.149000000000e+01 + x3 _C71 8.920000000000e+00 + x3 _C72 -1.481000000000e+01 + x3 _C73 -8.150000000000e+00 + x3 _C74 8.730000000000e+00 + x3 _C75 -1.625000000000e+01 + x3 _C76 -8.980000000000e+00 + x3 _C77 -2.020000000000e+00 + x3 _C78 -3.920000000000e+00 + x3 _C79 -8.410000000000e+00 + x3 _C80 -3.510000000000e+00 + x3 _C81 -8.280000000000e+00 + x3 _C82 -1.620000000000e+01 + x3 _C83 1.239000000000e+01 + x3 _C84 1.398000000000e+01 + x3 _C85 8.900000000000e+00 + x3 _C86 6.660000000000e+00 + x3 _C87 -3.880000000000e+00 + x3 _C88 5.920000000000e+00 + x3 _C89 -8.440000000000e+00 + x3 _C90 -5.860000000000e+00 + x3 _C91 1.549000000000e+01 + x3 _C92 1.636000000000e+01 + x3 _C93 1.766000000000e+01 + x3 _C94 -1.244000000000e+01 + x3 _C95 1.255000000000e+01 + x3 _C96 -1.951000000000e+01 + x3 _C97 -9.720000000000e+00 + x3 _C98 -1.427000000000e+01 + x3 OBJ -7.574000000000e+01 + MARK 'MARKER' 'INTEND' + MARK 'MARKER' 'INTORG' + x4 _C1 3.620000000000e+00 + x4 _C2 -6.880000000000e+00 + x4 _C3 -1.026000000000e+01 + x4 _C4 1.855000000000e+01 + x4 _C5 -6.390000000000e+00 + x4 _C6 -1.488000000000e+01 + x4 _C7 -1.490000000000e+01 + x4 _C8 -2.370000000000e+00 + x4 _C9 -1.908000000000e+01 + x4 _C10 1.402000000000e+01 + x4 _C11 -1.273000000000e+01 + x4 _C12 3.720000000000e+00 + x4 _C13 1.806000000000e+01 + x4 _C14 -7.200000000000e+00 + x4 _C15 -1.660000000000e+01 + x4 _C16 1.260000000000e+00 + x4 _C17 -4.590000000000e+00 + x4 _C18 1.133000000000e+01 + x4 _C19 1.300000000000e+00 + x4 _C20 1.142000000000e+01 + x4 _C21 -1.149000000000e+01 + x4 _C22 -1.652000000000e+01 + x4 _C23 1.326000000000e+01 + x4 _C24 -7.800000000000e-01 + x4 _C25 5.920000000000e+00 + x4 _C26 -1.194000000000e+01 + x4 _C27 8.400000000000e+00 + x4 _C28 -5.660000000000e+00 + x4 _C29 -8.350000000000e+00 + x4 _C30 5.230000000000e+00 + x4 _C31 -5.830000000000e+00 + x4 _C32 -1.913000000000e+01 + x4 _C33 3.900000000000e+00 + x4 _C34 -1.280000000000e+01 + x4 _C35 1.460000000000e+00 + x4 _C36 1.867000000000e+01 + x4 _C37 1.474000000000e+01 + x4 _C38 -1.753000000000e+01 + x4 _C39 5.830000000000e+00 + x4 _C40 -5.830000000000e+00 + x4 _C41 7.790000000000e+00 + x4 _C42 -1.888000000000e+01 + x4 _C43 1.361000000000e+01 + x4 _C44 1.787000000000e+01 + x4 _C45 5.900000000000e-01 + x4 _C46 -1.435000000000e+01 + x4 _C47 1.749000000000e+01 + x4 _C48 9.080000000000e+00 + x4 _C49 7.770000000000e+00 + x4 _C50 1.183000000000e+01 + x4 _C51 -7.610000000000e+00 + x4 _C52 -5.480000000000e+00 + x4 _C53 -7.040000000000e+00 + x4 _C54 -8.760000000000e+00 + x4 _C55 -9.500000000000e-01 + x4 _C56 -2.230000000000e+00 + x4 _C57 9.990000000000e+00 + x4 _C58 1.582000000000e+01 + x4 _C59 -1.104000000000e+01 + x4 _C60 -9.090000000000e+00 + x4 _C61 1.813000000000e+01 + x4 _C62 1.051000000000e+01 + x4 _C63 8.920000000000e+00 + x4 _C64 1.691000000000e+01 + x4 _C65 9.580000000000e+00 + x4 _C66 9.180000000000e+00 + x4 _C67 1.583000000000e+01 + x4 _C68 2.490000000000e+00 + x4 _C69 1.256000000000e+01 + x4 _C70 -1.404000000000e+01 + x4 _C71 4.130000000000e+00 + x4 _C72 8.550000000000e+00 + x4 _C73 -1.204000000000e+01 + x4 _C74 -8.820000000000e+00 + x4 _C75 5.400000000000e-01 + x4 _C76 1.760000000000e+01 + x4 _C77 -1.271000000000e+01 + x4 _C78 -7.680000000000e+00 + x4 _C79 1.494000000000e+01 + x4 _C80 6.050000000000e+00 + x4 _C81 1.763000000000e+01 + x4 _C82 1.535000000000e+01 + x4 _C83 -1.625000000000e+01 + x4 _C84 6.870000000000e+00 + x4 _C85 -1.560000000000e+00 + x4 _C86 3.150000000000e+00 + x4 _C87 1.113000000000e+01 + x4 _C88 1.362000000000e+01 + x4 _C89 -1.259000000000e+01 + x4 _C90 1.124000000000e+01 + x4 _C91 -9.740000000000e+00 + x4 _C92 9.950000000000e+00 + x4 _C93 -1.756000000000e+01 + x4 _C94 1.072000000000e+01 + x4 _C95 7.510000000000e+00 + x4 _C96 9.230000000000e+00 + x4 _C97 -7.070000000000e+00 + x4 _C98 2.750000000000e+00 + x4 OBJ -1.143000000000e+01 + MARK 'MARKER' 'INTEND' +RHS + RHS _C1 7.704000000000e+01 + RHS _C2 -1.601000000000e+01 + RHS _C3 7.370000000000e+01 + RHS _C4 1.586000000000e+01 + RHS _C5 -3.274000000000e+01 + RHS _C6 -4.474000000000e+01 + RHS _C7 -8.043000000000e+01 + RHS _C8 -8.811000000000e+01 + RHS _C9 6.287000000000e+01 + RHS _C10 -3.800000000000e-01 + RHS _C11 5.304000000000e+01 + RHS _C12 2.398000000000e+01 + RHS _C13 -6.376000000000e+01 + RHS _C14 -1.804000000000e+01 + RHS _C15 4.328000000000e+01 + RHS _C16 -5.559000000000e+01 + RHS _C17 -9.775000000000e+01 + RHS _C18 7.473000000000e+01 + RHS _C19 5.981000000000e+01 + RHS _C20 8.278000000000e+01 + RHS _C21 -1.600000000000e-01 + RHS _C22 -7.803000000000e+01 + RHS _C23 -2.654000000000e+01 + RHS _C24 -1.725000000000e+01 + RHS _C25 2.388000000000e+01 + RHS _C26 7.512000000000e+01 + RHS _C27 7.503000000000e+01 + RHS _C28 -5.365000000000e+01 + RHS _C29 7.422000000000e+01 + RHS _C30 8.743000000000e+01 + RHS _C31 -9.644000000000e+01 + RHS _C32 -2.519000000000e+01 + RHS _C33 9.879000000000e+01 + RHS _C34 6.983000000000e+01 + RHS _C35 6.159000000000e+01 + RHS _C36 2.694000000000e+01 + RHS _C37 5.155000000000e+01 + RHS _C38 9.375000000000e+01 + RHS _C39 -1.479000000000e+01 + RHS _C40 7.601000000000e+01 + RHS _C41 3.679000000000e+01 + RHS _C42 6.707000000000e+01 + RHS _C43 1.250000000000e+00 + RHS _C44 3.029000000000e+01 + RHS _C45 2.800000000000e+00 + RHS _C46 -2.180000000000e+01 + RHS _C47 -7.917000000000e+01 + RHS _C48 1.299000000000e+01 + RHS _C49 -8.319000000000e+01 + RHS _C50 6.803000000000e+01 + RHS _C51 -7.105000000000e+01 + RHS _C52 4.473000000000e+01 + RHS _C53 3.513000000000e+01 + RHS _C54 -1.420000000000e+00 + RHS _C55 -3.600000000000e+00 + RHS _C56 -2.532000000000e+01 + RHS _C57 9.410000000000e+00 + RHS _C58 2.140000000000e+00 + RHS _C59 7.600000000000e+01 + RHS _C60 -3.150000000000e+01 + RHS _C61 -9.743000000000e+01 + RHS _C62 9.303000000000e+01 + RHS _C63 6.213000000000e+01 + RHS _C64 4.019000000000e+01 + RHS _C65 6.691000000000e+01 + RHS _C66 1.925000000000e+01 + RHS _C67 8.789000000000e+01 + RHS _C68 4.610000000000e+00 + RHS _C69 1.242000000000e+01 + RHS _C70 8.063000000000e+01 + RHS _C71 9.538000000000e+01 + RHS _C72 -1.581000000000e+01 + RHS _C73 -5.479000000000e+01 + RHS _C74 2.576000000000e+01 + RHS _C75 -6.193000000000e+01 + RHS _C76 8.649000000000e+01 + RHS _C77 8.911000000000e+01 + RHS _C78 -8.219000000000e+01 + RHS _C79 -5.545000000000e+01 + RHS _C80 2.457000000000e+01 + RHS _C81 1.380000000000e+00 + RHS _C82 9.627000000000e+01 + RHS _C83 -2.008000000000e+01 + RHS _C84 1.059000000000e+01 + RHS _C85 -6.302000000000e+01 + RHS _C86 -8.181000000000e+01 + RHS _C87 6.376000000000e+01 + RHS _C88 -1.916000000000e+01 + RHS _C89 7.153000000000e+01 + RHS _C90 -2.240000000000e+00 + RHS _C91 -5.183000000000e+01 + RHS _C92 2.430000000000e+00 + RHS _C93 3.911000000000e+01 + RHS _C94 2.501000000000e+01 + RHS _C95 -7.167000000000e+01 + RHS _C96 -6.749000000000e+01 + RHS _C97 -5.058000000000e+01 + RHS _C98 -3.153000000000e+01 +BOUNDS + LO BND x0 -2.000000000000e+02 + UP BND x0 2.000000000000e+02 + LO BND x1 -2.000000000000e+02 + UP BND x1 2.000000000000e+02 + LO BND x2 -2.000000000000e+02 + UP BND x2 2.000000000000e+02 + LO BND x3 -2.000000000000e+02 + UP BND x3 2.000000000000e+02 + LO BND x4 -2.000000000000e+02 + UP BND x4 2.000000000000e+02 +ENDATA diff --git a/check/instances/gesa2.mps b/check/instances/gesa2.mps new file mode 100644 index 0000000000..0814f993d8 --- /dev/null +++ b/check/instances/gesa2.mps @@ -0,0 +1,5459 @@ +*NAME: gesa2 +*ROWS: 1392 +*COLUMNS: 1224 +*INTEGER: 408 +*NONZERO: 5064 +*BEST SOLN: 25779856.372 +*LP SOLN: 25476489.678 +*SOURCE: Spanish Electricity +* Laurence A. Wolsey (University of Louvain) +* Sebastian Ceria (Columbia University) +*APPLICATION: Optimization of electricity generation +* in the Balearic Islands of Spain +*COMMENTS: Same as gesa2_o, except that surrogate knapsacks +* have been added. +* 240 of the integer variables are binary +* +NAME GESA2 +ROWS + N COST.... + G CD..0101 + G CD..0102 + G CD..0103 + G CD..0104 + G CD..0105 + G CD..0106 + G CD..0107 + G CD..0108 + G CD..0109 + G CD..0110 + G CD..0111 + G CD..0112 + G CD..0113 + G CD..0114 + G CD..0115 + G CD..0116 + G CD..0117 + G CD..0118 + G CD..0119 + G CD..0120 + G CD..0121 + G CD..0122 + G CD..0123 + G CD..0124 + G CD..0201 + G CD..0202 + G CD..0203 + G CD..0204 + G CD..0205 + G CD..0206 + G CD..0207 + G CD..0208 + G CD..0209 + G CD..0210 + G CD..0211 + G CD..0212 + G CD..0213 + G CD..0214 + G CD..0215 + G CD..0216 + G CD..0217 + G CD..0218 + G CD..0219 + G CD..0220 + G CD..0221 + G CD..0222 + G CD..0223 + G CD..0224 + G CD..0301 + G CD..0302 + G CD..0303 + G CD..0304 + G CD..0305 + G CD..0306 + G CD..0307 + G CD..0308 + G CD..0309 + G CD..0310 + G CD..0311 + G CD..0312 + G CD..0313 + G CD..0314 + G CD..0315 + G CD..0316 + G CD..0317 + G CD..0318 + G CD..0319 + G CD..0320 + G CD..0321 + G CD..0322 + G CD..0323 + G CD..0324 + G SURD0101 + G SURD0102 + G SURD0103 + G SURD0104 + G SURD0105 + G SURD0106 + G SURD0107 + G SURD0108 + G SURD0109 + G SURD0110 + G SURD0111 + G SURD0112 + G SURD0113 + G SURD0114 + G SURD0115 + G SURD0116 + G SURD0117 + G SURD0118 + G SURD0119 + G SURD0120 + G SURD0121 + G SURD0122 + G SURD0123 + G SURD0124 + G SURD0201 + G SURD0202 + G SURD0203 + G SURD0204 + G SURD0205 + G SURD0206 + G SURD0207 + G SURD0208 + G SURD0209 + G SURD0210 + G SURD0211 + G SURD0212 + G SURD0213 + G SURD0214 + G SURD0215 + G SURD0216 + G SURD0217 + G SURD0218 + G SURD0219 + G SURD0220 + G SURD0221 + G SURD0222 + G SURD0223 + G SURD0224 + G SURD0301 + G SURD0302 + G SURD0303 + G SURD0304 + G SURD0305 + G SURD0306 + G SURD0307 + G SURD0308 + G SURD0309 + G SURD0310 + G SURD0311 + G SURD0312 + G SURD0313 + G SURD0314 + G SURD0315 + G SURD0316 + G SURD0317 + G SURD0318 + G SURD0319 + G SURD0320 + G SURD0321 + G SURD0322 + G SURD0323 + G SURD0324 + G S12D..01 + G S12D..02 + G S12D..03 + G S12D..04 + G S12D..05 + G S12D..06 + G S12D..07 + G S12D..08 + G S12D..09 + G S12D..10 + G S12D..11 + G S12D..12 + G S12D..13 + G S12D..14 + G S12D..15 + G S12D..16 + G S12D..17 + G S12D..18 + G S12D..19 + G S12D..20 + G S12D..21 + G S12D..22 + G S12D..23 + G S12D..24 + G S13D..01 + G S13D..02 + G S13D..03 + G S13D..04 + G S13D..05 + G S13D..06 + G S13D..07 + G S13D..08 + G S13D..09 + G S13D..10 + G S13D..11 + G S13D..12 + G S13D..13 + G S13D..14 + G S13D..15 + G S13D..16 + G S13D..17 + G S13D..18 + G S13D..19 + G S13D..20 + G S13D..21 + G S13D..22 + G S13D..23 + G S13D..24 + G S123D.01 + G S123D.02 + G S123D.03 + G S123D.04 + G S123D.05 + G S123D.06 + G S123D.07 + G S123D.08 + G S123D.09 + G S123D.10 + G S123D.11 + G S123D.12 + G S123D.13 + G S123D.14 + G S123D.15 + G S123D.16 + G S123D.17 + G S123D.18 + G S123D.19 + G S123D.20 + G S123D.21 + G S123D.22 + G S123D.23 + G S123D.24 + E SU..1301 + E SU..1302 + E SU..1303 + E SU..1304 + E SU..1305 + E SU..1306 + E SU..1307 + E SU..1308 + E SU..1309 + E SU..1310 + E SU..1311 + E SU..1312 + E SU..1313 + E SU..1314 + E SU..1315 + E SU..1316 + E SU..1317 + E SU..1318 + E SU..1319 + E SU..1320 + E SU..1321 + E SU..1322 + E SU..1323 + E SU..1324 + E SU..3101 + E SU..3102 + E SU..3103 + E SU..3104 + E SU..3105 + E SU..3106 + E SU..3107 + E SU..3108 + E SU..3109 + E SU..3110 + E SU..3111 + E SU..3112 + E SU..3113 + E SU..3114 + E SU..3115 + E SU..3116 + E SU..3117 + E SU..3118 + E SU..3119 + E SU..3120 + E SU..3121 + E SU..3122 + E SU..3123 + E SU..3124 + L LC.13101 + L LC.13102 + L LC.13103 + L LC.13104 + L LC.13105 + L LC.13106 + L LC.13107 + L LC.13108 + L LC.13109 + L LC.13110 + L LC.13111 + L LC.13112 + L LC.13113 + L LC.13114 + L LC.13115 + L LC.13116 + L LC.13117 + L LC.13118 + L LC.13119 + L LC.13120 + L LC.13121 + L LC.13122 + L LC.13123 + L LC.13124 + L LC.13201 + L LC.13202 + L LC.13203 + L LC.13204 + L LC.13205 + L LC.13206 + L LC.13207 + L LC.13208 + L LC.13209 + L LC.13210 + L LC.13211 + L LC.13212 + L LC.13213 + L LC.13214 + L LC.13215 + L LC.13216 + L LC.13217 + L LC.13218 + L LC.13219 + L LC.13220 + L LC.13221 + L LC.13222 + L LC.13223 + L LC.13224 + L LC.31101 + L LC.31102 + L LC.31103 + L LC.31104 + L LC.31105 + L LC.31106 + L LC.31107 + L LC.31108 + L LC.31109 + L LC.31110 + L LC.31111 + L LC.31112 + L LC.31113 + L LC.31114 + L LC.31115 + L LC.31116 + L LC.31117 + L LC.31118 + L LC.31119 + L LC.31120 + L LC.31121 + L LC.31122 + L LC.31123 + L LC.31124 + L LC.31201 + L LC.31202 + L LC.31203 + L LC.31204 + L LC.31205 + L LC.31206 + L LC.31207 + L LC.31208 + L LC.31209 + L LC.31210 + L LC.31211 + L LC.31212 + L LC.31213 + L LC.31214 + L LC.31215 + L LC.31216 + L LC.31217 + L LC.31218 + L LC.31219 + L LC.31220 + L LC.31221 + L LC.31222 + L LC.31223 + L LC.31224 + L LCC.1201 + L LCC.1202 + L LCC.1203 + L LCC.1204 + L LCC.1205 + L LCC.1206 + L LCC.1207 + L LCC.1208 + L LCC.1209 + L LCC.1210 + L LCC.1211 + L LCC.1212 + L LCC.1213 + L LCC.1214 + L LCC.1215 + L LCC.1216 + L LCC.1217 + L LCC.1218 + L LCC.1219 + L LCC.1220 + L LCC.1221 + L LCC.1222 + L LCC.1223 + L LCC.1224 + L LCC.2101 + L LCC.2102 + L LCC.2103 + L LCC.2104 + L LCC.2105 + L LCC.2106 + L LCC.2107 + L LCC.2108 + L LCC.2109 + L LCC.2110 + L LCC.2111 + L LCC.2112 + L LCC.2113 + L LCC.2114 + L LCC.2115 + L LCC.2116 + L LCC.2117 + L LCC.2118 + L LCC.2119 + L LCC.2120 + L LCC.2121 + L LCC.2122 + L LCC.2123 + L LCC.2124 + G CFQ.1301 + G CFQ.1302 + G CFQ.1303 + G CFQ.1304 + G CFQ.1305 + G CFQ.1306 + G CFQ.1307 + G CFQ.1308 + G CFQ.1309 + G CFQ.1310 + G CFQ.1311 + G CFQ.1312 + G CFQ.1313 + G CFQ.1314 + G CFQ.1315 + G CFQ.1316 + G CFQ.1317 + G CFQ.1318 + G CFQ.1319 + G CFQ.1320 + G CFQ.1321 + G CFQ.1322 + G CFQ.1323 + G CFQ.1324 + G CFQ.1401 + G CFQ.1402 + G CFQ.1403 + G CFQ.1404 + G CFQ.1405 + G CFQ.1406 + G CFQ.1407 + G CFQ.1408 + G CFQ.1409 + G CFQ.1410 + G CFQ.1411 + G CFQ.1412 + G CFQ.1413 + G CFQ.1414 + G CFQ.1415 + G CFQ.1416 + G CFQ.1417 + G CFQ.1418 + G CFQ.1419 + G CFQ.1420 + G CFQ.1421 + G CFQ.1422 + G CFQ.1423 + G CFQ.1424 + G CFQ.1501 + G CFQ.1502 + G CFQ.1503 + G CFQ.1504 + G CFQ.1505 + G CFQ.1506 + G CFQ.1507 + G CFQ.1508 + G CFQ.1509 + G CFQ.1510 + G CFQ.1511 + G CFQ.1512 + G CFQ.1513 + G CFQ.1514 + G CFQ.1515 + G CFQ.1516 + G CFQ.1517 + G CFQ.1518 + G CFQ.1519 + G CFQ.1520 + G CFQ.1521 + G CFQ.1522 + G CFQ.1523 + G CFQ.1524 + G CFQ.1601 + G CFQ.1602 + G CFQ.1603 + G CFQ.1604 + G CFQ.1605 + G CFQ.1606 + G CFQ.1607 + G CFQ.1608 + G CFQ.1609 + G CFQ.1610 + G CFQ.1611 + G CFQ.1612 + G CFQ.1613 + G CFQ.1614 + G CFQ.1615 + G CFQ.1616 + G CFQ.1617 + G CFQ.1618 + G CFQ.1619 + G CFQ.1620 + G CFQ.1621 + G CFQ.1622 + G CFQ.1623 + G CFQ.1624 + G CFQ.1701 + G CFQ.1702 + G CFQ.1703 + G CFQ.1704 + G CFQ.1705 + G CFQ.1706 + G CFQ.1707 + G CFQ.1708 + G CFQ.1709 + G CFQ.1710 + G CFQ.1711 + G CFQ.1712 + G CFQ.1713 + G CFQ.1714 + G CFQ.1715 + G CFQ.1716 + G CFQ.1717 + G CFQ.1718 + G CFQ.1719 + G CFQ.1720 + G CFQ.1721 + G CFQ.1722 + G CFQ.1723 + G CFQ.1724 + G CFQ.2201 + G CFQ.2202 + G CFQ.2203 + G CFQ.2204 + G CFQ.2205 + G CFQ.2206 + G CFQ.2207 + G CFQ.2208 + G CFQ.2209 + G CFQ.2210 + G CFQ.2211 + G CFQ.2212 + G CFQ.2213 + G CFQ.2214 + G CFQ.2215 + G CFQ.2216 + G CFQ.2217 + G CFQ.2218 + G CFQ.2219 + G CFQ.2220 + G CFQ.2221 + G CFQ.2222 + G CFQ.2223 + G CFQ.2224 + G CFQ.2301 + G CFQ.2302 + G CFQ.2303 + G CFQ.2304 + G CFQ.2305 + G CFQ.2306 + G CFQ.2307 + G CFQ.2308 + G CFQ.2309 + G CFQ.2310 + G CFQ.2311 + G CFQ.2312 + G CFQ.2313 + G CFQ.2314 + G CFQ.2315 + G CFQ.2316 + G CFQ.2317 + G CFQ.2318 + G CFQ.2319 + G CFQ.2320 + G CFQ.2321 + G CFQ.2322 + G CFQ.2323 + G CFQ.2324 + G CFQ.2401 + G CFQ.2402 + G CFQ.2403 + G CFQ.2404 + G CFQ.2405 + G CFQ.2406 + G CFQ.2407 + G CFQ.2408 + G CFQ.2409 + G CFQ.2410 + G CFQ.2411 + G CFQ.2412 + G CFQ.2413 + G CFQ.2414 + G CFQ.2415 + G CFQ.2416 + G CFQ.2417 + G CFQ.2418 + G CFQ.2419 + G CFQ.2420 + G CFQ.2421 + G CFQ.2422 + G CFQ.2423 + G CFQ.2424 + G CFQ.3101 + G CFQ.3102 + G CFQ.3103 + G CFQ.3104 + G CFQ.3105 + G CFQ.3106 + G CFQ.3107 + G CFQ.3108 + G CFQ.3109 + G CFQ.3110 + G CFQ.3111 + G CFQ.3112 + G CFQ.3113 + G CFQ.3114 + G CFQ.3115 + G CFQ.3116 + G CFQ.3117 + G CFQ.3118 + G CFQ.3119 + G CFQ.3120 + G CFQ.3121 + G CFQ.3122 + G CFQ.3123 + G CFQ.3124 + G CFQ.3201 + G CFQ.3202 + G CFQ.3203 + G CFQ.3204 + G CFQ.3205 + G CFQ.3206 + G CFQ.3207 + G CFQ.3208 + G CFQ.3209 + G CFQ.3210 + G CFQ.3211 + G CFQ.3212 + G CFQ.3213 + G CFQ.3214 + G CFQ.3215 + G CFQ.3216 + G CFQ.3217 + G CFQ.3218 + G CFQ.3219 + G CFQ.3220 + G CFQ.3221 + G CFQ.3222 + G CFQ.3223 + G CFQ.3224 + G CFQ.3301 + G CFQ.3302 + G CFQ.3303 + G CFQ.3304 + G CFQ.3305 + G CFQ.3306 + G CFQ.3307 + G CFQ.3308 + G CFQ.3309 + G CFQ.3310 + G CFQ.3311 + G CFQ.3312 + G CFQ.3313 + G CFQ.3314 + G CFQ.3315 + G CFQ.3316 + G CFQ.3317 + G CFQ.3318 + G CFQ.3319 + G CFQ.3320 + G CFQ.3321 + G CFQ.3322 + G CFQ.3323 + G CFQ.3324 + G CFQ.3401 + G CFQ.3402 + G CFQ.3403 + G CFQ.3404 + G CFQ.3405 + G CFQ.3406 + G CFQ.3407 + G CFQ.3408 + G CFQ.3409 + G CFQ.3410 + G CFQ.3411 + G CFQ.3412 + G CFQ.3413 + G CFQ.3414 + G CFQ.3415 + G CFQ.3416 + G CFQ.3417 + G CFQ.3418 + G CFQ.3419 + G CFQ.3420 + G CFQ.3421 + G CFQ.3422 + G CFQ.3423 + G CFQ.3424 + G CFQ.3501 + G CFQ.3502 + G CFQ.3503 + G CFQ.3504 + G CFQ.3505 + G CFQ.3506 + G CFQ.3507 + G CFQ.3508 + G CFQ.3509 + G CFQ.3510 + G CFQ.3511 + G CFQ.3512 + G CFQ.3513 + G CFQ.3514 + G CFQ.3515 + G CFQ.3516 + G CFQ.3517 + G CFQ.3518 + G CFQ.3519 + G CFQ.3520 + G CFQ.3521 + G CFQ.3522 + G CFQ.3523 + G CFQ.3524 + L CFN.1301 + L CFN.1302 + L CFN.1303 + L CFN.1304 + L CFN.1305 + L CFN.1306 + L CFN.1307 + L CFN.1308 + L CFN.1309 + L CFN.1310 + L CFN.1311 + L CFN.1312 + L CFN.1313 + L CFN.1314 + L CFN.1315 + L CFN.1316 + L CFN.1317 + L CFN.1318 + L CFN.1319 + L CFN.1320 + L CFN.1321 + L CFN.1322 + L CFN.1323 + L CFN.1324 + L CFN.1401 + L CFN.1402 + L CFN.1403 + L CFN.1404 + L CFN.1405 + L CFN.1406 + L CFN.1407 + L CFN.1408 + L CFN.1409 + L CFN.1410 + L CFN.1411 + L CFN.1412 + L CFN.1413 + L CFN.1414 + L CFN.1415 + L CFN.1416 + L CFN.1417 + L CFN.1418 + L CFN.1419 + L CFN.1420 + L CFN.1421 + L CFN.1422 + L CFN.1423 + L CFN.1424 + L CFN.1501 + L CFN.1502 + L CFN.1503 + L CFN.1504 + L CFN.1505 + L CFN.1506 + L CFN.1507 + L CFN.1508 + L CFN.1509 + L CFN.1510 + L CFN.1511 + L CFN.1512 + L CFN.1513 + L CFN.1514 + L CFN.1515 + L CFN.1516 + L CFN.1517 + L CFN.1518 + L CFN.1519 + L CFN.1520 + L CFN.1521 + L CFN.1522 + L CFN.1523 + L CFN.1524 + L CFN.1601 + L CFN.1602 + L CFN.1603 + L CFN.1604 + L CFN.1605 + L CFN.1606 + L CFN.1607 + L CFN.1608 + L CFN.1609 + L CFN.1610 + L CFN.1611 + L CFN.1612 + L CFN.1613 + L CFN.1614 + L CFN.1615 + L CFN.1616 + L CFN.1617 + L CFN.1618 + L CFN.1619 + L CFN.1620 + L CFN.1621 + L CFN.1622 + L CFN.1623 + L CFN.1624 + L CFN.1701 + L CFN.1702 + L CFN.1703 + L CFN.1704 + L CFN.1705 + L CFN.1706 + L CFN.1707 + L CFN.1708 + L CFN.1709 + L CFN.1710 + L CFN.1711 + L CFN.1712 + L CFN.1713 + L CFN.1714 + L CFN.1715 + L CFN.1716 + L CFN.1717 + L CFN.1718 + L CFN.1719 + L CFN.1720 + L CFN.1721 + L CFN.1722 + L CFN.1723 + L CFN.1724 + L CFN.2201 + L CFN.2202 + L CFN.2203 + L CFN.2204 + L CFN.2205 + L CFN.2206 + L CFN.2207 + L CFN.2208 + L CFN.2209 + L CFN.2210 + L CFN.2211 + L CFN.2212 + L CFN.2213 + L CFN.2214 + L CFN.2215 + L CFN.2216 + L CFN.2217 + L CFN.2218 + L CFN.2219 + L CFN.2220 + L CFN.2221 + L CFN.2222 + L CFN.2223 + L CFN.2224 + L CFN.2301 + L CFN.2302 + L CFN.2303 + L CFN.2304 + L CFN.2305 + L CFN.2306 + L CFN.2307 + L CFN.2308 + L CFN.2309 + L CFN.2310 + L CFN.2311 + L CFN.2312 + L CFN.2313 + L CFN.2314 + L CFN.2315 + L CFN.2316 + L CFN.2317 + L CFN.2318 + L CFN.2319 + L CFN.2320 + L CFN.2321 + L CFN.2322 + L CFN.2323 + L CFN.2324 + L CFN.2401 + L CFN.2402 + L CFN.2403 + L CFN.2404 + L CFN.2405 + L CFN.2406 + L CFN.2407 + L CFN.2408 + L CFN.2409 + L CFN.2410 + L CFN.2411 + L CFN.2412 + L CFN.2413 + L CFN.2414 + L CFN.2415 + L CFN.2416 + L CFN.2417 + L CFN.2418 + L CFN.2419 + L CFN.2420 + L CFN.2421 + L CFN.2422 + L CFN.2423 + L CFN.2424 + L CFN.3101 + L CFN.3102 + L CFN.3103 + L CFN.3104 + L CFN.3105 + L CFN.3106 + L CFN.3107 + L CFN.3108 + L CFN.3109 + L CFN.3110 + L CFN.3111 + L CFN.3112 + L CFN.3113 + L CFN.3114 + L CFN.3115 + L CFN.3116 + L CFN.3117 + L CFN.3118 + L CFN.3119 + L CFN.3120 + L CFN.3121 + L CFN.3122 + L CFN.3123 + L CFN.3124 + L CFN.3201 + L CFN.3202 + L CFN.3203 + L CFN.3204 + L CFN.3205 + L CFN.3206 + L CFN.3207 + L CFN.3208 + L CFN.3209 + L CFN.3210 + L CFN.3211 + L CFN.3212 + L CFN.3213 + L CFN.3214 + L CFN.3215 + L CFN.3216 + L CFN.3217 + L CFN.3218 + L CFN.3219 + L CFN.3220 + L CFN.3221 + L CFN.3222 + L CFN.3223 + L CFN.3224 + L CFN.3301 + L CFN.3302 + L CFN.3303 + L CFN.3304 + L CFN.3305 + L CFN.3306 + L CFN.3307 + L CFN.3308 + L CFN.3309 + L CFN.3310 + L CFN.3311 + L CFN.3312 + L CFN.3313 + L CFN.3314 + L CFN.3315 + L CFN.3316 + L CFN.3317 + L CFN.3318 + L CFN.3319 + L CFN.3320 + L CFN.3321 + L CFN.3322 + L CFN.3323 + L CFN.3324 + L CFN.3401 + L CFN.3402 + L CFN.3403 + L CFN.3404 + L CFN.3405 + L CFN.3406 + L CFN.3407 + L CFN.3408 + L CFN.3409 + L CFN.3410 + L CFN.3411 + L CFN.3412 + L CFN.3413 + L CFN.3414 + L CFN.3415 + L CFN.3416 + L CFN.3417 + L CFN.3418 + L CFN.3419 + L CFN.3420 + L CFN.3421 + L CFN.3422 + L CFN.3423 + L CFN.3424 + L CFN.3501 + L CFN.3502 + L CFN.3503 + L CFN.3504 + L CFN.3505 + L CFN.3506 + L CFN.3507 + L CFN.3508 + L CFN.3509 + L CFN.3510 + L CFN.3511 + L CFN.3512 + L CFN.3513 + L CFN.3514 + L CFN.3515 + L CFN.3516 + L CFN.3517 + L CFN.3518 + L CFN.3519 + L CFN.3520 + L CFN.3521 + L CFN.3522 + L CFN.3523 + L CFN.3524 + G CO..1302 + G CO..1303 + G CO..1304 + G CO..1305 + G CO..1306 + G CO..1307 + G CO..1308 + G CO..1309 + G CO..1310 + G CO..1311 + G CO..1312 + G CO..1313 + G CO..1314 + G CO..1315 + G CO..1316 + G CO..1317 + G CO..1318 + G CO..1319 + G CO..1320 + G CO..1321 + G CO..1322 + G CO..1323 + G CO..1324 + G CO..1402 + G CO..1403 + G CO..1404 + G CO..1405 + G CO..1406 + G CO..1407 + G CO..1408 + G CO..1409 + G CO..1410 + G CO..1411 + G CO..1412 + G CO..1413 + G CO..1414 + G CO..1415 + G CO..1416 + G CO..1417 + G CO..1418 + G CO..1419 + G CO..1420 + G CO..1421 + G CO..1422 + G CO..1423 + G CO..1424 + G CO..1502 + G CO..1503 + G CO..1504 + G CO..1505 + G CO..1506 + G CO..1507 + G CO..1508 + G CO..1509 + G CO..1510 + G CO..1511 + G CO..1512 + G CO..1513 + G CO..1514 + G CO..1515 + G CO..1516 + G CO..1517 + G CO..1518 + G CO..1519 + G CO..1520 + G CO..1521 + G CO..1522 + G CO..1523 + G CO..1524 + G CO..1602 + G CO..1603 + G CO..1604 + G CO..1605 + G CO..1606 + G CO..1607 + G CO..1608 + G CO..1609 + G CO..1610 + G CO..1611 + G CO..1612 + G CO..1613 + G CO..1614 + G CO..1615 + G CO..1616 + G CO..1617 + G CO..1618 + G CO..1619 + G CO..1620 + G CO..1621 + G CO..1622 + G CO..1623 + G CO..1624 + G CO..1702 + G CO..1703 + G CO..1704 + G CO..1705 + G CO..1706 + G CO..1707 + G CO..1708 + G CO..1709 + G CO..1710 + G CO..1711 + G CO..1712 + G CO..1713 + G CO..1714 + G CO..1715 + G CO..1716 + G CO..1717 + G CO..1718 + G CO..1719 + G CO..1720 + G CO..1721 + G CO..1722 + G CO..1723 + G CO..1724 + G CO..2202 + G CO..2203 + G CO..2204 + G CO..2205 + G CO..2206 + G CO..2207 + G CO..2208 + G CO..2209 + G CO..2210 + G CO..2211 + G CO..2212 + G CO..2213 + G CO..2214 + G CO..2215 + G CO..2216 + G CO..2217 + G CO..2218 + G CO..2219 + G CO..2220 + G CO..2221 + G CO..2222 + G CO..2223 + G CO..2224 + G CO..2302 + G CO..2303 + G CO..2304 + G CO..2305 + G CO..2306 + G CO..2307 + G CO..2308 + G CO..2309 + G CO..2310 + G CO..2311 + G CO..2312 + G CO..2313 + G CO..2314 + G CO..2315 + G CO..2316 + G CO..2317 + G CO..2318 + G CO..2319 + G CO..2320 + G CO..2321 + G CO..2322 + G CO..2323 + G CO..2324 + G CO..2402 + G CO..2403 + G CO..2404 + G CO..2405 + G CO..2406 + G CO..2407 + G CO..2408 + G CO..2409 + G CO..2410 + G CO..2411 + G CO..2412 + G CO..2413 + G CO..2414 + G CO..2415 + G CO..2416 + G CO..2417 + G CO..2418 + G CO..2419 + G CO..2420 + G CO..2421 + G CO..2422 + G CO..2423 + G CO..2424 + G CO..3102 + G CO..3103 + G CO..3104 + G CO..3105 + G CO..3106 + G CO..3107 + G CO..3108 + G CO..3109 + G CO..3110 + G CO..3111 + G CO..3112 + G CO..3113 + G CO..3114 + G CO..3115 + G CO..3116 + G CO..3117 + G CO..3118 + G CO..3119 + G CO..3120 + G CO..3121 + G CO..3122 + G CO..3123 + G CO..3124 + G CO..3202 + G CO..3203 + G CO..3204 + G CO..3205 + G CO..3206 + G CO..3207 + G CO..3208 + G CO..3209 + G CO..3210 + G CO..3211 + G CO..3212 + G CO..3213 + G CO..3214 + G CO..3215 + G CO..3216 + G CO..3217 + G CO..3218 + G CO..3219 + G CO..3220 + G CO..3221 + G CO..3222 + G CO..3223 + G CO..3224 + G CO..3302 + G CO..3303 + G CO..3304 + G CO..3305 + G CO..3306 + G CO..3307 + G CO..3308 + G CO..3309 + G CO..3310 + G CO..3311 + G CO..3312 + G CO..3313 + G CO..3314 + G CO..3315 + G CO..3316 + G CO..3317 + G CO..3318 + G CO..3319 + G CO..3320 + G CO..3321 + G CO..3322 + G CO..3323 + G CO..3324 + G CO..3402 + G CO..3403 + G CO..3404 + G CO..3405 + G CO..3406 + G CO..3407 + G CO..3408 + G CO..3409 + G CO..3410 + G CO..3411 + G CO..3412 + G CO..3413 + G CO..3414 + G CO..3415 + G CO..3416 + G CO..3417 + G CO..3418 + G CO..3419 + G CO..3420 + G CO..3421 + G CO..3422 + G CO..3423 + G CO..3424 + G CO..3502 + G CO..3503 + G CO..3504 + G CO..3505 + G CO..3506 + G CO..3507 + G CO..3508 + G CO..3509 + G CO..3510 + G CO..3511 + G CO..3512 + G CO..3513 + G CO..3514 + G CO..3515 + G CO..3516 + G CO..3517 + G CO..3518 + G CO..3519 + G CO..3520 + G CO..3521 + G CO..3522 + G CO..3523 + G CO..3524 + G CO..1301 + G CO..1401 + G CO..1501 + G CO..1601 + G CO..1701 + G CO..2201 + G CO..2301 + G CO..2401 + G CO..3101 + G CO..3201 + G CO..3301 + G CO..3401 + G CO..3501 + L AD..1201 + L AD..1202 + L AD..1203 + L AD..1204 + L AD..1205 + L AD..1206 + L AD..1207 + L AD..1208 + L AD..1209 + L AD..1210 + L AD..1211 + L AD..1212 + L AD..1213 + L AD..1214 + L AD..1215 + L AD..1216 + L AD..1217 + L AD..1218 + L AD..1219 + L AD..1220 + L AD..1221 + L AD..1222 + L AD..1223 + L AD..1224 + L AD..1301 + L AD..1302 + L AD..1303 + L AD..1304 + L AD..1305 + L AD..1306 + L AD..1307 + L AD..1308 + L AD..1309 + L AD..1310 + L AD..1311 + L AD..1312 + L AD..1313 + L AD..1314 + L AD..1315 + L AD..1316 + L AD..1317 + L AD..1318 + L AD..1319 + L AD..1320 + L AD..1321 + L AD..1322 + L AD..1323 + L AD..1324 +COLUMNS + x...3101 COST.... 7801.660000 CD..0301 1.000000 + x...3101 CFQ.3101 1.000000 CFN.3101 1.000000 + x...2201 COST.... 7723.650000 CD..0201 1.000000 + x...2201 CFQ.2201 1.000000 CFN.2201 1.000000 + x...3201 COST.... 7801.660000 CD..0301 1.000000 + x...3201 CFQ.3201 1.000000 CFN.3201 1.000000 + x...1301 COST.... 7801.660000 CD..0101 1.000000 + x...1301 CFQ.1301 1.000000 CFN.1301 1.000000 + x...2301 COST.... 6553.400000 CD..0201 1.000000 + x...2301 CFQ.2301 1.000000 CFN.2301 1.000000 + x...3301 COST.... 3670.010000 CD..0301 1.000000 + x...3301 CFQ.3301 1.000000 CFN.3301 1.000000 + x...1401 COST.... 7801.660000 CD..0101 1.000000 + x...1401 CFQ.1401 1.000000 CFN.1401 1.000000 + x...2401 COST.... 3369.750000 CD..0201 1.000000 + x...2401 CFQ.2401 1.000000 CFN.2401 1.000000 + x...3401 COST.... 3235.800000 CD..0301 1.000000 + x...3401 CFQ.3401 1.000000 CFN.3401 1.000000 + x...1501 COST.... 6553.400000 CD..0101 1.000000 + x...1501 CFQ.1501 1.000000 CFN.1501 1.000000 + x...3501 COST.... 2831.330000 CD..0301 1.000000 + x...3501 CFQ.3501 1.000000 CFN.3501 1.000000 + x...1601 COST.... 2433.270000 CD..0101 .960000 + x...1601 CFQ.1601 1.000000 CFN.1601 1.000000 + x...1701 COST.... 2341.750000 CD..0101 .955000 + x...1701 CFQ.1701 1.000000 CFN.1701 1.000000 + x...3102 COST.... 7801.660000 CD..0302 1.000000 + x...3102 CFQ.3102 1.000000 CFN.3102 1.000000 + x...2202 COST.... 7723.650000 CD..0202 1.000000 + x...2202 CFQ.2202 1.000000 CFN.2202 1.000000 + x...3202 COST.... 7801.660000 CD..0302 1.000000 + x...3202 CFQ.3202 1.000000 CFN.3202 1.000000 + x...1302 COST.... 7801.660000 CD..0102 1.000000 + x...1302 CFQ.1302 1.000000 CFN.1302 1.000000 + x...2302 COST.... 6553.400000 CD..0202 1.000000 + x...2302 CFQ.2302 1.000000 CFN.2302 1.000000 + x...3302 COST.... 3670.010000 CD..0302 1.000000 + x...3302 CFQ.3302 1.000000 CFN.3302 1.000000 + x...1402 COST.... 7801.660000 CD..0102 1.000000 + x...1402 CFQ.1402 1.000000 CFN.1402 1.000000 + x...2402 COST.... 3369.750000 CD..0202 1.000000 + x...2402 CFQ.2402 1.000000 CFN.2402 1.000000 + x...3402 COST.... 3235.800000 CD..0302 1.000000 + x...3402 CFQ.3402 1.000000 CFN.3402 1.000000 + x...1502 COST.... 6553.400000 CD..0102 1.000000 + x...1502 CFQ.1502 1.000000 CFN.1502 1.000000 + x...3502 COST.... 2831.330000 CD..0302 1.000000 + x...3502 CFQ.3502 1.000000 CFN.3502 1.000000 + x...1602 COST.... 2433.270000 CD..0102 .960000 + x...1602 CFQ.1602 1.000000 CFN.1602 1.000000 + x...1702 COST.... 2341.750000 CD..0102 .955000 + x...1702 CFQ.1702 1.000000 CFN.1702 1.000000 + x...3103 COST.... 7801.660000 CD..0303 1.000000 + x...3103 CFQ.3103 1.000000 CFN.3103 1.000000 + x...2203 COST.... 7723.650000 CD..0203 1.000000 + x...2203 CFQ.2203 1.000000 CFN.2203 1.000000 + x...3203 COST.... 7801.660000 CD..0303 1.000000 + x...3203 CFQ.3203 1.000000 CFN.3203 1.000000 + x...1303 COST.... 7801.660000 CD..0103 1.000000 + x...1303 CFQ.1303 1.000000 CFN.1303 1.000000 + x...2303 COST.... 6553.400000 CD..0203 1.000000 + x...2303 CFQ.2303 1.000000 CFN.2303 1.000000 + x...3303 COST.... 3670.010000 CD..0303 1.000000 + x...3303 CFQ.3303 1.000000 CFN.3303 1.000000 + x...1403 COST.... 7801.660000 CD..0103 1.000000 + x...1403 CFQ.1403 1.000000 CFN.1403 1.000000 + x...2403 COST.... 3369.750000 CD..0203 1.000000 + x...2403 CFQ.2403 1.000000 CFN.2403 1.000000 + x...3403 COST.... 3235.800000 CD..0303 1.000000 + x...3403 CFQ.3403 1.000000 CFN.3403 1.000000 + x...1503 COST.... 6553.400000 CD..0103 1.000000 + x...1503 CFQ.1503 1.000000 CFN.1503 1.000000 + x...3503 COST.... 2831.330000 CD..0303 1.000000 + x...3503 CFQ.3503 1.000000 CFN.3503 1.000000 + x...1603 COST.... 2433.270000 CD..0103 .960000 + x...1603 CFQ.1603 1.000000 CFN.1603 1.000000 + x...1703 COST.... 2341.750000 CD..0103 .955000 + x...1703 CFQ.1703 1.000000 CFN.1703 1.000000 + x...3104 COST.... 7801.660000 CD..0304 1.000000 + x...3104 CFQ.3104 1.000000 CFN.3104 1.000000 + x...2204 COST.... 7723.650000 CD..0204 1.000000 + x...2204 CFQ.2204 1.000000 CFN.2204 1.000000 + x...3204 COST.... 7801.660000 CD..0304 1.000000 + x...3204 CFQ.3204 1.000000 CFN.3204 1.000000 + x...1304 COST.... 7801.660000 CD..0104 1.000000 + x...1304 CFQ.1304 1.000000 CFN.1304 1.000000 + x...2304 COST.... 6553.400000 CD..0204 1.000000 + x...2304 CFQ.2304 1.000000 CFN.2304 1.000000 + x...3304 COST.... 3670.010000 CD..0304 1.000000 + x...3304 CFQ.3304 1.000000 CFN.3304 1.000000 + x...1404 COST.... 7801.660000 CD..0104 1.000000 + x...1404 CFQ.1404 1.000000 CFN.1404 1.000000 + x...2404 COST.... 3369.750000 CD..0204 1.000000 + x...2404 CFQ.2404 1.000000 CFN.2404 1.000000 + x...3404 COST.... 3235.800000 CD..0304 1.000000 + x...3404 CFQ.3404 1.000000 CFN.3404 1.000000 + x...1504 COST.... 6553.400000 CD..0104 1.000000 + x...1504 CFQ.1504 1.000000 CFN.1504 1.000000 + x...3504 COST.... 2831.330000 CD..0304 1.000000 + x...3504 CFQ.3504 1.000000 CFN.3504 1.000000 + x...1604 COST.... 2433.270000 CD..0104 .960000 + x...1604 CFQ.1604 1.000000 CFN.1604 1.000000 + x...1704 COST.... 2341.750000 CD..0104 .955000 + x...1704 CFQ.1704 1.000000 CFN.1704 1.000000 + x...3105 COST.... 7801.660000 CD..0305 1.000000 + x...3105 CFQ.3105 1.000000 CFN.3105 1.000000 + x...2205 COST.... 7723.650000 CD..0205 1.000000 + x...2205 CFQ.2205 1.000000 CFN.2205 1.000000 + x...3205 COST.... 7801.660000 CD..0305 1.000000 + x...3205 CFQ.3205 1.000000 CFN.3205 1.000000 + x...1305 COST.... 7801.660000 CD..0105 1.000000 + x...1305 CFQ.1305 1.000000 CFN.1305 1.000000 + x...2305 COST.... 6553.400000 CD..0205 1.000000 + x...2305 CFQ.2305 1.000000 CFN.2305 1.000000 + x...3305 COST.... 3670.010000 CD..0305 1.000000 + x...3305 CFQ.3305 1.000000 CFN.3305 1.000000 + x...1405 COST.... 7801.660000 CD..0105 1.000000 + x...1405 CFQ.1405 1.000000 CFN.1405 1.000000 + x...2405 COST.... 3369.750000 CD..0205 1.000000 + x...2405 CFQ.2405 1.000000 CFN.2405 1.000000 + x...3405 COST.... 3235.800000 CD..0305 1.000000 + x...3405 CFQ.3405 1.000000 CFN.3405 1.000000 + x...1505 COST.... 6553.400000 CD..0105 1.000000 + x...1505 CFQ.1505 1.000000 CFN.1505 1.000000 + x...3505 COST.... 2831.330000 CD..0305 1.000000 + x...3505 CFQ.3505 1.000000 CFN.3505 1.000000 + x...1605 COST.... 2433.270000 CD..0105 .960000 + x...1605 CFQ.1605 1.000000 CFN.1605 1.000000 + x...1705 COST.... 2341.750000 CD..0105 .955000 + x...1705 CFQ.1705 1.000000 CFN.1705 1.000000 + x...3106 COST.... 7801.660000 CD..0306 1.000000 + x...3106 CFQ.3106 1.000000 CFN.3106 1.000000 + x...2206 COST.... 7723.650000 CD..0206 1.000000 + x...2206 CFQ.2206 1.000000 CFN.2206 1.000000 + x...3206 COST.... 7801.660000 CD..0306 1.000000 + x...3206 CFQ.3206 1.000000 CFN.3206 1.000000 + x...1306 COST.... 7801.660000 CD..0106 1.000000 + x...1306 CFQ.1306 1.000000 CFN.1306 1.000000 + x...2306 COST.... 6553.400000 CD..0206 1.000000 + x...2306 CFQ.2306 1.000000 CFN.2306 1.000000 + x...3306 COST.... 3670.010000 CD..0306 1.000000 + x...3306 CFQ.3306 1.000000 CFN.3306 1.000000 + x...1406 COST.... 7801.660000 CD..0106 1.000000 + x...1406 CFQ.1406 1.000000 CFN.1406 1.000000 + x...2406 COST.... 3369.750000 CD..0206 1.000000 + x...2406 CFQ.2406 1.000000 CFN.2406 1.000000 + x...3406 COST.... 3235.800000 CD..0306 1.000000 + x...3406 CFQ.3406 1.000000 CFN.3406 1.000000 + x...1506 COST.... 6553.400000 CD..0106 1.000000 + x...1506 CFQ.1506 1.000000 CFN.1506 1.000000 + x...3506 COST.... 2831.330000 CD..0306 1.000000 + x...3506 CFQ.3506 1.000000 CFN.3506 1.000000 + x...1606 COST.... 2433.270000 CD..0106 .960000 + x...1606 CFQ.1606 1.000000 CFN.1606 1.000000 + x...1706 COST.... 2341.750000 CD..0106 .955000 + x...1706 CFQ.1706 1.000000 CFN.1706 1.000000 + x...3107 COST.... 7801.660000 CD..0307 1.000000 + x...3107 CFQ.3107 1.000000 CFN.3107 1.000000 + x...2207 COST.... 7723.650000 CD..0207 1.000000 + x...2207 CFQ.2207 1.000000 CFN.2207 1.000000 + x...3207 COST.... 7801.660000 CD..0307 1.000000 + x...3207 CFQ.3207 1.000000 CFN.3207 1.000000 + x...1307 COST.... 7801.660000 CD..0107 1.000000 + x...1307 CFQ.1307 1.000000 CFN.1307 1.000000 + x...2307 COST.... 6553.400000 CD..0207 1.000000 + x...2307 CFQ.2307 1.000000 CFN.2307 1.000000 + x...3307 COST.... 3670.010000 CD..0307 1.000000 + x...3307 CFQ.3307 1.000000 CFN.3307 1.000000 + x...1407 COST.... 7801.660000 CD..0107 1.000000 + x...1407 CFQ.1407 1.000000 CFN.1407 1.000000 + x...2407 COST.... 3369.750000 CD..0207 1.000000 + x...2407 CFQ.2407 1.000000 CFN.2407 1.000000 + x...3407 COST.... 3235.800000 CD..0307 1.000000 + x...3407 CFQ.3407 1.000000 CFN.3407 1.000000 + x...1507 COST.... 6553.400000 CD..0107 1.000000 + x...1507 CFQ.1507 1.000000 CFN.1507 1.000000 + x...3507 COST.... 2831.330000 CD..0307 1.000000 + x...3507 CFQ.3507 1.000000 CFN.3507 1.000000 + x...1607 COST.... 2433.270000 CD..0107 .960000 + x...1607 CFQ.1607 1.000000 CFN.1607 1.000000 + x...1707 COST.... 2341.750000 CD..0107 .955000 + x...1707 CFQ.1707 1.000000 CFN.1707 1.000000 + x...3108 COST.... 7801.660000 CD..0308 1.000000 + x...3108 CFQ.3108 1.000000 CFN.3108 1.000000 + x...2208 COST.... 7723.650000 CD..0208 1.000000 + x...2208 CFQ.2208 1.000000 CFN.2208 1.000000 + x...3208 COST.... 7801.660000 CD..0308 1.000000 + x...3208 CFQ.3208 1.000000 CFN.3208 1.000000 + x...1308 COST.... 7801.660000 CD..0108 1.000000 + x...1308 CFQ.1308 1.000000 CFN.1308 1.000000 + x...2308 COST.... 6553.400000 CD..0208 1.000000 + x...2308 CFQ.2308 1.000000 CFN.2308 1.000000 + x...3308 COST.... 3670.010000 CD..0308 1.000000 + x...3308 CFQ.3308 1.000000 CFN.3308 1.000000 + x...1408 COST.... 7801.660000 CD..0108 1.000000 + x...1408 CFQ.1408 1.000000 CFN.1408 1.000000 + x...2408 COST.... 3369.750000 CD..0208 1.000000 + x...2408 CFQ.2408 1.000000 CFN.2408 1.000000 + x...3408 COST.... 3235.800000 CD..0308 1.000000 + x...3408 CFQ.3408 1.000000 CFN.3408 1.000000 + x...1508 COST.... 6553.400000 CD..0108 1.000000 + x...1508 CFQ.1508 1.000000 CFN.1508 1.000000 + x...3508 COST.... 2831.330000 CD..0308 1.000000 + x...3508 CFQ.3508 1.000000 CFN.3508 1.000000 + x...1608 COST.... 2433.270000 CD..0108 .960000 + x...1608 CFQ.1608 1.000000 CFN.1608 1.000000 + x...1708 COST.... 2341.750000 CD..0108 .955000 + x...1708 CFQ.1708 1.000000 CFN.1708 1.000000 + x...3109 COST.... 7801.660000 CD..0309 1.000000 + x...3109 CFQ.3109 1.000000 CFN.3109 1.000000 + x...2209 COST.... 7723.650000 CD..0209 1.000000 + x...2209 CFQ.2209 1.000000 CFN.2209 1.000000 + x...3209 COST.... 7801.660000 CD..0309 1.000000 + x...3209 CFQ.3209 1.000000 CFN.3209 1.000000 + x...1309 COST.... 7801.660000 CD..0109 1.000000 + x...1309 CFQ.1309 1.000000 CFN.1309 1.000000 + x...2309 COST.... 6553.400000 CD..0209 1.000000 + x...2309 CFQ.2309 1.000000 CFN.2309 1.000000 + x...3309 COST.... 3670.010000 CD..0309 1.000000 + x...3309 CFQ.3309 1.000000 CFN.3309 1.000000 + x...1409 COST.... 7801.660000 CD..0109 1.000000 + x...1409 CFQ.1409 1.000000 CFN.1409 1.000000 + x...2409 COST.... 3369.750000 CD..0209 1.000000 + x...2409 CFQ.2409 1.000000 CFN.2409 1.000000 + x...3409 COST.... 3235.800000 CD..0309 1.000000 + x...3409 CFQ.3409 1.000000 CFN.3409 1.000000 + x...1509 COST.... 6553.400000 CD..0109 1.000000 + x...1509 CFQ.1509 1.000000 CFN.1509 1.000000 + x...3509 COST.... 2831.330000 CD..0309 1.000000 + x...3509 CFQ.3509 1.000000 CFN.3509 1.000000 + x...1609 COST.... 2433.270000 CD..0109 .960000 + x...1609 CFQ.1609 1.000000 CFN.1609 1.000000 + x...1709 COST.... 2341.750000 CD..0109 .955000 + x...1709 CFQ.1709 1.000000 CFN.1709 1.000000 + x...3110 COST.... 7801.660000 CD..0310 1.000000 + x...3110 CFQ.3110 1.000000 CFN.3110 1.000000 + x...2210 COST.... 7723.650000 CD..0210 1.000000 + x...2210 CFQ.2210 1.000000 CFN.2210 1.000000 + x...3210 COST.... 7801.660000 CD..0310 1.000000 + x...3210 CFQ.3210 1.000000 CFN.3210 1.000000 + x...1310 COST.... 7801.660000 CD..0110 1.000000 + x...1310 CFQ.1310 1.000000 CFN.1310 1.000000 + x...2310 COST.... 6553.400000 CD..0210 1.000000 + x...2310 CFQ.2310 1.000000 CFN.2310 1.000000 + x...3310 COST.... 3670.010000 CD..0310 1.000000 + x...3310 CFQ.3310 1.000000 CFN.3310 1.000000 + x...1410 COST.... 7801.660000 CD..0110 1.000000 + x...1410 CFQ.1410 1.000000 CFN.1410 1.000000 + x...2410 COST.... 3369.750000 CD..0210 1.000000 + x...2410 CFQ.2410 1.000000 CFN.2410 1.000000 + x...3410 COST.... 3235.800000 CD..0310 1.000000 + x...3410 CFQ.3410 1.000000 CFN.3410 1.000000 + x...1510 COST.... 6553.400000 CD..0110 1.000000 + x...1510 CFQ.1510 1.000000 CFN.1510 1.000000 + x...3510 COST.... 2831.330000 CD..0310 1.000000 + x...3510 CFQ.3510 1.000000 CFN.3510 1.000000 + x...1610 COST.... 2433.270000 CD..0110 .960000 + x...1610 CFQ.1610 1.000000 CFN.1610 1.000000 + x...1710 COST.... 2341.750000 CD..0110 .955000 + x...1710 CFQ.1710 1.000000 CFN.1710 1.000000 + x...3111 COST.... 7801.660000 CD..0311 1.000000 + x...3111 CFQ.3111 1.000000 CFN.3111 1.000000 + x...2211 COST.... 7723.650000 CD..0211 1.000000 + x...2211 CFQ.2211 1.000000 CFN.2211 1.000000 + x...3211 COST.... 7801.660000 CD..0311 1.000000 + x...3211 CFQ.3211 1.000000 CFN.3211 1.000000 + x...1311 COST.... 7801.660000 CD..0111 1.000000 + x...1311 CFQ.1311 1.000000 CFN.1311 1.000000 + x...2311 COST.... 6553.400000 CD..0211 1.000000 + x...2311 CFQ.2311 1.000000 CFN.2311 1.000000 + x...3311 COST.... 3670.010000 CD..0311 1.000000 + x...3311 CFQ.3311 1.000000 CFN.3311 1.000000 + x...1411 COST.... 7801.660000 CD..0111 1.000000 + x...1411 CFQ.1411 1.000000 CFN.1411 1.000000 + x...2411 COST.... 3369.750000 CD..0211 1.000000 + x...2411 CFQ.2411 1.000000 CFN.2411 1.000000 + x...3411 COST.... 3235.800000 CD..0311 1.000000 + x...3411 CFQ.3411 1.000000 CFN.3411 1.000000 + x...1511 COST.... 6553.400000 CD..0111 1.000000 + x...1511 CFQ.1511 1.000000 CFN.1511 1.000000 + x...3511 COST.... 2831.330000 CD..0311 1.000000 + x...3511 CFQ.3511 1.000000 CFN.3511 1.000000 + x...1611 COST.... 2433.270000 CD..0111 .960000 + x...1611 CFQ.1611 1.000000 CFN.1611 1.000000 + x...1711 COST.... 2341.750000 CD..0111 .955000 + x...1711 CFQ.1711 1.000000 CFN.1711 1.000000 + x...3112 COST.... 7801.660000 CD..0312 1.000000 + x...3112 CFQ.3112 1.000000 CFN.3112 1.000000 + x...2212 COST.... 7723.650000 CD..0212 1.000000 + x...2212 CFQ.2212 1.000000 CFN.2212 1.000000 + x...3212 COST.... 7801.660000 CD..0312 1.000000 + x...3212 CFQ.3212 1.000000 CFN.3212 1.000000 + x...1312 COST.... 7801.660000 CD..0112 1.000000 + x...1312 CFQ.1312 1.000000 CFN.1312 1.000000 + x...2312 COST.... 6553.400000 CD..0212 1.000000 + x...2312 CFQ.2312 1.000000 CFN.2312 1.000000 + x...3312 COST.... 3670.010000 CD..0312 1.000000 + x...3312 CFQ.3312 1.000000 CFN.3312 1.000000 + x...1412 COST.... 7801.660000 CD..0112 1.000000 + x...1412 CFQ.1412 1.000000 CFN.1412 1.000000 + x...2412 COST.... 3369.750000 CD..0212 1.000000 + x...2412 CFQ.2412 1.000000 CFN.2412 1.000000 + x...3412 COST.... 3235.800000 CD..0312 1.000000 + x...3412 CFQ.3412 1.000000 CFN.3412 1.000000 + x...1512 COST.... 6553.400000 CD..0112 1.000000 + x...1512 CFQ.1512 1.000000 CFN.1512 1.000000 + x...3512 COST.... 2831.330000 CD..0312 1.000000 + x...3512 CFQ.3512 1.000000 CFN.3512 1.000000 + x...1612 COST.... 2433.270000 CD..0112 .960000 + x...1612 CFQ.1612 1.000000 CFN.1612 1.000000 + x...1712 COST.... 2341.750000 CD..0112 .955000 + x...1712 CFQ.1712 1.000000 CFN.1712 1.000000 + x...3113 COST.... 7801.660000 CD..0313 1.000000 + x...3113 CFQ.3113 1.000000 CFN.3113 1.000000 + x...2213 COST.... 7723.650000 CD..0213 1.000000 + x...2213 CFQ.2213 1.000000 CFN.2213 1.000000 + x...3213 COST.... 7801.660000 CD..0313 1.000000 + x...3213 CFQ.3213 1.000000 CFN.3213 1.000000 + x...1313 COST.... 7801.660000 CD..0113 1.000000 + x...1313 CFQ.1313 1.000000 CFN.1313 1.000000 + x...2313 COST.... 6553.400000 CD..0213 1.000000 + x...2313 CFQ.2313 1.000000 CFN.2313 1.000000 + x...3313 COST.... 3670.010000 CD..0313 1.000000 + x...3313 CFQ.3313 1.000000 CFN.3313 1.000000 + x...1413 COST.... 7801.660000 CD..0113 1.000000 + x...1413 CFQ.1413 1.000000 CFN.1413 1.000000 + x...2413 COST.... 3369.750000 CD..0213 1.000000 + x...2413 CFQ.2413 1.000000 CFN.2413 1.000000 + x...3413 COST.... 3235.800000 CD..0313 1.000000 + x...3413 CFQ.3413 1.000000 CFN.3413 1.000000 + x...1513 COST.... 6553.400000 CD..0113 1.000000 + x...1513 CFQ.1513 1.000000 CFN.1513 1.000000 + x...3513 COST.... 2831.330000 CD..0313 1.000000 + x...3513 CFQ.3513 1.000000 CFN.3513 1.000000 + x...1613 COST.... 2433.270000 CD..0113 .960000 + x...1613 CFQ.1613 1.000000 CFN.1613 1.000000 + x...1713 COST.... 2341.750000 CD..0113 .955000 + x...1713 CFQ.1713 1.000000 CFN.1713 1.000000 + x...3114 COST.... 7801.660000 CD..0314 1.000000 + x...3114 CFQ.3114 1.000000 CFN.3114 1.000000 + x...2214 COST.... 7723.650000 CD..0214 1.000000 + x...2214 CFQ.2214 1.000000 CFN.2214 1.000000 + x...3214 COST.... 7801.660000 CD..0314 1.000000 + x...3214 CFQ.3214 1.000000 CFN.3214 1.000000 + x...1314 COST.... 7801.660000 CD..0114 1.000000 + x...1314 CFQ.1314 1.000000 CFN.1314 1.000000 + x...2314 COST.... 6553.400000 CD..0214 1.000000 + x...2314 CFQ.2314 1.000000 CFN.2314 1.000000 + x...3314 COST.... 3670.010000 CD..0314 1.000000 + x...3314 CFQ.3314 1.000000 CFN.3314 1.000000 + x...1414 COST.... 7801.660000 CD..0114 1.000000 + x...1414 CFQ.1414 1.000000 CFN.1414 1.000000 + x...2414 COST.... 3369.750000 CD..0214 1.000000 + x...2414 CFQ.2414 1.000000 CFN.2414 1.000000 + x...3414 COST.... 3235.800000 CD..0314 1.000000 + x...3414 CFQ.3414 1.000000 CFN.3414 1.000000 + x...1514 COST.... 6553.400000 CD..0114 1.000000 + x...1514 CFQ.1514 1.000000 CFN.1514 1.000000 + x...3514 COST.... 2831.330000 CD..0314 1.000000 + x...3514 CFQ.3514 1.000000 CFN.3514 1.000000 + x...1614 COST.... 2433.270000 CD..0114 .960000 + x...1614 CFQ.1614 1.000000 CFN.1614 1.000000 + x...1714 COST.... 2341.750000 CD..0114 .955000 + x...1714 CFQ.1714 1.000000 CFN.1714 1.000000 + x...3115 COST.... 7801.660000 CD..0315 1.000000 + x...3115 CFQ.3115 1.000000 CFN.3115 1.000000 + x...2215 COST.... 7723.650000 CD..0215 1.000000 + x...2215 CFQ.2215 1.000000 CFN.2215 1.000000 + x...3215 COST.... 7801.660000 CD..0315 1.000000 + x...3215 CFQ.3215 1.000000 CFN.3215 1.000000 + x...1315 COST.... 7801.660000 CD..0115 1.000000 + x...1315 CFQ.1315 1.000000 CFN.1315 1.000000 + x...2315 COST.... 6553.400000 CD..0215 1.000000 + x...2315 CFQ.2315 1.000000 CFN.2315 1.000000 + x...3315 COST.... 3670.010000 CD..0315 1.000000 + x...3315 CFQ.3315 1.000000 CFN.3315 1.000000 + x...1415 COST.... 7801.660000 CD..0115 1.000000 + x...1415 CFQ.1415 1.000000 CFN.1415 1.000000 + x...2415 COST.... 3369.750000 CD..0215 1.000000 + x...2415 CFQ.2415 1.000000 CFN.2415 1.000000 + x...3415 COST.... 3235.800000 CD..0315 1.000000 + x...3415 CFQ.3415 1.000000 CFN.3415 1.000000 + x...1515 COST.... 6553.400000 CD..0115 1.000000 + x...1515 CFQ.1515 1.000000 CFN.1515 1.000000 + x...3515 COST.... 2831.330000 CD..0315 1.000000 + x...3515 CFQ.3515 1.000000 CFN.3515 1.000000 + x...1615 COST.... 2433.270000 CD..0115 .960000 + x...1615 CFQ.1615 1.000000 CFN.1615 1.000000 + x...1715 COST.... 2341.750000 CD..0115 .955000 + x...1715 CFQ.1715 1.000000 CFN.1715 1.000000 + x...3116 COST.... 7801.660000 CD..0316 1.000000 + x...3116 CFQ.3116 1.000000 CFN.3116 1.000000 + x...2216 COST.... 7723.650000 CD..0216 1.000000 + x...2216 CFQ.2216 1.000000 CFN.2216 1.000000 + x...3216 COST.... 7801.660000 CD..0316 1.000000 + x...3216 CFQ.3216 1.000000 CFN.3216 1.000000 + x...1316 COST.... 7801.660000 CD..0116 1.000000 + x...1316 CFQ.1316 1.000000 CFN.1316 1.000000 + x...2316 COST.... 6553.400000 CD..0216 1.000000 + x...2316 CFQ.2316 1.000000 CFN.2316 1.000000 + x...3316 COST.... 3670.010000 CD..0316 1.000000 + x...3316 CFQ.3316 1.000000 CFN.3316 1.000000 + x...1416 COST.... 7801.660000 CD..0116 1.000000 + x...1416 CFQ.1416 1.000000 CFN.1416 1.000000 + x...2416 COST.... 3369.750000 CD..0216 1.000000 + x...2416 CFQ.2416 1.000000 CFN.2416 1.000000 + x...3416 COST.... 3235.800000 CD..0316 1.000000 + x...3416 CFQ.3416 1.000000 CFN.3416 1.000000 + x...1516 COST.... 6553.400000 CD..0116 1.000000 + x...1516 CFQ.1516 1.000000 CFN.1516 1.000000 + x...3516 COST.... 2831.330000 CD..0316 1.000000 + x...3516 CFQ.3516 1.000000 CFN.3516 1.000000 + x...1616 COST.... 2433.270000 CD..0116 .960000 + x...1616 CFQ.1616 1.000000 CFN.1616 1.000000 + x...1716 COST.... 2341.750000 CD..0116 .955000 + x...1716 CFQ.1716 1.000000 CFN.1716 1.000000 + x...3117 COST.... 7801.660000 CD..0317 1.000000 + x...3117 CFQ.3117 1.000000 CFN.3117 1.000000 + x...2217 COST.... 7723.650000 CD..0217 1.000000 + x...2217 CFQ.2217 1.000000 CFN.2217 1.000000 + x...3217 COST.... 7801.660000 CD..0317 1.000000 + x...3217 CFQ.3217 1.000000 CFN.3217 1.000000 + x...1317 COST.... 7801.660000 CD..0117 1.000000 + x...1317 CFQ.1317 1.000000 CFN.1317 1.000000 + x...2317 COST.... 6553.400000 CD..0217 1.000000 + x...2317 CFQ.2317 1.000000 CFN.2317 1.000000 + x...3317 COST.... 3670.010000 CD..0317 1.000000 + x...3317 CFQ.3317 1.000000 CFN.3317 1.000000 + x...1417 COST.... 7801.660000 CD..0117 1.000000 + x...1417 CFQ.1417 1.000000 CFN.1417 1.000000 + x...2417 COST.... 3369.750000 CD..0217 1.000000 + x...2417 CFQ.2417 1.000000 CFN.2417 1.000000 + x...3417 COST.... 3235.800000 CD..0317 1.000000 + x...3417 CFQ.3417 1.000000 CFN.3417 1.000000 + x...1517 COST.... 6553.400000 CD..0117 1.000000 + x...1517 CFQ.1517 1.000000 CFN.1517 1.000000 + x...3517 COST.... 2831.330000 CD..0317 1.000000 + x...3517 CFQ.3517 1.000000 CFN.3517 1.000000 + x...1617 COST.... 2433.270000 CD..0117 .960000 + x...1617 CFQ.1617 1.000000 CFN.1617 1.000000 + x...1717 COST.... 2341.750000 CD..0117 .955000 + x...1717 CFQ.1717 1.000000 CFN.1717 1.000000 + x...3118 COST.... 7801.660000 CD..0318 1.000000 + x...3118 CFQ.3118 1.000000 CFN.3118 1.000000 + x...2218 COST.... 7723.650000 CD..0218 1.000000 + x...2218 CFQ.2218 1.000000 CFN.2218 1.000000 + x...3218 COST.... 7801.660000 CD..0318 1.000000 + x...3218 CFQ.3218 1.000000 CFN.3218 1.000000 + x...1318 COST.... 7801.660000 CD..0118 1.000000 + x...1318 CFQ.1318 1.000000 CFN.1318 1.000000 + x...2318 COST.... 6553.400000 CD..0218 1.000000 + x...2318 CFQ.2318 1.000000 CFN.2318 1.000000 + x...3318 COST.... 3670.010000 CD..0318 1.000000 + x...3318 CFQ.3318 1.000000 CFN.3318 1.000000 + x...1418 COST.... 7801.660000 CD..0118 1.000000 + x...1418 CFQ.1418 1.000000 CFN.1418 1.000000 + x...2418 COST.... 3369.750000 CD..0218 1.000000 + x...2418 CFQ.2418 1.000000 CFN.2418 1.000000 + x...3418 COST.... 3235.800000 CD..0318 1.000000 + x...3418 CFQ.3418 1.000000 CFN.3418 1.000000 + x...1518 COST.... 6553.400000 CD..0118 1.000000 + x...1518 CFQ.1518 1.000000 CFN.1518 1.000000 + x...3518 COST.... 2831.330000 CD..0318 1.000000 + x...3518 CFQ.3518 1.000000 CFN.3518 1.000000 + x...1618 COST.... 2433.270000 CD..0118 .960000 + x...1618 CFQ.1618 1.000000 CFN.1618 1.000000 + x...1718 COST.... 2341.750000 CD..0118 .955000 + x...1718 CFQ.1718 1.000000 CFN.1718 1.000000 + x...3119 COST.... 7801.660000 CD..0319 1.000000 + x...3119 CFQ.3119 1.000000 CFN.3119 1.000000 + x...2219 COST.... 7723.650000 CD..0219 1.000000 + x...2219 CFQ.2219 1.000000 CFN.2219 1.000000 + x...3219 COST.... 7801.660000 CD..0319 1.000000 + x...3219 CFQ.3219 1.000000 CFN.3219 1.000000 + x...1319 COST.... 7801.660000 CD..0119 1.000000 + x...1319 CFQ.1319 1.000000 CFN.1319 1.000000 + x...2319 COST.... 6553.400000 CD..0219 1.000000 + x...2319 CFQ.2319 1.000000 CFN.2319 1.000000 + x...3319 COST.... 3670.010000 CD..0319 1.000000 + x...3319 CFQ.3319 1.000000 CFN.3319 1.000000 + x...1419 COST.... 7801.660000 CD..0119 1.000000 + x...1419 CFQ.1419 1.000000 CFN.1419 1.000000 + x...2419 COST.... 3369.750000 CD..0219 1.000000 + x...2419 CFQ.2419 1.000000 CFN.2419 1.000000 + x...3419 COST.... 3235.800000 CD..0319 1.000000 + x...3419 CFQ.3419 1.000000 CFN.3419 1.000000 + x...1519 COST.... 6553.400000 CD..0119 1.000000 + x...1519 CFQ.1519 1.000000 CFN.1519 1.000000 + x...3519 COST.... 2831.330000 CD..0319 1.000000 + x...3519 CFQ.3519 1.000000 CFN.3519 1.000000 + x...1619 COST.... 2433.270000 CD..0119 .960000 + x...1619 CFQ.1619 1.000000 CFN.1619 1.000000 + x...1719 COST.... 2341.750000 CD..0119 .955000 + x...1719 CFQ.1719 1.000000 CFN.1719 1.000000 + x...3120 COST.... 7801.660000 CD..0320 1.000000 + x...3120 CFQ.3120 1.000000 CFN.3120 1.000000 + x...2220 COST.... 7723.650000 CD..0220 1.000000 + x...2220 CFQ.2220 1.000000 CFN.2220 1.000000 + x...3220 COST.... 7801.660000 CD..0320 1.000000 + x...3220 CFQ.3220 1.000000 CFN.3220 1.000000 + x...1320 COST.... 7801.660000 CD..0120 1.000000 + x...1320 CFQ.1320 1.000000 CFN.1320 1.000000 + x...2320 COST.... 6553.400000 CD..0220 1.000000 + x...2320 CFQ.2320 1.000000 CFN.2320 1.000000 + x...3320 COST.... 3670.010000 CD..0320 1.000000 + x...3320 CFQ.3320 1.000000 CFN.3320 1.000000 + x...1420 COST.... 7801.660000 CD..0120 1.000000 + x...1420 CFQ.1420 1.000000 CFN.1420 1.000000 + x...2420 COST.... 3369.750000 CD..0220 1.000000 + x...2420 CFQ.2420 1.000000 CFN.2420 1.000000 + x...3420 COST.... 3235.800000 CD..0320 1.000000 + x...3420 CFQ.3420 1.000000 CFN.3420 1.000000 + x...1520 COST.... 6553.400000 CD..0120 1.000000 + x...1520 CFQ.1520 1.000000 CFN.1520 1.000000 + x...3520 COST.... 2831.330000 CD..0320 1.000000 + x...3520 CFQ.3520 1.000000 CFN.3520 1.000000 + x...1620 COST.... 2433.270000 CD..0120 .960000 + x...1620 CFQ.1620 1.000000 CFN.1620 1.000000 + x...1720 COST.... 2341.750000 CD..0120 .955000 + x...1720 CFQ.1720 1.000000 CFN.1720 1.000000 + x...3121 COST.... 7801.660000 CD..0321 1.000000 + x...3121 CFQ.3121 1.000000 CFN.3121 1.000000 + x...2221 COST.... 7723.650000 CD..0221 1.000000 + x...2221 CFQ.2221 1.000000 CFN.2221 1.000000 + x...3221 COST.... 7801.660000 CD..0321 1.000000 + x...3221 CFQ.3221 1.000000 CFN.3221 1.000000 + x...1321 COST.... 7801.660000 CD..0121 1.000000 + x...1321 CFQ.1321 1.000000 CFN.1321 1.000000 + x...2321 COST.... 6553.400000 CD..0221 1.000000 + x...2321 CFQ.2321 1.000000 CFN.2321 1.000000 + x...3321 COST.... 3670.010000 CD..0321 1.000000 + x...3321 CFQ.3321 1.000000 CFN.3321 1.000000 + x...1421 COST.... 7801.660000 CD..0121 1.000000 + x...1421 CFQ.1421 1.000000 CFN.1421 1.000000 + x...2421 COST.... 3369.750000 CD..0221 1.000000 + x...2421 CFQ.2421 1.000000 CFN.2421 1.000000 + x...3421 COST.... 3235.800000 CD..0321 1.000000 + x...3421 CFQ.3421 1.000000 CFN.3421 1.000000 + x...1521 COST.... 6553.400000 CD..0121 1.000000 + x...1521 CFQ.1521 1.000000 CFN.1521 1.000000 + x...3521 COST.... 2831.330000 CD..0321 1.000000 + x...3521 CFQ.3521 1.000000 CFN.3521 1.000000 + x...1621 COST.... 2433.270000 CD..0121 .960000 + x...1621 CFQ.1621 1.000000 CFN.1621 1.000000 + x...1721 COST.... 2341.750000 CD..0121 .955000 + x...1721 CFQ.1721 1.000000 CFN.1721 1.000000 + x...3122 COST.... 7801.660000 CD..0322 1.000000 + x...3122 CFQ.3122 1.000000 CFN.3122 1.000000 + x...2222 COST.... 7723.650000 CD..0222 1.000000 + x...2222 CFQ.2222 1.000000 CFN.2222 1.000000 + x...3222 COST.... 7801.660000 CD..0322 1.000000 + x...3222 CFQ.3222 1.000000 CFN.3222 1.000000 + x...1322 COST.... 7801.660000 CD..0122 1.000000 + x...1322 CFQ.1322 1.000000 CFN.1322 1.000000 + x...2322 COST.... 6553.400000 CD..0222 1.000000 + x...2322 CFQ.2322 1.000000 CFN.2322 1.000000 + x...3322 COST.... 3670.010000 CD..0322 1.000000 + x...3322 CFQ.3322 1.000000 CFN.3322 1.000000 + x...1422 COST.... 7801.660000 CD..0122 1.000000 + x...1422 CFQ.1422 1.000000 CFN.1422 1.000000 + x...2422 COST.... 3369.750000 CD..0222 1.000000 + x...2422 CFQ.2422 1.000000 CFN.2422 1.000000 + x...3422 COST.... 3235.800000 CD..0322 1.000000 + x...3422 CFQ.3422 1.000000 CFN.3422 1.000000 + x...1522 COST.... 6553.400000 CD..0122 1.000000 + x...1522 CFQ.1522 1.000000 CFN.1522 1.000000 + x...3522 COST.... 2831.330000 CD..0322 1.000000 + x...3522 CFQ.3522 1.000000 CFN.3522 1.000000 + x...1622 COST.... 2433.270000 CD..0122 .960000 + x...1622 CFQ.1622 1.000000 CFN.1622 1.000000 + x...1722 COST.... 2341.750000 CD..0122 .955000 + x...1722 CFQ.1722 1.000000 CFN.1722 1.000000 + x...3123 COST.... 7801.660000 CD..0323 1.000000 + x...3123 CFQ.3123 1.000000 CFN.3123 1.000000 + x...2223 COST.... 7723.650000 CD..0223 1.000000 + x...2223 CFQ.2223 1.000000 CFN.2223 1.000000 + x...3223 COST.... 7801.660000 CD..0323 1.000000 + x...3223 CFQ.3223 1.000000 CFN.3223 1.000000 + x...1323 COST.... 7801.660000 CD..0123 1.000000 + x...1323 CFQ.1323 1.000000 CFN.1323 1.000000 + x...2323 COST.... 6553.400000 CD..0223 1.000000 + x...2323 CFQ.2323 1.000000 CFN.2323 1.000000 + x...3323 COST.... 3670.010000 CD..0323 1.000000 + x...3323 CFQ.3323 1.000000 CFN.3323 1.000000 + x...1423 COST.... 7801.660000 CD..0123 1.000000 + x...1423 CFQ.1423 1.000000 CFN.1423 1.000000 + x...2423 COST.... 3369.750000 CD..0223 1.000000 + x...2423 CFQ.2423 1.000000 CFN.2423 1.000000 + x...3423 COST.... 3235.800000 CD..0323 1.000000 + x...3423 CFQ.3423 1.000000 CFN.3423 1.000000 + x...1523 COST.... 6553.400000 CD..0123 1.000000 + x...1523 CFQ.1523 1.000000 CFN.1523 1.000000 + x...3523 COST.... 2831.330000 CD..0323 1.000000 + x...3523 CFQ.3523 1.000000 CFN.3523 1.000000 + x...1623 COST.... 2433.270000 CD..0123 .960000 + x...1623 CFQ.1623 1.000000 CFN.1623 1.000000 + x...1723 COST.... 2341.750000 CD..0123 .955000 + x...1723 CFQ.1723 1.000000 CFN.1723 1.000000 + x...3124 COST.... 7801.660000 CD..0324 1.000000 + x...3124 CFQ.3124 1.000000 CFN.3124 1.000000 + x...2224 COST.... 7723.650000 CD..0224 1.000000 + x...2224 CFQ.2224 1.000000 CFN.2224 1.000000 + x...3224 COST.... 7801.660000 CD..0324 1.000000 + x...3224 CFQ.3224 1.000000 CFN.3224 1.000000 + x...1324 COST.... 7801.660000 CD..0124 1.000000 + x...1324 CFQ.1324 1.000000 CFN.1324 1.000000 + x...2324 COST.... 6553.400000 CD..0224 1.000000 + x...2324 CFQ.2324 1.000000 CFN.2324 1.000000 + x...3324 COST.... 3670.010000 CD..0324 1.000000 + x...3324 CFQ.3324 1.000000 CFN.3324 1.000000 + x...1424 COST.... 7801.660000 CD..0124 1.000000 + x...1424 CFQ.1424 1.000000 CFN.1424 1.000000 + x...2424 COST.... 3369.750000 CD..0224 1.000000 + x...2424 CFQ.2424 1.000000 CFN.2424 1.000000 + x...3424 COST.... 3235.800000 CD..0324 1.000000 + x...3424 CFQ.3424 1.000000 CFN.3424 1.000000 + x...1524 COST.... 6553.400000 CD..0124 1.000000 + x...1524 CFQ.1524 1.000000 CFN.1524 1.000000 + x...3524 COST.... 2831.330000 CD..0324 1.000000 + x...3524 CFQ.3524 1.000000 CFN.3524 1.000000 + x...1624 COST.... 2433.270000 CD..0124 .960000 + x...1624 CFQ.1624 1.000000 CFN.1624 1.000000 + x...1724 COST.... 2341.750000 CD..0124 .955000 + x...1724 CFQ.1724 1.000000 CFN.1724 1.000000 + y...3101 COST.... 59292.65000 CD..0301 -.130000 + y...3101 SURD0301 10.650000 S13D..01 10.650000 + y...3101 S123D.01 10.650000 CFQ.3101 -1.960000 + y...3101 CFN.3101 -10.780000 CO..3102 1.000000 + y...3101 CO..3101 -1.000000 + y...2201 COST.... 59292.65000 CD..0201 -.130000 + y...2201 SURD0201 10.650000 S12D..01 10.650000 + y...2201 S123D.01 10.650000 CFQ.2201 -1.960000 + y...2201 CFN.2201 -10.780000 CO..2202 1.000000 + y...2201 CO..2201 -1.000000 + y...3201 COST.... 68654.65000 CD..0301 -.220000 + y...3201 SURD0301 22.320000 S13D..01 22.320000 + y...3201 S123D.01 22.320000 CFQ.3201 -2.940000 + y...3201 CFN.3201 -22.540000 CO..3202 1.000000 + y...3201 CO..3201 -1.000000 + y...1301 COST.... 59292.65000 CD..0101 -.130000 + y...1301 SURD0101 10.650000 S12D..01 10.650000 + y...1301 S13D..01 10.650000 S123D.01 10.650000 + y...1301 CFQ.1301 -1.960000 CFN.1301 -10.780000 + y...1301 CO..1302 1.000000 CO..1301 -1.000000 + y...2301 COST.... 81137.31000 CD..0201 -.260000 + y...2301 SURD0201 34.040000 S12D..01 34.040000 + y...2301 S123D.01 34.040000 CFQ.2301 -4.900000 + y...2301 CFN.2301 -34.300000 CO..2302 1.000000 + y...2301 CO..2301 -1.000000 + y...3301 COST.... 1974.890000 CD..0301 -.150000 + y...3301 SURD0301 6.975000 S13D..01 6.975000 + y...3301 S123D.01 6.975000 CFQ.3301 -3.800000 + y...3301 CFN.3301 -7.125000 CO..3302 1.000000 + y...3301 CO..3301 -1.000000 + y...1401 COST.... 68654.65000 CD..0101 -.220000 + y...1401 SURD0101 22.320000 S12D..01 22.320000 + y...1401 S13D..01 22.320000 S123D.01 22.320000 + y...1401 CFQ.1401 -2.940000 CFN.1401 -22.540000 + y...1401 CO..1402 1.000000 CO..1401 -1.000000 + y...2401 COST.... 3888.170000 CD..0201 -.350000 + y...2401 SURD0201 12.670000 S12D..01 12.670000 + y...2401 S123D.01 12.670000 CFQ.2401 -7.440000 + y...2401 CFN.2401 -13.020000 CO..2402 1.000000 + y...2401 CO..2401 -1.000000 + y...3401 COST.... 3397.590000 CD..0301 -.350000 + y...3401 SURD0301 12.670000 S13D..01 12.670000 + y...3401 S123D.01 12.670000 CFQ.3401 -7.440000 + y...3401 CFN.3401 -13.020000 CO..3402 1.000000 + y...3401 CO..3401 -1.000000 + y...1501 COST.... 81137.31000 CD..0101 -.260000 + y...1501 SURD0101 34.040000 S12D..01 34.040000 + y...1501 S13D..01 34.040000 S123D.01 34.040000 + y...1501 CFQ.1501 -4.900000 CFN.1501 -34.300000 + y...1501 CO..1502 1.000000 CO..1501 -1.000000 + y...3501 COST.... 3397.590000 CD..0301 -.350000 + y...3501 SURD0301 13.600000 S13D..01 13.600000 + y...3501 S123D.01 13.600000 CFQ.3501 -7.440000 + y...3501 CFN.3501 -13.950000 CO..3502 1.000000 + y...3501 CO..3501 -1.000000 + y...1601 COST.... 20026.02000 CD..0101 -4.000000 + y...1601 SURD0101 111.200000 S12D..01 111.200000 + y...1601 S13D..01 111.200000 S123D.01 111.200000 + y...1601 CFQ.1601 -62.400000 CFN.1601 -120.000000 + y...1601 CO..1602 1.000000 CO..1601 -1.000000 + y...1701 COST.... 20026.02000 CD..0101 -4.500000 + y...1701 SURD0101 114.684000 S12D..01 114.684000 + y...1701 S13D..01 114.684000 S123D.01 114.684000 + y...1701 CFQ.1701 -48.000000 CFN.1701 -124.800000 + y...1701 CO..1702 1.000000 CO..1701 -1.000000 + y...3102 COST.... 59292.65000 CD..0302 -.130000 + y...3102 SURD0302 10.650000 S13D..02 10.650000 + y...3102 S123D.02 10.650000 CFQ.3102 -1.960000 + y...3102 CFN.3102 -10.780000 CO..3102 -1.000000 + y...3102 CO..3103 1.000000 + y...2202 COST.... 59292.65000 CD..0202 -.130000 + y...2202 SURD0202 10.650000 S12D..02 10.650000 + y...2202 S123D.02 10.650000 CFQ.2202 -1.960000 + y...2202 CFN.2202 -10.780000 CO..2202 -1.000000 + y...2202 CO..2203 1.000000 + y...3202 COST.... 68654.65000 CD..0302 -.220000 + y...3202 SURD0302 22.320000 S13D..02 22.320000 + y...3202 S123D.02 22.320000 CFQ.3202 -2.940000 + y...3202 CFN.3202 -22.540000 CO..3202 -1.000000 + y...3202 CO..3203 1.000000 + y...1302 COST.... 59292.65000 CD..0102 -.130000 + y...1302 SURD0102 10.650000 S12D..02 10.650000 + y...1302 S13D..02 10.650000 S123D.02 10.650000 + y...1302 CFQ.1302 -1.960000 CFN.1302 -10.780000 + y...1302 CO..1302 -1.000000 CO..1303 1.000000 + y...2302 COST.... 81137.31000 CD..0202 -.260000 + y...2302 SURD0202 34.040000 S12D..02 34.040000 + y...2302 S123D.02 34.040000 CFQ.2302 -4.900000 + y...2302 CFN.2302 -34.300000 CO..2302 -1.000000 + y...2302 CO..2303 1.000000 + y...3302 COST.... 1974.890000 CD..0302 -.150000 + y...3302 SURD0302 6.975000 S13D..02 6.975000 + y...3302 S123D.02 6.975000 CFQ.3302 -3.800000 + y...3302 CFN.3302 -7.125000 CO..3302 -1.000000 + y...3302 CO..3303 1.000000 + y...1402 COST.... 68654.65000 CD..0102 -.220000 + y...1402 SURD0102 22.320000 S12D..02 22.320000 + y...1402 S13D..02 22.320000 S123D.02 22.320000 + y...1402 CFQ.1402 -2.940000 CFN.1402 -22.540000 + y...1402 CO..1402 -1.000000 CO..1403 1.000000 + y...2402 COST.... 3888.170000 CD..0202 -.350000 + y...2402 SURD0202 12.670000 S12D..02 12.670000 + y...2402 S123D.02 12.670000 CFQ.2402 -7.440000 + y...2402 CFN.2402 -13.020000 CO..2402 -1.000000 + y...2402 CO..2403 1.000000 + y...3402 COST.... 3397.590000 CD..0302 -.350000 + y...3402 SURD0302 12.670000 S13D..02 12.670000 + y...3402 S123D.02 12.670000 CFQ.3402 -7.440000 + y...3402 CFN.3402 -13.020000 CO..3402 -1.000000 + y...3402 CO..3403 1.000000 + y...1502 COST.... 81137.31000 CD..0102 -.260000 + y...1502 SURD0102 34.040000 S12D..02 34.040000 + y...1502 S13D..02 34.040000 S123D.02 34.040000 + y...1502 CFQ.1502 -4.900000 CFN.1502 -34.300000 + y...1502 CO..1502 -1.000000 CO..1503 1.000000 + y...3502 COST.... 3397.590000 CD..0302 -.350000 + y...3502 SURD0302 13.600000 S13D..02 13.600000 + y...3502 S123D.02 13.600000 CFQ.3502 -7.440000 + y...3502 CFN.3502 -13.950000 CO..3502 -1.000000 + y...3502 CO..3503 1.000000 + y...1602 COST.... 20026.02000 CD..0102 -4.000000 + y...1602 SURD0102 111.200000 S12D..02 111.200000 + y...1602 S13D..02 111.200000 S123D.02 111.200000 + y...1602 CFQ.1602 -62.400000 CFN.1602 -120.000000 + y...1602 CO..1602 -1.000000 CO..1603 1.000000 + y...1702 COST.... 20026.02000 CD..0102 -4.500000 + y...1702 SURD0102 114.684000 S12D..02 114.684000 + y...1702 S13D..02 114.684000 S123D.02 114.684000 + y...1702 CFQ.1702 -48.000000 CFN.1702 -124.800000 + y...1702 CO..1702 -1.000000 CO..1703 1.000000 + y...3103 COST.... 59292.65000 CD..0303 -.130000 + y...3103 SURD0303 10.650000 S13D..03 10.650000 + y...3103 S123D.03 10.650000 CFQ.3103 -1.960000 + y...3103 CFN.3103 -10.780000 CO..3103 -1.000000 + y...3103 CO..3104 1.000000 + y...2203 COST.... 59292.65000 CD..0203 -.130000 + y...2203 SURD0203 10.650000 S12D..03 10.650000 + y...2203 S123D.03 10.650000 CFQ.2203 -1.960000 + y...2203 CFN.2203 -10.780000 CO..2203 -1.000000 + y...2203 CO..2204 1.000000 + y...3203 COST.... 68654.65000 CD..0303 -.220000 + y...3203 SURD0303 22.320000 S13D..03 22.320000 + y...3203 S123D.03 22.320000 CFQ.3203 -2.940000 + y...3203 CFN.3203 -22.540000 CO..3203 -1.000000 + y...3203 CO..3204 1.000000 + y...1303 COST.... 59292.65000 CD..0103 -.130000 + y...1303 SURD0103 10.650000 S12D..03 10.650000 + y...1303 S13D..03 10.650000 S123D.03 10.650000 + y...1303 CFQ.1303 -1.960000 CFN.1303 -10.780000 + y...1303 CO..1303 -1.000000 CO..1304 1.000000 + y...2303 COST.... 81137.31000 CD..0203 -.260000 + y...2303 SURD0203 34.040000 S12D..03 34.040000 + y...2303 S123D.03 34.040000 CFQ.2303 -4.900000 + y...2303 CFN.2303 -34.300000 CO..2303 -1.000000 + y...2303 CO..2304 1.000000 + y...3303 COST.... 1974.890000 CD..0303 -.150000 + y...3303 SURD0303 6.975000 S13D..03 6.975000 + y...3303 S123D.03 6.975000 CFQ.3303 -3.800000 + y...3303 CFN.3303 -7.125000 CO..3303 -1.000000 + y...3303 CO..3304 1.000000 + y...1403 COST.... 68654.65000 CD..0103 -.220000 + y...1403 SURD0103 22.320000 S12D..03 22.320000 + y...1403 S13D..03 22.320000 S123D.03 22.320000 + y...1403 CFQ.1403 -2.940000 CFN.1403 -22.540000 + y...1403 CO..1403 -1.000000 CO..1404 1.000000 + y...2403 COST.... 3888.170000 CD..0203 -.350000 + y...2403 SURD0203 12.670000 S12D..03 12.670000 + y...2403 S123D.03 12.670000 CFQ.2403 -7.440000 + y...2403 CFN.2403 -13.020000 CO..2403 -1.000000 + y...2403 CO..2404 1.000000 + y...3403 COST.... 3397.590000 CD..0303 -.350000 + y...3403 SURD0303 12.670000 S13D..03 12.670000 + y...3403 S123D.03 12.670000 CFQ.3403 -7.440000 + y...3403 CFN.3403 -13.020000 CO..3403 -1.000000 + y...3403 CO..3404 1.000000 + y...1503 COST.... 81137.31000 CD..0103 -.260000 + y...1503 SURD0103 34.040000 S12D..03 34.040000 + y...1503 S13D..03 34.040000 S123D.03 34.040000 + y...1503 CFQ.1503 -4.900000 CFN.1503 -34.300000 + y...1503 CO..1503 -1.000000 CO..1504 1.000000 + y...3503 COST.... 3397.590000 CD..0303 -.350000 + y...3503 SURD0303 13.600000 S13D..03 13.600000 + y...3503 S123D.03 13.600000 CFQ.3503 -7.440000 + y...3503 CFN.3503 -13.950000 CO..3503 -1.000000 + y...3503 CO..3504 1.000000 + y...1603 COST.... 20026.02000 CD..0103 -4.000000 + y...1603 SURD0103 111.200000 S12D..03 111.200000 + y...1603 S13D..03 111.200000 S123D.03 111.200000 + y...1603 CFQ.1603 -62.400000 CFN.1603 -120.000000 + y...1603 CO..1603 -1.000000 CO..1604 1.000000 + y...1703 COST.... 20026.02000 CD..0103 -4.500000 + y...1703 SURD0103 114.684000 S12D..03 114.684000 + y...1703 S13D..03 114.684000 S123D.03 114.684000 + y...1703 CFQ.1703 -48.000000 CFN.1703 -124.800000 + y...1703 CO..1703 -1.000000 CO..1704 1.000000 + y...3104 COST.... 59292.65000 CD..0304 -.130000 + y...3104 SURD0304 10.650000 S13D..04 10.650000 + y...3104 S123D.04 10.650000 CFQ.3104 -1.960000 + y...3104 CFN.3104 -10.780000 CO..3104 -1.000000 + y...3104 CO..3105 1.000000 + y...2204 COST.... 59292.65000 CD..0204 -.130000 + y...2204 SURD0204 10.650000 S12D..04 10.650000 + y...2204 S123D.04 10.650000 CFQ.2204 -1.960000 + y...2204 CFN.2204 -10.780000 CO..2204 -1.000000 + y...2204 CO..2205 1.000000 + y...3204 COST.... 68654.65000 CD..0304 -.220000 + y...3204 SURD0304 22.320000 S13D..04 22.320000 + y...3204 S123D.04 22.320000 CFQ.3204 -2.940000 + y...3204 CFN.3204 -22.540000 CO..3204 -1.000000 + y...3204 CO..3205 1.000000 + y...1304 COST.... 59292.65000 CD..0104 -.130000 + y...1304 SURD0104 10.650000 S12D..04 10.650000 + y...1304 S13D..04 10.650000 S123D.04 10.650000 + y...1304 CFQ.1304 -1.960000 CFN.1304 -10.780000 + y...1304 CO..1304 -1.000000 CO..1305 1.000000 + y...2304 COST.... 81137.31000 CD..0204 -.260000 + y...2304 SURD0204 34.040000 S12D..04 34.040000 + y...2304 S123D.04 34.040000 CFQ.2304 -4.900000 + y...2304 CFN.2304 -34.300000 CO..2304 -1.000000 + y...2304 CO..2305 1.000000 + y...3304 COST.... 1974.890000 CD..0304 -.150000 + y...3304 SURD0304 6.975000 S13D..04 6.975000 + y...3304 S123D.04 6.975000 CFQ.3304 -3.800000 + y...3304 CFN.3304 -7.125000 CO..3304 -1.000000 + y...3304 CO..3305 1.000000 + y...1404 COST.... 68654.65000 CD..0104 -.220000 + y...1404 SURD0104 22.320000 S12D..04 22.320000 + y...1404 S13D..04 22.320000 S123D.04 22.320000 + y...1404 CFQ.1404 -2.940000 CFN.1404 -22.540000 + y...1404 CO..1404 -1.000000 CO..1405 1.000000 + y...2404 COST.... 3888.170000 CD..0204 -.350000 + y...2404 SURD0204 12.670000 S12D..04 12.670000 + y...2404 S123D.04 12.670000 CFQ.2404 -7.440000 + y...2404 CFN.2404 -13.020000 CO..2404 -1.000000 + y...2404 CO..2405 1.000000 + y...3404 COST.... 3397.590000 CD..0304 -.350000 + y...3404 SURD0304 12.670000 S13D..04 12.670000 + y...3404 S123D.04 12.670000 CFQ.3404 -7.440000 + y...3404 CFN.3404 -13.020000 CO..3404 -1.000000 + y...3404 CO..3405 1.000000 + y...1504 COST.... 81137.31000 CD..0104 -.260000 + y...1504 SURD0104 34.040000 S12D..04 34.040000 + y...1504 S13D..04 34.040000 S123D.04 34.040000 + y...1504 CFQ.1504 -4.900000 CFN.1504 -34.300000 + y...1504 CO..1504 -1.000000 CO..1505 1.000000 + y...3504 COST.... 3397.590000 CD..0304 -.350000 + y...3504 SURD0304 13.600000 S13D..04 13.600000 + y...3504 S123D.04 13.600000 CFQ.3504 -7.440000 + y...3504 CFN.3504 -13.950000 CO..3504 -1.000000 + y...3504 CO..3505 1.000000 + y...1604 COST.... 20026.02000 CD..0104 -4.000000 + y...1604 SURD0104 111.200000 S12D..04 111.200000 + y...1604 S13D..04 111.200000 S123D.04 111.200000 + y...1604 CFQ.1604 -62.400000 CFN.1604 -120.000000 + y...1604 CO..1604 -1.000000 CO..1605 1.000000 + y...1704 COST.... 20026.02000 CD..0104 -4.500000 + y...1704 SURD0104 114.684000 S12D..04 114.684000 + y...1704 S13D..04 114.684000 S123D.04 114.684000 + y...1704 CFQ.1704 -48.000000 CFN.1704 -124.800000 + y...1704 CO..1704 -1.000000 CO..1705 1.000000 + y...3105 COST.... 59292.65000 CD..0305 -.130000 + y...3105 SURD0305 10.650000 S13D..05 10.650000 + y...3105 S123D.05 10.650000 CFQ.3105 -1.960000 + y...3105 CFN.3105 -10.780000 CO..3105 -1.000000 + y...3105 CO..3106 1.000000 + y...2205 COST.... 59292.65000 CD..0205 -.130000 + y...2205 SURD0205 10.650000 S12D..05 10.650000 + y...2205 S123D.05 10.650000 CFQ.2205 -1.960000 + y...2205 CFN.2205 -10.780000 CO..2205 -1.000000 + y...2205 CO..2206 1.000000 + y...3205 COST.... 68654.65000 CD..0305 -.220000 + y...3205 SURD0305 22.320000 S13D..05 22.320000 + y...3205 S123D.05 22.320000 CFQ.3205 -2.940000 + y...3205 CFN.3205 -22.540000 CO..3205 -1.000000 + y...3205 CO..3206 1.000000 + y...1305 COST.... 59292.65000 CD..0105 -.130000 + y...1305 SURD0105 10.650000 S12D..05 10.650000 + y...1305 S13D..05 10.650000 S123D.05 10.650000 + y...1305 CFQ.1305 -1.960000 CFN.1305 -10.780000 + y...1305 CO..1305 -1.000000 CO..1306 1.000000 + y...2305 COST.... 81137.31000 CD..0205 -.260000 + y...2305 SURD0205 34.040000 S12D..05 34.040000 + y...2305 S123D.05 34.040000 CFQ.2305 -4.900000 + y...2305 CFN.2305 -34.300000 CO..2305 -1.000000 + y...2305 CO..2306 1.000000 + y...3305 COST.... 1974.890000 CD..0305 -.150000 + y...3305 SURD0305 6.975000 S13D..05 6.975000 + y...3305 S123D.05 6.975000 CFQ.3305 -3.800000 + y...3305 CFN.3305 -7.125000 CO..3305 -1.000000 + y...3305 CO..3306 1.000000 + y...1405 COST.... 68654.65000 CD..0105 -.220000 + y...1405 SURD0105 22.320000 S12D..05 22.320000 + y...1405 S13D..05 22.320000 S123D.05 22.320000 + y...1405 CFQ.1405 -2.940000 CFN.1405 -22.540000 + y...1405 CO..1405 -1.000000 CO..1406 1.000000 + y...2405 COST.... 3888.170000 CD..0205 -.350000 + y...2405 SURD0205 12.670000 S12D..05 12.670000 + y...2405 S123D.05 12.670000 CFQ.2405 -7.440000 + y...2405 CFN.2405 -13.020000 CO..2405 -1.000000 + y...2405 CO..2406 1.000000 + y...3405 COST.... 3397.590000 CD..0305 -.350000 + y...3405 SURD0305 12.670000 S13D..05 12.670000 + y...3405 S123D.05 12.670000 CFQ.3405 -7.440000 + y...3405 CFN.3405 -13.020000 CO..3405 -1.000000 + y...3405 CO..3406 1.000000 + y...1505 COST.... 81137.31000 CD..0105 -.260000 + y...1505 SURD0105 34.040000 S12D..05 34.040000 + y...1505 S13D..05 34.040000 S123D.05 34.040000 + y...1505 CFQ.1505 -4.900000 CFN.1505 -34.300000 + y...1505 CO..1505 -1.000000 CO..1506 1.000000 + y...3505 COST.... 3397.590000 CD..0305 -.350000 + y...3505 SURD0305 13.600000 S13D..05 13.600000 + y...3505 S123D.05 13.600000 CFQ.3505 -7.440000 + y...3505 CFN.3505 -13.950000 CO..3505 -1.000000 + y...3505 CO..3506 1.000000 + y...1605 COST.... 20026.02000 CD..0105 -4.000000 + y...1605 SURD0105 111.200000 S12D..05 111.200000 + y...1605 S13D..05 111.200000 S123D.05 111.200000 + y...1605 CFQ.1605 -62.400000 CFN.1605 -120.000000 + y...1605 CO..1605 -1.000000 CO..1606 1.000000 + y...1705 COST.... 20026.02000 CD..0105 -4.500000 + y...1705 SURD0105 114.684000 S12D..05 114.684000 + y...1705 S13D..05 114.684000 S123D.05 114.684000 + y...1705 CFQ.1705 -48.000000 CFN.1705 -124.800000 + y...1705 CO..1705 -1.000000 CO..1706 1.000000 + y...3106 COST.... 59292.65000 CD..0306 -.130000 + y...3106 SURD0306 10.650000 S13D..06 10.650000 + y...3106 S123D.06 10.650000 CFQ.3106 -1.960000 + y...3106 CFN.3106 -10.780000 CO..3106 -1.000000 + y...3106 CO..3107 1.000000 + y...2206 COST.... 59292.65000 CD..0206 -.130000 + y...2206 SURD0206 10.650000 S12D..06 10.650000 + y...2206 S123D.06 10.650000 CFQ.2206 -1.960000 + y...2206 CFN.2206 -10.780000 CO..2206 -1.000000 + y...2206 CO..2207 1.000000 + y...3206 COST.... 68654.65000 CD..0306 -.220000 + y...3206 SURD0306 22.320000 S13D..06 22.320000 + y...3206 S123D.06 22.320000 CFQ.3206 -2.940000 + y...3206 CFN.3206 -22.540000 CO..3206 -1.000000 + y...3206 CO..3207 1.000000 + y...1306 COST.... 59292.65000 CD..0106 -.130000 + y...1306 SURD0106 10.650000 S12D..06 10.650000 + y...1306 S13D..06 10.650000 S123D.06 10.650000 + y...1306 CFQ.1306 -1.960000 CFN.1306 -10.780000 + y...1306 CO..1306 -1.000000 CO..1307 1.000000 + y...2306 COST.... 81137.31000 CD..0206 -.260000 + y...2306 SURD0206 34.040000 S12D..06 34.040000 + y...2306 S123D.06 34.040000 CFQ.2306 -4.900000 + y...2306 CFN.2306 -34.300000 CO..2306 -1.000000 + y...2306 CO..2307 1.000000 + y...3306 COST.... 1974.890000 CD..0306 -.150000 + y...3306 SURD0306 6.975000 S13D..06 6.975000 + y...3306 S123D.06 6.975000 CFQ.3306 -3.800000 + y...3306 CFN.3306 -7.125000 CO..3306 -1.000000 + y...3306 CO..3307 1.000000 + y...1406 COST.... 68654.65000 CD..0106 -.220000 + y...1406 SURD0106 22.320000 S12D..06 22.320000 + y...1406 S13D..06 22.320000 S123D.06 22.320000 + y...1406 CFQ.1406 -2.940000 CFN.1406 -22.540000 + y...1406 CO..1406 -1.000000 CO..1407 1.000000 + y...2406 COST.... 3888.170000 CD..0206 -.350000 + y...2406 SURD0206 12.670000 S12D..06 12.670000 + y...2406 S123D.06 12.670000 CFQ.2406 -7.440000 + y...2406 CFN.2406 -13.020000 CO..2406 -1.000000 + y...2406 CO..2407 1.000000 + y...3406 COST.... 3397.590000 CD..0306 -.350000 + y...3406 SURD0306 12.670000 S13D..06 12.670000 + y...3406 S123D.06 12.670000 CFQ.3406 -7.440000 + y...3406 CFN.3406 -13.020000 CO..3406 -1.000000 + y...3406 CO..3407 1.000000 + y...1506 COST.... 81137.31000 CD..0106 -.260000 + y...1506 SURD0106 34.040000 S12D..06 34.040000 + y...1506 S13D..06 34.040000 S123D.06 34.040000 + y...1506 CFQ.1506 -4.900000 CFN.1506 -34.300000 + y...1506 CO..1506 -1.000000 CO..1507 1.000000 + y...3506 COST.... 3397.590000 CD..0306 -.350000 + y...3506 SURD0306 13.600000 S13D..06 13.600000 + y...3506 S123D.06 13.600000 CFQ.3506 -7.440000 + y...3506 CFN.3506 -13.950000 CO..3506 -1.000000 + y...3506 CO..3507 1.000000 + y...1606 COST.... 20026.02000 CD..0106 -4.000000 + y...1606 SURD0106 111.200000 S12D..06 111.200000 + y...1606 S13D..06 111.200000 S123D.06 111.200000 + y...1606 CFQ.1606 -62.400000 CFN.1606 -120.000000 + y...1606 CO..1606 -1.000000 CO..1607 1.000000 + y...1706 COST.... 20026.02000 CD..0106 -4.500000 + y...1706 SURD0106 114.684000 S12D..06 114.684000 + y...1706 S13D..06 114.684000 S123D.06 114.684000 + y...1706 CFQ.1706 -48.000000 CFN.1706 -124.800000 + y...1706 CO..1706 -1.000000 CO..1707 1.000000 + y...3107 COST.... 59292.65000 CD..0307 -.130000 + y...3107 SURD0307 10.650000 S13D..07 10.650000 + y...3107 S123D.07 10.650000 CFQ.3107 -1.960000 + y...3107 CFN.3107 -10.780000 CO..3107 -1.000000 + y...3107 CO..3108 1.000000 + y...2207 COST.... 59292.65000 CD..0207 -.130000 + y...2207 SURD0207 10.650000 S12D..07 10.650000 + y...2207 S123D.07 10.650000 CFQ.2207 -1.960000 + y...2207 CFN.2207 -10.780000 CO..2207 -1.000000 + y...2207 CO..2208 1.000000 + y...3207 COST.... 68654.65000 CD..0307 -.220000 + y...3207 SURD0307 22.320000 S13D..07 22.320000 + y...3207 S123D.07 22.320000 CFQ.3207 -2.940000 + y...3207 CFN.3207 -22.540000 CO..3207 -1.000000 + y...3207 CO..3208 1.000000 + y...1307 COST.... 59292.65000 CD..0107 -.130000 + y...1307 SURD0107 10.650000 S12D..07 10.650000 + y...1307 S13D..07 10.650000 S123D.07 10.650000 + y...1307 CFQ.1307 -1.960000 CFN.1307 -10.780000 + y...1307 CO..1307 -1.000000 CO..1308 1.000000 + y...2307 COST.... 81137.31000 CD..0207 -.260000 + y...2307 SURD0207 34.040000 S12D..07 34.040000 + y...2307 S123D.07 34.040000 CFQ.2307 -4.900000 + y...2307 CFN.2307 -34.300000 CO..2307 -1.000000 + y...2307 CO..2308 1.000000 + y...3307 COST.... 1974.890000 CD..0307 -.150000 + y...3307 SURD0307 6.975000 S13D..07 6.975000 + y...3307 S123D.07 6.975000 CFQ.3307 -3.800000 + y...3307 CFN.3307 -7.125000 CO..3307 -1.000000 + y...3307 CO..3308 1.000000 + y...1407 COST.... 68654.65000 CD..0107 -.220000 + y...1407 SURD0107 22.320000 S12D..07 22.320000 + y...1407 S13D..07 22.320000 S123D.07 22.320000 + y...1407 CFQ.1407 -2.940000 CFN.1407 -22.540000 + y...1407 CO..1407 -1.000000 CO..1408 1.000000 + y...2407 COST.... 3888.170000 CD..0207 -.350000 + y...2407 SURD0207 12.670000 S12D..07 12.670000 + y...2407 S123D.07 12.670000 CFQ.2407 -7.440000 + y...2407 CFN.2407 -13.020000 CO..2407 -1.000000 + y...2407 CO..2408 1.000000 + y...3407 COST.... 3397.590000 CD..0307 -.350000 + y...3407 SURD0307 12.670000 S13D..07 12.670000 + y...3407 S123D.07 12.670000 CFQ.3407 -7.440000 + y...3407 CFN.3407 -13.020000 CO..3407 -1.000000 + y...3407 CO..3408 1.000000 + y...1507 COST.... 81137.31000 CD..0107 -.260000 + y...1507 SURD0107 34.040000 S12D..07 34.040000 + y...1507 S13D..07 34.040000 S123D.07 34.040000 + y...1507 CFQ.1507 -4.900000 CFN.1507 -34.300000 + y...1507 CO..1507 -1.000000 CO..1508 1.000000 + y...3507 COST.... 3397.590000 CD..0307 -.350000 + y...3507 SURD0307 13.600000 S13D..07 13.600000 + y...3507 S123D.07 13.600000 CFQ.3507 -7.440000 + y...3507 CFN.3507 -13.950000 CO..3507 -1.000000 + y...3507 CO..3508 1.000000 + y...1607 COST.... 20026.02000 CD..0107 -4.000000 + y...1607 SURD0107 111.200000 S12D..07 111.200000 + y...1607 S13D..07 111.200000 S123D.07 111.200000 + y...1607 CFQ.1607 -62.400000 CFN.1607 -120.000000 + y...1607 CO..1607 -1.000000 CO..1608 1.000000 + y...1707 COST.... 20026.02000 CD..0107 -4.500000 + y...1707 SURD0107 114.684000 S12D..07 114.684000 + y...1707 S13D..07 114.684000 S123D.07 114.684000 + y...1707 CFQ.1707 -48.000000 CFN.1707 -124.800000 + y...1707 CO..1707 -1.000000 CO..1708 1.000000 + y...3108 COST.... 59292.65000 CD..0308 -.130000 + y...3108 SURD0308 10.650000 S13D..08 10.650000 + y...3108 S123D.08 10.650000 CFQ.3108 -1.960000 + y...3108 CFN.3108 -10.780000 CO..3108 -1.000000 + y...3108 CO..3109 1.000000 + y...2208 COST.... 59292.65000 CD..0208 -.130000 + y...2208 SURD0208 10.650000 S12D..08 10.650000 + y...2208 S123D.08 10.650000 CFQ.2208 -1.960000 + y...2208 CFN.2208 -10.780000 CO..2208 -1.000000 + y...2208 CO..2209 1.000000 + y...3208 COST.... 68654.65000 CD..0308 -.220000 + y...3208 SURD0308 22.320000 S13D..08 22.320000 + y...3208 S123D.08 22.320000 CFQ.3208 -2.940000 + y...3208 CFN.3208 -22.540000 CO..3208 -1.000000 + y...3208 CO..3209 1.000000 + y...1308 COST.... 59292.65000 CD..0108 -.130000 + y...1308 SURD0108 10.650000 S12D..08 10.650000 + y...1308 S13D..08 10.650000 S123D.08 10.650000 + y...1308 CFQ.1308 -1.960000 CFN.1308 -10.780000 + y...1308 CO..1308 -1.000000 CO..1309 1.000000 + y...2308 COST.... 81137.31000 CD..0208 -.260000 + y...2308 SURD0208 34.040000 S12D..08 34.040000 + y...2308 S123D.08 34.040000 CFQ.2308 -4.900000 + y...2308 CFN.2308 -34.300000 CO..2308 -1.000000 + y...2308 CO..2309 1.000000 + y...3308 COST.... 1974.890000 CD..0308 -.150000 + y...3308 SURD0308 6.975000 S13D..08 6.975000 + y...3308 S123D.08 6.975000 CFQ.3308 -3.800000 + y...3308 CFN.3308 -7.125000 CO..3308 -1.000000 + y...3308 CO..3309 1.000000 + y...1408 COST.... 68654.65000 CD..0108 -.220000 + y...1408 SURD0108 22.320000 S12D..08 22.320000 + y...1408 S13D..08 22.320000 S123D.08 22.320000 + y...1408 CFQ.1408 -2.940000 CFN.1408 -22.540000 + y...1408 CO..1408 -1.000000 CO..1409 1.000000 + y...2408 COST.... 3888.170000 CD..0208 -.350000 + y...2408 SURD0208 12.670000 S12D..08 12.670000 + y...2408 S123D.08 12.670000 CFQ.2408 -7.440000 + y...2408 CFN.2408 -13.020000 CO..2408 -1.000000 + y...2408 CO..2409 1.000000 + y...3408 COST.... 3397.590000 CD..0308 -.350000 + y...3408 SURD0308 12.670000 S13D..08 12.670000 + y...3408 S123D.08 12.670000 CFQ.3408 -7.440000 + y...3408 CFN.3408 -13.020000 CO..3408 -1.000000 + y...3408 CO..3409 1.000000 + y...1508 COST.... 81137.31000 CD..0108 -.260000 + y...1508 SURD0108 34.040000 S12D..08 34.040000 + y...1508 S13D..08 34.040000 S123D.08 34.040000 + y...1508 CFQ.1508 -4.900000 CFN.1508 -34.300000 + y...1508 CO..1508 -1.000000 CO..1509 1.000000 + y...3508 COST.... 3397.590000 CD..0308 -.350000 + y...3508 SURD0308 13.600000 S13D..08 13.600000 + y...3508 S123D.08 13.600000 CFQ.3508 -7.440000 + y...3508 CFN.3508 -13.950000 CO..3508 -1.000000 + y...3508 CO..3509 1.000000 + y...1608 COST.... 20026.02000 CD..0108 -4.000000 + y...1608 SURD0108 111.200000 S12D..08 111.200000 + y...1608 S13D..08 111.200000 S123D.08 111.200000 + y...1608 CFQ.1608 -62.400000 CFN.1608 -120.000000 + y...1608 CO..1608 -1.000000 CO..1609 1.000000 + y...1708 COST.... 20026.02000 CD..0108 -4.500000 + y...1708 SURD0108 114.684000 S12D..08 114.684000 + y...1708 S13D..08 114.684000 S123D.08 114.684000 + y...1708 CFQ.1708 -48.000000 CFN.1708 -124.800000 + y...1708 CO..1708 -1.000000 CO..1709 1.000000 + y...3109 COST.... 59292.65000 CD..0309 -.130000 + y...3109 SURD0309 10.650000 S13D..09 10.650000 + y...3109 S123D.09 10.650000 CFQ.3109 -1.960000 + y...3109 CFN.3109 -10.780000 CO..3109 -1.000000 + y...3109 CO..3110 1.000000 + y...2209 COST.... 59292.65000 CD..0209 -.130000 + y...2209 SURD0209 10.650000 S12D..09 10.650000 + y...2209 S123D.09 10.650000 CFQ.2209 -1.960000 + y...2209 CFN.2209 -10.780000 CO..2209 -1.000000 + y...2209 CO..2210 1.000000 + y...3209 COST.... 68654.65000 CD..0309 -.220000 + y...3209 SURD0309 22.320000 S13D..09 22.320000 + y...3209 S123D.09 22.320000 CFQ.3209 -2.940000 + y...3209 CFN.3209 -22.540000 CO..3209 -1.000000 + y...3209 CO..3210 1.000000 + y...1309 COST.... 59292.65000 CD..0109 -.130000 + y...1309 SURD0109 10.650000 S12D..09 10.650000 + y...1309 S13D..09 10.650000 S123D.09 10.650000 + y...1309 CFQ.1309 -1.960000 CFN.1309 -10.780000 + y...1309 CO..1309 -1.000000 CO..1310 1.000000 + y...2309 COST.... 81137.31000 CD..0209 -.260000 + y...2309 SURD0209 34.040000 S12D..09 34.040000 + y...2309 S123D.09 34.040000 CFQ.2309 -4.900000 + y...2309 CFN.2309 -34.300000 CO..2309 -1.000000 + y...2309 CO..2310 1.000000 + y...3309 COST.... 1974.890000 CD..0309 -.150000 + y...3309 SURD0309 6.975000 S13D..09 6.975000 + y...3309 S123D.09 6.975000 CFQ.3309 -3.800000 + y...3309 CFN.3309 -7.125000 CO..3309 -1.000000 + y...3309 CO..3310 1.000000 + y...1409 COST.... 68654.65000 CD..0109 -.220000 + y...1409 SURD0109 22.320000 S12D..09 22.320000 + y...1409 S13D..09 22.320000 S123D.09 22.320000 + y...1409 CFQ.1409 -2.940000 CFN.1409 -22.540000 + y...1409 CO..1409 -1.000000 CO..1410 1.000000 + y...2409 COST.... 3888.170000 CD..0209 -.350000 + y...2409 SURD0209 12.670000 S12D..09 12.670000 + y...2409 S123D.09 12.670000 CFQ.2409 -7.440000 + y...2409 CFN.2409 -13.020000 CO..2409 -1.000000 + y...2409 CO..2410 1.000000 + y...3409 COST.... 3397.590000 CD..0309 -.350000 + y...3409 SURD0309 12.670000 S13D..09 12.670000 + y...3409 S123D.09 12.670000 CFQ.3409 -7.440000 + y...3409 CFN.3409 -13.020000 CO..3409 -1.000000 + y...3409 CO..3410 1.000000 + y...1509 COST.... 81137.31000 CD..0109 -.260000 + y...1509 SURD0109 34.040000 S12D..09 34.040000 + y...1509 S13D..09 34.040000 S123D.09 34.040000 + y...1509 CFQ.1509 -4.900000 CFN.1509 -34.300000 + y...1509 CO..1509 -1.000000 CO..1510 1.000000 + y...3509 COST.... 3397.590000 CD..0309 -.350000 + y...3509 SURD0309 13.600000 S13D..09 13.600000 + y...3509 S123D.09 13.600000 CFQ.3509 -7.440000 + y...3509 CFN.3509 -13.950000 CO..3509 -1.000000 + y...3509 CO..3510 1.000000 + y...1609 COST.... 20026.02000 CD..0109 -4.000000 + y...1609 SURD0109 111.200000 S12D..09 111.200000 + y...1609 S13D..09 111.200000 S123D.09 111.200000 + y...1609 CFQ.1609 -62.400000 CFN.1609 -120.000000 + y...1609 CO..1609 -1.000000 CO..1610 1.000000 + y...1709 COST.... 20026.02000 CD..0109 -4.500000 + y...1709 SURD0109 114.684000 S12D..09 114.684000 + y...1709 S13D..09 114.684000 S123D.09 114.684000 + y...1709 CFQ.1709 -48.000000 CFN.1709 -124.800000 + y...1709 CO..1709 -1.000000 CO..1710 1.000000 + y...3110 COST.... 59292.65000 CD..0310 -.130000 + y...3110 SURD0310 10.650000 S13D..10 10.650000 + y...3110 S123D.10 10.650000 CFQ.3110 -1.960000 + y...3110 CFN.3110 -10.780000 CO..3110 -1.000000 + y...3110 CO..3111 1.000000 + y...2210 COST.... 59292.65000 CD..0210 -.130000 + y...2210 SURD0210 10.650000 S12D..10 10.650000 + y...2210 S123D.10 10.650000 CFQ.2210 -1.960000 + y...2210 CFN.2210 -10.780000 CO..2210 -1.000000 + y...2210 CO..2211 1.000000 + y...3210 COST.... 68654.65000 CD..0310 -.220000 + y...3210 SURD0310 22.320000 S13D..10 22.320000 + y...3210 S123D.10 22.320000 CFQ.3210 -2.940000 + y...3210 CFN.3210 -22.540000 CO..3210 -1.000000 + y...3210 CO..3211 1.000000 + y...1310 COST.... 59292.65000 CD..0110 -.130000 + y...1310 SURD0110 10.650000 S12D..10 10.650000 + y...1310 S13D..10 10.650000 S123D.10 10.650000 + y...1310 CFQ.1310 -1.960000 CFN.1310 -10.780000 + y...1310 CO..1310 -1.000000 CO..1311 1.000000 + y...2310 COST.... 81137.31000 CD..0210 -.260000 + y...2310 SURD0210 34.040000 S12D..10 34.040000 + y...2310 S123D.10 34.040000 CFQ.2310 -4.900000 + y...2310 CFN.2310 -34.300000 CO..2310 -1.000000 + y...2310 CO..2311 1.000000 + y...3310 COST.... 1974.890000 CD..0310 -.150000 + y...3310 SURD0310 6.975000 S13D..10 6.975000 + y...3310 S123D.10 6.975000 CFQ.3310 -3.800000 + y...3310 CFN.3310 -7.125000 CO..3310 -1.000000 + y...3310 CO..3311 1.000000 + y...1410 COST.... 68654.65000 CD..0110 -.220000 + y...1410 SURD0110 22.320000 S12D..10 22.320000 + y...1410 S13D..10 22.320000 S123D.10 22.320000 + y...1410 CFQ.1410 -2.940000 CFN.1410 -22.540000 + y...1410 CO..1410 -1.000000 CO..1411 1.000000 + y...2410 COST.... 3888.170000 CD..0210 -.350000 + y...2410 SURD0210 12.670000 S12D..10 12.670000 + y...2410 S123D.10 12.670000 CFQ.2410 -7.440000 + y...2410 CFN.2410 -13.020000 CO..2410 -1.000000 + y...2410 CO..2411 1.000000 + y...3410 COST.... 3397.590000 CD..0310 -.350000 + y...3410 SURD0310 12.670000 S13D..10 12.670000 + y...3410 S123D.10 12.670000 CFQ.3410 -7.440000 + y...3410 CFN.3410 -13.020000 CO..3410 -1.000000 + y...3410 CO..3411 1.000000 + y...1510 COST.... 81137.31000 CD..0110 -.260000 + y...1510 SURD0110 34.040000 S12D..10 34.040000 + y...1510 S13D..10 34.040000 S123D.10 34.040000 + y...1510 CFQ.1510 -4.900000 CFN.1510 -34.300000 + y...1510 CO..1510 -1.000000 CO..1511 1.000000 + y...3510 COST.... 3397.590000 CD..0310 -.350000 + y...3510 SURD0310 13.600000 S13D..10 13.600000 + y...3510 S123D.10 13.600000 CFQ.3510 -7.440000 + y...3510 CFN.3510 -13.950000 CO..3510 -1.000000 + y...3510 CO..3511 1.000000 + y...1610 COST.... 20026.02000 CD..0110 -4.000000 + y...1610 SURD0110 111.200000 S12D..10 111.200000 + y...1610 S13D..10 111.200000 S123D.10 111.200000 + y...1610 CFQ.1610 -62.400000 CFN.1610 -120.000000 + y...1610 CO..1610 -1.000000 CO..1611 1.000000 + y...1710 COST.... 20026.02000 CD..0110 -4.500000 + y...1710 SURD0110 114.684000 S12D..10 114.684000 + y...1710 S13D..10 114.684000 S123D.10 114.684000 + y...1710 CFQ.1710 -48.000000 CFN.1710 -124.800000 + y...1710 CO..1710 -1.000000 CO..1711 1.000000 + y...3111 COST.... 59292.65000 CD..0311 -.130000 + y...3111 SURD0311 10.650000 S13D..11 10.650000 + y...3111 S123D.11 10.650000 CFQ.3111 -1.960000 + y...3111 CFN.3111 -10.780000 CO..3111 -1.000000 + y...3111 CO..3112 1.000000 + y...2211 COST.... 59292.65000 CD..0211 -.130000 + y...2211 SURD0211 10.650000 S12D..11 10.650000 + y...2211 S123D.11 10.650000 CFQ.2211 -1.960000 + y...2211 CFN.2211 -10.780000 CO..2211 -1.000000 + y...2211 CO..2212 1.000000 + y...3211 COST.... 68654.65000 CD..0311 -.220000 + y...3211 SURD0311 22.320000 S13D..11 22.320000 + y...3211 S123D.11 22.320000 CFQ.3211 -2.940000 + y...3211 CFN.3211 -22.540000 CO..3211 -1.000000 + y...3211 CO..3212 1.000000 + y...1311 COST.... 59292.65000 CD..0111 -.130000 + y...1311 SURD0111 10.650000 S12D..11 10.650000 + y...1311 S13D..11 10.650000 S123D.11 10.650000 + y...1311 CFQ.1311 -1.960000 CFN.1311 -10.780000 + y...1311 CO..1311 -1.000000 CO..1312 1.000000 + y...2311 COST.... 81137.31000 CD..0211 -.260000 + y...2311 SURD0211 34.040000 S12D..11 34.040000 + y...2311 S123D.11 34.040000 CFQ.2311 -4.900000 + y...2311 CFN.2311 -34.300000 CO..2311 -1.000000 + y...2311 CO..2312 1.000000 + y...3311 COST.... 1974.890000 CD..0311 -.150000 + y...3311 SURD0311 6.975000 S13D..11 6.975000 + y...3311 S123D.11 6.975000 CFQ.3311 -3.800000 + y...3311 CFN.3311 -7.125000 CO..3311 -1.000000 + y...3311 CO..3312 1.000000 + y...1411 COST.... 68654.65000 CD..0111 -.220000 + y...1411 SURD0111 22.320000 S12D..11 22.320000 + y...1411 S13D..11 22.320000 S123D.11 22.320000 + y...1411 CFQ.1411 -2.940000 CFN.1411 -22.540000 + y...1411 CO..1411 -1.000000 CO..1412 1.000000 + y...2411 COST.... 3888.170000 CD..0211 -.350000 + y...2411 SURD0211 12.670000 S12D..11 12.670000 + y...2411 S123D.11 12.670000 CFQ.2411 -7.440000 + y...2411 CFN.2411 -13.020000 CO..2411 -1.000000 + y...2411 CO..2412 1.000000 + y...3411 COST.... 3397.590000 CD..0311 -.350000 + y...3411 SURD0311 12.670000 S13D..11 12.670000 + y...3411 S123D.11 12.670000 CFQ.3411 -7.440000 + y...3411 CFN.3411 -13.020000 CO..3411 -1.000000 + y...3411 CO..3412 1.000000 + y...1511 COST.... 81137.31000 CD..0111 -.260000 + y...1511 SURD0111 34.040000 S12D..11 34.040000 + y...1511 S13D..11 34.040000 S123D.11 34.040000 + y...1511 CFQ.1511 -4.900000 CFN.1511 -34.300000 + y...1511 CO..1511 -1.000000 CO..1512 1.000000 + y...3511 COST.... 3397.590000 CD..0311 -.350000 + y...3511 SURD0311 13.600000 S13D..11 13.600000 + y...3511 S123D.11 13.600000 CFQ.3511 -7.440000 + y...3511 CFN.3511 -13.950000 CO..3511 -1.000000 + y...3511 CO..3512 1.000000 + y...1611 COST.... 20026.02000 CD..0111 -4.000000 + y...1611 SURD0111 111.200000 S12D..11 111.200000 + y...1611 S13D..11 111.200000 S123D.11 111.200000 + y...1611 CFQ.1611 -62.400000 CFN.1611 -120.000000 + y...1611 CO..1611 -1.000000 CO..1612 1.000000 + y...1711 COST.... 20026.02000 CD..0111 -4.500000 + y...1711 SURD0111 114.684000 S12D..11 114.684000 + y...1711 S13D..11 114.684000 S123D.11 114.684000 + y...1711 CFQ.1711 -48.000000 CFN.1711 -124.800000 + y...1711 CO..1711 -1.000000 CO..1712 1.000000 + y...3112 COST.... 59292.65000 CD..0312 -.130000 + y...3112 SURD0312 10.650000 S13D..12 10.650000 + y...3112 S123D.12 10.650000 CFQ.3112 -1.960000 + y...3112 CFN.3112 -10.780000 CO..3112 -1.000000 + y...3112 CO..3113 1.000000 + y...2212 COST.... 59292.65000 CD..0212 -.130000 + y...2212 SURD0212 10.650000 S12D..12 10.650000 + y...2212 S123D.12 10.650000 CFQ.2212 -1.960000 + y...2212 CFN.2212 -10.780000 CO..2212 -1.000000 + y...2212 CO..2213 1.000000 + y...3212 COST.... 68654.65000 CD..0312 -.220000 + y...3212 SURD0312 22.320000 S13D..12 22.320000 + y...3212 S123D.12 22.320000 CFQ.3212 -2.940000 + y...3212 CFN.3212 -22.540000 CO..3212 -1.000000 + y...3212 CO..3213 1.000000 + y...1312 COST.... 59292.65000 CD..0112 -.130000 + y...1312 SURD0112 10.650000 S12D..12 10.650000 + y...1312 S13D..12 10.650000 S123D.12 10.650000 + y...1312 CFQ.1312 -1.960000 CFN.1312 -10.780000 + y...1312 CO..1312 -1.000000 CO..1313 1.000000 + y...2312 COST.... 81137.31000 CD..0212 -.260000 + y...2312 SURD0212 34.040000 S12D..12 34.040000 + y...2312 S123D.12 34.040000 CFQ.2312 -4.900000 + y...2312 CFN.2312 -34.300000 CO..2312 -1.000000 + y...2312 CO..2313 1.000000 + y...3312 COST.... 1974.890000 CD..0312 -.150000 + y...3312 SURD0312 6.975000 S13D..12 6.975000 + y...3312 S123D.12 6.975000 CFQ.3312 -3.800000 + y...3312 CFN.3312 -7.125000 CO..3312 -1.000000 + y...3312 CO..3313 1.000000 + y...1412 COST.... 68654.65000 CD..0112 -.220000 + y...1412 SURD0112 22.320000 S12D..12 22.320000 + y...1412 S13D..12 22.320000 S123D.12 22.320000 + y...1412 CFQ.1412 -2.940000 CFN.1412 -22.540000 + y...1412 CO..1412 -1.000000 CO..1413 1.000000 + y...2412 COST.... 3888.170000 CD..0212 -.350000 + y...2412 SURD0212 12.670000 S12D..12 12.670000 + y...2412 S123D.12 12.670000 CFQ.2412 -7.440000 + y...2412 CFN.2412 -13.020000 CO..2412 -1.000000 + y...2412 CO..2413 1.000000 + y...3412 COST.... 3397.590000 CD..0312 -.350000 + y...3412 SURD0312 12.670000 S13D..12 12.670000 + y...3412 S123D.12 12.670000 CFQ.3412 -7.440000 + y...3412 CFN.3412 -13.020000 CO..3412 -1.000000 + y...3412 CO..3413 1.000000 + y...1512 COST.... 81137.31000 CD..0112 -.260000 + y...1512 SURD0112 34.040000 S12D..12 34.040000 + y...1512 S13D..12 34.040000 S123D.12 34.040000 + y...1512 CFQ.1512 -4.900000 CFN.1512 -34.300000 + y...1512 CO..1512 -1.000000 CO..1513 1.000000 + y...3512 COST.... 3397.590000 CD..0312 -.350000 + y...3512 SURD0312 13.600000 S13D..12 13.600000 + y...3512 S123D.12 13.600000 CFQ.3512 -7.440000 + y...3512 CFN.3512 -13.950000 CO..3512 -1.000000 + y...3512 CO..3513 1.000000 + y...1612 COST.... 20026.02000 CD..0112 -4.000000 + y...1612 SURD0112 111.200000 S12D..12 111.200000 + y...1612 S13D..12 111.200000 S123D.12 111.200000 + y...1612 CFQ.1612 -62.400000 CFN.1612 -120.000000 + y...1612 CO..1612 -1.000000 CO..1613 1.000000 + y...1712 COST.... 20026.02000 CD..0112 -4.500000 + y...1712 SURD0112 114.684000 S12D..12 114.684000 + y...1712 S13D..12 114.684000 S123D.12 114.684000 + y...1712 CFQ.1712 -48.000000 CFN.1712 -124.800000 + y...1712 CO..1712 -1.000000 CO..1713 1.000000 + y...3113 COST.... 59292.65000 CD..0313 -.130000 + y...3113 SURD0313 10.650000 S13D..13 10.650000 + y...3113 S123D.13 10.650000 CFQ.3113 -1.960000 + y...3113 CFN.3113 -10.780000 CO..3113 -1.000000 + y...3113 CO..3114 1.000000 + y...2213 COST.... 59292.65000 CD..0213 -.130000 + y...2213 SURD0213 10.650000 S12D..13 10.650000 + y...2213 S123D.13 10.650000 CFQ.2213 -1.960000 + y...2213 CFN.2213 -10.780000 CO..2213 -1.000000 + y...2213 CO..2214 1.000000 + y...3213 COST.... 68654.65000 CD..0313 -.220000 + y...3213 SURD0313 22.320000 S13D..13 22.320000 + y...3213 S123D.13 22.320000 CFQ.3213 -2.940000 + y...3213 CFN.3213 -22.540000 CO..3213 -1.000000 + y...3213 CO..3214 1.000000 + y...1313 COST.... 59292.65000 CD..0113 -.130000 + y...1313 SURD0113 10.650000 S12D..13 10.650000 + y...1313 S13D..13 10.650000 S123D.13 10.650000 + y...1313 CFQ.1313 -1.960000 CFN.1313 -10.780000 + y...1313 CO..1313 -1.000000 CO..1314 1.000000 + y...2313 COST.... 81137.31000 CD..0213 -.260000 + y...2313 SURD0213 34.040000 S12D..13 34.040000 + y...2313 S123D.13 34.040000 CFQ.2313 -4.900000 + y...2313 CFN.2313 -34.300000 CO..2313 -1.000000 + y...2313 CO..2314 1.000000 + y...3313 COST.... 1974.890000 CD..0313 -.150000 + y...3313 SURD0313 6.975000 S13D..13 6.975000 + y...3313 S123D.13 6.975000 CFQ.3313 -3.800000 + y...3313 CFN.3313 -7.125000 CO..3313 -1.000000 + y...3313 CO..3314 1.000000 + y...1413 COST.... 68654.65000 CD..0113 -.220000 + y...1413 SURD0113 22.320000 S12D..13 22.320000 + y...1413 S13D..13 22.320000 S123D.13 22.320000 + y...1413 CFQ.1413 -2.940000 CFN.1413 -22.540000 + y...1413 CO..1413 -1.000000 CO..1414 1.000000 + y...2413 COST.... 3888.170000 CD..0213 -.350000 + y...2413 SURD0213 12.670000 S12D..13 12.670000 + y...2413 S123D.13 12.670000 CFQ.2413 -7.440000 + y...2413 CFN.2413 -13.020000 CO..2413 -1.000000 + y...2413 CO..2414 1.000000 + y...3413 COST.... 3397.590000 CD..0313 -.350000 + y...3413 SURD0313 12.670000 S13D..13 12.670000 + y...3413 S123D.13 12.670000 CFQ.3413 -7.440000 + y...3413 CFN.3413 -13.020000 CO..3413 -1.000000 + y...3413 CO..3414 1.000000 + y...1513 COST.... 81137.31000 CD..0113 -.260000 + y...1513 SURD0113 34.040000 S12D..13 34.040000 + y...1513 S13D..13 34.040000 S123D.13 34.040000 + y...1513 CFQ.1513 -4.900000 CFN.1513 -34.300000 + y...1513 CO..1513 -1.000000 CO..1514 1.000000 + y...3513 COST.... 3397.590000 CD..0313 -.350000 + y...3513 SURD0313 13.600000 S13D..13 13.600000 + y...3513 S123D.13 13.600000 CFQ.3513 -7.440000 + y...3513 CFN.3513 -13.950000 CO..3513 -1.000000 + y...3513 CO..3514 1.000000 + y...1613 COST.... 20026.02000 CD..0113 -4.000000 + y...1613 SURD0113 111.200000 S12D..13 111.200000 + y...1613 S13D..13 111.200000 S123D.13 111.200000 + y...1613 CFQ.1613 -62.400000 CFN.1613 -120.000000 + y...1613 CO..1613 -1.000000 CO..1614 1.000000 + y...1713 COST.... 20026.02000 CD..0113 -4.500000 + y...1713 SURD0113 114.684000 S12D..13 114.684000 + y...1713 S13D..13 114.684000 S123D.13 114.684000 + y...1713 CFQ.1713 -48.000000 CFN.1713 -124.800000 + y...1713 CO..1713 -1.000000 CO..1714 1.000000 + y...3114 COST.... 59292.65000 CD..0314 -.130000 + y...3114 SURD0314 10.650000 S13D..14 10.650000 + y...3114 S123D.14 10.650000 CFQ.3114 -1.960000 + y...3114 CFN.3114 -10.780000 CO..3114 -1.000000 + y...3114 CO..3115 1.000000 + y...2214 COST.... 59292.65000 CD..0214 -.130000 + y...2214 SURD0214 10.650000 S12D..14 10.650000 + y...2214 S123D.14 10.650000 CFQ.2214 -1.960000 + y...2214 CFN.2214 -10.780000 CO..2214 -1.000000 + y...2214 CO..2215 1.000000 + y...3214 COST.... 68654.65000 CD..0314 -.220000 + y...3214 SURD0314 22.320000 S13D..14 22.320000 + y...3214 S123D.14 22.320000 CFQ.3214 -2.940000 + y...3214 CFN.3214 -22.540000 CO..3214 -1.000000 + y...3214 CO..3215 1.000000 + y...1314 COST.... 59292.65000 CD..0114 -.130000 + y...1314 SURD0114 10.650000 S12D..14 10.650000 + y...1314 S13D..14 10.650000 S123D.14 10.650000 + y...1314 CFQ.1314 -1.960000 CFN.1314 -10.780000 + y...1314 CO..1314 -1.000000 CO..1315 1.000000 + y...2314 COST.... 81137.31000 CD..0214 -.260000 + y...2314 SURD0214 34.040000 S12D..14 34.040000 + y...2314 S123D.14 34.040000 CFQ.2314 -4.900000 + y...2314 CFN.2314 -34.300000 CO..2314 -1.000000 + y...2314 CO..2315 1.000000 + y...3314 COST.... 1974.890000 CD..0314 -.150000 + y...3314 SURD0314 6.975000 S13D..14 6.975000 + y...3314 S123D.14 6.975000 CFQ.3314 -3.800000 + y...3314 CFN.3314 -7.125000 CO..3314 -1.000000 + y...3314 CO..3315 1.000000 + y...1414 COST.... 68654.65000 CD..0114 -.220000 + y...1414 SURD0114 22.320000 S12D..14 22.320000 + y...1414 S13D..14 22.320000 S123D.14 22.320000 + y...1414 CFQ.1414 -2.940000 CFN.1414 -22.540000 + y...1414 CO..1414 -1.000000 CO..1415 1.000000 + y...2414 COST.... 3888.170000 CD..0214 -.350000 + y...2414 SURD0214 12.670000 S12D..14 12.670000 + y...2414 S123D.14 12.670000 CFQ.2414 -7.440000 + y...2414 CFN.2414 -13.020000 CO..2414 -1.000000 + y...2414 CO..2415 1.000000 + y...3414 COST.... 3397.590000 CD..0314 -.350000 + y...3414 SURD0314 12.670000 S13D..14 12.670000 + y...3414 S123D.14 12.670000 CFQ.3414 -7.440000 + y...3414 CFN.3414 -13.020000 CO..3414 -1.000000 + y...3414 CO..3415 1.000000 + y...1514 COST.... 81137.31000 CD..0114 -.260000 + y...1514 SURD0114 34.040000 S12D..14 34.040000 + y...1514 S13D..14 34.040000 S123D.14 34.040000 + y...1514 CFQ.1514 -4.900000 CFN.1514 -34.300000 + y...1514 CO..1514 -1.000000 CO..1515 1.000000 + y...3514 COST.... 3397.590000 CD..0314 -.350000 + y...3514 SURD0314 13.600000 S13D..14 13.600000 + y...3514 S123D.14 13.600000 CFQ.3514 -7.440000 + y...3514 CFN.3514 -13.950000 CO..3514 -1.000000 + y...3514 CO..3515 1.000000 + y...1614 COST.... 20026.02000 CD..0114 -4.000000 + y...1614 SURD0114 111.200000 S12D..14 111.200000 + y...1614 S13D..14 111.200000 S123D.14 111.200000 + y...1614 CFQ.1614 -62.400000 CFN.1614 -120.000000 + y...1614 CO..1614 -1.000000 CO..1615 1.000000 + y...1714 COST.... 20026.02000 CD..0114 -4.500000 + y...1714 SURD0114 114.684000 S12D..14 114.684000 + y...1714 S13D..14 114.684000 S123D.14 114.684000 + y...1714 CFQ.1714 -48.000000 CFN.1714 -124.800000 + y...1714 CO..1714 -1.000000 CO..1715 1.000000 + y...3115 COST.... 59292.65000 CD..0315 -.130000 + y...3115 SURD0315 10.650000 S13D..15 10.650000 + y...3115 S123D.15 10.650000 CFQ.3115 -1.960000 + y...3115 CFN.3115 -10.780000 CO..3115 -1.000000 + y...3115 CO..3116 1.000000 + y...2215 COST.... 59292.65000 CD..0215 -.130000 + y...2215 SURD0215 10.650000 S12D..15 10.650000 + y...2215 S123D.15 10.650000 CFQ.2215 -1.960000 + y...2215 CFN.2215 -10.780000 CO..2215 -1.000000 + y...2215 CO..2216 1.000000 + y...3215 COST.... 68654.65000 CD..0315 -.220000 + y...3215 SURD0315 22.320000 S13D..15 22.320000 + y...3215 S123D.15 22.320000 CFQ.3215 -2.940000 + y...3215 CFN.3215 -22.540000 CO..3215 -1.000000 + y...3215 CO..3216 1.000000 + y...1315 COST.... 59292.65000 CD..0115 -.130000 + y...1315 SURD0115 10.650000 S12D..15 10.650000 + y...1315 S13D..15 10.650000 S123D.15 10.650000 + y...1315 CFQ.1315 -1.960000 CFN.1315 -10.780000 + y...1315 CO..1315 -1.000000 CO..1316 1.000000 + y...2315 COST.... 81137.31000 CD..0215 -.260000 + y...2315 SURD0215 34.040000 S12D..15 34.040000 + y...2315 S123D.15 34.040000 CFQ.2315 -4.900000 + y...2315 CFN.2315 -34.300000 CO..2315 -1.000000 + y...2315 CO..2316 1.000000 + y...3315 COST.... 1974.890000 CD..0315 -.150000 + y...3315 SURD0315 6.975000 S13D..15 6.975000 + y...3315 S123D.15 6.975000 CFQ.3315 -3.800000 + y...3315 CFN.3315 -7.125000 CO..3315 -1.000000 + y...3315 CO..3316 1.000000 + y...1415 COST.... 68654.65000 CD..0115 -.220000 + y...1415 SURD0115 22.320000 S12D..15 22.320000 + y...1415 S13D..15 22.320000 S123D.15 22.320000 + y...1415 CFQ.1415 -2.940000 CFN.1415 -22.540000 + y...1415 CO..1415 -1.000000 CO..1416 1.000000 + y...2415 COST.... 3888.170000 CD..0215 -.350000 + y...2415 SURD0215 12.670000 S12D..15 12.670000 + y...2415 S123D.15 12.670000 CFQ.2415 -7.440000 + y...2415 CFN.2415 -13.020000 CO..2415 -1.000000 + y...2415 CO..2416 1.000000 + y...3415 COST.... 3397.590000 CD..0315 -.350000 + y...3415 SURD0315 12.670000 S13D..15 12.670000 + y...3415 S123D.15 12.670000 CFQ.3415 -7.440000 + y...3415 CFN.3415 -13.020000 CO..3415 -1.000000 + y...3415 CO..3416 1.000000 + y...1515 COST.... 81137.31000 CD..0115 -.260000 + y...1515 SURD0115 34.040000 S12D..15 34.040000 + y...1515 S13D..15 34.040000 S123D.15 34.040000 + y...1515 CFQ.1515 -4.900000 CFN.1515 -34.300000 + y...1515 CO..1515 -1.000000 CO..1516 1.000000 + y...3515 COST.... 3397.590000 CD..0315 -.350000 + y...3515 SURD0315 13.600000 S13D..15 13.600000 + y...3515 S123D.15 13.600000 CFQ.3515 -7.440000 + y...3515 CFN.3515 -13.950000 CO..3515 -1.000000 + y...3515 CO..3516 1.000000 + y...1615 COST.... 20026.02000 CD..0115 -4.000000 + y...1615 SURD0115 111.200000 S12D..15 111.200000 + y...1615 S13D..15 111.200000 S123D.15 111.200000 + y...1615 CFQ.1615 -62.400000 CFN.1615 -120.000000 + y...1615 CO..1615 -1.000000 CO..1616 1.000000 + y...1715 COST.... 20026.02000 CD..0115 -4.500000 + y...1715 SURD0115 114.684000 S12D..15 114.684000 + y...1715 S13D..15 114.684000 S123D.15 114.684000 + y...1715 CFQ.1715 -48.000000 CFN.1715 -124.800000 + y...1715 CO..1715 -1.000000 CO..1716 1.000000 + y...3116 COST.... 59292.65000 CD..0316 -.130000 + y...3116 SURD0316 10.650000 S13D..16 10.650000 + y...3116 S123D.16 10.650000 CFQ.3116 -1.960000 + y...3116 CFN.3116 -10.780000 CO..3116 -1.000000 + y...3116 CO..3117 1.000000 + y...2216 COST.... 59292.65000 CD..0216 -.130000 + y...2216 SURD0216 10.650000 S12D..16 10.650000 + y...2216 S123D.16 10.650000 CFQ.2216 -1.960000 + y...2216 CFN.2216 -10.780000 CO..2216 -1.000000 + y...2216 CO..2217 1.000000 + y...3216 COST.... 68654.65000 CD..0316 -.220000 + y...3216 SURD0316 22.320000 S13D..16 22.320000 + y...3216 S123D.16 22.320000 CFQ.3216 -2.940000 + y...3216 CFN.3216 -22.540000 CO..3216 -1.000000 + y...3216 CO..3217 1.000000 + y...1316 COST.... 59292.65000 CD..0116 -.130000 + y...1316 SURD0116 10.650000 S12D..16 10.650000 + y...1316 S13D..16 10.650000 S123D.16 10.650000 + y...1316 CFQ.1316 -1.960000 CFN.1316 -10.780000 + y...1316 CO..1316 -1.000000 CO..1317 1.000000 + y...2316 COST.... 81137.31000 CD..0216 -.260000 + y...2316 SURD0216 34.040000 S12D..16 34.040000 + y...2316 S123D.16 34.040000 CFQ.2316 -4.900000 + y...2316 CFN.2316 -34.300000 CO..2316 -1.000000 + y...2316 CO..2317 1.000000 + y...3316 COST.... 1974.890000 CD..0316 -.150000 + y...3316 SURD0316 6.975000 S13D..16 6.975000 + y...3316 S123D.16 6.975000 CFQ.3316 -3.800000 + y...3316 CFN.3316 -7.125000 CO..3316 -1.000000 + y...3316 CO..3317 1.000000 + y...1416 COST.... 68654.65000 CD..0116 -.220000 + y...1416 SURD0116 22.320000 S12D..16 22.320000 + y...1416 S13D..16 22.320000 S123D.16 22.320000 + y...1416 CFQ.1416 -2.940000 CFN.1416 -22.540000 + y...1416 CO..1416 -1.000000 CO..1417 1.000000 + y...2416 COST.... 3888.170000 CD..0216 -.350000 + y...2416 SURD0216 12.670000 S12D..16 12.670000 + y...2416 S123D.16 12.670000 CFQ.2416 -7.440000 + y...2416 CFN.2416 -13.020000 CO..2416 -1.000000 + y...2416 CO..2417 1.000000 + y...3416 COST.... 3397.590000 CD..0316 -.350000 + y...3416 SURD0316 12.670000 S13D..16 12.670000 + y...3416 S123D.16 12.670000 CFQ.3416 -7.440000 + y...3416 CFN.3416 -13.020000 CO..3416 -1.000000 + y...3416 CO..3417 1.000000 + y...1516 COST.... 81137.31000 CD..0116 -.260000 + y...1516 SURD0116 34.040000 S12D..16 34.040000 + y...1516 S13D..16 34.040000 S123D.16 34.040000 + y...1516 CFQ.1516 -4.900000 CFN.1516 -34.300000 + y...1516 CO..1516 -1.000000 CO..1517 1.000000 + y...3516 COST.... 3397.590000 CD..0316 -.350000 + y...3516 SURD0316 13.600000 S13D..16 13.600000 + y...3516 S123D.16 13.600000 CFQ.3516 -7.440000 + y...3516 CFN.3516 -13.950000 CO..3516 -1.000000 + y...3516 CO..3517 1.000000 + y...1616 COST.... 20026.02000 CD..0116 -4.000000 + y...1616 SURD0116 111.200000 S12D..16 111.200000 + y...1616 S13D..16 111.200000 S123D.16 111.200000 + y...1616 CFQ.1616 -62.400000 CFN.1616 -120.000000 + y...1616 CO..1616 -1.000000 CO..1617 1.000000 + y...1716 COST.... 20026.02000 CD..0116 -4.500000 + y...1716 SURD0116 114.684000 S12D..16 114.684000 + y...1716 S13D..16 114.684000 S123D.16 114.684000 + y...1716 CFQ.1716 -48.000000 CFN.1716 -124.800000 + y...1716 CO..1716 -1.000000 CO..1717 1.000000 + y...3117 COST.... 59292.65000 CD..0317 -.130000 + y...3117 SURD0317 10.650000 S13D..17 10.650000 + y...3117 S123D.17 10.650000 CFQ.3117 -1.960000 + y...3117 CFN.3117 -10.780000 CO..3117 -1.000000 + y...3117 CO..3118 1.000000 + y...2217 COST.... 59292.65000 CD..0217 -.130000 + y...2217 SURD0217 10.650000 S12D..17 10.650000 + y...2217 S123D.17 10.650000 CFQ.2217 -1.960000 + y...2217 CFN.2217 -10.780000 CO..2217 -1.000000 + y...2217 CO..2218 1.000000 + y...3217 COST.... 68654.65000 CD..0317 -.220000 + y...3217 SURD0317 22.320000 S13D..17 22.320000 + y...3217 S123D.17 22.320000 CFQ.3217 -2.940000 + y...3217 CFN.3217 -22.540000 CO..3217 -1.000000 + y...3217 CO..3218 1.000000 + y...1317 COST.... 59292.65000 CD..0117 -.130000 + y...1317 SURD0117 10.650000 S12D..17 10.650000 + y...1317 S13D..17 10.650000 S123D.17 10.650000 + y...1317 CFQ.1317 -1.960000 CFN.1317 -10.780000 + y...1317 CO..1317 -1.000000 CO..1318 1.000000 + y...2317 COST.... 81137.31000 CD..0217 -.260000 + y...2317 SURD0217 34.040000 S12D..17 34.040000 + y...2317 S123D.17 34.040000 CFQ.2317 -4.900000 + y...2317 CFN.2317 -34.300000 CO..2317 -1.000000 + y...2317 CO..2318 1.000000 + y...3317 COST.... 1974.890000 CD..0317 -.150000 + y...3317 SURD0317 6.975000 S13D..17 6.975000 + y...3317 S123D.17 6.975000 CFQ.3317 -3.800000 + y...3317 CFN.3317 -7.125000 CO..3317 -1.000000 + y...3317 CO..3318 1.000000 + y...1417 COST.... 68654.65000 CD..0117 -.220000 + y...1417 SURD0117 22.320000 S12D..17 22.320000 + y...1417 S13D..17 22.320000 S123D.17 22.320000 + y...1417 CFQ.1417 -2.940000 CFN.1417 -22.540000 + y...1417 CO..1417 -1.000000 CO..1418 1.000000 + y...2417 COST.... 3888.170000 CD..0217 -.350000 + y...2417 SURD0217 12.670000 S12D..17 12.670000 + y...2417 S123D.17 12.670000 CFQ.2417 -7.440000 + y...2417 CFN.2417 -13.020000 CO..2417 -1.000000 + y...2417 CO..2418 1.000000 + y...3417 COST.... 3397.590000 CD..0317 -.350000 + y...3417 SURD0317 12.670000 S13D..17 12.670000 + y...3417 S123D.17 12.670000 CFQ.3417 -7.440000 + y...3417 CFN.3417 -13.020000 CO..3417 -1.000000 + y...3417 CO..3418 1.000000 + y...1517 COST.... 81137.31000 CD..0117 -.260000 + y...1517 SURD0117 34.040000 S12D..17 34.040000 + y...1517 S13D..17 34.040000 S123D.17 34.040000 + y...1517 CFQ.1517 -4.900000 CFN.1517 -34.300000 + y...1517 CO..1517 -1.000000 CO..1518 1.000000 + y...3517 COST.... 3397.590000 CD..0317 -.350000 + y...3517 SURD0317 13.600000 S13D..17 13.600000 + y...3517 S123D.17 13.600000 CFQ.3517 -7.440000 + y...3517 CFN.3517 -13.950000 CO..3517 -1.000000 + y...3517 CO..3518 1.000000 + y...1617 COST.... 20026.02000 CD..0117 -4.000000 + y...1617 SURD0117 111.200000 S12D..17 111.200000 + y...1617 S13D..17 111.200000 S123D.17 111.200000 + y...1617 CFQ.1617 -62.400000 CFN.1617 -120.000000 + y...1617 CO..1617 -1.000000 CO..1618 1.000000 + y...1717 COST.... 20026.02000 CD..0117 -4.500000 + y...1717 SURD0117 114.684000 S12D..17 114.684000 + y...1717 S13D..17 114.684000 S123D.17 114.684000 + y...1717 CFQ.1717 -48.000000 CFN.1717 -124.800000 + y...1717 CO..1717 -1.000000 CO..1718 1.000000 + y...3118 COST.... 59292.65000 CD..0318 -.130000 + y...3118 SURD0318 10.650000 S13D..18 10.650000 + y...3118 S123D.18 10.650000 CFQ.3118 -1.960000 + y...3118 CFN.3118 -10.780000 CO..3118 -1.000000 + y...3118 CO..3119 1.000000 + y...2218 COST.... 59292.65000 CD..0218 -.130000 + y...2218 SURD0218 10.650000 S12D..18 10.650000 + y...2218 S123D.18 10.650000 CFQ.2218 -1.960000 + y...2218 CFN.2218 -10.780000 CO..2218 -1.000000 + y...2218 CO..2219 1.000000 + y...3218 COST.... 68654.65000 CD..0318 -.220000 + y...3218 SURD0318 22.320000 S13D..18 22.320000 + y...3218 S123D.18 22.320000 CFQ.3218 -2.940000 + y...3218 CFN.3218 -22.540000 CO..3218 -1.000000 + y...3218 CO..3219 1.000000 + y...1318 COST.... 59292.65000 CD..0118 -.130000 + y...1318 SURD0118 10.650000 S12D..18 10.650000 + y...1318 S13D..18 10.650000 S123D.18 10.650000 + y...1318 CFQ.1318 -1.960000 CFN.1318 -10.780000 + y...1318 CO..1318 -1.000000 CO..1319 1.000000 + y...2318 COST.... 81137.31000 CD..0218 -.260000 + y...2318 SURD0218 34.040000 S12D..18 34.040000 + y...2318 S123D.18 34.040000 CFQ.2318 -4.900000 + y...2318 CFN.2318 -34.300000 CO..2318 -1.000000 + y...2318 CO..2319 1.000000 + y...3318 COST.... 1974.890000 CD..0318 -.150000 + y...3318 SURD0318 6.975000 S13D..18 6.975000 + y...3318 S123D.18 6.975000 CFQ.3318 -3.800000 + y...3318 CFN.3318 -7.125000 CO..3318 -1.000000 + y...3318 CO..3319 1.000000 + y...1418 COST.... 68654.65000 CD..0118 -.220000 + y...1418 SURD0118 22.320000 S12D..18 22.320000 + y...1418 S13D..18 22.320000 S123D.18 22.320000 + y...1418 CFQ.1418 -2.940000 CFN.1418 -22.540000 + y...1418 CO..1418 -1.000000 CO..1419 1.000000 + y...2418 COST.... 3888.170000 CD..0218 -.350000 + y...2418 SURD0218 12.670000 S12D..18 12.670000 + y...2418 S123D.18 12.670000 CFQ.2418 -7.440000 + y...2418 CFN.2418 -13.020000 CO..2418 -1.000000 + y...2418 CO..2419 1.000000 + y...3418 COST.... 3397.590000 CD..0318 -.350000 + y...3418 SURD0318 12.670000 S13D..18 12.670000 + y...3418 S123D.18 12.670000 CFQ.3418 -7.440000 + y...3418 CFN.3418 -13.020000 CO..3418 -1.000000 + y...3418 CO..3419 1.000000 + y...1518 COST.... 81137.31000 CD..0118 -.260000 + y...1518 SURD0118 34.040000 S12D..18 34.040000 + y...1518 S13D..18 34.040000 S123D.18 34.040000 + y...1518 CFQ.1518 -4.900000 CFN.1518 -34.300000 + y...1518 CO..1518 -1.000000 CO..1519 1.000000 + y...3518 COST.... 3397.590000 CD..0318 -.350000 + y...3518 SURD0318 13.600000 S13D..18 13.600000 + y...3518 S123D.18 13.600000 CFQ.3518 -7.440000 + y...3518 CFN.3518 -13.950000 CO..3518 -1.000000 + y...3518 CO..3519 1.000000 + y...1618 COST.... 20026.02000 CD..0118 -4.000000 + y...1618 SURD0118 111.200000 S12D..18 111.200000 + y...1618 S13D..18 111.200000 S123D.18 111.200000 + y...1618 CFQ.1618 -62.400000 CFN.1618 -120.000000 + y...1618 CO..1618 -1.000000 CO..1619 1.000000 + y...1718 COST.... 20026.02000 CD..0118 -4.500000 + y...1718 SURD0118 114.684000 S12D..18 114.684000 + y...1718 S13D..18 114.684000 S123D.18 114.684000 + y...1718 CFQ.1718 -48.000000 CFN.1718 -124.800000 + y...1718 CO..1718 -1.000000 CO..1719 1.000000 + y...3119 COST.... 59292.65000 CD..0319 -.130000 + y...3119 SURD0319 10.650000 S13D..19 10.650000 + y...3119 S123D.19 10.650000 CFQ.3119 -1.960000 + y...3119 CFN.3119 -10.780000 CO..3119 -1.000000 + y...3119 CO..3120 1.000000 + y...2219 COST.... 59292.65000 CD..0219 -.130000 + y...2219 SURD0219 10.650000 S12D..19 10.650000 + y...2219 S123D.19 10.650000 CFQ.2219 -1.960000 + y...2219 CFN.2219 -10.780000 CO..2219 -1.000000 + y...2219 CO..2220 1.000000 + y...3219 COST.... 68654.65000 CD..0319 -.220000 + y...3219 SURD0319 22.320000 S13D..19 22.320000 + y...3219 S123D.19 22.320000 CFQ.3219 -2.940000 + y...3219 CFN.3219 -22.540000 CO..3219 -1.000000 + y...3219 CO..3220 1.000000 + y...1319 COST.... 59292.65000 CD..0119 -.130000 + y...1319 SURD0119 10.650000 S12D..19 10.650000 + y...1319 S13D..19 10.650000 S123D.19 10.650000 + y...1319 CFQ.1319 -1.960000 CFN.1319 -10.780000 + y...1319 CO..1319 -1.000000 CO..1320 1.000000 + y...2319 COST.... 81137.31000 CD..0219 -.260000 + y...2319 SURD0219 34.040000 S12D..19 34.040000 + y...2319 S123D.19 34.040000 CFQ.2319 -4.900000 + y...2319 CFN.2319 -34.300000 CO..2319 -1.000000 + y...2319 CO..2320 1.000000 + y...3319 COST.... 1974.890000 CD..0319 -.150000 + y...3319 SURD0319 6.975000 S13D..19 6.975000 + y...3319 S123D.19 6.975000 CFQ.3319 -3.800000 + y...3319 CFN.3319 -7.125000 CO..3319 -1.000000 + y...3319 CO..3320 1.000000 + y...1419 COST.... 68654.65000 CD..0119 -.220000 + y...1419 SURD0119 22.320000 S12D..19 22.320000 + y...1419 S13D..19 22.320000 S123D.19 22.320000 + y...1419 CFQ.1419 -2.940000 CFN.1419 -22.540000 + y...1419 CO..1419 -1.000000 CO..1420 1.000000 + y...2419 COST.... 3888.170000 CD..0219 -.350000 + y...2419 SURD0219 12.670000 S12D..19 12.670000 + y...2419 S123D.19 12.670000 CFQ.2419 -7.440000 + y...2419 CFN.2419 -13.020000 CO..2419 -1.000000 + y...2419 CO..2420 1.000000 + y...3419 COST.... 3397.590000 CD..0319 -.350000 + y...3419 SURD0319 12.670000 S13D..19 12.670000 + y...3419 S123D.19 12.670000 CFQ.3419 -7.440000 + y...3419 CFN.3419 -13.020000 CO..3419 -1.000000 + y...3419 CO..3420 1.000000 + y...1519 COST.... 81137.31000 CD..0119 -.260000 + y...1519 SURD0119 34.040000 S12D..19 34.040000 + y...1519 S13D..19 34.040000 S123D.19 34.040000 + y...1519 CFQ.1519 -4.900000 CFN.1519 -34.300000 + y...1519 CO..1519 -1.000000 CO..1520 1.000000 + y...3519 COST.... 3397.590000 CD..0319 -.350000 + y...3519 SURD0319 13.600000 S13D..19 13.600000 + y...3519 S123D.19 13.600000 CFQ.3519 -7.440000 + y...3519 CFN.3519 -13.950000 CO..3519 -1.000000 + y...3519 CO..3520 1.000000 + y...1619 COST.... 20026.02000 CD..0119 -4.000000 + y...1619 SURD0119 111.200000 S12D..19 111.200000 + y...1619 S13D..19 111.200000 S123D.19 111.200000 + y...1619 CFQ.1619 -62.400000 CFN.1619 -120.000000 + y...1619 CO..1619 -1.000000 CO..1620 1.000000 + y...1719 COST.... 20026.02000 CD..0119 -4.500000 + y...1719 SURD0119 114.684000 S12D..19 114.684000 + y...1719 S13D..19 114.684000 S123D.19 114.684000 + y...1719 CFQ.1719 -48.000000 CFN.1719 -124.800000 + y...1719 CO..1719 -1.000000 CO..1720 1.000000 + y...3120 COST.... 59292.65000 CD..0320 -.130000 + y...3120 SURD0320 10.650000 S13D..20 10.650000 + y...3120 S123D.20 10.650000 CFQ.3120 -1.960000 + y...3120 CFN.3120 -10.780000 CO..3120 -1.000000 + y...3120 CO..3121 1.000000 + y...2220 COST.... 59292.65000 CD..0220 -.130000 + y...2220 SURD0220 10.650000 S12D..20 10.650000 + y...2220 S123D.20 10.650000 CFQ.2220 -1.960000 + y...2220 CFN.2220 -10.780000 CO..2220 -1.000000 + y...2220 CO..2221 1.000000 + y...3220 COST.... 68654.65000 CD..0320 -.220000 + y...3220 SURD0320 22.320000 S13D..20 22.320000 + y...3220 S123D.20 22.320000 CFQ.3220 -2.940000 + y...3220 CFN.3220 -22.540000 CO..3220 -1.000000 + y...3220 CO..3221 1.000000 + y...1320 COST.... 59292.65000 CD..0120 -.130000 + y...1320 SURD0120 10.650000 S12D..20 10.650000 + y...1320 S13D..20 10.650000 S123D.20 10.650000 + y...1320 CFQ.1320 -1.960000 CFN.1320 -10.780000 + y...1320 CO..1320 -1.000000 CO..1321 1.000000 + y...2320 COST.... 81137.31000 CD..0220 -.260000 + y...2320 SURD0220 34.040000 S12D..20 34.040000 + y...2320 S123D.20 34.040000 CFQ.2320 -4.900000 + y...2320 CFN.2320 -34.300000 CO..2320 -1.000000 + y...2320 CO..2321 1.000000 + y...3320 COST.... 1974.890000 CD..0320 -.150000 + y...3320 SURD0320 6.975000 S13D..20 6.975000 + y...3320 S123D.20 6.975000 CFQ.3320 -3.800000 + y...3320 CFN.3320 -7.125000 CO..3320 -1.000000 + y...3320 CO..3321 1.000000 + y...1420 COST.... 68654.65000 CD..0120 -.220000 + y...1420 SURD0120 22.320000 S12D..20 22.320000 + y...1420 S13D..20 22.320000 S123D.20 22.320000 + y...1420 CFQ.1420 -2.940000 CFN.1420 -22.540000 + y...1420 CO..1420 -1.000000 CO..1421 1.000000 + y...2420 COST.... 3888.170000 CD..0220 -.350000 + y...2420 SURD0220 12.670000 S12D..20 12.670000 + y...2420 S123D.20 12.670000 CFQ.2420 -7.440000 + y...2420 CFN.2420 -13.020000 CO..2420 -1.000000 + y...2420 CO..2421 1.000000 + y...3420 COST.... 3397.590000 CD..0320 -.350000 + y...3420 SURD0320 12.670000 S13D..20 12.670000 + y...3420 S123D.20 12.670000 CFQ.3420 -7.440000 + y...3420 CFN.3420 -13.020000 CO..3420 -1.000000 + y...3420 CO..3421 1.000000 + y...1520 COST.... 81137.31000 CD..0120 -.260000 + y...1520 SURD0120 34.040000 S12D..20 34.040000 + y...1520 S13D..20 34.040000 S123D.20 34.040000 + y...1520 CFQ.1520 -4.900000 CFN.1520 -34.300000 + y...1520 CO..1520 -1.000000 CO..1521 1.000000 + y...3520 COST.... 3397.590000 CD..0320 -.350000 + y...3520 SURD0320 13.600000 S13D..20 13.600000 + y...3520 S123D.20 13.600000 CFQ.3520 -7.440000 + y...3520 CFN.3520 -13.950000 CO..3520 -1.000000 + y...3520 CO..3521 1.000000 + y...1620 COST.... 20026.02000 CD..0120 -4.000000 + y...1620 SURD0120 111.200000 S12D..20 111.200000 + y...1620 S13D..20 111.200000 S123D.20 111.200000 + y...1620 CFQ.1620 -62.400000 CFN.1620 -120.000000 + y...1620 CO..1620 -1.000000 CO..1621 1.000000 + y...1720 COST.... 20026.02000 CD..0120 -4.500000 + y...1720 SURD0120 114.684000 S12D..20 114.684000 + y...1720 S13D..20 114.684000 S123D.20 114.684000 + y...1720 CFQ.1720 -48.000000 CFN.1720 -124.800000 + y...1720 CO..1720 -1.000000 CO..1721 1.000000 + y...3121 COST.... 59292.65000 CD..0321 -.130000 + y...3121 SURD0321 10.650000 S13D..21 10.650000 + y...3121 S123D.21 10.650000 CFQ.3121 -1.960000 + y...3121 CFN.3121 -10.780000 CO..3121 -1.000000 + y...3121 CO..3122 1.000000 + y...2221 COST.... 59292.65000 CD..0221 -.130000 + y...2221 SURD0221 10.650000 S12D..21 10.650000 + y...2221 S123D.21 10.650000 CFQ.2221 -1.960000 + y...2221 CFN.2221 -10.780000 CO..2221 -1.000000 + y...2221 CO..2222 1.000000 + y...3221 COST.... 68654.65000 CD..0321 -.220000 + y...3221 SURD0321 22.320000 S13D..21 22.320000 + y...3221 S123D.21 22.320000 CFQ.3221 -2.940000 + y...3221 CFN.3221 -22.540000 CO..3221 -1.000000 + y...3221 CO..3222 1.000000 + y...1321 COST.... 59292.65000 CD..0121 -.130000 + y...1321 SURD0121 10.650000 S12D..21 10.650000 + y...1321 S13D..21 10.650000 S123D.21 10.650000 + y...1321 CFQ.1321 -1.960000 CFN.1321 -10.780000 + y...1321 CO..1321 -1.000000 CO..1322 1.000000 + y...2321 COST.... 81137.31000 CD..0221 -.260000 + y...2321 SURD0221 34.040000 S12D..21 34.040000 + y...2321 S123D.21 34.040000 CFQ.2321 -4.900000 + y...2321 CFN.2321 -34.300000 CO..2321 -1.000000 + y...2321 CO..2322 1.000000 + y...3321 COST.... 1974.890000 CD..0321 -.150000 + y...3321 SURD0321 6.975000 S13D..21 6.975000 + y...3321 S123D.21 6.975000 CFQ.3321 -3.800000 + y...3321 CFN.3321 -7.125000 CO..3321 -1.000000 + y...3321 CO..3322 1.000000 + y...1421 COST.... 68654.65000 CD..0121 -.220000 + y...1421 SURD0121 22.320000 S12D..21 22.320000 + y...1421 S13D..21 22.320000 S123D.21 22.320000 + y...1421 CFQ.1421 -2.940000 CFN.1421 -22.540000 + y...1421 CO..1421 -1.000000 CO..1422 1.000000 + y...2421 COST.... 3888.170000 CD..0221 -.350000 + y...2421 SURD0221 12.670000 S12D..21 12.670000 + y...2421 S123D.21 12.670000 CFQ.2421 -7.440000 + y...2421 CFN.2421 -13.020000 CO..2421 -1.000000 + y...2421 CO..2422 1.000000 + y...3421 COST.... 3397.590000 CD..0321 -.350000 + y...3421 SURD0321 12.670000 S13D..21 12.670000 + y...3421 S123D.21 12.670000 CFQ.3421 -7.440000 + y...3421 CFN.3421 -13.020000 CO..3421 -1.000000 + y...3421 CO..3422 1.000000 + y...1521 COST.... 81137.31000 CD..0121 -.260000 + y...1521 SURD0121 34.040000 S12D..21 34.040000 + y...1521 S13D..21 34.040000 S123D.21 34.040000 + y...1521 CFQ.1521 -4.900000 CFN.1521 -34.300000 + y...1521 CO..1521 -1.000000 CO..1522 1.000000 + y...3521 COST.... 3397.590000 CD..0321 -.350000 + y...3521 SURD0321 13.600000 S13D..21 13.600000 + y...3521 S123D.21 13.600000 CFQ.3521 -7.440000 + y...3521 CFN.3521 -13.950000 CO..3521 -1.000000 + y...3521 CO..3522 1.000000 + y...1621 COST.... 20026.02000 CD..0121 -4.000000 + y...1621 SURD0121 111.200000 S12D..21 111.200000 + y...1621 S13D..21 111.200000 S123D.21 111.200000 + y...1621 CFQ.1621 -62.400000 CFN.1621 -120.000000 + y...1621 CO..1621 -1.000000 CO..1622 1.000000 + y...1721 COST.... 20026.02000 CD..0121 -4.500000 + y...1721 SURD0121 114.684000 S12D..21 114.684000 + y...1721 S13D..21 114.684000 S123D.21 114.684000 + y...1721 CFQ.1721 -48.000000 CFN.1721 -124.800000 + y...1721 CO..1721 -1.000000 CO..1722 1.000000 + y...3122 COST.... 59292.65000 CD..0322 -.130000 + y...3122 SURD0322 10.650000 S13D..22 10.650000 + y...3122 S123D.22 10.650000 CFQ.3122 -1.960000 + y...3122 CFN.3122 -10.780000 CO..3122 -1.000000 + y...3122 CO..3123 1.000000 + y...2222 COST.... 59292.65000 CD..0222 -.130000 + y...2222 SURD0222 10.650000 S12D..22 10.650000 + y...2222 S123D.22 10.650000 CFQ.2222 -1.960000 + y...2222 CFN.2222 -10.780000 CO..2222 -1.000000 + y...2222 CO..2223 1.000000 + y...3222 COST.... 68654.65000 CD..0322 -.220000 + y...3222 SURD0322 22.320000 S13D..22 22.320000 + y...3222 S123D.22 22.320000 CFQ.3222 -2.940000 + y...3222 CFN.3222 -22.540000 CO..3222 -1.000000 + y...3222 CO..3223 1.000000 + y...1322 COST.... 59292.65000 CD..0122 -.130000 + y...1322 SURD0122 10.650000 S12D..22 10.650000 + y...1322 S13D..22 10.650000 S123D.22 10.650000 + y...1322 CFQ.1322 -1.960000 CFN.1322 -10.780000 + y...1322 CO..1322 -1.000000 CO..1323 1.000000 + y...2322 COST.... 81137.31000 CD..0222 -.260000 + y...2322 SURD0222 34.040000 S12D..22 34.040000 + y...2322 S123D.22 34.040000 CFQ.2322 -4.900000 + y...2322 CFN.2322 -34.300000 CO..2322 -1.000000 + y...2322 CO..2323 1.000000 + y...3322 COST.... 1974.890000 CD..0322 -.150000 + y...3322 SURD0322 6.975000 S13D..22 6.975000 + y...3322 S123D.22 6.975000 CFQ.3322 -3.800000 + y...3322 CFN.3322 -7.125000 CO..3322 -1.000000 + y...3322 CO..3323 1.000000 + y...1422 COST.... 68654.65000 CD..0122 -.220000 + y...1422 SURD0122 22.320000 S12D..22 22.320000 + y...1422 S13D..22 22.320000 S123D.22 22.320000 + y...1422 CFQ.1422 -2.940000 CFN.1422 -22.540000 + y...1422 CO..1422 -1.000000 CO..1423 1.000000 + y...2422 COST.... 3888.170000 CD..0222 -.350000 + y...2422 SURD0222 12.670000 S12D..22 12.670000 + y...2422 S123D.22 12.670000 CFQ.2422 -7.440000 + y...2422 CFN.2422 -13.020000 CO..2422 -1.000000 + y...2422 CO..2423 1.000000 + y...3422 COST.... 3397.590000 CD..0322 -.350000 + y...3422 SURD0322 12.670000 S13D..22 12.670000 + y...3422 S123D.22 12.670000 CFQ.3422 -7.440000 + y...3422 CFN.3422 -13.020000 CO..3422 -1.000000 + y...3422 CO..3423 1.000000 + y...1522 COST.... 81137.31000 CD..0122 -.260000 + y...1522 SURD0122 34.040000 S12D..22 34.040000 + y...1522 S13D..22 34.040000 S123D.22 34.040000 + y...1522 CFQ.1522 -4.900000 CFN.1522 -34.300000 + y...1522 CO..1522 -1.000000 CO..1523 1.000000 + y...3522 COST.... 3397.590000 CD..0322 -.350000 + y...3522 SURD0322 13.600000 S13D..22 13.600000 + y...3522 S123D.22 13.600000 CFQ.3522 -7.440000 + y...3522 CFN.3522 -13.950000 CO..3522 -1.000000 + y...3522 CO..3523 1.000000 + y...1622 COST.... 20026.02000 CD..0122 -4.000000 + y...1622 SURD0122 111.200000 S12D..22 111.200000 + y...1622 S13D..22 111.200000 S123D.22 111.200000 + y...1622 CFQ.1622 -62.400000 CFN.1622 -120.000000 + y...1622 CO..1622 -1.000000 CO..1623 1.000000 + y...1722 COST.... 20026.02000 CD..0122 -4.500000 + y...1722 SURD0122 114.684000 S12D..22 114.684000 + y...1722 S13D..22 114.684000 S123D.22 114.684000 + y...1722 CFQ.1722 -48.000000 CFN.1722 -124.800000 + y...1722 CO..1722 -1.000000 CO..1723 1.000000 + y...3123 COST.... 59292.65000 CD..0323 -.130000 + y...3123 SURD0323 10.650000 S13D..23 10.650000 + y...3123 S123D.23 10.650000 CFQ.3123 -1.960000 + y...3123 CFN.3123 -10.780000 CO..3123 -1.000000 + y...3123 CO..3124 1.000000 + y...2223 COST.... 59292.65000 CD..0223 -.130000 + y...2223 SURD0223 10.650000 S12D..23 10.650000 + y...2223 S123D.23 10.650000 CFQ.2223 -1.960000 + y...2223 CFN.2223 -10.780000 CO..2223 -1.000000 + y...2223 CO..2224 1.000000 + y...3223 COST.... 68654.65000 CD..0323 -.220000 + y...3223 SURD0323 22.320000 S13D..23 22.320000 + y...3223 S123D.23 22.320000 CFQ.3223 -2.940000 + y...3223 CFN.3223 -22.540000 CO..3223 -1.000000 + y...3223 CO..3224 1.000000 + y...1323 COST.... 59292.65000 CD..0123 -.130000 + y...1323 SURD0123 10.650000 S12D..23 10.650000 + y...1323 S13D..23 10.650000 S123D.23 10.650000 + y...1323 CFQ.1323 -1.960000 CFN.1323 -10.780000 + y...1323 CO..1323 -1.000000 CO..1324 1.000000 + y...2323 COST.... 81137.31000 CD..0223 -.260000 + y...2323 SURD0223 34.040000 S12D..23 34.040000 + y...2323 S123D.23 34.040000 CFQ.2323 -4.900000 + y...2323 CFN.2323 -34.300000 CO..2323 -1.000000 + y...2323 CO..2324 1.000000 + y...3323 COST.... 1974.890000 CD..0323 -.150000 + y...3323 SURD0323 6.975000 S13D..23 6.975000 + y...3323 S123D.23 6.975000 CFQ.3323 -3.800000 + y...3323 CFN.3323 -7.125000 CO..3323 -1.000000 + y...3323 CO..3324 1.000000 + y...1423 COST.... 68654.65000 CD..0123 -.220000 + y...1423 SURD0123 22.320000 S12D..23 22.320000 + y...1423 S13D..23 22.320000 S123D.23 22.320000 + y...1423 CFQ.1423 -2.940000 CFN.1423 -22.540000 + y...1423 CO..1423 -1.000000 CO..1424 1.000000 + y...2423 COST.... 3888.170000 CD..0223 -.350000 + y...2423 SURD0223 12.670000 S12D..23 12.670000 + y...2423 S123D.23 12.670000 CFQ.2423 -7.440000 + y...2423 CFN.2423 -13.020000 CO..2423 -1.000000 + y...2423 CO..2424 1.000000 + y...3423 COST.... 3397.590000 CD..0323 -.350000 + y...3423 SURD0323 12.670000 S13D..23 12.670000 + y...3423 S123D.23 12.670000 CFQ.3423 -7.440000 + y...3423 CFN.3423 -13.020000 CO..3423 -1.000000 + y...3423 CO..3424 1.000000 + y...1523 COST.... 81137.31000 CD..0123 -.260000 + y...1523 SURD0123 34.040000 S12D..23 34.040000 + y...1523 S13D..23 34.040000 S123D.23 34.040000 + y...1523 CFQ.1523 -4.900000 CFN.1523 -34.300000 + y...1523 CO..1523 -1.000000 CO..1524 1.000000 + y...3523 COST.... 3397.590000 CD..0323 -.350000 + y...3523 SURD0323 13.600000 S13D..23 13.600000 + y...3523 S123D.23 13.600000 CFQ.3523 -7.440000 + y...3523 CFN.3523 -13.950000 CO..3523 -1.000000 + y...3523 CO..3524 1.000000 + y...1623 COST.... 20026.02000 CD..0123 -4.000000 + y...1623 SURD0123 111.200000 S12D..23 111.200000 + y...1623 S13D..23 111.200000 S123D.23 111.200000 + y...1623 CFQ.1623 -62.400000 CFN.1623 -120.000000 + y...1623 CO..1623 -1.000000 CO..1624 1.000000 + y...1723 COST.... 20026.02000 CD..0123 -4.500000 + y...1723 SURD0123 114.684000 S12D..23 114.684000 + y...1723 S13D..23 114.684000 S123D.23 114.684000 + y...1723 CFQ.1723 -48.000000 CFN.1723 -124.800000 + y...1723 CO..1723 -1.000000 CO..1724 1.000000 + y...3124 COST.... 59292.65000 CD..0324 -.130000 + y...3124 SURD0324 10.650000 S13D..24 10.650000 + y...3124 S123D.24 10.650000 CFQ.3124 -1.960000 + y...3124 CFN.3124 -10.780000 CO..3124 -1.000000 + y...3124 CO..3101 1.000000 + y...2224 COST.... 59292.65000 CD..0224 -.130000 + y...2224 SURD0224 10.650000 S12D..24 10.650000 + y...2224 S123D.24 10.650000 CFQ.2224 -1.960000 + y...2224 CFN.2224 -10.780000 CO..2224 -1.000000 + y...2224 CO..2201 1.000000 + y...3224 COST.... 68654.65000 CD..0324 -.220000 + y...3224 SURD0324 22.320000 S13D..24 22.320000 + y...3224 S123D.24 22.320000 CFQ.3224 -2.940000 + y...3224 CFN.3224 -22.540000 CO..3224 -1.000000 + y...3224 CO..3201 1.000000 + y...1324 COST.... 59292.65000 CD..0124 -.130000 + y...1324 SURD0124 10.650000 S12D..24 10.650000 + y...1324 S13D..24 10.650000 S123D.24 10.650000 + y...1324 CFQ.1324 -1.960000 CFN.1324 -10.780000 + y...1324 CO..1324 -1.000000 CO..1301 1.000000 + y...2324 COST.... 81137.31000 CD..0224 -.260000 + y...2324 SURD0224 34.040000 S12D..24 34.040000 + y...2324 S123D.24 34.040000 CFQ.2324 -4.900000 + y...2324 CFN.2324 -34.300000 CO..2324 -1.000000 + y...2324 CO..2301 1.000000 + y...3324 COST.... 1974.890000 CD..0324 -.150000 + y...3324 SURD0324 6.975000 S13D..24 6.975000 + y...3324 S123D.24 6.975000 CFQ.3324 -3.800000 + y...3324 CFN.3324 -7.125000 CO..3324 -1.000000 + y...3324 CO..3301 1.000000 + y...1424 COST.... 68654.65000 CD..0124 -.220000 + y...1424 SURD0124 22.320000 S12D..24 22.320000 + y...1424 S13D..24 22.320000 S123D.24 22.320000 + y...1424 CFQ.1424 -2.940000 CFN.1424 -22.540000 + y...1424 CO..1424 -1.000000 CO..1401 1.000000 + y...2424 COST.... 3888.170000 CD..0224 -.350000 + y...2424 SURD0224 12.670000 S12D..24 12.670000 + y...2424 S123D.24 12.670000 CFQ.2424 -7.440000 + y...2424 CFN.2424 -13.020000 CO..2424 -1.000000 + y...2424 CO..2401 1.000000 + y...3424 COST.... 3397.590000 CD..0324 -.350000 + y...3424 SURD0324 12.670000 S13D..24 12.670000 + y...3424 S123D.24 12.670000 CFQ.3424 -7.440000 + y...3424 CFN.3424 -13.020000 CO..3424 -1.000000 + y...3424 CO..3401 1.000000 + y...1524 COST.... 81137.31000 CD..0124 -.260000 + y...1524 SURD0124 34.040000 S12D..24 34.040000 + y...1524 S13D..24 34.040000 S123D.24 34.040000 + y...1524 CFQ.1524 -4.900000 CFN.1524 -34.300000 + y...1524 CO..1524 -1.000000 CO..1501 1.000000 + y...3524 COST.... 3397.590000 CD..0324 -.350000 + y...3524 SURD0324 13.600000 S13D..24 13.600000 + y...3524 S123D.24 13.600000 CFQ.3524 -7.440000 + y...3524 CFN.3524 -13.950000 CO..3524 -1.000000 + y...3524 CO..3501 1.000000 + y...1624 COST.... 20026.02000 CD..0124 -4.000000 + y...1624 SURD0124 111.200000 S12D..24 111.200000 + y...1624 S13D..24 111.200000 S123D.24 111.200000 + y...1624 CFQ.1624 -62.400000 CFN.1624 -120.000000 + y...1624 CO..1624 -1.000000 CO..1601 1.000000 + y...1724 COST.... 20026.02000 CD..0124 -4.500000 + y...1724 SURD0124 114.684000 S12D..24 114.684000 + y...1724 S13D..24 114.684000 S123D.24 114.684000 + y...1724 CFQ.1724 -48.000000 CFN.1724 -124.800000 + y...1724 CO..1724 -1.000000 CO..1701 1.000000 + z...3101 COST.... 6553.400000 CO..3101 1.000000 + z...2201 COST.... 6553.400000 CO..2201 1.000000 + z...3201 COST.... 7801.700000 CO..3201 1.000000 + z...1301 COST.... 6553.400000 CO..1301 1.000000 + z...2301 COST.... 9362.000000 CO..2301 1.000000 + z...3301 COST.... 8609.500000 CO..3301 1.000000 + z...1401 COST.... 7801.700000 CO..1401 1.000000 + z...2401 COST.... 9651.300000 CO..2401 1.000000 + z...3401 COST.... 9417.300000 CO..3401 1.000000 + z...1501 COST.... 9362.000000 CO..1501 1.000000 + z...3501 COST.... 9417.300000 CO..3501 1.000000 + z...1601 COST.... 1548886.600 CO..1601 1.000000 + z...1701 COST.... 1548886.600 CO..1701 1.000000 + z...3102 COST.... 6553.400000 CO..3102 1.000000 + z...2202 COST.... 6553.400000 CO..2202 1.000000 + z...3202 COST.... 7801.700000 CO..3202 1.000000 + z...1302 COST.... 6553.400000 CO..1302 1.000000 + z...2302 COST.... 9362.000000 CO..2302 1.000000 + z...3302 COST.... 8609.500000 CO..3302 1.000000 + z...1402 COST.... 7801.700000 CO..1402 1.000000 + z...2402 COST.... 9651.300000 CO..2402 1.000000 + z...3402 COST.... 9417.300000 CO..3402 1.000000 + z...1502 COST.... 9362.000000 CO..1502 1.000000 + z...3502 COST.... 9417.300000 CO..3502 1.000000 + z...1602 COST.... 1548886.600 CO..1602 1.000000 + z...1702 COST.... 1548886.600 CO..1702 1.000000 + z...3103 COST.... 6553.400000 CO..3103 1.000000 + z...2203 COST.... 6553.400000 CO..2203 1.000000 + z...3203 COST.... 7801.700000 CO..3203 1.000000 + z...1303 COST.... 6553.400000 CO..1303 1.000000 + z...2303 COST.... 9362.000000 CO..2303 1.000000 + z...3303 COST.... 8609.500000 CO..3303 1.000000 + z...1403 COST.... 7801.700000 CO..1403 1.000000 + z...2403 COST.... 9651.300000 CO..2403 1.000000 + z...3403 COST.... 9417.300000 CO..3403 1.000000 + z...1503 COST.... 9362.000000 CO..1503 1.000000 + z...3503 COST.... 9417.300000 CO..3503 1.000000 + z...1603 COST.... 1548886.600 CO..1603 1.000000 + z...1703 COST.... 1548886.600 CO..1703 1.000000 + z...3104 COST.... 6553.400000 CO..3104 1.000000 + z...2204 COST.... 6553.400000 CO..2204 1.000000 + z...3204 COST.... 7801.700000 CO..3204 1.000000 + z...1304 COST.... 6553.400000 CO..1304 1.000000 + z...2304 COST.... 9362.000000 CO..2304 1.000000 + z...3304 COST.... 8609.500000 CO..3304 1.000000 + z...1404 COST.... 7801.700000 CO..1404 1.000000 + z...2404 COST.... 9651.300000 CO..2404 1.000000 + z...3404 COST.... 9417.300000 CO..3404 1.000000 + z...1504 COST.... 9362.000000 CO..1504 1.000000 + z...3504 COST.... 9417.300000 CO..3504 1.000000 + z...1604 COST.... 1548886.600 CO..1604 1.000000 + z...1704 COST.... 1548886.600 CO..1704 1.000000 + z...3105 COST.... 6553.400000 CO..3105 1.000000 + z...2205 COST.... 6553.400000 CO..2205 1.000000 + z...3205 COST.... 7801.700000 CO..3205 1.000000 + z...1305 COST.... 6553.400000 CO..1305 1.000000 + z...2305 COST.... 9362.000000 CO..2305 1.000000 + z...3305 COST.... 8609.500000 CO..3305 1.000000 + z...1405 COST.... 7801.700000 CO..1405 1.000000 + z...2405 COST.... 9651.300000 CO..2405 1.000000 + z...3405 COST.... 9417.300000 CO..3405 1.000000 + z...1505 COST.... 9362.000000 CO..1505 1.000000 + z...3505 COST.... 9417.300000 CO..3505 1.000000 + z...1605 COST.... 1548886.600 CO..1605 1.000000 + z...1705 COST.... 1548886.600 CO..1705 1.000000 + z...3106 COST.... 6553.400000 CO..3106 1.000000 + z...2206 COST.... 6553.400000 CO..2206 1.000000 + z...3206 COST.... 7801.700000 CO..3206 1.000000 + z...1306 COST.... 6553.400000 CO..1306 1.000000 + z...2306 COST.... 9362.000000 CO..2306 1.000000 + z...3306 COST.... 8609.500000 CO..3306 1.000000 + z...1406 COST.... 7801.700000 CO..1406 1.000000 + z...2406 COST.... 9651.300000 CO..2406 1.000000 + z...3406 COST.... 9417.300000 CO..3406 1.000000 + z...1506 COST.... 9362.000000 CO..1506 1.000000 + z...3506 COST.... 9417.300000 CO..3506 1.000000 + z...1606 COST.... 1548886.600 CO..1606 1.000000 + z...1706 COST.... 1548886.600 CO..1706 1.000000 + z...3107 COST.... 6553.400000 CO..3107 1.000000 + z...2207 COST.... 6553.400000 CO..2207 1.000000 + z...3207 COST.... 7801.700000 CO..3207 1.000000 + z...1307 COST.... 6553.400000 CO..1307 1.000000 + z...2307 COST.... 9362.000000 CO..2307 1.000000 + z...3307 COST.... 8609.500000 CO..3307 1.000000 + z...1407 COST.... 7801.700000 CO..1407 1.000000 + z...2407 COST.... 9651.300000 CO..2407 1.000000 + z...3407 COST.... 9417.300000 CO..3407 1.000000 + z...1507 COST.... 9362.000000 CO..1507 1.000000 + z...3507 COST.... 9417.300000 CO..3507 1.000000 + z...1607 COST.... 1548886.600 CO..1607 1.000000 + z...1707 COST.... 1548886.600 CO..1707 1.000000 + z...3108 COST.... 6553.400000 CO..3108 1.000000 + z...2208 COST.... 6553.400000 CO..2208 1.000000 + z...3208 COST.... 7801.700000 CO..3208 1.000000 + z...1308 COST.... 6553.400000 CO..1308 1.000000 + z...2308 COST.... 9362.000000 CO..2308 1.000000 + z...3308 COST.... 8609.500000 CO..3308 1.000000 + z...1408 COST.... 7801.700000 CO..1408 1.000000 + z...2408 COST.... 9651.300000 CO..2408 1.000000 + z...3408 COST.... 9417.300000 CO..3408 1.000000 + z...1508 COST.... 9362.000000 CO..1508 1.000000 + z...3508 COST.... 9417.300000 CO..3508 1.000000 + z...1608 COST.... 1548886.600 CO..1608 1.000000 + z...1708 COST.... 1548886.600 CO..1708 1.000000 + z...3109 COST.... 6553.400000 CO..3109 1.000000 + z...2209 COST.... 6553.400000 CO..2209 1.000000 + z...3209 COST.... 7801.700000 CO..3209 1.000000 + z...1309 COST.... 6553.400000 CO..1309 1.000000 + z...2309 COST.... 9362.000000 CO..2309 1.000000 + z...3309 COST.... 8609.500000 CO..3309 1.000000 + z...1409 COST.... 7801.700000 CO..1409 1.000000 + z...2409 COST.... 9651.300000 CO..2409 1.000000 + z...3409 COST.... 9417.300000 CO..3409 1.000000 + z...1509 COST.... 9362.000000 CO..1509 1.000000 + z...3509 COST.... 9417.300000 CO..3509 1.000000 + z...1609 COST.... 1548886.600 CO..1609 1.000000 + z...1709 COST.... 1548886.600 CO..1709 1.000000 + z...3110 COST.... 6553.400000 CO..3110 1.000000 + z...2210 COST.... 6553.400000 CO..2210 1.000000 + z...3210 COST.... 7801.700000 CO..3210 1.000000 + z...1310 COST.... 6553.400000 CO..1310 1.000000 + z...2310 COST.... 9362.000000 CO..2310 1.000000 + z...3310 COST.... 8609.500000 CO..3310 1.000000 + z...1410 COST.... 7801.700000 CO..1410 1.000000 + z...2410 COST.... 9651.300000 CO..2410 1.000000 + z...3410 COST.... 9417.300000 CO..3410 1.000000 + z...1510 COST.... 9362.000000 CO..1510 1.000000 + z...3510 COST.... 9417.300000 CO..3510 1.000000 + z...1610 COST.... 1548886.600 CO..1610 1.000000 + z...1710 COST.... 1548886.600 CO..1710 1.000000 + z...3111 COST.... 6553.400000 CO..3111 1.000000 + z...2211 COST.... 6553.400000 CO..2211 1.000000 + z...3211 COST.... 7801.700000 CO..3211 1.000000 + z...1311 COST.... 6553.400000 CO..1311 1.000000 + z...2311 COST.... 9362.000000 CO..2311 1.000000 + z...3311 COST.... 8609.500000 CO..3311 1.000000 + z...1411 COST.... 7801.700000 CO..1411 1.000000 + z...2411 COST.... 9651.300000 CO..2411 1.000000 + z...3411 COST.... 9417.300000 CO..3411 1.000000 + z...1511 COST.... 9362.000000 CO..1511 1.000000 + z...3511 COST.... 9417.300000 CO..3511 1.000000 + z...1611 COST.... 1548886.600 CO..1611 1.000000 + z...1711 COST.... 1548886.600 CO..1711 1.000000 + z...3112 COST.... 6553.400000 CO..3112 1.000000 + z...2212 COST.... 6553.400000 CO..2212 1.000000 + z...3212 COST.... 7801.700000 CO..3212 1.000000 + z...1312 COST.... 6553.400000 CO..1312 1.000000 + z...2312 COST.... 9362.000000 CO..2312 1.000000 + z...3312 COST.... 8609.500000 CO..3312 1.000000 + z...1412 COST.... 7801.700000 CO..1412 1.000000 + z...2412 COST.... 9651.300000 CO..2412 1.000000 + z...3412 COST.... 9417.300000 CO..3412 1.000000 + z...1512 COST.... 9362.000000 CO..1512 1.000000 + z...3512 COST.... 9417.300000 CO..3512 1.000000 + z...1612 COST.... 1548886.600 CO..1612 1.000000 + z...1712 COST.... 1548886.600 CO..1712 1.000000 + z...3113 COST.... 6553.400000 CO..3113 1.000000 + z...2213 COST.... 6553.400000 CO..2213 1.000000 + z...3213 COST.... 7801.700000 CO..3213 1.000000 + z...1313 COST.... 6553.400000 CO..1313 1.000000 + z...2313 COST.... 9362.000000 CO..2313 1.000000 + z...3313 COST.... 8609.500000 CO..3313 1.000000 + z...1413 COST.... 7801.700000 CO..1413 1.000000 + z...2413 COST.... 9651.300000 CO..2413 1.000000 + z...3413 COST.... 9417.300000 CO..3413 1.000000 + z...1513 COST.... 9362.000000 CO..1513 1.000000 + z...3513 COST.... 9417.300000 CO..3513 1.000000 + z...1613 COST.... 1548886.600 CO..1613 1.000000 + z...1713 COST.... 1548886.600 CO..1713 1.000000 + z...3114 COST.... 6553.400000 CO..3114 1.000000 + z...2214 COST.... 6553.400000 CO..2214 1.000000 + z...3214 COST.... 7801.700000 CO..3214 1.000000 + z...1314 COST.... 6553.400000 CO..1314 1.000000 + z...2314 COST.... 9362.000000 CO..2314 1.000000 + z...3314 COST.... 8609.500000 CO..3314 1.000000 + z...1414 COST.... 7801.700000 CO..1414 1.000000 + z...2414 COST.... 9651.300000 CO..2414 1.000000 + z...3414 COST.... 9417.300000 CO..3414 1.000000 + z...1514 COST.... 9362.000000 CO..1514 1.000000 + z...3514 COST.... 9417.300000 CO..3514 1.000000 + z...1614 COST.... 1548886.600 CO..1614 1.000000 + z...1714 COST.... 1548886.600 CO..1714 1.000000 + z...3115 COST.... 6553.400000 CO..3115 1.000000 + z...2215 COST.... 6553.400000 CO..2215 1.000000 + z...3215 COST.... 7801.700000 CO..3215 1.000000 + z...1315 COST.... 6553.400000 CO..1315 1.000000 + z...2315 COST.... 9362.000000 CO..2315 1.000000 + z...3315 COST.... 8609.500000 CO..3315 1.000000 + z...1415 COST.... 7801.700000 CO..1415 1.000000 + z...2415 COST.... 9651.300000 CO..2415 1.000000 + z...3415 COST.... 9417.300000 CO..3415 1.000000 + z...1515 COST.... 9362.000000 CO..1515 1.000000 + z...3515 COST.... 9417.300000 CO..3515 1.000000 + z...1615 COST.... 1548886.600 CO..1615 1.000000 + z...1715 COST.... 1548886.600 CO..1715 1.000000 + z...3116 COST.... 6553.400000 CO..3116 1.000000 + z...2216 COST.... 6553.400000 CO..2216 1.000000 + z...3216 COST.... 7801.700000 CO..3216 1.000000 + z...1316 COST.... 6553.400000 CO..1316 1.000000 + z...2316 COST.... 9362.000000 CO..2316 1.000000 + z...3316 COST.... 8609.500000 CO..3316 1.000000 + z...1416 COST.... 7801.700000 CO..1416 1.000000 + z...2416 COST.... 9651.300000 CO..2416 1.000000 + z...3416 COST.... 9417.300000 CO..3416 1.000000 + z...1516 COST.... 9362.000000 CO..1516 1.000000 + z...3516 COST.... 9417.300000 CO..3516 1.000000 + z...1616 COST.... 1548886.600 CO..1616 1.000000 + z...1716 COST.... 1548886.600 CO..1716 1.000000 + z...3117 COST.... 6553.400000 CO..3117 1.000000 + z...2217 COST.... 6553.400000 CO..2217 1.000000 + z...3217 COST.... 7801.700000 CO..3217 1.000000 + z...1317 COST.... 6553.400000 CO..1317 1.000000 + z...2317 COST.... 9362.000000 CO..2317 1.000000 + z...3317 COST.... 8609.500000 CO..3317 1.000000 + z...1417 COST.... 7801.700000 CO..1417 1.000000 + z...2417 COST.... 9651.300000 CO..2417 1.000000 + z...3417 COST.... 9417.300000 CO..3417 1.000000 + z...1517 COST.... 9362.000000 CO..1517 1.000000 + z...3517 COST.... 9417.300000 CO..3517 1.000000 + z...1617 COST.... 1548886.600 CO..1617 1.000000 + z...1717 COST.... 1548886.600 CO..1717 1.000000 + z...3118 COST.... 6553.400000 CO..3118 1.000000 + z...2218 COST.... 6553.400000 CO..2218 1.000000 + z...3218 COST.... 7801.700000 CO..3218 1.000000 + z...1318 COST.... 6553.400000 CO..1318 1.000000 + z...2318 COST.... 9362.000000 CO..2318 1.000000 + z...3318 COST.... 8609.500000 CO..3318 1.000000 + z...1418 COST.... 7801.700000 CO..1418 1.000000 + z...2418 COST.... 9651.300000 CO..2418 1.000000 + z...3418 COST.... 9417.300000 CO..3418 1.000000 + z...1518 COST.... 9362.000000 CO..1518 1.000000 + z...3518 COST.... 9417.300000 CO..3518 1.000000 + z...1618 COST.... 1548886.600 CO..1618 1.000000 + z...1718 COST.... 1548886.600 CO..1718 1.000000 + z...3119 COST.... 6553.400000 CO..3119 1.000000 + z...2219 COST.... 6553.400000 CO..2219 1.000000 + z...3219 COST.... 7801.700000 CO..3219 1.000000 + z...1319 COST.... 6553.400000 CO..1319 1.000000 + z...2319 COST.... 9362.000000 CO..2319 1.000000 + z...3319 COST.... 8609.500000 CO..3319 1.000000 + z...1419 COST.... 7801.700000 CO..1419 1.000000 + z...2419 COST.... 9651.300000 CO..2419 1.000000 + z...3419 COST.... 9417.300000 CO..3419 1.000000 + z...1519 COST.... 9362.000000 CO..1519 1.000000 + z...3519 COST.... 9417.300000 CO..3519 1.000000 + z...1619 COST.... 1548886.600 CO..1619 1.000000 + z...1719 COST.... 1548886.600 CO..1719 1.000000 + z...3120 COST.... 6553.400000 CO..3120 1.000000 + z...2220 COST.... 6553.400000 CO..2220 1.000000 + z...3220 COST.... 7801.700000 CO..3220 1.000000 + z...1320 COST.... 6553.400000 CO..1320 1.000000 + z...2320 COST.... 9362.000000 CO..2320 1.000000 + z...3320 COST.... 8609.500000 CO..3320 1.000000 + z...1420 COST.... 7801.700000 CO..1420 1.000000 + z...2420 COST.... 9651.300000 CO..2420 1.000000 + z...3420 COST.... 9417.300000 CO..3420 1.000000 + z...1520 COST.... 9362.000000 CO..1520 1.000000 + z...3520 COST.... 9417.300000 CO..3520 1.000000 + z...1620 COST.... 1548886.600 CO..1620 1.000000 + z...1720 COST.... 1548886.600 CO..1720 1.000000 + z...3121 COST.... 6553.400000 CO..3121 1.000000 + z...2221 COST.... 6553.400000 CO..2221 1.000000 + z...3221 COST.... 7801.700000 CO..3221 1.000000 + z...1321 COST.... 6553.400000 CO..1321 1.000000 + z...2321 COST.... 9362.000000 CO..2321 1.000000 + z...3321 COST.... 8609.500000 CO..3321 1.000000 + z...1421 COST.... 7801.700000 CO..1421 1.000000 + z...2421 COST.... 9651.300000 CO..2421 1.000000 + z...3421 COST.... 9417.300000 CO..3421 1.000000 + z...1521 COST.... 9362.000000 CO..1521 1.000000 + z...3521 COST.... 9417.300000 CO..3521 1.000000 + z...1621 COST.... 1548886.600 CO..1621 1.000000 + z...1721 COST.... 1548886.600 CO..1721 1.000000 + z...3122 COST.... 6553.400000 CO..3122 1.000000 + z...2222 COST.... 6553.400000 CO..2222 1.000000 + z...3222 COST.... 7801.700000 CO..3222 1.000000 + z...1322 COST.... 6553.400000 CO..1322 1.000000 + z...2322 COST.... 9362.000000 CO..2322 1.000000 + z...3322 COST.... 8609.500000 CO..3322 1.000000 + z...1422 COST.... 7801.700000 CO..1422 1.000000 + z...2422 COST.... 9651.300000 CO..2422 1.000000 + z...3422 COST.... 9417.300000 CO..3422 1.000000 + z...1522 COST.... 9362.000000 CO..1522 1.000000 + z...3522 COST.... 9417.300000 CO..3522 1.000000 + z...1622 COST.... 1548886.600 CO..1622 1.000000 + z...1722 COST.... 1548886.600 CO..1722 1.000000 + z...3123 COST.... 6553.400000 CO..3123 1.000000 + z...2223 COST.... 6553.400000 CO..2223 1.000000 + z...3223 COST.... 7801.700000 CO..3223 1.000000 + z...1323 COST.... 6553.400000 CO..1323 1.000000 + z...2323 COST.... 9362.000000 CO..2323 1.000000 + z...3323 COST.... 8609.500000 CO..3323 1.000000 + z...1423 COST.... 7801.700000 CO..1423 1.000000 + z...2423 COST.... 9651.300000 CO..2423 1.000000 + z...3423 COST.... 9417.300000 CO..3423 1.000000 + z...1523 COST.... 9362.000000 CO..1523 1.000000 + z...3523 COST.... 9417.300000 CO..3523 1.000000 + z...1623 COST.... 1548886.600 CO..1623 1.000000 + z...1723 COST.... 1548886.600 CO..1723 1.000000 + z...3124 COST.... 6553.400000 CO..3124 1.000000 + z...2224 COST.... 6553.400000 CO..2224 1.000000 + z...3224 COST.... 7801.700000 CO..3224 1.000000 + z...1324 COST.... 6553.400000 CO..1324 1.000000 + z...2324 COST.... 9362.000000 CO..2324 1.000000 + z...3324 COST.... 8609.500000 CO..3324 1.000000 + z...1424 COST.... 7801.700000 CO..1424 1.000000 + z...2424 COST.... 9651.300000 CO..2424 1.000000 + z...3424 COST.... 9417.300000 CO..3424 1.000000 + z...1524 COST.... 9362.000000 CO..1524 1.000000 + z...3524 COST.... 9417.300000 CO..3524 1.000000 + z...1624 COST.... 1548886.600 CO..1624 1.000000 + z...1724 COST.... 1548886.600 CO..1724 1.000000 + vn.31101 CD..0101 .963925 SU..3101 -1.000000 + vn.31101 LC.31101 1.000000 + vn.13101 CD..0301 .963925 SU..1301 -1.000000 + vn.13101 LC.13101 1.000000 + vn.31201 CD..0101 .898705 SU..3101 -1.000000 + vn.31201 LC.31201 1.000000 + vn.13201 CD..0301 .898705 SU..1301 -1.000000 + vn.13201 LC.13201 1.000000 + vn.31102 CD..0102 .963925 SU..3102 -1.000000 + vn.31102 LC.31102 1.000000 + vn.13102 CD..0302 .963925 SU..1302 -1.000000 + vn.13102 LC.13102 1.000000 + vn.31202 CD..0102 .898705 SU..3102 -1.000000 + vn.31202 LC.31202 1.000000 + vn.13202 CD..0302 .898705 SU..1302 -1.000000 + vn.13202 LC.13202 1.000000 + vn.31103 CD..0103 .963925 SU..3103 -1.000000 + vn.31103 LC.31103 1.000000 + vn.13103 CD..0303 .963925 SU..1303 -1.000000 + vn.13103 LC.13103 1.000000 + vn.31203 CD..0103 .898705 SU..3103 -1.000000 + vn.31203 LC.31203 1.000000 + vn.13203 CD..0303 .898705 SU..1303 -1.000000 + vn.13203 LC.13203 1.000000 + vn.31104 CD..0104 .963925 SU..3104 -1.000000 + vn.31104 LC.31104 1.000000 + vn.13104 CD..0304 .963925 SU..1304 -1.000000 + vn.13104 LC.13104 1.000000 + vn.31204 CD..0104 .898705 SU..3104 -1.000000 + vn.31204 LC.31204 1.000000 + vn.13204 CD..0304 .898705 SU..1304 -1.000000 + vn.13204 LC.13204 1.000000 + vn.31105 CD..0105 .963925 SU..3105 -1.000000 + vn.31105 LC.31105 1.000000 + vn.13105 CD..0305 .963925 SU..1305 -1.000000 + vn.13105 LC.13105 1.000000 + vn.31205 CD..0105 .898705 SU..3105 -1.000000 + vn.31205 LC.31205 1.000000 + vn.13205 CD..0305 .898705 SU..1305 -1.000000 + vn.13205 LC.13205 1.000000 + vn.31106 CD..0106 .963925 SU..3106 -1.000000 + vn.31106 LC.31106 1.000000 + vn.13106 CD..0306 .963925 SU..1306 -1.000000 + vn.13106 LC.13106 1.000000 + vn.31206 CD..0106 .898705 SU..3106 -1.000000 + vn.31206 LC.31206 1.000000 + vn.13206 CD..0306 .898705 SU..1306 -1.000000 + vn.13206 LC.13206 1.000000 + vn.31107 CD..0107 .963925 SU..3107 -1.000000 + vn.31107 LC.31107 1.000000 + vn.13107 CD..0307 .963925 SU..1307 -1.000000 + vn.13107 LC.13107 1.000000 + vn.31207 CD..0107 .898705 SU..3107 -1.000000 + vn.31207 LC.31207 1.000000 + vn.13207 CD..0307 .898705 SU..1307 -1.000000 + vn.13207 LC.13207 1.000000 + vn.31108 CD..0108 .963925 SU..3108 -1.000000 + vn.31108 LC.31108 1.000000 + vn.13108 CD..0308 .963925 SU..1308 -1.000000 + vn.13108 LC.13108 1.000000 + vn.31208 CD..0108 .898705 SU..3108 -1.000000 + vn.31208 LC.31208 1.000000 + vn.13208 CD..0308 .898705 SU..1308 -1.000000 + vn.13208 LC.13208 1.000000 + vn.31109 CD..0109 .963925 SU..3109 -1.000000 + vn.31109 LC.31109 1.000000 + vn.13109 CD..0309 .963925 SU..1309 -1.000000 + vn.13109 LC.13109 1.000000 + vn.31209 CD..0109 .898705 SU..3109 -1.000000 + vn.31209 LC.31209 1.000000 + vn.13209 CD..0309 .898705 SU..1309 -1.000000 + vn.13209 LC.13209 1.000000 + vn.31110 CD..0110 .963925 SU..3110 -1.000000 + vn.31110 LC.31110 1.000000 + vn.13110 CD..0310 .963925 SU..1310 -1.000000 + vn.13110 LC.13110 1.000000 + vn.31210 CD..0110 .898705 SU..3110 -1.000000 + vn.31210 LC.31210 1.000000 + vn.13210 CD..0310 .898705 SU..1310 -1.000000 + vn.13210 LC.13210 1.000000 + vn.31111 CD..0111 .963925 SU..3111 -1.000000 + vn.31111 LC.31111 1.000000 + vn.13111 CD..0311 .963925 SU..1311 -1.000000 + vn.13111 LC.13111 1.000000 + vn.31211 CD..0111 .898705 SU..3111 -1.000000 + vn.31211 LC.31211 1.000000 + vn.13211 CD..0311 .898705 SU..1311 -1.000000 + vn.13211 LC.13211 1.000000 + vn.31112 CD..0112 .963925 SU..3112 -1.000000 + vn.31112 LC.31112 1.000000 + vn.13112 CD..0312 .963925 SU..1312 -1.000000 + vn.13112 LC.13112 1.000000 + vn.31212 CD..0112 .898705 SU..3112 -1.000000 + vn.31212 LC.31212 1.000000 + vn.13212 CD..0312 .898705 SU..1312 -1.000000 + vn.13212 LC.13212 1.000000 + vn.31113 CD..0113 .963925 SU..3113 -1.000000 + vn.31113 LC.31113 1.000000 + vn.13113 CD..0313 .963925 SU..1313 -1.000000 + vn.13113 LC.13113 1.000000 + vn.31213 CD..0113 .898705 SU..3113 -1.000000 + vn.31213 LC.31213 1.000000 + vn.13213 CD..0313 .898705 SU..1313 -1.000000 + vn.13213 LC.13213 1.000000 + vn.31114 CD..0114 .963925 SU..3114 -1.000000 + vn.31114 LC.31114 1.000000 + vn.13114 CD..0314 .963925 SU..1314 -1.000000 + vn.13114 LC.13114 1.000000 + vn.31214 CD..0114 .898705 SU..3114 -1.000000 + vn.31214 LC.31214 1.000000 + vn.13214 CD..0314 .898705 SU..1314 -1.000000 + vn.13214 LC.13214 1.000000 + vn.31115 CD..0115 .963925 SU..3115 -1.000000 + vn.31115 LC.31115 1.000000 + vn.13115 CD..0315 .963925 SU..1315 -1.000000 + vn.13115 LC.13115 1.000000 + vn.31215 CD..0115 .898705 SU..3115 -1.000000 + vn.31215 LC.31215 1.000000 + vn.13215 CD..0315 .898705 SU..1315 -1.000000 + vn.13215 LC.13215 1.000000 + vn.31116 CD..0116 .963925 SU..3116 -1.000000 + vn.31116 LC.31116 1.000000 + vn.13116 CD..0316 .963925 SU..1316 -1.000000 + vn.13116 LC.13116 1.000000 + vn.31216 CD..0116 .898705 SU..3116 -1.000000 + vn.31216 LC.31216 1.000000 + vn.13216 CD..0316 .898705 SU..1316 -1.000000 + vn.13216 LC.13216 1.000000 + vn.31117 CD..0117 .963925 SU..3117 -1.000000 + vn.31117 LC.31117 1.000000 + vn.13117 CD..0317 .963925 SU..1317 -1.000000 + vn.13117 LC.13117 1.000000 + vn.31217 CD..0117 .898705 SU..3117 -1.000000 + vn.31217 LC.31217 1.000000 + vn.13217 CD..0317 .898705 SU..1317 -1.000000 + vn.13217 LC.13217 1.000000 + vn.31118 CD..0118 .963925 SU..3118 -1.000000 + vn.31118 LC.31118 1.000000 + vn.13118 CD..0318 .963925 SU..1318 -1.000000 + vn.13118 LC.13118 1.000000 + vn.31218 CD..0118 .898705 SU..3118 -1.000000 + vn.31218 LC.31218 1.000000 + vn.13218 CD..0318 .898705 SU..1318 -1.000000 + vn.13218 LC.13218 1.000000 + vn.31119 CD..0119 .963925 SU..3119 -1.000000 + vn.31119 LC.31119 1.000000 + vn.13119 CD..0319 .963925 SU..1319 -1.000000 + vn.13119 LC.13119 1.000000 + vn.31219 CD..0119 .898705 SU..3119 -1.000000 + vn.31219 LC.31219 1.000000 + vn.13219 CD..0319 .898705 SU..1319 -1.000000 + vn.13219 LC.13219 1.000000 + vn.31120 CD..0120 .963925 SU..3120 -1.000000 + vn.31120 LC.31120 1.000000 + vn.13120 CD..0320 .963925 SU..1320 -1.000000 + vn.13120 LC.13120 1.000000 + vn.31220 CD..0120 .898705 SU..3120 -1.000000 + vn.31220 LC.31220 1.000000 + vn.13220 CD..0320 .898705 SU..1320 -1.000000 + vn.13220 LC.13220 1.000000 + vn.31121 CD..0121 .963925 SU..3121 -1.000000 + vn.31121 LC.31121 1.000000 + vn.13121 CD..0321 .963925 SU..1321 -1.000000 + vn.13121 LC.13121 1.000000 + vn.31221 CD..0121 .898705 SU..3121 -1.000000 + vn.31221 LC.31221 1.000000 + vn.13221 CD..0321 .898705 SU..1321 -1.000000 + vn.13221 LC.13221 1.000000 + vn.31122 CD..0122 .963925 SU..3122 -1.000000 + vn.31122 LC.31122 1.000000 + vn.13122 CD..0322 .963925 SU..1322 -1.000000 + vn.13122 LC.13122 1.000000 + vn.31222 CD..0122 .898705 SU..3122 -1.000000 + vn.31222 LC.31222 1.000000 + vn.13222 CD..0322 .898705 SU..1322 -1.000000 + vn.13222 LC.13222 1.000000 + vn.31123 CD..0123 .963925 SU..3123 -1.000000 + vn.31123 LC.31123 1.000000 + vn.13123 CD..0323 .963925 SU..1323 -1.000000 + vn.13123 LC.13123 1.000000 + vn.31223 CD..0123 .898705 SU..3123 -1.000000 + vn.31223 LC.31223 1.000000 + vn.13223 CD..0323 .898705 SU..1323 -1.000000 + vn.13223 LC.13223 1.000000 + vn.31124 CD..0124 .963925 SU..3124 -1.000000 + vn.31124 LC.31124 1.000000 + vn.13124 CD..0324 .963925 SU..1324 -1.000000 + vn.13124 LC.13124 1.000000 + vn.31224 CD..0124 .898705 SU..3124 -1.000000 + vn.31224 LC.31224 1.000000 + vn.13224 CD..0324 .898705 SU..1324 -1.000000 + vn.13224 LC.13224 1.000000 + v...2101 CD..0101 .970000 CD..0201 -1.000000 + v...2101 LCC.2101 1.000000 + v...3101 CD..0301 -1.000000 SU..3101 1.000000 + v...1201 CD..0101 -1.000000 CD..0201 .970000 + v...1201 LCC.1201 1.000000 + v...1301 CD..0101 -1.000000 SU..1301 1.000000 + v...2102 CD..0102 .970000 CD..0202 -1.000000 + v...2102 LCC.2102 1.000000 + v...3102 CD..0302 -1.000000 SU..3102 1.000000 + v...1202 CD..0102 -1.000000 CD..0202 .970000 + v...1202 LCC.1202 1.000000 + v...1302 CD..0102 -1.000000 SU..1302 1.000000 + v...2103 CD..0103 .970000 CD..0203 -1.000000 + v...2103 LCC.2103 1.000000 + v...3103 CD..0303 -1.000000 SU..3103 1.000000 + v...1203 CD..0103 -1.000000 CD..0203 .970000 + v...1203 LCC.1203 1.000000 + v...1303 CD..0103 -1.000000 SU..1303 1.000000 + v...2104 CD..0104 .970000 CD..0204 -1.000000 + v...2104 LCC.2104 1.000000 + v...3104 CD..0304 -1.000000 SU..3104 1.000000 + v...1204 CD..0104 -1.000000 CD..0204 .970000 + v...1204 LCC.1204 1.000000 + v...1304 CD..0104 -1.000000 SU..1304 1.000000 + v...2105 CD..0105 .970000 CD..0205 -1.000000 + v...2105 LCC.2105 1.000000 + v...3105 CD..0305 -1.000000 SU..3105 1.000000 + v...1205 CD..0105 -1.000000 CD..0205 .970000 + v...1205 LCC.1205 1.000000 + v...1305 CD..0105 -1.000000 SU..1305 1.000000 + v...2106 CD..0106 .970000 CD..0206 -1.000000 + v...2106 LCC.2106 1.000000 + v...3106 CD..0306 -1.000000 SU..3106 1.000000 + v...1206 CD..0106 -1.000000 CD..0206 .970000 + v...1206 LCC.1206 1.000000 + v...1306 CD..0106 -1.000000 SU..1306 1.000000 + v...2107 CD..0107 .970000 CD..0207 -1.000000 + v...2107 LCC.2107 1.000000 + v...3107 CD..0307 -1.000000 SU..3107 1.000000 + v...1207 CD..0107 -1.000000 CD..0207 .970000 + v...1207 LCC.1207 1.000000 + v...1307 CD..0107 -1.000000 SU..1307 1.000000 + v...2108 CD..0108 .970000 CD..0208 -1.000000 + v...2108 LCC.2108 1.000000 + v...3108 CD..0308 -1.000000 SU..3108 1.000000 + v...1208 CD..0108 -1.000000 CD..0208 .970000 + v...1208 LCC.1208 1.000000 + v...1308 CD..0108 -1.000000 SU..1308 1.000000 + v...2109 CD..0109 .970000 CD..0209 -1.000000 + v...2109 LCC.2109 1.000000 + v...3109 CD..0309 -1.000000 SU..3109 1.000000 + v...1209 CD..0109 -1.000000 CD..0209 .970000 + v...1209 LCC.1209 1.000000 + v...1309 CD..0109 -1.000000 SU..1309 1.000000 + v...2110 CD..0110 .970000 CD..0210 -1.000000 + v...2110 LCC.2110 1.000000 + v...3110 CD..0310 -1.000000 SU..3110 1.000000 + v...1210 CD..0110 -1.000000 CD..0210 .970000 + v...1210 LCC.1210 1.000000 + v...1310 CD..0110 -1.000000 SU..1310 1.000000 + v...2111 CD..0111 .970000 CD..0211 -1.000000 + v...2111 LCC.2111 1.000000 + v...3111 CD..0311 -1.000000 SU..3111 1.000000 + v...1211 CD..0111 -1.000000 CD..0211 .970000 + v...1211 LCC.1211 1.000000 + v...1311 CD..0111 -1.000000 SU..1311 1.000000 + v...2112 CD..0112 .970000 CD..0212 -1.000000 + v...2112 LCC.2112 1.000000 + v...3112 CD..0312 -1.000000 SU..3112 1.000000 + v...1212 CD..0112 -1.000000 CD..0212 .970000 + v...1212 LCC.1212 1.000000 + v...1312 CD..0112 -1.000000 SU..1312 1.000000 + v...2113 CD..0113 .970000 CD..0213 -1.000000 + v...2113 LCC.2113 1.000000 + v...3113 CD..0313 -1.000000 SU..3113 1.000000 + v...1213 CD..0113 -1.000000 CD..0213 .970000 + v...1213 LCC.1213 1.000000 + v...1313 CD..0113 -1.000000 SU..1313 1.000000 + v...2114 CD..0114 .970000 CD..0214 -1.000000 + v...2114 LCC.2114 1.000000 + v...3114 CD..0314 -1.000000 SU..3114 1.000000 + v...1214 CD..0114 -1.000000 CD..0214 .970000 + v...1214 LCC.1214 1.000000 + v...1314 CD..0114 -1.000000 SU..1314 1.000000 + v...2115 CD..0115 .970000 CD..0215 -1.000000 + v...2115 LCC.2115 1.000000 + v...3115 CD..0315 -1.000000 SU..3115 1.000000 + v...1215 CD..0115 -1.000000 CD..0215 .970000 + v...1215 LCC.1215 1.000000 + v...1315 CD..0115 -1.000000 SU..1315 1.000000 + v...2116 CD..0116 .970000 CD..0216 -1.000000 + v...2116 LCC.2116 1.000000 + v...3116 CD..0316 -1.000000 SU..3116 1.000000 + v...1216 CD..0116 -1.000000 CD..0216 .970000 + v...1216 LCC.1216 1.000000 + v...1316 CD..0116 -1.000000 SU..1316 1.000000 + v...2117 CD..0117 .970000 CD..0217 -1.000000 + v...2117 LCC.2117 1.000000 + v...3117 CD..0317 -1.000000 SU..3117 1.000000 + v...1217 CD..0117 -1.000000 CD..0217 .970000 + v...1217 LCC.1217 1.000000 + v...1317 CD..0117 -1.000000 SU..1317 1.000000 + v...2118 CD..0118 .970000 CD..0218 -1.000000 + v...2118 LCC.2118 1.000000 + v...3118 CD..0318 -1.000000 SU..3118 1.000000 + v...1218 CD..0118 -1.000000 CD..0218 .970000 + v...1218 LCC.1218 1.000000 + v...1318 CD..0118 -1.000000 SU..1318 1.000000 + v...2119 CD..0119 .970000 CD..0219 -1.000000 + v...2119 LCC.2119 1.000000 + v...3119 CD..0319 -1.000000 SU..3119 1.000000 + v...1219 CD..0119 -1.000000 CD..0219 .970000 + v...1219 LCC.1219 1.000000 + v...1319 CD..0119 -1.000000 SU..1319 1.000000 + v...2120 CD..0120 .970000 CD..0220 -1.000000 + v...2120 LCC.2120 1.000000 + v...3120 CD..0320 -1.000000 SU..3120 1.000000 + v...1220 CD..0120 -1.000000 CD..0220 .970000 + v...1220 LCC.1220 1.000000 + v...1320 CD..0120 -1.000000 SU..1320 1.000000 + v...2121 CD..0121 .970000 CD..0221 -1.000000 + v...2121 LCC.2121 1.000000 + v...3121 CD..0321 -1.000000 SU..3121 1.000000 + v...1221 CD..0121 -1.000000 CD..0221 .970000 + v...1221 LCC.1221 1.000000 + v...1321 CD..0121 -1.000000 SU..1321 1.000000 + v...2122 CD..0122 .970000 CD..0222 -1.000000 + v...2122 LCC.2122 1.000000 + v...3122 CD..0322 -1.000000 SU..3122 1.000000 + v...1222 CD..0122 -1.000000 CD..0222 .970000 + v...1222 LCC.1222 1.000000 + v...1322 CD..0122 -1.000000 SU..1322 1.000000 + v...2123 CD..0123 .970000 CD..0223 -1.000000 + v...2123 LCC.2123 1.000000 + v...3123 CD..0323 -1.000000 SU..3123 1.000000 + v...1223 CD..0123 -1.000000 CD..0223 .970000 + v...1223 LCC.1223 1.000000 + v...1323 CD..0123 -1.000000 SU..1323 1.000000 + v...2124 CD..0124 .970000 CD..0224 -1.000000 + v...2124 LCC.2124 1.000000 + v...3124 CD..0324 -1.000000 SU..3124 1.000000 + v...1224 CD..0124 -1.000000 CD..0224 .970000 + v...1224 LCC.1224 1.000000 + v...1324 CD..0124 -1.000000 SU..1324 1.000000 + yv..2101 CD..0101 -1.500000 SURD0101 42.150000 + yv..2101 S12D..01 -1.500000 S13D..01 42.150000 + yv..2101 S123D.01 -1.500000 LCC.2101 -45.000000 + yv..2101 AD..1201 1.000000 + yv..3101 CD..0101 -.068554 SURD0101 60.120350 + yv..3101 S12D..01 60.120350 S13D..01 -.068554 + yv..3101 S123D.01 -.068554 LC.31101 -31.320000 + yv..3101 LC.31201 -33.380000 AD..1301 1.000000 + yv..1201 CD..0201 -1.500000 SURD0201 42.150000 + yv..1201 S12D..01 -1.500000 S123D.01 -1.500000 + yv..1201 LCC.1201 -45.000000 AD..1201 1.000000 + yv..1301 CD..0301 -.068554 SURD0301 60.120350 + yv..1301 S13D..01 -.068554 S123D.01 -.068554 + yv..1301 LC.13101 -31.320000 LC.13201 -33.380000 + yv..1301 AD..1301 1.000000 + yv..2102 CD..0102 -1.500000 SURD0102 42.150000 + yv..2102 S12D..02 -1.500000 S13D..02 42.150000 + yv..2102 S123D.02 -1.500000 LCC.2102 -45.000000 + yv..2102 AD..1202 1.000000 + yv..3102 CD..0102 -.068554 SURD0102 60.120350 + yv..3102 S12D..02 60.120350 S13D..02 -.068554 + yv..3102 S123D.02 -.068554 LC.31102 -31.320000 + yv..3102 LC.31202 -33.380000 AD..1302 1.000000 + yv..1202 CD..0202 -1.500000 SURD0202 42.150000 + yv..1202 S12D..02 -1.500000 S123D.02 -1.500000 + yv..1202 LCC.1202 -45.000000 AD..1202 1.000000 + yv..1302 CD..0302 -.068554 SURD0302 60.120350 + yv..1302 S13D..02 -.068554 S123D.02 -.068554 + yv..1302 LC.13102 -31.320000 LC.13202 -33.380000 + yv..1302 AD..1302 1.000000 + yv..2103 CD..0103 -1.500000 SURD0103 42.150000 + yv..2103 S12D..03 -1.500000 S13D..03 42.150000 + yv..2103 S123D.03 -1.500000 LCC.2103 -45.000000 + yv..2103 AD..1203 1.000000 + yv..3103 CD..0103 -.068554 SURD0103 60.120350 + yv..3103 S12D..03 60.120350 S13D..03 -.068554 + yv..3103 S123D.03 -.068554 LC.31103 -31.320000 + yv..3103 LC.31203 -33.380000 AD..1303 1.000000 + yv..1203 CD..0203 -1.500000 SURD0203 42.150000 + yv..1203 S12D..03 -1.500000 S123D.03 -1.500000 + yv..1203 LCC.1203 -45.000000 AD..1203 1.000000 + yv..1303 CD..0303 -.068554 SURD0303 60.120350 + yv..1303 S13D..03 -.068554 S123D.03 -.068554 + yv..1303 LC.13103 -31.320000 LC.13203 -33.380000 + yv..1303 AD..1303 1.000000 + yv..2104 CD..0104 -1.500000 SURD0104 42.150000 + yv..2104 S12D..04 -1.500000 S13D..04 42.150000 + yv..2104 S123D.04 -1.500000 LCC.2104 -45.000000 + yv..2104 AD..1204 1.000000 + yv..3104 CD..0104 -.068554 SURD0104 60.120350 + yv..3104 S12D..04 60.120350 S13D..04 -.068554 + yv..3104 S123D.04 -.068554 LC.31104 -31.320000 + yv..3104 LC.31204 -33.380000 AD..1304 1.000000 + yv..1204 CD..0204 -1.500000 SURD0204 42.150000 + yv..1204 S12D..04 -1.500000 S123D.04 -1.500000 + yv..1204 LCC.1204 -45.000000 AD..1204 1.000000 + yv..1304 CD..0304 -.068554 SURD0304 60.120350 + yv..1304 S13D..04 -.068554 S123D.04 -.068554 + yv..1304 LC.13104 -31.320000 LC.13204 -33.380000 + yv..1304 AD..1304 1.000000 + yv..2105 CD..0105 -1.500000 SURD0105 42.150000 + yv..2105 S12D..05 -1.500000 S13D..05 42.150000 + yv..2105 S123D.05 -1.500000 LCC.2105 -45.000000 + yv..2105 AD..1205 1.000000 + yv..3105 CD..0105 -.068554 SURD0105 60.120350 + yv..3105 S12D..05 60.120350 S13D..05 -.068554 + yv..3105 S123D.05 -.068554 LC.31105 -31.320000 + yv..3105 LC.31205 -33.380000 AD..1305 1.000000 + yv..1205 CD..0205 -1.500000 SURD0205 42.150000 + yv..1205 S12D..05 -1.500000 S123D.05 -1.500000 + yv..1205 LCC.1205 -45.000000 AD..1205 1.000000 + yv..1305 CD..0305 -.068554 SURD0305 60.120350 + yv..1305 S13D..05 -.068554 S123D.05 -.068554 + yv..1305 LC.13105 -31.320000 LC.13205 -33.380000 + yv..1305 AD..1305 1.000000 + yv..2106 CD..0106 -1.500000 SURD0106 42.150000 + yv..2106 S12D..06 -1.500000 S13D..06 42.150000 + yv..2106 S123D.06 -1.500000 LCC.2106 -45.000000 + yv..2106 AD..1206 1.000000 + yv..3106 CD..0106 -.068554 SURD0106 60.120350 + yv..3106 S12D..06 60.120350 S13D..06 -.068554 + yv..3106 S123D.06 -.068554 LC.31106 -31.320000 + yv..3106 LC.31206 -33.380000 AD..1306 1.000000 + yv..1206 CD..0206 -1.500000 SURD0206 42.150000 + yv..1206 S12D..06 -1.500000 S123D.06 -1.500000 + yv..1206 LCC.1206 -45.000000 AD..1206 1.000000 + yv..1306 CD..0306 -.068554 SURD0306 60.120350 + yv..1306 S13D..06 -.068554 S123D.06 -.068554 + yv..1306 LC.13106 -31.320000 LC.13206 -33.380000 + yv..1306 AD..1306 1.000000 + yv..2107 CD..0107 -1.500000 SURD0107 42.150000 + yv..2107 S12D..07 -1.500000 S13D..07 42.150000 + yv..2107 S123D.07 -1.500000 LCC.2107 -45.000000 + yv..2107 AD..1207 1.000000 + yv..3107 CD..0107 -.068554 SURD0107 60.120350 + yv..3107 S12D..07 60.120350 S13D..07 -.068554 + yv..3107 S123D.07 -.068554 LC.31107 -31.320000 + yv..3107 LC.31207 -33.380000 AD..1307 1.000000 + yv..1207 CD..0207 -1.500000 SURD0207 42.150000 + yv..1207 S12D..07 -1.500000 S123D.07 -1.500000 + yv..1207 LCC.1207 -45.000000 AD..1207 1.000000 + yv..1307 CD..0307 -.068554 SURD0307 60.120350 + yv..1307 S13D..07 -.068554 S123D.07 -.068554 + yv..1307 LC.13107 -31.320000 LC.13207 -33.380000 + yv..1307 AD..1307 1.000000 + yv..2108 CD..0108 -1.500000 SURD0108 42.150000 + yv..2108 S12D..08 -1.500000 S13D..08 42.150000 + yv..2108 S123D.08 -1.500000 LCC.2108 -45.000000 + yv..2108 AD..1208 1.000000 + yv..3108 CD..0108 -.068554 SURD0108 60.120350 + yv..3108 S12D..08 60.120350 S13D..08 -.068554 + yv..3108 S123D.08 -.068554 LC.31108 -31.320000 + yv..3108 LC.31208 -33.380000 AD..1308 1.000000 + yv..1208 CD..0208 -1.500000 SURD0208 42.150000 + yv..1208 S12D..08 -1.500000 S123D.08 -1.500000 + yv..1208 LCC.1208 -45.000000 AD..1208 1.000000 + yv..1308 CD..0308 -.068554 SURD0308 60.120350 + yv..1308 S13D..08 -.068554 S123D.08 -.068554 + yv..1308 LC.13108 -31.320000 LC.13208 -33.380000 + yv..1308 AD..1308 1.000000 + yv..2109 CD..0109 -1.500000 SURD0109 42.150000 + yv..2109 S12D..09 -1.500000 S13D..09 42.150000 + yv..2109 S123D.09 -1.500000 LCC.2109 -45.000000 + yv..2109 AD..1209 1.000000 + yv..3109 CD..0109 -.068554 SURD0109 60.120350 + yv..3109 S12D..09 60.120350 S13D..09 -.068554 + yv..3109 S123D.09 -.068554 LC.31109 -31.320000 + yv..3109 LC.31209 -33.380000 AD..1309 1.000000 + yv..1209 CD..0209 -1.500000 SURD0209 42.150000 + yv..1209 S12D..09 -1.500000 S123D.09 -1.500000 + yv..1209 LCC.1209 -45.000000 AD..1209 1.000000 + yv..1309 CD..0309 -.068554 SURD0309 60.120350 + yv..1309 S13D..09 -.068554 S123D.09 -.068554 + yv..1309 LC.13109 -31.320000 LC.13209 -33.380000 + yv..1309 AD..1309 1.000000 + yv..2110 CD..0110 -1.500000 SURD0110 42.150000 + yv..2110 S12D..10 -1.500000 S13D..10 42.150000 + yv..2110 S123D.10 -1.500000 LCC.2110 -45.000000 + yv..2110 AD..1210 1.000000 + yv..3110 CD..0110 -.068554 SURD0110 60.120350 + yv..3110 S12D..10 60.120350 S13D..10 -.068554 + yv..3110 S123D.10 -.068554 LC.31110 -31.320000 + yv..3110 LC.31210 -33.380000 AD..1310 1.000000 + yv..1210 CD..0210 -1.500000 SURD0210 42.150000 + yv..1210 S12D..10 -1.500000 S123D.10 -1.500000 + yv..1210 LCC.1210 -45.000000 AD..1210 1.000000 + yv..1310 CD..0310 -.068554 SURD0310 60.120350 + yv..1310 S13D..10 -.068554 S123D.10 -.068554 + yv..1310 LC.13110 -31.320000 LC.13210 -33.380000 + yv..1310 AD..1310 1.000000 + yv..2111 CD..0111 -1.500000 SURD0111 42.150000 + yv..2111 S12D..11 -1.500000 S13D..11 42.150000 + yv..2111 S123D.11 -1.500000 LCC.2111 -45.000000 + yv..2111 AD..1211 1.000000 + yv..3111 CD..0111 -.068554 SURD0111 60.120350 + yv..3111 S12D..11 60.120350 S13D..11 -.068554 + yv..3111 S123D.11 -.068554 LC.31111 -31.320000 + yv..3111 LC.31211 -33.380000 AD..1311 1.000000 + yv..1211 CD..0211 -1.500000 SURD0211 42.150000 + yv..1211 S12D..11 -1.500000 S123D.11 -1.500000 + yv..1211 LCC.1211 -45.000000 AD..1211 1.000000 + yv..1311 CD..0311 -.068554 SURD0311 60.120350 + yv..1311 S13D..11 -.068554 S123D.11 -.068554 + yv..1311 LC.13111 -31.320000 LC.13211 -33.380000 + yv..1311 AD..1311 1.000000 + yv..2112 CD..0112 -1.500000 SURD0112 42.150000 + yv..2112 S12D..12 -1.500000 S13D..12 42.150000 + yv..2112 S123D.12 -1.500000 LCC.2112 -45.000000 + yv..2112 AD..1212 1.000000 + yv..3112 CD..0112 -.068554 SURD0112 60.120350 + yv..3112 S12D..12 60.120350 S13D..12 -.068554 + yv..3112 S123D.12 -.068554 LC.31112 -31.320000 + yv..3112 LC.31212 -33.380000 AD..1312 1.000000 + yv..1212 CD..0212 -1.500000 SURD0212 42.150000 + yv..1212 S12D..12 -1.500000 S123D.12 -1.500000 + yv..1212 LCC.1212 -45.000000 AD..1212 1.000000 + yv..1312 CD..0312 -.068554 SURD0312 60.120350 + yv..1312 S13D..12 -.068554 S123D.12 -.068554 + yv..1312 LC.13112 -31.320000 LC.13212 -33.380000 + yv..1312 AD..1312 1.000000 + yv..2113 CD..0113 -1.500000 SURD0113 42.150000 + yv..2113 S12D..13 -1.500000 S13D..13 42.150000 + yv..2113 S123D.13 -1.500000 LCC.2113 -45.000000 + yv..2113 AD..1213 1.000000 + yv..3113 CD..0113 -.068554 SURD0113 60.120350 + yv..3113 S12D..13 60.120350 S13D..13 -.068554 + yv..3113 S123D.13 -.068554 LC.31113 -31.320000 + yv..3113 LC.31213 -33.380000 AD..1313 1.000000 + yv..1213 CD..0213 -1.500000 SURD0213 42.150000 + yv..1213 S12D..13 -1.500000 S123D.13 -1.500000 + yv..1213 LCC.1213 -45.000000 AD..1213 1.000000 + yv..1313 CD..0313 -.068554 SURD0313 60.120350 + yv..1313 S13D..13 -.068554 S123D.13 -.068554 + yv..1313 LC.13113 -31.320000 LC.13213 -33.380000 + yv..1313 AD..1313 1.000000 + yv..2114 CD..0114 -1.500000 SURD0114 42.150000 + yv..2114 S12D..14 -1.500000 S13D..14 42.150000 + yv..2114 S123D.14 -1.500000 LCC.2114 -45.000000 + yv..2114 AD..1214 1.000000 + yv..3114 CD..0114 -.068554 SURD0114 60.120350 + yv..3114 S12D..14 60.120350 S13D..14 -.068554 + yv..3114 S123D.14 -.068554 LC.31114 -31.320000 + yv..3114 LC.31214 -33.380000 AD..1314 1.000000 + yv..1214 CD..0214 -1.500000 SURD0214 42.150000 + yv..1214 S12D..14 -1.500000 S123D.14 -1.500000 + yv..1214 LCC.1214 -45.000000 AD..1214 1.000000 + yv..1314 CD..0314 -.068554 SURD0314 60.120350 + yv..1314 S13D..14 -.068554 S123D.14 -.068554 + yv..1314 LC.13114 -31.320000 LC.13214 -33.380000 + yv..1314 AD..1314 1.000000 + yv..2115 CD..0115 -1.500000 SURD0115 42.150000 + yv..2115 S12D..15 -1.500000 S13D..15 42.150000 + yv..2115 S123D.15 -1.500000 LCC.2115 -45.000000 + yv..2115 AD..1215 1.000000 + yv..3115 CD..0115 -.068554 SURD0115 60.120350 + yv..3115 S12D..15 60.120350 S13D..15 -.068554 + yv..3115 S123D.15 -.068554 LC.31115 -31.320000 + yv..3115 LC.31215 -33.380000 AD..1315 1.000000 + yv..1215 CD..0215 -1.500000 SURD0215 42.150000 + yv..1215 S12D..15 -1.500000 S123D.15 -1.500000 + yv..1215 LCC.1215 -45.000000 AD..1215 1.000000 + yv..1315 CD..0315 -.068554 SURD0315 60.120350 + yv..1315 S13D..15 -.068554 S123D.15 -.068554 + yv..1315 LC.13115 -31.320000 LC.13215 -33.380000 + yv..1315 AD..1315 1.000000 + yv..2116 CD..0116 -1.500000 SURD0116 42.150000 + yv..2116 S12D..16 -1.500000 S13D..16 42.150000 + yv..2116 S123D.16 -1.500000 LCC.2116 -45.000000 + yv..2116 AD..1216 1.000000 + yv..3116 CD..0116 -.068554 SURD0116 60.120350 + yv..3116 S12D..16 60.120350 S13D..16 -.068554 + yv..3116 S123D.16 -.068554 LC.31116 -31.320000 + yv..3116 LC.31216 -33.380000 AD..1316 1.000000 + yv..1216 CD..0216 -1.500000 SURD0216 42.150000 + yv..1216 S12D..16 -1.500000 S123D.16 -1.500000 + yv..1216 LCC.1216 -45.000000 AD..1216 1.000000 + yv..1316 CD..0316 -.068554 SURD0316 60.120350 + yv..1316 S13D..16 -.068554 S123D.16 -.068554 + yv..1316 LC.13116 -31.320000 LC.13216 -33.380000 + yv..1316 AD..1316 1.000000 + yv..2117 CD..0117 -1.500000 SURD0117 42.150000 + yv..2117 S12D..17 -1.500000 S13D..17 42.150000 + yv..2117 S123D.17 -1.500000 LCC.2117 -45.000000 + yv..2117 AD..1217 1.000000 + yv..3117 CD..0117 -.068554 SURD0117 60.120350 + yv..3117 S12D..17 60.120350 S13D..17 -.068554 + yv..3117 S123D.17 -.068554 LC.31117 -31.320000 + yv..3117 LC.31217 -33.380000 AD..1317 1.000000 + yv..1217 CD..0217 -1.500000 SURD0217 42.150000 + yv..1217 S12D..17 -1.500000 S123D.17 -1.500000 + yv..1217 LCC.1217 -45.000000 AD..1217 1.000000 + yv..1317 CD..0317 -.068554 SURD0317 60.120350 + yv..1317 S13D..17 -.068554 S123D.17 -.068554 + yv..1317 LC.13117 -31.320000 LC.13217 -33.380000 + yv..1317 AD..1317 1.000000 + yv..2118 CD..0118 -1.500000 SURD0118 42.150000 + yv..2118 S12D..18 -1.500000 S13D..18 42.150000 + yv..2118 S123D.18 -1.500000 LCC.2118 -45.000000 + yv..2118 AD..1218 1.000000 + yv..3118 CD..0118 -.068554 SURD0118 60.120350 + yv..3118 S12D..18 60.120350 S13D..18 -.068554 + yv..3118 S123D.18 -.068554 LC.31118 -31.320000 + yv..3118 LC.31218 -33.380000 AD..1318 1.000000 + yv..1218 CD..0218 -1.500000 SURD0218 42.150000 + yv..1218 S12D..18 -1.500000 S123D.18 -1.500000 + yv..1218 LCC.1218 -45.000000 AD..1218 1.000000 + yv..1318 CD..0318 -.068554 SURD0318 60.120350 + yv..1318 S13D..18 -.068554 S123D.18 -.068554 + yv..1318 LC.13118 -31.320000 LC.13218 -33.380000 + yv..1318 AD..1318 1.000000 + yv..2119 CD..0119 -1.500000 SURD0119 42.150000 + yv..2119 S12D..19 -1.500000 S13D..19 42.150000 + yv..2119 S123D.19 -1.500000 LCC.2119 -45.000000 + yv..2119 AD..1219 1.000000 + yv..3119 CD..0119 -.068554 SURD0119 60.120350 + yv..3119 S12D..19 60.120350 S13D..19 -.068554 + yv..3119 S123D.19 -.068554 LC.31119 -31.320000 + yv..3119 LC.31219 -33.380000 AD..1319 1.000000 + yv..1219 CD..0219 -1.500000 SURD0219 42.150000 + yv..1219 S12D..19 -1.500000 S123D.19 -1.500000 + yv..1219 LCC.1219 -45.000000 AD..1219 1.000000 + yv..1319 CD..0319 -.068554 SURD0319 60.120350 + yv..1319 S13D..19 -.068554 S123D.19 -.068554 + yv..1319 LC.13119 -31.320000 LC.13219 -33.380000 + yv..1319 AD..1319 1.000000 + yv..2120 CD..0120 -1.500000 SURD0120 42.150000 + yv..2120 S12D..20 -1.500000 S13D..20 42.150000 + yv..2120 S123D.20 -1.500000 LCC.2120 -45.000000 + yv..2120 AD..1220 1.000000 + yv..3120 CD..0120 -.068554 SURD0120 60.120350 + yv..3120 S12D..20 60.120350 S13D..20 -.068554 + yv..3120 S123D.20 -.068554 LC.31120 -31.320000 + yv..3120 LC.31220 -33.380000 AD..1320 1.000000 + yv..1220 CD..0220 -1.500000 SURD0220 42.150000 + yv..1220 S12D..20 -1.500000 S123D.20 -1.500000 + yv..1220 LCC.1220 -45.000000 AD..1220 1.000000 + yv..1320 CD..0320 -.068554 SURD0320 60.120350 + yv..1320 S13D..20 -.068554 S123D.20 -.068554 + yv..1320 LC.13120 -31.320000 LC.13220 -33.380000 + yv..1320 AD..1320 1.000000 + yv..2121 CD..0121 -1.500000 SURD0121 42.150000 + yv..2121 S12D..21 -1.500000 S13D..21 42.150000 + yv..2121 S123D.21 -1.500000 LCC.2121 -45.000000 + yv..2121 AD..1221 1.000000 + yv..3121 CD..0121 -.068554 SURD0121 60.120350 + yv..3121 S12D..21 60.120350 S13D..21 -.068554 + yv..3121 S123D.21 -.068554 LC.31121 -31.320000 + yv..3121 LC.31221 -33.380000 AD..1321 1.000000 + yv..1221 CD..0221 -1.500000 SURD0221 42.150000 + yv..1221 S12D..21 -1.500000 S123D.21 -1.500000 + yv..1221 LCC.1221 -45.000000 AD..1221 1.000000 + yv..1321 CD..0321 -.068554 SURD0321 60.120350 + yv..1321 S13D..21 -.068554 S123D.21 -.068554 + yv..1321 LC.13121 -31.320000 LC.13221 -33.380000 + yv..1321 AD..1321 1.000000 + yv..2122 CD..0122 -1.500000 SURD0122 42.150000 + yv..2122 S12D..22 -1.500000 S13D..22 42.150000 + yv..2122 S123D.22 -1.500000 LCC.2122 -45.000000 + yv..2122 AD..1222 1.000000 + yv..3122 CD..0122 -.068554 SURD0122 60.120350 + yv..3122 S12D..22 60.120350 S13D..22 -.068554 + yv..3122 S123D.22 -.068554 LC.31122 -31.320000 + yv..3122 LC.31222 -33.380000 AD..1322 1.000000 + yv..1222 CD..0222 -1.500000 SURD0222 42.150000 + yv..1222 S12D..22 -1.500000 S123D.22 -1.500000 + yv..1222 LCC.1222 -45.000000 AD..1222 1.000000 + yv..1322 CD..0322 -.068554 SURD0322 60.120350 + yv..1322 S13D..22 -.068554 S123D.22 -.068554 + yv..1322 LC.13122 -31.320000 LC.13222 -33.380000 + yv..1322 AD..1322 1.000000 + yv..2123 CD..0123 -1.500000 SURD0123 42.150000 + yv..2123 S12D..23 -1.500000 S13D..23 42.150000 + yv..2123 S123D.23 -1.500000 LCC.2123 -45.000000 + yv..2123 AD..1223 1.000000 + yv..3123 CD..0123 -.068554 SURD0123 60.120350 + yv..3123 S12D..23 60.120350 S13D..23 -.068554 + yv..3123 S123D.23 -.068554 LC.31123 -31.320000 + yv..3123 LC.31223 -33.380000 AD..1323 1.000000 + yv..1223 CD..0223 -1.500000 SURD0223 42.150000 + yv..1223 S12D..23 -1.500000 S123D.23 -1.500000 + yv..1223 LCC.1223 -45.000000 AD..1223 1.000000 + yv..1323 CD..0323 -.068554 SURD0323 60.120350 + yv..1323 S13D..23 -.068554 S123D.23 -.068554 + yv..1323 LC.13123 -31.320000 LC.13223 -33.380000 + yv..1323 AD..1323 1.000000 + yv..2124 CD..0124 -1.500000 SURD0124 42.150000 + yv..2124 S12D..24 -1.500000 S13D..24 42.150000 + yv..2124 S123D.24 -1.500000 LCC.2124 -45.000000 + yv..2124 AD..1224 1.000000 + yv..3124 CD..0124 -.068554 SURD0124 60.120350 + yv..3124 S12D..24 60.120350 S13D..24 -.068554 + yv..3124 S123D.24 -.068554 LC.31124 -31.320000 + yv..3124 LC.31224 -33.380000 AD..1324 1.000000 + yv..1224 CD..0224 -1.500000 SURD0224 42.150000 + yv..1224 S12D..24 -1.500000 S123D.24 -1.500000 + yv..1224 LCC.1224 -45.000000 AD..1224 1.000000 + yv..1324 CD..0324 -.068554 SURD0324 60.120350 + yv..1324 S13D..24 -.068554 S123D.24 -.068554 + yv..1324 LC.13124 -31.320000 LC.13224 -33.380000 + yv..1324 AD..1324 1.000000 +RHS + RHS00001 CD..0101 196.530000 CD..0102 173.200000 + RHS00001 CD..0103 161.740000 CD..0104 157.820000 + RHS00001 CD..0105 157.660000 CD..0106 164.120000 + RHS00001 CD..0107 197.410000 CD..0108 264.490000 + RHS00001 CD..0109 309.680000 CD..0110 335.720000 + RHS00001 CD..0111 339.300000 CD..0112 335.740000 + RHS00001 CD..0113 324.510000 CD..0114 294.180000 + RHS00001 CD..0115 300.660000 CD..0116 311.660000 + RHS00001 CD..0117 329.070000 CD..0118 384.120000 + RHS00001 CD..0119 393.000000 CD..0120 385.800000 + RHS00001 CD..0121 369.890000 CD..0122 344.510000 + RHS00001 CD..0123 312.720000 CD..0124 263.180000 + RHS00001 CD..0201 22.490000 CD..0202 19.800000 + RHS00001 CD..0203 18.900000 CD..0204 18.470000 + RHS00001 CD..0205 18.590000 CD..0206 20.260000 + RHS00001 CD..0207 27.450000 CD..0208 38.910000 + RHS00001 CD..0209 42.560000 CD..0210 44.540000 + RHS00001 CD..0211 44.410000 CD..0212 43.300000 + RHS00001 CD..0213 41.620000 CD..0214 37.730000 + RHS00001 CD..0215 40.090000 CD..0216 42.430000 + RHS00001 CD..0217 43.740000 CD..0218 50.080000 + RHS00001 CD..0219 50.170000 CD..0220 49.210000 + RHS00001 CD..0221 48.460000 CD..0222 44.550000 + RHS00001 CD..0223 37.860000 CD..0224 29.470000 + RHS00001 CD..0301 29.670000 CD..0302 26.310000 + RHS00001 CD..0303 24.570000 CD..0304 23.690000 + RHS00001 CD..0305 23.360000 CD..0306 23.720000 + RHS00001 CD..0307 25.880000 CD..0308 32.560000 + RHS00001 CD..0309 39.030000 CD..0310 41.650000 + RHS00001 CD..0311 42.240000 CD..0312 41.480000 + RHS00001 CD..0313 39.650000 CD..0314 36.900000 + RHS00001 CD..0315 37.880000 CD..0316 39.170000 + RHS00001 CD..0317 41.440000 CD..0318 49.210000 + RHS00001 CD..0319 52.290000 CD..0320 51.750000 + RHS00001 CD..0321 51.040000 CD..0322 48.570000 + RHS00001 CD..0323 43.870000 CD..0324 37.440000 + RHS00001 SURD0101 196.530000 SURD0102 173.200000 + RHS00001 SURD0103 161.740000 SURD0104 157.820000 + RHS00001 SURD0105 157.660000 SURD0106 164.120000 + RHS00001 SURD0107 197.410000 SURD0108 264.490000 + RHS00001 SURD0109 309.680000 SURD0110 335.720000 + RHS00001 SURD0111 339.300000 SURD0112 335.740000 + RHS00001 SURD0113 324.510000 SURD0114 294.180000 + RHS00001 SURD0115 300.660000 SURD0116 311.660000 + RHS00001 SURD0117 329.070000 SURD0118 384.120000 + RHS00001 SURD0119 393.000000 SURD0120 385.800000 + RHS00001 SURD0121 369.890000 SURD0122 344.510000 + RHS00001 SURD0123 312.720000 SURD0124 263.180000 + RHS00001 SURD0201 22.490000 SURD0202 19.800000 + RHS00001 SURD0203 18.900000 SURD0204 18.470000 + RHS00001 SURD0205 18.590000 SURD0206 20.260000 + RHS00001 SURD0207 27.450000 SURD0208 38.910000 + RHS00001 SURD0209 42.560000 SURD0210 44.540000 + RHS00001 SURD0211 44.410000 SURD0212 43.300000 + RHS00001 SURD0213 41.620000 SURD0214 37.730000 + RHS00001 SURD0215 40.090000 SURD0216 42.430000 + RHS00001 SURD0217 43.740000 SURD0218 50.080000 + RHS00001 SURD0219 50.170000 SURD0220 49.210000 + RHS00001 SURD0221 48.460000 SURD0222 44.550000 + RHS00001 SURD0223 37.860000 SURD0224 29.470000 + RHS00001 SURD0301 29.670000 SURD0302 26.310000 + RHS00001 SURD0303 24.570000 SURD0304 23.690000 + RHS00001 SURD0305 23.360000 SURD0306 23.720000 + RHS00001 SURD0307 25.880000 SURD0308 32.560000 + RHS00001 SURD0309 39.030000 SURD0310 41.650000 + RHS00001 SURD0311 42.240000 SURD0312 41.480000 + RHS00001 SURD0313 39.650000 SURD0314 36.900000 + RHS00001 SURD0315 37.880000 SURD0316 39.170000 + RHS00001 SURD0317 41.440000 SURD0318 49.210000 + RHS00001 SURD0319 52.290000 SURD0320 51.750000 + RHS00001 SURD0321 51.040000 SURD0322 48.570000 + RHS00001 SURD0323 43.870000 SURD0324 37.440000 + RHS00001 S12D..01 219.020000 S12D..02 193.000000 + RHS00001 S12D..03 180.640000 S12D..04 176.290000 + RHS00001 S12D..05 176.250000 S12D..06 184.380000 + RHS00001 S12D..07 224.860000 S12D..08 303.400000 + RHS00001 S12D..09 352.240000 S12D..10 380.260000 + RHS00001 S12D..11 383.710000 S12D..12 379.040000 + RHS00001 S12D..13 366.130000 S12D..14 331.910000 + RHS00001 S12D..15 340.750000 S12D..16 354.090000 + RHS00001 S12D..17 372.810000 S12D..18 434.200000 + RHS00001 S12D..19 443.170000 S12D..20 435.010000 + RHS00001 S12D..21 418.350000 S12D..22 389.060000 + RHS00001 S12D..23 350.580000 S12D..24 292.650000 + RHS00001 S13D..01 226.200000 S13D..02 199.510000 + RHS00001 S13D..03 186.310000 S13D..04 181.510000 + RHS00001 S13D..05 181.020000 S13D..06 187.840000 + RHS00001 S13D..07 223.290000 S13D..08 297.050000 + RHS00001 S13D..09 348.710000 S13D..10 377.370000 + RHS00001 S13D..11 381.540000 S13D..12 377.220000 + RHS00001 S13D..13 364.160000 S13D..14 331.080000 + RHS00001 S13D..15 338.540000 S13D..16 350.830000 + RHS00001 S13D..17 370.510000 S13D..18 433.330000 + RHS00001 S13D..19 445.290000 S13D..20 437.550000 + RHS00001 S13D..21 420.930000 S13D..22 393.080000 + RHS00001 S13D..23 356.590000 S13D..24 300.620000 + RHS00001 S123D.01 248.690000 S123D.02 219.310000 + RHS00001 S123D.03 205.210000 S123D.04 199.980000 + RHS00001 S123D.05 199.610000 S123D.06 208.100000 + RHS00001 S123D.07 250.740000 S123D.08 335.960000 + RHS00001 S123D.09 391.270000 S123D.10 421.910000 + RHS00001 S123D.11 425.950000 S123D.12 420.520000 + RHS00001 S123D.13 405.780000 S123D.14 368.810000 + RHS00001 S123D.15 378.630000 S123D.16 393.260000 + RHS00001 S123D.17 414.250000 S123D.18 483.410000 + RHS00001 S123D.19 495.460000 S123D.20 486.760000 + RHS00001 S123D.21 469.390000 S123D.22 437.630000 + RHS00001 S123D.23 394.450000 S123D.24 330.090000 + RHS00001 AD..1201 1.000000 AD..1202 1.000000 + RHS00001 AD..1203 1.000000 AD..1204 1.000000 + RHS00001 AD..1205 1.000000 AD..1206 1.000000 + RHS00001 AD..1207 1.000000 AD..1208 1.000000 + RHS00001 AD..1209 1.000000 AD..1210 1.000000 + RHS00001 AD..1211 1.000000 AD..1212 1.000000 + RHS00001 AD..1213 1.000000 AD..1214 1.000000 + RHS00001 AD..1215 1.000000 AD..1216 1.000000 + RHS00001 AD..1217 1.000000 AD..1218 1.000000 + RHS00001 AD..1219 1.000000 AD..1220 1.000000 + RHS00001 AD..1221 1.000000 AD..1222 1.000000 + RHS00001 AD..1223 1.000000 AD..1224 1.000000 + RHS00001 AD..1301 1.000000 AD..1302 1.000000 + RHS00001 AD..1303 1.000000 AD..1304 1.000000 + RHS00001 AD..1305 1.000000 AD..1306 1.000000 + RHS00001 AD..1307 1.000000 AD..1308 1.000000 + RHS00001 AD..1309 1.000000 AD..1310 1.000000 + RHS00001 AD..1311 1.000000 AD..1312 1.000000 + RHS00001 AD..1313 1.000000 AD..1314 1.000000 + RHS00001 AD..1315 1.000000 AD..1316 1.000000 + RHS00001 AD..1317 1.000000 AD..1318 1.000000 + RHS00001 AD..1319 1.000000 AD..1320 1.000000 + RHS00001 AD..1321 1.000000 AD..1322 1.000000 + RHS00001 AD..1323 1.000000 AD..1324 1.000000 +BOUNDS + BV BOUND001 y...3101 + BV BOUND001 y...2201 + BV BOUND001 y...3201 + BV BOUND001 y...1301 + BV BOUND001 y...2301 + UI BOUND001 y...3301 4.000000 + UI BOUND001 y...1401 2.000000 + UI BOUND001 y...2401 3.000000 + UI BOUND001 y...3401 3.000000 + UI BOUND001 y...1501 2.000000 + UI BOUND001 y...3501 2.000000 + BV BOUND001 y...1601 + UI BOUND001 y...1701 2.000000 + BV BOUND001 y...3102 + BV BOUND001 y...2202 + BV BOUND001 y...3202 + BV BOUND001 y...1302 + BV BOUND001 y...2302 + UI BOUND001 y...3302 4.000000 + UI BOUND001 y...1402 2.000000 + UI BOUND001 y...2402 3.000000 + UI BOUND001 y...3402 3.000000 + UI BOUND001 y...1502 2.000000 + UI BOUND001 y...3502 2.000000 + BV BOUND001 y...1602 + UI BOUND001 y...1702 2.000000 + BV BOUND001 y...3103 + BV BOUND001 y...2203 + BV BOUND001 y...3203 + BV BOUND001 y...1303 + BV BOUND001 y...2303 + UI BOUND001 y...3303 4.000000 + UI BOUND001 y...1403 2.000000 + UI BOUND001 y...2403 3.000000 + UI BOUND001 y...3403 3.000000 + UI BOUND001 y...1503 2.000000 + UI BOUND001 y...3503 2.000000 + BV BOUND001 y...1603 + UI BOUND001 y...1703 2.000000 + BV BOUND001 y...3104 + BV BOUND001 y...2204 + BV BOUND001 y...3204 + BV BOUND001 y...1304 + BV BOUND001 y...2304 + UI BOUND001 y...3304 4.000000 + UI BOUND001 y...1404 2.000000 + UI BOUND001 y...2404 3.000000 + UI BOUND001 y...3404 3.000000 + UI BOUND001 y...1504 2.000000 + UI BOUND001 y...3504 2.000000 + BV BOUND001 y...1604 + UI BOUND001 y...1704 2.000000 + BV BOUND001 y...3105 + BV BOUND001 y...2205 + BV BOUND001 y...3205 + BV BOUND001 y...1305 + BV BOUND001 y...2305 + UI BOUND001 y...3305 4.000000 + UI BOUND001 y...1405 2.000000 + UI BOUND001 y...2405 3.000000 + UI BOUND001 y...3405 3.000000 + UI BOUND001 y...1505 2.000000 + UI BOUND001 y...3505 2.000000 + BV BOUND001 y...1605 + UI BOUND001 y...1705 2.000000 + BV BOUND001 y...3106 + BV BOUND001 y...2206 + BV BOUND001 y...3206 + BV BOUND001 y...1306 + BV BOUND001 y...2306 + UI BOUND001 y...3306 4.000000 + UI BOUND001 y...1406 2.000000 + UI BOUND001 y...2406 3.000000 + UI BOUND001 y...3406 3.000000 + UI BOUND001 y...1506 2.000000 + UI BOUND001 y...3506 2.000000 + BV BOUND001 y...1606 + UI BOUND001 y...1706 2.000000 + BV BOUND001 y...3107 + BV BOUND001 y...2207 + BV BOUND001 y...3207 + BV BOUND001 y...1307 + BV BOUND001 y...2307 + UI BOUND001 y...3307 4.000000 + UI BOUND001 y...1407 2.000000 + UI BOUND001 y...2407 3.000000 + UI BOUND001 y...3407 3.000000 + UI BOUND001 y...1507 2.000000 + UI BOUND001 y...3507 2.000000 + BV BOUND001 y...1607 + UI BOUND001 y...1707 2.000000 + BV BOUND001 y...3108 + BV BOUND001 y...2208 + BV BOUND001 y...3208 + BV BOUND001 y...1308 + BV BOUND001 y...2308 + UI BOUND001 y...3308 4.000000 + UI BOUND001 y...1408 2.000000 + UI BOUND001 y...2408 3.000000 + UI BOUND001 y...3408 3.000000 + UI BOUND001 y...1508 2.000000 + UI BOUND001 y...3508 2.000000 + BV BOUND001 y...1608 + UI BOUND001 y...1708 2.000000 + BV BOUND001 y...3109 + BV BOUND001 y...2209 + BV BOUND001 y...3209 + BV BOUND001 y...1309 + BV BOUND001 y...2309 + UI BOUND001 y...3309 4.000000 + UI BOUND001 y...1409 2.000000 + UI BOUND001 y...2409 3.000000 + UI BOUND001 y...3409 3.000000 + UI BOUND001 y...1509 2.000000 + UI BOUND001 y...3509 2.000000 + BV BOUND001 y...1609 + UI BOUND001 y...1709 2.000000 + BV BOUND001 y...3110 + BV BOUND001 y...2210 + BV BOUND001 y...3210 + BV BOUND001 y...1310 + BV BOUND001 y...2310 + UI BOUND001 y...3310 4.000000 + UI BOUND001 y...1410 2.000000 + UI BOUND001 y...2410 3.000000 + UI BOUND001 y...3410 3.000000 + UI BOUND001 y...1510 2.000000 + UI BOUND001 y...3510 2.000000 + BV BOUND001 y...1610 + UI BOUND001 y...1710 2.000000 + BV BOUND001 y...3111 + BV BOUND001 y...2211 + BV BOUND001 y...3211 + BV BOUND001 y...1311 + BV BOUND001 y...2311 + UI BOUND001 y...3311 4.000000 + UI BOUND001 y...1411 2.000000 + UI BOUND001 y...2411 3.000000 + UI BOUND001 y...3411 3.000000 + UI BOUND001 y...1511 2.000000 + UI BOUND001 y...3511 2.000000 + BV BOUND001 y...1611 + UI BOUND001 y...1711 2.000000 + BV BOUND001 y...3112 + BV BOUND001 y...2212 + BV BOUND001 y...3212 + BV BOUND001 y...1312 + BV BOUND001 y...2312 + UI BOUND001 y...3312 4.000000 + UI BOUND001 y...1412 2.000000 + UI BOUND001 y...2412 3.000000 + UI BOUND001 y...3412 3.000000 + UI BOUND001 y...1512 2.000000 + UI BOUND001 y...3512 2.000000 + BV BOUND001 y...1612 + UI BOUND001 y...1712 2.000000 + BV BOUND001 y...3113 + BV BOUND001 y...2213 + BV BOUND001 y...3213 + BV BOUND001 y...1313 + BV BOUND001 y...2313 + UI BOUND001 y...3313 4.000000 + UI BOUND001 y...1413 2.000000 + UI BOUND001 y...2413 3.000000 + UI BOUND001 y...3413 3.000000 + UI BOUND001 y...1513 2.000000 + UI BOUND001 y...3513 2.000000 + BV BOUND001 y...1613 + UI BOUND001 y...1713 2.000000 + BV BOUND001 y...3114 + BV BOUND001 y...2214 + BV BOUND001 y...3214 + BV BOUND001 y...1314 + BV BOUND001 y...2314 + UI BOUND001 y...3314 4.000000 + UI BOUND001 y...1414 2.000000 + UI BOUND001 y...2414 3.000000 + UI BOUND001 y...3414 3.000000 + UI BOUND001 y...1514 2.000000 + UI BOUND001 y...3514 2.000000 + BV BOUND001 y...1614 + UI BOUND001 y...1714 2.000000 + BV BOUND001 y...3115 + BV BOUND001 y...2215 + BV BOUND001 y...3215 + BV BOUND001 y...1315 + BV BOUND001 y...2315 + UI BOUND001 y...3315 4.000000 + UI BOUND001 y...1415 2.000000 + UI BOUND001 y...2415 3.000000 + UI BOUND001 y...3415 3.000000 + UI BOUND001 y...1515 2.000000 + UI BOUND001 y...3515 2.000000 + BV BOUND001 y...1615 + UI BOUND001 y...1715 2.000000 + BV BOUND001 y...3116 + BV BOUND001 y...2216 + BV BOUND001 y...3216 + BV BOUND001 y...1316 + BV BOUND001 y...2316 + UI BOUND001 y...3316 4.000000 + UI BOUND001 y...1416 2.000000 + UI BOUND001 y...2416 3.000000 + UI BOUND001 y...3416 3.000000 + UI BOUND001 y...1516 2.000000 + UI BOUND001 y...3516 2.000000 + BV BOUND001 y...1616 + UI BOUND001 y...1716 2.000000 + BV BOUND001 y...3117 + BV BOUND001 y...2217 + BV BOUND001 y...3217 + BV BOUND001 y...1317 + BV BOUND001 y...2317 + UI BOUND001 y...3317 4.000000 + UI BOUND001 y...1417 2.000000 + UI BOUND001 y...2417 3.000000 + UI BOUND001 y...3417 3.000000 + UI BOUND001 y...1517 2.000000 + UI BOUND001 y...3517 2.000000 + BV BOUND001 y...1617 + UI BOUND001 y...1717 2.000000 + BV BOUND001 y...3118 + BV BOUND001 y...2218 + BV BOUND001 y...3218 + BV BOUND001 y...1318 + BV BOUND001 y...2318 + UI BOUND001 y...3318 4.000000 + UI BOUND001 y...1418 2.000000 + UI BOUND001 y...2418 3.000000 + UI BOUND001 y...3418 3.000000 + UI BOUND001 y...1518 2.000000 + UI BOUND001 y...3518 2.000000 + BV BOUND001 y...1618 + UI BOUND001 y...1718 2.000000 + BV BOUND001 y...3119 + BV BOUND001 y...2219 + BV BOUND001 y...3219 + BV BOUND001 y...1319 + BV BOUND001 y...2319 + UI BOUND001 y...3319 4.000000 + UI BOUND001 y...1419 2.000000 + UI BOUND001 y...2419 3.000000 + UI BOUND001 y...3419 3.000000 + UI BOUND001 y...1519 2.000000 + UI BOUND001 y...3519 2.000000 + BV BOUND001 y...1619 + UI BOUND001 y...1719 2.000000 + BV BOUND001 y...3120 + BV BOUND001 y...2220 + BV BOUND001 y...3220 + BV BOUND001 y...1320 + BV BOUND001 y...2320 + UI BOUND001 y...3320 4.000000 + UI BOUND001 y...1420 2.000000 + UI BOUND001 y...2420 3.000000 + UI BOUND001 y...3420 3.000000 + UI BOUND001 y...1520 2.000000 + UI BOUND001 y...3520 2.000000 + BV BOUND001 y...1620 + UI BOUND001 y...1720 2.000000 + BV BOUND001 y...3121 + BV BOUND001 y...2221 + BV BOUND001 y...3221 + BV BOUND001 y...1321 + BV BOUND001 y...2321 + UI BOUND001 y...3321 4.000000 + UI BOUND001 y...1421 2.000000 + UI BOUND001 y...2421 3.000000 + UI BOUND001 y...3421 3.000000 + UI BOUND001 y...1521 2.000000 + UI BOUND001 y...3521 2.000000 + BV BOUND001 y...1621 + UI BOUND001 y...1721 2.000000 + BV BOUND001 y...3122 + BV BOUND001 y...2222 + BV BOUND001 y...3222 + BV BOUND001 y...1322 + BV BOUND001 y...2322 + UI BOUND001 y...3322 4.000000 + UI BOUND001 y...1422 2.000000 + UI BOUND001 y...2422 3.000000 + UI BOUND001 y...3422 3.000000 + UI BOUND001 y...1522 2.000000 + UI BOUND001 y...3522 2.000000 + BV BOUND001 y...1622 + UI BOUND001 y...1722 2.000000 + BV BOUND001 y...3123 + BV BOUND001 y...2223 + BV BOUND001 y...3223 + BV BOUND001 y...1323 + BV BOUND001 y...2323 + UI BOUND001 y...3323 4.000000 + UI BOUND001 y...1423 2.000000 + UI BOUND001 y...2423 3.000000 + UI BOUND001 y...3423 3.000000 + UI BOUND001 y...1523 2.000000 + UI BOUND001 y...3523 2.000000 + BV BOUND001 y...1623 + UI BOUND001 y...1723 2.000000 + BV BOUND001 y...3124 + BV BOUND001 y...2224 + BV BOUND001 y...3224 + BV BOUND001 y...1324 + BV BOUND001 y...2324 + UI BOUND001 y...3324 4.000000 + UI BOUND001 y...1424 2.000000 + UI BOUND001 y...2424 3.000000 + UI BOUND001 y...3424 3.000000 + UI BOUND001 y...1524 2.000000 + UI BOUND001 y...3524 2.000000 + BV BOUND001 y...1624 + UI BOUND001 y...1724 2.000000 + UP BOUND001 z...3101 1.000000 + UP BOUND001 z...2201 1.000000 + UP BOUND001 z...3201 1.000000 + UP BOUND001 z...1301 1.000000 + UP BOUND001 z...2301 1.000000 + UP BOUND001 z...3301 4.000000 + UP BOUND001 z...1401 2.000000 + UP BOUND001 z...2401 3.000000 + UP BOUND001 z...3401 3.000000 + UP BOUND001 z...1501 2.000000 + UP BOUND001 z...3501 2.000000 + UP BOUND001 z...1601 1.000000 + UP BOUND001 z...1701 2.000000 + UP BOUND001 z...3102 1.000000 + UP BOUND001 z...2202 1.000000 + UP BOUND001 z...3202 1.000000 + UP BOUND001 z...1302 1.000000 + UP BOUND001 z...2302 1.000000 + UP BOUND001 z...3302 4.000000 + UP BOUND001 z...1402 2.000000 + UP BOUND001 z...2402 3.000000 + UP BOUND001 z...3402 3.000000 + UP BOUND001 z...1502 2.000000 + UP BOUND001 z...3502 2.000000 + UP BOUND001 z...1602 1.000000 + UP BOUND001 z...1702 2.000000 + UP BOUND001 z...3103 1.000000 + UP BOUND001 z...2203 1.000000 + UP BOUND001 z...3203 1.000000 + UP BOUND001 z...1303 1.000000 + UP BOUND001 z...2303 1.000000 + UP BOUND001 z...3303 4.000000 + UP BOUND001 z...1403 2.000000 + UP BOUND001 z...2403 3.000000 + UP BOUND001 z...3403 3.000000 + UP BOUND001 z...1503 2.000000 + UP BOUND001 z...3503 2.000000 + UP BOUND001 z...1603 1.000000 + UP BOUND001 z...1703 2.000000 + UP BOUND001 z...3104 1.000000 + UP BOUND001 z...2204 1.000000 + UP BOUND001 z...3204 1.000000 + UP BOUND001 z...1304 1.000000 + UP BOUND001 z...2304 1.000000 + UP BOUND001 z...3304 4.000000 + UP BOUND001 z...1404 2.000000 + UP BOUND001 z...2404 3.000000 + UP BOUND001 z...3404 3.000000 + UP BOUND001 z...1504 2.000000 + UP BOUND001 z...3504 2.000000 + UP BOUND001 z...1604 1.000000 + UP BOUND001 z...1704 2.000000 + UP BOUND001 z...3105 1.000000 + UP BOUND001 z...2205 1.000000 + UP BOUND001 z...3205 1.000000 + UP BOUND001 z...1305 1.000000 + UP BOUND001 z...2305 1.000000 + UP BOUND001 z...3305 4.000000 + UP BOUND001 z...1405 2.000000 + UP BOUND001 z...2405 3.000000 + UP BOUND001 z...3405 3.000000 + UP BOUND001 z...1505 2.000000 + UP BOUND001 z...3505 2.000000 + UP BOUND001 z...1605 1.000000 + UP BOUND001 z...1705 2.000000 + UP BOUND001 z...3106 1.000000 + UP BOUND001 z...2206 1.000000 + UP BOUND001 z...3206 1.000000 + UP BOUND001 z...1306 1.000000 + UP BOUND001 z...2306 1.000000 + UP BOUND001 z...3306 4.000000 + UP BOUND001 z...1406 2.000000 + UP BOUND001 z...2406 3.000000 + UP BOUND001 z...3406 3.000000 + UP BOUND001 z...1506 2.000000 + UP BOUND001 z...3506 2.000000 + UP BOUND001 z...1606 1.000000 + UP BOUND001 z...1706 2.000000 + UP BOUND001 z...3107 1.000000 + UP BOUND001 z...2207 1.000000 + UP BOUND001 z...3207 1.000000 + UP BOUND001 z...1307 1.000000 + UP BOUND001 z...2307 1.000000 + UP BOUND001 z...3307 4.000000 + UP BOUND001 z...1407 2.000000 + UP BOUND001 z...2407 3.000000 + UP BOUND001 z...3407 3.000000 + UP BOUND001 z...1507 2.000000 + UP BOUND001 z...3507 2.000000 + UP BOUND001 z...1607 1.000000 + UP BOUND001 z...1707 2.000000 + UP BOUND001 z...3108 1.000000 + UP BOUND001 z...2208 1.000000 + UP BOUND001 z...3208 1.000000 + UP BOUND001 z...1308 1.000000 + UP BOUND001 z...2308 1.000000 + UP BOUND001 z...3308 4.000000 + UP BOUND001 z...1408 2.000000 + UP BOUND001 z...2408 3.000000 + UP BOUND001 z...3408 3.000000 + UP BOUND001 z...1508 2.000000 + UP BOUND001 z...3508 2.000000 + UP BOUND001 z...1608 1.000000 + UP BOUND001 z...1708 2.000000 + UP BOUND001 z...3109 1.000000 + UP BOUND001 z...2209 1.000000 + UP BOUND001 z...3209 1.000000 + UP BOUND001 z...1309 1.000000 + UP BOUND001 z...2309 1.000000 + UP BOUND001 z...3309 4.000000 + UP BOUND001 z...1409 2.000000 + UP BOUND001 z...2409 3.000000 + UP BOUND001 z...3409 3.000000 + UP BOUND001 z...1509 2.000000 + UP BOUND001 z...3509 2.000000 + UP BOUND001 z...1609 1.000000 + UP BOUND001 z...1709 2.000000 + UP BOUND001 z...3110 1.000000 + UP BOUND001 z...2210 1.000000 + UP BOUND001 z...3210 1.000000 + UP BOUND001 z...1310 1.000000 + UP BOUND001 z...2310 1.000000 + UP BOUND001 z...3310 4.000000 + UP BOUND001 z...1410 2.000000 + UP BOUND001 z...2410 3.000000 + UP BOUND001 z...3410 3.000000 + UP BOUND001 z...1510 2.000000 + UP BOUND001 z...3510 2.000000 + UP BOUND001 z...1610 1.000000 + UP BOUND001 z...1710 2.000000 + UP BOUND001 z...3111 1.000000 + UP BOUND001 z...2211 1.000000 + UP BOUND001 z...3211 1.000000 + UP BOUND001 z...1311 1.000000 + UP BOUND001 z...2311 1.000000 + UP BOUND001 z...3311 4.000000 + UP BOUND001 z...1411 2.000000 + UP BOUND001 z...2411 3.000000 + UP BOUND001 z...3411 3.000000 + UP BOUND001 z...1511 2.000000 + UP BOUND001 z...3511 2.000000 + UP BOUND001 z...1611 1.000000 + UP BOUND001 z...1711 2.000000 + UP BOUND001 z...3112 1.000000 + UP BOUND001 z...2212 1.000000 + UP BOUND001 z...3212 1.000000 + UP BOUND001 z...1312 1.000000 + UP BOUND001 z...2312 1.000000 + UP BOUND001 z...3312 4.000000 + UP BOUND001 z...1412 2.000000 + UP BOUND001 z...2412 3.000000 + UP BOUND001 z...3412 3.000000 + UP BOUND001 z...1512 2.000000 + UP BOUND001 z...3512 2.000000 + UP BOUND001 z...1612 1.000000 + UP BOUND001 z...1712 2.000000 + UP BOUND001 z...3113 1.000000 + UP BOUND001 z...2213 1.000000 + UP BOUND001 z...3213 1.000000 + UP BOUND001 z...1313 1.000000 + UP BOUND001 z...2313 1.000000 + UP BOUND001 z...3313 4.000000 + UP BOUND001 z...1413 2.000000 + UP BOUND001 z...2413 3.000000 + UP BOUND001 z...3413 3.000000 + UP BOUND001 z...1513 2.000000 + UP BOUND001 z...3513 2.000000 + UP BOUND001 z...1613 1.000000 + UP BOUND001 z...1713 2.000000 + UP BOUND001 z...3114 1.000000 + UP BOUND001 z...2214 1.000000 + UP BOUND001 z...3214 1.000000 + UP BOUND001 z...1314 1.000000 + UP BOUND001 z...2314 1.000000 + UP BOUND001 z...3314 4.000000 + UP BOUND001 z...1414 2.000000 + UP BOUND001 z...2414 3.000000 + UP BOUND001 z...3414 3.000000 + UP BOUND001 z...1514 2.000000 + UP BOUND001 z...3514 2.000000 + UP BOUND001 z...1614 1.000000 + UP BOUND001 z...1714 2.000000 + UP BOUND001 z...3115 1.000000 + UP BOUND001 z...2215 1.000000 + UP BOUND001 z...3215 1.000000 + UP BOUND001 z...1315 1.000000 + UP BOUND001 z...2315 1.000000 + UP BOUND001 z...3315 4.000000 + UP BOUND001 z...1415 2.000000 + UP BOUND001 z...2415 3.000000 + UP BOUND001 z...3415 3.000000 + UP BOUND001 z...1515 2.000000 + UP BOUND001 z...3515 2.000000 + UP BOUND001 z...1615 1.000000 + UP BOUND001 z...1715 2.000000 + UP BOUND001 z...3116 1.000000 + UP BOUND001 z...2216 1.000000 + UP BOUND001 z...3216 1.000000 + UP BOUND001 z...1316 1.000000 + UP BOUND001 z...2316 1.000000 + UP BOUND001 z...3316 4.000000 + UP BOUND001 z...1416 2.000000 + UP BOUND001 z...2416 3.000000 + UP BOUND001 z...3416 3.000000 + UP BOUND001 z...1516 2.000000 + UP BOUND001 z...3516 2.000000 + UP BOUND001 z...1616 1.000000 + UP BOUND001 z...1716 2.000000 + UP BOUND001 z...3117 1.000000 + UP BOUND001 z...2217 1.000000 + UP BOUND001 z...3217 1.000000 + UP BOUND001 z...1317 1.000000 + UP BOUND001 z...2317 1.000000 + UP BOUND001 z...3317 4.000000 + UP BOUND001 z...1417 2.000000 + UP BOUND001 z...2417 3.000000 + UP BOUND001 z...3417 3.000000 + UP BOUND001 z...1517 2.000000 + UP BOUND001 z...3517 2.000000 + UP BOUND001 z...1617 1.000000 + UP BOUND001 z...1717 2.000000 + UP BOUND001 z...3118 1.000000 + UP BOUND001 z...2218 1.000000 + UP BOUND001 z...3218 1.000000 + UP BOUND001 z...1318 1.000000 + UP BOUND001 z...2318 1.000000 + UP BOUND001 z...3318 4.000000 + UP BOUND001 z...1418 2.000000 + UP BOUND001 z...2418 3.000000 + UP BOUND001 z...3418 3.000000 + UP BOUND001 z...1518 2.000000 + UP BOUND001 z...3518 2.000000 + UP BOUND001 z...1618 1.000000 + UP BOUND001 z...1718 2.000000 + UP BOUND001 z...3119 1.000000 + UP BOUND001 z...2219 1.000000 + UP BOUND001 z...3219 1.000000 + UP BOUND001 z...1319 1.000000 + UP BOUND001 z...2319 1.000000 + UP BOUND001 z...3319 4.000000 + UP BOUND001 z...1419 2.000000 + UP BOUND001 z...2419 3.000000 + UP BOUND001 z...3419 3.000000 + UP BOUND001 z...1519 2.000000 + UP BOUND001 z...3519 2.000000 + UP BOUND001 z...1619 1.000000 + UP BOUND001 z...1719 2.000000 + UP BOUND001 z...3120 1.000000 + UP BOUND001 z...2220 1.000000 + UP BOUND001 z...3220 1.000000 + UP BOUND001 z...1320 1.000000 + UP BOUND001 z...2320 1.000000 + UP BOUND001 z...3320 4.000000 + UP BOUND001 z...1420 2.000000 + UP BOUND001 z...2420 3.000000 + UP BOUND001 z...3420 3.000000 + UP BOUND001 z...1520 2.000000 + UP BOUND001 z...3520 2.000000 + UP BOUND001 z...1620 1.000000 + UP BOUND001 z...1720 2.000000 + UP BOUND001 z...3121 1.000000 + UP BOUND001 z...2221 1.000000 + UP BOUND001 z...3221 1.000000 + UP BOUND001 z...1321 1.000000 + UP BOUND001 z...2321 1.000000 + UP BOUND001 z...3321 4.000000 + UP BOUND001 z...1421 2.000000 + UP BOUND001 z...2421 3.000000 + UP BOUND001 z...3421 3.000000 + UP BOUND001 z...1521 2.000000 + UP BOUND001 z...3521 2.000000 + UP BOUND001 z...1621 1.000000 + UP BOUND001 z...1721 2.000000 + UP BOUND001 z...3122 1.000000 + UP BOUND001 z...2222 1.000000 + UP BOUND001 z...3222 1.000000 + UP BOUND001 z...1322 1.000000 + UP BOUND001 z...2322 1.000000 + UP BOUND001 z...3322 4.000000 + UP BOUND001 z...1422 2.000000 + UP BOUND001 z...2422 3.000000 + UP BOUND001 z...3422 3.000000 + UP BOUND001 z...1522 2.000000 + UP BOUND001 z...3522 2.000000 + UP BOUND001 z...1622 1.000000 + UP BOUND001 z...1722 2.000000 + UP BOUND001 z...3123 1.000000 + UP BOUND001 z...2223 1.000000 + UP BOUND001 z...3223 1.000000 + UP BOUND001 z...1323 1.000000 + UP BOUND001 z...2323 1.000000 + UP BOUND001 z...3323 4.000000 + UP BOUND001 z...1423 2.000000 + UP BOUND001 z...2423 3.000000 + UP BOUND001 z...3423 3.000000 + UP BOUND001 z...1523 2.000000 + UP BOUND001 z...3523 2.000000 + UP BOUND001 z...1623 1.000000 + UP BOUND001 z...1723 2.000000 + UP BOUND001 z...3124 1.000000 + UP BOUND001 z...2224 1.000000 + UP BOUND001 z...3224 1.000000 + UP BOUND001 z...1324 1.000000 + UP BOUND001 z...2324 1.000000 + UP BOUND001 z...3324 4.000000 + UP BOUND001 z...1424 2.000000 + UP BOUND001 z...2424 3.000000 + UP BOUND001 z...3424 3.000000 + UP BOUND001 z...1524 2.000000 + UP BOUND001 z...3524 2.000000 + UP BOUND001 z...1624 1.000000 + UP BOUND001 z...1724 2.000000 + BV BOUND001 yv..2101 + BV BOUND001 yv..3101 + BV BOUND001 yv..1201 + BV BOUND001 yv..1301 + BV BOUND001 yv..2102 + BV BOUND001 yv..3102 + BV BOUND001 yv..1202 + BV BOUND001 yv..1302 + BV BOUND001 yv..2103 + BV BOUND001 yv..3103 + BV BOUND001 yv..1203 + BV BOUND001 yv..1303 + BV BOUND001 yv..2104 + BV BOUND001 yv..3104 + BV BOUND001 yv..1204 + BV BOUND001 yv..1304 + BV BOUND001 yv..2105 + BV BOUND001 yv..3105 + BV BOUND001 yv..1205 + BV BOUND001 yv..1305 + BV BOUND001 yv..2106 + BV BOUND001 yv..3106 + BV BOUND001 yv..1206 + BV BOUND001 yv..1306 + BV BOUND001 yv..2107 + BV BOUND001 yv..3107 + BV BOUND001 yv..1207 + BV BOUND001 yv..1307 + BV BOUND001 yv..2108 + BV BOUND001 yv..3108 + BV BOUND001 yv..1208 + BV BOUND001 yv..1308 + BV BOUND001 yv..2109 + BV BOUND001 yv..3109 + BV BOUND001 yv..1209 + BV BOUND001 yv..1309 + BV BOUND001 yv..2110 + BV BOUND001 yv..3110 + BV BOUND001 yv..1210 + BV BOUND001 yv..1310 + BV BOUND001 yv..2111 + BV BOUND001 yv..3111 + BV BOUND001 yv..1211 + BV BOUND001 yv..1311 + BV BOUND001 yv..2112 + BV BOUND001 yv..3112 + BV BOUND001 yv..1212 + BV BOUND001 yv..1312 + BV BOUND001 yv..2113 + BV BOUND001 yv..3113 + BV BOUND001 yv..1213 + BV BOUND001 yv..1313 + BV BOUND001 yv..2114 + BV BOUND001 yv..3114 + BV BOUND001 yv..1214 + BV BOUND001 yv..1314 + BV BOUND001 yv..2115 + BV BOUND001 yv..3115 + BV BOUND001 yv..1215 + BV BOUND001 yv..1315 + BV BOUND001 yv..2116 + BV BOUND001 yv..3116 + BV BOUND001 yv..1216 + BV BOUND001 yv..1316 + BV BOUND001 yv..2117 + BV BOUND001 yv..3117 + BV BOUND001 yv..1217 + BV BOUND001 yv..1317 + BV BOUND001 yv..2118 + BV BOUND001 yv..3118 + BV BOUND001 yv..1218 + BV BOUND001 yv..1318 + BV BOUND001 yv..2119 + BV BOUND001 yv..3119 + BV BOUND001 yv..1219 + BV BOUND001 yv..1319 + BV BOUND001 yv..2120 + BV BOUND001 yv..3120 + BV BOUND001 yv..1220 + BV BOUND001 yv..1320 + BV BOUND001 yv..2121 + BV BOUND001 yv..3121 + BV BOUND001 yv..1221 + BV BOUND001 yv..1321 + BV BOUND001 yv..2122 + BV BOUND001 yv..3122 + BV BOUND001 yv..1222 + BV BOUND001 yv..1322 + BV BOUND001 yv..2123 + BV BOUND001 yv..3123 + BV BOUND001 yv..1223 + BV BOUND001 yv..1323 + BV BOUND001 yv..2124 + BV BOUND001 yv..3124 + BV BOUND001 yv..1224 + BV BOUND001 yv..1324 +ENDATA diff --git a/check/instances/issue-2095.mps b/check/instances/issue-2095.mps new file mode 100644 index 0000000000..a05dc4ef22 --- /dev/null +++ b/check/instances/issue-2095.mps @@ -0,0 +1,836 @@ +NAME +ROWS + N Obj + E r0 + E r1 + E r2 + E r3 + E r4 + E r5 + E r6 + E r7 + E r8 + E r9 + E r10 + E r11 + E r12 + E r13 + E r14 + E r15 + E r16 + E r17 + E r18 + E r19 + E r20 + E r21 + E r22 + E r23 + E r24 + E r25 + E r26 + E r27 + E r28 +COLUMNS + MARK0000 'MARKER' 'INTORG' + c0 Obj 1 + c0 r0 1 + c1 Obj 1 + c1 r1 1 + c2 Obj 1 + c2 r2 1 + c3 Obj 1 + c3 r3 1 + c4 Obj 1 + c4 r5 1 + c5 Obj 1 + c5 r6 1 + c6 Obj 1 + c6 r7 1 + c7 Obj 1 + c7 r25 1 + c8 Obj 1 + c8 r26 1 + c9 Obj 1 + c9 r27 1 + c10 Obj 1 + c10 r28 1 + c11 Obj 1 + c11 r0 1 + c11 r1 1 + c11 r2 1 + c11 r3 1 + c12 Obj 1 + c12 r1 1 + c12 r2 1 + c12 r3 1 + c12 r4 1 + c13 Obj 1 + c13 r5 1 + c13 r6 1 + c13 r7 1 + c13 r8 1 + c14 Obj 1 + c14 r8 1 + c14 r9 1 + c14 r10 1 + c14 r11 1 + c15 Obj 1 + c15 r24 1 + c15 r25 1 + c15 r26 1 + c15 r27 1 + c16 Obj 1 + c16 r0 1 + c16 r1 1 + c16 r2 1 + c16 r3 1 + c16 r4 1 + c17 Obj 1 + c17 r4 1 + c17 r5 1 + c17 r6 1 + c17 r7 1 + c17 r8 1 + c18 Obj 1 + c18 r5 1 + c18 r6 1 + c18 r7 1 + c18 r8 1 + c18 r9 1 + c19 Obj 1 + c19 r8 1 + c19 r9 1 + c19 r10 1 + c19 r11 1 + c19 r12 1 + c20 Obj 1 + c20 r23 1 + c20 r24 1 + c20 r25 1 + c20 r26 1 + c20 r27 1 + c21 Obj 1 + c21 r4 1 + c21 r5 1 + c21 r6 1 + c21 r7 1 + c21 r8 1 + c21 r9 1 + c22 Obj 1 + c22 r5 1 + c22 r6 1 + c22 r7 1 + c22 r8 1 + c22 r9 1 + c22 r10 1 + c23 Obj 1 + c23 r8 1 + c23 r9 1 + c23 r10 1 + c23 r11 1 + c23 r12 1 + c23 r13 1 + c24 Obj 1 + c24 r22 1 + c24 r23 1 + c24 r24 1 + c24 r25 1 + c24 r26 1 + c24 r27 1 + c25 Obj 1 + c25 r4 1 + c25 r5 1 + c25 r6 1 + c25 r7 1 + c25 r8 1 + c25 r9 1 + c25 r10 1 + c26 Obj 1 + c26 r8 1 + c26 r9 1 + c26 r10 1 + c26 r11 1 + c26 r12 1 + c26 r13 1 + c26 r14 1 + c27 Obj 1 + c27 r21 1 + c27 r22 1 + c27 r23 1 + c27 r24 1 + c27 r25 1 + c27 r26 1 + c27 r27 1 + c28 Obj 1 + c28 r8 1 + c28 r9 1 + c28 r10 1 + c28 r11 1 + c28 r12 1 + c28 r13 1 + c28 r14 1 + c28 r15 1 + c29 Obj 1 + c29 r20 1 + c29 r21 1 + c29 r22 1 + c29 r23 1 + c29 r24 1 + c29 r25 1 + c29 r26 1 + c29 r27 1 + c30 Obj 1 + c30 r8 1 + c30 r9 1 + c30 r10 1 + c30 r11 1 + c30 r12 1 + c30 r13 1 + c30 r14 1 + c30 r15 1 + c30 r16 1 + c31 Obj 1 + c31 r19 1 + c31 r20 1 + c31 r21 1 + c31 r22 1 + c31 r23 1 + c31 r24 1 + c31 r25 1 + c31 r26 1 + c31 r27 1 + c32 Obj 1 + c32 r8 1 + c32 r9 1 + c32 r10 1 + c32 r11 1 + c32 r12 1 + c32 r13 1 + c32 r14 1 + c32 r15 1 + c32 r16 1 + c32 r17 1 + c33 Obj 1 + c33 r18 1 + c33 r19 1 + c33 r20 1 + c33 r21 1 + c33 r22 1 + c33 r23 1 + c33 r24 1 + c33 r25 1 + c33 r26 1 + c33 r27 1 + c34 Obj 1 + c34 r8 1 + c34 r9 1 + c34 r10 1 + c34 r11 1 + c34 r12 1 + c34 r13 1 + c34 r14 1 + c34 r15 1 + c34 r16 1 + c34 r17 1 + c34 r18 1 + c35 Obj 1 + c35 r17 1 + c35 r18 1 + c35 r19 1 + c35 r20 1 + c35 r21 1 + c35 r22 1 + c35 r23 1 + c35 r24 1 + c35 r25 1 + c35 r26 1 + c35 r27 1 + c36 Obj 1 + c36 r7 1 + c36 r8 1 + c36 r9 1 + c36 r10 1 + c36 r11 1 + c36 r12 1 + c36 r13 1 + c36 r14 1 + c36 r15 1 + c36 r16 1 + c36 r17 1 + c36 r18 1 + c37 Obj 1 + c37 r8 1 + c37 r9 1 + c37 r10 1 + c37 r11 1 + c37 r12 1 + c37 r13 1 + c37 r14 1 + c37 r15 1 + c37 r16 1 + c37 r17 1 + c37 r18 1 + c37 r19 1 + c38 Obj 1 + c38 r16 1 + c38 r17 1 + c38 r18 1 + c38 r19 1 + c38 r20 1 + c38 r21 1 + c38 r22 1 + c38 r23 1 + c38 r24 1 + c38 r25 1 + c38 r26 1 + c38 r27 1 + c39 Obj 1 + c39 r17 1 + c39 r18 1 + c39 r19 1 + c39 r20 1 + c39 r21 1 + c39 r22 1 + c39 r23 1 + c39 r24 1 + c39 r25 1 + c39 r26 1 + c39 r27 1 + c39 r28 1 + c40 Obj 1 + c40 r7 1 + c40 r8 1 + c40 r9 1 + c40 r10 1 + c40 r11 1 + c40 r12 1 + c40 r13 1 + c40 r14 1 + c40 r15 1 + c40 r16 1 + c40 r17 1 + c40 r18 1 + c40 r19 1 + c41 Obj 1 + c41 r8 1 + c41 r9 1 + c41 r10 1 + c41 r11 1 + c41 r12 1 + c41 r13 1 + c41 r14 1 + c41 r15 1 + c41 r16 1 + c41 r17 1 + c41 r18 1 + c41 r19 1 + c41 r20 1 + c42 Obj 1 + c42 r15 1 + c42 r16 1 + c42 r17 1 + c42 r18 1 + c42 r19 1 + c42 r20 1 + c42 r21 1 + c42 r22 1 + c42 r23 1 + c42 r24 1 + c42 r25 1 + c42 r26 1 + c42 r27 1 + c43 Obj 1 + c43 r16 1 + c43 r17 1 + c43 r18 1 + c43 r19 1 + c43 r20 1 + c43 r21 1 + c43 r22 1 + c43 r23 1 + c43 r24 1 + c43 r25 1 + c43 r26 1 + c43 r27 1 + c43 r28 1 + c44 Obj 1 + c44 r7 1 + c44 r8 1 + c44 r9 1 + c44 r10 1 + c44 r11 1 + c44 r12 1 + c44 r13 1 + c44 r14 1 + c44 r15 1 + c44 r16 1 + c44 r17 1 + c44 r18 1 + c44 r19 1 + c44 r20 1 + c45 Obj 1 + c45 r8 1 + c45 r9 1 + c45 r10 1 + c45 r11 1 + c45 r12 1 + c45 r13 1 + c45 r14 1 + c45 r15 1 + c45 r16 1 + c45 r17 1 + c45 r18 1 + c45 r19 1 + c45 r20 1 + c45 r21 1 + c46 Obj 1 + c46 r14 1 + c46 r15 1 + c46 r16 1 + c46 r17 1 + c46 r18 1 + c46 r19 1 + c46 r20 1 + c46 r21 1 + c46 r22 1 + c46 r23 1 + c46 r24 1 + c46 r25 1 + c46 r26 1 + c46 r27 1 + c47 Obj 1 + c47 r15 1 + c47 r16 1 + c47 r17 1 + c47 r18 1 + c47 r19 1 + c47 r20 1 + c47 r21 1 + c47 r22 1 + c47 r23 1 + c47 r24 1 + c47 r25 1 + c47 r26 1 + c47 r27 1 + c47 r28 1 + c48 Obj 1 + c48 r7 1 + c48 r8 1 + c48 r9 1 + c48 r10 1 + c48 r11 1 + c48 r12 1 + c48 r13 1 + c48 r14 1 + c48 r15 1 + c48 r16 1 + c48 r17 1 + c48 r18 1 + c48 r19 1 + c48 r20 1 + c48 r21 1 + c49 Obj 1 + c49 r8 1 + c49 r9 1 + c49 r10 1 + c49 r11 1 + c49 r12 1 + c49 r13 1 + c49 r14 1 + c49 r15 1 + c49 r16 1 + c49 r17 1 + c49 r18 1 + c49 r19 1 + c49 r20 1 + c49 r21 1 + c49 r22 1 + c50 Obj 1 + c50 r13 1 + c50 r14 1 + c50 r15 1 + c50 r16 1 + c50 r17 1 + c50 r18 1 + c50 r19 1 + c50 r20 1 + c50 r21 1 + c50 r22 1 + c50 r23 1 + c50 r24 1 + c50 r25 1 + c50 r26 1 + c50 r27 1 + c51 Obj 1 + c51 r14 1 + c51 r15 1 + c51 r16 1 + c51 r17 1 + c51 r18 1 + c51 r19 1 + c51 r20 1 + c51 r21 1 + c51 r22 1 + c51 r23 1 + c51 r24 1 + c51 r25 1 + c51 r26 1 + c51 r27 1 + c51 r28 1 + c52 Obj 1 + c52 r7 1 + c52 r8 1 + c52 r9 1 + c52 r10 1 + c52 r11 1 + c52 r12 1 + c52 r13 1 + c52 r14 1 + c52 r15 1 + c52 r16 1 + c52 r17 1 + c52 r18 1 + c52 r19 1 + c52 r20 1 + c52 r21 1 + c52 r22 1 + c53 Obj 1 + c53 r8 1 + c53 r9 1 + c53 r10 1 + c53 r11 1 + c53 r12 1 + c53 r13 1 + c53 r14 1 + c53 r15 1 + c53 r16 1 + c53 r17 1 + c53 r18 1 + c53 r19 1 + c53 r20 1 + c53 r21 1 + c53 r22 1 + c53 r23 1 + c54 Obj 1 + c54 r12 1 + c54 r13 1 + c54 r14 1 + c54 r15 1 + c54 r16 1 + c54 r17 1 + c54 r18 1 + c54 r19 1 + c54 r20 1 + c54 r21 1 + c54 r22 1 + c54 r23 1 + c54 r24 1 + c54 r25 1 + c54 r26 1 + c54 r27 1 + c55 Obj 1 + c55 r13 1 + c55 r14 1 + c55 r15 1 + c55 r16 1 + c55 r17 1 + c55 r18 1 + c55 r19 1 + c55 r20 1 + c55 r21 1 + c55 r22 1 + c55 r23 1 + c55 r24 1 + c55 r25 1 + c55 r26 1 + c55 r27 1 + c55 r28 1 + c56 Obj 1 + c56 r7 1 + c56 r8 1 + c56 r9 1 + c56 r10 1 + c56 r11 1 + c56 r12 1 + c56 r13 1 + c56 r14 1 + c56 r15 1 + c56 r16 1 + c56 r17 1 + c56 r18 1 + c56 r19 1 + c56 r20 1 + c56 r21 1 + c56 r22 1 + c56 r23 1 + c57 Obj 1 + c57 r8 1 + c57 r9 1 + c57 r10 1 + c57 r11 1 + c57 r12 1 + c57 r13 1 + c57 r14 1 + c57 r15 1 + c57 r16 1 + c57 r17 1 + c57 r18 1 + c57 r19 1 + c57 r20 1 + c57 r21 1 + c57 r22 1 + c57 r23 1 + c57 r24 1 + c58 Obj 1 + c58 r11 1 + c58 r12 1 + c58 r13 1 + c58 r14 1 + c58 r15 1 + c58 r16 1 + c58 r17 1 + c58 r18 1 + c58 r19 1 + c58 r20 1 + c58 r21 1 + c58 r22 1 + c58 r23 1 + c58 r24 1 + c58 r25 1 + c58 r26 1 + c58 r27 1 + c59 Obj 1 + c59 r12 1 + c59 r13 1 + c59 r14 1 + c59 r15 1 + c59 r16 1 + c59 r17 1 + c59 r18 1 + c59 r19 1 + c59 r20 1 + c59 r21 1 + c59 r22 1 + c59 r23 1 + c59 r24 1 + c59 r25 1 + c59 r26 1 + c59 r27 1 + c59 r28 1 + c60 Obj 1 + c60 r7 1 + c60 r8 1 + c60 r9 1 + c60 r10 1 + c60 r11 1 + c60 r12 1 + c60 r13 1 + c60 r14 1 + c60 r15 1 + c60 r16 1 + c60 r17 1 + c60 r18 1 + c60 r19 1 + c60 r20 1 + c60 r21 1 + c60 r22 1 + c60 r23 1 + c60 r24 1 + c61 Obj 1 + c61 r10 1 + c61 r11 1 + c61 r12 1 + c61 r13 1 + c61 r14 1 + c61 r15 1 + c61 r16 1 + c61 r17 1 + c61 r18 1 + c61 r19 1 + c61 r20 1 + c61 r21 1 + c61 r22 1 + c61 r23 1 + c61 r24 1 + c61 r25 1 + c61 r26 1 + c61 r27 1 + c62 Obj 1 + c62 r11 1 + c62 r12 1 + c62 r13 1 + c62 r14 1 + c62 r15 1 + c62 r16 1 + c62 r17 1 + c62 r18 1 + c62 r19 1 + c62 r20 1 + c62 r21 1 + c62 r22 1 + c62 r23 1 + c62 r24 1 + c62 r25 1 + c62 r26 1 + c62 r27 1 + c62 r28 1 + c63 Obj 1 + c63 r9 1 + c63 r10 1 + c63 r11 1 + c63 r12 1 + c63 r13 1 + c63 r14 1 + c63 r15 1 + c63 r16 1 + c63 r17 1 + c63 r18 1 + c63 r19 1 + c63 r20 1 + c63 r21 1 + c63 r22 1 + c63 r23 1 + c63 r24 1 + c63 r25 1 + c63 r26 1 + c63 r27 1 + c64 Obj 1 + c64 r10 1 + c64 r11 1 + c64 r12 1 + c64 r13 1 + c64 r14 1 + c64 r15 1 + c64 r16 1 + c64 r17 1 + c64 r18 1 + c64 r19 1 + c64 r20 1 + c64 r21 1 + c64 r22 1 + c64 r23 1 + c64 r24 1 + c64 r25 1 + c64 r26 1 + c64 r27 1 + c64 r28 1 + c65 Obj 1 + c65 r9 1 + c65 r10 1 + c65 r11 1 + c65 r12 1 + c65 r13 1 + c65 r14 1 + c65 r15 1 + c65 r16 1 + c65 r17 1 + c65 r18 1 + c65 r19 1 + c65 r20 1 + c65 r21 1 + c65 r22 1 + c65 r23 1 + c65 r24 1 + c65 r25 1 + c65 r26 1 + c65 r27 1 + c65 r28 1 + MARK0001 'MARKER' 'INTEND' +RHS + RHS_V r0 1 + RHS_V r1 1 + RHS_V r2 1 + RHS_V r3 1 + RHS_V r4 1 + RHS_V r5 1 + RHS_V r6 1 + RHS_V r7 1 + RHS_V r8 1 + RHS_V r9 1 + RHS_V r10 1 + RHS_V r11 1 + RHS_V r12 1 + RHS_V r13 1 + RHS_V r14 1 + RHS_V r15 1 + RHS_V r16 1 + RHS_V r17 1 + RHS_V r18 1 + RHS_V r19 1 + RHS_V r20 1 + RHS_V r21 1 + RHS_V r22 1 + RHS_V r23 1 + RHS_V r24 1 + RHS_V r25 1 + RHS_V r26 1 + RHS_V r27 1 + RHS_V r28 1 +BOUNDS + BV BOUND c0 + BV BOUND c1 + BV BOUND c2 + BV BOUND c3 + BV BOUND c4 + BV BOUND c5 + BV BOUND c6 + BV BOUND c7 + BV BOUND c8 + BV BOUND c9 + BV BOUND c10 + BV BOUND c11 + BV BOUND c12 + BV BOUND c13 + BV BOUND c14 + BV BOUND c15 + BV BOUND c16 + BV BOUND c17 + BV BOUND c18 + BV BOUND c19 + BV BOUND c20 + BV BOUND c21 + BV BOUND c22 + BV BOUND c23 + BV BOUND c24 + BV BOUND c25 + BV BOUND c26 + BV BOUND c27 + BV BOUND c28 + BV BOUND c29 + BV BOUND c30 + BV BOUND c31 + BV BOUND c32 + BV BOUND c33 + BV BOUND c34 + BV BOUND c35 + BV BOUND c36 + BV BOUND c37 + BV BOUND c38 + BV BOUND c39 + BV BOUND c40 + BV BOUND c41 + BV BOUND c42 + BV BOUND c43 + BV BOUND c44 + BV BOUND c45 + BV BOUND c46 + BV BOUND c47 + BV BOUND c48 + BV BOUND c49 + BV BOUND c50 + BV BOUND c51 + BV BOUND c52 + BV BOUND c53 + BV BOUND c54 + BV BOUND c55 + BV BOUND c56 + BV BOUND c57 + BV BOUND c58 + BV BOUND c59 + BV BOUND c60 + BV BOUND c61 + BV BOUND c62 + BV BOUND c63 + BV BOUND c64 + BV BOUND c65 +ENDATA diff --git a/cmake/cpp-highs.cmake b/cmake/cpp-highs.cmake index 88a529a6f3..3e25a3e601 100644 --- a/cmake/cpp-highs.cmake +++ b/cmake/cpp-highs.cmake @@ -57,18 +57,20 @@ install(TARGETS highs PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/highs) # Add library targets to the build-tree export set -export(TARGETS highs - NAMESPACE ${PROJECT_NAMESPACE}::highs - FILE "${HIGHS_BINARY_DIR}/highs-targets.cmake") - -install(EXPORT ${lower}-targets - NAMESPACE ${PROJECT_NAMESPACE}:: - FILE highs-targets.cmake - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${lower}) -# install(FILES "${HIGHS_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/highs-config.cmake" -# DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/highs) -# install(FILES "${HIGHS_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/highs.pc" -# DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) +if (NOT HIGHS_COVERAGE) + export(TARGETS highs + NAMESPACE ${PROJECT_NAMESPACE}::highs + FILE "${HIGHS_BINARY_DIR}/highs-targets.cmake") + + install(EXPORT ${lower}-targets + NAMESPACE ${PROJECT_NAMESPACE}:: + FILE highs-targets.cmake + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${lower}) + # install(FILES "${HIGHS_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/highs-config.cmake" + # DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/highs) + # install(FILES "${HIGHS_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/highs.pc" + # DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) +endif() include(CMakePackageConfigHelpers) diff --git a/docs/src/interfaces/python/example-py.md b/docs/src/interfaces/python/example-py.md index fd4eef038b..ddb72b24e8 100644 --- a/docs/src/interfaces/python/example-py.md +++ b/docs/src/interfaces/python/example-py.md @@ -175,6 +175,8 @@ print('Basis validity = ', h.basisValidityToString(info.basis_validity)) * `getInfo` * `getSolution` * `getBasis` + * `getObjectiveValue` + * `getDualObjectiveValue` ## Report results @@ -206,6 +208,8 @@ print('Basis validity = ', h.basisValidityToString(info.basis_validity)) ## Modify model data + * `EnsureColwise` + * `EnsureRowwise` * `changeObjectiveSense` * `changeColCost` * `changeColBounds` @@ -236,6 +240,30 @@ print('Basis validity = ', h.basisValidityToString(info.basis_validity)) * `presolveStatusToString` * `presolveRuleTypeToString` * `postsolve` + +## Basis solves and tableau calculation + * `getBasicVariables` + * `getBasisInverseRow` + * `getBasisInverseRowSparse` + * `getBasisInverseCol` + * `getBasisInverseColSparse` + * `getBasisSolve` + * `getBasisSolveSparse` + * `getBasisTransposeSolve` + * `getBasisTransposeSolveSparse` + * `getReducedRow` + * `getReducedRowSparse` + * `getReducedColumn` + * `getReducedColumnSparse` + +## Rays and unboundedness + + * `getDualRayExist` + * `getDualRay` + * `getDualUnboundednessDirectionExist` + * `getDualUnboundednessDirection` + * `getPrimalRayExist` + * `getPrimalRay` ## Multi-objective optimization diff --git a/docs/src/options/definitions.md b/docs/src/options/definitions.md index f4e932523c..5ff9199ac6 100644 --- a/docs/src/options/definitions.md +++ b/docs/src/options/definitions.md @@ -73,6 +73,18 @@ - Range: [1e-12, inf] - Default: 1e-08 +## primal\_residual\_tolerance +- Primal residual tolerance +- Type: double +- Range: [1e-10, inf] +- Default: 1e-07 + +## dual\_residual\_tolerance +- Dual residual tolerance +- Type: double +- Range: [1e-10, inf] +- Default: 1e-07 + ## objective\_bound - Objective bound for termination of the dual simplex solver - Type: double @@ -110,7 +122,7 @@ - Default: 0 ## [simplex\_strategy](@id option-simplex_strategy) -- Strategy for simplex solver 0 => Choose; 1 => Dual (serial); 2 => Dual (PAMI); 3 => Dual (SIP); 4 => Primal +- Strategy for simplex solver 0 => Choose; 1 => Dual (serial); 2 => Dual (SIP); 3 => Dual (PAMI); 4 => Primal - Type: integer - Range: {0, 4} - Default: 1 @@ -198,6 +210,16 @@ - Type: boolean - Default: "false" +## write\_presolved\_model\_file +- Write presolved model file +- Type: string +- Default: "" + +## write\_presolved\_model\_to\_file +- Write the presolved model to a file +- Type: boolean +- Default: "false" + ## mip\_detect\_symmetry - Whether MIP symmetry should be detected - Type: boolean @@ -220,6 +242,12 @@ - Range: {0, 2147483647} - Default: 2147483647 +## mip\_max\_start\_nodes +- MIP solver max number of nodes when completing a partial MIP start +- Type: integer +- Range: {0, 2147483647} +- Default: 500 + ## mip\_improving\_solution\_save - Whether improving MIP solutions should be saved - Type: boolean @@ -354,7 +382,7 @@ - Default: 4000 ## blend\_multi\_objectives -- Blend multiple objectives or apply lexicographically +- Blend multiple objectives or apply lexicographically: Default = true - Type: boolean - Default: "true" diff --git a/extern/filereaderlp/reader.cpp b/extern/filereaderlp/reader.cpp index 0a289c0ea8..a90ea00ca1 100644 --- a/extern/filereaderlp/reader.cpp +++ b/extern/filereaderlp/reader.cpp @@ -1,1319 +1,1319 @@ -#include "reader.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "HConfig.h" // for ZLIB_FOUND -#include "builder.hpp" -#include "def.hpp" -#ifdef ZLIB_FOUND -#include "../extern/zstr/zstr.hpp" -#endif - -// Cygwin doesn't come with an implementation for strdup if compiled with -// std=cxx -#ifdef __CYGWIN__ -#include -char* strdup(const char* s) { - size_t slen = strlen(s); - char* result = (char*)malloc(slen + 1); - if (result == NULL) { - return NULL; - } - - memcpy(result, s, slen + 1); - return result; -} -#endif - -enum class RawTokenType { - NONE, - STR, - CONS, - LESS, - GREATER, - EQUAL, - COLON, - LNEND, - FLEND, - BRKOP, - BRKCL, - PLUS, - MINUS, - HAT, - SLASH, - ASTERISK -}; - -struct RawToken { - RawTokenType type = RawTokenType::NONE; - std::string svalue; - double dvalue = 0.0; - - inline bool istype(RawTokenType t) const { return this->type == t; } - - RawToken& operator=(RawTokenType t) { - type = t; - return *this; - } - RawToken& operator=(const std::string& v) { - svalue = v; - type = RawTokenType::STR; - return *this; - } - RawToken& operator=(const double v) { - dvalue = v; - type = RawTokenType::CONS; - return *this; - } -}; - -enum class ProcessedTokenType { - NONE, - SECID, - VARID, - CONID, - CONST, - FREE, - BRKOP, - BRKCL, - COMP, - LNEND, - SLASH, - ASTERISK, - HAT, - SOSTYPE -}; - -enum class LpSectionKeyword { - NONE, - OBJMIN, - OBJMAX, - CON, - BOUNDS, - GEN, - BIN, - SEMI, - SOS, - END -}; - -static const std::unordered_map - sectionkeywordmap{{"minimize", LpSectionKeyword::OBJMIN}, - {"min", LpSectionKeyword::OBJMIN}, - {"minimum", LpSectionKeyword::OBJMIN}, - {"maximize", LpSectionKeyword::OBJMAX}, - {"max", LpSectionKeyword::OBJMAX}, - {"maximum", LpSectionKeyword::OBJMAX}, - {"subject to", LpSectionKeyword::CON}, - {"such that", LpSectionKeyword::CON}, - {"st", LpSectionKeyword::CON}, - {"s.t.", LpSectionKeyword::CON}, - {"bounds", LpSectionKeyword::BOUNDS}, - {"bound", LpSectionKeyword::BOUNDS}, - {"binary", LpSectionKeyword::BIN}, - {"binaries", LpSectionKeyword::BIN}, - {"bin", LpSectionKeyword::BIN}, - {"general", LpSectionKeyword::GEN}, - {"generals", LpSectionKeyword::GEN}, - {"gen", LpSectionKeyword::GEN}, - {"integer", LpSectionKeyword::GEN}, - {"integers", LpSectionKeyword::GEN}, - {"semi-continuous", LpSectionKeyword::SEMI}, - {"semi", LpSectionKeyword::SEMI}, - {"semis", LpSectionKeyword::SEMI}, - {"sos", LpSectionKeyword::SOS}, - {"end", LpSectionKeyword::END}}; - -enum class SosType { SOS1, SOS2 }; - -enum class LpComparisonType { LEQ, L, EQ, G, GEQ }; - -struct ProcessedToken { - ProcessedTokenType type; - union { - LpSectionKeyword keyword; - SosType sostype; - char* name; - double value; - LpComparisonType dir; - }; - - ProcessedToken(const ProcessedToken&) = delete; - ProcessedToken(ProcessedToken&& t) : type(t.type) { - switch (type) { - case ProcessedTokenType::SECID: - keyword = t.keyword; - break; - case ProcessedTokenType::SOSTYPE: - sostype = t.sostype; - break; - case ProcessedTokenType::CONID: - case ProcessedTokenType::VARID: - name = t.name; - break; - case ProcessedTokenType::CONST: - value = t.value; - break; - case ProcessedTokenType::COMP: - dir = t.dir; - break; - default:; - } - t.type = ProcessedTokenType::NONE; - } - - ProcessedToken(ProcessedTokenType t) : type(t){}; - - ProcessedToken(LpSectionKeyword kw) - : type(ProcessedTokenType::SECID), keyword(kw){}; - - ProcessedToken(SosType sos) - : type(ProcessedTokenType::SOSTYPE), sostype(sos){}; - - ProcessedToken(ProcessedTokenType t, const std::string& s) : type(t) { - assert(t == ProcessedTokenType::CONID || t == ProcessedTokenType::VARID); -#ifndef _WIN32 - name = strdup(s.c_str()); -#else - name = _strdup(s.c_str()); -#endif - }; - - ProcessedToken(double v) : type(ProcessedTokenType::CONST), value(v){}; - - ProcessedToken(LpComparisonType comp) - : type(ProcessedTokenType::COMP), dir(comp){}; - - ~ProcessedToken() { - if (type == ProcessedTokenType::CONID || type == ProcessedTokenType::VARID) - free(name); - } -}; - -// how many raw tokens to cache -// set to how many tokens we may need to look ahead -#define NRAWTOKEN 3 - -const double kHighsInf = std::numeric_limits::infinity(); -class Reader { - private: -#ifdef ZLIB_FOUND - zstr::ifstream file; -#else - std::ifstream file; -#endif - std::string linebuffer; - std::size_t linebufferpos; - std::array rawtokens; - std::vector processedtokens; - // store for each section a pointer to its begin and end (pointer to element - // after last) - std::map::iterator, - std::vector::iterator> > - sectiontokens; - - Builder builder; - - bool readnexttoken(RawToken&); - void nextrawtoken(size_t howmany = 1); - void processtokens(); - void splittokens(); - void processsections(); - void processnonesec(); - void processobjsec(); - void processconsec(); - void processboundssec(); - void processbinsec(); - void processgensec(); - void processsemisec(); - void processsossec(); - void processendsec(); - void parseexpression(std::vector::iterator& it, - std::vector::iterator end, - std::shared_ptr expr, bool isobj); - - public: - Reader(std::string filename) { -#ifdef ZLIB_FOUND - try { - file.open(filename); - } catch (const strict_fstream::Exception& e) { - } -#else - file.open(filename); -#endif - lpassert(file.is_open()); - }; - - ~Reader() { file.close(); } - - Model read(); -}; - -Model readinstance(std::string filename) { - Reader reader(filename); - return reader.read(); -} - -// convert string to lower-case, modifies string -static inline void tolower(std::string& s) { - std::transform(s.begin(), s.end(), s.begin(), - [](unsigned char c) { return std::tolower(c); }); -} - -static inline bool iskeyword(const std::string& str, - const std::string* keywords, const int nkeywords) { - for (int i = 0; i < nkeywords; i++) { - if (str == keywords[i]) { - return true; - } - } - return false; -} - -static inline LpSectionKeyword parsesectionkeyword(const std::string& str) { - // look up lower case - auto it(sectionkeywordmap.find(str)); - if (it != sectionkeywordmap.end()) return it->second; - - return LpSectionKeyword::NONE; -} - -Model Reader::read() { - // std::clog << "Reading input, tokenizing..." << std::endl; - this->linebufferpos = 0; - // read first NRAWTOKEN token - // if file ends early, then all remaining tokens are set to FLEND - for (size_t i = 0; i < NRAWTOKEN; ++i) - while (!readnexttoken(rawtokens[i])) - ; - - processtokens(); - - linebuffer.clear(); - linebuffer.shrink_to_fit(); - - // std::clog << "Splitting tokens..." << std::endl; - splittokens(); - - // std::clog << "Setting up model..." << std::endl; - // - // Since - // - // "The problem statement must begin with the word MINIMIZE or - // MAXIMIZE, MINIMUM or MAXIMUM, or the abbreviations MIN or MAX, in - // any combination of upper- and lower-case characters. The word - // introduces the objective function section." - // - // Use positivity of sectiontokens.count(LpSectionKeyword::OBJMIN) + - // sectiontokens.count(LpSectionKeyword::OBJMAX) to identify garbage file - // - - const int num_objective_section = - sectiontokens.count(LpSectionKeyword::OBJMIN) + - sectiontokens.count(LpSectionKeyword::OBJMAX); - lpassert(num_objective_section>0); - - processsections(); - processedtokens.clear(); - processedtokens.shrink_to_fit(); - - return builder.model; -} - -void Reader::processnonesec() { - lpassert(sectiontokens.count(LpSectionKeyword::NONE) == 0); -} - -void Reader::parseexpression(std::vector::iterator& it, - std::vector::iterator end, - std::shared_ptr expr, bool isobj) { - if (it != end && it->type == ProcessedTokenType::CONID) { - expr->name = it->name; - ++it; - } - - while (it != end) { - std::vector::iterator next = it; - ++next; - // const var - if (next != end && it->type == ProcessedTokenType::CONST && - next->type == ProcessedTokenType::VARID) { - std::string name = next->name; - - std::shared_ptr linterm = - std::shared_ptr(new LinTerm()); - linterm->coef = it->value; - linterm->var = builder.getvarbyname(name); - // printf("LpReader: Term %+g %s\n", linterm->coef, - //name.c_str()); - expr->linterms.push_back(linterm); - - ++it; - ++it; - continue; - } - - // const - if (it->type == ProcessedTokenType::CONST) { - // printf("LpReader: Offset change from %+g by %+g\n", expr->offset, it->value); - expr->offset += it->value; - ++it; - continue; - } - - // var - if (it->type == ProcessedTokenType::VARID) { - std::string name = it->name; - - std::shared_ptr linterm = - std::shared_ptr(new LinTerm()); - linterm->coef = 1.0; - linterm->var = builder.getvarbyname(name); - // printf("LpReader: Term %+g %s\n", linterm->coef, - //name.c_str()); - expr->linterms.push_back(linterm); - - ++it; - continue; - } - - // quadratic expression - if (next != end && it->type == ProcessedTokenType::BRKOP) { - ++it; - while (it != end && it->type != ProcessedTokenType::BRKCL) { - // const var hat const - std::vector::iterator next1 = it; // token after it - std::vector::iterator next2 = it; // token 2nd-after it - std::vector::iterator next3 = it; // token 3rd-after it - ++next1; - ++next2; - ++next3; - if (next1 != end) { - ++next2; - ++next3; - } - if (next2 != end) ++next3; - - if (next3 != end && it->type == ProcessedTokenType::CONST && - next1->type == ProcessedTokenType::VARID && - next2->type == ProcessedTokenType::HAT && - next3->type == ProcessedTokenType::CONST) { - std::string name = next1->name; - - lpassert(next3->value == 2.0); - - std::shared_ptr quadterm = - std::shared_ptr(new QuadTerm()); - quadterm->coef = it->value; - quadterm->var1 = builder.getvarbyname(name); - quadterm->var2 = builder.getvarbyname(name); - expr->quadterms.push_back(quadterm); - - it = ++next3; - continue; - } - - // var hat const - if (next2 != end && it->type == ProcessedTokenType::VARID && - next1->type == ProcessedTokenType::HAT && - next2->type == ProcessedTokenType::CONST) { - std::string name = it->name; - - lpassert(next2->value == 2.0); - - std::shared_ptr quadterm = - std::shared_ptr(new QuadTerm()); - quadterm->coef = 1.0; - quadterm->var1 = builder.getvarbyname(name); - quadterm->var2 = builder.getvarbyname(name); - expr->quadterms.push_back(quadterm); - - it = next3; - continue; - } - - // const var asterisk var - if (next3 != end && it->type == ProcessedTokenType::CONST && - next1->type == ProcessedTokenType::VARID && - next2->type == ProcessedTokenType::ASTERISK && - next3->type == ProcessedTokenType::VARID) { - std::string name1 = next1->name; - std::string name2 = next3->name; - - std::shared_ptr quadterm = - std::shared_ptr(new QuadTerm()); - quadterm->coef = it->value; - quadterm->var1 = builder.getvarbyname(name1); - quadterm->var2 = builder.getvarbyname(name2); - expr->quadterms.push_back(quadterm); - - it = ++next3; - continue; - } - - // var asterisk var - if (next2 != end && it->type == ProcessedTokenType::VARID && - next1->type == ProcessedTokenType::ASTERISK && - next2->type == ProcessedTokenType::VARID) { - std::string name1 = it->name; - std::string name2 = next2->name; - - std::shared_ptr quadterm = - std::shared_ptr(new QuadTerm()); - quadterm->coef = 1.0; - quadterm->var1 = builder.getvarbyname(name1); - quadterm->var2 = builder.getvarbyname(name2); - expr->quadterms.push_back(quadterm); - - it = next3; - continue; - } - break; - } - if (isobj) { - // only in the objective function, a quadratic term is followed by - // "/2.0" - std::vector::iterator next1 = it; // token after it - std::vector::iterator next2 = it; // token 2nd-after it - ++next1; - ++next2; - if (next1 != end) ++next2; - - lpassert(next2 != end); - lpassert(it->type == ProcessedTokenType::BRKCL); - lpassert(next1->type == ProcessedTokenType::SLASH); - lpassert(next2->type == ProcessedTokenType::CONST); - lpassert(next2->value == 2.0); - it = ++next2; - } else { - lpassert(it != end); - lpassert(it->type == ProcessedTokenType::BRKCL); - ++it; - } - continue; - } - - break; - } -} - -void Reader::processobjsec() { - builder.model.objective = std::shared_ptr(new Expression); - if (sectiontokens.count(LpSectionKeyword::OBJMIN)) { - builder.model.sense = ObjectiveSense::MIN; - parseexpression(sectiontokens[LpSectionKeyword::OBJMIN].first, - sectiontokens[LpSectionKeyword::OBJMIN].second, - builder.model.objective, true); - lpassert(sectiontokens[LpSectionKeyword::OBJMIN].first == - sectiontokens[LpSectionKeyword::OBJMIN] - .second); // all section tokens should have been processed - } else if (sectiontokens.count(LpSectionKeyword::OBJMAX)) { - builder.model.sense = ObjectiveSense::MAX; - parseexpression(sectiontokens[LpSectionKeyword::OBJMAX].first, - sectiontokens[LpSectionKeyword::OBJMAX].second, - builder.model.objective, true); - lpassert(sectiontokens[LpSectionKeyword::OBJMAX].first == - sectiontokens[LpSectionKeyword::OBJMAX] - .second); // all section tokens should have been processed - } -} - -void Reader::processconsec() { - if (!sectiontokens.count(LpSectionKeyword::CON)) return; - std::vector::iterator& begin( - sectiontokens[LpSectionKeyword::CON].first); - std::vector::iterator& end( - sectiontokens[LpSectionKeyword::CON].second); - while (begin != end) { - std::shared_ptr con = - std::shared_ptr(new Constraint); - parseexpression(begin, end, con->expr, false); - // should not be at end of section yet, but a comparison operator should be - // next - lpassert(begin != sectiontokens[LpSectionKeyword::CON].second); - lpassert(begin->type == ProcessedTokenType::COMP); - LpComparisonType dir = begin->dir; - ++begin; - - // should still not be at end of section yet, but a right-hand-side value - // should be next - lpassert(begin != sectiontokens[LpSectionKeyword::CON].second); - lpassert(begin->type == ProcessedTokenType::CONST); - switch (dir) { - case LpComparisonType::EQ: - con->lowerbound = con->upperbound = begin->value; - break; - case LpComparisonType::LEQ: - con->upperbound = begin->value; - break; - case LpComparisonType::GEQ: - con->lowerbound = begin->value; - break; - default: - lpassert(false); - } - builder.model.constraints.push_back(con); - ++begin; - } -} - -void Reader::processboundssec() { - if (!sectiontokens.count(LpSectionKeyword::BOUNDS)) return; - std::vector::iterator& begin( - sectiontokens[LpSectionKeyword::BOUNDS].first); - std::vector::iterator& end( - sectiontokens[LpSectionKeyword::BOUNDS].second); - while (begin != end) { - std::vector::iterator next1 = begin; // token after begin - ++next1; - - // VAR free - if (next1 != end && begin->type == ProcessedTokenType::VARID && - next1->type == ProcessedTokenType::FREE) { - std::string name = begin->name; - std::shared_ptr var = builder.getvarbyname(name); - var->lowerbound = -kHighsInf; - var->upperbound = kHighsInf; - begin = ++next1; - continue; - } - - std::vector::iterator next2 = - next1; // token 2nd-after begin - std::vector::iterator next3 = - next1; // token 3rd-after begin - std::vector::iterator next4 = - next1; // token 4th-after begin - if (next1 != end) { - ++next2; - ++next3; - ++next4; - } - if (next2 != end) { - ++next3; - ++next4; - } - if (next3 != end) ++next4; - - // CONST COMP VAR COMP CONST - if (next4 != end && begin->type == ProcessedTokenType::CONST && - next1->type == ProcessedTokenType::COMP && - next2->type == ProcessedTokenType::VARID && - next3->type == ProcessedTokenType::COMP && - next4->type == ProcessedTokenType::CONST) { - lpassert(next1->dir == LpComparisonType::LEQ); - lpassert(next3->dir == LpComparisonType::LEQ); - - double lb = begin->value; - double ub = next4->value; - - std::string name = next2->name; - std::shared_ptr var = builder.getvarbyname(name); - - var->lowerbound = lb; - var->upperbound = ub; - - begin = ++next4; - continue; - } - - // CONST COMP VAR - if (next2 != end && begin->type == ProcessedTokenType::CONST && - next1->type == ProcessedTokenType::COMP && - next2->type == ProcessedTokenType::VARID) { - double value = begin->value; - std::string name = next2->name; - std::shared_ptr var = builder.getvarbyname(name); - LpComparisonType dir = next1->dir; - - lpassert(dir != LpComparisonType::L && dir != LpComparisonType::G); - - switch (dir) { - case LpComparisonType::LEQ: - var->lowerbound = value; - break; - case LpComparisonType::GEQ: - var->upperbound = value; - break; - case LpComparisonType::EQ: - var->lowerbound = var->upperbound = value; - break; - default: - lpassert(false); - } - begin = next3; - continue; - } - - // VAR COMP CONST - if (next2 != end && begin->type == ProcessedTokenType::VARID && - next1->type == ProcessedTokenType::COMP && - next2->type == ProcessedTokenType::CONST) { - double value = next2->value; - std::string name = begin->name; - std::shared_ptr var = builder.getvarbyname(name); - LpComparisonType dir = next1->dir; - - lpassert(dir != LpComparisonType::L && dir != LpComparisonType::G); - - switch (dir) { - case LpComparisonType::LEQ: - var->upperbound = value; - break; - case LpComparisonType::GEQ: - var->lowerbound = value; - break; - case LpComparisonType::EQ: - var->lowerbound = var->upperbound = value; - break; - default: - lpassert(false); - } - begin = next3; - continue; - } - - lpassert(false); - } -} - -void Reader::processbinsec() { - const LpSectionKeyword this_section_keyword = LpSectionKeyword::BIN; - if (!sectiontokens.count(this_section_keyword)) return; - std::vector::iterator& begin( - sectiontokens[this_section_keyword].first); - std::vector::iterator& end( - sectiontokens[this_section_keyword].second); - for (; begin != end; ++begin) { - if (begin->type == ProcessedTokenType::SECID) { - // Possible to have repeat of keyword for this section type - lpassert(begin->keyword == this_section_keyword); - continue; - } - lpassert(begin->type == ProcessedTokenType::VARID); - std::string name = begin->name; - std::shared_ptr var = builder.getvarbyname(name); - var->type = VariableType::BINARY; - // Respect any bounds already declared - if (var->upperbound == kHighsInf) var->upperbound = 1.0; - } -} - -void Reader::processgensec() { - const LpSectionKeyword this_section_keyword = LpSectionKeyword::GEN; - if (!sectiontokens.count(this_section_keyword)) return; - std::vector::iterator& begin( - sectiontokens[this_section_keyword].first); - std::vector::iterator& end( - sectiontokens[this_section_keyword].second); - for (; begin != end; ++begin) { - if (begin->type == ProcessedTokenType::SECID) { - // Possible to have repeat of keyword for this section type - lpassert(begin->keyword == this_section_keyword); - continue; - } - lpassert(begin->type == ProcessedTokenType::VARID); - std::string name = begin->name; - std::shared_ptr var = builder.getvarbyname(name); - if (var->type == VariableType::SEMICONTINUOUS) { - var->type = VariableType::SEMIINTEGER; - } else { - var->type = VariableType::GENERAL; - } - } -} - -void Reader::processsemisec() { - const LpSectionKeyword this_section_keyword = LpSectionKeyword::SEMI; - if (!sectiontokens.count(this_section_keyword)) return; - std::vector::iterator& begin( - sectiontokens[this_section_keyword].first); - std::vector::iterator& end( - sectiontokens[this_section_keyword].second); - for (; begin != end; ++begin) { - if (begin->type == ProcessedTokenType::SECID) { - // Possible to have repeat of keyword for this section type - lpassert(begin->keyword == this_section_keyword); - continue; - } - lpassert(begin->type == ProcessedTokenType::VARID); - std::string name = begin->name; - std::shared_ptr var = builder.getvarbyname(name); - if (var->type == VariableType::GENERAL) { - var->type = VariableType::SEMIINTEGER; - } else { - var->type = VariableType::SEMICONTINUOUS; - } - } -} - -void Reader::processsossec() { - const LpSectionKeyword this_section_keyword = LpSectionKeyword::SOS; - if (!sectiontokens.count(this_section_keyword)) return; - std::vector::iterator& begin( - sectiontokens[this_section_keyword].first); - std::vector::iterator& end( - sectiontokens[this_section_keyword].second); - while (begin != end) { - std::shared_ptr sos = std::shared_ptr(new SOS); - - // sos1: S1 :: x1 : 1 x2 : 2 x3 : 3 - - // name of SOS is mandatory - lpassert(begin->type == ProcessedTokenType::CONID); - sos->name = begin->name; - ++begin; - - // SOS type - lpassert(begin != end); - lpassert(begin->type == ProcessedTokenType::SOSTYPE); - sos->type = begin->sostype == SosType::SOS1 ? 1 : 2; - ++begin; - - while (begin != end) { - // process all "var : weight" entries - // when processtokens() sees a string followed by a colon, it classifies - // this as a CONID but in a SOS section, this is actually a variable - // identifier - if (begin->type != ProcessedTokenType::CONID) break; - std::string name = begin->name; - std::vector::iterator next = begin; - ++next; - if (next != end && next->type == ProcessedTokenType::CONST) { - auto var = builder.getvarbyname(name); - double weight = next->value; - - sos->entries.push_back({var, weight}); - - begin = ++next; - continue; - } - - break; - } - - builder.model.soss.push_back(sos); - } -} - -void Reader::processendsec() { - lpassert(sectiontokens.count(LpSectionKeyword::END) == 0); -} - -void Reader::processsections() { - processnonesec(); - processobjsec(); - processconsec(); - processboundssec(); - processgensec(); - processbinsec(); - processsemisec(); - processsossec(); - processendsec(); -} - -void Reader::splittokens() { - LpSectionKeyword currentsection = LpSectionKeyword::NONE; - - bool debug_open_section = false; - for (std::vector::iterator it(processedtokens.begin()); - it != processedtokens.end(); ++it) { - // Look for section keywords - if (it->type != ProcessedTokenType::SECID) continue; - // currentsection is initially LpSectionKeyword::NONE, so the - // first section ID will be a new section type - // - // Only record change of section and check for repeated - // section if the keyword is for a different section. Allows - // repetition of Integers and General (cf #1299) for example - const bool new_section_type = currentsection != it->keyword; - if (new_section_type) { - if (currentsection != LpSectionKeyword::NONE) { - // Current section is non-trivial, so mark its end, using the - // value of currentsection to indicate that there is no open - // section - lpassert(debug_open_section); - sectiontokens[currentsection].second = it; - debug_open_section = false; - currentsection = LpSectionKeyword::NONE; - } - } - std::vector::iterator next = it; - ++next; - if (next == processedtokens.end() || - next->type == ProcessedTokenType::SECID) { - // Reached the end of the tokens or the new section is empty - // - // currentsection will be LpSectionKeyword::NONE unless the - // second of two sections of the same type is empty and the - // next section is of a new type, in which case mark the end of - // the current section - if (currentsection != LpSectionKeyword::NONE && - currentsection != next->keyword) { - lpassert(debug_open_section); - sectiontokens[currentsection].second = it; - debug_open_section = false; - } - currentsection = LpSectionKeyword::NONE; - lpassert(!debug_open_section); - continue; - } - // Next section is non-empty - if (new_section_type) { - // Section type change - currentsection = it->keyword; - // Make sure the new section type has not occurred previously - lpassert(sectiontokens.count(currentsection) == 0); - // Remember the beginning of the new section: its the token - // following the current one - lpassert(!debug_open_section); - sectiontokens[currentsection].first = next; - debug_open_section = true; - } - // Always ends with either an open section or a section type of - // LpSectionKeyword::NONE - lpassert(debug_open_section != (currentsection == LpSectionKeyword::NONE)); - } - // Check that the last section has been closed - lpassert(currentsection == LpSectionKeyword::NONE); -} - -void Reader::processtokens() { - std::string svalue_lc; - while (!rawtokens[0].istype(RawTokenType::FLEND)) { - fflush(stdout); - - // Slash + asterisk: comment, skip everything up to next asterisk + slash - if (rawtokens[0].istype(RawTokenType::SLASH) && - rawtokens[1].istype(RawTokenType::ASTERISK)) { - do { - nextrawtoken(2); - } while (!(rawtokens[0].istype(RawTokenType::ASTERISK) && - rawtokens[1].istype(RawTokenType::SLASH)) && - !rawtokens[0].istype(RawTokenType::FLEND)); - nextrawtoken(2); - continue; - } - - if (rawtokens[0].istype(RawTokenType::STR)) { - svalue_lc = rawtokens[0].svalue; - tolower(svalue_lc); - } - - // long section keyword semi-continuous - if (rawtokens[0].istype(RawTokenType::STR) && - rawtokens[1].istype(RawTokenType::MINUS) && - rawtokens[2].istype(RawTokenType::STR)) { - std::string temp = rawtokens[2].svalue; - tolower(temp); - LpSectionKeyword keyword = parsesectionkeyword(svalue_lc + "-" + temp); - if (keyword != LpSectionKeyword::NONE) { - processedtokens.emplace_back(keyword); - nextrawtoken(3); - continue; - } - } - - // long section keyword subject to/such that - if (rawtokens[0].istype(RawTokenType::STR) && - rawtokens[1].istype(RawTokenType::STR)) { - std::string temp = rawtokens[1].svalue; - tolower(temp); - LpSectionKeyword keyword = parsesectionkeyword(svalue_lc + " " + temp); - if (keyword != LpSectionKeyword::NONE) { - processedtokens.emplace_back(keyword); - nextrawtoken(2); - continue; - } - } - - // other section keyword - if (rawtokens[0].istype(RawTokenType::STR)) { - LpSectionKeyword keyword = parsesectionkeyword(svalue_lc); - if (keyword != LpSectionKeyword::NONE) { - processedtokens.emplace_back(keyword); - nextrawtoken(); - continue; - } - } - - // sos type identifier? "S1 ::" or "S2 ::" - if (rawtokens[0].istype(RawTokenType::STR) && - rawtokens[1].istype(RawTokenType::COLON) && - rawtokens[2].istype(RawTokenType::COLON)) { - lpassert(rawtokens[0].svalue.length() == 2); - lpassert(rawtokens[0].svalue[0] == 'S' || rawtokens[0].svalue[0] == 's'); - lpassert(rawtokens[0].svalue[1] == '1' || rawtokens[0].svalue[1] == '2'); - processedtokens.emplace_back( - rawtokens[0].svalue[1] == '1' ? SosType::SOS1 : SosType::SOS2); - nextrawtoken(3); - continue; - } - - // constraint identifier? - if (rawtokens[0].istype(RawTokenType::STR) && - rawtokens[1].istype(RawTokenType::COLON)) { - processedtokens.emplace_back(ProcessedTokenType::CONID, - rawtokens[0].svalue); - nextrawtoken(2); - continue; - } - - // check if free - if (rawtokens[0].istype(RawTokenType::STR) && - iskeyword(svalue_lc, LP_KEYWORD_FREE, LP_KEYWORD_FREE_N)) { - processedtokens.emplace_back(ProcessedTokenType::FREE); - nextrawtoken(); - continue; - } - - // check if infinity - if (rawtokens[0].istype(RawTokenType::STR) && - iskeyword(svalue_lc, LP_KEYWORD_INF, LP_KEYWORD_INF_N)) { - processedtokens.emplace_back(kHighsInf); - nextrawtoken(); - continue; - } - - // assume var identifier - if (rawtokens[0].istype(RawTokenType::STR)) { - processedtokens.emplace_back(ProcessedTokenType::VARID, - rawtokens[0].svalue); - nextrawtoken(); - continue; - } - - // + or - - if (rawtokens[0].istype(RawTokenType::PLUS) || - rawtokens[0].istype(RawTokenType::MINUS)) { - double sign = rawtokens[0].istype(RawTokenType::PLUS) ? 1.0 : -1.0; - nextrawtoken(); - - // another + or - for #948, #950 - if (rawtokens[0].istype(RawTokenType::PLUS) || - rawtokens[0].istype(RawTokenType::MINUS)) { - sign *= rawtokens[0].istype(RawTokenType::PLUS) ? 1.0 : -1.0; - nextrawtoken(); - } - - // +/- Constant - if (rawtokens[0].istype(RawTokenType::CONS)) { - processedtokens.emplace_back(sign * rawtokens[0].dvalue); - nextrawtoken(); - continue; - } - - // + [, + + [, - - [ - if (rawtokens[0].istype(RawTokenType::BRKOP) && sign == 1.0) { - processedtokens.emplace_back(ProcessedTokenType::BRKOP); - nextrawtoken(); - continue; - } - - // - [, + - [, - + [ - if (rawtokens[0].istype(RawTokenType::BRKOP)) lpassert(false); - - // +/- variable name - if (rawtokens[0].istype(RawTokenType::STR)) { - processedtokens.emplace_back(sign); - continue; - } - - // +/- (possibly twice) followed by something that isn't a constant, - // opening bracket, or string (variable name) - if (rawtokens[0].istype(RawTokenType::GREATER)) { - // ">" suggests that the file contains indicator constraints - printf( - "File appears to contain indicator constraints: cannot currently " - "be handled by HiGHS\n"); - } - lpassert(false); - } - - // constant [ - if (rawtokens[0].istype(RawTokenType::CONS) && - rawtokens[1].istype(RawTokenType::BRKOP)) { - lpassert(false); - } - - // constant - if (rawtokens[0].istype(RawTokenType::CONS)) { - processedtokens.emplace_back(rawtokens[0].dvalue); - nextrawtoken(); - continue; - } - - // [ - if (rawtokens[0].istype(RawTokenType::BRKOP)) { - processedtokens.emplace_back(ProcessedTokenType::BRKOP); - nextrawtoken(); - continue; - } - - // ] - if (rawtokens[0].istype(RawTokenType::BRKCL)) { - processedtokens.emplace_back(ProcessedTokenType::BRKCL); - nextrawtoken(); - continue; - } - - // / - if (rawtokens[0].istype(RawTokenType::SLASH)) { - processedtokens.emplace_back(ProcessedTokenType::SLASH); - nextrawtoken(); - continue; - } - - // * - if (rawtokens[0].istype(RawTokenType::ASTERISK)) { - processedtokens.emplace_back(ProcessedTokenType::ASTERISK); - nextrawtoken(); - continue; - } - - // ^ - if (rawtokens[0].istype(RawTokenType::HAT)) { - processedtokens.emplace_back(ProcessedTokenType::HAT); - nextrawtoken(); - continue; - } - - // <= - if (rawtokens[0].istype(RawTokenType::LESS) && - rawtokens[1].istype(RawTokenType::EQUAL)) { - processedtokens.emplace_back(LpComparisonType::LEQ); - nextrawtoken(2); - continue; - } - - // < - if (rawtokens[0].istype(RawTokenType::LESS)) { - processedtokens.emplace_back(LpComparisonType::L); - nextrawtoken(); - continue; - } - - // >= - if (rawtokens[0].istype(RawTokenType::GREATER) && - rawtokens[1].istype(RawTokenType::EQUAL)) { - processedtokens.emplace_back(LpComparisonType::GEQ); - nextrawtoken(2); - continue; - } - - // > - if (rawtokens[0].istype(RawTokenType::GREATER)) { - processedtokens.emplace_back(LpComparisonType::G); - nextrawtoken(); - continue; - } - - // = - if (rawtokens[0].istype(RawTokenType::EQUAL)) { - processedtokens.emplace_back(LpComparisonType::EQ); - nextrawtoken(); - continue; - } - - // FILEEND should have been handled in condition of while() - assert(!rawtokens[0].istype(RawTokenType::FLEND)); - - // catch all unknown symbols - lpassert(false); - break; - } -} - -void Reader::nextrawtoken(size_t howmany) { - assert(howmany > 0); - assert(howmany <= NRAWTOKEN); - static_assert(NRAWTOKEN == 3, - "code below need to be adjusted if NRAWTOKEN changes"); - switch (howmany) { - case 1: { - rawtokens[0] = std::move(rawtokens[1]); - rawtokens[1] = std::move(rawtokens[2]); - while (!readnexttoken(rawtokens[2])) - ; - break; - } - case 2: { - rawtokens[0] = std::move(rawtokens[2]); - while (!readnexttoken(rawtokens[1])) - ; - while (!readnexttoken(rawtokens[2])) - ; - break; - } - case 3: { - while (!readnexttoken(rawtokens[0])) - ; - while (!readnexttoken(rawtokens[1])) - ; - while (!readnexttoken(rawtokens[2])) - ; - break; - } - default: { - size_t i = 0; - // move tokens up - for (; i < NRAWTOKEN - howmany; ++i) - rawtokens[i] = std::move(rawtokens[i + howmany]); - // read new tokens at end positions - for (; i < NRAWTOKEN; ++i) - // call readnexttoken() to overwrite current token - // if it didn't actually read a token (returns false), then call again - while (!readnexttoken(rawtokens[i])) - ; - } - } -} - -// return true, if token has been set; return false if skipped over whitespace -// only -bool Reader::readnexttoken(RawToken& t) { - if (this->linebufferpos == this->linebuffer.size()) { - // read next line if any are left. - if (this->file.eof()) { - t = RawTokenType::FLEND; - return true; - } - std::getline(this->file, linebuffer); - - // drop \r - if (!linebuffer.empty() && linebuffer.back() == '\r') linebuffer.pop_back(); - - // reset linebufferpos - this->linebufferpos = 0; - } - - // check single character tokens - char nextchar = this->linebuffer[this->linebufferpos]; - - switch (nextchar) { - // check for comment - case '\\': - // skip rest of line - this->linebufferpos = this->linebuffer.size(); - return false; - - // check for bracket opening - case '[': - t = RawTokenType::BRKOP; - this->linebufferpos++; - return true; - - // check for bracket closing - case ']': - t = RawTokenType::BRKCL; - this->linebufferpos++; - return true; - - // check for less sign - case '<': - t = RawTokenType::LESS; - this->linebufferpos++; - return true; - - // check for greater sign - case '>': - t = RawTokenType::GREATER; - this->linebufferpos++; - return true; - - // check for equal sign - case '=': - t = RawTokenType::EQUAL; - this->linebufferpos++; - return true; - - // check for colon - case ':': - t = RawTokenType::COLON; - this->linebufferpos++; - return true; - - // check for plus - case '+': - t = RawTokenType::PLUS; - this->linebufferpos++; - return true; - - // check for hat - case '^': - t = RawTokenType::HAT; - this->linebufferpos++; - return true; - - // check for slash - case '/': - t = RawTokenType::SLASH; - this->linebufferpos++; - return true; - - // check for asterisk - case '*': - t = RawTokenType::ASTERISK; - this->linebufferpos++; - return true; - - // check for minus - case '-': - t = RawTokenType::MINUS; - this->linebufferpos++; - return true; - - // check for whitespace - case ' ': - case '\t': - this->linebufferpos++; - return false; - - // check for line end - case ';': - case '\n': // \n should not happen due to using getline() - this->linebufferpos = this->linebuffer.size(); - return false; - - case '\0': // empty line - lpassert(this->linebufferpos == this->linebuffer.size()); - return false; - } - - // check for double value - const char* startptr = this->linebuffer.data() + this->linebufferpos; - char* endptr; - double constant = strtod(startptr, &endptr); - if (endptr != startptr) { - t = constant; - this->linebufferpos += endptr - startptr; - return true; - } - - // assume it's an (section/variable/constraint) identifier - auto endpos = - this->linebuffer.find_first_of("\t\n\\:+<>^= /-*[]", this->linebufferpos); - if (endpos == std::string::npos) - endpos = this->linebuffer.size(); // take complete rest of string - if (endpos > this->linebufferpos) { - t = std::string(this->linebuffer, this->linebufferpos, - endpos - this->linebufferpos); - this->linebufferpos = endpos; - return true; - } - - lpassert(false); - return false; -} +#include "reader.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "HConfig.h" // for ZLIB_FOUND +#include "builder.hpp" +#include "def.hpp" +#ifdef ZLIB_FOUND +#include "../extern/zstr/zstr.hpp" +#endif + +// Cygwin doesn't come with an implementation for strdup if compiled with +// std=cxx +#ifdef __CYGWIN__ +#include +char* strdup(const char* s) { + size_t slen = strlen(s); + char* result = (char*)malloc(slen + 1); + if (result == NULL) { + return NULL; + } + + memcpy(result, s, slen + 1); + return result; +} +#endif + +enum class RawTokenType { + NONE, + STR, + CONS, + LESS, + GREATER, + EQUAL, + COLON, + LNEND, + FLEND, + BRKOP, + BRKCL, + PLUS, + MINUS, + HAT, + SLASH, + ASTERISK +}; + +struct RawToken { + RawTokenType type = RawTokenType::NONE; + std::string svalue; + double dvalue = 0.0; + + inline bool istype(RawTokenType t) const { return this->type == t; } + + RawToken& operator=(RawTokenType t) { + type = t; + return *this; + } + RawToken& operator=(const std::string& v) { + svalue = v; + type = RawTokenType::STR; + return *this; + } + RawToken& operator=(const double v) { + dvalue = v; + type = RawTokenType::CONS; + return *this; + } +}; + +enum class ProcessedTokenType { + NONE, + SECID, + VARID, + CONID, + CONST, + FREE, + BRKOP, + BRKCL, + COMP, + LNEND, + SLASH, + ASTERISK, + HAT, + SOSTYPE +}; + +enum class LpSectionKeyword { + NONE, + OBJMIN, + OBJMAX, + CON, + BOUNDS, + GEN, + BIN, + SEMI, + SOS, + END +}; + +static const std::unordered_map + sectionkeywordmap{{"minimize", LpSectionKeyword::OBJMIN}, + {"min", LpSectionKeyword::OBJMIN}, + {"minimum", LpSectionKeyword::OBJMIN}, + {"maximize", LpSectionKeyword::OBJMAX}, + {"max", LpSectionKeyword::OBJMAX}, + {"maximum", LpSectionKeyword::OBJMAX}, + {"subject to", LpSectionKeyword::CON}, + {"such that", LpSectionKeyword::CON}, + {"st", LpSectionKeyword::CON}, + {"s.t.", LpSectionKeyword::CON}, + {"bounds", LpSectionKeyword::BOUNDS}, + {"bound", LpSectionKeyword::BOUNDS}, + {"binary", LpSectionKeyword::BIN}, + {"binaries", LpSectionKeyword::BIN}, + {"bin", LpSectionKeyword::BIN}, + {"general", LpSectionKeyword::GEN}, + {"generals", LpSectionKeyword::GEN}, + {"gen", LpSectionKeyword::GEN}, + {"integer", LpSectionKeyword::GEN}, + {"integers", LpSectionKeyword::GEN}, + {"semi-continuous", LpSectionKeyword::SEMI}, + {"semi", LpSectionKeyword::SEMI}, + {"semis", LpSectionKeyword::SEMI}, + {"sos", LpSectionKeyword::SOS}, + {"end", LpSectionKeyword::END}}; + +enum class SosType { SOS1, SOS2 }; + +enum class LpComparisonType { LEQ, L, EQ, G, GEQ }; + +struct ProcessedToken { + ProcessedTokenType type; + union { + LpSectionKeyword keyword; + SosType sostype; + char* name; + double value; + LpComparisonType dir; + }; + + ProcessedToken(const ProcessedToken&) = delete; + ProcessedToken(ProcessedToken&& t) : type(t.type) { + switch (type) { + case ProcessedTokenType::SECID: + keyword = t.keyword; + break; + case ProcessedTokenType::SOSTYPE: + sostype = t.sostype; + break; + case ProcessedTokenType::CONID: + case ProcessedTokenType::VARID: + name = t.name; + break; + case ProcessedTokenType::CONST: + value = t.value; + break; + case ProcessedTokenType::COMP: + dir = t.dir; + break; + default:; + } + t.type = ProcessedTokenType::NONE; + } + + ProcessedToken(ProcessedTokenType t) : type(t){}; + + ProcessedToken(LpSectionKeyword kw) + : type(ProcessedTokenType::SECID), keyword(kw){}; + + ProcessedToken(SosType sos) + : type(ProcessedTokenType::SOSTYPE), sostype(sos){}; + + ProcessedToken(ProcessedTokenType t, const std::string& s) : type(t) { + assert(t == ProcessedTokenType::CONID || t == ProcessedTokenType::VARID); +#ifndef _WIN32 + name = strdup(s.c_str()); +#else + name = _strdup(s.c_str()); +#endif + }; + + ProcessedToken(double v) : type(ProcessedTokenType::CONST), value(v){}; + + ProcessedToken(LpComparisonType comp) + : type(ProcessedTokenType::COMP), dir(comp){}; + + ~ProcessedToken() { + if (type == ProcessedTokenType::CONID || type == ProcessedTokenType::VARID) + free(name); + } +}; + +// how many raw tokens to cache +// set to how many tokens we may need to look ahead +#define NRAWTOKEN 3 + +const double kHighsInf = std::numeric_limits::infinity(); +class Reader { + private: +#ifdef ZLIB_FOUND + zstr::ifstream file; +#else + std::ifstream file; +#endif + std::string linebuffer; + std::size_t linebufferpos; + std::array rawtokens; + std::vector processedtokens; + // store for each section a pointer to its begin and end (pointer to element + // after last) + std::map::iterator, + std::vector::iterator> > + sectiontokens; + + Builder builder; + + bool readnexttoken(RawToken&); + void nextrawtoken(size_t howmany = 1); + void processtokens(); + void splittokens(); + void processsections(); + void processnonesec(); + void processobjsec(); + void processconsec(); + void processboundssec(); + void processbinsec(); + void processgensec(); + void processsemisec(); + void processsossec(); + void processendsec(); + void parseexpression(std::vector::iterator& it, + std::vector::iterator end, + std::shared_ptr expr, bool isobj); + + public: + Reader(std::string filename) { +#ifdef ZLIB_FOUND + try { + file.open(filename); + } catch (const strict_fstream::Exception& e) { + } +#else + file.open(filename); +#endif + lpassert(file.is_open()); + }; + + ~Reader() { file.close(); } + + Model read(); +}; + +Model readinstance(std::string filename) { + Reader reader(filename); + return reader.read(); +} + +// convert string to lower-case, modifies string +static inline void tolower(std::string& s) { + std::transform(s.begin(), s.end(), s.begin(), + [](unsigned char c) { return std::tolower(c); }); +} + +static inline bool iskeyword(const std::string& str, + const std::string* keywords, const int nkeywords) { + for (int i = 0; i < nkeywords; i++) { + if (str == keywords[i]) { + return true; + } + } + return false; +} + +static inline LpSectionKeyword parsesectionkeyword(const std::string& str) { + // look up lower case + auto it(sectionkeywordmap.find(str)); + if (it != sectionkeywordmap.end()) return it->second; + + return LpSectionKeyword::NONE; +} + +Model Reader::read() { + // std::clog << "Reading input, tokenizing..." << std::endl; + this->linebufferpos = 0; + // read first NRAWTOKEN token + // if file ends early, then all remaining tokens are set to FLEND + for (size_t i = 0; i < NRAWTOKEN; ++i) + while (!readnexttoken(rawtokens[i])) + ; + + processtokens(); + + linebuffer.clear(); + linebuffer.shrink_to_fit(); + + // std::clog << "Splitting tokens..." << std::endl; + splittokens(); + + // std::clog << "Setting up model..." << std::endl; + // + // Since + // + // "The problem statement must begin with the word MINIMIZE or + // MAXIMIZE, MINIMUM or MAXIMUM, or the abbreviations MIN or MAX, in + // any combination of upper- and lower-case characters. The word + // introduces the objective function section." + // + // Use positivity of sectiontokens.count(LpSectionKeyword::OBJMIN) + + // sectiontokens.count(LpSectionKeyword::OBJMAX) to identify garbage file + // + + const int num_objective_section = + sectiontokens.count(LpSectionKeyword::OBJMIN) + + sectiontokens.count(LpSectionKeyword::OBJMAX); + lpassert(num_objective_section>0); + + processsections(); + processedtokens.clear(); + processedtokens.shrink_to_fit(); + + return builder.model; +} + +void Reader::processnonesec() { + lpassert(sectiontokens.count(LpSectionKeyword::NONE) == 0); +} + +void Reader::parseexpression(std::vector::iterator& it, + std::vector::iterator end, + std::shared_ptr expr, bool isobj) { + if (it != end && it->type == ProcessedTokenType::CONID) { + expr->name = it->name; + ++it; + } + + while (it != end) { + std::vector::iterator next = it; + ++next; + // const var + if (next != end && it->type == ProcessedTokenType::CONST && + next->type == ProcessedTokenType::VARID) { + std::string name = next->name; + + std::shared_ptr linterm = + std::shared_ptr(new LinTerm()); + linterm->coef = it->value; + linterm->var = builder.getvarbyname(name); + // printf("LpReader: Term %+g %s\n", linterm->coef, + //name.c_str()); + expr->linterms.push_back(linterm); + + ++it; + ++it; + continue; + } + + // const + if (it->type == ProcessedTokenType::CONST) { + // printf("LpReader: Offset change from %+g by %+g\n", expr->offset, it->value); + expr->offset += it->value; + ++it; + continue; + } + + // var + if (it->type == ProcessedTokenType::VARID) { + std::string name = it->name; + + std::shared_ptr linterm = + std::shared_ptr(new LinTerm()); + linterm->coef = 1.0; + linterm->var = builder.getvarbyname(name); + // printf("LpReader: Term %+g %s\n", linterm->coef, + //name.c_str()); + expr->linterms.push_back(linterm); + + ++it; + continue; + } + + // quadratic expression + if (next != end && it->type == ProcessedTokenType::BRKOP) { + ++it; + while (it != end && it->type != ProcessedTokenType::BRKCL) { + // const var hat const + std::vector::iterator next1 = it; // token after it + std::vector::iterator next2 = it; // token 2nd-after it + std::vector::iterator next3 = it; // token 3rd-after it + ++next1; + ++next2; + ++next3; + if (next1 != end) { + ++next2; + ++next3; + } + if (next2 != end) ++next3; + + if (next3 != end && it->type == ProcessedTokenType::CONST && + next1->type == ProcessedTokenType::VARID && + next2->type == ProcessedTokenType::HAT && + next3->type == ProcessedTokenType::CONST) { + std::string name = next1->name; + + lpassert(next3->value == 2.0); + + std::shared_ptr quadterm = + std::shared_ptr(new QuadTerm()); + quadterm->coef = it->value; + quadterm->var1 = builder.getvarbyname(name); + quadterm->var2 = builder.getvarbyname(name); + expr->quadterms.push_back(quadterm); + + it = ++next3; + continue; + } + + // var hat const + if (next2 != end && it->type == ProcessedTokenType::VARID && + next1->type == ProcessedTokenType::HAT && + next2->type == ProcessedTokenType::CONST) { + std::string name = it->name; + + lpassert(next2->value == 2.0); + + std::shared_ptr quadterm = + std::shared_ptr(new QuadTerm()); + quadterm->coef = 1.0; + quadterm->var1 = builder.getvarbyname(name); + quadterm->var2 = builder.getvarbyname(name); + expr->quadterms.push_back(quadterm); + + it = next3; + continue; + } + + // const var asterisk var + if (next3 != end && it->type == ProcessedTokenType::CONST && + next1->type == ProcessedTokenType::VARID && + next2->type == ProcessedTokenType::ASTERISK && + next3->type == ProcessedTokenType::VARID) { + std::string name1 = next1->name; + std::string name2 = next3->name; + + std::shared_ptr quadterm = + std::shared_ptr(new QuadTerm()); + quadterm->coef = it->value; + quadterm->var1 = builder.getvarbyname(name1); + quadterm->var2 = builder.getvarbyname(name2); + expr->quadterms.push_back(quadterm); + + it = ++next3; + continue; + } + + // var asterisk var + if (next2 != end && it->type == ProcessedTokenType::VARID && + next1->type == ProcessedTokenType::ASTERISK && + next2->type == ProcessedTokenType::VARID) { + std::string name1 = it->name; + std::string name2 = next2->name; + + std::shared_ptr quadterm = + std::shared_ptr(new QuadTerm()); + quadterm->coef = 1.0; + quadterm->var1 = builder.getvarbyname(name1); + quadterm->var2 = builder.getvarbyname(name2); + expr->quadterms.push_back(quadterm); + + it = next3; + continue; + } + break; + } + if (isobj) { + // only in the objective function, a quadratic term is followed by + // "/2.0" + std::vector::iterator next1 = it; // token after it + std::vector::iterator next2 = it; // token 2nd-after it + ++next1; + ++next2; + if (next1 != end) ++next2; + + lpassert(next2 != end); + lpassert(it->type == ProcessedTokenType::BRKCL); + lpassert(next1->type == ProcessedTokenType::SLASH); + lpassert(next2->type == ProcessedTokenType::CONST); + lpassert(next2->value == 2.0); + it = ++next2; + } else { + lpassert(it != end); + lpassert(it->type == ProcessedTokenType::BRKCL); + ++it; + } + continue; + } + + break; + } +} + +void Reader::processobjsec() { + builder.model.objective = std::shared_ptr(new Expression); + if (sectiontokens.count(LpSectionKeyword::OBJMIN)) { + builder.model.sense = ObjectiveSense::MIN; + parseexpression(sectiontokens[LpSectionKeyword::OBJMIN].first, + sectiontokens[LpSectionKeyword::OBJMIN].second, + builder.model.objective, true); + lpassert(sectiontokens[LpSectionKeyword::OBJMIN].first == + sectiontokens[LpSectionKeyword::OBJMIN] + .second); // all section tokens should have been processed + } else if (sectiontokens.count(LpSectionKeyword::OBJMAX)) { + builder.model.sense = ObjectiveSense::MAX; + parseexpression(sectiontokens[LpSectionKeyword::OBJMAX].first, + sectiontokens[LpSectionKeyword::OBJMAX].second, + builder.model.objective, true); + lpassert(sectiontokens[LpSectionKeyword::OBJMAX].first == + sectiontokens[LpSectionKeyword::OBJMAX] + .second); // all section tokens should have been processed + } +} + +void Reader::processconsec() { + if (!sectiontokens.count(LpSectionKeyword::CON)) return; + std::vector::iterator& begin( + sectiontokens[LpSectionKeyword::CON].first); + std::vector::iterator& end( + sectiontokens[LpSectionKeyword::CON].second); + while (begin != end) { + std::shared_ptr con = + std::shared_ptr(new Constraint); + parseexpression(begin, end, con->expr, false); + // should not be at end of section yet, but a comparison operator should be + // next + lpassert(begin != sectiontokens[LpSectionKeyword::CON].second); + lpassert(begin->type == ProcessedTokenType::COMP); + LpComparisonType dir = begin->dir; + ++begin; + + // should still not be at end of section yet, but a right-hand-side value + // should be next + lpassert(begin != sectiontokens[LpSectionKeyword::CON].second); + lpassert(begin->type == ProcessedTokenType::CONST); + switch (dir) { + case LpComparisonType::EQ: + con->lowerbound = con->upperbound = begin->value; + break; + case LpComparisonType::LEQ: + con->upperbound = begin->value; + break; + case LpComparisonType::GEQ: + con->lowerbound = begin->value; + break; + default: + lpassert(false); + } + builder.model.constraints.push_back(con); + ++begin; + } +} + +void Reader::processboundssec() { + if (!sectiontokens.count(LpSectionKeyword::BOUNDS)) return; + std::vector::iterator& begin( + sectiontokens[LpSectionKeyword::BOUNDS].first); + std::vector::iterator& end( + sectiontokens[LpSectionKeyword::BOUNDS].second); + while (begin != end) { + std::vector::iterator next1 = begin; // token after begin + ++next1; + + // VAR free + if (next1 != end && begin->type == ProcessedTokenType::VARID && + next1->type == ProcessedTokenType::FREE) { + std::string name = begin->name; + std::shared_ptr var = builder.getvarbyname(name); + var->lowerbound = -kHighsInf; + var->upperbound = kHighsInf; + begin = ++next1; + continue; + } + + std::vector::iterator next2 = + next1; // token 2nd-after begin + std::vector::iterator next3 = + next1; // token 3rd-after begin + std::vector::iterator next4 = + next1; // token 4th-after begin + if (next1 != end) { + ++next2; + ++next3; + ++next4; + } + if (next2 != end) { + ++next3; + ++next4; + } + if (next3 != end) ++next4; + + // CONST COMP VAR COMP CONST + if (next4 != end && begin->type == ProcessedTokenType::CONST && + next1->type == ProcessedTokenType::COMP && + next2->type == ProcessedTokenType::VARID && + next3->type == ProcessedTokenType::COMP && + next4->type == ProcessedTokenType::CONST) { + lpassert(next1->dir == LpComparisonType::LEQ); + lpassert(next3->dir == LpComparisonType::LEQ); + + double lb = begin->value; + double ub = next4->value; + + std::string name = next2->name; + std::shared_ptr var = builder.getvarbyname(name); + + var->lowerbound = lb; + var->upperbound = ub; + + begin = ++next4; + continue; + } + + // CONST COMP VAR + if (next2 != end && begin->type == ProcessedTokenType::CONST && + next1->type == ProcessedTokenType::COMP && + next2->type == ProcessedTokenType::VARID) { + double value = begin->value; + std::string name = next2->name; + std::shared_ptr var = builder.getvarbyname(name); + LpComparisonType dir = next1->dir; + + lpassert(dir != LpComparisonType::L && dir != LpComparisonType::G); + + switch (dir) { + case LpComparisonType::LEQ: + var->lowerbound = value; + break; + case LpComparisonType::GEQ: + var->upperbound = value; + break; + case LpComparisonType::EQ: + var->lowerbound = var->upperbound = value; + break; + default: + lpassert(false); + } + begin = next3; + continue; + } + + // VAR COMP CONST + if (next2 != end && begin->type == ProcessedTokenType::VARID && + next1->type == ProcessedTokenType::COMP && + next2->type == ProcessedTokenType::CONST) { + double value = next2->value; + std::string name = begin->name; + std::shared_ptr var = builder.getvarbyname(name); + LpComparisonType dir = next1->dir; + + lpassert(dir != LpComparisonType::L && dir != LpComparisonType::G); + + switch (dir) { + case LpComparisonType::LEQ: + var->upperbound = value; + break; + case LpComparisonType::GEQ: + var->lowerbound = value; + break; + case LpComparisonType::EQ: + var->lowerbound = var->upperbound = value; + break; + default: + lpassert(false); + } + begin = next3; + continue; + } + + lpassert(false); + } +} + +void Reader::processbinsec() { + const LpSectionKeyword this_section_keyword = LpSectionKeyword::BIN; + if (!sectiontokens.count(this_section_keyword)) return; + std::vector::iterator& begin( + sectiontokens[this_section_keyword].first); + std::vector::iterator& end( + sectiontokens[this_section_keyword].second); + for (; begin != end; ++begin) { + if (begin->type == ProcessedTokenType::SECID) { + // Possible to have repeat of keyword for this section type + lpassert(begin->keyword == this_section_keyword); + continue; + } + lpassert(begin->type == ProcessedTokenType::VARID); + std::string name = begin->name; + std::shared_ptr var = builder.getvarbyname(name); + var->type = VariableType::BINARY; + // Respect any bounds already declared + if (var->upperbound == kHighsInf) var->upperbound = 1.0; + } +} + +void Reader::processgensec() { + const LpSectionKeyword this_section_keyword = LpSectionKeyword::GEN; + if (!sectiontokens.count(this_section_keyword)) return; + std::vector::iterator& begin( + sectiontokens[this_section_keyword].first); + std::vector::iterator& end( + sectiontokens[this_section_keyword].second); + for (; begin != end; ++begin) { + if (begin->type == ProcessedTokenType::SECID) { + // Possible to have repeat of keyword for this section type + lpassert(begin->keyword == this_section_keyword); + continue; + } + lpassert(begin->type == ProcessedTokenType::VARID); + std::string name = begin->name; + std::shared_ptr var = builder.getvarbyname(name); + if (var->type == VariableType::SEMICONTINUOUS) { + var->type = VariableType::SEMIINTEGER; + } else { + var->type = VariableType::GENERAL; + } + } +} + +void Reader::processsemisec() { + const LpSectionKeyword this_section_keyword = LpSectionKeyword::SEMI; + if (!sectiontokens.count(this_section_keyword)) return; + std::vector::iterator& begin( + sectiontokens[this_section_keyword].first); + std::vector::iterator& end( + sectiontokens[this_section_keyword].second); + for (; begin != end; ++begin) { + if (begin->type == ProcessedTokenType::SECID) { + // Possible to have repeat of keyword for this section type + lpassert(begin->keyword == this_section_keyword); + continue; + } + lpassert(begin->type == ProcessedTokenType::VARID); + std::string name = begin->name; + std::shared_ptr var = builder.getvarbyname(name); + if (var->type == VariableType::GENERAL) { + var->type = VariableType::SEMIINTEGER; + } else { + var->type = VariableType::SEMICONTINUOUS; + } + } +} + +void Reader::processsossec() { + const LpSectionKeyword this_section_keyword = LpSectionKeyword::SOS; + if (!sectiontokens.count(this_section_keyword)) return; + std::vector::iterator& begin( + sectiontokens[this_section_keyword].first); + std::vector::iterator& end( + sectiontokens[this_section_keyword].second); + while (begin != end) { + std::shared_ptr sos = std::shared_ptr(new SOS); + + // sos1: S1 :: x1 : 1 x2 : 2 x3 : 3 + + // name of SOS is mandatory + lpassert(begin->type == ProcessedTokenType::CONID); + sos->name = begin->name; + ++begin; + + // SOS type + lpassert(begin != end); + lpassert(begin->type == ProcessedTokenType::SOSTYPE); + sos->type = begin->sostype == SosType::SOS1 ? 1 : 2; + ++begin; + + while (begin != end) { + // process all "var : weight" entries + // when processtokens() sees a string followed by a colon, it classifies + // this as a CONID but in a SOS section, this is actually a variable + // identifier + if (begin->type != ProcessedTokenType::CONID) break; + std::string name = begin->name; + std::vector::iterator next = begin; + ++next; + if (next != end && next->type == ProcessedTokenType::CONST) { + auto var = builder.getvarbyname(name); + double weight = next->value; + + sos->entries.push_back({var, weight}); + + begin = ++next; + continue; + } + + break; + } + + builder.model.soss.push_back(sos); + } +} + +void Reader::processendsec() { + lpassert(sectiontokens.count(LpSectionKeyword::END) == 0); +} + +void Reader::processsections() { + processnonesec(); + processobjsec(); + processconsec(); + processboundssec(); + processgensec(); + processbinsec(); + processsemisec(); + processsossec(); + processendsec(); +} + +void Reader::splittokens() { + LpSectionKeyword currentsection = LpSectionKeyword::NONE; + + bool debug_open_section = false; + for (std::vector::iterator it(processedtokens.begin()); + it != processedtokens.end(); ++it) { + // Look for section keywords + if (it->type != ProcessedTokenType::SECID) continue; + // currentsection is initially LpSectionKeyword::NONE, so the + // first section ID will be a new section type + // + // Only record change of section and check for repeated + // section if the keyword is for a different section. Allows + // repetition of Integers and General (cf #1299) for example + const bool new_section_type = currentsection != it->keyword; + if (new_section_type) { + if (currentsection != LpSectionKeyword::NONE) { + // Current section is non-trivial, so mark its end, using the + // value of currentsection to indicate that there is no open + // section + lpassert(debug_open_section); + sectiontokens[currentsection].second = it; + debug_open_section = false; + currentsection = LpSectionKeyword::NONE; + } + } + std::vector::iterator next = it; + ++next; + if (next == processedtokens.end() || + next->type == ProcessedTokenType::SECID) { + // Reached the end of the tokens or the new section is empty + // + // currentsection will be LpSectionKeyword::NONE unless the + // second of two sections of the same type is empty and the + // next section is of a new type, in which case mark the end of + // the current section + if (currentsection != LpSectionKeyword::NONE && + currentsection != next->keyword) { + lpassert(debug_open_section); + sectiontokens[currentsection].second = it; + debug_open_section = false; + } + currentsection = LpSectionKeyword::NONE; + lpassert(!debug_open_section); + continue; + } + // Next section is non-empty + if (new_section_type) { + // Section type change + currentsection = it->keyword; + // Make sure the new section type has not occurred previously + lpassert(sectiontokens.count(currentsection) == 0); + // Remember the beginning of the new section: its the token + // following the current one + lpassert(!debug_open_section); + sectiontokens[currentsection].first = next; + debug_open_section = true; + } + // Always ends with either an open section or a section type of + // LpSectionKeyword::NONE + lpassert(debug_open_section != (currentsection == LpSectionKeyword::NONE)); + } + // Check that the last section has been closed + lpassert(currentsection == LpSectionKeyword::NONE); +} + +void Reader::processtokens() { + std::string svalue_lc; + while (!rawtokens[0].istype(RawTokenType::FLEND)) { + fflush(stdout); + + // Slash + asterisk: comment, skip everything up to next asterisk + slash + if (rawtokens[0].istype(RawTokenType::SLASH) && + rawtokens[1].istype(RawTokenType::ASTERISK)) { + do { + nextrawtoken(2); + } while (!(rawtokens[0].istype(RawTokenType::ASTERISK) && + rawtokens[1].istype(RawTokenType::SLASH)) && + !rawtokens[0].istype(RawTokenType::FLEND)); + nextrawtoken(2); + continue; + } + + if (rawtokens[0].istype(RawTokenType::STR)) { + svalue_lc = rawtokens[0].svalue; + tolower(svalue_lc); + } + + // long section keyword semi-continuous + if (rawtokens[0].istype(RawTokenType::STR) && + rawtokens[1].istype(RawTokenType::MINUS) && + rawtokens[2].istype(RawTokenType::STR)) { + std::string temp = rawtokens[2].svalue; + tolower(temp); + LpSectionKeyword keyword = parsesectionkeyword(svalue_lc + "-" + temp); + if (keyword != LpSectionKeyword::NONE) { + processedtokens.emplace_back(keyword); + nextrawtoken(3); + continue; + } + } + + // long section keyword subject to/such that + if (rawtokens[0].istype(RawTokenType::STR) && + rawtokens[1].istype(RawTokenType::STR)) { + std::string temp = rawtokens[1].svalue; + tolower(temp); + LpSectionKeyword keyword = parsesectionkeyword(svalue_lc + " " + temp); + if (keyword != LpSectionKeyword::NONE) { + processedtokens.emplace_back(keyword); + nextrawtoken(2); + continue; + } + } + + // other section keyword + if (rawtokens[0].istype(RawTokenType::STR)) { + LpSectionKeyword keyword = parsesectionkeyword(svalue_lc); + if (keyword != LpSectionKeyword::NONE) { + processedtokens.emplace_back(keyword); + nextrawtoken(); + continue; + } + } + + // sos type identifier? "S1 ::" or "S2 ::" + if (rawtokens[0].istype(RawTokenType::STR) && + rawtokens[1].istype(RawTokenType::COLON) && + rawtokens[2].istype(RawTokenType::COLON)) { + lpassert(rawtokens[0].svalue.length() == 2); + lpassert(rawtokens[0].svalue[0] == 'S' || rawtokens[0].svalue[0] == 's'); + lpassert(rawtokens[0].svalue[1] == '1' || rawtokens[0].svalue[1] == '2'); + processedtokens.emplace_back( + rawtokens[0].svalue[1] == '1' ? SosType::SOS1 : SosType::SOS2); + nextrawtoken(3); + continue; + } + + // constraint identifier? + if (rawtokens[0].istype(RawTokenType::STR) && + rawtokens[1].istype(RawTokenType::COLON)) { + processedtokens.emplace_back(ProcessedTokenType::CONID, + rawtokens[0].svalue); + nextrawtoken(2); + continue; + } + + // check if free + if (rawtokens[0].istype(RawTokenType::STR) && + iskeyword(svalue_lc, LP_KEYWORD_FREE, LP_KEYWORD_FREE_N)) { + processedtokens.emplace_back(ProcessedTokenType::FREE); + nextrawtoken(); + continue; + } + + // check if infinity + if (rawtokens[0].istype(RawTokenType::STR) && + iskeyword(svalue_lc, LP_KEYWORD_INF, LP_KEYWORD_INF_N)) { + processedtokens.emplace_back(kHighsInf); + nextrawtoken(); + continue; + } + + // assume var identifier + if (rawtokens[0].istype(RawTokenType::STR)) { + processedtokens.emplace_back(ProcessedTokenType::VARID, + rawtokens[0].svalue); + nextrawtoken(); + continue; + } + + // + or - + if (rawtokens[0].istype(RawTokenType::PLUS) || + rawtokens[0].istype(RawTokenType::MINUS)) { + double sign = rawtokens[0].istype(RawTokenType::PLUS) ? 1.0 : -1.0; + nextrawtoken(); + + // another + or - for #948, #950 + if (rawtokens[0].istype(RawTokenType::PLUS) || + rawtokens[0].istype(RawTokenType::MINUS)) { + sign *= rawtokens[0].istype(RawTokenType::PLUS) ? 1.0 : -1.0; + nextrawtoken(); + } + + // +/- Constant + if (rawtokens[0].istype(RawTokenType::CONS)) { + processedtokens.emplace_back(sign * rawtokens[0].dvalue); + nextrawtoken(); + continue; + } + + // + [, + + [, - - [ + if (rawtokens[0].istype(RawTokenType::BRKOP) && sign == 1.0) { + processedtokens.emplace_back(ProcessedTokenType::BRKOP); + nextrawtoken(); + continue; + } + + // - [, + - [, - + [ + if (rawtokens[0].istype(RawTokenType::BRKOP)) lpassert(false); + + // +/- variable name + if (rawtokens[0].istype(RawTokenType::STR)) { + processedtokens.emplace_back(sign); + continue; + } + + // +/- (possibly twice) followed by something that isn't a constant, + // opening bracket, or string (variable name) + if (rawtokens[0].istype(RawTokenType::GREATER)) { + // ">" suggests that the file contains indicator constraints + printf( + "File appears to contain indicator constraints: cannot currently " + "be handled by HiGHS\n"); + } + lpassert(false); + } + + // constant [ + if (rawtokens[0].istype(RawTokenType::CONS) && + rawtokens[1].istype(RawTokenType::BRKOP)) { + lpassert(false); + } + + // constant + if (rawtokens[0].istype(RawTokenType::CONS)) { + processedtokens.emplace_back(rawtokens[0].dvalue); + nextrawtoken(); + continue; + } + + // [ + if (rawtokens[0].istype(RawTokenType::BRKOP)) { + processedtokens.emplace_back(ProcessedTokenType::BRKOP); + nextrawtoken(); + continue; + } + + // ] + if (rawtokens[0].istype(RawTokenType::BRKCL)) { + processedtokens.emplace_back(ProcessedTokenType::BRKCL); + nextrawtoken(); + continue; + } + + // / + if (rawtokens[0].istype(RawTokenType::SLASH)) { + processedtokens.emplace_back(ProcessedTokenType::SLASH); + nextrawtoken(); + continue; + } + + // * + if (rawtokens[0].istype(RawTokenType::ASTERISK)) { + processedtokens.emplace_back(ProcessedTokenType::ASTERISK); + nextrawtoken(); + continue; + } + + // ^ + if (rawtokens[0].istype(RawTokenType::HAT)) { + processedtokens.emplace_back(ProcessedTokenType::HAT); + nextrawtoken(); + continue; + } + + // <= + if (rawtokens[0].istype(RawTokenType::LESS) && + rawtokens[1].istype(RawTokenType::EQUAL)) { + processedtokens.emplace_back(LpComparisonType::LEQ); + nextrawtoken(2); + continue; + } + + // < + if (rawtokens[0].istype(RawTokenType::LESS)) { + processedtokens.emplace_back(LpComparisonType::L); + nextrawtoken(); + continue; + } + + // >= + if (rawtokens[0].istype(RawTokenType::GREATER) && + rawtokens[1].istype(RawTokenType::EQUAL)) { + processedtokens.emplace_back(LpComparisonType::GEQ); + nextrawtoken(2); + continue; + } + + // > + if (rawtokens[0].istype(RawTokenType::GREATER)) { + processedtokens.emplace_back(LpComparisonType::G); + nextrawtoken(); + continue; + } + + // = + if (rawtokens[0].istype(RawTokenType::EQUAL)) { + processedtokens.emplace_back(LpComparisonType::EQ); + nextrawtoken(); + continue; + } + + // FILEEND should have been handled in condition of while() + assert(!rawtokens[0].istype(RawTokenType::FLEND)); + + // catch all unknown symbols + lpassert(false); + break; + } +} + +void Reader::nextrawtoken(size_t howmany) { + assert(howmany > 0); + assert(howmany <= NRAWTOKEN); + static_assert(NRAWTOKEN == 3, + "code below need to be adjusted if NRAWTOKEN changes"); + switch (howmany) { + case 1: { + rawtokens[0] = std::move(rawtokens[1]); + rawtokens[1] = std::move(rawtokens[2]); + while (!readnexttoken(rawtokens[2])) + ; + break; + } + case 2: { + rawtokens[0] = std::move(rawtokens[2]); + while (!readnexttoken(rawtokens[1])) + ; + while (!readnexttoken(rawtokens[2])) + ; + break; + } + case 3: { + while (!readnexttoken(rawtokens[0])) + ; + while (!readnexttoken(rawtokens[1])) + ; + while (!readnexttoken(rawtokens[2])) + ; + break; + } + default: { + size_t i = 0; + // move tokens up + for (; i < NRAWTOKEN - howmany; ++i) + rawtokens[i] = std::move(rawtokens[i + howmany]); + // read new tokens at end positions + for (; i < NRAWTOKEN; ++i) + // call readnexttoken() to overwrite current token + // if it didn't actually read a token (returns false), then call again + while (!readnexttoken(rawtokens[i])) + ; + } + } +} + +// return true, if token has been set; return false if skipped over whitespace +// only +bool Reader::readnexttoken(RawToken& t) { + if (this->linebufferpos == this->linebuffer.size()) { + // read next line if any are left. + if (this->file.eof()) { + t = RawTokenType::FLEND; + return true; + } + std::getline(this->file, linebuffer); + + // drop \r + if (!linebuffer.empty() && linebuffer.back() == '\r') linebuffer.pop_back(); + + // reset linebufferpos + this->linebufferpos = 0; + } + + // check single character tokens + char nextchar = this->linebuffer[this->linebufferpos]; + + switch (nextchar) { + // check for comment + case '\\': + // skip rest of line + this->linebufferpos = this->linebuffer.size(); + return false; + + // check for bracket opening + case '[': + t = RawTokenType::BRKOP; + this->linebufferpos++; + return true; + + // check for bracket closing + case ']': + t = RawTokenType::BRKCL; + this->linebufferpos++; + return true; + + // check for less sign + case '<': + t = RawTokenType::LESS; + this->linebufferpos++; + return true; + + // check for greater sign + case '>': + t = RawTokenType::GREATER; + this->linebufferpos++; + return true; + + // check for equal sign + case '=': + t = RawTokenType::EQUAL; + this->linebufferpos++; + return true; + + // check for colon + case ':': + t = RawTokenType::COLON; + this->linebufferpos++; + return true; + + // check for plus + case '+': + t = RawTokenType::PLUS; + this->linebufferpos++; + return true; + + // check for hat + case '^': + t = RawTokenType::HAT; + this->linebufferpos++; + return true; + + // check for slash + case '/': + t = RawTokenType::SLASH; + this->linebufferpos++; + return true; + + // check for asterisk + case '*': + t = RawTokenType::ASTERISK; + this->linebufferpos++; + return true; + + // check for minus + case '-': + t = RawTokenType::MINUS; + this->linebufferpos++; + return true; + + // check for whitespace + case ' ': + case '\t': + this->linebufferpos++; + return false; + + // check for line end + case ';': + case '\n': // \n should not happen due to using getline() + this->linebufferpos = this->linebuffer.size(); + return false; + + case '\0': // empty line + lpassert(this->linebufferpos == this->linebuffer.size()); + return false; + } + + // check for double value + const char* startptr = this->linebuffer.data() + this->linebufferpos; + char* endptr; + double constant = strtod(startptr, &endptr); + if (endptr != startptr) { + t = constant; + this->linebufferpos += endptr - startptr; + return true; + } + + // assume it's an (section/variable/constraint) identifier + auto endpos = + this->linebuffer.find_first_of("\t\n\\:+<>^= /-*[]", this->linebufferpos); + if (endpos == std::string::npos) + endpos = this->linebuffer.size(); // take complete rest of string + if (endpos > this->linebufferpos) { + t = std::string(this->linebuffer, this->linebufferpos, + endpos - this->linebufferpos); + this->linebufferpos = endpos; + return true; + } + + lpassert(false); + return false; +} diff --git a/extern/filereaderlp/reader.hpp b/extern/filereaderlp/reader.hpp index f292d1df14..b86a954281 100644 --- a/extern/filereaderlp/reader.hpp +++ b/extern/filereaderlp/reader.hpp @@ -1,10 +1,10 @@ -#ifndef __READERLP_READER_HPP__ -#define __READERLP_READER_HPP__ - -#include - -#include "model.hpp" - -Model readinstance(std::string filename); - -#endif +#ifndef __READERLP_READER_HPP__ +#define __READERLP_READER_HPP__ + +#include + +#include "model.hpp" + +Model readinstance(std::string filename); + +#endif diff --git a/src/HConfig.h.bazel.in b/src/HConfig.h.bazel.in index d6cd6003fa..3f370785ef 100644 --- a/src/HConfig.h.bazel.in +++ b/src/HConfig.h.bazel.in @@ -11,9 +11,9 @@ #define HIGHS_HAVE_BUILTIN_CLZ /* #undef HIGHS_HAVE_BITSCAN_REVERSE */ -#define HIGHS_GITHASH "50670fd4c" +#define HIGHS_GITHASH "bdf95f2e0" #define HIGHS_VERSION_MAJOR 1 -#define HIGHS_VERSION_MINOR 7 +#define HIGHS_VERSION_MINOR 9 #define HIGHS_VERSION_PATCH 0 /* #undef HIGHS_DIR */ diff --git a/src/Highs.h b/src/Highs.h index 6759529bd4..8bebbd16c2 100644 --- a/src/Highs.h +++ b/src/Highs.h @@ -312,11 +312,11 @@ class Highs { /** * @brief Write (deviations from default values of) the options to a - * file, with the extension ".html" producing HTML, otherwise using - * the standard format used to read options from a file. + * file, using the standard format used to read options from a file. + * Possible to write only deviations from default values. */ HighsStatus writeOptions(const std::string& filename, //!< The filename - const bool report_only_deviations = false) const; + const bool report_only_deviations = false); /** * @brief Returns the number of user-settable options @@ -411,7 +411,7 @@ class Highs { /** * @brief Get the run time of HiGHS */ - double getRunTime() { return timer_.readRunHighsClock(); } + double getRunTime() { return timer_.read(); } /** * Methods for model output @@ -510,29 +510,31 @@ class Highs { } /** - * @brief Indicate whether a dual unbounded ray exists, and gets - * it if it does and dual_ray is not nullptr + * @brief Indicate whether a dual unbounded ray exists, and (at the + * expense of solving an LP) gets it if it does not and + * dual_ray_value is not nullptr */ HighsStatus getDualRay(bool& has_dual_ray, double* dual_ray_value = nullptr); /** - * @brief Indicate whether a dual unbounded ray exists, and gets - * it if it does + * @brief Indicate whether a dual unbounded ray exists, and gets it + * if it does */ HighsStatus getDualRaySparse(bool& has_dual_ray, HVector& row_ep_buffer); /** * @brief Indicate whether a dual unboundedness direction exists, - * and gets it if it does and dual_unboundedness_direction is not - * nullptr + * and (at the expense of solving an LP) gets it if + * dual_unboundedness_direction is not nullptr */ HighsStatus getDualUnboundednessDirection( bool& has_dual_unboundedness_direction, double* dual_unboundedness_direction_value = nullptr); /** - * @brief Indicate whether a primal unbounded ray exists, and gets - * it if it does and primal_ray is not nullptr + * @brief Indicate whether a primal unbounded ray exists, and (at + * the expense of solving an LP) gets it if primal_ray is not + * nullptr */ HighsStatus getPrimalRay(bool& has_primal_ray, double* primal_ray_value = nullptr); @@ -1046,6 +1048,16 @@ class Highs { const HighsInt* starts, const HighsInt* indices, const double* values); + HighsStatus ensureColwise() { + this->model_.lp_.ensureColwise(); + return HighsStatus::kOk; + } + + HighsStatus ensureRowwise() { + this->model_.lp_.ensureRowwise(); + return HighsStatus::kOk; + } + /** * @brief Delete multiple columns from the incumbent model given by an * interval [from_col, to_col] @@ -1304,6 +1316,19 @@ class Highs { return ekk_instance_.primal_phase1_dual_; } + /** + * @brief Development methods + */ + HighsInt defineClock(const char* name) { + return this->timer_.clock_def(name); + } + void writeAllClocks() { this->timer_.writeAllClocks(); } + HighsStatus clearModelNames() { + this->model_.lp_.col_names_.clear(); + this->model_.lp_.row_names_.clear(); + return HighsStatus::kOk; + } + // Start of deprecated methods std::string compilationDate() const { return "deprecated"; } @@ -1446,7 +1471,7 @@ class Highs { bool called_return_from_run = true; HighsInt debug_run_call_num_ = 0; - bool written_log_header = false; + bool written_log_header_ = false; HighsStatus solve(); @@ -1480,11 +1505,6 @@ class Highs { // and basis data void setHighsModelStatusAndClearSolutionAndBasis( const HighsModelStatus model_status); - // - // Sets model status, basis, solution and info from the - // highs_model_object - void setBasisValidity(); - // // Clears the presolved model and its status void clearPresolve(); // @@ -1553,15 +1573,14 @@ class Highs { void deleteRowsInterface(HighsIndexCollection& index_collection); void getColsInterface(const HighsIndexCollection& index_collection, - HighsInt& num_col, double* col_cost, double* col_lower, - double* col_upper, HighsInt& num_nz, - HighsInt* col_matrix_start, HighsInt* col_matrix_index, - double* col_matrix_value); + HighsInt& num_col, double* cost, double* lower, + double* upper, HighsInt& num_nz, HighsInt* start, + HighsInt* index, double* value); void getRowsInterface(const HighsIndexCollection& index_collection, - HighsInt& num_row, double* row_lower, double* row_upper, - HighsInt& num_nz, HighsInt* row_matrix_start, - HighsInt* row_matrix_index, double* row_matrix_value); + HighsInt& num_row, double* lower, double* upper, + HighsInt& num_nz, HighsInt* start, HighsInt* index, + double* value); void getCoefficientInterface(const HighsInt ext_row, const HighsInt ext_col, double& value); diff --git a/src/highs_bindings.cpp b/src/highs_bindings.cpp index 5b4069a96c..5b03d426c6 100644 --- a/src/highs_bindings.cpp +++ b/src/highs_bindings.cpp @@ -187,6 +187,240 @@ std::tuple highs_getRanging(Highs* h) { return std::make_tuple(status, ranging); } +std::tuple> +highs_getBasicVariables(Highs* h) { + HighsInt num_row = h->getNumRow(); + + HighsStatus status = HighsStatus::kOk; + std::vector basic_variables(num_row); + HighsInt* basic_variables_ptr = static_cast(basic_variables.data()); + if (num_row > 0) status = h->getBasicVariables(basic_variables_ptr); + return std::make_tuple(status, py::cast(basic_variables)); +} + +std::tuple> +highs_getBasisInverseRow(Highs* h, HighsInt row) { + HighsInt num_row = h->getNumRow(); + + HighsStatus status = HighsStatus::kOk; + std::vector solution_vector(num_row); + double* solution_vector_ptr = static_cast(solution_vector.data()); + + if (num_row > 0) status = h->getBasisInverseRow(row, solution_vector_ptr); + return std::make_tuple(status, py::cast(solution_vector)); +} + +std::tuple, HighsInt, dense_array_t> +highs_getBasisInverseRowSparse(Highs* h, HighsInt row) { + HighsInt num_row = h->getNumRow(); + + HighsStatus status = HighsStatus::kOk; + HighsInt solution_num_nz = 0; + std::vector solution_vector(num_row); + std::vector solution_index(num_row); + double* solution_vector_ptr = static_cast(solution_vector.data()); + HighsInt* solution_index_ptr = static_cast(solution_index.data()); + + if (num_row > 0) status = h->getBasisInverseRow(row, solution_vector_ptr, &solution_num_nz, solution_index_ptr); + return std::make_tuple(status, py::cast(solution_vector), solution_num_nz, py::cast(solution_index)); +} + +std::tuple> +highs_getBasisInverseCol(Highs* h, HighsInt col) { + HighsInt num_row = h->getNumRow(); + + HighsStatus status = HighsStatus::kOk; + std::vector solution_vector(num_row); + double* solution_vector_ptr = static_cast(solution_vector.data()); + + if (num_row > 0) status = h->getBasisInverseCol(col, solution_vector_ptr); + return std::make_tuple(status, py::cast(solution_vector)); +} + +std::tuple, HighsInt, dense_array_t> +highs_getBasisInverseColSparse(Highs* h, HighsInt col) { + HighsInt num_row = h->getNumRow(); + + HighsStatus status = HighsStatus::kOk; + HighsInt solution_num_nz = 0; + std::vector solution_vector(num_row); + std::vector solution_index(num_row); + double* solution_vector_ptr = static_cast(solution_vector.data()); + HighsInt* solution_index_ptr = static_cast(solution_index.data()); + + if (num_row > 0) status = h->getBasisInverseCol(col, solution_vector_ptr, &solution_num_nz, solution_index_ptr); + return std::make_tuple(status, py::cast(solution_vector), solution_num_nz, py::cast(solution_index)); +} + +std::tuple> +highs_getBasisSolve(Highs* h, dense_array_t rhs) { + HighsInt num_row = h->getNumRow(); + + py::buffer_info rhs_info = rhs.request(); + double* rhs_ptr = static_cast(rhs_info.ptr); + + HighsStatus status = HighsStatus::kOk; + std::vector solution_vector(num_row); + double* solution_vector_ptr = static_cast(solution_vector.data()); + + if (num_row > 0) status = h->getBasisSolve(rhs_ptr, solution_vector_ptr); + return std::make_tuple(status, py::cast(solution_vector)); +} + +std::tuple, HighsInt, dense_array_t> +highs_getBasisSolveSparse(Highs* h, dense_array_t rhs) { + HighsInt num_row = h->getNumRow(); + + py::buffer_info rhs_info = rhs.request(); + double* rhs_ptr = static_cast(rhs_info.ptr); + + HighsStatus status = HighsStatus::kOk; + HighsInt solution_num_nz = 0; + std::vector solution_vector(num_row); + std::vector solution_index(num_row); + double* solution_vector_ptr = static_cast(solution_vector.data()); + HighsInt* solution_index_ptr = static_cast(solution_index.data()); + + if (num_row > 0) status = h->getBasisSolve(rhs_ptr, solution_vector_ptr, &solution_num_nz, solution_index_ptr); + return std::make_tuple(status, py::cast(solution_vector), solution_num_nz, py::cast(solution_index)); +} + +std::tuple> highs_getBasisTransposeSolve(Highs* h, dense_array_t rhs) { + HighsInt num_row = h->getNumRow(); + + py::buffer_info rhs_info = rhs.request(); + double* rhs_ptr = static_cast(rhs_info.ptr); + + HighsStatus status = HighsStatus::kOk; + std::vector solution_vector(num_row); + double* solution_vector_ptr = static_cast(solution_vector.data()); + + if (num_row > 0) status = h->getBasisTransposeSolve(rhs_ptr, solution_vector_ptr); + return std::make_tuple(status, py::cast(solution_vector)); +} + +std::tuple, HighsInt, dense_array_t> +highs_getBasisTransposeSolveSparse(Highs* h, dense_array_t rhs) { + HighsInt num_row = h->getNumRow(); + + py::buffer_info rhs_info = rhs.request(); + double* rhs_ptr = static_cast(rhs_info.ptr); + + HighsStatus status = HighsStatus::kOk; + HighsInt solution_num_nz = 0; + std::vector solution_vector(num_row); + std::vector solution_index(num_row); + double* solution_vector_ptr = static_cast(solution_vector.data()); + HighsInt* solution_index_ptr = static_cast(solution_index.data()); + + if (num_row > 0) status = h->getBasisTransposeSolve(rhs_ptr, solution_vector_ptr, &solution_num_nz, solution_index_ptr); + return std::make_tuple(status, py::cast(solution_vector), solution_num_nz, py::cast(solution_index)); +} + +std::tuple> +highs_getReducedRow(Highs* h, HighsInt row) { + HighsInt num_col = h->getNumCol(); + HighsInt num_row = h->getNumRow(); + + HighsStatus status = HighsStatus::kOk; + std::vector solution_vector(num_col); + double* solution_vector_ptr = static_cast(solution_vector.data()); + + if (num_row > 0) status = h->getReducedRow(row, solution_vector_ptr); + return std::make_tuple(status, py::cast(solution_vector)); +} + +std::tuple, HighsInt, dense_array_t> +highs_getReducedRowSparse(Highs* h, HighsInt row) { + HighsInt num_col = h->getNumCol(); + HighsInt num_row = h->getNumRow(); + + HighsStatus status = HighsStatus::kOk; + HighsInt solution_num_nz = 0; + std::vector solution_vector(num_row); + std::vector solution_index(num_row); + double* solution_vector_ptr = static_cast(solution_vector.data()); + HighsInt* solution_index_ptr = static_cast(solution_index.data()); + + if (num_row > 0) status = h->getReducedRow(row, solution_vector_ptr, &solution_num_nz, solution_index_ptr); + return std::make_tuple(status, py::cast(solution_vector), solution_num_nz, py::cast(solution_index)); +} + +std::tuple> +highs_getReducedColumn(Highs* h, HighsInt col) { + HighsInt num_row = h->getNumRow(); + + HighsStatus status = HighsStatus::kOk; + std::vector solution_vector(num_row); + double* solution_vector_ptr = static_cast(solution_vector.data()); + + if (num_row > 0) status = h->getReducedColumn(col, solution_vector_ptr); + return std::make_tuple(status, py::cast(solution_vector)); +} + +std::tuple, HighsInt, dense_array_t> +highs_getReducedColumnSparse(Highs* h, HighsInt col) { + HighsInt num_row = h->getNumRow(); + + HighsStatus status = HighsStatus::kOk; + HighsInt solution_num_nz = 0; + std::vector solution_vector(num_row); + std::vector solution_index(num_row); + double* solution_vector_ptr = static_cast(solution_vector.data()); + HighsInt* solution_index_ptr = static_cast(solution_index.data()); + + if (num_row > 0) status = h->getReducedColumn(col, solution_vector_ptr, &solution_num_nz, solution_index_ptr); + return std::make_tuple(status, py::cast(solution_vector), solution_num_nz, py::cast(solution_index)); +} + +std::tuple highs_getDualRayExist(Highs* h) { + bool has_dual_ray; + HighsStatus status = h->getDualRay(has_dual_ray); + return std::make_tuple(status, has_dual_ray); +} + +std::tuple> highs_getDualRay(Highs* h) { + HighsInt num_row = h->getNumRow(); + bool has_dual_ray; + HighsStatus status = HighsStatus::kOk; + std::vector value(num_row); + double* value_ptr = static_cast(value.data()); + if (num_row > 0) status = h->getDualRay(has_dual_ray, value_ptr); + return std::make_tuple(status, has_dual_ray, py::cast(value)); +} + +std::tuple highs_getDualUnboundednessDirectionExist(Highs* h) { + bool has_dual_unboundedness_direction; + HighsStatus status = h->getDualUnboundednessDirection(has_dual_unboundedness_direction); + return std::make_tuple(status, has_dual_unboundedness_direction); +} + +std::tuple> highs_getDualUnboundednessDirection(Highs* h) { + HighsInt num_col = h->getNumCol(); + bool has_dual_unboundedness_direction; + HighsStatus status = HighsStatus::kOk; + std::vector value(num_col); + double* value_ptr = static_cast(value.data()); + if (num_col > 0) status = h->getDualUnboundednessDirection(has_dual_unboundedness_direction, value_ptr); + return std::make_tuple(status, has_dual_unboundedness_direction, py::cast(value)); +} + +std::tuple highs_getPrimalRayExist(Highs* h) { + bool has_primal_ray; + HighsStatus status = h->getPrimalRay(has_primal_ray); + return std::make_tuple(status, has_primal_ray); +} + +std::tuple> highs_getPrimalRay(Highs* h) { + HighsInt num_col = h->getNumCol(); + bool has_primal_ray; + HighsStatus status = HighsStatus::kOk; + std::vector value(num_col); + double* value_ptr = static_cast(value.data()); + if (num_col > 0) status = h->getPrimalRay(has_primal_ray, value_ptr); + return std::make_tuple(status, has_primal_ray, py::cast(value)); +} + HighsStatus highs_addRow(Highs* h, double lower, double upper, HighsInt num_new_nz, dense_array_t indices, dense_array_t values) { @@ -652,27 +886,27 @@ PYBIND11_MODULE(_core, m, py::mod_gil_not_used()) { // parent scope, which should be skipped for newer C++11-style strongly typed // enums." // [1]: https://pybind11.readthedocs.io/en/stable/classes.html - py::enum_(m, "ObjSense") + py::enum_(m, "ObjSense", py::module_local()) .value("kMinimize", ObjSense::kMinimize) .value("kMaximize", ObjSense::kMaximize); - py::enum_(m, "MatrixFormat") + py::enum_(m, "MatrixFormat", py::module_local()) .value("kColwise", MatrixFormat::kColwise) .value("kRowwise", MatrixFormat::kRowwise) .value("kRowwisePartitioned", MatrixFormat::kRowwisePartitioned); - py::enum_(m, "HessianFormat") + py::enum_(m, "HessianFormat", py::module_local()) .value("kTriangular", HessianFormat::kTriangular) .value("kSquare", HessianFormat::kSquare); - py::enum_(m, "SolutionStatus") + py::enum_(m, "SolutionStatus", py::module_local()) .value("kSolutionStatusNone", SolutionStatus::kSolutionStatusNone) .value("kSolutionStatusInfeasible", SolutionStatus::kSolutionStatusInfeasible) .value("kSolutionStatusFeasible", SolutionStatus::kSolutionStatusFeasible) .export_values(); - py::enum_(m, "BasisValidity") + py::enum_(m, "BasisValidity", py::module_local()) .value("kBasisValidityInvalid", BasisValidity::kBasisValidityInvalid) .value("kBasisValidityValid", BasisValidity::kBasisValidityValid) .export_values(); - py::enum_(m, "HighsModelStatus") + py::enum_(m, "HighsModelStatus", py::module_local()) .value("kNotset", HighsModelStatus::kNotset) .value("kLoadError", HighsModelStatus::kLoadError) .value("kModelError", HighsModelStatus::kModelError) @@ -692,7 +926,7 @@ PYBIND11_MODULE(_core, m, py::mod_gil_not_used()) { .value("kSolutionLimit", HighsModelStatus::kSolutionLimit) .value("kInterrupt", HighsModelStatus::kInterrupt) .value("kMemoryLimit", HighsModelStatus::kMemoryLimit); - py::enum_(m, "HighsPresolveStatus") + py::enum_(m, "HighsPresolveStatus", py::module_local()) .value("kNotPresolved", HighsPresolveStatus::kNotPresolved) .value("kNotReduced", HighsPresolveStatus::kNotReduced) .value("kInfeasible", HighsPresolveStatus::kInfeasible) @@ -703,37 +937,38 @@ PYBIND11_MODULE(_core, m, py::mod_gil_not_used()) { .value("kTimeout", HighsPresolveStatus::kTimeout) .value("kNullError", HighsPresolveStatus::kNullError) .value("kOptionsError", HighsPresolveStatus::kOptionsError); - py::enum_(m, "HighsBasisStatus") + py::enum_(m, "HighsBasisStatus", py::module_local()) .value("kLower", HighsBasisStatus::kLower) .value("kBasic", HighsBasisStatus::kBasic) .value("kUpper", HighsBasisStatus::kUpper) .value("kZero", HighsBasisStatus::kZero) .value("kNonbasic", HighsBasisStatus::kNonbasic); - py::enum_(m, "HighsVarType") + py::enum_(m, "HighsVarType", py::module_local()) .value("kContinuous", HighsVarType::kContinuous) .value("kInteger", HighsVarType::kInteger) .value("kSemiContinuous", HighsVarType::kSemiContinuous) - .value("kSemiInteger", HighsVarType::kSemiInteger); - py::enum_(m, "HighsOptionType") + .value("kSemiInteger", HighsVarType::kSemiInteger) + .value("kImplicitInteger", HighsVarType::kImplicitInteger); + py::enum_(m, "HighsOptionType", py::module_local()) .value("kBool", HighsOptionType::kBool) .value("kInt", HighsOptionType::kInt) .value("kDouble", HighsOptionType::kDouble) .value("kString", HighsOptionType::kString); - py::enum_(m, "HighsInfoType") + py::enum_(m, "HighsInfoType", py::module_local()) .value("kInt64", HighsInfoType::kInt64) .value("kInt", HighsInfoType::kInt) .value("kDouble", HighsInfoType::kDouble); - py::enum_(m, "HighsStatus") + py::enum_(m, "HighsStatus", py::module_local()) .value("kError", HighsStatus::kError) .value("kOk", HighsStatus::kOk) .value("kWarning", HighsStatus::kWarning); - py::enum_(m, "HighsLogType") + py::enum_(m, "HighsLogType", py::module_local()) .value("kInfo", HighsLogType::kInfo) .value("kDetailed", HighsLogType::kDetailed) .value("kVerbose", HighsLogType::kVerbose) .value("kWarning", HighsLogType::kWarning) .value("kError", HighsLogType::kError); - py::enum_(m, "IisStrategy") + py::enum_(m, "IisStrategy", py::module_local()) .value("kIisStrategyMin", IisStrategy::kIisStrategyMin) .value("kIisStrategyFromLpRowPriority", IisStrategy::kIisStrategyFromLpRowPriority) @@ -741,7 +976,7 @@ PYBIND11_MODULE(_core, m, py::mod_gil_not_used()) { IisStrategy::kIisStrategyFromLpColPriority) .value("kIisStrategyMax", IisStrategy::kIisStrategyMax) .export_values(); - py::enum_(m, "IisBoundStatus") + py::enum_(m, "IisBoundStatus", py::module_local()) .value("kIisBoundStatusDropped", IisBoundStatus::kIisBoundStatusDropped) .value("kIisBoundStatusNull", IisBoundStatus::kIisBoundStatusNull) .value("kIisBoundStatusFree", IisBoundStatus::kIisBoundStatusFree) @@ -749,7 +984,7 @@ PYBIND11_MODULE(_core, m, py::mod_gil_not_used()) { .value("kIisBoundStatusUpper", IisBoundStatus::kIisBoundStatusUpper) .value("kIisBoundStatusBoxed", IisBoundStatus::kIisBoundStatusBoxed) .export_values(); - py::enum_(m, "HighsDebugLevel") + py::enum_(m, "HighsDebugLevel", py::module_local()) .value("kHighsDebugLevelNone", HighsDebugLevel::kHighsDebugLevelNone) .value("kHighsDebugLevelCheap", HighsDebugLevel::kHighsDebugLevelCheap) .value("kHighsDebugLevelCostly", HighsDebugLevel::kHighsDebugLevelCostly) @@ -758,7 +993,7 @@ PYBIND11_MODULE(_core, m, py::mod_gil_not_used()) { .value("kHighsDebugLevelMax", HighsDebugLevel::kHighsDebugLevelMax) .export_values(); // Classes - py::class_(m, "HighsSparseMatrix") + py::class_(m, "HighsSparseMatrix", py::module_local()) .def(py::init<>()) .def_readwrite("format_", &HighsSparseMatrix::format_) .def_readwrite("num_col_", &HighsSparseMatrix::num_col_) @@ -767,9 +1002,9 @@ PYBIND11_MODULE(_core, m, py::mod_gil_not_used()) { .def_readwrite("p_end_", &HighsSparseMatrix::p_end_) .def_readwrite("index_", &HighsSparseMatrix::index_) .def_readwrite("value_", &HighsSparseMatrix::value_); - py::class_(m, "HighsLpMods"); - py::class_(m, "HighsScale"); - py::class_(m, "HighsLp") + py::class_(m, "HighsLpMods", py::module_local()); + py::class_(m, "HighsScale", py::module_local()); + py::class_(m, "HighsLp", py::module_local()) .def(py::init<>()) .def_readwrite("num_col_", &HighsLp::num_col_) .def_readwrite("num_row_", &HighsLp::num_row_) @@ -789,18 +1024,18 @@ PYBIND11_MODULE(_core, m, py::mod_gil_not_used()) { .def_readwrite("is_scaled_", &HighsLp::is_scaled_) .def_readwrite("is_moved_", &HighsLp::is_moved_) .def_readwrite("mods_", &HighsLp::mods_); - py::class_(m, "HighsHessian") + py::class_(m, "HighsHessian", py::module_local()) .def(py::init<>()) .def_readwrite("dim_", &HighsHessian::dim_) .def_readwrite("format_", &HighsHessian::format_) .def_readwrite("start_", &HighsHessian::start_) .def_readwrite("index_", &HighsHessian::index_) .def_readwrite("value_", &HighsHessian::value_); - py::class_(m, "HighsModel") + py::class_(m, "HighsModel", py::module_local()) .def(py::init<>()) .def_readwrite("lp_", &HighsModel::lp_) .def_readwrite("hessian_", &HighsModel::hessian_); - py::class_(m, "HighsInfo") + py::class_(m, "HighsInfo", py::module_local()) .def(py::init<>()) .def_readwrite("valid", &HighsInfo::valid) .def_readwrite("mip_node_count", &HighsInfo::mip_node_count) @@ -839,7 +1074,7 @@ PYBIND11_MODULE(_core, m, py::mod_gil_not_used()) { &HighsInfo::sum_complementarity_violations) .def_readwrite("primal_dual_integral", &HighsInfo::primal_dual_integral); - py::class_(m, "HighsOptions") + py::class_(m, "HighsOptions", py::module_local()) .def(py::init<>()) .def_readwrite("presolve", &HighsOptions::presolve) .def_readwrite("solver", &HighsOptions::solver) @@ -927,7 +1162,7 @@ PYBIND11_MODULE(_core, m, py::mod_gil_not_used()) { &HighsOptions::mip_heuristic_effort) .def_readwrite("mip_min_logging_interval", &HighsOptions::mip_min_logging_interval); - py::class_(m, "_Highs") + py::class_(m, "_Highs", py::module_local()) .def(py::init<>()) .def("version", &Highs::version) .def("versionMajor", &Highs::versionMajor) @@ -1036,6 +1271,26 @@ PYBIND11_MODULE(_core, m, py::mod_gil_not_used()) { .def("getModelPresolveStatus", &Highs::getModelPresolveStatus) .def("getRanging", &highs_getRanging) .def("getObjectiveValue", &Highs::getObjectiveValue) + .def("getDualObjectiveValue", &Highs::getDualObjectiveValue) + .def("getBasicVariables", &highs_getBasicVariables) + .def("getBasisInverseRow", &highs_getBasisInverseRow) + .def("getBasisInverseRowSparse", &highs_getBasisInverseRowSparse) + .def("getBasisInverseCol", &highs_getBasisInverseCol) + .def("getBasisInverseColSparse", &highs_getBasisInverseColSparse) + .def("getBasisSolve", &highs_getBasisSolve) + .def("getBasisSolveSparse", &highs_getBasisSolveSparse) + .def("getBasisTransposeSolve", &highs_getBasisTransposeSolve) + .def("getBasisTransposeSolveSparse", &highs_getBasisTransposeSolveSparse) + .def("getReducedRow", &highs_getReducedRow) + .def("getReducedRowSparse", &highs_getReducedRowSparse) + .def("getReducedColumn", &highs_getReducedColumn) + .def("getReducedColumnSparse", &highs_getReducedColumnSparse) + .def("getDualRayExist", &highs_getDualRayExist) + .def("getDualRay", &highs_getDualRay) + .def("getDualUnboundednessDirectionExist", &highs_getDualUnboundednessDirectionExist) + .def("getDualUnboundednessDirection", &highs_getDualUnboundednessDirection) + .def("getPrimalRayExist", &highs_getPrimalRayExist) + .def("getPrimalRay", &highs_getPrimalRay) .def("getNumCol", &Highs::getNumCol) .def("getNumRow", &Highs::getNumRow) .def("getNumNz", &Highs::getNumNz) @@ -1076,6 +1331,8 @@ PYBIND11_MODULE(_core, m, py::mod_gil_not_used()) { .def("addCols", &highs_addCols) .def("addVar", &highs_addVar) .def("addVars", &highs_addVars) + .def("ensureColwise", &Highs::ensureColwise) + .def("ensureRowwise", &Highs::ensureRowwise) .def("changeColsCost", &highs_changeColsCost) .def("changeColsBounds", &highs_changeColsBounds) .def("changeColsIntegrality", &highs_changeColsIntegrality) @@ -1102,7 +1359,7 @@ PYBIND11_MODULE(_core, m, py::mod_gil_not_used()) { .def("stopCallbackInt", static_cast( &Highs::stopCallback)); - py::class_(m, "HighsIis") + py::class_(m, "HighsIis", py::module_local()) .def(py::init<>()) .def("invalidate", &HighsIis::invalidate) .def_readwrite("valid", &HighsIis::valid_) @@ -1113,7 +1370,7 @@ PYBIND11_MODULE(_core, m, py::mod_gil_not_used()) { .def_readwrite("row_bound", &HighsIis::row_bound_) .def_readwrite("info", &HighsIis::info_); // structs - py::class_(m, "HighsSolution") + py::class_(m, "HighsSolution", py::module_local()) .def(py::init<>()) .def_readwrite("value_valid", &HighsSolution::value_valid) .def_readwrite("dual_valid", &HighsSolution::dual_valid) @@ -1121,11 +1378,11 @@ PYBIND11_MODULE(_core, m, py::mod_gil_not_used()) { .def_readwrite("col_dual", &HighsSolution::col_dual) .def_readwrite("row_value", &HighsSolution::row_value) .def_readwrite("row_dual", &HighsSolution::row_dual); - py::class_(m, "HighsObjectiveSolution") + py::class_(m, "HighsObjectiveSolution", py::module_local()) .def(py::init<>()) .def_readwrite("objective", &HighsObjectiveSolution::objective) .def_readwrite("col_value", &HighsObjectiveSolution::col_value); - py::class_(m, "HighsBasis") + py::class_(m, "HighsBasis", py::module_local()) .def(py::init<>()) .def_readwrite("valid", &HighsBasis::valid) .def_readwrite("alien", &HighsBasis::alien) @@ -1135,13 +1392,13 @@ PYBIND11_MODULE(_core, m, py::mod_gil_not_used()) { .def_readwrite("debug_origin_name", &HighsBasis::debug_origin_name) .def_readwrite("col_status", &HighsBasis::col_status) .def_readwrite("row_status", &HighsBasis::row_status); - py::class_(m, "HighsRangingRecord") + py::class_(m, "HighsRangingRecord", py::module_local()) .def(py::init<>()) .def_readwrite("value_", &HighsRangingRecord::value_) .def_readwrite("objective_", &HighsRangingRecord::objective_) .def_readwrite("in_var_", &HighsRangingRecord::in_var_) .def_readwrite("ou_var_", &HighsRangingRecord::ou_var_); - py::class_(m, "HighsRanging") + py::class_(m, "HighsRanging", py::module_local()) .def(py::init<>()) .def_readwrite("valid", &HighsRanging::valid) .def_readwrite("col_cost_up", &HighsRanging::col_cost_up) @@ -1150,11 +1407,11 @@ PYBIND11_MODULE(_core, m, py::mod_gil_not_used()) { .def_readwrite("col_bound_dn", &HighsRanging::col_bound_dn) .def_readwrite("row_bound_up", &HighsRanging::row_bound_up) .def_readwrite("row_bound_dn", &HighsRanging::row_bound_dn); - py::class_(m, "HighsIisInfo") + py::class_(m, "HighsIisInfo", py::module_local()) .def(py::init<>()) .def_readwrite("simplex_time", &HighsIisInfo::simplex_time) .def_readwrite("simplex_iterations", &HighsIisInfo::simplex_iterations); - py::class_(m, "HighsLinearObjective") + py::class_(m, "HighsLinearObjective", py::module_local()) .def(py::init<>()) .def_readwrite("weight", &HighsLinearObjective::weight) .def_readwrite("offset", &HighsLinearObjective::offset) @@ -1174,7 +1431,7 @@ PYBIND11_MODULE(_core, m, py::mod_gil_not_used()) { py::module_ simplex_constants = m.def_submodule("simplex_constants", "Submodule for simplex constants"); - py::enum_(simplex_constants, "SimplexStrategy") + py::enum_(simplex_constants, "SimplexStrategy", py::module_local()) .value("kSimplexStrategyMin", SimplexStrategy::kSimplexStrategyMin) .value("kSimplexStrategyChoose", SimplexStrategy::kSimplexStrategyChoose) .value("kSimplexStrategyDual", SimplexStrategy::kSimplexStrategyDual) @@ -1189,7 +1446,7 @@ PYBIND11_MODULE(_core, m, py::mod_gil_not_used()) { .value("kSimplexStrategyNum", SimplexStrategy::kSimplexStrategyNum) .export_values(); py::enum_(simplex_constants, - "SimplexUnscaledSolutionStrategy") + "SimplexUnscaledSolutionStrategy", py::module_local()) .value( "kSimplexUnscaledSolutionStrategyMin", SimplexUnscaledSolutionStrategy::kSimplexUnscaledSolutionStrategyMin) @@ -1209,7 +1466,7 @@ PYBIND11_MODULE(_core, m, py::mod_gil_not_used()) { "kSimplexUnscaledSolutionStrategyNum", SimplexUnscaledSolutionStrategy::kSimplexUnscaledSolutionStrategyNum) .export_values(); - py::enum_(simplex_constants, "SimplexSolvePhase") + py::enum_(simplex_constants, "SimplexSolvePhase", py::module_local()) .value("kSolvePhaseMin", SimplexSolvePhase::kSolvePhaseMin) .value("kSolvePhaseError", SimplexSolvePhase::kSolvePhaseError) .value("kSolvePhaseExit", SimplexSolvePhase::kSolvePhaseExit) @@ -1225,7 +1482,7 @@ PYBIND11_MODULE(_core, m, py::mod_gil_not_used()) { .value("kSolvePhaseMax", SimplexSolvePhase::kSolvePhaseMax) .export_values(); py::enum_(simplex_constants, - "SimplexEdgeWeightStrategy") + "SimplexEdgeWeightStrategy", py::module_local()) .value("kSimplexEdgeWeightStrategyMin", SimplexEdgeWeightStrategy::kSimplexEdgeWeightStrategyMin) .value("kSimplexEdgeWeightStrategyChoose", @@ -1239,7 +1496,7 @@ PYBIND11_MODULE(_core, m, py::mod_gil_not_used()) { .value("kSimplexEdgeWeightStrategyMax", SimplexEdgeWeightStrategy::kSimplexEdgeWeightStrategyMax) .export_values(); - py::enum_(simplex_constants, "SimplexPriceStrategy") + py::enum_(simplex_constants, "SimplexPriceStrategy", py::module_local()) .value("kSimplexPriceStrategyMin", SimplexPriceStrategy::kSimplexPriceStrategyMin) .value("kSimplexPriceStrategyCol", @@ -1254,7 +1511,7 @@ PYBIND11_MODULE(_core, m, py::mod_gil_not_used()) { SimplexPriceStrategy::kSimplexPriceStrategyMax) .export_values(); py::enum_( - simplex_constants, "SimplexPivotalRowRefinementStrategy") + simplex_constants, "SimplexPivotalRowRefinementStrategy", py::module_local()) .value("kSimplexInfeasibilityProofRefinementMin", SimplexPivotalRowRefinementStrategy:: kSimplexInfeasibilityProofRefinementMin) @@ -1272,7 +1529,7 @@ PYBIND11_MODULE(_core, m, py::mod_gil_not_used()) { kSimplexInfeasibilityProofRefinementMax) .export_values(); py::enum_(simplex_constants, - "SimplexPrimalCorrectionStrategy") + "SimplexPrimalCorrectionStrategy", py::module_local()) .value( "kSimplexPrimalCorrectionStrategyNone", SimplexPrimalCorrectionStrategy::kSimplexPrimalCorrectionStrategyNone) @@ -1283,7 +1540,7 @@ PYBIND11_MODULE(_core, m, py::mod_gil_not_used()) { SimplexPrimalCorrectionStrategy:: kSimplexPrimalCorrectionStrategyAlways) .export_values(); - py::enum_(simplex_constants, "SimplexNlaOperation") + py::enum_(simplex_constants, "SimplexNlaOperation", py::module_local()) .value("kSimplexNlaNull", SimplexNlaOperation::kSimplexNlaNull) .value("kSimplexNlaBtranFull", SimplexNlaOperation::kSimplexNlaBtranFull) .value("kSimplexNlaPriceFull", SimplexNlaOperation::kSimplexNlaPriceFull) @@ -1300,14 +1557,14 @@ PYBIND11_MODULE(_core, m, py::mod_gil_not_used()) { .value("kNumSimplexNlaOperation", SimplexNlaOperation::kNumSimplexNlaOperation) .export_values(); - py::enum_(simplex_constants, "EdgeWeightMode") + py::enum_(simplex_constants, "EdgeWeightMode", py::module_local()) .value("kDantzig", EdgeWeightMode::kDantzig) .value("kDevex", EdgeWeightMode::kDevex) .value("kSteepestEdge", EdgeWeightMode::kSteepestEdge) .value("kCount", EdgeWeightMode::kCount); py::module_ callbacks = m.def_submodule("cb", "Callback interface submodule"); // Types for interface - py::enum_(callbacks, "HighsCallbackType") + py::enum_(callbacks, "HighsCallbackType", py::module_local()) .value("kCallbackMin", HighsCallbackType::kCallbackMin) .value("kCallbackLogging", HighsCallbackType::kCallbackLogging) .value("kCallbackSimplexInterrupt", @@ -1322,16 +1579,18 @@ PYBIND11_MODULE(_core, m, py::mod_gil_not_used()) { HighsCallbackType::kCallbackMipGetCutPool) .value("kCallbackMipDefineLazyConstraints", HighsCallbackType::kCallbackMipDefineLazyConstraints) + .value("kCallbackMipUserSolution", + HighsCallbackType::kCallbackMipUserSolution) .value("kCallbackMax", HighsCallbackType::kCallbackMax) .value("kNumCallbackType", HighsCallbackType::kNumCallbackType) .export_values(); // Classes - py::class_>(m, "readonly_ptr_wrapper_double") + py::class_>(m, "readonly_ptr_wrapper_double", py::module_local()) .def(py::init()) .def("__getitem__", &readonly_ptr_wrapper::operator[]) .def("__bool__", &readonly_ptr_wrapper::is_valid) .def("to_array", &readonly_ptr_wrapper::to_array); - py::class_(callbacks, "HighsCallbackDataOut") + py::class_(callbacks, "HighsCallbackDataOut", py::module_local()) .def(py::init<>()) .def_readwrite("log_type", &HighsCallbackDataOut::log_type) .def_readwrite("running_time", &HighsCallbackDataOut::running_time) @@ -1353,7 +1612,7 @@ PYBIND11_MODULE(_core, m, py::mod_gil_not_used()) { [](const HighsCallbackDataOut& self) -> readonly_ptr_wrapper { return readonly_ptr_wrapper(self.mip_solution); }); - py::class_(callbacks, "HighsCallbackDataIn") + py::class_(callbacks, "HighsCallbackDataIn", py::module_local()) .def(py::init<>()) .def_readwrite("user_interrupt", &HighsCallbackDataIn::user_interrupt); } diff --git a/src/highspy/highs.py b/src/highspy/highs.py index af42594be9..a434c2ed7f 100644 --- a/src/highspy/highs.py +++ b/src/highspy/highs.py @@ -1303,6 +1303,10 @@ def cbMipGetCutPool(self): def cbMipDefineLazyConstraints(self): return self.callbacks[int(cb.HighsCallbackType.kCallbackMipDefineLazyConstraints)] + @property + def cbkMipUserSolution(self): + return self.callbacks[int(cb.HighsCallbackType.kCallbackMipUserSolution)] + # callback setters are required for +=/-= syntax # e.g., h.cbLogging += my_callback @cbLogging.setter diff --git a/src/interfaces/highs_c_api.cpp b/src/interfaces/highs_c_api.cpp index af354daf02..e5fefce606 100644 --- a/src/interfaces/highs_c_api.cpp +++ b/src/interfaces/highs_c_api.cpp @@ -802,6 +802,14 @@ HighsInt Highs_addRows(void* highs, const HighsInt num_new_row, ->addRows(num_new_row, lower, upper, num_new_nz, starts, index, value); } +HighsInt Highs_ensureColwise(void* highs) { + return (HighsInt)((Highs*)highs)->ensureColwise(); +} + +HighsInt Highs_ensureRowwise(void* highs) { + return (HighsInt)((Highs*)highs)->ensureRowwise(); +} + HighsInt Highs_changeObjectiveSense(void* highs, const HighsInt sense) { ObjSense pass_sense = ObjSense::kMinimize; if (sense == (HighsInt)ObjSense::kMaximize) pass_sense = ObjSense::kMaximize; diff --git a/src/interfaces/highs_c_api.h b/src/interfaces/highs_c_api.h index 89f6fa4f79..2aa17cb6cd 100644 --- a/src/interfaces/highs_c_api.h +++ b/src/interfaces/highs_c_api.h @@ -1426,6 +1426,25 @@ HighsInt Highs_addRows(void* highs, const HighsInt num_new_row, const HighsInt num_new_nz, const HighsInt* starts, const HighsInt* index, const double* value); +/** + * Ensure that the constraint matrix of the incumbent model is stored + * column-wise. + * + * @param highs A pointer to the Highs instance. + * + * @returns A `kHighsStatus` constant indicating whether the call succeeded. + */ +HighsInt Highs_ensureColwise(void* highs); + +/** + * Ensure that the constraint matrix of the incumbent model is stored row-wise. + * + * @param highs A pointer to the Highs instance. + * + * @returns A `kHighsStatus` constant indicating whether the call succeeded. + */ +HighsInt Highs_ensureRowwise(void* highs); + /** * Change the objective sense of the model. * @@ -1813,7 +1832,7 @@ HighsInt Highs_getColsByMask(const void* highs, const HighsInt* mask, * @param from_row The first row for which to query data for. * @param to_row The last row (inclusive) for which to query data for. * @param num_row An integer to be populated with the number of rows got - * from the smodel. + * from the model. * @param lower An array of size [to_row - from_row + 1] for the row * lower bounds. * @param upper An array of size [to_row - from_row + 1] for the row diff --git a/src/io/HMPSIO.cpp b/src/io/HMPSIO.cpp index 02d2c0c61f..ee38a36e31 100644 --- a/src/io/HMPSIO.cpp +++ b/src/io/HMPSIO.cpp @@ -913,6 +913,9 @@ HighsStatus writeMps( if (lb || highs_isInfinity(ub)) fprintf(file, " LI BOUND %-8s %.10g\n", col_names[c_n].c_str(), lb); + } else { + // Infinite lower bound + fprintf(file, " MI BOUND %-8s\n", col_names[c_n].c_str()); } if (!highs_isInfinity(ub)) { // Finite upper bound diff --git a/src/io/HMpsFF.cpp b/src/io/HMpsFF.cpp index 80bf0b897b..06ee0ea8f1 100644 --- a/src/io/HMpsFF.cpp +++ b/src/io/HMpsFF.cpp @@ -399,57 +399,63 @@ HMpsFF::Parsekey HMpsFF::checkFirstWord(std::string& strline, size_t& start, word = strline.substr(start, end - start); + // Create an upper-case version of WORD, so that keywords are + // read as if they were in lower or mixed case + std::string upper_word = word; + toupper(upper_word); + // store rest of strline for keywords that have arguments - if (word == "QCMATRIX" || word == "QSECTION" || word == "CSECTION") + if (upper_word == "QCMATRIX" || upper_word == "QSECTION" || + upper_word == "CSECTION") section_args = strline.substr(end, strline.length()); - if (word == "NAME") + if (upper_word == "NAME") return HMpsFF::Parsekey::kName; - else if (word == "OBJSENSE") + else if (upper_word == "OBJSENSE") return HMpsFF::Parsekey::kObjsense; - else if (word == "MAX") + else if (upper_word == "MAX") return HMpsFF::Parsekey::kMax; - else if (word == "MIN") + else if (upper_word == "MIN") return HMpsFF::Parsekey::kMin; - else if (word == "ROWS") + else if (upper_word == "ROWS") return HMpsFF::Parsekey::kRows; - else if (word == "COLUMNS") + else if (upper_word == "COLUMNS") return HMpsFF::Parsekey::kCols; - else if (word == "RHS") + else if (upper_word == "RHS") return HMpsFF::Parsekey::kRhs; - else if (word == "BOUNDS") + else if (upper_word == "BOUNDS") return HMpsFF::Parsekey::kBounds; - else if (word == "RANGES") + else if (upper_word == "RANGES") return HMpsFF::Parsekey::kRanges; - else if (word == "QSECTION") + else if (upper_word == "QSECTION") return HMpsFF::Parsekey::kQsection; - else if (word == "QMATRIX") + else if (upper_word == "QMATRIX") return HMpsFF::Parsekey::kQmatrix; - else if (word == "QUADOBJ") + else if (upper_word == "QUADOBJ") return HMpsFF::Parsekey::kQuadobj; - else if (word == "QCMATRIX") + else if (upper_word == "QCMATRIX") return HMpsFF::Parsekey::kQcmatrix; - else if (word == "CSECTION") + else if (upper_word == "CSECTION") return HMpsFF::Parsekey::kCsection; - else if (word == "DELAYEDROWS") + else if (upper_word == "DELAYEDROWS") return HMpsFF::Parsekey::kDelayedrows; - else if (word == "MODELCUTS") + else if (upper_word == "MODELCUTS") return HMpsFF::Parsekey::kModelcuts; - else if (word == "INDICATORS") + else if (upper_word == "INDICATORS") return HMpsFF::Parsekey::kIndicators; - else if (word == "SETS") + else if (upper_word == "SETS") return HMpsFF::Parsekey::kSets; - else if (word == "SOS") + else if (upper_word == "SOS") return HMpsFF::Parsekey::kSos; - else if (word == "GENCONS") + else if (upper_word == "GENCONS") return HMpsFF::Parsekey::kGencons; - else if (word == "PWLOBJ") + else if (upper_word == "PWLOBJ") return HMpsFF::Parsekey::kPwlobj; - else if (word == "PWLNAM") + else if (upper_word == "PWLNAM") return HMpsFF::Parsekey::kPwlnam; - else if (word == "PWLCON") + else if (upper_word == "PWLCON") return HMpsFF::Parsekey::kPwlcon; - else if (word == "ENDATA") + else if (upper_word == "ENDATA") return HMpsFF::Parsekey::kEnd; else return HMpsFF::Parsekey::kNone; @@ -496,6 +502,8 @@ HMpsFF::Parsekey HMpsFF::parseDefault(const HighsLogOptions& log_options, // Look for Gurobi-style definition of MAX/MIN on OBJSENSE line if (e < strline.length()) { std::string sense = first_word(strline, e); + // Convert to upper case + toupper(sense); if (sense.compare("MAX") == 0) { // Found MAX sense on OBJSENSE line obj_sense = ObjSense::kMaximize; diff --git a/src/ipm/IpxWrapper.cpp b/src/ipm/IpxWrapper.cpp index ccd7e4b3dd..51f84dec04 100644 --- a/src/ipm/IpxWrapper.cpp +++ b/src/ipm/IpxWrapper.cpp @@ -85,6 +85,7 @@ HighsStatus solveLpIpx(const HighsOptions& options, HighsTimer& timer, parameters.debug = 4; } parameters.highs_logging = true; + parameters.timeless_log = options.timeless_log; parameters.log_options = &options.log_options; // Just test feasibility and optimality tolerances for now // ToDo Set more parameters @@ -115,7 +116,7 @@ HighsStatus solveLpIpx(const HighsOptions& options, HighsTimer& timer, parameters.analyse_basis_data = kHighsAnalysisLevelNlaData & options.highs_analysis_level; // Determine the run time allowed for IPX - parameters.time_limit = options.time_limit - timer.readRunHighsClock(); + parameters.time_limit = options.time_limit - timer.read(); parameters.ipm_maxiter = options.ipm_iteration_limit - highs_info.ipm_iteration_count; // Determine if crossover is to be run or not @@ -150,18 +151,19 @@ HighsStatus solveLpIpx(const HighsOptions& options, HighsTimer& timer, lps.SetCallback(&callback); ipx::Int num_col, num_row; + double offset; std::vector Ap, Ai; std::vector objective, col_lb, col_ub, Av, rhs; std::vector constraint_type; - fillInIpxData(lp, num_col, num_row, objective, col_lb, col_ub, Ap, Ai, Av, - rhs, constraint_type); + fillInIpxData(lp, num_col, num_row, offset, objective, col_lb, col_ub, Ap, Ai, + Av, rhs, constraint_type); highsLogUser(options.log_options, HighsLogType::kInfo, "IPX model has %" HIGHSINT_FORMAT " rows, %" HIGHSINT_FORMAT " columns and %" HIGHSINT_FORMAT " nonzeros\n", num_row, num_col, Ap[num_col]); ipx::Int load_status = lps.LoadModel( - num_col, objective.data(), col_lb.data(), col_ub.data(), num_row, + num_col, offset, objective.data(), col_lb.data(), col_ub.data(), num_row, Ap.data(), Ai.data(), Av.data(), rhs.data(), constraint_type.data()); if (load_status) { @@ -387,10 +389,10 @@ HighsStatus solveLpIpx(const HighsOptions& options, HighsTimer& timer, } void fillInIpxData(const HighsLp& lp, ipx::Int& num_col, ipx::Int& num_row, - std::vector& obj, std::vector& col_lb, - std::vector& col_ub, std::vector& Ap, - std::vector& Ai, std::vector& Ax, - std::vector& rhs, + double& offset, std::vector& obj, + std::vector& col_lb, std::vector& col_ub, + std::vector& Ap, std::vector& Ai, + std::vector& Ax, std::vector& rhs, std::vector& constraint_type) { num_col = lp.num_col_; num_row = lp.num_row_; @@ -517,6 +519,7 @@ void fillInIpxData(const HighsLp& lp, ipx::Int& num_col, ipx::Int& num_row, col_ub[lp.num_col_ + slack] = lp.row_upper_[row]; } + offset = HighsInt(lp.sense_) * lp.offset_; obj.resize(num_col); for (HighsInt col = 0; col < lp.num_col_; col++) { obj[col] = (HighsInt)lp.sense_ * lp.col_cost_[col]; diff --git a/src/ipm/IpxWrapper.h b/src/ipm/IpxWrapper.h index 28a46fe202..99486c2107 100644 --- a/src/ipm/IpxWrapper.h +++ b/src/ipm/IpxWrapper.h @@ -28,10 +28,10 @@ HighsStatus solveLpIpx(const HighsOptions& options, HighsTimer& timer, HighsCallback& callback); void fillInIpxData(const HighsLp& lp, ipx::Int& num_col, ipx::Int& num_row, - std::vector& obj, std::vector& col_lb, - std::vector& col_ub, std::vector& Ap, - std::vector& Ai, std::vector& Ax, - std::vector& rhs, + double& offset, std::vector& obj, + std::vector& col_lb, std::vector& col_ub, + std::vector& Ap, std::vector& Ai, + std::vector& Ax, std::vector& rhs, std::vector& constraint_type); HighsStatus reportIpxSolveStatus(const HighsOptions& options, diff --git a/src/ipm/ipx/control.h b/src/ipm/ipx/control.h index d322b0d383..f234cec1ce 100644 --- a/src/ipm/ipx/control.h +++ b/src/ipm/ipx/control.h @@ -91,6 +91,7 @@ class Control { double centringRatioReduction() const {return parameters_.centring_ratio_reduction; } double centringAlphaScaling() const{return parameters_.centring_alpha_scaling; } ipxint badProductsTolerance() const{return parameters_.bad_products_tolerance; } + bool timelessLog() const{return parameters_.timeless_log; } const Parameters& parameters() const; void parameters(const Parameters& new_parameters); diff --git a/src/ipm/ipx/ipm.cc b/src/ipm/ipx/ipm.cc index 4a21364951..e1a9f2ec82 100644 --- a/src/ipm/ipx/ipm.cc +++ b/src/ipm/ipx/ipm.cc @@ -825,8 +825,9 @@ void IPM::PrintHeader() { << " " << Format("Iter", 4) << " " << Format("P.res", 8) << " " << Format("D.res", 8) << " " << Format("P.obj", 15) << " " << Format("D.obj", 15) - << " " << Format("mu", 8) - << " " << Format("Time", 7); + << " " << Format("mu", 8); + if (!control_.timelessLog()) + h_logging_stream << " " << Format("Time", 7); control_.hLog(h_logging_stream); control_.Debug() << " " << Format("stepsizes", 9) @@ -850,8 +851,9 @@ void IPM::PrintOutput() { << " " << Scientific(iterate_->dresidual(), 8, 2) << " " << Scientific(iterate_->pobjective_after_postproc(), 15, 8) << " " << Scientific(iterate_->dobjective_after_postproc(), 15, 8) - << " " << Scientific(iterate_->mu(), 8, 2) - << " " << Fixed(control_.Elapsed(), 6, 0) << "s"; + << " " << Scientific(iterate_->mu(), 8, 2); + if (!control_.timelessLog()) + h_logging_stream << " " << Fixed(control_.Elapsed(), 6, 0) << "s"; control_.hLog(h_logging_stream); control_.Debug() << " " << Fixed(step_primal_, 4, 2) << " " << Fixed(step_dual_, 4, 2) diff --git a/src/ipm/ipx/ipx_c.cc b/src/ipm/ipx/ipx_c.cc index e70f1dbfed..33c2817f99 100644 --- a/src/ipm/ipx/ipx_c.cc +++ b/src/ipm/ipx/ipx_c.cc @@ -9,7 +9,8 @@ ipxint ipx_load_model(void* self, ipxint num_var, const double* obj, const ipxint* Ap, const ipxint* Ai, const double* Ax, const double* rhs, const char* constr_type) { LpSolver* solver = static_cast(self); - return solver->LoadModel(num_var, obj, lb, ub, num_constr, Ap, Ai, Ax, rhs, + const double offset = 0; + return solver->LoadModel(num_var, offset, obj, lb, ub, num_constr, Ap, Ai, Ax, rhs, constr_type); } diff --git a/src/ipm/ipx/ipx_parameters.h b/src/ipm/ipx/ipx_parameters.h index 2f9db89186..7bffbc992b 100644 --- a/src/ipm/ipx/ipx_parameters.h +++ b/src/ipm/ipx/ipx_parameters.h @@ -64,6 +64,7 @@ struct ipx_parameters { /* HiGHS logging parameters */ bool highs_logging; + bool timeless_log; const HighsLogOptions* log_options; }; diff --git a/src/ipm/ipx/iterate.cc b/src/ipm/ipx/iterate.cc index c407eb3de4..030620ea0d 100644 --- a/src/ipm/ipx/iterate.cc +++ b/src/ipm/ipx/iterate.cc @@ -617,8 +617,8 @@ void Iterate::ComputeObjectives() const { if (postprocessed_) { // Compute objective values as defined for the LP model. offset_ = 0.0; - pobjective_ = Dot(c, x_); - dobjective_ = Dot(b, y_); + pobjective_ = model_.offset() + Dot(c, x_); + dobjective_ = model_.offset() + Dot(b, y_); for (Int j = 0; j < n+m; j++) { if (std::isfinite(lb[j])) dobjective_ += lb[j] * zl_[j]; @@ -630,7 +630,7 @@ void Iterate::ComputeObjectives() const { // (after fixing and implying variables). The offset is such that // pobjective_ + offset_ is the primal objective after postprocessing. offset_ = 0.0; - pobjective_ = 0.0; + pobjective_ = model_.offset(); for (Int j = 0; j < n+m; j++) { if (StateOf(j) != State::fixed) pobjective_ += c[j] * x_[j]; @@ -643,7 +643,7 @@ void Iterate::ComputeObjectives() const { offset_ += (zl_[j]-zu_[j]) * x_[j]; } } - dobjective_ = Dot(b, y_); + dobjective_ = model_.offset() + Dot(b, y_); for (Int j = 0; j < n+m; j++) { if (has_barrier_lb(j)) dobjective_ += lb[j] * zl_[j]; diff --git a/src/ipm/ipx/lp_solver.cc b/src/ipm/ipx/lp_solver.cc index 145930c75b..52b643a57a 100644 --- a/src/ipm/ipx/lp_solver.cc +++ b/src/ipm/ipx/lp_solver.cc @@ -12,13 +12,14 @@ namespace ipx { -Int LpSolver::LoadModel(Int num_var, const double* obj, const double* lb, +Int LpSolver::LoadModel(Int num_var, const double offset, + const double* obj, const double* lb, const double* ub, Int num_constr, const Int* Ap, const Int* Ai, const double* Ax, const double* rhs, const char* constr_type) { ClearModel(); Int errflag = model_.Load(control_, num_constr, num_var, Ap, Ai, Ax, rhs, - constr_type, obj, lb, ub); + constr_type, offset, obj, lb, ub); model_.GetInfo(&info_); return errflag; } @@ -648,9 +649,10 @@ void LpSolver::RunCrossover() { void LpSolver::PrintSummary() { std::stringstream h_logging_stream; h_logging_stream.str(std::string()); - h_logging_stream << "Summary\n" - << Textline("Runtime:") << fix2(control_.Elapsed()) << "s\n" - << Textline("Status interior point solve:") + h_logging_stream << "Summary\n"; + if (!control_.timelessLog()) + h_logging_stream << Textline("Runtime:") << fix2(control_.Elapsed()) << "s\n"; + h_logging_stream << Textline("Status interior point solve:") << StatusString(info_.status_ipm) << '\n' << Textline("Status crossover:") << StatusString(info_.status_crossover) << '\n'; diff --git a/src/ipm/ipx/lp_solver.h b/src/ipm/ipx/lp_solver.h index 18eb70606f..2fb8097776 100644 --- a/src/ipm/ipx/lp_solver.h +++ b/src/ipm/ipx/lp_solver.h @@ -28,7 +28,8 @@ class LpSolver { // IPX_ERROR_invalid_dimension // IPX_ERROR_invalid_matrix // IPX_ERROR_invalid_vector - Int LoadModel(Int num_var, const double* obj, const double* lb, + Int LoadModel(Int num_var, const double offset, + const double* obj, const double* lb, const double* ub, Int num_constr, const Int* Ap, const Int* Ai, const double* Ax, const double* rhs, const char* constr_type); @@ -94,7 +95,7 @@ class LpSolver { Int GetBasicSolution(double* x, double* slack, double* y, double* z, Int* cbasis, Int* vbasis) const; - // Returns/sets all paramters. Without calling SetParameters(), the solver + // Returns/sets all parameters. Without calling SetParameters(), the solver // uses the default values of a Parameters object. Parameters GetParameters() const; void SetParameters(Parameters new_parameters); diff --git a/src/ipm/ipx/model.cc b/src/ipm/ipx/model.cc index 94d251c2e4..321a419d82 100644 --- a/src/ipm/ipx/model.cc +++ b/src/ipm/ipx/model.cc @@ -9,11 +9,11 @@ namespace ipx { Int Model::Load(const Control& control, Int num_constr, Int num_var, const Int* Ap, const Int* Ai, const double* Ax, - const double* rhs, const char* constr_type, const double* obj, - const double* lbuser, const double* ubuser) { + const double* rhs, const char* constr_type, const double offset, + const double* obj, const double* lbuser, const double* ubuser) { clear(); Int errflag = CopyInput(num_constr, num_var, Ap, Ai, Ax, rhs, constr_type, - obj, lbuser, ubuser); + offset, obj, lbuser, ubuser); if (errflag) return errflag; std::stringstream h_logging_stream; @@ -336,8 +336,8 @@ void Model::EvaluateInteriorSolution(const Vector& x_solver, presidual = std::max(presidual, Infnorm(ru)); double dresidual = Infnorm(rc); - double pobjective = Dot(scaled_obj_, x); - double dobjective = Dot(scaled_rhs_, y); + double pobjective = offset_ + Dot(scaled_obj_, x); + double dobjective = offset_ + Dot(scaled_rhs_, y); for (Int j = 0; j < num_var_; j++) { if (std::isfinite(scaled_lbuser_[j])) dobjective += scaled_lbuser_[j] * zl[j]; @@ -541,7 +541,7 @@ static Int CheckMatrix(Int m, Int n, const Int *Ap, const Int *Ai, const double Int Model::CopyInput(Int num_constr, Int num_var, const Int* Ap, const Int* Ai, const double* Ax, const double* rhs, - const char* constr_type, const double* obj, + const char* constr_type, const double offset, const double* obj, const double* lbuser, const double* ubuser) { if (!(Ap && Ai && Ax && rhs && constr_type && obj && lbuser && ubuser)) { return IPX_ERROR_argument_null; @@ -569,6 +569,7 @@ Int Model::CopyInput(Int num_constr, Int num_var, const Int* Ap, const Int* Ai, boxed_vars_.push_back(j); } constr_type_ = std::vector(constr_type, constr_type+num_constr); + offset_ = offset; scaled_obj_ = Vector(obj, num_var); scaled_rhs_ = Vector(rhs, num_constr); scaled_lbuser_ = Vector(lbuser, num_var); diff --git a/src/ipm/ipx/model.h b/src/ipm/ipx/model.h index e57fe4bd0e..a06dec3ec0 100644 --- a/src/ipm/ipx/model.h +++ b/src/ipm/ipx/model.h @@ -58,8 +58,8 @@ class Model { // IPX_ERROR_invalid_vector Int Load(const Control& control, Int num_constr, Int num_var, const Int* Ap, const Int* Ai, const double* Ax, - const double* rhs, const char* constr_type, const double* obj, - const double* lbuser, const double* ubuser); + const double* rhs, const char* constr_type, const double offset, + const double* obj, const double* lbuser, const double* ubuser); // Performs Flippo's test for deciding dualization bool filippoDualizationTest() const; // Writes statistics of input data and preprocessing to @info. @@ -93,6 +93,9 @@ class Model { const SparseMatrix& AI() const { return AI_; } const SparseMatrix& AIt() const { return AIt_; } + // Returns the offset + const double offset() const { return offset_; } + // Returns a reference to a model vector. const Vector& b() const { return b_; } const Vector& c() const { return c_; } @@ -207,7 +210,7 @@ class Model { // IPX_ERROR_invalid_vector Int CopyInput(Int num_constr, Int num_var, const Int* Ap, const Int* Ai, const double* Ax, const double* rhs, const char* constr_type, - const double* obj, const double* lbuser, + const double offset, const double* obj, const double* lbuser, const double* ubuser); // Scales A_, scaled_obj_, scaled_rhs_, scaled_lbuser_ and scaled_ubuser_ @@ -376,6 +379,7 @@ class Model { std::vector constr_type_; double norm_obj_{0.0}; // Infnorm(obj) as given by user double norm_rhs_{0.0}; // Infnorm(rhs,lb,ub) as given by user + double offset_; Vector scaled_obj_; Vector scaled_rhs_; Vector scaled_lbuser_; diff --git a/src/lp_data/HConst.h b/src/lp_data/HConst.h index 178c84332a..aa7d0a745e 100644 --- a/src/lp_data/HConst.h +++ b/src/lp_data/HConst.h @@ -225,7 +225,8 @@ enum HighsCallbackType : int { kCallbackMipInterrupt, // 6 kCallbackMipGetCutPool, // 7 kCallbackMipDefineLazyConstraints, // 8 - kCallbackMax = kCallbackMipDefineLazyConstraints, + kCallbackMipUserSolution, // 9 + kCallbackMax = kCallbackMipUserSolution, kNumCallbackType }; diff --git a/src/lp_data/HStruct.h b/src/lp_data/HStruct.h index 77b9e6e11b..d69c36dede 100644 --- a/src/lp_data/HStruct.h +++ b/src/lp_data/HStruct.h @@ -58,14 +58,27 @@ struct HotStart { }; struct HighsBasis { + // Logical flags for a HiGHS basis: + // + // valid: has been factored by HiGHS + // + // alien: a basis that's been set externally, so cannot be assumed + // to even have the right number of basic and nonbasic variables + // + // useful: a basis that may be useful + // + // Need useful since, by default, a basis is alien but not useful bool valid = false; bool alien = true; + bool useful = false; bool was_alien = true; HighsInt debug_id = -1; HighsInt debug_update_count = -1; std::string debug_origin_name = "None"; std::vector col_status; std::vector row_status; + void print(std::string message = "") const; + void printScalars(std::string message = "") const; void invalidate(); void clear(); }; diff --git a/src/lp_data/Highs.cpp b/src/lp_data/Highs.cpp index 1006ce43a0..488da77a5e 100644 --- a/src/lp_data/Highs.cpp +++ b/src/lp_data/Highs.cpp @@ -139,7 +139,8 @@ HighsStatus Highs::resetOptions() { } HighsStatus Highs::writeOptions(const std::string& filename, - const bool report_only_deviations) const { + const bool report_only_deviations) { + this->logHeader(); HighsStatus return_status = HighsStatus::kOk; FILE* file; HighsFileType file_type; @@ -148,15 +149,16 @@ HighsStatus Highs::writeOptions(const std::string& filename, openWriteFile(filename, "writeOptions", file, file_type), return_status, "openWriteFile"); if (return_status == HighsStatus::kError) return return_status; + if (filename == "") file_type = HighsFileType::kMinimal; // Report to user that options are being written to a file if (filename != "") highsLogUser(options_.log_options, HighsLogType::kInfo, "Writing the option values to %s\n", filename.c_str()); - return_status = - interpretCallStatus(options_.log_options, - writeOptionsToFile(file, options_.records, - report_only_deviations, file_type), - return_status, "writeOptionsToFile"); + return_status = interpretCallStatus( + options_.log_options, + writeOptionsToFile(file, options_.log_options, options_.records, + report_only_deviations, file_type), + return_status, "writeOptionsToFile"); if (file != stdout) fclose(file); return return_status; } @@ -716,6 +718,7 @@ HighsStatus Highs::readBasis(const std::string& filename) { // Update the HiGHS basis and invalidate any simplex basis for the model basis_ = read_basis; basis_.valid = true; + basis_.useful = true; // Follow implications of a new HiGHS basis newHighsBasis(); // Can't use returnFromHighs since... @@ -1048,7 +1051,7 @@ HighsStatus Highs::solve() { // Zero the iteration counts zeroIterationCounts(); // Start the HiGHS run clock - timer_.startRunHighsClock(); + timer_.start(); // Return immediately if the model has no columns if (!model_.lp_.num_col_) { setHighsModelStatusAndClearSolutionAndBasis(HighsModelStatus::kModelEmpty); @@ -1166,7 +1169,7 @@ HighsStatus Highs::solve() { // // Record the initial time and set the component times and postsolve // iteration count to -1 to identify whether they are not required - double initial_time = timer_.readRunHighsClock(); + double initial_time = timer_.read(); double this_presolve_time = -1; double this_solve_presolved_lp_time = -1; double this_postsolve_time = -1; @@ -1222,7 +1225,7 @@ HighsStatus Highs::solve() { return returnFromRun(crossover_status, undo_mods); assert(options_.simplex_strategy == kSimplexStrategyPrimal); } - // timer_.stopRunHighsClock(); + // timer_.stop(); // run(); // todo: add "dual" values @@ -1260,15 +1263,29 @@ HighsStatus Highs::solve() { const bool unconstrained_lp = incumbent_lp.a_matrix_.numNz() == 0; assert(incumbent_lp.num_row_ || unconstrained_lp); - if (basis_.valid || options_.presolve == kHighsOffString || - unconstrained_lp) { + // Even if options_.solver == kHighsChooseString in isolation will, + // ultimately lead to a choice between simplex and IPM, if a basis + // is available, simplex should surely be chosen. + const bool solver_will_use_basis = options_.solver == kSimplexString || + options_.solver == kHighsChooseString; + const bool has_basis = basis_.useful; + if (has_basis) { + assert(basis_.col_status.size() == + static_cast(incumbent_lp.num_col_)); + assert(basis_.row_status.size() == + static_cast(incumbent_lp.num_row_)); + } + if (basis_.valid) assert(basis_.useful); + + if ((has_basis || options_.presolve == kHighsOffString || unconstrained_lp) && + solver_will_use_basis) { // There is a valid basis for the problem, presolve is off, or LP - // has no constraint matrix + // has no constraint matrix, and the solver will use the basis ekk_instance_.lp_name_ = "LP without presolve, or with basis, or unconstrained"; // If there is a valid HiGHS basis, refine any status values that // are simply HighsBasisStatus::kNonbasic - if (basis_.valid) refineBasis(incumbent_lp, solution_, basis_); + if (basis_.useful) refineBasis(incumbent_lp, solution_, basis_); solveLp(incumbent_lp, "Solving LP without presolve, or with basis, or unconstrained", this_solve_original_lp_time); @@ -1394,6 +1411,12 @@ HighsStatus Highs::solve() { model_status_ == HighsModelStatus::kTimeLimit || model_status_ == HighsModelStatus::kIterationLimit || model_status_ == HighsModelStatus::kInterrupt; + if (no_incumbent_lp_solution_or_basis) { + // Postsolve won't be performed, so clear the HEkk data + // corresponding to the (strictly reduced) presolved LP here + ekk_instance_.clear(); + setHighsModelStatusAndClearSolutionAndBasis(model_status_); + } break; } case HighsPresolveStatus::kReducedToEmpty: { @@ -1404,6 +1427,7 @@ HighsStatus Highs::solve() { basis_.debug_origin_name = "Presolve to empty"; basis_.valid = true; basis_.alien = false; + basis_.useful = true; basis_.was_alien = false; solution_.value_valid = true; solution_.dual_valid = true; @@ -1443,10 +1467,7 @@ HighsStatus Highs::solve() { options_ = save_options; if (return_status == HighsStatus::kError) return returnFromRun(return_status, undo_mods); - // ToDo Eliminate setBasisValidity once ctest passes. Asserts - // verify that it does nothing - other than setting - // info_.valid = true; - setBasisValidity(); + info_.valid = true; assert(model_status_ == HighsModelStatus::kInfeasible || model_status_ == HighsModelStatus::kUnbounded); return returnFromRun(return_status, undo_mods); @@ -1486,152 +1507,142 @@ HighsStatus Highs::solve() { // Postsolve. Does nothing if there were no reductions during presolve. - if (have_optimal_solution) { + const bool have_optimal_reduced_solution = + model_presolve_status_ == HighsPresolveStatus::kReducedToEmpty || + (model_presolve_status_ == HighsPresolveStatus::kReduced && + model_status_ == HighsModelStatus::kOptimal); + const bool have_unknown_reduced_solution = + model_presolve_status_ == HighsPresolveStatus::kReduced && + model_status_ == HighsModelStatus::kUnknown; + + if (have_optimal_reduced_solution || have_unknown_reduced_solution) { // ToDo Put this in a separate method assert(model_status_ == HighsModelStatus::kOptimal || + model_status_ == HighsModelStatus::kUnknown || model_presolve_status_ == HighsPresolveStatus::kReducedToEmpty); - if (model_presolve_status_ == HighsPresolveStatus::kReduced || - model_presolve_status_ == HighsPresolveStatus::kReducedToEmpty) { - // If presolve is nontrivial, extract the optimal solution - // and basis for the presolved problem in order to generate - // the solution and basis for postsolve to use to generate a - // solution(?) and basis that is, hopefully, optimal. This is - // confirmed or corrected by hot-starting the simplex solver - presolve_.data_.recovered_solution_ = solution_; - presolve_.data_.recovered_basis_ = basis_; - - this_postsolve_time = -timer_.read(timer_.postsolve_clock); - timer_.start(timer_.postsolve_clock); - HighsPostsolveStatus postsolve_status = runPostsolve(); - timer_.stop(timer_.postsolve_clock); - this_postsolve_time += -timer_.read(timer_.postsolve_clock); - presolve_.info_.postsolve_time = this_postsolve_time; - - if (postsolve_status == HighsPostsolveStatus::kSolutionRecovered) { - highsLogDev(log_options, HighsLogType::kVerbose, - "Postsolve finished\n"); - // Set solution and its status - solution_.clear(); - solution_ = presolve_.data_.recovered_solution_; - solution_.value_valid = true; - // if (ipx_no_crossover) { - if (!basis_.valid) { - // Have a primal-dual solution, but no basis, since IPX - // was used without crossover, either because - // run_crossover was "off" or "choose" and IPX determined - // optimality - solution_.dual_valid = true; - basis_.invalidate(); - } else { - // - // Hot-start the simplex solver for the incumbent LP - // - solution_.dual_valid = true; - // Set basis and its status - basis_.valid = true; - basis_.col_status = presolve_.data_.recovered_basis_.col_status; - basis_.row_status = presolve_.data_.recovered_basis_.row_status; - basis_.debug_origin_name += ": after postsolve"; - // Basic primal activities are wrong after postsolve, so - // possibly skip KKT check - const bool perform_kkt_check = true; - if (perform_kkt_check) { - // Possibly force debug to perform KKT check on what's - // returned from postsolve - const bool force_debug = false; - HighsInt save_highs_debug_level = options_.highs_debug_level; - if (force_debug) - options_.highs_debug_level = kHighsDebugLevelCostly; - if (debugHighsSolution("After returning from postsolve", options_, - model_, solution_, - basis_) == HighsDebugStatus::kLogicalError) - return returnFromRun(HighsStatus::kError, undo_mods); - options_.highs_debug_level = save_highs_debug_level; - } - // Save the options to allow the best simplex strategy to - // be used - HighsOptions save_options = options_; - const bool full_logging = false; - if (full_logging) options_.log_dev_level = kHighsLogDevLevelVerbose; - // Force the use of simplex to clean up if IPM has been used - // to solve the presolved problem - if (options_.solver == kIpmString) options_.solver = kSimplexString; - options_.simplex_strategy = kSimplexStrategyChoose; - // Ensure that the parallel solver isn't used - options_.simplex_min_concurrency = 1; - options_.simplex_max_concurrency = 1; - // Use any pivot threshold resulting from solving the presolved LP - if (factor_pivot_threshold > 0) - options_.factor_pivot_threshold = factor_pivot_threshold; - // The basis returned from postsolve is just basic/nonbasic - // and EKK expects a refined basis, so set it up now - refineBasis(incumbent_lp, solution_, basis_); - // Scrap the EKK data from solving the presolved LP - ekk_instance_.invalidate(); - ekk_instance_.lp_name_ = "Postsolve LP"; - // Set up the iteration count and timing records so that - // adding the corresponding values after callSolveLp gives - // difference - postsolve_iteration_count = -info_.simplex_iteration_count; - solveLp(incumbent_lp, - "Solving the original LP from the solution after postsolve", - this_solve_original_lp_time); - // Determine the iteration count - postsolve_iteration_count += info_.simplex_iteration_count; - return_status = - interpretCallStatus(options_.log_options, call_status, - return_status, "callSolveLp"); - // Recover the options - options_ = save_options; - if (return_status == HighsStatus::kError) - return returnFromRun(return_status, undo_mods); - if (postsolve_iteration_count > 0) - highsLogUser(options_.log_options, HighsLogType::kInfo, - "Required %d simplex iterations after postsolve\n", - int(postsolve_iteration_count)); - } + assert(model_presolve_status_ == HighsPresolveStatus::kReduced || + model_presolve_status_ == HighsPresolveStatus::kReducedToEmpty); + if (have_unknown_reduced_solution) + highsLogUser( + options_.log_options, HighsLogType::kWarning, + "Running postsolve on non-optimal solution of reduced LP\n"); + // If presolve is nontrivial, extract the optimal solution + // and basis for the presolved problem in order to generate + // the solution and basis for postsolve to use to generate a + // solution(?) and basis that is, hopefully, optimal. This is + // confirmed or corrected by hot-starting the simplex solver + presolve_.data_.recovered_solution_ = solution_; + presolve_.data_.recovered_basis_ = basis_; + + this_postsolve_time = -timer_.read(timer_.postsolve_clock); + timer_.start(timer_.postsolve_clock); + HighsPostsolveStatus postsolve_status = runPostsolve(); + timer_.stop(timer_.postsolve_clock); + this_postsolve_time += -timer_.read(timer_.postsolve_clock); + presolve_.info_.postsolve_time = this_postsolve_time; + + if (postsolve_status == HighsPostsolveStatus::kSolutionRecovered) { + highsLogDev(log_options, HighsLogType::kVerbose, + "Postsolve finished\n"); + // Set solution and its status + solution_.clear(); + solution_ = presolve_.data_.recovered_solution_; + solution_.value_valid = true; + // if (ipx_no_crossover) { + if (!basis_.valid) { + // Have a primal-dual solution, but no basis, since IPX + // was used without crossover, either because + // run_crossover was "off" or "choose" and IPX determined + // optimality + solution_.dual_valid = true; + basis_.invalidate(); } else { - highsLogUser(log_options, HighsLogType::kError, - "Postsolve return status is %d\n", - (int)postsolve_status); - setHighsModelStatusAndClearSolutionAndBasis( - HighsModelStatus::kPostsolveError); - return returnFromRun(HighsStatus::kError, undo_mods); + // + // Hot-start the simplex solver for the incumbent LP + // + solution_.dual_valid = true; + // Set basis and its status + basis_.valid = true; + basis_.useful = true; + basis_.col_status = presolve_.data_.recovered_basis_.col_status; + basis_.row_status = presolve_.data_.recovered_basis_.row_status; + basis_.debug_origin_name += ": after postsolve"; + // Basic primal activities are wrong after postsolve, so + // possibly skip KKT check + const bool perform_kkt_check = true; + if (perform_kkt_check) { + // Possibly force debug to perform KKT check on what's + // returned from postsolve + const bool force_debug = false; + HighsInt save_highs_debug_level = options_.highs_debug_level; + if (force_debug) + options_.highs_debug_level = kHighsDebugLevelCostly; + if (debugHighsSolution("After returning from postsolve", options_, + model_, solution_, + basis_) == HighsDebugStatus::kLogicalError) + return returnFromRun(HighsStatus::kError, undo_mods); + options_.highs_debug_level = save_highs_debug_level; + } + // Save the options to allow the best simplex strategy to + // be used + HighsOptions save_options = options_; + const bool full_logging = false; + if (full_logging) options_.log_dev_level = kHighsLogDevLevelVerbose; + // Force the use of simplex to clean up if IPM has been used + // to solve the presolved problem + if (options_.solver == kIpmString) options_.solver = kSimplexString; + options_.simplex_strategy = kSimplexStrategyChoose; + // Ensure that the parallel solver isn't used + options_.simplex_min_concurrency = 1; + options_.simplex_max_concurrency = 1; + // Use any pivot threshold resulting from solving the presolved LP + if (factor_pivot_threshold > 0) + options_.factor_pivot_threshold = factor_pivot_threshold; + // The basis returned from postsolve is just basic/nonbasic + // and EKK expects a refined basis, so set it up now + refineBasis(incumbent_lp, solution_, basis_); + // Scrap the EKK data from solving the presolved LP + ekk_instance_.invalidate(); + ekk_instance_.lp_name_ = "Postsolve LP"; + // Set up the iteration count and timing records so that + // adding the corresponding values after callSolveLp gives + // difference + postsolve_iteration_count = -info_.simplex_iteration_count; + solveLp(incumbent_lp, + "Solving the original LP from the solution after postsolve", + this_solve_original_lp_time); + // Determine the iteration count + postsolve_iteration_count += info_.simplex_iteration_count; + // + return_status = HighsStatus::kOk; + return_status = interpretCallStatus(options_.log_options, call_status, + return_status, "callSolveLp"); + // Recover the options + options_ = save_options; + if (return_status == HighsStatus::kError) + return returnFromRun(return_status, undo_mods); + if (postsolve_iteration_count > 0) + highsLogUser(options_.log_options, HighsLogType::kInfo, + "Required %d simplex iterations after postsolve\n", + int(postsolve_iteration_count)); } } else { - // LP was not reduced by presolve, so have simply solved the original LP - assert(model_presolve_status_ == HighsPresolveStatus::kNotReduced); + highsLogUser(log_options, HighsLogType::kError, + "Postsolve return status is %d\n", (int)postsolve_status); + setHighsModelStatusAndClearSolutionAndBasis( + HighsModelStatus::kPostsolveError); + return returnFromRun(HighsStatus::kError, undo_mods); } } } // Cycling can yield model_status_ == HighsModelStatus::kNotset, // assert(model_status_ != HighsModelStatus::kNotset); - if (no_incumbent_lp_solution_or_basis) { - // In solving the (strictly reduced) presolved LP, it is found to - // be infeasible or unbounded, the time/iteration limit has been - // reached, a user interrupt has occurred, or the status is unknown - // (cycling) - // - // Hence there's no incumbent lp solution or basis to drive dual - // postsolve - assert(model_status_ == HighsModelStatus::kInfeasible || - model_status_ == HighsModelStatus::kUnbounded || - model_status_ == HighsModelStatus::kUnboundedOrInfeasible || - model_status_ == HighsModelStatus::kTimeLimit || - model_status_ == HighsModelStatus::kIterationLimit || - model_status_ == HighsModelStatus::kInterrupt || - model_status_ == HighsModelStatus::kUnknown); - // The HEkk data correspond to the (strictly reduced) presolved LP - // so must be cleared - ekk_instance_.clear(); - setHighsModelStatusAndClearSolutionAndBasis(model_status_); - } else { - // ToDo Eliminate setBasisValidity once ctest passes. Asserts - // verify that it does nothing - other than setting info_.valid = - // true; - setBasisValidity(); - } - double lp_solve_final_time = timer_.readRunHighsClock(); + + // Unless the model status was determined using the strictly reduced LP, the + // HiGHS info is valid + if (!no_incumbent_lp_solution_or_basis) info_.valid = true; + + double lp_solve_final_time = timer_.read(); double this_solve_time = lp_solve_final_time - initial_time; if (postsolve_iteration_count < 0) { highsLogDev(log_options, HighsLogType::kInfo, "Postsolve : \n"); @@ -1706,6 +1717,7 @@ HighsStatus Highs::getStandardFormLp(HighsInt& num_col, HighsInt& num_row, HighsInt& num_nz, double& offset, double* cost, double* rhs, HighsInt* start, HighsInt* index, double* value) { + this->logHeader(); if (!this->standard_form_valid_) { HighsStatus status = formStandardFormLp(); assert(status == HighsStatus::kOk); @@ -2341,6 +2353,7 @@ HighsStatus Highs::setBasis(const HighsBasis& basis, basis_ = basis; } basis_.valid = true; + basis_.useful = true; if (origin != "") basis_.debug_origin_name = origin; assert(basis_.debug_origin_name != ""); assert(!basis_.alien); @@ -3433,9 +3446,9 @@ HighsPresolveStatus Highs::runPresolve(const bool force_lp_presolve, if (original_lp.num_col_ == 0 && original_lp.num_row_ == 0) return HighsPresolveStatus::kNullError; - // Ensure that the RunHighsClock is running - if (!timer_.runningRunHighsClock()) timer_.startRunHighsClock(); - double start_presolve = timer_.readRunHighsClock(); + // Ensure that the timer is running + if (!timer_.running()) timer_.start(); + double start_presolve = timer_.read(); // Set time limit. if (options_.time_limit > 0 && options_.time_limit < kHighsInf) { @@ -3461,9 +3474,9 @@ HighsPresolveStatus Highs::runPresolve(const bool force_lp_presolve, // Presolved model is extracted now since it's part of solver, // which is lost on return HighsMipSolver solver(callback_, options_, original_lp, solution_); - // Start the MIP solver's total clock so that timeout in presolve - // can be identified - solver.timer_.start(timer_.total_clock); + // Start the MIP solver's timer so that timeout in presolve can be + // identified + solver.timer_.start(); // Only place that HighsMipSolver::runPresolve is called solver.runPresolve(options_.presolve_reduction_limit); presolve_return_status = solver.getPresolveStatus(); @@ -3477,7 +3490,7 @@ HighsPresolveStatus Highs::runPresolve(const bool force_lp_presolve, presolve_.init(original_lp, timer_); presolve_.options_ = &options_; if (options_.time_limit > 0 && options_.time_limit < kHighsInf) { - double current = timer_.readRunHighsClock(); + double current = timer_.read(); double time_init = current - start_presolve; double left = presolve_.options_->time_limit - time_init; if (left <= 0) { @@ -3862,10 +3875,13 @@ HighsStatus Highs::callSolveQp() { // Define the QP solver iteration logging function settings.iteration_log.subscribe([this](Statistics& stats) { int rep = stats.iteration.size() - 1; + std::string time_string = + options_.timeless_log ? "" + : highsFormatToString(" %9.2fs", stats.time[rep]); highsLogUser(options_.log_options, HighsLogType::kInfo, - "%11d %15.8g %6d %9.2fs\n", - int(stats.iteration[rep]), stats.objval[rep], - int(stats.nullspacedimension[rep]), stats.time[rep]); + "%11d %15.8g %6d%s\n", int(stats.iteration[rep]), + stats.objval[rep], int(stats.nullspacedimension[rep]), + time_string.c_str()); }); // Define the QP nullspace limit logging function @@ -4159,6 +4175,7 @@ HighsStatus Highs::callRunPostsolve(const HighsSolution& solution, // Set basis and its status // // basis_.valid = true; + // basis_.useful = true; // basis_.col_status = presolve_.data_.recovered_basis_.col_status; // basis_.row_status = presolve_.data_.recovered_basis_.row_status; basis_.debug_origin_name += ": after postsolve"; @@ -4236,9 +4253,10 @@ HighsStatus Highs::callRunPostsolve(const HighsSolution& solution, // End of public methods void Highs::logHeader() { - if (written_log_header) return; + if (written_log_header_) return; + if (!*options_.log_options.output_flag) return; highsLogHeader(options_.log_options, options_.log_githash); - written_log_header = true; + written_log_header_ = true; return; } @@ -4272,10 +4290,12 @@ void Highs::forceHighsSolutionBasisSize() { if (basis_.col_status.size() != static_cast(model_.lp_.num_col_)) { basis_.col_status.resize(model_.lp_.num_col_); basis_.valid = false; + basis_.useful = false; } if (basis_.row_status.size() != static_cast(model_.lp_.num_row_)) { basis_.row_status.resize(model_.lp_.num_row_); basis_.valid = false; + basis_.useful = false; } } @@ -4287,17 +4307,6 @@ void Highs::setHighsModelStatusAndClearSolutionAndBasis( info_.valid = true; } -void Highs::setBasisValidity() { - if (basis_.valid) { - assert(info_.basis_validity == kBasisValidityValid); - info_.basis_validity = kBasisValidityValid; - } else { - assert(info_.basis_validity == kBasisValidityInvalid); - info_.basis_validity = kBasisValidityInvalid; - } - info_.valid = true; -} - HighsStatus Highs::openWriteFile(const string filename, const string method_name, FILE*& file, HighsFileType& file_type) const { @@ -4543,7 +4552,7 @@ HighsStatus Highs::returnFromHighs(HighsStatus highs_return_status) { assert(called_return_from_run); } // Stop the HiGHS run clock if it is running - if (timer_.runningRunHighsClock()) timer_.stopRunHighsClock(); + if (timer_.running()) timer_.stop(); const bool dimensions_ok = lpDimensionsOk("returnFromHighs", model_.lp_, options_.log_options); if (!dimensions_ok) { @@ -4607,9 +4616,11 @@ void Highs::reportSolvedLpQpStats() { highsLogUser(log_options, HighsLogType::kInfo, "Relative P-D gap : %17.10e\n", relative_primal_dual_gap); } - double run_time = timer_.readRunHighsClock(); - highsLogUser(log_options, HighsLogType::kInfo, - "HiGHS run time : %13.2f\n", run_time); + if (!options_.timeless_log) { + double run_time = timer_.read(); + highsLogUser(log_options, HighsLogType::kInfo, + "HiGHS run time : %13.2f\n", run_time); + } } HighsStatus Highs::crossover(const HighsSolution& user_solution) { diff --git a/src/lp_data/HighsCallback.cpp b/src/lp_data/HighsCallback.cpp index 99e148aa51..556f6b38b7 100644 --- a/src/lp_data/HighsCallback.cpp +++ b/src/lp_data/HighsCallback.cpp @@ -24,10 +24,20 @@ void HighsCallback::clearHighsCallbackDataOut() { this->data_out.mip_dual_bound = -kHighsInf; this->data_out.mip_gap = -1; this->data_out.mip_solution = nullptr; + this->data_out.cutpool_num_col = 0; + this->data_out.cutpool_num_cut = 0; + this->data_out.cutpool_num_nz = 0; + this->data_out.cutpool_start = nullptr; + this->data_out.cutpool_index = nullptr; + this->data_out.cutpool_value = nullptr; + this->data_out.cutpool_lower = nullptr; + this->data_out.cutpool_upper = nullptr; + this->data_out.user_solution_callback_origin = 0; } void HighsCallback::clearHighsCallbackDataIn() { this->data_in.user_interrupt = false; + this->data_in.user_solution = nullptr; } void HighsCallback::clear() { @@ -65,7 +75,8 @@ bool HighsCallback::callbackAction(const int callback_type, callback_type == kCallbackMipSolution || callback_type == kCallbackMipLogging || callback_type == kCallbackMipGetCutPool || - callback_type == kCallbackMipDefineLazyConstraints) + callback_type == kCallbackMipDefineLazyConstraints || + callback_type == kCallbackMipUserSolution) assert(!action); return action; } diff --git a/src/lp_data/HighsCallback.h b/src/lp_data/HighsCallback.h index 73d53f3926..ae13c07811 100644 --- a/src/lp_data/HighsCallback.h +++ b/src/lp_data/HighsCallback.h @@ -16,6 +16,16 @@ #include "lp_data/HStruct.h" #include "lp_data/HighsCallbackStruct.h" +enum userMipSolutionCallbackOrigin { + kUserMipSolutionCallbackOriginAfterSetup = 0, + kUserMipSolutionCallbackOriginBeforeDive, + kUserMipSolutionCallbackOriginEvaluateRootNode0, + kUserMipSolutionCallbackOriginEvaluateRootNode1, + kUserMipSolutionCallbackOriginEvaluateRootNode2, + kUserMipSolutionCallbackOriginEvaluateRootNode3, + kUserMipSolutionCallbackOriginEvaluateRootNode4 +}; + using HighsCallbackFunctionType = std::function; diff --git a/src/lp_data/HighsCallbackStruct.h b/src/lp_data/HighsCallbackStruct.h index 342193f4a5..d7b488598c 100644 --- a/src/lp_data/HighsCallbackStruct.h +++ b/src/lp_data/HighsCallbackStruct.h @@ -42,10 +42,12 @@ typedef struct { double* cutpool_value; double* cutpool_lower; double* cutpool_upper; + HighsInt user_solution_callback_origin; } HighsCallbackDataOut; typedef struct { int user_interrupt; + double* user_solution; } HighsCallbackDataIn; // Additional callback handling diff --git a/src/lp_data/HighsInterface.cpp b/src/lp_data/HighsInterface.cpp index 5e030dfc59..4b0ea432e2 100644 --- a/src/lp_data/HighsInterface.cpp +++ b/src/lp_data/HighsInterface.cpp @@ -305,7 +305,7 @@ HighsStatus Highs::addColsInterface( HighsLp& lp = model_.lp_; HighsBasis& basis = basis_; HighsScale& scale = lp.scale_; - bool& valid_basis = basis.valid; + bool& useful_basis = basis.useful; bool& lp_has_scaling = lp.scale_.has_scaling; // Check that if nonzeros are to be added then the model has a positive number @@ -415,7 +415,7 @@ HighsStatus Highs::addColsInterface( &scale.col[lp.num_col_]); } // Update the basis corresponding to new nonbasic columns - if (valid_basis) appendNonbasicColsToBasisInterface(ext_num_new_col); + if (useful_basis) appendNonbasicColsToBasisInterface(ext_num_new_col); // Possibly add column names lp.addColNames("", ext_num_new_col); @@ -471,7 +471,8 @@ HighsStatus Highs::addRowsInterface(HighsInt ext_num_new_row, HighsLp& lp = model_.lp_; HighsBasis& basis = basis_; HighsScale& scale = lp.scale_; - bool& valid_basis = basis.valid; + bool& useful_basis = basis.useful; + bool& lp_has_scaling = lp.scale_.has_scaling; // Check that if nonzeros are to be added then the model has a positive number @@ -559,7 +560,7 @@ HighsStatus Highs::addRowsInterface(HighsInt ext_num_new_row, &scale.row[lp.num_row_]); } // Update the basis corresponding to new basic rows - if (valid_basis) appendBasicRowsToBasisInterface(ext_num_new_row); + if (useful_basis) appendBasicRowsToBasisInterface(ext_num_new_row); // Possibly add row names lp.addRowNames("", ext_num_new_row); @@ -576,6 +577,69 @@ HighsStatus Highs::addRowsInterface(HighsInt ext_num_new_row, return return_status; } +void deleteBasisEntries(std::vector& status, + bool& deleted_basic, bool& deleted_nonbasic, + const HighsIndexCollection& index_collection, + const HighsInt entry_dim) { + assert(ok(index_collection)); + assert(static_cast(entry_dim) == status.size()); + HighsInt from_k; + HighsInt to_k; + limits(index_collection, from_k, to_k); + if (from_k > to_k) return; + + HighsInt delete_from_entry; + HighsInt delete_to_entry; + HighsInt keep_from_entry; + HighsInt keep_to_entry = -1; + HighsInt current_set_entry = 0; + HighsInt new_num_entry = 0; + deleted_basic = false; + deleted_nonbasic = false; + for (HighsInt k = from_k; k <= to_k; k++) { + updateOutInIndex(index_collection, delete_from_entry, delete_to_entry, + keep_from_entry, keep_to_entry, current_set_entry); + // Account for the initial entries being kept + if (k == from_k) new_num_entry = delete_from_entry; + // Identify whether a basic or a nonbasic entry has been deleted + for (HighsInt entry = delete_from_entry; entry <= delete_to_entry; + entry++) { + if (status[entry] == HighsBasisStatus::kBasic) { + deleted_basic = true; + } else { + deleted_nonbasic = true; + } + } + if (delete_to_entry >= entry_dim - 1) break; + for (HighsInt entry = keep_from_entry; entry <= keep_to_entry; entry++) { + status[new_num_entry] = status[entry]; + new_num_entry++; + } + if (keep_to_entry >= entry_dim - 1) break; + } + status.resize(new_num_entry); +} + +void deleteBasisCols(HighsBasis& basis, + const HighsIndexCollection& index_collection, + const HighsInt original_num_col) { + bool deleted_basic; + bool deleted_nonbasic; + deleteBasisEntries(basis.col_status, deleted_basic, deleted_nonbasic, + index_collection, original_num_col); + if (deleted_basic) basis.valid = false; +} + +void deleteBasisRows(HighsBasis& basis, + const HighsIndexCollection& index_collection, + const HighsInt original_num_row) { + bool deleted_basic; + bool deleted_nonbasic; + deleteBasisEntries(basis.row_status, deleted_basic, deleted_nonbasic, + index_collection, original_num_row); + if (deleted_nonbasic) basis.valid = false; +} + void Highs::deleteColsInterface(HighsIndexCollection& index_collection) { HighsLp& lp = model_.lp_; HighsBasis& basis = basis_; @@ -587,13 +651,24 @@ void Highs::deleteColsInterface(HighsIndexCollection& index_collection) { lp.deleteCols(index_collection); model_.hessian_.deleteCols(index_collection); - assert(lp.num_col_ <= original_num_col); - if (lp.num_col_ < original_num_col) { - // Nontrivial deletion so reset the model_status and invalidate - // the Highs basis - model_status_ = HighsModelStatus::kNotset; - basis.valid = false; + // Bail out if no columns were actually deleted + if (lp.num_col_ == original_num_col) return; + + assert(lp.num_col_ < original_num_col); + + // Nontrivial deletion so reset the model_status and update any + // Highs basis + model_status_ = HighsModelStatus::kNotset; + if (basis_.useful) { + assert(basis_.col_status.size() == static_cast(original_num_col)); + // Have a full set of column basis status values, so maintain + // them, and only invalidate the basis if a basic column has been + // deleted + deleteBasisCols(basis_, index_collection, original_num_col); + } else { + assert(!basis.valid); } + if (lp.scale_.has_scaling) { deleteScale(lp.scale_.col, index_collection); lp.scale_.col.resize(lp.num_col_); @@ -632,13 +707,24 @@ void Highs::deleteRowsInterface(HighsIndexCollection& index_collection) { HighsInt original_num_row = lp.num_row_; lp.deleteRows(index_collection); - assert(lp.num_row_ <= original_num_row); - if (lp.num_row_ < original_num_row) { - // Nontrivial deletion so reset the model_status and invalidate - // the Highs basis - model_status_ = HighsModelStatus::kNotset; - basis.valid = false; + // Bail out if no rows were actually deleted + if (lp.num_row_ == original_num_row) return; + + assert(lp.num_row_ < original_num_row); + + // Nontrivial deletion so reset the model_status and update any + // Highs basis + model_status_ = HighsModelStatus::kNotset; + if (basis_.useful) { + assert(basis_.row_status.size() == static_cast(original_num_row)); + // Have a full set of row basis status values, so maintain them, + // and only invalidate the basis if a nonbasic row has been + // deleted + deleteBasisRows(basis_, index_collection, original_num_row); + } else { + assert(!basis.valid); } + if (lp.scale_.has_scaling) { deleteScale(lp.scale_.row, index_collection); lp.scale_.row.resize(lp.num_row_); @@ -666,181 +752,36 @@ void Highs::deleteRowsInterface(HighsIndexCollection& index_collection) { } void Highs::getColsInterface(const HighsIndexCollection& index_collection, - HighsInt& get_num_col, double* col_cost, - double* col_lower, double* col_upper, - HighsInt& get_num_nz, HighsInt* col_matrix_start, - HighsInt* col_matrix_index, - double* col_matrix_value) { - HighsLp& lp = model_.lp_; - // Ensure that the LP is column-wise - lp.ensureColwise(); - assert(ok(index_collection)); - HighsInt from_k; - HighsInt to_k; - limits(index_collection, from_k, to_k); - // Surely this is checked elsewhere - assert(0 <= from_k && to_k < lp.num_col_); - assert(from_k <= to_k); - HighsInt out_from_col; - HighsInt out_to_col; - HighsInt in_from_col; - HighsInt in_to_col = -1; - HighsInt current_set_entry = 0; - HighsInt col_dim = lp.num_col_; - get_num_col = 0; - get_num_nz = 0; - for (HighsInt k = from_k; k <= to_k; k++) { - updateOutInIndex(index_collection, out_from_col, out_to_col, in_from_col, - in_to_col, current_set_entry); - assert(out_to_col < col_dim); - assert(in_to_col < col_dim); - for (HighsInt iCol = out_from_col; iCol <= out_to_col; iCol++) { - if (col_cost != NULL) col_cost[get_num_col] = lp.col_cost_[iCol]; - if (col_lower != NULL) col_lower[get_num_col] = lp.col_lower_[iCol]; - if (col_upper != NULL) col_upper[get_num_col] = lp.col_upper_[iCol]; - if (col_matrix_start != NULL) - col_matrix_start[get_num_col] = get_num_nz + lp.a_matrix_.start_[iCol] - - lp.a_matrix_.start_[out_from_col]; - get_num_col++; - } - for (HighsInt iEl = lp.a_matrix_.start_[out_from_col]; - iEl < lp.a_matrix_.start_[out_to_col + 1]; iEl++) { - if (col_matrix_index != NULL) - col_matrix_index[get_num_nz] = lp.a_matrix_.index_[iEl]; - if (col_matrix_value != NULL) - col_matrix_value[get_num_nz] = lp.a_matrix_.value_[iEl]; - get_num_nz++; - } - if (out_to_col == col_dim - 1 || in_to_col == col_dim - 1) break; + HighsInt& num_col, double* cost, double* lower, + double* upper, HighsInt& num_nz, HighsInt* start, + HighsInt* index, double* value) { + const HighsLp& lp = model_.lp_; + if (lp.a_matrix_.isColwise()) { + getSubVectors(index_collection, lp.num_col_, lp.col_cost_.data(), + lp.col_lower_.data(), lp.col_upper_.data(), lp.a_matrix_, + num_col, cost, lower, upper, num_nz, start, index, value); + } else { + getSubVectorsTranspose(index_collection, lp.num_col_, lp.col_cost_.data(), + lp.col_lower_.data(), lp.col_upper_.data(), + lp.a_matrix_, num_col, cost, lower, upper, num_nz, + start, index, value); } } void Highs::getRowsInterface(const HighsIndexCollection& index_collection, - HighsInt& get_num_row, double* row_lower, - double* row_upper, HighsInt& get_num_nz, - HighsInt* row_matrix_start, - HighsInt* row_matrix_index, - double* row_matrix_value) { - HighsLp& lp = model_.lp_; - // Ensure that the LP is column-wise - lp.ensureColwise(); - assert(ok(index_collection)); - HighsInt from_k; - HighsInt to_k; - limits(index_collection, from_k, to_k); - // Surely this is checked elsewhere - assert(0 <= from_k && to_k < lp.num_row_); - assert(from_k <= to_k); - // "Out" means not in the set to be extracted - // "In" means in the set to be extracted - HighsInt out_from_row; - HighsInt out_to_row; - HighsInt in_from_row; - HighsInt in_to_row = -1; - HighsInt current_set_entry = 0; - HighsInt row_dim = lp.num_row_; - // Ensure that the LP is column-wise - lp.ensureColwise(); - // Set up a row mask so that entries to be got from the column-wise - // matrix can be identified and have their correct row index. - vector new_index; - new_index.resize(lp.num_row_); - - get_num_row = 0; - get_num_nz = 0; - if (!index_collection.is_mask_) { - out_to_row = -1; - current_set_entry = 0; - for (HighsInt k = from_k; k <= to_k; k++) { - updateOutInIndex(index_collection, in_from_row, in_to_row, out_from_row, - out_to_row, current_set_entry); - if (k == from_k) { - // Account for any initial rows not being extracted - for (HighsInt iRow = 0; iRow < in_from_row; iRow++) { - new_index[iRow] = -1; - } - } - for (HighsInt iRow = in_from_row; iRow <= in_to_row; iRow++) { - new_index[iRow] = get_num_row; - get_num_row++; - } - for (HighsInt iRow = out_from_row; iRow <= out_to_row; iRow++) { - new_index[iRow] = -1; - } - if (out_to_row >= row_dim - 1) break; - } + HighsInt& num_row, double* lower, double* upper, + HighsInt& num_nz, HighsInt* start, HighsInt* index, + double* value) { + const HighsLp& lp = model_.lp_; + if (lp.a_matrix_.isColwise()) { + getSubVectorsTranspose(index_collection, lp.num_row_, nullptr, + lp.row_lower_.data(), lp.row_upper_.data(), + lp.a_matrix_, num_row, nullptr, lower, upper, num_nz, + start, index, value); } else { - for (HighsInt iRow = 0; iRow < lp.num_row_; iRow++) { - if (index_collection.mask_[iRow]) { - new_index[iRow] = get_num_row; - get_num_row++; - } else { - new_index[iRow] = -1; - } - } - } - - // Bail out if no rows are to be extracted - if (get_num_row == 0) return; - - for (HighsInt iRow = 0; iRow < lp.num_row_; iRow++) { - HighsInt new_iRow = new_index[iRow]; - if (new_iRow >= 0) { - assert(new_iRow < get_num_row); - if (row_lower != NULL) row_lower[new_iRow] = lp.row_lower_[iRow]; - if (row_upper != NULL) row_upper[new_iRow] = lp.row_upper_[iRow]; - } - } - const bool extract_start = row_matrix_start != NULL; - const bool extract_index = row_matrix_index != NULL; - const bool extract_value = row_matrix_value != NULL; - const bool extract_matrix = extract_index || extract_value; - // Allocate an array of lengths for the row-wise matrix to be - // extracted: necessary even if just the number of nonzeros is - // required - vector row_matrix_length; - row_matrix_length.assign(get_num_row, 0); - // Identify the lengths of the rows in the row-wise matrix to be extracted - for (HighsInt col = 0; col < lp.num_col_; col++) { - for (HighsInt iEl = lp.a_matrix_.start_[col]; - iEl < lp.a_matrix_.start_[col + 1]; iEl++) { - HighsInt iRow = lp.a_matrix_.index_[iEl]; - HighsInt new_iRow = new_index[iRow]; - if (new_iRow >= 0) row_matrix_length[new_iRow]++; - } - } - if (!extract_start) { - // bail out if no matrix starts are to be extracted, but only after - // computing the number of nonzeros - for (HighsInt iRow = 0; iRow < get_num_row; iRow++) - get_num_nz += row_matrix_length[iRow]; - return; - } - // Allocate an array of lengths for the row-wise matrix to be extracted - row_matrix_start[0] = 0; - for (HighsInt iRow = 0; iRow < get_num_row - 1; iRow++) { - row_matrix_start[iRow + 1] = - row_matrix_start[iRow] + row_matrix_length[iRow]; - row_matrix_length[iRow] = row_matrix_start[iRow]; - } - HighsInt iRow = get_num_row - 1; - get_num_nz = row_matrix_start[iRow] + row_matrix_length[iRow]; - // Bail out if matrix indices and values are not required - if (!extract_matrix) return; - row_matrix_length[iRow] = row_matrix_start[iRow]; - // Fill the row-wise matrix with indices and values - for (HighsInt col = 0; col < lp.num_col_; col++) { - for (HighsInt iEl = lp.a_matrix_.start_[col]; - iEl < lp.a_matrix_.start_[col + 1]; iEl++) { - HighsInt iRow = lp.a_matrix_.index_[iEl]; - HighsInt new_iRow = new_index[iRow]; - if (new_iRow >= 0) { - HighsInt row_iEl = row_matrix_length[new_iRow]; - if (extract_index) row_matrix_index[row_iEl] = col; - if (extract_value) row_matrix_value[row_iEl] = lp.a_matrix_.value_[iEl]; - row_matrix_length[new_iRow]++; - } - } + getSubVectors(index_collection, lp.num_row_, nullptr, lp.row_lower_.data(), + lp.row_upper_.data(), lp.a_matrix_, num_row, nullptr, lower, + upper, num_nz, start, index, value); } } @@ -1314,14 +1255,17 @@ void Highs::setNonbasicStatusInterface( } void Highs::appendNonbasicColsToBasisInterface(const HighsInt ext_num_new_col) { + if (ext_num_new_col == 0) return; HighsBasis& highs_basis = basis_; - if (!highs_basis.valid) return; + if (!highs_basis.useful) return; const bool has_simplex_basis = ekk_instance_.status_.has_basis; SimplexBasis& simplex_basis = ekk_instance_.basis_; HighsLp& lp = model_.lp_; + assert(highs_basis.col_status.size() == static_cast(lp.num_col_)); + assert(highs_basis.row_status.size() == static_cast(lp.num_row_)); + // Add nonbasic structurals - if (ext_num_new_col == 0) return; HighsInt newNumCol = lp.num_col_ + ext_num_new_col; HighsInt newNumTot = newNumCol + lp.num_row_; highs_basis.col_status.resize(newNumCol); @@ -1388,13 +1332,17 @@ void Highs::appendNonbasicColsToBasisInterface(const HighsInt ext_num_new_col) { } void Highs::appendBasicRowsToBasisInterface(const HighsInt ext_num_new_row) { + if (ext_num_new_row == 0) return; HighsBasis& highs_basis = basis_; - if (!highs_basis.valid) return; + if (!highs_basis.useful) return; const bool has_simplex_basis = ekk_instance_.status_.has_basis; SimplexBasis& simplex_basis = ekk_instance_.basis_; HighsLp& lp = model_.lp_; + + assert(highs_basis.col_status.size() == static_cast(lp.num_col_)); + assert(highs_basis.row_status.size() == static_cast(lp.num_row_)); + // Add basic logicals - if (ext_num_new_row == 0) return; // Add the new rows to the Highs basis HighsInt newNumRow = lp.num_row_ + ext_num_new_row; highs_basis.row_status.resize(newNumRow); @@ -1683,6 +1631,7 @@ HighsStatus Highs::setHotStartInterface(const HotStart& hot_start) { nonbasicMove[num_col + iRow] = move; } basis_.valid = true; + basis_.useful = true; ekk_instance_.status_.has_basis = true; ekk_instance_.setNlaRefactorInfo(); ekk_instance_.updateStatus(LpAction::kHotStart); @@ -2060,6 +2009,7 @@ HighsStatus Highs::getIisInterface() { max_iterations = std::max(iterations, max_iterations); } highsLogUser(options_.log_options, HighsLogType::kInfo, + " %d cols, %d rows, %d LPs solved" " (min / average / max) iteration count (%6d / %6.2g / % 6d)" " and time (%6.2f / %6.2f / % 6.2f) \n", int(this->iis_.col_index_.size()), @@ -2089,6 +2039,12 @@ HighsStatus Highs::elasticityFilterReturn( run_status = this->deleteCols(original_num_col, lp.num_col_ - 1); assert(run_status == HighsStatus::kOk); + // + // Now that deleteRows and deleteCols may yield a valid basis, the + // lack of dual values triggers an assert in + // getKktFailures. Ultimately (#2081) the dual values will be + // available but, for now, make the basis invalid. + basis_.valid = false; run_status = this->changeColsCost(0, original_num_col - 1, original_col_cost.data()); @@ -3612,7 +3568,7 @@ bool Highs::hasRepeatedLinearObjectivePriorities( // O(n^2), but who will have more than O(1) linear objectives! HighsInt num_linear_objective = this->multi_linear_objective_.size(); if (num_linear_objective <= 0 || - num_linear_objective <= 1 && !linear_objective) + (num_linear_objective <= 1 && !linear_objective)) return false; for (HighsInt iObj0 = 0; iObj0 < num_linear_objective; iObj0++) { HighsInt priority0 = this->multi_linear_objective_[iObj0].priority; @@ -3627,8 +3583,8 @@ bool Highs::hasRepeatedLinearObjectivePriorities( return false; } -bool comparison(std::pair x1, - std::pair x2) { +static bool comparison(std::pair x1, + std::pair x2) { return x1.first >= x2.first; } diff --git a/src/lp_data/HighsLpUtils.cpp b/src/lp_data/HighsLpUtils.cpp index 253d8a26f6..fd270dee49 100644 --- a/src/lp_data/HighsLpUtils.cpp +++ b/src/lp_data/HighsLpUtils.cpp @@ -23,7 +23,6 @@ #include "util/HighsCDouble.h" #include "util/HighsMatrixUtils.h" #include "util/HighsSort.h" -#include "util/HighsTimer.h" using std::fabs; using std::max; @@ -478,11 +477,14 @@ HighsStatus assessSemiVariables(HighsLp& lp, const HighsOptions& options, assert((HighsInt)lp.integrality_.size() == lp.num_col_); HighsInt num_illegal_lower = 0; HighsInt num_illegal_upper = 0; - HighsInt num_modified_upper = 0; + HighsInt num_tightened_upper = 0; HighsInt num_inconsistent_semi = 0; HighsInt num_non_semi = 0; HighsInt num_non_continuous_variables = 0; const double kLowerBoundMu = 10.0; + + std::vector& save_non_semi_variable_index = + lp.mods_.save_non_semi_variable_index; std::vector& inconsistent_semi_variable_index = lp.mods_.save_inconsistent_semi_variable_index; std::vector& inconsistent_semi_variable_lower_bound_value = @@ -516,7 +518,7 @@ HighsStatus assessSemiVariables(HighsLp& lp, const HighsOptions& options, // Semi-variables with zero lower bound are not semi if (lp.col_lower_[iCol] == 0) { num_non_semi++; - lp.mods_.save_non_semi_variable_index.push_back(iCol); + save_non_semi_variable_index.push_back(iCol); // Semi-integer become integer so still have a non-continuous variable if (lp.integrality_[iCol] == HighsVarType::kSemiInteger) num_non_continuous_variables++; @@ -536,7 +538,7 @@ HighsStatus assessSemiVariables(HighsLp& lp, const HighsOptions& options, tightened_semi_variable_upper_bound_index.push_back(iCol); tightened_semi_variable_upper_bound_value.push_back( kMaxSemiVariableUpper); - num_modified_upper++; + num_tightened_upper++; } } num_non_continuous_variables++; @@ -568,12 +570,12 @@ HighsStatus assessSemiVariables(HighsLp& lp, const HighsOptions& options, return_status = HighsStatus::kWarning; } const bool has_illegal_bounds = num_illegal_lower || num_illegal_upper; - if (num_modified_upper) { + if (num_tightened_upper) { highsLogUser(options.log_options, HighsLogType::kWarning, "%" HIGHSINT_FORMAT " semi-continuous/integer variable(s) have upper bounds " - "exceeding %g that can be modified to %g > %g*lower)\n", - num_modified_upper, kMaxSemiVariableUpper, + "exceeding %g that can be tightened to %g > %g*lower)\n", + num_tightened_upper, kMaxSemiVariableUpper, kMaxSemiVariableUpper, kLowerBoundMu); return_status = HighsStatus::kWarning; if (has_illegal_bounds) { @@ -581,10 +583,11 @@ HighsStatus assessSemiVariables(HighsLp& lp, const HighsOptions& options, assert(num_illegal_lower || num_illegal_upper); tightened_semi_variable_upper_bound_index.clear(); tightened_semi_variable_upper_bound_value.clear(); + num_tightened_upper = 0; } else { // Apply the upper bound tightenings, saving the over-written // values - for (HighsInt k = 0; k < num_modified_upper; k++) { + for (HighsInt k = 0; k < num_tightened_upper; k++) { const double use_upper_bound = tightened_semi_variable_upper_bound_value[k]; const HighsInt iCol = tightened_semi_variable_upper_bound_index[k]; @@ -600,6 +603,7 @@ HighsStatus assessSemiVariables(HighsLp& lp, const HighsOptions& options, inconsistent_semi_variable_lower_bound_value.clear(); inconsistent_semi_variable_upper_bound_value.clear(); inconsistent_semi_variable_type.clear(); + num_inconsistent_semi = 0; } else { for (HighsInt k = 0; k < num_inconsistent_semi; k++) { const HighsInt iCol = inconsistent_semi_variable_index[k]; @@ -612,10 +616,10 @@ HighsStatus assessSemiVariables(HighsLp& lp, const HighsOptions& options, if (num_non_semi) { if (has_illegal_bounds) { // Don't apply type changes if there are illegal bounds - lp.mods_.save_non_semi_variable_index.clear(); + save_non_semi_variable_index.clear(); } else { for (HighsInt k = 0; k < num_non_semi; k++) { - const HighsInt iCol = lp.mods_.save_non_semi_variable_index[k]; + const HighsInt iCol = save_non_semi_variable_index[k]; if (lp.integrality_[iCol] == HighsVarType::kSemiContinuous) { // Semi-continuous become continuous lp.integrality_[iCol] = HighsVarType::kContinuous; @@ -644,9 +648,14 @@ HighsStatus assessSemiVariables(HighsLp& lp, const HighsOptions& options, return_status = HighsStatus::kError; } made_semi_variable_mods = - lp.mods_.save_non_semi_variable_index.size() > 0 || - inconsistent_semi_variable_index.size() > 0 || - tightened_semi_variable_upper_bound_index.size() > 0; + num_non_semi > 0 || num_inconsistent_semi > 0 || num_tightened_upper > 0; + assert(num_non_semi <= save_non_semi_variable_index.size()); + assert(num_inconsistent_semi <= inconsistent_semi_variable_index.size()); + assert(num_tightened_upper <= + tightened_semi_variable_upper_bound_index.size()); + // save_non_semi_variable_index.size() > 0 || + // inconsistent_semi_variable_index.size() > 0 || + // tightened_semi_variable_upper_bound_index.size() > 0; return return_status; } @@ -677,11 +686,11 @@ bool activeModifiedUpperBounds(const HighsOptions& options, const HighsLp& lp, const std::vector col_value) { const std::vector& tightened_semi_variable_upper_bound_index = lp.mods_.save_tightened_semi_variable_upper_bound_index; - const HighsInt num_modified_upper = + const HighsInt num_tightened_upper = tightened_semi_variable_upper_bound_index.size(); HighsInt num_active_modified_upper = 0; double min_semi_variable_margin = kHighsInf; - for (HighsInt k = 0; k < num_modified_upper; k++) { + for (HighsInt k = 0; k < num_tightened_upper; k++) { const double value = col_value[tightened_semi_variable_upper_bound_index[k]]; const double upper = @@ -700,7 +709,7 @@ bool activeModifiedUpperBounds(const HighsOptions& options, const HighsLp& lp, "%" HIGHSINT_FORMAT " semi-variables are active at modified upper bounds\n", num_active_modified_upper); - } else if (num_modified_upper) { + } else if (num_tightened_upper) { highsLogUser(options.log_options, HighsLogType::kWarning, "No semi-variables are active at modified upper bounds:" " a large minimum margin (%g) suggests optimality," @@ -3077,3 +3086,196 @@ void removeRowsOfCountOne(const HighsLogOptions& log_options, HighsLp& lp) { highsLogUser(log_options, HighsLogType::kWarning, "Removed %d rows of count 1\n", (int)num_row_count_1); } + +void getSubVectors(const HighsIndexCollection& index_collection, + const HighsInt data_dim, const double* data0, + const double* data1, const double* data2, + const HighsSparseMatrix& matrix, HighsInt& num_sub_vector, + double* sub_vector_data0, double* sub_vector_data1, + double* sub_vector_data2, HighsInt& sub_matrix_num_nz, + HighsInt* sub_matrix_start, HighsInt* sub_matrix_index, + double* sub_matrix_value) { + // Ensure that if there's no data0 then it's not required in the + // sub-vector + if (data0 == nullptr) assert(sub_vector_data0 == nullptr); + assert(ok(index_collection)); + HighsInt from_k; + HighsInt to_k; + limits(index_collection, from_k, to_k); + // Surely this is checked elsewhere + assert(0 <= from_k && to_k < data_dim); + assert(from_k <= to_k); + HighsInt out_from_vector; + HighsInt out_to_vector; + HighsInt in_from_vector; + HighsInt in_to_vector = -1; + HighsInt current_set_entry = 0; + num_sub_vector = 0; + sub_matrix_num_nz = 0; + for (HighsInt k = from_k; k <= to_k; k++) { + updateOutInIndex(index_collection, out_from_vector, out_to_vector, + in_from_vector, in_to_vector, current_set_entry); + assert(out_to_vector < data_dim); + assert(in_to_vector < data_dim); + for (HighsInt iVector = out_from_vector; iVector <= out_to_vector; + iVector++) { + if (sub_vector_data0 != nullptr) + sub_vector_data0[num_sub_vector] = data0[iVector]; + if (sub_vector_data1 != nullptr) + sub_vector_data1[num_sub_vector] = data1[iVector]; + if (sub_vector_data2 != nullptr) + sub_vector_data2[num_sub_vector] = data2[iVector]; + if (sub_matrix_start != nullptr) + sub_matrix_start[num_sub_vector] = sub_matrix_num_nz + + matrix.start_[iVector] - + matrix.start_[out_from_vector]; + num_sub_vector++; + } + for (HighsInt iEl = matrix.start_[out_from_vector]; + iEl < matrix.start_[out_to_vector + 1]; iEl++) { + if (sub_matrix_index != nullptr) + sub_matrix_index[sub_matrix_num_nz] = matrix.index_[iEl]; + if (sub_matrix_value != nullptr) + sub_matrix_value[sub_matrix_num_nz] = matrix.value_[iEl]; + sub_matrix_num_nz++; + } + if (out_to_vector == data_dim - 1 || in_to_vector == data_dim - 1) break; + } +} + +void getSubVectorsTranspose(const HighsIndexCollection& index_collection, + const HighsInt data_dim, const double* data0, + const double* data1, const double* data2, + const HighsSparseMatrix& matrix, + HighsInt& num_sub_vector, double* sub_vector_data0, + double* sub_vector_data1, double* sub_vector_data2, + HighsInt& sub_matrix_num_nz, + HighsInt* sub_matrix_start, + HighsInt* sub_matrix_index, + double* sub_matrix_value) { + // Ensure that if there's no data0 then it's not required in the + // sub-vector + if (data0 == nullptr) assert(sub_vector_data0 == nullptr); + assert(ok(index_collection)); + HighsInt from_k; + HighsInt to_k; + limits(index_collection, from_k, to_k); + // Surely this is checked elsewhere + assert(0 <= from_k && to_k < data_dim); + assert(from_k <= to_k); + // "Out" means not in the set to be extracted + // "In" means in the set to be extracted + HighsInt out_from_vector; + HighsInt out_to_vector; + HighsInt in_from_vector; + HighsInt in_to_vector = -1; + HighsInt current_set_entry = 0; + // Set up a mask so that entries to be got from the matrix can be + // identified and have their correct index. + vector new_index; + new_index.resize(data_dim); + + num_sub_vector = 0; + sub_matrix_num_nz = 0; + if (!index_collection.is_mask_) { + out_to_vector = -1; + current_set_entry = 0; + for (HighsInt k = from_k; k <= to_k; k++) { + updateOutInIndex(index_collection, in_from_vector, in_to_vector, + out_from_vector, out_to_vector, current_set_entry); + if (k == from_k) { + // Account for any initial vectors not being extracted + for (HighsInt iVector = 0; iVector < in_from_vector; iVector++) { + new_index[iVector] = -1; + } + } + for (HighsInt iVector = in_from_vector; iVector <= in_to_vector; + iVector++) { + new_index[iVector] = num_sub_vector; + num_sub_vector++; + } + for (HighsInt iVector = out_from_vector; iVector <= out_to_vector; + iVector++) { + new_index[iVector] = -1; + } + if (out_to_vector >= data_dim - 1) break; + } + } else { + for (HighsInt iVector = 0; iVector < data_dim; iVector++) { + if (index_collection.mask_[iVector]) { + new_index[iVector] = num_sub_vector; + num_sub_vector++; + } else { + new_index[iVector] = -1; + } + } + } + + // Bail out if no vectors are to be extracted + if (num_sub_vector == 0) return; + + for (HighsInt iVector = 0; iVector < data_dim; iVector++) { + HighsInt new_iVector = new_index[iVector]; + if (new_iVector >= 0) { + assert(new_iVector < num_sub_vector); + if (sub_vector_data0 != NULL) + sub_vector_data0[new_iVector] = data0[iVector]; + if (sub_vector_data1 != NULL) + sub_vector_data1[new_iVector] = data1[iVector]; + if (sub_vector_data2 != NULL) + sub_vector_data2[new_iVector] = data2[iVector]; + } + } + const bool extract_start = sub_matrix_start != NULL; + const bool extract_index = sub_matrix_index != NULL; + const bool extract_value = sub_matrix_value != NULL; + const bool extract_matrix = extract_index || extract_value; + // Allocate an array of lengths for the sub-matrix to be + // extracted: necessary even if just the number of nonzeros is + // required + vector sub_matrix_length; + sub_matrix_length.assign(num_sub_vector, 0); + // Identify the lengths of the vectors in the sub-matrix to be extracted + HighsInt num_vector = matrix.start_.size() - 1; + for (HighsInt vector = 0; vector < num_vector; vector++) { + for (HighsInt iEl = matrix.start_[vector]; iEl < matrix.start_[vector + 1]; + iEl++) { + HighsInt iVector = matrix.index_[iEl]; + HighsInt new_iVector = new_index[iVector]; + if (new_iVector >= 0) sub_matrix_length[new_iVector]++; + } + } + if (!extract_start) { + // bail out if no matrix starts are to be extracted, but only after + // computing the number of nonzeros + for (HighsInt iVector = 0; iVector < num_sub_vector; iVector++) + sub_matrix_num_nz += sub_matrix_length[iVector]; + return; + } + // Allocate an array of lengths for the sub-matrix to be extracted + sub_matrix_start[0] = 0; + for (HighsInt iVector = 0; iVector < num_sub_vector - 1; iVector++) { + sub_matrix_start[iVector + 1] = + sub_matrix_start[iVector] + sub_matrix_length[iVector]; + sub_matrix_length[iVector] = sub_matrix_start[iVector]; + } + HighsInt iVector = num_sub_vector - 1; + sub_matrix_num_nz = sub_matrix_start[iVector] + sub_matrix_length[iVector]; + // Bail out if matrix indices and values are not required + if (!extract_matrix) return; + sub_matrix_length[iVector] = sub_matrix_start[iVector]; + // Fill the row-wise matrix with indices and values + for (HighsInt vector = 0; vector < num_vector; vector++) { + for (HighsInt iEl = matrix.start_[vector]; iEl < matrix.start_[vector + 1]; + iEl++) { + HighsInt iVector = matrix.index_[iEl]; + HighsInt new_iVector = new_index[iVector]; + if (new_iVector >= 0) { + HighsInt row_iEl = sub_matrix_length[new_iVector]; + if (extract_index) sub_matrix_index[row_iEl] = vector; + if (extract_value) sub_matrix_value[row_iEl] = matrix.value_[iEl]; + sub_matrix_length[new_iVector]++; + } + } + } +} diff --git a/src/lp_data/HighsLpUtils.h b/src/lp_data/HighsLpUtils.h index c6cff7a8bb..867e92c12c 100644 --- a/src/lp_data/HighsLpUtils.h +++ b/src/lp_data/HighsLpUtils.h @@ -263,4 +263,36 @@ HighsLp withoutSemiVariables(const HighsLp& lp, HighsSolution& solution, void removeRowsOfCountOne(const HighsLogOptions& log_options, HighsLp& lp); +// Get subvectors from data structure of data0, data1, data2 and +// matrix, where the storage of the matrix is compatible with the +// vectors to be extracted from it +// +// Data to be extracted is given by sub_* being nullpointer +// +// * cost, lower and upper bounds for columns, and column-wise LP constraint +// matrix +// +// * lower and upper bounds for rows, and row-wise LP constraint +// * matrix. "cost" is nullptr, and so must be sub_vector_data0 +// +void getSubVectors(const HighsIndexCollection& index_collection, + const HighsInt data_dim, const double* data0, + const double* data1, const double* data2, + const HighsSparseMatrix& matrix, HighsInt& num_sub_vector, + double* sub_vector_data0, double* sub_vector_data1, + double* sub_vector_data2, HighsInt& sub_matrix_num_nz, + HighsInt* sub_matrix_start, HighsInt* sub_matrix_index, + double* sub_matrix_value); + +void getSubVectorsTranspose(const HighsIndexCollection& index_collection, + const HighsInt data_dim, const double* data0, + const double* data1, const double* data2, + const HighsSparseMatrix& matrix, + HighsInt& num_sub_vector, double* sub_vector_data0, + double* sub_vector_data1, double* sub_vector_data2, + HighsInt& sub_matrix_num_nz, + HighsInt* sub_matrix_start, + HighsInt* sub_matrix_index, + double* sub_matrix_value); + #endif // LP_DATA_HIGHSLPUTILS_H_ diff --git a/src/lp_data/HighsOptions.cpp b/src/lp_data/HighsOptions.cpp index 29ddd37629..13ec2abdcb 100644 --- a/src/lp_data/HighsOptions.cpp +++ b/src/lp_data/HighsOptions.cpp @@ -94,10 +94,11 @@ bool commandLineSolverOk(const HighsLogOptions& report_log_options, bool boolFromString(std::string value, bool& bool_value) { std::transform(value.begin(), value.end(), value.begin(), [](unsigned char c) { return std::tolower(c); }); - if (value == "t" || value == "true" || value == "1" || value == "on") { + if (value == "t" || value == "true" || value == "1" || + value == kHighsOnString) { bool_value = true; } else if (value == "f" || value == "false" || value == "0" || - value == "off") { + value == kHighsOffString) { bool_value = false; } else { return false; @@ -811,15 +812,17 @@ void resetLocalOptions(std::vector& option_records) { } } -HighsStatus writeOptionsToFile(FILE* file, +HighsStatus writeOptionsToFile(FILE* file, const HighsLogOptions& log_options, const std::vector& option_records, const bool report_only_deviations, const HighsFileType file_type) { - reportOptions(file, option_records, report_only_deviations, file_type); + reportOptions(file, log_options, option_records, report_only_deviations, + file_type); return HighsStatus::kOk; } -void reportOptions(FILE* file, const std::vector& option_records, +void reportOptions(FILE* file, const HighsLogOptions& log_options, + const std::vector& option_records, const bool report_only_deviations, const HighsFileType file_type) { HighsInt num_options = option_records.size(); @@ -831,22 +834,27 @@ void reportOptions(FILE* file, const std::vector& option_records, if (!kAdvancedInDocumentation) continue; } if (type == HighsOptionType::kBool) { - reportOption(file, ((OptionRecordBool*)option_records[index])[0], + reportOption(file, log_options, + ((OptionRecordBool*)option_records[index])[0], report_only_deviations, file_type); } else if (type == HighsOptionType::kInt) { - reportOption(file, ((OptionRecordInt*)option_records[index])[0], + reportOption(file, log_options, + ((OptionRecordInt*)option_records[index])[0], report_only_deviations, file_type); } else if (type == HighsOptionType::kDouble) { - reportOption(file, ((OptionRecordDouble*)option_records[index])[0], + reportOption(file, log_options, + ((OptionRecordDouble*)option_records[index])[0], report_only_deviations, file_type); } else { - reportOption(file, ((OptionRecordString*)option_records[index])[0], + reportOption(file, log_options, + ((OptionRecordString*)option_records[index])[0], report_only_deviations, file_type); } } } -void reportOption(FILE* file, const OptionRecordBool& option, +void reportOption(FILE* file, const HighsLogOptions& log_options, + const OptionRecordBool& option, const bool report_only_deviations, const HighsFileType file_type) { if (!report_only_deviations || option.default_value != *option.value) { @@ -865,40 +873,53 @@ void reportOption(FILE* file, const OptionRecordBool& option, fprintf(file, "%s = %s\n", option.name.c_str(), highsBoolToString(*option.value).c_str()); } else { - fprintf(file, "%s = %s\n", option.name.c_str(), - highsBoolToString(*option.value).c_str()); + std::string line = + highsFormatToString("Set option %s to %s\n", option.name.c_str(), + highsBoolToString(*option.value).c_str()); + if (file == stdout) { + highsLogUser(log_options, HighsLogType::kInfo, "%s", line.c_str()); + } else { + fprintf(file, "%s", line.c_str()); + } } } } -void reportOption(FILE* file, const OptionRecordInt& option, +void reportOption(FILE* file, const HighsLogOptions& log_options, + const OptionRecordInt& option, const bool report_only_deviations, const HighsFileType file_type) { if (!report_only_deviations || option.default_value != *option.value) { if (file_type == HighsFileType::kMd) { - fprintf(file, - "## %s\n- %s\n- Type: integer\n- Range: {%" HIGHSINT_FORMAT - ", %" HIGHSINT_FORMAT "}\n- Default: %" HIGHSINT_FORMAT "\n\n", - highsInsertMdEscapes(option.name).c_str(), - highsInsertMdEscapes(option.description).c_str(), - option.lower_bound, option.upper_bound, option.default_value); + fprintf( + file, + "## %s\n- %s\n- Type: integer\n- Range: {%d, %d}\n- Default: %d\n\n", + highsInsertMdEscapes(option.name).c_str(), + highsInsertMdEscapes(option.description).c_str(), + int(option.lower_bound), int(option.upper_bound), + int(option.default_value)); } else if (file_type == HighsFileType::kFull) { fprintf(file, "\n# %s\n", option.description.c_str()); fprintf(file, "# [type: integer, advanced: %s, range: {%" HIGHSINT_FORMAT - ", %" HIGHSINT_FORMAT "}, default: %" HIGHSINT_FORMAT "]\n", + ", %d}, default: %d]\n", highsBoolToString(option.advanced).c_str(), option.lower_bound, - option.upper_bound, option.default_value); - fprintf(file, "%s = %" HIGHSINT_FORMAT "\n", option.name.c_str(), - *option.value); + int(option.upper_bound), int(option.default_value)); + fprintf(file, "%s = %d\n", option.name.c_str(), int(*option.value)); } else { - fprintf(file, "%s = %" HIGHSINT_FORMAT "\n", option.name.c_str(), - *option.value); + std::string line = highsFormatToString( + "Set option %s to %d\n", option.name.c_str(), int(*option.value)); + if (file == stdout) { + highsLogUser(log_options, HighsLogType::kInfo, "%s", line.c_str()); + } else { + fprintf(file, "%s", line.c_str()); + } } } } -void reportOption(FILE* file, const OptionRecordDouble& option, +void reportOption(FILE* file, const HighsLogOptions& log_options, + const OptionRecordDouble& option, const bool report_only_deviations, const HighsFileType file_type) { if (!report_only_deviations || option.default_value != *option.value) { @@ -917,12 +938,19 @@ void reportOption(FILE* file, const OptionRecordDouble& option, option.upper_bound, option.default_value); fprintf(file, "%s = %g\n", option.name.c_str(), *option.value); } else { - fprintf(file, "%s = %g\n", option.name.c_str(), *option.value); + std::string line = highsFormatToString( + "Set option %s to %g\n", option.name.c_str(), *option.value); + if (file == stdout) { + highsLogUser(log_options, HighsLogType::kInfo, "%s", line.c_str()); + } else { + fprintf(file, "%s", line.c_str()); + } } } } -void reportOption(FILE* file, const OptionRecordString& option, +void reportOption(FILE* file, const HighsLogOptions& log_options, + const OptionRecordString& option, const bool report_only_deviations, const HighsFileType file_type) { // Don't report for the options file if writing to an options file @@ -943,7 +971,14 @@ void reportOption(FILE* file, const OptionRecordString& option, option.default_value.c_str()); fprintf(file, "%s = %s\n", option.name.c_str(), (*option.value).c_str()); } else { - fprintf(file, "%s = %s\n", option.name.c_str(), (*option.value).c_str()); + std::string line = + highsFormatToString("Set option %s to \"%s\"\n", option.name.c_str(), + (*option.value).c_str()); + if (file == stdout) { + highsLogUser(log_options, HighsLogType::kInfo, "%s", line.c_str()); + } else { + fprintf(file, "%s", line.c_str()); + } } } } diff --git a/src/lp_data/HighsOptions.h b/src/lp_data/HighsOptions.h index eb315b8bcd..2ec5de3cec 100644 --- a/src/lp_data/HighsOptions.h +++ b/src/lp_data/HighsOptions.h @@ -233,22 +233,28 @@ OptionStatus getLocalOptionType( void resetLocalOptions(std::vector& option_records); HighsStatus writeOptionsToFile( - FILE* file, const std::vector& option_records, + FILE* file, const HighsLogOptions& report_log_options, + const std::vector& option_records, const bool report_only_deviations = false, const HighsFileType file_type = HighsFileType::kFull); -void reportOptions(FILE* file, const std::vector& option_records, +void reportOptions(FILE* file, const HighsLogOptions& report_log_options, + const std::vector& option_records, const bool report_only_deviations = false, const HighsFileType file_type = HighsFileType::kFull); -void reportOption(FILE* file, const OptionRecordBool& option, +void reportOption(FILE* file, const HighsLogOptions& report_log_options, + const OptionRecordBool& option, const bool report_only_deviations, const HighsFileType file_type); -void reportOption(FILE* file, const OptionRecordInt& option, +void reportOption(FILE* file, const HighsLogOptions& report_log_options, + const OptionRecordInt& option, const bool report_only_deviations, const HighsFileType file_type); -void reportOption(FILE* file, const OptionRecordDouble& option, +void reportOption(FILE* file, const HighsLogOptions& report_log_options, + const OptionRecordDouble& option, const bool report_only_deviations, const HighsFileType file_type); -void reportOption(FILE* file, const OptionRecordString& option, +void reportOption(FILE* file, const HighsLogOptions& report_log_options, + const OptionRecordString& option, const bool report_only_deviations, const HighsFileType file_type); @@ -299,6 +305,8 @@ struct HighsOptionsStruct { double primal_feasibility_tolerance; double dual_feasibility_tolerance; double ipm_optimality_tolerance; + double primal_residual_tolerance; + double dual_residual_tolerance; double objective_bound; double objective_target; HighsInt threads; @@ -327,6 +335,7 @@ struct HighsOptionsStruct { // Control of HiGHS log bool output_flag; bool log_to_console; + bool timeless_log; // Options for IPM solver HighsInt ipm_iteration_limit; @@ -390,8 +399,6 @@ struct HighsOptionsStruct { bool less_infeasible_DSE_choose_row; bool use_original_HFactor_logic; bool run_centring; - double primal_residual_tolerance; - double dual_residual_tolerance; HighsInt max_centring_steps; double centring_ratio_tolerance; @@ -430,6 +437,7 @@ struct HighsOptionsStruct { bool mip_improving_solution_save; bool mip_improving_solution_report_sparse; std::string mip_improving_solution_file; + bool mip_root_presolve_only; // Logging callback identifiers HighsLogOptions log_options; @@ -452,6 +460,8 @@ struct HighsOptionsStruct { primal_feasibility_tolerance(0.0), dual_feasibility_tolerance(0.0), ipm_optimality_tolerance(0.0), + primal_residual_tolerance(0.0), + dual_residual_tolerance(0.0), objective_bound(0.0), objective_target(0.0), threads(0), @@ -477,6 +487,7 @@ struct HighsOptionsStruct { write_presolved_model_file(""), output_flag(false), log_to_console(false), + timeless_log(false), ipm_iteration_limit(0), pdlp_native_termination(false), pdlp_scaling(false), @@ -528,8 +539,6 @@ struct HighsOptionsStruct { less_infeasible_DSE_choose_row(false), use_original_HFactor_logic(false), run_centring(false), - primal_residual_tolerance(0.0), - dual_residual_tolerance(0.0), max_centring_steps(0), centring_ratio_tolerance(0.0), icrash(false), @@ -564,7 +573,8 @@ struct HighsOptionsStruct { mip_improving_solution_save(false), mip_improving_solution_report_sparse(false), // clang-format off - mip_improving_solution_file("") {}; + mip_improving_solution_file(""), + mip_root_presolve_only(false) {}; // clang-format on }; @@ -707,6 +717,16 @@ class HighsOptions : public HighsOptionsStruct { &ipm_optimality_tolerance, 1e-12, 1e-8, kHighsInf); records.push_back(record_double); + record_double = new OptionRecordDouble( + "primal_residual_tolerance", "Primal residual tolerance", advanced, + &primal_residual_tolerance, 1e-10, 1e-7, kHighsInf); + records.push_back(record_double); + + record_double = new OptionRecordDouble( + "dual_residual_tolerance", "Dual residual tolerance", advanced, + &dual_residual_tolerance, 1e-10, 1e-7, kHighsInf); + records.push_back(record_double); + record_double = new OptionRecordDouble( "objective_bound", "Objective bound for termination of the dual simplex solver", advanced, @@ -755,7 +775,7 @@ class HighsOptions : public HighsOptionsStruct { record_int = new OptionRecordInt( "simplex_strategy", "Strategy for simplex solver 0 => Choose; 1 => Dual (serial); 2 => " - "Dual (PAMI); 3 => Dual (SIP); 4 => Primal", + "Dual (SIP); 3 => Dual (PAMI); 4 => Primal", advanced, &simplex_strategy, kSimplexStrategyMin, kSimplexStrategyDual, kSimplexStrategyMax); records.push_back(record_int); @@ -831,6 +851,11 @@ class HighsOptions : public HighsOptionsStruct { advanced, &log_to_console, true); records.push_back(record_bool); + record_bool = new OptionRecordBool( + "timeless_log", "Suppression of time-based data in logging", true, + &timeless_log, false); + records.push_back(record_bool); + record_string = new OptionRecordString(kSolutionFileString, "Solution file", advanced, &solution_file, kHighsFilenameDefault); @@ -980,6 +1005,12 @@ class HighsOptions : public HighsOptionsStruct { advanced, &mip_improving_solution_file, kHighsFilenameDefault); records.push_back(record_string); + record_bool = new OptionRecordBool( + "mip_root_presolve_only", + "Whether MIP presolve is only applied at the root node", advanced, + &mip_root_presolve_only, false); + records.push_back(record_bool); + record_int = new OptionRecordInt( "mip_max_leaves", "MIP solver max number of leaf nodes", advanced, &mip_max_leaves, 0, kHighsIInf, kHighsIInf); @@ -1134,11 +1165,12 @@ class HighsOptions : public HighsOptionsStruct { // Advanced options advanced = true; - record_int = new OptionRecordInt( - "log_dev_level", - "Output development messages: 0 => none; 1 => info; 2 => verbose", - advanced, &log_dev_level, kHighsLogDevLevelMin, kHighsLogDevLevelNone, - kHighsLogDevLevelMax); + record_int = + new OptionRecordInt("log_dev_level", + "Output development messages: 0 => none; 1 => " + "info; 2 => detailed; 3 => verbose", + advanced, &log_dev_level, kHighsLogDevLevelMin, + kHighsLogDevLevelNone, kHighsLogDevLevelMax); records.push_back(record_int); record_bool = new OptionRecordBool("log_githash", "Log the githash", @@ -1399,16 +1431,6 @@ class HighsOptions : public HighsOptionsStruct { advanced, ¢ring_ratio_tolerance, 0, 100, kHighsInf); records.push_back(record_double); - record_double = new OptionRecordDouble( - "primal_residual_tolerance", "Primal residual tolerance", advanced, - &primal_residual_tolerance, 1e-10, 1e-7, kHighsInf); - records.push_back(record_double); - - record_double = new OptionRecordDouble( - "dual_residual_tolerance", "Dual residual tolerance", advanced, - &dual_residual_tolerance, 1e-10, 1e-7, kHighsInf); - records.push_back(record_double); - // Set up the log_options aliases log_options.clear(); log_options.log_stream = diff --git a/src/lp_data/HighsSolution.cpp b/src/lp_data/HighsSolution.cpp index 5375a3b6b9..a28060861a 100644 --- a/src/lp_data/HighsSolution.cpp +++ b/src/lp_data/HighsSolution.cpp @@ -677,7 +677,7 @@ double computeObjectiveValue(const HighsLp& lp, const HighsSolution& solution) { // and any solution values void refineBasis(const HighsLp& lp, const HighsSolution& solution, HighsBasis& basis) { - assert(basis.valid); + assert(basis.useful); assert(isBasisRightSize(lp, basis)); const bool have_highs_solution = solution.value_valid; @@ -1319,6 +1319,7 @@ HighsStatus ipxBasicSolutionToHighsBasicSolution( highs_solution.value_valid = true; highs_solution.dual_valid = true; highs_basis.valid = true; + highs_basis.useful = true; return HighsStatus::kOk; } @@ -1356,9 +1357,14 @@ HighsStatus formSimplexLpBasisAndFactor(HighsLpSolverObject& solver_object, // If new scaling is performed, the hot start information is // no longer valid if (new_scaling) ekk_instance.clearHotStart(); - if (basis.alien) { - // An alien basis needs to be checked for rank deficiency, and - // possibly completed if it is rectangular + const bool check_basis = basis.alien || (!basis.valid && basis.useful); + if (check_basis) { + // The basis needs to be checked for rank deficiency, and possibly + // completed if it is rectangular + // + // If it's not valid but useful, but not alien, + // accommodateAlienBasis will assert, so make the basis alien + basis.alien = true; assert(!only_from_known_basis); accommodateAlienBasis(solver_object); basis.alien = false; @@ -1605,9 +1611,32 @@ void HighsSolution::clear() { void HighsObjectiveSolution::clear() { this->col_value.clear(); } +void HighsBasis::print(std::string message) const { + if (!this->useful) return; + this->printScalars(message); + for (HighsInt iCol = 0; iCol < HighsInt(this->col_status.size()); iCol++) + printf("Basis: col_status[%2d] = %d\n", int(iCol), + int(this->col_status[iCol])); + for (HighsInt iRow = 0; iRow < HighsInt(this->row_status.size()); iRow++) + printf("Basis: row_status[%2d] = %d\n", int(iRow), + int(this->row_status[iRow])); +} + +void HighsBasis::printScalars(std::string message) const { + printf("\nBasis: %s\n", message.c_str()); + printf(" valid = %d\n", this->valid); + printf(" alien = %d\n", this->alien); + printf(" useful = %d\n", this->useful); + printf(" was_alien = %d\n", this->was_alien); + printf(" debug_id = %d\n", int(this->debug_id)); + printf(" debug_update_count = %d\n", int(this->debug_update_count)); + printf(" debug_origin_name = %s\n", this->debug_origin_name.c_str()); +} + void HighsBasis::invalidate() { this->valid = false; this->alien = true; + this->useful = false; this->was_alien = true; this->debug_id = -1; this->debug_update_count = -1; diff --git a/src/lp_data/HighsSolve.cpp b/src/lp_data/HighsSolve.cpp index 1062b35e5f..ef6dd14237 100644 --- a/src/lp_data/HighsSolve.cpp +++ b/src/lp_data/HighsSolve.cpp @@ -107,7 +107,8 @@ HighsStatus solveLp(HighsLpSolverObject& solver_object, const string message) { utilModelStatusToString(solver_object.model_status_).c_str(), solver_object.basis_.valid ? "" : "not ", solver_object.solution_.value_valid ? "" : "not ", - options.run_centring ? "off" : options.run_crossover.c_str()); + options.run_centring ? kHighsOffString.c_str() + : options.run_crossover.c_str()); const bool allow_simplex_cleanup = options.run_crossover != kHighsOffString && !options.run_centring; if (allow_simplex_cleanup) { @@ -390,6 +391,7 @@ HighsStatus solveUnconstrainedLp(const HighsOptions& options, const HighsLp& lp, solution.value_valid = true; solution.dual_valid = true; basis.valid = true; + basis.useful = true; highs_info.basis_validity = kBasisValidityValid; setSolutionStatus(highs_info); if (highs_info.num_primal_infeasibilities) { diff --git a/src/mip/HighsCutGeneration.cpp b/src/mip/HighsCutGeneration.cpp index cefb63fc88..d9552d418f 100644 --- a/src/mip/HighsCutGeneration.cpp +++ b/src/mip/HighsCutGeneration.cpp @@ -215,6 +215,10 @@ void HighsCutGeneration::separateLiftedKnapsackCover() { } bool HighsCutGeneration::separateLiftedMixedBinaryCover() { + // initialize indicators + integralSupport = false; + integralCoefficients = false; + HighsInt coversize = cover.size(); std::vector S; S.resize(coversize); @@ -275,6 +279,10 @@ bool HighsCutGeneration::separateLiftedMixedBinaryCover() { } bool HighsCutGeneration::separateLiftedMixedIntegerCover() { + // initialize indicators + integralSupport = false; + integralCoefficients = false; + HighsInt coversize = cover.size(); HighsInt l = -1; @@ -501,6 +509,10 @@ bool HighsCutGeneration::cmirCutGenerationHeuristic(double minEfficacy, using std::max; using std::sqrt; + // initialize indicators + integralSupport = false; + integralCoefficients = false; + double continuouscontribution = 0.0; double continuoussqrnorm = 0.0; @@ -1376,6 +1388,8 @@ bool HighsCutGeneration::tryGenerateCut(std::vector& inds_, // the lifting functions have minimality of the cover as necessary facet // condition bool success = false; + bool saveIntegalSupport = false; + bool saveIntegralCoefficients = false; do { if (!determineCover(lpSol)) break; @@ -1397,6 +1411,11 @@ bool HighsCutGeneration::tryGenerateCut(std::vector& inds_, double minMirEfficacy = minEfficacy; if (success) { + // save data that might otherwise be overwritten when calling the cmir + // separator + saveIntegalSupport = integralSupport; + saveIntegralCoefficients = integralCoefficients; + // compute violation and squared norm double violation = -double(rhs); double sqrnorm = 0.0; @@ -1422,11 +1441,6 @@ bool HighsCutGeneration::tryGenerateCut(std::vector& inds_, inds = tmpInds.data(); vals = tmpVals.data(); - // save data that might otherwise be overwritten when calling the cmir - // separator - bool saveIntegalSupport = integralSupport; - bool saveIntegralCoefficients = integralCoefficients; - if (cmirCutGenerationHeuristic(minMirEfficacy, onlyInitialCMIRScale)) { // take the cmir cut as it is better inds_.swap(tmpInds); diff --git a/src/mip/HighsImplications.cpp b/src/mip/HighsImplications.cpp index a40ac8dddd..7e1c1d62bc 100644 --- a/src/mip/HighsImplications.cpp +++ b/src/mip/HighsImplications.cpp @@ -697,42 +697,11 @@ void HighsImplications::cleanupVarbounds(HighsInt col) { std::vector delVbds; vubs[col].for_each([&](HighsInt vubCol, VarBound& vub) { - mipsolver.mipdata_->debugSolution.checkVub(col, vubCol, vub.coef, - vub.constant); - - if (vub.coef > 0) { - double minub = vub.constant; - double maxub = vub.constant + vub.coef; - if (minub >= ub - mipsolver.mipdata_->feastol) - delVbds.push_back(vubCol); // variable bound is redundant - else if (maxub > ub + mipsolver.mipdata_->epsilon) { - vub.coef = ub - vub.constant; // coefficient can be tightened - mipsolver.mipdata_->debugSolution.checkVub(col, vubCol, vub.coef, - vub.constant); - } else if (maxub < ub - mipsolver.mipdata_->epsilon) { - mipsolver.mipdata_->domain.changeBound( - HighsBoundType::kUpper, col, maxub, - HighsDomain::Reason::unspecified()); - if (mipsolver.mipdata_->domain.infeasible()) return; - } - } else { - HighsCDouble minub = HighsCDouble(vub.constant) + vub.coef; - double maxub = vub.constant; - if (minub >= ub - mipsolver.mipdata_->feastol) - delVbds.push_back(vubCol); // variable bound is redundant - else if (maxub > ub + mipsolver.mipdata_->epsilon) { - // variable bound can be tightened - vub.constant = ub; - vub.coef = double(minub - ub); - mipsolver.mipdata_->debugSolution.checkVub(col, vubCol, vub.coef, - vub.constant); - } else if (maxub < ub - mipsolver.mipdata_->epsilon) { - mipsolver.mipdata_->domain.changeBound( - HighsBoundType::kUpper, col, maxub, - HighsDomain::Reason::unspecified()); - if (mipsolver.mipdata_->domain.infeasible()) return; - } - } + bool redundant = false; + bool infeasible = false; + cleanupVub(col, vubCol, vub, ub, redundant, infeasible); + if (redundant) delVbds.push_back(vubCol); + if (infeasible) return; }); if (!delVbds.empty()) { @@ -741,44 +710,94 @@ void HighsImplications::cleanupVarbounds(HighsInt col) { } vlbs[col].for_each([&](HighsInt vlbCol, VarBound& vlb) { - mipsolver.mipdata_->debugSolution.checkVlb(col, vlbCol, vlb.coef, - vlb.constant); + bool redundant = false; + bool infeasible = false; + cleanupVlb(col, vlbCol, vlb, lb, redundant, infeasible); + if (redundant) delVbds.push_back(vlbCol); + if (infeasible) return; + }); - if (vlb.coef > 0) { - HighsCDouble maxlb = HighsCDouble(vlb.constant) + vlb.coef; - double minlb = vlb.constant; - if (maxlb <= lb + mipsolver.mipdata_->feastol) - delVbds.push_back(vlbCol); // variable bound is redundant - else if (minlb < lb - mipsolver.mipdata_->epsilon) { - // variable bound can be tightened - vlb.constant = lb; - vlb.coef = double(maxlb - lb); - mipsolver.mipdata_->debugSolution.checkVlb(col, vlbCol, vlb.coef, - vlb.constant); - } else if (minlb > lb + mipsolver.mipdata_->epsilon) { - mipsolver.mipdata_->domain.changeBound( - HighsBoundType::kLower, col, minlb, - HighsDomain::Reason::unspecified()); - if (mipsolver.mipdata_->domain.infeasible()) return; - } + for (HighsInt vlbCol : delVbds) vlbs[col].erase(vlbCol); +} +void HighsImplications::cleanupVlb(HighsInt col, HighsInt vlbCol, + HighsImplications::VarBound& vlb, double lb, + bool& redundant, bool& infeasible, + bool allowBoundChanges) const { + // initialize + redundant = false; + infeasible = false; + + // return if there is no variable bound + if (vlbCol == -1) return; + + // check variable lower bound + mipsolver.mipdata_->debugSolution.checkVlb(col, vlbCol, vlb.coef, + vlb.constant); + + HighsCDouble maxlb = vlb.maxValue(); + HighsCDouble minlb = vlb.minValue(); + + if (maxlb <= lb + mipsolver.mipdata_->feastol) { + // variable bound is redundant + redundant = true; + } else if (minlb < lb - mipsolver.mipdata_->epsilon) { + // coefficient can be tightened + double newcoef = static_cast(lb - maxlb); + if (vlb.coef < 0) { + vlb.coef = newcoef; } else { - double maxlb = vlb.constant; - double minlb = vlb.constant + vlb.coef; - if (maxlb <= lb + mipsolver.mipdata_->feastol) - delVbds.push_back(vlbCol); // variable bound is redundant - else if (minlb < lb - mipsolver.mipdata_->epsilon) { - vlb.coef = lb - vlb.constant; // variable bound can be tightened - mipsolver.mipdata_->debugSolution.checkVlb(col, vlbCol, vlb.coef, - vlb.constant); - } else if (minlb > lb + mipsolver.mipdata_->epsilon) { - mipsolver.mipdata_->domain.changeBound( - HighsBoundType::kLower, col, minlb, - HighsDomain::Reason::unspecified()); - if (mipsolver.mipdata_->domain.infeasible()) return; - } + vlb.constant = lb; + vlb.coef = -newcoef; } - }); + // check tightened variable lower bound + mipsolver.mipdata_->debugSolution.checkVlb(col, vlbCol, vlb.coef, + vlb.constant); + } else if (allowBoundChanges && minlb > lb + mipsolver.mipdata_->epsilon) { + mipsolver.mipdata_->domain.changeBound(HighsBoundType::kLower, col, + static_cast(minlb), + HighsDomain::Reason::unspecified()); + infeasible = mipsolver.mipdata_->domain.infeasible(); + } +} - for (HighsInt vlbCol : delVbds) vlbs[col].erase(vlbCol); +void HighsImplications::cleanupVub(HighsInt col, HighsInt vubCol, + HighsImplications::VarBound& vub, double ub, + bool& redundant, bool& infeasible, + bool allowBoundChanges) const { + // initialize + redundant = false; + infeasible = false; + + // return if there is no variable bound + if (vubCol == -1) return; + + // check variable upper bound + mipsolver.mipdata_->debugSolution.checkVub(col, vubCol, vub.coef, + vub.constant); + + HighsCDouble maxub = vub.maxValue(); + HighsCDouble minub = vub.minValue(); + + if (minub >= ub - mipsolver.mipdata_->feastol) { + // variable bound is redundant + redundant = true; + } else if (maxub > ub + mipsolver.mipdata_->epsilon) { + // coefficient can be tightened + double newcoef = static_cast(ub - minub); + if (vub.coef > 0) { + vub.coef = newcoef; + } else { + vub.constant = ub; + vub.coef = -newcoef; + } + // check tightened variable upper bound + mipsolver.mipdata_->debugSolution.checkVub(col, vubCol, vub.coef, + vub.constant); + } else if (allowBoundChanges && maxub < ub - mipsolver.mipdata_->epsilon) { + mipsolver.mipdata_->domain.changeBound(HighsBoundType::kUpper, col, + static_cast(maxub), + HighsDomain::Reason::unspecified()); + infeasible = mipsolver.mipdata_->domain.infeasible(); + } } diff --git a/src/mip/HighsImplications.h b/src/mip/HighsImplications.h index 3fc3e61de3..9761b339c8 100644 --- a/src/mip/HighsImplications.h +++ b/src/mip/HighsImplications.h @@ -37,8 +37,14 @@ class HighsImplications { double coef; double constant; - double minValue() const { return constant + std::min(coef, 0.0); } - double maxValue() const { return constant + std::max(coef, 0.0); } + double minValue() const { + return static_cast(static_cast(constant) + + std::min(coef, 0.0)); + } + double maxValue() const { + return static_cast(static_cast(constant) + + std::max(coef, 0.0)); + } }; private: @@ -148,6 +154,14 @@ class HighsImplications { HighsCutPool& cutpool, double feastol); void cleanupVarbounds(HighsInt col); + + void cleanupVlb(HighsInt col, HighsInt vlbCol, + HighsImplications::VarBound& vlb, double lb, bool& redundant, + bool& infeasible, bool allowBoundChanges = true) const; + + void cleanupVub(HighsInt col, HighsInt vubCol, + HighsImplications::VarBound& vub, double ub, bool& redundant, + bool& infeasible, bool allowBoundChanges = true) const; }; #endif diff --git a/src/mip/HighsLpRelaxation.cpp b/src/mip/HighsLpRelaxation.cpp index 926a9616f8..76cc06f4f1 100644 --- a/src/mip/HighsLpRelaxation.cpp +++ b/src/mip/HighsLpRelaxation.cpp @@ -1043,9 +1043,9 @@ void HighsLpRelaxation::setObjectiveLimit(double objlim) { } HighsLpRelaxation::Status HighsLpRelaxation::run(bool resolve_on_error) { - lpsolver.setOptionValue( - "time_limit", lpsolver.getRunTime() + mipsolver.options_mip_->time_limit - - mipsolver.timer_.read(mipsolver.timer_.total_clock)); + lpsolver.setOptionValue("time_limit", lpsolver.getRunTime() + + mipsolver.options_mip_->time_limit - + mipsolver.timer_.read()); // lpsolver.setOptionValue("output_flag", true); const bool valid_basis = lpsolver.getBasis().valid; const HighsInt simplex_solve_clock = valid_basis @@ -1207,6 +1207,9 @@ HighsLpRelaxation::Status HighsLpRelaxation::run(bool resolve_on_error) { ipm.setOptionValue("output_flag", false); ipm.setOptionValue("solver", "ipm"); ipm.setOptionValue("ipm_iteration_limit", 200); + // check if only root presolve is allowed + if (mipsolver.options_mip_->mip_root_presolve_only) + ipm.setOptionValue("presolve", kHighsOffString); ipm.passModel(lpsolver.getLp()); // todo @ Julian : If you remove this you can see the looping on // istanbul-no-cutoff diff --git a/src/mip/HighsMipAnalysis.cpp b/src/mip/HighsMipAnalysis.cpp index cdd773960c..7a6ea2d486 100644 --- a/src/mip/HighsMipAnalysis.cpp +++ b/src/mip/HighsMipAnalysis.cpp @@ -13,6 +13,7 @@ #include #include "mip/MipTimer.h" +#include "util/HighsUtils.h" const HighsInt check_mip_clock = -4; @@ -153,4 +154,8 @@ void HighsMipAnalysis::reportMipTimer() { reportMipSolveLpClock(true); mip_timer.csvMipClock(this->model_name, mip_clocks, false, false); reportMipSolveLpClock(false); + analyseVectorValues(nullptr, "Node search time", + HighsInt(node_search_time.size()), node_search_time); + analyseVectorValues(nullptr, "Dive time", HighsInt(dive_time.size()), + dive_time); } diff --git a/src/mip/HighsMipAnalysis.h b/src/mip/HighsMipAnalysis.h index 9b6a098dc7..20ab0bd4d0 100644 --- a/src/mip/HighsMipAnalysis.h +++ b/src/mip/HighsMipAnalysis.h @@ -42,6 +42,8 @@ class HighsMipAnalysis { std::string model_name; HighsTimerClock mip_clocks; bool analyse_mip_time; + std::vector dive_time; + std::vector node_search_time; }; #endif /* MIP_HIGHSMIPANALYSIS_H_ */ diff --git a/src/mip/HighsMipSolver.cpp b/src/mip/HighsMipSolver.cpp index 4830bd932d..cb88c8e5d5 100644 --- a/src/mip/HighsMipSolver.cpp +++ b/src/mip/HighsMipSolver.cpp @@ -53,51 +53,13 @@ HighsMipSolver::HighsMipSolver(HighsCallback& callback, integral, feasible); assert(valid); #endif - bound_violation_ = 0; - row_violation_ = 0; - integrality_violation_ = 0; - - HighsCDouble obj = orig_model_->offset_; - assert((HighsInt)solution.col_value.size() == orig_model_->num_col_); - for (HighsInt i = 0; i != orig_model_->num_col_; ++i) { - const double value = solution.col_value[i]; - obj += orig_model_->col_cost_[i] * value; - - if (orig_model_->integrality_[i] == HighsVarType::kInteger) { - integrality_violation_ = - std::max(fractionality(value), integrality_violation_); - } - - const double lower = orig_model_->col_lower_[i]; - const double upper = orig_model_->col_upper_[i]; - double primal_infeasibility; - if (value < lower - options_mip_->mip_feasibility_tolerance) { - primal_infeasibility = lower - value; - } else if (value > upper + options_mip_->mip_feasibility_tolerance) { - primal_infeasibility = value - upper; - } else - continue; - - bound_violation_ = std::max(bound_violation_, primal_infeasibility); - } - - for (HighsInt i = 0; i != orig_model_->num_row_; ++i) { - const double value = solution.row_value[i]; - const double lower = orig_model_->row_lower_[i]; - const double upper = orig_model_->row_upper_[i]; - - double primal_infeasibility; - if (value < lower - options_mip_->mip_feasibility_tolerance) { - primal_infeasibility = lower - value; - } else if (value > upper + options_mip_->mip_feasibility_tolerance) { - primal_infeasibility = value - upper; - } else - continue; - - row_violation_ = std::max(row_violation_, primal_infeasibility); - } - - solution_objective_ = double(obj); + // Initial solution can be infeasible, but need to set values for violation + // and objective + HighsCDouble quad_solution_objective_; + solutionFeasible(orig_model_, solution.col_value, &solution.row_value, + bound_violation_, row_violation_, integrality_violation_, + quad_solution_objective_); + solution_objective_ = double(quad_solution_objective_); solution_ = solution.col_value; } } @@ -113,9 +75,7 @@ void HighsMipSolver::run() { analysis_.timer_ = &this->timer_; analysis_.setup(*orig_model_, *options_mip_); } - // Start the total_clock for the timer that is local to the HighsMipSolver - // instance - timer_.start(timer_.total_clock); + timer_.start(); improving_solution_file_ = nullptr; if (!submip && options_mip_->mip_improving_solution_file != "") @@ -131,12 +91,12 @@ void HighsMipSolver::run() { mipdata_->runPresolve(options_mip_->presolve_reduction_limit); analysis_.mipTimerStop(kMipClockRunPresolve); analysis_.mipTimerStop(kMipClockPresolve); - if (analysis_.analyse_mip_time & !submip) + if (analysis_.analyse_mip_time && !submip) highsLogUser(options_mip_->log_options, HighsLogType::kInfo, "MIP-Timing: %11.2g - completed presolve\n", timer_.read()); // Identify whether time limit has been reached (in presolve) if (modelstatus_ == HighsModelStatus::kNotset && - timer_.read(timer_.total_clock) >= options_mip_->time_limit) + timer_.read() >= options_mip_->time_limit) modelstatus_ = HighsModelStatus::kTimeLimit; if (modelstatus_ != HighsModelStatus::kNotset) { @@ -155,16 +115,15 @@ void HighsMipSolver::run() { analysis_.mipTimerStart(kMipClockSolve); - if (analysis_.analyse_mip_time & !submip) + if (analysis_.analyse_mip_time && !submip) highsLogUser(options_mip_->log_options, HighsLogType::kInfo, "MIP-Timing: %11.2g - starting setup\n", timer_.read()); analysis_.mipTimerStart(kMipClockRunSetup); mipdata_->runSetup(); analysis_.mipTimerStop(kMipClockRunSetup); - if (analysis_.analyse_mip_time & !submip) + if (analysis_.analyse_mip_time && !submip) highsLogUser(options_mip_->log_options, HighsLogType::kInfo, - "MIP-Timing: %11.2g - completed setup\n", - timer_.read(timer_.total_clock)); + "MIP-Timing: %11.2g - completed setup\n", timer_.read()); restart: if (modelstatus_ == HighsModelStatus::kNotset) { // Check limits have not been reached before evaluating root node @@ -172,6 +131,12 @@ void HighsMipSolver::run() { cleanupSolve(); return; } + // Possibly look for primal solution from the user + if (!submip && callback_->user_callback && + callback_->active[kCallbackMipUserSolution]) + mipdata_->callbackUserSolution(solution_objective_, + kUserMipSolutionCallbackOriginAfterSetup); + // Apply the trivial heuristics analysis_.mipTimerStart(kMipClockTrivialHeuristics); HighsModelStatus model_status = mipdata_->trivialHeuristics(); @@ -183,10 +148,10 @@ void HighsMipSolver::run() { return; } analysis_.mipTimerStop(kMipClockTrivialHeuristics); - if (analysis_.analyse_mip_time & !submip) + if (analysis_.analyse_mip_time && !submip) highsLogUser(options_mip_->log_options, HighsLogType::kInfo, "MIP-Timing: %11.2g - starting evaluate root node\n", - timer_.read(timer_.total_clock)); + timer_.read()); analysis_.mipTimerStart(kMipClockEvaluateRootNode); mipdata_->evaluateRootNode(); analysis_.mipTimerStop(kMipClockEvaluateRootNode); @@ -195,10 +160,10 @@ void HighsMipSolver::run() { if (analysis_.analyse_mip_time && analysis_.mipTimerRunning(kMipClockIpmSolveLp)) analysis_.mipTimerStop(kMipClockIpmSolveLp); - if (analysis_.analyse_mip_time & !submip) + if (analysis_.analyse_mip_time && !submip) highsLogUser(options_mip_->log_options, HighsLogType::kInfo, "MIP-Timing: %11.2g - completed evaluate root node\n", - timer_.read(timer_.total_clock)); + timer_.read()); // age 5 times to remove stored but never violated cuts after root // separation analysis_.mipTimerStart(kMipClockPerformAging0); @@ -245,6 +210,12 @@ void HighsMipSolver::run() { double lowerBoundLastCheck = mipdata_->lower_bound; analysis_.mipTimerStart(kMipClockSearch); while (search.hasNode()) { + // Possibly look for primal solution from the user + if (!submip && callback_->user_callback && + callback_->active[kCallbackMipUserSolution]) + mipdata_->callbackUserSolution(solution_objective_, + kUserMipSolutionCallbackOriginBeforeDive); + analysis_.mipTimerStart(kMipClockPerformAging1); mipdata_->conflictPool.performAging(); analysis_.mipTimerStop(kMipClockPerformAging1); @@ -307,10 +278,14 @@ void HighsMipSolver::run() { if (mipdata_->domain.infeasible()) break; if (!search.currentNodePruned()) { + double this_dive_time = -analysis_.mipTimerRead(kMipClockTheDive); analysis_.mipTimerStart(kMipClockTheDive); const HighsSearch::NodeResult search_dive_result = search.dive(); analysis_.mipTimerStop(kMipClockTheDive); - + if (analysis_.analyse_mip_time) { + this_dive_time += analysis_.mipTimerRead(kMipClockNodeSearch); + analysis_.dive_time.push_back(this_dive_time); + } if (search_dive_result == HighsSearch::NodeResult::kSubOptimal) break; ++mipdata_->num_leaves; @@ -510,6 +485,7 @@ void HighsMipSolver::run() { // mipdata_->lp.setIterationLimit(); // loop to install the next node for the search + double this_node_search_time = -analysis_.mipTimerRead(kMipClockNodeSearch); analysis_.mipTimerStart(kMipClockNodeSearch); while (!mipdata_->nodequeue.empty()) { @@ -654,7 +630,10 @@ void HighsMipSolver::run() { break; } // while(!mipdata_->nodequeue.empty()) analysis_.mipTimerStop(kMipClockNodeSearch); - + if (analysis_.analyse_mip_time) { + this_node_search_time += analysis_.mipTimerRead(kMipClockNodeSearch); + analysis_.node_search_time.push_back(this_node_search_time); + } if (limit_reached) break; } // while(search.hasNode()) analysis_.mipTimerStop(kMipClockSearch); @@ -718,7 +697,7 @@ void HighsMipSolver::cleanupSolve() { } analysis_.mipTimerStop(kMipClockPostsolve); - timer_.stop(timer_.total_clock); + timer_.stop(); std::string solutionstatus = "-"; @@ -768,6 +747,7 @@ void HighsMipSolver::cleanupSolve() { gapValString.data()); } + bool timeless_log = options_mip_->timeless_log; highsLogUser(options_mip_->log_options, HighsLogType::kInfo, "\nSolving report\n"); if (this->orig_model_->model_name_.length()) @@ -778,12 +758,15 @@ void HighsMipSolver::cleanupSolve() { " Status %s\n" " Primal bound %.12g\n" " Dual bound %.12g\n" - " Gap %s\n" - " P-D integral %.12g\n" - " Solution status %s\n", + " Gap %s\n", utilModelStatusToString(modelstatus_).c_str(), primal_bound_, - dual_bound_, gapString.data(), - mipdata_->primal_dual_integral.value, solutionstatus.c_str()); + dual_bound_, gapString.data()); + if (!timeless_log) + highsLogUser(options_mip_->log_options, HighsLogType::kInfo, + " P-D integral %.12g\n", + mipdata_->primal_dual_integral.value); + highsLogUser(options_mip_->log_options, HighsLogType::kInfo, + " Solution status %s\n", solutionstatus.c_str()); if (solutionstatus != "-") highsLogUser(options_mip_->log_options, HighsLogType::kInfo, " %.12g (objective)\n" @@ -792,11 +775,16 @@ void HighsMipSolver::cleanupSolve() { " %.12g (row viol.)\n", solution_objective_, bound_violation_, integrality_violation_, row_violation_); + if (!timeless_log) + highsLogUser(options_mip_->log_options, HighsLogType::kInfo, + " Timing %.2f (total)\n" + " %.2f (presolve)\n" + " %.2f (solve)\n" + " %.2f (postsolve)\n", + timer_.read(), analysis_.mipTimerRead(kMipClockPresolve), + analysis_.mipTimerRead(kMipClockSolve), + analysis_.mipTimerRead(kMipClockPostsolve)); highsLogUser(options_mip_->log_options, HighsLogType::kInfo, - " Timing %.2f (total)\n" - " %.2f (presolve)\n" - " %.2f (solve)\n" - " %.2f (postsolve)\n" " Max sub-MIP depth %d\n" " Nodes %llu\n" " Repair LPs %llu (%llu feasible; %llu iterations)\n" @@ -804,10 +792,6 @@ void HighsMipSolver::cleanupSolve() { " %llu (strong br.)\n" " %llu (separation)\n" " %llu (heuristics)\n", - timer_.read(timer_.total_clock), - analysis_.mipTimerRead(kMipClockPresolve), - analysis_.mipTimerRead(kMipClockSolve), - analysis_.mipTimerRead(kMipClockPostsolve), int(max_submip_level), (long long unsigned)mipdata_->num_nodes, (long long unsigned)mipdata_->total_repair_lp, (long long unsigned)mipdata_->total_repair_lp_feasible, @@ -817,7 +801,7 @@ void HighsMipSolver::cleanupSolve() { (long long unsigned)mipdata_->sepa_lp_iterations, (long long unsigned)mipdata_->heuristic_lp_iterations); - analysis_.reportMipTimer(); + if (!timeless_log) analysis_.reportMipTimer(); assert(modelstatus_ != HighsModelStatus::kNotset); } @@ -863,3 +847,77 @@ void HighsMipSolver::callbackGetCutPool() const { &callback_->data_out, &callback_->data_in, callback_->user_callback_data); } + +bool HighsMipSolver::solutionFeasible( + const HighsLp* lp, const std::vector& col_value, + const std::vector* pass_row_value, double& bound_violation, + double& row_violation, double& integrality_violation, HighsCDouble& obj) { + bound_violation = 0; + row_violation = 0; + integrality_violation = 0; + const double mip_feasibility_tolerance = + options_mip_->mip_feasibility_tolerance; + + obj = lp->offset_; + + if (kAllowDeveloperAssert) assert(HighsInt(col_value.size()) == lp->num_col_); + for (HighsInt i = 0; i != lp->num_col_; ++i) { + const double value = col_value[i]; + obj += lp->col_cost_[i] * value; + + if (lp->integrality_[i] == HighsVarType::kInteger) { + integrality_violation = + std::max(fractionality(value), integrality_violation); + } + + const double lower = lp->col_lower_[i]; + const double upper = lp->col_upper_[i]; + double primal_infeasibility; + if (value < lower - mip_feasibility_tolerance) { + primal_infeasibility = lower - value; + } else if (value > upper + mip_feasibility_tolerance) { + primal_infeasibility = value - upper; + } else + continue; + + bound_violation = std::max(bound_violation, primal_infeasibility); + } + + // Check row feasibility if there are a positive number of rows. + // + // If there are no rows and pass_row_value is nullptr, then + // row_value_p is also nullptr since row_value is not resized + if (lp->num_row_ > 0) { + std::vector row_value; + if (pass_row_value) { + if (kAllowDeveloperAssert) + assert(HighsInt((*pass_row_value).size()) == lp->num_col_); + } else { + calculateRowValuesQuad(*lp, col_value, row_value); + } + const double* row_value_p = + pass_row_value ? (*pass_row_value).data() : row_value.data(); + assert(row_value_p); + + for (HighsInt i = 0; i != lp->num_row_; ++i) { + const double value = row_value_p[i]; + const double lower = lp->row_lower_[i]; + const double upper = lp->row_upper_[i]; + + double primal_infeasibility; + if (value < lower - mip_feasibility_tolerance) { + primal_infeasibility = lower - value; + } else if (value > upper + mip_feasibility_tolerance) { + primal_infeasibility = value - upper; + } else + continue; + + row_violation = std::max(row_violation, primal_infeasibility); + } + } + + const bool feasible = bound_violation <= mip_feasibility_tolerance && + integrality_violation <= mip_feasibility_tolerance && + row_violation <= mip_feasibility_tolerance; + return feasible; +} diff --git a/src/mip/HighsMipSolver.h b/src/mip/HighsMipSolver.h index 2517b09a85..e1e9b380ca 100644 --- a/src/mip/HighsMipSolver.h +++ b/src/mip/HighsMipSolver.h @@ -103,6 +103,10 @@ class HighsMipSolver { presolve::HighsPostsolveStack getPostsolveStack() const; void callbackGetCutPool() const; + bool solutionFeasible(const HighsLp* lp, const std::vector& col_value, + const std::vector* pass_row_value, + double& bound_violation, double& row_violation, + double& integrality_violation, HighsCDouble& obj); }; #endif diff --git a/src/mip/HighsMipSolverData.cpp b/src/mip/HighsMipSolverData.cpp index eb5f919e57..dd0330e989 100644 --- a/src/mip/HighsMipSolverData.cpp +++ b/src/mip/HighsMipSolverData.cpp @@ -69,12 +69,9 @@ std::string HighsMipSolverData::solutionSourceToString( } else if (solution_source == kSolutionSourceTrivialP) { if (code) return "p"; return "Trivial point"; - // } else if (solution_source == kSolutionSourceOpt1) { - // if (code) return "1"; - // return "1-opt"; - // } else if (solution_source == kSolutionSourceOpt2) { - // if (code) return "2"; - // return "2-opt"; + } else if (solution_source == kSolutionSourceUserSolution) { + if (code) return "X"; + return "User solution"; } else if (solution_source == kSolutionSourceCleanup) { if (code) return " "; return ""; @@ -302,7 +299,7 @@ void HighsMipSolverData::startAnalyticCenterComputation( Highs ipm; ipm.setOptionValue("solver", "ipm"); ipm.setOptionValue("run_crossover", kHighsOffString); - ipm.setOptionValue("presolve", "off"); + ipm.setOptionValue("presolve", kHighsOffString); ipm.setOptionValue("output_flag", false); // ipm.setOptionValue("output_flag", !mipsolver.submip); ipm.setOptionValue("ipm_iteration_limit", 200); @@ -372,10 +369,9 @@ void HighsMipSolverData::finishAnalyticCenterComputation( } if (nfixed > 0) highsLogDev(mipsolver.options_mip_->log_options, HighsLogType::kInfo, - "Fixing %" HIGHSINT_FORMAT " columns (%" HIGHSINT_FORMAT - " integers) sitting at bound at " + "Fixing %d columns (%d integers) sitting at bound at " "analytic center\n", - nfixed, nintfixed); + int(nfixed), int(nintfixed)); mipsolver.mipdata_->domain.propagate(); if (mipsolver.mipdata_->domain.infeasible()) return; } @@ -406,9 +402,12 @@ void HighsMipSolverData::finishSymmetryDetection( taskGroup.sync(); symmetries = std::move(symData->symmetries); + std::string symmetry_time = + mipsolver.options_mip_->timeless_log + ? "" + : highsFormatToString(" %.1fs", symData->detectionTime); highsLogUser(mipsolver.options_mip_->log_options, HighsLogType::kInfo, - "\nSymmetry detection completed in %.1fs\n", - symData->detectionTime); + "\nSymmetry detection completed in%s\n", symmetry_time.c_str()); if (symmetries.numGenerators == 0) { detectSymmetries = false; @@ -416,24 +415,20 @@ void HighsMipSolverData::finishSymmetryDetection( "No symmetry present\n\n"); } else if (symmetries.orbitopes.size() == 0) { highsLogUser(mipsolver.options_mip_->log_options, HighsLogType::kInfo, - "Found %" HIGHSINT_FORMAT " generator(s)\n\n", - symmetries.numGenerators); + "Found %d generator(s)\n\n", int(symmetries.numGenerators)); } else { if (symmetries.numPerms != 0) { - highsLogUser( - mipsolver.options_mip_->log_options, HighsLogType::kInfo, - "Found %" HIGHSINT_FORMAT " generator(s) and %" HIGHSINT_FORMAT - " full orbitope(s) acting on %" HIGHSINT_FORMAT " columns\n\n", - symmetries.numPerms, (HighsInt)symmetries.orbitopes.size(), - (HighsInt)symmetries.columnToOrbitope.size()); + highsLogUser(mipsolver.options_mip_->log_options, HighsLogType::kInfo, + "Found %d generator(s) and %d full orbitope(s) acting on %d " + "columns\n\n", + int(symmetries.numPerms), int(symmetries.orbitopes.size()), + int(symmetries.columnToOrbitope.size())); } else { highsLogUser(mipsolver.options_mip_->log_options, HighsLogType::kInfo, - "Found %" HIGHSINT_FORMAT - " full orbitope(s) acting on %" HIGHSINT_FORMAT - " columns\n\n", - (HighsInt)symmetries.orbitopes.size(), - (HighsInt)symmetries.columnToOrbitope.size()); + "Found %d full orbitope(s) acting on %d columns\n\n", + int(symmetries.orbitopes.size()), + int(symmetries.columnToOrbitope.size())); } } symData.reset(); @@ -678,6 +673,7 @@ void HighsMipSolverData::runSetup() { const HighsLp& model = *mipsolver.model_; last_disptime = -kHighsInf; + disptime = 0; // Transform the reference of the objective limit and lower/upper // bounds from the original model to the current model, undoing the @@ -759,8 +755,9 @@ void HighsMipSolverData::runSetup() { highsSparseTranspose(model.num_row_, model.num_col_, model.a_matrix_.start_, model.a_matrix_.index_, model.a_matrix_.value_, ARstart_, ARindex_, ARvalue_); - uplocks.resize(model.num_col_); - downlocks.resize(model.num_col_); + // (re-)initialize number of uplocks and downlocks + uplocks.assign(model.num_col_, 0); + downlocks.assign(model.num_col_, 0); for (HighsInt i = 0; i != model.num_col_; ++i) { HighsInt start = model.a_matrix_.start_[i]; HighsInt end = model.a_matrix_.start_[i + 1]; @@ -849,9 +846,9 @@ void HighsMipSolverData::runSetup() { implications.cleanupVarbounds(col); domain.clearChangedCols(); - lp.getLpSolver().setOptionValue("presolve", "off"); + lp.getLpSolver().setOptionValue("presolve", kHighsOffString); // lp.getLpSolver().setOptionValue("dual_simplex_cost_perturbation_multiplier", - // 0.0); lp.getLpSolver().setOptionValue("parallel", "on"); + // 0.0); lp.getLpSolver().setOptionValue("parallel", kHighsOnString); lp.getLpSolver().setOptionValue("simplex_initial_condition_check", false); checkObjIntegrality(); @@ -981,10 +978,8 @@ double HighsMipSolverData::transformNewIntegerFeasibleSolution( postSolveStack.undoPrimal(*mipsolver.options_mip_, solution); // Determine the row values, as they aren't computed in primal // postsolve - HighsInt first_check_row = - -1; // mipsolver.mipdata_->presolve.debugGetCheckRow(); HighsStatus return_status = - calculateRowValuesQuad(*mipsolver.orig_model_, solution, first_check_row); + calculateRowValuesQuad(*mipsolver.orig_model_, solution); if (kAllowDeveloperAssert) assert(return_status == HighsStatus::kOk); bool allow_try_again = true; try_again: @@ -993,89 +988,12 @@ double HighsMipSolverData::transformNewIntegerFeasibleSolution( double bound_violation_ = 0; double row_violation_ = 0; double integrality_violation_ = 0; - - // Compute to quad precision the objective function value of the MIP - // being solved - including the offset, and independent of objective - // sense - // - HighsCDouble mipsolver_quad_precision_objective_value = - mipsolver.orig_model_->offset_; - if (kAllowDeveloperAssert) - assert((HighsInt)solution.col_value.size() == - mipsolver.orig_model_->num_col_); - HighsInt check_col = -1; - HighsInt check_int = -1; - HighsInt check_row = -1; - const bool debug_report = false; - for (HighsInt i = 0; i != mipsolver.orig_model_->num_col_; ++i) { - const double value = solution.col_value[i]; - mipsolver_quad_precision_objective_value += - mipsolver.orig_model_->col_cost_[i] * value; - - if (mipsolver.orig_model_->integrality_[i] == HighsVarType::kInteger) { - double integrality_infeasibility = fractionality(value); - if (integrality_infeasibility > - mipsolver.options_mip_->mip_feasibility_tolerance) { - if (debug_report) - printf("Col %d[%s] value %g has integrality infeasibility %g\n", - int(i), mipsolver.orig_model_->col_names_[i].c_str(), value, - integrality_infeasibility); - check_int = i; - } - integrality_violation_ = - std::max(integrality_infeasibility, integrality_violation_); - } - - const double lower = mipsolver.orig_model_->col_lower_[i]; - const double upper = mipsolver.orig_model_->col_upper_[i]; - double primal_infeasibility = 0; - if (value < lower - mipsolver.options_mip_->mip_feasibility_tolerance) { - primal_infeasibility = lower - value; - } else if (value > - upper + mipsolver.options_mip_->mip_feasibility_tolerance) { - primal_infeasibility = value - upper; - } else - continue; - if (primal_infeasibility > - mipsolver.options_mip_->primal_feasibility_tolerance) { - if (debug_report) - printf("Col %d[%s] [%g, %g, %g] has infeasibility %g\n", int(i), - mipsolver.orig_model_->col_names_[i].c_str(), lower, value, - upper, primal_infeasibility); - check_col = i; - } - bound_violation_ = std::max(bound_violation_, primal_infeasibility); - } - - for (HighsInt i = 0; i != mipsolver.orig_model_->num_row_; ++i) { - const double value = solution.row_value[i]; - const double lower = mipsolver.orig_model_->row_lower_[i]; - const double upper = mipsolver.orig_model_->row_upper_[i]; - double primal_infeasibility; - if (value < lower - mipsolver.options_mip_->mip_feasibility_tolerance) { - primal_infeasibility = lower - value; - } else if (value > - upper + mipsolver.options_mip_->mip_feasibility_tolerance) { - primal_infeasibility = value - upper; - } else - continue; - if (primal_infeasibility > - mipsolver.options_mip_->primal_feasibility_tolerance) { - if (debug_report) - printf("Row %d[%s] [%g, %g, %g] has infeasibility %g\n", int(i), - mipsolver.orig_model_->row_names_[i].c_str(), lower, value, - upper, primal_infeasibility); - check_row = i; - } - row_violation_ = std::max(row_violation_, primal_infeasibility); - } - - bool feasible = - bound_violation_ <= mipsolver.options_mip_->mip_feasibility_tolerance && - integrality_violation_ <= - mipsolver.options_mip_->mip_feasibility_tolerance && - row_violation_ <= mipsolver.options_mip_->mip_feasibility_tolerance; - + HighsCDouble mipsolver_quad_objective_value = 0; + bool feasible = mipsolver.solutionFeasible( + mipsolver.orig_model_, solution.col_value, &solution.row_value, + bound_violation_, row_violation_, integrality_violation_, + mipsolver_quad_objective_value); + double mipsolver_objective_value = double(mipsolver_quad_objective_value); if (!feasible && allow_try_again) { // printf( // "trying to repair sol that is violated by %.12g bounds, %.12g " @@ -1091,10 +1009,8 @@ double HighsMipSolverData::transformNewIntegerFeasibleSolution( } } this->total_repair_lp++; - double time_available = - std::max(mipsolver.options_mip_->time_limit - - mipsolver.timer_.read(mipsolver.timer_.total_clock), - 0.1); + double time_available = std::max( + mipsolver.options_mip_->time_limit - mipsolver.timer_.read(), 0.1); Highs tmpSolver; const bool debug_report = false; if (debug_report) { @@ -1104,10 +1020,13 @@ double HighsMipSolverData::transformNewIntegerFeasibleSolution( tmpSolver.setOptionValue("output_flag", false); } // tmpSolver.setOptionValue("simplex_scale_strategy", 0); - // tmpSolver.setOptionValue("presolve", "off"); + // tmpSolver.setOptionValue("presolve", kHighsOffString); tmpSolver.setOptionValue("time_limit", time_available); tmpSolver.setOptionValue("primal_feasibility_tolerance", mipsolver.options_mip_->mip_feasibility_tolerance); + // check if only root presolve is allowed + if (mipsolver.options_mip_->mip_root_presolve_only) + tmpSolver.setOptionValue("presolve", kHighsOffString); tmpSolver.passModel(std::move(fixedModel)); mipsolver.analysis_.mipTimerStart(kMipClockSimplexNoBasisSolveLp); tmpSolver.run(); @@ -1123,10 +1042,6 @@ double HighsMipSolverData::transformNewIntegerFeasibleSolution( } } - // Get a double precision version of the objective function value of - // the MIP being solved - const double mipsolver_objective_value = - double(mipsolver_quad_precision_objective_value); // Possible MIP solution callback if (!mipsolver.submip && feasible && mipsolver.callback_->user_callback && mipsolver.callback_->active[kCallbackMipSolution]) { @@ -1159,51 +1074,11 @@ double HighsMipSolverData::transformNewIntegerFeasibleSolution( mipsolver.options_mip_->mip_feasibility_tolerance && mipsolver.row_violation_ <= mipsolver.options_mip_->mip_feasibility_tolerance; - // check_col = 37;//mipsolver.mipdata_->presolve.debugGetCheckCol(); - // check_row = 37;//mipsolver.mipdata_->presolve.debugGetCheckRow(); - std::string check_col_data = ""; - if (check_col >= 0) { - check_col_data = " (col " + std::to_string(check_col); - if (mipsolver.orig_model_->col_names_.size()) - check_col_data += - "[" + mipsolver.orig_model_->col_names_[check_col] + "]"; - check_col_data += ")"; - } - std::string check_int_data = ""; - if (check_int >= 0) { - check_int_data = " (col " + std::to_string(check_int); - if (mipsolver.orig_model_->col_names_.size()) - check_int_data += - "[" + mipsolver.orig_model_->col_names_[check_int] + "]"; - check_int_data += ")"; - } - std::string check_row_data = ""; - if (check_row >= 0) { - check_row_data = " (row " + std::to_string(check_row); - if (mipsolver.orig_model_->row_names_.size()) - check_row_data += - "[" + mipsolver.orig_model_->row_names_[check_row] + "]"; - check_row_data += ")"; - } highsLogUser(mipsolver.options_mip_->log_options, HighsLogType::kWarning, "Solution with objective %g has untransformed violations: " - "bound = %.4g%s; integrality = %.4g%s; row = %.4g%s\n", + "bound = %.4g; integrality = %.4g; row = %.4g\n", mipsolver_objective_value, bound_violation_, - check_col_data.c_str(), integrality_violation_, - check_int_data.c_str(), row_violation_, - check_row_data.c_str()); - - const bool debug_repeat = false; // true;// - if (debug_repeat) { - HighsSolution check_solution; - check_solution.col_value = sol; - check_solution.value_valid = true; - postSolveStack.undoPrimal(*mipsolver.options_mip_, check_solution, - check_col); - fflush(stdout); - if (kAllowDeveloperAssert) assert(111 == 999); - } - + integrality_violation_, row_violation_); if (!currentFeasible) { // if the current incumbent is non existent or also not feasible we // still store the new one @@ -1220,11 +1095,9 @@ double HighsMipSolverData::transformNewIntegerFeasibleSolution( } // return the objective value in the transformed space if (mipsolver.orig_model_->sense_ == ObjSense::kMaximize) - return -double(mipsolver_quad_precision_objective_value + - mipsolver.model_->offset_); + return -double(mipsolver_quad_objective_value + mipsolver.model_->offset_); - return double(mipsolver_quad_precision_objective_value - - mipsolver.model_->offset_); + return double(mipsolver_quad_objective_value - mipsolver.model_->offset_); } double HighsMipSolverData::percentageInactiveIntegers() const { @@ -1267,6 +1140,7 @@ void HighsMipSolverData::performRestart() { root_basis.row_status.resize(postSolveStack.getOrigNumRow(), HighsBasisStatus::kBasic); root_basis.valid = true; + root_basis.useful = true; for (HighsInt i = 0; i < mipsolver.model_->num_col_; ++i) root_basis.col_status[postSolveStack.getOrigColIndex(i)] = @@ -1281,7 +1155,7 @@ void HighsMipSolverData::performRestart() { } // Transform the reference of the objective limit and lower/upper - // bounds to the original model, since offset will generally changte + // bounds to the original model, since offset will generally change // in presolve. Bound changes are transitory, so no real gap change, // and no update to P-D integral is necessary upper_limit += mipsolver.model_->offset_; @@ -1381,6 +1255,7 @@ void HighsMipSolverData::basisTransfer() { firstrootbasis.row_status.assign(numRow, HighsBasisStatus::kNonbasic); firstrootbasis.valid = true; firstrootbasis.alien = true; + firstrootbasis.useful = true; for (HighsInt i = 0; i < numRow; ++i) { HighsBasisStatus status = @@ -1402,9 +1277,10 @@ const std::vector& HighsMipSolverData::getSolution() const { bool HighsMipSolverData::addIncumbent(const std::vector& sol, double solobj, const int solution_source, - const bool print_display_line) { + const bool print_display_line, + const bool is_user_solution) { const bool execute_mip_solution_callback = - !mipsolver.submip && + !is_user_solution && !mipsolver.submip && (mipsolver.callback_->user_callback ? mipsolver.callback_->active[kCallbackMipSolution] : false); @@ -1423,10 +1299,7 @@ bool HighsMipSolverData::addIncumbent(const std::vector& sol, : 0; if (possibly_store_as_new_incumbent) { - // #1463 use pre-computed transformed_solobj solobj = transformed_solobj; - // solobj = transformNewIntegerFeasibleSolution(sol); - if (solobj >= upper_bound) return false; double prev_upper_bound = upper_bound; @@ -1441,7 +1314,8 @@ bool HighsMipSolverData::addIncumbent(const std::vector& sol, incumbent = sol; double new_upper_limit = computeNewUpperLimit(solobj, 0.0, 0.0); - if (!mipsolver.submip) saveReportMipSolution(new_upper_limit); + if (!is_user_solution && !mipsolver.submip) + saveReportMipSolution(new_upper_limit); if (new_upper_limit < upper_limit) { ++numImprovingSols; upper_limit = new_upper_limit; @@ -1598,21 +1472,26 @@ void HighsMipSolverData::printDisplayLine(const int solution_source) { bool output_flag = *mipsolver.options_mip_->log_options.output_flag; if (!output_flag) return; - double time = mipsolver.timer_.read(mipsolver.timer_.total_clock); + bool timeless_log = mipsolver.options_mip_->timeless_log; + disptime = timeless_log ? disptime + 1 : mipsolver.timer_.read(); if (solution_source == kSolutionSourceNone && - time - last_disptime < mipsolver.options_mip_->mip_min_logging_interval) + disptime - last_disptime < + mipsolver.options_mip_->mip_min_logging_interval) return; - last_disptime = time; + last_disptime = disptime; + std::string time_string = + timeless_log ? "" : highsFormatToString(" %7.1fs", disptime); if (num_disp_lines % 20 == 0) { if (num_disp_lines == 0) printSolutionSourceKey(); - highsLogUser( - mipsolver.options_mip_->log_options, HighsLogType::kInfo, - // clang-format off - "\n Nodes | B&B Tree | Objective Bounds | Dynamic Constraints | Work \n" - "Src Proc. InQueue | Leaves Expl. | BestBound BestSol Gap | Cuts InLp Confl. | LpIters Time\n\n" - // clang-format on - ); + std::string work_string0 = timeless_log ? " Work" : " Work "; + std::string work_string1 = timeless_log ? "LpIters" : "LpIters Time"; + highsLogUser(mipsolver.options_mip_->log_options, HighsLogType::kInfo, + // clang-format off + "\n Nodes | B&B Tree | Objective Bounds | Dynamic Constraints | %s\n" + "Src Proc. InQueue | Leaves Expl. | BestBound BestSol Gap | Cuts InLp Confl. | %s\n\n", + // clang-format on + work_string0.c_str(), work_string1.c_str()); //" %7s | %10s | %10s | %10s | %10s | %-15s | %-15s | %7s | %7s " //"| %8s | %8s\n", @@ -1636,6 +1515,8 @@ void HighsMipSolverData::printDisplayLine(const int solution_source) { ub = mipsolver.options_mip_->objective_bound; auto print_lp_iters = convertToPrintString(total_lp_iterations); + HighsInt dynamic_constraints_in_lp = + lp.numRows() > 0 ? lp.numRows() - lp.getNumModelRows() : 0; if (upper_bound != kHighsInf) { std::array gap_string = {}; if (gap >= 9999.) @@ -1656,13 +1537,13 @@ void HighsMipSolverData::printDisplayLine(const int solution_source) { highsLogUser( mipsolver.options_mip_->log_options, HighsLogType::kInfo, // clang-format off - " %s %7s %7s %7s %6.2f%% %-15s %-15s %8s %6" HIGHSINT_FORMAT " %6" HIGHSINT_FORMAT " %6" HIGHSINT_FORMAT " %7s %7.1fs\n", + " %s %7s %7s %7s %6.2f%% %-15s %-15s %8s %6" HIGHSINT_FORMAT " %6" HIGHSINT_FORMAT " %6" HIGHSINT_FORMAT " %7s%s\n", // clang-format on solutionSourceToString(solution_source).c_str(), print_nodes.data(), queue_nodes.data(), print_leaves.data(), explored, lb_string.data(), ub_string.data(), gap_string.data(), cutpool.getNumCuts(), - lp.numRows() - lp.getNumModelRows(), conflictPool.getNumConflicts(), - print_lp_iters.data(), time); + dynamic_constraints_in_lp, conflictPool.getNumConflicts(), + print_lp_iters.data(), time_string.c_str()); } else { std::array ub_string; if (mipsolver.options_mip_->objective_bound < ub) { @@ -1677,13 +1558,13 @@ void HighsMipSolverData::printDisplayLine(const int solution_source) { highsLogUser( mipsolver.options_mip_->log_options, HighsLogType::kInfo, // clang-format off - " %s %7s %7s %7s %6.2f%% %-15s %-15s %8.2f %6" HIGHSINT_FORMAT " %6" HIGHSINT_FORMAT " %6" HIGHSINT_FORMAT " %7s %7.1fs\n", + " %s %7s %7s %7s %6.2f%% %-15s %-15s %8.2f %6" HIGHSINT_FORMAT " %6" HIGHSINT_FORMAT " %6" HIGHSINT_FORMAT " %7s%s\n", // clang-format on solutionSourceToString(solution_source).c_str(), print_nodes.data(), queue_nodes.data(), print_leaves.data(), explored, lb_string.data(), - ub_string.data(), gap, cutpool.getNumCuts(), - lp.numRows() - lp.getNumModelRows(), conflictPool.getNumConflicts(), - print_lp_iters.data(), time); + ub_string.data(), gap, cutpool.getNumCuts(), dynamic_constraints_in_lp, + conflictPool.getNumConflicts(), print_lp_iters.data(), + time_string.c_str()); } // Check that limitsToBounds yields the same values for the // dual_bound, primal_bound (modulo optimization sense) and @@ -1891,11 +1772,21 @@ void HighsMipSolverData::evaluateRootNode() { printDisplayLine(); + // Possibly look for primal solution from the user + if (!mipsolver.submip && mipsolver.callback_->user_callback && + mipsolver.callback_->active[kCallbackMipUserSolution]) + mipsolver.mipdata_->callbackUserSolution( + mipsolver.solution_objective_, + kUserMipSolutionCallbackOriginEvaluateRootNode0); + + // check if only root presolve is allowed if (firstrootbasis.valid) lp.getLpSolver().setBasis(firstrootbasis, "HighsMipSolverData::evaluateRootNode"); + else if (mipsolver.options_mip_->mip_root_presolve_only) + lp.getLpSolver().setOptionValue("presolve", kHighsOffString); else - lp.getLpSolver().setOptionValue("presolve", "on"); + lp.getLpSolver().setOptionValue("presolve", kHighsOnString); if (mipsolver.options_mip_->highs_debug_level) lp.getLpSolver().setOptionValue("output_flag", mipsolver.options_mip_->output_flag); @@ -1909,8 +1800,8 @@ void HighsMipSolverData::evaluateRootNode() { if (numRestarts == 0) firstrootlpiters = total_lp_iterations; lp.getLpSolver().setOptionValue("output_flag", false); - lp.getLpSolver().setOptionValue("presolve", "off"); - lp.getLpSolver().setOptionValue("parallel", "off"); + lp.getLpSolver().setOptionValue("presolve", kHighsOffString); + lp.getLpSolver().setOptionValue("parallel", kHighsOffString); if (status == HighsLpRelaxation::Status::kInfeasible || status == HighsLpRelaxation::Status::kUnbounded) @@ -1931,6 +1822,7 @@ void HighsMipSolverData::evaluateRootNode() { firstrootbasis.row_status.assign(mipsolver.numRow(), HighsBasisStatus::kBasic); firstrootbasis.valid = true; + firstrootbasis.useful = true; } if (cutpool.getNumCuts() != 0) { @@ -1959,6 +1851,7 @@ void HighsMipSolverData::evaluateRootNode() { // make sure first line after solving root LP is printed last_disptime = -kHighsInf; + disptime = 0; mipsolver.analysis_.mipTimerStart(kMipClockRandomizedRounding1); heuristics.randomizedRounding(firstlpsol); @@ -2121,6 +2014,13 @@ void HighsMipSolverData::evaluateRootNode() { rootlpsolobj = lp.getObjective(); lp.setIterationLimit(std::max(10000, int(10 * avgrootlpiters))); if (ncuts == 0) break; + + // Possibly look for primal solution from the user + if (!mipsolver.submip && mipsolver.callback_->user_callback && + mipsolver.callback_->active[kCallbackMipUserSolution]) + mipsolver.mipdata_->callbackUserSolution( + mipsolver.solution_objective_, + kUserMipSolutionCallbackOriginEvaluateRootNode1); } mipsolver.analysis_.mipTimerStop(kMipClockSeparation); if (mipsolver.analysis_.analyse_mip_time) { @@ -2172,6 +2072,13 @@ void HighsMipSolverData::evaluateRootNode() { } printDisplayLine(); + // Possibly look for primal solution from the user + if (!mipsolver.submip && mipsolver.callback_->user_callback && + mipsolver.callback_->active[kCallbackMipUserSolution]) + mipsolver.mipdata_->callbackUserSolution( + mipsolver.solution_objective_, + kUserMipSolutionCallbackOriginEvaluateRootNode2); + // Possible cut extraction callback if (!mipsolver.submip && mipsolver.callback_->user_callback && mipsolver.callback_->callbackActive(kCallbackMipGetCutPool)) @@ -2219,6 +2126,12 @@ void HighsMipSolverData::evaluateRootNode() { ++nseparounds; printDisplayLine(); + // Possibly look for primal solution from the user + if (!mipsolver.submip && mipsolver.callback_->user_callback && + mipsolver.callback_->active[kCallbackMipUserSolution]) + mipsolver.mipdata_->callbackUserSolution( + mipsolver.solution_objective_, + kUserMipSolutionCallbackOriginEvaluateRootNode3); } if (upper_limit != kHighsInf || mipsolver.submip) break; @@ -2253,6 +2166,13 @@ void HighsMipSolverData::evaluateRootNode() { printDisplayLine(); } + // Possibly look for primal solution from the user + if (!mipsolver.submip && mipsolver.callback_->user_callback && + mipsolver.callback_->active[kCallbackMipUserSolution]) + mipsolver.mipdata_->callbackUserSolution( + mipsolver.solution_objective_, + kUserMipSolutionCallbackOriginEvaluateRootNode4); + removeFixedIndices(); if (lp.getLpSolver().getBasis().valid) lp.removeObsoleteRows(); rootlpsolobj = lp.getObjective(); @@ -2377,11 +2297,10 @@ bool HighsMipSolverData::checkLimits(int64_t nodeOffset) const { return true; } - // const double time = mipsolver.timer_.read(mipsolver.timer_.total_clock); + // const double time = mipsolver.timer_.read(); // printf("checkLimits: time = %g\n", time); if (options.time_limit < kHighsInf && - mipsolver.timer_.read(mipsolver.timer_.total_clock) >= - options.time_limit) { + mipsolver.timer_.read() >= options.time_limit) { if (mipsolver.modelstatus_ == HighsModelStatus::kNotset) { highsLogDev(options.log_options, HighsLogType::kInfo, "Reached time limit\n"); @@ -2477,18 +2396,13 @@ void HighsMipSolverData::limitsToBounds(double& dual_bound, // incumbent value (mipsolver.solution_objective_) is not right for // callback_type = kCallbackMipSolution -bool HighsMipSolverData::interruptFromCallbackWithData( - const int callback_type, const double mipsolver_objective_value, - const std::string message) const { - if (!mipsolver.callback_->callbackActive(callback_type)) return false; - assert(!mipsolver.submip); - +void HighsMipSolverData::setCallbackDataOut( + const double mipsolver_objective_value) const { double dual_bound; double primal_bound; double mip_rel_gap; limitsToBounds(dual_bound, primal_bound, mip_rel_gap); - mipsolver.callback_->data_out.running_time = - mipsolver.timer_.read(mipsolver.timer_.total_clock); + mipsolver.callback_->data_out.running_time = mipsolver.timer_.read(); mipsolver.callback_->data_out.objective_function_value = mipsolver_objective_value; mipsolver.callback_->data_out.mip_node_count = mipsolver.mipdata_->num_nodes; @@ -2497,9 +2411,62 @@ bool HighsMipSolverData::interruptFromCallbackWithData( mipsolver.callback_->data_out.mip_primal_bound = primal_bound; mipsolver.callback_->data_out.mip_dual_bound = dual_bound; mipsolver.callback_->data_out.mip_gap = mip_rel_gap; +} + +bool HighsMipSolverData::interruptFromCallbackWithData( + const int callback_type, const double mipsolver_objective_value, + const std::string message) const { + if (!mipsolver.callback_->callbackActive(callback_type)) return false; + assert(!mipsolver.submip); + setCallbackDataOut(mipsolver_objective_value); return mipsolver.callback_->callbackAction(callback_type, message); } +void HighsMipSolverData::callbackUserSolution( + const double mipsolver_objective_value, + const HighsInt user_solution_callback_origin) { + setCallbackDataOut(mipsolver_objective_value); + mipsolver.callback_->data_out.user_solution_callback_origin = + user_solution_callback_origin; + + mipsolver.callback_->clearHighsCallbackDataIn(); + const bool interrupt = mipsolver.callback_->callbackAction( + kCallbackMipUserSolution, "MIP User solution"); + assert(!interrupt); + if (mipsolver.callback_->data_in.user_solution) { + std::vector user_solution(mipsolver.orig_model_->num_col_); + for (HighsInt iCol = 0; iCol < mipsolver.orig_model_->num_col_; iCol++) + user_solution[iCol] = mipsolver.callback_->data_in.user_solution[iCol]; + double bound_violation_ = 0; + double row_violation_ = 0; + double integrality_violation_ = 0; + HighsCDouble user_solution_quad_objective_value = 0; + const bool feasible = mipsolver.solutionFeasible( + mipsolver.orig_model_, user_solution, nullptr, bound_violation_, + row_violation_, integrality_violation_, + user_solution_quad_objective_value); + double user_solution_objective_value = + double(user_solution_quad_objective_value); + if (!feasible) { + highsLogUser( + mipsolver.options_mip_->log_options, HighsLogType::kWarning, + "User-supplied solution has with objective %g has violations: " + "bound = %.4g; integrality = %.4g; row = %.4g\n", + user_solution_objective_value, bound_violation_, + integrality_violation_, row_violation_); + return; + } + std::vector reduced_user_solution; + reduced_user_solution = + postSolveStack.getReducedPrimalSolution(user_solution); + const bool print_display_line = true; + const bool is_user_solution = true; + addIncumbent(reduced_user_solution, user_solution_objective_value, + kSolutionSourceUserSolution, print_display_line, + is_user_solution); + } +} + static double possInfRelDiff(const double v0, const double v1, const double den) { double rel_diff; @@ -2617,7 +2584,7 @@ void HighsMipSolverData::updatePrimalDualIntegral(const double from_lower_bound, assert(gap_consistent); } if (to_gap < kHighsInf) { - double time = mipsolver.timer_.read(mipsolver.timer_.total_clock); + double time = mipsolver.timer_.read(); if (from_gap < kHighsInf) { // Need to update the P-D integral double time_diff = time - pdi.prev_time; diff --git a/src/mip/HighsMipSolverData.h b/src/mip/HighsMipSolverData.h index 080016b9a9..b4cd86d4bf 100644 --- a/src/mip/HighsMipSolverData.h +++ b/src/mip/HighsMipSolverData.h @@ -57,8 +57,7 @@ enum MipSolutionSource : int { kSolutionSourceTrivialL, kSolutionSourceTrivialU, kSolutionSourceTrivialP, - // kSolutionSourceOpt1, - // kSolutionSourceOpt2, + kSolutionSourceUserSolution, kSolutionSourceCleanup, kSolutionSourceCount }; @@ -118,6 +117,7 @@ struct HighsMipSolverData { HighsCDouble pruned_treeweight; double avgrootlpiters; + double disptime; double last_disptime; int64_t firstrootlpiters; int64_t num_nodes; @@ -183,6 +183,7 @@ struct HighsMipSolverData { maxTreeSizeLog2(0), pruned_treeweight(0), avgrootlpiters(0.0), + disptime(0.0), last_disptime(0.0), firstrootlpiters(0), num_nodes(0), @@ -264,7 +265,8 @@ struct HighsMipSolverData { void evaluateRootNode(); bool addIncumbent(const std::vector& sol, double solobj, const int solution_source, - const bool print_display_line = true); + const bool print_display_line = true, + const bool is_user_solution = false); const std::vector& getSolution() const; @@ -284,9 +286,12 @@ struct HighsMipSolverData { bool checkLimits(int64_t nodeOffset = 0) const; void limitsToBounds(double& dual_bound, double& primal_bound, double& mip_rel_gap) const; + void setCallbackDataOut(const double mipsolver_objective_value) const; bool interruptFromCallbackWithData(const int callback_type, const double mipsolver_objective_value, const std::string message = "") const; + void callbackUserSolution(const double mipsolver_objective_value, + const HighsInt user_solution_callback_origin); }; #endif diff --git a/src/mip/HighsModkSeparator.h b/src/mip/HighsModkSeparator.h index 203e59bf13..43f8f01442 100644 --- a/src/mip/HighsModkSeparator.h +++ b/src/mip/HighsModkSeparator.h @@ -54,7 +54,7 @@ class HighsModkSeparator : public HighsSeparator { HighsCutPool& cutpool) override; HighsModkSeparator(const HighsMipSolver& mipsolver) - : HighsSeparator(mipsolver, "Mod-k sepa", "Mod") {} + : HighsSeparator(mipsolver, "Mod-k sepa") {} }; #endif diff --git a/src/mip/HighsPathSeparator.h b/src/mip/HighsPathSeparator.h index 8cb13c6138..88a5e3e238 100644 --- a/src/mip/HighsPathSeparator.h +++ b/src/mip/HighsPathSeparator.h @@ -31,7 +31,7 @@ class HighsPathSeparator : public HighsSeparator { HighsCutPool& cutpool) override; HighsPathSeparator(const HighsMipSolver& mipsolver) - : HighsSeparator(mipsolver, "PathAggr sepa", "Agg") { + : HighsSeparator(mipsolver, "PathAggr sepa") { randgen.initialise(mipsolver.options_mip_->random_seed); } }; diff --git a/src/mip/HighsPrimalHeuristics.cpp b/src/mip/HighsPrimalHeuristics.cpp index 43e34bae6f..6cdc6a997a 100644 --- a/src/mip/HighsPrimalHeuristics.cpp +++ b/src/mip/HighsPrimalHeuristics.cpp @@ -108,8 +108,7 @@ bool HighsPrimalHeuristics::solveSubMip( submipoptions.mip_max_nodes = maxnodes; submipoptions.mip_max_stall_nodes = stallnodes; submipoptions.mip_pscost_minreliable = 0; - submipoptions.time_limit -= - mipsolver.timer_.read(mipsolver.timer_.total_clock); + submipoptions.time_limit -= mipsolver.timer_.read(); submipoptions.objective_bound = mipsolver.mipdata_->upper_limit; if (!mipsolver.submip) { @@ -126,7 +125,11 @@ bool HighsPrimalHeuristics::solveSubMip( mipsolver.mipdata_->feastol * std::max(curr_abs_gap, 1000.0); } - submipoptions.presolve = "on"; + // check if only root presolve is allowed + if (submipoptions.mip_root_presolve_only) + submipoptions.presolve = kHighsOffString; + else + submipoptions.presolve = kHighsOnString; submipoptions.mip_detect_symmetry = false; submipoptions.mip_heuristic_effort = 0.8; // setup solver and run it @@ -885,8 +888,12 @@ bool HighsPrimalHeuristics::tryRoundedPoint(const std::vector& point, localdom.col_lower_.data(), localdom.col_upper_.data()); - if (numintcols / (double)mipsolver.numCol() >= 0.2) - lprelax.getLpSolver().setOptionValue("presolve", "on"); + // check if only root presolve is allowed + if (mipsolver.options_mip_->mip_root_presolve_only) + lprelax.getLpSolver().setOptionValue("presolve", kHighsOffString); + if (!mipsolver.options_mip_->mip_root_presolve_only && + (5 * numintcols) / mipsolver.numCol() >= 1) + lprelax.getLpSolver().setOptionValue("presolve", kHighsOnString); else lprelax.getLpSolver().setBasis(mipsolver.mipdata_->firstrootbasis, "HighsPrimalHeuristics::tryRoundedPoint"); @@ -1000,7 +1007,8 @@ void HighsPrimalHeuristics::randomizedRounding( } } - if (int(mipsolver.mipdata_->integer_cols.size()) != mipsolver.numCol()) { + if (mipsolver.mipdata_->integer_cols.size() != + static_cast(mipsolver.numCol())) { HighsLpRelaxation lprelax(mipsolver); lprelax.loadModel(); lprelax.setIterationLimit( @@ -1008,12 +1016,18 @@ void HighsPrimalHeuristics::randomizedRounding( lprelax.getLpSolver().changeColsBounds(0, mipsolver.numCol() - 1, localdom.col_lower_.data(), localdom.col_upper_.data()); - if ((5 * intcols.size()) / mipsolver.numCol() >= 1) - lprelax.getLpSolver().setOptionValue("presolve", "on"); + + // check if only root presolve is allowed + if (mipsolver.options_mip_->mip_root_presolve_only) + lprelax.getLpSolver().setOptionValue("presolve", kHighsOffString); + if (!mipsolver.options_mip_->mip_root_presolve_only && + (5 * intcols.size()) / mipsolver.numCol() >= 1) + lprelax.getLpSolver().setOptionValue("presolve", kHighsOnString); else lprelax.getLpSolver().setBasis( mipsolver.mipdata_->firstrootbasis, "HighsPrimalHeuristics::randomizedRounding"); + HighsLpRelaxation::Status st = lprelax.resolveLp(); if (st == HighsLpRelaxation::Status::kInfeasible) { diff --git a/src/mip/HighsSearch.cpp b/src/mip/HighsSearch.cpp index 3b5497fe5a..4c6f1f0fde 100644 --- a/src/mip/HighsSearch.cpp +++ b/src/mip/HighsSearch.cpp @@ -1530,7 +1530,7 @@ HighsSearch::NodeResult HighsSearch::branch() { std::swap(tmpLp, lp); // reevaluate the node with LP presolve enabled - lp->getLpSolver().setOptionValue("presolve", "on"); + lp->getLpSolver().setOptionValue("presolve", kHighsOnString); result = evaluateNode(); if (result == NodeResult::kOpen) { diff --git a/src/mip/HighsSeparation.cpp b/src/mip/HighsSeparation.cpp index cb5dda1ce5..b125c88df7 100644 --- a/src/mip/HighsSeparation.cpp +++ b/src/mip/HighsSeparation.cpp @@ -23,8 +23,8 @@ #include "mip/HighsTransformedLp.h" HighsSeparation::HighsSeparation(const HighsMipSolver& mipsolver) { - implBoundClock = mipsolver.timer_.clock_def("Implbound sepa", "Ibd"); - cliqueClock = mipsolver.timer_.clock_def("Clique sepa", "Clq"); + implBoundClock = mipsolver.timer_.clock_def("Implbound sepa"); + cliqueClock = mipsolver.timer_.clock_def("Clique sepa"); separators.emplace_back(new HighsTableauSeparator(mipsolver)); separators.emplace_back(new HighsPathSeparator(mipsolver)); separators.emplace_back(new HighsModkSeparator(mipsolver)); diff --git a/src/mip/HighsSeparator.cpp b/src/mip/HighsSeparator.cpp index dd74466d96..8589250d8d 100644 --- a/src/mip/HighsSeparator.cpp +++ b/src/mip/HighsSeparator.cpp @@ -14,9 +14,9 @@ #include "mip/HighsMipSolver.h" HighsSeparator::HighsSeparator(const HighsMipSolver& mipsolver, - const char* name, const char* ch3_name) + const char* name) : numCutsFound(0), numCalls(0) { - clockIndex = mipsolver.timer_.clock_def(name, ch3_name); + clockIndex = mipsolver.timer_.clock_def(name); } void HighsSeparator::run(HighsLpRelaxation& lpRelaxation, diff --git a/src/mip/HighsSeparator.h b/src/mip/HighsSeparator.h index 6a7c1eaf0e..e385538fcf 100644 --- a/src/mip/HighsSeparator.h +++ b/src/mip/HighsSeparator.h @@ -30,8 +30,7 @@ class HighsSeparator { int clockIndex; public: - HighsSeparator(const HighsMipSolver& mipsolver, const char* name, - const char* ch3_name); + HighsSeparator(const HighsMipSolver& mipsolver, const char* name); virtual void separateLpSolution(HighsLpRelaxation& lpRelaxation, HighsLpAggregator& lpAggregator, diff --git a/src/mip/HighsTableauSeparator.h b/src/mip/HighsTableauSeparator.h index 56bb46189e..98d4934206 100644 --- a/src/mip/HighsTableauSeparator.h +++ b/src/mip/HighsTableauSeparator.h @@ -28,7 +28,7 @@ class HighsTableauSeparator : public HighsSeparator { HighsCutPool& cutpool) override; HighsTableauSeparator(const HighsMipSolver& mipsolver) - : HighsSeparator(mipsolver, "Tableau sepa", "Tbl"), numTries(0) {} + : HighsSeparator(mipsolver, "Tableau sepa"), numTries(0) {} }; #endif diff --git a/src/mip/HighsTransformedLp.cpp b/src/mip/HighsTransformedLp.cpp index 7960290227..703b377e09 100644 --- a/src/mip/HighsTransformedLp.cpp +++ b/src/mip/HighsTransformedLp.cpp @@ -175,6 +175,36 @@ bool HighsTransformedLp::transform(std::vector& vals, return false; } + // the code below uses the difference between the column upper and lower + // bounds as the upper bound for the slack from the variable upper bound + // constraint (upper[j] = ub - lb) and thus assumes that the variable upper + // bound constraints are tight. this assumption may not be satisfied when + // new bound changes were derived during cut generation and, therefore, we + // tighten the best variable upper bound. + if (bestVub[col].first != -1 && + bestVub[col].second.maxValue() > ub + mip.mipdata_->feastol) { + bool redundant = false; + bool infeasible = false; + mip.mipdata_->implications.cleanupVub(col, bestVub[col].first, + bestVub[col].second, ub, redundant, + infeasible, false); + } + + // the code below uses the difference between the column upper and lower + // bounds as the upper bound for the slack from the variable lower bound + // constraint (upper[j] = ub - lb) and thus assumes that the variable lower + // bound constraints are tight. this assumption may not be satisfied when + // new bound changes were derived during cut generation and, therefore, we + // tighten the best variable lower bound. + if (bestVlb[col].first != -1 && + bestVlb[col].second.minValue() < lb - mip.mipdata_->feastol) { + bool redundant = false; + bool infeasible = false; + mip.mipdata_->implications.cleanupVlb(col, bestVlb[col].first, + bestVlb[col].second, lb, redundant, + infeasible, false); + } + // store the old bound type so that we can restore it if the continuous // column is relaxed out anyways. This allows to correctly transform and // then untransform multiple base rows which is useful to compute cuts based @@ -190,10 +220,18 @@ bool HighsTransformedLp::transform(std::vector& vals, if (ub - lb <= 1.5 || boundDist[col] != 0.0 || simpleLbDist[col] == 0 || simpleUbDist[col] == 0) { // since we skip the handling of variable bound constraints for all - // binary and some general-integer variables, the bound type used should - // be a simple lower or upper bound - assert(oldBoundType == BoundType::kSimpleLb || - oldBoundType == BoundType::kSimpleUb); + // binary and some general-integer variables here, the bound type used + // should be a simple lower or upper bound + if (simpleLbDist[col] < simpleUbDist[col] - mip.mipdata_->feastol) { + boundTypes[col] = BoundType::kSimpleLb; + } else if (simpleUbDist[col] < + simpleLbDist[col] - mip.mipdata_->feastol) { + boundTypes[col] = BoundType::kSimpleUb; + } else if (vals[i] > 0) { + boundTypes[col] = BoundType::kSimpleLb; + } else { + boundTypes[col] = BoundType::kSimpleUb; + } i++; continue; } diff --git a/src/mip/MipTimer.h b/src/mip/MipTimer.h index bb113ad7aa..6b04972612 100644 --- a/src/mip/MipTimer.h +++ b/src/mip/MipTimer.h @@ -84,7 +84,7 @@ class MipTimer { HighsTimer* timer_pointer = mip_timer_clock.timer_pointer_; std::vector& clock = mip_timer_clock.clock_; clock.resize(kNumMipClock); - clock[kMipClockTotal] = timer_pointer->total_clock; + clock[kMipClockTotal] = 0; clock[kMipClockPresolve] = timer_pointer->clock_def("MIP presolve"); clock[kMipClockSolve] = timer_pointer->clock_def("MIP solve"); clock[kMipClockPostsolve] = timer_pointer->clock_def("MIP postsolve"); @@ -334,7 +334,7 @@ class MipTimer { const bool end_line) { const std::vector mip_clock_list{ kMipClockRunPresolve, kMipClockEvaluateRootNode, - kMipClockPrimalHeuristics, kMipClockTheDive}; + kMipClockPrimalHeuristics, kMipClockTheDive, kMipClockNodeSearch}; csvMipClockList(model_name, mip_clock_list, mip_timer_clock, kMipClockTotal, header, end_line); }; diff --git a/src/parallel/HighsBinarySemaphore.h b/src/parallel/HighsBinarySemaphore.h index 5ca24e0f6b..ee40b5931b 100644 --- a/src/parallel/HighsBinarySemaphore.h +++ b/src/parallel/HighsBinarySemaphore.h @@ -110,4 +110,4 @@ class HighsBinarySemaphore { } }; -#endif \ No newline at end of file +#endif diff --git a/src/parallel/HighsCacheAlign.h b/src/parallel/HighsCacheAlign.h index b16e145a47..90ec627617 100644 --- a/src/parallel/HighsCacheAlign.h +++ b/src/parallel/HighsCacheAlign.h @@ -84,4 +84,4 @@ struct cache_aligned { } // namespace highs -#endif \ No newline at end of file +#endif diff --git a/src/parallel/HighsCombinable.h b/src/parallel/HighsCombinable.h index b7b877189e..ddfa8561e7 100644 --- a/src/parallel/HighsCombinable.h +++ b/src/parallel/HighsCombinable.h @@ -118,4 +118,4 @@ HighsCombinable makeHighsCombinable(FConstruct&& fconstruct) { return HighsCombinable(std::forward(fconstruct)); } -#endif \ No newline at end of file +#endif diff --git a/src/parallel/HighsMutex.h b/src/parallel/HighsMutex.h index 34d8b95541..787b492c9d 100644 --- a/src/parallel/HighsMutex.h +++ b/src/parallel/HighsMutex.h @@ -126,4 +126,4 @@ class HighsMutex { } }; -#endif \ No newline at end of file +#endif diff --git a/src/parallel/HighsRaceTimer.h b/src/parallel/HighsRaceTimer.h index 180b13a0b5..cc1629d293 100644 --- a/src/parallel/HighsRaceTimer.h +++ b/src/parallel/HighsRaceTimer.h @@ -40,4 +40,4 @@ class HighsRaceTimer { } }; -#endif \ No newline at end of file +#endif diff --git a/src/parallel/HighsSchedulerConstants.h b/src/parallel/HighsSchedulerConstants.h index 1121724d9d..ad21fdaf23 100644 --- a/src/parallel/HighsSchedulerConstants.h +++ b/src/parallel/HighsSchedulerConstants.h @@ -21,4 +21,4 @@ struct HighsSchedulerConstants { }; }; -#endif \ No newline at end of file +#endif diff --git a/src/pdlp/cupdlp/cupdlp_utils.c b/src/pdlp/cupdlp/cupdlp_utils.c index 58b14b2ac3..e648e9ad31 100644 --- a/src/pdlp/cupdlp/cupdlp_utils.c +++ b/src/pdlp/cupdlp/cupdlp_utils.c @@ -431,7 +431,7 @@ void PDHG_PrintPDHGParam(CUPDLPwork *w) { cupdlp_printf("\n"); } -void PDHG_PrintHugeCUPDHG() { +void PDHG_PrintHugeCUPDHG(void) { cupdlp_printf("\n"); cupdlp_printf(" ____ _ _ ____ ____ _ ____\n"); cupdlp_printf(" / ___| | | | _ \\| _ \\| | | _ \\\n"); @@ -441,7 +441,7 @@ void PDHG_PrintHugeCUPDHG() { cupdlp_printf("\n"); } -void PDHG_PrintUserParamHelper() { +void PDHG_PrintUserParamHelper(void) { PDHG_PrintHugeCUPDHG(); cupdlp_printf("CUPDHG User Parameters:\n"); diff --git a/src/pdlp/cupdlp/cupdlp_utils.h b/src/pdlp/cupdlp/cupdlp_utils.h index 49c9510a06..337a743c8e 100644 --- a/src/pdlp/cupdlp/cupdlp_utils.h +++ b/src/pdlp/cupdlp/cupdlp_utils.h @@ -37,9 +37,9 @@ cupdlp_int PDHG_Clear(CUPDLPwork *w); void PDHG_PrintPDHGParam(CUPDLPwork *w); -void PDHG_PrintHugeCUPDHG(); +void PDHG_PrintHugeCUPDHG(void); -void PDHG_PrintUserParamHelper(); +void PDHG_PrintUserParamHelper(void); cupdlp_retcode getUserParam(int argc, char **argv, cupdlp_bool *ifChangeIntParam, cupdlp_int *intParam, diff --git a/src/presolve/HPresolve.cpp b/src/presolve/HPresolve.cpp index d7977a0ebb..cc3f3fad8b 100644 --- a/src/presolve/HPresolve.cpp +++ b/src/presolve/HPresolve.cpp @@ -140,7 +140,7 @@ bool HPresolve::okSetInput(HighsLp& model_, const HighsOptions& options_, reductionLimit < kHighsSize_tInf) { highsLogDev(options->log_options, HighsLogType::kInfo, "HPresolve::okSetInput reductionLimit = %d\n", - int(reductionLimit)); + static_cast(reductionLimit)); } return true; } @@ -404,13 +404,9 @@ bool HPresolve::convertImpliedInteger(HighsInt col, HighsInt row, ++rowsizeImplInt[nonzero.index()]; } - // round bounds - double ceilLower = std::ceil(model->col_lower_[col] - primal_feastol); - double floorUpper = std::floor(model->col_upper_[col] + primal_feastol); - - // use tighter bounds - if (ceilLower > model->col_lower_[col]) changeColLower(col, ceilLower); - if (floorUpper < model->col_upper_[col]) changeColUpper(col, floorUpper); + // round and update bounds + changeColLower(col, model->col_lower_[col]); + changeColUpper(col, model->col_upper_[col]); return true; } @@ -458,11 +454,6 @@ void HPresolve::unlink(HighsInt pos) { markChangedCol(Acol[pos]); impliedDualRowBounds.remove(Acol[pos], Arow[pos], Avalue[pos]); - if (colUpperSource[Acol[pos]] == Arow[pos]) - changeImplColUpper(Acol[pos], kHighsInf, -1); - - if (colLowerSource[Acol[pos]] == Arow[pos]) - changeImplColLower(Acol[pos], -kHighsInf, -1); } auto get_row_left = [&](HighsInt pos) -> HighsInt& { return ARleft[pos]; }; @@ -482,14 +473,16 @@ void HPresolve::unlink(HighsInt pos) { else markChangedRow(Arow[pos]); impliedRowBounds.remove(Arow[pos], Acol[pos], Avalue[pos]); + } - if (rowDualUpperSource[Arow[pos]] == Acol[pos]) - changeImplRowDualUpper(Arow[pos], kHighsInf, -1); + // remove implied bounds on row duals that where implied by this column's dual + // constraint + resetRowDualImpliedBoundsDerivedFromCol(Acol[pos]); - if (rowDualLowerSource[Arow[pos]] == Acol[pos]) - changeImplRowDualLower(Arow[pos], -kHighsInf, -1); - } + // remove implied bounds on columns that where implied by this row + resetColImpliedBoundsDerivedFromRow(Arow[pos]); + // remove non-zero Avalue[pos] = 0; freeslots.push_back(pos); @@ -554,8 +547,8 @@ void HPresolve::updateRowDualImpliedBounds(HighsInt row, HighsInt col, double dualRowBnd, double residualAct, HighsInt direction) { if (direction * residualAct <= -kHighsInf) return; - double impliedBound = - double((HighsCDouble(dualRowBnd) - residualAct) / val); + double impliedBound = static_cast( + (static_cast(dualRowBnd) - residualAct) / val); if (std::abs(impliedBound) * kHighsTiny > options->dual_feasibility_tolerance) @@ -600,7 +593,8 @@ void HPresolve::updateColImpliedBounds(HighsInt row, HighsInt col, double val) { double rowBnd, double residualAct, HighsInt direction) { if (direction * residualAct <= -kHighsInf) return; - double impliedBound = double((HighsCDouble(rowBnd) - residualAct) / val); + double impliedBound = static_cast( + (static_cast(rowBnd) - residualAct) / val); if (std::abs(impliedBound) * kHighsTiny > primal_feastol) return; @@ -666,43 +660,60 @@ void HPresolve::updateColImpliedBounds(HighsInt row, HighsInt col, double val) { HighsInt{-1}); } -void HPresolve::recomputeColImpliedBounds(HighsInt row) { - // recompute implied column bounds affected by a modification in a row +void HPresolve::resetColImpliedBounds(HighsInt col, HighsInt row) { + assert(row == -1 || colLowerSource[col] == row || colUpperSource[col] == row); + if (!colDeleted[col]) { + // set implied bounds to infinite values if (1) they were deduced from the + // given row or (2) no row was given + if (colLowerSource[col] != -1 && (row == -1 || colLowerSource[col] == row)) + changeImplColLower(col, -kHighsInf, -1); + if (colUpperSource[col] != -1 && (row == -1 || colUpperSource[col] == row)) + changeImplColUpper(col, kHighsInf, -1); + } else if (row != -1 && !rowDeleted[row]) { + // remove column from row-wise implied bound storage + colImplSourceByRow[row].erase(col); + } +} + +void HPresolve::resetRowDualImpliedBounds(HighsInt row, HighsInt col) { + assert(col == -1 || rowDualLowerSource[row] == col || + rowDualUpperSource[row] == col); + if (!rowDeleted[row]) { + // set implied bounds to infinite values if (1) they were deduced from the + // given column or (2) no column was given + if (rowDualLowerSource[row] != -1 && + (col == -1 || rowDualLowerSource[row] == col)) + changeImplRowDualLower(row, -kHighsInf, -1); + if (rowDualUpperSource[row] != -1 && + (col == -1 || rowDualUpperSource[row] == col)) + changeImplRowDualUpper(row, kHighsInf, -1); + } else if (col != -1 && !colDeleted[col]) { + // remove row from column-wise implied bound storage + implRowDualSourceByCol[col].erase(row); + } +} + +void HPresolve::resetColImpliedBoundsDerivedFromRow(HighsInt row) { + // reset implied column bounds affected by a modification in a row // (removed / added non-zeros, etc.) if (colImplSourceByRow[row].empty()) return; std::set affectedCols(colImplSourceByRow[row]); for (const HighsInt& col : affectedCols) { - // set implied bounds to infinite values if they were deduced from the given - // row - if (colLowerSource[col] == row) changeImplColLower(col, -kHighsInf, -1); - if (colUpperSource[col] == row) changeImplColUpper(col, kHighsInf, -1); - - // iterate over column and recompute the implied bounds - for (const HighsSliceNonzero& nonz : getColumnVector(col)) { - updateColImpliedBounds(nonz.index(), col, nonz.value()); - } + // set implied bounds to infinite values if they were deduced from the + // given row + resetColImpliedBounds(col, row); } } -void HPresolve::recomputeRowDualImpliedBounds(HighsInt col) { - // recompute implied row dual bounds affected by a modification in a column +void HPresolve::resetRowDualImpliedBoundsDerivedFromCol(HighsInt col) { + // reset implied row dual bounds affected by a modification in a column // (removed / added non-zeros, etc.) if (implRowDualSourceByCol[col].empty()) return; std::set affectedRows(implRowDualSourceByCol[col]); for (const HighsInt& row : affectedRows) { - // set implied bounds to infinite values if they were deduced from the given - // column - if (rowDualLowerSource[row] == col) - changeImplRowDualLower(row, -kHighsInf, -1); - if (rowDualUpperSource[row] == col) - changeImplRowDualUpper(row, kHighsInf, -1); - - // iterate over row and recompute the implied bounds - for (const HighsSliceNonzero& nonz : getRowVector(row)) { - // integer columns cannot be used to tighten bounds on dual multipliers - if (model->integrality_[nonz.index()] != HighsVarType::kInteger) - updateRowDualImpliedBounds(row, nonz.index(), nonz.value()); - } + // set implied bounds to infinite values if they were deduced from the + // given column + resetRowDualImpliedBounds(row, col); } } @@ -725,7 +736,8 @@ void HPresolve::shrinkProblem(HighsPostsolveStack& postsolve_stack) { model->num_col_ = 0; std::vector newColIndex(oldNumCol); const bool have_col_names = model->col_names_.size() > 0; - assert(!have_col_names || HighsInt(model->col_names_.size()) == oldNumCol); + assert(!have_col_names || + model->col_names_.size() == static_cast(oldNumCol)); for (HighsInt i = 0; i != oldNumCol; ++i) { if (colDeleted[i]) newColIndex[i] = -1; @@ -768,7 +780,8 @@ void HPresolve::shrinkProblem(HighsPostsolveStack& postsolve_stack) { numDeletedCols = 0; HighsInt oldNumRow = model->num_row_; const bool have_row_names = model->row_names_.size() > 0; - assert(!have_row_names || HighsInt(model->row_names_.size()) == oldNumRow); + assert(!have_row_names || + model->row_names_.size() == static_cast(oldNumRow)); model->num_row_ = 0; std::vector newRowIndex(oldNumRow); for (HighsInt i = 0; i != oldNumRow; ++i) { @@ -1652,23 +1665,25 @@ void HPresolve::addToMatrix(const HighsInt row, const HighsInt col, } link(pos); + + // remove implied bounds on row duals that where implied by this column's + // dual constraint + resetRowDualImpliedBoundsDerivedFromCol(col); + + // remove implied bounds on columns that where implied by this row + resetColImpliedBoundsDerivedFromRow(row); + } else { double sum = Avalue[pos] + val; if (std::abs(sum) <= options->small_matrix_value) { unlink(pos); } else { - // remove implied bounds on the row dual that where implied by this - // columns dual constraint - if (rowDualUpperSource[row] == col) - changeImplRowDualUpper(row, kHighsInf, -1); - - if (rowDualLowerSource[row] == col) - changeImplRowDualLower(row, -kHighsInf, -1); + // remove implied bounds on row duals that where implied by this column's + // dual constraint + resetRowDualImpliedBoundsDerivedFromCol(col); - // remove implied bounds on the column that where implied by this row - if (colUpperSource[col] == row) changeImplColUpper(col, kHighsInf, -1); - - if (colLowerSource[col] == row) changeImplColLower(col, -kHighsInf, -1); + // remove implied bounds on columns that where implied by this row + resetColImpliedBoundsDerivedFromRow(row); // remove the locks and contribution to implied (dual) row bounds, then // add then again @@ -1711,25 +1726,15 @@ void HPresolve::markRowDeleted(HighsInt row) { changedRowFlag[row] = true; rowDeleted[row] = true; ++numDeletedRows; - - // remove row from column-wise implied bound storage - if (rowDualLowerSource[row] != -1) - implRowDualSourceByCol[rowDualLowerSource[row]].erase(row); - if (rowDualUpperSource[row] != -1) - implRowDualSourceByCol[rowDualUpperSource[row]].erase(row); } void HPresolve::markColDeleted(HighsInt col) { assert(!colDeleted[col]); + // prevents col from being added to change vector changedColFlag[col] = true; colDeleted[col] = true; ++numDeletedCols; - // remove column from row-wise implied bound storage - if (colLowerSource[col] != -1) - colImplSourceByRow[colLowerSource[col]].erase(col); - if (colUpperSource[col] != -1) - colImplSourceByRow[colUpperSource[col]].erase(col); } void HPresolve::changeColUpper(HighsInt col, double newUpper) { @@ -1812,11 +1817,15 @@ void HPresolve::changeImplColUpper(HighsInt col, double newUpper, // remember the source of this upper bound, so that we can correctly identify // weak domination - if (oldUpperSource != -1 && oldUpperSource != colLowerSource[col]) - colImplSourceByRow[oldUpperSource].erase(col); - if (originRow != -1) colImplSourceByRow[originRow].emplace(col); + if (oldUpperSource != originRow) { + if (oldUpperSource != -1 && oldUpperSource != colLowerSource[col]) + colImplSourceByRow[oldUpperSource].erase(col); + if (originRow != -1) colImplSourceByRow[originRow].emplace(col); + + colUpperSource[col] = originRow; + } - colUpperSource[col] = originRow; + // update implied bound implColUpper[col] = newUpper; // if the old and the new implied bound are not better than the upper bound, @@ -1852,11 +1861,15 @@ void HPresolve::changeImplColLower(HighsInt col, double newLower, // remember the source of this lower bound, so that we can correctly identify // weak domination - if (oldLowerSource != -1 && oldLowerSource != colUpperSource[col]) - colImplSourceByRow[oldLowerSource].erase(col); - if (originRow != -1) colImplSourceByRow[originRow].emplace(col); + if (oldLowerSource != originRow) { + if (oldLowerSource != -1 && oldLowerSource != colUpperSource[col]) + colImplSourceByRow[oldLowerSource].erase(col); + if (originRow != -1) colImplSourceByRow[originRow].emplace(col); - colLowerSource[col] = originRow; + colLowerSource[col] = originRow; + } + + // update implied bound implColLower[col] = newLower; // if the old and the new implied bound are not better than the lower bound, @@ -1891,12 +1904,15 @@ void HPresolve::changeImplRowDualUpper(HighsInt row, double newUpper, // remember the source of this upper bound, so that we can correctly identify // weak domination - if (rowDualUpperSource[row] != -1 && - rowDualLowerSource[row] != rowDualUpperSource[row]) - implRowDualSourceByCol[rowDualUpperSource[row]].erase(row); - if (originCol != -1) implRowDualSourceByCol[originCol].emplace(row); + if (oldUpperSource != originCol) { + if (oldUpperSource != -1 && oldUpperSource != rowDualLowerSource[row]) + implRowDualSourceByCol[oldUpperSource].erase(row); + if (originCol != -1) implRowDualSourceByCol[originCol].emplace(row); + + rowDualUpperSource[row] = originCol; + } - rowDualUpperSource[row] = originCol; + // update implied bound implRowDualUpper[row] = newUpper; // nothing needs to be updated @@ -1929,12 +1945,15 @@ void HPresolve::changeImplRowDualLower(HighsInt row, double newLower, // remember the source of this lower bound, so that we can correctly identify // weak domination - if (rowDualLowerSource[row] != -1 && - rowDualLowerSource[row] != rowDualUpperSource[row]) - implRowDualSourceByCol[rowDualLowerSource[row]].erase(row); - if (originCol != -1) implRowDualSourceByCol[originCol].emplace(row); + if (oldLowerSource != originCol) { + if (oldLowerSource != -1 && oldLowerSource != rowDualUpperSource[row]) + implRowDualSourceByCol[oldLowerSource].erase(row); + if (originCol != -1) implRowDualSourceByCol[originCol].emplace(row); - rowDualLowerSource[row] = originCol; + rowDualLowerSource[row] = originCol; + } + + // update implied bound implRowDualLower[row] = newLower; // nothing needs to be updated @@ -2052,14 +2071,17 @@ HPresolve::Result HPresolve::applyConflictGraphSubstitutions( return Result::kOk; } -void HPresolve::storeRow(HighsInt row) { - rowpositions.clear(); +void HPresolve::getRowPositions(HighsInt row, + std::vector& myrowpositions) const { + myrowpositions.clear(); - auto rowVec = getSortedRowVector(row); - for (auto iter = rowVec.begin(); iter != rowVec.end(); ++iter) - rowpositions.push_back(iter.position()); + auto rowvector = getSortedRowVector(row); + for (auto rowiter = rowvector.begin(); rowiter != rowvector.end(); ++rowiter) + myrowpositions.push_back(rowiter.position()); } +void HPresolve::storeRow(HighsInt row) { getRowPositions(row, rowpositions); } + HighsTripletPositionSlice HPresolve::getStoredRow() const { return HighsTripletPositionSlice(Acol.data(), Avalue.data(), rowpositions.data(), rowpositions.size()); @@ -2205,7 +2227,7 @@ HighsInt HPresolve::countFillin(HighsInt row) { bool HPresolve::checkFillin(HighsHashTable& fillinCache, HighsInt row, HighsInt col) { // check numerics against markowitz tolerance - assert(int(rowpositions.size()) == rowsize[row]); + assert(rowpositions.size() == static_cast(rowsize[row])); // check fillin against max fillin HighsInt fillin = -(rowsize[row] + colsize[col] - 1); @@ -2275,33 +2297,47 @@ void HPresolve::reinsertEquation(HighsInt row) { void HPresolve::transformColumn(HighsPostsolveStack& postsolve_stack, HighsInt col, double scale, double constant) { + // replace column x by x = scale * x' + constant if (mipsolver != nullptr) mipsolver->mipdata_->implications.columnTransformed(col, scale, constant); postsolve_stack.linearTransform(col, scale, constant); - double oldLower = model->col_lower_[col]; - double oldUpper = model->col_upper_[col]; - model->col_upper_[col] -= constant; - model->col_lower_[col] -= constant; - - for (const HighsSliceNonzero& nonzero : getColumnVector(col)) { - impliedRowBounds.updatedVarLower(nonzero.index(), col, nonzero.value(), - oldLower); - impliedRowBounds.updatedVarUpper(nonzero.index(), col, nonzero.value(), - oldUpper); - } - - double oldImplLower = implColLower[col]; - double oldImplUpper = implColUpper[col]; - implColLower[col] -= constant; - implColUpper[col] -= constant; + // new variable x' has the following bounds: + // scale > 0 --> (lb - constant) / scale <= x' <= (ub - constant) / scale + // scale < 0 --> (ub - constant) / scale <= x' <= (lb - constant) / scale + // each matrix coefficient a will be replaced by scale * a and, therefore, the + // contributions to the constraint activities will change as follows: + // a * lb --> (a * scale) * (lb - constant) / scale = a * (lb - constant) + // a * ub --> (a * scale) * (ub - constant) / scale = a * (ub - constant). + // therefore, for now the scaling can be neglected and the bounds on + // constraint activities can be updated using the constant term. + if (constant != 0.0) { + double oldLower = model->col_lower_[col]; + double oldUpper = model->col_upper_[col]; + model->col_upper_[col] -= constant; + model->col_lower_[col] -= constant; + + for (const HighsSliceNonzero& nonzero : getColumnVector(col)) { + impliedRowBounds.updatedVarLower(nonzero.index(), col, nonzero.value(), + oldLower); + impliedRowBounds.updatedVarUpper(nonzero.index(), col, nonzero.value(), + oldUpper); + } - for (const HighsSliceNonzero& nonzero : getColumnVector(col)) { - impliedRowBounds.updatedImplVarLower(nonzero.index(), col, nonzero.value(), - oldImplLower, colLowerSource[col]); - impliedRowBounds.updatedImplVarUpper(nonzero.index(), col, nonzero.value(), - oldImplUpper, colUpperSource[col]); + double oldImplLower = implColLower[col]; + double oldImplUpper = implColUpper[col]; + implColLower[col] -= constant; + implColUpper[col] -= constant; + + for (const HighsSliceNonzero& nonzero : getColumnVector(col)) { + impliedRowBounds.updatedImplVarLower(nonzero.index(), col, + nonzero.value(), oldImplLower, + colLowerSource[col]); + impliedRowBounds.updatedImplVarUpper(nonzero.index(), col, + nonzero.value(), oldImplUpper, + colUpperSource[col]); + } } // now apply the scaling, which does not change the contributions to the @@ -2314,13 +2350,6 @@ void HPresolve::transformColumn(HighsPostsolveStack& postsolve_stack, model->col_upper_[col] *= boundScale; implColLower[col] *= boundScale; implColUpper[col] *= boundScale; - if (model->integrality_[col] != HighsVarType::kContinuous) { - // we rely on the integrality status being already updated to the newly - // scaled column by the caller, if necessary - model->col_upper_[col] = - std::floor(model->col_upper_[col] + primal_feastol); - model->col_lower_[col] = std::ceil(model->col_lower_[col] - primal_feastol); - } if (scale < 0) { std::swap(model->col_lower_[col], model->col_upper_[col]); @@ -2343,6 +2372,17 @@ void HPresolve::transformColumn(HighsPostsolveStack& postsolve_stack, model->row_upper_[row] -= rowConstant; } + // finally, use utility methods for rounding scaled bounds of + // integer-constrained variables and updating bounds on constraint activities + // accordingly. this should not be done before the preceding bound updates + // (scaling and swaps) and matrix updates. we rely on the integrality status + // being already updated to the newly scaled column by the caller, if + // necessary. + if (model->integrality_[col] != HighsVarType::kContinuous) { + changeColLower(col, model->col_lower_[col]); + changeColUpper(col, model->col_upper_[col]); + } + markChangedCol(col); } @@ -2434,9 +2474,6 @@ void HPresolve::substitute(HighsInt row, HighsInt col, double rhs) { addToMatrix(colrow, Acol[rowiter], scale * Avalue[rowiter]); } - // recompute implied column bounds affected by the substitution - recomputeColImpliedBounds(colrow); - // check if this is an equation row and it now has a different size reinsertEquation(colrow); // printf("after substitution: "); @@ -2448,30 +2485,24 @@ void HPresolve::substitute(HighsInt row, HighsInt col, double rhs) { // substitute column in the objective function if (model->col_cost_[col] != 0.0) { HighsCDouble objscale = model->col_cost_[col] * substrowscale; - model->offset_ = double(model->offset_ - objscale * rhs); + model->offset_ = static_cast(model->offset_ - objscale * rhs); assert(std::isfinite(model->offset_)); for (HighsInt rowiter : rowpositions) { // printf("changing col cost to %g = %g + %g * %g\n", // double(model->col_cost_[Acol[rowiter]] + objscale * Avalue[rowiter]), // model->col_cost_[Acol[rowiter]], double(objscale), Avalue[rowiter]); - model->col_cost_[Acol[rowiter]] = - double(model->col_cost_[Acol[rowiter]] + objscale * Avalue[rowiter]); + model->col_cost_[Acol[rowiter]] = static_cast( + model->col_cost_[Acol[rowiter]] + objscale * Avalue[rowiter]); if (std::abs(model->col_cost_[Acol[rowiter]]) <= options->small_matrix_value) model->col_cost_[Acol[rowiter]] = 0.0; } assert(std::abs(model->col_cost_[col]) <= std::max(options->dual_feasibility_tolerance, - kHighsTiny * std::abs(double(objscale)))); + kHighsTiny * std::abs(static_cast(objscale)))); model->col_cost_[col] = 0.0; } - // recompute implied row dual bounds affected by substitution - for (HighsInt rowiter : rowpositions) { - if (Acol[rowiter] == col) continue; - recomputeRowDualImpliedBounds(Acol[rowiter]); - } - // finally remove the entries of the row that was used for substitution for (HighsInt rowiter : rowpositions) unlink(rowiter); } @@ -2651,23 +2682,27 @@ HPresolve::Result HPresolve::doubletonEq(HighsPostsolveStack& postsolve_stack, // lower(-substcoef/staycoef * substcol) is (-substcoef/staycoef) * // substLower if (-substcoef/staycoef) is positive, i.e. if the coefficients // have opposite sign - stayImplLower = - substLower == -kHighsInf - ? -kHighsInf - : double((HighsCDouble(rhs) - substcoef * substLower) / staycoef); - stayImplUpper = - substUpper == kHighsInf - ? kHighsInf - : double((HighsCDouble(rhs) - substcoef * substUpper) / staycoef); + stayImplLower = substLower == -kHighsInf + ? -kHighsInf + : static_cast((static_cast(rhs) - + substcoef * substLower) / + staycoef); + stayImplUpper = substUpper == kHighsInf + ? kHighsInf + : static_cast((static_cast(rhs) - + substcoef * substUpper) / + staycoef); } else { - stayImplLower = - substUpper == kHighsInf - ? -kHighsInf - : double((HighsCDouble(rhs) - substcoef * substUpper) / staycoef); - stayImplUpper = - substLower == -kHighsInf - ? kHighsInf - : double((HighsCDouble(rhs) - substcoef * substLower) / staycoef); + stayImplLower = substUpper == kHighsInf + ? -kHighsInf + : static_cast((static_cast(rhs) - + substcoef * substUpper) / + staycoef); + stayImplUpper = substLower == -kHighsInf + ? kHighsInf + : static_cast((static_cast(rhs) - + substcoef * substLower) / + staycoef); } // possibly tighten bounds of the column that stays @@ -2970,15 +3005,13 @@ HPresolve::Result HPresolve::rowPresolve(HighsPostsolveStack& postsolve_stack, assert(model->col_cost_[col] != 0.0); if (colsize[col] != 1) return; if (model->col_cost_[col] > 0) { - assert(model->col_lower_[col] == -kHighsInf || - (model->col_lower_[col] <= implColLower[col] + primal_feastol && - colLowerSource[col] == row)); + assert(model->col_lower_[col] == -kHighsInf || !isLowerImplied(col) || + colLowerSource[col] == row); if (model->col_lower_[col] > implColLower[col] - primal_feastol) changeColLower(col, -kHighsInf); } else { - assert(model->col_upper_[col] == kHighsInf || - (model->col_upper_[col] >= implColUpper[col] - primal_feastol && - colUpperSource[col] == row)); + assert(model->col_upper_[col] == kHighsInf || !isUpperImplied(col) || + colUpperSource[col] == row); if (model->col_upper_[col] < implColUpper[col] + primal_feastol) changeColUpper(col, kHighsInf); } @@ -3235,7 +3268,8 @@ HPresolve::Result HPresolve::rowPresolve(HighsPostsolveStack& postsolve_stack, int64_t a1Inverse = HighsIntegers::modularInverse(a1, d); // now compute b = a1^-1 rhs (mod d) - double b = HighsIntegers::mod(a1Inverse * rhs, (double)d); + double b = + HighsIntegers::mod(a1Inverse * rhs, static_cast(d)); // printf( // "substitute integral column x with integral column z with @@ -3322,219 +3356,165 @@ HPresolve::Result HPresolve::rowPresolve(HighsPostsolveStack& postsolve_stack, double intScale = HighsIntegers::integralScale(rowCoefs, deltaDown, deltaUp); - if (intScale != 0.0) { - HighsInt numRowCoefs = rowCoefs.size(); - if (model->row_lower_[row] == -kHighsInf) { - // <= inequality - HighsCDouble rhs = model->row_upper_[row] * intScale; - bool success = true; - double minRhsTightening = 0.0; - double maxVal = 0.0; - for (HighsInt i = 0; i < numRowCoefs; ++i) { - double coef = rowCoefs[i]; - HighsCDouble scaleCoef = HighsCDouble(coef) * intScale; - HighsCDouble intCoef = floor(scaleCoef + 0.5); - HighsCDouble coefDelta = intCoef - scaleCoef; - rowCoefs[i] = double(intCoef); - maxVal = std::max(std::abs(rowCoefs[i]), maxVal); - if (coefDelta < -options->small_matrix_value) { - minRhsTightening = - std::max(-double(coefDelta), minRhsTightening); - } else if (coefDelta > options->small_matrix_value) { - if (model->col_upper_[rowIndex[i]] == kHighsInf) { - success = false; - break; - } - - rhs += model->col_upper_[rowIndex[i]] * coefDelta; - } - } - - if (success) { - HighsCDouble roundRhs = floor(rhs + primal_feastol); - if (rhs - roundRhs >= - minRhsTightening - options->small_matrix_value) { - // scaled and rounded is not weaker than the original constraint - if (maxVal <= 1000.0 || intScale <= 100.0) { - // printf( - // "scaling constraint to integral values with scale %g, " - // "rounded scaled side from %g to %g\n", - // intScale, double(rhs), double(roundRhs)); - // the scale value is reasonably small, change the row values - // to be integral - model->row_upper_[row] = double(roundRhs); - for (HighsInt i = 0; i < numRowCoefs; ++i) { - addToMatrix(row, rowIndex[i], - rowCoefs[i] - Avalue[rowpositions[i]]); - } - } else if (rhs - roundRhs < minRhsTightening - primal_feastol) { - // printf( - // "tightening right hand side from %g to %g due to " - // "rounding with integral scale %g\n", - // model->row_upper_[row], double(roundRhs / intScale), - // intScale); - // scale value is large, so we scale back the altered - // constraint the scaled back constraint must be stronger than - // the original constraint for this to make sense with is - // checked with the condition above - model->row_upper_[row] = double(roundRhs / intScale); - for (HighsInt i = 0; i < numRowCoefs; ++i) { - double delta = double(HighsCDouble(rowCoefs[i]) / intScale - - Avalue[rowpositions[i]]); - if (std::abs(delta) > options->small_matrix_value) - addToMatrix(row, rowIndex[i], delta); + auto roundRhs = [&](HighsCDouble rhs, HighsCDouble& roundedRhs, + HighsCDouble& fractionRhs, double minRhsTightening, + bool& rhsTightened, HighsInt direction) { + // round rhs + roundedRhs = direction * floor(direction * rhs + primal_feastol); + // compute fractional part + fractionRhs = direction * (rhs - roundedRhs); + // check if tightened + rhsTightened = + fractionRhs >= minRhsTightening - options->small_matrix_value; + }; + + auto checkScaleRow = + [&](HighsInt row, HighsCDouble& roundedLhs, + HighsCDouble& roundedRhs, HighsCDouble& fractionLhs, + HighsCDouble& fractionRhs, double& minLhsTightening, + double& minRhsTightening, double& maxVal, bool& lhsTightened, + bool& rhsTightened, bool& isInfeasible, double intScale) { + HighsCDouble lhs = model->row_lower_[row]; + HighsCDouble rhs = model->row_upper_[row]; + bool lhsFinite = lhs != -kHighsInf; + bool rhsFinite = rhs != kHighsInf; + if (lhsFinite) lhs = lhs * intScale; + if (rhsFinite) rhs = rhs * intScale; + roundedLhs = -kHighsInf; + roundedRhs = kHighsInf; + fractionLhs = 0.0; + fractionRhs = 0.0; + minRhsTightening = 0.0; + minLhsTightening = 0.0; + maxVal = 0.0; + lhsTightened = false; + rhsTightened = false; + isInfeasible = false; + for (size_t i = 0; i < rowCoefs.size(); ++i) { + // computed scaled coefficient + HighsCDouble scaleCoef = + static_cast(rowCoefs[i]) * intScale; + // round to the nearest integer + HighsCDouble intCoef = floor(scaleCoef + 0.5); + // compute difference + HighsCDouble coefDelta = intCoef - scaleCoef; + // store integral coefficient and maximum absolute value + rowCoefs[i] = static_cast(intCoef); + maxVal = std::max(std::abs(rowCoefs[i]), maxVal); + // get column upper bound + double ub = model->col_upper_[rowIndex[i]]; + if (coefDelta < -options->small_matrix_value) { + // for the >= side of the constraint a smaller coefficient is + // stronger: Therefore we relax the left hand side using the + // bound constraint, if the bound is infinite, abort + if (lhsFinite) { + if (ub == kHighsInf) return false; + lhs += ub * coefDelta; } - } - } - } - } else if (model->row_upper_[row] == kHighsInf) { - // >= inequality - HighsCDouble rhs = model->row_lower_[row] * intScale; - bool success = true; - double minRhsTightening = 0.0; - double maxVal = 0.0; - for (HighsInt i = 0; i < numRowCoefs; ++i) { - double coef = rowCoefs[i]; - HighsCDouble scaleCoef = HighsCDouble(coef) * intScale; - HighsCDouble intCoef = floor(scaleCoef + 0.5); - HighsCDouble coefDelta = intCoef - scaleCoef; - rowCoefs[i] = double(intCoef); - maxVal = std::max(std::abs(rowCoefs[i]), maxVal); - if (coefDelta < -options->small_matrix_value) { - if (model->col_upper_[rowIndex[i]] == kHighsInf) { - success = false; - break; - } - - rhs += model->col_upper_[rowIndex[i]] * coefDelta; - } else if (coefDelta > options->small_matrix_value) { - minRhsTightening = - std::max(-double(coefDelta), minRhsTightening); - } - } - - if (success) { - HighsCDouble roundRhs = ceil(rhs - primal_feastol); - if (rhs - roundRhs <= - minRhsTightening + options->small_matrix_value) { - // scaled and rounded is not weaker than the original constraint - if (maxVal <= 1000.0 || intScale <= 100.0) { - // printf( - // "scaling constraint to integral values with scale %g, " - // "rounded scaled side from %g to %g\n", - // intScale, double(rhs), double(roundRhs)); - // the scale value is reasonably small, change the row values - // to be integral - model->row_lower_[row] = double(roundRhs); - for (HighsInt i = 0; i < numRowCoefs; ++i) - addToMatrix(row, rowIndex[i], - rowCoefs[i] - Avalue[rowpositions[i]]); - } else if (rhs - roundRhs > minRhsTightening + primal_feastol) { - // scale value is large, so we scale back the altered - // constraint the scaled back constraint must be stronger than - // the original constraint for this to make sense with is - // checked with the condition above - // printf( - // "tightening left hand side from %g to %g due to - // rounding " "with integral scale %g\n", - // model->row_lower_[row], double(roundRhs / intScale), - // intScale); - model->row_lower_[row] = double(roundRhs / intScale); - for (HighsInt i = 0; i < numRowCoefs; ++i) { - double delta = double(HighsCDouble(rowCoefs[i]) / intScale - - Avalue[rowpositions[i]]); - if (std::abs(delta) > options->small_matrix_value) - addToMatrix(row, rowIndex[i], delta); + minRhsTightening = std::max(-static_cast(coefDelta), + minRhsTightening); + } else if (coefDelta > options->small_matrix_value) { + if (rhsFinite) { + if (ub == kHighsInf) return false; + rhs += ub * coefDelta; } + // the coefficient was relaxed regarding the rows lower bound. + // Therefore the lower bound should be tightened by at least + // this amount for the scaled constraint to dominate the + // unscaled constraint be rounded by at least this value + minLhsTightening = std::max(static_cast(coefDelta), + minLhsTightening); } } - } - } else { - // ranged row or equation, can maybe tighten sides and - HighsCDouble lhs = model->row_lower_[row] * intScale; - HighsCDouble rhs = model->row_upper_[row] * intScale; - bool success = true; - double minRhsTightening = 0.0; - double minLhsTightening = 0.0; - double maxVal = 0.0; - for (HighsInt i = 0; i < numRowCoefs; ++i) { - double coef = rowCoefs[i]; - HighsCDouble scaleCoef = HighsCDouble(coef) * intScale; - HighsCDouble intCoef = floor(scaleCoef + 0.5); - HighsCDouble coefDelta = intCoef - scaleCoef; - rowCoefs[i] = double(intCoef); - maxVal = std::max(std::abs(rowCoefs[i]), maxVal); - if (coefDelta < -options->small_matrix_value) { - // for the >= side of the constraint a smaller coefficient is - // stronger: Therefore we relax the left hand side using the - // bound constraint, if the bound is infinite, abort - if (model->col_upper_[rowIndex[i]] == kHighsInf) { - success = false; - break; - } - - lhs += model->col_upper_[rowIndex[i]] * coefDelta; - minRhsTightening = - std::max(-double(coefDelta), minRhsTightening); - } else if (coefDelta > options->small_matrix_value) { - if (model->col_upper_[rowIndex[i]] == kHighsInf) { - success = false; - break; - } - - rhs += model->col_upper_[rowIndex[i]] * coefDelta; + // round left-hand and right-hand sides + if (lhsFinite) + roundRhs(lhs, roundedLhs, fractionLhs, minLhsTightening, + lhsTightened, HighsInt{-1}); + if (rhsFinite) + roundRhs(rhs, roundedRhs, fractionRhs, minRhsTightening, + rhsTightened, HighsInt{1}); + // check for infeasibility + isInfeasible = + lhsFinite && rhsFinite && roundedRhs < roundedLhs - 0.5; + return true; + }; - // the coefficient was relaxed regarding the rows lower bound. - // Therefore the lower bound should be tightened by at least - // this amount for the scaled constraint to dominate the - // unscaled constraint be rounded by at least this value - minLhsTightening = - std::max(double(coefDelta), minLhsTightening); - } - } + auto scaleRow = [&](HighsInt row, HighsCDouble roundedLhs, + HighsCDouble roundedRhs, double scalar, + bool checkDelta) { + // scale the row + if (roundedLhs != -kHighsInf) + model->row_lower_[row] = static_cast(roundedLhs / scalar); + if (roundedRhs != kHighsInf) + model->row_upper_[row] = static_cast(roundedRhs / scalar); + for (size_t i = 0; i < rowCoefs.size(); ++i) { + double delta = static_cast( + static_cast(rowCoefs[i]) / scalar - + Avalue[rowpositions[i]]); + if (!checkDelta || std::fabs(delta) > options->small_matrix_value) + addToMatrix(row, rowIndex[i], delta); + } + }; + + auto scaleRowIntVals = [&](HighsInt row, HighsCDouble roundedLhs, + HighsCDouble roundedRhs, double intScale, + double maxVal) { + // return if maximum value in scaled row or scalar are too large + if (maxVal > 1000.0 && intScale > 100.0) return false; + // the scale value is reasonably small, change the row values to be + // integral + scaleRow(row, roundedLhs, roundedRhs, 1.0, false); + return true; + }; - if (success) { - HighsCDouble roundLhs = ceil(lhs - primal_feastol); - HighsCDouble roundRhs = floor(rhs + primal_feastol); - - // rounded row proves infeasibility regardless of coefficient - // values - if (roundRhs - roundLhs < -0.5) return Result::kPrimalInfeasible; - - if (roundLhs >= intScale * model->row_lower_[row] + - minLhsTightening - - options->small_matrix_value && - roundRhs <= intScale * model->row_upper_[row] - - minRhsTightening + - options->small_matrix_value) { - // scaled row with adjusted coefficients and sides is not weaker - // than the original row - if (maxVal <= 1000.0 || intScale <= 100.0) { - // printf( - // "scaling constraint to integral values with scale %g, " - // "rounded scaled sides from %g to %g and %g to %g\n", - // intScale, double(rhs), double(roundRhs), double(lhs), - // double(roundLhs)); - // the scale value is reasonably small, change the row values - // to be integral - model->row_lower_[row] = double(roundLhs); - model->row_upper_[row] = double(roundRhs); - for (HighsInt i = 0; i < numRowCoefs; ++i) - addToMatrix(row, rowIndex[i], - rowCoefs[i] - Avalue[rowpositions[i]]); - } else { + if (intScale != 0.0) { + HighsCDouble roundedLhs; + HighsCDouble roundedRhs; + HighsCDouble fractionLhs; + HighsCDouble fractionRhs; + double minLhsTightening; + double minRhsTightening; + double maxVal; + bool lhsTightened; + bool rhsTightened; + bool isInfeasible; + if (checkScaleRow(row, roundedLhs, roundedRhs, fractionLhs, + fractionRhs, minLhsTightening, minRhsTightening, + maxVal, lhsTightened, rhsTightened, isInfeasible, + intScale)) { + // check for infeasibility + if (isInfeasible) return Result::kPrimalInfeasible; + // only accept row whose sides were tightened + bool rangedOrEquationRow = lhsTightened && rhsTightened; + if (rangedOrEquationRow || + (lhsTightened && model->row_upper_[row] == kHighsInf) || + (rhsTightened && model->row_lower_[row] == -kHighsInf)) { + // check if constraint can be scaled to integral values + if (!scaleRowIntVals(row, roundedLhs, roundedRhs, intScale, + maxVal)) { + if (rangedOrEquationRow) { + // ranged or equation row // scale value is large, just tighten the sides - roundLhs /= intScale; - roundRhs /= intScale; - if (roundRhs < model->row_upper_[row] - primal_feastol) - model->row_upper_[row] = double(roundRhs); - if (roundLhs > model->row_lower_[row] + primal_feastol) - model->row_lower_[row] = double(roundLhs); + roundedLhs /= intScale; + roundedRhs /= intScale; + if (roundedRhs < model->row_upper_[row] - primal_feastol) + model->row_upper_[row] = static_cast(roundedRhs); + if (roundedLhs > model->row_lower_[row] + primal_feastol) + model->row_lower_[row] = static_cast(roundedLhs); + } else if ((rhsTightened && + fractionRhs < minRhsTightening - primal_feastol) || + (lhsTightened && + fractionLhs < minLhsTightening - primal_feastol)) { + // <= or >= inequality + // scale value is large, so we scale back the altered + // constraint the scaled back constraint must be stronger + // than the original constraint for this to make sense with + // is checked with the condition above + scaleRow(row, roundedLhs, roundedRhs, intScale, true); } } } } - impliedRowUpper = impliedRowBounds.getSumUpper(row); impliedRowLower = impliedRowBounds.getSumLower(row); } @@ -3542,19 +3522,27 @@ HPresolve::Result HPresolve::rowPresolve(HighsPostsolveStack& postsolve_stack, auto strengthenCoefs = [&](HighsCDouble& rhs, HighsInt direction, double maxCoefValue) { - for (const HighsSliceNonzero& nonz : getStoredRow()) { - if (model->integrality_[nonz.index()] == HighsVarType::kContinuous) - continue; - - if (direction * nonz.value() > maxCoefValue + primal_feastol) { - double delta = direction * maxCoefValue - nonz.value(); - addToMatrix(row, nonz.index(), delta); - rhs += delta * model->col_upper_[nonz.index()]; - } else if (direction * nonz.value() < - -maxCoefValue - primal_feastol) { - double delta = -direction * maxCoefValue - nonz.value(); - addToMatrix(row, nonz.index(), delta); - rhs += delta * model->col_lower_[nonz.index()]; + // iterate over non-zero positions instead of iterating over the + // HighsMatrixSlice (provided by HPresolve::getStoredRow) because the + // latter contains pointers to Acol and Avalue that may be invalidated + // if these vectors are reallocated (see std::vector::push_back + // performed in HPresolve::addToMatrix). + for (HighsInt rowiter : rowpositions) { + // get column index and coefficient + HighsInt col = Acol[rowiter]; + double val = Avalue[rowiter]; + + // skip continuous variables + if (model->integrality_[col] == HighsVarType::kContinuous) continue; + + if (direction * val > maxCoefValue + primal_feastol) { + double delta = direction * maxCoefValue - val; + addToMatrix(row, col, delta); + rhs += delta * model->col_upper_[col]; + } else if (direction * val < -maxCoefValue - primal_feastol) { + double delta = -direction * maxCoefValue - val; + addToMatrix(row, col, delta); + rhs += delta * model->col_lower_[col]; } } }; @@ -3565,7 +3553,7 @@ HPresolve::Result HPresolve::rowPresolve(HighsPostsolveStack& postsolve_stack, HighsCDouble rhs = model->row_upper_[row]; strengthenCoefs(rhs, HighsInt{1}, impliedRowUpper - model->row_upper_[row]); - model->row_upper_[row] = double(rhs); + model->row_upper_[row] = static_cast(rhs); } if (model->row_upper_[row] == kHighsInf && @@ -3574,7 +3562,7 @@ HPresolve::Result HPresolve::rowPresolve(HighsPostsolveStack& postsolve_stack, HighsCDouble rhs = model->row_lower_[row]; strengthenCoefs(rhs, HighsInt{-1}, model->row_lower_[row] - impliedRowLower); - model->row_lower_[row] = double(rhs); + model->row_lower_[row] = static_cast(rhs); } } } // if (rowsizeInteger[row] != 0 || rowsizeImplInt[row] != 0) { @@ -3995,11 +3983,9 @@ HPresolve::Result HPresolve::initialRowAndColPresolve( for (HighsInt col = 0; col != model->num_col_; ++col) { if (colDeleted[col]) continue; if (model->integrality_[col] != HighsVarType::kContinuous) { - double ceilLower = std::ceil(model->col_lower_[col] - primal_feastol); - double floorUpper = std::floor(model->col_upper_[col] + primal_feastol); - - if (ceilLower > model->col_lower_[col]) changeColLower(col, ceilLower); - if (floorUpper < model->col_upper_[col]) changeColUpper(col, floorUpper); + // round and update bounds + changeColLower(col, model->col_lower_[col]); + changeColUpper(col, model->col_upper_[col]); } HPRESOLVE_CHECKED_CALL(colPresolve(postsolve_stack, col)); changedColFlag[col] = false; @@ -4085,8 +4071,10 @@ HPresolve::Result HPresolve::presolve(HighsPostsolveStack& postsolve_stack) { #ifndef NDEBUG std::string time_str = " " + std::to_string(run_time) + "s"; #else - std::string time_str = " " + std::to_string(int(run_time)) + "s"; + std::string time_str = + " " + std::to_string(static_cast(run_time)) + "s"; #endif + if (options->timeless_log) time_str = ""; highsLogUser(options->log_options, HighsLogType::kInfo, "%" HIGHSINT_FORMAT " rows, %" HIGHSINT_FORMAT " cols, %" HIGHSINT_FORMAT " nonzeros %s\n", @@ -4098,7 +4086,7 @@ HPresolve::Result HPresolve::presolve(HighsPostsolveStack& postsolve_stack) { // the timer is well defined, and that its total time clock is // running assert(this->timer); - assert(this->timer->runningRunHighsClock()); + assert(this->timer->running()); HPRESOLVE_CHECKED_CALL(initialRowAndColPresolve(postsolve_stack)); @@ -4145,7 +4133,8 @@ HPresolve::Result HPresolve::presolve(HighsPostsolveStack& postsolve_stack) { if (trySparsify) { HighsInt numNz = numNonzeros(); HPRESOLVE_CHECKED_CALL(sparsify(postsolve_stack)); - double nzReduction = 100.0 * (1.0 - (numNonzeros() / (double)numNz)); + double nzReduction = + 100.0 * (1.0 - (numNonzeros() / static_cast(numNz))); if (nzReduction > 0) { highsLogDev(options->log_options, HighsLogType::kInfo, @@ -4182,7 +4171,8 @@ HPresolve::Result HPresolve::presolve(HighsPostsolveStack& postsolve_stack) { if (mipsolver != nullptr) { HighsInt num_strengthened = -1; - HPRESOLVE_CHECKED_CALL(strengthenInequalities(num_strengthened)); + HPRESOLVE_CHECKED_CALL( + strengthenInequalities(postsolve_stack, num_strengthened)); assert(num_strengthened >= 0); if (num_strengthened > 0) highsLogDev(options->log_options, HighsLogType::kInfo, @@ -4354,14 +4344,14 @@ HPresolve::Result HPresolve::checkLimits(HighsPostsolveStack& postsolve_stack) { } if (check_col >= 0 && col_bound_change && debug_report) { printf("After reduction %4d: col = %4d[%s] has bounds [%11.4g, %11.4g]\n", - int(numreductions - 1), int(check_col), + static_cast(numreductions - 1), static_cast(check_col), model->col_names_[check_col].c_str(), model->col_lower_[check_col], model->col_upper_[check_col]); postsolve_stack.debug_prev_numreductions = numreductions; } if (check_row >= 0 && row_bound_change && debug_report) { printf("After reduction %4d: row = %4d[%s] has bounds [%11.4g, %11.4g]\n", - int(numreductions - 1), int(check_row), + static_cast(numreductions - 1), static_cast(check_row), model->row_names_[check_row].c_str(), model->row_lower_[check_row], model->row_upper_[check_row]); postsolve_stack.debug_prev_numreductions = numreductions; @@ -4378,12 +4368,14 @@ void HPresolve::storeCurrentProblemSize() { } double HPresolve::problemSizeReduction() { - double colReduction = 100.0 * - double(oldNumCol - (model->num_col_ - numDeletedCols)) / - oldNumCol; - double rowReduction = 100.0 * - double(oldNumRow - (model->num_row_ - numDeletedRows)) / - oldNumRow; + double colReduction = + 100.0 * + static_cast(oldNumCol - (model->num_col_ - numDeletedCols)) / + oldNumCol; + double rowReduction = + 100.0 * + static_cast(oldNumRow - (model->num_row_ - numDeletedRows)) / + oldNumRow; return std::max(rowReduction, colReduction); } @@ -4540,7 +4532,7 @@ HPresolve::Result HPresolve::removeDependentEquations( highsLogDev(options->log_options, HighsLogType::kInfo, "HPresolve::removeDependentEquations Got %d equations, checking " "for dependent equations\n", - (int)matrix.num_col_); + static_cast(matrix.num_col_)); matrix.num_row_ = model->num_col_ + 1; matrix.start_.resize(matrix.num_col_ + 1); matrix.start_[0] = 0; @@ -4616,11 +4608,11 @@ HPresolve::Result HPresolve::removeDependentEquations( highsLogDev( options->log_options, HighsLogType::kInfo, "HPresolve::removeDependentEquations Removed %d rows and %d nonzeros", - (int)num_removed_row, (int)num_removed_nz); + static_cast(num_removed_row), static_cast(num_removed_nz)); if (num_fictitious_rows_skipped) highsLogDev(options->log_options, HighsLogType::kInfo, ", avoiding %d fictitious rows", - (int)num_fictitious_rows_skipped); + static_cast(num_fictitious_rows_skipped)); highsLogDev(options->log_options, HighsLogType::kInfo, "\n"); analysis_.logging_on_ = logging_on; @@ -4998,8 +4990,8 @@ void HPresolve::fixColToZero(HighsPostsolveStack& postsolve_stack, } void HPresolve::removeRow(HighsInt row) { - assert(row < int(rowroot.size())); assert(row >= 0); + assert(static_cast(row) < rowroot.size()); // first mark the row as logically deleted, so that it is not register as // singleton row upon removing its nonzeros markRowDeleted(row); @@ -5122,7 +5114,7 @@ HPresolve::Result HPresolve::removeDoubletonEquations( } HPresolve::Result HPresolve::strengthenInequalities( - HighsInt& num_strengthened) { + HighsPostsolveStack& postsolve_stack, HighsInt& num_strengthened) { std::vector complementation; std::vector reducedcost; std::vector upper; @@ -5155,9 +5147,11 @@ HPresolve::Result HPresolve::strengthenInequalities( double scale; if (model->row_lower_[row] != -kHighsInf) { + // ax >= lb, treat as -ax <= -lb --> -ax + lb <= 0 maxviolation = model->row_lower_[row]; scale = -1.0; } else { + // ax <= ub --> ax - ub <= 0 maxviolation = -model->row_upper_[row]; scale = 1.0; } @@ -5171,38 +5165,42 @@ HPresolve::Result HPresolve::strengthenInequalities( reducedcost.reserve(rowsize[row]); upper.reserve(rowsize[row]); indices.reserve(rowsize[row]); + positions.reserve(rowsize[row]); stack.reserve(rowsize[row]); stack.push_back(rowroot[row]); bool skiprow = false; while (!stack.empty()) { + // pop element from stack HighsInt pos = stack.back(); stack.pop_back(); + // add non-zeros to stack if (ARright[pos] != -1) stack.push_back(ARright[pos]); if (ARleft[pos] != -1) stack.push_back(ARleft[pos]); - int8_t comp; - double weight; - double ub; - weight = Avalue[pos] * scale; + // get column index HighsInt col = Acol[pos]; - ub = model->col_upper_[col] - model->col_lower_[col]; - skiprow = ub == kHighsInf; + // skip row if a column bound is not finite + skiprow = model->col_lower_[col] == -kHighsInf || + model->col_upper_[col] == kHighsInf; if (skiprow) break; + // compute maximum violation + // scale = 1: ax <= ub --> violation = ax - ub > 0 + // scale = -1: -ax <= -lb --> violation = -ax + lb > 0 + // this means that for scale = 1 we sum up an upper bound on constraint + // activity, and for scale = -1 we sum up a lower bound on constraint + // activity. + int8_t comp; + double weight = Avalue[pos] * scale; + double ub = model->col_upper_[col] - model->col_lower_[col]; if (weight > 0) { - skiprow = model->col_upper_[col] == kHighsInf; - if (skiprow) break; - comp = 1; maxviolation += model->col_upper_[col] * weight; } else { - skiprow = model->col_lower_[col] == -kHighsInf; - if (skiprow) break; - comp = -1; maxviolation += model->col_lower_[col] * weight; weight = -weight; @@ -5232,8 +5230,17 @@ HPresolve::Result HPresolve::strengthenInequalities( continue; } + // maxviolation <= 0 implies that the constraint is redundant: + // scale = 1: upper bound on activity <= model->row_upper_[row] + // scale = -1: model->row_lower_[row] <= lower bound on activity + if (maxviolation <= primal_feastol) { + HPRESOLVE_CHECKED_CALL(rowPresolve(postsolve_stack, row)); + continue; + } + const double smallVal = - std::max(100 * primal_feastol, primal_feastol * double(maxviolation)); + std::max(100 * primal_feastol, + primal_feastol * static_cast(maxviolation)); while (true) { if (maxviolation - continuouscontribution <= smallVal || indices.empty()) break; @@ -5248,12 +5255,13 @@ HPresolve::Result HPresolve::strengthenInequalities( cover.clear(); cover.reserve(indices.size()); - for (HighsInt i = indices.size() - 1; i >= 0; --i) { - double delta = upper[indices[i]] * reducedcost[indices[i]]; + for (size_t i = indices.size(); i > 0; --i) { + HighsInt index = indices[i - 1]; + double delta = upper[index] * reducedcost[index]; - if (upper[indices[i]] <= 1000.0 && reducedcost[indices[i]] > smallVal && + if (upper[index] <= 1000.0 && reducedcost[index] > smallVal && lambda - delta <= smallVal) - cover.push_back(indices[i]); + cover.push_back(index); else lambda -= delta; } @@ -5267,30 +5275,28 @@ HPresolve::Result HPresolve::strengthenInequalities( return reducedcost[i1] < reducedcost[i2]; }); - HighsInt coverend = cover.size(); - double al = reducedcost[alpos]; - coefs.resize(coverend); - double coverrhs = - std::max(std::ceil(double(lambda / al - primal_feastol)), 1.0); + coefs.resize(cover.size()); + double coverrhs = std::max( + std::ceil(static_cast(lambda / al - primal_feastol)), 1.0); HighsCDouble slackupper = -coverrhs; double step = kHighsInf; - for (HighsInt i = 0; i != coverend; ++i) { - coefs[i] = - std::ceil(std::min(reducedcost[cover[i]], double(lambda)) / al - - options->small_matrix_value); + for (size_t i = 0; i != cover.size(); ++i) { + coefs[i] = std::ceil( + std::min(reducedcost[cover[i]], static_cast(lambda)) / al - + options->small_matrix_value); slackupper += upper[cover[i]] * coefs[i]; step = std::min(step, reducedcost[cover[i]] / coefs[i]); } - step = std::min(step, double(maxviolation / coverrhs)); + step = std::min(step, static_cast(maxviolation / coverrhs)); maxviolation -= step * coverrhs; HighsInt slackind = reducedcost.size(); reducedcost.push_back(step); - upper.push_back(double(slackupper)); + upper.push_back(static_cast(slackupper)); - for (HighsInt i = 0; i != coverend; ++i) + for (size_t i = 0; i != cover.size(); ++i) reducedcost[cover[i]] -= step * coefs[i]; indices.erase(std::remove_if(indices.begin(), indices.end(), @@ -5301,48 +5307,44 @@ HPresolve::Result HPresolve::strengthenInequalities( indices.push_back(slackind); } - double threshold = double(maxviolation + primal_feastol); + double threshold = static_cast(maxviolation + primal_feastol); indices.erase(std::remove_if(indices.begin(), indices.end(), [&](HighsInt i) { - return i >= (HighsInt)positions.size() || + return static_cast(i) >= + positions.size() || std::abs(reducedcost[i]) <= threshold; }), indices.end()); if (indices.empty()) continue; - if (scale == -1.0) { - HighsCDouble lhs = model->row_lower_[row]; + auto updateNonZeros = [&](HighsInt row, HighsCDouble& rhs, + HighsInt direction) { for (HighsInt i : indices) { - double coefdelta = double(reducedcost[i] - maxviolation); - HighsInt pos = positions[i]; + assert(Arow[positions[i]] == row); + double coefdelta = + direction * static_cast(reducedcost[i] - maxviolation); + HighsInt col = Acol[positions[i]]; if (complementation[i] == -1) { - lhs -= coefdelta * model->col_lower_[Acol[pos]]; - addToMatrix(row, Acol[pos], -coefdelta); + rhs += coefdelta * model->col_lower_[col]; + addToMatrix(row, col, coefdelta); } else { - lhs += coefdelta * model->col_upper_[Acol[pos]]; - addToMatrix(row, Acol[pos], coefdelta); + rhs -= coefdelta * model->col_upper_[col]; + addToMatrix(row, col, -coefdelta); } } + }; - model->row_lower_[row] = double(lhs); + // update / add non-zeros + if (scale < 0) { + HighsCDouble lhs = model->row_lower_[row]; + updateNonZeros(row, lhs, HighsInt{-1}); + model->row_lower_[row] = static_cast(lhs); } else { HighsCDouble rhs = model->row_upper_[row]; - for (HighsInt i : indices) { - double coefdelta = double(reducedcost[i] - maxviolation); - HighsInt pos = positions[i]; - - if (complementation[i] == -1) { - rhs += coefdelta * model->col_lower_[Acol[pos]]; - addToMatrix(row, Acol[pos], coefdelta); - } else { - rhs -= coefdelta * model->col_upper_[Acol[pos]]; - addToMatrix(row, Acol[pos], -coefdelta); - } - } - - model->row_upper_[row] = double(rhs); + updateNonZeros(row, rhs, HighsInt{1}); + model->row_upper_[row] = static_cast(rhs); } num_strengthened += indices.size(); @@ -5589,8 +5591,9 @@ HPresolve::Result HPresolve::detectParallelRowsAndCols( model->integrality_[parallelColCandidate] != HighsVarType::kInteger; } - double objDiff = double(model->col_cost_[col] * HighsCDouble(colScale) - - model->col_cost_[duplicateCol]); + double objDiff = static_cast( + model->col_cost_[col] * static_cast(colScale) - + model->col_cost_[duplicateCol]); // if (std::abs(objDiff) > options->small_matrix_value) continue; constexpr HighsInt kMergeParallelCols = 0; constexpr HighsInt kDominanceColToUpper = 1; @@ -5692,8 +5695,9 @@ HPresolve::Result HPresolve::detectParallelRowsAndCols( parallel = duplicateColRowPos != -1; if (!parallel) break; - parallel = std::abs(double(Avalue[duplicateColRowPos] - - colScale * colNz.value())) <= + parallel = std::abs(static_cast( + Avalue[duplicateColRowPos] - + static_cast(colScale) * colNz.value())) <= options->small_matrix_value; if (!parallel) break; } @@ -5865,10 +5869,7 @@ HPresolve::Result HPresolve::detectParallelRowsAndCols( // remove implied bounds, since they might in general not be valid // anymore - if (colLowerSource[col] != -1) - changeImplColLower(col, -kHighsInf, -1); - - if (colUpperSource[col] != -1) changeImplColUpper(col, kHighsInf, -1); + resetColImpliedBounds(col); // if an implicit integer and an integer column were merged, check if // merged continuous column is implicit integer after merge @@ -5972,8 +5973,9 @@ HPresolve::Result HPresolve::detectParallelRowsAndCols( parallel = nzPos != -1; if (!parallel) break; - parallel = std::abs(double(Avalue[nzPos] - - HighsCDouble(rowScale) * rowNz.value())) <= + parallel = std::abs(static_cast( + Avalue[nzPos] - + static_cast(rowScale) * rowNz.value())) <= options->small_matrix_value; if (!parallel) break; } @@ -6048,10 +6050,9 @@ HPresolve::Result HPresolve::detectParallelRowsAndCols( model->row_lower_[parallelRowCand] = newLower; } } - if (rowDualLowerSource[parallelRowCand] != -1) - changeImplRowDualLower(parallelRowCand, -kHighsInf, -1); - if (rowDualUpperSource[parallelRowCand] != -1) - changeImplRowDualUpper(parallelRowCand, kHighsInf, -1); + // remove implied bounds, since they might in general not be valid + // anymore + resetRowDualImpliedBounds(parallelRowCand); postsolve_stack.duplicateRow(parallelRowCand, rowUpperTightened, rowLowerTightened, i, rowScale); @@ -6128,25 +6129,35 @@ HPresolve::Result HPresolve::detectParallelRowsAndCols( template HPresolve::Result HPresolve::equalityRowAddition( HighsPostsolveStack& postsolve_stack, HighsInt stayrow, HighsInt removerow, - double scale, const HighsMatrixSlice& vector) { - postsolve_stack.equalityRowAddition(removerow, stayrow, scale, vector); - for (const auto& rowNz : vector) { - HighsInt pos = findNonzero(removerow, rowNz.index()); + double scale, const HighsMatrixSlice& rowvector) { + // extract non-zero positions + std::vector stay_rowpositions; + getRowPositions(stayrow, stay_rowpositions); + + // update postsolve information + postsolve_stack.equalityRowAddition(removerow, stayrow, scale, rowvector); + + // iterate over non-zero positions instead of iterating over the + // HighsMatrixSlice because the latter contains pointers to Acol and Avalue + // that may be invalidated if these vectors are reallocated + // (see std::vector::push_back performed in HPresolve::addToMatrix). + for (HighsInt rowiter : stay_rowpositions) { + HighsInt pos = findNonzero(removerow, Acol[rowiter]); if (pos != -1) unlink(pos); // all common nonzeros are cancelled, as the rows are // parallel else // might introduce a singleton - addToMatrix(removerow, rowNz.index(), scale * rowNz.value()); + addToMatrix(removerow, Acol[rowiter], scale * Avalue[rowiter]); } if (model->row_upper_[removerow] != kHighsInf) - model->row_upper_[removerow] = - double(model->row_upper_[removerow] + - HighsCDouble(scale) * model->row_upper_[stayrow]); + model->row_upper_[removerow] = static_cast( + model->row_upper_[removerow] + + static_cast(scale) * model->row_upper_[stayrow]); if (model->row_lower_[removerow] != -kHighsInf) - model->row_lower_[removerow] = - double(model->row_lower_[removerow] + - HighsCDouble(scale) * model->row_upper_[stayrow]); + model->row_lower_[removerow] = static_cast( + model->row_lower_[removerow] + + static_cast(scale) * model->row_upper_[stayrow]); // row is now a singleton row, doubleton equation, or a row // that contains only singletons and we let the normal row presolve @@ -6286,8 +6297,7 @@ void HPresolve::debug(const HighsLp& lp, const HighsOptions& options) { sol = reducedsol; basis = reducedbasis; - postsolve_stack.undoUntil(options, flagRow, flagCol, sol, basis, - tmp.numReductions()); + postsolve_stack.undoUntil(options, sol, basis, tmp.numReductions()); HighsBasis temp_basis; HighsSolution temp_sol; @@ -6309,6 +6319,7 @@ void HPresolve::debug(const HighsLp& lp, const HighsOptions& options) { temp_sol.row_value.resize(model.num_row_); calculateRowValuesQuad(model, sol); temp_basis.valid = true; + temp_basis.useful = true; refineBasis(model, temp_sol, temp_basis); Highs highs; highs.passOptions(options); @@ -6332,8 +6343,7 @@ void HPresolve::debug(const HighsLp& lp, const HighsOptions& options) { ARstart, ARindex, ARvalue); sol = reducedsol; basis = reducedbasis; - postsolve_stack.undoUntil(options, flagRow, flagCol, sol, basis, - reductionLim); + postsolve_stack.undoUntil(options, sol, basis, reductionLim); calculateRowValuesQuad(model, sol); kktinfo = dev_kkt_check::initInfo(); @@ -6598,7 +6608,8 @@ HighsInt HPresolve::debugGetCheckCol() const { HighsInt check_col = -1; if (check_col_name == "") return check_col; if (model->col_names_.size()) { - if (HighsInt(model->col_hash_.name2index.size()) != model->num_col_) + if (model->col_hash_.name2index.size() != + static_cast(model->num_col_)) model->col_hash_.form(model->col_names_); auto search = model->col_hash_.name2index.find(check_col_name); if (search != model->col_hash_.name2index.end()) { @@ -6614,7 +6625,8 @@ HighsInt HPresolve::debugGetCheckRow() const { HighsInt check_row = -1; if (check_row_name == "") return check_row; if (model->row_names_.size()) { - if (HighsInt(model->row_hash_.name2index.size()) != model->num_row_) + if (model->row_hash_.name2index.size() != + static_cast(model->num_row_)) model->row_hash_.form(model->row_names_); auto search = model->row_hash_.name2index.find(check_row_name); if (search != model->row_hash_.name2index.end()) { diff --git a/src/presolve/HPresolve.h b/src/presolve/HPresolve.h index a64bbf07fb..2240f79981 100644 --- a/src/presolve/HPresolve.h +++ b/src/presolve/HPresolve.h @@ -154,11 +154,15 @@ class HPresolve { void updateColImpliedBounds(HighsInt row, HighsInt col, double val); - void recomputeColImpliedBounds(HighsInt row); + void updateRowDualImpliedBounds(HighsInt row, HighsInt col, double val); - void recomputeRowDualImpliedBounds(HighsInt col); + void resetColImpliedBounds(HighsInt col, HighsInt row = -1); - void updateRowDualImpliedBounds(HighsInt row, HighsInt col, double val); + void resetRowDualImpliedBounds(HighsInt row, HighsInt col = -1); + + void resetColImpliedBoundsDerivedFromRow(HighsInt row); + + void resetRowDualImpliedBoundsDerivedFromCol(HighsInt col); bool rowCoefficientsIntegral(HighsInt row, double scale) const; @@ -212,6 +216,9 @@ class HPresolve { void toCSR(std::vector& ARval, std::vector& ARindex, std::vector& ARstart); + void getRowPositions(HighsInt row, + std::vector& myrowpositions) const; + void storeRow(HighsInt row); HighsTripletPositionSlice getStoredRow() const; @@ -353,7 +360,8 @@ class HPresolve { Result removeDoubletonEquations(HighsPostsolveStack& postsolve_stack); - Result strengthenInequalities(HighsInt& num_strenghtened); + Result strengthenInequalities(HighsPostsolveStack& postsolve_stack, + HighsInt& num_strenghtened); HighsInt detectImpliedIntegers(); diff --git a/src/presolve/HighsPostsolveStack.h b/src/presolve/HighsPostsolveStack.h index bb1b1f785b..e324af710b 100644 --- a/src/presolve/HighsPostsolveStack.h +++ b/src/presolve/HighsPostsolveStack.h @@ -784,9 +784,7 @@ class HighsPostsolveStack { */ // Only used for debugging - void undoUntil(const HighsOptions& options, - const std::vector& flagRow, - const std::vector& flagCol, HighsSolution& solution, + void undoUntil(const HighsOptions& options, HighsSolution& solution, HighsBasis& basis, size_t numReductions) { reductionValues.resetPosition(); diff --git a/src/presolve/ICrashUtil.h b/src/presolve/ICrashUtil.h index 883bc7b270..4383fc4f0c 100644 --- a/src/presolve/ICrashUtil.h +++ b/src/presolve/ICrashUtil.h @@ -59,4 +59,4 @@ void updateResidualFast(const HighsLp& lp, const HighsSolution& sol, // Allows negative residuals void updateResidualIca(const HighsLp& lp, const HighsSolution& sol, std::vector& residual); -#endif \ No newline at end of file +#endif diff --git a/src/presolve/ICrashX.cpp b/src/presolve/ICrashX.cpp index b4eab7d1e3..45e0c9cc5e 100644 --- a/src/presolve/ICrashX.cpp +++ b/src/presolve/ICrashX.cpp @@ -20,12 +20,13 @@ HighsStatus callCrossover(const HighsOptions& options, const HighsLp& lp, HighsModelStatus& model_status, HighsInfo& highs_info, HighsCallback& highs_callback) { ipx::Int num_col, num_row; + double offset; std::vector Ap, Ai; std::vector objective, col_lb, col_ub, Av, rhs; std::vector constraint_type; - fillInIpxData(lp, num_col, num_row, objective, col_lb, col_ub, Ap, Ai, Av, - rhs, constraint_type); + fillInIpxData(lp, num_col, num_row, offset, objective, col_lb, col_ub, Ap, Ai, + Av, rhs, constraint_type); // if (res != IpxStatus::OK) return HighsStatus::kError; const HighsLogOptions& log_options = options.log_options; @@ -55,7 +56,7 @@ HighsStatus callCrossover(const HighsOptions& options, const HighsLp& lp, lps.SetCallback(&highs_callback); ipx::Int load_status = lps.LoadModel( - num_col, objective.data(), col_lb.data(), col_ub.data(), num_row, + num_col, offset, objective.data(), col_lb.data(), col_ub.data(), num_row, Ap.data(), Ai.data(), Av.data(), rhs.data(), constraint_type.data()); if (load_status != 0) { highsLogUser(log_options, HighsLogType::kError, diff --git a/src/qpsolver/a_asm.cpp b/src/qpsolver/a_asm.cpp index 4fb9706c4e..4dc238e0be 100644 --- a/src/qpsolver/a_asm.cpp +++ b/src/qpsolver/a_asm.cpp @@ -47,7 +47,7 @@ std::string qpModelStatusToString(const QpModelStatus qp_model_status) { case QpModelStatus::kNotset: return "Not set"; case QpModelStatus::kUndetermined: - return "Undertermined"; + return "Undetermined"; case QpModelStatus::kOptimal: return "Optimal"; case QpModelStatus::kUnbounded: diff --git a/src/qpsolver/a_quass.cpp b/src/qpsolver/a_quass.cpp index 56ff800596..d60bc999e5 100644 --- a/src/qpsolver/a_quass.cpp +++ b/src/qpsolver/a_quass.cpp @@ -116,6 +116,7 @@ static QpAsmStatus quass2highs(Instance& instance, Settings& settings, } highs_basis.valid = true; highs_basis.alien = false; + highs_basis.useful = true; return qp_asm_return_status; } diff --git a/src/qpsolver/feasibility_highs.hpp b/src/qpsolver/feasibility_highs.hpp index 3164808d0e..4cf349bc4a 100644 --- a/src/qpsolver/feasibility_highs.hpp +++ b/src/qpsolver/feasibility_highs.hpp @@ -58,10 +58,10 @@ static void computeStartingPointHighs( // set HiGHS to be silent highs.setOptionValue("output_flag", false); - highs.setOptionValue("presolve", "on"); + highs.setOptionValue("presolve", kHighsOnString); // Set the residual time limit const double use_time_limit = - std::max(settings.time_limit - timer.readRunHighsClock(), 0.001); + std::max(settings.time_limit - timer.read(), 0.001); highs.setOptionValue("time_limit", use_time_limit); HighsLp lp; diff --git a/src/qpsolver/quass.cpp b/src/qpsolver/quass.cpp index 2f7cd40648..19736c2743 100644 --- a/src/qpsolver/quass.cpp +++ b/src/qpsolver/quass.cpp @@ -31,7 +31,7 @@ static void loginformation(Runtime& rt, Basis& basis, CholeskyFactor& factor, rt.statistics.nullspacedimension.push_back(rt.instance.num_var - basis.getnumactive()); rt.statistics.objval.push_back(rt.instance.objval(rt.primal)); - rt.statistics.time.push_back(timer.readRunHighsClock()); + rt.statistics.time.push_back(timer.read()); SumNum sm = rt.instance.sumnumprimalinfeasibilities(rt.primal, rt.rowactivity); rt.statistics.sum_primal_infeasibilities.push_back(sm.sum); @@ -337,7 +337,7 @@ void Quass::solve(const QpVector& x0, const QpVector& ra, Basis& b0, } // check time limit - if (timer.readRunHighsClock() >= runtime.settings.time_limit) { + if (timer.read() >= runtime.settings.time_limit) { runtime.status = QpModelStatus::kTimeLimit; break; } @@ -350,7 +350,7 @@ void Quass::solve(const QpVector& x0, const QpVector& ra, Basis& b0, } // LOGGING - double run_time = timer.readRunHighsClock(); + double run_time = timer.read(); if ((runtime.statistics.num_iterations % runtime.settings.reportingfequency == 0 || diff --git a/src/simplex/HApp.h b/src/simplex/HApp.h index 9fc35589b4..178593cbc6 100644 --- a/src/simplex/HApp.h +++ b/src/simplex/HApp.h @@ -136,6 +136,22 @@ inline HighsStatus solveLpSimplex(HighsLpSolverObject& solver_object) { // If new scaling is performed, the hot start information is // no longer valid if (new_scaling) ekk_instance.clearHotStart(); + // + if (!status.has_basis && !basis.valid && basis.useful) { + // There is no simplex basis, but there is a useful HiGHS basis + // that is not validated + assert(basis.col_status.size() == + static_cast(incumbent_lp.num_col_)); + assert(basis.row_status.size() == + static_cast(incumbent_lp.num_row_)); + HighsStatus return_status = formSimplexLpBasisAndFactor(solver_object); + if (return_status != HighsStatus::kOk) + return returnFromSolveLpSimplex(solver_object, HighsStatus::kError); + // formSimplexLpBasisAndFactor may introduce variables with + // HighsBasisStatus::kNonbasic, so refine it + refineBasis(incumbent_lp, solution, basis); + basis.valid = true; + } // Move the LP to EKK, updating other EKK pointers and any simplex // NLA pointers, since they may have moved if the LP has been // modified diff --git a/src/simplex/HEkk.cpp b/src/simplex/HEkk.cpp index 83cdd6159e..95121d9536 100644 --- a/src/simplex/HEkk.cpp +++ b/src/simplex/HEkk.cpp @@ -1105,13 +1105,13 @@ HighsStatus HEkk::solve(const bool force_phase2) { if (simplex_strategy == kSimplexStrategyDualTasks) { highsLogUser(options_->log_options, HighsLogType::kInfo, "Using EKK parallel dual simplex solver - SIP with " - "concurrency of %" HIGHSINT_FORMAT "\n", - info_.num_concurrency); + "concurrency of %d\n", + int(info_.num_concurrency)); } else if (simplex_strategy == kSimplexStrategyDualMulti) { highsLogUser(options_->log_options, HighsLogType::kInfo, "Using EKK parallel dual simplex solver - PAMI with " - "concurrency of %" HIGHSINT_FORMAT "\n", - info_.num_concurrency); + "concurrency of %d\n", + int(info_.num_concurrency)); } else { highsLogUser(options_->log_options, HighsLogType::kInfo, "Using EKK dual simplex solver - serial\n"); @@ -1465,6 +1465,7 @@ HighsBasis HEkk::getHighsBasis(HighsLp& use_lp) const { } highs_basis.valid = true; highs_basis.alien = false; + highs_basis.useful = true; highs_basis.was_alien = false; highs_basis.debug_id = (HighsInt)(build_synthetic_tick_ + total_synthetic_tick_); @@ -3468,7 +3469,7 @@ bool HEkk::bailout() { model_status_ == HighsModelStatus::kObjectiveBound || model_status_ == HighsModelStatus::kObjectiveTarget); } else if (options_->time_limit < kHighsInf && - timer_->readRunHighsClock() > options_->time_limit) { + timer_->read() > options_->time_limit) { solve_bailout_ = true; model_status_ = HighsModelStatus::kTimeLimit; } else if (iteration_count_ >= options_->simplex_iteration_limit) { @@ -4421,12 +4422,14 @@ void HEkk::unitBtranResidual(const HighsInt row_out, const HVector& row_ep, void HighsSimplexStats::report(FILE* file, std::string message) const { fprintf(file, "\nSimplex stats: %s\n", message.c_str()); fprintf(file, " valid = %d\n", this->valid); - fprintf(file, " iteration_count = %d\n", this->iteration_count); - fprintf(file, " num_invert = %d\n", this->num_invert); + fprintf(file, " iteration_count = %d\n", + static_cast(this->iteration_count)); + fprintf(file, " num_invert = %d\n", + static_cast(this->num_invert)); fprintf(file, " last_invert_num_el = %d\n", - this->last_invert_num_el); + static_cast(this->last_invert_num_el)); fprintf(file, " last_factored_basis_num_el = %d\n", - this->last_factored_basis_num_el); + static_cast(this->last_factored_basis_num_el)); fprintf(file, " col_aq_density = %g\n", this->col_aq_density); fprintf(file, " row_ep_density = %g\n", this->row_ep_density); fprintf(file, " row_ap_density = %g\n", this->row_ap_density); diff --git a/src/simplex/HEkkPrimal.cpp b/src/simplex/HEkkPrimal.cpp index 1c39033e7e..6c12ef3c77 100644 --- a/src/simplex/HEkkPrimal.cpp +++ b/src/simplex/HEkkPrimal.cpp @@ -1212,11 +1212,11 @@ void HEkkPrimal::phase1ChooseRow() { analysis->simplexTimerStart(Chuzr2Clock); pdqsort(ph1SorterR.begin(), ph1SorterR.end()); - double dMaxTheta = ph1SorterR.at(0).first; + double dMaxTheta = ph1SorterR[0].first; double dGradient = fabs(theta_dual); for (size_t i = 0; i < ph1SorterR.size(); i++) { - double dMyTheta = ph1SorterR.at(i).first; - HighsInt index = ph1SorterR.at(i).second; + double dMyTheta = ph1SorterR[i].first; + HighsInt index = ph1SorterR[i].second; HighsInt iRow = index >= 0 ? index : index + num_row; dGradient -= fabs(col_aq.array[iRow]); // Stop when the gradient start to decrease @@ -1231,8 +1231,8 @@ void HEkkPrimal::phase1ChooseRow() { double dMaxAlpha = 0.0; size_t iLast = ph1SorterT.size(); for (size_t i = 0; i < ph1SorterT.size(); i++) { - double dMyTheta = ph1SorterT.at(i).first; - HighsInt index = ph1SorterT.at(i).second; + double dMyTheta = ph1SorterT[i].first; + HighsInt index = ph1SorterT[i].second; HighsInt iRow = index >= 0 ? index : index + num_row; double dAbsAlpha = fabs(col_aq.array[iRow]); // Stop when the theta is too large @@ -1251,7 +1251,7 @@ void HEkkPrimal::phase1ChooseRow() { variable_out = -1; move_out = 0; for (size_t i = iLast; i > 0; i--) { - HighsInt index = ph1SorterT.at(i - 1).second; + HighsInt index = ph1SorterT[i - 1].second; HighsInt iRow = index >= 0 ? index : index + num_row; double dAbsAlpha = fabs(col_aq.array[iRow]); if (dAbsAlpha > dMaxAlpha * 0.1) { @@ -1931,13 +1931,13 @@ void HEkkPrimal::considerInfeasibleValueIn() { // Perturb the upper bound to accommodate the infeasibility shiftBound(false, variable_in, value_in, info.numTotRandomValue_[variable_in], - info.workUpper_[variable_in], bound_shift, true); + info.workUpper_[variable_in], bound_shift); info.workUpperShift_[variable_in] += bound_shift; } else { // Perturb the lower bound to accommodate the infeasibility shiftBound(true, variable_in, value_in, info.numTotRandomValue_[variable_in], - info.workLower_[variable_in], bound_shift, true); + info.workLower_[variable_in], bound_shift); info.workLowerShift_[variable_in] += bound_shift; } info.bounds_perturbed = true; @@ -2010,14 +2010,14 @@ void HEkkPrimal::phase2UpdatePrimal(const bool initialise) { // Perturb the upper bound to accommodate the infeasibility shiftBound(false, iCol, info.baseValue_[iRow], info.numTotRandomValue_[iCol], info.workUpper_[iCol], - bound_shift, true); + bound_shift); info.baseUpper_[iRow] = info.workUpper_[iCol]; info.workUpperShift_[iCol] += bound_shift; } else { // Perturb the lower bound to accommodate the infeasibility shiftBound(true, iCol, info.baseValue_[iRow], info.numTotRandomValue_[iCol], info.workLower_[iCol], - bound_shift, true); + bound_shift); info.baseLower_[iRow] = info.workLower_[iCol]; info.workLowerShift_[iCol] += bound_shift; } @@ -2076,14 +2076,14 @@ bool HEkkPrimal::correctPrimal(const bool initialise) { // Perturb the upper bound to accommodate the infeasibility shiftBound(false, iCol, info.baseValue_[iRow], info.numTotRandomValue_[iCol], info.workUpper_[iCol], - bound_shift, true); + bound_shift); info.baseUpper_[iRow] = info.workUpper_[iCol]; info.workUpperShift_[iCol] += bound_shift; } else { // Perturb the lower bound to accommodate the infeasibility shiftBound(true, iCol, info.baseValue_[iRow], info.numTotRandomValue_[iCol], info.workLower_[iCol], - bound_shift, true); + bound_shift); info.baseLower_[iRow] = info.workLower_[iCol]; info.workLowerShift_[iCol] += bound_shift; } @@ -2792,7 +2792,16 @@ void HEkkPrimal::getBasicPrimalInfeasibility() { void HEkkPrimal::shiftBound(const bool lower, const HighsInt iVar, const double value, const double random_value, - double& bound, double& shift, const bool report) { + double& bound, double& shift) { + // If infeasibility is very large, then adding feasibility may not + // yield a new value (see #1144) so new_infeasibility < 0 is false, + // tripping the old assert + // + // Ambros proposed adding feasibility + // *(infeasibility/scale_threshold) when + // infeasibility/scale_threshold > 1, but this could lead to a large + // value for new_infeasibility. Sounds better to accept degeneracy + // in this edge case. double feasibility = (1 + random_value) * primal_feasibility_tolerance; double old_bound = bound; std::string type; @@ -2805,20 +2814,10 @@ void HEkkPrimal::shiftBound(const bool lower, const HighsInt iVar, infeasibility = bound - value; assert(infeasibility > 0); // Determine the amount by which value will be feasible - so that - // it's not degenerate + // (ideally) it's not degenerate shift = infeasibility + feasibility; bound -= shift; new_infeasibility = bound - value; - if (new_infeasibility >= 0) { - printf( - "HEkkPrimal::shiftBound LB = %g; random_value = %g; value = %g; " - "feasibility = %g; infeasibility = %g; shift = %g; bound = %g; " - "new_infeasibility = %g; \n", - old_bound, random_value, value, feasibility, infeasibility, shift, - bound, new_infeasibility); - fflush(stdout); - } - assert(new_infeasibility < 0); } else { // Bound to shift is upper type = "upper"; @@ -2826,20 +2825,26 @@ void HEkkPrimal::shiftBound(const bool lower, const HighsInt iVar, infeasibility = value - bound; assert(infeasibility > 0); // Determine the amount by which value will be feasible - so that - // it's not degenerate + // (ideally) it's not degenerate shift = infeasibility + feasibility; bound += shift; new_infeasibility = value - bound; - assert(new_infeasibility < 0); - } - double error = fabs(-new_infeasibility - feasibility); - if (report) - highsLogDev(ekk_instance_.options_->log_options, HighsLogType::kVerbose, - "Value(%4" HIGHSINT_FORMAT - ") = %10.4g exceeds %s = %10.4g by %9.4g, so shift bound by " - "%9.4g to %10.4g: infeasibility %10.4g with error %g\n", - iVar, value, type.c_str(), old_bound, infeasibility, shift, - bound, new_infeasibility, error); + } + if (new_infeasibility > 0) { + // new_infeasibility should be non-positive, and negative unless + // bound is excessively large, whereas feasibility is positive + double error = std::fabs(new_infeasibility + feasibility); + highsLogDev(ekk_instance_.options_->log_options, HighsLogType::kInfo, + "HEkkPrimal::shiftBound Value(%4d) = %10.4g exceeds %s: " + "random_value = %g; value = %g; " + "feasibility = %g; infeasibility = %g; shift = %g; bound = %g; " + "new_infeasibility = %g with error %g\n", + int(iVar), value, type.c_str(), old_bound, random_value, value, + feasibility, infeasibility, shift, bound, new_infeasibility, + error); + fflush(stdout); + } + assert(new_infeasibility <= 0); } void HEkkPrimal::savePrimalRay() { diff --git a/src/simplex/HEkkPrimal.h b/src/simplex/HEkkPrimal.h index cf43716ccc..242e1643c2 100644 --- a/src/simplex/HEkkPrimal.h +++ b/src/simplex/HEkkPrimal.h @@ -101,8 +101,7 @@ class HEkkPrimal { void getBasicPrimalInfeasibility(); bool correctPrimal(const bool initialise = false); void shiftBound(const bool lower, const HighsInt iVar, const double value, - const double random_value, double& bound, double& shift, - const bool report = false); + const double random_value, double& bound, double& shift); void savePrimalRay(); HighsDebugStatus debugPrimalSimplex(const std::string message, const bool initialise = false); diff --git a/src/simplex/HighsSimplexAnalysis.cpp b/src/simplex/HighsSimplexAnalysis.cpp index 6e326d5c3e..e876194396 100644 --- a/src/simplex/HighsSimplexAnalysis.cpp +++ b/src/simplex/HighsSimplexAnalysis.cpp @@ -36,6 +36,7 @@ void HighsSimplexAnalysis::setup(const std::string lp_name, const HighsLp& lp, kHighsAnalysisLevelNlaData & options.highs_analysis_level; analyse_simplex_data = analyse_simplex_summary_data || analyse_simplex_runtime_data; + highs_run_time = 0; last_user_log_time = -kHighsInf; delta_user_log_time = 5e0; @@ -54,6 +55,7 @@ void HighsSimplexAnalysis::setup(const std::string lp_name, const HighsLp& lp, // AnIterNumCostlyDseIt = 0; // Copy messaging parameter from options messaging(options.log_options); + timeless_log = options.timeless_log; // Initialise the densities col_aq_density = 0; row_ep_density = 0; @@ -380,13 +382,13 @@ void HighsSimplexAnalysis::userInvertReport(const bool force) { void HighsSimplexAnalysis::userInvertReport(const bool header, const bool force) { - const double highs_run_time = timer_->readRunHighsClock(); + highs_run_time = timeless_log ? highs_run_time + 1 : timer_->read(); if (!force && highs_run_time < last_user_log_time + delta_user_log_time) return; analysis_log = std::unique_ptr(new std::stringstream()); reportIterationObjective(header); reportInfeasibility(header); - reportRunTime(header, highs_run_time); + if (!timeless_log) reportRunTime(header, highs_run_time); highsLogUser(log_options, HighsLogType::kInfo, "%s\n", analysis_log->str().c_str()); if (!header) last_user_log_time = highs_run_time; diff --git a/src/simplex/HighsSimplexAnalysis.h b/src/simplex/HighsSimplexAnalysis.h index 34802614f3..94a0292a67 100644 --- a/src/simplex/HighsSimplexAnalysis.h +++ b/src/simplex/HighsSimplexAnalysis.h @@ -152,8 +152,10 @@ class HighsSimplexAnalysis { max_sum_average_log_extreme_dual_steepest_edge_weight_error(0.0), num_invert_report_since_last_header(-1), num_iteration_report_since_last_header(-1), + highs_run_time(0.0), last_user_log_time(-kHighsInf), delta_user_log_time(1e0), + timeless_log(false), average_concurrency(0.0), average_fraction_of_possible_minor_iterations_performed(0.0), sum_multi_chosen(0), @@ -428,8 +430,10 @@ class HighsSimplexAnalysis { HighsInt num_invert_report_since_last_header; HighsInt num_iteration_report_since_last_header; + double highs_run_time; double last_user_log_time; double delta_user_log_time; + bool timeless_log; double average_concurrency; double average_fraction_of_possible_minor_iterations_performed; diff --git a/src/simplex/SimplexTimer.h b/src/simplex/SimplexTimer.h index 78183ec349..f33612125d 100644 --- a/src/simplex/SimplexTimer.h +++ b/src/simplex/SimplexTimer.h @@ -120,116 +120,101 @@ class SimplexTimer { HighsTimer* timer_pointer = simplex_timer_clock.timer_pointer_; std::vector& clock = simplex_timer_clock.clock_; clock.resize(SimplexNumClock); - clock[SimplexTotalClock] = timer_pointer->clock_def("Simplex total", "STT"); - clock[SimplexIzDseWtClock] = timer_pointer->clock_def("Iz DSE Wt", "IWT"); - clock[SimplexDualPhase1Clock] = - timer_pointer->clock_def("Dual Phase 1", "DP1"); - clock[SimplexDualPhase2Clock] = - timer_pointer->clock_def("Dual Phase 2", "DP2"); + clock[SimplexTotalClock] = timer_pointer->clock_def("Simplex total"); + clock[SimplexIzDseWtClock] = timer_pointer->clock_def("Iz DSE Wt"); + clock[SimplexDualPhase1Clock] = timer_pointer->clock_def("Dual Phase 1"); + clock[SimplexDualPhase2Clock] = timer_pointer->clock_def("Dual Phase 2"); clock[SimplexPrimalPhase1Clock] = - timer_pointer->clock_def("Primal Phase 1", "PP1"); + timer_pointer->clock_def("Primal Phase 1"); clock[SimplexPrimalPhase2Clock] = - timer_pointer->clock_def("Primal Phase 2", "PP2"); - clock[Group1Clock] = timer_pointer->clock_def("GROUP1", "GP1"); - clock[IterateClock] = timer_pointer->clock_def("ITERATE", "ITR"); - clock[IterateDualRebuildClock] = - timer_pointer->clock_def("DUAL REBUILD", "DRB"); + timer_pointer->clock_def("Primal Phase 2"); + clock[Group1Clock] = timer_pointer->clock_def("GROUP1"); + clock[IterateClock] = timer_pointer->clock_def("ITERATE"); + clock[IterateDualRebuildClock] = timer_pointer->clock_def("DUAL REBUILD"); clock[IteratePrimalRebuildClock] = - timer_pointer->clock_def("PRIMAL REBUILD", "PRB"); - clock[IterateChuzrClock] = timer_pointer->clock_def("CHUZR", "CZR"); - clock[IterateChuzcClock] = timer_pointer->clock_def("CHUZC", "CZC"); - clock[IterateFtranClock] = timer_pointer->clock_def("FTRAN", "FTR"); - clock[IterateVerifyClock] = timer_pointer->clock_def("VERIFY", "VRF"); - clock[IterateDualClock] = timer_pointer->clock_def("DUAL", "UDU"); - clock[IteratePrimalClock] = timer_pointer->clock_def("PRIMAL", "UPR"); - clock[IterateDevexIzClock] = timer_pointer->clock_def("DEVEX_IZ", "DVI"); - clock[IteratePivotsClock] = timer_pointer->clock_def("PIVOTS", "PIV"); + timer_pointer->clock_def("PRIMAL REBUILD"); + clock[IterateChuzrClock] = timer_pointer->clock_def("CHUZR"); + clock[IterateChuzcClock] = timer_pointer->clock_def("CHUZC"); + clock[IterateFtranClock] = timer_pointer->clock_def("FTRAN"); + clock[IterateVerifyClock] = timer_pointer->clock_def("VERIFY"); + clock[IterateDualClock] = timer_pointer->clock_def("DUAL"); + clock[IteratePrimalClock] = timer_pointer->clock_def("PRIMAL"); + clock[IterateDevexIzClock] = timer_pointer->clock_def("DEVEX_IZ"); + clock[IteratePivotsClock] = timer_pointer->clock_def("PIVOTS"); clock[initialiseSimplexLpBasisAndFactorClock] = - timer_pointer->clock_def("IZ_SIMPLEX_LP_DEF", "ISD"); + timer_pointer->clock_def("IZ_SIMPLEX_LP_DEF"); clock[allocateSimplexArraysClock] = - timer_pointer->clock_def("ALLOC_SIMPLEX_ARRS", "ASA"); + timer_pointer->clock_def("ALLOC_SIMPLEX_ARRS"); clock[initialiseSimplexCostBoundsClock] = - timer_pointer->clock_def("IZ_SIMPLEX_CO_BD", "ICB"); - clock[ScaleClock] = timer_pointer->clock_def("SCALE", "SCL"); - clock[CrashClock] = timer_pointer->clock_def("CRASH", "CSH"); - clock[BasisConditionClock] = - timer_pointer->clock_def("BASIS_CONDITION", "CON"); - clock[matrixSetupClock] = timer_pointer->clock_def("MATRIX_SETUP", "FST"); - clock[setNonbasicMoveClock] = - timer_pointer->clock_def("SET_NONBASICMOVE", "SNM"); - clock[DseIzClock] = timer_pointer->clock_def("DSE_IZ", "DEI"); - clock[InvertClock] = timer_pointer->clock_def("INVERT", "INV"); - clock[PermWtClock] = timer_pointer->clock_def("PERM_WT", "PWT"); - clock[ComputeDualClock] = timer_pointer->clock_def("COMPUTE_DUAL", "CPD"); - clock[CorrectDualClock] = timer_pointer->clock_def("CORRECT_DUAL", "CRD"); - clock[ComputePrimalClock] = - timer_pointer->clock_def("COMPUTE_PRIMAL", "CPP"); - clock[CollectPrIfsClock] = - timer_pointer->clock_def("COLLECT_PR_IFS", "IFS"); - clock[ComputePrIfsClock] = - timer_pointer->clock_def("COMPUTE_PR_IFS", "PIF"); - clock[ComputeDuIfsClock] = - timer_pointer->clock_def("COMPUTE_DU_IFS", "DIF"); - clock[ComputeDuObjClock] = - timer_pointer->clock_def("COMPUTE_DU_OBJ", "DOB"); - clock[ComputePrObjClock] = - timer_pointer->clock_def("COMPUTE_PR_OBJ", "POB"); - clock[ReportRebuildClock] = - timer_pointer->clock_def("REPORT_REBUILD", "RPR"); - clock[ChuzrDualClock] = timer_pointer->clock_def("CHUZR_DUAL", "CRD"); - clock[Chuzr1Clock] = timer_pointer->clock_def("CHUZR1", "CR1"); - clock[Chuzr2Clock] = timer_pointer->clock_def("CHUZR2", "CR2"); - clock[ChuzcPrimalClock] = timer_pointer->clock_def("CHUZC_PRIMAL", "CCP"); + timer_pointer->clock_def("IZ_SIMPLEX_CO_BD"); + clock[ScaleClock] = timer_pointer->clock_def("SCALE"); + clock[CrashClock] = timer_pointer->clock_def("CRASH"); + clock[BasisConditionClock] = timer_pointer->clock_def("BASIS_CONDITION"); + clock[matrixSetupClock] = timer_pointer->clock_def("MATRIX_SETUP"); + clock[setNonbasicMoveClock] = timer_pointer->clock_def("SET_NONBASICMOVE"); + clock[DseIzClock] = timer_pointer->clock_def("DSE_IZ"); + clock[InvertClock] = timer_pointer->clock_def("INVERT"); + clock[PermWtClock] = timer_pointer->clock_def("PERM_WT"); + clock[ComputeDualClock] = timer_pointer->clock_def("COMPUTE_DUAL"); + clock[CorrectDualClock] = timer_pointer->clock_def("CORRECT_DUAL"); + clock[ComputePrimalClock] = timer_pointer->clock_def("COMPUTE_PRIMAL"); + clock[CollectPrIfsClock] = timer_pointer->clock_def("COLLECT_PR_IFS"); + clock[ComputePrIfsClock] = timer_pointer->clock_def("COMPUTE_PR_IFS"); + clock[ComputeDuIfsClock] = timer_pointer->clock_def("COMPUTE_DU_IFS"); + clock[ComputeDuObjClock] = timer_pointer->clock_def("COMPUTE_DU_OBJ"); + clock[ComputePrObjClock] = timer_pointer->clock_def("COMPUTE_PR_OBJ"); + clock[ReportRebuildClock] = timer_pointer->clock_def("REPORT_REBUILD"); + clock[ChuzrDualClock] = timer_pointer->clock_def("CHUZR_DUAL"); + clock[Chuzr1Clock] = timer_pointer->clock_def("CHUZR1"); + clock[Chuzr2Clock] = timer_pointer->clock_def("CHUZR2"); + clock[ChuzcPrimalClock] = timer_pointer->clock_def("CHUZC_PRIMAL"); clock[ChuzcHyperInitialiselClock] = - timer_pointer->clock_def("CHUZC_HYPER_IZ", "CHI"); + timer_pointer->clock_def("CHUZC_HYPER_IZ"); clock[ChuzcHyperBasicFeasibilityChangeClock] = - timer_pointer->clock_def("CHUZC_HYPER_FEAS", "CHF"); - clock[ChuzcHyperDualClock] = - timer_pointer->clock_def("CHUZC_HYPER_DUAL", "CHD"); - clock[ChuzcHyperClock] = timer_pointer->clock_def("CHUZC_HYPER", "CHC"); - clock[Chuzc0Clock] = timer_pointer->clock_def("CHUZC0", "CC0"); - clock[PriceChuzc1Clock] = timer_pointer->clock_def("PRICE_CHUZC1", "PC1"); - clock[Chuzc1Clock] = timer_pointer->clock_def("CHUZC1", "CC1"); - clock[Chuzc2Clock] = timer_pointer->clock_def("CHUZC2", "CC2"); - clock[Chuzc3Clock] = timer_pointer->clock_def("CHUZC3", "CC3"); - clock[Chuzc4Clock] = timer_pointer->clock_def("CHUZC4", "CC4"); - clock[Chuzc4a0Clock] = timer_pointer->clock_def("CHUZC4a0", "C40"); - clock[Chuzc4a1Clock] = timer_pointer->clock_def("CHUZC4a1", "C41"); - clock[Chuzc4bClock] = timer_pointer->clock_def("CHUZC4b", "C4b"); - clock[Chuzc4cClock] = timer_pointer->clock_def("CHUZC4c", "C4c"); - clock[Chuzc4dClock] = timer_pointer->clock_def("CHUZC4d", "C4d"); - clock[Chuzc4eClock] = timer_pointer->clock_def("CHUZC4e", "C4e"); - clock[Chuzc5Clock] = timer_pointer->clock_def("CHUZC5", "CC5"); - clock[DevexWtClock] = timer_pointer->clock_def("DEVEX_WT", "DWT"); - clock[BtranClock] = timer_pointer->clock_def("BTRAN", "REP"); + timer_pointer->clock_def("CHUZC_HYPER_FEAS"); + clock[ChuzcHyperDualClock] = timer_pointer->clock_def("CHUZC_HYPER_DUAL"); + clock[ChuzcHyperClock] = timer_pointer->clock_def("CHUZC_HYPER"); + clock[Chuzc0Clock] = timer_pointer->clock_def("CHUZC0"); + clock[PriceChuzc1Clock] = timer_pointer->clock_def("PRICE_CHUZC1"); + clock[Chuzc1Clock] = timer_pointer->clock_def("CHUZC1"); + clock[Chuzc2Clock] = timer_pointer->clock_def("CHUZC2"); + clock[Chuzc3Clock] = timer_pointer->clock_def("CHUZC3"); + clock[Chuzc4Clock] = timer_pointer->clock_def("CHUZC4"); + clock[Chuzc4a0Clock] = timer_pointer->clock_def("CHUZC4a0"); + clock[Chuzc4a1Clock] = timer_pointer->clock_def("CHUZC4a1"); + clock[Chuzc4bClock] = timer_pointer->clock_def("CHUZC4b"); + clock[Chuzc4cClock] = timer_pointer->clock_def("CHUZC4c"); + clock[Chuzc4dClock] = timer_pointer->clock_def("CHUZC4d"); + clock[Chuzc4eClock] = timer_pointer->clock_def("CHUZC4e"); + clock[Chuzc5Clock] = timer_pointer->clock_def("CHUZC5"); + clock[DevexWtClock] = timer_pointer->clock_def("DEVEX_WT"); + clock[BtranClock] = timer_pointer->clock_def("BTRAN"); clock[BtranBasicFeasibilityChangeClock] = - timer_pointer->clock_def("BTRAN_FEAS", "BT1"); - clock[BtranFullClock] = timer_pointer->clock_def("BTRAN_FULL", "BTF"); - clock[PriceClock] = timer_pointer->clock_def("PRICE", "RAP"); + timer_pointer->clock_def("BTRAN_FEAS"); + clock[BtranFullClock] = timer_pointer->clock_def("BTRAN_FULL"); + clock[PriceClock] = timer_pointer->clock_def("PRICE"); clock[PriceBasicFeasibilityChangeClock] = - timer_pointer->clock_def("PRICE_FEAS", "PC1"); - clock[PriceFullClock] = timer_pointer->clock_def("PRICE_FULL", "PCF"); - clock[FtranClock] = timer_pointer->clock_def("FTRAN", "COL"); - clock[FtranDseClock] = timer_pointer->clock_def("FTRAN_DSE", "DSE"); - clock[BtranPseClock] = timer_pointer->clock_def("BTRAN_PSE", "PSE"); - clock[FtranMixParClock] = timer_pointer->clock_def("FTRAN_MIX_PAR", "FMP"); - clock[FtranMixFinalClock] = - timer_pointer->clock_def("FTRAN_MIX_FINAL", "FMF"); - clock[FtranBfrtClock] = timer_pointer->clock_def("FTRAN_BFRT", "BFR"); - clock[UpdateRowClock] = timer_pointer->clock_def("UPDATE_ROW", "UPR"); - clock[UpdateDualClock] = timer_pointer->clock_def("UPDATE_DUAL", "UPD"); + timer_pointer->clock_def("PRICE_FEAS"); + clock[PriceFullClock] = timer_pointer->clock_def("PRICE_FULL"); + clock[FtranClock] = timer_pointer->clock_def("FTRAN"); + clock[FtranDseClock] = timer_pointer->clock_def("FTRAN_DSE"); + clock[BtranPseClock] = timer_pointer->clock_def("BTRAN_PSE"); + clock[FtranMixParClock] = timer_pointer->clock_def("FTRAN_MIX_PAR"); + clock[FtranMixFinalClock] = timer_pointer->clock_def("FTRAN_MIX_FINAL"); + clock[FtranBfrtClock] = timer_pointer->clock_def("FTRAN_BFRT"); + clock[UpdateRowClock] = timer_pointer->clock_def("UPDATE_ROW"); + clock[UpdateDualClock] = timer_pointer->clock_def("UPDATE_DUAL"); clock[UpdateDualBasicFeasibilityChangeClock] = - timer_pointer->clock_def("UPDATE_DUAL_FEAS", "UD1"); - clock[UpdatePrimalClock] = timer_pointer->clock_def("UPDATE_PRIMAL", "UPP"); - clock[DevexIzClock] = timer_pointer->clock_def("DEVEX_IZ", "DIZ"); + timer_pointer->clock_def("UPDATE_DUAL_FEAS"); + clock[UpdatePrimalClock] = timer_pointer->clock_def("UPDATE_PRIMAL"); + clock[DevexIzClock] = timer_pointer->clock_def("DEVEX_IZ"); clock[DevexUpdateWeightClock] = - timer_pointer->clock_def("UPDATE_DVX_WEIGHT", "UDW"); - clock[DseUpdateWeightClock] = - timer_pointer->clock_def("UPDATE_DSE_WEIGHT", "USW"); - clock[UpdatePivotsClock] = timer_pointer->clock_def("UPDATE_PIVOTS", "UPP"); - clock[UpdateFactorClock] = timer_pointer->clock_def("UPDATE_FACTOR", "UPF"); - clock[UpdateMatrixClock] = timer_pointer->clock_def("UPDATE_MATRIX", "UPM"); - clock[UpdateRowEpClock] = timer_pointer->clock_def("UPDATE_ROW_EP", "UPR"); + timer_pointer->clock_def("UPDATE_DVX_WEIGHT"); + clock[DseUpdateWeightClock] = timer_pointer->clock_def("UPDATE_DSE_WEIGHT"); + clock[UpdatePivotsClock] = timer_pointer->clock_def("UPDATE_PIVOTS"); + clock[UpdateFactorClock] = timer_pointer->clock_def("UPDATE_FACTOR"); + clock[UpdateMatrixClock] = timer_pointer->clock_def("UPDATE_MATRIX"); + clock[UpdateRowEpClock] = timer_pointer->clock_def("UPDATE_ROW_EP"); } bool reportSimplexClockList(const char* grepStamp, diff --git a/src/util/FactorTimer.h b/src/util/FactorTimer.h index f8c0a866c1..8f31b71411 100644 --- a/src/util/FactorTimer.h +++ b/src/util/FactorTimer.h @@ -88,76 +88,54 @@ class FactorTimer { HighsTimer* timer_pointer = factor_timer_clock.timer_pointer_; std::vector& clock = factor_timer_clock.clock_; clock.resize(FactorNumClock); - clock[FactorInvert] = timer_pointer->clock_def("INVERT", "INV"); - clock[FactorInvertSimple] = - timer_pointer->clock_def("INVERT Simple", "IVS"); - clock[FactorInvertKernel] = - timer_pointer->clock_def("INVERT Kernel", "IVK"); - clock[FactorInvertDeficient] = - timer_pointer->clock_def("INVERT Deficient", "IVD"); - clock[FactorInvertFinish] = - timer_pointer->clock_def("INVERT Finish", "IVF"); - clock[FactorFtran] = timer_pointer->clock_def("FTRAN", "FTR"); - clock[FactorFtranLower] = timer_pointer->clock_def("FTRAN Lower", "FTL"); - clock[FactorFtranLowerAPF] = - timer_pointer->clock_def("FTRAN Lower APF", "FLA"); - clock[FactorFtranLowerDse] = - timer_pointer->clock_def("FTRAN Lower Dse", "FLD"); - clock[FactorFtranLowerSps] = - timer_pointer->clock_def("FTRAN Lower Sps", "FLS"); + clock[FactorInvert] = timer_pointer->clock_def("INVERT"); + clock[FactorInvertSimple] = timer_pointer->clock_def("INVERT Simple"); + clock[FactorInvertKernel] = timer_pointer->clock_def("INVERT Kernel"); + clock[FactorInvertDeficient] = timer_pointer->clock_def("INVERT Deficient"); + clock[FactorInvertFinish] = timer_pointer->clock_def("INVERT Finish"); + clock[FactorFtran] = timer_pointer->clock_def("FTRAN"); + clock[FactorFtranLower] = timer_pointer->clock_def("FTRAN Lower"); + clock[FactorFtranLowerAPF] = timer_pointer->clock_def("FTRAN Lower APF"); + clock[FactorFtranLowerDse] = timer_pointer->clock_def("FTRAN Lower Dse"); + clock[FactorFtranLowerSps] = timer_pointer->clock_def("FTRAN Lower Sps"); clock[FactorFtranLowerHyper] = - timer_pointer->clock_def("FTRAN Lower Hyper", "FLH"); - clock[FactorFtranUpper] = timer_pointer->clock_def("FTRAN Upper", "FTU"); - clock[FactorFtranUpperFT] = - timer_pointer->clock_def("FTRAN Upper FT", "FUF"); - clock[FactorFtranUpperMPF] = - timer_pointer->clock_def("FTRAN Upper MPF", "FUM"); - clock[FactorFtranUpperDse] = - timer_pointer->clock_def("FTRAN Upper Dse", "FUD"); - clock[FactorFtranUpperSps0] = - timer_pointer->clock_def("FTRAN Upper Sps0", "FUS"); - clock[FactorFtranUpperSps1] = - timer_pointer->clock_def("FTRAN Upper Sps1", "FUS"); - clock[FactorFtranUpperSps2] = - timer_pointer->clock_def("FTRAN Upper Sps2", "FUS"); + timer_pointer->clock_def("FTRAN Lower Hyper"); + clock[FactorFtranUpper] = timer_pointer->clock_def("FTRAN Upper"); + clock[FactorFtranUpperFT] = timer_pointer->clock_def("FTRAN Upper FT"); + clock[FactorFtranUpperMPF] = timer_pointer->clock_def("FTRAN Upper MPF"); + clock[FactorFtranUpperDse] = timer_pointer->clock_def("FTRAN Upper Dse"); + clock[FactorFtranUpperSps0] = timer_pointer->clock_def("FTRAN Upper Sps0"); + clock[FactorFtranUpperSps1] = timer_pointer->clock_def("FTRAN Upper Sps1"); + clock[FactorFtranUpperSps2] = timer_pointer->clock_def("FTRAN Upper Sps2"); clock[FactorFtranUpperHyper0] = - timer_pointer->clock_def("FTRAN Upper Hyper0", "FUH"); + timer_pointer->clock_def("FTRAN Upper Hyper0"); clock[FactorFtranUpperHyper1] = - timer_pointer->clock_def("FTRAN Upper Hyper1", "FUH"); + timer_pointer->clock_def("FTRAN Upper Hyper1"); clock[FactorFtranUpperHyper2] = - timer_pointer->clock_def("FTRAN Upper Hyper2", "FUH"); + timer_pointer->clock_def("FTRAN Upper Hyper2"); clock[FactorFtranUpperHyper3] = - timer_pointer->clock_def("FTRAN Upper Hyper3", "FUH"); + timer_pointer->clock_def("FTRAN Upper Hyper3"); clock[FactorFtranUpperHyper4] = - timer_pointer->clock_def("FTRAN Upper Hyper4", "FUH"); + timer_pointer->clock_def("FTRAN Upper Hyper4"); clock[FactorFtranUpperHyper5] = - timer_pointer->clock_def("FTRAN Upper Hyper5", "FUH"); - clock[FactorFtranUpperPF] = - timer_pointer->clock_def("FTRAN Upper PF", "FUP"); - clock[FactorBtran] = timer_pointer->clock_def("BTRAN", "BTR"); - clock[FactorBtranLower] = timer_pointer->clock_def("BTRAN Lower", "BTL"); - clock[FactorBtranLowerDse] = - timer_pointer->clock_def("BTRAN Lower Dse", "BLD"); - clock[FactorBtranLowerSps] = - timer_pointer->clock_def("BTRAN Lower Sps", "BLS"); + timer_pointer->clock_def("FTRAN Upper Hyper5"); + clock[FactorFtranUpperPF] = timer_pointer->clock_def("FTRAN Upper PF"); + clock[FactorBtran] = timer_pointer->clock_def("BTRAN"); + clock[FactorBtranLower] = timer_pointer->clock_def("BTRAN Lower"); + clock[FactorBtranLowerDse] = timer_pointer->clock_def("BTRAN Lower Dse"); + clock[FactorBtranLowerSps] = timer_pointer->clock_def("BTRAN Lower Sps"); clock[FactorBtranLowerHyper] = - timer_pointer->clock_def("BTRAN Lower Hyper", "BLH"); - clock[FactorBtranLowerAPF] = - timer_pointer->clock_def("BTRAN Lower APF", "BLA"); - clock[FactorBtranUpper] = timer_pointer->clock_def("BTRAN Upper", "BTU"); - clock[FactorBtranUpperPF] = - timer_pointer->clock_def("BTRAN Upper PF", "BUP"); - clock[FactorBtranUpperDse] = - timer_pointer->clock_def("BTRAN Upper Dse", "BUD"); - clock[FactorBtranUpperSps] = - timer_pointer->clock_def("BTRAN Upper Sps", "BUS"); + timer_pointer->clock_def("BTRAN Lower Hyper"); + clock[FactorBtranLowerAPF] = timer_pointer->clock_def("BTRAN Lower APF"); + clock[FactorBtranUpper] = timer_pointer->clock_def("BTRAN Upper"); + clock[FactorBtranUpperPF] = timer_pointer->clock_def("BTRAN Upper PF"); + clock[FactorBtranUpperDse] = timer_pointer->clock_def("BTRAN Upper Dse"); + clock[FactorBtranUpperSps] = timer_pointer->clock_def("BTRAN Upper Sps"); clock[FactorBtranUpperHyper] = - timer_pointer->clock_def("BTRAN Upper Hyper", "BUH"); - clock[FactorBtranUpperFT] = - timer_pointer->clock_def("BTRAN Upper FT", "BUF"); - clock[FactorBtranUpperMPF] = - timer_pointer->clock_def("BTRAN Upper MPS", "BUM"); - clock[FactorReinvert] = timer_pointer->clock_def("ReINVERT", "RIV"); + timer_pointer->clock_def("BTRAN Upper Hyper"); + clock[FactorBtranUpperFT] = timer_pointer->clock_def("BTRAN Upper FT"); + clock[FactorBtranUpperMPF] = timer_pointer->clock_def("BTRAN Upper MPS"); + clock[FactorReinvert] = timer_pointer->clock_def("ReINVERT"); }; void reportFactorClockList(const char* grepStamp, diff --git a/src/util/HFactor.cpp b/src/util/HFactor.cpp index 1e94db9f11..bdfa0bd180 100644 --- a/src/util/HFactor.cpp +++ b/src/util/HFactor.cpp @@ -359,7 +359,7 @@ HighsInt HFactor::build(HighsTimerClock* factor_timer_clock_pointer) { // HPresolve::removeDependentEquations HighsTimer build_timer; build_timer_ = &build_timer; - build_timer.startRunHighsClock(); + build_timer.start(); const bool report_lu = false; // Ensure that the A matrix is valid for factorization @@ -892,7 +892,7 @@ HighsInt HFactor::buildKernel() { } // Determine whether to return due to exceeding the time limit if (check_for_timeout && search_k % timer_frequency == 0) { - double current_time = build_timer_->readRunHighsClock(); + double current_time = build_timer_->read(); double time_difference = current_time - previous_iteration_time; previous_iteration_time = current_time; double iteration_time = time_difference / (1.0 * timer_frequency); diff --git a/src/util/HighsTimer.h b/src/util/HighsTimer.h index 71f1c63223..eb427524fd 100644 --- a/src/util/HighsTimer.h +++ b/src/util/HighsTimer.h @@ -34,7 +34,6 @@ struct HighsClockRecord { double start; double time; std::string name; - std::string ch3_name; }; */ /** @@ -46,8 +45,6 @@ class HighsTimer { num_clock = 0; HighsInt i_clock = clock_def("Run HiGHS"); assert(i_clock == 0); - run_highs_clock = i_clock; - total_clock = run_highs_clock; presolve_clock = clock_def("Presolve"); solve_clock = clock_def("Solve"); @@ -58,15 +55,13 @@ class HighsTimer { * @brief Define a clock */ HighsInt clock_def( - const char* name, //!< Full-length name (<=16 characters) for the clock - const char* ch3_name = "N/A" //!< 3-character name for the clock - ) { + const char* name) //!< Full-length name (<=16 characters) for the clock + { HighsInt i_clock = num_clock; clock_num_call.push_back(0); clock_start.push_back(initial_clock_start); clock_time.push_back(0); clock_names.push_back(name); - clock_ch3_names.push_back(ch3_name); num_clock++; return i_clock; } @@ -81,7 +76,6 @@ class HighsTimer { x_clock.start = 0; x_clock.time = 0; x_clock.name = ""; - x_clock.ch3_name = ""; } */ @@ -106,13 +100,11 @@ class HighsTimer { this->clock_num_call.clear(); this->clock_start.clear(); this->clock_names.clear(); - this->clock_ch3_names.clear(); - HighsInt i_clock = clock_def("Run HiGHS", "RnH"); + HighsInt i_clock = clock_def("Run HiGHS"); assert(i_clock == 0); - this->run_highs_clock = i_clock; - this->presolve_clock = clock_def("Presolve", "Pre"); - this->solve_clock = clock_def("Solve", "Slv"); - this->postsolve_clock = clock_def("Postsolve", "Pst"); + this->presolve_clock = clock_def("Presolve"); + this->solve_clock = clock_def("Solve"); + this->postsolve_clock = clock_def("Postsolve"); } /** @@ -126,6 +118,16 @@ class HighsTimer { } } + /** + * @brief write all clocks + */ + void writeAllClocks() { + for (HighsInt i = 0; i < num_clock; i++) + if (clock_num_call[i]) + printf("Time %7.5f for %9d calls of clock %3d: %s\n", clock_time[i], + int(clock_num_call[i]), int(i), clock_names[i].c_str()); + } + /** * @brief Start a clock */ @@ -223,26 +225,6 @@ class HighsTimer { return clock_start[i_clock] < 0; } - /** - * @brief Start the RunHighs clock - */ - void startRunHighsClock() { start(run_highs_clock); } - - /** - * @brief Stop the RunHighs clock - */ - void stopRunHighsClock() { stop(run_highs_clock); } - - /** - * @brief Read the RunHighs clock - */ - double readRunHighsClock() { return read(run_highs_clock); } - - /** - * @brief Test whether the RunHighs clock is running - */ - bool runningRunHighsClock() { return running(run_highs_clock); } - /** * @brief Report timing information for the clock indices in the list */ @@ -266,7 +248,7 @@ class HighsTimer { //!< before an individual clock is reported ) { size_t num_clock_list_entries = clock_list.size(); - double current_run_highs_time = readRunHighsClock(); + double current_run_highs_time = read(); bool non_null_report = false; // Check validity of the clock list and check no clocks are still @@ -375,12 +357,6 @@ class HighsTimer { std::vector clock_start; std::vector clock_time; std::vector clock_names; - std::vector clock_ch3_names; - // The index of the RunHighsClock - should always be 0 - HighsInt run_highs_clock; - // Synonym for run_highs_clock that makes more sense when (as in MIP - // solver) there is an independent timer - HighsInt total_clock; // Fundamental clocks HighsInt presolve_clock; HighsInt solve_clock; diff --git a/src/util/HighsUtils.cpp b/src/util/HighsUtils.cpp index 7e0ab9051c..9dc4fa6a20 100644 --- a/src/util/HighsUtils.cpp +++ b/src/util/HighsUtils.cpp @@ -435,7 +435,7 @@ void analyseVectorValues(const HighsLogOptions* log_options, highsFormatToString("%12" HIGHSINT_FORMAT " values satisfy 10^(%3" HIGHSINT_FORMAT ") <= v < 10^(%3" HIGHSINT_FORMAT ")\n", - vK, k, k + 1)); + vK, k - 1, k)); } for (HighsInt k = 1; k <= nVK; k++) { HighsInt vK = negVK[k]; @@ -445,7 +445,7 @@ void analyseVectorValues(const HighsLogOptions* log_options, highsFormatToString("%12" HIGHSINT_FORMAT " values satisfy 10^(%3" HIGHSINT_FORMAT ") <= v < 10^(%3" HIGHSINT_FORMAT ")\n", - vK, -k, 1 - k)); + vK, -k - 1, -k)); } vK = vecDim - nNz; if (vK > 0) diff --git a/src/util/stringutil.cpp b/src/util/stringutil.cpp index 9d6e312d90..49bceaa0f1 100644 --- a/src/util/stringutil.cpp +++ b/src/util/stringutil.cpp @@ -72,6 +72,11 @@ void tolower(std::string& str) { [](unsigned char c) { return std::tolower(c); }); } +void toupper(std::string& str) { + std::transform(str.begin(), str.end(), str.begin(), + [](unsigned char c) { return std::toupper(c); }); +} + std::string& ltrim(std::string& str, const std::string& chars) { str.erase(0, str.find_first_not_of(chars)); return str; diff --git a/src/util/stringutil.h b/src/util/stringutil.h index 32132730ef..0e0b277738 100644 --- a/src/util/stringutil.h +++ b/src/util/stringutil.h @@ -23,6 +23,7 @@ void strTrim(char* str); // std::string& str_tolower(std::string s); void tolower(std::string& str); +void toupper(std::string& str); const std::string default_non_chars = "\t\n\v\f\r "; std::string& ltrim(std::string& str,