lpsolver 0.1.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile +1 -0
- data/README.md +104 -26
- data/ext/lpsolver/Makefile +269 -0
- data/ext/lpsolver/ext.c +353 -0
- data/ext/lpsolver/ext.o +0 -0
- data/ext/lpsolver/extconf.rb +79 -0
- data/ext/lpsolver/native.so +0 -0
- data/ext/lpsolver-highs/AUTHORS +7 -0
- data/ext/lpsolver-highs/BUILD.bazel +243 -0
- data/ext/lpsolver-highs/CITATION.cff +29 -0
- data/ext/lpsolver-highs/CMakeCache.txt +406 -0
- data/ext/lpsolver-highs/CMakeFiles/3.31.4/CMakeCCompiler.cmake +81 -0
- data/ext/lpsolver-highs/CMakeFiles/3.31.4/CMakeCXXCompiler.cmake +101 -0
- data/ext/lpsolver-highs/CMakeFiles/3.31.4/CMakeDetermineCompilerABI_C.bin +0 -0
- data/ext/lpsolver-highs/CMakeFiles/3.31.4/CMakeDetermineCompilerABI_CXX.bin +0 -0
- data/ext/lpsolver-highs/CMakeFiles/3.31.4/CMakeSystem.cmake +15 -0
- data/ext/lpsolver-highs/CMakeFiles/3.31.4/CompilerIdC/CMakeCCompilerId.c +904 -0
- data/ext/lpsolver-highs/CMakeFiles/3.31.4/CompilerIdC/a.out +0 -0
- data/ext/lpsolver-highs/CMakeFiles/3.31.4/CompilerIdCXX/CMakeCXXCompilerId.cpp +919 -0
- data/ext/lpsolver-highs/CMakeFiles/3.31.4/CompilerIdCXX/a.out +0 -0
- data/ext/lpsolver-highs/CMakeFiles/CMakeConfigureLog.yaml +576 -0
- data/ext/lpsolver-highs/CMakeFiles/cmake.check_cache +1 -0
- data/ext/lpsolver-highs/CMakeLists.txt +983 -0
- data/ext/lpsolver-highs/CODE_OF_CONDUCT.md +128 -0
- data/ext/lpsolver-highs/CONTRIBUTING.md +31 -0
- data/ext/lpsolver-highs/FEATURES.md +61 -0
- data/ext/lpsolver-highs/LICENSE.txt +21 -0
- data/ext/lpsolver-highs/MODULE.bazel +38 -0
- data/ext/lpsolver-highs/README.md +281 -0
- data/ext/lpsolver-highs/THIRD_PARTY_NOTICES.md +78 -0
- data/ext/lpsolver-highs/Version.txt +4 -0
- data/ext/lpsolver-highs/WORKSPACE +33 -0
- data/ext/lpsolver-highs/app/CMakeLists.txt +110 -0
- data/ext/lpsolver-highs/app/HighsRuntimeOptions.h +292 -0
- data/ext/lpsolver-highs/app/RunHighs.cpp +147 -0
- data/ext/lpsolver-highs/app/highs_webdemo_shell.html +73 -0
- data/ext/lpsolver-highs/build/bin/highs +0 -0
- data/ext/lpsolver-highs/build/include/highs/HConfig.h +22 -0
- data/ext/lpsolver-highs/build/include/highs/Highs.h +1812 -0
- data/ext/lpsolver-highs/build/include/highs/interfaces/highs_c_api.h +2651 -0
- data/ext/lpsolver-highs/build/include/highs/io/Filereader.h +45 -0
- data/ext/lpsolver-highs/build/include/highs/io/FilereaderLp.h +49 -0
- data/ext/lpsolver-highs/build/include/highs/io/FilereaderMps.h +27 -0
- data/ext/lpsolver-highs/build/include/highs/io/HMPSIO.h +78 -0
- data/ext/lpsolver-highs/build/include/highs/io/HMpsFF.h +245 -0
- data/ext/lpsolver-highs/build/include/highs/io/HighsIO.h +118 -0
- data/ext/lpsolver-highs/build/include/highs/io/LoadOptions.h +24 -0
- data/ext/lpsolver-highs/build/include/highs/io/filereaderlp/builder.hpp +25 -0
- data/ext/lpsolver-highs/build/include/highs/io/filereaderlp/def.hpp +19 -0
- data/ext/lpsolver-highs/build/include/highs/io/filereaderlp/model.hpp +68 -0
- data/ext/lpsolver-highs/build/include/highs/io/filereaderlp/reader.hpp +10 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/IpxSolution.h +32 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/IpxWrapper.h +106 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/basiclu.h +161 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/basiclu_factorize.h +247 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/basiclu_get_factors.h +108 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/basiclu_initialize.h +119 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/basiclu_obj_factorize.h +34 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/basiclu_obj_free.h +19 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/basiclu_obj_get_factors.h +34 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/basiclu_obj_initialize.h +46 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/basiclu_obj_solve_dense.h +29 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/basiclu_obj_solve_for_update.h +42 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/basiclu_obj_solve_sparse.h +32 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/basiclu_obj_update.h +31 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/basiclu_object.h +30 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/basiclu_solve_dense.h +75 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/basiclu_solve_for_update.h +169 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/basiclu_solve_sparse.h +112 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/basiclu_update.h +125 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/lu_def.h +39 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/lu_file.h +21 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/lu_internal.h +220 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/lu_list.h +173 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/basiclu_kernel.h +20 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/basiclu_wrapper.h +47 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/basis.h +350 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/conjugate_residuals.h +74 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/control.h +167 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/crossover.h +157 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/diagonal_precond.h +45 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/forrest_tomlin.h +102 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/guess_basis.h +21 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/indexed_vector.h +113 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/info.h +27 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/ipm.h +94 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/ipx_c.h +47 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/ipx_config.h +9 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/ipx_info.h +111 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/ipx_internal.h +89 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/ipx_parameters.h +76 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/ipx_status.h +57 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/iterate.h +331 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/kkt_solver.h +70 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/kkt_solver_basis.h +66 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/kkt_solver_diag.h +48 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/linear_operator.h +26 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/lp_solver.h +204 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/lu_factorization.h +79 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/lu_update.h +129 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/maxvolume.h +54 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/model.h +413 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/multistream.h +52 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/normal_matrix.h +44 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/power_method.h +44 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/sparse_matrix.h +195 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/sparse_utils.h +58 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/splitted_normal_matrix.h +63 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/starting_basis.h +39 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/symbolic_invert.h +29 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/timer.h +25 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/utils.h +37 -0
- data/ext/lpsolver-highs/build/include/highs/lp_data/HConst.h +430 -0
- data/ext/lpsolver-highs/build/include/highs/lp_data/HStruct.h +213 -0
- data/ext/lpsolver-highs/build/include/highs/lp_data/HighsAnalysis.h +23 -0
- data/ext/lpsolver-highs/build/include/highs/lp_data/HighsCallback.h +104 -0
- data/ext/lpsolver-highs/build/include/highs/lp_data/HighsCallbackStruct.h +70 -0
- data/ext/lpsolver-highs/build/include/highs/lp_data/HighsDebug.h +34 -0
- data/ext/lpsolver-highs/build/include/highs/lp_data/HighsIis.h +139 -0
- data/ext/lpsolver-highs/build/include/highs/lp_data/HighsInfo.h +421 -0
- data/ext/lpsolver-highs/build/include/highs/lp_data/HighsInfoDebug.h +27 -0
- data/ext/lpsolver-highs/build/include/highs/lp_data/HighsLp.h +97 -0
- data/ext/lpsolver-highs/build/include/highs/lp_data/HighsLpSolverObject.h +47 -0
- data/ext/lpsolver-highs/build/include/highs/lp_data/HighsLpUtils.h +330 -0
- data/ext/lpsolver-highs/build/include/highs/lp_data/HighsModelUtils.h +129 -0
- data/ext/lpsolver-highs/build/include/highs/lp_data/HighsOptions.h +1715 -0
- data/ext/lpsolver-highs/build/include/highs/lp_data/HighsRanging.h +43 -0
- data/ext/lpsolver-highs/build/include/highs/lp_data/HighsSolution.h +179 -0
- data/ext/lpsolver-highs/build/include/highs/lp_data/HighsSolutionDebug.h +87 -0
- data/ext/lpsolver-highs/build/include/highs/lp_data/HighsSolve.h +29 -0
- data/ext/lpsolver-highs/build/include/highs/lp_data/HighsStatus.h +29 -0
- data/ext/lpsolver-highs/build/include/highs/mip/HighsCliqueTable.h +329 -0
- data/ext/lpsolver-highs/build/include/highs/mip/HighsConflictPool.h +109 -0
- data/ext/lpsolver-highs/build/include/highs/mip/HighsCutGeneration.h +108 -0
- data/ext/lpsolver-highs/build/include/highs/mip/HighsCutPool.h +168 -0
- data/ext/lpsolver-highs/build/include/highs/mip/HighsDebugSol.h +133 -0
- data/ext/lpsolver-highs/build/include/highs/mip/HighsDomain.h +657 -0
- data/ext/lpsolver-highs/build/include/highs/mip/HighsDomainChange.h +48 -0
- data/ext/lpsolver-highs/build/include/highs/mip/HighsDynamicRowMatrix.h +104 -0
- data/ext/lpsolver-highs/build/include/highs/mip/HighsGFkSolve.h +439 -0
- data/ext/lpsolver-highs/build/include/highs/mip/HighsImplications.h +194 -0
- data/ext/lpsolver-highs/build/include/highs/mip/HighsLpAggregator.h +50 -0
- data/ext/lpsolver-highs/build/include/highs/mip/HighsLpRelaxation.h +361 -0
- data/ext/lpsolver-highs/build/include/highs/mip/HighsMipAnalysis.h +71 -0
- data/ext/lpsolver-highs/build/include/highs/mip/HighsMipSolver.h +159 -0
- data/ext/lpsolver-highs/build/include/highs/mip/HighsMipSolverData.h +313 -0
- data/ext/lpsolver-highs/build/include/highs/mip/HighsModkSeparator.h +60 -0
- data/ext/lpsolver-highs/build/include/highs/mip/HighsNodeQueue.h +312 -0
- data/ext/lpsolver-highs/build/include/highs/mip/HighsObjectiveFunction.h +71 -0
- data/ext/lpsolver-highs/build/include/highs/mip/HighsPathSeparator.h +39 -0
- data/ext/lpsolver-highs/build/include/highs/mip/HighsPrimalHeuristics.h +75 -0
- data/ext/lpsolver-highs/build/include/highs/mip/HighsPseudocost.h +366 -0
- data/ext/lpsolver-highs/build/include/highs/mip/HighsRedcostFixing.h +42 -0
- data/ext/lpsolver-highs/build/include/highs/mip/HighsSearch.h +241 -0
- data/ext/lpsolver-highs/build/include/highs/mip/HighsSeparation.h +41 -0
- data/ext/lpsolver-highs/build/include/highs/mip/HighsSeparator.h +60 -0
- data/ext/lpsolver-highs/build/include/highs/mip/HighsTableauSeparator.h +34 -0
- data/ext/lpsolver-highs/build/include/highs/mip/HighsTransformedLp.h +63 -0
- data/ext/lpsolver-highs/build/include/highs/mip/MipTimer.h +544 -0
- data/ext/lpsolver-highs/build/include/highs/mip/feasibilityjump.hh +800 -0
- data/ext/lpsolver-highs/build/include/highs/model/HighsHessian.h +54 -0
- data/ext/lpsolver-highs/build/include/highs/model/HighsHessianUtils.h +47 -0
- data/ext/lpsolver-highs/build/include/highs/model/HighsModel.h +42 -0
- data/ext/lpsolver-highs/build/include/highs/parallel/HighsBinarySemaphore.h +108 -0
- data/ext/lpsolver-highs/build/include/highs/parallel/HighsCacheAlign.h +82 -0
- data/ext/lpsolver-highs/build/include/highs/parallel/HighsCombinable.h +116 -0
- data/ext/lpsolver-highs/build/include/highs/parallel/HighsMutex.h +124 -0
- data/ext/lpsolver-highs/build/include/highs/parallel/HighsParallel.h +128 -0
- data/ext/lpsolver-highs/build/include/highs/parallel/HighsRaceTimer.h +38 -0
- data/ext/lpsolver-highs/build/include/highs/parallel/HighsSchedulerConstants.h +19 -0
- data/ext/lpsolver-highs/build/include/highs/parallel/HighsSpinMutex.h +48 -0
- data/ext/lpsolver-highs/build/include/highs/parallel/HighsSplitDeque.h +606 -0
- data/ext/lpsolver-highs/build/include/highs/parallel/HighsTask.h +170 -0
- data/ext/lpsolver-highs/build/include/highs/parallel/HighsTaskExecutor.h +217 -0
- data/ext/lpsolver-highs/build/include/highs/pdlp/CupdlpWrapper.h +108 -0
- data/ext/lpsolver-highs/build/include/highs/pdlp/HiPdlpTimer.h +155 -0
- data/ext/lpsolver-highs/build/include/highs/pdlp/HiPdlpWrapper.h +26 -0
- data/ext/lpsolver-highs/build/include/highs/pdlp/cupdlp/cupdlp_cs.h +40 -0
- data/ext/lpsolver-highs/build/include/highs/pdlp/cupdlp/cupdlp_defs.h +447 -0
- data/ext/lpsolver-highs/build/include/highs/pdlp/cupdlp/cupdlp_linalg.h +189 -0
- data/ext/lpsolver-highs/build/include/highs/pdlp/cupdlp/cupdlp_proj.h +19 -0
- data/ext/lpsolver-highs/build/include/highs/pdlp/cupdlp/cupdlp_restart.h +31 -0
- data/ext/lpsolver-highs/build/include/highs/pdlp/cupdlp/cupdlp_scaling.h +26 -0
- data/ext/lpsolver-highs/build/include/highs/pdlp/cupdlp/cupdlp_solver.h +105 -0
- data/ext/lpsolver-highs/build/include/highs/pdlp/cupdlp/cupdlp_step.h +37 -0
- data/ext/lpsolver-highs/build/include/highs/pdlp/cupdlp/cupdlp_utils.c +1850 -0
- data/ext/lpsolver-highs/build/include/highs/pdlp/hipdlp/defs.hpp +222 -0
- data/ext/lpsolver-highs/build/include/highs/pdlp/hipdlp/linalg.hpp +61 -0
- data/ext/lpsolver-highs/build/include/highs/pdlp/hipdlp/logger.hpp +80 -0
- data/ext/lpsolver-highs/build/include/highs/pdlp/hipdlp/pdhg.hpp +358 -0
- data/ext/lpsolver-highs/build/include/highs/pdlp/hipdlp/restart.hpp +96 -0
- data/ext/lpsolver-highs/build/include/highs/pdlp/hipdlp/scaling.hpp +74 -0
- data/ext/lpsolver-highs/build/include/highs/pdlp/hipdlp/solver_results.hpp +65 -0
- data/ext/lpsolver-highs/build/include/highs/pdqsort/pdqsort.h +532 -0
- data/ext/lpsolver-highs/build/include/highs/presolve/HPresolve.h +505 -0
- data/ext/lpsolver-highs/build/include/highs/presolve/HPresolveAnalysis.h +52 -0
- data/ext/lpsolver-highs/build/include/highs/presolve/HighsPostsolveStack.h +943 -0
- data/ext/lpsolver-highs/build/include/highs/presolve/HighsSymmetry.h +284 -0
- data/ext/lpsolver-highs/build/include/highs/presolve/ICrash.h +124 -0
- data/ext/lpsolver-highs/build/include/highs/presolve/ICrashUtil.h +62 -0
- data/ext/lpsolver-highs/build/include/highs/presolve/ICrashX.h +23 -0
- data/ext/lpsolver-highs/build/include/highs/presolve/PresolveComponent.h +90 -0
- data/ext/lpsolver-highs/build/include/highs/qpsolver/a_asm.hpp +77 -0
- data/ext/lpsolver-highs/build/include/highs/qpsolver/a_quass.hpp +22 -0
- data/ext/lpsolver-highs/build/include/highs/qpsolver/basis.hpp +159 -0
- data/ext/lpsolver-highs/build/include/highs/qpsolver/crashsolution.hpp +20 -0
- data/ext/lpsolver-highs/build/include/highs/qpsolver/dantzigpricing.hpp +80 -0
- data/ext/lpsolver-highs/build/include/highs/qpsolver/devexpricing.hpp +108 -0
- data/ext/lpsolver-highs/build/include/highs/qpsolver/eventhandler.hpp +30 -0
- data/ext/lpsolver-highs/build/include/highs/qpsolver/factor.hpp +408 -0
- data/ext/lpsolver-highs/build/include/highs/qpsolver/feasibility_bounded.hpp +114 -0
- data/ext/lpsolver-highs/build/include/highs/qpsolver/feasibility_highs.hpp +301 -0
- data/ext/lpsolver-highs/build/include/highs/qpsolver/gradient.hpp +46 -0
- data/ext/lpsolver-highs/build/include/highs/qpsolver/instance.hpp +70 -0
- data/ext/lpsolver-highs/build/include/highs/qpsolver/matrix.hpp +342 -0
- data/ext/lpsolver-highs/build/include/highs/qpsolver/perturbation.hpp +15 -0
- data/ext/lpsolver-highs/build/include/highs/qpsolver/pricing.hpp +22 -0
- data/ext/lpsolver-highs/build/include/highs/qpsolver/qpconst.hpp +34 -0
- data/ext/lpsolver-highs/build/include/highs/qpsolver/qpvector.hpp +242 -0
- data/ext/lpsolver-highs/build/include/highs/qpsolver/quass.hpp +27 -0
- data/ext/lpsolver-highs/build/include/highs/qpsolver/ratiotest.hpp +26 -0
- data/ext/lpsolver-highs/build/include/highs/qpsolver/runtime.hpp +45 -0
- data/ext/lpsolver-highs/build/include/highs/qpsolver/scaling.hpp +15 -0
- data/ext/lpsolver-highs/build/include/highs/qpsolver/settings.hpp +84 -0
- data/ext/lpsolver-highs/build/include/highs/qpsolver/snippets.hpp +36 -0
- data/ext/lpsolver-highs/build/include/highs/qpsolver/statistics.hpp +30 -0
- data/ext/lpsolver-highs/build/include/highs/qpsolver/steepestedgepricing.hpp +173 -0
- data/ext/lpsolver-highs/build/include/highs/simplex/HApp.h +550 -0
- data/ext/lpsolver-highs/build/include/highs/simplex/HEkk.h +419 -0
- data/ext/lpsolver-highs/build/include/highs/simplex/HEkkDual.h +513 -0
- data/ext/lpsolver-highs/build/include/highs/simplex/HEkkDualRHS.h +134 -0
- data/ext/lpsolver-highs/build/include/highs/simplex/HEkkDualRow.h +201 -0
- data/ext/lpsolver-highs/build/include/highs/simplex/HEkkPrimal.h +191 -0
- data/ext/lpsolver-highs/build/include/highs/simplex/HSimplex.h +42 -0
- data/ext/lpsolver-highs/build/include/highs/simplex/HSimplexDebug.h +48 -0
- data/ext/lpsolver-highs/build/include/highs/simplex/HSimplexNla.h +158 -0
- data/ext/lpsolver-highs/build/include/highs/simplex/HSimplexReport.h +21 -0
- data/ext/lpsolver-highs/build/include/highs/simplex/HighsSimplexAnalysis.h +500 -0
- data/ext/lpsolver-highs/build/include/highs/simplex/SimplexConst.h +273 -0
- data/ext/lpsolver-highs/build/include/highs/simplex/SimplexStruct.h +263 -0
- data/ext/lpsolver-highs/build/include/highs/simplex/SimplexTimer.h +414 -0
- data/ext/lpsolver-highs/build/include/highs/test_kkt/DevKkt.h +143 -0
- data/ext/lpsolver-highs/build/include/highs/test_kkt/KktCh2.h +79 -0
- data/ext/lpsolver-highs/build/include/highs/util/FactorTimer.h +199 -0
- data/ext/lpsolver-highs/build/include/highs/util/HFactor.h +587 -0
- data/ext/lpsolver-highs/build/include/highs/util/HFactorConst.h +81 -0
- data/ext/lpsolver-highs/build/include/highs/util/HFactorDebug.h +55 -0
- data/ext/lpsolver-highs/build/include/highs/util/HSet.h +89 -0
- data/ext/lpsolver-highs/build/include/highs/util/HVector.h +22 -0
- data/ext/lpsolver-highs/build/include/highs/util/HVectorBase.h +102 -0
- data/ext/lpsolver-highs/build/include/highs/util/HighsCDouble.h +323 -0
- data/ext/lpsolver-highs/build/include/highs/util/HighsComponent.h +53 -0
- data/ext/lpsolver-highs/build/include/highs/util/HighsDataStack.h +83 -0
- data/ext/lpsolver-highs/build/include/highs/util/HighsDisjointSets.h +107 -0
- data/ext/lpsolver-highs/build/include/highs/util/HighsHash.h +1274 -0
- data/ext/lpsolver-highs/build/include/highs/util/HighsHashTree.h +1461 -0
- data/ext/lpsolver-highs/build/include/highs/util/HighsInt.h +36 -0
- data/ext/lpsolver-highs/build/include/highs/util/HighsIntegers.h +212 -0
- data/ext/lpsolver-highs/build/include/highs/util/HighsLinearSumBounds.h +203 -0
- data/ext/lpsolver-highs/build/include/highs/util/HighsMatrixPic.h +37 -0
- data/ext/lpsolver-highs/build/include/highs/util/HighsMatrixSlice.h +561 -0
- data/ext/lpsolver-highs/build/include/highs/util/HighsMatrixUtils.h +57 -0
- data/ext/lpsolver-highs/build/include/highs/util/HighsMemoryAllocation.h +63 -0
- data/ext/lpsolver-highs/build/include/highs/util/HighsRandom.h +242 -0
- data/ext/lpsolver-highs/build/include/highs/util/HighsRbTree.h +452 -0
- data/ext/lpsolver-highs/build/include/highs/util/HighsSort.h +131 -0
- data/ext/lpsolver-highs/build/include/highs/util/HighsSparseMatrix.h +151 -0
- data/ext/lpsolver-highs/build/include/highs/util/HighsSparseVectorSum.h +95 -0
- data/ext/lpsolver-highs/build/include/highs/util/HighsSplay.h +135 -0
- data/ext/lpsolver-highs/build/include/highs/util/HighsTimer.h +385 -0
- data/ext/lpsolver-highs/build/include/highs/util/HighsUtils.h +272 -0
- data/ext/lpsolver-highs/build/include/highs/util/stringutil.h +46 -0
- data/ext/lpsolver-highs/build/include/highs/zstr/strict_fstream.hpp +237 -0
- data/ext/lpsolver-highs/build/include/highs/zstr/zstr.hpp +473 -0
- data/ext/lpsolver-highs/build/include/highs_export.h +43 -0
- data/ext/lpsolver-highs/build/lib/cmake/highs/highs-config-version.cmake +65 -0
- data/ext/lpsolver-highs/build/lib/cmake/highs/highs-config.cmake +36 -0
- data/ext/lpsolver-highs/build/lib/cmake/highs/highs-targets-release.cmake +19 -0
- data/ext/lpsolver-highs/build/lib/cmake/highs/highs-targets.cmake +111 -0
- data/ext/lpsolver-highs/build/lib/libhighs.a +0 -0
- data/ext/lpsolver-highs/build/lib/pkgconfig/highs.pc +12 -0
- data/ext/lpsolver-highs/build/share/doc/HIGHS/AUTHORS +7 -0
- data/ext/lpsolver-highs/build/share/doc/HIGHS/CITATION.cff +29 -0
- data/ext/lpsolver-highs/build/share/doc/HIGHS/CODE_OF_CONDUCT.md +128 -0
- data/ext/lpsolver-highs/build/share/doc/HIGHS/CONTRIBUTING.md +31 -0
- data/ext/lpsolver-highs/build/share/doc/HIGHS/FEATURES.md +61 -0
- data/ext/lpsolver-highs/build/share/doc/HIGHS/LICENSE.txt +21 -0
- data/ext/lpsolver-highs/build/share/doc/HIGHS/README.md +281 -0
- data/ext/lpsolver-highs/build_webdemo.sh +46 -0
- data/ext/lpsolver-highs/check/Avgas.cpp +245 -0
- data/ext/lpsolver-highs/check/Avgas.h +44 -0
- data/ext/lpsolver-highs/check/CMakeLists.txt +573 -0
- data/ext/lpsolver-highs/check/HCheckConfig.h.bazel.in +6 -0
- data/ext/lpsolver-highs/check/HCheckConfig.h.in +12 -0
- data/ext/lpsolver-highs/check/HCheckConfig.h.meson.in +6 -0
- data/ext/lpsolver-highs/check/SpecialLps.h +405 -0
- data/ext/lpsolver-highs/check/TestAlienBasis.cpp +720 -0
- data/ext/lpsolver-highs/check/TestBasis.cpp +359 -0
- data/ext/lpsolver-highs/check/TestBasisSolves.cpp +669 -0
- data/ext/lpsolver-highs/check/TestCAPI.c +2513 -0
- data/ext/lpsolver-highs/check/TestCallbacks.cpp +608 -0
- data/ext/lpsolver-highs/check/TestCheckSolution.cpp +740 -0
- data/ext/lpsolver-highs/check/TestCrossover.cpp +111 -0
- data/ext/lpsolver-highs/check/TestDualize.cpp +172 -0
- data/ext/lpsolver-highs/check/TestEkk.cpp +100 -0
- data/ext/lpsolver-highs/check/TestFactor.cpp +389 -0
- data/ext/lpsolver-highs/check/TestFilereader.cpp +568 -0
- data/ext/lpsolver-highs/check/TestFortranAPI.f90 +65 -0
- data/ext/lpsolver-highs/check/TestHSet.cpp +80 -0
- data/ext/lpsolver-highs/check/TestHighsCDouble.cpp +109 -0
- data/ext/lpsolver-highs/check/TestHighsGFkSolve.cpp +102 -0
- data/ext/lpsolver-highs/check/TestHighsHash.cpp +126 -0
- data/ext/lpsolver-highs/check/TestHighsHessian.cpp +329 -0
- data/ext/lpsolver-highs/check/TestHighsIntegers.cpp +42 -0
- data/ext/lpsolver-highs/check/TestHighsModel.cpp +134 -0
- data/ext/lpsolver-highs/check/TestHighsParallel.cpp +277 -0
- data/ext/lpsolver-highs/check/TestHighsRbTree.cpp +109 -0
- data/ext/lpsolver-highs/check/TestHighsSparseMatrix.cpp +126 -0
- data/ext/lpsolver-highs/check/TestHighsVersion.cpp +61 -0
- data/ext/lpsolver-highs/check/TestHipo.cpp +122 -0
- data/ext/lpsolver-highs/check/TestICrash.cpp +46 -0
- data/ext/lpsolver-highs/check/TestIO.cpp +163 -0
- data/ext/lpsolver-highs/check/TestIis.cpp +1063 -0
- data/ext/lpsolver-highs/check/TestInfo.cpp +116 -0
- data/ext/lpsolver-highs/check/TestIpm.cpp +226 -0
- data/ext/lpsolver-highs/check/TestIpx.cpp +96 -0
- data/ext/lpsolver-highs/check/TestLPFileFormat.cpp +22 -0
- data/ext/lpsolver-highs/check/TestLogging.cpp +69 -0
- data/ext/lpsolver-highs/check/TestLpModification.cpp +2497 -0
- data/ext/lpsolver-highs/check/TestLpOrientation.cpp +121 -0
- data/ext/lpsolver-highs/check/TestLpSolvers.cpp +555 -0
- data/ext/lpsolver-highs/check/TestLpValidation.cpp +689 -0
- data/ext/lpsolver-highs/check/TestMain.cpp +6 -0
- data/ext/lpsolver-highs/check/TestMipSolver.cpp +1406 -0
- data/ext/lpsolver-highs/check/TestModelProperties.cpp +143 -0
- data/ext/lpsolver-highs/check/TestMultiObjective.cpp +198 -0
- data/ext/lpsolver-highs/check/TestNames.cpp +187 -0
- data/ext/lpsolver-highs/check/TestOptions.cpp +544 -0
- data/ext/lpsolver-highs/check/TestPdlp.cpp +327 -0
- data/ext/lpsolver-highs/check/TestPdlpHi.cpp +40 -0
- data/ext/lpsolver-highs/check/TestPresolve.cpp +912 -0
- data/ext/lpsolver-highs/check/TestQpSolver.cpp +1345 -0
- data/ext/lpsolver-highs/check/TestRanging.cpp +558 -0
- data/ext/lpsolver-highs/check/TestRays.cpp +1010 -0
- data/ext/lpsolver-highs/check/TestSemiVariables.cpp +329 -0
- data/ext/lpsolver-highs/check/TestSetup.cpp +12 -0
- data/ext/lpsolver-highs/check/TestSort.cpp +247 -0
- data/ext/lpsolver-highs/check/TestSpecialLps.cpp +775 -0
- data/ext/lpsolver-highs/check/TestThrow.cpp +83 -0
- data/ext/lpsolver-highs/check/TestTspSolver.cpp +19 -0
- data/ext/lpsolver-highs/check/TestUserScale.cpp +444 -0
- data/ext/lpsolver-highs/check/cublas_example.cpp +76 -0
- data/ext/lpsolver-highs/check/cublas_gpu_start.cpp +88 -0
- data/ext/lpsolver-highs/check/hipo_test_option_files/hipo_options_0 +1 -0
- data/ext/lpsolver-highs/check/instances/1448.lp +1 -0
- data/ext/lpsolver-highs/check/instances/1449a.lp +1 -0
- data/ext/lpsolver-highs/check/instances/1449b.lp +1 -0
- data/ext/lpsolver-highs/check/instances/1451.lp +8 -0
- data/ext/lpsolver-highs/check/instances/2122.lp +1822 -0
- data/ext/lpsolver-highs/check/instances/2171.mps +717 -0
- data/ext/lpsolver-highs/check/instances/25fv47.mps +6919 -0
- data/ext/lpsolver-highs/check/instances/2821-duplicate.mps +31 -0
- data/ext/lpsolver-highs/check/instances/2821-qmatrix.mps +31 -0
- data/ext/lpsolver-highs/check/instances/2821-quadobj.mps +29 -0
- data/ext/lpsolver-highs/check/instances/2821-summation.mps +30 -0
- data/ext/lpsolver-highs/check/instances/2821.mps +29 -0
- data/ext/lpsolver-highs/check/instances/2894.mps +89 -0
- data/ext/lpsolver-highs/check/instances/80bau3b.mps +23732 -0
- data/ext/lpsolver-highs/check/instances/WithInf.set +3 -0
- data/ext/lpsolver-highs/check/instances/adlittle.mps +335 -0
- data/ext/lpsolver-highs/check/instances/afiro.mps +83 -0
- data/ext/lpsolver-highs/check/instances/avgas.mps +51 -0
- data/ext/lpsolver-highs/check/instances/bell5.mps +384 -0
- data/ext/lpsolver-highs/check/instances/bgetam.mps +2112 -0
- data/ext/lpsolver-highs/check/instances/blending.mps +13 -0
- data/ext/lpsolver-highs/check/instances/box1.mps +1085 -0
- data/ext/lpsolver-highs/check/instances/chip.mps +13 -0
- data/ext/lpsolver-highs/check/instances/comment.mps +23 -0
- data/ext/lpsolver-highs/check/instances/cplex1.mps +9674 -0
- data/ext/lpsolver-highs/check/instances/dD2e.mps +10 -0
- data/ext/lpsolver-highs/check/instances/dcmulti.mps +2310 -0
- data/ext/lpsolver-highs/check/instances/e226.mps +1733 -0
- data/ext/lpsolver-highs/check/instances/egout-ac.mps +473 -0
- data/ext/lpsolver-highs/check/instances/egout.mps +403 -0
- data/ext/lpsolver-highs/check/instances/etamacro.mps +2084 -0
- data/ext/lpsolver-highs/check/instances/ex72a.mps +849 -0
- data/ext/lpsolver-highs/check/instances/fixed-binary.lp +11 -0
- data/ext/lpsolver-highs/check/instances/flugpl.mps +111 -0
- data/ext/lpsolver-highs/check/instances/flugpl_illegal_integer.sol +24 -0
- data/ext/lpsolver-highs/check/instances/flugpl_integer.sol +25 -0
- data/ext/lpsolver-highs/check/instances/forest6.mps +261 -0
- data/ext/lpsolver-highs/check/instances/galenet.mps +34 -0
- data/ext/lpsolver-highs/check/instances/gams10am.mps +478 -0
- data/ext/lpsolver-highs/check/instances/garbage.ems +3 -0
- data/ext/lpsolver-highs/check/instances/garbage.lp +3 -0
- data/ext/lpsolver-highs/check/instances/garbage.mps +3 -0
- data/ext/lpsolver-highs/check/instances/gas11.mps +2924 -0
- data/ext/lpsolver-highs/check/instances/gesa2.mps +5459 -0
- data/ext/lpsolver-highs/check/instances/greenbea.mps +19215 -0
- data/ext/lpsolver-highs/check/instances/gt2.mps +534 -0
- data/ext/lpsolver-highs/check/instances/infeasible-mip0.mps +140 -0
- data/ext/lpsolver-highs/check/instances/infeasible-mip1.mps +371 -0
- data/ext/lpsolver-highs/check/instances/israel.mps +1490 -0
- data/ext/lpsolver-highs/check/instances/issue-2095.mps +836 -0
- data/ext/lpsolver-highs/check/instances/issue-2173.mps +3331 -0
- data/ext/lpsolver-highs/check/instances/issue-2204.mps +143 -0
- data/ext/lpsolver-highs/check/instances/issue-2290.mps +158 -0
- data/ext/lpsolver-highs/check/instances/issue-2388.lp +76 -0
- data/ext/lpsolver-highs/check/instances/issue-2402.mps +435 -0
- data/ext/lpsolver-highs/check/instances/issue-2446.mps +9154 -0
- data/ext/lpsolver-highs/check/instances/issue-2585.lp +16 -0
- data/ext/lpsolver-highs/check/instances/issue-2874-3.mps +97 -0
- data/ext/lpsolver-highs/check/instances/klein1.mps +422 -0
- data/ext/lpsolver-highs/check/instances/lseu.mps +371 -0
- data/ext/lpsolver-highs/check/instances/model.xyz +1 -0
- data/ext/lpsolver-highs/check/instances/nan0.mps +13 -0
- data/ext/lpsolver-highs/check/instances/nan1.mps +13 -0
- data/ext/lpsolver-highs/check/instances/nan2.mps +13 -0
- data/ext/lpsolver-highs/check/instances/no-newline-eof.lp +5 -0
- data/ext/lpsolver-highs/check/instances/p01.mps +909 -0
- data/ext/lpsolver-highs/check/instances/p0548.mps +1992 -0
- data/ext/lpsolver-highs/check/instances/primal1.mps +3909 -0
- data/ext/lpsolver-highs/check/instances/qap04.mps +606 -0
- data/ext/lpsolver-highs/check/instances/qcqp.lp +8 -0
- data/ext/lpsolver-highs/check/instances/qjh.lp +9 -0
- data/ext/lpsolver-highs/check/instances/qjh.mps +18 -0
- data/ext/lpsolver-highs/check/instances/qjh_qmatrix.mps +19 -0
- data/ext/lpsolver-highs/check/instances/qjh_quadobj.mps +18 -0
- data/ext/lpsolver-highs/check/instances/qjh_quadobj_qmatrix.mps +25 -0
- data/ext/lpsolver-highs/check/instances/qjh_uncon.lp +10 -0
- data/ext/lpsolver-highs/check/instances/qjh_uncon.mps +17 -0
- data/ext/lpsolver-highs/check/instances/qpinfeasible.lp +8 -0
- data/ext/lpsolver-highs/check/instances/qptestnw.lp +7 -0
- data/ext/lpsolver-highs/check/instances/qpunbounded.lp +5 -0
- data/ext/lpsolver-highs/check/instances/refinery.mps +1882 -0
- data/ext/lpsolver-highs/check/instances/rgn.mps +559 -0
- data/ext/lpsolver-highs/check/instances/scrs8.mps +2717 -0
- data/ext/lpsolver-highs/check/instances/sctest.mps +66 -0
- data/ext/lpsolver-highs/check/instances/semi-continuous.lp +13 -0
- data/ext/lpsolver-highs/check/instances/semi-continuous.mps +24 -0
- data/ext/lpsolver-highs/check/instances/semi-integer.lp +15 -0
- data/ext/lpsolver-highs/check/instances/semi-integer.mps +22 -0
- data/ext/lpsolver-highs/check/instances/shell.mps +4039 -0
- data/ext/lpsolver-highs/check/instances/silly-names.mps +14 -0
- data/ext/lpsolver-highs/check/instances/small_mip.mps +87 -0
- data/ext/lpsolver-highs/check/instances/smalllp.mps +21 -0
- data/ext/lpsolver-highs/check/instances/sp150x300d.mps +1983 -0
- data/ext/lpsolver-highs/check/instances/stair.mps +2499 -0
- data/ext/lpsolver-highs/check/instances/standata.mps +2317 -0
- data/ext/lpsolver-highs/check/instances/standgub.mps +2428 -0
- data/ext/lpsolver-highs/check/instances/standmps.mps +2695 -0
- data/ext/lpsolver-highs/check/instances/test.mps +53 -0
- data/ext/lpsolver-highs/check/instances/vol1.mps +1895 -0
- data/ext/lpsolver-highs/check/instances/warnings.mps +68 -0
- data/ext/lpsolver-highs/check/instances/woodinfe.mps +216 -0
- data/ext/lpsolver-highs/check/matrix_multiplication.hpp +49 -0
- data/ext/lpsolver-highs/check/meson.build +92 -0
- data/ext/lpsolver-highs/check/pythontest.py +11 -0
- data/ext/lpsolver-highs/check/sample_options_file +8 -0
- data/ext/lpsolver-highs/cmake/CheckAtomic.cmake +74 -0
- data/ext/lpsolver-highs/cmake/FindCUDAConf.cmake +44 -0
- data/ext/lpsolver-highs/cmake/FindHipoDeps.cmake +351 -0
- data/ext/lpsolver-highs/cmake/README.md +243 -0
- data/ext/lpsolver-highs/cmake/cpp-highs.cmake +243 -0
- data/ext/lpsolver-highs/cmake/dotnet.cmake +94 -0
- data/ext/lpsolver-highs/cmake/highs-config.cmake.in +22 -0
- data/ext/lpsolver-highs/cmake/python-highs.cmake +74 -0
- data/ext/lpsolver-highs/cmake/set-version.cmake +26 -0
- data/ext/lpsolver-highs/cmake/sources-python.cmake +461 -0
- data/ext/lpsolver-highs/cmake/sources.cmake +618 -0
- data/ext/lpsolver-highs/docs/HiGHS_CopyrightHeader.pl +78 -0
- data/ext/lpsolver-highs/docs/HiGHS_CopyrightHeaderUpdateAll +32 -0
- data/ext/lpsolver-highs/docs/Project.toml +7 -0
- data/ext/lpsolver-highs/docs/README.md +27 -0
- data/ext/lpsolver-highs/docs/c_api_gen/HConfig.h +1 -0
- data/ext/lpsolver-highs/docs/c_api_gen/build.jl +48 -0
- data/ext/lpsolver-highs/docs/make.jl +115 -0
- data/ext/lpsolver-highs/docs/src/assets/logo.png +0 -0
- data/ext/lpsolver-highs/docs/src/callbacks.md +171 -0
- data/ext/lpsolver-highs/docs/src/executable.md +88 -0
- data/ext/lpsolver-highs/docs/src/guide/advanced.md +66 -0
- data/ext/lpsolver-highs/docs/src/guide/basic.md +116 -0
- data/ext/lpsolver-highs/docs/src/guide/further.md +193 -0
- data/ext/lpsolver-highs/docs/src/guide/gpu.md +58 -0
- data/ext/lpsolver-highs/docs/src/guide/index.md +18 -0
- data/ext/lpsolver-highs/docs/src/guide/kkt.md +219 -0
- data/ext/lpsolver-highs/docs/src/guide/numerics.md +55 -0
- data/ext/lpsolver-highs/docs/src/index.md +86 -0
- data/ext/lpsolver-highs/docs/src/installation.md +130 -0
- data/ext/lpsolver-highs/docs/src/interfaces/c_api.md +6 -0
- data/ext/lpsolver-highs/docs/src/interfaces/cpp/examples.md +1 -0
- data/ext/lpsolver-highs/docs/src/interfaces/cpp/index.md +29 -0
- data/ext/lpsolver-highs/docs/src/interfaces/cpp/library.md +107 -0
- data/ext/lpsolver-highs/docs/src/interfaces/csharp.md +55 -0
- data/ext/lpsolver-highs/docs/src/interfaces/fortran.md +11 -0
- data/ext/lpsolver-highs/docs/src/interfaces/julia/index.md +130 -0
- data/ext/lpsolver-highs/docs/src/interfaces/other.md +41 -0
- data/ext/lpsolver-highs/docs/src/interfaces/python/example-py.md +275 -0
- data/ext/lpsolver-highs/docs/src/interfaces/python/index.md +91 -0
- data/ext/lpsolver-highs/docs/src/interfaces/python/model-py.md +90 -0
- data/ext/lpsolver-highs/docs/src/options/definitions.md +529 -0
- data/ext/lpsolver-highs/docs/src/options/intro.md +46 -0
- data/ext/lpsolver-highs/docs/src/parallel.md +88 -0
- data/ext/lpsolver-highs/docs/src/solvers.md +168 -0
- data/ext/lpsolver-highs/docs/src/structures/classes/HighsHessian.md +9 -0
- data/ext/lpsolver-highs/docs/src/structures/classes/HighsIis.md +16 -0
- data/ext/lpsolver-highs/docs/src/structures/classes/HighsLp.md +19 -0
- data/ext/lpsolver-highs/docs/src/structures/classes/HighsModel.md +6 -0
- data/ext/lpsolver-highs/docs/src/structures/classes/HighsSparseMatrix.md +10 -0
- data/ext/lpsolver-highs/docs/src/structures/classes/index.md +11 -0
- data/ext/lpsolver-highs/docs/src/structures/enums.md +114 -0
- data/ext/lpsolver-highs/docs/src/structures/index.md +12 -0
- data/ext/lpsolver-highs/docs/src/structures/structs/HighsBasis.md +8 -0
- data/ext/lpsolver-highs/docs/src/structures/structs/HighsInfo.md +148 -0
- data/ext/lpsolver-highs/docs/src/structures/structs/HighsLinearObjective.md +11 -0
- data/ext/lpsolver-highs/docs/src/structures/structs/HighsSolution.md +10 -0
- data/ext/lpsolver-highs/docs/src/structures/structs/index.md +10 -0
- data/ext/lpsolver-highs/docs/src/terminology.md +163 -0
- data/ext/lpsolver-highs/examples/CMakeLists.txt +26 -0
- data/ext/lpsolver-highs/examples/Docs.py +104 -0
- data/ext/lpsolver-highs/examples/branch-and-price.py +465 -0
- data/ext/lpsolver-highs/examples/call_highs_from_c.c +685 -0
- data/ext/lpsolver-highs/examples/call_highs_from_c_minimal.c +659 -0
- data/ext/lpsolver-highs/examples/call_highs_from_cpp.cpp +178 -0
- data/ext/lpsolver-highs/examples/call_highs_from_csharp.cs +83 -0
- data/ext/lpsolver-highs/examples/call_highs_from_fortran.f90 +579 -0
- data/ext/lpsolver-highs/examples/call_highs_from_python.py +448 -0
- data/ext/lpsolver-highs/examples/call_highs_from_python_highspy.py +71 -0
- data/ext/lpsolver-highs/examples/call_highs_from_python_mps.py +59 -0
- data/ext/lpsolver-highs/examples/callback_gap.py +71 -0
- data/ext/lpsolver-highs/examples/chip.py +43 -0
- data/ext/lpsolver-highs/examples/chip0.py +29 -0
- data/ext/lpsolver-highs/examples/distillation.py +77 -0
- data/ext/lpsolver-highs/examples/knapsack.py +43 -0
- data/ext/lpsolver-highs/examples/minimal.py +11 -0
- data/ext/lpsolver-highs/examples/multi_objective.py +139 -0
- data/ext/lpsolver-highs/examples/multiple_objective.py +120 -0
- data/ext/lpsolver-highs/examples/network_flow.py +37 -0
- data/ext/lpsolver-highs/examples/nqueens.py +29 -0
- data/ext/lpsolver-highs/examples/plot_highs_log.py +134 -0
- data/ext/lpsolver-highs/extern/CLI11.hpp +11546 -0
- data/ext/lpsolver-highs/extern/LICENCE_1_0.txt +23 -0
- data/ext/lpsolver-highs/extern/amd/License.txt +35 -0
- data/ext/lpsolver-highs/extern/amd/SuiteSparse_config.c +54 -0
- data/ext/lpsolver-highs/extern/amd/SuiteSparse_config.h +56 -0
- data/ext/lpsolver-highs/extern/amd/amd.h +357 -0
- data/ext/lpsolver-highs/extern/amd/amd_1.c +172 -0
- data/ext/lpsolver-highs/extern/amd/amd_2.c +1761 -0
- data/ext/lpsolver-highs/extern/amd/amd_aat.c +179 -0
- data/ext/lpsolver-highs/extern/amd/amd_control.c +65 -0
- data/ext/lpsolver-highs/extern/amd/amd_defaults.c +37 -0
- data/ext/lpsolver-highs/extern/amd/amd_info.c +120 -0
- data/ext/lpsolver-highs/extern/amd/amd_internal.h +137 -0
- data/ext/lpsolver-highs/extern/amd/amd_order.c +195 -0
- data/ext/lpsolver-highs/extern/amd/amd_post_tree.c +105 -0
- data/ext/lpsolver-highs/extern/amd/amd_postorder.c +140 -0
- data/ext/lpsolver-highs/extern/amd/amd_preprocess.c +107 -0
- data/ext/lpsolver-highs/extern/amd/amd_valid.c +93 -0
- data/ext/lpsolver-highs/extern/amd/changes.txt +8 -0
- data/ext/lpsolver-highs/extern/catch.hpp +18861 -0
- data/ext/lpsolver-highs/extern/metis/Changes.txt +31 -0
- data/ext/lpsolver-highs/extern/metis/GKlib/GKlib.h +62 -0
- data/ext/lpsolver-highs/extern/metis/GKlib/error.c +21 -0
- data/ext/lpsolver-highs/extern/metis/GKlib/gk_arch.h +64 -0
- data/ext/lpsolver-highs/extern/metis/GKlib/gk_defs.h +19 -0
- data/ext/lpsolver-highs/extern/metis/GKlib/gk_macros.h +50 -0
- data/ext/lpsolver-highs/extern/metis/GKlib/gk_mkblas.h +51 -0
- data/ext/lpsolver-highs/extern/metis/GKlib/gk_mkmemory.h +80 -0
- data/ext/lpsolver-highs/extern/metis/GKlib/gk_mkpqueue.h +329 -0
- data/ext/lpsolver-highs/extern/metis/GKlib/gk_mkrandom.h +89 -0
- data/ext/lpsolver-highs/extern/metis/GKlib/gk_mksort.h +271 -0
- data/ext/lpsolver-highs/extern/metis/GKlib/gk_ms_inttypes.h +41 -0
- data/ext/lpsolver-highs/extern/metis/GKlib/gk_ms_stat.h +22 -0
- data/ext/lpsolver-highs/extern/metis/GKlib/gk_ms_stdint.h +41 -0
- data/ext/lpsolver-highs/extern/metis/GKlib/gk_proto.h +50 -0
- data/ext/lpsolver-highs/extern/metis/GKlib/gk_struct.h +66 -0
- data/ext/lpsolver-highs/extern/metis/GKlib/gk_types.h +15 -0
- data/ext/lpsolver-highs/extern/metis/GKlib/mcore.c +176 -0
- data/ext/lpsolver-highs/extern/metis/GKlib/memory.c +23 -0
- data/ext/lpsolver-highs/extern/metis/GKlib/random.c +37 -0
- data/ext/lpsolver-highs/extern/metis/LICENSE.txt +18 -0
- data/ext/lpsolver-highs/extern/metis/libmetis/auxapi.c +27 -0
- data/ext/lpsolver-highs/extern/metis/libmetis/balance.c +491 -0
- data/ext/lpsolver-highs/extern/metis/libmetis/bucketsort.c +44 -0
- data/ext/lpsolver-highs/extern/metis/libmetis/coarsen.c +895 -0
- data/ext/lpsolver-highs/extern/metis/libmetis/compress.c +231 -0
- data/ext/lpsolver-highs/extern/metis/libmetis/contig.c +83 -0
- data/ext/lpsolver-highs/extern/metis/libmetis/defs.h +39 -0
- data/ext/lpsolver-highs/extern/metis/libmetis/fm.c +527 -0
- data/ext/lpsolver-highs/extern/metis/libmetis/gklib.c +55 -0
- data/ext/lpsolver-highs/extern/metis/libmetis/gklib_defs.h +33 -0
- data/ext/lpsolver-highs/extern/metis/libmetis/graph.c +268 -0
- data/ext/lpsolver-highs/extern/metis/libmetis/initpart.c +385 -0
- data/ext/lpsolver-highs/extern/metis/libmetis/macros.h +59 -0
- data/ext/lpsolver-highs/extern/metis/libmetis/mcutil.c +162 -0
- data/ext/lpsolver-highs/extern/metis/libmetis/metislib.h +35 -0
- data/ext/lpsolver-highs/extern/metis/libmetis/mmd.c +598 -0
- data/ext/lpsolver-highs/extern/metis/libmetis/ometis.c +661 -0
- data/ext/lpsolver-highs/extern/metis/libmetis/options.c +260 -0
- data/ext/lpsolver-highs/extern/metis/libmetis/proto.h +172 -0
- data/ext/lpsolver-highs/extern/metis/libmetis/refine.c +99 -0
- data/ext/lpsolver-highs/extern/metis/libmetis/separator.c +57 -0
- data/ext/lpsolver-highs/extern/metis/libmetis/sfm.c +581 -0
- data/ext/lpsolver-highs/extern/metis/libmetis/srefine.c +152 -0
- data/ext/lpsolver-highs/extern/metis/libmetis/stdheaders.h +29 -0
- data/ext/lpsolver-highs/extern/metis/libmetis/struct.h +117 -0
- data/ext/lpsolver-highs/extern/metis/libmetis/util.c +59 -0
- data/ext/lpsolver-highs/extern/metis/libmetis/wspace.c +91 -0
- data/ext/lpsolver-highs/extern/metis/metis.h +271 -0
- data/ext/lpsolver-highs/extern/pdqsort/license.txt +16 -0
- data/ext/lpsolver-highs/extern/pdqsort/pdqsort.h +532 -0
- data/ext/lpsolver-highs/extern/rcm/LICENSE +19 -0
- data/ext/lpsolver-highs/extern/rcm/rcm.cpp +873 -0
- data/ext/lpsolver-highs/extern/rcm/rcm.h +22 -0
- data/ext/lpsolver-highs/extern/zstr/LICENSE +21 -0
- data/ext/lpsolver-highs/extern/zstr/strict_fstream.hpp +237 -0
- data/ext/lpsolver-highs/extern/zstr/zstr.hpp +473 -0
- data/ext/lpsolver-highs/flake.lock +61 -0
- data/ext/lpsolver-highs/flake.nix +73 -0
- data/ext/lpsolver-highs/highs/CMakeLists.txt +499 -0
- data/ext/lpsolver-highs/highs/HConfig.h.bazel.in +25 -0
- data/ext/lpsolver-highs/highs/HConfig.h.in +22 -0
- data/ext/lpsolver-highs/highs/HConfig.h.meson.in +17 -0
- data/ext/lpsolver-highs/highs/Highs.h +1812 -0
- data/ext/lpsolver-highs/highs/HighsRun.md +143 -0
- data/ext/lpsolver-highs/highs/highs_bindings.cpp +1826 -0
- data/ext/lpsolver-highs/highs/highspy/__init__.py +93 -0
- data/ext/lpsolver-highs/highs/highspy/__init__.pyi +91 -0
- data/ext/lpsolver-highs/highs/highspy/_core/__init__.pyi +1058 -0
- data/ext/lpsolver-highs/highs/highspy/_core/cb.pyi +118 -0
- data/ext/lpsolver-highs/highs/highspy/_core/simplex_constants.pyi +472 -0
- data/ext/lpsolver-highs/highs/highspy/highs.py +2430 -0
- data/ext/lpsolver-highs/highs/interfaces/highs_c_api.cpp +1812 -0
- data/ext/lpsolver-highs/highs/interfaces/highs_c_api.h +2651 -0
- data/ext/lpsolver-highs/highs/interfaces/highs_csharp_api.cs +1142 -0
- data/ext/lpsolver-highs/highs/interfaces/highs_fortran_api.f90 +873 -0
- data/ext/lpsolver-highs/highs/io/Filereader.cpp +87 -0
- data/ext/lpsolver-highs/highs/io/Filereader.h +45 -0
- data/ext/lpsolver-highs/highs/io/FilereaderLp.cpp +539 -0
- data/ext/lpsolver-highs/highs/io/FilereaderLp.h +49 -0
- data/ext/lpsolver-highs/highs/io/FilereaderMps.cpp +86 -0
- data/ext/lpsolver-highs/highs/io/FilereaderMps.h +27 -0
- data/ext/lpsolver-highs/highs/io/HMPSIO.cpp +1001 -0
- data/ext/lpsolver-highs/highs/io/HMPSIO.h +78 -0
- data/ext/lpsolver-highs/highs/io/HMpsFF.cpp +2113 -0
- data/ext/lpsolver-highs/highs/io/HMpsFF.h +245 -0
- data/ext/lpsolver-highs/highs/io/HighsIO.cpp +371 -0
- data/ext/lpsolver-highs/highs/io/HighsIO.h +118 -0
- data/ext/lpsolver-highs/highs/io/LoadOptions.cpp +60 -0
- data/ext/lpsolver-highs/highs/io/LoadOptions.h +24 -0
- data/ext/lpsolver-highs/highs/io/filereaderlp/LICENSE +19 -0
- data/ext/lpsolver-highs/highs/io/filereaderlp/builder.hpp +25 -0
- data/ext/lpsolver-highs/highs/io/filereaderlp/def.hpp +19 -0
- data/ext/lpsolver-highs/highs/io/filereaderlp/model.hpp +68 -0
- data/ext/lpsolver-highs/highs/io/filereaderlp/reader.cpp +1375 -0
- data/ext/lpsolver-highs/highs/io/filereaderlp/reader.hpp +10 -0
- data/ext/lpsolver-highs/highs/ipm/IpxSolution.h +32 -0
- data/ext/lpsolver-highs/highs/ipm/IpxWrapper.cpp +1526 -0
- data/ext/lpsolver-highs/highs/ipm/IpxWrapper.h +106 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu.h +161 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_factorize.c +132 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_factorize.h +247 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_get_factors.c +148 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_get_factors.h +108 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_initialize.c +24 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_initialize.h +119 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_obj_factorize.h +34 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_obj_free.h +19 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_obj_get_factors.h +34 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_obj_initialize.h +46 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_obj_solve_dense.h +29 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_obj_solve_for_update.h +42 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_obj_solve_sparse.h +32 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_obj_update.h +31 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_object.c +325 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_object.h +30 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_solve_dense.c +46 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_solve_dense.h +75 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_solve_for_update.c +79 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_solve_for_update.h +169 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_solve_sparse.c +63 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_solve_sparse.h +112 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_update.c +44 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_update.h +125 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/lu_build_factors.c +441 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/lu_condest.c +124 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/lu_def.h +39 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/lu_dfs.c +141 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/lu_factorize_bump.c +56 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/lu_file.c +184 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/lu_file.h +21 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/lu_garbage_perm.c +53 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/lu_initialize.c +56 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/lu_internal.c +352 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/lu_internal.h +220 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/lu_list.h +173 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/lu_markowitz.c +188 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/lu_matrix_norm.c +51 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/lu_pivot.c +1247 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/lu_residual_test.c +155 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/lu_setup_bump.c +198 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/lu_singletons.c +511 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/lu_solve_dense.c +129 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/lu_solve_for_update.c +360 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/lu_solve_sparse.c +284 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/lu_solve_symbolic.c +48 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/lu_solve_triangular.c +140 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/lu_update.c +908 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/auxiliary/Auxiliary.cpp +301 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/auxiliary/Auxiliary.h +104 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/auxiliary/IntConfig.h +27 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/auxiliary/KrylovMethods.cpp +193 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/auxiliary/KrylovMethods.h +30 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/auxiliary/Log.cpp +60 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/auxiliary/Log.h +62 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/auxiliary/OrderingPrint.h +10 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/auxiliary/VectorOperations.cpp +117 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/auxiliary/VectorOperations.h +59 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/auxiliary/mycblas.h +85 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/Analyse.cpp +1367 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/Analyse.h +122 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/CallAndTimeBlas.cpp +114 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/CallAndTimeBlas.h +46 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/CliqueStack.cpp +82 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/CliqueStack.h +83 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/DataCollector.cpp +326 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/DataCollector.h +86 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/DenseFact.h +48 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/DenseFactHybrid.cpp +279 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/DenseFactKernel.cpp +284 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/DgemmParallel.cpp +38 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/DgemmParallel.h +32 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/FactorHiGHS.cpp +57 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/FactorHiGHS.h +112 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/FactorHiGHSSettings.h +63 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/Factorise.cpp +405 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/Factorise.h +85 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/FormatHandler.cpp +46 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/FormatHandler.h +95 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/HybridHybridFormatHandler.cpp +238 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/HybridHybridFormatHandler.h +31 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/HybridSolveHandler.cpp +272 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/HybridSolveHandler.h +26 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/KrylovMethodsIpm.cpp +83 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/KrylovMethodsIpm.h +45 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/Numeric.cpp +54 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/Numeric.h +46 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/ReturnValues.h +19 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/SolveHandler.cpp +10 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/SolveHandler.h +48 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/Swaps.cpp +70 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/Swaps.h +19 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/Symbolic.cpp +101 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/Symbolic.h +220 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/Timing.h +114 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/ipm/Control.cpp +38 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/ipm/Control.h +41 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/ipm/FactorHiGHSSolver.cpp +887 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/ipm/FactorHiGHSSolver.h +92 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/ipm/Info.h +58 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/ipm/IpmData.cpp +8 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/ipm/IpmData.h +37 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/ipm/Iterate.cpp +640 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/ipm/Iterate.h +172 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/ipm/LinearSolver.h +81 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/ipm/LogHighs.cpp +71 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/ipm/LogHighs.h +33 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/ipm/Model.cpp +403 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/ipm/Model.h +136 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/ipm/Options.h +35 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/ipm/Parameters.h +63 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/ipm/PreProcess.cpp +646 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/ipm/PreProcess.h +94 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/ipm/Refine.cpp +214 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/ipm/Solver.cpp +1346 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/ipm/Solver.h +338 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/ipm/Status.h +88 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/basiclu_kernel.cc +71 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/basiclu_kernel.h +20 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/basiclu_wrapper.cc +299 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/basiclu_wrapper.h +47 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/basis.cc +966 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/basis.h +350 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/conjugate_residuals.cc +217 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/conjugate_residuals.h +74 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/control.cc +151 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/control.h +167 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/crossover.cc +479 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/crossover.h +157 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/diagonal_precond.cc +70 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/diagonal_precond.h +45 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/forrest_tomlin.cc +360 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/forrest_tomlin.h +102 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/guess_basis.cc +233 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/guess_basis.h +21 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/indexed_vector.cc +30 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/indexed_vector.h +113 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/info.cc +124 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/info.h +27 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/ipm.cc +897 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/ipm.h +94 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/ipx_c.cc +83 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/ipx_c.h +47 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/ipx_config.h +9 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/ipx_info.h +111 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/ipx_internal.h +89 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/ipx_parameters.h +76 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/ipx_status.h +57 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/iterate.cc +683 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/iterate.h +331 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/kkt_solver.cc +23 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/kkt_solver.h +70 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/kkt_solver_basis.cc +387 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/kkt_solver_basis.h +66 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/kkt_solver_diag.cc +120 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/kkt_solver_diag.h +48 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/linear_operator.cc +10 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/linear_operator.h +26 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/lp_solver.cc +686 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/lp_solver.h +204 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/lu_factorization.cc +131 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/lu_factorization.h +79 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/lu_update.cc +62 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/lu_update.h +129 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/maxvolume.cc +337 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/maxvolume.h +54 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/model.cc +1528 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/model.h +413 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/multistream.h +52 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/normal_matrix.cc +126 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/normal_matrix.h +44 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/power_method.h +44 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/sparse_matrix.cc +382 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/sparse_matrix.h +195 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/sparse_utils.cc +92 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/sparse_utils.h +58 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/splitted_normal_matrix.cc +117 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/splitted_normal_matrix.h +63 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/starting_basis.cc +182 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/starting_basis.h +39 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/symbolic_invert.cc +183 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/symbolic_invert.h +29 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/timer.cc +16 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/timer.h +25 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/utils.cc +95 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/utils.h +37 -0
- data/ext/lpsolver-highs/highs/lp_data/HConst.h +430 -0
- data/ext/lpsolver-highs/highs/lp_data/HStruct.h +213 -0
- data/ext/lpsolver-highs/highs/lp_data/Highs.cpp +4949 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsAnalysis.h +23 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsCallback.cpp +323 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsCallback.h +104 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsCallbackStruct.h +70 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsDebug.cpp +54 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsDebug.h +34 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsDeprecated.cpp +181 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsIis.cpp +1290 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsIis.h +139 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsInfo.cpp +426 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsInfo.h +421 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsInfoDebug.cpp +175 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsInfoDebug.h +27 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsInterface.cpp +4344 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsLp.cpp +564 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsLp.h +97 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsLpSolverObject.h +47 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsLpUtils.cpp +3794 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsLpUtils.h +330 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsModelUtils.cpp +1650 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsModelUtils.h +129 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsOptions.cpp +1176 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsOptions.h +1715 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsRanging.cpp +733 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsRanging.h +43 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsSolution.cpp +2194 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsSolution.h +179 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsSolutionDebug.cpp +490 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsSolutionDebug.h +87 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsSolve.cpp +747 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsSolve.h +29 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsStatus.cpp +48 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsStatus.h +29 -0
- data/ext/lpsolver-highs/highs/lp_data/Iis.md +113 -0
- data/ext/lpsolver-highs/highs/meson.build +433 -0
- data/ext/lpsolver-highs/highs/mip/HighsCliqueTable.cpp +2236 -0
- data/ext/lpsolver-highs/highs/mip/HighsCliqueTable.h +329 -0
- data/ext/lpsolver-highs/highs/mip/HighsConflictPool.cpp +201 -0
- data/ext/lpsolver-highs/highs/mip/HighsConflictPool.h +109 -0
- data/ext/lpsolver-highs/highs/mip/HighsCutGeneration.cpp +1491 -0
- data/ext/lpsolver-highs/highs/mip/HighsCutGeneration.h +108 -0
- data/ext/lpsolver-highs/highs/mip/HighsCutPool.cpp +526 -0
- data/ext/lpsolver-highs/highs/mip/HighsCutPool.h +168 -0
- data/ext/lpsolver-highs/highs/mip/HighsDebugSol.cpp +313 -0
- data/ext/lpsolver-highs/highs/mip/HighsDebugSol.h +133 -0
- data/ext/lpsolver-highs/highs/mip/HighsDomain.cpp +3861 -0
- data/ext/lpsolver-highs/highs/mip/HighsDomain.h +657 -0
- data/ext/lpsolver-highs/highs/mip/HighsDomainChange.h +48 -0
- data/ext/lpsolver-highs/highs/mip/HighsDynamicRowMatrix.cpp +199 -0
- data/ext/lpsolver-highs/highs/mip/HighsDynamicRowMatrix.h +104 -0
- data/ext/lpsolver-highs/highs/mip/HighsFeasibilityJump.cpp +139 -0
- data/ext/lpsolver-highs/highs/mip/HighsGFkSolve.cpp +106 -0
- data/ext/lpsolver-highs/highs/mip/HighsGFkSolve.h +439 -0
- data/ext/lpsolver-highs/highs/mip/HighsImplications.cpp +915 -0
- data/ext/lpsolver-highs/highs/mip/HighsImplications.h +194 -0
- data/ext/lpsolver-highs/highs/mip/HighsLpAggregator.cpp +56 -0
- data/ext/lpsolver-highs/highs/mip/HighsLpAggregator.h +50 -0
- data/ext/lpsolver-highs/highs/mip/HighsLpRelaxation.cpp +1609 -0
- data/ext/lpsolver-highs/highs/mip/HighsLpRelaxation.h +361 -0
- data/ext/lpsolver-highs/highs/mip/HighsMipAnalysis.cpp +313 -0
- data/ext/lpsolver-highs/highs/mip/HighsMipAnalysis.h +71 -0
- data/ext/lpsolver-highs/highs/mip/HighsMipSolver.cpp +1002 -0
- data/ext/lpsolver-highs/highs/mip/HighsMipSolver.h +159 -0
- data/ext/lpsolver-highs/highs/mip/HighsMipSolverData.cpp +2936 -0
- data/ext/lpsolver-highs/highs/mip/HighsMipSolverData.h +313 -0
- data/ext/lpsolver-highs/highs/mip/HighsModkSeparator.cpp +267 -0
- data/ext/lpsolver-highs/highs/mip/HighsModkSeparator.h +60 -0
- data/ext/lpsolver-highs/highs/mip/HighsNodeQueue.cpp +443 -0
- data/ext/lpsolver-highs/highs/mip/HighsNodeQueue.h +312 -0
- data/ext/lpsolver-highs/highs/mip/HighsObjectiveFunction.cpp +124 -0
- data/ext/lpsolver-highs/highs/mip/HighsObjectiveFunction.h +71 -0
- data/ext/lpsolver-highs/highs/mip/HighsPathSeparator.cpp +549 -0
- data/ext/lpsolver-highs/highs/mip/HighsPathSeparator.h +39 -0
- data/ext/lpsolver-highs/highs/mip/HighsPrimalHeuristics.cpp +1673 -0
- data/ext/lpsolver-highs/highs/mip/HighsPrimalHeuristics.h +75 -0
- data/ext/lpsolver-highs/highs/mip/HighsPseudocost.cpp +129 -0
- data/ext/lpsolver-highs/highs/mip/HighsPseudocost.h +366 -0
- data/ext/lpsolver-highs/highs/mip/HighsRedcostFixing.cpp +316 -0
- data/ext/lpsolver-highs/highs/mip/HighsRedcostFixing.h +42 -0
- data/ext/lpsolver-highs/highs/mip/HighsSearch.cpp +1881 -0
- data/ext/lpsolver-highs/highs/mip/HighsSearch.h +241 -0
- data/ext/lpsolver-highs/highs/mip/HighsSeparation.cpp +186 -0
- data/ext/lpsolver-highs/highs/mip/HighsSeparation.h +41 -0
- data/ext/lpsolver-highs/highs/mip/HighsSeparator.cpp +39 -0
- data/ext/lpsolver-highs/highs/mip/HighsSeparator.h +60 -0
- data/ext/lpsolver-highs/highs/mip/HighsTableauSeparator.cpp +244 -0
- data/ext/lpsolver-highs/highs/mip/HighsTableauSeparator.h +34 -0
- data/ext/lpsolver-highs/highs/mip/HighsTransformedLp.cpp +563 -0
- data/ext/lpsolver-highs/highs/mip/HighsTransformedLp.h +63 -0
- data/ext/lpsolver-highs/highs/mip/MipTimer.h +544 -0
- data/ext/lpsolver-highs/highs/mip/feasibilityjump.hh +800 -0
- data/ext/lpsolver-highs/highs/model/HighsHessian.cpp +263 -0
- data/ext/lpsolver-highs/highs/model/HighsHessian.h +54 -0
- data/ext/lpsolver-highs/highs/model/HighsHessianUtils.cpp +584 -0
- data/ext/lpsolver-highs/highs/model/HighsHessianUtils.h +47 -0
- data/ext/lpsolver-highs/highs/model/HighsModel.cpp +46 -0
- data/ext/lpsolver-highs/highs/model/HighsModel.h +42 -0
- data/ext/lpsolver-highs/highs/parallel/HighsBinarySemaphore.h +108 -0
- data/ext/lpsolver-highs/highs/parallel/HighsCacheAlign.h +82 -0
- data/ext/lpsolver-highs/highs/parallel/HighsCombinable.h +116 -0
- data/ext/lpsolver-highs/highs/parallel/HighsMutex.h +124 -0
- data/ext/lpsolver-highs/highs/parallel/HighsParallel.h +128 -0
- data/ext/lpsolver-highs/highs/parallel/HighsRaceTimer.h +38 -0
- data/ext/lpsolver-highs/highs/parallel/HighsSchedulerConstants.h +19 -0
- data/ext/lpsolver-highs/highs/parallel/HighsSpinMutex.h +48 -0
- data/ext/lpsolver-highs/highs/parallel/HighsSplitDeque.h +606 -0
- data/ext/lpsolver-highs/highs/parallel/HighsTask.h +170 -0
- data/ext/lpsolver-highs/highs/parallel/HighsTaskExecutor.cpp +43 -0
- data/ext/lpsolver-highs/highs/parallel/HighsTaskExecutor.h +217 -0
- data/ext/lpsolver-highs/highs/pdlp/CupdlpWrapper.cpp +848 -0
- data/ext/lpsolver-highs/highs/pdlp/CupdlpWrapper.h +108 -0
- data/ext/lpsolver-highs/highs/pdlp/HiPdlpTimer.h +155 -0
- data/ext/lpsolver-highs/highs/pdlp/HiPdlpWrapper.cpp +141 -0
- data/ext/lpsolver-highs/highs/pdlp/HiPdlpWrapper.h +26 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/Diff +12 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/Meld +7 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/Merge +2 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/README.md +95 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/cuda/CMakeLists.txt +58 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/cuda/cupdlp_cuda_kernels.cu +338 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/cuda/cupdlp_cuda_kernels.cuh +319 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/cuda/cupdlp_cudalinalg.cu +386 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/cuda/cupdlp_cudalinalg.cuh +149 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/cuda/test_cublas.c +154 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/cuda/test_cuda_linalg.c +79 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/cupdlp.h +16 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/cupdlp_cs.c +214 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/cupdlp_cs.h +40 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/cupdlp_defs.h +447 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/cupdlp_linalg.c +802 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/cupdlp_linalg.h +189 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/cupdlp_proj.c +148 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/cupdlp_proj.h +19 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/cupdlp_restart.c +124 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/cupdlp_restart.h +31 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/cupdlp_scaling.c +425 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/cupdlp_scaling.h +26 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/cupdlp_solver.c +1498 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/cupdlp_solver.h +105 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/cupdlp_step.c +478 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/cupdlp_step.h +37 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/cupdlp_utils.c +1850 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/cupdlp_utils.h +212 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/glbopts.h +342 -0
- data/ext/lpsolver-highs/highs/pdlp/hipdlp/defs.hpp +222 -0
- data/ext/lpsolver-highs/highs/pdlp/hipdlp/linalg.cc +231 -0
- data/ext/lpsolver-highs/highs/pdlp/hipdlp/linalg.hpp +61 -0
- data/ext/lpsolver-highs/highs/pdlp/hipdlp/logger.cc +225 -0
- data/ext/lpsolver-highs/highs/pdlp/hipdlp/logger.hpp +80 -0
- data/ext/lpsolver-highs/highs/pdlp/hipdlp/pdhg.cc +2798 -0
- data/ext/lpsolver-highs/highs/pdlp/hipdlp/pdhg.cu +497 -0
- data/ext/lpsolver-highs/highs/pdlp/hipdlp/pdhg.hpp +358 -0
- data/ext/lpsolver-highs/highs/pdlp/hipdlp/pdhg_kernels.hpp +77 -0
- data/ext/lpsolver-highs/highs/pdlp/hipdlp/pdlp_gpu_debug.hpp +62 -0
- data/ext/lpsolver-highs/highs/pdlp/hipdlp/restart.cc +132 -0
- data/ext/lpsolver-highs/highs/pdlp/hipdlp/restart.hpp +96 -0
- data/ext/lpsolver-highs/highs/pdlp/hipdlp/scaling.cc +307 -0
- data/ext/lpsolver-highs/highs/pdlp/hipdlp/scaling.hpp +74 -0
- data/ext/lpsolver-highs/highs/pdlp/hipdlp/solver_results.hpp +65 -0
- data/ext/lpsolver-highs/highs/presolve/HPresolve.cpp +8511 -0
- data/ext/lpsolver-highs/highs/presolve/HPresolve.h +505 -0
- data/ext/lpsolver-highs/highs/presolve/HPresolveAnalysis.cpp +239 -0
- data/ext/lpsolver-highs/highs/presolve/HPresolveAnalysis.h +52 -0
- data/ext/lpsolver-highs/highs/presolve/HighsPostsolveStack.cpp +1368 -0
- data/ext/lpsolver-highs/highs/presolve/HighsPostsolveStack.h +943 -0
- data/ext/lpsolver-highs/highs/presolve/HighsSymmetry.cpp +1921 -0
- data/ext/lpsolver-highs/highs/presolve/HighsSymmetry.h +284 -0
- data/ext/lpsolver-highs/highs/presolve/ICrash.cpp +474 -0
- data/ext/lpsolver-highs/highs/presolve/ICrash.h +124 -0
- data/ext/lpsolver-highs/highs/presolve/ICrashUtil.cpp +267 -0
- data/ext/lpsolver-highs/highs/presolve/ICrashUtil.h +62 -0
- data/ext/lpsolver-highs/highs/presolve/ICrashX.cpp +173 -0
- data/ext/lpsolver-highs/highs/presolve/ICrashX.h +23 -0
- data/ext/lpsolver-highs/highs/presolve/PresolveComponent.cpp +45 -0
- data/ext/lpsolver-highs/highs/presolve/PresolveComponent.h +90 -0
- data/ext/lpsolver-highs/highs/qpsolver/README.md +185 -0
- data/ext/lpsolver-highs/highs/qpsolver/a_asm.cpp +139 -0
- data/ext/lpsolver-highs/highs/qpsolver/a_asm.hpp +77 -0
- data/ext/lpsolver-highs/highs/qpsolver/a_quass.cpp +194 -0
- data/ext/lpsolver-highs/highs/qpsolver/a_quass.hpp +22 -0
- data/ext/lpsolver-highs/highs/qpsolver/basis.cpp +443 -0
- data/ext/lpsolver-highs/highs/qpsolver/basis.hpp +159 -0
- data/ext/lpsolver-highs/highs/qpsolver/crashsolution.hpp +20 -0
- data/ext/lpsolver-highs/highs/qpsolver/dantzigpricing.hpp +80 -0
- data/ext/lpsolver-highs/highs/qpsolver/devexharrispricing.hpp +98 -0
- data/ext/lpsolver-highs/highs/qpsolver/devexpricing.hpp +108 -0
- data/ext/lpsolver-highs/highs/qpsolver/eventhandler.hpp +30 -0
- data/ext/lpsolver-highs/highs/qpsolver/factor.hpp +408 -0
- data/ext/lpsolver-highs/highs/qpsolver/feasibility_bounded.hpp +114 -0
- data/ext/lpsolver-highs/highs/qpsolver/feasibility_highs.hpp +301 -0
- data/ext/lpsolver-highs/highs/qpsolver/gradient.hpp +46 -0
- data/ext/lpsolver-highs/highs/qpsolver/instance.hpp +70 -0
- data/ext/lpsolver-highs/highs/qpsolver/matrix.hpp +342 -0
- data/ext/lpsolver-highs/highs/qpsolver/perturbation.cpp +41 -0
- data/ext/lpsolver-highs/highs/qpsolver/perturbation.hpp +15 -0
- data/ext/lpsolver-highs/highs/qpsolver/pricing.hpp +22 -0
- data/ext/lpsolver-highs/highs/qpsolver/qpconst.hpp +34 -0
- data/ext/lpsolver-highs/highs/qpsolver/qpvector.hpp +242 -0
- data/ext/lpsolver-highs/highs/qpsolver/quass.cpp +551 -0
- data/ext/lpsolver-highs/highs/qpsolver/quass.hpp +27 -0
- data/ext/lpsolver-highs/highs/qpsolver/ratiotest.cpp +146 -0
- data/ext/lpsolver-highs/highs/qpsolver/ratiotest.hpp +26 -0
- data/ext/lpsolver-highs/highs/qpsolver/reducedcosts.hpp +46 -0
- data/ext/lpsolver-highs/highs/qpsolver/reducedgradient.hpp +95 -0
- data/ext/lpsolver-highs/highs/qpsolver/runtime.hpp +45 -0
- data/ext/lpsolver-highs/highs/qpsolver/scaling.cpp +123 -0
- data/ext/lpsolver-highs/highs/qpsolver/scaling.hpp +15 -0
- data/ext/lpsolver-highs/highs/qpsolver/settings.hpp +84 -0
- data/ext/lpsolver-highs/highs/qpsolver/snippets.hpp +36 -0
- data/ext/lpsolver-highs/highs/qpsolver/statistics.hpp +30 -0
- data/ext/lpsolver-highs/highs/qpsolver/steepestedgepricing.hpp +173 -0
- data/ext/lpsolver-highs/highs/simplex/HApp.h +550 -0
- data/ext/lpsolver-highs/highs/simplex/HEkk.cpp +4404 -0
- data/ext/lpsolver-highs/highs/simplex/HEkk.h +419 -0
- data/ext/lpsolver-highs/highs/simplex/HEkkControl.cpp +146 -0
- data/ext/lpsolver-highs/highs/simplex/HEkkDebug.cpp +1722 -0
- data/ext/lpsolver-highs/highs/simplex/HEkkDual.cpp +3003 -0
- data/ext/lpsolver-highs/highs/simplex/HEkkDual.h +513 -0
- data/ext/lpsolver-highs/highs/simplex/HEkkDualMulti.cpp +1020 -0
- data/ext/lpsolver-highs/highs/simplex/HEkkDualRHS.cpp +535 -0
- data/ext/lpsolver-highs/highs/simplex/HEkkDualRHS.h +134 -0
- data/ext/lpsolver-highs/highs/simplex/HEkkDualRow.cpp +697 -0
- data/ext/lpsolver-highs/highs/simplex/HEkkDualRow.h +201 -0
- data/ext/lpsolver-highs/highs/simplex/HEkkInterface.cpp +26 -0
- data/ext/lpsolver-highs/highs/simplex/HEkkPrimal.cpp +2984 -0
- data/ext/lpsolver-highs/highs/simplex/HEkkPrimal.h +191 -0
- data/ext/lpsolver-highs/highs/simplex/HSimplex.cpp +330 -0
- data/ext/lpsolver-highs/highs/simplex/HSimplex.h +42 -0
- data/ext/lpsolver-highs/highs/simplex/HSimplexDebug.cpp +145 -0
- data/ext/lpsolver-highs/highs/simplex/HSimplexDebug.h +48 -0
- data/ext/lpsolver-highs/highs/simplex/HSimplexNla.cpp +517 -0
- data/ext/lpsolver-highs/highs/simplex/HSimplexNla.h +158 -0
- data/ext/lpsolver-highs/highs/simplex/HSimplexNlaDebug.cpp +373 -0
- data/ext/lpsolver-highs/highs/simplex/HSimplexNlaFreeze.cpp +28 -0
- data/ext/lpsolver-highs/highs/simplex/HSimplexNlaProductForm.cpp +113 -0
- data/ext/lpsolver-highs/highs/simplex/HSimplexReport.cpp +77 -0
- data/ext/lpsolver-highs/highs/simplex/HSimplexReport.h +21 -0
- data/ext/lpsolver-highs/highs/simplex/HighsSimplexAnalysis.cpp +1495 -0
- data/ext/lpsolver-highs/highs/simplex/HighsSimplexAnalysis.h +500 -0
- data/ext/lpsolver-highs/highs/simplex/SimplexConst.h +273 -0
- data/ext/lpsolver-highs/highs/simplex/SimplexStruct.h +263 -0
- data/ext/lpsolver-highs/highs/simplex/SimplexTimer.h +414 -0
- data/ext/lpsolver-highs/highs/test_kkt/DevKkt.cpp +469 -0
- data/ext/lpsolver-highs/highs/test_kkt/DevKkt.h +143 -0
- data/ext/lpsolver-highs/highs/test_kkt/KktCh2.cpp +305 -0
- data/ext/lpsolver-highs/highs/test_kkt/KktCh2.h +79 -0
- data/ext/lpsolver-highs/highs/util/FactorTimer.h +199 -0
- data/ext/lpsolver-highs/highs/util/HFactor.cpp +2597 -0
- data/ext/lpsolver-highs/highs/util/HFactor.h +587 -0
- data/ext/lpsolver-highs/highs/util/HFactorConst.h +81 -0
- data/ext/lpsolver-highs/highs/util/HFactorDebug.cpp +231 -0
- data/ext/lpsolver-highs/highs/util/HFactorDebug.h +55 -0
- data/ext/lpsolver-highs/highs/util/HFactorExtend.cpp +229 -0
- data/ext/lpsolver-highs/highs/util/HFactorRefactor.cpp +304 -0
- data/ext/lpsolver-highs/highs/util/HFactorUtils.cpp +122 -0
- data/ext/lpsolver-highs/highs/util/HSet.cpp +197 -0
- data/ext/lpsolver-highs/highs/util/HSet.h +89 -0
- data/ext/lpsolver-highs/highs/util/HVector.h +22 -0
- data/ext/lpsolver-highs/highs/util/HVectorBase.cpp +271 -0
- data/ext/lpsolver-highs/highs/util/HVectorBase.h +102 -0
- data/ext/lpsolver-highs/highs/util/HighsCDouble.h +323 -0
- data/ext/lpsolver-highs/highs/util/HighsComponent.h +53 -0
- data/ext/lpsolver-highs/highs/util/HighsDataStack.h +83 -0
- data/ext/lpsolver-highs/highs/util/HighsDisjointSets.h +107 -0
- data/ext/lpsolver-highs/highs/util/HighsHash.cpp +10 -0
- data/ext/lpsolver-highs/highs/util/HighsHash.h +1274 -0
- data/ext/lpsolver-highs/highs/util/HighsHashTree.h +1461 -0
- data/ext/lpsolver-highs/highs/util/HighsInt.h +36 -0
- data/ext/lpsolver-highs/highs/util/HighsIntegers.h +212 -0
- data/ext/lpsolver-highs/highs/util/HighsLinearSumBounds.cpp +267 -0
- data/ext/lpsolver-highs/highs/util/HighsLinearSumBounds.h +203 -0
- data/ext/lpsolver-highs/highs/util/HighsMatrixPic.cpp +146 -0
- data/ext/lpsolver-highs/highs/util/HighsMatrixPic.h +37 -0
- data/ext/lpsolver-highs/highs/util/HighsMatrixSlice.h +561 -0
- data/ext/lpsolver-highs/highs/util/HighsMatrixUtils.cpp +407 -0
- data/ext/lpsolver-highs/highs/util/HighsMatrixUtils.h +57 -0
- data/ext/lpsolver-highs/highs/util/HighsMemoryAllocation.h +63 -0
- data/ext/lpsolver-highs/highs/util/HighsRandom.h +242 -0
- data/ext/lpsolver-highs/highs/util/HighsRbTree.h +452 -0
- data/ext/lpsolver-highs/highs/util/HighsSort.cpp +364 -0
- data/ext/lpsolver-highs/highs/util/HighsSort.h +131 -0
- data/ext/lpsolver-highs/highs/util/HighsSparseMatrix.cpp +1746 -0
- data/ext/lpsolver-highs/highs/util/HighsSparseMatrix.h +151 -0
- data/ext/lpsolver-highs/highs/util/HighsSparseVectorSum.h +95 -0
- data/ext/lpsolver-highs/highs/util/HighsSplay.h +135 -0
- data/ext/lpsolver-highs/highs/util/HighsTimer.h +385 -0
- data/ext/lpsolver-highs/highs/util/HighsUtils.cpp +1259 -0
- data/ext/lpsolver-highs/highs/util/HighsUtils.h +272 -0
- data/ext/lpsolver-highs/highs/util/stringutil.cpp +131 -0
- data/ext/lpsolver-highs/highs/util/stringutil.h +46 -0
- data/ext/lpsolver-highs/highs.pc.in +12 -0
- data/ext/lpsolver-highs/meson.build +198 -0
- data/ext/lpsolver-highs/meson_options.txt +31 -0
- data/ext/lpsolver-highs/nuget/HiGHS_Logo.png +0 -0
- data/ext/lpsolver-highs/nuget/Highs.csproj +25 -0
- data/ext/lpsolver-highs/nuget/Highs.csproj.in +36 -0
- data/ext/lpsolver-highs/nuget/HowToAlternative.md +77 -0
- data/ext/lpsolver-highs/nuget/README.md +38 -0
- data/ext/lpsolver-highs/nuget/arm-toolchain.cmake +15 -0
- data/ext/lpsolver-highs/nuget/build_linux-arm.sh +13 -0
- data/ext/lpsolver-highs/nuget/build_linux.sh +10 -0
- data/ext/lpsolver-highs/nuget/build_windows.ps1 +27 -0
- data/ext/lpsolver-highs/nuget/generatePackage.ps1 +28 -0
- data/ext/lpsolver-highs/pyproject.toml +221 -0
- data/ext/lpsolver-highs/subprojects/pybind11.wrap +13 -0
- data/ext/lpsolver-highs/tests/test_highspy.py +2310 -0
- data/ext/lpsolver-highs/version.rc.in +50 -0
- data/lib/lpsolver/highs +0 -0
- data/lib/lpsolver/model.rb +35 -7
- data/lib/lpsolver/native.so +0 -0
- data/lib/lpsolver/native_model.rb +261 -0
- data/lib/lpsolver/solution.rb +93 -8
- data/lib/lpsolver/version.rb +1 -1
- data/lpsolver.gemspec +4 -1
- metadata +1176 -4
|
@@ -0,0 +1,2984 @@
|
|
|
1
|
+
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
2
|
+
/* */
|
|
3
|
+
/* This file is part of the HiGHS linear optimization suite */
|
|
4
|
+
/* */
|
|
5
|
+
/* Available as open-source under the MIT License */
|
|
6
|
+
/* */
|
|
7
|
+
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
8
|
+
/**@file simplex/HEkkPrimal.cpp
|
|
9
|
+
* @brief
|
|
10
|
+
*/
|
|
11
|
+
#include "simplex/HEkkPrimal.h"
|
|
12
|
+
|
|
13
|
+
#include "../extern/pdqsort/pdqsort.h"
|
|
14
|
+
#include "simplex/HEkkDual.h"
|
|
15
|
+
#include "simplex/SimplexTimer.h"
|
|
16
|
+
#include "util/HighsSort.h"
|
|
17
|
+
|
|
18
|
+
using std::min;
|
|
19
|
+
|
|
20
|
+
HighsStatus HEkkPrimal::solve(const bool pass_force_phase2) {
|
|
21
|
+
// Initialise control data for a particular solve
|
|
22
|
+
initialiseSolve();
|
|
23
|
+
// Assumes that the LP has a positive number of rows
|
|
24
|
+
if (ekk_instance_.isUnconstrainedLp())
|
|
25
|
+
return ekk_instance_.returnFromSolve(HighsStatus::kError);
|
|
26
|
+
|
|
27
|
+
HighsOptions& options = *ekk_instance_.options_;
|
|
28
|
+
HighsSimplexInfo& info = ekk_instance_.info_;
|
|
29
|
+
HighsSimplexStatus& status = ekk_instance_.status_;
|
|
30
|
+
|
|
31
|
+
if (!status.has_invert) {
|
|
32
|
+
highsLogDev(options.log_options, HighsLogType::kError,
|
|
33
|
+
"HEkkPrimal::solve called without INVERT\n");
|
|
34
|
+
assert(status.has_fresh_invert);
|
|
35
|
+
return ekk_instance_.returnFromSolve(HighsStatus::kError);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (debugPrimalSimplex("Initialise", true) == HighsDebugStatus::kLogicalError)
|
|
39
|
+
return ekk_instance_.returnFromSolve(HighsStatus::kError);
|
|
40
|
+
|
|
41
|
+
// Get the nonbasic free column set
|
|
42
|
+
getNonbasicFreeColumnSet();
|
|
43
|
+
|
|
44
|
+
const bool primal_feasible_with_unperturbed_bounds =
|
|
45
|
+
info.num_primal_infeasibilities == 0;
|
|
46
|
+
const bool force_phase2 =
|
|
47
|
+
pass_force_phase2 ||
|
|
48
|
+
info.max_primal_infeasibility * info.max_primal_infeasibility <
|
|
49
|
+
options.primal_feasibility_tolerance;
|
|
50
|
+
// Determine whether the solution is near-optimal. Values 1000 and
|
|
51
|
+
// 1e-3 (ensuring sum<1) are unimportant, as the sum of dual
|
|
52
|
+
// infeasibilities for near-optimal solutions is typically many
|
|
53
|
+
// orders of magnitude smaller than 1, and the sum of dual
|
|
54
|
+
// infeasibilities will be very much larger for non-trivial LPs
|
|
55
|
+
// that are primal feasible for a logical or crash basis.
|
|
56
|
+
//
|
|
57
|
+
// Consider there to be no primal infeasibilities if there are none,
|
|
58
|
+
// or if phase 2 is forced, in which case any primal infeasibilities
|
|
59
|
+
// will be shifted
|
|
60
|
+
const bool no_simplex_primal_infeasibilities =
|
|
61
|
+
primal_feasible_with_unperturbed_bounds || force_phase2;
|
|
62
|
+
const bool near_optimal = info.num_dual_infeasibilities < 1000 &&
|
|
63
|
+
info.max_dual_infeasibility < 1e-3 &&
|
|
64
|
+
no_simplex_primal_infeasibilities;
|
|
65
|
+
// For reporting, save primal infeasibility data for the LP without
|
|
66
|
+
// bound perturbations
|
|
67
|
+
const HighsInt unperturbed_num_infeasibilities =
|
|
68
|
+
info.num_primal_infeasibilities;
|
|
69
|
+
const double unperturbed_max_infeasibility = info.max_primal_infeasibility;
|
|
70
|
+
const double unperturbed_sum_infeasibilities =
|
|
71
|
+
info.sum_primal_infeasibilities;
|
|
72
|
+
if (near_optimal)
|
|
73
|
+
highsLogDev(options.log_options, HighsLogType::kDetailed,
|
|
74
|
+
"Primal feasible and num / max / sum "
|
|
75
|
+
"dual infeasibilities of "
|
|
76
|
+
"%" HIGHSINT_FORMAT
|
|
77
|
+
" / %g "
|
|
78
|
+
"/ %g, so near-optimal\n",
|
|
79
|
+
info.num_dual_infeasibilities, info.max_dual_infeasibility,
|
|
80
|
+
info.sum_dual_infeasibilities);
|
|
81
|
+
|
|
82
|
+
// Perturb bounds according to whether the solution is near-optimal
|
|
83
|
+
const bool perturb_bounds = !near_optimal;
|
|
84
|
+
if (!perturb_bounds)
|
|
85
|
+
highsLogDev(options.log_options, HighsLogType::kDetailed,
|
|
86
|
+
"Near-optimal, so don't use bound perturbation\n");
|
|
87
|
+
if (perturb_bounds && info.primal_simplex_bound_perturbation_multiplier) {
|
|
88
|
+
ekk_instance_.initialiseBound(SimplexAlgorithm::kPrimal, kSolvePhaseUnknown,
|
|
89
|
+
perturb_bounds);
|
|
90
|
+
ekk_instance_.initialiseNonbasicValueAndMove();
|
|
91
|
+
ekk_instance_.computePrimal();
|
|
92
|
+
ekk_instance_.computeSimplexPrimalInfeasible();
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Check whether the time/iteration limit has been reached. First
|
|
96
|
+
// point at which a non-error return can occur
|
|
97
|
+
if (ekk_instance_.bailout())
|
|
98
|
+
return ekk_instance_.returnFromSolve(HighsStatus::kWarning);
|
|
99
|
+
|
|
100
|
+
// Now to do some iterations!
|
|
101
|
+
HighsInt num_primal_infeasibility =
|
|
102
|
+
ekk_instance_.info_.num_primal_infeasibilities;
|
|
103
|
+
solve_phase = num_primal_infeasibility > 0 ? kSolvePhase1 : kSolvePhase2;
|
|
104
|
+
if (force_phase2) {
|
|
105
|
+
// Dual infeasibilities without cost perturbation involved
|
|
106
|
+
// fixed variables or were (at most) small, so can easily be
|
|
107
|
+
// removed by flips for and fixed variables shifts for the rest
|
|
108
|
+
solve_phase = kSolvePhase2;
|
|
109
|
+
if (!pass_force_phase2) {
|
|
110
|
+
const bool local_report = false; // true;
|
|
111
|
+
if (!primal_feasible_with_unperturbed_bounds && local_report) {
|
|
112
|
+
printf(
|
|
113
|
+
"Solve %d: Forcing phase 2 since near primal feasible with "
|
|
114
|
+
"unperturbed "
|
|
115
|
+
"costs\n"
|
|
116
|
+
"num / max / sum primal infeasibilities\n"
|
|
117
|
+
"%d / %11.4g / %11.4g ( perturbed bounds)\n"
|
|
118
|
+
"%d / %11.4g / %11.4g (unperturbed bounds)\n",
|
|
119
|
+
(int)ekk_instance_.debug_solve_call_num_,
|
|
120
|
+
(int)info.num_primal_infeasibilities, info.max_primal_infeasibility,
|
|
121
|
+
info.sum_primal_infeasibilities,
|
|
122
|
+
(int)unperturbed_num_infeasibilities, unperturbed_max_infeasibility,
|
|
123
|
+
unperturbed_sum_infeasibilities);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
if (ekk_instance_.debugOkForSolve(algorithm, solve_phase) ==
|
|
128
|
+
HighsDebugStatus::kLogicalError)
|
|
129
|
+
return ekk_instance_.returnFromSolve(HighsStatus::kError);
|
|
130
|
+
// Resize the copy of scattered edge weights for backtracking
|
|
131
|
+
info.backtracking_basis_edge_weight_.resize(num_tot);
|
|
132
|
+
|
|
133
|
+
// The major solving loop
|
|
134
|
+
//
|
|
135
|
+
// Possibly write out the column header for iteration reports, and
|
|
136
|
+
// initialise records for primal correction reporting
|
|
137
|
+
localReportIter(true);
|
|
138
|
+
correctPrimal(true);
|
|
139
|
+
while (solve_phase) {
|
|
140
|
+
HighsInt it0 = ekk_instance_.iteration_count_;
|
|
141
|
+
// When starting a new phase the (updated) primal objective function
|
|
142
|
+
// value isn't known. Indicate this so that when the value
|
|
143
|
+
// computed from scratch in rebuild() isn't checked against the
|
|
144
|
+
// updated value
|
|
145
|
+
status.has_primal_objective_value = false;
|
|
146
|
+
if (solve_phase == kSolvePhaseUnknown) {
|
|
147
|
+
// Determine the number of primal infeasibilities, and hence the solve
|
|
148
|
+
// phase
|
|
149
|
+
ekk_instance_.computeSimplexPrimalInfeasible();
|
|
150
|
+
num_primal_infeasibility = ekk_instance_.info_.num_primal_infeasibilities;
|
|
151
|
+
solve_phase = num_primal_infeasibility > 0 ? kSolvePhase1 : kSolvePhase2;
|
|
152
|
+
if (info.backtracking_) {
|
|
153
|
+
// Backtracking
|
|
154
|
+
ekk_instance_.initialiseCost(SimplexAlgorithm::kPrimal, solve_phase);
|
|
155
|
+
ekk_instance_.initialiseNonbasicValueAndMove();
|
|
156
|
+
// Can now forget that we might have been backtracking
|
|
157
|
+
info.backtracking_ = false;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
assert(solve_phase == kSolvePhase1 || solve_phase == kSolvePhase2);
|
|
161
|
+
if (solve_phase == kSolvePhase1) {
|
|
162
|
+
//
|
|
163
|
+
// Phase 1
|
|
164
|
+
//
|
|
165
|
+
// solve_phase = kSolvePhase1 if the iteration or time limit has
|
|
166
|
+
// been reached
|
|
167
|
+
//
|
|
168
|
+
// solve_phase = kSolvePhase2 if there are no primal infeasibilities
|
|
169
|
+
//
|
|
170
|
+
// solve_phase = kSolvePhaseUnknown if backtracking
|
|
171
|
+
//
|
|
172
|
+
// solve_phase = kSolvePhaseExit if primal infeasibility is
|
|
173
|
+
// detected, in which case model_status_ =
|
|
174
|
+
// HighsModelStatus::kInfeasible is set
|
|
175
|
+
//
|
|
176
|
+
// solve_phase = kSolvePhaseTabooBasis is set if only basis change is
|
|
177
|
+
// taboo
|
|
178
|
+
//
|
|
179
|
+
// solve_phase = kSolvePhaseError is set if an error occurs
|
|
180
|
+
solvePhase1();
|
|
181
|
+
assert(solve_phase == kSolvePhase1 || solve_phase == kSolvePhase2 ||
|
|
182
|
+
solve_phase == kSolvePhaseUnknown ||
|
|
183
|
+
solve_phase == kSolvePhaseExit ||
|
|
184
|
+
solve_phase == kSolvePhaseTabooBasis ||
|
|
185
|
+
solve_phase == kSolvePhaseError);
|
|
186
|
+
info.primal_phase1_iteration_count +=
|
|
187
|
+
(ekk_instance_.iteration_count_ - it0);
|
|
188
|
+
} else if (solve_phase == kSolvePhase2) {
|
|
189
|
+
//
|
|
190
|
+
// Phase 2
|
|
191
|
+
//
|
|
192
|
+
// solve_phase = kSolvePhaseOptimal if there are no dual
|
|
193
|
+
// infeasibilities
|
|
194
|
+
//
|
|
195
|
+
// solve_phase = kSolvePhase1 if there are primal
|
|
196
|
+
// infeasibilities
|
|
197
|
+
//
|
|
198
|
+
// solve_phase = kSolvePhase2 if the iteration or time limit has
|
|
199
|
+
// been reached
|
|
200
|
+
//
|
|
201
|
+
// solve_phase = kSolvePhaseOptimalCleanup if, after removing bound
|
|
202
|
+
// shifts, there are primal infeasibilities to clean up
|
|
203
|
+
//
|
|
204
|
+
// solve_phase = kSolvePhaseUnknown if backtracking
|
|
205
|
+
//
|
|
206
|
+
// solve_phase = kSolvePhaseExit if primal unboundedness is
|
|
207
|
+
// detected, in which case model_status_ =
|
|
208
|
+
// HighsModelStatus::kUnbounded is set
|
|
209
|
+
//
|
|
210
|
+
// solve_phase = kSolvePhaseTabooBasis is set if only basis change is
|
|
211
|
+
// taboo
|
|
212
|
+
//
|
|
213
|
+
// solve_phase = kSolvePhaseError is set if an error occurs
|
|
214
|
+
solvePhase2();
|
|
215
|
+
assert(solve_phase == kSolvePhaseOptimal || solve_phase == kSolvePhase1 ||
|
|
216
|
+
solve_phase == kSolvePhase2 ||
|
|
217
|
+
solve_phase == kSolvePhaseOptimalCleanup ||
|
|
218
|
+
solve_phase == kSolvePhaseUnknown ||
|
|
219
|
+
solve_phase == kSolvePhaseExit ||
|
|
220
|
+
solve_phase == kSolvePhaseTabooBasis ||
|
|
221
|
+
solve_phase == kSolvePhaseError);
|
|
222
|
+
assert(solve_phase != kSolvePhaseExit ||
|
|
223
|
+
ekk_instance_.model_status_ == HighsModelStatus::kUnbounded);
|
|
224
|
+
info.primal_phase2_iteration_count +=
|
|
225
|
+
(ekk_instance_.iteration_count_ - it0);
|
|
226
|
+
} else {
|
|
227
|
+
// Should only be kSolvePhase1 or kSolvePhase2
|
|
228
|
+
ekk_instance_.model_status_ = HighsModelStatus::kSolveError;
|
|
229
|
+
return ekk_instance_.returnFromSolve(HighsStatus::kError);
|
|
230
|
+
}
|
|
231
|
+
// Return if bailing out from solve
|
|
232
|
+
if (ekk_instance_.solve_bailout_)
|
|
233
|
+
return ekk_instance_.returnFromSolve(HighsStatus::kWarning);
|
|
234
|
+
// Can have all possible cases of solve_phase
|
|
235
|
+
assert(solve_phase >= kSolvePhaseMin && solve_phase <= kSolvePhaseMax);
|
|
236
|
+
// Look for scenarios when the major solving loop ends
|
|
237
|
+
if (solve_phase == kSolvePhaseTabooBasis) {
|
|
238
|
+
// Only basis change is taboo so return HighsStatus::kWarning
|
|
239
|
+
highsLogDev(options.log_options, HighsLogType::kInfo,
|
|
240
|
+
"HEkkPrimal::solve Only basis change is taboo\n");
|
|
241
|
+
ekk_instance_.model_status_ = HighsModelStatus::kUnknown;
|
|
242
|
+
return ekk_instance_.returnFromSolve(HighsStatus::kWarning);
|
|
243
|
+
}
|
|
244
|
+
if (solve_phase == kSolvePhaseError) {
|
|
245
|
+
// Solver error so return HighsStatus::kError
|
|
246
|
+
ekk_instance_.model_status_ = HighsModelStatus::kSolveError;
|
|
247
|
+
return ekk_instance_.returnFromSolve(HighsStatus::kError);
|
|
248
|
+
}
|
|
249
|
+
if (solve_phase == kSolvePhaseExit) {
|
|
250
|
+
// LP identified as not having an optimal solution
|
|
251
|
+
assert(ekk_instance_.model_status_ == HighsModelStatus::kInfeasible ||
|
|
252
|
+
ekk_instance_.model_status_ == HighsModelStatus::kUnbounded);
|
|
253
|
+
// If infeasible, save the primal phase 1 dual values before
|
|
254
|
+
// they are overwritten with the duals for the original
|
|
255
|
+
// objective
|
|
256
|
+
if (ekk_instance_.model_status_ == HighsModelStatus::kInfeasible)
|
|
257
|
+
ekk_instance_.primal_phase1_dual_ = ekk_instance_.info_.workDual_;
|
|
258
|
+
break;
|
|
259
|
+
}
|
|
260
|
+
if (solve_phase == kSolvePhaseOptimalCleanup) {
|
|
261
|
+
// Primal infeasibilities after phase 2. Dual feasible with
|
|
262
|
+
// primal infeasibilities so use dual simplex to clean up
|
|
263
|
+
break;
|
|
264
|
+
}
|
|
265
|
+
// If solve_phase == kSolvePhaseOptimal == 0 then major solving
|
|
266
|
+
// loop ends naturally since solve_phase is false
|
|
267
|
+
}
|
|
268
|
+
// If bailing out, should have returned already
|
|
269
|
+
assert(!ekk_instance_.solve_bailout_);
|
|
270
|
+
// Should only have these cases
|
|
271
|
+
assert(solve_phase ==
|
|
272
|
+
kSolvePhaseExit || // solve_phase == kSolvePhaseUnknown ||
|
|
273
|
+
solve_phase == kSolvePhaseOptimal || // solve_phase == kSolvePhase1 ||
|
|
274
|
+
solve_phase == kSolvePhaseOptimalCleanup);
|
|
275
|
+
if (solve_phase == kSolvePhaseOptimal)
|
|
276
|
+
ekk_instance_.model_status_ = HighsModelStatus::kOptimal;
|
|
277
|
+
|
|
278
|
+
if (solve_phase == kSolvePhaseOptimalCleanup) {
|
|
279
|
+
highsLogDev(options.log_options, HighsLogType::kInfo,
|
|
280
|
+
"HEkkPrimal:: Using dual simplex to try to clean up num / "
|
|
281
|
+
"max / sum = %" HIGHSINT_FORMAT
|
|
282
|
+
" / %g / %g primal infeasibilities\n",
|
|
283
|
+
info.num_primal_infeasibilities, info.max_primal_infeasibility,
|
|
284
|
+
info.sum_primal_infeasibilities);
|
|
285
|
+
ekk_instance_.computePrimalObjectiveValue();
|
|
286
|
+
// Use dual to clean up. This almost always yields optimality,
|
|
287
|
+
// and shouldn't yield infeasibility - since the current point
|
|
288
|
+
// is dual feasible - but can yield
|
|
289
|
+
// unboundedness. Time/iteration limit return is, of course,
|
|
290
|
+
// possible, as are solver error
|
|
291
|
+
HighsStatus return_status = HighsStatus::kOk;
|
|
292
|
+
// Switch off any bound perturbation
|
|
293
|
+
double save_dual_simplex_cost_perturbation_multiplier =
|
|
294
|
+
info.dual_simplex_cost_perturbation_multiplier;
|
|
295
|
+
info.dual_simplex_cost_perturbation_multiplier = 0;
|
|
296
|
+
HighsInt simplex_strategy = info.simplex_strategy;
|
|
297
|
+
info.simplex_strategy = kSimplexStrategyDualPlain;
|
|
298
|
+
HEkkDual dual_solver(ekk_instance_);
|
|
299
|
+
HighsStatus call_status = dual_solver.solve(true);
|
|
300
|
+
// Restore any bound perturbation
|
|
301
|
+
info.dual_simplex_cost_perturbation_multiplier =
|
|
302
|
+
save_dual_simplex_cost_perturbation_multiplier;
|
|
303
|
+
info.simplex_strategy = simplex_strategy;
|
|
304
|
+
assert(ekk_instance_.called_return_from_solve_);
|
|
305
|
+
return_status = interpretCallStatus(options.log_options, call_status,
|
|
306
|
+
return_status, "HEkkDual::solve");
|
|
307
|
+
// Reset called_return_from_solve_ to be false, since it's
|
|
308
|
+
// called for this solve
|
|
309
|
+
ekk_instance_.called_return_from_solve_ = false;
|
|
310
|
+
if (return_status != HighsStatus::kOk)
|
|
311
|
+
return ekk_instance_.returnFromSolve(return_status);
|
|
312
|
+
if (ekk_instance_.model_status_ == HighsModelStatus::kOptimal &&
|
|
313
|
+
info.num_primal_infeasibilities + info.num_dual_infeasibilities)
|
|
314
|
+
highsLogDev(options.log_options, HighsLogType::kWarning,
|
|
315
|
+
"HEkkPrimal:: Dual simplex clean up yields optimality, but "
|
|
316
|
+
"with %" HIGHSINT_FORMAT
|
|
317
|
+
" (max %g) primal infeasibilities and " HIGHSINT_FORMAT
|
|
318
|
+
" (max %g) dual infeasibilities\n",
|
|
319
|
+
info.num_primal_infeasibilities,
|
|
320
|
+
info.max_primal_infeasibility, info.num_dual_infeasibilities,
|
|
321
|
+
info.max_dual_infeasibility);
|
|
322
|
+
}
|
|
323
|
+
if (ekk_instance_.debugOkForSolve(algorithm, solve_phase) ==
|
|
324
|
+
HighsDebugStatus::kLogicalError)
|
|
325
|
+
return ekk_instance_.returnFromSolve(HighsStatus::kError);
|
|
326
|
+
return ekk_instance_.returnFromSolve(HighsStatus::kOk);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
void HEkkPrimal::initialiseInstance() {
|
|
330
|
+
// Called in constructor for HEkkPrimal class
|
|
331
|
+
analysis = &ekk_instance_.analysis_;
|
|
332
|
+
|
|
333
|
+
num_col = ekk_instance_.lp_.num_col_;
|
|
334
|
+
num_row = ekk_instance_.lp_.num_row_;
|
|
335
|
+
num_tot = num_col + num_row;
|
|
336
|
+
|
|
337
|
+
// Setup local vectors
|
|
338
|
+
col_aq.setup(num_row);
|
|
339
|
+
row_ep.setup(num_row);
|
|
340
|
+
row_ap.setup(num_col);
|
|
341
|
+
col_basic_feasibility_change.setup(num_row);
|
|
342
|
+
row_basic_feasibility_change.setup(num_col);
|
|
343
|
+
col_steepest_edge.setup(num_row);
|
|
344
|
+
|
|
345
|
+
ph1SorterR.reserve(num_row);
|
|
346
|
+
ph1SorterT.reserve(num_row);
|
|
347
|
+
|
|
348
|
+
num_free_col = 0;
|
|
349
|
+
for (HighsInt iCol = 0; iCol < num_tot; iCol++) {
|
|
350
|
+
if (ekk_instance_.info_.workLower_[iCol] == -kHighsInf &&
|
|
351
|
+
ekk_instance_.info_.workUpper_[iCol] == kHighsInf) {
|
|
352
|
+
// Free column
|
|
353
|
+
num_free_col++;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
// Set up the HSet instances, possibly using the internal error reporting and
|
|
357
|
+
// debug option
|
|
358
|
+
const bool debug =
|
|
359
|
+
ekk_instance_.options_->highs_debug_level > kHighsDebugLevelCheap;
|
|
360
|
+
if (num_free_col) {
|
|
361
|
+
highsLogDev(ekk_instance_.options_->log_options, HighsLogType::kInfo,
|
|
362
|
+
"HEkkPrimal:: LP has %" HIGHSINT_FORMAT " free columns\n",
|
|
363
|
+
num_free_col);
|
|
364
|
+
nonbasic_free_col_set.setup(
|
|
365
|
+
num_free_col, num_tot, ekk_instance_.options_->output_flag,
|
|
366
|
+
ekk_instance_.options_->log_options.log_stream, debug);
|
|
367
|
+
}
|
|
368
|
+
// Set up the hyper-sparse CHUZC data
|
|
369
|
+
hyper_chuzc_candidate.resize(1 + max_num_hyper_chuzc_candidates);
|
|
370
|
+
hyper_chuzc_measure.resize(1 + max_num_hyper_chuzc_candidates);
|
|
371
|
+
hyper_chuzc_candidate_set.setup(
|
|
372
|
+
max_num_hyper_chuzc_candidates, num_tot,
|
|
373
|
+
ekk_instance_.options_->output_flag,
|
|
374
|
+
ekk_instance_.options_->log_options.log_stream, debug);
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
void HEkkPrimal::initialiseSolve() {
|
|
378
|
+
// Copy values of simplex solver options to dual simplex options
|
|
379
|
+
primal_feasibility_tolerance =
|
|
380
|
+
ekk_instance_.options_->primal_feasibility_tolerance;
|
|
381
|
+
dual_feasibility_tolerance =
|
|
382
|
+
ekk_instance_.options_->dual_feasibility_tolerance;
|
|
383
|
+
objective_target = ekk_instance_.options_->objective_target;
|
|
384
|
+
|
|
385
|
+
ekk_instance_.status_.has_primal_objective_value = false;
|
|
386
|
+
ekk_instance_.status_.has_dual_objective_value = false;
|
|
387
|
+
|
|
388
|
+
ekk_instance_.model_status_ = HighsModelStatus::kNotset;
|
|
389
|
+
ekk_instance_.solve_bailout_ = false;
|
|
390
|
+
ekk_instance_.called_return_from_solve_ = false;
|
|
391
|
+
ekk_instance_.exit_algorithm_ = SimplexAlgorithm::kPrimal;
|
|
392
|
+
|
|
393
|
+
rebuild_reason = kRebuildReasonNo;
|
|
394
|
+
if (!ekk_instance_.status_.has_dual_steepest_edge_weights) {
|
|
395
|
+
// No dual weights to maintain, so ensure that the vectors are
|
|
396
|
+
// assigned since they are used around factorization and when
|
|
397
|
+
// setting up the backtracking information. ToDo Eliminate this
|
|
398
|
+
// opacity
|
|
399
|
+
ekk_instance_.dual_edge_weight_.assign(num_row, 1.0);
|
|
400
|
+
ekk_instance_.scattered_dual_edge_weight_.resize(num_tot);
|
|
401
|
+
}
|
|
402
|
+
const HighsInt edge_weight_strategy =
|
|
403
|
+
ekk_instance_.options_->simplex_primal_edge_weight_strategy;
|
|
404
|
+
if (edge_weight_strategy == kSimplexEdgeWeightStrategyChoose ||
|
|
405
|
+
edge_weight_strategy == kSimplexEdgeWeightStrategyDevex) {
|
|
406
|
+
// By default, use Devex
|
|
407
|
+
edge_weight_mode = EdgeWeightMode::kDevex;
|
|
408
|
+
} else if (edge_weight_strategy == kSimplexEdgeWeightStrategyDantzig) {
|
|
409
|
+
edge_weight_mode = EdgeWeightMode::kDantzig;
|
|
410
|
+
} else {
|
|
411
|
+
assert(edge_weight_strategy == kSimplexEdgeWeightStrategySteepestEdge);
|
|
412
|
+
edge_weight_mode = EdgeWeightMode::kSteepestEdge;
|
|
413
|
+
}
|
|
414
|
+
if (edge_weight_mode == EdgeWeightMode::kDantzig) {
|
|
415
|
+
edge_weight_.assign(num_tot, 1.0);
|
|
416
|
+
} else if (edge_weight_mode == EdgeWeightMode::kDevex) {
|
|
417
|
+
initialiseDevexFramework();
|
|
418
|
+
} else if (edge_weight_mode == EdgeWeightMode::kSteepestEdge) {
|
|
419
|
+
computePrimalSteepestEdgeWeights();
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
void HEkkPrimal::solvePhase1() {
|
|
424
|
+
HighsSimplexInfo& info = ekk_instance_.info_;
|
|
425
|
+
HighsSimplexStatus& status = ekk_instance_.status_;
|
|
426
|
+
// When starting a new phase the (updated) primal objective function
|
|
427
|
+
// value isn't known. Indicate this so that when the value
|
|
428
|
+
// computed from scratch in build() isn't checked against the
|
|
429
|
+
// updated value
|
|
430
|
+
status.has_primal_objective_value = false;
|
|
431
|
+
status.has_dual_objective_value = false;
|
|
432
|
+
// Possibly bail out immediately if iteration limit is current value
|
|
433
|
+
if (ekk_instance_.bailout()) return;
|
|
434
|
+
highsLogDev(ekk_instance_.options_->log_options, HighsLogType::kDetailed,
|
|
435
|
+
"primal-phase1-start\n");
|
|
436
|
+
// If there's no backtracking basis, save the initial basis in case of
|
|
437
|
+
// backtracking
|
|
438
|
+
if (!info.valid_backtracking_basis_) ekk_instance_.putBacktrackingBasis();
|
|
439
|
+
|
|
440
|
+
// Main solving structure
|
|
441
|
+
for (;;) {
|
|
442
|
+
//
|
|
443
|
+
// Rebuild
|
|
444
|
+
//
|
|
445
|
+
// solve_phase = kSolvePhaseError is set if the basis matrix is singular
|
|
446
|
+
rebuild();
|
|
447
|
+
if (solve_phase == kSolvePhaseError) return;
|
|
448
|
+
if (solve_phase == kSolvePhaseUnknown) return;
|
|
449
|
+
if (ekk_instance_.bailout()) return;
|
|
450
|
+
assert(solve_phase == kSolvePhase1 || solve_phase == kSolvePhase2);
|
|
451
|
+
//
|
|
452
|
+
// solve_phase = kSolvePhase2 is set if no primal infeasibilities
|
|
453
|
+
// are found in rebuild(), in which case return for phase 2
|
|
454
|
+
if (solve_phase == kSolvePhase2) break;
|
|
455
|
+
|
|
456
|
+
for (;;) {
|
|
457
|
+
iterate();
|
|
458
|
+
if (ekk_instance_.bailout()) return;
|
|
459
|
+
if (solve_phase == kSolvePhaseError) return;
|
|
460
|
+
assert(solve_phase == kSolvePhase1);
|
|
461
|
+
if (rebuild_reason) break;
|
|
462
|
+
}
|
|
463
|
+
// If the data are fresh from rebuild() and no flips have
|
|
464
|
+
// occurred, possibly break out of the outer loop to see what's
|
|
465
|
+
// occurred
|
|
466
|
+
bool finished = status.has_fresh_rebuild && num_flip_since_rebuild == 0 &&
|
|
467
|
+
!ekk_instance_.rebuildRefactor(rebuild_reason);
|
|
468
|
+
if (finished && ekk_instance_.tabooBadBasisChange()) {
|
|
469
|
+
// A bad basis change has had to be made taboo without any other
|
|
470
|
+
// basis changes or flips having been performed from a fresh
|
|
471
|
+
// rebuild. In other words, the only basis change that could be
|
|
472
|
+
// made is not permitted, so no definitive statement about the
|
|
473
|
+
// LP can be made.
|
|
474
|
+
solve_phase = kSolvePhaseTabooBasis;
|
|
475
|
+
return;
|
|
476
|
+
}
|
|
477
|
+
if (finished) break;
|
|
478
|
+
}
|
|
479
|
+
// If bailing out, should have returned already
|
|
480
|
+
assert(!ekk_instance_.solve_bailout_);
|
|
481
|
+
// Will only have accurate simplex info if moving to phase 2 - but
|
|
482
|
+
// should check primal feasibility and residual information if LP
|
|
483
|
+
// is primal infeasible
|
|
484
|
+
if (debugPrimalSimplex("End of solvePhase1") ==
|
|
485
|
+
HighsDebugStatus::kLogicalError) {
|
|
486
|
+
solve_phase = kSolvePhaseError;
|
|
487
|
+
return;
|
|
488
|
+
}
|
|
489
|
+
if (solve_phase == kSolvePhase1) {
|
|
490
|
+
// Determine whether primal infeasibility has been identified
|
|
491
|
+
if (variable_in < 0) {
|
|
492
|
+
// Optimal in phase 1, so should have primal infeasibilities
|
|
493
|
+
assert(info.num_primal_infeasibilities > 0);
|
|
494
|
+
if (ekk_instance_.info_.bounds_shifted ||
|
|
495
|
+
ekk_instance_.info_.bounds_perturbed) {
|
|
496
|
+
// Remove any bound shifts or perturbations and return to
|
|
497
|
+
// phase 1
|
|
498
|
+
cleanup();
|
|
499
|
+
} else {
|
|
500
|
+
ekk_instance_.model_status_ = HighsModelStatus::kInfeasible;
|
|
501
|
+
solve_phase = kSolvePhaseExit;
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
if (solve_phase == kSolvePhase2) {
|
|
506
|
+
// Moving to phase 2 so comment if bound perturbation is not permitted
|
|
507
|
+
//
|
|
508
|
+
// It may have been prevented to avoid cleanup-perturbation loops
|
|
509
|
+
if (!info.allow_bound_perturbation)
|
|
510
|
+
highsLogDev(ekk_instance_.options_->log_options, HighsLogType::kWarning,
|
|
511
|
+
"Moving to phase 2, but not allowing bound perturbation\n");
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
void HEkkPrimal::solvePhase2() {
|
|
516
|
+
HighsOptions& options = *ekk_instance_.options_;
|
|
517
|
+
HighsSimplexStatus& status = ekk_instance_.status_;
|
|
518
|
+
HighsModelStatus& model_status = ekk_instance_.model_status_;
|
|
519
|
+
// When starting a new phase the (updated) primal objective function
|
|
520
|
+
// value isn't known. Indicate this so that when the value
|
|
521
|
+
// computed from scratch in build() isn't checked against the
|
|
522
|
+
// updated value
|
|
523
|
+
status.has_primal_objective_value = false;
|
|
524
|
+
status.has_dual_objective_value = false;
|
|
525
|
+
// Possibly bail out immediately if iteration limit is current value
|
|
526
|
+
if (ekk_instance_.bailout()) return;
|
|
527
|
+
highsLogDev(options.log_options, HighsLogType::kDetailed,
|
|
528
|
+
"primal-phase2-start\n");
|
|
529
|
+
phase2UpdatePrimal(true);
|
|
530
|
+
|
|
531
|
+
// If there's no backtracking basis Save the initial basis in case of
|
|
532
|
+
// backtracking
|
|
533
|
+
if (!ekk_instance_.info_.valid_backtracking_basis_)
|
|
534
|
+
ekk_instance_.putBacktrackingBasis();
|
|
535
|
+
|
|
536
|
+
// Main solving structure
|
|
537
|
+
for (;;) {
|
|
538
|
+
//
|
|
539
|
+
// Rebuild
|
|
540
|
+
//
|
|
541
|
+
// solve_phase = kSolvePhaseError is set if the basis matrix is singular
|
|
542
|
+
rebuild();
|
|
543
|
+
if (solve_phase == kSolvePhaseError) return;
|
|
544
|
+
if (solve_phase == kSolvePhaseUnknown) return;
|
|
545
|
+
if (ekk_instance_.bailout()) return;
|
|
546
|
+
assert(solve_phase == kSolvePhase1 || solve_phase == kSolvePhase2);
|
|
547
|
+
//
|
|
548
|
+
// solve_phase = kSolvePhase1 is set if primal infeasibilities
|
|
549
|
+
// are found in rebuild(), in which case return for phase 1
|
|
550
|
+
if (solve_phase == kSolvePhase1) break;
|
|
551
|
+
|
|
552
|
+
for (;;) {
|
|
553
|
+
iterate();
|
|
554
|
+
if (ekk_instance_.bailout()) return;
|
|
555
|
+
if (solve_phase == kSolvePhaseError) return;
|
|
556
|
+
assert(solve_phase == kSolvePhase2);
|
|
557
|
+
if (rebuild_reason) break;
|
|
558
|
+
}
|
|
559
|
+
// If the data are fresh from rebuild() and no flips have
|
|
560
|
+
// occurred, possibly break out of the outer loop to see what's
|
|
561
|
+
// occurred
|
|
562
|
+
bool finished = status.has_fresh_rebuild && num_flip_since_rebuild == 0 &&
|
|
563
|
+
!ekk_instance_.rebuildRefactor(rebuild_reason);
|
|
564
|
+
if (finished && ekk_instance_.tabooBadBasisChange()) {
|
|
565
|
+
// A bad basis change has had to be made taboo without any other
|
|
566
|
+
// basis changes or flips having been performed from a fresh
|
|
567
|
+
// rebuild. In other words, the only basis change that could be
|
|
568
|
+
// made is not permitted, so no definitive statement about the
|
|
569
|
+
// LP can be made.
|
|
570
|
+
solve_phase = kSolvePhaseTabooBasis;
|
|
571
|
+
return;
|
|
572
|
+
}
|
|
573
|
+
if (finished) break;
|
|
574
|
+
}
|
|
575
|
+
// If bailing out, should have returned already
|
|
576
|
+
assert(!ekk_instance_.solve_bailout_);
|
|
577
|
+
if (debugPrimalSimplex("End of solvePhase2") ==
|
|
578
|
+
HighsDebugStatus::kLogicalError) {
|
|
579
|
+
solve_phase = kSolvePhaseError;
|
|
580
|
+
return;
|
|
581
|
+
}
|
|
582
|
+
if (solve_phase == kSolvePhase1) {
|
|
583
|
+
highsLogDev(options.log_options, HighsLogType::kDetailed,
|
|
584
|
+
"primal-return-phase1\n");
|
|
585
|
+
} else if (variable_in == -1) {
|
|
586
|
+
// There is no candidate in CHUZC, even after rebuild so probably optimal
|
|
587
|
+
highsLogDev(options.log_options, HighsLogType::kDetailed,
|
|
588
|
+
"primal-phase-2-optimal\n");
|
|
589
|
+
// Remove any bound perturbations and see if basis is still primal feasible
|
|
590
|
+
cleanup();
|
|
591
|
+
if (ekk_instance_.info_.num_primal_infeasibilities > 0) {
|
|
592
|
+
// There are primal infeasibilities, so consider performing dual
|
|
593
|
+
// simplex iterations to get primal feasibility
|
|
594
|
+
solve_phase = kSolvePhaseOptimalCleanup;
|
|
595
|
+
} else {
|
|
596
|
+
// There are no primal infeasibilities so optimal!
|
|
597
|
+
solve_phase = kSolvePhaseOptimal;
|
|
598
|
+
highsLogDev(options.log_options, HighsLogType::kDetailed,
|
|
599
|
+
"problem-optimal\n");
|
|
600
|
+
model_status = HighsModelStatus::kOptimal;
|
|
601
|
+
ekk_instance_.computeDualObjectiveValue(); // Why?
|
|
602
|
+
}
|
|
603
|
+
} else if (row_out == kNoRowSought) {
|
|
604
|
+
// CHUZR has not been performed - because the chosen reduced cost
|
|
605
|
+
// was unattractive when computed from scratch and no rebuild was
|
|
606
|
+
// required. This is very rare and should be handled otherwise
|
|
607
|
+
//
|
|
608
|
+
printf("HEkkPrimal::solvePhase2 row_out = %d solve %d\n", (int)row_out,
|
|
609
|
+
(int)ekk_instance_.debug_solve_call_num_);
|
|
610
|
+
fflush(stdout);
|
|
611
|
+
assert(row_out != kNoRowSought);
|
|
612
|
+
} else {
|
|
613
|
+
// No candidate in CHUZR
|
|
614
|
+
if (row_out >= 0) {
|
|
615
|
+
printf("HEkkPrimal::solvePhase2 row_out = %d solve %d\n", (int)row_out,
|
|
616
|
+
(int)ekk_instance_.debug_solve_call_num_);
|
|
617
|
+
fflush(stdout);
|
|
618
|
+
}
|
|
619
|
+
// Ensure that CHUZR was performed and found no row
|
|
620
|
+
assert(row_out == kNoRowChosen);
|
|
621
|
+
|
|
622
|
+
// There is no candidate in CHUZR, so probably primal unbounded
|
|
623
|
+
highsLogDev(options.log_options, HighsLogType::kInfo,
|
|
624
|
+
"primal-phase-2-unbounded\n");
|
|
625
|
+
if (ekk_instance_.info_.bounds_shifted ||
|
|
626
|
+
ekk_instance_.info_.bounds_perturbed) {
|
|
627
|
+
// If the bounds have been shifted or perturbed, clean up and
|
|
628
|
+
// return
|
|
629
|
+
cleanup();
|
|
630
|
+
// If there are primal infeasibilities, go back to phase 1
|
|
631
|
+
if (ekk_instance_.info_.num_primal_infeasibilities > 0)
|
|
632
|
+
solve_phase = kSolvePhase1;
|
|
633
|
+
} else {
|
|
634
|
+
// The bounds have not been perturbed, so primal unbounded
|
|
635
|
+
solve_phase = kSolvePhaseExit;
|
|
636
|
+
// Primal unbounded, so save primal ray
|
|
637
|
+
savePrimalRay();
|
|
638
|
+
// Model status should be unset
|
|
639
|
+
assert(model_status == HighsModelStatus::kNotset);
|
|
640
|
+
highsLogDev(options.log_options, HighsLogType::kInfo,
|
|
641
|
+
"problem-primal-unbounded\n");
|
|
642
|
+
model_status = HighsModelStatus::kUnbounded;
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
void HEkkPrimal::cleanup() {
|
|
648
|
+
HighsSimplexInfo& info = ekk_instance_.info_;
|
|
649
|
+
if (!info.bounds_shifted && !info.bounds_perturbed) return;
|
|
650
|
+
highsLogDev(ekk_instance_.options_->log_options, HighsLogType::kDetailed,
|
|
651
|
+
"primal-cleanup-shift\n");
|
|
652
|
+
// Remove perturbation and don't permit further perturbation
|
|
653
|
+
ekk_instance_.initialiseBound(SimplexAlgorithm::kPrimal, solve_phase, false);
|
|
654
|
+
ekk_instance_.initialiseNonbasicValueAndMove();
|
|
655
|
+
info.allow_bound_perturbation = false;
|
|
656
|
+
// Possibly take a copy of the original duals before recomputing them
|
|
657
|
+
/*
|
|
658
|
+
vector<double> original_baseValue;
|
|
659
|
+
if (ekk_instance_.options_->highs_debug_level > kHighsDebugLevelCheap)
|
|
660
|
+
original_baseValue = info.baseValue_;
|
|
661
|
+
*/
|
|
662
|
+
// Compute the primal values
|
|
663
|
+
ekk_instance_.computePrimal();
|
|
664
|
+
// Possibly analyse the change in duals
|
|
665
|
+
/* debugCleanup(ekk_instance_, original_baseValue); */
|
|
666
|
+
// Compute the primal infeasibilities
|
|
667
|
+
ekk_instance_.computeSimplexPrimalInfeasible();
|
|
668
|
+
|
|
669
|
+
// Compute the primal objective value
|
|
670
|
+
ekk_instance_.computePrimalObjectiveValue();
|
|
671
|
+
// Now that there's a new primal_objective_value, reset the updated
|
|
672
|
+
// value
|
|
673
|
+
info.updated_primal_objective_value = info.primal_objective_value;
|
|
674
|
+
|
|
675
|
+
// if (!info.run_quiet) {
|
|
676
|
+
// Report the dual infeasibilities
|
|
677
|
+
ekk_instance_.computeSimplexDualInfeasible();
|
|
678
|
+
// In phase 1, report the simplex LP dual infeasibilities
|
|
679
|
+
// In phase 2, report the simplex dual infeasibilities (known)
|
|
680
|
+
// if (solve_phase == kSolvePhase1)
|
|
681
|
+
// computeSimplexLpDualInfeasible(ekk_instance_);
|
|
682
|
+
reportRebuild(kRebuildReasonCleanup);
|
|
683
|
+
// }
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
void HEkkPrimal::rebuild() {
|
|
687
|
+
HighsSimplexInfo& info = ekk_instance_.info_;
|
|
688
|
+
HighsSimplexStatus& status = ekk_instance_.status_;
|
|
689
|
+
// Clear taboo flag from any bad basis changes
|
|
690
|
+
ekk_instance_.clearBadBasisChangeTabooFlag();
|
|
691
|
+
|
|
692
|
+
// Record whether the update objective value should be tested. If
|
|
693
|
+
// the objective value is known, then the updated objective value
|
|
694
|
+
// should be correct - once the correction due to recomputing the
|
|
695
|
+
// dual values has been applied.
|
|
696
|
+
//
|
|
697
|
+
// Note that computePrimalObjectiveValue sets
|
|
698
|
+
// has_primal_objective_value
|
|
699
|
+
//
|
|
700
|
+
// Have to do this before INVERT, as this permutes the indices of
|
|
701
|
+
// basic variables, and baseValue only corresponds to the new
|
|
702
|
+
// ordering once computePrimal has been called
|
|
703
|
+
const bool check_updated_objective_value = status.has_primal_objective_value;
|
|
704
|
+
double previous_primal_objective_value = -kHighsInf;
|
|
705
|
+
if (check_updated_objective_value) {
|
|
706
|
+
// debugUpdatedObjectiveValue(ekk_instance_, algorithm, solve_phase,
|
|
707
|
+
// "Before INVERT");
|
|
708
|
+
previous_primal_objective_value = info.updated_primal_objective_value;
|
|
709
|
+
} else {
|
|
710
|
+
// Reset the knowledge of previous objective values
|
|
711
|
+
// debugUpdatedObjectiveValue(ekk_instance_, algorithm, -1, "");
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
// Decide whether refactorization should be performed
|
|
715
|
+
const bool refactor_basis_matrix =
|
|
716
|
+
ekk_instance_.rebuildRefactor(rebuild_reason);
|
|
717
|
+
|
|
718
|
+
// Take a local copy of the rebuild reason and then reset the global value
|
|
719
|
+
const HighsInt local_rebuild_reason = rebuild_reason;
|
|
720
|
+
rebuild_reason = kRebuildReasonNo;
|
|
721
|
+
if (refactor_basis_matrix) {
|
|
722
|
+
// Get a nonsingular inverse if possible. One of three things
|
|
723
|
+
// happens: Current basis is nonsingular; Current basis is
|
|
724
|
+
// singular and last nonsingular basis is refactorized as
|
|
725
|
+
// nonsingular - or found singular. Latter is code failure.
|
|
726
|
+
if (!ekk_instance_.getNonsingularInverse(solve_phase)) {
|
|
727
|
+
solve_phase = kSolvePhaseError;
|
|
728
|
+
return;
|
|
729
|
+
}
|
|
730
|
+
// Record the synthetic clock for INVERT, and zero it for UPDATE
|
|
731
|
+
ekk_instance_.resetSyntheticClock();
|
|
732
|
+
}
|
|
733
|
+
if (!ekk_instance_.status_.has_ar_matrix) {
|
|
734
|
+
// Don't have the row-wise matrix, so reinitialise it
|
|
735
|
+
//
|
|
736
|
+
// Should only happen when backtracking
|
|
737
|
+
assert(info.backtracking_);
|
|
738
|
+
ekk_instance_.initialisePartitionedRowwiseMatrix();
|
|
739
|
+
assert(ekk_instance_.ar_matrix_.debugPartitionOk(
|
|
740
|
+
ekk_instance_.basis_.nonbasicFlag_.data()));
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
if (info.backtracking_) {
|
|
744
|
+
// If backtracking, may change phase, so drop out
|
|
745
|
+
solve_phase = kSolvePhaseUnknown;
|
|
746
|
+
return;
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
ekk_instance_.computePrimal();
|
|
750
|
+
if (solve_phase == kSolvePhase2) {
|
|
751
|
+
bool correct_primal_ok = correctPrimal();
|
|
752
|
+
if (kAllowDeveloperAssert) {
|
|
753
|
+
assert(correct_primal_ok);
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
getBasicPrimalInfeasibility();
|
|
757
|
+
if (info.num_primal_infeasibilities > 0) {
|
|
758
|
+
// Primal infeasibilities so should be in phase 1
|
|
759
|
+
if (solve_phase == kSolvePhase2) {
|
|
760
|
+
highsLogDev(
|
|
761
|
+
ekk_instance_.options_->log_options, HighsLogType::kWarning,
|
|
762
|
+
"HEkkPrimal::rebuild switching back to phase 1 from phase 2\n");
|
|
763
|
+
solve_phase = kSolvePhase1;
|
|
764
|
+
}
|
|
765
|
+
phase1ComputeDual();
|
|
766
|
+
} else {
|
|
767
|
+
// No primal infeasibilities so in phase 2. Reset costs if was
|
|
768
|
+
// previously in phase 1
|
|
769
|
+
if (solve_phase == kSolvePhase1) {
|
|
770
|
+
ekk_instance_.initialiseCost(SimplexAlgorithm::kPrimal, solve_phase);
|
|
771
|
+
solve_phase = kSolvePhase2;
|
|
772
|
+
}
|
|
773
|
+
ekk_instance_.computeDual();
|
|
774
|
+
}
|
|
775
|
+
ekk_instance_.computeSimplexDualInfeasible();
|
|
776
|
+
ekk_instance_.computePrimalObjectiveValue();
|
|
777
|
+
if (check_updated_objective_value) {
|
|
778
|
+
// Apply the objective value correction due to computing primal
|
|
779
|
+
// values from scratch.
|
|
780
|
+
const double primal_objective_value_correction =
|
|
781
|
+
info.primal_objective_value - previous_primal_objective_value;
|
|
782
|
+
info.updated_primal_objective_value += primal_objective_value_correction;
|
|
783
|
+
// debugUpdatedObjectiveValue(ekk_instance_, algorithm);
|
|
784
|
+
}
|
|
785
|
+
// Now that there's a new dual_objective_value, reset the updated
|
|
786
|
+
// value
|
|
787
|
+
info.updated_primal_objective_value = info.primal_objective_value;
|
|
788
|
+
|
|
789
|
+
reportRebuild(local_rebuild_reason);
|
|
790
|
+
|
|
791
|
+
// Record the synthetic clock for INVERT, and zero it for UPDATE
|
|
792
|
+
ekk_instance_.resetSyntheticClock();
|
|
793
|
+
|
|
794
|
+
// Determine whether to use hyper-sparse CHUZC
|
|
795
|
+
if (solve_phase == kSolvePhase1) {
|
|
796
|
+
use_hyper_chuzc = false;
|
|
797
|
+
} else {
|
|
798
|
+
use_hyper_chuzc = false; // true;
|
|
799
|
+
}
|
|
800
|
+
hyperChooseColumnClear();
|
|
801
|
+
|
|
802
|
+
num_flip_since_rebuild = 0;
|
|
803
|
+
// Data are fresh from rebuild
|
|
804
|
+
status.has_fresh_rebuild = true;
|
|
805
|
+
assert(solve_phase == kSolvePhase1 || solve_phase == kSolvePhase2);
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
void HEkkPrimal::iterate() {
|
|
809
|
+
const HighsInt from_check_iter = 15;
|
|
810
|
+
const HighsInt to_check_iter = from_check_iter + 10;
|
|
811
|
+
if (ekk_instance_.debug_solve_report_) {
|
|
812
|
+
ekk_instance_.debug_iteration_report_ =
|
|
813
|
+
ekk_instance_.iteration_count_ >= from_check_iter &&
|
|
814
|
+
ekk_instance_.iteration_count_ <= to_check_iter;
|
|
815
|
+
if (ekk_instance_.debug_iteration_report_) {
|
|
816
|
+
printf("HEkkDual::iterate Debug iteration %d\n",
|
|
817
|
+
(int)ekk_instance_.iteration_count_);
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
if (debugPrimalSimplex("Before iteration") ==
|
|
822
|
+
HighsDebugStatus::kLogicalError) {
|
|
823
|
+
solve_phase = kSolvePhaseError;
|
|
824
|
+
return;
|
|
825
|
+
}
|
|
826
|
+
// Initialise row_out so that aborting iteration before CHUZR due to
|
|
827
|
+
// numerical test of chosen reduced cost can be spotted - and
|
|
828
|
+
// eliminates the unassigned read that can occur when the first
|
|
829
|
+
// iteration is aborted in primal clean-up
|
|
830
|
+
row_out = kNoRowSought;
|
|
831
|
+
// Perform CHUZC
|
|
832
|
+
//
|
|
833
|
+
chuzc();
|
|
834
|
+
if (variable_in == -1) {
|
|
835
|
+
rebuild_reason = kRebuildReasonPossiblyOptimal;
|
|
836
|
+
return;
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
// Perform FTRAN - and dual value cross-check to decide whether to use the
|
|
840
|
+
// variable
|
|
841
|
+
//
|
|
842
|
+
// rebuild_reason = kRebuildReasonPossiblySingularBasis is set if
|
|
843
|
+
// numerical trouble is detected
|
|
844
|
+
if (!useVariableIn()) {
|
|
845
|
+
if (rebuild_reason)
|
|
846
|
+
assert(rebuild_reason == kRebuildReasonPossiblySingularBasis);
|
|
847
|
+
return;
|
|
848
|
+
}
|
|
849
|
+
assert(!rebuild_reason);
|
|
850
|
+
|
|
851
|
+
// Perform CHUZR
|
|
852
|
+
if (solve_phase == kSolvePhase1) {
|
|
853
|
+
phase1ChooseRow();
|
|
854
|
+
assert(row_out != kNoRowSought);
|
|
855
|
+
if (row_out == kNoRowChosen) {
|
|
856
|
+
highsLogDev(ekk_instance_.options_->log_options, HighsLogType::kError,
|
|
857
|
+
"Primal phase 1 choose row failed\n");
|
|
858
|
+
solve_phase = kSolvePhaseError;
|
|
859
|
+
return;
|
|
860
|
+
}
|
|
861
|
+
} else {
|
|
862
|
+
chooseRow();
|
|
863
|
+
}
|
|
864
|
+
assert(!rebuild_reason);
|
|
865
|
+
|
|
866
|
+
// Consider whether to perform a bound swap - either because it's
|
|
867
|
+
// shorter than the pivoting step or, in the case of Phase 1,
|
|
868
|
+
// because it's cheaper than pivoting - which may be questionable
|
|
869
|
+
//
|
|
870
|
+
// rebuild_reason = kRebuildReasonPossiblyPrimalUnbounded is set
|
|
871
|
+
// in phase 2 if there's no pivot or bound swap. In phase 1 there is
|
|
872
|
+
// always a pivot at this stage since row_out < 0 is trapped (above)
|
|
873
|
+
// as an error.
|
|
874
|
+
assert(solve_phase == kSolvePhase2 || row_out >= 0);
|
|
875
|
+
considerBoundSwap();
|
|
876
|
+
if (rebuild_reason == kRebuildReasonPossiblyPrimalUnbounded) return;
|
|
877
|
+
assert(!rebuild_reason);
|
|
878
|
+
|
|
879
|
+
if (row_out >= 0) {
|
|
880
|
+
//
|
|
881
|
+
// Perform unit BTRAN and PRICE to get pivotal row - and do a
|
|
882
|
+
// numerical check.
|
|
883
|
+
//
|
|
884
|
+
// rebuild_reason = kRebuildReasonPossiblySingularBasis is set
|
|
885
|
+
// if numerical trouble is detected
|
|
886
|
+
assessPivot();
|
|
887
|
+
if (rebuild_reason) {
|
|
888
|
+
assert(rebuild_reason == kRebuildReasonPossiblySingularBasis);
|
|
889
|
+
return;
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
if (isBadBasisChange()) return;
|
|
894
|
+
|
|
895
|
+
// Any pivoting is numerically acceptable, so perform update.
|
|
896
|
+
//
|
|
897
|
+
// rebuild_reason =
|
|
898
|
+
// kRebuildReasonPrimalInfeasibleInPrimalSimplex is set if a
|
|
899
|
+
// primal infeasibility is found in phase 2
|
|
900
|
+
//
|
|
901
|
+
// rebuild_reason = kRebuildReasonPossiblyPhase1Feasible is set in
|
|
902
|
+
// phase 1 if the number of primal infeasibilities is reduced to
|
|
903
|
+
// zero
|
|
904
|
+
//
|
|
905
|
+
// rebuild_reason = kRebuildReasonUpdateLimitReached is set in
|
|
906
|
+
// either phase if the update count reaches the limit!
|
|
907
|
+
//
|
|
908
|
+
// rebuild_reason = kRebuildReasonSyntheticClockSaysInvert is
|
|
909
|
+
// set in updateFactor() if it is considered to be more efficient to
|
|
910
|
+
// reinvert.
|
|
911
|
+
update();
|
|
912
|
+
// Force rebuild if there are no infeasibilities in phase 1
|
|
913
|
+
if (!ekk_instance_.info_.num_primal_infeasibilities &&
|
|
914
|
+
solve_phase == kSolvePhase1)
|
|
915
|
+
rebuild_reason = kRebuildReasonPossiblyPhase1Feasible;
|
|
916
|
+
|
|
917
|
+
const bool ok_rebuild_reason =
|
|
918
|
+
rebuild_reason == kRebuildReasonNo ||
|
|
919
|
+
rebuild_reason == kRebuildReasonPossiblyPhase1Feasible ||
|
|
920
|
+
rebuild_reason == kRebuildReasonPrimalInfeasibleInPrimalSimplex ||
|
|
921
|
+
rebuild_reason == kRebuildReasonSyntheticClockSaysInvert ||
|
|
922
|
+
rebuild_reason == kRebuildReasonUpdateLimitReached;
|
|
923
|
+
if (!ok_rebuild_reason) {
|
|
924
|
+
printf("HEkkPrimal::rebuild Solve %d; Iter %d: rebuild_reason = %d\n",
|
|
925
|
+
(int)ekk_instance_.debug_solve_call_num_,
|
|
926
|
+
(int)ekk_instance_.iteration_count_, (int)rebuild_reason);
|
|
927
|
+
fflush(stdout);
|
|
928
|
+
}
|
|
929
|
+
assert(ok_rebuild_reason);
|
|
930
|
+
assert(solve_phase == kSolvePhase1 || solve_phase == kSolvePhase2);
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
void HEkkPrimal::chuzc() {
|
|
934
|
+
if (done_next_chuzc) assert(use_hyper_chuzc);
|
|
935
|
+
vector<double>& workDual = ekk_instance_.info_.workDual_;
|
|
936
|
+
ekk_instance_.applyTabooVariableIn(workDual, 0);
|
|
937
|
+
if (use_hyper_chuzc) {
|
|
938
|
+
// Perform hyper-sparse CHUZC and then check result using full CHUZC
|
|
939
|
+
if (!done_next_chuzc) chooseColumn(true);
|
|
940
|
+
const bool check_hyper_chuzc = true;
|
|
941
|
+
if (check_hyper_chuzc) {
|
|
942
|
+
HighsInt hyper_sparse_variable_in = variable_in;
|
|
943
|
+
chooseColumn(false);
|
|
944
|
+
double hyper_sparse_measure = 0;
|
|
945
|
+
if (hyper_sparse_variable_in >= 0) {
|
|
946
|
+
double squared_dual_infeasibility = workDual[hyper_sparse_variable_in] *
|
|
947
|
+
workDual[hyper_sparse_variable_in];
|
|
948
|
+
hyper_sparse_measure =
|
|
949
|
+
squared_dual_infeasibility / edge_weight_[hyper_sparse_variable_in];
|
|
950
|
+
}
|
|
951
|
+
double measure = 0;
|
|
952
|
+
if (variable_in >= 0) {
|
|
953
|
+
double squared_dual_infeasibility =
|
|
954
|
+
workDual[variable_in] * workDual[variable_in];
|
|
955
|
+
measure = squared_dual_infeasibility / edge_weight_[variable_in];
|
|
956
|
+
}
|
|
957
|
+
double abs_measure_error = fabs(hyper_sparse_measure - measure);
|
|
958
|
+
bool measure_error = abs_measure_error > 1e-12;
|
|
959
|
+
// if (measure_error)
|
|
960
|
+
// printf("Iteration %" HIGHSINT_FORMAT
|
|
961
|
+
// ": Hyper-sparse CHUZC measure %g != %g = Full "
|
|
962
|
+
// "CHUZC measure (%" HIGHSINT_FORMAT ", %" HIGHSINT_FORMAT
|
|
963
|
+
// "): error %g\n",
|
|
964
|
+
// ekk_instance_.iteration_count_, hyper_sparse_measure, measure,
|
|
965
|
+
// hyper_sparse_variable_in, variable_in, abs_measure_error);
|
|
966
|
+
|
|
967
|
+
// todo this fails on some rarer occasions, e.g. on glass4
|
|
968
|
+
assert(!measure_error);
|
|
969
|
+
variable_in = hyper_sparse_variable_in;
|
|
970
|
+
}
|
|
971
|
+
} else {
|
|
972
|
+
chooseColumn(false);
|
|
973
|
+
}
|
|
974
|
+
ekk_instance_.unapplyTabooVariableIn(workDual);
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
void HEkkPrimal::chooseColumn(const bool hyper_sparse) {
|
|
978
|
+
assert(!hyper_sparse || !done_next_chuzc);
|
|
979
|
+
const vector<int8_t>& nonbasicMove = ekk_instance_.basis_.nonbasicMove_;
|
|
980
|
+
const vector<double>& workDual = ekk_instance_.info_.workDual_;
|
|
981
|
+
double best_measure = 0;
|
|
982
|
+
variable_in = -1;
|
|
983
|
+
|
|
984
|
+
const bool local_use_hyper_chuzc = hyper_sparse;
|
|
985
|
+
// Consider nonbasic free columns first
|
|
986
|
+
const HighsInt& num_nonbasic_free_col = nonbasic_free_col_set.count();
|
|
987
|
+
if (local_use_hyper_chuzc) {
|
|
988
|
+
if (!initialise_hyper_chuzc) hyperChooseColumn();
|
|
989
|
+
if (initialise_hyper_chuzc) {
|
|
990
|
+
analysis->simplexTimerStart(ChuzcHyperInitialiselClock);
|
|
991
|
+
num_hyper_chuzc_candidates = 0;
|
|
992
|
+
if (num_nonbasic_free_col) {
|
|
993
|
+
const vector<HighsInt>& nonbasic_free_col_set_entry =
|
|
994
|
+
nonbasic_free_col_set.entry();
|
|
995
|
+
for (HighsInt ix = 0; ix < num_nonbasic_free_col; ix++) {
|
|
996
|
+
HighsInt iCol = nonbasic_free_col_set_entry[ix];
|
|
997
|
+
double dual_infeasibility = fabs(workDual[iCol]);
|
|
998
|
+
if (dual_infeasibility > dual_feasibility_tolerance) {
|
|
999
|
+
double measure =
|
|
1000
|
+
dual_infeasibility * dual_infeasibility / edge_weight_[iCol];
|
|
1001
|
+
addToDecreasingHeap(
|
|
1002
|
+
num_hyper_chuzc_candidates, max_num_hyper_chuzc_candidates,
|
|
1003
|
+
hyper_chuzc_measure, hyper_chuzc_candidate, measure, iCol);
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
// Now look at other columns
|
|
1008
|
+
for (HighsInt iCol = 0; iCol < num_tot; iCol++) {
|
|
1009
|
+
double dual_infeasibility = -nonbasicMove[iCol] * workDual[iCol];
|
|
1010
|
+
if (dual_infeasibility > dual_feasibility_tolerance) {
|
|
1011
|
+
double measure =
|
|
1012
|
+
dual_infeasibility * dual_infeasibility / edge_weight_[iCol];
|
|
1013
|
+
addToDecreasingHeap(
|
|
1014
|
+
num_hyper_chuzc_candidates, max_num_hyper_chuzc_candidates,
|
|
1015
|
+
hyper_chuzc_measure, hyper_chuzc_candidate, measure, iCol);
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
1018
|
+
// Sort the heap
|
|
1019
|
+
sortDecreasingHeap(num_hyper_chuzc_candidates, hyper_chuzc_measure,
|
|
1020
|
+
hyper_chuzc_candidate);
|
|
1021
|
+
initialise_hyper_chuzc = false;
|
|
1022
|
+
analysis->simplexTimerStop(ChuzcHyperInitialiselClock);
|
|
1023
|
+
// Choose the first entry - if there is one
|
|
1024
|
+
if (num_hyper_chuzc_candidates) {
|
|
1025
|
+
variable_in = hyper_chuzc_candidate[1];
|
|
1026
|
+
best_measure = hyper_chuzc_measure[1];
|
|
1027
|
+
max_hyper_chuzc_non_candidate_measure =
|
|
1028
|
+
hyper_chuzc_measure[num_hyper_chuzc_candidates];
|
|
1029
|
+
if (report_hyper_chuzc)
|
|
1030
|
+
printf(
|
|
1031
|
+
"Full CHUZC: Max measure is %9.4g for column "
|
|
1032
|
+
"%4" HIGHSINT_FORMAT
|
|
1033
|
+
", and "
|
|
1034
|
+
"max non-candidate measure of %9.4g\n",
|
|
1035
|
+
best_measure, variable_in, max_hyper_chuzc_non_candidate_measure);
|
|
1036
|
+
}
|
|
1037
|
+
}
|
|
1038
|
+
} else {
|
|
1039
|
+
analysis->simplexTimerStart(ChuzcPrimalClock);
|
|
1040
|
+
// Choose any attractive nonbasic free column
|
|
1041
|
+
if (num_nonbasic_free_col) {
|
|
1042
|
+
const vector<HighsInt>& nonbasic_free_col_set_entry =
|
|
1043
|
+
nonbasic_free_col_set.entry();
|
|
1044
|
+
for (HighsInt ix = 0; ix < num_nonbasic_free_col; ix++) {
|
|
1045
|
+
HighsInt iCol = nonbasic_free_col_set_entry[ix];
|
|
1046
|
+
double dual_infeasibility = fabs(workDual[iCol]);
|
|
1047
|
+
if (dual_infeasibility > dual_feasibility_tolerance &&
|
|
1048
|
+
dual_infeasibility * dual_infeasibility >
|
|
1049
|
+
best_measure * edge_weight_[iCol]) {
|
|
1050
|
+
variable_in = iCol;
|
|
1051
|
+
best_measure =
|
|
1052
|
+
dual_infeasibility * dual_infeasibility / edge_weight_[iCol];
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
// Now look at other columns
|
|
1057
|
+
for (HighsInt iCol = 0; iCol < num_tot; iCol++) {
|
|
1058
|
+
double dual_infeasibility = -nonbasicMove[iCol] * workDual[iCol];
|
|
1059
|
+
if (dual_infeasibility > dual_feasibility_tolerance &&
|
|
1060
|
+
dual_infeasibility * dual_infeasibility >
|
|
1061
|
+
best_measure * edge_weight_[iCol]) {
|
|
1062
|
+
variable_in = iCol;
|
|
1063
|
+
best_measure =
|
|
1064
|
+
dual_infeasibility * dual_infeasibility / edge_weight_[iCol];
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
analysis->simplexTimerStop(ChuzcPrimalClock);
|
|
1068
|
+
}
|
|
1069
|
+
// printf("ChooseColumn: Iteration %" HIGHSINT_FORMAT ", choose column %"
|
|
1070
|
+
// HIGHSINT_FORMAT " with measure %g\n",
|
|
1071
|
+
// ekk_instance_.iteration_count_, variable_in, best_measure);
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
bool HEkkPrimal::useVariableIn() {
|
|
1075
|
+
// rebuild_reason = kRebuildReasonPossiblySingularBasis is set if
|
|
1076
|
+
// numerical trouble is detected
|
|
1077
|
+
HighsSimplexInfo& info = ekk_instance_.info_;
|
|
1078
|
+
vector<double>& workDual = info.workDual_;
|
|
1079
|
+
const vector<int8_t>& nonbasicMove = ekk_instance_.basis_.nonbasicMove_;
|
|
1080
|
+
const double updated_theta_dual = workDual[variable_in];
|
|
1081
|
+
// Determine the move direction - can't use nonbasicMove_[variable_in]
|
|
1082
|
+
// due to free columns
|
|
1083
|
+
move_in = updated_theta_dual > 0 ? -1 : 1;
|
|
1084
|
+
// Unless the variable is free, nonbasicMove[variable_in] should be the same
|
|
1085
|
+
// as move_in
|
|
1086
|
+
if (nonbasicMove[variable_in]) assert(nonbasicMove[variable_in] == move_in);
|
|
1087
|
+
//
|
|
1088
|
+
// FTRAN
|
|
1089
|
+
//
|
|
1090
|
+
// Compute pivot column
|
|
1091
|
+
ekk_instance_.pivotColumnFtran(variable_in, col_aq);
|
|
1092
|
+
// Compute the dual for the pivot column and compare it with the
|
|
1093
|
+
// updated value
|
|
1094
|
+
double computed_theta_dual =
|
|
1095
|
+
ekk_instance_.computeDualForTableauColumn(variable_in, col_aq);
|
|
1096
|
+
ekk_instance_.debugUpdatedDual(updated_theta_dual, computed_theta_dual);
|
|
1097
|
+
// Feed in the computed dual value.
|
|
1098
|
+
//
|
|
1099
|
+
// The sum of dual infeasibilities (and maybe max dual
|
|
1100
|
+
// infeasibility) will be wrong, but there's a big tolerance on
|
|
1101
|
+
// this in debugSimplex. Have to be careful (below) if the computed
|
|
1102
|
+
// dual value is no longer a dual infeasibility
|
|
1103
|
+
info.workDual_[variable_in] = computed_theta_dual;
|
|
1104
|
+
// Reassign theta_dual to be the computed value
|
|
1105
|
+
theta_dual = info.workDual_[variable_in];
|
|
1106
|
+
// Determine whether theta_dual is too small or has changed sign
|
|
1107
|
+
const bool theta_dual_small = fabs(theta_dual) <= dual_feasibility_tolerance;
|
|
1108
|
+
const bool theta_dual_sign_error =
|
|
1109
|
+
updated_theta_dual * computed_theta_dual <= 0;
|
|
1110
|
+
|
|
1111
|
+
// If theta_dual is small, then it's no longer a dual infeasibility,
|
|
1112
|
+
// so reduce the number of dual infeasibilities. Otherwise an error
|
|
1113
|
+
// is identified in debugSimplex
|
|
1114
|
+
if (theta_dual_small) ekk_instance_.info_.num_dual_infeasibilities--;
|
|
1115
|
+
if (theta_dual_small || theta_dual_sign_error) {
|
|
1116
|
+
// The computed dual is small or has a sign error, so don't use it
|
|
1117
|
+
std::string theta_dual_size = "";
|
|
1118
|
+
if (theta_dual_small) theta_dual_size = "; too small";
|
|
1119
|
+
std::string theta_dual_sign = "";
|
|
1120
|
+
if (theta_dual_sign_error) theta_dual_sign = "; sign error";
|
|
1121
|
+
highsLogDev(ekk_instance_.options_->log_options, HighsLogType::kInfo,
|
|
1122
|
+
"Chosen entering variable %" HIGHSINT_FORMAT
|
|
1123
|
+
" (Iter = %" HIGHSINT_FORMAT "; Update = %" HIGHSINT_FORMAT
|
|
1124
|
+
") has computed "
|
|
1125
|
+
"(updated) dual of %10.4g (%10.4g) so don't use it%s%s\n",
|
|
1126
|
+
variable_in, ekk_instance_.iteration_count_, info.update_count,
|
|
1127
|
+
computed_theta_dual, updated_theta_dual,
|
|
1128
|
+
theta_dual_size.c_str(), theta_dual_sign.c_str());
|
|
1129
|
+
// If a significant computed dual has sign error, consider reinverting
|
|
1130
|
+
if (!theta_dual_small && info.update_count > 0)
|
|
1131
|
+
rebuild_reason = kRebuildReasonPossiblySingularBasis;
|
|
1132
|
+
hyperChooseColumnClear();
|
|
1133
|
+
return false;
|
|
1134
|
+
}
|
|
1135
|
+
return true;
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
void HEkkPrimal::phase1ChooseRow() {
|
|
1139
|
+
const HighsSimplexInfo& info = ekk_instance_.info_;
|
|
1140
|
+
const vector<double>& baseLower = info.baseLower_;
|
|
1141
|
+
const vector<double>& baseUpper = info.baseUpper_;
|
|
1142
|
+
const vector<double>& baseValue = info.baseValue_;
|
|
1143
|
+
analysis->simplexTimerStart(Chuzr1Clock);
|
|
1144
|
+
// Collect phase 1 theta lists
|
|
1145
|
+
//
|
|
1146
|
+
|
|
1147
|
+
const double dPivotTol = info.update_count < 10 ? 1e-9
|
|
1148
|
+
: info.update_count < 20 ? 1e-8
|
|
1149
|
+
: 1e-7;
|
|
1150
|
+
ph1SorterR.clear();
|
|
1151
|
+
ph1SorterT.clear();
|
|
1152
|
+
for (HighsInt i = 0; i < col_aq.count; i++) {
|
|
1153
|
+
HighsInt iRow = col_aq.index[i];
|
|
1154
|
+
double dAlpha = col_aq.array[iRow] * move_in;
|
|
1155
|
+
|
|
1156
|
+
// When the basic variable x[i] decrease
|
|
1157
|
+
if (dAlpha > +dPivotTol) {
|
|
1158
|
+
// Whether it can become feasible by going below its upper bound
|
|
1159
|
+
if (baseValue[iRow] > baseUpper[iRow] + primal_feasibility_tolerance) {
|
|
1160
|
+
double dFeasTheta =
|
|
1161
|
+
(baseValue[iRow] - baseUpper[iRow] - primal_feasibility_tolerance) /
|
|
1162
|
+
dAlpha;
|
|
1163
|
+
ph1SorterR.push_back(std::make_pair(dFeasTheta, iRow));
|
|
1164
|
+
ph1SorterT.push_back(std::make_pair(dFeasTheta, iRow));
|
|
1165
|
+
}
|
|
1166
|
+
// Whether it can become infeasible (again) by going below its
|
|
1167
|
+
// lower bound
|
|
1168
|
+
if (baseValue[iRow] > baseLower[iRow] - primal_feasibility_tolerance &&
|
|
1169
|
+
baseLower[iRow] > -kHighsInf) {
|
|
1170
|
+
double dRelaxTheta =
|
|
1171
|
+
(baseValue[iRow] - baseLower[iRow] + primal_feasibility_tolerance) /
|
|
1172
|
+
dAlpha;
|
|
1173
|
+
double dTightTheta = (baseValue[iRow] - baseLower[iRow]) / dAlpha;
|
|
1174
|
+
ph1SorterR.push_back(std::make_pair(dRelaxTheta, iRow - num_row));
|
|
1175
|
+
ph1SorterT.push_back(std::make_pair(dTightTheta, iRow - num_row));
|
|
1176
|
+
}
|
|
1177
|
+
}
|
|
1178
|
+
|
|
1179
|
+
// When the basic variable x[i] increase
|
|
1180
|
+
if (dAlpha < -dPivotTol) {
|
|
1181
|
+
// Whether it can become feasible by going above its lower bound
|
|
1182
|
+
if (baseValue[iRow] < baseLower[iRow] - primal_feasibility_tolerance) {
|
|
1183
|
+
double dFeasTheta =
|
|
1184
|
+
(baseValue[iRow] - baseLower[iRow] + primal_feasibility_tolerance) /
|
|
1185
|
+
dAlpha;
|
|
1186
|
+
ph1SorterR.push_back(std::make_pair(dFeasTheta, iRow - num_row));
|
|
1187
|
+
ph1SorterT.push_back(std::make_pair(dFeasTheta, iRow - num_row));
|
|
1188
|
+
}
|
|
1189
|
+
// Whether it can become infeasible (again) by going above its
|
|
1190
|
+
// upper bound
|
|
1191
|
+
if (baseValue[iRow] < baseUpper[iRow] + primal_feasibility_tolerance &&
|
|
1192
|
+
baseUpper[iRow] < +kHighsInf) {
|
|
1193
|
+
double dRelaxTheta =
|
|
1194
|
+
(baseValue[iRow] - baseUpper[iRow] - primal_feasibility_tolerance) /
|
|
1195
|
+
dAlpha;
|
|
1196
|
+
double dTightTheta = (baseValue[iRow] - baseUpper[iRow]) / dAlpha;
|
|
1197
|
+
ph1SorterR.push_back(std::make_pair(dRelaxTheta, iRow));
|
|
1198
|
+
ph1SorterT.push_back(std::make_pair(dTightTheta, iRow));
|
|
1199
|
+
}
|
|
1200
|
+
}
|
|
1201
|
+
}
|
|
1202
|
+
|
|
1203
|
+
analysis->simplexTimerStop(Chuzr1Clock);
|
|
1204
|
+
// When there are no candidates at all, we can leave it here
|
|
1205
|
+
if (ph1SorterR.empty()) {
|
|
1206
|
+
row_out = kNoRowChosen;
|
|
1207
|
+
variable_out = -1;
|
|
1208
|
+
return;
|
|
1209
|
+
}
|
|
1210
|
+
|
|
1211
|
+
// Now sort the relaxed theta to find the final break point. TODO:
|
|
1212
|
+
// Consider partial sort. Or heapify [O(n)] and then pop k points
|
|
1213
|
+
// [kO(log(n))].
|
|
1214
|
+
|
|
1215
|
+
analysis->simplexTimerStart(Chuzr2Clock);
|
|
1216
|
+
pdqsort(ph1SorterR.begin(), ph1SorterR.end());
|
|
1217
|
+
double dMaxTheta = ph1SorterR[0].first;
|
|
1218
|
+
double dGradient = fabs(theta_dual);
|
|
1219
|
+
for (const auto& candidate : ph1SorterR) {
|
|
1220
|
+
double dMyTheta = candidate.first;
|
|
1221
|
+
HighsInt index = candidate.second;
|
|
1222
|
+
HighsInt iRow = index >= 0 ? index : index + num_row;
|
|
1223
|
+
dGradient -= fabs(col_aq.array[iRow]);
|
|
1224
|
+
// Stop when the gradient start to decrease
|
|
1225
|
+
if (dGradient <= 0) {
|
|
1226
|
+
break;
|
|
1227
|
+
}
|
|
1228
|
+
dMaxTheta = dMyTheta;
|
|
1229
|
+
}
|
|
1230
|
+
|
|
1231
|
+
// Find out the biggest possible alpha for pivot
|
|
1232
|
+
pdqsort(ph1SorterT.begin(), ph1SorterT.end());
|
|
1233
|
+
double dMaxAlpha = 0.0;
|
|
1234
|
+
size_t iLast = ph1SorterT.size();
|
|
1235
|
+
for (size_t i = 0; i < ph1SorterT.size(); i++) {
|
|
1236
|
+
double dMyTheta = ph1SorterT[i].first;
|
|
1237
|
+
HighsInt index = ph1SorterT[i].second;
|
|
1238
|
+
HighsInt iRow = index >= 0 ? index : index + num_row;
|
|
1239
|
+
double dAbsAlpha = fabs(col_aq.array[iRow]);
|
|
1240
|
+
// Stop when the theta is too large
|
|
1241
|
+
if (dMyTheta > dMaxTheta) {
|
|
1242
|
+
iLast = i;
|
|
1243
|
+
break;
|
|
1244
|
+
}
|
|
1245
|
+
// Update the maximal possible alpha
|
|
1246
|
+
if (dMaxAlpha < dAbsAlpha) {
|
|
1247
|
+
dMaxAlpha = dAbsAlpha;
|
|
1248
|
+
}
|
|
1249
|
+
}
|
|
1250
|
+
|
|
1251
|
+
// Finally choose a pivot with good enough alpha, working backwards
|
|
1252
|
+
row_out = kNoRowChosen;
|
|
1253
|
+
variable_out = -1;
|
|
1254
|
+
move_out = 0;
|
|
1255
|
+
for (size_t i = iLast; i > 0; i--) {
|
|
1256
|
+
HighsInt index = ph1SorterT[i - 1].second;
|
|
1257
|
+
HighsInt iRow = index >= 0 ? index : index + num_row;
|
|
1258
|
+
double dAbsAlpha = fabs(col_aq.array[iRow]);
|
|
1259
|
+
if (dAbsAlpha > dMaxAlpha * 0.1) {
|
|
1260
|
+
row_out = iRow;
|
|
1261
|
+
move_out = index >= 0 ? 1 : -1;
|
|
1262
|
+
break;
|
|
1263
|
+
}
|
|
1264
|
+
}
|
|
1265
|
+
analysis->simplexTimerStop(Chuzr2Clock);
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1268
|
+
void HEkkPrimal::chooseRow() {
|
|
1269
|
+
HighsSimplexInfo& info = ekk_instance_.info_;
|
|
1270
|
+
const vector<double>& baseLower = info.baseLower_;
|
|
1271
|
+
const vector<double>& baseUpper = info.baseUpper_;
|
|
1272
|
+
const vector<double>& baseValue = info.baseValue_;
|
|
1273
|
+
analysis->simplexTimerStart(Chuzr1Clock);
|
|
1274
|
+
// Initialize
|
|
1275
|
+
row_out = kNoRowChosen;
|
|
1276
|
+
|
|
1277
|
+
// Choose row pass 1
|
|
1278
|
+
double alphaTol = info.update_count < 10 ? 1e-9
|
|
1279
|
+
: info.update_count < 20 ? 1e-8
|
|
1280
|
+
: 1e-7;
|
|
1281
|
+
|
|
1282
|
+
double relaxTheta = 1e100;
|
|
1283
|
+
double relaxSpace;
|
|
1284
|
+
for (HighsInt i = 0; i < col_aq.count; i++) {
|
|
1285
|
+
HighsInt iRow = col_aq.index[i];
|
|
1286
|
+
double alpha = col_aq.array[iRow] * move_in;
|
|
1287
|
+
if (alpha > alphaTol) {
|
|
1288
|
+
relaxSpace =
|
|
1289
|
+
baseValue[iRow] - baseLower[iRow] + primal_feasibility_tolerance;
|
|
1290
|
+
if (relaxSpace < relaxTheta * alpha) relaxTheta = relaxSpace / alpha;
|
|
1291
|
+
} else if (alpha < -alphaTol) {
|
|
1292
|
+
relaxSpace =
|
|
1293
|
+
baseValue[iRow] - baseUpper[iRow] - primal_feasibility_tolerance;
|
|
1294
|
+
if (relaxSpace > relaxTheta * alpha) relaxTheta = relaxSpace / alpha;
|
|
1295
|
+
}
|
|
1296
|
+
}
|
|
1297
|
+
analysis->simplexTimerStop(Chuzr1Clock);
|
|
1298
|
+
|
|
1299
|
+
analysis->simplexTimerStart(Chuzr2Clock);
|
|
1300
|
+
double bestAlpha = 0;
|
|
1301
|
+
for (HighsInt i = 0; i < col_aq.count; i++) {
|
|
1302
|
+
HighsInt iRow = col_aq.index[i];
|
|
1303
|
+
double alpha = col_aq.array[iRow] * move_in;
|
|
1304
|
+
if (alpha > alphaTol) {
|
|
1305
|
+
// Positive pivotal column entry
|
|
1306
|
+
double tightSpace = baseValue[iRow] - baseLower[iRow];
|
|
1307
|
+
if (tightSpace < relaxTheta * alpha) {
|
|
1308
|
+
if (bestAlpha < alpha) {
|
|
1309
|
+
bestAlpha = alpha;
|
|
1310
|
+
row_out = iRow;
|
|
1311
|
+
}
|
|
1312
|
+
}
|
|
1313
|
+
} else if (alpha < -alphaTol) {
|
|
1314
|
+
// Negative pivotal column entry
|
|
1315
|
+
double tightSpace = baseValue[iRow] - baseUpper[iRow];
|
|
1316
|
+
if (tightSpace > relaxTheta * alpha) {
|
|
1317
|
+
if (bestAlpha < -alpha) {
|
|
1318
|
+
bestAlpha = -alpha;
|
|
1319
|
+
row_out = iRow;
|
|
1320
|
+
}
|
|
1321
|
+
}
|
|
1322
|
+
}
|
|
1323
|
+
}
|
|
1324
|
+
analysis->simplexTimerStop(Chuzr2Clock);
|
|
1325
|
+
}
|
|
1326
|
+
|
|
1327
|
+
void HEkkPrimal::considerBoundSwap() {
|
|
1328
|
+
const HighsSimplexInfo& info = ekk_instance_.info_;
|
|
1329
|
+
const vector<double>& workLower = info.workLower_;
|
|
1330
|
+
const vector<double>& workUpper = info.workUpper_;
|
|
1331
|
+
const vector<double>& baseLower = info.baseLower_;
|
|
1332
|
+
const vector<double>& baseUpper = info.baseUpper_;
|
|
1333
|
+
const vector<double>& workValue = info.workValue_;
|
|
1334
|
+
const vector<double>& baseValue = info.baseValue_;
|
|
1335
|
+
|
|
1336
|
+
// Compute the primal theta and see if we should have done a bound
|
|
1337
|
+
// flip instead
|
|
1338
|
+
if (row_out == kNoRowChosen) {
|
|
1339
|
+
assert(solve_phase == kSolvePhase2);
|
|
1340
|
+
// No binding ratio in CHUZR, so flip or unbounded
|
|
1341
|
+
theta_primal = move_in * kHighsInf;
|
|
1342
|
+
move_out = 0;
|
|
1343
|
+
} else {
|
|
1344
|
+
assert(row_out >= 0);
|
|
1345
|
+
// Determine the step to the leaving bound
|
|
1346
|
+
//
|
|
1347
|
+
alpha_col = col_aq.array[row_out];
|
|
1348
|
+
// In Phase 1, move_out depends on whether the leaving variable is
|
|
1349
|
+
// becoming feasible - moves up to lower (down to upper) - or
|
|
1350
|
+
// remaining feasible - moves down to lower (up to upper) - so
|
|
1351
|
+
// can't be set so easily as in phase 2
|
|
1352
|
+
if (solve_phase == kSolvePhase2)
|
|
1353
|
+
move_out = alpha_col * move_in > 0 ? -1 : 1;
|
|
1354
|
+
theta_primal = 0;
|
|
1355
|
+
if (move_out == 1) {
|
|
1356
|
+
theta_primal = (baseValue[row_out] - baseUpper[row_out]) / alpha_col;
|
|
1357
|
+
} else {
|
|
1358
|
+
theta_primal = (baseValue[row_out] - baseLower[row_out]) / alpha_col;
|
|
1359
|
+
}
|
|
1360
|
+
assert(theta_primal > -kHighsInf && theta_primal < kHighsInf);
|
|
1361
|
+
}
|
|
1362
|
+
|
|
1363
|
+
// Look to see if there is a bound flip
|
|
1364
|
+
bool flipped = false;
|
|
1365
|
+
double lower_in = workLower[variable_in];
|
|
1366
|
+
double upper_in = workUpper[variable_in];
|
|
1367
|
+
value_in = workValue[variable_in] + theta_primal;
|
|
1368
|
+
if (move_in > 0) {
|
|
1369
|
+
if (value_in > upper_in + primal_feasibility_tolerance) {
|
|
1370
|
+
flipped = true;
|
|
1371
|
+
row_out = kNoRowChosen;
|
|
1372
|
+
value_in = upper_in;
|
|
1373
|
+
theta_primal = upper_in - lower_in;
|
|
1374
|
+
}
|
|
1375
|
+
} else {
|
|
1376
|
+
if (value_in < lower_in - primal_feasibility_tolerance) {
|
|
1377
|
+
flipped = true;
|
|
1378
|
+
row_out = kNoRowChosen;
|
|
1379
|
+
value_in = lower_in;
|
|
1380
|
+
theta_primal = lower_in - upper_in;
|
|
1381
|
+
}
|
|
1382
|
+
}
|
|
1383
|
+
const bool pivot_or_flipped = row_out >= 0 || flipped;
|
|
1384
|
+
if (solve_phase == kSolvePhase2) {
|
|
1385
|
+
// Check for possible unboundedness
|
|
1386
|
+
if (!pivot_or_flipped) {
|
|
1387
|
+
rebuild_reason = kRebuildReasonPossiblyPrimalUnbounded;
|
|
1388
|
+
return;
|
|
1389
|
+
}
|
|
1390
|
+
}
|
|
1391
|
+
// Check for possible error
|
|
1392
|
+
assert(pivot_or_flipped);
|
|
1393
|
+
assert(flipped == (row_out == kNoRowChosen));
|
|
1394
|
+
}
|
|
1395
|
+
|
|
1396
|
+
void HEkkPrimal::assessPivot() {
|
|
1397
|
+
assert(row_out >= 0);
|
|
1398
|
+
// Record the pivot entry
|
|
1399
|
+
alpha_col = col_aq.array[row_out];
|
|
1400
|
+
variable_out = ekk_instance_.basis_.basicIndex_[row_out];
|
|
1401
|
+
|
|
1402
|
+
// Compute the tableau row
|
|
1403
|
+
//
|
|
1404
|
+
// BTRAN
|
|
1405
|
+
//
|
|
1406
|
+
// Compute unit BTran for tableau row and FT update
|
|
1407
|
+
ekk_instance_.unitBtran(row_out, row_ep);
|
|
1408
|
+
//
|
|
1409
|
+
// PRICE
|
|
1410
|
+
//
|
|
1411
|
+
const bool quad_precision = false;
|
|
1412
|
+
ekk_instance_.tableauRowPrice(quad_precision, row_ep, row_ap);
|
|
1413
|
+
|
|
1414
|
+
// Checks row-wise pivot against column-wise pivot for
|
|
1415
|
+
// numerical trouble
|
|
1416
|
+
//
|
|
1417
|
+
// rebuild_reason = kRebuildReasonPossiblySingularBasis is set if
|
|
1418
|
+
// numerical trouble is detected
|
|
1419
|
+
updateVerify();
|
|
1420
|
+
}
|
|
1421
|
+
|
|
1422
|
+
void HEkkPrimal::update() {
|
|
1423
|
+
// Perform update operations that are independent of phase
|
|
1424
|
+
HighsSimplexInfo& info = ekk_instance_.info_;
|
|
1425
|
+
assert(!rebuild_reason);
|
|
1426
|
+
bool flipped = row_out < 0;
|
|
1427
|
+
if (flipped) {
|
|
1428
|
+
variable_out = variable_in;
|
|
1429
|
+
alpha_col = 0;
|
|
1430
|
+
numericalTrouble = 0;
|
|
1431
|
+
info.workValue_[variable_in] = value_in;
|
|
1432
|
+
assert(ekk_instance_.basis_.nonbasicMove_[variable_in] == move_in);
|
|
1433
|
+
ekk_instance_.basis_.nonbasicMove_[variable_in] = -move_in;
|
|
1434
|
+
} else {
|
|
1435
|
+
// Adjust perturbation if leaving equation
|
|
1436
|
+
adjustPerturbedEquationOut();
|
|
1437
|
+
}
|
|
1438
|
+
|
|
1439
|
+
// Start hyper-sparse CHUZC, that takes place through phase1Update()
|
|
1440
|
+
hyperChooseColumnStart();
|
|
1441
|
+
|
|
1442
|
+
if (solve_phase == kSolvePhase1) {
|
|
1443
|
+
// Update primal values
|
|
1444
|
+
phase1UpdatePrimal();
|
|
1445
|
+
|
|
1446
|
+
// Update the duals with respect to feasibility changes
|
|
1447
|
+
basicFeasibilityChangeUpdateDual();
|
|
1448
|
+
|
|
1449
|
+
// For hyper-sparse CHUZC, analyse the duals that have just changed
|
|
1450
|
+
hyperChooseColumnBasicFeasibilityChange();
|
|
1451
|
+
|
|
1452
|
+
} else {
|
|
1453
|
+
// Update primal values, and identify any infeasibilities
|
|
1454
|
+
//
|
|
1455
|
+
// rebuild_reason =
|
|
1456
|
+
// kRebuildReasonPrimalInfeasibleInPrimalSimplex is set if a
|
|
1457
|
+
// primal infeasibility is found
|
|
1458
|
+
phase2UpdatePrimal();
|
|
1459
|
+
}
|
|
1460
|
+
|
|
1461
|
+
assert(rebuild_reason == kRebuildReasonNo ||
|
|
1462
|
+
rebuild_reason == kRebuildReasonPrimalInfeasibleInPrimalSimplex);
|
|
1463
|
+
|
|
1464
|
+
if (flipped) {
|
|
1465
|
+
info.primal_bound_swap++;
|
|
1466
|
+
ekk_instance_.invalidateDualInfeasibilityRecord();
|
|
1467
|
+
iterationAnalysis();
|
|
1468
|
+
localReportIter();
|
|
1469
|
+
num_flip_since_rebuild++;
|
|
1470
|
+
// Update the synthetic clock for UPDATE
|
|
1471
|
+
ekk_instance_.total_synthetic_tick_ += col_aq.synthetic_tick;
|
|
1472
|
+
return;
|
|
1473
|
+
}
|
|
1474
|
+
|
|
1475
|
+
assert(row_out >= 0);
|
|
1476
|
+
|
|
1477
|
+
// Now set the value of the entering variable
|
|
1478
|
+
info.baseValue_[row_out] = value_in;
|
|
1479
|
+
// Consider whether the entering value is feasible and, if not, take
|
|
1480
|
+
// action
|
|
1481
|
+
//
|
|
1482
|
+
// rebuild_reason =
|
|
1483
|
+
// kRebuildReasonPrimalInfeasibleInPrimalSimplex is set in
|
|
1484
|
+
// phase 2 if a primal infeasibility is found
|
|
1485
|
+
considerInfeasibleValueIn();
|
|
1486
|
+
|
|
1487
|
+
// Update the dual values
|
|
1488
|
+
theta_dual = info.workDual_[variable_in];
|
|
1489
|
+
updateDual();
|
|
1490
|
+
|
|
1491
|
+
// Update any non-unit primal edge weights
|
|
1492
|
+
if (edge_weight_mode == EdgeWeightMode::kDevex) {
|
|
1493
|
+
updateDevex();
|
|
1494
|
+
} else if (edge_weight_mode == EdgeWeightMode::kSteepestEdge) {
|
|
1495
|
+
debugPrimalSteepestEdgeWeights("before update");
|
|
1496
|
+
updatePrimalSteepestEdgeWeights();
|
|
1497
|
+
}
|
|
1498
|
+
|
|
1499
|
+
// If entering column was nonbasic free, remove it from the set
|
|
1500
|
+
removeNonbasicFreeColumn();
|
|
1501
|
+
|
|
1502
|
+
// For hyper-sparse CHUZC, analyse the duals and weights that have
|
|
1503
|
+
// just changed
|
|
1504
|
+
hyperChooseColumnDualChange();
|
|
1505
|
+
|
|
1506
|
+
if (ekk_instance_.status_.has_dual_steepest_edge_weights) {
|
|
1507
|
+
ekk_instance_.devDebugDualSteepestEdgeWeights("before update");
|
|
1508
|
+
updateDualSteepestEdgeWeights();
|
|
1509
|
+
}
|
|
1510
|
+
// Perform pivoting
|
|
1511
|
+
//
|
|
1512
|
+
// Transform the vectors used in updateFactor if the simplex NLA involves
|
|
1513
|
+
// scaling
|
|
1514
|
+
ekk_instance_.transformForUpdate(&col_aq, &row_ep, variable_in, &row_out);
|
|
1515
|
+
//
|
|
1516
|
+
// Update the sets of indices of basic and nonbasic variables
|
|
1517
|
+
ekk_instance_.updatePivots(variable_in, row_out, move_out);
|
|
1518
|
+
//
|
|
1519
|
+
// Update the invertible representation of the basis matrix
|
|
1520
|
+
ekk_instance_.updateFactor(&col_aq, &row_ep, &row_out, &rebuild_reason);
|
|
1521
|
+
|
|
1522
|
+
if (ekk_instance_.status_.has_dual_steepest_edge_weights)
|
|
1523
|
+
ekk_instance_.devDebugDualSteepestEdgeWeights("after update");
|
|
1524
|
+
if (edge_weight_mode == EdgeWeightMode::kSteepestEdge)
|
|
1525
|
+
debugPrimalSteepestEdgeWeights("after update");
|
|
1526
|
+
//
|
|
1527
|
+
// Update the row-wise representation of the nonbasic columns
|
|
1528
|
+
ekk_instance_.updateMatrix(variable_in, variable_out);
|
|
1529
|
+
if (info.update_count >= info.update_limit)
|
|
1530
|
+
rebuild_reason = kRebuildReasonUpdateLimitReached;
|
|
1531
|
+
|
|
1532
|
+
// Update the iteration count
|
|
1533
|
+
ekk_instance_.iteration_count_++;
|
|
1534
|
+
|
|
1535
|
+
// Reset the devex when there are too many errors
|
|
1536
|
+
if (edge_weight_mode == EdgeWeightMode::kDevex &&
|
|
1537
|
+
num_bad_devex_weight_ > kAllowedNumBadDevexWeight)
|
|
1538
|
+
initialiseDevexFramework();
|
|
1539
|
+
|
|
1540
|
+
// Report on the iteration
|
|
1541
|
+
iterationAnalysis();
|
|
1542
|
+
localReportIter();
|
|
1543
|
+
|
|
1544
|
+
// Update the synthetic clock for UPDATE
|
|
1545
|
+
ekk_instance_.total_synthetic_tick_ += col_aq.synthetic_tick;
|
|
1546
|
+
ekk_instance_.total_synthetic_tick_ += row_ep.synthetic_tick;
|
|
1547
|
+
|
|
1548
|
+
// Perform hyper-sparse CHUZC
|
|
1549
|
+
hyperChooseColumn();
|
|
1550
|
+
}
|
|
1551
|
+
|
|
1552
|
+
void HEkkPrimal::hyperChooseColumn() {
|
|
1553
|
+
if (!use_hyper_chuzc) return;
|
|
1554
|
+
if (initialise_hyper_chuzc) return;
|
|
1555
|
+
analysis->simplexTimerStart(ChuzcHyperClock);
|
|
1556
|
+
const vector<int8_t>& nonbasicMove = ekk_instance_.basis_.nonbasicMove_;
|
|
1557
|
+
const vector<int8_t>& nonbasicFlag = ekk_instance_.basis_.nonbasicFlag_;
|
|
1558
|
+
const vector<double>& workDual = ekk_instance_.info_.workDual_;
|
|
1559
|
+
if (report_hyper_chuzc)
|
|
1560
|
+
printf(
|
|
1561
|
+
"H-S CHUZC: Max changed measure is %9.4g for column %4" HIGHSINT_FORMAT
|
|
1562
|
+
"",
|
|
1563
|
+
max_changed_measure_value, max_changed_measure_column);
|
|
1564
|
+
double best_measure = max_changed_measure_value;
|
|
1565
|
+
variable_in = -1;
|
|
1566
|
+
if (max_changed_measure_column >= 0) {
|
|
1567
|
+
// Use max_changed_measure_column if it is well defined and has
|
|
1568
|
+
// nonzero dual. It may have been zeroed because it is taboo
|
|
1569
|
+
if (workDual[max_changed_measure_column])
|
|
1570
|
+
variable_in = max_changed_measure_column;
|
|
1571
|
+
}
|
|
1572
|
+
const bool consider_nonbasic_free_column =
|
|
1573
|
+
(nonbasic_free_col_set.count() != 0);
|
|
1574
|
+
if (num_hyper_chuzc_candidates) {
|
|
1575
|
+
for (HighsInt iEntry = 1; iEntry <= num_hyper_chuzc_candidates; iEntry++) {
|
|
1576
|
+
HighsInt iCol = hyper_chuzc_candidate[iEntry];
|
|
1577
|
+
if (nonbasicFlag[iCol] == kNonbasicFlagFalse) {
|
|
1578
|
+
assert(!nonbasicMove[iCol]);
|
|
1579
|
+
continue;
|
|
1580
|
+
}
|
|
1581
|
+
// Assess any dual infeasibility
|
|
1582
|
+
double dual_infeasibility = -nonbasicMove[iCol] * workDual[iCol];
|
|
1583
|
+
if (consider_nonbasic_free_column) {
|
|
1584
|
+
if (nonbasic_free_col_set.in(iCol))
|
|
1585
|
+
dual_infeasibility = fabs(workDual[iCol]);
|
|
1586
|
+
}
|
|
1587
|
+
if (dual_infeasibility > dual_feasibility_tolerance) {
|
|
1588
|
+
if (dual_infeasibility * dual_infeasibility >
|
|
1589
|
+
best_measure * edge_weight_[iCol]) {
|
|
1590
|
+
best_measure =
|
|
1591
|
+
dual_infeasibility * dual_infeasibility / edge_weight_[iCol];
|
|
1592
|
+
variable_in = iCol;
|
|
1593
|
+
}
|
|
1594
|
+
}
|
|
1595
|
+
}
|
|
1596
|
+
}
|
|
1597
|
+
if (variable_in != max_changed_measure_column) {
|
|
1598
|
+
if (report_hyper_chuzc)
|
|
1599
|
+
printf(
|
|
1600
|
+
", and after HS CHUZC set it is now %9.4g for column "
|
|
1601
|
+
"%4" HIGHSINT_FORMAT "",
|
|
1602
|
+
best_measure, variable_in);
|
|
1603
|
+
max_hyper_chuzc_non_candidate_measure =
|
|
1604
|
+
max(max_changed_measure_value, max_hyper_chuzc_non_candidate_measure);
|
|
1605
|
+
}
|
|
1606
|
+
if (best_measure >= max_hyper_chuzc_non_candidate_measure) {
|
|
1607
|
+
// Candidate is at least as good as any unknown column, so accept it
|
|
1608
|
+
done_next_chuzc = true;
|
|
1609
|
+
if (report_hyper_chuzc)
|
|
1610
|
+
printf(", and no has measure > %9.4g\n",
|
|
1611
|
+
max_hyper_chuzc_non_candidate_measure);
|
|
1612
|
+
} else {
|
|
1613
|
+
// Candidate isn't as good as best unknown column, so do a full CHUZC
|
|
1614
|
+
// Shouldn't claim to have done the next CHUZC
|
|
1615
|
+
assert(!done_next_chuzc);
|
|
1616
|
+
done_next_chuzc = false;
|
|
1617
|
+
initialise_hyper_chuzc = true;
|
|
1618
|
+
if (report_hyper_chuzc)
|
|
1619
|
+
printf(", but some may have measure >= %9.4g\n",
|
|
1620
|
+
max_hyper_chuzc_non_candidate_measure);
|
|
1621
|
+
}
|
|
1622
|
+
analysis->simplexTimerStop(ChuzcHyperClock);
|
|
1623
|
+
}
|
|
1624
|
+
|
|
1625
|
+
void HEkkPrimal::hyperChooseColumnStart() {
|
|
1626
|
+
max_changed_measure_value = 0;
|
|
1627
|
+
max_changed_measure_column = -1;
|
|
1628
|
+
done_next_chuzc = false;
|
|
1629
|
+
}
|
|
1630
|
+
|
|
1631
|
+
void HEkkPrimal::hyperChooseColumnClear() {
|
|
1632
|
+
initialise_hyper_chuzc = use_hyper_chuzc;
|
|
1633
|
+
max_hyper_chuzc_non_candidate_measure = -1;
|
|
1634
|
+
done_next_chuzc = false;
|
|
1635
|
+
}
|
|
1636
|
+
|
|
1637
|
+
void HEkkPrimal::hyperChooseColumnChangedInfeasibility(
|
|
1638
|
+
const double infeasibility, const HighsInt iCol) {
|
|
1639
|
+
if (infeasibility * infeasibility >
|
|
1640
|
+
max_changed_measure_value * edge_weight_[iCol]) {
|
|
1641
|
+
max_hyper_chuzc_non_candidate_measure =
|
|
1642
|
+
max(max_changed_measure_value, max_hyper_chuzc_non_candidate_measure);
|
|
1643
|
+
max_changed_measure_value =
|
|
1644
|
+
infeasibility * infeasibility / edge_weight_[iCol];
|
|
1645
|
+
max_changed_measure_column = iCol;
|
|
1646
|
+
} else if (infeasibility * infeasibility >
|
|
1647
|
+
max_hyper_chuzc_non_candidate_measure * edge_weight_[iCol]) {
|
|
1648
|
+
max_hyper_chuzc_non_candidate_measure =
|
|
1649
|
+
infeasibility * infeasibility / edge_weight_[iCol];
|
|
1650
|
+
}
|
|
1651
|
+
}
|
|
1652
|
+
|
|
1653
|
+
void HEkkPrimal::hyperChooseColumnBasicFeasibilityChange() {
|
|
1654
|
+
if (!use_hyper_chuzc) return;
|
|
1655
|
+
analysis->simplexTimerStart(ChuzcHyperBasicFeasibilityChangeClock);
|
|
1656
|
+
const vector<double>& workDual = ekk_instance_.info_.workDual_;
|
|
1657
|
+
const vector<int8_t>& nonbasicMove = ekk_instance_.basis_.nonbasicMove_;
|
|
1658
|
+
HighsInt to_entry;
|
|
1659
|
+
const bool use_row_indices = ekk_instance_.simplex_nla_.sparseLoopStyle(
|
|
1660
|
+
row_basic_feasibility_change.count, num_col, to_entry);
|
|
1661
|
+
for (HighsInt iEntry = 0; iEntry < to_entry; iEntry++) {
|
|
1662
|
+
const HighsInt iCol =
|
|
1663
|
+
use_row_indices ? row_basic_feasibility_change.index[iEntry] : iEntry;
|
|
1664
|
+
double dual_infeasibility = -nonbasicMove[iCol] * workDual[iCol];
|
|
1665
|
+
if (dual_infeasibility > dual_feasibility_tolerance)
|
|
1666
|
+
hyperChooseColumnChangedInfeasibility(dual_infeasibility, iCol);
|
|
1667
|
+
}
|
|
1668
|
+
const bool use_col_indices = ekk_instance_.simplex_nla_.sparseLoopStyle(
|
|
1669
|
+
col_basic_feasibility_change.count, num_row, to_entry);
|
|
1670
|
+
for (HighsInt iEntry = 0; iEntry < to_entry; iEntry++) {
|
|
1671
|
+
const HighsInt iRow =
|
|
1672
|
+
use_col_indices ? col_basic_feasibility_change.index[iEntry] : iEntry;
|
|
1673
|
+
HighsInt iCol = num_col + iRow;
|
|
1674
|
+
double dual_infeasibility = -nonbasicMove[iCol] * workDual[iCol];
|
|
1675
|
+
if (dual_infeasibility > dual_feasibility_tolerance)
|
|
1676
|
+
hyperChooseColumnChangedInfeasibility(dual_infeasibility, iCol);
|
|
1677
|
+
}
|
|
1678
|
+
// Any nonbasic free columns will be handled explicitly in
|
|
1679
|
+
// hyperChooseColumnDualChange, so only look at them here if not
|
|
1680
|
+
// flipping
|
|
1681
|
+
const HighsInt& num_nonbasic_free_col = nonbasic_free_col_set.count();
|
|
1682
|
+
if (row_out < 0 && num_nonbasic_free_col) {
|
|
1683
|
+
const vector<HighsInt>& nonbasic_free_col_set_entry =
|
|
1684
|
+
nonbasic_free_col_set.entry();
|
|
1685
|
+
for (HighsInt iEntry = 0; iEntry < num_nonbasic_free_col; iEntry++) {
|
|
1686
|
+
HighsInt iCol = nonbasic_free_col_set_entry[iEntry];
|
|
1687
|
+
double dual_infeasibility = fabs(workDual[iCol]);
|
|
1688
|
+
if (dual_infeasibility > dual_feasibility_tolerance)
|
|
1689
|
+
hyperChooseColumnChangedInfeasibility(dual_infeasibility, iCol);
|
|
1690
|
+
}
|
|
1691
|
+
}
|
|
1692
|
+
analysis->simplexTimerStop(ChuzcHyperBasicFeasibilityChangeClock);
|
|
1693
|
+
}
|
|
1694
|
+
|
|
1695
|
+
void HEkkPrimal::hyperChooseColumnDualChange() {
|
|
1696
|
+
if (!use_hyper_chuzc) return;
|
|
1697
|
+
analysis->simplexTimerStart(ChuzcHyperDualClock);
|
|
1698
|
+
const vector<double>& workDual = ekk_instance_.info_.workDual_;
|
|
1699
|
+
const vector<int8_t>& nonbasicMove = ekk_instance_.basis_.nonbasicMove_;
|
|
1700
|
+
HighsInt to_entry;
|
|
1701
|
+
// Look at changes in the columns and assess any dual infeasibility
|
|
1702
|
+
const bool use_row_indices = ekk_instance_.simplex_nla_.sparseLoopStyle(
|
|
1703
|
+
row_ap.count, num_col, to_entry);
|
|
1704
|
+
for (HighsInt iEntry = 0; iEntry < to_entry; iEntry++) {
|
|
1705
|
+
const HighsInt iCol = use_row_indices ? row_ap.index[iEntry] : iEntry;
|
|
1706
|
+
double dual_infeasibility = -nonbasicMove[iCol] * workDual[iCol];
|
|
1707
|
+
if (iCol == check_column && ekk_instance_.iteration_count_ >= check_iter) {
|
|
1708
|
+
double measure =
|
|
1709
|
+
dual_infeasibility * dual_infeasibility / edge_weight_[iCol];
|
|
1710
|
+
if (report_hyper_chuzc) {
|
|
1711
|
+
printf("Changing column %" HIGHSINT_FORMAT ": measure = %g \n",
|
|
1712
|
+
check_column, measure);
|
|
1713
|
+
}
|
|
1714
|
+
}
|
|
1715
|
+
if (dual_infeasibility > dual_feasibility_tolerance)
|
|
1716
|
+
hyperChooseColumnChangedInfeasibility(dual_infeasibility, iCol);
|
|
1717
|
+
}
|
|
1718
|
+
// Look at changes in the rows and assess any dual infeasibility
|
|
1719
|
+
const bool use_col_indices = ekk_instance_.simplex_nla_.sparseLoopStyle(
|
|
1720
|
+
row_ep.count, num_row, to_entry);
|
|
1721
|
+
for (HighsInt iEntry = 0; iEntry < to_entry; iEntry++) {
|
|
1722
|
+
const HighsInt iRow = use_col_indices ? row_ep.index[iEntry] : iEntry;
|
|
1723
|
+
HighsInt iCol = iRow + num_col;
|
|
1724
|
+
double dual_infeasibility = -nonbasicMove[iCol] * workDual[iCol];
|
|
1725
|
+
if (iCol == check_column && ekk_instance_.iteration_count_ >= check_iter) {
|
|
1726
|
+
double measure =
|
|
1727
|
+
dual_infeasibility * dual_infeasibility / edge_weight_[iCol];
|
|
1728
|
+
if (report_hyper_chuzc) {
|
|
1729
|
+
printf("Changing column %" HIGHSINT_FORMAT ": measure = %g \n",
|
|
1730
|
+
check_column, measure);
|
|
1731
|
+
}
|
|
1732
|
+
}
|
|
1733
|
+
if (dual_infeasibility > dual_feasibility_tolerance)
|
|
1734
|
+
hyperChooseColumnChangedInfeasibility(dual_infeasibility, iCol);
|
|
1735
|
+
}
|
|
1736
|
+
// Look for measure changes in any nonbasic free columns and assess
|
|
1737
|
+
// any dual infeasibility
|
|
1738
|
+
const HighsInt& num_nonbasic_free_col = nonbasic_free_col_set.count();
|
|
1739
|
+
if (num_nonbasic_free_col) {
|
|
1740
|
+
const vector<HighsInt>& nonbasic_free_col_set_entry =
|
|
1741
|
+
nonbasic_free_col_set.entry();
|
|
1742
|
+
for (HighsInt iEntry = 0; iEntry < num_nonbasic_free_col; iEntry++) {
|
|
1743
|
+
HighsInt iCol = nonbasic_free_col_set_entry[iEntry];
|
|
1744
|
+
double dual_infeasibility = fabs(workDual[iCol]);
|
|
1745
|
+
if (dual_infeasibility > dual_feasibility_tolerance)
|
|
1746
|
+
hyperChooseColumnChangedInfeasibility(dual_infeasibility, iCol);
|
|
1747
|
+
}
|
|
1748
|
+
}
|
|
1749
|
+
// Assess any dual infeasibility for the leaving column - should be dual
|
|
1750
|
+
// feasible!
|
|
1751
|
+
HighsInt iCol = variable_out;
|
|
1752
|
+
double dual_infeasibility = -nonbasicMove[iCol] * workDual[iCol];
|
|
1753
|
+
if (dual_infeasibility > dual_feasibility_tolerance) {
|
|
1754
|
+
printf("Dual infeasibility %g for leaving column!\n", dual_infeasibility);
|
|
1755
|
+
assert(dual_infeasibility <= dual_feasibility_tolerance);
|
|
1756
|
+
hyperChooseColumnChangedInfeasibility(dual_infeasibility, iCol);
|
|
1757
|
+
}
|
|
1758
|
+
analysis->simplexTimerStop(ChuzcHyperDualClock);
|
|
1759
|
+
}
|
|
1760
|
+
|
|
1761
|
+
void HEkkPrimal::updateDual() {
|
|
1762
|
+
analysis->simplexTimerStart(UpdateDualClock);
|
|
1763
|
+
assert(alpha_col);
|
|
1764
|
+
assert(row_out >= 0);
|
|
1765
|
+
vector<double>& workDual = ekk_instance_.info_.workDual_;
|
|
1766
|
+
// const vector<HighsInt>& nonbasicMove =
|
|
1767
|
+
// ekk_instance_.basis_.nonbasicMove_;
|
|
1768
|
+
// Update the duals
|
|
1769
|
+
theta_dual = workDual[variable_in] / alpha_col;
|
|
1770
|
+
for (HighsInt iEl = 0; iEl < row_ap.count; iEl++) {
|
|
1771
|
+
HighsInt iCol = row_ap.index[iEl];
|
|
1772
|
+
workDual[iCol] -= theta_dual * row_ap.array[iCol];
|
|
1773
|
+
}
|
|
1774
|
+
for (HighsInt iEl = 0; iEl < row_ep.count; iEl++) {
|
|
1775
|
+
HighsInt iRow = row_ep.index[iEl];
|
|
1776
|
+
HighsInt iCol = iRow + num_col;
|
|
1777
|
+
workDual[iCol] -= theta_dual * row_ep.array[iRow];
|
|
1778
|
+
}
|
|
1779
|
+
// Dual for the pivot
|
|
1780
|
+
workDual[variable_in] = 0;
|
|
1781
|
+
workDual[variable_out] = -theta_dual;
|
|
1782
|
+
|
|
1783
|
+
ekk_instance_.invalidateDualInfeasibilityRecord();
|
|
1784
|
+
// After dual update in primal simplex the dual objective value is not known
|
|
1785
|
+
ekk_instance_.status_.has_dual_objective_value = false;
|
|
1786
|
+
analysis->simplexTimerStop(UpdateDualClock);
|
|
1787
|
+
}
|
|
1788
|
+
|
|
1789
|
+
void HEkkPrimal::phase1ComputeDual() {
|
|
1790
|
+
HighsSimplexInfo& info = ekk_instance_.info_;
|
|
1791
|
+
const vector<int8_t>& nonbasicFlag = ekk_instance_.basis_.nonbasicFlag_;
|
|
1792
|
+
|
|
1793
|
+
HVector buffer;
|
|
1794
|
+
buffer.setup(num_row);
|
|
1795
|
+
buffer.clear();
|
|
1796
|
+
buffer.count = 0;
|
|
1797
|
+
// Accumulate costs for checking
|
|
1798
|
+
info.workCost_.assign(num_tot, 0);
|
|
1799
|
+
// Zero the dual values
|
|
1800
|
+
info.workDual_.assign(num_tot, 0);
|
|
1801
|
+
// Determine the base value for cost perturbation
|
|
1802
|
+
const double base =
|
|
1803
|
+
info.primal_simplex_phase1_cost_perturbation_multiplier * 5e-7;
|
|
1804
|
+
for (HighsInt iRow = 0; iRow < num_row; iRow++) {
|
|
1805
|
+
const double value = info.baseValue_[iRow];
|
|
1806
|
+
const double lower = info.baseLower_[iRow];
|
|
1807
|
+
const double upper = info.baseUpper_[iRow];
|
|
1808
|
+
HighsInt bound_violated = 0;
|
|
1809
|
+
if (value < lower - primal_feasibility_tolerance) {
|
|
1810
|
+
bound_violated = -1;
|
|
1811
|
+
} else if (value > upper + primal_feasibility_tolerance) {
|
|
1812
|
+
bound_violated = 1;
|
|
1813
|
+
}
|
|
1814
|
+
if (!bound_violated) continue;
|
|
1815
|
+
double cost = bound_violated;
|
|
1816
|
+
if (base) cost *= 1 + base * info.numTotRandomValue_[iRow];
|
|
1817
|
+
buffer.array[iRow] = cost;
|
|
1818
|
+
buffer.index[buffer.count++] = iRow;
|
|
1819
|
+
}
|
|
1820
|
+
if (buffer.count <= 0) {
|
|
1821
|
+
// Strange, should be a non-trivial RHS
|
|
1822
|
+
assert(buffer.count > 0);
|
|
1823
|
+
return;
|
|
1824
|
+
}
|
|
1825
|
+
for (HighsInt iRow = 0; iRow < num_row; iRow++)
|
|
1826
|
+
info.workCost_[ekk_instance_.basis_.basicIndex_[iRow]] = buffer.array[iRow];
|
|
1827
|
+
//
|
|
1828
|
+
// Full BTRAN
|
|
1829
|
+
//
|
|
1830
|
+
ekk_instance_.fullBtran(buffer);
|
|
1831
|
+
//
|
|
1832
|
+
// Full PRICE
|
|
1833
|
+
//
|
|
1834
|
+
HVector bufferLong;
|
|
1835
|
+
bufferLong.setup(num_col);
|
|
1836
|
+
ekk_instance_.fullPrice(buffer, bufferLong);
|
|
1837
|
+
|
|
1838
|
+
for (HighsInt iCol = 0; iCol < num_col; iCol++)
|
|
1839
|
+
info.workDual_[iCol] = -nonbasicFlag[iCol] * bufferLong.array[iCol];
|
|
1840
|
+
for (HighsInt iRow = 0, iCol = num_col; iRow < num_row; iRow++, iCol++)
|
|
1841
|
+
info.workDual_[iCol] = -nonbasicFlag[iCol] * buffer.array[iRow];
|
|
1842
|
+
}
|
|
1843
|
+
|
|
1844
|
+
void HEkkPrimal::phase1UpdatePrimal() {
|
|
1845
|
+
analysis->simplexTimerStart(UpdatePrimalClock);
|
|
1846
|
+
HighsSimplexInfo& info = ekk_instance_.info_;
|
|
1847
|
+
col_basic_feasibility_change.clear();
|
|
1848
|
+
//
|
|
1849
|
+
// Update basic primal values, identifying all the feasibility
|
|
1850
|
+
// changes giving a value to col_basic_feasibility_change so that the duals
|
|
1851
|
+
// can be updated.
|
|
1852
|
+
//
|
|
1853
|
+
// Determine the base value for cost perturbation
|
|
1854
|
+
const double base =
|
|
1855
|
+
info.primal_simplex_phase1_cost_perturbation_multiplier * 5e-7;
|
|
1856
|
+
// if (ekk_instance_.sparseLoopStyle(col_aq.count, num_row, to_entry)) {
|
|
1857
|
+
for (HighsInt iEl = 0; iEl < col_aq.count; iEl++) {
|
|
1858
|
+
HighsInt iRow = col_aq.index[iEl];
|
|
1859
|
+
info.baseValue_[iRow] -= theta_primal * col_aq.array[iRow];
|
|
1860
|
+
HighsInt iCol = ekk_instance_.basis_.basicIndex_[iRow];
|
|
1861
|
+
double was_cost = info.workCost_[iCol];
|
|
1862
|
+
const double value = info.baseValue_[iRow];
|
|
1863
|
+
const double lower = info.baseLower_[iRow];
|
|
1864
|
+
const double upper = info.baseUpper_[iRow];
|
|
1865
|
+
HighsInt bound_violated = 0;
|
|
1866
|
+
if (value < lower - primal_feasibility_tolerance) {
|
|
1867
|
+
bound_violated = -1.0;
|
|
1868
|
+
} else if (value > upper + primal_feasibility_tolerance) {
|
|
1869
|
+
bound_violated = 1.0;
|
|
1870
|
+
}
|
|
1871
|
+
double cost = bound_violated;
|
|
1872
|
+
if (base) cost *= 1 + base * info.numTotRandomValue_[iRow];
|
|
1873
|
+
info.workCost_[iCol] = cost;
|
|
1874
|
+
if (was_cost) {
|
|
1875
|
+
if (!cost) info.num_primal_infeasibilities--;
|
|
1876
|
+
} else {
|
|
1877
|
+
if (cost) info.num_primal_infeasibilities++;
|
|
1878
|
+
}
|
|
1879
|
+
double delta_cost = cost - was_cost;
|
|
1880
|
+
if (delta_cost) {
|
|
1881
|
+
col_basic_feasibility_change.array[iRow] = delta_cost;
|
|
1882
|
+
col_basic_feasibility_change.index[col_basic_feasibility_change.count++] =
|
|
1883
|
+
iRow;
|
|
1884
|
+
if (iCol >= num_col) info.workDual_[iCol] += delta_cost;
|
|
1885
|
+
}
|
|
1886
|
+
}
|
|
1887
|
+
// Don't set baseValue[row_out] yet so that dual update due to
|
|
1888
|
+
// feasibility changes is done correctly
|
|
1889
|
+
ekk_instance_.invalidatePrimalMaxSumInfeasibilityRecord();
|
|
1890
|
+
analysis->simplexTimerStop(UpdatePrimalClock);
|
|
1891
|
+
}
|
|
1892
|
+
|
|
1893
|
+
void HEkkPrimal::considerInfeasibleValueIn() {
|
|
1894
|
+
assert(row_out >= 0);
|
|
1895
|
+
HighsSimplexInfo& info = ekk_instance_.info_;
|
|
1896
|
+
// Determine the base value for cost perturbation
|
|
1897
|
+
const double base =
|
|
1898
|
+
info.primal_simplex_phase1_cost_perturbation_multiplier * 5e-7;
|
|
1899
|
+
const double lower = info.workLower_[variable_in];
|
|
1900
|
+
const double upper = info.workUpper_[variable_in];
|
|
1901
|
+
HighsInt bound_violated = 0;
|
|
1902
|
+
if (value_in < lower - primal_feasibility_tolerance) {
|
|
1903
|
+
bound_violated = -1;
|
|
1904
|
+
} else if (value_in > upper + primal_feasibility_tolerance) {
|
|
1905
|
+
bound_violated = 1;
|
|
1906
|
+
}
|
|
1907
|
+
if (!bound_violated) return;
|
|
1908
|
+
// The primal value of the entering variable is not feasible
|
|
1909
|
+
if (solve_phase == kSolvePhase1) {
|
|
1910
|
+
info.num_primal_infeasibilities++;
|
|
1911
|
+
double cost = bound_violated;
|
|
1912
|
+
if (base) cost *= 1 + base * info.numTotRandomValue_[row_out];
|
|
1913
|
+
info.workCost_[variable_in] = cost;
|
|
1914
|
+
info.workDual_[variable_in] += cost;
|
|
1915
|
+
} else if (primal_correction_strategy ==
|
|
1916
|
+
kSimplexPrimalCorrectionStrategyNone) {
|
|
1917
|
+
// @primal_infeasibility calculation
|
|
1918
|
+
double primal_infeasibility;
|
|
1919
|
+
if (bound_violated < 0) {
|
|
1920
|
+
primal_infeasibility = lower - value_in;
|
|
1921
|
+
} else {
|
|
1922
|
+
primal_infeasibility = value_in - upper;
|
|
1923
|
+
}
|
|
1924
|
+
info.num_primal_infeasibilities++;
|
|
1925
|
+
highsLogDev(
|
|
1926
|
+
ekk_instance_.options_->log_options, HighsLogType::kWarning,
|
|
1927
|
+
"Entering variable has primal infeasibility of %g for [%g, %g, %g]\n",
|
|
1928
|
+
primal_infeasibility, lower, value_in, upper);
|
|
1929
|
+
rebuild_reason = kRebuildReasonPrimalInfeasibleInPrimalSimplex;
|
|
1930
|
+
} else {
|
|
1931
|
+
double bound_shift;
|
|
1932
|
+
if (bound_violated > 0) {
|
|
1933
|
+
// Perturb the upper bound to accommodate the infeasibility
|
|
1934
|
+
shiftBound(false, variable_in, value_in,
|
|
1935
|
+
info.numTotRandomValue_[variable_in],
|
|
1936
|
+
info.workUpper_[variable_in], bound_shift);
|
|
1937
|
+
info.workUpperShift_[variable_in] += bound_shift;
|
|
1938
|
+
} else {
|
|
1939
|
+
// Perturb the lower bound to accommodate the infeasibility
|
|
1940
|
+
shiftBound(true, variable_in, value_in,
|
|
1941
|
+
info.numTotRandomValue_[variable_in],
|
|
1942
|
+
info.workLower_[variable_in], bound_shift);
|
|
1943
|
+
info.workLowerShift_[variable_in] += bound_shift;
|
|
1944
|
+
}
|
|
1945
|
+
// Surely better to record this
|
|
1946
|
+
//
|
|
1947
|
+
// info.bounds_shifted = true;
|
|
1948
|
+
info.bounds_perturbed = true;
|
|
1949
|
+
}
|
|
1950
|
+
ekk_instance_.invalidatePrimalMaxSumInfeasibilityRecord();
|
|
1951
|
+
}
|
|
1952
|
+
|
|
1953
|
+
void HEkkPrimal::phase2UpdatePrimal(const bool initialise) {
|
|
1954
|
+
if (initialise) {
|
|
1955
|
+
max_max_local_primal_infeasibility_ = 0;
|
|
1956
|
+
max_max_ignored_violation_ = 0;
|
|
1957
|
+
return;
|
|
1958
|
+
}
|
|
1959
|
+
analysis->simplexTimerStart(UpdatePrimalClock);
|
|
1960
|
+
HighsSimplexInfo& info = ekk_instance_.info_;
|
|
1961
|
+
bool primal_infeasible = false;
|
|
1962
|
+
double max_local_primal_infeasibility = 0;
|
|
1963
|
+
double max_ignored_violation = 0;
|
|
1964
|
+
// If shifts are only identified in rebuild() the bounds can be
|
|
1965
|
+
// ignored. If they aren't ignored, then violations lead to either
|
|
1966
|
+
// identification of infeasibilities (and return to Phase 1) or
|
|
1967
|
+
// shifting of bounds to accommodate them.
|
|
1968
|
+
//
|
|
1969
|
+
// primal_correction_strategy is defined (const) as
|
|
1970
|
+
// kSimplexPrimalCorrectionStrategyAlways
|
|
1971
|
+
const bool ignore_bounds =
|
|
1972
|
+
primal_correction_strategy == kSimplexPrimalCorrectionStrategyInRebuild;
|
|
1973
|
+
assert(primal_correction_strategy == kSimplexPrimalCorrectionStrategyAlways);
|
|
1974
|
+
HighsInt to_entry;
|
|
1975
|
+
const bool use_col_indices = ekk_instance_.simplex_nla_.sparseLoopStyle(
|
|
1976
|
+
col_aq.count, num_row, to_entry);
|
|
1977
|
+
for (HighsInt iEntry = 0; iEntry < to_entry; iEntry++) {
|
|
1978
|
+
const HighsInt iRow = use_col_indices ? col_aq.index[iEntry] : iEntry;
|
|
1979
|
+
info.baseValue_[iRow] -= theta_primal * col_aq.array[iRow];
|
|
1980
|
+
// if (ignore_bounds) continue;
|
|
1981
|
+
// Determine whether a bound is violated and take action
|
|
1982
|
+
double lower = info.baseLower_[iRow];
|
|
1983
|
+
double upper = info.baseUpper_[iRow];
|
|
1984
|
+
double value = info.baseValue_[iRow];
|
|
1985
|
+
HighsInt bound_violated = 0;
|
|
1986
|
+
if (value < lower - primal_feasibility_tolerance) {
|
|
1987
|
+
bound_violated = -1;
|
|
1988
|
+
} else if (value > upper + primal_feasibility_tolerance) {
|
|
1989
|
+
bound_violated = 1;
|
|
1990
|
+
}
|
|
1991
|
+
if (!bound_violated) continue;
|
|
1992
|
+
// A bound is violated
|
|
1993
|
+
if (primal_correction_strategy == kSimplexPrimalCorrectionStrategyNone) {
|
|
1994
|
+
// Not used
|
|
1995
|
+
assert(111 == 222);
|
|
1996
|
+
// @primal_infeasibility calculation
|
|
1997
|
+
double primal_infeasibility;
|
|
1998
|
+
if (bound_violated < 0) {
|
|
1999
|
+
primal_infeasibility = lower - value;
|
|
2000
|
+
} else {
|
|
2001
|
+
primal_infeasibility = value - upper;
|
|
2002
|
+
}
|
|
2003
|
+
max_local_primal_infeasibility =
|
|
2004
|
+
max(primal_infeasibility, max_local_primal_infeasibility);
|
|
2005
|
+
if (primal_infeasibility > primal_feasibility_tolerance) {
|
|
2006
|
+
info.num_primal_infeasibilities++;
|
|
2007
|
+
primal_infeasible = true;
|
|
2008
|
+
}
|
|
2009
|
+
} else if (ignore_bounds) {
|
|
2010
|
+
// Not used
|
|
2011
|
+
assert(111 == 333);
|
|
2012
|
+
double ignored_violation;
|
|
2013
|
+
if (bound_violated < 0) {
|
|
2014
|
+
ignored_violation = lower - value;
|
|
2015
|
+
} else {
|
|
2016
|
+
ignored_violation = value - upper;
|
|
2017
|
+
}
|
|
2018
|
+
max_ignored_violation = max(ignored_violation, max_ignored_violation);
|
|
2019
|
+
} else {
|
|
2020
|
+
HighsInt iCol = ekk_instance_.basis_.basicIndex_[iRow];
|
|
2021
|
+
double bound_shift;
|
|
2022
|
+
if (bound_violated > 0) {
|
|
2023
|
+
// Perturb the upper bound to accommodate the infeasibility
|
|
2024
|
+
shiftBound(false, iCol, info.baseValue_[iRow],
|
|
2025
|
+
info.numTotRandomValue_[iCol], info.workUpper_[iCol],
|
|
2026
|
+
bound_shift);
|
|
2027
|
+
info.baseUpper_[iRow] = info.workUpper_[iCol];
|
|
2028
|
+
info.workUpperShift_[iCol] += bound_shift;
|
|
2029
|
+
} else {
|
|
2030
|
+
// Perturb the lower bound to accommodate the infeasibility
|
|
2031
|
+
shiftBound(true, iCol, info.baseValue_[iRow],
|
|
2032
|
+
info.numTotRandomValue_[iCol], info.workLower_[iCol],
|
|
2033
|
+
bound_shift);
|
|
2034
|
+
info.baseLower_[iRow] = info.workLower_[iCol];
|
|
2035
|
+
info.workLowerShift_[iCol] += bound_shift;
|
|
2036
|
+
}
|
|
2037
|
+
info.bounds_shifted = true;
|
|
2038
|
+
assert(bound_shift > 0);
|
|
2039
|
+
}
|
|
2040
|
+
}
|
|
2041
|
+
if (primal_infeasible) {
|
|
2042
|
+
rebuild_reason = kRebuildReasonPrimalInfeasibleInPrimalSimplex;
|
|
2043
|
+
if (max_local_primal_infeasibility >
|
|
2044
|
+
max_max_local_primal_infeasibility_ * 2) {
|
|
2045
|
+
max_max_local_primal_infeasibility_ = max_local_primal_infeasibility;
|
|
2046
|
+
printf("phase2UpdatePrimal: max_local_primal_infeasibility = %g\n",
|
|
2047
|
+
max_local_primal_infeasibility);
|
|
2048
|
+
}
|
|
2049
|
+
ekk_instance_.invalidatePrimalMaxSumInfeasibilityRecord();
|
|
2050
|
+
}
|
|
2051
|
+
if (max_ignored_violation > max_max_ignored_violation_ * 2) {
|
|
2052
|
+
max_max_ignored_violation_ = max_ignored_violation;
|
|
2053
|
+
printf("phase2UpdatePrimal: max_ignored_violation = %g\n",
|
|
2054
|
+
max_ignored_violation);
|
|
2055
|
+
}
|
|
2056
|
+
info.updated_primal_objective_value +=
|
|
2057
|
+
info.workDual_[variable_in] * theta_primal;
|
|
2058
|
+
|
|
2059
|
+
analysis->simplexTimerStop(UpdatePrimalClock);
|
|
2060
|
+
}
|
|
2061
|
+
|
|
2062
|
+
bool HEkkPrimal::correctPrimal(const bool initialise) {
|
|
2063
|
+
if (primal_correction_strategy == kSimplexPrimalCorrectionStrategyNone)
|
|
2064
|
+
return true;
|
|
2065
|
+
if (initialise) {
|
|
2066
|
+
max_max_primal_correction_ = 0;
|
|
2067
|
+
return true;
|
|
2068
|
+
}
|
|
2069
|
+
assert(solve_phase == kSolvePhase2);
|
|
2070
|
+
HighsSimplexInfo& info = ekk_instance_.info_;
|
|
2071
|
+
HighsInt num_primal_correction = 0;
|
|
2072
|
+
double max_primal_correction = 0;
|
|
2073
|
+
double sum_primal_correction = 0;
|
|
2074
|
+
HighsInt num_primal_correction_skipped = 0;
|
|
2075
|
+
for (HighsInt iRow = 0; iRow < num_row; iRow++) {
|
|
2076
|
+
double lower = info.baseLower_[iRow];
|
|
2077
|
+
double upper = info.baseUpper_[iRow];
|
|
2078
|
+
double value = info.baseValue_[iRow];
|
|
2079
|
+
HighsInt bound_violated = 0;
|
|
2080
|
+
if (value < lower - primal_feasibility_tolerance) {
|
|
2081
|
+
bound_violated = -1;
|
|
2082
|
+
} else if (value > upper + primal_feasibility_tolerance) {
|
|
2083
|
+
bound_violated = 1;
|
|
2084
|
+
}
|
|
2085
|
+
if (bound_violated) {
|
|
2086
|
+
if (info.allow_bound_perturbation) {
|
|
2087
|
+
HighsInt iCol = ekk_instance_.basis_.basicIndex_[iRow];
|
|
2088
|
+
double bound_shift;
|
|
2089
|
+
if (bound_violated > 0) {
|
|
2090
|
+
// Perturb the upper bound to accommodate the infeasibility
|
|
2091
|
+
shiftBound(false, iCol, info.baseValue_[iRow],
|
|
2092
|
+
info.numTotRandomValue_[iCol], info.workUpper_[iCol],
|
|
2093
|
+
bound_shift);
|
|
2094
|
+
info.baseUpper_[iRow] = info.workUpper_[iCol];
|
|
2095
|
+
info.workUpperShift_[iCol] += bound_shift;
|
|
2096
|
+
} else {
|
|
2097
|
+
// Perturb the lower bound to accommodate the infeasibility
|
|
2098
|
+
shiftBound(true, iCol, info.baseValue_[iRow],
|
|
2099
|
+
info.numTotRandomValue_[iCol], info.workLower_[iCol],
|
|
2100
|
+
bound_shift);
|
|
2101
|
+
info.baseLower_[iRow] = info.workLower_[iCol];
|
|
2102
|
+
info.workLowerShift_[iCol] += bound_shift;
|
|
2103
|
+
}
|
|
2104
|
+
assert(bound_shift > 0);
|
|
2105
|
+
num_primal_correction++;
|
|
2106
|
+
max_primal_correction = max(bound_shift, max_primal_correction);
|
|
2107
|
+
sum_primal_correction += bound_shift;
|
|
2108
|
+
// Surely better to record this
|
|
2109
|
+
//
|
|
2110
|
+
// info.bounds_shifted = true;
|
|
2111
|
+
info.bounds_perturbed = true;
|
|
2112
|
+
} else {
|
|
2113
|
+
// Bound perturbation is not permitted
|
|
2114
|
+
num_primal_correction_skipped++;
|
|
2115
|
+
}
|
|
2116
|
+
}
|
|
2117
|
+
}
|
|
2118
|
+
if (num_primal_correction_skipped) {
|
|
2119
|
+
highsLogDev(ekk_instance_.options_->log_options, HighsLogType::kError,
|
|
2120
|
+
"correctPrimal: Missed %d bound shifts\n",
|
|
2121
|
+
num_primal_correction_skipped);
|
|
2122
|
+
if (kAllowDeveloperAssert) {
|
|
2123
|
+
assert(!num_primal_correction_skipped);
|
|
2124
|
+
}
|
|
2125
|
+
return false;
|
|
2126
|
+
}
|
|
2127
|
+
if (max_primal_correction > 2 * max_max_primal_correction_) {
|
|
2128
|
+
highsLogDev(ekk_instance_.options_->log_options, HighsLogType::kInfo,
|
|
2129
|
+
"phase2CorrectPrimal: num / max / sum primal corrections = "
|
|
2130
|
+
"%" HIGHSINT_FORMAT
|
|
2131
|
+
" / %g / "
|
|
2132
|
+
"%g\n",
|
|
2133
|
+
num_primal_correction, max_primal_correction,
|
|
2134
|
+
sum_primal_correction);
|
|
2135
|
+
max_max_primal_correction_ = max_primal_correction;
|
|
2136
|
+
}
|
|
2137
|
+
return true;
|
|
2138
|
+
}
|
|
2139
|
+
|
|
2140
|
+
void HEkkPrimal::basicFeasibilityChangeUpdateDual() {
|
|
2141
|
+
analysis->simplexTimerStart(UpdateDualBasicFeasibilityChangeClock);
|
|
2142
|
+
HighsSimplexInfo& info = ekk_instance_.info_;
|
|
2143
|
+
// For basic logicals, the change in the basic cost will be a
|
|
2144
|
+
// component in col_basic_feasibility_change. This will lead to it being
|
|
2145
|
+
// subtracted from workDual in the loop below over the
|
|
2146
|
+
// nonzeros in col_basic_feasibility_change, so add it in now. For basic
|
|
2147
|
+
// structurals, there will be no corresponding component in
|
|
2148
|
+
// row_basic_feasibility_change, since only the nonbasic components are
|
|
2149
|
+
// computed (avoided using row pricing, and basic components
|
|
2150
|
+
// zeroed after column pricing). Hence there will be no
|
|
2151
|
+
// subtraction in the loop below over the nonzeros in
|
|
2152
|
+
// row_basic_feasibility_change. Hence, only add in the basic cost change
|
|
2153
|
+
// for logicals.
|
|
2154
|
+
//
|
|
2155
|
+
// Assumes that row_basic_feasibility_change has been set up in
|
|
2156
|
+
// phase1UpdatePrimal()
|
|
2157
|
+
|
|
2158
|
+
basicFeasibilityChangeBtran();
|
|
2159
|
+
basicFeasibilityChangePrice();
|
|
2160
|
+
HighsInt to_entry;
|
|
2161
|
+
const bool use_row_indices = ekk_instance_.simplex_nla_.sparseLoopStyle(
|
|
2162
|
+
row_basic_feasibility_change.count, num_col, to_entry);
|
|
2163
|
+
for (HighsInt iEntry = 0; iEntry < to_entry; iEntry++) {
|
|
2164
|
+
const HighsInt iCol =
|
|
2165
|
+
use_row_indices ? row_basic_feasibility_change.index[iEntry] : iEntry;
|
|
2166
|
+
info.workDual_[iCol] -= row_basic_feasibility_change.array[iCol];
|
|
2167
|
+
}
|
|
2168
|
+
const bool use_col_indices = ekk_instance_.simplex_nla_.sparseLoopStyle(
|
|
2169
|
+
col_basic_feasibility_change.count, num_row, to_entry);
|
|
2170
|
+
for (HighsInt iEntry = 0; iEntry < to_entry; iEntry++) {
|
|
2171
|
+
const HighsInt iRow =
|
|
2172
|
+
use_col_indices ? col_basic_feasibility_change.index[iEntry] : iEntry;
|
|
2173
|
+
HighsInt iCol = num_col + iRow;
|
|
2174
|
+
info.workDual_[iCol] -= col_basic_feasibility_change.array[iRow];
|
|
2175
|
+
}
|
|
2176
|
+
ekk_instance_.invalidateDualInfeasibilityRecord();
|
|
2177
|
+
analysis->simplexTimerStop(UpdateDualBasicFeasibilityChangeClock);
|
|
2178
|
+
}
|
|
2179
|
+
|
|
2180
|
+
void HEkkPrimal::basicFeasibilityChangeBtran() {
|
|
2181
|
+
// Performs BTRAN on col_basic_feasibility_change. Make sure that
|
|
2182
|
+
// col_basic_feasibility_change.count is large (>lp_.num_row_ to be
|
|
2183
|
+
// sure) rather than 0 if the indices of the RHS (and true value of
|
|
2184
|
+
// col_basic_feasibility_change.count) isn't known.
|
|
2185
|
+
analysis->simplexTimerStart(BtranBasicFeasibilityChangeClock);
|
|
2186
|
+
const HighsInt solver_num_row = ekk_instance_.lp_.num_row_;
|
|
2187
|
+
if (analysis->analyse_simplex_summary_data)
|
|
2188
|
+
analysis->operationRecordBefore(
|
|
2189
|
+
kSimplexNlaBtranBasicFeasibilityChange, col_basic_feasibility_change,
|
|
2190
|
+
ekk_instance_.info_.col_basic_feasibility_change_density);
|
|
2191
|
+
ekk_instance_.simplex_nla_.btran(
|
|
2192
|
+
col_basic_feasibility_change,
|
|
2193
|
+
ekk_instance_.info_.col_basic_feasibility_change_density,
|
|
2194
|
+
analysis->pointer_serial_factor_clocks);
|
|
2195
|
+
|
|
2196
|
+
if (analysis->analyse_simplex_summary_data)
|
|
2197
|
+
analysis->operationRecordAfter(kSimplexNlaBtranBasicFeasibilityChange,
|
|
2198
|
+
col_basic_feasibility_change);
|
|
2199
|
+
const double local_col_basic_feasibility_change_density =
|
|
2200
|
+
(double)col_basic_feasibility_change.count / solver_num_row;
|
|
2201
|
+
ekk_instance_.updateOperationResultDensity(
|
|
2202
|
+
local_col_basic_feasibility_change_density,
|
|
2203
|
+
ekk_instance_.info_.col_basic_feasibility_change_density);
|
|
2204
|
+
analysis->simplexTimerStop(BtranBasicFeasibilityChangeClock);
|
|
2205
|
+
}
|
|
2206
|
+
|
|
2207
|
+
void HEkkPrimal::basicFeasibilityChangePrice() {
|
|
2208
|
+
analysis->simplexTimerStart(PriceBasicFeasibilityChangeClock);
|
|
2209
|
+
const HighsSimplexInfo& info = ekk_instance_.info_;
|
|
2210
|
+
const double local_density =
|
|
2211
|
+
1.0 * col_basic_feasibility_change.count / num_row;
|
|
2212
|
+
bool use_col_price;
|
|
2213
|
+
bool use_row_price_w_switch;
|
|
2214
|
+
ekk_instance_.choosePriceTechnique(info.price_strategy, local_density,
|
|
2215
|
+
use_col_price, use_row_price_w_switch);
|
|
2216
|
+
if (analysis->analyse_simplex_summary_data) {
|
|
2217
|
+
if (use_col_price) {
|
|
2218
|
+
const double expected_density = 1;
|
|
2219
|
+
analysis->operationRecordBefore(kSimplexNlaPriceBasicFeasibilityChange,
|
|
2220
|
+
col_basic_feasibility_change,
|
|
2221
|
+
expected_density);
|
|
2222
|
+
analysis->num_col_price++;
|
|
2223
|
+
} else if (use_row_price_w_switch) {
|
|
2224
|
+
analysis->operationRecordBefore(
|
|
2225
|
+
kSimplexNlaPriceBasicFeasibilityChange, col_basic_feasibility_change,
|
|
2226
|
+
ekk_instance_.info_.col_basic_feasibility_change_density);
|
|
2227
|
+
analysis->num_row_price_with_switch++;
|
|
2228
|
+
} else {
|
|
2229
|
+
analysis->operationRecordBefore(
|
|
2230
|
+
kSimplexNlaPriceBasicFeasibilityChange, col_basic_feasibility_change,
|
|
2231
|
+
ekk_instance_.info_.col_basic_feasibility_change_density);
|
|
2232
|
+
analysis->num_row_price++;
|
|
2233
|
+
}
|
|
2234
|
+
}
|
|
2235
|
+
row_basic_feasibility_change.clear();
|
|
2236
|
+
const bool quad_precision = false;
|
|
2237
|
+
if (use_col_price) {
|
|
2238
|
+
// Perform column-wise PRICE
|
|
2239
|
+
ekk_instance_.lp_.a_matrix_.priceByColumn(quad_precision,
|
|
2240
|
+
row_basic_feasibility_change,
|
|
2241
|
+
col_basic_feasibility_change);
|
|
2242
|
+
} else if (use_row_price_w_switch) {
|
|
2243
|
+
// Perform hyper-sparse row-wise PRICE, but switch if the density of
|
|
2244
|
+
// row_basic_feasibility_change becomes extreme
|
|
2245
|
+
//
|
|
2246
|
+
const double switch_density = kHyperPriceDensity;
|
|
2247
|
+
ekk_instance_.ar_matrix_.priceByRowWithSwitch(
|
|
2248
|
+
quad_precision, row_basic_feasibility_change,
|
|
2249
|
+
col_basic_feasibility_change, info.row_basic_feasibility_change_density,
|
|
2250
|
+
0, switch_density);
|
|
2251
|
+
} else {
|
|
2252
|
+
// Perform hyper-sparse row-wise PRICE
|
|
2253
|
+
ekk_instance_.ar_matrix_.priceByRow(quad_precision,
|
|
2254
|
+
row_basic_feasibility_change,
|
|
2255
|
+
col_basic_feasibility_change);
|
|
2256
|
+
}
|
|
2257
|
+
if (use_col_price) {
|
|
2258
|
+
// Column-wise PRICE computes components corresponding to basic
|
|
2259
|
+
// variables, so zero these by exploiting the fact that, for basic
|
|
2260
|
+
// variables, nonbasicFlag[*]=0
|
|
2261
|
+
const std::vector<int8_t>& nonbasicFlag =
|
|
2262
|
+
ekk_instance_.basis_.nonbasicFlag_;
|
|
2263
|
+
for (HighsInt iCol = 0; iCol < num_col; iCol++)
|
|
2264
|
+
row_basic_feasibility_change.array[iCol] *= nonbasicFlag[iCol];
|
|
2265
|
+
}
|
|
2266
|
+
// Update the record of average row_basic_feasibility_change density
|
|
2267
|
+
const double local_row_basic_feasibility_change_density =
|
|
2268
|
+
(double)row_basic_feasibility_change.count / num_col;
|
|
2269
|
+
ekk_instance_.updateOperationResultDensity(
|
|
2270
|
+
local_row_basic_feasibility_change_density,
|
|
2271
|
+
ekk_instance_.info_.row_basic_feasibility_change_density);
|
|
2272
|
+
if (analysis->analyse_simplex_summary_data)
|
|
2273
|
+
analysis->operationRecordAfter(kSimplexNlaPriceBasicFeasibilityChange,
|
|
2274
|
+
row_basic_feasibility_change);
|
|
2275
|
+
analysis->simplexTimerStop(PriceBasicFeasibilityChangeClock);
|
|
2276
|
+
}
|
|
2277
|
+
|
|
2278
|
+
void HEkkPrimal::initialiseDevexFramework() {
|
|
2279
|
+
edge_weight_.assign(num_tot, 1.0);
|
|
2280
|
+
devex_index_.assign(num_tot, 0);
|
|
2281
|
+
for (HighsInt iCol = 0; iCol < num_tot; iCol++) {
|
|
2282
|
+
const HighsInt nonbasicFlag = ekk_instance_.basis_.nonbasicFlag_[iCol];
|
|
2283
|
+
devex_index_[iCol] = nonbasicFlag * nonbasicFlag;
|
|
2284
|
+
}
|
|
2285
|
+
num_devex_iterations_ = 0;
|
|
2286
|
+
num_bad_devex_weight_ = 0;
|
|
2287
|
+
if (report_hyper_chuzc) printf("initialiseDevexFramework\n");
|
|
2288
|
+
hyperChooseColumnClear();
|
|
2289
|
+
}
|
|
2290
|
+
|
|
2291
|
+
void HEkkPrimal::updateDevex() {
|
|
2292
|
+
analysis->simplexTimerStart(DevexUpdateWeightClock);
|
|
2293
|
+
// Compute the pivot weight from the reference set
|
|
2294
|
+
double dPivotWeight = 0.0;
|
|
2295
|
+
HighsInt to_entry;
|
|
2296
|
+
const bool use_col_indices = ekk_instance_.simplex_nla_.sparseLoopStyle(
|
|
2297
|
+
col_aq.count, num_row, to_entry);
|
|
2298
|
+
for (HighsInt iEntry = 0; iEntry < to_entry; iEntry++) {
|
|
2299
|
+
const HighsInt iRow = use_col_indices ? col_aq.index[iEntry] : iEntry;
|
|
2300
|
+
HighsInt iCol = ekk_instance_.basis_.basicIndex_[iRow];
|
|
2301
|
+
double dAlpha = devex_index_[iCol] * col_aq.array[iRow];
|
|
2302
|
+
dPivotWeight += dAlpha * dAlpha;
|
|
2303
|
+
}
|
|
2304
|
+
dPivotWeight += devex_index_[variable_in] * 1.0;
|
|
2305
|
+
|
|
2306
|
+
// Check if the saved weight is too large
|
|
2307
|
+
if (edge_weight_[variable_in] > kBadDevexWeightFactor * dPivotWeight)
|
|
2308
|
+
num_bad_devex_weight_++;
|
|
2309
|
+
|
|
2310
|
+
// Update the devex weight for all
|
|
2311
|
+
double dPivot = col_aq.array[row_out];
|
|
2312
|
+
dPivotWeight /= (dPivot * dPivot);
|
|
2313
|
+
|
|
2314
|
+
for (HighsInt iEl = 0; iEl < row_ap.count; iEl++) {
|
|
2315
|
+
HighsInt iCol = row_ap.index[iEl];
|
|
2316
|
+
double alpha = row_ap.array[iCol];
|
|
2317
|
+
double devex = dPivotWeight * alpha * alpha;
|
|
2318
|
+
devex += devex_index_[iCol] * 1.0;
|
|
2319
|
+
if (edge_weight_[iCol] < devex) {
|
|
2320
|
+
edge_weight_[iCol] = devex;
|
|
2321
|
+
}
|
|
2322
|
+
}
|
|
2323
|
+
for (HighsInt iEl = 0; iEl < row_ep.count; iEl++) {
|
|
2324
|
+
HighsInt iRow = row_ep.index[iEl];
|
|
2325
|
+
HighsInt iCol = iRow + num_col;
|
|
2326
|
+
double alpha = row_ep.array[iRow];
|
|
2327
|
+
double devex = dPivotWeight * alpha * alpha;
|
|
2328
|
+
devex += devex_index_[iCol] * 1.0;
|
|
2329
|
+
if (edge_weight_[iCol] < devex) {
|
|
2330
|
+
edge_weight_[iCol] = devex;
|
|
2331
|
+
}
|
|
2332
|
+
}
|
|
2333
|
+
// Update devex weight for the pivots
|
|
2334
|
+
edge_weight_[variable_out] = max(1.0, dPivotWeight);
|
|
2335
|
+
edge_weight_[variable_in] = 1.0;
|
|
2336
|
+
num_devex_iterations_++;
|
|
2337
|
+
analysis->simplexTimerStop(DevexUpdateWeightClock);
|
|
2338
|
+
}
|
|
2339
|
+
|
|
2340
|
+
void HEkkPrimal::computePrimalSteepestEdgeWeights() {
|
|
2341
|
+
const HighsInt report_var = -16;
|
|
2342
|
+
edge_weight_.resize(num_tot);
|
|
2343
|
+
if (ekk_instance_.logicalBasis()) {
|
|
2344
|
+
HighsSparseMatrix& a_matrix = ekk_instance_.lp_.a_matrix_;
|
|
2345
|
+
for (HighsInt iCol = 0; iCol < num_col; iCol++) {
|
|
2346
|
+
edge_weight_[iCol] = 1;
|
|
2347
|
+
for (HighsInt iEl = a_matrix.start_[iCol];
|
|
2348
|
+
iEl < a_matrix.start_[iCol + 1]; iEl++)
|
|
2349
|
+
edge_weight_[iCol] += a_matrix.value_[iEl] * a_matrix.value_[iEl];
|
|
2350
|
+
}
|
|
2351
|
+
} else {
|
|
2352
|
+
HVector local_col_aq;
|
|
2353
|
+
local_col_aq.setup(num_row);
|
|
2354
|
+
for (HighsInt iVar = 0; iVar < num_tot; iVar++) {
|
|
2355
|
+
if (ekk_instance_.basis_.nonbasicFlag_[iVar]) {
|
|
2356
|
+
edge_weight_[iVar] =
|
|
2357
|
+
computePrimalSteepestEdgeWeight(iVar, local_col_aq);
|
|
2358
|
+
if (iVar == report_var) {
|
|
2359
|
+
printf("Tableau column %d\nRow Value\n", (int)report_var);
|
|
2360
|
+
for (HighsInt iRow = 0; iRow < num_row; iRow++) {
|
|
2361
|
+
if (local_col_aq.array[iRow])
|
|
2362
|
+
printf("%3d %10.7g\n", (int)iRow, local_col_aq.array[iRow]);
|
|
2363
|
+
}
|
|
2364
|
+
}
|
|
2365
|
+
}
|
|
2366
|
+
}
|
|
2367
|
+
}
|
|
2368
|
+
}
|
|
2369
|
+
|
|
2370
|
+
double HEkkPrimal::computePrimalSteepestEdgeWeight(const HighsInt iVar,
|
|
2371
|
+
HVector& local_col_aq) {
|
|
2372
|
+
local_col_aq.clear();
|
|
2373
|
+
ekk_instance_.lp_.a_matrix_.collectAj(local_col_aq, iVar, 1);
|
|
2374
|
+
local_col_aq.packFlag = false;
|
|
2375
|
+
ekk_instance_.simplex_nla_.ftran(
|
|
2376
|
+
local_col_aq, ekk_instance_.info_.col_aq_density,
|
|
2377
|
+
ekk_instance_.analysis_.pointer_serial_factor_clocks);
|
|
2378
|
+
const double local_col_aq_density =
|
|
2379
|
+
(1.0 * local_col_aq.count) / ekk_instance_.lp_.num_row_;
|
|
2380
|
+
ekk_instance_.updateOperationResultDensity(
|
|
2381
|
+
local_col_aq_density, ekk_instance_.info_.col_aq_density);
|
|
2382
|
+
return 1 + local_col_aq.norm2();
|
|
2383
|
+
}
|
|
2384
|
+
|
|
2385
|
+
void HEkkPrimal::updatePrimalSteepestEdgeWeights() {
|
|
2386
|
+
// Compute, for all j
|
|
2387
|
+
//
|
|
2388
|
+
// lambda_j = hat{a}_{pj} / hat{a}_{pq}
|
|
2389
|
+
//
|
|
2390
|
+
// Then contribution to updated weight j is
|
|
2391
|
+
//
|
|
2392
|
+
// 1 + (hat{a}_j - lambda_j*hat{a}_q).(hat{a}_j - lambda_j*hat{a}_q)
|
|
2393
|
+
//
|
|
2394
|
+
// = 1 + hat{a}_j.hat{a}_j - 2*lambda_j*hat{a}_qB^{-1}a_j +
|
|
2395
|
+
// lambda_j^2*hat{a}_q.hat{a}_q
|
|
2396
|
+
//
|
|
2397
|
+
// = w_j - 2*lambda_j*(hat{a}_qB^{-1})a_j + lambda_j^2*||hat{a}_q||^2
|
|
2398
|
+
//
|
|
2399
|
+
// So need to compute mu = B^{-T}hat{a}_q
|
|
2400
|
+
//
|
|
2401
|
+
// Note that hat{a}_pj - lambda_j*hat{a}_pq is zero, but the updated
|
|
2402
|
+
// tableau entry is lambda_j, so have to add lambda_j*lambda_j
|
|
2403
|
+
HighsSparseMatrix& a_matrix = ekk_instance_.lp_.a_matrix_;
|
|
2404
|
+
col_steepest_edge.copy(&col_aq);
|
|
2405
|
+
updateBtranPSE(col_steepest_edge);
|
|
2406
|
+
const double col_aq_squared_2norm = col_aq.norm2();
|
|
2407
|
+
const bool report_col_aq = false;
|
|
2408
|
+
if (report_col_aq) {
|
|
2409
|
+
printf(
|
|
2410
|
+
"updatePrimalSteepestEdgeWeights: in = %d; out = %d; ||col_aq||^2 = "
|
|
2411
|
+
"%g\n",
|
|
2412
|
+
(int)variable_in, (int)variable_out, col_aq_squared_2norm);
|
|
2413
|
+
printf("Pivotal column %d\nRow Value\n", (int)variable_in);
|
|
2414
|
+
for (HighsInt iRow = 0; iRow < num_row; iRow++) {
|
|
2415
|
+
if (col_aq.array[iRow])
|
|
2416
|
+
printf("%3d %10.7g\n", (int)iRow, col_aq.array[iRow]);
|
|
2417
|
+
}
|
|
2418
|
+
}
|
|
2419
|
+
assert(ekk_instance_.basis_.nonbasicFlag_[variable_in]);
|
|
2420
|
+
HighsInt iVar;
|
|
2421
|
+
double pivotal_row_value;
|
|
2422
|
+
for (HighsInt iX = 0; iX < row_ap.count + row_ep.count; iX++) {
|
|
2423
|
+
if (iX < row_ap.count) {
|
|
2424
|
+
iVar = row_ap.index[iX];
|
|
2425
|
+
pivotal_row_value = row_ap.array[iVar];
|
|
2426
|
+
} else {
|
|
2427
|
+
HighsInt iRow = row_ep.index[iX - row_ap.count];
|
|
2428
|
+
iVar = num_col + iRow;
|
|
2429
|
+
pivotal_row_value = row_ep.array[iRow];
|
|
2430
|
+
}
|
|
2431
|
+
if (iVar == variable_in) continue;
|
|
2432
|
+
if (!ekk_instance_.basis_.nonbasicFlag_[iVar]) continue;
|
|
2433
|
+
const double lambda = pivotal_row_value / alpha_col;
|
|
2434
|
+
double mu_aj = 0;
|
|
2435
|
+
if (iVar < num_col) {
|
|
2436
|
+
for (HighsInt iEl = a_matrix.start_[iVar];
|
|
2437
|
+
iEl < a_matrix.start_[iVar + 1]; iEl++)
|
|
2438
|
+
mu_aj += col_steepest_edge.array[a_matrix.index_[iEl]] *
|
|
2439
|
+
a_matrix.value_[iEl];
|
|
2440
|
+
} else {
|
|
2441
|
+
mu_aj = col_steepest_edge.array[iVar - num_col];
|
|
2442
|
+
}
|
|
2443
|
+
const double min_weight = 1 + lambda * lambda;
|
|
2444
|
+
edge_weight_[iVar] +=
|
|
2445
|
+
(lambda * lambda * col_aq_squared_2norm - 2 * lambda * mu_aj);
|
|
2446
|
+
edge_weight_[iVar] += lambda * lambda;
|
|
2447
|
+
if (edge_weight_[iVar] < min_weight) {
|
|
2448
|
+
// printf("Augmenting weight(%2d)=%10.4g to %10.4g\n", (int)iVar,
|
|
2449
|
+
// edge_weight_[iVar], min_weight);
|
|
2450
|
+
edge_weight_[iVar] = min_weight;
|
|
2451
|
+
}
|
|
2452
|
+
}
|
|
2453
|
+
// The tableau column for the variable leaving the basis is the
|
|
2454
|
+
// pivotal column, divided through by the pivot, except for the
|
|
2455
|
+
// value in the pivotal location, which is 1/pivot
|
|
2456
|
+
//
|
|
2457
|
+
// We have col_aq_squared_2norm = s^2 + pivot^2, where s^2 is the
|
|
2458
|
+
// sum of squares of the non-pivotal entries
|
|
2459
|
+
//
|
|
2460
|
+
// The new weight is s^2/pivot^2 + 1/pivot^2 + 1
|
|
2461
|
+
//
|
|
2462
|
+
// = (s^2 + pivot^2)/pivot^2 + 1/pivot^2
|
|
2463
|
+
//
|
|
2464
|
+
// = col_aq_squared_2norm/pivot^2 + 1/pivot^2
|
|
2465
|
+
//
|
|
2466
|
+
// = (col_aq_squared_2norm + 1) / pivot^2
|
|
2467
|
+
edge_weight_[variable_out] =
|
|
2468
|
+
(1 + col_aq_squared_2norm) / (alpha_col * alpha_col);
|
|
2469
|
+
edge_weight_[variable_in] = 0;
|
|
2470
|
+
}
|
|
2471
|
+
|
|
2472
|
+
void HEkkPrimal::updateDualSteepestEdgeWeights() {
|
|
2473
|
+
col_steepest_edge.copy(&row_ep);
|
|
2474
|
+
updateFtranDSE(col_steepest_edge);
|
|
2475
|
+
std::vector<double>& edge_weight = ekk_instance_.dual_edge_weight_;
|
|
2476
|
+
// Compute the weight from row_ep and over-write the updated weight
|
|
2477
|
+
if (ekk_instance_.simplex_in_scaled_space_) {
|
|
2478
|
+
edge_weight[row_out] = row_ep.norm2();
|
|
2479
|
+
} else {
|
|
2480
|
+
edge_weight[row_out] =
|
|
2481
|
+
ekk_instance_.simplex_nla_.rowEp2NormInScaledSpace(row_out, row_ep);
|
|
2482
|
+
}
|
|
2483
|
+
const double pivot_in_scaled_space =
|
|
2484
|
+
ekk_instance_.simplex_nla_.pivotInScaledSpace(&col_aq, variable_in,
|
|
2485
|
+
row_out);
|
|
2486
|
+
if (ekk_instance_.simplex_in_scaled_space_)
|
|
2487
|
+
assert(pivot_in_scaled_space == alpha_col);
|
|
2488
|
+
const double new_pivotal_edge_weight =
|
|
2489
|
+
edge_weight[row_out] / (pivot_in_scaled_space * pivot_in_scaled_space);
|
|
2490
|
+
const double Kai = -2 / pivot_in_scaled_space;
|
|
2491
|
+
ekk_instance_.updateDualSteepestEdgeWeights(row_out, variable_in, &col_aq,
|
|
2492
|
+
new_pivotal_edge_weight, Kai,
|
|
2493
|
+
col_steepest_edge.array.data());
|
|
2494
|
+
edge_weight[row_out] = new_pivotal_edge_weight;
|
|
2495
|
+
}
|
|
2496
|
+
|
|
2497
|
+
void HEkkPrimal::updateFtranDSE(HVector& col_steepest_edge) {
|
|
2498
|
+
// For comments on scaling actions, see HEkkDual::updateFtranDSE
|
|
2499
|
+
analysis->simplexTimerStart(FtranDseClock);
|
|
2500
|
+
if (analysis->analyse_simplex_summary_data)
|
|
2501
|
+
analysis->operationRecordBefore(kSimplexNlaFtranDse, col_steepest_edge,
|
|
2502
|
+
ekk_instance_.info_.row_DSE_density);
|
|
2503
|
+
// Apply R{-1}
|
|
2504
|
+
ekk_instance_.simplex_nla_.unapplyBasisMatrixRowScale(col_steepest_edge);
|
|
2505
|
+
|
|
2506
|
+
// Perform FTRAN DSE
|
|
2507
|
+
ekk_instance_.simplex_nla_.ftranInScaledSpace(
|
|
2508
|
+
col_steepest_edge, ekk_instance_.info_.row_DSE_density,
|
|
2509
|
+
analysis->pointer_serial_factor_clocks);
|
|
2510
|
+
if (analysis->analyse_simplex_summary_data)
|
|
2511
|
+
analysis->operationRecordAfter(kSimplexNlaFtranDse, col_steepest_edge);
|
|
2512
|
+
analysis->simplexTimerStop(FtranDseClock);
|
|
2513
|
+
const double local_row_DSE_density =
|
|
2514
|
+
(1.0 * col_steepest_edge.count) / num_row;
|
|
2515
|
+
ekk_instance_.updateOperationResultDensity(
|
|
2516
|
+
local_row_DSE_density, ekk_instance_.info_.row_DSE_density);
|
|
2517
|
+
}
|
|
2518
|
+
|
|
2519
|
+
void HEkkPrimal::updateBtranPSE(HVector& col_steepest_edge) {
|
|
2520
|
+
analysis->simplexTimerStart(BtranPseClock);
|
|
2521
|
+
if (analysis->analyse_simplex_summary_data)
|
|
2522
|
+
analysis->operationRecordBefore(
|
|
2523
|
+
kSimplexNlaBtranPse, col_steepest_edge,
|
|
2524
|
+
ekk_instance_.info_.col_steepest_edge_density);
|
|
2525
|
+
// Perform BTRAN PSE
|
|
2526
|
+
ekk_instance_.simplex_nla_.btran(
|
|
2527
|
+
col_steepest_edge, ekk_instance_.info_.col_steepest_edge_density,
|
|
2528
|
+
analysis->pointer_serial_factor_clocks);
|
|
2529
|
+
if (analysis->analyse_simplex_summary_data)
|
|
2530
|
+
analysis->operationRecordAfter(kSimplexNlaBtranPse, col_steepest_edge);
|
|
2531
|
+
analysis->simplexTimerStop(BtranPseClock);
|
|
2532
|
+
const double local_col_steepest_edge_density =
|
|
2533
|
+
(1.0 * col_steepest_edge.count) / num_row;
|
|
2534
|
+
ekk_instance_.updateOperationResultDensity(
|
|
2535
|
+
local_col_steepest_edge_density,
|
|
2536
|
+
ekk_instance_.info_.col_steepest_edge_density);
|
|
2537
|
+
}
|
|
2538
|
+
|
|
2539
|
+
void HEkkPrimal::updateVerify() {
|
|
2540
|
+
// updateVerify for primal
|
|
2541
|
+
const HighsSimplexInfo& info = ekk_instance_.info_;
|
|
2542
|
+
const double numerical_trouble_tolerance = 1e-7;
|
|
2543
|
+
numericalTrouble = 0;
|
|
2544
|
+
double abs_alpha_from_col = fabs(alpha_col);
|
|
2545
|
+
std::string alpha_row_source;
|
|
2546
|
+
if (variable_in < num_col) {
|
|
2547
|
+
alpha_row = row_ap.array[variable_in];
|
|
2548
|
+
alpha_row_source = "Col";
|
|
2549
|
+
} else {
|
|
2550
|
+
alpha_row = row_ep.array[variable_in - num_col];
|
|
2551
|
+
alpha_row_source = "Row";
|
|
2552
|
+
}
|
|
2553
|
+
double abs_alpha_from_row = fabs(alpha_row);
|
|
2554
|
+
double abs_alpha_diff = fabs(abs_alpha_from_col - abs_alpha_from_row);
|
|
2555
|
+
double min_abs_alpha = min(abs_alpha_from_col, abs_alpha_from_row);
|
|
2556
|
+
numericalTrouble = abs_alpha_diff / min_abs_alpha;
|
|
2557
|
+
if (numericalTrouble > numerical_trouble_tolerance)
|
|
2558
|
+
highsLogDev(ekk_instance_.options_->log_options, HighsLogType::kInfo,
|
|
2559
|
+
"Numerical check: Iter %4" HIGHSINT_FORMAT
|
|
2560
|
+
": alpha_col = %12g, (From %3s alpha_row = "
|
|
2561
|
+
"%12g), aDiff = %12g: measure = %12g\n",
|
|
2562
|
+
ekk_instance_.iteration_count_, alpha_col,
|
|
2563
|
+
alpha_row_source.c_str(), alpha_row, abs_alpha_diff,
|
|
2564
|
+
numericalTrouble);
|
|
2565
|
+
if (kAllowDeveloperAssert) {
|
|
2566
|
+
assert(numericalTrouble < 1e-3);
|
|
2567
|
+
}
|
|
2568
|
+
// Reinvert if the relative difference is large enough, and updates have been
|
|
2569
|
+
// performed
|
|
2570
|
+
//
|
|
2571
|
+
if (numericalTrouble > 1e-7 && info.update_count > 0)
|
|
2572
|
+
rebuild_reason = kRebuildReasonPossiblySingularBasis;
|
|
2573
|
+
}
|
|
2574
|
+
|
|
2575
|
+
void HEkkPrimal::iterationAnalysisData() {
|
|
2576
|
+
// Possibly compute the infeasibility data
|
|
2577
|
+
if (analysis->analyse_simplex_runtime_data)
|
|
2578
|
+
ekk_instance_.computeInfeasibilitiesForReporting(SimplexAlgorithm::kPrimal);
|
|
2579
|
+
HighsSimplexInfo& info = ekk_instance_.info_;
|
|
2580
|
+
analysis->simplex_strategy = kSimplexStrategyPrimal;
|
|
2581
|
+
analysis->edge_weight_mode = edge_weight_mode;
|
|
2582
|
+
analysis->solve_phase = solve_phase;
|
|
2583
|
+
analysis->simplex_iteration_count = ekk_instance_.iteration_count_;
|
|
2584
|
+
analysis->devex_iteration_count = num_devex_iterations_;
|
|
2585
|
+
analysis->pivotal_row_index = row_out;
|
|
2586
|
+
analysis->leaving_variable = variable_out;
|
|
2587
|
+
analysis->entering_variable = variable_in;
|
|
2588
|
+
analysis->rebuild_reason = rebuild_reason;
|
|
2589
|
+
analysis->reduced_rhs_value = 0;
|
|
2590
|
+
analysis->reduced_cost_value = 0;
|
|
2591
|
+
analysis->edge_weight = 0;
|
|
2592
|
+
analysis->primal_delta = 0;
|
|
2593
|
+
analysis->primal_step = theta_primal;
|
|
2594
|
+
analysis->dual_step = theta_dual;
|
|
2595
|
+
analysis->pivot_value_from_column = alpha_col;
|
|
2596
|
+
analysis->pivot_value_from_row = alpha_row;
|
|
2597
|
+
analysis->numerical_trouble = numericalTrouble;
|
|
2598
|
+
analysis->edge_weight_error = ekk_instance_.edge_weight_error_;
|
|
2599
|
+
analysis->objective_value = info.updated_primal_objective_value;
|
|
2600
|
+
analysis->num_primal_infeasibility = info.num_primal_infeasibilities;
|
|
2601
|
+
analysis->num_dual_infeasibility = info.num_dual_infeasibilities;
|
|
2602
|
+
analysis->sum_primal_infeasibility = info.sum_primal_infeasibilities;
|
|
2603
|
+
analysis->sum_dual_infeasibility = info.sum_dual_infeasibilities;
|
|
2604
|
+
if ((edge_weight_mode == EdgeWeightMode::kDevex) &&
|
|
2605
|
+
(num_devex_iterations_ == 0))
|
|
2606
|
+
analysis->num_devex_framework++;
|
|
2607
|
+
analysis->col_aq_density = info.col_aq_density;
|
|
2608
|
+
analysis->row_ep_density = info.row_ep_density;
|
|
2609
|
+
analysis->row_ap_density = info.row_ap_density;
|
|
2610
|
+
analysis->row_DSE_density = info.row_DSE_density;
|
|
2611
|
+
analysis->col_steepest_edge_density = info.col_steepest_edge_density;
|
|
2612
|
+
analysis->col_basic_feasibility_change_density =
|
|
2613
|
+
info.col_basic_feasibility_change_density;
|
|
2614
|
+
analysis->row_basic_feasibility_change_density =
|
|
2615
|
+
info.row_basic_feasibility_change_density;
|
|
2616
|
+
analysis->col_BFRT_density = info.col_BFRT_density;
|
|
2617
|
+
analysis->primal_col_density = info.primal_col_density;
|
|
2618
|
+
analysis->dual_col_density = info.dual_col_density;
|
|
2619
|
+
analysis->num_costly_DSE_iteration = info.num_costly_DSE_iteration;
|
|
2620
|
+
analysis->costly_DSE_measure = info.costly_DSE_measure;
|
|
2621
|
+
}
|
|
2622
|
+
|
|
2623
|
+
void HEkkPrimal::iterationAnalysis() {
|
|
2624
|
+
iterationAnalysisData();
|
|
2625
|
+
analysis->iterationReport();
|
|
2626
|
+
if (analysis->analyse_simplex_summary_data) analysis->iterationRecord();
|
|
2627
|
+
}
|
|
2628
|
+
|
|
2629
|
+
void HEkkPrimal::localReportIterHeader() {
|
|
2630
|
+
printf(" Iter ColIn Row_Out ColOut\n");
|
|
2631
|
+
}
|
|
2632
|
+
|
|
2633
|
+
void HEkkPrimal::localReportIter(const bool header) {
|
|
2634
|
+
if (!report_hyper_chuzc) return;
|
|
2635
|
+
const HighsSimplexInfo& info = ekk_instance_.info_;
|
|
2636
|
+
HighsInt iteration_count = ekk_instance_.iteration_count_;
|
|
2637
|
+
if (header) {
|
|
2638
|
+
localReportIterHeader();
|
|
2639
|
+
last_header_iteration_count_ = iteration_count;
|
|
2640
|
+
} else {
|
|
2641
|
+
if (ekk_instance_.iteration_count_ > last_header_iteration_count_ + 10) {
|
|
2642
|
+
localReportIterHeader();
|
|
2643
|
+
last_header_iteration_count_ = iteration_count;
|
|
2644
|
+
}
|
|
2645
|
+
if (row_out >= 0) {
|
|
2646
|
+
printf("%5" HIGHSINT_FORMAT " %5" HIGHSINT_FORMAT " %5" HIGHSINT_FORMAT
|
|
2647
|
+
" %5" HIGHSINT_FORMAT "",
|
|
2648
|
+
iteration_count, variable_in, row_out, variable_out);
|
|
2649
|
+
} else {
|
|
2650
|
+
printf("%5" HIGHSINT_FORMAT " %5" HIGHSINT_FORMAT " Bound flip ",
|
|
2651
|
+
iteration_count, variable_in);
|
|
2652
|
+
}
|
|
2653
|
+
if (check_column >= 0 && iteration_count >= check_iter) {
|
|
2654
|
+
HighsInt flag = ekk_instance_.basis_.nonbasicFlag_[check_column];
|
|
2655
|
+
HighsInt move = ekk_instance_.basis_.nonbasicMove_[check_column];
|
|
2656
|
+
double lower = info.workLower_[check_column];
|
|
2657
|
+
double upper = info.workUpper_[check_column];
|
|
2658
|
+
double value;
|
|
2659
|
+
if (flag == kNonbasicFlagTrue) {
|
|
2660
|
+
value = info.workValue_[check_column];
|
|
2661
|
+
} else {
|
|
2662
|
+
HighsInt iRow;
|
|
2663
|
+
for (iRow = 0; iRow < num_row; iRow++) {
|
|
2664
|
+
if (ekk_instance_.basis_.basicIndex_[iRow] == check_column) break;
|
|
2665
|
+
}
|
|
2666
|
+
assert(iRow < num_row);
|
|
2667
|
+
value = info.baseValue_[iRow];
|
|
2668
|
+
}
|
|
2669
|
+
printf(": Var %2" HIGHSINT_FORMAT " (%1" HIGHSINT_FORMAT
|
|
2670
|
+
", %2" HIGHSINT_FORMAT ") [%9.4g, %9.4g, %9.4g]",
|
|
2671
|
+
check_column, flag, move, lower, value, upper);
|
|
2672
|
+
if (flag == kNonbasicFlagTrue) {
|
|
2673
|
+
double dual = info.workDual_[check_column];
|
|
2674
|
+
double weight = edge_weight_[check_column];
|
|
2675
|
+
double infeasibility = -move * dual;
|
|
2676
|
+
if (lower == -kHighsInf && upper == kHighsInf)
|
|
2677
|
+
infeasibility = fabs(dual);
|
|
2678
|
+
if (infeasibility < dual_feasibility_tolerance) infeasibility = 0;
|
|
2679
|
+
double measure = infeasibility * infeasibility / weight;
|
|
2680
|
+
printf(" Du = %9.4g; Wt = %9.4g; Ms = %9.4g", dual, weight, measure);
|
|
2681
|
+
}
|
|
2682
|
+
}
|
|
2683
|
+
printf("\n");
|
|
2684
|
+
}
|
|
2685
|
+
}
|
|
2686
|
+
|
|
2687
|
+
void HEkkPrimal::reportRebuild(const HighsInt reason_for_rebuild) {
|
|
2688
|
+
analysis->simplexTimerStart(ReportRebuildClock);
|
|
2689
|
+
iterationAnalysisData();
|
|
2690
|
+
analysis->rebuild_reason = reason_for_rebuild;
|
|
2691
|
+
analysis->rebuild_reason_string =
|
|
2692
|
+
ekk_instance_.rebuildReason(reason_for_rebuild);
|
|
2693
|
+
if (ekk_instance_.options_->output_flag) analysis->invertReport();
|
|
2694
|
+
analysis->simplexTimerStop(ReportRebuildClock);
|
|
2695
|
+
}
|
|
2696
|
+
|
|
2697
|
+
void HEkkPrimal::getNonbasicFreeColumnSet() {
|
|
2698
|
+
if (!num_free_col) return;
|
|
2699
|
+
assert(num_free_col > 0);
|
|
2700
|
+
const HighsSimplexInfo& info = ekk_instance_.info_;
|
|
2701
|
+
const SimplexBasis& basis = ekk_instance_.basis_;
|
|
2702
|
+
nonbasic_free_col_set.clear();
|
|
2703
|
+
for (HighsInt iCol = 0; iCol < num_tot; iCol++) {
|
|
2704
|
+
bool nonbasic_free = basis.nonbasicFlag_[iCol] == kNonbasicFlagTrue &&
|
|
2705
|
+
info.workLower_[iCol] <= -kHighsInf &&
|
|
2706
|
+
info.workUpper_[iCol] >= kHighsInf;
|
|
2707
|
+
if (nonbasic_free) nonbasic_free_col_set.add(iCol);
|
|
2708
|
+
}
|
|
2709
|
+
// nonbasic_free_col_set.print();
|
|
2710
|
+
}
|
|
2711
|
+
|
|
2712
|
+
void HEkkPrimal::removeNonbasicFreeColumn() {
|
|
2713
|
+
bool remove_nonbasic_free_column =
|
|
2714
|
+
ekk_instance_.basis_.nonbasicMove_[variable_in] == 0;
|
|
2715
|
+
if (remove_nonbasic_free_column) {
|
|
2716
|
+
bool removed_nonbasic_free_column =
|
|
2717
|
+
nonbasic_free_col_set.remove(variable_in);
|
|
2718
|
+
if (!removed_nonbasic_free_column) {
|
|
2719
|
+
highsLogDev(ekk_instance_.options_->log_options, HighsLogType::kError,
|
|
2720
|
+
"HEkkPrimal::phase1update failed to remove nonbasic free "
|
|
2721
|
+
"column %" HIGHSINT_FORMAT "\n",
|
|
2722
|
+
variable_in);
|
|
2723
|
+
assert(removed_nonbasic_free_column);
|
|
2724
|
+
}
|
|
2725
|
+
}
|
|
2726
|
+
}
|
|
2727
|
+
|
|
2728
|
+
void HEkkPrimal::adjustPerturbedEquationOut() {
|
|
2729
|
+
if (!ekk_instance_.info_.bounds_perturbed) return;
|
|
2730
|
+
const HighsLp& lp = ekk_instance_.lp_;
|
|
2731
|
+
HighsSimplexInfo& info = ekk_instance_.info_;
|
|
2732
|
+
double lp_lower;
|
|
2733
|
+
double lp_upper;
|
|
2734
|
+
if (variable_out < num_col) {
|
|
2735
|
+
lp_lower = lp.col_lower_[variable_out];
|
|
2736
|
+
lp_upper = lp.col_upper_[variable_out];
|
|
2737
|
+
} else {
|
|
2738
|
+
lp_lower = -lp.row_upper_[variable_out - num_col];
|
|
2739
|
+
lp_upper = -lp.row_lower_[variable_out - num_col];
|
|
2740
|
+
}
|
|
2741
|
+
if (lp_lower < lp_upper) return;
|
|
2742
|
+
// Leaving variable is fixed
|
|
2743
|
+
// double save_theta_primal = theta_primal;
|
|
2744
|
+
double true_fixed_value = lp_lower;
|
|
2745
|
+
// Modify theta_primal so that variable leaves at true fixed value
|
|
2746
|
+
theta_primal = (info.baseValue_[row_out] - true_fixed_value) / alpha_col;
|
|
2747
|
+
/*
|
|
2748
|
+
printf("For equation %4" HIGHSINT_FORMAT " to be nonbasic at RHS %10.4g
|
|
2749
|
+
requires theta_primal to change by %10.4g from %10.4g to %10.4g\n",
|
|
2750
|
+
variable_out, true_fixed_value, theta_primal-save_theta_primal,
|
|
2751
|
+
save_theta_primal, theta_primal);
|
|
2752
|
+
*/
|
|
2753
|
+
info.workLower_[variable_out] = true_fixed_value;
|
|
2754
|
+
info.workUpper_[variable_out] = true_fixed_value;
|
|
2755
|
+
info.workRange_[variable_out] = 0;
|
|
2756
|
+
value_in = info.workValue_[variable_in] + theta_primal;
|
|
2757
|
+
}
|
|
2758
|
+
|
|
2759
|
+
void HEkkPrimal::getBasicPrimalInfeasibility() {
|
|
2760
|
+
// Gets the num/max/sum of basic primal infeasibilities,
|
|
2761
|
+
analysis->simplexTimerStart(ComputePrIfsClock);
|
|
2762
|
+
const double primal_feasibility_tolerance =
|
|
2763
|
+
ekk_instance_.options_->primal_feasibility_tolerance;
|
|
2764
|
+
HighsSimplexInfo& info = ekk_instance_.info_;
|
|
2765
|
+
HighsInt& num_primal_infeasibility = info.num_primal_infeasibilities;
|
|
2766
|
+
double& max_primal_infeasibility = info.max_primal_infeasibility;
|
|
2767
|
+
double& sum_primal_infeasibility = info.sum_primal_infeasibilities;
|
|
2768
|
+
const HighsInt updated_num_primal_infeasibility = num_primal_infeasibility;
|
|
2769
|
+
num_primal_infeasibility = 0;
|
|
2770
|
+
max_primal_infeasibility = 0;
|
|
2771
|
+
sum_primal_infeasibility = 0;
|
|
2772
|
+
|
|
2773
|
+
for (HighsInt iRow = 0; iRow < num_row; iRow++) {
|
|
2774
|
+
double value = info.baseValue_[iRow];
|
|
2775
|
+
double lower = info.baseLower_[iRow];
|
|
2776
|
+
double upper = info.baseUpper_[iRow];
|
|
2777
|
+
// @primal_infeasibility calculation
|
|
2778
|
+
double primal_infeasibility = 0;
|
|
2779
|
+
if (value < lower - primal_feasibility_tolerance) {
|
|
2780
|
+
primal_infeasibility = lower - value;
|
|
2781
|
+
} else if (value > upper + primal_feasibility_tolerance) {
|
|
2782
|
+
primal_infeasibility = value - upper;
|
|
2783
|
+
}
|
|
2784
|
+
if (primal_infeasibility > 0) {
|
|
2785
|
+
if (primal_infeasibility > primal_feasibility_tolerance)
|
|
2786
|
+
num_primal_infeasibility++;
|
|
2787
|
+
max_primal_infeasibility =
|
|
2788
|
+
std::max(primal_infeasibility, max_primal_infeasibility);
|
|
2789
|
+
sum_primal_infeasibility += primal_infeasibility;
|
|
2790
|
+
}
|
|
2791
|
+
}
|
|
2792
|
+
if (updated_num_primal_infeasibility >= 0) {
|
|
2793
|
+
// The number of primal infeasibilities should be correct
|
|
2794
|
+
bool num_primal_infeasibility_ok =
|
|
2795
|
+
num_primal_infeasibility == updated_num_primal_infeasibility;
|
|
2796
|
+
// if (!num_primal_infeasibility_ok)
|
|
2797
|
+
// printf("In iteration %" HIGHSINT_FORMAT
|
|
2798
|
+
// ": num_primal_infeasibility = %" HIGHSINT_FORMAT
|
|
2799
|
+
// " != %" HIGHSINT_FORMAT
|
|
2800
|
+
// " = "
|
|
2801
|
+
// "updated_num_primal_infeasibility\n",
|
|
2802
|
+
// ekk_instance_.iteration_count_, num_primal_infeasibility,
|
|
2803
|
+
// updated_num_primal_infeasibility);
|
|
2804
|
+
|
|
2805
|
+
assert(num_primal_infeasibility_ok);
|
|
2806
|
+
}
|
|
2807
|
+
analysis->simplexTimerStop(ComputePrIfsClock);
|
|
2808
|
+
}
|
|
2809
|
+
|
|
2810
|
+
void HEkkPrimal::shiftBound(const bool lower, const HighsInt iVar,
|
|
2811
|
+
const double value, const double random_value,
|
|
2812
|
+
double& bound, double& shift) {
|
|
2813
|
+
// If infeasibility is very large, then adding feasibility may not
|
|
2814
|
+
// yield a new value (see #1144) so new_infeasibility < 0 is false,
|
|
2815
|
+
// tripping the old assert
|
|
2816
|
+
//
|
|
2817
|
+
// Ambros proposed adding feasibility
|
|
2818
|
+
// *(infeasibility/scale_threshold) when
|
|
2819
|
+
// infeasibility/scale_threshold > 1, but this could lead to a large
|
|
2820
|
+
// value for new_infeasibility. Sounds better to accept degeneracy
|
|
2821
|
+
// in this edge case.
|
|
2822
|
+
double feasibility = (1 + random_value) * primal_feasibility_tolerance;
|
|
2823
|
+
double old_bound = bound;
|
|
2824
|
+
std::string type;
|
|
2825
|
+
double infeasibility;
|
|
2826
|
+
double new_infeasibility;
|
|
2827
|
+
if (lower) {
|
|
2828
|
+
// Bound to shift is lower
|
|
2829
|
+
type = "lower";
|
|
2830
|
+
assert(value < bound - primal_feasibility_tolerance);
|
|
2831
|
+
infeasibility = bound - value;
|
|
2832
|
+
assert(infeasibility > 0);
|
|
2833
|
+
// Determine the amount by which value will be feasible - so that
|
|
2834
|
+
// (ideally) it's not degenerate
|
|
2835
|
+
shift = infeasibility + feasibility;
|
|
2836
|
+
bound -= shift;
|
|
2837
|
+
new_infeasibility = bound - value;
|
|
2838
|
+
} else {
|
|
2839
|
+
// Bound to shift is upper
|
|
2840
|
+
type = "upper";
|
|
2841
|
+
assert(value > bound + primal_feasibility_tolerance);
|
|
2842
|
+
infeasibility = value - bound;
|
|
2843
|
+
assert(infeasibility > 0);
|
|
2844
|
+
// Determine the amount by which value will be feasible - so that
|
|
2845
|
+
// (ideally) it's not degenerate
|
|
2846
|
+
shift = infeasibility + feasibility;
|
|
2847
|
+
bound += shift;
|
|
2848
|
+
new_infeasibility = value - bound;
|
|
2849
|
+
}
|
|
2850
|
+
if (new_infeasibility > 0) {
|
|
2851
|
+
// new_infeasibility should be non-positive, and negative unless
|
|
2852
|
+
// bound is excessively large, whereas feasibility is positive
|
|
2853
|
+
double error = std::fabs(new_infeasibility + feasibility);
|
|
2854
|
+
highsLogDev(ekk_instance_.options_->log_options, HighsLogType::kInfo,
|
|
2855
|
+
"HEkkPrimal::shiftBound Value(%4d) = %10.4g exceeds %s: "
|
|
2856
|
+
"random_value = %g; value = %g; "
|
|
2857
|
+
"feasibility = %g; infeasibility = %g; shift = %g; bound = %g; "
|
|
2858
|
+
"new_infeasibility = %g with error %g\n",
|
|
2859
|
+
int(iVar), value, type.c_str(), old_bound, random_value, value,
|
|
2860
|
+
feasibility, infeasibility, shift, bound, new_infeasibility,
|
|
2861
|
+
error);
|
|
2862
|
+
fflush(stdout);
|
|
2863
|
+
}
|
|
2864
|
+
assert(new_infeasibility <= 0);
|
|
2865
|
+
}
|
|
2866
|
+
|
|
2867
|
+
void HEkkPrimal::savePrimalRay() {
|
|
2868
|
+
assert(variable_in >= 0);
|
|
2869
|
+
assert(move_in != kNoRaySign);
|
|
2870
|
+
ekk_instance_.primal_ray_record_.clear();
|
|
2871
|
+
ekk_instance_.primal_ray_record_.index = variable_in;
|
|
2872
|
+
ekk_instance_.primal_ray_record_.sign = -move_in;
|
|
2873
|
+
}
|
|
2874
|
+
|
|
2875
|
+
HighsDebugStatus HEkkPrimal::debugPrimalSimplex(const std::string message,
|
|
2876
|
+
const bool initialise) {
|
|
2877
|
+
HighsDebugStatus return_status =
|
|
2878
|
+
ekk_instance_.debugSimplex(message, algorithm, solve_phase, initialise);
|
|
2879
|
+
if (return_status == HighsDebugStatus::kLogicalError) return return_status;
|
|
2880
|
+
if (initialise) return return_status;
|
|
2881
|
+
return_status = ekk_instance_.debugNonbasicFreeColumnSet(
|
|
2882
|
+
num_free_col, nonbasic_free_col_set);
|
|
2883
|
+
if (return_status == HighsDebugStatus::kLogicalError) return return_status;
|
|
2884
|
+
return HighsDebugStatus::kOk;
|
|
2885
|
+
}
|
|
2886
|
+
|
|
2887
|
+
HighsDebugStatus HEkkPrimal::debugPrimalSteepestEdgeWeights(
|
|
2888
|
+
const std::string message) {
|
|
2889
|
+
// Possibly force the expensive check for development work
|
|
2890
|
+
const bool check_primal_edge_weights = true;
|
|
2891
|
+
if (check_primal_edge_weights) {
|
|
2892
|
+
const bool check_all_primal_edge_weights = false;
|
|
2893
|
+
const HighsInt alt_debug_level = check_all_primal_edge_weights
|
|
2894
|
+
? (HighsInt)kHighsDebugLevelExpensive
|
|
2895
|
+
: (HighsInt)kHighsDebugLevelCostly;
|
|
2896
|
+
// printf("\nPerforming level %1d check %s for primal steepest edge
|
|
2897
|
+
// weights\n", (int)alt_debug_level, message.c_str());
|
|
2898
|
+
return debugPrimalSteepestEdgeWeights(alt_debug_level);
|
|
2899
|
+
} else {
|
|
2900
|
+
return debugPrimalSteepestEdgeWeights();
|
|
2901
|
+
}
|
|
2902
|
+
}
|
|
2903
|
+
|
|
2904
|
+
HighsDebugStatus HEkkPrimal::debugPrimalSteepestEdgeWeights(
|
|
2905
|
+
const HighsInt alt_debug_level) {
|
|
2906
|
+
const HighsInt use_debug_level =
|
|
2907
|
+
alt_debug_level >= 0 ? alt_debug_level
|
|
2908
|
+
: ekk_instance_.options_->highs_debug_level;
|
|
2909
|
+
if (use_debug_level < kHighsDebugLevelCostly)
|
|
2910
|
+
return HighsDebugStatus::kNotChecked;
|
|
2911
|
+
const HighsLp& lp = ekk_instance_.lp_;
|
|
2912
|
+
const HighsInt num_row = lp.num_row_;
|
|
2913
|
+
const std::vector<int8_t> nonbasic_flag = ekk_instance_.basis_.nonbasicFlag_;
|
|
2914
|
+
double primal_steepest_edge_weight_norm = 0;
|
|
2915
|
+
double primal_steepest_edge_weight_error = 0;
|
|
2916
|
+
HighsInt num_check_weight;
|
|
2917
|
+
HVector local_col_aq;
|
|
2918
|
+
local_col_aq.setup(num_row);
|
|
2919
|
+
if (use_debug_level < kHighsDebugLevelExpensive) {
|
|
2920
|
+
for (HighsInt iVar = 0; iVar < num_tot; iVar++) {
|
|
2921
|
+
primal_steepest_edge_weight_norm +=
|
|
2922
|
+
std::fabs(nonbasic_flag[iVar] * edge_weight_[iVar]);
|
|
2923
|
+
}
|
|
2924
|
+
// Just check a few weights
|
|
2925
|
+
num_check_weight =
|
|
2926
|
+
std::max((HighsInt)1, std::min((HighsInt)10, num_tot / 10));
|
|
2927
|
+
for (HighsInt iCheck = 0; iCheck < num_check_weight; iCheck++) {
|
|
2928
|
+
HighsInt iVar;
|
|
2929
|
+
for (;;) {
|
|
2930
|
+
iVar = random_.integer(num_tot);
|
|
2931
|
+
if (nonbasic_flag[iVar]) break;
|
|
2932
|
+
}
|
|
2933
|
+
const double true_weight =
|
|
2934
|
+
computePrimalSteepestEdgeWeight(iVar, local_col_aq);
|
|
2935
|
+
primal_steepest_edge_weight_error +=
|
|
2936
|
+
std::fabs(edge_weight_[iVar] - true_weight);
|
|
2937
|
+
}
|
|
2938
|
+
} else {
|
|
2939
|
+
// Check all weights
|
|
2940
|
+
num_check_weight = num_col;
|
|
2941
|
+
std::vector<double> updated_primal_edge_weight = edge_weight_;
|
|
2942
|
+
computePrimalSteepestEdgeWeights();
|
|
2943
|
+
for (HighsInt iVar = 0; iVar < num_tot; iVar++) {
|
|
2944
|
+
if (!nonbasic_flag[iVar]) continue;
|
|
2945
|
+
primal_steepest_edge_weight_norm += std::fabs(edge_weight_[iVar]);
|
|
2946
|
+
const double error =
|
|
2947
|
+
std::fabs(updated_primal_edge_weight[iVar] - edge_weight_[iVar]);
|
|
2948
|
+
if (error > 1e-4)
|
|
2949
|
+
printf(
|
|
2950
|
+
"debugPrimalSteepestEdgeWeights: var = %2d; weight (true = %10.4g; "
|
|
2951
|
+
"updated = %10.4g) error = %10.4g\n",
|
|
2952
|
+
(int)iVar, edge_weight_[iVar], updated_primal_edge_weight[iVar],
|
|
2953
|
+
error);
|
|
2954
|
+
primal_steepest_edge_weight_error += error;
|
|
2955
|
+
}
|
|
2956
|
+
edge_weight_ = updated_primal_edge_weight;
|
|
2957
|
+
}
|
|
2958
|
+
// Now assess the relative error
|
|
2959
|
+
assert(primal_steepest_edge_weight_norm > 0);
|
|
2960
|
+
double relative_primal_steepest_edge_weight_error =
|
|
2961
|
+
primal_steepest_edge_weight_error / primal_steepest_edge_weight_norm;
|
|
2962
|
+
const double large_relative_primal_steepest_edge_weight_error = 1e-3;
|
|
2963
|
+
if (relative_primal_steepest_edge_weight_error >
|
|
2964
|
+
10 * debug_max_relative_primal_steepest_edge_weight_error) {
|
|
2965
|
+
printf(
|
|
2966
|
+
"HEkk::debugPrimalSteepestEdgeWeights Iteration %5d: Checked %2d "
|
|
2967
|
+
"weights: "
|
|
2968
|
+
"error = %10.4g; norm = %10.4g; relative error = %10.4g\n",
|
|
2969
|
+
(int)ekk_instance_.iteration_count_, (int)num_check_weight,
|
|
2970
|
+
primal_steepest_edge_weight_error, primal_steepest_edge_weight_norm,
|
|
2971
|
+
relative_primal_steepest_edge_weight_error);
|
|
2972
|
+
debug_max_relative_primal_steepest_edge_weight_error =
|
|
2973
|
+
relative_primal_steepest_edge_weight_error;
|
|
2974
|
+
if (relative_primal_steepest_edge_weight_error >
|
|
2975
|
+
large_relative_primal_steepest_edge_weight_error)
|
|
2976
|
+
return HighsDebugStatus::kLargeError;
|
|
2977
|
+
}
|
|
2978
|
+
return HighsDebugStatus::kOk;
|
|
2979
|
+
}
|
|
2980
|
+
|
|
2981
|
+
bool HEkkPrimal::isBadBasisChange() {
|
|
2982
|
+
return ekk_instance_.isBadBasisChange(SimplexAlgorithm::kPrimal, variable_in,
|
|
2983
|
+
row_out, rebuild_reason);
|
|
2984
|
+
}
|