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.
Files changed (1165) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -0
  3. data/README.md +104 -26
  4. data/ext/lpsolver/Makefile +269 -0
  5. data/ext/lpsolver/ext.c +353 -0
  6. data/ext/lpsolver/ext.o +0 -0
  7. data/ext/lpsolver/extconf.rb +79 -0
  8. data/ext/lpsolver/native.so +0 -0
  9. data/ext/lpsolver-highs/AUTHORS +7 -0
  10. data/ext/lpsolver-highs/BUILD.bazel +243 -0
  11. data/ext/lpsolver-highs/CITATION.cff +29 -0
  12. data/ext/lpsolver-highs/CMakeCache.txt +406 -0
  13. data/ext/lpsolver-highs/CMakeFiles/3.31.4/CMakeCCompiler.cmake +81 -0
  14. data/ext/lpsolver-highs/CMakeFiles/3.31.4/CMakeCXXCompiler.cmake +101 -0
  15. data/ext/lpsolver-highs/CMakeFiles/3.31.4/CMakeDetermineCompilerABI_C.bin +0 -0
  16. data/ext/lpsolver-highs/CMakeFiles/3.31.4/CMakeDetermineCompilerABI_CXX.bin +0 -0
  17. data/ext/lpsolver-highs/CMakeFiles/3.31.4/CMakeSystem.cmake +15 -0
  18. data/ext/lpsolver-highs/CMakeFiles/3.31.4/CompilerIdC/CMakeCCompilerId.c +904 -0
  19. data/ext/lpsolver-highs/CMakeFiles/3.31.4/CompilerIdC/a.out +0 -0
  20. data/ext/lpsolver-highs/CMakeFiles/3.31.4/CompilerIdCXX/CMakeCXXCompilerId.cpp +919 -0
  21. data/ext/lpsolver-highs/CMakeFiles/3.31.4/CompilerIdCXX/a.out +0 -0
  22. data/ext/lpsolver-highs/CMakeFiles/CMakeConfigureLog.yaml +576 -0
  23. data/ext/lpsolver-highs/CMakeFiles/cmake.check_cache +1 -0
  24. data/ext/lpsolver-highs/CMakeLists.txt +983 -0
  25. data/ext/lpsolver-highs/CODE_OF_CONDUCT.md +128 -0
  26. data/ext/lpsolver-highs/CONTRIBUTING.md +31 -0
  27. data/ext/lpsolver-highs/FEATURES.md +61 -0
  28. data/ext/lpsolver-highs/LICENSE.txt +21 -0
  29. data/ext/lpsolver-highs/MODULE.bazel +38 -0
  30. data/ext/lpsolver-highs/README.md +281 -0
  31. data/ext/lpsolver-highs/THIRD_PARTY_NOTICES.md +78 -0
  32. data/ext/lpsolver-highs/Version.txt +4 -0
  33. data/ext/lpsolver-highs/WORKSPACE +33 -0
  34. data/ext/lpsolver-highs/app/CMakeLists.txt +110 -0
  35. data/ext/lpsolver-highs/app/HighsRuntimeOptions.h +292 -0
  36. data/ext/lpsolver-highs/app/RunHighs.cpp +147 -0
  37. data/ext/lpsolver-highs/app/highs_webdemo_shell.html +73 -0
  38. data/ext/lpsolver-highs/build/bin/highs +0 -0
  39. data/ext/lpsolver-highs/build/include/highs/HConfig.h +22 -0
  40. data/ext/lpsolver-highs/build/include/highs/Highs.h +1812 -0
  41. data/ext/lpsolver-highs/build/include/highs/interfaces/highs_c_api.h +2651 -0
  42. data/ext/lpsolver-highs/build/include/highs/io/Filereader.h +45 -0
  43. data/ext/lpsolver-highs/build/include/highs/io/FilereaderLp.h +49 -0
  44. data/ext/lpsolver-highs/build/include/highs/io/FilereaderMps.h +27 -0
  45. data/ext/lpsolver-highs/build/include/highs/io/HMPSIO.h +78 -0
  46. data/ext/lpsolver-highs/build/include/highs/io/HMpsFF.h +245 -0
  47. data/ext/lpsolver-highs/build/include/highs/io/HighsIO.h +118 -0
  48. data/ext/lpsolver-highs/build/include/highs/io/LoadOptions.h +24 -0
  49. data/ext/lpsolver-highs/build/include/highs/io/filereaderlp/builder.hpp +25 -0
  50. data/ext/lpsolver-highs/build/include/highs/io/filereaderlp/def.hpp +19 -0
  51. data/ext/lpsolver-highs/build/include/highs/io/filereaderlp/model.hpp +68 -0
  52. data/ext/lpsolver-highs/build/include/highs/io/filereaderlp/reader.hpp +10 -0
  53. data/ext/lpsolver-highs/build/include/highs/ipm/IpxSolution.h +32 -0
  54. data/ext/lpsolver-highs/build/include/highs/ipm/IpxWrapper.h +106 -0
  55. data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/basiclu.h +161 -0
  56. data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/basiclu_factorize.h +247 -0
  57. data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/basiclu_get_factors.h +108 -0
  58. data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/basiclu_initialize.h +119 -0
  59. data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/basiclu_obj_factorize.h +34 -0
  60. data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/basiclu_obj_free.h +19 -0
  61. data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/basiclu_obj_get_factors.h +34 -0
  62. data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/basiclu_obj_initialize.h +46 -0
  63. data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/basiclu_obj_solve_dense.h +29 -0
  64. data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/basiclu_obj_solve_for_update.h +42 -0
  65. data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/basiclu_obj_solve_sparse.h +32 -0
  66. data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/basiclu_obj_update.h +31 -0
  67. data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/basiclu_object.h +30 -0
  68. data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/basiclu_solve_dense.h +75 -0
  69. data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/basiclu_solve_for_update.h +169 -0
  70. data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/basiclu_solve_sparse.h +112 -0
  71. data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/basiclu_update.h +125 -0
  72. data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/lu_def.h +39 -0
  73. data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/lu_file.h +21 -0
  74. data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/lu_internal.h +220 -0
  75. data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/lu_list.h +173 -0
  76. data/ext/lpsolver-highs/build/include/highs/ipm/ipx/basiclu_kernel.h +20 -0
  77. data/ext/lpsolver-highs/build/include/highs/ipm/ipx/basiclu_wrapper.h +47 -0
  78. data/ext/lpsolver-highs/build/include/highs/ipm/ipx/basis.h +350 -0
  79. data/ext/lpsolver-highs/build/include/highs/ipm/ipx/conjugate_residuals.h +74 -0
  80. data/ext/lpsolver-highs/build/include/highs/ipm/ipx/control.h +167 -0
  81. data/ext/lpsolver-highs/build/include/highs/ipm/ipx/crossover.h +157 -0
  82. data/ext/lpsolver-highs/build/include/highs/ipm/ipx/diagonal_precond.h +45 -0
  83. data/ext/lpsolver-highs/build/include/highs/ipm/ipx/forrest_tomlin.h +102 -0
  84. data/ext/lpsolver-highs/build/include/highs/ipm/ipx/guess_basis.h +21 -0
  85. data/ext/lpsolver-highs/build/include/highs/ipm/ipx/indexed_vector.h +113 -0
  86. data/ext/lpsolver-highs/build/include/highs/ipm/ipx/info.h +27 -0
  87. data/ext/lpsolver-highs/build/include/highs/ipm/ipx/ipm.h +94 -0
  88. data/ext/lpsolver-highs/build/include/highs/ipm/ipx/ipx_c.h +47 -0
  89. data/ext/lpsolver-highs/build/include/highs/ipm/ipx/ipx_config.h +9 -0
  90. data/ext/lpsolver-highs/build/include/highs/ipm/ipx/ipx_info.h +111 -0
  91. data/ext/lpsolver-highs/build/include/highs/ipm/ipx/ipx_internal.h +89 -0
  92. data/ext/lpsolver-highs/build/include/highs/ipm/ipx/ipx_parameters.h +76 -0
  93. data/ext/lpsolver-highs/build/include/highs/ipm/ipx/ipx_status.h +57 -0
  94. data/ext/lpsolver-highs/build/include/highs/ipm/ipx/iterate.h +331 -0
  95. data/ext/lpsolver-highs/build/include/highs/ipm/ipx/kkt_solver.h +70 -0
  96. data/ext/lpsolver-highs/build/include/highs/ipm/ipx/kkt_solver_basis.h +66 -0
  97. data/ext/lpsolver-highs/build/include/highs/ipm/ipx/kkt_solver_diag.h +48 -0
  98. data/ext/lpsolver-highs/build/include/highs/ipm/ipx/linear_operator.h +26 -0
  99. data/ext/lpsolver-highs/build/include/highs/ipm/ipx/lp_solver.h +204 -0
  100. data/ext/lpsolver-highs/build/include/highs/ipm/ipx/lu_factorization.h +79 -0
  101. data/ext/lpsolver-highs/build/include/highs/ipm/ipx/lu_update.h +129 -0
  102. data/ext/lpsolver-highs/build/include/highs/ipm/ipx/maxvolume.h +54 -0
  103. data/ext/lpsolver-highs/build/include/highs/ipm/ipx/model.h +413 -0
  104. data/ext/lpsolver-highs/build/include/highs/ipm/ipx/multistream.h +52 -0
  105. data/ext/lpsolver-highs/build/include/highs/ipm/ipx/normal_matrix.h +44 -0
  106. data/ext/lpsolver-highs/build/include/highs/ipm/ipx/power_method.h +44 -0
  107. data/ext/lpsolver-highs/build/include/highs/ipm/ipx/sparse_matrix.h +195 -0
  108. data/ext/lpsolver-highs/build/include/highs/ipm/ipx/sparse_utils.h +58 -0
  109. data/ext/lpsolver-highs/build/include/highs/ipm/ipx/splitted_normal_matrix.h +63 -0
  110. data/ext/lpsolver-highs/build/include/highs/ipm/ipx/starting_basis.h +39 -0
  111. data/ext/lpsolver-highs/build/include/highs/ipm/ipx/symbolic_invert.h +29 -0
  112. data/ext/lpsolver-highs/build/include/highs/ipm/ipx/timer.h +25 -0
  113. data/ext/lpsolver-highs/build/include/highs/ipm/ipx/utils.h +37 -0
  114. data/ext/lpsolver-highs/build/include/highs/lp_data/HConst.h +430 -0
  115. data/ext/lpsolver-highs/build/include/highs/lp_data/HStruct.h +213 -0
  116. data/ext/lpsolver-highs/build/include/highs/lp_data/HighsAnalysis.h +23 -0
  117. data/ext/lpsolver-highs/build/include/highs/lp_data/HighsCallback.h +104 -0
  118. data/ext/lpsolver-highs/build/include/highs/lp_data/HighsCallbackStruct.h +70 -0
  119. data/ext/lpsolver-highs/build/include/highs/lp_data/HighsDebug.h +34 -0
  120. data/ext/lpsolver-highs/build/include/highs/lp_data/HighsIis.h +139 -0
  121. data/ext/lpsolver-highs/build/include/highs/lp_data/HighsInfo.h +421 -0
  122. data/ext/lpsolver-highs/build/include/highs/lp_data/HighsInfoDebug.h +27 -0
  123. data/ext/lpsolver-highs/build/include/highs/lp_data/HighsLp.h +97 -0
  124. data/ext/lpsolver-highs/build/include/highs/lp_data/HighsLpSolverObject.h +47 -0
  125. data/ext/lpsolver-highs/build/include/highs/lp_data/HighsLpUtils.h +330 -0
  126. data/ext/lpsolver-highs/build/include/highs/lp_data/HighsModelUtils.h +129 -0
  127. data/ext/lpsolver-highs/build/include/highs/lp_data/HighsOptions.h +1715 -0
  128. data/ext/lpsolver-highs/build/include/highs/lp_data/HighsRanging.h +43 -0
  129. data/ext/lpsolver-highs/build/include/highs/lp_data/HighsSolution.h +179 -0
  130. data/ext/lpsolver-highs/build/include/highs/lp_data/HighsSolutionDebug.h +87 -0
  131. data/ext/lpsolver-highs/build/include/highs/lp_data/HighsSolve.h +29 -0
  132. data/ext/lpsolver-highs/build/include/highs/lp_data/HighsStatus.h +29 -0
  133. data/ext/lpsolver-highs/build/include/highs/mip/HighsCliqueTable.h +329 -0
  134. data/ext/lpsolver-highs/build/include/highs/mip/HighsConflictPool.h +109 -0
  135. data/ext/lpsolver-highs/build/include/highs/mip/HighsCutGeneration.h +108 -0
  136. data/ext/lpsolver-highs/build/include/highs/mip/HighsCutPool.h +168 -0
  137. data/ext/lpsolver-highs/build/include/highs/mip/HighsDebugSol.h +133 -0
  138. data/ext/lpsolver-highs/build/include/highs/mip/HighsDomain.h +657 -0
  139. data/ext/lpsolver-highs/build/include/highs/mip/HighsDomainChange.h +48 -0
  140. data/ext/lpsolver-highs/build/include/highs/mip/HighsDynamicRowMatrix.h +104 -0
  141. data/ext/lpsolver-highs/build/include/highs/mip/HighsGFkSolve.h +439 -0
  142. data/ext/lpsolver-highs/build/include/highs/mip/HighsImplications.h +194 -0
  143. data/ext/lpsolver-highs/build/include/highs/mip/HighsLpAggregator.h +50 -0
  144. data/ext/lpsolver-highs/build/include/highs/mip/HighsLpRelaxation.h +361 -0
  145. data/ext/lpsolver-highs/build/include/highs/mip/HighsMipAnalysis.h +71 -0
  146. data/ext/lpsolver-highs/build/include/highs/mip/HighsMipSolver.h +159 -0
  147. data/ext/lpsolver-highs/build/include/highs/mip/HighsMipSolverData.h +313 -0
  148. data/ext/lpsolver-highs/build/include/highs/mip/HighsModkSeparator.h +60 -0
  149. data/ext/lpsolver-highs/build/include/highs/mip/HighsNodeQueue.h +312 -0
  150. data/ext/lpsolver-highs/build/include/highs/mip/HighsObjectiveFunction.h +71 -0
  151. data/ext/lpsolver-highs/build/include/highs/mip/HighsPathSeparator.h +39 -0
  152. data/ext/lpsolver-highs/build/include/highs/mip/HighsPrimalHeuristics.h +75 -0
  153. data/ext/lpsolver-highs/build/include/highs/mip/HighsPseudocost.h +366 -0
  154. data/ext/lpsolver-highs/build/include/highs/mip/HighsRedcostFixing.h +42 -0
  155. data/ext/lpsolver-highs/build/include/highs/mip/HighsSearch.h +241 -0
  156. data/ext/lpsolver-highs/build/include/highs/mip/HighsSeparation.h +41 -0
  157. data/ext/lpsolver-highs/build/include/highs/mip/HighsSeparator.h +60 -0
  158. data/ext/lpsolver-highs/build/include/highs/mip/HighsTableauSeparator.h +34 -0
  159. data/ext/lpsolver-highs/build/include/highs/mip/HighsTransformedLp.h +63 -0
  160. data/ext/lpsolver-highs/build/include/highs/mip/MipTimer.h +544 -0
  161. data/ext/lpsolver-highs/build/include/highs/mip/feasibilityjump.hh +800 -0
  162. data/ext/lpsolver-highs/build/include/highs/model/HighsHessian.h +54 -0
  163. data/ext/lpsolver-highs/build/include/highs/model/HighsHessianUtils.h +47 -0
  164. data/ext/lpsolver-highs/build/include/highs/model/HighsModel.h +42 -0
  165. data/ext/lpsolver-highs/build/include/highs/parallel/HighsBinarySemaphore.h +108 -0
  166. data/ext/lpsolver-highs/build/include/highs/parallel/HighsCacheAlign.h +82 -0
  167. data/ext/lpsolver-highs/build/include/highs/parallel/HighsCombinable.h +116 -0
  168. data/ext/lpsolver-highs/build/include/highs/parallel/HighsMutex.h +124 -0
  169. data/ext/lpsolver-highs/build/include/highs/parallel/HighsParallel.h +128 -0
  170. data/ext/lpsolver-highs/build/include/highs/parallel/HighsRaceTimer.h +38 -0
  171. data/ext/lpsolver-highs/build/include/highs/parallel/HighsSchedulerConstants.h +19 -0
  172. data/ext/lpsolver-highs/build/include/highs/parallel/HighsSpinMutex.h +48 -0
  173. data/ext/lpsolver-highs/build/include/highs/parallel/HighsSplitDeque.h +606 -0
  174. data/ext/lpsolver-highs/build/include/highs/parallel/HighsTask.h +170 -0
  175. data/ext/lpsolver-highs/build/include/highs/parallel/HighsTaskExecutor.h +217 -0
  176. data/ext/lpsolver-highs/build/include/highs/pdlp/CupdlpWrapper.h +108 -0
  177. data/ext/lpsolver-highs/build/include/highs/pdlp/HiPdlpTimer.h +155 -0
  178. data/ext/lpsolver-highs/build/include/highs/pdlp/HiPdlpWrapper.h +26 -0
  179. data/ext/lpsolver-highs/build/include/highs/pdlp/cupdlp/cupdlp_cs.h +40 -0
  180. data/ext/lpsolver-highs/build/include/highs/pdlp/cupdlp/cupdlp_defs.h +447 -0
  181. data/ext/lpsolver-highs/build/include/highs/pdlp/cupdlp/cupdlp_linalg.h +189 -0
  182. data/ext/lpsolver-highs/build/include/highs/pdlp/cupdlp/cupdlp_proj.h +19 -0
  183. data/ext/lpsolver-highs/build/include/highs/pdlp/cupdlp/cupdlp_restart.h +31 -0
  184. data/ext/lpsolver-highs/build/include/highs/pdlp/cupdlp/cupdlp_scaling.h +26 -0
  185. data/ext/lpsolver-highs/build/include/highs/pdlp/cupdlp/cupdlp_solver.h +105 -0
  186. data/ext/lpsolver-highs/build/include/highs/pdlp/cupdlp/cupdlp_step.h +37 -0
  187. data/ext/lpsolver-highs/build/include/highs/pdlp/cupdlp/cupdlp_utils.c +1850 -0
  188. data/ext/lpsolver-highs/build/include/highs/pdlp/hipdlp/defs.hpp +222 -0
  189. data/ext/lpsolver-highs/build/include/highs/pdlp/hipdlp/linalg.hpp +61 -0
  190. data/ext/lpsolver-highs/build/include/highs/pdlp/hipdlp/logger.hpp +80 -0
  191. data/ext/lpsolver-highs/build/include/highs/pdlp/hipdlp/pdhg.hpp +358 -0
  192. data/ext/lpsolver-highs/build/include/highs/pdlp/hipdlp/restart.hpp +96 -0
  193. data/ext/lpsolver-highs/build/include/highs/pdlp/hipdlp/scaling.hpp +74 -0
  194. data/ext/lpsolver-highs/build/include/highs/pdlp/hipdlp/solver_results.hpp +65 -0
  195. data/ext/lpsolver-highs/build/include/highs/pdqsort/pdqsort.h +532 -0
  196. data/ext/lpsolver-highs/build/include/highs/presolve/HPresolve.h +505 -0
  197. data/ext/lpsolver-highs/build/include/highs/presolve/HPresolveAnalysis.h +52 -0
  198. data/ext/lpsolver-highs/build/include/highs/presolve/HighsPostsolveStack.h +943 -0
  199. data/ext/lpsolver-highs/build/include/highs/presolve/HighsSymmetry.h +284 -0
  200. data/ext/lpsolver-highs/build/include/highs/presolve/ICrash.h +124 -0
  201. data/ext/lpsolver-highs/build/include/highs/presolve/ICrashUtil.h +62 -0
  202. data/ext/lpsolver-highs/build/include/highs/presolve/ICrashX.h +23 -0
  203. data/ext/lpsolver-highs/build/include/highs/presolve/PresolveComponent.h +90 -0
  204. data/ext/lpsolver-highs/build/include/highs/qpsolver/a_asm.hpp +77 -0
  205. data/ext/lpsolver-highs/build/include/highs/qpsolver/a_quass.hpp +22 -0
  206. data/ext/lpsolver-highs/build/include/highs/qpsolver/basis.hpp +159 -0
  207. data/ext/lpsolver-highs/build/include/highs/qpsolver/crashsolution.hpp +20 -0
  208. data/ext/lpsolver-highs/build/include/highs/qpsolver/dantzigpricing.hpp +80 -0
  209. data/ext/lpsolver-highs/build/include/highs/qpsolver/devexpricing.hpp +108 -0
  210. data/ext/lpsolver-highs/build/include/highs/qpsolver/eventhandler.hpp +30 -0
  211. data/ext/lpsolver-highs/build/include/highs/qpsolver/factor.hpp +408 -0
  212. data/ext/lpsolver-highs/build/include/highs/qpsolver/feasibility_bounded.hpp +114 -0
  213. data/ext/lpsolver-highs/build/include/highs/qpsolver/feasibility_highs.hpp +301 -0
  214. data/ext/lpsolver-highs/build/include/highs/qpsolver/gradient.hpp +46 -0
  215. data/ext/lpsolver-highs/build/include/highs/qpsolver/instance.hpp +70 -0
  216. data/ext/lpsolver-highs/build/include/highs/qpsolver/matrix.hpp +342 -0
  217. data/ext/lpsolver-highs/build/include/highs/qpsolver/perturbation.hpp +15 -0
  218. data/ext/lpsolver-highs/build/include/highs/qpsolver/pricing.hpp +22 -0
  219. data/ext/lpsolver-highs/build/include/highs/qpsolver/qpconst.hpp +34 -0
  220. data/ext/lpsolver-highs/build/include/highs/qpsolver/qpvector.hpp +242 -0
  221. data/ext/lpsolver-highs/build/include/highs/qpsolver/quass.hpp +27 -0
  222. data/ext/lpsolver-highs/build/include/highs/qpsolver/ratiotest.hpp +26 -0
  223. data/ext/lpsolver-highs/build/include/highs/qpsolver/runtime.hpp +45 -0
  224. data/ext/lpsolver-highs/build/include/highs/qpsolver/scaling.hpp +15 -0
  225. data/ext/lpsolver-highs/build/include/highs/qpsolver/settings.hpp +84 -0
  226. data/ext/lpsolver-highs/build/include/highs/qpsolver/snippets.hpp +36 -0
  227. data/ext/lpsolver-highs/build/include/highs/qpsolver/statistics.hpp +30 -0
  228. data/ext/lpsolver-highs/build/include/highs/qpsolver/steepestedgepricing.hpp +173 -0
  229. data/ext/lpsolver-highs/build/include/highs/simplex/HApp.h +550 -0
  230. data/ext/lpsolver-highs/build/include/highs/simplex/HEkk.h +419 -0
  231. data/ext/lpsolver-highs/build/include/highs/simplex/HEkkDual.h +513 -0
  232. data/ext/lpsolver-highs/build/include/highs/simplex/HEkkDualRHS.h +134 -0
  233. data/ext/lpsolver-highs/build/include/highs/simplex/HEkkDualRow.h +201 -0
  234. data/ext/lpsolver-highs/build/include/highs/simplex/HEkkPrimal.h +191 -0
  235. data/ext/lpsolver-highs/build/include/highs/simplex/HSimplex.h +42 -0
  236. data/ext/lpsolver-highs/build/include/highs/simplex/HSimplexDebug.h +48 -0
  237. data/ext/lpsolver-highs/build/include/highs/simplex/HSimplexNla.h +158 -0
  238. data/ext/lpsolver-highs/build/include/highs/simplex/HSimplexReport.h +21 -0
  239. data/ext/lpsolver-highs/build/include/highs/simplex/HighsSimplexAnalysis.h +500 -0
  240. data/ext/lpsolver-highs/build/include/highs/simplex/SimplexConst.h +273 -0
  241. data/ext/lpsolver-highs/build/include/highs/simplex/SimplexStruct.h +263 -0
  242. data/ext/lpsolver-highs/build/include/highs/simplex/SimplexTimer.h +414 -0
  243. data/ext/lpsolver-highs/build/include/highs/test_kkt/DevKkt.h +143 -0
  244. data/ext/lpsolver-highs/build/include/highs/test_kkt/KktCh2.h +79 -0
  245. data/ext/lpsolver-highs/build/include/highs/util/FactorTimer.h +199 -0
  246. data/ext/lpsolver-highs/build/include/highs/util/HFactor.h +587 -0
  247. data/ext/lpsolver-highs/build/include/highs/util/HFactorConst.h +81 -0
  248. data/ext/lpsolver-highs/build/include/highs/util/HFactorDebug.h +55 -0
  249. data/ext/lpsolver-highs/build/include/highs/util/HSet.h +89 -0
  250. data/ext/lpsolver-highs/build/include/highs/util/HVector.h +22 -0
  251. data/ext/lpsolver-highs/build/include/highs/util/HVectorBase.h +102 -0
  252. data/ext/lpsolver-highs/build/include/highs/util/HighsCDouble.h +323 -0
  253. data/ext/lpsolver-highs/build/include/highs/util/HighsComponent.h +53 -0
  254. data/ext/lpsolver-highs/build/include/highs/util/HighsDataStack.h +83 -0
  255. data/ext/lpsolver-highs/build/include/highs/util/HighsDisjointSets.h +107 -0
  256. data/ext/lpsolver-highs/build/include/highs/util/HighsHash.h +1274 -0
  257. data/ext/lpsolver-highs/build/include/highs/util/HighsHashTree.h +1461 -0
  258. data/ext/lpsolver-highs/build/include/highs/util/HighsInt.h +36 -0
  259. data/ext/lpsolver-highs/build/include/highs/util/HighsIntegers.h +212 -0
  260. data/ext/lpsolver-highs/build/include/highs/util/HighsLinearSumBounds.h +203 -0
  261. data/ext/lpsolver-highs/build/include/highs/util/HighsMatrixPic.h +37 -0
  262. data/ext/lpsolver-highs/build/include/highs/util/HighsMatrixSlice.h +561 -0
  263. data/ext/lpsolver-highs/build/include/highs/util/HighsMatrixUtils.h +57 -0
  264. data/ext/lpsolver-highs/build/include/highs/util/HighsMemoryAllocation.h +63 -0
  265. data/ext/lpsolver-highs/build/include/highs/util/HighsRandom.h +242 -0
  266. data/ext/lpsolver-highs/build/include/highs/util/HighsRbTree.h +452 -0
  267. data/ext/lpsolver-highs/build/include/highs/util/HighsSort.h +131 -0
  268. data/ext/lpsolver-highs/build/include/highs/util/HighsSparseMatrix.h +151 -0
  269. data/ext/lpsolver-highs/build/include/highs/util/HighsSparseVectorSum.h +95 -0
  270. data/ext/lpsolver-highs/build/include/highs/util/HighsSplay.h +135 -0
  271. data/ext/lpsolver-highs/build/include/highs/util/HighsTimer.h +385 -0
  272. data/ext/lpsolver-highs/build/include/highs/util/HighsUtils.h +272 -0
  273. data/ext/lpsolver-highs/build/include/highs/util/stringutil.h +46 -0
  274. data/ext/lpsolver-highs/build/include/highs/zstr/strict_fstream.hpp +237 -0
  275. data/ext/lpsolver-highs/build/include/highs/zstr/zstr.hpp +473 -0
  276. data/ext/lpsolver-highs/build/include/highs_export.h +43 -0
  277. data/ext/lpsolver-highs/build/lib/cmake/highs/highs-config-version.cmake +65 -0
  278. data/ext/lpsolver-highs/build/lib/cmake/highs/highs-config.cmake +36 -0
  279. data/ext/lpsolver-highs/build/lib/cmake/highs/highs-targets-release.cmake +19 -0
  280. data/ext/lpsolver-highs/build/lib/cmake/highs/highs-targets.cmake +111 -0
  281. data/ext/lpsolver-highs/build/lib/libhighs.a +0 -0
  282. data/ext/lpsolver-highs/build/lib/pkgconfig/highs.pc +12 -0
  283. data/ext/lpsolver-highs/build/share/doc/HIGHS/AUTHORS +7 -0
  284. data/ext/lpsolver-highs/build/share/doc/HIGHS/CITATION.cff +29 -0
  285. data/ext/lpsolver-highs/build/share/doc/HIGHS/CODE_OF_CONDUCT.md +128 -0
  286. data/ext/lpsolver-highs/build/share/doc/HIGHS/CONTRIBUTING.md +31 -0
  287. data/ext/lpsolver-highs/build/share/doc/HIGHS/FEATURES.md +61 -0
  288. data/ext/lpsolver-highs/build/share/doc/HIGHS/LICENSE.txt +21 -0
  289. data/ext/lpsolver-highs/build/share/doc/HIGHS/README.md +281 -0
  290. data/ext/lpsolver-highs/build_webdemo.sh +46 -0
  291. data/ext/lpsolver-highs/check/Avgas.cpp +245 -0
  292. data/ext/lpsolver-highs/check/Avgas.h +44 -0
  293. data/ext/lpsolver-highs/check/CMakeLists.txt +573 -0
  294. data/ext/lpsolver-highs/check/HCheckConfig.h.bazel.in +6 -0
  295. data/ext/lpsolver-highs/check/HCheckConfig.h.in +12 -0
  296. data/ext/lpsolver-highs/check/HCheckConfig.h.meson.in +6 -0
  297. data/ext/lpsolver-highs/check/SpecialLps.h +405 -0
  298. data/ext/lpsolver-highs/check/TestAlienBasis.cpp +720 -0
  299. data/ext/lpsolver-highs/check/TestBasis.cpp +359 -0
  300. data/ext/lpsolver-highs/check/TestBasisSolves.cpp +669 -0
  301. data/ext/lpsolver-highs/check/TestCAPI.c +2513 -0
  302. data/ext/lpsolver-highs/check/TestCallbacks.cpp +608 -0
  303. data/ext/lpsolver-highs/check/TestCheckSolution.cpp +740 -0
  304. data/ext/lpsolver-highs/check/TestCrossover.cpp +111 -0
  305. data/ext/lpsolver-highs/check/TestDualize.cpp +172 -0
  306. data/ext/lpsolver-highs/check/TestEkk.cpp +100 -0
  307. data/ext/lpsolver-highs/check/TestFactor.cpp +389 -0
  308. data/ext/lpsolver-highs/check/TestFilereader.cpp +568 -0
  309. data/ext/lpsolver-highs/check/TestFortranAPI.f90 +65 -0
  310. data/ext/lpsolver-highs/check/TestHSet.cpp +80 -0
  311. data/ext/lpsolver-highs/check/TestHighsCDouble.cpp +109 -0
  312. data/ext/lpsolver-highs/check/TestHighsGFkSolve.cpp +102 -0
  313. data/ext/lpsolver-highs/check/TestHighsHash.cpp +126 -0
  314. data/ext/lpsolver-highs/check/TestHighsHessian.cpp +329 -0
  315. data/ext/lpsolver-highs/check/TestHighsIntegers.cpp +42 -0
  316. data/ext/lpsolver-highs/check/TestHighsModel.cpp +134 -0
  317. data/ext/lpsolver-highs/check/TestHighsParallel.cpp +277 -0
  318. data/ext/lpsolver-highs/check/TestHighsRbTree.cpp +109 -0
  319. data/ext/lpsolver-highs/check/TestHighsSparseMatrix.cpp +126 -0
  320. data/ext/lpsolver-highs/check/TestHighsVersion.cpp +61 -0
  321. data/ext/lpsolver-highs/check/TestHipo.cpp +122 -0
  322. data/ext/lpsolver-highs/check/TestICrash.cpp +46 -0
  323. data/ext/lpsolver-highs/check/TestIO.cpp +163 -0
  324. data/ext/lpsolver-highs/check/TestIis.cpp +1063 -0
  325. data/ext/lpsolver-highs/check/TestInfo.cpp +116 -0
  326. data/ext/lpsolver-highs/check/TestIpm.cpp +226 -0
  327. data/ext/lpsolver-highs/check/TestIpx.cpp +96 -0
  328. data/ext/lpsolver-highs/check/TestLPFileFormat.cpp +22 -0
  329. data/ext/lpsolver-highs/check/TestLogging.cpp +69 -0
  330. data/ext/lpsolver-highs/check/TestLpModification.cpp +2497 -0
  331. data/ext/lpsolver-highs/check/TestLpOrientation.cpp +121 -0
  332. data/ext/lpsolver-highs/check/TestLpSolvers.cpp +555 -0
  333. data/ext/lpsolver-highs/check/TestLpValidation.cpp +689 -0
  334. data/ext/lpsolver-highs/check/TestMain.cpp +6 -0
  335. data/ext/lpsolver-highs/check/TestMipSolver.cpp +1406 -0
  336. data/ext/lpsolver-highs/check/TestModelProperties.cpp +143 -0
  337. data/ext/lpsolver-highs/check/TestMultiObjective.cpp +198 -0
  338. data/ext/lpsolver-highs/check/TestNames.cpp +187 -0
  339. data/ext/lpsolver-highs/check/TestOptions.cpp +544 -0
  340. data/ext/lpsolver-highs/check/TestPdlp.cpp +327 -0
  341. data/ext/lpsolver-highs/check/TestPdlpHi.cpp +40 -0
  342. data/ext/lpsolver-highs/check/TestPresolve.cpp +912 -0
  343. data/ext/lpsolver-highs/check/TestQpSolver.cpp +1345 -0
  344. data/ext/lpsolver-highs/check/TestRanging.cpp +558 -0
  345. data/ext/lpsolver-highs/check/TestRays.cpp +1010 -0
  346. data/ext/lpsolver-highs/check/TestSemiVariables.cpp +329 -0
  347. data/ext/lpsolver-highs/check/TestSetup.cpp +12 -0
  348. data/ext/lpsolver-highs/check/TestSort.cpp +247 -0
  349. data/ext/lpsolver-highs/check/TestSpecialLps.cpp +775 -0
  350. data/ext/lpsolver-highs/check/TestThrow.cpp +83 -0
  351. data/ext/lpsolver-highs/check/TestTspSolver.cpp +19 -0
  352. data/ext/lpsolver-highs/check/TestUserScale.cpp +444 -0
  353. data/ext/lpsolver-highs/check/cublas_example.cpp +76 -0
  354. data/ext/lpsolver-highs/check/cublas_gpu_start.cpp +88 -0
  355. data/ext/lpsolver-highs/check/hipo_test_option_files/hipo_options_0 +1 -0
  356. data/ext/lpsolver-highs/check/instances/1448.lp +1 -0
  357. data/ext/lpsolver-highs/check/instances/1449a.lp +1 -0
  358. data/ext/lpsolver-highs/check/instances/1449b.lp +1 -0
  359. data/ext/lpsolver-highs/check/instances/1451.lp +8 -0
  360. data/ext/lpsolver-highs/check/instances/2122.lp +1822 -0
  361. data/ext/lpsolver-highs/check/instances/2171.mps +717 -0
  362. data/ext/lpsolver-highs/check/instances/25fv47.mps +6919 -0
  363. data/ext/lpsolver-highs/check/instances/2821-duplicate.mps +31 -0
  364. data/ext/lpsolver-highs/check/instances/2821-qmatrix.mps +31 -0
  365. data/ext/lpsolver-highs/check/instances/2821-quadobj.mps +29 -0
  366. data/ext/lpsolver-highs/check/instances/2821-summation.mps +30 -0
  367. data/ext/lpsolver-highs/check/instances/2821.mps +29 -0
  368. data/ext/lpsolver-highs/check/instances/2894.mps +89 -0
  369. data/ext/lpsolver-highs/check/instances/80bau3b.mps +23732 -0
  370. data/ext/lpsolver-highs/check/instances/WithInf.set +3 -0
  371. data/ext/lpsolver-highs/check/instances/adlittle.mps +335 -0
  372. data/ext/lpsolver-highs/check/instances/afiro.mps +83 -0
  373. data/ext/lpsolver-highs/check/instances/avgas.mps +51 -0
  374. data/ext/lpsolver-highs/check/instances/bell5.mps +384 -0
  375. data/ext/lpsolver-highs/check/instances/bgetam.mps +2112 -0
  376. data/ext/lpsolver-highs/check/instances/blending.mps +13 -0
  377. data/ext/lpsolver-highs/check/instances/box1.mps +1085 -0
  378. data/ext/lpsolver-highs/check/instances/chip.mps +13 -0
  379. data/ext/lpsolver-highs/check/instances/comment.mps +23 -0
  380. data/ext/lpsolver-highs/check/instances/cplex1.mps +9674 -0
  381. data/ext/lpsolver-highs/check/instances/dD2e.mps +10 -0
  382. data/ext/lpsolver-highs/check/instances/dcmulti.mps +2310 -0
  383. data/ext/lpsolver-highs/check/instances/e226.mps +1733 -0
  384. data/ext/lpsolver-highs/check/instances/egout-ac.mps +473 -0
  385. data/ext/lpsolver-highs/check/instances/egout.mps +403 -0
  386. data/ext/lpsolver-highs/check/instances/etamacro.mps +2084 -0
  387. data/ext/lpsolver-highs/check/instances/ex72a.mps +849 -0
  388. data/ext/lpsolver-highs/check/instances/fixed-binary.lp +11 -0
  389. data/ext/lpsolver-highs/check/instances/flugpl.mps +111 -0
  390. data/ext/lpsolver-highs/check/instances/flugpl_illegal_integer.sol +24 -0
  391. data/ext/lpsolver-highs/check/instances/flugpl_integer.sol +25 -0
  392. data/ext/lpsolver-highs/check/instances/forest6.mps +261 -0
  393. data/ext/lpsolver-highs/check/instances/galenet.mps +34 -0
  394. data/ext/lpsolver-highs/check/instances/gams10am.mps +478 -0
  395. data/ext/lpsolver-highs/check/instances/garbage.ems +3 -0
  396. data/ext/lpsolver-highs/check/instances/garbage.lp +3 -0
  397. data/ext/lpsolver-highs/check/instances/garbage.mps +3 -0
  398. data/ext/lpsolver-highs/check/instances/gas11.mps +2924 -0
  399. data/ext/lpsolver-highs/check/instances/gesa2.mps +5459 -0
  400. data/ext/lpsolver-highs/check/instances/greenbea.mps +19215 -0
  401. data/ext/lpsolver-highs/check/instances/gt2.mps +534 -0
  402. data/ext/lpsolver-highs/check/instances/infeasible-mip0.mps +140 -0
  403. data/ext/lpsolver-highs/check/instances/infeasible-mip1.mps +371 -0
  404. data/ext/lpsolver-highs/check/instances/israel.mps +1490 -0
  405. data/ext/lpsolver-highs/check/instances/issue-2095.mps +836 -0
  406. data/ext/lpsolver-highs/check/instances/issue-2173.mps +3331 -0
  407. data/ext/lpsolver-highs/check/instances/issue-2204.mps +143 -0
  408. data/ext/lpsolver-highs/check/instances/issue-2290.mps +158 -0
  409. data/ext/lpsolver-highs/check/instances/issue-2388.lp +76 -0
  410. data/ext/lpsolver-highs/check/instances/issue-2402.mps +435 -0
  411. data/ext/lpsolver-highs/check/instances/issue-2446.mps +9154 -0
  412. data/ext/lpsolver-highs/check/instances/issue-2585.lp +16 -0
  413. data/ext/lpsolver-highs/check/instances/issue-2874-3.mps +97 -0
  414. data/ext/lpsolver-highs/check/instances/klein1.mps +422 -0
  415. data/ext/lpsolver-highs/check/instances/lseu.mps +371 -0
  416. data/ext/lpsolver-highs/check/instances/model.xyz +1 -0
  417. data/ext/lpsolver-highs/check/instances/nan0.mps +13 -0
  418. data/ext/lpsolver-highs/check/instances/nan1.mps +13 -0
  419. data/ext/lpsolver-highs/check/instances/nan2.mps +13 -0
  420. data/ext/lpsolver-highs/check/instances/no-newline-eof.lp +5 -0
  421. data/ext/lpsolver-highs/check/instances/p01.mps +909 -0
  422. data/ext/lpsolver-highs/check/instances/p0548.mps +1992 -0
  423. data/ext/lpsolver-highs/check/instances/primal1.mps +3909 -0
  424. data/ext/lpsolver-highs/check/instances/qap04.mps +606 -0
  425. data/ext/lpsolver-highs/check/instances/qcqp.lp +8 -0
  426. data/ext/lpsolver-highs/check/instances/qjh.lp +9 -0
  427. data/ext/lpsolver-highs/check/instances/qjh.mps +18 -0
  428. data/ext/lpsolver-highs/check/instances/qjh_qmatrix.mps +19 -0
  429. data/ext/lpsolver-highs/check/instances/qjh_quadobj.mps +18 -0
  430. data/ext/lpsolver-highs/check/instances/qjh_quadobj_qmatrix.mps +25 -0
  431. data/ext/lpsolver-highs/check/instances/qjh_uncon.lp +10 -0
  432. data/ext/lpsolver-highs/check/instances/qjh_uncon.mps +17 -0
  433. data/ext/lpsolver-highs/check/instances/qpinfeasible.lp +8 -0
  434. data/ext/lpsolver-highs/check/instances/qptestnw.lp +7 -0
  435. data/ext/lpsolver-highs/check/instances/qpunbounded.lp +5 -0
  436. data/ext/lpsolver-highs/check/instances/refinery.mps +1882 -0
  437. data/ext/lpsolver-highs/check/instances/rgn.mps +559 -0
  438. data/ext/lpsolver-highs/check/instances/scrs8.mps +2717 -0
  439. data/ext/lpsolver-highs/check/instances/sctest.mps +66 -0
  440. data/ext/lpsolver-highs/check/instances/semi-continuous.lp +13 -0
  441. data/ext/lpsolver-highs/check/instances/semi-continuous.mps +24 -0
  442. data/ext/lpsolver-highs/check/instances/semi-integer.lp +15 -0
  443. data/ext/lpsolver-highs/check/instances/semi-integer.mps +22 -0
  444. data/ext/lpsolver-highs/check/instances/shell.mps +4039 -0
  445. data/ext/lpsolver-highs/check/instances/silly-names.mps +14 -0
  446. data/ext/lpsolver-highs/check/instances/small_mip.mps +87 -0
  447. data/ext/lpsolver-highs/check/instances/smalllp.mps +21 -0
  448. data/ext/lpsolver-highs/check/instances/sp150x300d.mps +1983 -0
  449. data/ext/lpsolver-highs/check/instances/stair.mps +2499 -0
  450. data/ext/lpsolver-highs/check/instances/standata.mps +2317 -0
  451. data/ext/lpsolver-highs/check/instances/standgub.mps +2428 -0
  452. data/ext/lpsolver-highs/check/instances/standmps.mps +2695 -0
  453. data/ext/lpsolver-highs/check/instances/test.mps +53 -0
  454. data/ext/lpsolver-highs/check/instances/vol1.mps +1895 -0
  455. data/ext/lpsolver-highs/check/instances/warnings.mps +68 -0
  456. data/ext/lpsolver-highs/check/instances/woodinfe.mps +216 -0
  457. data/ext/lpsolver-highs/check/matrix_multiplication.hpp +49 -0
  458. data/ext/lpsolver-highs/check/meson.build +92 -0
  459. data/ext/lpsolver-highs/check/pythontest.py +11 -0
  460. data/ext/lpsolver-highs/check/sample_options_file +8 -0
  461. data/ext/lpsolver-highs/cmake/CheckAtomic.cmake +74 -0
  462. data/ext/lpsolver-highs/cmake/FindCUDAConf.cmake +44 -0
  463. data/ext/lpsolver-highs/cmake/FindHipoDeps.cmake +351 -0
  464. data/ext/lpsolver-highs/cmake/README.md +243 -0
  465. data/ext/lpsolver-highs/cmake/cpp-highs.cmake +243 -0
  466. data/ext/lpsolver-highs/cmake/dotnet.cmake +94 -0
  467. data/ext/lpsolver-highs/cmake/highs-config.cmake.in +22 -0
  468. data/ext/lpsolver-highs/cmake/python-highs.cmake +74 -0
  469. data/ext/lpsolver-highs/cmake/set-version.cmake +26 -0
  470. data/ext/lpsolver-highs/cmake/sources-python.cmake +461 -0
  471. data/ext/lpsolver-highs/cmake/sources.cmake +618 -0
  472. data/ext/lpsolver-highs/docs/HiGHS_CopyrightHeader.pl +78 -0
  473. data/ext/lpsolver-highs/docs/HiGHS_CopyrightHeaderUpdateAll +32 -0
  474. data/ext/lpsolver-highs/docs/Project.toml +7 -0
  475. data/ext/lpsolver-highs/docs/README.md +27 -0
  476. data/ext/lpsolver-highs/docs/c_api_gen/HConfig.h +1 -0
  477. data/ext/lpsolver-highs/docs/c_api_gen/build.jl +48 -0
  478. data/ext/lpsolver-highs/docs/make.jl +115 -0
  479. data/ext/lpsolver-highs/docs/src/assets/logo.png +0 -0
  480. data/ext/lpsolver-highs/docs/src/callbacks.md +171 -0
  481. data/ext/lpsolver-highs/docs/src/executable.md +88 -0
  482. data/ext/lpsolver-highs/docs/src/guide/advanced.md +66 -0
  483. data/ext/lpsolver-highs/docs/src/guide/basic.md +116 -0
  484. data/ext/lpsolver-highs/docs/src/guide/further.md +193 -0
  485. data/ext/lpsolver-highs/docs/src/guide/gpu.md +58 -0
  486. data/ext/lpsolver-highs/docs/src/guide/index.md +18 -0
  487. data/ext/lpsolver-highs/docs/src/guide/kkt.md +219 -0
  488. data/ext/lpsolver-highs/docs/src/guide/numerics.md +55 -0
  489. data/ext/lpsolver-highs/docs/src/index.md +86 -0
  490. data/ext/lpsolver-highs/docs/src/installation.md +130 -0
  491. data/ext/lpsolver-highs/docs/src/interfaces/c_api.md +6 -0
  492. data/ext/lpsolver-highs/docs/src/interfaces/cpp/examples.md +1 -0
  493. data/ext/lpsolver-highs/docs/src/interfaces/cpp/index.md +29 -0
  494. data/ext/lpsolver-highs/docs/src/interfaces/cpp/library.md +107 -0
  495. data/ext/lpsolver-highs/docs/src/interfaces/csharp.md +55 -0
  496. data/ext/lpsolver-highs/docs/src/interfaces/fortran.md +11 -0
  497. data/ext/lpsolver-highs/docs/src/interfaces/julia/index.md +130 -0
  498. data/ext/lpsolver-highs/docs/src/interfaces/other.md +41 -0
  499. data/ext/lpsolver-highs/docs/src/interfaces/python/example-py.md +275 -0
  500. data/ext/lpsolver-highs/docs/src/interfaces/python/index.md +91 -0
  501. data/ext/lpsolver-highs/docs/src/interfaces/python/model-py.md +90 -0
  502. data/ext/lpsolver-highs/docs/src/options/definitions.md +529 -0
  503. data/ext/lpsolver-highs/docs/src/options/intro.md +46 -0
  504. data/ext/lpsolver-highs/docs/src/parallel.md +88 -0
  505. data/ext/lpsolver-highs/docs/src/solvers.md +168 -0
  506. data/ext/lpsolver-highs/docs/src/structures/classes/HighsHessian.md +9 -0
  507. data/ext/lpsolver-highs/docs/src/structures/classes/HighsIis.md +16 -0
  508. data/ext/lpsolver-highs/docs/src/structures/classes/HighsLp.md +19 -0
  509. data/ext/lpsolver-highs/docs/src/structures/classes/HighsModel.md +6 -0
  510. data/ext/lpsolver-highs/docs/src/structures/classes/HighsSparseMatrix.md +10 -0
  511. data/ext/lpsolver-highs/docs/src/structures/classes/index.md +11 -0
  512. data/ext/lpsolver-highs/docs/src/structures/enums.md +114 -0
  513. data/ext/lpsolver-highs/docs/src/structures/index.md +12 -0
  514. data/ext/lpsolver-highs/docs/src/structures/structs/HighsBasis.md +8 -0
  515. data/ext/lpsolver-highs/docs/src/structures/structs/HighsInfo.md +148 -0
  516. data/ext/lpsolver-highs/docs/src/structures/structs/HighsLinearObjective.md +11 -0
  517. data/ext/lpsolver-highs/docs/src/structures/structs/HighsSolution.md +10 -0
  518. data/ext/lpsolver-highs/docs/src/structures/structs/index.md +10 -0
  519. data/ext/lpsolver-highs/docs/src/terminology.md +163 -0
  520. data/ext/lpsolver-highs/examples/CMakeLists.txt +26 -0
  521. data/ext/lpsolver-highs/examples/Docs.py +104 -0
  522. data/ext/lpsolver-highs/examples/branch-and-price.py +465 -0
  523. data/ext/lpsolver-highs/examples/call_highs_from_c.c +685 -0
  524. data/ext/lpsolver-highs/examples/call_highs_from_c_minimal.c +659 -0
  525. data/ext/lpsolver-highs/examples/call_highs_from_cpp.cpp +178 -0
  526. data/ext/lpsolver-highs/examples/call_highs_from_csharp.cs +83 -0
  527. data/ext/lpsolver-highs/examples/call_highs_from_fortran.f90 +579 -0
  528. data/ext/lpsolver-highs/examples/call_highs_from_python.py +448 -0
  529. data/ext/lpsolver-highs/examples/call_highs_from_python_highspy.py +71 -0
  530. data/ext/lpsolver-highs/examples/call_highs_from_python_mps.py +59 -0
  531. data/ext/lpsolver-highs/examples/callback_gap.py +71 -0
  532. data/ext/lpsolver-highs/examples/chip.py +43 -0
  533. data/ext/lpsolver-highs/examples/chip0.py +29 -0
  534. data/ext/lpsolver-highs/examples/distillation.py +77 -0
  535. data/ext/lpsolver-highs/examples/knapsack.py +43 -0
  536. data/ext/lpsolver-highs/examples/minimal.py +11 -0
  537. data/ext/lpsolver-highs/examples/multi_objective.py +139 -0
  538. data/ext/lpsolver-highs/examples/multiple_objective.py +120 -0
  539. data/ext/lpsolver-highs/examples/network_flow.py +37 -0
  540. data/ext/lpsolver-highs/examples/nqueens.py +29 -0
  541. data/ext/lpsolver-highs/examples/plot_highs_log.py +134 -0
  542. data/ext/lpsolver-highs/extern/CLI11.hpp +11546 -0
  543. data/ext/lpsolver-highs/extern/LICENCE_1_0.txt +23 -0
  544. data/ext/lpsolver-highs/extern/amd/License.txt +35 -0
  545. data/ext/lpsolver-highs/extern/amd/SuiteSparse_config.c +54 -0
  546. data/ext/lpsolver-highs/extern/amd/SuiteSparse_config.h +56 -0
  547. data/ext/lpsolver-highs/extern/amd/amd.h +357 -0
  548. data/ext/lpsolver-highs/extern/amd/amd_1.c +172 -0
  549. data/ext/lpsolver-highs/extern/amd/amd_2.c +1761 -0
  550. data/ext/lpsolver-highs/extern/amd/amd_aat.c +179 -0
  551. data/ext/lpsolver-highs/extern/amd/amd_control.c +65 -0
  552. data/ext/lpsolver-highs/extern/amd/amd_defaults.c +37 -0
  553. data/ext/lpsolver-highs/extern/amd/amd_info.c +120 -0
  554. data/ext/lpsolver-highs/extern/amd/amd_internal.h +137 -0
  555. data/ext/lpsolver-highs/extern/amd/amd_order.c +195 -0
  556. data/ext/lpsolver-highs/extern/amd/amd_post_tree.c +105 -0
  557. data/ext/lpsolver-highs/extern/amd/amd_postorder.c +140 -0
  558. data/ext/lpsolver-highs/extern/amd/amd_preprocess.c +107 -0
  559. data/ext/lpsolver-highs/extern/amd/amd_valid.c +93 -0
  560. data/ext/lpsolver-highs/extern/amd/changes.txt +8 -0
  561. data/ext/lpsolver-highs/extern/catch.hpp +18861 -0
  562. data/ext/lpsolver-highs/extern/metis/Changes.txt +31 -0
  563. data/ext/lpsolver-highs/extern/metis/GKlib/GKlib.h +62 -0
  564. data/ext/lpsolver-highs/extern/metis/GKlib/error.c +21 -0
  565. data/ext/lpsolver-highs/extern/metis/GKlib/gk_arch.h +64 -0
  566. data/ext/lpsolver-highs/extern/metis/GKlib/gk_defs.h +19 -0
  567. data/ext/lpsolver-highs/extern/metis/GKlib/gk_macros.h +50 -0
  568. data/ext/lpsolver-highs/extern/metis/GKlib/gk_mkblas.h +51 -0
  569. data/ext/lpsolver-highs/extern/metis/GKlib/gk_mkmemory.h +80 -0
  570. data/ext/lpsolver-highs/extern/metis/GKlib/gk_mkpqueue.h +329 -0
  571. data/ext/lpsolver-highs/extern/metis/GKlib/gk_mkrandom.h +89 -0
  572. data/ext/lpsolver-highs/extern/metis/GKlib/gk_mksort.h +271 -0
  573. data/ext/lpsolver-highs/extern/metis/GKlib/gk_ms_inttypes.h +41 -0
  574. data/ext/lpsolver-highs/extern/metis/GKlib/gk_ms_stat.h +22 -0
  575. data/ext/lpsolver-highs/extern/metis/GKlib/gk_ms_stdint.h +41 -0
  576. data/ext/lpsolver-highs/extern/metis/GKlib/gk_proto.h +50 -0
  577. data/ext/lpsolver-highs/extern/metis/GKlib/gk_struct.h +66 -0
  578. data/ext/lpsolver-highs/extern/metis/GKlib/gk_types.h +15 -0
  579. data/ext/lpsolver-highs/extern/metis/GKlib/mcore.c +176 -0
  580. data/ext/lpsolver-highs/extern/metis/GKlib/memory.c +23 -0
  581. data/ext/lpsolver-highs/extern/metis/GKlib/random.c +37 -0
  582. data/ext/lpsolver-highs/extern/metis/LICENSE.txt +18 -0
  583. data/ext/lpsolver-highs/extern/metis/libmetis/auxapi.c +27 -0
  584. data/ext/lpsolver-highs/extern/metis/libmetis/balance.c +491 -0
  585. data/ext/lpsolver-highs/extern/metis/libmetis/bucketsort.c +44 -0
  586. data/ext/lpsolver-highs/extern/metis/libmetis/coarsen.c +895 -0
  587. data/ext/lpsolver-highs/extern/metis/libmetis/compress.c +231 -0
  588. data/ext/lpsolver-highs/extern/metis/libmetis/contig.c +83 -0
  589. data/ext/lpsolver-highs/extern/metis/libmetis/defs.h +39 -0
  590. data/ext/lpsolver-highs/extern/metis/libmetis/fm.c +527 -0
  591. data/ext/lpsolver-highs/extern/metis/libmetis/gklib.c +55 -0
  592. data/ext/lpsolver-highs/extern/metis/libmetis/gklib_defs.h +33 -0
  593. data/ext/lpsolver-highs/extern/metis/libmetis/graph.c +268 -0
  594. data/ext/lpsolver-highs/extern/metis/libmetis/initpart.c +385 -0
  595. data/ext/lpsolver-highs/extern/metis/libmetis/macros.h +59 -0
  596. data/ext/lpsolver-highs/extern/metis/libmetis/mcutil.c +162 -0
  597. data/ext/lpsolver-highs/extern/metis/libmetis/metislib.h +35 -0
  598. data/ext/lpsolver-highs/extern/metis/libmetis/mmd.c +598 -0
  599. data/ext/lpsolver-highs/extern/metis/libmetis/ometis.c +661 -0
  600. data/ext/lpsolver-highs/extern/metis/libmetis/options.c +260 -0
  601. data/ext/lpsolver-highs/extern/metis/libmetis/proto.h +172 -0
  602. data/ext/lpsolver-highs/extern/metis/libmetis/refine.c +99 -0
  603. data/ext/lpsolver-highs/extern/metis/libmetis/separator.c +57 -0
  604. data/ext/lpsolver-highs/extern/metis/libmetis/sfm.c +581 -0
  605. data/ext/lpsolver-highs/extern/metis/libmetis/srefine.c +152 -0
  606. data/ext/lpsolver-highs/extern/metis/libmetis/stdheaders.h +29 -0
  607. data/ext/lpsolver-highs/extern/metis/libmetis/struct.h +117 -0
  608. data/ext/lpsolver-highs/extern/metis/libmetis/util.c +59 -0
  609. data/ext/lpsolver-highs/extern/metis/libmetis/wspace.c +91 -0
  610. data/ext/lpsolver-highs/extern/metis/metis.h +271 -0
  611. data/ext/lpsolver-highs/extern/pdqsort/license.txt +16 -0
  612. data/ext/lpsolver-highs/extern/pdqsort/pdqsort.h +532 -0
  613. data/ext/lpsolver-highs/extern/rcm/LICENSE +19 -0
  614. data/ext/lpsolver-highs/extern/rcm/rcm.cpp +873 -0
  615. data/ext/lpsolver-highs/extern/rcm/rcm.h +22 -0
  616. data/ext/lpsolver-highs/extern/zstr/LICENSE +21 -0
  617. data/ext/lpsolver-highs/extern/zstr/strict_fstream.hpp +237 -0
  618. data/ext/lpsolver-highs/extern/zstr/zstr.hpp +473 -0
  619. data/ext/lpsolver-highs/flake.lock +61 -0
  620. data/ext/lpsolver-highs/flake.nix +73 -0
  621. data/ext/lpsolver-highs/highs/CMakeLists.txt +499 -0
  622. data/ext/lpsolver-highs/highs/HConfig.h.bazel.in +25 -0
  623. data/ext/lpsolver-highs/highs/HConfig.h.in +22 -0
  624. data/ext/lpsolver-highs/highs/HConfig.h.meson.in +17 -0
  625. data/ext/lpsolver-highs/highs/Highs.h +1812 -0
  626. data/ext/lpsolver-highs/highs/HighsRun.md +143 -0
  627. data/ext/lpsolver-highs/highs/highs_bindings.cpp +1826 -0
  628. data/ext/lpsolver-highs/highs/highspy/__init__.py +93 -0
  629. data/ext/lpsolver-highs/highs/highspy/__init__.pyi +91 -0
  630. data/ext/lpsolver-highs/highs/highspy/_core/__init__.pyi +1058 -0
  631. data/ext/lpsolver-highs/highs/highspy/_core/cb.pyi +118 -0
  632. data/ext/lpsolver-highs/highs/highspy/_core/simplex_constants.pyi +472 -0
  633. data/ext/lpsolver-highs/highs/highspy/highs.py +2430 -0
  634. data/ext/lpsolver-highs/highs/interfaces/highs_c_api.cpp +1812 -0
  635. data/ext/lpsolver-highs/highs/interfaces/highs_c_api.h +2651 -0
  636. data/ext/lpsolver-highs/highs/interfaces/highs_csharp_api.cs +1142 -0
  637. data/ext/lpsolver-highs/highs/interfaces/highs_fortran_api.f90 +873 -0
  638. data/ext/lpsolver-highs/highs/io/Filereader.cpp +87 -0
  639. data/ext/lpsolver-highs/highs/io/Filereader.h +45 -0
  640. data/ext/lpsolver-highs/highs/io/FilereaderLp.cpp +539 -0
  641. data/ext/lpsolver-highs/highs/io/FilereaderLp.h +49 -0
  642. data/ext/lpsolver-highs/highs/io/FilereaderMps.cpp +86 -0
  643. data/ext/lpsolver-highs/highs/io/FilereaderMps.h +27 -0
  644. data/ext/lpsolver-highs/highs/io/HMPSIO.cpp +1001 -0
  645. data/ext/lpsolver-highs/highs/io/HMPSIO.h +78 -0
  646. data/ext/lpsolver-highs/highs/io/HMpsFF.cpp +2113 -0
  647. data/ext/lpsolver-highs/highs/io/HMpsFF.h +245 -0
  648. data/ext/lpsolver-highs/highs/io/HighsIO.cpp +371 -0
  649. data/ext/lpsolver-highs/highs/io/HighsIO.h +118 -0
  650. data/ext/lpsolver-highs/highs/io/LoadOptions.cpp +60 -0
  651. data/ext/lpsolver-highs/highs/io/LoadOptions.h +24 -0
  652. data/ext/lpsolver-highs/highs/io/filereaderlp/LICENSE +19 -0
  653. data/ext/lpsolver-highs/highs/io/filereaderlp/builder.hpp +25 -0
  654. data/ext/lpsolver-highs/highs/io/filereaderlp/def.hpp +19 -0
  655. data/ext/lpsolver-highs/highs/io/filereaderlp/model.hpp +68 -0
  656. data/ext/lpsolver-highs/highs/io/filereaderlp/reader.cpp +1375 -0
  657. data/ext/lpsolver-highs/highs/io/filereaderlp/reader.hpp +10 -0
  658. data/ext/lpsolver-highs/highs/ipm/IpxSolution.h +32 -0
  659. data/ext/lpsolver-highs/highs/ipm/IpxWrapper.cpp +1526 -0
  660. data/ext/lpsolver-highs/highs/ipm/IpxWrapper.h +106 -0
  661. data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu.h +161 -0
  662. data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_factorize.c +132 -0
  663. data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_factorize.h +247 -0
  664. data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_get_factors.c +148 -0
  665. data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_get_factors.h +108 -0
  666. data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_initialize.c +24 -0
  667. data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_initialize.h +119 -0
  668. data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_obj_factorize.h +34 -0
  669. data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_obj_free.h +19 -0
  670. data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_obj_get_factors.h +34 -0
  671. data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_obj_initialize.h +46 -0
  672. data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_obj_solve_dense.h +29 -0
  673. data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_obj_solve_for_update.h +42 -0
  674. data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_obj_solve_sparse.h +32 -0
  675. data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_obj_update.h +31 -0
  676. data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_object.c +325 -0
  677. data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_object.h +30 -0
  678. data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_solve_dense.c +46 -0
  679. data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_solve_dense.h +75 -0
  680. data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_solve_for_update.c +79 -0
  681. data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_solve_for_update.h +169 -0
  682. data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_solve_sparse.c +63 -0
  683. data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_solve_sparse.h +112 -0
  684. data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_update.c +44 -0
  685. data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_update.h +125 -0
  686. data/ext/lpsolver-highs/highs/ipm/basiclu/lu_build_factors.c +441 -0
  687. data/ext/lpsolver-highs/highs/ipm/basiclu/lu_condest.c +124 -0
  688. data/ext/lpsolver-highs/highs/ipm/basiclu/lu_def.h +39 -0
  689. data/ext/lpsolver-highs/highs/ipm/basiclu/lu_dfs.c +141 -0
  690. data/ext/lpsolver-highs/highs/ipm/basiclu/lu_factorize_bump.c +56 -0
  691. data/ext/lpsolver-highs/highs/ipm/basiclu/lu_file.c +184 -0
  692. data/ext/lpsolver-highs/highs/ipm/basiclu/lu_file.h +21 -0
  693. data/ext/lpsolver-highs/highs/ipm/basiclu/lu_garbage_perm.c +53 -0
  694. data/ext/lpsolver-highs/highs/ipm/basiclu/lu_initialize.c +56 -0
  695. data/ext/lpsolver-highs/highs/ipm/basiclu/lu_internal.c +352 -0
  696. data/ext/lpsolver-highs/highs/ipm/basiclu/lu_internal.h +220 -0
  697. data/ext/lpsolver-highs/highs/ipm/basiclu/lu_list.h +173 -0
  698. data/ext/lpsolver-highs/highs/ipm/basiclu/lu_markowitz.c +188 -0
  699. data/ext/lpsolver-highs/highs/ipm/basiclu/lu_matrix_norm.c +51 -0
  700. data/ext/lpsolver-highs/highs/ipm/basiclu/lu_pivot.c +1247 -0
  701. data/ext/lpsolver-highs/highs/ipm/basiclu/lu_residual_test.c +155 -0
  702. data/ext/lpsolver-highs/highs/ipm/basiclu/lu_setup_bump.c +198 -0
  703. data/ext/lpsolver-highs/highs/ipm/basiclu/lu_singletons.c +511 -0
  704. data/ext/lpsolver-highs/highs/ipm/basiclu/lu_solve_dense.c +129 -0
  705. data/ext/lpsolver-highs/highs/ipm/basiclu/lu_solve_for_update.c +360 -0
  706. data/ext/lpsolver-highs/highs/ipm/basiclu/lu_solve_sparse.c +284 -0
  707. data/ext/lpsolver-highs/highs/ipm/basiclu/lu_solve_symbolic.c +48 -0
  708. data/ext/lpsolver-highs/highs/ipm/basiclu/lu_solve_triangular.c +140 -0
  709. data/ext/lpsolver-highs/highs/ipm/basiclu/lu_update.c +908 -0
  710. data/ext/lpsolver-highs/highs/ipm/hipo/auxiliary/Auxiliary.cpp +301 -0
  711. data/ext/lpsolver-highs/highs/ipm/hipo/auxiliary/Auxiliary.h +104 -0
  712. data/ext/lpsolver-highs/highs/ipm/hipo/auxiliary/IntConfig.h +27 -0
  713. data/ext/lpsolver-highs/highs/ipm/hipo/auxiliary/KrylovMethods.cpp +193 -0
  714. data/ext/lpsolver-highs/highs/ipm/hipo/auxiliary/KrylovMethods.h +30 -0
  715. data/ext/lpsolver-highs/highs/ipm/hipo/auxiliary/Log.cpp +60 -0
  716. data/ext/lpsolver-highs/highs/ipm/hipo/auxiliary/Log.h +62 -0
  717. data/ext/lpsolver-highs/highs/ipm/hipo/auxiliary/OrderingPrint.h +10 -0
  718. data/ext/lpsolver-highs/highs/ipm/hipo/auxiliary/VectorOperations.cpp +117 -0
  719. data/ext/lpsolver-highs/highs/ipm/hipo/auxiliary/VectorOperations.h +59 -0
  720. data/ext/lpsolver-highs/highs/ipm/hipo/auxiliary/mycblas.h +85 -0
  721. data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/Analyse.cpp +1367 -0
  722. data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/Analyse.h +122 -0
  723. data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/CallAndTimeBlas.cpp +114 -0
  724. data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/CallAndTimeBlas.h +46 -0
  725. data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/CliqueStack.cpp +82 -0
  726. data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/CliqueStack.h +83 -0
  727. data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/DataCollector.cpp +326 -0
  728. data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/DataCollector.h +86 -0
  729. data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/DenseFact.h +48 -0
  730. data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/DenseFactHybrid.cpp +279 -0
  731. data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/DenseFactKernel.cpp +284 -0
  732. data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/DgemmParallel.cpp +38 -0
  733. data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/DgemmParallel.h +32 -0
  734. data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/FactorHiGHS.cpp +57 -0
  735. data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/FactorHiGHS.h +112 -0
  736. data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/FactorHiGHSSettings.h +63 -0
  737. data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/Factorise.cpp +405 -0
  738. data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/Factorise.h +85 -0
  739. data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/FormatHandler.cpp +46 -0
  740. data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/FormatHandler.h +95 -0
  741. data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/HybridHybridFormatHandler.cpp +238 -0
  742. data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/HybridHybridFormatHandler.h +31 -0
  743. data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/HybridSolveHandler.cpp +272 -0
  744. data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/HybridSolveHandler.h +26 -0
  745. data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/KrylovMethodsIpm.cpp +83 -0
  746. data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/KrylovMethodsIpm.h +45 -0
  747. data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/Numeric.cpp +54 -0
  748. data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/Numeric.h +46 -0
  749. data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/ReturnValues.h +19 -0
  750. data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/SolveHandler.cpp +10 -0
  751. data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/SolveHandler.h +48 -0
  752. data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/Swaps.cpp +70 -0
  753. data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/Swaps.h +19 -0
  754. data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/Symbolic.cpp +101 -0
  755. data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/Symbolic.h +220 -0
  756. data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/Timing.h +114 -0
  757. data/ext/lpsolver-highs/highs/ipm/hipo/ipm/Control.cpp +38 -0
  758. data/ext/lpsolver-highs/highs/ipm/hipo/ipm/Control.h +41 -0
  759. data/ext/lpsolver-highs/highs/ipm/hipo/ipm/FactorHiGHSSolver.cpp +887 -0
  760. data/ext/lpsolver-highs/highs/ipm/hipo/ipm/FactorHiGHSSolver.h +92 -0
  761. data/ext/lpsolver-highs/highs/ipm/hipo/ipm/Info.h +58 -0
  762. data/ext/lpsolver-highs/highs/ipm/hipo/ipm/IpmData.cpp +8 -0
  763. data/ext/lpsolver-highs/highs/ipm/hipo/ipm/IpmData.h +37 -0
  764. data/ext/lpsolver-highs/highs/ipm/hipo/ipm/Iterate.cpp +640 -0
  765. data/ext/lpsolver-highs/highs/ipm/hipo/ipm/Iterate.h +172 -0
  766. data/ext/lpsolver-highs/highs/ipm/hipo/ipm/LinearSolver.h +81 -0
  767. data/ext/lpsolver-highs/highs/ipm/hipo/ipm/LogHighs.cpp +71 -0
  768. data/ext/lpsolver-highs/highs/ipm/hipo/ipm/LogHighs.h +33 -0
  769. data/ext/lpsolver-highs/highs/ipm/hipo/ipm/Model.cpp +403 -0
  770. data/ext/lpsolver-highs/highs/ipm/hipo/ipm/Model.h +136 -0
  771. data/ext/lpsolver-highs/highs/ipm/hipo/ipm/Options.h +35 -0
  772. data/ext/lpsolver-highs/highs/ipm/hipo/ipm/Parameters.h +63 -0
  773. data/ext/lpsolver-highs/highs/ipm/hipo/ipm/PreProcess.cpp +646 -0
  774. data/ext/lpsolver-highs/highs/ipm/hipo/ipm/PreProcess.h +94 -0
  775. data/ext/lpsolver-highs/highs/ipm/hipo/ipm/Refine.cpp +214 -0
  776. data/ext/lpsolver-highs/highs/ipm/hipo/ipm/Solver.cpp +1346 -0
  777. data/ext/lpsolver-highs/highs/ipm/hipo/ipm/Solver.h +338 -0
  778. data/ext/lpsolver-highs/highs/ipm/hipo/ipm/Status.h +88 -0
  779. data/ext/lpsolver-highs/highs/ipm/ipx/basiclu_kernel.cc +71 -0
  780. data/ext/lpsolver-highs/highs/ipm/ipx/basiclu_kernel.h +20 -0
  781. data/ext/lpsolver-highs/highs/ipm/ipx/basiclu_wrapper.cc +299 -0
  782. data/ext/lpsolver-highs/highs/ipm/ipx/basiclu_wrapper.h +47 -0
  783. data/ext/lpsolver-highs/highs/ipm/ipx/basis.cc +966 -0
  784. data/ext/lpsolver-highs/highs/ipm/ipx/basis.h +350 -0
  785. data/ext/lpsolver-highs/highs/ipm/ipx/conjugate_residuals.cc +217 -0
  786. data/ext/lpsolver-highs/highs/ipm/ipx/conjugate_residuals.h +74 -0
  787. data/ext/lpsolver-highs/highs/ipm/ipx/control.cc +151 -0
  788. data/ext/lpsolver-highs/highs/ipm/ipx/control.h +167 -0
  789. data/ext/lpsolver-highs/highs/ipm/ipx/crossover.cc +479 -0
  790. data/ext/lpsolver-highs/highs/ipm/ipx/crossover.h +157 -0
  791. data/ext/lpsolver-highs/highs/ipm/ipx/diagonal_precond.cc +70 -0
  792. data/ext/lpsolver-highs/highs/ipm/ipx/diagonal_precond.h +45 -0
  793. data/ext/lpsolver-highs/highs/ipm/ipx/forrest_tomlin.cc +360 -0
  794. data/ext/lpsolver-highs/highs/ipm/ipx/forrest_tomlin.h +102 -0
  795. data/ext/lpsolver-highs/highs/ipm/ipx/guess_basis.cc +233 -0
  796. data/ext/lpsolver-highs/highs/ipm/ipx/guess_basis.h +21 -0
  797. data/ext/lpsolver-highs/highs/ipm/ipx/indexed_vector.cc +30 -0
  798. data/ext/lpsolver-highs/highs/ipm/ipx/indexed_vector.h +113 -0
  799. data/ext/lpsolver-highs/highs/ipm/ipx/info.cc +124 -0
  800. data/ext/lpsolver-highs/highs/ipm/ipx/info.h +27 -0
  801. data/ext/lpsolver-highs/highs/ipm/ipx/ipm.cc +897 -0
  802. data/ext/lpsolver-highs/highs/ipm/ipx/ipm.h +94 -0
  803. data/ext/lpsolver-highs/highs/ipm/ipx/ipx_c.cc +83 -0
  804. data/ext/lpsolver-highs/highs/ipm/ipx/ipx_c.h +47 -0
  805. data/ext/lpsolver-highs/highs/ipm/ipx/ipx_config.h +9 -0
  806. data/ext/lpsolver-highs/highs/ipm/ipx/ipx_info.h +111 -0
  807. data/ext/lpsolver-highs/highs/ipm/ipx/ipx_internal.h +89 -0
  808. data/ext/lpsolver-highs/highs/ipm/ipx/ipx_parameters.h +76 -0
  809. data/ext/lpsolver-highs/highs/ipm/ipx/ipx_status.h +57 -0
  810. data/ext/lpsolver-highs/highs/ipm/ipx/iterate.cc +683 -0
  811. data/ext/lpsolver-highs/highs/ipm/ipx/iterate.h +331 -0
  812. data/ext/lpsolver-highs/highs/ipm/ipx/kkt_solver.cc +23 -0
  813. data/ext/lpsolver-highs/highs/ipm/ipx/kkt_solver.h +70 -0
  814. data/ext/lpsolver-highs/highs/ipm/ipx/kkt_solver_basis.cc +387 -0
  815. data/ext/lpsolver-highs/highs/ipm/ipx/kkt_solver_basis.h +66 -0
  816. data/ext/lpsolver-highs/highs/ipm/ipx/kkt_solver_diag.cc +120 -0
  817. data/ext/lpsolver-highs/highs/ipm/ipx/kkt_solver_diag.h +48 -0
  818. data/ext/lpsolver-highs/highs/ipm/ipx/linear_operator.cc +10 -0
  819. data/ext/lpsolver-highs/highs/ipm/ipx/linear_operator.h +26 -0
  820. data/ext/lpsolver-highs/highs/ipm/ipx/lp_solver.cc +686 -0
  821. data/ext/lpsolver-highs/highs/ipm/ipx/lp_solver.h +204 -0
  822. data/ext/lpsolver-highs/highs/ipm/ipx/lu_factorization.cc +131 -0
  823. data/ext/lpsolver-highs/highs/ipm/ipx/lu_factorization.h +79 -0
  824. data/ext/lpsolver-highs/highs/ipm/ipx/lu_update.cc +62 -0
  825. data/ext/lpsolver-highs/highs/ipm/ipx/lu_update.h +129 -0
  826. data/ext/lpsolver-highs/highs/ipm/ipx/maxvolume.cc +337 -0
  827. data/ext/lpsolver-highs/highs/ipm/ipx/maxvolume.h +54 -0
  828. data/ext/lpsolver-highs/highs/ipm/ipx/model.cc +1528 -0
  829. data/ext/lpsolver-highs/highs/ipm/ipx/model.h +413 -0
  830. data/ext/lpsolver-highs/highs/ipm/ipx/multistream.h +52 -0
  831. data/ext/lpsolver-highs/highs/ipm/ipx/normal_matrix.cc +126 -0
  832. data/ext/lpsolver-highs/highs/ipm/ipx/normal_matrix.h +44 -0
  833. data/ext/lpsolver-highs/highs/ipm/ipx/power_method.h +44 -0
  834. data/ext/lpsolver-highs/highs/ipm/ipx/sparse_matrix.cc +382 -0
  835. data/ext/lpsolver-highs/highs/ipm/ipx/sparse_matrix.h +195 -0
  836. data/ext/lpsolver-highs/highs/ipm/ipx/sparse_utils.cc +92 -0
  837. data/ext/lpsolver-highs/highs/ipm/ipx/sparse_utils.h +58 -0
  838. data/ext/lpsolver-highs/highs/ipm/ipx/splitted_normal_matrix.cc +117 -0
  839. data/ext/lpsolver-highs/highs/ipm/ipx/splitted_normal_matrix.h +63 -0
  840. data/ext/lpsolver-highs/highs/ipm/ipx/starting_basis.cc +182 -0
  841. data/ext/lpsolver-highs/highs/ipm/ipx/starting_basis.h +39 -0
  842. data/ext/lpsolver-highs/highs/ipm/ipx/symbolic_invert.cc +183 -0
  843. data/ext/lpsolver-highs/highs/ipm/ipx/symbolic_invert.h +29 -0
  844. data/ext/lpsolver-highs/highs/ipm/ipx/timer.cc +16 -0
  845. data/ext/lpsolver-highs/highs/ipm/ipx/timer.h +25 -0
  846. data/ext/lpsolver-highs/highs/ipm/ipx/utils.cc +95 -0
  847. data/ext/lpsolver-highs/highs/ipm/ipx/utils.h +37 -0
  848. data/ext/lpsolver-highs/highs/lp_data/HConst.h +430 -0
  849. data/ext/lpsolver-highs/highs/lp_data/HStruct.h +213 -0
  850. data/ext/lpsolver-highs/highs/lp_data/Highs.cpp +4949 -0
  851. data/ext/lpsolver-highs/highs/lp_data/HighsAnalysis.h +23 -0
  852. data/ext/lpsolver-highs/highs/lp_data/HighsCallback.cpp +323 -0
  853. data/ext/lpsolver-highs/highs/lp_data/HighsCallback.h +104 -0
  854. data/ext/lpsolver-highs/highs/lp_data/HighsCallbackStruct.h +70 -0
  855. data/ext/lpsolver-highs/highs/lp_data/HighsDebug.cpp +54 -0
  856. data/ext/lpsolver-highs/highs/lp_data/HighsDebug.h +34 -0
  857. data/ext/lpsolver-highs/highs/lp_data/HighsDeprecated.cpp +181 -0
  858. data/ext/lpsolver-highs/highs/lp_data/HighsIis.cpp +1290 -0
  859. data/ext/lpsolver-highs/highs/lp_data/HighsIis.h +139 -0
  860. data/ext/lpsolver-highs/highs/lp_data/HighsInfo.cpp +426 -0
  861. data/ext/lpsolver-highs/highs/lp_data/HighsInfo.h +421 -0
  862. data/ext/lpsolver-highs/highs/lp_data/HighsInfoDebug.cpp +175 -0
  863. data/ext/lpsolver-highs/highs/lp_data/HighsInfoDebug.h +27 -0
  864. data/ext/lpsolver-highs/highs/lp_data/HighsInterface.cpp +4344 -0
  865. data/ext/lpsolver-highs/highs/lp_data/HighsLp.cpp +564 -0
  866. data/ext/lpsolver-highs/highs/lp_data/HighsLp.h +97 -0
  867. data/ext/lpsolver-highs/highs/lp_data/HighsLpSolverObject.h +47 -0
  868. data/ext/lpsolver-highs/highs/lp_data/HighsLpUtils.cpp +3794 -0
  869. data/ext/lpsolver-highs/highs/lp_data/HighsLpUtils.h +330 -0
  870. data/ext/lpsolver-highs/highs/lp_data/HighsModelUtils.cpp +1650 -0
  871. data/ext/lpsolver-highs/highs/lp_data/HighsModelUtils.h +129 -0
  872. data/ext/lpsolver-highs/highs/lp_data/HighsOptions.cpp +1176 -0
  873. data/ext/lpsolver-highs/highs/lp_data/HighsOptions.h +1715 -0
  874. data/ext/lpsolver-highs/highs/lp_data/HighsRanging.cpp +733 -0
  875. data/ext/lpsolver-highs/highs/lp_data/HighsRanging.h +43 -0
  876. data/ext/lpsolver-highs/highs/lp_data/HighsSolution.cpp +2194 -0
  877. data/ext/lpsolver-highs/highs/lp_data/HighsSolution.h +179 -0
  878. data/ext/lpsolver-highs/highs/lp_data/HighsSolutionDebug.cpp +490 -0
  879. data/ext/lpsolver-highs/highs/lp_data/HighsSolutionDebug.h +87 -0
  880. data/ext/lpsolver-highs/highs/lp_data/HighsSolve.cpp +747 -0
  881. data/ext/lpsolver-highs/highs/lp_data/HighsSolve.h +29 -0
  882. data/ext/lpsolver-highs/highs/lp_data/HighsStatus.cpp +48 -0
  883. data/ext/lpsolver-highs/highs/lp_data/HighsStatus.h +29 -0
  884. data/ext/lpsolver-highs/highs/lp_data/Iis.md +113 -0
  885. data/ext/lpsolver-highs/highs/meson.build +433 -0
  886. data/ext/lpsolver-highs/highs/mip/HighsCliqueTable.cpp +2236 -0
  887. data/ext/lpsolver-highs/highs/mip/HighsCliqueTable.h +329 -0
  888. data/ext/lpsolver-highs/highs/mip/HighsConflictPool.cpp +201 -0
  889. data/ext/lpsolver-highs/highs/mip/HighsConflictPool.h +109 -0
  890. data/ext/lpsolver-highs/highs/mip/HighsCutGeneration.cpp +1491 -0
  891. data/ext/lpsolver-highs/highs/mip/HighsCutGeneration.h +108 -0
  892. data/ext/lpsolver-highs/highs/mip/HighsCutPool.cpp +526 -0
  893. data/ext/lpsolver-highs/highs/mip/HighsCutPool.h +168 -0
  894. data/ext/lpsolver-highs/highs/mip/HighsDebugSol.cpp +313 -0
  895. data/ext/lpsolver-highs/highs/mip/HighsDebugSol.h +133 -0
  896. data/ext/lpsolver-highs/highs/mip/HighsDomain.cpp +3861 -0
  897. data/ext/lpsolver-highs/highs/mip/HighsDomain.h +657 -0
  898. data/ext/lpsolver-highs/highs/mip/HighsDomainChange.h +48 -0
  899. data/ext/lpsolver-highs/highs/mip/HighsDynamicRowMatrix.cpp +199 -0
  900. data/ext/lpsolver-highs/highs/mip/HighsDynamicRowMatrix.h +104 -0
  901. data/ext/lpsolver-highs/highs/mip/HighsFeasibilityJump.cpp +139 -0
  902. data/ext/lpsolver-highs/highs/mip/HighsGFkSolve.cpp +106 -0
  903. data/ext/lpsolver-highs/highs/mip/HighsGFkSolve.h +439 -0
  904. data/ext/lpsolver-highs/highs/mip/HighsImplications.cpp +915 -0
  905. data/ext/lpsolver-highs/highs/mip/HighsImplications.h +194 -0
  906. data/ext/lpsolver-highs/highs/mip/HighsLpAggregator.cpp +56 -0
  907. data/ext/lpsolver-highs/highs/mip/HighsLpAggregator.h +50 -0
  908. data/ext/lpsolver-highs/highs/mip/HighsLpRelaxation.cpp +1609 -0
  909. data/ext/lpsolver-highs/highs/mip/HighsLpRelaxation.h +361 -0
  910. data/ext/lpsolver-highs/highs/mip/HighsMipAnalysis.cpp +313 -0
  911. data/ext/lpsolver-highs/highs/mip/HighsMipAnalysis.h +71 -0
  912. data/ext/lpsolver-highs/highs/mip/HighsMipSolver.cpp +1002 -0
  913. data/ext/lpsolver-highs/highs/mip/HighsMipSolver.h +159 -0
  914. data/ext/lpsolver-highs/highs/mip/HighsMipSolverData.cpp +2936 -0
  915. data/ext/lpsolver-highs/highs/mip/HighsMipSolverData.h +313 -0
  916. data/ext/lpsolver-highs/highs/mip/HighsModkSeparator.cpp +267 -0
  917. data/ext/lpsolver-highs/highs/mip/HighsModkSeparator.h +60 -0
  918. data/ext/lpsolver-highs/highs/mip/HighsNodeQueue.cpp +443 -0
  919. data/ext/lpsolver-highs/highs/mip/HighsNodeQueue.h +312 -0
  920. data/ext/lpsolver-highs/highs/mip/HighsObjectiveFunction.cpp +124 -0
  921. data/ext/lpsolver-highs/highs/mip/HighsObjectiveFunction.h +71 -0
  922. data/ext/lpsolver-highs/highs/mip/HighsPathSeparator.cpp +549 -0
  923. data/ext/lpsolver-highs/highs/mip/HighsPathSeparator.h +39 -0
  924. data/ext/lpsolver-highs/highs/mip/HighsPrimalHeuristics.cpp +1673 -0
  925. data/ext/lpsolver-highs/highs/mip/HighsPrimalHeuristics.h +75 -0
  926. data/ext/lpsolver-highs/highs/mip/HighsPseudocost.cpp +129 -0
  927. data/ext/lpsolver-highs/highs/mip/HighsPseudocost.h +366 -0
  928. data/ext/lpsolver-highs/highs/mip/HighsRedcostFixing.cpp +316 -0
  929. data/ext/lpsolver-highs/highs/mip/HighsRedcostFixing.h +42 -0
  930. data/ext/lpsolver-highs/highs/mip/HighsSearch.cpp +1881 -0
  931. data/ext/lpsolver-highs/highs/mip/HighsSearch.h +241 -0
  932. data/ext/lpsolver-highs/highs/mip/HighsSeparation.cpp +186 -0
  933. data/ext/lpsolver-highs/highs/mip/HighsSeparation.h +41 -0
  934. data/ext/lpsolver-highs/highs/mip/HighsSeparator.cpp +39 -0
  935. data/ext/lpsolver-highs/highs/mip/HighsSeparator.h +60 -0
  936. data/ext/lpsolver-highs/highs/mip/HighsTableauSeparator.cpp +244 -0
  937. data/ext/lpsolver-highs/highs/mip/HighsTableauSeparator.h +34 -0
  938. data/ext/lpsolver-highs/highs/mip/HighsTransformedLp.cpp +563 -0
  939. data/ext/lpsolver-highs/highs/mip/HighsTransformedLp.h +63 -0
  940. data/ext/lpsolver-highs/highs/mip/MipTimer.h +544 -0
  941. data/ext/lpsolver-highs/highs/mip/feasibilityjump.hh +800 -0
  942. data/ext/lpsolver-highs/highs/model/HighsHessian.cpp +263 -0
  943. data/ext/lpsolver-highs/highs/model/HighsHessian.h +54 -0
  944. data/ext/lpsolver-highs/highs/model/HighsHessianUtils.cpp +584 -0
  945. data/ext/lpsolver-highs/highs/model/HighsHessianUtils.h +47 -0
  946. data/ext/lpsolver-highs/highs/model/HighsModel.cpp +46 -0
  947. data/ext/lpsolver-highs/highs/model/HighsModel.h +42 -0
  948. data/ext/lpsolver-highs/highs/parallel/HighsBinarySemaphore.h +108 -0
  949. data/ext/lpsolver-highs/highs/parallel/HighsCacheAlign.h +82 -0
  950. data/ext/lpsolver-highs/highs/parallel/HighsCombinable.h +116 -0
  951. data/ext/lpsolver-highs/highs/parallel/HighsMutex.h +124 -0
  952. data/ext/lpsolver-highs/highs/parallel/HighsParallel.h +128 -0
  953. data/ext/lpsolver-highs/highs/parallel/HighsRaceTimer.h +38 -0
  954. data/ext/lpsolver-highs/highs/parallel/HighsSchedulerConstants.h +19 -0
  955. data/ext/lpsolver-highs/highs/parallel/HighsSpinMutex.h +48 -0
  956. data/ext/lpsolver-highs/highs/parallel/HighsSplitDeque.h +606 -0
  957. data/ext/lpsolver-highs/highs/parallel/HighsTask.h +170 -0
  958. data/ext/lpsolver-highs/highs/parallel/HighsTaskExecutor.cpp +43 -0
  959. data/ext/lpsolver-highs/highs/parallel/HighsTaskExecutor.h +217 -0
  960. data/ext/lpsolver-highs/highs/pdlp/CupdlpWrapper.cpp +848 -0
  961. data/ext/lpsolver-highs/highs/pdlp/CupdlpWrapper.h +108 -0
  962. data/ext/lpsolver-highs/highs/pdlp/HiPdlpTimer.h +155 -0
  963. data/ext/lpsolver-highs/highs/pdlp/HiPdlpWrapper.cpp +141 -0
  964. data/ext/lpsolver-highs/highs/pdlp/HiPdlpWrapper.h +26 -0
  965. data/ext/lpsolver-highs/highs/pdlp/cupdlp/Diff +12 -0
  966. data/ext/lpsolver-highs/highs/pdlp/cupdlp/Meld +7 -0
  967. data/ext/lpsolver-highs/highs/pdlp/cupdlp/Merge +2 -0
  968. data/ext/lpsolver-highs/highs/pdlp/cupdlp/README.md +95 -0
  969. data/ext/lpsolver-highs/highs/pdlp/cupdlp/cuda/CMakeLists.txt +58 -0
  970. data/ext/lpsolver-highs/highs/pdlp/cupdlp/cuda/cupdlp_cuda_kernels.cu +338 -0
  971. data/ext/lpsolver-highs/highs/pdlp/cupdlp/cuda/cupdlp_cuda_kernels.cuh +319 -0
  972. data/ext/lpsolver-highs/highs/pdlp/cupdlp/cuda/cupdlp_cudalinalg.cu +386 -0
  973. data/ext/lpsolver-highs/highs/pdlp/cupdlp/cuda/cupdlp_cudalinalg.cuh +149 -0
  974. data/ext/lpsolver-highs/highs/pdlp/cupdlp/cuda/test_cublas.c +154 -0
  975. data/ext/lpsolver-highs/highs/pdlp/cupdlp/cuda/test_cuda_linalg.c +79 -0
  976. data/ext/lpsolver-highs/highs/pdlp/cupdlp/cupdlp.h +16 -0
  977. data/ext/lpsolver-highs/highs/pdlp/cupdlp/cupdlp_cs.c +214 -0
  978. data/ext/lpsolver-highs/highs/pdlp/cupdlp/cupdlp_cs.h +40 -0
  979. data/ext/lpsolver-highs/highs/pdlp/cupdlp/cupdlp_defs.h +447 -0
  980. data/ext/lpsolver-highs/highs/pdlp/cupdlp/cupdlp_linalg.c +802 -0
  981. data/ext/lpsolver-highs/highs/pdlp/cupdlp/cupdlp_linalg.h +189 -0
  982. data/ext/lpsolver-highs/highs/pdlp/cupdlp/cupdlp_proj.c +148 -0
  983. data/ext/lpsolver-highs/highs/pdlp/cupdlp/cupdlp_proj.h +19 -0
  984. data/ext/lpsolver-highs/highs/pdlp/cupdlp/cupdlp_restart.c +124 -0
  985. data/ext/lpsolver-highs/highs/pdlp/cupdlp/cupdlp_restart.h +31 -0
  986. data/ext/lpsolver-highs/highs/pdlp/cupdlp/cupdlp_scaling.c +425 -0
  987. data/ext/lpsolver-highs/highs/pdlp/cupdlp/cupdlp_scaling.h +26 -0
  988. data/ext/lpsolver-highs/highs/pdlp/cupdlp/cupdlp_solver.c +1498 -0
  989. data/ext/lpsolver-highs/highs/pdlp/cupdlp/cupdlp_solver.h +105 -0
  990. data/ext/lpsolver-highs/highs/pdlp/cupdlp/cupdlp_step.c +478 -0
  991. data/ext/lpsolver-highs/highs/pdlp/cupdlp/cupdlp_step.h +37 -0
  992. data/ext/lpsolver-highs/highs/pdlp/cupdlp/cupdlp_utils.c +1850 -0
  993. data/ext/lpsolver-highs/highs/pdlp/cupdlp/cupdlp_utils.h +212 -0
  994. data/ext/lpsolver-highs/highs/pdlp/cupdlp/glbopts.h +342 -0
  995. data/ext/lpsolver-highs/highs/pdlp/hipdlp/defs.hpp +222 -0
  996. data/ext/lpsolver-highs/highs/pdlp/hipdlp/linalg.cc +231 -0
  997. data/ext/lpsolver-highs/highs/pdlp/hipdlp/linalg.hpp +61 -0
  998. data/ext/lpsolver-highs/highs/pdlp/hipdlp/logger.cc +225 -0
  999. data/ext/lpsolver-highs/highs/pdlp/hipdlp/logger.hpp +80 -0
  1000. data/ext/lpsolver-highs/highs/pdlp/hipdlp/pdhg.cc +2798 -0
  1001. data/ext/lpsolver-highs/highs/pdlp/hipdlp/pdhg.cu +497 -0
  1002. data/ext/lpsolver-highs/highs/pdlp/hipdlp/pdhg.hpp +358 -0
  1003. data/ext/lpsolver-highs/highs/pdlp/hipdlp/pdhg_kernels.hpp +77 -0
  1004. data/ext/lpsolver-highs/highs/pdlp/hipdlp/pdlp_gpu_debug.hpp +62 -0
  1005. data/ext/lpsolver-highs/highs/pdlp/hipdlp/restart.cc +132 -0
  1006. data/ext/lpsolver-highs/highs/pdlp/hipdlp/restart.hpp +96 -0
  1007. data/ext/lpsolver-highs/highs/pdlp/hipdlp/scaling.cc +307 -0
  1008. data/ext/lpsolver-highs/highs/pdlp/hipdlp/scaling.hpp +74 -0
  1009. data/ext/lpsolver-highs/highs/pdlp/hipdlp/solver_results.hpp +65 -0
  1010. data/ext/lpsolver-highs/highs/presolve/HPresolve.cpp +8511 -0
  1011. data/ext/lpsolver-highs/highs/presolve/HPresolve.h +505 -0
  1012. data/ext/lpsolver-highs/highs/presolve/HPresolveAnalysis.cpp +239 -0
  1013. data/ext/lpsolver-highs/highs/presolve/HPresolveAnalysis.h +52 -0
  1014. data/ext/lpsolver-highs/highs/presolve/HighsPostsolveStack.cpp +1368 -0
  1015. data/ext/lpsolver-highs/highs/presolve/HighsPostsolveStack.h +943 -0
  1016. data/ext/lpsolver-highs/highs/presolve/HighsSymmetry.cpp +1921 -0
  1017. data/ext/lpsolver-highs/highs/presolve/HighsSymmetry.h +284 -0
  1018. data/ext/lpsolver-highs/highs/presolve/ICrash.cpp +474 -0
  1019. data/ext/lpsolver-highs/highs/presolve/ICrash.h +124 -0
  1020. data/ext/lpsolver-highs/highs/presolve/ICrashUtil.cpp +267 -0
  1021. data/ext/lpsolver-highs/highs/presolve/ICrashUtil.h +62 -0
  1022. data/ext/lpsolver-highs/highs/presolve/ICrashX.cpp +173 -0
  1023. data/ext/lpsolver-highs/highs/presolve/ICrashX.h +23 -0
  1024. data/ext/lpsolver-highs/highs/presolve/PresolveComponent.cpp +45 -0
  1025. data/ext/lpsolver-highs/highs/presolve/PresolveComponent.h +90 -0
  1026. data/ext/lpsolver-highs/highs/qpsolver/README.md +185 -0
  1027. data/ext/lpsolver-highs/highs/qpsolver/a_asm.cpp +139 -0
  1028. data/ext/lpsolver-highs/highs/qpsolver/a_asm.hpp +77 -0
  1029. data/ext/lpsolver-highs/highs/qpsolver/a_quass.cpp +194 -0
  1030. data/ext/lpsolver-highs/highs/qpsolver/a_quass.hpp +22 -0
  1031. data/ext/lpsolver-highs/highs/qpsolver/basis.cpp +443 -0
  1032. data/ext/lpsolver-highs/highs/qpsolver/basis.hpp +159 -0
  1033. data/ext/lpsolver-highs/highs/qpsolver/crashsolution.hpp +20 -0
  1034. data/ext/lpsolver-highs/highs/qpsolver/dantzigpricing.hpp +80 -0
  1035. data/ext/lpsolver-highs/highs/qpsolver/devexharrispricing.hpp +98 -0
  1036. data/ext/lpsolver-highs/highs/qpsolver/devexpricing.hpp +108 -0
  1037. data/ext/lpsolver-highs/highs/qpsolver/eventhandler.hpp +30 -0
  1038. data/ext/lpsolver-highs/highs/qpsolver/factor.hpp +408 -0
  1039. data/ext/lpsolver-highs/highs/qpsolver/feasibility_bounded.hpp +114 -0
  1040. data/ext/lpsolver-highs/highs/qpsolver/feasibility_highs.hpp +301 -0
  1041. data/ext/lpsolver-highs/highs/qpsolver/gradient.hpp +46 -0
  1042. data/ext/lpsolver-highs/highs/qpsolver/instance.hpp +70 -0
  1043. data/ext/lpsolver-highs/highs/qpsolver/matrix.hpp +342 -0
  1044. data/ext/lpsolver-highs/highs/qpsolver/perturbation.cpp +41 -0
  1045. data/ext/lpsolver-highs/highs/qpsolver/perturbation.hpp +15 -0
  1046. data/ext/lpsolver-highs/highs/qpsolver/pricing.hpp +22 -0
  1047. data/ext/lpsolver-highs/highs/qpsolver/qpconst.hpp +34 -0
  1048. data/ext/lpsolver-highs/highs/qpsolver/qpvector.hpp +242 -0
  1049. data/ext/lpsolver-highs/highs/qpsolver/quass.cpp +551 -0
  1050. data/ext/lpsolver-highs/highs/qpsolver/quass.hpp +27 -0
  1051. data/ext/lpsolver-highs/highs/qpsolver/ratiotest.cpp +146 -0
  1052. data/ext/lpsolver-highs/highs/qpsolver/ratiotest.hpp +26 -0
  1053. data/ext/lpsolver-highs/highs/qpsolver/reducedcosts.hpp +46 -0
  1054. data/ext/lpsolver-highs/highs/qpsolver/reducedgradient.hpp +95 -0
  1055. data/ext/lpsolver-highs/highs/qpsolver/runtime.hpp +45 -0
  1056. data/ext/lpsolver-highs/highs/qpsolver/scaling.cpp +123 -0
  1057. data/ext/lpsolver-highs/highs/qpsolver/scaling.hpp +15 -0
  1058. data/ext/lpsolver-highs/highs/qpsolver/settings.hpp +84 -0
  1059. data/ext/lpsolver-highs/highs/qpsolver/snippets.hpp +36 -0
  1060. data/ext/lpsolver-highs/highs/qpsolver/statistics.hpp +30 -0
  1061. data/ext/lpsolver-highs/highs/qpsolver/steepestedgepricing.hpp +173 -0
  1062. data/ext/lpsolver-highs/highs/simplex/HApp.h +550 -0
  1063. data/ext/lpsolver-highs/highs/simplex/HEkk.cpp +4404 -0
  1064. data/ext/lpsolver-highs/highs/simplex/HEkk.h +419 -0
  1065. data/ext/lpsolver-highs/highs/simplex/HEkkControl.cpp +146 -0
  1066. data/ext/lpsolver-highs/highs/simplex/HEkkDebug.cpp +1722 -0
  1067. data/ext/lpsolver-highs/highs/simplex/HEkkDual.cpp +3003 -0
  1068. data/ext/lpsolver-highs/highs/simplex/HEkkDual.h +513 -0
  1069. data/ext/lpsolver-highs/highs/simplex/HEkkDualMulti.cpp +1020 -0
  1070. data/ext/lpsolver-highs/highs/simplex/HEkkDualRHS.cpp +535 -0
  1071. data/ext/lpsolver-highs/highs/simplex/HEkkDualRHS.h +134 -0
  1072. data/ext/lpsolver-highs/highs/simplex/HEkkDualRow.cpp +697 -0
  1073. data/ext/lpsolver-highs/highs/simplex/HEkkDualRow.h +201 -0
  1074. data/ext/lpsolver-highs/highs/simplex/HEkkInterface.cpp +26 -0
  1075. data/ext/lpsolver-highs/highs/simplex/HEkkPrimal.cpp +2984 -0
  1076. data/ext/lpsolver-highs/highs/simplex/HEkkPrimal.h +191 -0
  1077. data/ext/lpsolver-highs/highs/simplex/HSimplex.cpp +330 -0
  1078. data/ext/lpsolver-highs/highs/simplex/HSimplex.h +42 -0
  1079. data/ext/lpsolver-highs/highs/simplex/HSimplexDebug.cpp +145 -0
  1080. data/ext/lpsolver-highs/highs/simplex/HSimplexDebug.h +48 -0
  1081. data/ext/lpsolver-highs/highs/simplex/HSimplexNla.cpp +517 -0
  1082. data/ext/lpsolver-highs/highs/simplex/HSimplexNla.h +158 -0
  1083. data/ext/lpsolver-highs/highs/simplex/HSimplexNlaDebug.cpp +373 -0
  1084. data/ext/lpsolver-highs/highs/simplex/HSimplexNlaFreeze.cpp +28 -0
  1085. data/ext/lpsolver-highs/highs/simplex/HSimplexNlaProductForm.cpp +113 -0
  1086. data/ext/lpsolver-highs/highs/simplex/HSimplexReport.cpp +77 -0
  1087. data/ext/lpsolver-highs/highs/simplex/HSimplexReport.h +21 -0
  1088. data/ext/lpsolver-highs/highs/simplex/HighsSimplexAnalysis.cpp +1495 -0
  1089. data/ext/lpsolver-highs/highs/simplex/HighsSimplexAnalysis.h +500 -0
  1090. data/ext/lpsolver-highs/highs/simplex/SimplexConst.h +273 -0
  1091. data/ext/lpsolver-highs/highs/simplex/SimplexStruct.h +263 -0
  1092. data/ext/lpsolver-highs/highs/simplex/SimplexTimer.h +414 -0
  1093. data/ext/lpsolver-highs/highs/test_kkt/DevKkt.cpp +469 -0
  1094. data/ext/lpsolver-highs/highs/test_kkt/DevKkt.h +143 -0
  1095. data/ext/lpsolver-highs/highs/test_kkt/KktCh2.cpp +305 -0
  1096. data/ext/lpsolver-highs/highs/test_kkt/KktCh2.h +79 -0
  1097. data/ext/lpsolver-highs/highs/util/FactorTimer.h +199 -0
  1098. data/ext/lpsolver-highs/highs/util/HFactor.cpp +2597 -0
  1099. data/ext/lpsolver-highs/highs/util/HFactor.h +587 -0
  1100. data/ext/lpsolver-highs/highs/util/HFactorConst.h +81 -0
  1101. data/ext/lpsolver-highs/highs/util/HFactorDebug.cpp +231 -0
  1102. data/ext/lpsolver-highs/highs/util/HFactorDebug.h +55 -0
  1103. data/ext/lpsolver-highs/highs/util/HFactorExtend.cpp +229 -0
  1104. data/ext/lpsolver-highs/highs/util/HFactorRefactor.cpp +304 -0
  1105. data/ext/lpsolver-highs/highs/util/HFactorUtils.cpp +122 -0
  1106. data/ext/lpsolver-highs/highs/util/HSet.cpp +197 -0
  1107. data/ext/lpsolver-highs/highs/util/HSet.h +89 -0
  1108. data/ext/lpsolver-highs/highs/util/HVector.h +22 -0
  1109. data/ext/lpsolver-highs/highs/util/HVectorBase.cpp +271 -0
  1110. data/ext/lpsolver-highs/highs/util/HVectorBase.h +102 -0
  1111. data/ext/lpsolver-highs/highs/util/HighsCDouble.h +323 -0
  1112. data/ext/lpsolver-highs/highs/util/HighsComponent.h +53 -0
  1113. data/ext/lpsolver-highs/highs/util/HighsDataStack.h +83 -0
  1114. data/ext/lpsolver-highs/highs/util/HighsDisjointSets.h +107 -0
  1115. data/ext/lpsolver-highs/highs/util/HighsHash.cpp +10 -0
  1116. data/ext/lpsolver-highs/highs/util/HighsHash.h +1274 -0
  1117. data/ext/lpsolver-highs/highs/util/HighsHashTree.h +1461 -0
  1118. data/ext/lpsolver-highs/highs/util/HighsInt.h +36 -0
  1119. data/ext/lpsolver-highs/highs/util/HighsIntegers.h +212 -0
  1120. data/ext/lpsolver-highs/highs/util/HighsLinearSumBounds.cpp +267 -0
  1121. data/ext/lpsolver-highs/highs/util/HighsLinearSumBounds.h +203 -0
  1122. data/ext/lpsolver-highs/highs/util/HighsMatrixPic.cpp +146 -0
  1123. data/ext/lpsolver-highs/highs/util/HighsMatrixPic.h +37 -0
  1124. data/ext/lpsolver-highs/highs/util/HighsMatrixSlice.h +561 -0
  1125. data/ext/lpsolver-highs/highs/util/HighsMatrixUtils.cpp +407 -0
  1126. data/ext/lpsolver-highs/highs/util/HighsMatrixUtils.h +57 -0
  1127. data/ext/lpsolver-highs/highs/util/HighsMemoryAllocation.h +63 -0
  1128. data/ext/lpsolver-highs/highs/util/HighsRandom.h +242 -0
  1129. data/ext/lpsolver-highs/highs/util/HighsRbTree.h +452 -0
  1130. data/ext/lpsolver-highs/highs/util/HighsSort.cpp +364 -0
  1131. data/ext/lpsolver-highs/highs/util/HighsSort.h +131 -0
  1132. data/ext/lpsolver-highs/highs/util/HighsSparseMatrix.cpp +1746 -0
  1133. data/ext/lpsolver-highs/highs/util/HighsSparseMatrix.h +151 -0
  1134. data/ext/lpsolver-highs/highs/util/HighsSparseVectorSum.h +95 -0
  1135. data/ext/lpsolver-highs/highs/util/HighsSplay.h +135 -0
  1136. data/ext/lpsolver-highs/highs/util/HighsTimer.h +385 -0
  1137. data/ext/lpsolver-highs/highs/util/HighsUtils.cpp +1259 -0
  1138. data/ext/lpsolver-highs/highs/util/HighsUtils.h +272 -0
  1139. data/ext/lpsolver-highs/highs/util/stringutil.cpp +131 -0
  1140. data/ext/lpsolver-highs/highs/util/stringutil.h +46 -0
  1141. data/ext/lpsolver-highs/highs.pc.in +12 -0
  1142. data/ext/lpsolver-highs/meson.build +198 -0
  1143. data/ext/lpsolver-highs/meson_options.txt +31 -0
  1144. data/ext/lpsolver-highs/nuget/HiGHS_Logo.png +0 -0
  1145. data/ext/lpsolver-highs/nuget/Highs.csproj +25 -0
  1146. data/ext/lpsolver-highs/nuget/Highs.csproj.in +36 -0
  1147. data/ext/lpsolver-highs/nuget/HowToAlternative.md +77 -0
  1148. data/ext/lpsolver-highs/nuget/README.md +38 -0
  1149. data/ext/lpsolver-highs/nuget/arm-toolchain.cmake +15 -0
  1150. data/ext/lpsolver-highs/nuget/build_linux-arm.sh +13 -0
  1151. data/ext/lpsolver-highs/nuget/build_linux.sh +10 -0
  1152. data/ext/lpsolver-highs/nuget/build_windows.ps1 +27 -0
  1153. data/ext/lpsolver-highs/nuget/generatePackage.ps1 +28 -0
  1154. data/ext/lpsolver-highs/pyproject.toml +221 -0
  1155. data/ext/lpsolver-highs/subprojects/pybind11.wrap +13 -0
  1156. data/ext/lpsolver-highs/tests/test_highspy.py +2310 -0
  1157. data/ext/lpsolver-highs/version.rc.in +50 -0
  1158. data/lib/lpsolver/highs +0 -0
  1159. data/lib/lpsolver/model.rb +35 -7
  1160. data/lib/lpsolver/native.so +0 -0
  1161. data/lib/lpsolver/native_model.rb +261 -0
  1162. data/lib/lpsolver/solution.rb +93 -8
  1163. data/lib/lpsolver/version.rb +1 -1
  1164. data/lpsolver.gemspec +4 -1
  1165. metadata +1176 -4
