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