@@ -0,0 +1,2936 @@
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
+ #include "mip/HighsMipSolverData.h"
9
+
10
+ #include <random>
11
+ #include <sstream>
12
+
13
+ #include "../extern/pdqsort/pdqsort.h"
14
+ #include "lp_data/HighsModelUtils.h"
15
+ #include "mip/HighsPseudocost.h"
16
+ #include "mip/HighsRedcostFixing.h"
17
+ #include "mip/MipTimer.h"
18
+ #include "parallel/HighsParallel.h"
19
+ #include "presolve/HPresolve.h"
20
+ #include "util/HighsIntegers.h"
21
+
22
+ std::string HighsMipSolverData::solutionSourceToString(
23
+ const int solution_source, const bool code) const {
24
+ if (solution_source == kSolutionSourceNone) {
25
+ if (code) return " ";
26
+ return "None";
27
+ // } else if (solution_source == kSolutionSourceInitial) {
28
+ // if (code) return "0";
29
+ // return "Initial";
30
+ } else if (solution_source == kSolutionSourceBranching) {
31
+ if (code) return "B";
32
+ return "Branching";
33
+ } else if (solution_source == kSolutionSourceCentralRounding) {
34
+ if (code) return "C";
35
+ return "Central rounding";
36
+ } else if (solution_source == kSolutionSourceFeasibilityPump) {
37
+ if (code) return "F";
38
+ return "Feasibility pump";
39
+ } else if (solution_source == kSolutionSourceHeuristic) {
40
+ if (code) return "H";
41
+ return "Heuristic";
42
+ } else if (solution_source == kSolutionSourceShifting) {
43
+ if (code) return "I";
44
+ return "Shifting";
45
+ } else if (solution_source == kSolutionSourceFeasibilityJump) {
46
+ if (code) return "J";
47
+ return "Feasibility jump";
48
+ } else if (solution_source == kSolutionSourceSubMip) {
49
+ if (code) return "L";
50
+ return "Sub-MIP";
51
+ } else if (solution_source == kSolutionSourceEmptyMip) {
52
+ if (code) return "P";
53
+ return "Empty MIP";
54
+ } else if (solution_source == kSolutionSourceRandomizedRounding) {
55
+ if (code) return "R";
56
+ return "Randomized rounding";
57
+ } else if (solution_source == kSolutionSourceSolveLp) {
58
+ if (code) return "S";
59
+ return "Solve LP";
60
+ } else if (solution_source == kSolutionSourceEvaluateNode) {
61
+ if (code) return "T";
62
+ return "Evaluate node";
63
+ } else if (solution_source == kSolutionSourceUnbounded) {
64
+ if (code) return "U";
65
+ return "Unbounded";
66
+ } else if (solution_source == kSolutionSourceUserSolution) {
67
+ if (code) return "X";
68
+ return "User solution";
69
+ } else if (solution_source == kSolutionSourceHighsSolution) {
70
+ if (code) return "Y";
71
+ return "HiGHS solution";
72
+ } else if (solution_source == kSolutionSourceZiRound) {
73
+ if (code) return "Z";
74
+ return "ZI Round";
75
+ } else if (solution_source == kSolutionSourceTrivialZ) {
76
+ if (code) return "z";
77
+ return "Trivial zero";
78
+ } else if (solution_source == kSolutionSourceTrivialL) {
79
+ if (code) return "l";
80
+ return "Trivial lower";
81
+ } else if (solution_source == kSolutionSourceTrivialU) {
82
+ if (code) return "u";
83
+ return "Trivial upper";
84
+ } else if (solution_source == kSolutionSourceTrivialP) {
85
+ if (code) return "p";
86
+ return "Trivial point";
87
+ } else if (solution_source == kSolutionSourceCleanup) {
88
+ if (code) return " ";
89
+ return "";
90
+ } else {
91
+ printf("HighsMipSolverData::solutionSourceToString: Unknown source = %d\n",
92
+ solution_source);
93
+ assert(0 == 111);
94
+ if (code) return "*";
95
+ return "None";
96
+ }
97
+ }
98
+
99
+ bool HighsMipSolverData::checkSolution(
100
+ const std::vector<double>& solution) const {
101
+ for (HighsInt i = 0; i != mipsolver.numCol(); ++i) {
102
+ if (solution[i] < mipsolver.model_->col_lower_[i] - feastol) return false;
103
+ if (solution[i] > mipsolver.model_->col_upper_[i] + feastol) return false;
104
+ if (mipsolver.isColInteger(i) && fractionality(solution[i]) > feastol)
105
+ return false;
106
+ }
107
+
108
+ for (HighsInt i = 0; i != mipsolver.numRow(); ++i) {
109
+ double rowactivity = 0.0;
110
+
111
+ HighsInt start = ARstart_[i];
112
+ HighsInt end = ARstart_[i + 1];
113
+
114
+ for (HighsInt j = start; j != end; ++j)
115
+ rowactivity += solution[ARindex_[j]] * ARvalue_[j];
116
+
117
+ if (rowactivity > mipsolver.rowUpper(i) + feastol) return false;
118
+ if (rowactivity < mipsolver.rowLower(i) - feastol) return false;
119
+ }
120
+
121
+ return true;
122
+ }
123
+
124
+ std::vector<std::tuple<HighsInt, HighsInt, double>>
125
+ HighsMipSolverData::getInfeasibleRows(
126
+ const std::vector<double>& solution) const {
127
+ std::vector<std::tuple<HighsInt, HighsInt, double>> infeasibleRows;
128
+ for (HighsInt i = 0; i != mipsolver.numRow(); ++i) {
129
+ HighsInt start = ARstart_[i];
130
+ HighsInt end = ARstart_[i + 1];
131
+
132
+ HighsCDouble row_activity_quad = 0.0;
133
+ for (HighsInt j = start; j != end; ++j)
134
+ row_activity_quad +=
135
+ static_cast<HighsCDouble>(solution[ARindex_[j]]) * ARvalue_[j];
136
+
137
+ double row_activity = static_cast<double>(row_activity_quad);
138
+ if (row_activity > mipsolver.rowUpper(i) + feastol) {
139
+ double difference = std::abs(row_activity - mipsolver.rowUpper(i));
140
+ infeasibleRows.push_back({i, +1, difference});
141
+ }
142
+ if (row_activity < mipsolver.rowLower(i) - feastol) {
143
+ double difference = std::abs(mipsolver.rowLower(i) - row_activity);
144
+ infeasibleRows.push_back({i, -1, difference});
145
+ }
146
+ }
147
+ return infeasibleRows;
148
+ }
149
+
150
+ bool HighsMipSolverData::trySolution(const std::vector<double>& solution,
151
+ const int solution_source) {
152
+ if (int(solution.size()) != mipsolver.numCol()) return false;
153
+
154
+ HighsCDouble obj = 0;
155
+
156
+ for (HighsInt i = 0; i != mipsolver.numCol(); ++i) {
157
+ if (solution[i] < mipsolver.model_->col_lower_[i] - feastol) return false;
158
+ if (solution[i] > mipsolver.model_->col_upper_[i] + feastol) return false;
159
+ if (mipsolver.isColInteger(i) && fractionality(solution[i]) > feastol)
160
+ return false;
161
+
162
+ obj += mipsolver.colCost(i) * solution[i];
163
+ }
164
+
165
+ for (HighsInt i = 0; i != mipsolver.numRow(); ++i) {
166
+ double rowactivity = 0.0;
167
+
168
+ HighsInt start = ARstart_[i];
169
+ HighsInt end = ARstart_[i + 1];
170
+
171
+ for (HighsInt j = start; j != end; ++j)
172
+ rowactivity += solution[ARindex_[j]] * ARvalue_[j];
173
+
174
+ if (rowactivity > mipsolver.rowUpper(i) + feastol) return false;
175
+ if (rowactivity < mipsolver.rowLower(i) - feastol) return false;
176
+ }
177
+
178
+ return addIncumbent(solution, double(obj), solution_source);
179
+ }
180
+
181
+ bool HighsMipSolverData::solutionRowFeasible(
182
+ const std::vector<double>& solution) const {
183
+ for (HighsInt i = 0; i != mipsolver.numRow(); ++i) {
184
+ HighsCDouble c_double_rowactivity = HighsCDouble(0.0);
185
+
186
+ HighsInt start = ARstart_[i];
187
+ HighsInt end = ARstart_[i + 1];
188
+
189
+ for (HighsInt j = start; j != end; ++j)
190
+ c_double_rowactivity += HighsCDouble(solution[ARindex_[j]] * ARvalue_[j]);
191
+
192
+ double rowactivity = double(c_double_rowactivity);
193
+ if (rowactivity > mipsolver.rowUpper(i) + feastol) return false;
194
+ if (rowactivity < mipsolver.rowLower(i) - feastol) return false;
195
+ }
196
+ return true;
197
+ }
198
+
199
+ HighsModelStatus HighsMipSolverData::trivialHeuristics() {
200
+ // printf("\nHighsMipSolverData::trivialHeuristics() Number of continuous
201
+ // columns is %d\n",
202
+ // int(continuous_cols.size()));
203
+ if (continuous_cols.size() > 0) return HighsModelStatus::kNotset;
204
+ const HighsInt num_try_heuristic = 4;
205
+ const std::vector<int> heuristic_source = {
206
+ kSolutionSourceTrivialZ, kSolutionSourceTrivialL, kSolutionSourceTrivialU,
207
+ kSolutionSourceTrivialP};
208
+
209
+ std::vector<double> col_lower = mipsolver.model_->col_lower_;
210
+ std::vector<double> col_upper = mipsolver.model_->col_upper_;
211
+ const std::vector<double>& row_lower = mipsolver.model_->row_lower_;
212
+ const std::vector<double>& row_upper = mipsolver.model_->row_upper_;
213
+ const HighsSparseMatrix& matrix = mipsolver.model_->a_matrix_;
214
+ // Determine the following properties, according to which some
215
+ // trivial heuristics are duplicated or fail immediately
216
+ bool all_integer_lower_non_positive = true;
217
+ bool all_integer_lower_zero = true;
218
+ bool all_integer_lower_finite = true;
219
+ bool all_integer_upper_finite = true;
220
+ for (HighsInt integer_col = 0; integer_col < numintegercols; integer_col++) {
221
+ HighsInt iCol = integer_cols[integer_col];
222
+ // Round bounds in to nearest integer
223
+ col_lower[iCol] = std::ceil(col_lower[iCol]);
224
+ col_upper[iCol] = std::floor(col_upper[iCol]);
225
+ const bool legal_bounds =
226
+ col_lower[iCol] <= col_upper[iCol] && col_lower[iCol] < kHighsInf &&
227
+ col_upper[iCol] > -kHighsInf && !std::isnan(col_lower[iCol]) &&
228
+ !std::isnan(col_upper[iCol]);
229
+ if (!legal_bounds) {
230
+ assert(legal_bounds);
231
+ highsLogUser(mipsolver.options_mip_->log_options, HighsLogType::kInfo,
232
+ "HighsMipSolverData::trivialHeuristics() has detected "
233
+ "infeasible/illegal bounds [%g, %g] for column %d: MIP is "
234
+ "infeasible\n",
235
+ col_lower[iCol], col_upper[iCol], int(iCol));
236
+ return HighsModelStatus::kInfeasible;
237
+ }
238
+ // If bounds are inconsistent then MIP is infeasible
239
+ if (col_lower[iCol] > col_upper[iCol]) return HighsModelStatus::kInfeasible;
240
+
241
+ if (col_lower[iCol] > 0) all_integer_lower_non_positive = false;
242
+ if (col_lower[iCol]) all_integer_lower_zero = false;
243
+ if (col_lower[iCol] <= -kHighsInf) all_integer_lower_finite = false;
244
+ if (col_upper[iCol] >= kHighsInf) all_integer_upper_finite = false;
245
+ // Only continue if one of the properties still holds
246
+ if (!(all_integer_lower_non_positive || all_integer_lower_zero ||
247
+ all_integer_upper_finite))
248
+ break;
249
+ }
250
+ const bool all_integer_boxed =
251
+ all_integer_lower_finite && all_integer_upper_finite;
252
+ // printf(
253
+ // "Trying trivial heuristics\n"
254
+ // " all_integer_lower_non_positive = %d\n"
255
+ // " all_integer_lower_zero = %d\n"
256
+ // " all_integer_upper_finite = %d\n"
257
+ // " all_integer_boxed = %d\n",
258
+ // all_integer_lower_non_positive, all_integer_lower_zero,
259
+ // all_integer_upper_finite, all_integer_boxed);
260
+ const double feasibility_tolerance =
261
+ mipsolver.options_mip_->mip_feasibility_tolerance;
262
+ // Loop through the trivial heuristics
263
+ std::vector<double> solution(mipsolver.numCol());
264
+ for (HighsInt try_heuristic = 0; try_heuristic < num_try_heuristic;
265
+ try_heuristic++) {
266
+ if (try_heuristic == 0) {
267
+ // First heuristic is to see whether all-zero for integer
268
+ // variables is feasible
269
+ //
270
+ // If there is a positive lower bound then the heuristic fails
271
+ if (!all_integer_lower_non_positive) continue;
272
+ // Determine whether a zero row activity is feasible
273
+ bool heuristic_failed = false;
274
+ for (HighsInt iRow = 0; iRow < mipsolver.numRow(); iRow++) {
275
+ if (row_lower[iRow] > feasibility_tolerance ||
276
+ row_upper[iRow] < -feasibility_tolerance) {
277
+ heuristic_failed = true;
278
+ break;
279
+ }
280
+ }
281
+ if (heuristic_failed) continue;
282
+ solution.assign(mipsolver.numCol(), 0);
283
+ } else if (try_heuristic == 1) {
284
+ // Second heuristic is to see whether all-lower for integer
285
+ // variables (if distinct from all-zero) is feasible
286
+ if (all_integer_lower_zero) continue;
287
+ // Trivially feasible for columns
288
+ if (!solutionRowFeasible(col_lower)) continue;
289
+ solution = col_lower;
290
+ } else if (try_heuristic == 2) {
291
+ // Third heuristic is to see whether all-upper for integer
292
+ // variables is feasible
293
+ //
294
+ // If there is an infinite upper bound then the heuristic fails
295
+ if (!all_integer_upper_finite) continue;
296
+ // Trivially feasible for columns
297
+ if (!solutionRowFeasible(col_upper)) continue;
298
+ solution = col_upper;
299
+ } else if (try_heuristic == 3) {
300
+ // Fourth heuristic is to see whether the "lock point" is feasible
301
+ if (!all_integer_boxed) continue;
302
+ for (HighsInt integer_col = 0; integer_col < numintegercols;
303
+ integer_col++) {
304
+ HighsInt iCol = integer_cols[integer_col];
305
+ HighsInt num_positive_values = 0;
306
+ HighsInt num_negative_values = 0;
307
+ for (HighsInt iEl = matrix.start_[iCol]; iEl < matrix.start_[iCol + 1];
308
+ iEl++) {
309
+ if (matrix.value_[iEl] > 0)
310
+ num_positive_values++;
311
+ else
312
+ num_negative_values++;
313
+ }
314
+ solution[iCol] = num_positive_values > num_negative_values
315
+ ? col_lower[iCol]
316
+ : col_upper[iCol];
317
+ }
318
+ // Trivially feasible for columns
319
+ if (!solutionRowFeasible(solution)) continue;
320
+ }
321
+
322
+ HighsCDouble cdouble_obj = 0.0;
323
+ for (HighsInt iCol = 0; iCol < mipsolver.numCol(); iCol++)
324
+ cdouble_obj += mipsolver.colCost(iCol) * solution[iCol];
325
+ double obj = double(cdouble_obj);
326
+ const double save_upper_bound = upper_bound;
327
+ const bool new_incumbent =
328
+ addIncumbent(solution, obj, heuristic_source[try_heuristic]);
329
+ const bool lc_report = false;
330
+ if (lc_report) {
331
+ printf("Trivial heuristic %d has succeeded: objective = %g",
332
+ int(try_heuristic), obj);
333
+ if (new_incumbent) {
334
+ printf("; upper bound from %g to %g\n", save_upper_bound, upper_bound);
335
+ } else {
336
+ printf("\n");
337
+ }
338
+ }
339
+ }
340
+ return HighsModelStatus::kNotset;
341
+ }
342
+
343
+ void HighsMipSolverData::startAnalyticCenterComputation(
344
+ const highs::parallel::TaskGroup& taskGroup) {
345
+ taskGroup.spawn([&]() {
346
+ // first check if the analytic centre computation should be cancelled, e.g.
347
+ // due to early return in the root node evaluation
348
+ Highs ipm;
349
+ ipm.setOptionValue("output_flag", false);
350
+ const std::vector<double>& sol = ipm.getSolution().col_value;
351
+ // Don't use presolve - because this can lead to postsolve putting
352
+ // integer variables onto bounds. This is not just a "less good"
353
+ // AC. It can have implications leading to erroneous fixing of
354
+ // variables and a suboptimal solution declared as optimal.
355
+ ipm.setOptionValue("presolve", kHighsOffString);
356
+ // Determine the solver
357
+ const std::string mip_ipm_solver = mipsolver.options_mip_->mip_ipm_solver;
358
+ // Currently use IPX by default and take action on failure here if
359
+ // using HiPO.
360
+ bool use_hipo =
361
+ /*
362
+ #ifdef HIPO
363
+ // Later use HiPO by default
364
+ mip_ipm_solver == kHighsChooseString ||
365
+ #endif
366
+ */
367
+ mip_ipm_solver == kHipoString;
368
+ // Later still, pass mip_ipm_solver and take action on failure in
369
+ // solveLp
370
+ #ifndef HIPO
371
+ // Shouldn't be possible to choose HiPO if it's not in the build
372
+ assert(!use_hipo);
373
+ use_hipo = false;
374
+ #endif
375
+ const std::string ipm_solver = use_hipo ? kHipoString : kIpxString;
376
+ ipm.setOptionValue("solver", ipm_solver);
377
+ ipm.setOptionValue("ipm_iteration_limit", 200);
378
+ ipm.setOptionValue("run_crossover", kHighsOffString);
379
+ ipm.setOptionValue("run_centring", true);
380
+ HighsLp lpmodel(*mipsolver.model_);
381
+ lpmodel.col_cost_.assign(lpmodel.num_col_, 0.0);
382
+ lpmodel.integrality_.clear();
383
+ ipm.passModel(std::move(lpmodel));
384
+ const bool dump_ipm_lp = false;
385
+ if (dump_ipm_lp && !mipsolver.submip) {
386
+ const std::string file_name = mipsolver.model_->model_name_ + "_ac.mps";
387
+ printf(
388
+ "HighsMipSolverData::startAnalyticCenterComputation: Calling "
389
+ "ipm.writeModel(%s)\n",
390
+ file_name.c_str());
391
+ ipm.writeModel(file_name);
392
+ fflush(stdout);
393
+ exit(1);
394
+ }
395
+ const bool ipm_logging = false;
396
+ if (ipm_logging) {
397
+ bool output_flag;
398
+ ipm.getOptionValue("output_flag", output_flag);
399
+ assert(output_flag == false);
400
+ (void)output_flag;
401
+ ipm.setOptionValue("output_flag", !mipsolver.submip);
402
+ }
403
+ ipm.optimizeLp();
404
+ if (ipm_logging) ipm.setOptionValue("output_flag", false);
405
+ if (use_hipo && mip_ipm_solver == kHighsChooseString &&
406
+ HighsInt(sol.size()) != mipsolver.numCol()) {
407
+ printf(
408
+ "In HighsMipSolverData::startAnalyticCenterComputation HiPO has "
409
+ "failed to get a solution: status = %s Try IPX\n",
410
+ ipm.modelStatusToString(ipm.getModelStatus()).c_str());
411
+ // HiPO has failed to get a solution, so try IPX
412
+ ipm.setOptionValue("solver", kIpxString);
413
+ ipm.optimizeLp();
414
+ }
415
+ if (!mipsolver.submip) {
416
+ const HighsSubSolverCallTime& sub_solver_call_time =
417
+ ipm.getSubSolverCallTime();
418
+ const bool analytic_centre = true;
419
+ mipsolver.analysis_.addSubSolverCallTime(sub_solver_call_time,
420
+ analytic_centre);
421
+ // Go through sub_solver_call_time to update any MIP clocks
422
+ const bool valid_basis = false;
423
+ const bool use_presolve = false;
424
+ mipsolver.analysis_.mipTimerUpdate(sub_solver_call_time, valid_basis,
425
+ use_presolve, analytic_centre);
426
+ }
427
+ if (HighsInt(sol.size()) != mipsolver.numCol()) return;
428
+ analyticCenterStatus = ipm.getModelStatus();
429
+ analyticCenter = sol;
430
+ });
431
+ }
432
+
433
+ void HighsMipSolverData::finishAnalyticCenterComputation(
434
+ const highs::parallel::TaskGroup& taskGroup) {
435
+ if (mipsolver.analysis_.analyse_mip_time) {
436
+ highsLogUser(mipsolver.options_mip_->log_options, HighsLogType::kInfo,
437
+ "MIP-Timing: %11.2g - starting analytic centre synch\n",
438
+ mipsolver.analysis_.mipTimerRead());
439
+ fflush(stdout);
440
+ }
441
+ taskGroup.sync();
442
+ if (mipsolver.analysis_.analyse_mip_time) {
443
+ highsLogUser(mipsolver.options_mip_->log_options, HighsLogType::kInfo,
444
+ "MIP-Timing: %11.2g - completed analytic centre synch\n",
445
+ mipsolver.analysis_.mipTimerRead());
446
+ fflush(stdout);
447
+ }
448
+ analyticCenterComputed = true;
449
+ if (analyticCenterStatus == HighsModelStatus::kOptimal) {
450
+ HighsInt nfixed = 0;
451
+ HighsInt nintfixed = 0;
452
+ for (HighsInt i = 0; i != mipsolver.numCol(); ++i) {
453
+ double boundRange = mipsolver.mipdata_->domain.col_upper_[i] -
454
+ mipsolver.mipdata_->domain.col_lower_[i];
455
+ if (boundRange == 0.0) continue;
456
+
457
+ double tolerance =
458
+ mipsolver.mipdata_->feastol * std::min(boundRange, 1.0);
459
+
460
+ if (analyticCenter[i] <= mipsolver.model_->col_lower_[i] + tolerance) {
461
+ mipsolver.mipdata_->domain.changeBound(
462
+ HighsBoundType::kUpper, i, mipsolver.model_->col_lower_[i],
463
+ HighsDomain::Reason::unspecified());
464
+ if (mipsolver.mipdata_->domain.infeasible()) return;
465
+ ++nfixed;
466
+ if (mipsolver.isColInteger(i)) ++nintfixed;
467
+ } else if (analyticCenter[i] >=
468
+ mipsolver.model_->col_upper_[i] - tolerance) {
469
+ mipsolver.mipdata_->domain.changeBound(
470
+ HighsBoundType::kLower, i, mipsolver.model_->col_upper_[i],
471
+ HighsDomain::Reason::unspecified());
472
+ if (mipsolver.mipdata_->domain.infeasible()) return;
473
+ ++nfixed;
474
+ if (mipsolver.isColInteger(i)) ++nintfixed;
475
+ }
476
+ }
477
+ if (nfixed > 0)
478
+ highsLogDev(mipsolver.options_mip_->log_options, HighsLogType::kInfo,
479
+ "Fixing %d columns (%d integers) sitting at bound at "
480
+ "analytic center\n",
481
+ int(nfixed), int(nintfixed));
482
+ mipsolver.mipdata_->domain.propagate();
483
+ if (mipsolver.mipdata_->domain.infeasible()) return;
484
+ }
485
+ }
486
+
487
+ void HighsMipSolverData::startSymmetryDetection(
488
+ const highs::parallel::TaskGroup& taskGroup,
489
+ std::unique_ptr<SymmetryDetectionData>& symData) {
490
+ symData = std::unique_ptr<SymmetryDetectionData>(new SymmetryDetectionData());
491
+ symData->symDetection.loadModelAsGraph(
492
+ mipsolver.mipdata_->presolvedModel,
493
+ mipsolver.options_mip_->small_matrix_value);
494
+ detectSymmetries = symData->symDetection.initializeDetection();
495
+
496
+ if (detectSymmetries) {
497
+ taskGroup.spawn([&]() {
498
+ double startTime = mipsolver.timer_.getWallTime();
499
+ symData->symDetection.run(symData->symmetries);
500
+ symData->detectionTime = mipsolver.timer_.getWallTime() - startTime;
501
+ });
502
+ } else
503
+ symData.reset();
504
+ }
505
+
506
+ void HighsMipSolverData::finishSymmetryDetection(
507
+ const highs::parallel::TaskGroup& taskGroup,
508
+ std::unique_ptr<SymmetryDetectionData>& symData) {
509
+ taskGroup.sync();
510
+
511
+ symmetries = std::move(symData->symmetries);
512
+ std::string symmetry_time =
513
+ mipsolver.options_mip_->timeless_log
514
+ ? ""
515
+ : highsFormatToString(" %.1fs", symData->detectionTime);
516
+ highsLogUser(mipsolver.options_mip_->log_options, HighsLogType::kInfo,
517
+ "\nSymmetry detection completed in%s\n", symmetry_time.c_str());
518
+
519
+ if (symmetries.numGenerators == 0) {
520
+ detectSymmetries = false;
521
+ highsLogUser(mipsolver.options_mip_->log_options, HighsLogType::kInfo,
522
+ "No symmetry present\n\n");
523
+ } else if (symmetries.orbitopes.size() == 0) {
524
+ highsLogUser(mipsolver.options_mip_->log_options, HighsLogType::kInfo,
525
+ "Found %d generator(s)\n\n", int(symmetries.numGenerators));
526
+
527
+ } else {
528
+ if (symmetries.numPerms != 0) {
529
+ highsLogUser(mipsolver.options_mip_->log_options, HighsLogType::kInfo,
530
+ "Found %d generator(s) and %d full orbitope(s) acting on %d "
531
+ "columns\n\n",
532
+ int(symmetries.numPerms), int(symmetries.orbitopes.size()),
533
+ int(symmetries.columnToOrbitope.size()));
534
+ } else {
535
+ highsLogUser(mipsolver.options_mip_->log_options, HighsLogType::kInfo,
536
+ "Found %d full orbitope(s) acting on %d columns\n\n",
537
+ int(symmetries.orbitopes.size()),
538
+ int(symmetries.columnToOrbitope.size()));
539
+ }
540
+ }
541
+ symData.reset();
542
+
543
+ for (HighsOrbitopeMatrix& orbitope : symmetries.orbitopes)
544
+ orbitope.determineOrbitopeType(cliquetable);
545
+
546
+ if (symmetries.numPerms != 0)
547
+ globalOrbits = symmetries.computeStabilizerOrbits(domain);
548
+ }
549
+
550
+ double HighsMipSolverData::limitsToGap(const double use_lower_bound,
551
+ const double use_upper_bound, double& lb,
552
+ double& ub) const {
553
+ double offset = mipsolver.model_->offset_;
554
+ lb = use_lower_bound + offset;
555
+ if (std::abs(lb) <= epsilon) lb = 0;
556
+ ub = kHighsInf;
557
+ double gap = kHighsInf;
558
+ if (use_upper_bound != kHighsInf) {
559
+ ub = use_upper_bound + offset;
560
+ if (std::fabs(ub) <= epsilon) ub = 0;
561
+ lb = std::min(ub, lb);
562
+ if (ub == 0.0)
563
+ gap = lb == 0.0 ? 0.0 : kHighsInf;
564
+ else
565
+ gap = (ub - lb) / fabs(ub);
566
+ }
567
+ return gap;
568
+ }
569
+
570
+ double HighsMipSolverData::computeNewUpperLimit(double ub, double mip_abs_gap,
571
+ double mip_rel_gap) const {
572
+ double new_upper_limit;
573
+ if (objectiveFunction.isIntegral()) {
574
+ new_upper_limit =
575
+ (std::floor(objectiveFunction.integralScale() * ub - 0.5) /
576
+ objectiveFunction.integralScale());
577
+
578
+ if (mip_rel_gap != 0.0)
579
+ new_upper_limit = std::min(
580
+ new_upper_limit,
581
+ ub - std::ceil(mip_rel_gap * fabs(ub + mipsolver.model_->offset_) *
582
+ objectiveFunction.integralScale() -
583
+ mipsolver.mipdata_->epsilon) /
584
+ objectiveFunction.integralScale());
585
+
586
+ if (mip_abs_gap != 0.0)
587
+ new_upper_limit = std::min(
588
+ new_upper_limit,
589
+ ub - std::ceil(mip_abs_gap * objectiveFunction.integralScale() -
590
+ mipsolver.mipdata_->epsilon) /
591
+ objectiveFunction.integralScale());
592
+
593
+ // add feasibility tolerance so that the next best integer feasible solution
594
+ // is definitely included in the remaining search
595
+ new_upper_limit += feastol;
596
+ } else {
597
+ new_upper_limit = std::min(ub - feastol, std::nextafter(ub, -kHighsInf));
598
+
599
+ if (mip_rel_gap != 0.0)
600
+ new_upper_limit =
601
+ std::min(new_upper_limit,
602
+ ub - mip_rel_gap * fabs(ub + mipsolver.model_->offset_));
603
+
604
+ if (mip_abs_gap != 0.0)
605
+ new_upper_limit = std::min(new_upper_limit, ub - mip_abs_gap);
606
+ }
607
+
608
+ return new_upper_limit;
609
+ }
610
+
611
+ bool HighsMipSolverData::moreHeuristicsAllowed() const {
612
+ // in the beginning of the search and in sub-MIP heuristics we only allow
613
+ // what is proportionally for the currently spent effort plus an initial
614
+ // offset. This is because in a sub-MIP we usually do a truncated search and
615
+ // therefore should not extrapolate the time we spent for heuristics as in
616
+ // the other case. Moreover, since we estimate the total effort for
617
+ // exploring the tree based on the weight of the already pruned nodes, the
618
+ // estimated effort the is not expected to be a good prediction in the
619
+ // beginning.
620
+ if (mipsolver.submip) {
621
+ return heuristic_lp_iterations < total_lp_iterations * heuristic_effort;
622
+ } else if (pruned_treeweight < 1e-3 &&
623
+ num_leaves - num_leaves_before_run < 10 &&
624
+ num_nodes - num_nodes_before_run < 1000) {
625
+ // in the main MIP solver allow an initial offset of 10000 heuristic LP
626
+ // iterations
627
+ if (heuristic_lp_iterations <
628
+ total_lp_iterations * heuristic_effort + 10000)
629
+ return true;
630
+ } else if (heuristic_lp_iterations <
631
+ 100000 + ((total_lp_iterations - heuristic_lp_iterations -
632
+ sb_lp_iterations) >>
633
+ 1)) {
634
+ // compute the node LP iterations in the current run as only those should be
635
+ // used when estimating the total required LP iterations to complete the
636
+ // search
637
+ int64_t heur_iters_curr_run =
638
+ heuristic_lp_iterations - heuristic_lp_iterations_before_run;
639
+ int64_t sb_iters_curr_run = sb_lp_iterations - sb_lp_iterations_before_run;
640
+ int64_t node_iters_curr_run = total_lp_iterations -
641
+ total_lp_iterations_before_run -
642
+ heur_iters_curr_run - sb_iters_curr_run;
643
+ // now estimate the total fraction of LP iterations that we have spent on
644
+ // heuristics by assuming the node iterations of the current run will
645
+ // grow proportional to the pruned weight of the current tree and the
646
+ // iterations spent for anything else are just added as an offset
647
+ double total_heuristic_effort_estim =
648
+ heuristic_lp_iterations /
649
+ ((total_lp_iterations - node_iters_curr_run) +
650
+ node_iters_curr_run / std::max(0.01, double(pruned_treeweight)));
651
+ // since heuristics help most in the beginning of the search, we want to
652
+ // spent the time we have for heuristics in the first 80% of the tree
653
+ // exploration. Additionally we want to spent the proportional effort
654
+ // of heuristics that is allowed in the first 30% of tree exploration as
655
+ // fast as possible, which is why we have the max(0.3/0.8,...).
656
+ // Hence, in the first 30% of the tree exploration we allow to spent all
657
+ // effort available for heuristics in that part of the search as early as
658
+ // possible, whereas after that we allow the part that is proportionally
659
+ // adequate when we want to spent all available time in the first 80%.
660
+ if (total_heuristic_effort_estim <
661
+ std::max(0.3 / 0.8, std::min(double(pruned_treeweight), 0.8) / 0.8) *
662
+ heuristic_effort) {
663
+ // printf(
664
+ // "heuristic lp iterations: %ld, total_lp_iterations: %ld, "
665
+ // "total_heur_effort_estim = %.3f%%\n",
666
+ // heuristic_lp_iterations, total_lp_iterations,
667
+ // total_heuristic_effort_estim);
668
+ return true;
669
+ }
670
+ }
671
+
672
+ return false;
673
+ }
674
+
675
+ void HighsMipSolverData::removeFixedIndices() {
676
+ integral_cols.erase(
677
+ std::remove_if(integral_cols.begin(), integral_cols.end(),
678
+ [&](HighsInt col) { return domain.isFixed(col); }),
679
+ integral_cols.end());
680
+ integer_cols.erase(
681
+ std::remove_if(integer_cols.begin(), integer_cols.end(),
682
+ [&](HighsInt col) { return domain.isFixed(col); }),
683
+ integer_cols.end());
684
+ implint_cols.erase(
685
+ std::remove_if(implint_cols.begin(), implint_cols.end(),
686
+ [&](HighsInt col) { return domain.isFixed(col); }),
687
+ implint_cols.end());
688
+ continuous_cols.erase(
689
+ std::remove_if(continuous_cols.begin(), continuous_cols.end(),
690
+ [&](HighsInt col) { return domain.isFixed(col); }),
691
+ continuous_cols.end());
692
+ }
693
+
694
+ void HighsMipSolverData::init() {
695
+ postSolveStack.initializeIndexMaps(mipsolver.numRow(), mipsolver.numCol());
696
+ mipsolver.orig_model_ = mipsolver.model_;
697
+ feastol = mipsolver.options_mip_->mip_feasibility_tolerance;
698
+ epsilon = mipsolver.options_mip_->small_matrix_value;
699
+ if (mipsolver.clqtableinit)
700
+ cliquetable.buildFrom(mipsolver.orig_model_, *mipsolver.clqtableinit);
701
+ cliquetable.setMinEntriesForParallelism(
702
+ highs::parallel::num_threads() > 1
703
+ ? mipsolver.options_mip_->mip_min_cliquetable_entries_for_parallelism
704
+ : kHighsIInf);
705
+ if (mipsolver.implicinit) implications.buildFrom(*mipsolver.implicinit);
706
+ heuristic_effort = mipsolver.options_mip_->mip_heuristic_effort;
707
+ detectSymmetries = mipsolver.options_mip_->mip_detect_symmetry;
708
+
709
+ firstlpsolobj = -kHighsInf;
710
+ rootlpsolobj = -kHighsInf;
711
+ analyticCenterComputed = false;
712
+ analyticCenterStatus = HighsModelStatus::kNotset;
713
+ maxTreeSizeLog2 = 0;
714
+ numRestarts = 0;
715
+ numRestartsRoot = 0;
716
+ numImprovingSols = 0;
717
+ pruned_treeweight = 0;
718
+ avgrootlpiters = 0;
719
+ num_nodes = 0;
720
+ num_nodes_before_run = 0;
721
+ num_leaves = 0;
722
+ num_leaves_before_run = 0;
723
+ total_repair_lp = 0;
724
+ total_repair_lp_feasible = 0;
725
+ total_repair_lp_iterations = 0;
726
+ total_lp_iterations = 0;
727
+ heuristic_lp_iterations = 0;
728
+ sepa_lp_iterations = 0;
729
+ sb_lp_iterations = 0;
730
+ total_lp_iterations_before_run = 0;
731
+ heuristic_lp_iterations_before_run = 0;
732
+ sepa_lp_iterations_before_run = 0;
733
+ sb_lp_iterations_before_run = 0;
734
+ num_disp_lines = 0;
735
+ numCliqueEntriesAfterPresolve = 0;
736
+ numCliqueEntriesAfterFirstPresolve = 0;
737
+ cliquesExtracted = false;
738
+ rowMatrixSet = false;
739
+ lower_bound = -kHighsInf;
740
+ upper_bound = kHighsInf;
741
+ upper_limit = mipsolver.options_mip_->objective_bound;
742
+ optimality_limit = mipsolver.options_mip_->objective_bound;
743
+ primal_dual_integral.initialise();
744
+
745
+ if (mipsolver.options_mip_->mip_report_level == 0)
746
+ dispfreq = 0;
747
+ else if (mipsolver.options_mip_->mip_report_level == 1)
748
+ dispfreq = 2000;
749
+ else
750
+ dispfreq = 100;
751
+ }
752
+
753
+ void HighsMipSolverData::runMipPresolve(
754
+ const HighsInt presolve_reduction_limit) {
755
+ mipsolver.timer_.start(mipsolver.timer_.presolve_clock);
756
+ presolve::HPresolve presolve;
757
+ if (!presolve.okSetInput(mipsolver, presolve_reduction_limit)) {
758
+ mipsolver.modelstatus_ = HighsModelStatus::kMemoryLimit;
759
+ presolve_status = HighsPresolveStatus::kOutOfMemory;
760
+ } else {
761
+ mipsolver.modelstatus_ = presolve.run(postSolveStack);
762
+ presolve_status = presolve.getPresolveStatus();
763
+ }
764
+ mipsolver.timer_.stop(mipsolver.timer_.presolve_clock);
765
+
766
+ // Report the final presolve reductions unless this is a restart
767
+ if (mipsolver.options_mip_->presolve != kHighsOffString && numRestarts == 0)
768
+ reportPresolveReductions(mipsolver.options_mip_->log_options,
769
+ presolve_status, *mipsolver.orig_model_,
770
+ *mipsolver.model_);
771
+ }
772
+
773
+ void HighsMipSolverData::runSetup() {
774
+ const HighsLp& model = *mipsolver.model_;
775
+
776
+ // Indicate that the first LP has not been solved
777
+ this->lp.setSolvedFirstLp(false);
778
+
779
+ last_disptime = -kHighsInf;
780
+ disptime = 0;
781
+
782
+ // Transform the reference of the objective limit and lower/upper
783
+ // bounds from the original model to the current model, undoing the
784
+ // transformation done before restart so that the offset change due
785
+ // to presolve is incorporated. Bound changes are transitory, so no
786
+ // real gap change, and no update to P-D integral is necessary
787
+ upper_limit -= mipsolver.model_->offset_;
788
+ optimality_limit -= mipsolver.model_->offset_;
789
+
790
+ lower_bound -= mipsolver.model_->offset_;
791
+ upper_bound -= mipsolver.model_->offset_;
792
+
793
+ if (mipsolver.solution_objective_ != kHighsInf) {
794
+ // Assigning new incumbent
795
+ incumbent = postSolveStack.getReducedPrimalSolution(mipsolver.solution_);
796
+ // return the objective value in the transformed space
797
+ double solobj =
798
+ mipsolver.solution_objective_ * (int)mipsolver.orig_model_->sense_ -
799
+ mipsolver.model_->offset_;
800
+ bool feasible = mipsolver.bound_violation_ <=
801
+ mipsolver.options_mip_->mip_feasibility_tolerance &&
802
+ mipsolver.integrality_violation_ <=
803
+ mipsolver.options_mip_->mip_feasibility_tolerance &&
804
+ mipsolver.row_violation_ <=
805
+ mipsolver.options_mip_->mip_feasibility_tolerance;
806
+ if (numRestarts == 0) {
807
+ highsLogUser(mipsolver.options_mip_->log_options, HighsLogType::kInfo,
808
+ "\nMIP start solution is %s, objective value is %.12g\n",
809
+ feasible ? "feasible" : "infeasible",
810
+ mipsolver.solution_objective_);
811
+ }
812
+ if (feasible && solobj < upper_bound) {
813
+ double prev_upper_bound = upper_bound;
814
+
815
+ upper_bound = solobj;
816
+
817
+ bool bound_change = upper_bound != prev_upper_bound;
818
+ if (!mipsolver.submip && bound_change)
819
+ updatePrimalDualIntegral(lower_bound, lower_bound, prev_upper_bound,
820
+ upper_bound);
821
+
822
+ double new_upper_limit = computeNewUpperLimit(solobj, 0.0, 0.0);
823
+
824
+ saveReportMipSolution(new_upper_limit);
825
+ if (new_upper_limit < upper_limit) {
826
+ upper_limit = new_upper_limit;
827
+ optimality_limit =
828
+ computeNewUpperLimit(solobj, mipsolver.options_mip_->mip_abs_gap,
829
+ mipsolver.options_mip_->mip_rel_gap);
830
+ nodequeue.setOptimalityLimit(optimality_limit);
831
+ }
832
+ }
833
+ if (!mipsolver.submip && feasible && mipsolver.callback_->user_callback &&
834
+ mipsolver.callback_->active[kCallbackMipSolution]) {
835
+ assert(!mipsolver.submip);
836
+ mipsolver.callback_->clearHighsCallbackOutput();
837
+ mipsolver.callback_->data_out.mip_solution = mipsolver.solution_;
838
+ const bool interrupt = interruptFromCallbackWithData(
839
+ kCallbackMipSolution, mipsolver.solution_objective_,
840
+ "Feasible solution");
841
+ assert(!interrupt);
842
+ }
843
+ }
844
+
845
+ if (mipsolver.numCol() == 0)
846
+ addIncumbent(std::vector<double>(), 0, kSolutionSourceEmptyMip);
847
+
848
+ redcostfixing = HighsRedcostFixing();
849
+ pseudocost = HighsPseudocost(mipsolver);
850
+ nodequeue.setNumCol(mipsolver.numCol());
851
+ nodequeue.setOptimalityLimit(optimality_limit);
852
+
853
+ continuous_cols.clear();
854
+ integer_cols.clear();
855
+ implint_cols.clear();
856
+ integral_cols.clear();
857
+
858
+ rowMatrixSet = false;
859
+ if (!rowMatrixSet) {
860
+ rowMatrixSet = true;
861
+ highsSparseTranspose(model.num_row_, model.num_col_, model.a_matrix_.start_,
862
+ model.a_matrix_.index_, model.a_matrix_.value_,
863
+ ARstart_, ARindex_, ARvalue_);
864
+ // (re-)initialize number of uplocks and downlocks
865
+ uplocks.assign(model.num_col_, 0);
866
+ downlocks.assign(model.num_col_, 0);
867
+ for (HighsInt i = 0; i != model.num_col_; ++i) {
868
+ HighsInt start = model.a_matrix_.start_[i];
869
+ HighsInt end = model.a_matrix_.start_[i + 1];
870
+ for (HighsInt j = start; j != end; ++j) {
871
+ HighsInt row = model.a_matrix_.index_[j];
872
+
873
+ if (model.row_lower_[row] != -kHighsInf) {
874
+ if (model.a_matrix_.value_[j] < 0)
875
+ ++uplocks[i];
876
+ else
877
+ ++downlocks[i];
878
+ }
879
+ if (model.row_upper_[row] != kHighsInf) {
880
+ if (model.a_matrix_.value_[j] < 0)
881
+ ++downlocks[i];
882
+ else
883
+ ++uplocks[i];
884
+ }
885
+ }
886
+ }
887
+ }
888
+
889
+ rowintegral.resize(mipsolver.numRow());
890
+
891
+ // compute the maximal absolute coefficients to filter propagation
892
+ maxAbsRowCoef.resize(mipsolver.numRow());
893
+ for (HighsInt i = 0; i != mipsolver.numRow(); ++i) {
894
+ double maxabsval = 0.0;
895
+
896
+ HighsInt start = ARstart_[i];
897
+ HighsInt end = ARstart_[i + 1];
898
+ bool integral = true;
899
+ for (HighsInt j = start; j != end; ++j) {
900
+ integral = integral && mipsolver.isColIntegral(ARindex_[j]) &&
901
+ fractionality(ARvalue_[j]) <= epsilon;
902
+
903
+ maxabsval = std::max(maxabsval, std::abs(ARvalue_[j]));
904
+ }
905
+
906
+ if (integral) {
907
+ if (presolvedModel.row_lower_[i] != -kHighsInf)
908
+ presolvedModel.row_lower_[i] =
909
+ std::ceil(presolvedModel.row_lower_[i] - feastol);
910
+
911
+ if (presolvedModel.row_upper_[i] != kHighsInf)
912
+ presolvedModel.row_upper_[i] =
913
+ std::floor(presolvedModel.row_upper_[i] + feastol);
914
+ }
915
+
916
+ rowintegral[i] = integral;
917
+ maxAbsRowCoef[i] = maxabsval;
918
+ }
919
+
920
+ // compute row activities and propagate all rows once
921
+ objectiveFunction.setupCliquePartition(domain, cliquetable);
922
+ domain.setupObjectivePropagation();
923
+ domain.computeRowActivities();
924
+ domain.propagate();
925
+ if (domain.infeasible()) {
926
+ mipsolver.modelstatus_ = HighsModelStatus::kInfeasible;
927
+
928
+ updateLowerBound(kHighsInf);
929
+
930
+ pruned_treeweight = 1.0;
931
+ return;
932
+ }
933
+
934
+ if (model.num_col_ == 0) {
935
+ mipsolver.modelstatus_ = HighsModelStatus::kOptimal;
936
+ return;
937
+ }
938
+
939
+ if (checkLimits()) return;
940
+ // extract cliques if they have not been extracted before
941
+
942
+ for (HighsInt col : domain.getChangedCols())
943
+ implications.cleanupVarbounds(col);
944
+ domain.clearChangedCols();
945
+
946
+ lp.getLpSolver().setOptionValue("presolve", kHighsOffString);
947
+ // lp.getLpSolver().setOptionValue("dual_simplex_cost_perturbation_multiplier",
948
+ // 0.0); lp.getLpSolver().setOptionValue("parallel", kHighsOnString);
949
+ lp.getLpSolver().setOptionValue("simplex_initial_condition_check", false);
950
+
951
+ checkObjIntegrality();
952
+ rootlpsol.clear();
953
+ firstlpsol.clear();
954
+ HighsInt num_binary = 0;
955
+ HighsInt num_domain_fixed = 0;
956
+ maxTreeSizeLog2 = 0;
957
+ for (HighsInt i = 0; i != mipsolver.numCol(); ++i) {
958
+ switch (mipsolver.variableType(i)) {
959
+ case HighsVarType::kContinuous:
960
+ if (domain.isFixed(i)) {
961
+ num_domain_fixed++;
962
+ continue;
963
+ }
964
+ continuous_cols.push_back(i);
965
+ break;
966
+ case HighsVarType::kImplicitInteger:
967
+ if (domain.isFixed(i)) {
968
+ num_domain_fixed++;
969
+ continue;
970
+ }
971
+ implint_cols.push_back(i);
972
+ integral_cols.push_back(i);
973
+ break;
974
+ case HighsVarType::kInteger:
975
+ if (domain.isFixed(i)) {
976
+ num_domain_fixed++;
977
+ if (fractionality(domain.col_lower_[i]) > feastol) {
978
+ // integer variable is fixed to a fractional value -> infeasible
979
+ mipsolver.modelstatus_ = HighsModelStatus::kInfeasible;
980
+
981
+ updateLowerBound(kHighsInf);
982
+
983
+ pruned_treeweight = 1.0;
984
+ return;
985
+ }
986
+ continue;
987
+ }
988
+ integer_cols.push_back(i);
989
+ integral_cols.push_back(i);
990
+ maxTreeSizeLog2 += (HighsInt)std::ceil(
991
+ std::log2(std::min(1024.0, 1.0 + mipsolver.model_->col_upper_[i] -
992
+ mipsolver.model_->col_lower_[i])));
993
+ // NB Since this is for counting the number of times the
994
+ // condition is true using the bitwise operator avoids having
995
+ // any conditional branch whereas using the logical operator
996
+ // would require a branch due to short circuit
997
+ // evaluation. Semantically both is equivalent and correct. If
998
+ // there was any code to be executed for the condition being
999
+ // true then there would be a conditional branch in any case
1000
+ // and I would have used the logical to begin with.
1001
+ //
1002
+ // Hence any compiler warning can be ignored safely
1003
+ num_binary +=
1004
+ (static_cast<HighsInt>(mipsolver.model_->col_lower_[i] == 0.0) &
1005
+ static_cast<HighsInt>(mipsolver.model_->col_upper_[i] == 1.0));
1006
+ break;
1007
+ case HighsVarType::kSemiContinuous:
1008
+ case HighsVarType::kSemiInteger:
1009
+ highsLogUser(mipsolver.options_mip_->log_options, HighsLogType::kError,
1010
+ "Semicontinuous or semiinteger variables should have been "
1011
+ "reformulated away before HighsMipSolverData::runSetup() "
1012
+ "is called.");
1013
+ throw std::logic_error("Unexpected variable type");
1014
+ }
1015
+ }
1016
+
1017
+ basisTransfer();
1018
+
1019
+ numintegercols = integer_cols.size();
1020
+ detectSymmetries = detectSymmetries && num_binary > 0;
1021
+ numCliqueEntriesAfterPresolve = cliquetable.getNumEntries();
1022
+ HighsInt num_col = mipsolver.numCol();
1023
+ HighsInt num_general_integer = numintegercols - num_binary;
1024
+ HighsInt num_implied_integer = implint_cols.size();
1025
+ HighsInt num_continuous = continuous_cols.size();
1026
+ assert(num_col == num_continuous + num_binary + num_general_integer +
1027
+ num_implied_integer + num_domain_fixed);
1028
+ if (numRestarts == 0) {
1029
+ numCliqueEntriesAfterFirstPresolve = cliquetable.getNumEntries();
1030
+ highsLogUser(mipsolver.options_mip_->log_options, HighsLogType::kInfo,
1031
+ // clang-format off
1032
+ "\nSolving MIP model with:\n"
1033
+ " %" HIGHSINT_FORMAT " row%s\n"
1034
+ " %" HIGHSINT_FORMAT " col%s ("
1035
+ "%" HIGHSINT_FORMAT" binary, "
1036
+ "%" HIGHSINT_FORMAT " integer, "
1037
+ "%" HIGHSINT_FORMAT" implied int., "
1038
+ "%" HIGHSINT_FORMAT " continuous, "
1039
+ "%" HIGHSINT_FORMAT " domain fixed)\n"
1040
+ " %" HIGHSINT_FORMAT " nonzero%s\n",
1041
+ // clang-format on
1042
+ mipsolver.numRow(), mipsolver.numRow() == 1 ? "" : "s",
1043
+ num_col, num_col == 1 ? "" : "s", num_binary,
1044
+ num_general_integer, num_implied_integer, num_continuous,
1045
+ num_domain_fixed, mipsolver.numNonzero(),
1046
+ mipsolver.numNonzero() == 1 ? "" : "s");
1047
+ } else {
1048
+ highsLogUser(mipsolver.options_mip_->log_options, HighsLogType::kInfo,
1049
+ "Model after restart has "
1050
+ // clang-format off
1051
+ "%" HIGHSINT_FORMAT " row%s, "
1052
+ "%" HIGHSINT_FORMAT " col%s ("
1053
+ "%" HIGHSINT_FORMAT " bin., "
1054
+ "%" HIGHSINT_FORMAT " int., "
1055
+ "%" HIGHSINT_FORMAT " impl., "
1056
+ "%" HIGHSINT_FORMAT " cont., "
1057
+ "%" HIGHSINT_FORMAT " dom.fix.), and "
1058
+ "%" HIGHSINT_FORMAT " nonzero%s\n",
1059
+ // clang-format on
1060
+ mipsolver.numRow(), mipsolver.numRow() == 1 ? "" : "s",
1061
+ num_col, num_col == 1 ? "" : "s", num_binary,
1062
+ num_general_integer, num_implied_integer, num_continuous,
1063
+ num_domain_fixed, mipsolver.numNonzero(),
1064
+ mipsolver.numNonzero() == 1 ? "" : "s");
1065
+ }
1066
+
1067
+ heuristics.setupIntCols();
1068
+
1069
+ #ifdef HIGHS_DEBUGSOL
1070
+ if (debugSolution.debugSolActive) {
1071
+ debugSolution.debugSolution.clear();
1072
+ debugSolution.debugSolution = postSolveStack.getReducedPrimalSolution(
1073
+ debugSolution.debugOrigSolution);
1074
+ debugSolution.debugSolObjective = 0;
1075
+ HighsCDouble debugsolobj = 0.0;
1076
+ for (HighsInt i = 0; i != mipsolver.numCol(); ++i)
1077
+ debugsolobj +=
1078
+ mipsolver.colCost(i) * HighsCDouble(debugSolution.debugSolution[i]);
1079
+ debugSolution.debugSolObjective = static_cast<double>(debugsolobj);
1080
+ debugSolution.registerDomain(domain);
1081
+ assert(checkSolution(debugSolution.debugSolution));
1082
+ }
1083
+ #endif
1084
+
1085
+ if (upper_limit == kHighsInf) analyticCenterComputed = false;
1086
+ analyticCenterStatus = HighsModelStatus::kNotset;
1087
+ analyticCenter.clear();
1088
+
1089
+ symmetries.clear();
1090
+
1091
+ if (numRestarts != 0)
1092
+ highsLogUser(mipsolver.options_mip_->log_options, HighsLogType::kInfo,
1093
+ "\n");
1094
+ }
1095
+
1096
+ double HighsMipSolverData::transformNewIntegerFeasibleSolution(
1097
+ const std::vector<double>& sol,
1098
+ const bool possibly_store_as_new_incumbent) {
1099
+ HighsSolution solution;
1100
+ solution.col_value = sol;
1101
+ solution.value_valid = true;
1102
+ // Perform primal postsolve to get the original column values
1103
+ postSolveStack.undoPrimal(*mipsolver.options_mip_, solution);
1104
+ // Determine the row values, as they aren't computed in primal
1105
+ // postsolve
1106
+ HighsStatus return_status =
1107
+ calculateRowValuesQuad(*mipsolver.orig_model_, solution);
1108
+ if (kAllowDeveloperAssert) assert(return_status == HighsStatus::kOk);
1109
+ bool allow_try_again = true;
1110
+ try_again:
1111
+
1112
+ // compute the objective value in the original space
1113
+ double bound_violation_ = 0;
1114
+ double row_violation_ = 0;
1115
+ double integrality_violation_ = 0;
1116
+ HighsCDouble mipsolver_quad_objective_value = 0;
1117
+ bool feasible = mipsolver.solutionFeasible(
1118
+ mipsolver.orig_model_, solution.col_value, &solution.row_value,
1119
+ bound_violation_, row_violation_, integrality_violation_,
1120
+ mipsolver_quad_objective_value);
1121
+ double mipsolver_objective_value = double(mipsolver_quad_objective_value);
1122
+ if (!feasible && allow_try_again) {
1123
+ // printf(
1124
+ // "trying to repair sol that is violated by %.12g bounds, %.12g "
1125
+ // "integrality, %.12g rows\n",
1126
+ // bound_violation_, integrality_violation_, row_violation_);
1127
+ HighsLp fixedModel = *mipsolver.orig_model_;
1128
+ fixedModel.integrality_.clear();
1129
+ for (HighsInt i = 0; i != mipsolver.orig_model_->num_col_; ++i) {
1130
+ if (mipsolver.orig_model_->integrality_[i] == HighsVarType::kInteger) {
1131
+ double solval = std::round(solution.col_value[i]);
1132
+ fixedModel.col_lower_[i] = std::max(fixedModel.col_lower_[i], solval);
1133
+ fixedModel.col_upper_[i] = std::min(fixedModel.col_upper_[i], solval);
1134
+ }
1135
+ }
1136
+ this->total_repair_lp++;
1137
+ double time_available = std::max(
1138
+ mipsolver.options_mip_->time_limit - mipsolver.timer_.read(), 0.1);
1139
+ Highs tmpSolver;
1140
+ const bool debug_report = false;
1141
+ if (debug_report) {
1142
+ tmpSolver.setOptionValue("log_dev_level", 2);
1143
+ tmpSolver.setOptionValue("highs_analysis_level", 4);
1144
+ } else {
1145
+ tmpSolver.setOptionValue("output_flag", false);
1146
+ }
1147
+ // tmpSolver.setOptionValue("simplex_scale_strategy", 0);
1148
+ // tmpSolver.setOptionValue("presolve", kHighsOffString);
1149
+ tmpSolver.setOptionValue("time_limit", time_available);
1150
+ // Set primal feasibility tolerance for LP solves according to
1151
+ // mip_feasibility_tolerance. Interestingly, dual feasibility
1152
+ // tolerance not set to smaller tolerance as in
1153
+ // HighsLpRelaxationconstructor.
1154
+ double mip_primal_feasibility_tolerance =
1155
+ mipsolver.options_mip_->mip_feasibility_tolerance;
1156
+ tmpSolver.setOptionValue("primal_feasibility_tolerance",
1157
+ mip_primal_feasibility_tolerance);
1158
+ // check if only root presolve is allowed
1159
+ const bool use_presolve = !mipsolver.options_mip_->mip_root_presolve_only;
1160
+ const std::string presolve =
1161
+ use_presolve ? kHighsChooseString : kHighsOffString;
1162
+ tmpSolver.setOptionValue("presolve", presolve);
1163
+ tmpSolver.passModel(std::move(fixedModel));
1164
+ // Until a good decision can be made on whether to use simplex,
1165
+ // HiPO or IPX to solve an LP without a basis, use simplex
1166
+ tmpSolver.setOptionValue("solver", kSimplexString);
1167
+ tmpSolver.optimizeLp();
1168
+ if (!mipsolver.submip) {
1169
+ const HighsSubSolverCallTime& sub_solver_call_time =
1170
+ tmpSolver.getSubSolverCallTime();
1171
+ const bool analytic_centre = false;
1172
+ mipsolver.analysis_.addSubSolverCallTime(sub_solver_call_time,
1173
+ analytic_centre);
1174
+ // Go through sub_solver_call_time to update any MIP clocks
1175
+ const bool valid_basis = false;
1176
+ mipsolver.analysis_.mipTimerUpdate(sub_solver_call_time, valid_basis,
1177
+ use_presolve, analytic_centre);
1178
+ }
1179
+ this->total_repair_lp_iterations =
1180
+ tmpSolver.getInfo().simplex_iteration_count;
1181
+ if (tmpSolver.getInfo().primal_solution_status == kSolutionStatusFeasible) {
1182
+ this->total_repair_lp_feasible++;
1183
+ solution = tmpSolver.getSolution();
1184
+ allow_try_again = false;
1185
+ goto try_again;
1186
+ }
1187
+ }
1188
+
1189
+ const double transformed_solobj =
1190
+ static_cast<double>(static_cast<HighsInt>(mipsolver.orig_model_->sense_) *
1191
+ mipsolver_quad_objective_value -
1192
+ mipsolver.model_->offset_);
1193
+
1194
+ // Possible MIP solution callback
1195
+ if (!mipsolver.submip && feasible && mipsolver.callback_->user_callback &&
1196
+ mipsolver.callback_->active[kCallbackMipSolution]) {
1197
+ mipsolver.callback_->clearHighsCallbackOutput();
1198
+ mipsolver.callback_->data_out.mip_solution = solution.col_value;
1199
+ const bool interrupt = interruptFromCallbackWithData(
1200
+ kCallbackMipSolution, mipsolver_objective_value, "Feasible solution");
1201
+ assert(!interrupt);
1202
+ }
1203
+
1204
+ // Catch the case where the repaired solution now has worse objective
1205
+ // than the current stored solution
1206
+ if (transformed_solobj >= upper_bound && !sol.empty()) {
1207
+ return transformed_solobj;
1208
+ }
1209
+
1210
+ if (possibly_store_as_new_incumbent) {
1211
+ // Store the solution as incumbent in the original space if there
1212
+ // is no solution or if it is feasible
1213
+ if (feasible) {
1214
+ // if (!allow_try_again)
1215
+ // printf("repaired solution with value %g\n",
1216
+ // mipsolver_objective_value);
1217
+ // store
1218
+ mipsolver.row_violation_ = row_violation_;
1219
+ mipsolver.bound_violation_ = bound_violation_;
1220
+ mipsolver.integrality_violation_ = integrality_violation_;
1221
+ mipsolver.solution_ = std::move(solution.col_value);
1222
+ mipsolver.solution_objective_ = mipsolver_objective_value;
1223
+ } else {
1224
+ bool currentFeasible =
1225
+ mipsolver.solution_objective_ != kHighsInf &&
1226
+ mipsolver.bound_violation_ <=
1227
+ mipsolver.options_mip_->mip_feasibility_tolerance &&
1228
+ mipsolver.integrality_violation_ <=
1229
+ mipsolver.options_mip_->mip_feasibility_tolerance &&
1230
+ mipsolver.row_violation_ <=
1231
+ mipsolver.options_mip_->mip_feasibility_tolerance;
1232
+ highsLogUser(mipsolver.options_mip_->log_options, HighsLogType::kWarning,
1233
+ "Solution with objective %g has untransformed violations: "
1234
+ "bound = %.4g; integrality = %.4g; row = %.4g\n",
1235
+ mipsolver_objective_value, bound_violation_,
1236
+ integrality_violation_, row_violation_);
1237
+ if (!currentFeasible) {
1238
+ // if the current incumbent is non existent or also not feasible we
1239
+ // still store the new one
1240
+ mipsolver.row_violation_ = row_violation_;
1241
+ mipsolver.bound_violation_ = bound_violation_;
1242
+ mipsolver.integrality_violation_ = integrality_violation_;
1243
+ mipsolver.solution_ = std::move(solution.col_value);
1244
+ mipsolver.solution_objective_ = mipsolver_objective_value;
1245
+ }
1246
+
1247
+ // return infinity so that it is not used for bounding
1248
+ return kHighsInf;
1249
+ }
1250
+ }
1251
+
1252
+ // return the objective value in the transformed space
1253
+ return transformed_solobj;
1254
+ }
1255
+
1256
+ double HighsMipSolverData::percentageInactiveIntegers() const {
1257
+ return 100.0 *
1258
+ (1.0 - static_cast<double>(integer_cols.size() -
1259
+ cliquetable.getSubstitutions().size()) /
1260
+ numintegercols);
1261
+ }
1262
+
1263
+ void HighsMipSolverData::performRestart() {
1264
+ HighsBasis root_basis;
1265
+ HighsPseudocostInitialization pscostinit(
1266
+ pseudocost, mipsolver.options_mip_->mip_pscost_minreliable,
1267
+ postSolveStack);
1268
+
1269
+ mipsolver.pscostinit = &pscostinit;
1270
+ ++numRestarts;
1271
+ num_leaves_before_run = num_leaves;
1272
+ num_nodes_before_run = num_nodes;
1273
+ num_nodes_before_run = num_nodes;
1274
+ total_lp_iterations_before_run = total_lp_iterations;
1275
+ heuristic_lp_iterations_before_run = heuristic_lp_iterations;
1276
+ sepa_lp_iterations_before_run = sepa_lp_iterations;
1277
+ sb_lp_iterations_before_run = sb_lp_iterations;
1278
+ HighsInt numLpRows = lp.getLp().num_row_;
1279
+ HighsInt numModelRows = mipsolver.numRow();
1280
+ HighsInt numCuts = numLpRows - numModelRows;
1281
+ if (numCuts > 0) postSolveStack.appendCutsToModel(numCuts);
1282
+ auto integrality = std::move(presolvedModel.integrality_);
1283
+ double offset = presolvedModel.offset_;
1284
+ presolvedModel = lp.getLp();
1285
+ presolvedModel.offset_ = offset;
1286
+ presolvedModel.integrality_ = std::move(integrality);
1287
+ #ifdef HIGHS_DEBUGSOL
1288
+ bool debugSolActive = false;
1289
+ std::swap(debugSolution.debugSolActive, debugSolActive);
1290
+ #endif
1291
+
1292
+ const HighsBasis& basis = firstrootbasis;
1293
+ if (basis.valid) {
1294
+ // if we have a basis after solving the root LP, we expand it to the
1295
+ // original space so that it can be used for constructing a starting basis
1296
+ // for the presolved model after the restart
1297
+ root_basis.col_status.resize(postSolveStack.getOrigNumCol());
1298
+ root_basis.row_status.resize(postSolveStack.getOrigNumRow(),
1299
+ HighsBasisStatus::kBasic);
1300
+ root_basis.valid = true;
1301
+ root_basis.useful = true;
1302
+
1303
+ for (HighsInt i = 0; i < mipsolver.numCol(); ++i)
1304
+ root_basis.col_status[postSolveStack.getOrigColIndex(i)] =
1305
+ basis.col_status[i];
1306
+
1307
+ HighsInt numRow = basis.row_status.size();
1308
+ for (HighsInt i = 0; i < numRow; ++i)
1309
+ root_basis.row_status[postSolveStack.getOrigRowIndex(i)] =
1310
+ basis.row_status[i];
1311
+
1312
+ mipsolver.rootbasis = &root_basis;
1313
+ }
1314
+
1315
+ // Transform the reference of the objective limit and lower/upper
1316
+ // bounds to the original model, since offset will generally change
1317
+ // in presolve. Bound changes are transitory, so no real gap change,
1318
+ // and no update to P-D integral is necessary
1319
+ upper_limit += mipsolver.model_->offset_;
1320
+ optimality_limit += mipsolver.model_->offset_;
1321
+
1322
+ upper_bound += mipsolver.model_->offset_;
1323
+ lower_bound += mipsolver.model_->offset_;
1324
+
1325
+ // remove the current incumbent. Any incumbent is already transformed into the
1326
+ // original space and kept there
1327
+ incumbent.clear();
1328
+ pruned_treeweight = 0;
1329
+ nodequeue.clear();
1330
+ globalOrbits.reset();
1331
+
1332
+ // Need to be able to set presolve reduction limit separately when
1333
+ // restarting - so that bugs in presolve restart can be investigated
1334
+ // independently (see #1553)
1335
+ //
1336
+ // However, when restarting, presolve is (naturally) applied to the
1337
+ // presolved problem, so have to control the number of _further_
1338
+ // presolve reductions
1339
+ //
1340
+ // The number of further presolve reductions must be positive,
1341
+ // otherwise the MIP solver cycles, hence
1342
+ // restart_presolve_reduction_limit cannot be zero
1343
+ //
1344
+ // Although postSolveStack.numReductions() is size_t, it makes no
1345
+ // sense to use presolve_reduction_limit when the number of
1346
+ // reductions is vast
1347
+ HighsInt num_reductions = HighsInt(postSolveStack.numReductions());
1348
+ HighsInt restart_presolve_reduction_limit =
1349
+ mipsolver.options_mip_->restart_presolve_reduction_limit;
1350
+ assert(restart_presolve_reduction_limit);
1351
+ HighsInt further_presolve_reduction_limit =
1352
+ restart_presolve_reduction_limit >= 0
1353
+ ? num_reductions + restart_presolve_reduction_limit
1354
+ : -1;
1355
+ runMipPresolve(further_presolve_reduction_limit);
1356
+
1357
+ if (mipsolver.modelstatus_ != HighsModelStatus::kNotset) {
1358
+ // transform the objective limit to the current model
1359
+ upper_limit -= mipsolver.model_->offset_;
1360
+ optimality_limit -= mipsolver.model_->offset_;
1361
+
1362
+ if (mipsolver.modelstatus_ == HighsModelStatus::kOptimal) {
1363
+ mipsolver.mipdata_->upper_bound = 0;
1364
+ mipsolver.mipdata_->transformNewIntegerFeasibleSolution(
1365
+ std::vector<double>());
1366
+ } else {
1367
+ upper_bound -= mipsolver.model_->offset_;
1368
+ }
1369
+
1370
+ // lower_bound still relates to the original model, and the offset
1371
+ // is never applied, since MIP solving is complete, and
1372
+ // lower_bound is set to upper_bound, so apply the offset now, so
1373
+ // that housekeeping in updatePrimalDualIntegral is correct
1374
+ lower_bound -= mipsolver.model_->offset_;
1375
+
1376
+ // There must be a gap change, since it's now zero, so always call
1377
+ // updatePrimalDualIntegral (unless solving a sub-MIP)
1378
+ //
1379
+ // Surely there must be a lower bound change
1380
+ updateLowerBound(upper_bound);
1381
+
1382
+ if (mipsolver.solution_objective_ != kHighsInf &&
1383
+ mipsolver.modelstatus_ == HighsModelStatus::kInfeasible)
1384
+ mipsolver.modelstatus_ = HighsModelStatus::kOptimal;
1385
+ return;
1386
+ }
1387
+ // Bounds are currently in the original space since presolve will have
1388
+ // changed offset_
1389
+ #ifdef HIGHS_DEBUGSOL
1390
+ debugSolution.debugSolActive = debugSolActive;
1391
+ #endif
1392
+ runSetup();
1393
+ if (mipsolver.terminate()) return;
1394
+
1395
+ postSolveStack.removeCutsFromModel(numCuts);
1396
+
1397
+ // HighsNodeQueue oldNodeQueue;
1398
+ // std::swap(nodequeue, oldNodeQueue);
1399
+
1400
+ // remove the pointer into the stack-space of this function
1401
+ if (mipsolver.rootbasis == &root_basis) mipsolver.rootbasis = nullptr;
1402
+ mipsolver.pscostinit = nullptr;
1403
+ }
1404
+
1405
+ void HighsMipSolverData::basisTransfer() {
1406
+ // if a root basis is given, construct a basis for the root LP from
1407
+ // in the reduced problem space after presolving
1408
+ if (mipsolver.rootbasis) {
1409
+ const HighsInt numRow = mipsolver.numRow();
1410
+ const HighsInt numCol = mipsolver.numCol();
1411
+ firstrootbasis.col_status.assign(numCol, HighsBasisStatus::kNonbasic);
1412
+ firstrootbasis.row_status.assign(numRow, HighsBasisStatus::kNonbasic);
1413
+ firstrootbasis.valid = true;
1414
+ firstrootbasis.alien = true;
1415
+ firstrootbasis.useful = true;
1416
+
1417
+ for (HighsInt i = 0; i < numRow; ++i) {
1418
+ HighsBasisStatus status =
1419
+ mipsolver.rootbasis->row_status[postSolveStack.getOrigRowIndex(i)];
1420
+ firstrootbasis.row_status[i] = status;
1421
+ }
1422
+
1423
+ for (HighsInt i = 0; i < numCol; ++i) {
1424
+ HighsBasisStatus status =
1425
+ mipsolver.rootbasis->col_status[postSolveStack.getOrigColIndex(i)];
1426
+ firstrootbasis.col_status[i] = status;
1427
+ }
1428
+ }
1429
+ }
1430
+
1431
+ const std::vector<double>& HighsMipSolverData::getSolution() const {
1432
+ return incumbent;
1433
+ }
1434
+
1435
+ bool HighsMipSolverData::addIncumbent(const std::vector<double>& sol,
1436
+ double solobj, const int solution_source,
1437
+ const bool print_display_line,
1438
+ const bool is_user_solution) {
1439
+ const bool execute_mip_solution_callback =
1440
+ !is_user_solution && !mipsolver.submip &&
1441
+ (mipsolver.callback_->user_callback
1442
+ ? mipsolver.callback_->active[kCallbackMipSolution]
1443
+ : false);
1444
+ // Determine whether the potential new incumbent should be
1445
+ // transformed
1446
+ //
1447
+ // Happens if solobj improves on the upper bound or the MIP solution
1448
+ // callback is active
1449
+ const bool possibly_store_as_new_incumbent = solobj < upper_bound;
1450
+ const bool get_transformed_solution =
1451
+ possibly_store_as_new_incumbent || execute_mip_solution_callback;
1452
+ // Get the transformed objective and solution if required
1453
+ const double transformed_solobj =
1454
+ get_transformed_solution ? transformNewIntegerFeasibleSolution(
1455
+ sol, possibly_store_as_new_incumbent)
1456
+ : 0;
1457
+ const bool highs_solution_report = false;
1458
+ if (solution_source == kSolutionSourceHighsSolution && highs_solution_report
1459
+ //&& possibly_store_as_new_incumbent
1460
+ ) {
1461
+ std::stringstream ss;
1462
+ ss.str(std::string());
1463
+ ss << highsFormatToString(
1464
+ "HighsMipSolverData::addIncumbent HiGHS solution Obj "
1465
+ "= %15.8g; UB = %15.8g; Obj-UB = %11.4g; PossAdd = %s",
1466
+ solobj, upper_bound, solobj - upper_bound,
1467
+ possibly_store_as_new_incumbent ? "T" : "F");
1468
+ if (possibly_store_as_new_incumbent)
1469
+ ss << highsFormatToString(
1470
+ "; TransObj = %15.8g; TransObj-UB = %11.4g; TransSolobj < UB %s",
1471
+ transformed_solobj, transformed_solobj - upper_bound,
1472
+ transformed_solobj < upper_bound ? "T" : "F");
1473
+ highsLogUser(mipsolver.options_mip_->log_options, HighsLogType::kInfo,
1474
+ "%s\n", ss.str().c_str());
1475
+ fflush(stdout);
1476
+ }
1477
+ if (possibly_store_as_new_incumbent) {
1478
+ solobj = transformed_solobj;
1479
+ if (solobj >= upper_bound) return false;
1480
+
1481
+ double prev_upper_bound = upper_bound;
1482
+
1483
+ upper_bound = solobj;
1484
+
1485
+ bool bound_change = upper_bound != prev_upper_bound;
1486
+ if (!mipsolver.submip && bound_change)
1487
+ updatePrimalDualIntegral(lower_bound, lower_bound, prev_upper_bound,
1488
+ upper_bound);
1489
+
1490
+ // Assigning new incumbent
1491
+ incumbent = sol;
1492
+ double new_upper_limit = computeNewUpperLimit(solobj, 0.0, 0.0);
1493
+
1494
+ if (!is_user_solution && !mipsolver.submip)
1495
+ saveReportMipSolution(new_upper_limit);
1496
+ if (new_upper_limit < upper_limit) {
1497
+ ++numImprovingSols;
1498
+ upper_limit = new_upper_limit;
1499
+ optimality_limit =
1500
+ computeNewUpperLimit(solobj, mipsolver.options_mip_->mip_abs_gap,
1501
+ mipsolver.options_mip_->mip_rel_gap);
1502
+ nodequeue.setOptimalityLimit(optimality_limit);
1503
+ debugSolution.newIncumbentFound();
1504
+ domain.propagate();
1505
+ if (!domain.infeasible()) redcostfixing.propagateRootRedcost(mipsolver);
1506
+
1507
+ // Two calls to printDisplayLine added for completeness,
1508
+ // ensuring that when the root node has an integer solution, a
1509
+ // logging line is issued
1510
+
1511
+ if (domain.infeasible()) {
1512
+ pruned_treeweight = 1.0;
1513
+ nodequeue.clear();
1514
+ if (print_display_line)
1515
+ printDisplayLine(solution_source); // Added for completeness
1516
+ return true;
1517
+ }
1518
+ cliquetable.extractObjCliques(mipsolver);
1519
+ if (domain.infeasible()) {
1520
+ pruned_treeweight = 1.0;
1521
+ nodequeue.clear();
1522
+ if (print_display_line)
1523
+ printDisplayLine(solution_source); // Added for completeness
1524
+ return true;
1525
+ }
1526
+ pruned_treeweight += nodequeue.performBounding(upper_limit);
1527
+ printDisplayLine(solution_source);
1528
+ }
1529
+ } else if (incumbent.empty())
1530
+ // Assigning new incumbent
1531
+ incumbent = sol;
1532
+
1533
+ return true;
1534
+ }
1535
+
1536
+ static std::array<char, 22> convertToPrintString(int64_t val) {
1537
+ decltype(convertToPrintString(std::declval<int64_t>())) printString = {};
1538
+ double l = std::log10(std::max(1.0, double(val)));
1539
+ switch (int(l)) {
1540
+ case 0:
1541
+ case 1:
1542
+ case 2:
1543
+ case 3:
1544
+ case 4:
1545
+ case 5:
1546
+ std::snprintf(printString.data(), printString.size(), "%" PRId64, val);
1547
+ break;
1548
+ case 6:
1549
+ case 7:
1550
+ case 8:
1551
+ std::snprintf(printString.data(), printString.size(), "%" PRId64 "k",
1552
+ val / 1000);
1553
+ break;
1554
+ default:
1555
+ std::snprintf(printString.data(), printString.size(), "%" PRId64 "m",
1556
+ val / 1000000);
1557
+ }
1558
+
1559
+ return printString;
1560
+ }
1561
+
1562
+ static std::array<char, 22> convertToPrintString(double val,
1563
+ const char* trailingStr = "") {
1564
+ decltype(convertToPrintString(std::declval<double>(),
1565
+ std::declval<char*>())) printString = {};
1566
+ double l = std::abs(val) == kHighsInf
1567
+ ? 0.0
1568
+ : std::log10(std::max(1e-6, std::abs(val)));
1569
+ switch (int(l)) {
1570
+ case 0:
1571
+ case 1:
1572
+ case 2:
1573
+ case 3:
1574
+ std::snprintf(printString.data(), printString.size(), "%.10g%s", val,
1575
+ trailingStr);
1576
+ break;
1577
+ case 4:
1578
+ std::snprintf(printString.data(), printString.size(), "%.11g%s", val,
1579
+ trailingStr);
1580
+ break;
1581
+ case 5:
1582
+ std::snprintf(printString.data(), printString.size(), "%.12g%s", val,
1583
+ trailingStr);
1584
+ break;
1585
+ case 6:
1586
+ case 7:
1587
+ case 8:
1588
+ case 9:
1589
+ case 10:
1590
+ std::snprintf(printString.data(), printString.size(), "%.13g%s", val,
1591
+ trailingStr);
1592
+ break;
1593
+ default:
1594
+ std::snprintf(printString.data(), printString.size(), "%.9g%s", val,
1595
+ trailingStr);
1596
+ }
1597
+
1598
+ return printString;
1599
+ }
1600
+
1601
+ void HighsMipSolverData::printSolutionSourceKey() const {
1602
+ std::stringstream ss;
1603
+ // Last MipSolutionSource enum is kSolutionSourceCleanup - which is
1604
+ // not a solution source, but used to force the last logging line to
1605
+ // be printed
1606
+ const int last_enum = kSolutionSourceCount - 1;
1607
+ // Set the index of the last solution source to be printed in each
1608
+ // line of the key. Four or five can be printed, depending on the
1609
+ // lengths of the solution source strings in that line
1610
+ std::vector<int> limits = {4, 9, 14, last_enum};
1611
+ assert(last_enum > limits[limits.size() - 2]);
1612
+
1613
+ ss.str(std::string());
1614
+ for (int k = 0; k < limits[0]; k++) {
1615
+ if (k == 0) {
1616
+ ss << "\nSrc: ";
1617
+ } else {
1618
+ ss << "; ";
1619
+ }
1620
+ ss << solutionSourceToString(k) << " => "
1621
+ << solutionSourceToString(k, false);
1622
+ }
1623
+ highsLogUser(mipsolver.options_mip_->log_options, HighsLogType::kInfo,
1624
+ "%s;\n", ss.str().c_str());
1625
+ int to_line = limits.size() - 1;
1626
+ for (int line = 0; line < to_line; line++) {
1627
+ ss.str(std::string());
1628
+ for (int k = limits[line]; k < limits[line + 1]; k++) {
1629
+ if (k == limits[line]) {
1630
+ ss << " ";
1631
+ } else {
1632
+ ss << "; ";
1633
+ }
1634
+ ss << solutionSourceToString(k) << " => "
1635
+ << solutionSourceToString(k, false);
1636
+ }
1637
+ highsLogUser(mipsolver.options_mip_->log_options, HighsLogType::kInfo,
1638
+ "%s%s\n", ss.str().c_str(), line < to_line - 1 ? ";" : "");
1639
+ }
1640
+ }
1641
+
1642
+ void HighsMipSolverData::printDisplayLine(const int solution_source) {
1643
+ // MIP logging method
1644
+ //
1645
+ // Note that if the original problem is a maximization, the cost
1646
+ // coefficients are negated so that the MIP solver only solves a
1647
+ // minimization. Hence, in preparing to print the display line, the
1648
+ // dual bound (lb) is always less than the primal bound (ub). When
1649
+ // printed, the sense of the optimization is applied so that the
1650
+ // values printed correspond to the original objective.
1651
+
1652
+ // No point in computing all the logging values if logging is off
1653
+ bool output_flag = *mipsolver.options_mip_->log_options.output_flag;
1654
+ if (!output_flag) return;
1655
+
1656
+ bool timeless_log = mipsolver.options_mip_->timeless_log;
1657
+ disptime = timeless_log ? disptime + 1 : mipsolver.timer_.read();
1658
+ if (solution_source == kSolutionSourceNone &&
1659
+ disptime - last_disptime <
1660
+ mipsolver.options_mip_->mip_min_logging_interval)
1661
+ return;
1662
+ last_disptime = disptime;
1663
+ std::string time_string =
1664
+ timeless_log ? "" : highsFormatToString(" %7.1fs", disptime);
1665
+
1666
+ if (num_disp_lines % 20 == 0) {
1667
+ if (num_disp_lines == 0) printSolutionSourceKey();
1668
+ std::string work_string0 = timeless_log ? " Work" : " Work ";
1669
+ std::string work_string1 = timeless_log ? "LpIters" : "LpIters Time";
1670
+ highsLogUser(mipsolver.options_mip_->log_options, HighsLogType::kInfo,
1671
+ // clang-format off
1672
+ "\n Nodes | B&B Tree | Objective Bounds | Dynamic Constraints | %s\n"
1673
+ "Src Proc. InQueue | Leaves Expl. | BestBound BestSol Gap | Cuts InLp Confl. | %s\n\n",
1674
+ // clang-format on
1675
+ work_string0.c_str(), work_string1.c_str());
1676
+
1677
+ //" %7s | %10s | %10s | %10s | %10s | %-15s | %-15s | %7s | %7s "
1678
+ //"| %8s | %8s\n",
1679
+ //"time", "open nodes", "nodes", "leaves", "lpiters", "dual bound",
1680
+ //"primal bound", "cutpool", "confl.", "gap", "explored");
1681
+ }
1682
+
1683
+ ++num_disp_lines;
1684
+
1685
+ auto print_nodes = convertToPrintString(num_nodes);
1686
+ auto queue_nodes = convertToPrintString(nodequeue.numActiveNodes());
1687
+ auto print_leaves = convertToPrintString(num_leaves - num_leaves_before_run);
1688
+
1689
+ double explored = 100 * double(pruned_treeweight);
1690
+
1691
+ double lb;
1692
+ double ub;
1693
+ double gap = limitsToGap(lower_bound, upper_bound, lb, ub);
1694
+ gap *= 1e2;
1695
+ if (mipsolver.options_mip_->objective_bound < ub)
1696
+ ub = mipsolver.options_mip_->objective_bound;
1697
+
1698
+ auto print_lp_iters = convertToPrintString(total_lp_iterations);
1699
+ HighsInt dynamic_constraints_in_lp =
1700
+ lp.numRows() > 0 ? lp.numRows() - lp.getNumModelRows() : 0;
1701
+ if (upper_bound != kHighsInf) {
1702
+ std::array<char, 22> gap_string = {};
1703
+ if (gap >= 9999.)
1704
+ std::strcpy(gap_string.data(), "Large");
1705
+ else
1706
+ std::snprintf(gap_string.data(), gap_string.size(), "%.2f%%", gap);
1707
+
1708
+ std::array<char, 22> ub_string;
1709
+ if (mipsolver.options_mip_->objective_bound < ub) {
1710
+ ub_string =
1711
+ convertToPrintString((int)mipsolver.orig_model_->sense_ * ub, "*");
1712
+ } else
1713
+ ub_string = convertToPrintString((int)mipsolver.orig_model_->sense_ * ub);
1714
+
1715
+ auto lb_string =
1716
+ convertToPrintString((int)mipsolver.orig_model_->sense_ * lb);
1717
+
1718
+ highsLogUser(
1719
+ mipsolver.options_mip_->log_options, HighsLogType::kInfo,
1720
+ // clang-format off
1721
+ " %s %7s %7s %7s %6.2f%% %-15s %-15s %8s %6" HIGHSINT_FORMAT " %6" HIGHSINT_FORMAT " %6" HIGHSINT_FORMAT " %7s%s\n",
1722
+ // clang-format on
1723
+ solutionSourceToString(solution_source).c_str(), print_nodes.data(),
1724
+ queue_nodes.data(), print_leaves.data(), explored, lb_string.data(),
1725
+ ub_string.data(), gap_string.data(), cutpool.getNumCuts(),
1726
+ dynamic_constraints_in_lp, conflictPool.getNumConflicts(),
1727
+ print_lp_iters.data(), time_string.c_str());
1728
+ } else {
1729
+ std::array<char, 22> ub_string;
1730
+ if (mipsolver.options_mip_->objective_bound < ub) {
1731
+ ub_string =
1732
+ convertToPrintString((int)mipsolver.orig_model_->sense_ * ub, "*");
1733
+ } else
1734
+ ub_string = convertToPrintString((int)mipsolver.orig_model_->sense_ * ub);
1735
+
1736
+ auto lb_string =
1737
+ convertToPrintString((int)mipsolver.orig_model_->sense_ * lb);
1738
+
1739
+ highsLogUser(
1740
+ mipsolver.options_mip_->log_options, HighsLogType::kInfo,
1741
+ // clang-format off
1742
+ " %s %7s %7s %7s %6.2f%% %-15s %-15s %8.2f %6" HIGHSINT_FORMAT " %6" HIGHSINT_FORMAT " %6" HIGHSINT_FORMAT " %7s%s\n",
1743
+ // clang-format on
1744
+ solutionSourceToString(solution_source).c_str(), print_nodes.data(),
1745
+ queue_nodes.data(), print_leaves.data(), explored, lb_string.data(),
1746
+ ub_string.data(), gap, cutpool.getNumCuts(), dynamic_constraints_in_lp,
1747
+ conflictPool.getNumConflicts(), print_lp_iters.data(),
1748
+ time_string.c_str());
1749
+ }
1750
+ // Check that limitsToBounds yields the same values for the
1751
+ // dual_bound, primal_bound (modulo optimization sense) and
1752
+ // mip_rel_gap
1753
+ double dual_bound;
1754
+ double primal_bound;
1755
+ double mip_rel_gap;
1756
+ limitsToBounds(dual_bound, primal_bound, mip_rel_gap);
1757
+ mip_rel_gap *= 1e2;
1758
+ assert(dual_bound == (int)mipsolver.orig_model_->sense_ * lb);
1759
+ assert(primal_bound == (int)mipsolver.orig_model_->sense_ * ub);
1760
+ assert(gap == mip_rel_gap);
1761
+
1762
+ // Possibly interrupt from MIP logging callback
1763
+ mipsolver.callback_->clearHighsCallbackOutput();
1764
+ const bool interrupt = interruptFromCallbackWithData(
1765
+ kCallbackMipLogging, mipsolver.solution_objective_, "MIP logging");
1766
+ assert(!interrupt);
1767
+ }
1768
+
1769
+ bool HighsMipSolverData::rootSeparationRound(
1770
+ HighsSeparation& sepa, HighsInt& ncuts, HighsLpRelaxation::Status& status) {
1771
+ int64_t tmpLpIters = -lp.getNumLpIterations();
1772
+ ncuts = sepa.separationRound(domain, status);
1773
+ tmpLpIters += lp.getNumLpIterations();
1774
+ avgrootlpiters = lp.getAvgSolveIters();
1775
+ total_lp_iterations += tmpLpIters;
1776
+ sepa_lp_iterations += tmpLpIters;
1777
+
1778
+ status = evaluateRootLp();
1779
+ if (status == HighsLpRelaxation::Status::kInfeasible) return true;
1780
+
1781
+ const std::vector<double>& solvals = lp.getLpSolver().getSolution().col_value;
1782
+
1783
+ if (mipsolver.submip || incumbent.empty()) {
1784
+ heuristics.randomizedRounding(solvals);
1785
+ if (mipsolver.options_mip_->mip_heuristic_run_shifting)
1786
+ heuristics.shifting(solvals);
1787
+ heuristics.flushStatistics();
1788
+ status = evaluateRootLp();
1789
+ if (status == HighsLpRelaxation::Status::kInfeasible) return true;
1790
+ }
1791
+
1792
+ return false;
1793
+ }
1794
+
1795
+ HighsLpRelaxation::Status HighsMipSolverData::evaluateRootLp() {
1796
+ do {
1797
+ domain.propagate();
1798
+
1799
+ if (globalOrbits && !domain.infeasible())
1800
+ globalOrbits->orbitalFixing(domain);
1801
+
1802
+ if (domain.infeasible()) {
1803
+ updateLowerBound(std::min(kHighsInf, upper_bound));
1804
+ pruned_treeweight = 1.0;
1805
+ num_nodes += 1;
1806
+ num_leaves += 1;
1807
+ return HighsLpRelaxation::Status::kInfeasible;
1808
+ }
1809
+
1810
+ bool lpBoundsChanged = false;
1811
+ if (!domain.getChangedCols().empty()) {
1812
+ lpBoundsChanged = true;
1813
+ removeFixedIndices();
1814
+ lp.flushDomain(domain);
1815
+ }
1816
+
1817
+ bool lpWasSolved = false;
1818
+ HighsLpRelaxation::Status status;
1819
+ if (lpBoundsChanged ||
1820
+ lp.getLpSolver().getModelStatus() == HighsModelStatus::kNotset) {
1821
+ int64_t lpIters = -lp.getNumLpIterations();
1822
+ status = lp.resolveLp(&domain);
1823
+ lpIters += lp.getNumLpIterations();
1824
+ total_lp_iterations += lpIters;
1825
+ avgrootlpiters = lp.getAvgSolveIters();
1826
+ lpWasSolved = true;
1827
+
1828
+ if (status == HighsLpRelaxation::Status::kUnbounded) {
1829
+ if (mipsolver.solution_.empty())
1830
+ mipsolver.modelstatus_ = HighsModelStatus::kUnboundedOrInfeasible;
1831
+ else
1832
+ mipsolver.modelstatus_ = HighsModelStatus::kUnbounded;
1833
+
1834
+ pruned_treeweight = 1.0;
1835
+ num_nodes += 1;
1836
+ num_leaves += 1;
1837
+ return status;
1838
+ }
1839
+
1840
+ if (status == HighsLpRelaxation::Status::kOptimal &&
1841
+ lp.getFractionalIntegers().empty() &&
1842
+ addIncumbent(lp.getLpSolver().getSolution().col_value,
1843
+ lp.getObjective(), kSolutionSourceEvaluateNode)) {
1844
+ mipsolver.modelstatus_ = HighsModelStatus::kOptimal;
1845
+ updateLowerBound(upper_bound);
1846
+ pruned_treeweight = 1.0;
1847
+ num_nodes += 1;
1848
+ num_leaves += 1;
1849
+ return HighsLpRelaxation::Status::kInfeasible;
1850
+ }
1851
+
1852
+ if (status == HighsLpRelaxation::Status::kOptimal &&
1853
+ mipsolver.options_mip_->mip_heuristic_run_zi_round)
1854
+ heuristics.ziRound(lp.getLpSolver().getSolution().col_value);
1855
+
1856
+ } else
1857
+ status = lp.getStatus();
1858
+
1859
+ if (status == HighsLpRelaxation::Status::kInfeasible) {
1860
+ updateLowerBound(std::min(kHighsInf, upper_bound));
1861
+ pruned_treeweight = 1.0;
1862
+ num_nodes += 1;
1863
+ num_leaves += 1;
1864
+ return status;
1865
+ }
1866
+
1867
+ if (lp.unscaledDualFeasible(lp.getStatus())) {
1868
+ updateLowerBound(std::max(lp.getObjective(), lower_bound));
1869
+
1870
+ if (lpWasSolved) {
1871
+ redcostfixing.addRootRedcost(mipsolver,
1872
+ lp.getLpSolver().getSolution().col_dual,
1873
+ lp.getObjective());
1874
+ if (upper_limit != kHighsInf)
1875
+ redcostfixing.propagateRootRedcost(mipsolver);
1876
+ }
1877
+ }
1878
+
1879
+ if (lower_bound > optimality_limit) {
1880
+ pruned_treeweight = 1.0;
1881
+ num_nodes += 1;
1882
+ num_leaves += 1;
1883
+ return HighsLpRelaxation::Status::kInfeasible;
1884
+ }
1885
+
1886
+ if (domain.getChangedCols().empty()) return status;
1887
+ } while (true);
1888
+ }
1889
+
1890
+ static void clockOff(HighsMipAnalysis& analysis) {
1891
+ if (!analysis.analyse_mip_time) return;
1892
+ // Make sure that exactly one of the following clocks is running
1893
+ const int clock0_running =
1894
+ analysis.mipTimerRunning(kMipClockEvaluateRootNode0) ? 1 : 0;
1895
+ const int clock1_running =
1896
+ analysis.mipTimerRunning(kMipClockEvaluateRootNode1) ? 1 : 0;
1897
+ const int clock2_running =
1898
+ analysis.mipTimerRunning(kMipClockEvaluateRootNode2) ? 1 : 0;
1899
+ const bool one_running = clock0_running + clock1_running + clock2_running;
1900
+ if (!one_running)
1901
+ printf("HighsMipSolverData::clockOff Clocks running are (%d; %d; %d)\n",
1902
+ clock0_running, clock1_running, clock2_running);
1903
+ assert(one_running);
1904
+ if (clock0_running) analysis.mipTimerStop(kMipClockEvaluateRootNode0);
1905
+ if (clock1_running) analysis.mipTimerStop(kMipClockEvaluateRootNode1);
1906
+ if (clock2_running) analysis.mipTimerStop(kMipClockEvaluateRootNode2);
1907
+ }
1908
+
1909
+ void HighsMipSolverData::evaluateRootNode() {
1910
+ const bool compute_analytic_centre = true;
1911
+ if (!compute_analytic_centre) printf("NOT COMPUTING ANALYTIC CENTRE!\n");
1912
+ HighsInt maxSepaRounds = mipsolver.submip ? 5 : kHighsIInf;
1913
+ if (numRestarts == 0)
1914
+ maxSepaRounds =
1915
+ std::min(HighsInt(2 * std::sqrt(maxTreeSizeLog2)), maxSepaRounds);
1916
+ std::unique_ptr<SymmetryDetectionData> symData;
1917
+ highs::parallel::TaskGroup tg;
1918
+ HighsMipAnalysis& analysis = mipsolver.analysis_;
1919
+ restart:
1920
+ analysis.mipTimerStart(kMipClockEvaluateRootNode0);
1921
+
1922
+ if (detectSymmetries) {
1923
+ analysis.mipTimerStart(kMipClockStartSymmetryDetection);
1924
+ startSymmetryDetection(tg, symData);
1925
+ analysis.mipTimerStop(kMipClockStartSymmetryDetection);
1926
+ }
1927
+ if (compute_analytic_centre && !analyticCenterComputed) {
1928
+ if (analysis.analyse_mip_time)
1929
+ highsLogUser(
1930
+ mipsolver.options_mip_->log_options, HighsLogType::kInfo,
1931
+ "MIP-Timing: %11.2g - starting analytic centre calculation\n",
1932
+ mipsolver.timer_.read());
1933
+ analysis.mipTimerStart(kMipClockStartAnalyticCentreComputation);
1934
+ startAnalyticCenterComputation(tg);
1935
+ analysis.mipTimerStop(kMipClockStartAnalyticCentreComputation);
1936
+ }
1937
+
1938
+ // lp.getLpSolver().setOptionValue(
1939
+ // "dual_simplex_cost_perturbation_multiplier", 10.0);
1940
+ lp.setIterationLimit();
1941
+ lp.loadModel();
1942
+ domain.clearChangedCols();
1943
+ lp.setObjectiveLimit(upper_limit);
1944
+
1945
+ updateLowerBound(std::max(lower_bound, domain.getObjectiveLowerBound()));
1946
+
1947
+ printDisplayLine();
1948
+
1949
+ // Possibly query existence of an external solution
1950
+ if (!mipsolver.submip)
1951
+ mipsolver.mipdata_->queryExternalSolution(
1952
+ mipsolver.solution_objective_,
1953
+ kExternalMipSolutionQueryOriginEvaluateRootNode0);
1954
+
1955
+ // check if only root presolve is allowed
1956
+ if (firstrootbasis.valid)
1957
+ lp.getLpSolver().setBasis(firstrootbasis,
1958
+ "HighsMipSolverData::evaluateRootNode");
1959
+ else if (mipsolver.options_mip_->mip_root_presolve_only)
1960
+ lp.getLpSolver().setOptionValue("presolve", kHighsOffString);
1961
+ else
1962
+ lp.getLpSolver().setOptionValue("presolve", kHighsOnString);
1963
+ if (mipsolver.options_mip_->highs_debug_level)
1964
+ lp.getLpSolver().setOptionValue("output_flag",
1965
+ mipsolver.options_mip_->output_flag);
1966
+ // lp.getLpSolver().setOptionValue("log_dev_level", kHighsLogDevLevelInfo);
1967
+ // lp.getLpSolver().setOptionValue("log_file",
1968
+ // mipsolver.options_mip_->log_file);
1969
+
1970
+ analysis.mipTimerStart(kMipClockEvaluateRootLp);
1971
+ HighsLpRelaxation::Status status = evaluateRootLp();
1972
+ analysis.mipTimerStop(kMipClockEvaluateRootLp);
1973
+ if (numRestarts == 0) firstrootlpiters = total_lp_iterations;
1974
+
1975
+ lp.getLpSolver().setOptionValue("output_flag", false);
1976
+ lp.getLpSolver().setOptionValue("presolve", kHighsOffString);
1977
+ lp.getLpSolver().setOptionValue("parallel", kHighsOffString);
1978
+
1979
+ if (status == HighsLpRelaxation::Status::kInfeasible ||
1980
+ status == HighsLpRelaxation::Status::kUnbounded)
1981
+ return clockOff(analysis);
1982
+
1983
+ firstlpsol = lp.getSolution().col_value;
1984
+ firstlpsolobj = lp.getObjective();
1985
+ rootlpsolobj = firstlpsolobj;
1986
+
1987
+ if (lp.getLpSolver().getBasis().valid && lp.numRows() == mipsolver.numRow())
1988
+ firstrootbasis = lp.getLpSolver().getBasis();
1989
+ else {
1990
+ // the root basis is later expected to be consistent for the model without
1991
+ // cuts so set it to the slack basis if the current basis already includes
1992
+ // cuts, e.g. due to a restart
1993
+ firstrootbasis.col_status.assign(mipsolver.numCol(),
1994
+ HighsBasisStatus::kNonbasic);
1995
+ firstrootbasis.row_status.assign(mipsolver.numRow(),
1996
+ HighsBasisStatus::kBasic);
1997
+ firstrootbasis.valid = true;
1998
+ firstrootbasis.useful = true;
1999
+ }
2000
+
2001
+ if (cutpool.getNumCuts() != 0) {
2002
+ assert(numRestarts != 0);
2003
+ HighsCutSet cutset;
2004
+ analysis.mipTimerStart(kMipClockSeparateLpCuts);
2005
+ cutpool.separateLpCutsAfterRestart(cutset);
2006
+ analysis.mipTimerStop(kMipClockSeparateLpCuts);
2007
+ #ifdef HIGHS_DEBUGSOL
2008
+ for (HighsInt i = 0; i < cutset.numCuts(); ++i) {
2009
+ debugSolution.checkCut(cutset.ARindex_.data() + cutset.ARstart_[i],
2010
+ cutset.ARvalue_.data() + cutset.ARstart_[i],
2011
+ cutset.ARstart_[i + 1] - cutset.ARstart_[i],
2012
+ cutset.upper_[i]);
2013
+ }
2014
+ #endif
2015
+ lp.addCuts(cutset);
2016
+ analysis.mipTimerStart(kMipClockEvaluateRootLp);
2017
+ status = evaluateRootLp();
2018
+ analysis.mipTimerStop(kMipClockEvaluateRootLp);
2019
+ lp.removeObsoleteRows();
2020
+ if (status == HighsLpRelaxation::Status::kInfeasible)
2021
+ return clockOff(analysis);
2022
+ }
2023
+
2024
+ lp.setIterationLimit(std::max(10000, int(10 * avgrootlpiters)));
2025
+
2026
+ // make sure first line after solving root LP is printed
2027
+ last_disptime = -kHighsInf;
2028
+ disptime = 0;
2029
+
2030
+ if (mipsolver.options_mip_->mip_heuristic_run_zi_round)
2031
+ heuristics.ziRound(firstlpsol);
2032
+ analysis.mipTimerStart(kMipClockRandomizedRounding);
2033
+ heuristics.randomizedRounding(firstlpsol);
2034
+ analysis.mipTimerStop(kMipClockRandomizedRounding);
2035
+ if (mipsolver.options_mip_->mip_heuristic_run_shifting)
2036
+ heuristics.shifting(firstlpsol);
2037
+
2038
+ heuristics.flushStatistics();
2039
+
2040
+ analysis.mipTimerStart(kMipClockEvaluateRootLp);
2041
+ status = evaluateRootLp();
2042
+ analysis.mipTimerStop(kMipClockEvaluateRootLp);
2043
+ if (status == HighsLpRelaxation::Status::kInfeasible)
2044
+ return clockOff(analysis);
2045
+
2046
+ rootlpsolobj = firstlpsolobj;
2047
+ removeFixedIndices();
2048
+ if (mipsolver.options_mip_->mip_allow_restart &&
2049
+ mipsolver.options_mip_->presolve != kHighsOffString) {
2050
+ double fixingRate = percentageInactiveIntegers();
2051
+ if (fixingRate >= 10.0) {
2052
+ tg.cancel();
2053
+ highsLogUser(mipsolver.options_mip_->log_options, HighsLogType::kInfo,
2054
+ "\n%.1f%% inactive integer columns, restarting\n",
2055
+ fixingRate);
2056
+ tg.taskWait();
2057
+ analysis.mipTimerStart(kMipClockPerformRestart);
2058
+ performRestart();
2059
+ analysis.mipTimerStop(kMipClockPerformRestart);
2060
+ ++numRestartsRoot;
2061
+ if (mipsolver.modelstatus_ == HighsModelStatus::kNotset) {
2062
+ clockOff(analysis);
2063
+ goto restart;
2064
+ }
2065
+
2066
+ return clockOff(analysis);
2067
+ }
2068
+ }
2069
+
2070
+ // begin separation
2071
+ if (analysis.analyse_mip_time) {
2072
+ highsLogUser(mipsolver.options_mip_->log_options, HighsLogType::kInfo,
2073
+ "MIP-Timing: %11.2g - starting separation\n",
2074
+ analysis.mip_clocks.timer_pointer_->read(0));
2075
+ fflush(stdout);
2076
+ }
2077
+ analysis.mipTimerStart(kMipClockRootSeparation);
2078
+ std::vector<double> avgdirection;
2079
+ std::vector<double> curdirection;
2080
+ avgdirection.resize(mipsolver.numCol());
2081
+ curdirection.resize(mipsolver.numCol());
2082
+
2083
+ HighsInt stall = 0;
2084
+ double smoothprogress = 0.0;
2085
+ HighsInt nseparounds = 0;
2086
+ HighsSeparation sepa(mipsolver);
2087
+ sepa.setLpRelaxation(&lp);
2088
+
2089
+ while (lp.scaledOptimal(status) && !lp.getFractionalIntegers().empty() &&
2090
+ stall < 3) {
2091
+ printDisplayLine();
2092
+
2093
+ if (checkLimits()) {
2094
+ analysis.mipTimerStop(kMipClockRootSeparation);
2095
+ return clockOff(analysis);
2096
+ }
2097
+
2098
+ if (nseparounds == maxSepaRounds) break;
2099
+
2100
+ removeFixedIndices();
2101
+
2102
+ if (!mipsolver.submip &&
2103
+ mipsolver.options_mip_->presolve != kHighsOffString) {
2104
+ double fixingRate = percentageInactiveIntegers();
2105
+ if (fixingRate >= 10.0) {
2106
+ stall = -1;
2107
+ break;
2108
+ }
2109
+ }
2110
+
2111
+ ++nseparounds;
2112
+
2113
+ HighsInt ncuts;
2114
+
2115
+ analysis.mipTimerStart(kMipClockRootSeparationRound);
2116
+ const bool root_separation_round_result =
2117
+ rootSeparationRound(sepa, ncuts, status);
2118
+ analysis.mipTimerStop(kMipClockRootSeparationRound);
2119
+ if (root_separation_round_result) {
2120
+ analysis.mipTimerStop(kMipClockRootSeparation);
2121
+ return clockOff(analysis);
2122
+ }
2123
+ if (nseparounds >= 5 && !mipsolver.submip && !analyticCenterComputed &&
2124
+ compute_analytic_centre) {
2125
+ if (checkLimits()) {
2126
+ analysis.mipTimerStop(kMipClockRootSeparation);
2127
+ return clockOff(analysis);
2128
+ }
2129
+ analysis.mipTimerStart(
2130
+ kMipClockRootSeparationFinishAnalyticCentreComputation);
2131
+ finishAnalyticCenterComputation(tg);
2132
+ analysis.mipTimerStop(
2133
+ kMipClockRootSeparationFinishAnalyticCentreComputation);
2134
+
2135
+ analysis.mipTimerStart(kMipClockRootSeparationCentralRounding);
2136
+ heuristics.centralRounding();
2137
+ analysis.mipTimerStop(kMipClockRootSeparationCentralRounding);
2138
+
2139
+ heuristics.flushStatistics();
2140
+
2141
+ if (checkLimits()) {
2142
+ analysis.mipTimerStop(kMipClockRootSeparation);
2143
+ return clockOff(analysis);
2144
+ }
2145
+ analysis.mipTimerStart(kMipClockRootSeparationEvaluateRootLp);
2146
+ status = evaluateRootLp();
2147
+ analysis.mipTimerStop(kMipClockRootSeparationEvaluateRootLp);
2148
+ if (status == HighsLpRelaxation::Status::kInfeasible) {
2149
+ analysis.mipTimerStop(kMipClockRootSeparation);
2150
+ return clockOff(analysis);
2151
+ }
2152
+ }
2153
+
2154
+ HighsCDouble sqrnorm = 0.0;
2155
+ const auto& solvals = lp.getSolution().col_value;
2156
+
2157
+ for (HighsInt i = 0; i != mipsolver.numCol(); ++i) {
2158
+ curdirection[i] = firstlpsol[i] - solvals[i];
2159
+
2160
+ // if (mip.integrality_[i] == 2 && lp.getObjective() > firstobj &&
2161
+ // std::abs(curdirection[i]) > 1e-6)
2162
+ // pseudocost.addObservation(i, -curdirection[i],
2163
+ // lp.getObjective() - firstobj);
2164
+
2165
+ sqrnorm += curdirection[i] * curdirection[i];
2166
+ }
2167
+ #if 1
2168
+ double scale = double(1.0 / sqrt(sqrnorm));
2169
+ sqrnorm = 0.0;
2170
+ HighsCDouble dotproduct = 0.0;
2171
+ for (HighsInt i = 0; i != mipsolver.numCol(); ++i) {
2172
+ avgdirection[i] =
2173
+ (scale * curdirection[i] - avgdirection[i]) / nseparounds;
2174
+ sqrnorm += avgdirection[i] * avgdirection[i];
2175
+ dotproduct += avgdirection[i] * curdirection[i];
2176
+ }
2177
+ #endif
2178
+
2179
+ double progress = double(dotproduct / sqrt(sqrnorm));
2180
+
2181
+ if (nseparounds == 1) {
2182
+ smoothprogress = progress;
2183
+ } else {
2184
+ double alpha = 1.0 / 3.0;
2185
+ double nextprogress = (1.0 - alpha) * smoothprogress + alpha * progress;
2186
+
2187
+ if (nextprogress < smoothprogress * 1.01 &&
2188
+ (lp.getObjective() - firstlpsolobj) <=
2189
+ (rootlpsolobj - firstlpsolobj) * 1.001)
2190
+ ++stall;
2191
+ else {
2192
+ stall = 0;
2193
+ }
2194
+ smoothprogress = nextprogress;
2195
+ }
2196
+
2197
+ rootlpsolobj = lp.getObjective();
2198
+ lp.setIterationLimit(std::max(10000, int(10 * avgrootlpiters)));
2199
+ if (ncuts == 0) break;
2200
+
2201
+ // Possibly query existence of an external solution
2202
+ if (!mipsolver.submip)
2203
+ mipsolver.mipdata_->queryExternalSolution(
2204
+ mipsolver.solution_objective_,
2205
+ kExternalMipSolutionQueryOriginEvaluateRootNode1);
2206
+ }
2207
+ analysis.mipTimerStop(kMipClockRootSeparation);
2208
+ if (analysis.analyse_mip_time) {
2209
+ highsLogUser(mipsolver.options_mip_->log_options, HighsLogType::kInfo,
2210
+ "MIP-Timing: %11.2g - completed separation\n",
2211
+ analysis.mip_clocks.timer_pointer_->read(0));
2212
+ fflush(stdout);
2213
+ }
2214
+
2215
+ lp.setIterationLimit();
2216
+ analysis.mipTimerStart(kMipClockEvaluateRootLp);
2217
+ status = evaluateRootLp();
2218
+ analysis.mipTimerStop(kMipClockEvaluateRootLp);
2219
+ if (status == HighsLpRelaxation::Status::kInfeasible)
2220
+ return clockOff(analysis);
2221
+
2222
+ rootlpsol = lp.getLpSolver().getSolution().col_value;
2223
+ rootlpsolobj = lp.getObjective();
2224
+ lp.setIterationLimit(std::max(10000, int(10 * avgrootlpiters)));
2225
+
2226
+ if (mipsolver.options_mip_->mip_heuristic_run_zi_round) {
2227
+ heuristics.ziRound(firstlpsol);
2228
+ heuristics.flushStatistics();
2229
+ }
2230
+ if (mipsolver.options_mip_->mip_heuristic_run_shifting) {
2231
+ heuristics.shifting(rootlpsol);
2232
+ heuristics.flushStatistics();
2233
+ }
2234
+
2235
+ if (!analyticCenterComputed && compute_analytic_centre) {
2236
+ if (checkLimits()) return clockOff(analysis);
2237
+
2238
+ analysis.mipTimerStart(kMipClockFinishAnalyticCentreComputation);
2239
+ finishAnalyticCenterComputation(tg);
2240
+ analysis.mipTimerStop(kMipClockFinishAnalyticCentreComputation);
2241
+
2242
+ analysis.mipTimerStart(kMipClockRootCentralRounding);
2243
+ heuristics.centralRounding();
2244
+ analysis.mipTimerStop(kMipClockRootCentralRounding);
2245
+
2246
+ heuristics.flushStatistics();
2247
+
2248
+ // if there are new global bound changes we re-evaluate the LP and do one
2249
+ // more separation round
2250
+ if (checkLimits()) return clockOff(analysis);
2251
+ bool separate = !domain.getChangedCols().empty();
2252
+ analysis.mipTimerStart(kMipClockEvaluateRootLp);
2253
+ status = evaluateRootLp();
2254
+ analysis.mipTimerStop(kMipClockEvaluateRootLp);
2255
+ if (status == HighsLpRelaxation::Status::kInfeasible)
2256
+ return clockOff(analysis);
2257
+ if (separate && lp.scaledOptimal(status)) {
2258
+ HighsInt ncuts;
2259
+ analysis.mipTimerStart(kMipClockRootSeparationRound0);
2260
+ const bool root_separation_round_result =
2261
+ rootSeparationRound(sepa, ncuts, status);
2262
+ analysis.mipTimerStop(kMipClockRootSeparationRound0);
2263
+ if (root_separation_round_result) return clockOff(analysis);
2264
+ ++nseparounds;
2265
+ printDisplayLine();
2266
+ }
2267
+ }
2268
+
2269
+ printDisplayLine();
2270
+ // Possibly query existence of an external solution
2271
+ if (!mipsolver.submip)
2272
+ mipsolver.mipdata_->queryExternalSolution(
2273
+ mipsolver.solution_objective_,
2274
+ kExternalMipSolutionQueryOriginEvaluateRootNode2);
2275
+
2276
+ // Possible cut extraction callback
2277
+ if (!mipsolver.submip && mipsolver.callback_->user_callback &&
2278
+ mipsolver.callback_->callbackActive(kCallbackMipGetCutPool))
2279
+ mipsolver.callbackGetCutPool();
2280
+ if (checkLimits()) return clockOff(analysis);
2281
+
2282
+ analysis.mipTimerStop(kMipClockEvaluateRootNode0);
2283
+ analysis.mipTimerStart(kMipClockEvaluateRootNode1);
2284
+ do {
2285
+ if (rootlpsol.empty()) break;
2286
+ if (upper_limit != kHighsInf && !moreHeuristicsAllowed()) break;
2287
+
2288
+ if (mipsolver.options_mip_->mip_heuristic_run_root_reduced_cost) {
2289
+ analysis.mipTimerStart(kMipClockRootHeuristicsReducedCost);
2290
+ heuristics.rootReducedCost();
2291
+ analysis.mipTimerStop(kMipClockRootHeuristicsReducedCost);
2292
+ heuristics.flushStatistics();
2293
+ }
2294
+
2295
+ if (checkLimits()) return clockOff(analysis);
2296
+
2297
+ // if there are new global bound changes we re-evaluate the LP and do one
2298
+ // more separation round
2299
+ bool separate = !domain.getChangedCols().empty();
2300
+ analysis.mipTimerStart(kMipClockEvaluateRootLp);
2301
+ status = evaluateRootLp();
2302
+ analysis.mipTimerStop(kMipClockEvaluateRootLp);
2303
+ if (status == HighsLpRelaxation::Status::kInfeasible)
2304
+ return clockOff(analysis);
2305
+ if (separate && lp.scaledOptimal(status)) {
2306
+ HighsInt ncuts;
2307
+ analysis.mipTimerStart(kMipClockRootSeparationRound1);
2308
+ const bool root_separation_round_result =
2309
+ rootSeparationRound(sepa, ncuts, status);
2310
+ analysis.mipTimerStop(kMipClockRootSeparationRound1);
2311
+ if (root_separation_round_result) return clockOff(analysis);
2312
+ ++nseparounds;
2313
+ printDisplayLine();
2314
+ }
2315
+
2316
+ if (upper_limit != kHighsInf && !moreHeuristicsAllowed()) break;
2317
+
2318
+ if (checkLimits()) return clockOff(analysis);
2319
+ if (mipsolver.options_mip_->mip_heuristic_run_rens) {
2320
+ analysis.mipTimerStart(kMipClockRootHeuristicsRens);
2321
+ heuristics.RENS(rootlpsol);
2322
+ analysis.mipTimerStop(kMipClockRootHeuristicsRens);
2323
+ heuristics.flushStatistics();
2324
+ }
2325
+
2326
+ if (checkLimits()) return clockOff(analysis);
2327
+ // if there are new global bound changes we re-evaluate the LP and do one
2328
+ // more separation round
2329
+ separate = !domain.getChangedCols().empty();
2330
+ analysis.mipTimerStart(kMipClockEvaluateRootLp);
2331
+ status = evaluateRootLp();
2332
+ analysis.mipTimerStop(kMipClockEvaluateRootLp);
2333
+ if (status == HighsLpRelaxation::Status::kInfeasible)
2334
+ return clockOff(analysis);
2335
+ if (separate && lp.scaledOptimal(status)) {
2336
+ HighsInt ncuts;
2337
+ analysis.mipTimerStart(kMipClockRootSeparationRound2);
2338
+ const bool root_separation_round_result =
2339
+ rootSeparationRound(sepa, ncuts, status);
2340
+ analysis.mipTimerStop(kMipClockRootSeparationRound2);
2341
+ if (root_separation_round_result) return clockOff(analysis);
2342
+ ++nseparounds;
2343
+
2344
+ printDisplayLine();
2345
+ // Possibly query existence of an external solution
2346
+ if (!mipsolver.submip)
2347
+ mipsolver.mipdata_->queryExternalSolution(
2348
+ mipsolver.solution_objective_,
2349
+ kExternalMipSolutionQueryOriginEvaluateRootNode3);
2350
+ }
2351
+
2352
+ if (upper_limit != kHighsInf || mipsolver.submip) break;
2353
+
2354
+ if (checkLimits()) return clockOff(analysis);
2355
+ analysis.mipTimerStart(kMipClockRootFeasibilityPump);
2356
+ heuristics.feasibilityPump();
2357
+ analysis.mipTimerStop(kMipClockRootFeasibilityPump);
2358
+ heuristics.flushStatistics();
2359
+
2360
+ if (checkLimits()) return clockOff(analysis);
2361
+ analysis.mipTimerStart(kMipClockEvaluateRootLp);
2362
+ status = evaluateRootLp();
2363
+ analysis.mipTimerStop(kMipClockEvaluateRootLp);
2364
+ if (status == HighsLpRelaxation::Status::kInfeasible)
2365
+ return clockOff(analysis);
2366
+ } while (false);
2367
+
2368
+ analysis.mipTimerStop(kMipClockEvaluateRootNode1);
2369
+ analysis.mipTimerStart(kMipClockEvaluateRootNode2);
2370
+ if (lower_bound > upper_limit) {
2371
+ mipsolver.modelstatus_ = HighsModelStatus::kOptimal;
2372
+ pruned_treeweight = 1.0;
2373
+ num_nodes += 1;
2374
+ num_leaves += 1;
2375
+ return clockOff(analysis);
2376
+ }
2377
+
2378
+ // if there are new global bound changes we re-evaluate the LP and do one
2379
+ // more separation round
2380
+ bool separate = !domain.getChangedCols().empty();
2381
+ analysis.mipTimerStart(kMipClockEvaluateRootLp);
2382
+ status = evaluateRootLp();
2383
+ analysis.mipTimerStop(kMipClockEvaluateRootLp);
2384
+ if (status == HighsLpRelaxation::Status::kInfeasible)
2385
+ return clockOff(analysis);
2386
+ if (separate && lp.scaledOptimal(status)) {
2387
+ HighsInt ncuts;
2388
+ analysis.mipTimerStart(kMipClockRootSeparationRound3);
2389
+ const bool root_separation_round_result =
2390
+ rootSeparationRound(sepa, ncuts, status);
2391
+ analysis.mipTimerStop(kMipClockRootSeparationRound3);
2392
+ if (root_separation_round_result) return clockOff(analysis);
2393
+ ++nseparounds;
2394
+ printDisplayLine();
2395
+ }
2396
+
2397
+ // Possibly query existence of an external solution
2398
+ if (!mipsolver.submip)
2399
+ mipsolver.mipdata_->queryExternalSolution(
2400
+ mipsolver.solution_objective_,
2401
+ kExternalMipSolutionQueryOriginEvaluateRootNode4);
2402
+
2403
+ removeFixedIndices();
2404
+ if (lp.getLpSolver().getBasis().valid) lp.removeObsoleteRows();
2405
+ rootlpsolobj = lp.getObjective();
2406
+
2407
+ printDisplayLine();
2408
+
2409
+ if (lower_bound <= upper_limit) {
2410
+ if (!mipsolver.submip && mipsolver.options_mip_->mip_allow_restart &&
2411
+ mipsolver.options_mip_->presolve != kHighsOffString) {
2412
+ if (!analyticCenterComputed && compute_analytic_centre) {
2413
+ analysis.mipTimerStart(kMipClockFinishAnalyticCentreComputation);
2414
+ finishAnalyticCenterComputation(tg);
2415
+ analysis.mipTimerStop(kMipClockFinishAnalyticCentreComputation);
2416
+ }
2417
+ double fixingRate = percentageInactiveIntegers();
2418
+ if (fixingRate >= 2.5 + 7.5 * mipsolver.submip ||
2419
+ (!mipsolver.submip && fixingRate > 0 && numRestarts == 0)) {
2420
+ tg.cancel();
2421
+ highsLogUser(mipsolver.options_mip_->log_options, HighsLogType::kInfo,
2422
+ "\n%.1f%% inactive integer columns, restarting\n",
2423
+ fixingRate);
2424
+ if (stall != -1) maxSepaRounds = std::min(maxSepaRounds, nseparounds);
2425
+ tg.taskWait();
2426
+ analysis.mipTimerStart(kMipClockPerformRestart);
2427
+ performRestart();
2428
+ analysis.mipTimerStop(kMipClockPerformRestart);
2429
+ if (mipsolver.terminate()) return;
2430
+ ++numRestartsRoot;
2431
+ if (mipsolver.modelstatus_ == HighsModelStatus::kNotset) {
2432
+ clockOff(analysis);
2433
+ goto restart;
2434
+ }
2435
+ return clockOff(analysis);
2436
+ }
2437
+ }
2438
+
2439
+ if (detectSymmetries) {
2440
+ finishSymmetryDetection(tg, symData);
2441
+ analysis.mipTimerStart(kMipClockEvaluateRootLp);
2442
+ status = evaluateRootLp();
2443
+ analysis.mipTimerStop(kMipClockEvaluateRootLp);
2444
+ if (status == HighsLpRelaxation::Status::kInfeasible)
2445
+ return clockOff(analysis);
2446
+ }
2447
+
2448
+ // add the root node to the nodequeue to initialize the search
2449
+ nodequeue.emplaceNode(std::vector<HighsDomainChange>(),
2450
+ std::vector<HighsInt>(), lower_bound,
2451
+ lp.computeBestEstimate(pseudocost), 1);
2452
+ }
2453
+ // End of HighsMipSolverData::evaluateRootNode()
2454
+ clockOff(analysis);
2455
+ }
2456
+
2457
+ bool HighsMipSolverData::checkLimits(int64_t nodeOffset) const {
2458
+ const HighsOptions& options = *mipsolver.options_mip_;
2459
+
2460
+ // This MIP instance may have been terminated
2461
+ if (terminatorActive())
2462
+ if (this->terminatorTerminated()) return true;
2463
+
2464
+ // Possible user interrupt
2465
+ if (!mipsolver.submip && mipsolver.callback_->user_callback) {
2466
+ mipsolver.callback_->clearHighsCallbackOutput();
2467
+ if (interruptFromCallbackWithData(kCallbackMipInterrupt,
2468
+ mipsolver.solution_objective_,
2469
+ "MIP check limits")) {
2470
+ if (mipsolver.modelstatus_ == HighsModelStatus::kNotset) {
2471
+ highsLogDev(options.log_options, HighsLogType::kInfo,
2472
+ "User interrupt\n");
2473
+ mipsolver.modelstatus_ = HighsModelStatus::kInterrupt;
2474
+ }
2475
+ return true;
2476
+ }
2477
+ }
2478
+ // Possible termination due to objective being at least as good as
2479
+ // the target value
2480
+ if (!mipsolver.submip && mipsolver.solution_objective_ < kHighsInf &&
2481
+ options.objective_target > -kHighsInf) {
2482
+ // Note:
2483
+ //
2484
+ // Whether the sense is ObjSense::kMinimize or
2485
+ // ObjSense::kMaximize, the undefined value of
2486
+ // mipsolver.solution_objective_ is kHighsInf, and the default
2487
+ // target value is -kHighsInf, so had to rule out these cases in
2488
+ // the conditional statement above.
2489
+ //
2490
+ // mipsolver.solution_objective_ is the actual objective of the
2491
+ // MIP - including the offset, and independent of objective sense
2492
+ //
2493
+ // The target is reached if the objective is below (above) the
2494
+ // target value when minimizing (maximizing).
2495
+ const int int_sense = int(this->mipsolver.orig_model_->sense_);
2496
+ const bool reached_objective_target =
2497
+ int_sense * mipsolver.solution_objective_ <
2498
+ int_sense * options.objective_target;
2499
+ if (reached_objective_target) {
2500
+ if (mipsolver.modelstatus_ == HighsModelStatus::kNotset) {
2501
+ highsLogDev(options.log_options, HighsLogType::kInfo,
2502
+ "Reached objective target\n");
2503
+ mipsolver.modelstatus_ = HighsModelStatus::kObjectiveTarget;
2504
+ }
2505
+ return true;
2506
+ }
2507
+ }
2508
+
2509
+ if (options.mip_max_nodes != kHighsIInf &&
2510
+ num_nodes + nodeOffset >= options.mip_max_nodes) {
2511
+ if (mipsolver.modelstatus_ == HighsModelStatus::kNotset) {
2512
+ highsLogDev(options.log_options, HighsLogType::kInfo,
2513
+ "Reached node limit\n");
2514
+ mipsolver.modelstatus_ = HighsModelStatus::kSolutionLimit;
2515
+ }
2516
+ return true;
2517
+ }
2518
+
2519
+ if (options.mip_max_leaves != kHighsIInf &&
2520
+ num_leaves >= options.mip_max_leaves) {
2521
+ if (mipsolver.modelstatus_ == HighsModelStatus::kNotset) {
2522
+ highsLogDev(options.log_options, HighsLogType::kInfo,
2523
+ "Reached leaf node limit\n");
2524
+ mipsolver.modelstatus_ = HighsModelStatus::kSolutionLimit;
2525
+ }
2526
+ return true;
2527
+ }
2528
+
2529
+ if (options.mip_max_improving_sols != kHighsIInf &&
2530
+ numImprovingSols >= options.mip_max_improving_sols) {
2531
+ if (mipsolver.modelstatus_ == HighsModelStatus::kNotset) {
2532
+ highsLogDev(options.log_options, HighsLogType::kInfo,
2533
+ "Reached improving solution limit\n");
2534
+ mipsolver.modelstatus_ = HighsModelStatus::kSolutionLimit;
2535
+ }
2536
+ return true;
2537
+ }
2538
+
2539
+ // const double time = mipsolver.timer_.read();
2540
+ // printf("checkLimits: time = %g\n", time);
2541
+ if (options.time_limit < kHighsInf &&
2542
+ mipsolver.timer_.read() >= options.time_limit) {
2543
+ if (mipsolver.modelstatus_ == HighsModelStatus::kNotset) {
2544
+ highsLogDev(options.log_options, HighsLogType::kInfo,
2545
+ "Reached time limit\n");
2546
+ mipsolver.modelstatus_ = HighsModelStatus::kTimeLimit;
2547
+ }
2548
+ return true;
2549
+ }
2550
+
2551
+ return false;
2552
+ }
2553
+
2554
+ void HighsMipSolverData::checkObjIntegrality() {
2555
+ objectiveFunction.checkIntegrality(epsilon);
2556
+ if (objectiveFunction.isIntegral() && numRestarts == 0) {
2557
+ highsLogUser(mipsolver.options_mip_->log_options, HighsLogType::kInfo,
2558
+ "Objective function is integral with scale %g\n",
2559
+ objectiveFunction.integralScale());
2560
+ }
2561
+ }
2562
+
2563
+ void HighsMipSolverData::setupDomainPropagation() {
2564
+ const HighsLp& model = *mipsolver.model_;
2565
+ highsSparseTranspose(model.num_row_, model.num_col_, model.a_matrix_.start_,
2566
+ model.a_matrix_.index_, model.a_matrix_.value_, ARstart_,
2567
+ ARindex_, ARvalue_);
2568
+
2569
+ pseudocost = HighsPseudocost(mipsolver);
2570
+
2571
+ // compute the maximal absolute coefficients to filter propagation
2572
+ maxAbsRowCoef.resize(mipsolver.numRow());
2573
+ for (HighsInt i = 0; i != mipsolver.numRow(); ++i) {
2574
+ double maxabsval = 0.0;
2575
+
2576
+ HighsInt start = ARstart_[i];
2577
+ HighsInt end = ARstart_[i + 1];
2578
+ for (HighsInt j = start; j != end; ++j)
2579
+ maxabsval = std::max(maxabsval, std::abs(ARvalue_[j]));
2580
+
2581
+ maxAbsRowCoef[i] = maxabsval;
2582
+ }
2583
+
2584
+ domain = HighsDomain(mipsolver);
2585
+ domain.computeRowActivities();
2586
+ }
2587
+
2588
+ void HighsMipSolverData::saveReportMipSolution(const double new_upper_limit) {
2589
+ const bool non_improving = new_upper_limit >= upper_limit;
2590
+ if (mipsolver.submip) return;
2591
+ if (non_improving) return;
2592
+
2593
+ if (mipsolver.callback_->user_callback) {
2594
+ if (mipsolver.callback_->active[kCallbackMipImprovingSolution]) {
2595
+ mipsolver.callback_->clearHighsCallbackOutput();
2596
+ mipsolver.callback_->data_out.mip_solution = mipsolver.solution_;
2597
+ const bool interrupt = interruptFromCallbackWithData(
2598
+ kCallbackMipImprovingSolution, mipsolver.solution_objective_,
2599
+ "Improving solution");
2600
+ assert(!interrupt);
2601
+ }
2602
+ }
2603
+
2604
+ if (mipsolver.options_mip_->mip_improving_solution_save) {
2605
+ HighsObjectiveSolution record;
2606
+ record.objective = mipsolver.solution_objective_;
2607
+ record.col_value = mipsolver.solution_;
2608
+ mipsolver.saved_objective_and_solution_.push_back(record);
2609
+ }
2610
+ FILE* file = mipsolver.improving_solution_file_;
2611
+ if (file) {
2612
+ writeLpObjective(file, mipsolver.options_mip_->log_options,
2613
+ *(mipsolver.orig_model_), mipsolver.solution_);
2614
+ writePrimalSolution(
2615
+ file, mipsolver.options_mip_->log_options, *(mipsolver.orig_model_),
2616
+ mipsolver.solution_,
2617
+ mipsolver.options_mip_->mip_improving_solution_report_sparse);
2618
+ }
2619
+ }
2620
+
2621
+ void HighsMipSolverData::limitsToBounds(double& dual_bound,
2622
+ double& primal_bound,
2623
+ double& mip_rel_gap) const {
2624
+ mip_rel_gap = limitsToGap(lower_bound, upper_bound, dual_bound, primal_bound);
2625
+ primal_bound =
2626
+ std::min(mipsolver.options_mip_->objective_bound, primal_bound);
2627
+ // Adjust objective sense in case of maximization problem
2628
+ if (this->mipsolver.orig_model_->sense_ == ObjSense::kMaximize) {
2629
+ dual_bound = -dual_bound;
2630
+ primal_bound = -primal_bound;
2631
+ }
2632
+ }
2633
+
2634
+ void HighsMipSolverData::updateLowerBound(double new_lower_bound) {
2635
+ // Update lower bound
2636
+ double prev_lower_bound = lower_bound;
2637
+ lower_bound = new_lower_bound;
2638
+ if (!mipsolver.submip && lower_bound != prev_lower_bound)
2639
+ updatePrimalDualIntegral(prev_lower_bound, lower_bound, upper_bound,
2640
+ upper_bound);
2641
+ }
2642
+
2643
+ // Interface to callbackAction, with mipsolver_objective_value since
2644
+ // incumbent value (mipsolver.solution_objective_) is not right for
2645
+ // callback_type = kCallbackMipSolution
2646
+
2647
+ void HighsMipSolverData::setCallbackDataOut(
2648
+ const double mipsolver_objective_value) const {
2649
+ double dual_bound;
2650
+ double primal_bound;
2651
+ double mip_rel_gap;
2652
+ limitsToBounds(dual_bound, primal_bound, mip_rel_gap);
2653
+ mipsolver.callback_->data_out.running_time = mipsolver.timer_.read();
2654
+ mipsolver.callback_->data_out.objective_function_value =
2655
+ mipsolver_objective_value;
2656
+ mipsolver.callback_->data_out.mip_node_count = mipsolver.mipdata_->num_nodes;
2657
+ mipsolver.callback_->data_out.mip_total_lp_iterations =
2658
+ mipsolver.mipdata_->total_lp_iterations;
2659
+ mipsolver.callback_->data_out.mip_primal_bound = primal_bound;
2660
+ mipsolver.callback_->data_out.mip_dual_bound = dual_bound;
2661
+ mipsolver.callback_->data_out.mip_gap = mip_rel_gap;
2662
+ }
2663
+
2664
+ bool HighsMipSolverData::interruptFromCallbackWithData(
2665
+ const int callback_type, const double mipsolver_objective_value,
2666
+ const std::string message) const {
2667
+ if (!mipsolver.callback_->callbackActive(callback_type)) return false;
2668
+ assert(!mipsolver.submip);
2669
+ setCallbackDataOut(mipsolver_objective_value);
2670
+ return mipsolver.callback_->callbackAction(callback_type, message);
2671
+ }
2672
+
2673
+ void HighsMipSolverData::queryExternalSolution(
2674
+ const double mipsolver_objective_value,
2675
+ const ExternalMipSolutionQueryOrigin external_solution_query_origin) {
2676
+ assert(!mipsolver.submip);
2677
+ HighsCallback* callback = mipsolver.callback_;
2678
+ const bool use_callback =
2679
+ callback->user_callback && callback->active[kCallbackMipUserSolution];
2680
+ if (use_callback) {
2681
+ setCallbackDataOut(mipsolver_objective_value);
2682
+ callback->data_out.external_solution_query_origin =
2683
+ external_solution_query_origin;
2684
+ callback->clearHighsCallbackInput();
2685
+
2686
+ const bool interrupt =
2687
+ callback->callbackAction(kCallbackMipUserSolution, "MIP User solution");
2688
+ assert(!interrupt);
2689
+ if (callback->data_in.user_has_solution) {
2690
+ // Objective is assumed to be original_offset +
2691
+ // (original_c)^T(original_x), but MIP solver bounds are based on the
2692
+ // reduced objective (reduced_c)^T(reduced_x)
2693
+ //
2694
+ // Now, original_sense*[reduced_offset + (reduced_c)^T(reduced_x)] is an
2695
+ // objective in the original space, so
2696
+ //
2697
+ // f0 + c0^Tx0 = s*(f1 + c1^Tx1)
2698
+ //
2699
+ // where 0 => original; 1 => reduced
2700
+ //
2701
+ // This allows the reduced objective value to be deduced as
2702
+ //
2703
+ // c1^Tx1 = s*(f0 + c0^Tx0) - f1
2704
+ //
2705
+ // (reduced_c)^T(reduced_x) = original_sense*[original_offset +
2706
+ // (original_c)^T(original_x) - reduced_offset]
2707
+ const auto& user_solution = callback->data_in.user_solution;
2708
+ double bound_violation_ = 0;
2709
+ double row_violation_ = 0;
2710
+ double integrality_violation_ = 0;
2711
+ HighsCDouble user_solution_quad_objective_value = 0;
2712
+ const bool feasible = mipsolver.solutionFeasible(
2713
+ mipsolver.orig_model_, user_solution, nullptr, bound_violation_,
2714
+ row_violation_, integrality_violation_,
2715
+ user_solution_quad_objective_value);
2716
+ double user_solution_objective_value =
2717
+ double(user_solution_quad_objective_value);
2718
+ if (!feasible) {
2719
+ highsLogUser(
2720
+ mipsolver.options_mip_->log_options, HighsLogType::kWarning,
2721
+ "User-supplied solution has with objective %g has violations: "
2722
+ "bound = %.4g; integrality = %.4g; row = %.4g\n",
2723
+ user_solution_objective_value, bound_violation_,
2724
+ integrality_violation_, row_violation_);
2725
+ return;
2726
+ }
2727
+ std::vector<double> reduced_user_solution;
2728
+ reduced_user_solution =
2729
+ postSolveStack.getReducedPrimalSolution(user_solution);
2730
+ const bool print_display_line = true;
2731
+ const bool is_user_solution = true;
2732
+ addIncumbent(reduced_user_solution, user_solution_objective_value,
2733
+ kSolutionSourceUserSolution, print_display_line,
2734
+ is_user_solution);
2735
+ }
2736
+ }
2737
+ }
2738
+
2739
+ HighsInt HighsMipSolverData::terminatorConcurrency() const {
2740
+ return mipsolver.terminator_.num_instance;
2741
+ }
2742
+
2743
+ HighsInt HighsMipSolverData::terminatorMyInstance() const {
2744
+ return mipsolver.terminator_.my_instance;
2745
+ }
2746
+
2747
+ void HighsMipSolverData::terminatorTerminate() {
2748
+ assert(terminatorActive());
2749
+ mipsolver.terminator_.terminate();
2750
+ }
2751
+
2752
+ bool HighsMipSolverData::terminatorTerminated() const {
2753
+ if (this->terminatorActive())
2754
+ mipsolver.termination_status_ = mipsolver.terminator_.terminationStatus();
2755
+ return mipsolver.termination_status_ != HighsModelStatus::kNotset;
2756
+ }
2757
+
2758
+ void HighsMipSolverData::terminatorReport() const {
2759
+ if (this->terminatorActive())
2760
+ mipsolver.terminator_.report(mipsolver.options_mip_->log_options);
2761
+ }
2762
+
2763
+ static double possInfRelDiff(const double v0, const double v1,
2764
+ const double den) {
2765
+ double rel_diff;
2766
+ if (std::fabs(v0) == kHighsInf) {
2767
+ if (std::fabs(v1) == kHighsInf) {
2768
+ rel_diff = 0;
2769
+ } else {
2770
+ rel_diff = kHighsInf;
2771
+ }
2772
+ } else {
2773
+ if (std::fabs(v1) == kHighsInf) {
2774
+ rel_diff = kHighsInf;
2775
+ } else {
2776
+ rel_diff = std::fabs(v1 - v0) / std::max(1.0, std::fabs(den));
2777
+ }
2778
+ }
2779
+ return rel_diff;
2780
+ }
2781
+
2782
+ void HighsMipSolverData::updatePrimalDualIntegral(const double from_lower_bound,
2783
+ const double to_lower_bound,
2784
+ const double from_upper_bound,
2785
+ const double to_upper_bound,
2786
+ const bool check_bound_change,
2787
+ const bool check_prev_data) {
2788
+ // Parameters to updatePrimalDualIntegral are lower and upper bounds
2789
+ // before/after a change
2790
+ //
2791
+ // updatePrimalDualIntegral should only be called when there is a
2792
+ // change in one of the bounds, except when the final update is
2793
+ // made, in which case the bounds must NOT have changed. By default,
2794
+ // a check for some bound change is made, unless check_bound_change
2795
+ // is false, in which case there is a check for unchanged bounds.
2796
+ //
2797
+ HighsPrimaDualIntegral& pdi = this->primal_dual_integral;
2798
+ // HighsPrimaDualIntegral struct contains the following data
2799
+ //
2800
+ // * value: Current value of the P-D integral
2801
+ //
2802
+ // * prev_lb: Value of lb that was computed from to_lower_bound in
2803
+ // the previous call. Used as a check that the value of lb
2804
+ // computed from from_lower_bound in this call is equal - to
2805
+ // within bound_change_tolerance. If not true, then a change in lb
2806
+ // has been missed. Only for checking/debugging
2807
+ //
2808
+ // * prev_ub: Ditto for upper_bound. Only for checking/debugging
2809
+ //
2810
+ // * prev_gap: Ditto for gap. Only for checking/debugging
2811
+ //
2812
+ // * prev_time: Used to determine the time spent at the previous gap
2813
+
2814
+ double from_lb;
2815
+ double from_ub;
2816
+ const double from_gap =
2817
+ this->limitsToGap(from_lower_bound, from_upper_bound, from_lb, from_ub);
2818
+ double to_lb;
2819
+ double to_ub;
2820
+ const double to_gap =
2821
+ this->limitsToGap(to_lower_bound, to_upper_bound, to_lb, to_ub);
2822
+
2823
+ const double lb_difference = possInfRelDiff(from_lb, to_lb, to_lb);
2824
+ const double ub_difference = possInfRelDiff(from_ub, to_ub, to_ub);
2825
+ const double bound_change_tolerance = 0;
2826
+ const bool bound_change = lb_difference > bound_change_tolerance ||
2827
+ ub_difference > bound_change_tolerance;
2828
+
2829
+ if (check_bound_change) {
2830
+ if (!bound_change) {
2831
+ if (from_lower_bound == to_lower_bound &&
2832
+ from_upper_bound == to_upper_bound) {
2833
+ const double lower_bound_difference =
2834
+ possInfRelDiff(from_lower_bound, to_lower_bound, to_lower_bound);
2835
+ const double upper_bound_difference =
2836
+ possInfRelDiff(from_upper_bound, to_upper_bound, to_upper_bound);
2837
+ assert(bound_change);
2838
+ }
2839
+ }
2840
+ } else {
2841
+ if (bound_change) {
2842
+ if (from_lower_bound != to_lower_bound ||
2843
+ from_upper_bound != to_upper_bound) {
2844
+ const double lower_bound_difference =
2845
+ possInfRelDiff(from_lower_bound, to_lower_bound, to_lower_bound);
2846
+ const double upper_bound_difference =
2847
+ possInfRelDiff(from_upper_bound, to_upper_bound, to_upper_bound);
2848
+ assert(!bound_change);
2849
+ }
2850
+ }
2851
+ }
2852
+ if (pdi.value > -kHighsInf) {
2853
+ // updatePrimalDualIntegral has been called previously, so can
2854
+ // usually test housekeeping, even if gap is still inf
2855
+ //
2856
+ // The one case where the checking can't be done comes after restart, where
2857
+ // the
2858
+ //
2859
+ if (check_prev_data) {
2860
+ // These housekeeping tests check that the previous saved
2861
+ // lower/upper bounds and gap are very close to the "from"
2862
+ // lower/upper bounds and corresponding gap. They are usually
2863
+ // identical, but rounding error can occur when passing through
2864
+ // reset, when the old/new offsets are added/subtracted from the
2865
+ // bounds due to changes in offset during presolve.
2866
+ const double lb_inconsistency =
2867
+ possInfRelDiff(from_lb, pdi.prev_lb, pdi.prev_lb);
2868
+ const bool lb_consistent = lb_inconsistency < 1e-12;
2869
+ const double ub_inconsistency =
2870
+ possInfRelDiff(from_ub, pdi.prev_ub, pdi.prev_ub);
2871
+ const bool ub_consistent = ub_inconsistency < 1e-12;
2872
+ const double gap_inconsistency =
2873
+ possInfRelDiff(from_gap, pdi.prev_gap, 1.0);
2874
+ const bool gap_consistent = gap_inconsistency < 1e-12;
2875
+ assert(lb_consistent);
2876
+ assert(ub_consistent);
2877
+ assert(gap_consistent);
2878
+ }
2879
+ if (to_gap < kHighsInf) {
2880
+ double time = mipsolver.timer_.read();
2881
+ if (from_gap < kHighsInf) {
2882
+ // Need to update the P-D integral
2883
+ double time_diff = time - pdi.prev_time;
2884
+ assert(time_diff >= 0);
2885
+ pdi.value += time_diff * pdi.prev_gap;
2886
+ }
2887
+ pdi.prev_time = time;
2888
+ }
2889
+ } else {
2890
+ pdi.value = 0;
2891
+ }
2892
+ pdi.prev_lb = to_lb;
2893
+ pdi.prev_ub = to_ub;
2894
+ pdi.prev_gap = to_gap;
2895
+ }
2896
+
2897
+ void HighsPrimaDualIntegral::initialise() { this->value = -kHighsInf; }
2898
+
2899
+ void HighsTerminator::clear() {
2900
+ this->num_instance = 0;
2901
+ this->my_instance = kNoThreadInstance;
2902
+ this->record = nullptr;
2903
+ }
2904
+
2905
+ void HighsTerminator::initialise(HighsInt num_instance_, HighsInt my_instance_,
2906
+ HighsModelStatus* record_) {
2907
+ this->clear();
2908
+ this->num_instance = num_instance_;
2909
+ this->my_instance = my_instance_;
2910
+ this->record = record_;
2911
+ }
2912
+
2913
+ HighsInt HighsTerminator::concurrency() const { return this->num_instance; }
2914
+
2915
+ void HighsTerminator::terminate() {
2916
+ assert(this->record);
2917
+ assert(this->my_instance < this->num_instance);
2918
+ this->record[this->my_instance] = HighsModelStatus::kHighsInterrupt;
2919
+ }
2920
+
2921
+ HighsModelStatus HighsTerminator::terminationStatus() const {
2922
+ assert(this->record);
2923
+ for (HighsInt instance = 0; instance < this->num_instance; instance++) {
2924
+ if (this->record[instance] != HighsModelStatus::kNotset)
2925
+ return this->record[instance];
2926
+ }
2927
+ return HighsModelStatus::kNotset;
2928
+ }
2929
+
2930
+ void HighsTerminator::report(const HighsLogOptions log_options) const {
2931
+ highsLogUser(log_options, HighsLogType::kInfo, "\nTerminator: ");
2932
+ for (HighsInt instance = 0; instance < this->num_instance; instance++)
2933
+ highsLogUser(log_options, HighsLogType::kInfo, " %20d",
2934
+ int(this->record[instance]));
2935
+ highsLogUser(log_options, HighsLogType::kInfo, "\n");
2936
+ }