lpsolver 0.1.0 → 0.2.0

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 +70 -26
  4. data/ext/lpsolver/Makefile +273 -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 +28 -4
  1160. data/lib/lpsolver/native.so +0 -0
  1161. data/lib/lpsolver/native_model.rb +261 -0
  1162. data/lib/lpsolver/solution.rb +72 -7
  1163. data/lib/lpsolver/version.rb +1 -1
  1164. data/lpsolver.gemspec +4 -1
  1165. metadata +1176 -4
@@ -0,0 +1,3794 @@
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 lp_data/HighsUtils.cpp
9
+ * @brief Class-independent utilities for HiGHS
10
+ */
11
+ #include "lp_data/HighsLpUtils.h"
12
+
13
+ #include <algorithm>
14
+ #include <cassert>
15
+
16
+ #include "HConfig.h"
17
+ #include "io/Filereader.h"
18
+ #include "io/HMPSIO.h"
19
+ #include "io/HighsIO.h"
20
+ #include "lp_data/HighsModelUtils.h"
21
+ #include "lp_data/HighsSolution.h"
22
+ #include "lp_data/HighsStatus.h"
23
+ #include "util/HighsCDouble.h"
24
+ #include "util/HighsMatrixUtils.h"
25
+ #include "util/HighsSort.h"
26
+
27
+ using std::fabs;
28
+ using std::max;
29
+ using std::min;
30
+
31
+ const HighsInt kMaxLineLength = 80;
32
+
33
+ HighsStatus assessLp(HighsLp& lp, const HighsOptions& options) {
34
+ HighsStatus return_status = HighsStatus::kOk;
35
+ HighsStatus call_status = lpDimensionsOk("assessLp", lp, options.log_options)
36
+ ? HighsStatus::kOk
37
+ : HighsStatus::kError;
38
+ return_status = interpretCallStatus(options.log_options, call_status,
39
+ return_status, "assessLpDimensions");
40
+ if (return_status == HighsStatus::kError) return return_status;
41
+
42
+ if (lp.num_col_) {
43
+ // Assess the LP column costs
44
+ HighsIndexCollection index_collection;
45
+ index_collection.dimension_ = lp.num_col_;
46
+ index_collection.is_interval_ = true;
47
+ index_collection.from_ = 0;
48
+ index_collection.to_ = lp.num_col_ - 1;
49
+ call_status = assessCosts(options, 0, index_collection, lp.col_cost_,
50
+ lp.has_infinite_cost_, options.infinite_cost);
51
+ return_status = interpretCallStatus(options.log_options, call_status,
52
+ return_status, "assessCosts");
53
+ if (return_status == HighsStatus::kError) return return_status;
54
+ // Assess the LP column bounds
55
+ call_status = assessBounds(
56
+ options, "Col", 0, index_collection, lp.col_lower_, lp.col_upper_,
57
+ options.infinite_bound, lp.isMip() ? lp.integrality_.data() : nullptr);
58
+ return_status = interpretCallStatus(options.log_options, call_status,
59
+ return_status, "assessBounds");
60
+ if (return_status == HighsStatus::kError) return return_status;
61
+ }
62
+ if (lp.num_row_) {
63
+ // Assess the LP row bounds
64
+ HighsIndexCollection index_collection;
65
+ index_collection.dimension_ = lp.num_row_;
66
+ index_collection.is_interval_ = true;
67
+ index_collection.from_ = 0;
68
+ index_collection.to_ = lp.num_row_ - 1;
69
+ call_status =
70
+ assessBounds(options, "Row", 0, index_collection, lp.row_lower_,
71
+ lp.row_upper_, options.infinite_bound);
72
+ return_status = interpretCallStatus(options.log_options, call_status,
73
+ return_status, "assessBounds");
74
+ if (return_status == HighsStatus::kError) return return_status;
75
+ }
76
+ // If the LP has no columns the matrix must be empty and there is
77
+ // nothing left to test
78
+ if (lp.num_col_ == 0) {
79
+ assert(!lp.a_matrix_.numNz());
80
+ return HighsStatus::kOk;
81
+ }
82
+ // From here, any LP has lp.num_col_ > 0 and lp.a_matrix_.start_[lp.num_col_]
83
+ // exists (as the number of nonzeros)
84
+ assert(lp.num_col_ > 0);
85
+
86
+ // Assess the LP matrix - even if there are no rows!
87
+ call_status =
88
+ lp.a_matrix_.assess(options.log_options, "LP", options.small_matrix_value,
89
+ options.large_matrix_value);
90
+ return_status = interpretCallStatus(options.log_options, call_status,
91
+ return_status, "assessMatrix");
92
+ if (return_status == HighsStatus::kError) return return_status;
93
+ // If entries have been removed from the matrix, resize the index
94
+ // and value vectors to prevent bug in presolve
95
+ HighsInt lp_num_nz = lp.a_matrix_.numNz();
96
+ if ((HighsInt)lp.a_matrix_.index_.size() > lp_num_nz)
97
+ lp.a_matrix_.index_.resize(lp_num_nz);
98
+ if ((HighsInt)lp.a_matrix_.value_.size() > lp_num_nz)
99
+ lp.a_matrix_.value_.resize(lp_num_nz);
100
+ if (return_status != HighsStatus::kOk)
101
+ highsLogDev(options.log_options, HighsLogType::kInfo,
102
+ "assessLp returns HighsStatus = %s\n",
103
+ highsStatusToString(return_status).c_str());
104
+ return return_status;
105
+ }
106
+
107
+ bool lpDimensionsOk(const std::string& message, const HighsLp& lp,
108
+ const HighsLogOptions& log_options) {
109
+ bool ok = true;
110
+ const HighsInt num_col = lp.num_col_;
111
+ const HighsInt num_row = lp.num_row_;
112
+ if (!(num_col >= 0))
113
+ highsLogUser(log_options, HighsLogType::kError,
114
+ "LP dimension validation (%s) fails on num_col = %d >= 0\n",
115
+ message.c_str(), (int)num_col);
116
+ ok = num_col >= 0 && ok;
117
+ if (!(num_row >= 0))
118
+ highsLogUser(log_options, HighsLogType::kError,
119
+ "LP dimension validation (%s) fails on num_row = %d >= 0\n",
120
+ message.c_str(), (int)num_row);
121
+ ok = num_row >= 0 && ok;
122
+ if (!ok) return ok;
123
+
124
+ HighsInt col_cost_size = lp.col_cost_.size();
125
+ HighsInt col_lower_size = lp.col_lower_.size();
126
+ HighsInt col_upper_size = lp.col_upper_.size();
127
+ bool legal_col_cost_size = col_cost_size >= num_col;
128
+ bool legal_col_lower_size = col_lower_size >= num_col;
129
+ bool legal_col_upper_size = col_upper_size >= num_col;
130
+ if (!legal_col_cost_size)
131
+ highsLogUser(log_options, HighsLogType::kError,
132
+ "LP dimension validation (%s) fails on col_cost.size() = %d < "
133
+ "%d = num_col\n",
134
+ message.c_str(), (int)col_cost_size, (int)num_col);
135
+ ok = legal_col_cost_size && ok;
136
+ if (!legal_col_lower_size)
137
+ highsLogUser(log_options, HighsLogType::kError,
138
+ "LP dimension validation (%s) fails on col_lower.size() = %d "
139
+ "< %d = num_col\n",
140
+ message.c_str(), (int)col_lower_size, (int)num_col);
141
+ ok = legal_col_lower_size && ok;
142
+ if (!legal_col_upper_size)
143
+ highsLogUser(log_options, HighsLogType::kError,
144
+ "LP dimension validation (%s) fails on col_upper.size() = %d "
145
+ "< %d = num_col\n",
146
+ message.c_str(), (int)col_upper_size, (int)num_col);
147
+ ok = legal_col_upper_size && ok;
148
+
149
+ bool legal_format = lp.a_matrix_.format_ == MatrixFormat::kColwise ||
150
+ lp.a_matrix_.format_ == MatrixFormat::kRowwise;
151
+ if (!legal_format)
152
+ highsLogUser(log_options, HighsLogType::kError,
153
+ "LP dimension validation (%s) fails on a_matrix_.format\n",
154
+ message.c_str());
155
+ ok = legal_format && ok;
156
+ HighsInt num_vec;
157
+ if (lp.a_matrix_.isColwise()) {
158
+ num_vec = num_col;
159
+ } else {
160
+ num_vec = num_row;
161
+ }
162
+ const bool partitioned = false;
163
+ vector<HighsInt> a_matrix_p_end;
164
+ bool legal_matrix_dimensions =
165
+ assessMatrixDimensions(log_options, num_vec, partitioned,
166
+ lp.a_matrix_.start_, a_matrix_p_end,
167
+ lp.a_matrix_.index_,
168
+ lp.a_matrix_.value_) == HighsStatus::kOk;
169
+ if (!legal_matrix_dimensions)
170
+ highsLogUser(log_options, HighsLogType::kError,
171
+ "LP dimension validation (%s) fails on a_matrix dimensions\n",
172
+ message.c_str());
173
+ ok = legal_matrix_dimensions && ok;
174
+
175
+ HighsInt row_lower_size = lp.row_lower_.size();
176
+ HighsInt row_upper_size = lp.row_upper_.size();
177
+ bool legal_row_lower_size = row_lower_size >= num_row;
178
+ bool legal_row_upper_size = row_upper_size >= num_row;
179
+ if (!legal_row_lower_size)
180
+ highsLogUser(log_options, HighsLogType::kError,
181
+ "LP dimension validation (%s) fails on row_lower.size() = %d "
182
+ "< %d = num_row\n",
183
+ message.c_str(), (int)row_lower_size, (int)num_row);
184
+ ok = legal_row_lower_size && ok;
185
+ if (!legal_row_upper_size)
186
+ highsLogUser(log_options, HighsLogType::kError,
187
+ "LP dimension validation (%s) fails on row_upper.size() = %d "
188
+ "< %d = num_row\n",
189
+ message.c_str(), (int)row_upper_size, (int)num_row);
190
+ ok = legal_row_upper_size && ok;
191
+
192
+ bool legal_a_matrix_num_col = lp.a_matrix_.num_col_ == num_col;
193
+ bool legal_a_matrix_num_row = lp.a_matrix_.num_row_ == num_row;
194
+ if (!legal_a_matrix_num_col)
195
+ highsLogUser(log_options, HighsLogType::kError,
196
+ "LP dimension validation (%s) fails on a_matrix.num_col_ = %d "
197
+ "!= %d = num_col\n",
198
+ message.c_str(), (int)lp.a_matrix_.num_col_, (int)num_col);
199
+ ok = legal_a_matrix_num_col && ok;
200
+ if (!legal_a_matrix_num_row)
201
+ highsLogUser(log_options, HighsLogType::kError,
202
+ "LP dimension validation (%s) fails on a_matrix.num_row_ = %d "
203
+ "!= %d = num_row\n",
204
+ message.c_str(), (int)lp.a_matrix_.num_row_, (int)num_row);
205
+ ok = legal_a_matrix_num_row && ok;
206
+
207
+ HighsInt scale_strategy = (HighsInt)lp.scale_.strategy;
208
+ bool legal_scale_strategy = scale_strategy >= 0;
209
+ if (!legal_scale_strategy)
210
+ highsLogUser(
211
+ log_options, HighsLogType::kError,
212
+ "LP dimension validation (%s) fails on scale_.scale_strategy\n",
213
+ message.c_str());
214
+ ok = legal_scale_strategy && ok;
215
+ HighsInt scale_row_size = (HighsInt)lp.scale_.row.size();
216
+ HighsInt scale_col_size = (HighsInt)lp.scale_.col.size();
217
+ bool legal_scale_num_col = false;
218
+ bool legal_scale_num_row = false;
219
+ bool legal_scale_row_size = false;
220
+ bool legal_scale_col_size = false;
221
+ if (lp.scale_.has_scaling) {
222
+ legal_scale_num_col = lp.scale_.num_col == num_col;
223
+ legal_scale_num_row = lp.scale_.num_row == num_row;
224
+ legal_scale_row_size = scale_row_size >= num_row;
225
+ legal_scale_col_size = scale_col_size >= num_col;
226
+ } else {
227
+ legal_scale_num_col = lp.scale_.num_col == 0;
228
+ legal_scale_num_row = lp.scale_.num_row == 0;
229
+ legal_scale_row_size = scale_row_size == 0;
230
+ legal_scale_col_size = scale_col_size == 0;
231
+ }
232
+ if (!legal_scale_num_col)
233
+ highsLogUser(
234
+ log_options, HighsLogType::kError,
235
+ "LP dimension validation (%s) fails on scale_.num_col = %d != %d\n",
236
+ message.c_str(), (int)lp.scale_.num_col,
237
+ (int)(lp.scale_.has_scaling ? num_col : 0));
238
+ ok = legal_scale_num_col && ok;
239
+ if (!legal_scale_num_row)
240
+ highsLogUser(
241
+ log_options, HighsLogType::kError,
242
+ "LP dimension validation (%s) fails on scale_.num_row = %d != %d\n",
243
+ message.c_str(), (int)lp.scale_.num_row,
244
+ (int)(lp.scale_.has_scaling ? num_row : 0));
245
+ ok = legal_scale_num_row && ok;
246
+ if (!legal_scale_col_size)
247
+ highsLogUser(
248
+ log_options, HighsLogType::kError,
249
+ "LP dimension validation (%s) fails on scale_.col.size() = %d %s %d\n",
250
+ message.c_str(), (int)scale_col_size,
251
+ lp.scale_.has_scaling ? ">=" : "==",
252
+ (int)(lp.scale_.has_scaling ? num_col : 0));
253
+ ok = legal_scale_col_size && ok;
254
+ if (!legal_scale_row_size)
255
+ highsLogUser(
256
+ log_options, HighsLogType::kError,
257
+ "LP dimension validation (%s) fails on scale_.row.size() = %d %s %d\n",
258
+ message.c_str(), (int)scale_row_size,
259
+ lp.scale_.has_scaling ? ">=" : "==",
260
+ (int)(lp.scale_.has_scaling ? num_row : 0));
261
+ ok = legal_scale_row_size && ok;
262
+ if (!ok) {
263
+ highsLogUser(log_options, HighsLogType::kError,
264
+ "LP dimension validation (%s) fails\n", message.c_str());
265
+ }
266
+
267
+ return ok;
268
+ }
269
+
270
+ HighsStatus assessCosts(const HighsOptions& options, const HighsInt ml_col_os,
271
+ const HighsIndexCollection& index_collection,
272
+ vector<double>& cost, bool& has_infinite_cost,
273
+ const double infinite_cost) {
274
+ HighsStatus return_status = HighsStatus::kOk;
275
+ assert(ok(index_collection));
276
+ HighsInt from_k;
277
+ HighsInt to_k;
278
+ limits(index_collection, from_k, to_k);
279
+ if (from_k > to_k) return return_status;
280
+
281
+ return_status = HighsStatus::kOk;
282
+ // Work through the data to be assessed.
283
+ //
284
+ // Loop is k \in [from_k...to_k) covering the entries in the
285
+ // interval, set or mask to be considered.
286
+ //
287
+ // For an interval or mask, these values of k are the columns to be
288
+ // considered in a local sense, as well as the entries in the
289
+ // cost data to be assessed
290
+ //
291
+ // For a set, these values of k are the indices in the set, from
292
+ // which the columns to be considered in a local sense are
293
+ // drawn. The entries in the cost data to be assessed correspond
294
+ // to the values of k
295
+ //
296
+ // Adding the value of ml_col_os to local_col yields the value of
297
+ // ml_col, being the column in a global (whole-model) sense. This is
298
+ // necessary when assessing the costs of columns being added to a
299
+ // model, since they are specified using an interval
300
+ // [0...num_new_col) which must be offset by the current number of
301
+ // columns in the model.
302
+ //
303
+ HighsInt local_col;
304
+ HighsInt usr_col = -1;
305
+ HighsInt num_infinite_cost = 0;
306
+ for (HighsInt k = from_k; k < to_k + 1; k++) {
307
+ if (index_collection.is_interval_ || index_collection.is_mask_) {
308
+ local_col = k;
309
+ } else {
310
+ local_col = index_collection.set_[k];
311
+ }
312
+ if (index_collection.is_interval_) {
313
+ usr_col++;
314
+ } else {
315
+ usr_col = k;
316
+ }
317
+ if (index_collection.is_mask_ && !index_collection.mask_[local_col])
318
+ continue;
319
+ if (cost[usr_col] >= infinite_cost) {
320
+ num_infinite_cost++;
321
+ cost[usr_col] = kHighsInf;
322
+ } else if (cost[usr_col] <= -infinite_cost) {
323
+ num_infinite_cost++;
324
+ cost[usr_col] = -kHighsInf;
325
+ }
326
+ }
327
+ if (num_infinite_cost > 0) {
328
+ has_infinite_cost = true;
329
+ highsLogUser(options.log_options, HighsLogType::kInfo,
330
+ "%" HIGHSINT_FORMAT
331
+ " |cost| values greater than or equal to %12g are treated as "
332
+ "Infinity\n",
333
+ num_infinite_cost, infinite_cost);
334
+ }
335
+ return return_status;
336
+ }
337
+
338
+ HighsStatus assessBounds(const HighsOptions& options, const char* type,
339
+ const HighsInt ml_ix_os,
340
+ const HighsIndexCollection& index_collection,
341
+ vector<double>& lower, vector<double>& upper,
342
+ const double infinite_bound,
343
+ const HighsVarType* integrality) {
344
+ HighsStatus return_status = HighsStatus::kOk;
345
+ assert(ok(index_collection));
346
+ HighsInt from_k;
347
+ HighsInt to_k;
348
+ limits(index_collection, from_k, to_k);
349
+ if (from_k > to_k) return HighsStatus::kOk;
350
+
351
+ return_status = HighsStatus::kOk;
352
+ bool error_found = false;
353
+ bool warning_found = false;
354
+ // Work through the data to be assessed.
355
+ //
356
+ // Loop is k \in [from_k...to_k) covering the entries in the
357
+ // interval, set or mask to be considered.
358
+ //
359
+ // For an interval or mask, these values of k are the row/column
360
+ // indices to be considered in a local sense, as well as the entries
361
+ // in the lower and upper bound data to be assessed
362
+ //
363
+ // For a set, these values of k are the indices in the set, from
364
+ // which the indices to be considered in a local sense are
365
+ // drawn. The entries in the lower and
366
+ // upper bound data to be assessed correspond to the values of
367
+ // k.
368
+ //
369
+ // Adding the value of ml_ix_os to local_ix yields the value of
370
+ // ml_ix, being the index in a global (whole-model) sense. This is
371
+ // necessary when assessing the bounds of rows/columns being added
372
+ // to a model, since they are specified using an interval
373
+ // [0...num_new_row/col) which must be offset by the current number
374
+ // of rows/columns (generically indices) in the model.
375
+ //
376
+ HighsInt num_infinite_lower_bound = 0;
377
+ HighsInt num_infinite_upper_bound = 0;
378
+ HighsInt local_ix;
379
+ HighsInt ml_ix;
380
+ HighsInt usr_ix = -1;
381
+ for (HighsInt k = from_k; k < to_k + 1; k++) {
382
+ if (index_collection.is_interval_ || index_collection.is_mask_) {
383
+ local_ix = k;
384
+ } else {
385
+ local_ix = index_collection.set_[k];
386
+ }
387
+ if (index_collection.is_interval_) {
388
+ usr_ix++;
389
+ } else {
390
+ usr_ix = k;
391
+ }
392
+ ml_ix = ml_ix_os + local_ix;
393
+ if (index_collection.is_mask_ && !index_collection.mask_[local_ix])
394
+ continue;
395
+
396
+ if (!highs_isInfinity(-lower[usr_ix])) {
397
+ // Check whether a finite lower bound will be treated as -Infinity
398
+ bool infinite_lower_bound = lower[usr_ix] <= -infinite_bound;
399
+ if (infinite_lower_bound) {
400
+ lower[usr_ix] = -kHighsInf;
401
+ num_infinite_lower_bound++;
402
+ }
403
+ }
404
+ if (!highs_isInfinity(upper[usr_ix])) {
405
+ // Check whether a finite upper bound will be treated as Infinity
406
+ bool infinite_upper_bound = upper[usr_ix] >= infinite_bound;
407
+ if (infinite_upper_bound) {
408
+ upper[usr_ix] = kHighsInf;
409
+ num_infinite_upper_bound++;
410
+ }
411
+ }
412
+ // Check that the lower bound does not exceed the upper bound
413
+ bool legalLowerUpperBound = lower[usr_ix] <= upper[usr_ix];
414
+ if (integrality) {
415
+ // Legal for semi-variables to have inconsistent bounds
416
+ if (integrality[usr_ix] == HighsVarType::kSemiContinuous ||
417
+ integrality[usr_ix] == HighsVarType::kSemiInteger)
418
+ legalLowerUpperBound = true;
419
+ }
420
+ if (!legalLowerUpperBound) {
421
+ // Leave inconsistent bounds to be used to deduce infeasibility
422
+ highsLogUser(options.log_options, HighsLogType::kWarning,
423
+ "%3s %12" HIGHSINT_FORMAT
424
+ " has inconsistent bounds [%12g, %12g]\n",
425
+ type, ml_ix, lower[usr_ix], upper[usr_ix]);
426
+ warning_found = true;
427
+ }
428
+ // Check that the lower bound is not as much as +Infinity
429
+ bool legalLowerBound = lower[usr_ix] < infinite_bound;
430
+ if (!legalLowerBound) {
431
+ highsLogUser(options.log_options, HighsLogType::kError,
432
+ "%3s %12" HIGHSINT_FORMAT
433
+ " has lower bound of %12g >= %12g\n",
434
+ type, ml_ix, lower[usr_ix], infinite_bound);
435
+ error_found = true;
436
+ }
437
+ // Check that the upper bound is not as little as -Infinity
438
+ bool legalUpperBound = upper[usr_ix] > -infinite_bound;
439
+ if (!legalUpperBound) {
440
+ highsLogUser(options.log_options, HighsLogType::kError,
441
+ "%3s %12" HIGHSINT_FORMAT
442
+ " has upper bound of %12g <= %12g\n",
443
+ type, ml_ix, upper[usr_ix], -infinite_bound);
444
+ error_found = true;
445
+ }
446
+ }
447
+ if (num_infinite_lower_bound) {
448
+ highsLogUser(options.log_options, HighsLogType::kInfo,
449
+ "%3ss:%12" HIGHSINT_FORMAT
450
+ " lower bounds less than or equal to %12g are treated as "
451
+ "-Infinity\n",
452
+ type, num_infinite_lower_bound, -infinite_bound);
453
+ }
454
+ if (num_infinite_upper_bound) {
455
+ highsLogUser(options.log_options, HighsLogType::kInfo,
456
+ "%3ss:%12" HIGHSINT_FORMAT
457
+ " upper bounds greater than or equal to %12g are treated as "
458
+ "+Infinity\n",
459
+ type, num_infinite_upper_bound, infinite_bound);
460
+ }
461
+
462
+ if (error_found)
463
+ return_status = HighsStatus::kError;
464
+ else if (warning_found)
465
+ return_status = HighsStatus::kWarning;
466
+ else
467
+ return_status = HighsStatus::kOk;
468
+
469
+ return return_status;
470
+ }
471
+
472
+ HighsStatus assessSemiVariables(HighsLp& lp, const HighsOptions& options,
473
+ bool& made_semi_variable_mods) {
474
+ made_semi_variable_mods = false;
475
+ HighsStatus return_status = HighsStatus::kOk;
476
+ if (!lp.integrality_.size()) return return_status;
477
+ assert((HighsInt)lp.integrality_.size() == lp.num_col_);
478
+ HighsInt num_illegal_lower = 0;
479
+ HighsInt num_illegal_upper = 0;
480
+ HighsInt num_tightened_upper = 0;
481
+ HighsInt num_inconsistent_semi = 0;
482
+ HighsInt num_non_semi = 0;
483
+ HighsInt num_non_continuous_variables = 0;
484
+ const double kLowerBoundMu = 10.0;
485
+
486
+ std::vector<HighsInt>& save_non_semi_variable_index =
487
+ lp.mods_.save_non_semi_variable_index;
488
+ std::vector<HighsInt>& inconsistent_semi_variable_index =
489
+ lp.mods_.save_inconsistent_semi_variable_index;
490
+ std::vector<double>& inconsistent_semi_variable_lower_bound_value =
491
+ lp.mods_.save_inconsistent_semi_variable_lower_bound_value;
492
+ std::vector<double>& inconsistent_semi_variable_upper_bound_value =
493
+ lp.mods_.save_inconsistent_semi_variable_upper_bound_value;
494
+ std::vector<HighsVarType>& inconsistent_semi_variable_type =
495
+ lp.mods_.save_inconsistent_semi_variable_type;
496
+
497
+ std::vector<HighsInt>& tightened_semi_variable_upper_bound_index =
498
+ lp.mods_.save_tightened_semi_variable_upper_bound_index;
499
+ std::vector<double>& tightened_semi_variable_upper_bound_value =
500
+ lp.mods_.save_tightened_semi_variable_upper_bound_value;
501
+
502
+ assert(int(lp.mods_.save_inconsistent_semi_variable_index.size()) == 0);
503
+ for (HighsInt iCol = 0; iCol < lp.num_col_; iCol++) {
504
+ if (lp.integrality_[iCol] == HighsVarType::kSemiContinuous ||
505
+ lp.integrality_[iCol] == HighsVarType::kSemiInteger) {
506
+ if (lp.col_lower_[iCol] > lp.col_upper_[iCol]) {
507
+ // Semi-variables with inconsistent bounds become continuous
508
+ // and fixed at zero
509
+ num_inconsistent_semi++;
510
+ inconsistent_semi_variable_index.push_back(iCol);
511
+ inconsistent_semi_variable_lower_bound_value.push_back(
512
+ lp.col_lower_[iCol]);
513
+ inconsistent_semi_variable_upper_bound_value.push_back(
514
+ lp.col_upper_[iCol]);
515
+ inconsistent_semi_variable_type.push_back(lp.integrality_[iCol]);
516
+ continue;
517
+ }
518
+ // Semi-variables with zero lower bound are not semi
519
+ if (lp.col_lower_[iCol] == 0) {
520
+ num_non_semi++;
521
+ save_non_semi_variable_index.push_back(iCol);
522
+ // Semi-integer become integer so still have a non-continuous variable
523
+ if (lp.integrality_[iCol] == HighsVarType::kSemiInteger)
524
+ num_non_continuous_variables++;
525
+ continue;
526
+ }
527
+ if (lp.col_lower_[iCol] < 0) {
528
+ // Semi-variables must have a positive lower bound
529
+ num_illegal_lower++;
530
+ } else if (lp.col_upper_[iCol] > kMaxSemiVariableUpper) {
531
+ // Semi-variables must have upper bound that's not too large,
532
+ // so see whether the limiting value is sufficiently larger than the
533
+ // lower bound
534
+ if (kLowerBoundMu * lp.col_lower_[iCol] > kMaxSemiVariableUpper) {
535
+ num_illegal_upper++;
536
+ } else {
537
+ // Record the upper bound change to be made later
538
+ tightened_semi_variable_upper_bound_index.push_back(iCol);
539
+ tightened_semi_variable_upper_bound_value.push_back(
540
+ kMaxSemiVariableUpper);
541
+ num_tightened_upper++;
542
+ }
543
+ }
544
+ num_non_continuous_variables++;
545
+ } else if (lp.integrality_[iCol] == HighsVarType::kInteger) {
546
+ num_non_continuous_variables++;
547
+ }
548
+ }
549
+ if (num_inconsistent_semi) {
550
+ highsLogUser(
551
+ options.log_options, HighsLogType::kWarning,
552
+ "%" HIGHSINT_FORMAT
553
+ " semi-continuous/integer variable(s) have inconsistent bounds "
554
+ "so are fixed at zero\n",
555
+ num_inconsistent_semi);
556
+ return_status = HighsStatus::kWarning;
557
+ }
558
+ if (num_non_semi) {
559
+ highsLogUser(options.log_options, HighsLogType::kWarning,
560
+ "%" HIGHSINT_FORMAT
561
+ " semi-continuous/integer variable(s) have zero lower bound "
562
+ "so are continuous/integer\n",
563
+ num_non_semi);
564
+ return_status = HighsStatus::kWarning;
565
+ }
566
+ if (!num_non_continuous_variables) {
567
+ highsLogUser(options.log_options, HighsLogType::kWarning,
568
+ "No semi-integer/integer variables in model with non-empty "
569
+ "integrality\n");
570
+ return_status = HighsStatus::kWarning;
571
+ }
572
+ const bool has_illegal_bounds = num_illegal_lower || num_illegal_upper;
573
+ if (num_tightened_upper) {
574
+ highsLogUser(options.log_options, HighsLogType::kWarning,
575
+ "%" HIGHSINT_FORMAT
576
+ " semi-continuous/integer variable(s) have upper bounds "
577
+ "exceeding %g that can be tightened to %g > %g*lower)\n",
578
+ num_tightened_upper, kMaxSemiVariableUpper,
579
+ kMaxSemiVariableUpper, kLowerBoundMu);
580
+ return_status = HighsStatus::kWarning;
581
+ if (has_illegal_bounds) {
582
+ // Don't apply upper bound tightenings if there are illegal bounds
583
+ assert(num_illegal_lower || num_illegal_upper);
584
+ tightened_semi_variable_upper_bound_index.clear();
585
+ tightened_semi_variable_upper_bound_value.clear();
586
+ num_tightened_upper = 0;
587
+ } else {
588
+ // Apply the upper bound tightenings, saving the over-written
589
+ // values
590
+ for (HighsInt k = 0; k < num_tightened_upper; k++) {
591
+ const double use_upper_bound =
592
+ tightened_semi_variable_upper_bound_value[k];
593
+ const HighsInt iCol = tightened_semi_variable_upper_bound_index[k];
594
+ tightened_semi_variable_upper_bound_value[k] = lp.col_upper_[iCol];
595
+ lp.col_upper_[iCol] = use_upper_bound;
596
+ }
597
+ }
598
+ }
599
+ if (num_inconsistent_semi) {
600
+ if (has_illegal_bounds) {
601
+ // Don't apply bound changes if there are illegal bounds
602
+ inconsistent_semi_variable_index.clear();
603
+ inconsistent_semi_variable_lower_bound_value.clear();
604
+ inconsistent_semi_variable_upper_bound_value.clear();
605
+ inconsistent_semi_variable_type.clear();
606
+ num_inconsistent_semi = 0;
607
+ } else {
608
+ for (HighsInt k = 0; k < num_inconsistent_semi; k++) {
609
+ const HighsInt iCol = inconsistent_semi_variable_index[k];
610
+ lp.col_lower_[iCol] = 0;
611
+ lp.col_upper_[iCol] = 0;
612
+ lp.integrality_[iCol] = HighsVarType::kContinuous;
613
+ }
614
+ }
615
+ }
616
+ if (num_non_semi) {
617
+ if (has_illegal_bounds) {
618
+ // Don't apply type changes if there are illegal bounds
619
+ save_non_semi_variable_index.clear();
620
+ } else {
621
+ for (HighsInt k = 0; k < num_non_semi; k++) {
622
+ const HighsInt iCol = save_non_semi_variable_index[k];
623
+ if (lp.integrality_[iCol] == HighsVarType::kSemiContinuous) {
624
+ // Semi-continuous become continuous
625
+ lp.integrality_[iCol] = HighsVarType::kContinuous;
626
+ } else {
627
+ // Semi-integer become integer
628
+ lp.integrality_[iCol] = HighsVarType::kInteger;
629
+ }
630
+ }
631
+ }
632
+ }
633
+ if (num_illegal_lower) {
634
+ highsLogUser(
635
+ options.log_options, HighsLogType::kError,
636
+ "%" HIGHSINT_FORMAT
637
+ " semi-continuous/integer variable(s) have negative lower bounds\n",
638
+ num_illegal_lower);
639
+ return_status = HighsStatus::kError;
640
+ }
641
+ if (num_illegal_upper) {
642
+ highsLogUser(
643
+ options.log_options, HighsLogType::kError,
644
+ "%" HIGHSINT_FORMAT
645
+ " semi-continuous/integer variables have upper bounds "
646
+ "exceeding %g that cannot be modified due to large lower bounds\n",
647
+ num_illegal_upper, kMaxSemiVariableUpper);
648
+ return_status = HighsStatus::kError;
649
+ }
650
+ made_semi_variable_mods =
651
+ num_non_semi > 0 || num_inconsistent_semi > 0 || num_tightened_upper > 0;
652
+ assert(static_cast<size_t>(num_non_semi) <=
653
+ save_non_semi_variable_index.size());
654
+ assert(static_cast<size_t>(num_inconsistent_semi) <=
655
+ inconsistent_semi_variable_index.size());
656
+ assert(static_cast<size_t>(num_tightened_upper) <=
657
+ tightened_semi_variable_upper_bound_index.size());
658
+ // save_non_semi_variable_index.size() > 0 ||
659
+ // inconsistent_semi_variable_index.size() > 0 ||
660
+ // tightened_semi_variable_upper_bound_index.size() > 0;
661
+ return return_status;
662
+ }
663
+
664
+ void relaxSemiVariables(HighsLp& lp, bool& made_semi_variable_mods) {
665
+ // When solving relaxation, semi-variables are continuous between 0
666
+ // and their upper bound, so have to modify the lower bound to be
667
+ // zero
668
+ made_semi_variable_mods = false;
669
+ if (!lp.integrality_.size()) return;
670
+ assert((HighsInt)lp.integrality_.size() == lp.num_col_);
671
+ std::vector<HighsInt>& relaxed_semi_variable_lower_index =
672
+ lp.mods_.save_relaxed_semi_variable_lower_bound_index;
673
+ std::vector<double>& relaxed_semi_variable_lower_value =
674
+ lp.mods_.save_relaxed_semi_variable_lower_bound_value;
675
+ assert(relaxed_semi_variable_lower_index.size() == 0);
676
+ for (HighsInt iCol = 0; iCol < lp.num_col_; iCol++) {
677
+ if (lp.integrality_[iCol] == HighsVarType::kSemiContinuous ||
678
+ lp.integrality_[iCol] == HighsVarType::kSemiInteger) {
679
+ relaxed_semi_variable_lower_index.push_back(iCol);
680
+ relaxed_semi_variable_lower_value.push_back(lp.col_lower_[iCol]);
681
+ lp.col_lower_[iCol] = 0;
682
+ }
683
+ }
684
+ made_semi_variable_mods = relaxed_semi_variable_lower_index.size() > 0;
685
+ }
686
+
687
+ bool activeModifiedUpperBounds(const HighsOptions& options, const HighsLp& lp,
688
+ const std::vector<double>& col_value) {
689
+ const std::vector<HighsInt>& tightened_semi_variable_upper_bound_index =
690
+ lp.mods_.save_tightened_semi_variable_upper_bound_index;
691
+ const HighsInt num_tightened_upper =
692
+ tightened_semi_variable_upper_bound_index.size();
693
+ HighsInt num_active_modified_upper = 0;
694
+ double min_semi_variable_margin = kHighsInf;
695
+ for (HighsInt k = 0; k < num_tightened_upper; k++) {
696
+ const double value =
697
+ col_value[tightened_semi_variable_upper_bound_index[k]];
698
+ const double upper =
699
+ lp.col_upper_[tightened_semi_variable_upper_bound_index[k]];
700
+ double semi_variable_margin = upper - value;
701
+ if (value > upper - options.primal_feasibility_tolerance) {
702
+ min_semi_variable_margin = 0;
703
+ num_active_modified_upper++;
704
+ } else {
705
+ min_semi_variable_margin =
706
+ std::min(semi_variable_margin, min_semi_variable_margin);
707
+ }
708
+ }
709
+ if (num_active_modified_upper) {
710
+ highsLogUser(options.log_options, HighsLogType::kError,
711
+ "%" HIGHSINT_FORMAT
712
+ " semi-variables are active at modified upper bounds\n",
713
+ num_active_modified_upper);
714
+ } else if (num_tightened_upper) {
715
+ highsLogUser(options.log_options, HighsLogType::kWarning,
716
+ "No semi-variables are active at modified upper bounds:"
717
+ " a large minimum margin (%g) suggests optimality,"
718
+ " but there is no guarantee\n",
719
+ min_semi_variable_margin);
720
+ }
721
+ return (num_active_modified_upper != 0);
722
+ }
723
+
724
+ HighsStatus cleanBounds(const HighsOptions& options, HighsLp& lp) {
725
+ double max_residual = 0;
726
+ HighsInt num_change = 0;
727
+ for (HighsInt iCol = 0; iCol < lp.num_col_; iCol++) {
728
+ double residual = lp.col_lower_[iCol] - lp.col_upper_[iCol];
729
+ if (residual > options.primal_feasibility_tolerance) {
730
+ highsLogUser(options.log_options, HighsLogType::kError,
731
+ "Column %" HIGHSINT_FORMAT
732
+ " has inconsistent bounds [%g, %g] (residual = "
733
+ "%g) after presolve\n",
734
+ iCol, lp.col_lower_[iCol], lp.col_upper_[iCol], residual);
735
+ return HighsStatus::kError;
736
+ } else if (residual > 0) {
737
+ num_change++;
738
+ max_residual = std::max(residual, max_residual);
739
+ double mid = 0.5 * (lp.col_lower_[iCol] + lp.col_upper_[iCol]);
740
+ lp.col_lower_[iCol] = mid;
741
+ lp.col_upper_[iCol] = mid;
742
+ }
743
+ }
744
+ for (HighsInt iRow = 0; iRow < lp.num_row_; iRow++) {
745
+ double residual = lp.row_lower_[iRow] - lp.row_upper_[iRow];
746
+ if (residual > options.primal_feasibility_tolerance) {
747
+ highsLogUser(options.log_options, HighsLogType::kError,
748
+ "Row %" HIGHSINT_FORMAT
749
+ " has inconsistent bounds [%g, %g] (residual = %g) "
750
+ "after presolve\n",
751
+ iRow, lp.row_lower_[iRow], lp.row_upper_[iRow], residual);
752
+ return HighsStatus::kError;
753
+ } else if (residual > 0) {
754
+ num_change++;
755
+ max_residual = std::max(residual, max_residual);
756
+ double mid = 0.5 * (lp.row_lower_[iRow] + lp.row_upper_[iRow]);
757
+ lp.row_lower_[iRow] = mid;
758
+ lp.row_upper_[iRow] = mid;
759
+ }
760
+ }
761
+ if (num_change) {
762
+ highsLogUser(options.log_options, HighsLogType::kWarning,
763
+ "Resolved %" HIGHSINT_FORMAT
764
+ " inconsistent bounds (maximum residual = "
765
+ "%9.4g) after presolve\n",
766
+ num_change, max_residual);
767
+ return HighsStatus::kWarning;
768
+ }
769
+ return HighsStatus::kOk;
770
+ }
771
+
772
+ HighsStatus userScaleLp(HighsLp& lp, HighsUserScaleData& data,
773
+ const HighsLogOptions& log_options) {
774
+ userScaleLp(lp, data, false);
775
+ HighsStatus return_status = userScaleStatus(log_options, data);
776
+ if (return_status == HighsStatus::kError) return HighsStatus::kError;
777
+ userScaleLp(lp, data);
778
+ return return_status;
779
+ }
780
+
781
+ void userScaleLp(HighsLp& lp, HighsUserScaleData& data, const bool apply) {
782
+ userScaleCosts(lp.integrality_, lp.col_cost_, data, apply);
783
+ userScaleColBounds(lp.integrality_, lp.col_lower_, lp.col_upper_, data,
784
+ apply);
785
+ userScaleMatrix(lp.integrality_, lp.a_matrix_, data, apply);
786
+ userScaleRowBounds(lp.row_lower_, lp.row_upper_, data, apply);
787
+ }
788
+
789
+ void userScaleCosts(const vector<HighsVarType>& integrality,
790
+ vector<double>& cost, HighsUserScaleData& data,
791
+ const bool apply) {
792
+ data.num_infinite_costs = 0;
793
+ const HighsInt user_bound_scale = data.user_bound_scale;
794
+ const HighsInt user_objective_scale = data.user_objective_scale;
795
+ if (!user_bound_scale && !user_objective_scale) return;
796
+ const HighsInt num_col = cost.size();
797
+ if (num_col <= 0) return;
798
+ const HighsInt integrality_size = HighsInt(integrality.size());
799
+ const bool has_integrality = integrality_size > 0;
800
+ double bound_scale_value = std::pow(2, user_bound_scale);
801
+ double objective_scale_value = std::pow(2, user_objective_scale);
802
+ assert(!has_integrality || integrality_size >= num_col);
803
+ for (HighsInt iCol = 0; iCol < num_col; iCol++) {
804
+ double value = cost[iCol];
805
+ if (has_integrality && integrality[iCol] != HighsVarType::kContinuous)
806
+ value *= bound_scale_value;
807
+ value *= objective_scale_value;
808
+ if (std::abs(value) > data.infinite_cost) data.num_infinite_costs++;
809
+ if (apply) cost[iCol] = value;
810
+ }
811
+ }
812
+
813
+ void userScaleColBounds(const vector<HighsVarType>& integrality,
814
+ vector<double>& lower, vector<double>& upper,
815
+ HighsUserScaleData& data, const bool apply) {
816
+ data.num_infinite_col_bounds = 0;
817
+ const HighsInt user_bound_scale = data.user_bound_scale;
818
+ if (!user_bound_scale) return;
819
+ const HighsInt num_col = lower.size();
820
+ if (num_col <= 0) return;
821
+ const HighsInt integrality_size = HighsInt(integrality.size());
822
+ const bool has_integrality = integrality_size > 0;
823
+ assert(!has_integrality || integrality_size >= num_col);
824
+ double bound_scale_value = std::pow(2, user_bound_scale);
825
+ for (HighsInt iCol = 0; iCol < num_col; iCol++) {
826
+ if (!has_integrality || integrality[iCol] == HighsVarType::kContinuous) {
827
+ if (lower[iCol] > -kHighsInf) {
828
+ double value = lower[iCol] * bound_scale_value;
829
+ if (std::abs(value) > data.infinite_bound)
830
+ data.num_infinite_col_bounds++;
831
+ if (apply) lower[iCol] = value;
832
+ }
833
+ if (upper[iCol] < kHighsInf) {
834
+ double value = upper[iCol] * bound_scale_value;
835
+ if (std::abs(value) > data.infinite_bound)
836
+ data.num_infinite_col_bounds++;
837
+ if (apply) upper[iCol] = value;
838
+ }
839
+ }
840
+ }
841
+ }
842
+
843
+ void userScaleRowBounds(vector<double>& lower, vector<double>& upper,
844
+ HighsUserScaleData& data, const bool apply) {
845
+ data.num_infinite_row_bounds = 0;
846
+ const HighsInt user_bound_scale = data.user_bound_scale;
847
+ if (!user_bound_scale) return;
848
+ const HighsInt num_row = lower.size();
849
+ if (num_row <= 0) return;
850
+ double bound_scale_value = std::pow(2, user_bound_scale);
851
+ for (HighsInt iRow = 0; iRow < num_row; iRow++) {
852
+ if (lower[iRow] > -kHighsInf) {
853
+ double value = lower[iRow] * bound_scale_value;
854
+ if (std::abs(value) > data.infinite_bound) data.num_infinite_row_bounds++;
855
+ if (apply) lower[iRow] = value;
856
+ }
857
+ if (upper[iRow] < kHighsInf) {
858
+ double value = upper[iRow] * bound_scale_value;
859
+ if (std::abs(value) > data.infinite_bound) data.num_infinite_row_bounds++;
860
+ if (apply) upper[iRow] = value;
861
+ }
862
+ }
863
+ }
864
+
865
+ void userScaleMatrix(const vector<HighsVarType>& integrality,
866
+ HighsSparseMatrix& matrix, HighsUserScaleData& data,
867
+ const bool apply) {
868
+ data.num_small_matrix_values = 0;
869
+ data.num_large_matrix_values = 0;
870
+ const HighsInt user_bound_scale = data.user_bound_scale;
871
+ if (!user_bound_scale) return;
872
+ if (!integrality.size()) return;
873
+ const HighsInt num_col = matrix.num_col_;
874
+ if (num_col <= 0) return;
875
+ const HighsInt num_row = matrix.num_row_;
876
+ if (num_row <= 0) return;
877
+ assert(HighsInt(integrality.size()) >= num_col);
878
+ double bound_scale_value = std::pow(2, user_bound_scale);
879
+ if (matrix.isColwise()) {
880
+ for (HighsInt iCol = 0; iCol < num_col; iCol++) {
881
+ if (integrality[iCol] == HighsVarType::kContinuous) continue;
882
+ for (HighsInt iEl = matrix.start_[iCol]; iEl < matrix.start_[iCol + 1];
883
+ iEl++) {
884
+ double value = matrix.value_[iEl] * bound_scale_value;
885
+ double abs_value = std::fabs(value);
886
+ if (abs_value <= data.small_matrix_value)
887
+ data.num_small_matrix_values++;
888
+ else if (abs_value >= data.large_matrix_value)
889
+ data.num_large_matrix_values++;
890
+ if (apply) matrix.value_[iEl] = value;
891
+ }
892
+ }
893
+ } else {
894
+ for (HighsInt iRow = 0; iRow < num_row; iRow++) {
895
+ for (HighsInt iEl = matrix.start_[iRow]; iEl < matrix.start_[iRow + 1];
896
+ iEl++) {
897
+ HighsInt iCol = matrix.index_[iEl];
898
+ if (integrality[iCol] == HighsVarType::kContinuous) continue;
899
+ double value = matrix.value_[iEl] * bound_scale_value;
900
+ double abs_value = std::fabs(value);
901
+ if (abs_value <= data.small_matrix_value)
902
+ data.num_small_matrix_values++;
903
+ else if (abs_value >= data.large_matrix_value)
904
+ data.num_large_matrix_values++;
905
+ if (apply) matrix.value_[iEl] = value;
906
+ }
907
+ }
908
+ }
909
+ }
910
+
911
+ HighsStatus userScaleStatus(const HighsLogOptions& log_options,
912
+ const HighsUserScaleData& data) {
913
+ HighsStatus return_status = HighsStatus::kOk;
914
+ std::string message;
915
+ if (data.scaleWarning(message)) {
916
+ highsLogUser(log_options, HighsLogType::kWarning, "%s\n", message.c_str());
917
+ return_status = HighsStatus::kWarning;
918
+ }
919
+ if (data.scaleError(message)) {
920
+ highsLogUser(log_options, HighsLogType::kError, "%s\n", message.c_str());
921
+ return_status = HighsStatus::kError;
922
+ }
923
+ return return_status;
924
+ }
925
+
926
+ bool considerScaling(const HighsOptions& options, HighsLp& lp) {
927
+ // Indicate whether new scaling has been determined in the return value.
928
+ bool new_scaling = false;
929
+ // Consider scaling the LP - either by finding new factors or by
930
+ // applying any existing factors
931
+ const bool allow_scaling =
932
+ lp.num_col_ > 0 &&
933
+ options.simplex_scale_strategy != kSimplexScaleStrategyOff;
934
+ if (lp.scale_.has_scaling && !allow_scaling) {
935
+ // LP had scaling before, but now it is not permitted, clear any
936
+ // scaling. Return true as scaling position has changed
937
+ lp.clearScale();
938
+ return true;
939
+ }
940
+ const bool scaling_not_tried = lp.scale_.strategy == kSimplexScaleStrategyOff;
941
+ const bool new_scaling_strategy =
942
+ options.simplex_scale_strategy != lp.scale_.strategy &&
943
+ options.simplex_scale_strategy != kSimplexScaleStrategyChoose;
944
+ const bool try_scaling =
945
+ allow_scaling && (scaling_not_tried || new_scaling_strategy);
946
+ if (try_scaling) {
947
+ // Scaling will be tried, so ensure that any previous scaling is not applied
948
+ lp.unapplyScale();
949
+ const bool analyse_lp_data =
950
+ kHighsAnalysisLevelModelData & options.highs_analysis_level;
951
+ if (analyse_lp_data) analyseLp(options.log_options, lp);
952
+ scaleLp(options, lp);
953
+ // If the LP is now scaled, then the scaling is new
954
+ new_scaling = lp.is_scaled_;
955
+ if (analyse_lp_data && lp.is_scaled_) analyseLp(options.log_options, lp);
956
+ } else if (lp.scale_.has_scaling) {
957
+ // Scaling factors are known, so ensure that they are applied
958
+ lp.applyScale();
959
+ }
960
+ // Ensure that either the LP has scale factors and is scaled, or
961
+ // it doesn't have scale factors and isn't scaled
962
+ assert(lp.scale_.has_scaling == lp.is_scaled_);
963
+ return new_scaling;
964
+ }
965
+
966
+ void scaleLp(const HighsOptions& options, HighsLp& lp,
967
+ const bool force_scaling) {
968
+ lp.clearScaling();
969
+ HighsInt numCol = lp.num_col_;
970
+ HighsInt numRow = lp.num_row_;
971
+ // Scaling not well defined for models with no columns
972
+ assert(numCol > 0);
973
+ vector<double>& colCost = lp.col_cost_;
974
+ vector<double>& colLower = lp.col_lower_;
975
+ vector<double>& colUpper = lp.col_upper_;
976
+ vector<double>& rowLower = lp.row_lower_;
977
+ vector<double>& rowUpper = lp.row_upper_;
978
+
979
+ // Save the simplex_scale_strategy so that the option can be
980
+ // modified for the course of this method
981
+ HighsInt simplex_scale_strategy = options.simplex_scale_strategy;
982
+ // Determine the actual strategy to use
983
+ HighsInt use_scale_strategy = simplex_scale_strategy;
984
+ if (use_scale_strategy == kSimplexScaleStrategyChoose) {
985
+ // HiGHS is left to choose: currently use forced equilibration, but maybe do
986
+ // something more intelligent
987
+ use_scale_strategy = kSimplexScaleStrategyForcedEquilibration;
988
+ }
989
+ // Find out range of matrix values and skip matrix scaling if all
990
+ // |values| are in [0.2, 5]
991
+ const double no_scaling_original_matrix_min_value = 0.2;
992
+ const double no_scaling_original_matrix_max_value = 5.0;
993
+ double original_matrix_min_value = kHighsInf;
994
+ double original_matrix_max_value = 0;
995
+ lp.a_matrix_.range(original_matrix_min_value, original_matrix_max_value);
996
+ // Possibly force scaling, otherwise base the decision on the range
997
+ // of values in the matrix, values that will be used later for
998
+ // reporting
999
+ const bool no_scaling = force_scaling
1000
+ ? false
1001
+ : (original_matrix_min_value >=
1002
+ no_scaling_original_matrix_min_value) &&
1003
+ (original_matrix_max_value <=
1004
+ no_scaling_original_matrix_max_value);
1005
+ bool scaled_matrix = false;
1006
+ if (no_scaling) {
1007
+ // No matrix scaling, but possible cost scaling
1008
+ if (options.highs_analysis_level)
1009
+ highsLogDev(options.log_options, HighsLogType::kInfo,
1010
+ "Scaling: Matrix has [min, max] values of [%g, %g] within "
1011
+ "[%g, %g] so no scaling performed\n",
1012
+ original_matrix_min_value, original_matrix_max_value,
1013
+ no_scaling_original_matrix_min_value,
1014
+ no_scaling_original_matrix_max_value);
1015
+ } else {
1016
+ // Try scaling, so assign unit factors - partly because initial
1017
+ // factors may be assumed by the scaling method, but also because
1018
+ // scaling factors may not be computed for empty rows/columns
1019
+ HighsScale& scale = lp.scale_;
1020
+ scale.col.assign(numCol, 1);
1021
+ scale.row.assign(numRow, 1);
1022
+ const bool equilibration_scaling =
1023
+ use_scale_strategy == kSimplexScaleStrategyEquilibration ||
1024
+ use_scale_strategy == kSimplexScaleStrategyForcedEquilibration;
1025
+ // Try scaling. Value of scaled_matrix indicates whether scaling
1026
+ // was considered valuable (and performed). If it's not valuable
1027
+ // then the matrix remains unscaled
1028
+ if (equilibration_scaling) {
1029
+ scaled_matrix = equilibrationScaleMatrix(options, lp, use_scale_strategy);
1030
+ } else {
1031
+ scaled_matrix = maxValueScaleMatrix(options, lp, use_scale_strategy);
1032
+ }
1033
+ if (scaled_matrix) {
1034
+ // Matrix is scaled, so scale the bounds and costs
1035
+ for (HighsInt iCol = 0; iCol < numCol; iCol++) {
1036
+ colLower[iCol] /= scale.col[iCol];
1037
+ colUpper[iCol] /= scale.col[iCol];
1038
+ colCost[iCol] *= scale.col[iCol];
1039
+ }
1040
+ for (HighsInt iRow = 0; iRow < numRow; iRow++) {
1041
+ rowLower[iRow] *= scale.row[iRow];
1042
+ rowUpper[iRow] *= scale.row[iRow];
1043
+ }
1044
+ scale.has_scaling = true;
1045
+ scale.num_col = numCol;
1046
+ scale.num_row = numRow;
1047
+ scale.cost = 1.0;
1048
+ lp.is_scaled_ = true;
1049
+ } else {
1050
+ // Matrix is not scaled, so clear the scaling
1051
+ lp.clearScaling();
1052
+ }
1053
+ }
1054
+ // Record the scaling strategy used
1055
+ lp.scale_.strategy = use_scale_strategy;
1056
+ // Possibly scale the costs
1057
+ // if (allow_cost_scaling) scaleSimplexCost(options, lp, scale.cost);
1058
+
1059
+ // If matrix is unscaled, then LP is only scaled if there is a cost scaling
1060
+ // factor
1061
+ // if (!scaled_matrix) lp.is_scaled_ = scale.cost != 1;
1062
+ }
1063
+
1064
+ bool equilibrationScaleMatrix(const HighsOptions& options, HighsLp& lp,
1065
+ const HighsInt use_scale_strategy) {
1066
+ HighsInt numCol = lp.num_col_;
1067
+ HighsInt numRow = lp.num_row_;
1068
+ HighsScale& scale = lp.scale_;
1069
+ vector<double>& colScale = scale.col;
1070
+ vector<double>& rowScale = scale.row;
1071
+ vector<HighsInt>& Astart = lp.a_matrix_.start_;
1072
+ vector<HighsInt>& Aindex = lp.a_matrix_.index_;
1073
+ vector<double>& Avalue = lp.a_matrix_.value_;
1074
+ vector<double>& colCost = lp.col_cost_;
1075
+
1076
+ HighsInt simplex_scale_strategy = use_scale_strategy;
1077
+
1078
+ double original_matrix_min_value = kHighsInf;
1079
+ double original_matrix_max_value = 0;
1080
+ for (HighsInt k = 0, AnX = Astart[numCol]; k < AnX; k++) {
1081
+ double value = fabs(Avalue[k]);
1082
+ original_matrix_min_value = min(original_matrix_min_value, value);
1083
+ original_matrix_max_value = max(original_matrix_max_value, value);
1084
+ }
1085
+
1086
+ // Include cost in scaling if minimum nonzero cost is less than 0.1
1087
+ double min_nonzero_cost = kHighsInf;
1088
+ for (HighsInt i = 0; i < numCol; i++) {
1089
+ if (colCost[i]) min_nonzero_cost = min(fabs(colCost[i]), min_nonzero_cost);
1090
+ }
1091
+ bool include_cost_in_scaling = false;
1092
+ include_cost_in_scaling = min_nonzero_cost < 0.1;
1093
+
1094
+ // Limits on scaling factors
1095
+ double max_allow_scale;
1096
+ double min_allow_scale;
1097
+ // Now that kHighsInf =
1098
+ // std::numeric_limits<double>::infinity(), this Qi-trick doesn't
1099
+ // work so, in recognition, use the old value of kHighsInf
1100
+ const double finite_infinity = 1e200;
1101
+ max_allow_scale = pow(2.0, options.allowed_matrix_scale_factor);
1102
+ min_allow_scale = 1 / max_allow_scale;
1103
+
1104
+ double min_allow_col_scale = min_allow_scale;
1105
+ double max_allow_col_scale = max_allow_scale;
1106
+ double min_allow_row_scale = min_allow_scale;
1107
+ double max_allow_row_scale = max_allow_scale;
1108
+
1109
+ // Search up to 6 times
1110
+ vector<double> row_min_value(numRow, finite_infinity);
1111
+ vector<double> row_max_value(numRow, 1 / finite_infinity);
1112
+ for (HighsInt search_count = 0; search_count < 6; search_count++) {
1113
+ // Find column scale, prepare row data
1114
+ for (HighsInt iCol = 0; iCol < numCol; iCol++) {
1115
+ // For column scale (find)
1116
+ double col_min_value = finite_infinity;
1117
+ double col_max_value = 1 / finite_infinity;
1118
+ double abs_col_cost = fabs(colCost[iCol]);
1119
+ if (include_cost_in_scaling && abs_col_cost != 0) {
1120
+ col_min_value = min(col_min_value, abs_col_cost);
1121
+ col_max_value = max(col_max_value, abs_col_cost);
1122
+ }
1123
+ for (HighsInt k = Astart[iCol]; k < Astart[iCol + 1]; k++) {
1124
+ double value = fabs(Avalue[k]) * rowScale[Aindex[k]];
1125
+ col_min_value = min(col_min_value, value);
1126
+ col_max_value = max(col_max_value, value);
1127
+ }
1128
+ double col_equilibration = 1 / sqrt(col_min_value * col_max_value);
1129
+ // Ensure that column scale factor is not excessively large or small
1130
+ colScale[iCol] =
1131
+ min(max(min_allow_col_scale, col_equilibration), max_allow_col_scale);
1132
+ // For row scale (only collect)
1133
+ for (HighsInt k = Astart[iCol]; k < Astart[iCol + 1]; k++) {
1134
+ HighsInt iRow = Aindex[k];
1135
+ double value = fabs(Avalue[k]) * colScale[iCol];
1136
+ row_min_value[iRow] = min(row_min_value[iRow], value);
1137
+ row_max_value[iRow] = max(row_max_value[iRow], value);
1138
+ }
1139
+ }
1140
+ // For row scale (find)
1141
+ for (HighsInt iRow = 0; iRow < numRow; iRow++) {
1142
+ double row_equilibration =
1143
+ 1 / sqrt(row_min_value[iRow] * row_max_value[iRow]);
1144
+ // Ensure that row scale factor is not excessively large or small
1145
+ rowScale[iRow] =
1146
+ min(max(min_allow_row_scale, row_equilibration), max_allow_row_scale);
1147
+ }
1148
+ row_min_value.assign(numRow, finite_infinity);
1149
+ row_max_value.assign(numRow, 1 / finite_infinity);
1150
+ }
1151
+ // Make it numerically better
1152
+ // Also determine the max and min row and column scaling factors
1153
+ double min_col_scale = finite_infinity;
1154
+ double max_col_scale = 1 / finite_infinity;
1155
+ double min_row_scale = finite_infinity;
1156
+ double max_row_scale = 1 / finite_infinity;
1157
+ const double log2 = log(2.0);
1158
+ for (HighsInt iCol = 0; iCol < numCol; iCol++) {
1159
+ colScale[iCol] = pow(2.0, floor(log(colScale[iCol]) / log2 + 0.5));
1160
+ min_col_scale = min(colScale[iCol], min_col_scale);
1161
+ max_col_scale = max(colScale[iCol], max_col_scale);
1162
+ }
1163
+ for (HighsInt iRow = 0; iRow < numRow; iRow++) {
1164
+ rowScale[iRow] = pow(2.0, floor(log(rowScale[iRow]) / log2 + 0.5));
1165
+ min_row_scale = min(rowScale[iRow], min_row_scale);
1166
+ max_row_scale = max(rowScale[iRow], max_row_scale);
1167
+ }
1168
+ // Apply scaling to matrix and bounds
1169
+ double matrix_min_value = finite_infinity;
1170
+ double matrix_max_value = 0;
1171
+ double min_original_col_equilibration = finite_infinity;
1172
+ double sum_original_log_col_equilibration = 0;
1173
+ double max_original_col_equilibration = 0;
1174
+ double min_original_row_equilibration = finite_infinity;
1175
+ double sum_original_log_row_equilibration = 0;
1176
+ double max_original_row_equilibration = 0;
1177
+ double min_col_equilibration = finite_infinity;
1178
+ double sum_log_col_equilibration = 0;
1179
+ double max_col_equilibration = 0;
1180
+ double min_row_equilibration = finite_infinity;
1181
+ double sum_log_row_equilibration = 0;
1182
+ double max_row_equilibration = 0;
1183
+ vector<double> original_row_min_value(numRow, finite_infinity);
1184
+ vector<double> original_row_max_value(numRow, 1 / finite_infinity);
1185
+ row_min_value.assign(numRow, finite_infinity);
1186
+ row_max_value.assign(numRow, 1 / finite_infinity);
1187
+ for (HighsInt iCol = 0; iCol < numCol; iCol++) {
1188
+ double original_col_min_value = finite_infinity;
1189
+ double original_col_max_value = 1 / finite_infinity;
1190
+ double col_min_value = finite_infinity;
1191
+ double col_max_value = 1 / finite_infinity;
1192
+ for (HighsInt k = Astart[iCol]; k < Astart[iCol + 1]; k++) {
1193
+ HighsInt iRow = Aindex[k];
1194
+ const double original_value = fabs(Avalue[k]);
1195
+ original_col_min_value = min(original_value, original_col_min_value);
1196
+ original_col_max_value = max(original_value, original_col_max_value);
1197
+ original_row_min_value[iRow] =
1198
+ min(original_row_min_value[iRow], original_value);
1199
+ original_row_max_value[iRow] =
1200
+ max(original_row_max_value[iRow], original_value);
1201
+ Avalue[k] *= (colScale[iCol] * rowScale[iRow]);
1202
+ const double value = fabs(Avalue[k]);
1203
+ col_min_value = min(value, col_min_value);
1204
+ col_max_value = max(value, col_max_value);
1205
+ row_min_value[iRow] = min(row_min_value[iRow], value);
1206
+ row_max_value[iRow] = max(row_max_value[iRow], value);
1207
+ }
1208
+ matrix_min_value = min(matrix_min_value, col_min_value);
1209
+ matrix_max_value = max(matrix_max_value, col_max_value);
1210
+
1211
+ const double original_col_equilibration =
1212
+ 1 / sqrt(original_col_min_value * original_col_max_value);
1213
+ min_original_col_equilibration =
1214
+ min(original_col_equilibration, min_original_col_equilibration);
1215
+ sum_original_log_col_equilibration += log(original_col_equilibration);
1216
+ max_original_col_equilibration =
1217
+ max(original_col_equilibration, max_original_col_equilibration);
1218
+ const double col_equilibration = 1 / sqrt(col_min_value * col_max_value);
1219
+ min_col_equilibration = min(col_equilibration, min_col_equilibration);
1220
+ sum_log_col_equilibration += log(col_equilibration);
1221
+ max_col_equilibration = max(col_equilibration, max_col_equilibration);
1222
+ }
1223
+
1224
+ for (HighsInt iRow = 0; iRow < numRow; iRow++) {
1225
+ const double original_row_equilibration =
1226
+ 1 / sqrt(original_row_min_value[iRow] * original_row_max_value[iRow]);
1227
+ min_original_row_equilibration =
1228
+ min(original_row_equilibration, min_original_row_equilibration);
1229
+ sum_original_log_row_equilibration += log(original_row_equilibration);
1230
+ max_original_row_equilibration =
1231
+ max(original_row_equilibration, max_original_row_equilibration);
1232
+ const double row_equilibration =
1233
+ 1 / sqrt(row_min_value[iRow] * row_max_value[iRow]);
1234
+ min_row_equilibration = min(row_equilibration, min_row_equilibration);
1235
+ sum_log_row_equilibration += log(row_equilibration);
1236
+ max_row_equilibration = max(row_equilibration, max_row_equilibration);
1237
+ }
1238
+ const double geomean_original_col_equilibration =
1239
+ exp(sum_original_log_col_equilibration / numCol);
1240
+ const double geomean_original_row_equilibration =
1241
+ exp(sum_original_log_row_equilibration / numRow);
1242
+ const double geomean_col_equilibration =
1243
+ exp(sum_log_col_equilibration / numCol);
1244
+ const double geomean_row_equilibration =
1245
+ exp(sum_log_row_equilibration / numRow);
1246
+ if (options.log_dev_level) {
1247
+ highsLogDev(
1248
+ options.log_options, HighsLogType::kInfo,
1249
+ "Scaling: Original equilibration: min/mean/max %11.4g/%11.4g/%11.4g "
1250
+ "(cols); min/mean/max %11.4g/%11.4g/%11.4g (rows)\n",
1251
+ min_original_col_equilibration, geomean_original_col_equilibration,
1252
+ max_original_col_equilibration, min_original_row_equilibration,
1253
+ geomean_original_row_equilibration, max_original_row_equilibration);
1254
+ highsLogDev(
1255
+ options.log_options, HighsLogType::kInfo,
1256
+ "Scaling: Final equilibration: min/mean/max %11.4g/%11.4g/%11.4g "
1257
+ "(cols); min/mean/max %11.4g/%11.4g/%11.4g (rows)\n",
1258
+ min_col_equilibration, geomean_col_equilibration, max_col_equilibration,
1259
+ min_row_equilibration, geomean_row_equilibration,
1260
+ max_row_equilibration);
1261
+ }
1262
+
1263
+ // Compute the mean equilibration improvement
1264
+ const double geomean_original_col =
1265
+ max(geomean_original_col_equilibration,
1266
+ 1 / geomean_original_col_equilibration);
1267
+ const double geomean_original_row =
1268
+ max(geomean_original_row_equilibration,
1269
+ 1 / geomean_original_row_equilibration);
1270
+ const double geomean_col =
1271
+ max(geomean_col_equilibration, 1 / geomean_col_equilibration);
1272
+ const double geomean_row =
1273
+ max(geomean_row_equilibration, 1 / geomean_row_equilibration);
1274
+ const double mean_equilibration_improvement =
1275
+ sqrt((geomean_original_col * geomean_original_row) /
1276
+ (geomean_col * geomean_row));
1277
+ // Compute the extreme equilibration improvement
1278
+ const double original_col_ratio =
1279
+ max_original_col_equilibration / min_original_col_equilibration;
1280
+ const double original_row_ratio =
1281
+ max_original_row_equilibration / min_original_row_equilibration;
1282
+ const double col_ratio = max_col_equilibration / min_col_equilibration;
1283
+ const double row_ratio = max_row_equilibration / min_row_equilibration;
1284
+ const double extreme_equilibration_improvement =
1285
+ (original_col_ratio + original_row_ratio) / (col_ratio + row_ratio);
1286
+ // Compute the max/min matrix value improvement
1287
+ const double matrix_value_ratio = matrix_max_value / matrix_min_value;
1288
+ const double original_matrix_value_ratio =
1289
+ original_matrix_max_value / original_matrix_min_value;
1290
+ const double matrix_value_ratio_improvement =
1291
+ original_matrix_value_ratio / matrix_value_ratio;
1292
+ if (options.log_dev_level) {
1293
+ highsLogDev(
1294
+ options.log_options, HighsLogType::kInfo,
1295
+ "Scaling: Extreme equilibration improvement = ( %11.4g + "
1296
+ "%11.4g) / ( %11.4g + %11.4g) = %11.4g / %11.4g = %11.4g\n",
1297
+ original_col_ratio, original_row_ratio, col_ratio, row_ratio,
1298
+ (original_col_ratio + original_row_ratio), (col_ratio + row_ratio),
1299
+ extreme_equilibration_improvement);
1300
+ highsLogDev(
1301
+ options.log_options, HighsLogType::kInfo,
1302
+ "Scaling: Mean equilibration improvement = sqrt(( %11.4g * "
1303
+ "%11.4g) / ( %11.4g * %11.4g)) = sqrt(%11.4g / %11.4g) = %11.4g\n",
1304
+ geomean_original_col, geomean_original_row, geomean_col, geomean_row,
1305
+ (geomean_original_col * geomean_original_row),
1306
+ (geomean_col * geomean_row), mean_equilibration_improvement);
1307
+ highsLogDev(
1308
+ options.log_options, HighsLogType::kInfo,
1309
+ "Scaling: Yields [min, max, ratio] matrix values of [%0.4g, %0.4g, "
1310
+ "%0.4g]; Originally [%0.4g, %0.4g, %0.4g]: Improvement of %0.4g\n",
1311
+ matrix_min_value, matrix_max_value, matrix_value_ratio,
1312
+ original_matrix_min_value, original_matrix_max_value,
1313
+ original_matrix_value_ratio, matrix_value_ratio_improvement);
1314
+ highsLogDev(options.log_options, HighsLogType::kInfo,
1315
+ "Scaling: Improves mean equilibration by a factor %0.4g\n",
1316
+ mean_equilibration_improvement);
1317
+ highsLogDev(options.log_options, HighsLogType::kInfo,
1318
+ "Scaling: Improves extreme equilibration by a factor %0.4g\n",
1319
+ extreme_equilibration_improvement);
1320
+ highsLogDev(options.log_options, HighsLogType::kInfo,
1321
+ "Scaling: Improves max/min matrix values by a factor %0.4g\n",
1322
+ matrix_value_ratio_improvement);
1323
+ }
1324
+ const bool possibly_abandon_scaling =
1325
+ simplex_scale_strategy != kSimplexScaleStrategyForcedEquilibration;
1326
+ const double improvement_factor = extreme_equilibration_improvement *
1327
+ mean_equilibration_improvement *
1328
+ matrix_value_ratio_improvement;
1329
+
1330
+ const double improvement_factor_required = 1.0;
1331
+ const bool poor_improvement =
1332
+ improvement_factor < improvement_factor_required;
1333
+
1334
+ // Possibly abandon scaling if it's not improved equilibration significantly
1335
+ if (possibly_abandon_scaling && poor_improvement) {
1336
+ // Unscale the matrix
1337
+ for (HighsInt iCol = 0; iCol < numCol; iCol++) {
1338
+ for (HighsInt k = Astart[iCol]; k < Astart[iCol + 1]; k++) {
1339
+ HighsInt iRow = Aindex[k];
1340
+ Avalue[k] /= (colScale[iCol] * rowScale[iRow]);
1341
+ }
1342
+ }
1343
+ if (options.log_dev_level)
1344
+ highsLogDev(options.log_options, HighsLogType::kInfo,
1345
+ "Scaling: Improvement factor %0.4g < %0.4g required, so no "
1346
+ "scaling applied\n",
1347
+ improvement_factor, improvement_factor_required);
1348
+ return false;
1349
+ } else {
1350
+ if (options.log_dev_level) {
1351
+ highsLogDev(options.log_options, HighsLogType::kInfo,
1352
+ "Scaling: Factors are in [%0.4g, %0.4g] for columns and in "
1353
+ "[%0.4g, %0.4g] for rows\n",
1354
+ min_col_scale, max_col_scale, min_row_scale, max_row_scale);
1355
+ highsLogDev(options.log_options, HighsLogType::kInfo,
1356
+ "Scaling: Improvement factor is %0.4g >= %0.4g so scale LP\n",
1357
+ improvement_factor, improvement_factor_required);
1358
+ if (extreme_equilibration_improvement < 1.0) {
1359
+ highsLogDev(
1360
+ options.log_options, HighsLogType::kWarning,
1361
+ "Scaling: Applying scaling with extreme improvement of %0.4g\n",
1362
+ extreme_equilibration_improvement);
1363
+ }
1364
+ if (mean_equilibration_improvement < 1.0) {
1365
+ highsLogDev(
1366
+ options.log_options, HighsLogType::kWarning,
1367
+ "Scaling: Applying scaling with mean improvement of %0.4g\n",
1368
+ mean_equilibration_improvement);
1369
+ }
1370
+ if (matrix_value_ratio_improvement < 1.0) {
1371
+ highsLogDev(options.log_options, HighsLogType::kWarning,
1372
+ "Scaling: Applying scaling with matrix value ratio "
1373
+ "improvement of %0.4g\n",
1374
+ matrix_value_ratio_improvement);
1375
+ }
1376
+ if (improvement_factor < 10 * improvement_factor_required) {
1377
+ highsLogDev(options.log_options, HighsLogType::kWarning,
1378
+ "Scaling: Applying scaling with improvement factor %0.4g "
1379
+ "< 10*(%0.4g) improvement\n",
1380
+ improvement_factor, improvement_factor_required);
1381
+ }
1382
+ }
1383
+ }
1384
+ return true;
1385
+ }
1386
+
1387
+ bool maxValueScaleMatrix(const HighsOptions& options, HighsLp& lp,
1388
+ const HighsInt use_scale_strategy) {
1389
+ HighsInt numCol = lp.num_col_;
1390
+ HighsInt numRow = lp.num_row_;
1391
+ HighsScale& scale = lp.scale_;
1392
+ vector<double>& colScale = scale.col;
1393
+ vector<double>& rowScale = scale.row;
1394
+ vector<HighsInt>& Astart = lp.a_matrix_.start_;
1395
+ vector<HighsInt>& Aindex = lp.a_matrix_.index_;
1396
+ vector<double>& Avalue = lp.a_matrix_.value_;
1397
+
1398
+ assert(options.simplex_scale_strategy == kSimplexScaleStrategyMaxValue);
1399
+ assert(kSimplexScaleStrategyMaxValue015 == kSimplexScaleStrategyMaxValue);
1400
+ assert(kSimplexScaleStrategyMaxValue0157 == kSimplexScaleStrategyMaxValue);
1401
+
1402
+ // The 015(7) values refer to bit settings in FICO's scaling options.
1403
+ // Specifically
1404
+ //
1405
+ // 0: Row scaling
1406
+ //
1407
+ // 1: Column scaling
1408
+ //
1409
+ // 5: Scale by maximum element
1410
+ //
1411
+ // 7: Scale objective function for the simplex method
1412
+ //
1413
+ // Note that 7 is not yet implemented, so
1414
+ // kSimplexScaleStrategyMaxValue015 and
1415
+ // kSimplexScaleStrategyMaxValue0157 are equivalent. However, cost
1416
+ // scaling could be well worth adding, now that the unscaled problem
1417
+ // can be solved using scaled NLA
1418
+
1419
+ const double log2 = log(2.0);
1420
+ const double max_allow_scale = pow(2.0, options.allowed_matrix_scale_factor);
1421
+ const double min_allow_scale = 1 / max_allow_scale;
1422
+
1423
+ const double min_allow_col_scale = min_allow_scale;
1424
+ const double max_allow_col_scale = max_allow_scale;
1425
+ const double min_allow_row_scale = min_allow_scale;
1426
+ const double max_allow_row_scale = max_allow_scale;
1427
+
1428
+ double min_row_scale = kHighsInf;
1429
+ double max_row_scale = 0;
1430
+ double original_matrix_min_value = kHighsInf;
1431
+ double original_matrix_max_value = 0;
1432
+ // Determine the row scaling. Also determine the max/min row scaling
1433
+ // factors, and max/min original matrix values
1434
+ vector<double> row_max_value(numRow, 0);
1435
+ for (HighsInt iCol = 0; iCol < numCol; iCol++) {
1436
+ for (HighsInt k = Astart[iCol]; k < Astart[iCol + 1]; k++) {
1437
+ const HighsInt iRow = Aindex[k];
1438
+ const double value = fabs(Avalue[k]);
1439
+ row_max_value[iRow] = max(row_max_value[iRow], value);
1440
+ original_matrix_min_value = min(original_matrix_min_value, value);
1441
+ original_matrix_max_value = max(original_matrix_max_value, value);
1442
+ }
1443
+ }
1444
+ for (HighsInt iRow = 0; iRow < numRow; iRow++) {
1445
+ if (row_max_value[iRow]) {
1446
+ double row_scale_value = 1 / row_max_value[iRow];
1447
+ // Convert the row scale factor to the nearest power of two, and
1448
+ // ensure that it is not excessively large or small
1449
+ row_scale_value = pow(2.0, floor(log(row_scale_value) / log2 + 0.5));
1450
+ row_scale_value =
1451
+ min(max(min_allow_row_scale, row_scale_value), max_allow_row_scale);
1452
+ min_row_scale = min(row_scale_value, min_row_scale);
1453
+ max_row_scale = max(row_scale_value, max_row_scale);
1454
+ rowScale[iRow] = row_scale_value;
1455
+ }
1456
+ }
1457
+ // Determine the column scaling, whilst applying the row scaling
1458
+ // Also determine the max/min column scaling factors, and max/min
1459
+ // matrix values
1460
+ double min_col_scale = kHighsInf;
1461
+ double max_col_scale = 0;
1462
+ double matrix_min_value = kHighsInf;
1463
+ double matrix_max_value = 0;
1464
+ for (HighsInt iCol = 0; iCol < numCol; iCol++) {
1465
+ double col_max_value = 0;
1466
+ for (HighsInt k = Astart[iCol]; k < Astart[iCol + 1]; k++) {
1467
+ const HighsInt iRow = Aindex[k];
1468
+ Avalue[k] *= rowScale[iRow];
1469
+ const double value = fabs(Avalue[k]);
1470
+ col_max_value = max(col_max_value, value);
1471
+ }
1472
+ if (col_max_value) {
1473
+ double col_scale_value = 1 / col_max_value;
1474
+ // Convert the col scale factor to the nearest power of two, and
1475
+ // ensure that it is not excessively large or small
1476
+ col_scale_value = pow(2.0, floor(log(col_scale_value) / log2 + 0.5));
1477
+ col_scale_value =
1478
+ min(max(min_allow_col_scale, col_scale_value), max_allow_col_scale);
1479
+ min_col_scale = min(col_scale_value, min_col_scale);
1480
+ max_col_scale = max(col_scale_value, max_col_scale);
1481
+ colScale[iCol] = col_scale_value;
1482
+ for (HighsInt k = Astart[iCol]; k < Astart[iCol + 1]; k++) {
1483
+ Avalue[k] *= colScale[iCol];
1484
+ const double value = fabs(Avalue[k]);
1485
+ matrix_min_value = min(matrix_min_value, value);
1486
+ matrix_max_value = max(matrix_max_value, value);
1487
+ }
1488
+ }
1489
+ }
1490
+ const double matrix_value_ratio = matrix_max_value / matrix_min_value;
1491
+ const double original_matrix_value_ratio =
1492
+ original_matrix_max_value / original_matrix_min_value;
1493
+ const double matrix_value_ratio_improvement =
1494
+ original_matrix_value_ratio / matrix_value_ratio;
1495
+
1496
+ const double improvement_factor = matrix_value_ratio_improvement;
1497
+
1498
+ const double improvement_factor_required = 1.0;
1499
+ const bool poor_improvement =
1500
+ improvement_factor <= improvement_factor_required;
1501
+
1502
+ if (poor_improvement) {
1503
+ // Unscale the matrix
1504
+ for (HighsInt iCol = 0; iCol < numCol; iCol++) {
1505
+ for (HighsInt k = Astart[iCol]; k < Astart[iCol + 1]; k++) {
1506
+ HighsInt iRow = Aindex[k];
1507
+ Avalue[k] /= (colScale[iCol] * rowScale[iRow]);
1508
+ }
1509
+ }
1510
+ if (options.log_dev_level)
1511
+ highsLogDev(options.log_options, HighsLogType::kInfo,
1512
+ "Scaling: Improvement factor %0.4g < %0.4g required, so no "
1513
+ "scaling applied\n",
1514
+ improvement_factor, improvement_factor_required);
1515
+ return false;
1516
+ } else {
1517
+ if (options.log_dev_level) {
1518
+ highsLogDev(options.log_options, HighsLogType::kInfo,
1519
+ "Scaling: Factors are in [%0.4g, %0.4g] for columns and in "
1520
+ "[%0.4g, %0.4g] for rows\n",
1521
+ min_col_scale, max_col_scale, min_row_scale, max_row_scale);
1522
+ highsLogDev(
1523
+ options.log_options, HighsLogType::kInfo,
1524
+ "Scaling: Yields [min, max, ratio] matrix values of [%0.4g, %0.4g, "
1525
+ "%0.4g]; Originally [%0.4g, %0.4g, %0.4g]: Improvement of %0.4g\n",
1526
+ matrix_min_value, matrix_max_value, matrix_value_ratio,
1527
+ original_matrix_min_value, original_matrix_max_value,
1528
+ original_matrix_value_ratio, matrix_value_ratio_improvement);
1529
+ }
1530
+ return true;
1531
+ }
1532
+ }
1533
+
1534
+ HighsStatus applyScalingToLpCol(HighsLp& lp, const HighsInt col,
1535
+ const double colScale) {
1536
+ if (col < 0) return HighsStatus::kError;
1537
+ if (col >= lp.num_col_) return HighsStatus::kError;
1538
+ if (!colScale) return HighsStatus::kError;
1539
+
1540
+ lp.a_matrix_.scaleCol(col, colScale);
1541
+ lp.col_cost_[col] *= colScale;
1542
+ if (colScale > 0) {
1543
+ lp.col_lower_[col] /= colScale;
1544
+ lp.col_upper_[col] /= colScale;
1545
+ } else {
1546
+ const double new_upper = lp.col_lower_[col] / colScale;
1547
+ lp.col_lower_[col] = lp.col_upper_[col] / colScale;
1548
+ lp.col_upper_[col] = new_upper;
1549
+ }
1550
+ return HighsStatus::kOk;
1551
+ }
1552
+
1553
+ HighsStatus applyScalingToLpRow(HighsLp& lp, const HighsInt row,
1554
+ const double rowScale) {
1555
+ if (row < 0) return HighsStatus::kError;
1556
+ if (row >= lp.num_row_) return HighsStatus::kError;
1557
+ if (!rowScale) return HighsStatus::kError;
1558
+
1559
+ lp.a_matrix_.scaleRow(row, rowScale);
1560
+ if (rowScale > 0) {
1561
+ lp.row_lower_[row] *= rowScale;
1562
+ lp.row_upper_[row] *= rowScale;
1563
+ } else {
1564
+ const double new_upper = lp.row_lower_[row] * rowScale;
1565
+ lp.row_lower_[row] = lp.row_upper_[row] * rowScale;
1566
+ lp.row_upper_[row] = new_upper;
1567
+ }
1568
+ return HighsStatus::kOk;
1569
+ }
1570
+
1571
+ void unscaleSolution(HighsSolution& solution, const HighsScale& scale) {
1572
+ assert(scale.has_scaling);
1573
+ assert(solution.col_value.size() == static_cast<size_t>(scale.num_col));
1574
+ assert(solution.col_dual.size() == static_cast<size_t>(scale.num_col));
1575
+ assert(solution.row_value.size() == static_cast<size_t>(scale.num_row));
1576
+ assert(solution.row_dual.size() == static_cast<size_t>(scale.num_row));
1577
+
1578
+ for (HighsInt iCol = 0; iCol < scale.num_col; iCol++) {
1579
+ solution.col_value[iCol] *= scale.col[iCol];
1580
+ solution.col_dual[iCol] /= (scale.col[iCol] / scale.cost);
1581
+ }
1582
+ for (HighsInt iRow = 0; iRow < scale.num_row; iRow++) {
1583
+ solution.row_value[iRow] /= scale.row[iRow];
1584
+ solution.row_dual[iRow] *= (scale.row[iRow] * scale.cost);
1585
+ }
1586
+ }
1587
+
1588
+ void appendColsToLpVectors(HighsLp& lp, const HighsInt num_new_col,
1589
+ const vector<double>& colCost,
1590
+ const vector<double>& colLower,
1591
+ const vector<double>& colUpper) {
1592
+ assert(num_new_col >= 0);
1593
+ if (num_new_col == 0) return;
1594
+ HighsInt new_num_col = lp.num_col_ + num_new_col;
1595
+ lp.col_cost_.resize(new_num_col);
1596
+ lp.col_lower_.resize(new_num_col);
1597
+ lp.col_upper_.resize(new_num_col);
1598
+ const bool have_integrality = (lp.integrality_.size() != 0);
1599
+ if (have_integrality) {
1600
+ assert(HighsInt(lp.integrality_.size()) == lp.num_col_);
1601
+ lp.integrality_.resize(new_num_col);
1602
+ }
1603
+ bool have_names = (lp.col_names_.size() != 0);
1604
+ if (have_names) lp.col_names_.resize(new_num_col);
1605
+ for (HighsInt new_col = 0; new_col < num_new_col; new_col++) {
1606
+ HighsInt iCol = lp.num_col_ + new_col;
1607
+ lp.col_cost_[iCol] = colCost[new_col];
1608
+ lp.col_lower_[iCol] = colLower[new_col];
1609
+ lp.col_upper_[iCol] = colUpper[new_col];
1610
+ // Cannot guarantee to create unique names, so name is blank
1611
+ if (have_names) lp.col_names_[iCol] = "";
1612
+ if (have_integrality) lp.integrality_[iCol] = HighsVarType::kContinuous;
1613
+ }
1614
+ }
1615
+
1616
+ void appendRowsToLpVectors(HighsLp& lp, const HighsInt num_new_row,
1617
+ const vector<double>& rowLower,
1618
+ const vector<double>& rowUpper) {
1619
+ assert(num_new_row >= 0);
1620
+ if (num_new_row == 0) return;
1621
+ HighsInt new_num_row = lp.num_row_ + num_new_row;
1622
+ lp.row_lower_.resize(new_num_row);
1623
+ lp.row_upper_.resize(new_num_row);
1624
+ bool have_names = (lp.row_names_.size() != 0);
1625
+ if (have_names) lp.row_names_.resize(new_num_row);
1626
+
1627
+ for (HighsInt new_row = 0; new_row < num_new_row; new_row++) {
1628
+ HighsInt iRow = lp.num_row_ + new_row;
1629
+ lp.row_lower_[iRow] = rowLower[new_row];
1630
+ lp.row_upper_[iRow] = rowUpper[new_row];
1631
+ // Cannot guarantee to create unique names, so name is blank
1632
+ if (have_names) lp.row_names_[iRow] = "";
1633
+ }
1634
+ }
1635
+
1636
+ void deleteScale(vector<double>& scale,
1637
+ const HighsIndexCollection& index_collection) {
1638
+ assert(ok(index_collection));
1639
+ HighsInt from_k;
1640
+ HighsInt to_k;
1641
+ limits(index_collection, from_k, to_k);
1642
+ if (from_k > to_k) return;
1643
+
1644
+ HighsInt delete_from_col;
1645
+ HighsInt delete_to_col;
1646
+ HighsInt keep_from_col;
1647
+ HighsInt keep_to_col = -1;
1648
+ HighsInt current_set_entry = 0;
1649
+
1650
+ HighsInt col_dim = index_collection.dimension_;
1651
+ HighsInt new_num_col = 0;
1652
+ for (HighsInt k = from_k; k <= to_k; k++) {
1653
+ updateOutInIndex(index_collection, delete_from_col, delete_to_col,
1654
+ keep_from_col, keep_to_col, current_set_entry);
1655
+ // Account for the initial columns being kept
1656
+ if (k == from_k) new_num_col = delete_from_col;
1657
+ if (delete_to_col >= col_dim - 1) break;
1658
+ assert(delete_to_col < col_dim);
1659
+ for (HighsInt col = keep_from_col; col <= keep_to_col; col++) {
1660
+ assert((HighsInt)scale.size() > new_num_col);
1661
+ scale[new_num_col] = scale[col];
1662
+ new_num_col++;
1663
+ }
1664
+ if (keep_to_col >= col_dim - 1) break;
1665
+ }
1666
+ }
1667
+
1668
+ void changeLpMatrixCoefficient(HighsLp& lp, const HighsInt row,
1669
+ const HighsInt col, const double new_value,
1670
+ const bool zero_new_value) {
1671
+ assert(0 <= row && row < lp.num_row_);
1672
+ assert(0 <= col && col < lp.num_col_);
1673
+
1674
+ // Determine whether the coefficient corresponds to an existing
1675
+ // nonzero
1676
+ HighsInt change_el = -1;
1677
+ for (HighsInt el = lp.a_matrix_.start_[col];
1678
+ el < lp.a_matrix_.start_[col + 1]; el++) {
1679
+ if (lp.a_matrix_.index_[el] == row) {
1680
+ change_el = el;
1681
+ break;
1682
+ }
1683
+ }
1684
+ if (change_el < 0) {
1685
+ // Coefficient doesn't correspond to an existing nonzero
1686
+ //
1687
+ // If coefficient is small, then just ignore it
1688
+ if (zero_new_value) return;
1689
+ // New nonzero goes at the end of column "col", so have to shift
1690
+ // all index and value entries forward by 1 to accommodate it
1691
+ change_el = lp.a_matrix_.start_[col + 1];
1692
+ HighsInt new_num_nz = lp.a_matrix_.start_[lp.num_col_] + 1;
1693
+ lp.a_matrix_.index_.resize(new_num_nz);
1694
+ lp.a_matrix_.value_.resize(new_num_nz);
1695
+ for (HighsInt i = col + 1; i <= lp.num_col_; i++) lp.a_matrix_.start_[i]++;
1696
+ for (HighsInt el = new_num_nz - 1; el > change_el; el--) {
1697
+ lp.a_matrix_.index_[el] = lp.a_matrix_.index_[el - 1];
1698
+ lp.a_matrix_.value_[el] = lp.a_matrix_.value_[el - 1];
1699
+ }
1700
+ } else if (zero_new_value) {
1701
+ // Coefficient zeroes an existing nonzero, so shift all index and
1702
+ // value entries backward by 1 to eliminate it
1703
+ HighsInt new_num_nz = lp.a_matrix_.start_[lp.num_col_] - 1;
1704
+ for (HighsInt i = col + 1; i <= lp.num_col_; i++) lp.a_matrix_.start_[i]--;
1705
+ for (HighsInt el = change_el; el < new_num_nz; el++) {
1706
+ lp.a_matrix_.index_[el] = lp.a_matrix_.index_[el + 1];
1707
+ lp.a_matrix_.value_[el] = lp.a_matrix_.value_[el + 1];
1708
+ }
1709
+ return;
1710
+ }
1711
+ lp.a_matrix_.index_[change_el] = row;
1712
+ lp.a_matrix_.value_[change_el] = new_value;
1713
+ }
1714
+
1715
+ HighsStatus changeLpIntegrality(HighsLp& lp,
1716
+ const HighsIndexCollection& index_collection,
1717
+ const vector<HighsVarType>& new_integrality,
1718
+ const HighsOptions options) {
1719
+ HighsStatus return_status = HighsStatus::kOk;
1720
+ assert(ok(index_collection));
1721
+ HighsInt from_k;
1722
+ HighsInt to_k;
1723
+ limits(index_collection, from_k, to_k);
1724
+ if (from_k > to_k) return return_status;
1725
+
1726
+ const bool& interval = index_collection.is_interval_;
1727
+ const bool& mask = index_collection.is_mask_;
1728
+ const vector<HighsInt>& col_set = index_collection.set_;
1729
+ const vector<HighsInt>& col_mask = index_collection.mask_;
1730
+
1731
+ // Change the integrality to the user-supplied integrality, according to the
1732
+ // technique
1733
+ HighsInt lp_col;
1734
+ HighsInt usr_col = -1;
1735
+
1736
+ // If changing integrality for a problem without an integrality
1737
+ // vector (ie an LP), have to create it for the incumbent columns -
1738
+ // which are naturally continuous
1739
+ if (lp.integrality_.size() == 0)
1740
+ lp.integrality_.assign(lp.num_col_, HighsVarType::kContinuous);
1741
+
1742
+ assert(HighsInt(lp.integrality_.size()) == lp.num_col_);
1743
+ for (HighsInt k = from_k; k < to_k + 1; k++) {
1744
+ if (interval || mask) {
1745
+ lp_col = k;
1746
+ } else {
1747
+ lp_col = col_set[k];
1748
+ }
1749
+ HighsInt col = lp_col;
1750
+ if (interval) {
1751
+ usr_col++;
1752
+ } else {
1753
+ usr_col = k;
1754
+ }
1755
+ if (mask && !col_mask[col]) continue;
1756
+ lp.integrality_[col] = new_integrality[usr_col];
1757
+ }
1758
+ // If integrality_ contains only HighsVarType::kContinuous then
1759
+ // clear it
1760
+ if (!lp.isMip()) lp.integrality_.clear();
1761
+ return return_status;
1762
+ }
1763
+
1764
+ void changeLpCosts(HighsLp& lp, const HighsIndexCollection& index_collection,
1765
+ const vector<double>& new_col_cost,
1766
+ const double infinite_cost) {
1767
+ assert(ok(index_collection));
1768
+ HighsInt from_k;
1769
+ HighsInt to_k;
1770
+ limits(index_collection, from_k, to_k);
1771
+ if (from_k > to_k) return;
1772
+
1773
+ const bool& interval = index_collection.is_interval_;
1774
+ const bool& mask = index_collection.is_mask_;
1775
+ const vector<HighsInt>& col_set = index_collection.set_;
1776
+ const vector<HighsInt>& col_mask = index_collection.mask_;
1777
+
1778
+ // Change the costs to the user-supplied costs, according to the technique
1779
+ HighsInt lp_col;
1780
+ HighsInt usr_col = -1;
1781
+ for (HighsInt k = from_k; k < to_k + 1; k++) {
1782
+ if (interval || mask) {
1783
+ lp_col = k;
1784
+ } else {
1785
+ lp_col = col_set[k];
1786
+ }
1787
+ HighsInt col = lp_col;
1788
+ if (interval) {
1789
+ usr_col++;
1790
+ } else {
1791
+ usr_col = k;
1792
+ }
1793
+ if (mask && !col_mask[col]) continue;
1794
+ lp.col_cost_[col] = new_col_cost[usr_col];
1795
+ }
1796
+ // Check whether the LP still has an infinite cost
1797
+ if (lp.has_infinite_cost_)
1798
+ lp.has_infinite_cost_ = lp.hasInfiniteCost(infinite_cost);
1799
+ }
1800
+
1801
+ void changeLpColBounds(HighsLp& lp,
1802
+ const HighsIndexCollection& index_collection,
1803
+ const vector<double>& new_col_lower,
1804
+ const vector<double>& new_col_upper) {
1805
+ changeBounds(lp.col_lower_, lp.col_upper_, index_collection, new_col_lower,
1806
+ new_col_upper);
1807
+ }
1808
+
1809
+ void changeLpRowBounds(HighsLp& lp,
1810
+ const HighsIndexCollection& index_collection,
1811
+ const vector<double>& new_row_lower,
1812
+ const vector<double>& new_row_upper) {
1813
+ changeBounds(lp.row_lower_, lp.row_upper_, index_collection, new_row_lower,
1814
+ new_row_upper);
1815
+ }
1816
+
1817
+ void changeBounds(vector<double>& lower, vector<double>& upper,
1818
+ const HighsIndexCollection& index_collection,
1819
+ const vector<double>& new_lower,
1820
+ const vector<double>& new_upper) {
1821
+ assert(ok(index_collection));
1822
+ HighsInt from_k;
1823
+ HighsInt to_k;
1824
+ limits(index_collection, from_k, to_k);
1825
+ if (from_k > to_k) return;
1826
+
1827
+ const bool& interval = index_collection.is_interval_;
1828
+ const bool& mask = index_collection.is_mask_;
1829
+ const vector<HighsInt>& ix_set = index_collection.set_;
1830
+ const vector<HighsInt>& ix_mask = index_collection.mask_;
1831
+
1832
+ // Change the bounds to the user-supplied bounds, according to the technique
1833
+ HighsInt lp_ix;
1834
+ HighsInt usr_ix = -1;
1835
+ for (HighsInt k = from_k; k < to_k + 1; k++) {
1836
+ if (interval || mask) {
1837
+ lp_ix = k;
1838
+ } else {
1839
+ lp_ix = ix_set[k];
1840
+ }
1841
+ HighsInt ix = lp_ix;
1842
+ if (interval) {
1843
+ usr_ix++;
1844
+ } else {
1845
+ usr_ix = k;
1846
+ }
1847
+ if (mask && !ix_mask[ix]) continue;
1848
+ lower[ix] = new_lower[usr_ix];
1849
+ upper[ix] = new_upper[usr_ix];
1850
+ }
1851
+ }
1852
+
1853
+ HighsInt getNumInt(const HighsLp& lp) {
1854
+ HighsInt num_int = 0;
1855
+ if (lp.integrality_.size()) {
1856
+ for (HighsInt iCol = 0; iCol < lp.num_col_; iCol++)
1857
+ if (lp.integrality_[iCol] == HighsVarType::kInteger) num_int++;
1858
+ }
1859
+ return num_int;
1860
+ }
1861
+
1862
+ void getLpCosts(const HighsLp& lp, const HighsInt from_col,
1863
+ const HighsInt to_col, double* XcolCost) {
1864
+ assert(0 <= from_col && from_col < lp.num_col_);
1865
+ assert(0 <= to_col && to_col < lp.num_col_);
1866
+ if (from_col > to_col) return;
1867
+ for (HighsInt col = from_col; col < to_col + 1; col++)
1868
+ XcolCost[col - from_col] = lp.col_cost_[col];
1869
+ }
1870
+
1871
+ void getLpColBounds(const HighsLp& lp, const HighsInt from_col,
1872
+ const HighsInt to_col, double* XcolLower,
1873
+ double* XcolUpper) {
1874
+ assert(0 <= from_col && from_col < lp.num_col_);
1875
+ assert(0 <= to_col && to_col < lp.num_col_);
1876
+ if (from_col > to_col) return;
1877
+ for (HighsInt col = from_col; col < to_col + 1; col++) {
1878
+ if (XcolLower != nullptr) XcolLower[col - from_col] = lp.col_lower_[col];
1879
+ if (XcolUpper != nullptr) XcolUpper[col - from_col] = lp.col_upper_[col];
1880
+ }
1881
+ }
1882
+
1883
+ void getLpRowBounds(const HighsLp& lp, const HighsInt from_row,
1884
+ const HighsInt to_row, double* XrowLower,
1885
+ double* XrowUpper) {
1886
+ assert(0 <= from_row && from_row < lp.num_row_);
1887
+ assert(0 <= to_row && to_row < lp.num_row_);
1888
+ if (from_row > to_row) return;
1889
+ for (HighsInt row = from_row; row < to_row + 1; row++) {
1890
+ if (XrowLower != nullptr) XrowLower[row - from_row] = lp.row_lower_[row];
1891
+ if (XrowUpper != nullptr) XrowUpper[row - from_row] = lp.row_upper_[row];
1892
+ }
1893
+ }
1894
+
1895
+ // Get a single coefficient from the matrix
1896
+ void getLpMatrixCoefficient(const HighsLp& lp, const HighsInt Xrow,
1897
+ const HighsInt Xcol, double* val) {
1898
+ assert(0 <= Xrow && Xrow < lp.num_row_);
1899
+ assert(0 <= Xcol && Xcol < lp.num_col_);
1900
+
1901
+ HighsInt get_el = -1;
1902
+ for (HighsInt el = lp.a_matrix_.start_[Xcol];
1903
+ el < lp.a_matrix_.start_[Xcol + 1]; el++) {
1904
+ if (lp.a_matrix_.index_[el] == Xrow) {
1905
+ get_el = el;
1906
+ break;
1907
+ }
1908
+ }
1909
+ if (get_el < 0) {
1910
+ *val = 0;
1911
+ } else {
1912
+ *val = lp.a_matrix_.value_[get_el];
1913
+ }
1914
+ }
1915
+
1916
+ // Methods for reporting an LP, including its row and column data and matrix
1917
+ //
1918
+ // Report the whole LP
1919
+ void reportLp(const HighsLogOptions& log_options, const HighsLp& lp,
1920
+ const HighsLogType report_level) {
1921
+ reportLpBrief(log_options, lp);
1922
+ if ((HighsInt)report_level >= (HighsInt)HighsLogType::kDetailed) {
1923
+ reportLpColVectors(log_options, lp);
1924
+ reportLpRowVectors(log_options, lp);
1925
+ if ((HighsInt)report_level >= (HighsInt)HighsLogType::kVerbose)
1926
+ reportLpColMatrix(log_options, lp);
1927
+ }
1928
+ }
1929
+
1930
+ // Report the LP briefly
1931
+ void reportLpBrief(const HighsLogOptions& log_options, const HighsLp& lp) {
1932
+ reportLpDimensions(log_options, lp);
1933
+ reportLpObjSense(log_options, lp);
1934
+ }
1935
+
1936
+ // Report the LP dimensions
1937
+ void reportLpDimensions(const HighsLogOptions& log_options, const HighsLp& lp) {
1938
+ HighsInt lp_num_nz;
1939
+ if (lp.num_col_ == 0)
1940
+ lp_num_nz = 0;
1941
+ else
1942
+ lp_num_nz = lp.a_matrix_.start_[lp.num_col_];
1943
+ highsLogUser(log_options, HighsLogType::kInfo,
1944
+ "LP has %" HIGHSINT_FORMAT " row%s, %" HIGHSINT_FORMAT
1945
+ " column%s",
1946
+ lp.num_row_, lp.num_row_ == 1 ? "" : "s", lp.num_col_,
1947
+ lp.num_col_ == 1 ? "" : "s");
1948
+ HighsInt num_int = getNumInt(lp);
1949
+ if (num_int) {
1950
+ highsLogUser(log_options, HighsLogType::kInfo,
1951
+ ", %" HIGHSINT_FORMAT " nonzero%s and %" HIGHSINT_FORMAT
1952
+ " integer column%s\n",
1953
+ lp_num_nz, lp_num_nz == 1 ? "" : "s", num_int,
1954
+ num_int == 1 ? "" : "s");
1955
+ } else {
1956
+ highsLogUser(log_options, HighsLogType::kInfo,
1957
+ " and %" HIGHSINT_FORMAT " nonzero%s\n", lp_num_nz,
1958
+ lp_num_nz == 1 ? "" : "s");
1959
+ }
1960
+ }
1961
+
1962
+ // Report the LP objective sense
1963
+ void reportLpObjSense(const HighsLogOptions& log_options, const HighsLp& lp) {
1964
+ if (lp.sense_ == ObjSense::kMinimize)
1965
+ highsLogUser(log_options, HighsLogType::kInfo,
1966
+ "Objective sense is minimize\n");
1967
+ else if (lp.sense_ == ObjSense::kMaximize)
1968
+ highsLogUser(log_options, HighsLogType::kInfo,
1969
+ "Objective sense is maximize\n");
1970
+ else
1971
+ highsLogUser(log_options, HighsLogType::kInfo,
1972
+ "Objective sense is ill-defined as %" HIGHSINT_FORMAT "\n",
1973
+ lp.sense_);
1974
+ }
1975
+
1976
+ static std::string getBoundType(const double lower, const double upper) {
1977
+ std::string type;
1978
+ if (highs_isInfinity(-lower)) {
1979
+ if (highs_isInfinity(upper)) {
1980
+ type = "FR";
1981
+ } else {
1982
+ type = "UB";
1983
+ }
1984
+ } else {
1985
+ if (highs_isInfinity(upper)) {
1986
+ type = "LB";
1987
+ } else {
1988
+ if (lower < upper) {
1989
+ type = "BX";
1990
+ } else {
1991
+ type = "FX";
1992
+ }
1993
+ }
1994
+ }
1995
+ return type;
1996
+ }
1997
+
1998
+ // Report the vectors of LP column data
1999
+ void reportLpColVectors(const HighsLogOptions& log_options, const HighsLp& lp) {
2000
+ if (lp.num_col_ <= 0) return;
2001
+ std::string type;
2002
+ HighsInt count;
2003
+ bool have_integer_columns = (getNumInt(lp) != 0);
2004
+ bool have_col_names =
2005
+ lp.col_names_.size() == static_cast<size_t>(lp.num_col_);
2006
+
2007
+ highsLogUser(log_options, HighsLogType::kInfo,
2008
+ " Column Lower Upper Cost "
2009
+ "Type Count");
2010
+ if (have_integer_columns)
2011
+ highsLogUser(log_options, HighsLogType::kInfo, " Discrete");
2012
+ if (have_col_names) highsLogUser(log_options, HighsLogType::kInfo, " Name");
2013
+ highsLogUser(log_options, HighsLogType::kInfo, "\n");
2014
+
2015
+ for (HighsInt iCol = 0; iCol < lp.num_col_; iCol++) {
2016
+ type = getBoundType(lp.col_lower_[iCol], lp.col_upper_[iCol]);
2017
+ count = lp.a_matrix_.start_[iCol + 1] - lp.a_matrix_.start_[iCol];
2018
+ highsLogUser(log_options, HighsLogType::kInfo,
2019
+ "%8" HIGHSINT_FORMAT
2020
+ " %12g %12g %12g %2s %12" HIGHSINT_FORMAT "",
2021
+ iCol, lp.col_lower_[iCol], lp.col_upper_[iCol],
2022
+ lp.col_cost_[iCol], type.c_str(), count);
2023
+ if (have_integer_columns) {
2024
+ std::string integer_column = "";
2025
+ if (lp.integrality_[iCol] == HighsVarType::kInteger) {
2026
+ if (lp.col_lower_[iCol] == 0 && lp.col_upper_[iCol] == 1) {
2027
+ integer_column = "Binary";
2028
+ } else {
2029
+ integer_column = "Integer";
2030
+ }
2031
+ }
2032
+ highsLogUser(log_options, HighsLogType::kInfo, " %-8s",
2033
+ integer_column.c_str());
2034
+ }
2035
+ if (have_col_names)
2036
+ highsLogUser(log_options, HighsLogType::kInfo, " %-s",
2037
+ lp.col_names_[iCol].c_str());
2038
+ highsLogUser(log_options, HighsLogType::kInfo, "\n");
2039
+ }
2040
+ }
2041
+
2042
+ // Report the vectors of LP row data
2043
+ void reportLpRowVectors(const HighsLogOptions& log_options, const HighsLp& lp) {
2044
+ if (lp.num_row_ <= 0) return;
2045
+ std::string type;
2046
+ vector<HighsInt> count;
2047
+ bool have_row_names = (lp.row_names_.size() != 0);
2048
+
2049
+ count.resize(lp.num_row_, 0);
2050
+ if (lp.num_col_ > 0) {
2051
+ for (HighsInt el = 0; el < lp.a_matrix_.start_[lp.num_col_]; el++)
2052
+ count[lp.a_matrix_.index_[el]]++;
2053
+ }
2054
+
2055
+ highsLogUser(log_options, HighsLogType::kInfo,
2056
+ " Row Lower Upper Type Count");
2057
+ if (have_row_names) highsLogUser(log_options, HighsLogType::kInfo, " Name");
2058
+ highsLogUser(log_options, HighsLogType::kInfo, "\n");
2059
+
2060
+ for (HighsInt iRow = 0; iRow < lp.num_row_; iRow++) {
2061
+ type = getBoundType(lp.row_lower_[iRow], lp.row_upper_[iRow]);
2062
+ std::string name = "";
2063
+ highsLogUser(log_options, HighsLogType::kInfo,
2064
+ "%8" HIGHSINT_FORMAT
2065
+ " %12g %12g %2s %12" HIGHSINT_FORMAT "",
2066
+ iRow, lp.row_lower_[iRow], lp.row_upper_[iRow], type.c_str(),
2067
+ count[iRow]);
2068
+ if (have_row_names)
2069
+ highsLogUser(log_options, HighsLogType::kInfo, " %-s",
2070
+ lp.row_names_[iRow].c_str());
2071
+ highsLogUser(log_options, HighsLogType::kInfo, "\n");
2072
+ }
2073
+ }
2074
+
2075
+ // Report the LP column-wise matrix
2076
+ void reportLpColMatrix(const HighsLogOptions& log_options, const HighsLp& lp) {
2077
+ if (lp.num_col_ <= 0) return;
2078
+ if (lp.num_row_) {
2079
+ // With positive number of rows, can assume that there are index and value
2080
+ // vectors to pass
2081
+ reportMatrix(log_options, "Column", lp.num_col_,
2082
+ lp.a_matrix_.start_[lp.num_col_], lp.a_matrix_.start_.data(),
2083
+ lp.a_matrix_.index_.data(), lp.a_matrix_.value_.data());
2084
+ } else {
2085
+ // With no rows, can's assume that there are index and value vectors to pass
2086
+ reportMatrix(log_options, "Column", lp.num_col_,
2087
+ lp.a_matrix_.start_[lp.num_col_], lp.a_matrix_.start_.data(),
2088
+ NULL, NULL);
2089
+ }
2090
+ }
2091
+
2092
+ void reportMatrix(const HighsLogOptions& log_options,
2093
+ const std::string& message, const HighsInt num_col,
2094
+ const HighsInt num_nz, const HighsInt* start,
2095
+ const HighsInt* index, const double* value) {
2096
+ if (num_col <= 0) return;
2097
+ highsLogUser(log_options, HighsLogType::kInfo,
2098
+ "%-7s Index Value\n", message.c_str());
2099
+ for (HighsInt col = 0; col < num_col; col++) {
2100
+ highsLogUser(log_options, HighsLogType::kInfo,
2101
+ " %8" HIGHSINT_FORMAT " Start %10" HIGHSINT_FORMAT "\n",
2102
+ col, start[col]);
2103
+ HighsInt to_el = (col < num_col - 1 ? start[col + 1] : num_nz);
2104
+ for (HighsInt el = start[col]; el < to_el; el++)
2105
+ highsLogUser(log_options, HighsLogType::kInfo,
2106
+ " %8" HIGHSINT_FORMAT " %12g\n", index[el],
2107
+ value[el]);
2108
+ }
2109
+ highsLogUser(log_options, HighsLogType::kInfo,
2110
+ " Start %10" HIGHSINT_FORMAT "\n", num_nz);
2111
+ }
2112
+
2113
+ void analyseLp(const HighsLogOptions& log_options, const HighsLp& lp) {
2114
+ /*
2115
+ vector<double> min_colBound;
2116
+ vector<double> min_rowBound;
2117
+ vector<double> colRange;
2118
+ vector<double> rowRange;
2119
+ min_colBound.resize(lp.num_col_);
2120
+ min_rowBound.resize(lp.num_row_);
2121
+ colRange.resize(lp.num_col_);
2122
+ rowRange.resize(lp.num_row_);
2123
+ for (HighsInt col = 0; col < lp.num_col_; col++)
2124
+ min_colBound[col] = min(fabs(lp.col_lower_[col]), fabs(lp.col_upper_[col]));
2125
+ for (HighsInt row = 0; row < lp.num_row_; row++)
2126
+ min_rowBound[row] = min(fabs(lp.row_lower_[row]), fabs(lp.row_upper_[row]));
2127
+ for (HighsInt col = 0; col < lp.num_col_; col++)
2128
+ colRange[col] = lp.col_upper_[col] - lp.col_lower_[col];
2129
+ for (HighsInt row = 0; row < lp.num_row_; row++)
2130
+ rowRange[row] = lp.row_upper_[row] - lp.row_lower_[row];
2131
+ */
2132
+ std::string message;
2133
+ if (lp.is_scaled_) {
2134
+ message = "Scaled";
2135
+ } else {
2136
+ message = "Unscaled";
2137
+ }
2138
+ highsLogDev(log_options, HighsLogType::kInfo, "\n%s model data: Analysis\n",
2139
+ message.c_str());
2140
+ if (lp.is_scaled_) {
2141
+ const HighsScale& scale = lp.scale_;
2142
+ analyseVectorValues(&log_options, "Column scaling factors", lp.num_col_,
2143
+ scale.col, true, lp.model_name_);
2144
+ analyseVectorValues(&log_options, "Row scaling factors", lp.num_row_,
2145
+ scale.row, true, lp.model_name_);
2146
+ }
2147
+ analyseVectorValues(&log_options, "Column costs", lp.num_col_, lp.col_cost_,
2148
+ true, lp.model_name_);
2149
+ analyseVectorValues(&log_options, "Column lower bounds", lp.num_col_,
2150
+ lp.col_lower_, true, lp.model_name_);
2151
+ analyseVectorValues(&log_options, "Column upper bounds", lp.num_col_,
2152
+ lp.col_upper_, true, lp.model_name_);
2153
+ // analyseVectorValues(&log_options, "Column min abs bound", lp.num_col_,
2154
+ // min_colBound, true, lp.model_name_);
2155
+ // analyseVectorValues(&log_options, "Column range", lp.num_col_, colRange,
2156
+ // true,
2157
+ // lp.model_name_);
2158
+ analyseVectorValues(&log_options, "Row lower bounds", lp.num_row_,
2159
+ lp.row_lower_, true, lp.model_name_);
2160
+ analyseVectorValues(&log_options, "Row upper bounds", lp.num_row_,
2161
+ lp.row_upper_, true, lp.model_name_);
2162
+ // analyseVectorValues(&log_options, "Row min abs bound", lp.num_row_,
2163
+ // min_rowBound, true, lp.model_name_);
2164
+ // analyseVectorValues(&log_options, "Row range", lp.num_row_, rowRange,
2165
+ // true,
2166
+ // lp.model_name_);
2167
+ analyseVectorValues(&log_options, "Matrix sparsity",
2168
+ lp.a_matrix_.start_[lp.num_col_], lp.a_matrix_.value_,
2169
+ true, lp.model_name_);
2170
+ analyseMatrixSparsity(log_options, "Constraint matrix", lp.num_col_,
2171
+ lp.num_row_, lp.a_matrix_.start_, lp.a_matrix_.index_);
2172
+ analyseModelBounds(log_options, "Column", lp.num_col_, lp.col_lower_,
2173
+ lp.col_upper_);
2174
+ analyseModelBounds(log_options, "Row", lp.num_row_, lp.row_lower_,
2175
+ lp.row_upper_);
2176
+ }
2177
+
2178
+ HighsStatus readSolutionFile(const std::string& filename,
2179
+ const HighsOptions& options, HighsLp& lp,
2180
+ HighsBasis& basis, HighsSolution& solution,
2181
+ const HighsInt style) {
2182
+ HighsStatus return_status = HighsStatus::kOk;
2183
+ const HighsLogOptions& log_options = options.log_options;
2184
+ if (style != kSolutionStyleRaw && style != kSolutionStyleSparse) {
2185
+ highsLogUser(log_options, HighsLogType::kError,
2186
+ "readSolutionFile: Cannot read file of style %d\n",
2187
+ (int)style);
2188
+ return HighsStatus::kError;
2189
+ }
2190
+ std::ifstream in_file(filename);
2191
+ if (in_file.fail()) {
2192
+ highsLogUser(log_options, HighsLogType::kError,
2193
+ "readSolutionFile: Cannot open readable file \"%s\"\n",
2194
+ filename.c_str());
2195
+ return HighsStatus::kError;
2196
+ }
2197
+ std::string from_method = "readSolutionFile";
2198
+ std::string hash;
2199
+ std::string keyword;
2200
+ std::string value_string;
2201
+ std::string name;
2202
+ double value;
2203
+ HighsInt num_col = -1;
2204
+ HighsInt num_row = -1;
2205
+ const HighsInt lp_num_col = lp.num_col_;
2206
+ const HighsInt lp_num_row = lp.num_row_;
2207
+ // Define identifiers for reading in
2208
+ HighsSolution read_solution = solution;
2209
+ HighsBasis read_basis = basis;
2210
+ read_solution.clear();
2211
+ read_basis.clear();
2212
+ read_solution.col_value.resize(lp_num_col);
2213
+ read_solution.row_value.resize(lp_num_row);
2214
+ read_solution.col_dual.resize(lp_num_col);
2215
+ read_solution.row_dual.resize(lp_num_row);
2216
+ read_basis.col_status.resize(lp_num_col);
2217
+ read_basis.row_status.resize(lp_num_row);
2218
+ std::string section_name;
2219
+ if (!readSolutionFileIdIgnoreLineOk(section_name, in_file))
2220
+ return readSolutionFileErrorReturn(
2221
+ in_file); // Model (status) or =obj= (value)
2222
+ const bool miplib_sol = section_name == "=obj=";
2223
+ const bool have_col_names =
2224
+ lp.col_names_.size() == static_cast<size_t>(lp_num_col);
2225
+ const bool have_row_names =
2226
+ lp.row_names_.size() == static_cast<size_t>(lp_num_row);
2227
+ if (miplib_sol) {
2228
+ // A MIPLIB solution file has nonzero solution values for a subset
2229
+ // of the variables identified by name, so there must be column
2230
+ // names,
2231
+ if (!have_col_names) {
2232
+ highsLogUser(log_options, HighsLogType::kError,
2233
+ "readSolutionFile: Cannot read a MIPLIB solution file "
2234
+ "without column names in the model\n");
2235
+ return HighsStatus::kError;
2236
+ }
2237
+ }
2238
+ if (have_col_names) {
2239
+ // Ensure that the col name hash table has been formed
2240
+ if (!lp.col_hash_.name2index.size()) lp.col_hash_.form(lp.col_names_);
2241
+ }
2242
+ if (have_row_names) {
2243
+ // Ensure that the row name hash table has been formed
2244
+ if (!lp.row_hash_.name2index.size()) lp.row_hash_.form(lp.row_names_);
2245
+ }
2246
+ bool sparse = false;
2247
+ if (!miplib_sol) {
2248
+ if (!readSolutionFileIgnoreLineOk(in_file))
2249
+ return readSolutionFileErrorReturn(in_file); // Optimal
2250
+ if (!readSolutionFileIgnoreLineOk(in_file))
2251
+ return readSolutionFileErrorReturn(in_file); //
2252
+ if (!readSolutionFileIgnoreLineOk(in_file))
2253
+ return readSolutionFileErrorReturn(in_file); // # Primal solution values
2254
+ if (!readSolutionFileKeywordLineOk(keyword, in_file))
2255
+ return readSolutionFileErrorReturn(in_file);
2256
+ // Read in the primal solution values: return warning if there is none
2257
+ if (keyword == "None")
2258
+ return readSolutionFileReturn(HighsStatus::kWarning, solution, basis,
2259
+ read_solution, read_basis, in_file);
2260
+ // If there are primal solution values then keyword is the status
2261
+ // and the next line is objective
2262
+ if (!readSolutionFileIgnoreLineOk(in_file))
2263
+ return readSolutionFileErrorReturn(in_file); // EOL
2264
+ if (!readSolutionFileIgnoreLineOk(in_file))
2265
+ return readSolutionFileErrorReturn(in_file); // Objective
2266
+ // Next line should be "Columns" and correct number
2267
+ if (!readSolutionFileHashKeywordIntLineOk(hash, keyword, value_string,
2268
+ num_col, in_file)) {
2269
+ highsLogUser(log_options, HighsLogType::kError,
2270
+ "readSolutionFile: Error reading line \"%s %s %s\"\n",
2271
+ hash.c_str(), keyword.c_str(), value_string.c_str());
2272
+ return readSolutionFileErrorReturn(in_file);
2273
+ }
2274
+ assert(keyword == "Columns");
2275
+ // The default style parameter is kSolutionStyleRaw, and this still
2276
+ // allows sparse files to be read. Recognise the latter from num_col
2277
+ // <= 0. Doesn't matter if num_col = 0, since there's nothing to
2278
+ // read either way
2279
+ sparse = num_col <= 0;
2280
+ if (style == kSolutionStyleSparse) assert(sparse);
2281
+ if (sparse) {
2282
+ num_col = -num_col;
2283
+ assert(num_col <= lp_num_col);
2284
+ } else {
2285
+ if (num_col != lp_num_col) {
2286
+ highsLogUser(
2287
+ log_options, HighsLogType::kError,
2288
+ "readSolutionFile: Solution file is for %d columns, not %d\n",
2289
+ int(num_col), int(lp_num_col));
2290
+ return readSolutionFileErrorReturn(in_file);
2291
+ }
2292
+ }
2293
+ }
2294
+ bool is_col = true;
2295
+ HighsInt iCol;
2296
+ if (miplib_sol) {
2297
+ HighsInt num_value = 0;
2298
+ read_solution.col_value.assign(lp_num_col, 0);
2299
+ assert(is_col);
2300
+ for (;;) {
2301
+ // Only false return is for encountering EOF
2302
+ if (!readSolutionFileIdDoubleLineOk(name, value, in_file)) break;
2303
+ return_status =
2304
+ getIndexFromName(log_options, from_method, is_col, name,
2305
+ lp.col_hash_.name2index, iCol, lp.col_names_);
2306
+ if (return_status != HighsStatus::kOk) return return_status;
2307
+ read_solution.col_value[iCol] = value;
2308
+ num_value++;
2309
+ if (in_file.eof()) break;
2310
+ }
2311
+ } else if (sparse) {
2312
+ read_solution.col_value.assign(lp_num_col, 0);
2313
+ for (HighsInt iX = 0; iX < num_col; iX++) {
2314
+ if (!readSolutionFileIdDoubleIntLineOk(name, value, iCol, in_file))
2315
+ return readSolutionFileErrorReturn(in_file);
2316
+ if (have_col_names) {
2317
+ // Use the column name if possible
2318
+ return_status =
2319
+ getIndexFromName(log_options, from_method, is_col, name,
2320
+ lp.col_hash_.name2index, iCol, lp.col_names_);
2321
+ if (return_status != HighsStatus::kOk) return return_status;
2322
+ }
2323
+ read_solution.col_value[iCol] = value;
2324
+ }
2325
+ } else {
2326
+ assert(is_col);
2327
+ for (HighsInt iX = 0; iX < num_col; iX++) {
2328
+ if (!readSolutionFileIdDoubleLineOk(name, value, in_file))
2329
+ return readSolutionFileErrorReturn(in_file);
2330
+ if (have_col_names) {
2331
+ // Use the column name if possible
2332
+ return_status =
2333
+ getIndexFromName(log_options, from_method, is_col, name,
2334
+ lp.col_hash_.name2index, iCol, lp.col_names_);
2335
+ if (return_status != HighsStatus::kOk) return return_status;
2336
+ } else {
2337
+ // Have to assume column solution values are in the right order
2338
+ iCol = iX;
2339
+ }
2340
+ read_solution.col_value[iCol] = value;
2341
+ }
2342
+ }
2343
+ read_solution.value_valid = true;
2344
+ if (miplib_sol || sparse) {
2345
+ // MIPLIB and sparse format only have column values, so compute
2346
+ // the row values and return
2347
+ if (calculateRowValuesQuad(lp, read_solution.col_value,
2348
+ read_solution.row_value) != HighsStatus::kOk)
2349
+ return readSolutionFileErrorReturn(in_file);
2350
+ return readSolutionFileReturn(HighsStatus::kOk, solution, basis,
2351
+ read_solution, read_basis, in_file);
2352
+ }
2353
+ // Read in the row values: OK to have none, otherwise next line
2354
+ // should be "Rows" and correct number
2355
+ if (!readSolutionFileHashKeywordIntLineOk(hash, keyword, value_string,
2356
+ num_row, in_file)) {
2357
+ // Compute the row values since there are none to read
2358
+ if (calculateRowValuesQuad(lp, read_solution.col_value,
2359
+ read_solution.row_value) != HighsStatus::kOk)
2360
+ return readSolutionFileErrorReturn(in_file);
2361
+ return readSolutionFileReturn(HighsStatus::kOk, solution, basis,
2362
+ read_solution, read_basis, in_file);
2363
+ }
2364
+ assert(keyword == "Rows");
2365
+ // OK to read from a file with different number of rows, since the
2366
+ // primal solution is all that's important. For example, see #1284,
2367
+ // where the user is solving a sequence of MIPs with the same number
2368
+ // of variables, but increasing numbers of constraints, and wants to
2369
+ // used the solution from one MIP as the starting solution for the
2370
+ // next.
2371
+ HighsInt iRow;
2372
+ const bool num_row_ok = num_row == lp_num_row;
2373
+ assert(!have_row_names || lp.row_hash_.name2index.size());
2374
+ is_col = false;
2375
+ assert(!is_col);
2376
+ for (HighsInt iX = 0; iX < num_row; iX++) {
2377
+ if (!readSolutionFileIdDoubleLineOk(name, value, in_file))
2378
+ return readSolutionFileErrorReturn(in_file);
2379
+ if (num_row_ok) {
2380
+ if (have_row_names) {
2381
+ // Use the row name if possible
2382
+ return_status =
2383
+ getIndexFromName(log_options, from_method, is_col, name,
2384
+ lp.row_hash_.name2index, iRow, lp.row_names_);
2385
+ if (return_status != HighsStatus::kOk) return return_status;
2386
+ } else {
2387
+ // Have to assume row solution values are in the right order
2388
+ iRow = iX;
2389
+ }
2390
+ read_solution.row_value[iRow] = value;
2391
+ }
2392
+ }
2393
+ if (!num_row_ok) {
2394
+ highsLogUser(log_options, HighsLogType::kWarning,
2395
+ "readSolutionFile: Solution file is for %d rows, not %d: row "
2396
+ "values ignored\n",
2397
+ int(num_row), int(lp_num_row));
2398
+ // Calculate the row values
2399
+ if (calculateRowValuesQuad(lp, read_solution.col_value,
2400
+ read_solution.row_value) != HighsStatus::kOk)
2401
+ return readSolutionFileErrorReturn(in_file);
2402
+ }
2403
+ // OK to have no EOL
2404
+ if (!readSolutionFileIgnoreLineOk(in_file))
2405
+ return readSolutionFileReturn(HighsStatus::kOk, solution, basis,
2406
+ read_solution, read_basis,
2407
+ in_file); // EOL
2408
+ // OK to have no blank line
2409
+ if (!readSolutionFileIgnoreLineOk(in_file))
2410
+ return readSolutionFileReturn(HighsStatus::kOk, solution, basis,
2411
+ read_solution, read_basis,
2412
+ in_file); //
2413
+ // OK to have no reference to dual solution values
2414
+ if (!readSolutionFileIgnoreLineOk(in_file))
2415
+ return readSolutionFileReturn(HighsStatus::kOk, solution, basis,
2416
+ read_solution, read_basis,
2417
+ in_file); // # Dual solution values
2418
+ // If there's a reference to dual solution values, there's a keyword
2419
+ // to indicate their status
2420
+ if (!readSolutionFileKeywordLineOk(keyword, in_file))
2421
+ return readSolutionFileErrorReturn(in_file);
2422
+ if (keyword != "None") {
2423
+ if (!readSolutionFileIgnoreLineOk(in_file))
2424
+ return readSolutionFileErrorReturn(in_file); // EOL
2425
+ // Next line should be "Columns" and correct number
2426
+ if (!readSolutionFileHashKeywordIntLineOk(hash, keyword, value_string,
2427
+ num_col, in_file)) {
2428
+ highsLogUser(log_options, HighsLogType::kError,
2429
+ "readSolutionFile: Error reading line \"%s %s %s\"\n",
2430
+ hash.c_str(), keyword.c_str(), value_string.c_str());
2431
+ return readSolutionFileReturn(HighsStatus::kOk, solution, basis,
2432
+ read_solution, read_basis, in_file);
2433
+ }
2434
+ assert(keyword == "Columns");
2435
+ double dual;
2436
+ is_col = true;
2437
+ assert(is_col);
2438
+ for (HighsInt iX = 0; iX < num_col; iX++) {
2439
+ if (!readSolutionFileIdDoubleLineOk(name, dual, in_file))
2440
+ return readSolutionFileErrorReturn(in_file);
2441
+ if (have_col_names) {
2442
+ // Use the column name if possible
2443
+ return_status =
2444
+ getIndexFromName(log_options, from_method, is_col, name,
2445
+ lp.col_hash_.name2index, iCol, lp.col_names_);
2446
+ if (return_status != HighsStatus::kOk) return return_status;
2447
+ } else {
2448
+ // Have to assume column dual values are in the right order
2449
+ iCol = iX;
2450
+ }
2451
+ read_solution.col_dual[iCol] = dual;
2452
+ }
2453
+ // Read in the col dual values: next line should be "Rows" and correct
2454
+ // number
2455
+ if (!readSolutionFileHashKeywordIntLineOk(hash, keyword, value_string,
2456
+ num_col, in_file)) {
2457
+ highsLogUser(log_options, HighsLogType::kError,
2458
+ "readSolutionFile: Error reading line \"%s %s %s\"\n",
2459
+ hash.c_str(), keyword.c_str(), value_string.c_str());
2460
+ return readSolutionFileReturn(HighsStatus::kOk, solution, basis,
2461
+ read_solution, read_basis, in_file);
2462
+ }
2463
+ assert(keyword == "Rows");
2464
+ is_col = false;
2465
+ assert(!is_col);
2466
+ for (HighsInt iX = 0; iX < num_row; iX++) {
2467
+ if (!readSolutionFileIdDoubleLineOk(name, dual, in_file))
2468
+ return readSolutionFileErrorReturn(in_file);
2469
+ if (have_row_names) {
2470
+ // Use the row name if possible
2471
+ return_status =
2472
+ getIndexFromName(log_options, from_method, is_col, name,
2473
+ lp.row_hash_.name2index, iRow, lp.row_names_);
2474
+ if (return_status != HighsStatus::kOk) return return_status;
2475
+ } else {
2476
+ // Have to assume row dual values are in the right order
2477
+ iRow = iX;
2478
+ }
2479
+ read_solution.row_dual[iRow] = dual;
2480
+ }
2481
+ }
2482
+ // OK to have no EOL
2483
+ if (!readSolutionFileIgnoreLineOk(in_file))
2484
+ return readSolutionFileReturn(HighsStatus::kOk, solution, basis,
2485
+ read_solution, read_basis,
2486
+ in_file); // EOL
2487
+ // OK to have no blank line
2488
+ if (!readSolutionFileIgnoreLineOk(in_file))
2489
+ return readSolutionFileReturn(HighsStatus::kOk, solution, basis,
2490
+ read_solution, read_basis,
2491
+ in_file); //
2492
+ // OK to have no reference to basis
2493
+ if (!readSolutionFileIgnoreLineOk(in_file))
2494
+ return readSolutionFileReturn(HighsStatus::kOk, solution, basis,
2495
+ read_solution, read_basis,
2496
+ in_file); // # Basis
2497
+ HighsStatus basis_read_status =
2498
+ readBasisStream(log_options, lp, read_basis, in_file);
2499
+ // Return with basis read status
2500
+ return readSolutionFileReturn(basis_read_status, solution, basis,
2501
+ read_solution, read_basis, in_file);
2502
+ }
2503
+
2504
+ HighsStatus readSolutionFileErrorReturn(std::ifstream& in_file) {
2505
+ in_file.close();
2506
+ return HighsStatus::kError;
2507
+ }
2508
+
2509
+ HighsStatus readSolutionFileReturn(const HighsStatus status,
2510
+ HighsSolution& solution, HighsBasis& basis,
2511
+ const HighsSolution& read_solution,
2512
+ const HighsBasis& read_basis,
2513
+ std::ifstream& in_file) {
2514
+ in_file.close();
2515
+ if (status != HighsStatus::kOk) {
2516
+ return status;
2517
+ }
2518
+ solution = read_solution;
2519
+ basis = read_basis;
2520
+ return HighsStatus::kOk;
2521
+ }
2522
+
2523
+ bool readSolutionFileIgnoreLineOk(std::ifstream& in_file) {
2524
+ if (in_file.eof()) return false;
2525
+ in_file.ignore(kMaxLineLength, '\n');
2526
+ return true;
2527
+ }
2528
+
2529
+ bool readSolutionFileKeywordLineOk(std::string& keyword,
2530
+ std::ifstream& in_file) {
2531
+ if (in_file.eof()) return false;
2532
+ in_file >> keyword;
2533
+ return true;
2534
+ }
2535
+
2536
+ bool readSolutionFileHashKeywordIntLineOk(std::string& hash,
2537
+ std::string& keyword,
2538
+ std::string& value_string,
2539
+ HighsInt& value,
2540
+ std::ifstream& in_file) {
2541
+ hash = "";
2542
+ keyword = "";
2543
+ value_string = "";
2544
+ // Read the hash symbol
2545
+ if (in_file.eof()) return false;
2546
+ in_file >> hash; // #
2547
+ if (hash != "#") return false;
2548
+
2549
+ // Read the keyword
2550
+ if (in_file.eof()) return false;
2551
+ in_file >> keyword; // keyword
2552
+
2553
+ // Read the value
2554
+ if (in_file.eof()) return false;
2555
+ // Read as a string, and then check it only contains digits
2556
+ in_file >> value_string;
2557
+ if (value_string[std::strspn(value_string.c_str(), "-0123456789")])
2558
+ return false;
2559
+ value = std::stoi(value_string); // integer value
2560
+ return true;
2561
+ }
2562
+
2563
+ bool readSolutionFileIdIgnoreLineOk(std::string& id, std::ifstream& in_file) {
2564
+ if (in_file.eof()) return false;
2565
+ in_file >> id; // Id
2566
+ in_file.ignore(kMaxLineLength, '\n');
2567
+ return true;
2568
+ }
2569
+
2570
+ bool readSolutionFileIdDoubleLineOk(std::string& id, double& value,
2571
+ std::ifstream& in_file) {
2572
+ if (in_file.eof()) return false;
2573
+ in_file >> id; // Id
2574
+ if (in_file.eof()) return false;
2575
+ in_file >> value; // double value
2576
+ return true;
2577
+ }
2578
+
2579
+ bool readSolutionFileIdDoubleIntLineOk(std::string& id, double& value,
2580
+ HighsInt& index,
2581
+ std::ifstream& in_file) {
2582
+ if (in_file.eof()) return false;
2583
+ in_file >> id; // Id
2584
+ if (in_file.eof()) return false;
2585
+ in_file >> value; // double value
2586
+ if (in_file.eof()) return false;
2587
+ in_file >> index; // double value
2588
+ return true;
2589
+ }
2590
+
2591
+ void assessColPrimalSolution(const HighsOptions& options, const double primal,
2592
+ const double lower, const double upper,
2593
+ const HighsVarType type, double& col_infeasibility,
2594
+ double& integer_infeasibility) {
2595
+ // @primal_infeasibility calculation
2596
+ col_infeasibility = 0;
2597
+ if (primal < lower - options.primal_feasibility_tolerance) {
2598
+ col_infeasibility = lower - primal;
2599
+ } else if (primal > upper + options.primal_feasibility_tolerance) {
2600
+ col_infeasibility = primal - upper;
2601
+ }
2602
+ integer_infeasibility = 0;
2603
+ if (type == HighsVarType::kInteger || type == HighsVarType::kSemiInteger) {
2604
+ integer_infeasibility = fractionality(primal);
2605
+ }
2606
+ if (col_infeasibility > 0 && (type == HighsVarType::kSemiContinuous ||
2607
+ type == HighsVarType::kSemiInteger)) {
2608
+ // Semi-variables at zero will have positive col
2609
+ // infeasibility, so possibly zero this
2610
+ if (std::fabs(primal) <= options.mip_feasibility_tolerance)
2611
+ col_infeasibility = 0;
2612
+ // If there is (still) column infeasibility due to value being
2613
+ // off zero or below lower bound, then this counts as an integer
2614
+ // infeasibility
2615
+ if (col_infeasibility && primal < upper)
2616
+ integer_infeasibility =
2617
+ std::max(col_infeasibility, integer_infeasibility);
2618
+ }
2619
+ }
2620
+
2621
+ // Determine validity, primal feasibility and (when relevant) integer
2622
+ // feasibility of a solution
2623
+ HighsStatus assessLpPrimalSolution(const std::string& message,
2624
+ const HighsOptions& options,
2625
+ const HighsLp& lp,
2626
+ const HighsSolution& solution, bool& valid,
2627
+ bool& integral, bool& feasible) {
2628
+ valid = false;
2629
+ integral = false;
2630
+ feasible = false;
2631
+ HighsInt num_col_infeasibilities = 0;
2632
+ double max_col_infeasibility = 0;
2633
+ double sum_col_infeasibilities = 0;
2634
+ HighsInt num_integer_infeasibilities = 0;
2635
+ double max_integer_infeasibility = 0;
2636
+ double sum_integer_infeasibilities = 0;
2637
+ HighsInt num_row_infeasibilities = 0;
2638
+ double max_row_infeasibility = 0;
2639
+ double sum_row_infeasibilities = 0;
2640
+ HighsInt num_row_residuals = 0;
2641
+ double max_row_residual = 0;
2642
+ double sum_row_residuals = 0;
2643
+ const double kRowResidualTolerance =
2644
+ options.primal_feasibility_tolerance; // 1e-12;
2645
+ const double kPrimalFeasibilityTolerance =
2646
+ lp.isMip() ? options.mip_feasibility_tolerance
2647
+ : options.primal_feasibility_tolerance;
2648
+ highsLogUser(options.log_options, HighsLogType::kInfo,
2649
+ "%sAssessing feasibility of %s tolerance of %11.4g\n",
2650
+ message.c_str(),
2651
+ lp.isMip() ? "MIP using primal feasibility and integrality"
2652
+ : "LP using primal feasibility",
2653
+ kPrimalFeasibilityTolerance);
2654
+ vector<double> row_value;
2655
+ row_value.assign(lp.num_row_, 0);
2656
+ const bool have_integrality = (lp.integrality_.size() != 0);
2657
+ if (!solution.value_valid) return HighsStatus::kError;
2658
+ const bool have_col_names =
2659
+ lp.col_names_.size() == static_cast<size_t>(lp.num_col_);
2660
+ for (HighsInt iCol = 0; iCol < lp.num_col_; iCol++) {
2661
+ const std::string name_string =
2662
+ have_col_names ? (" (" + lp.col_names_[iCol] + ")") : "";
2663
+ const double primal = solution.col_value[iCol];
2664
+ const double lower = lp.col_lower_[iCol];
2665
+ const double upper = lp.col_upper_[iCol];
2666
+ const HighsVarType type =
2667
+ have_integrality ? lp.integrality_[iCol] : HighsVarType::kContinuous;
2668
+
2669
+ double col_infeasibility = 0;
2670
+ double integer_infeasibility = 0;
2671
+
2672
+ assessColPrimalSolution(options, primal, lower, upper, type,
2673
+ col_infeasibility, integer_infeasibility);
2674
+ if (col_infeasibility > 0) {
2675
+ if (col_infeasibility > kPrimalFeasibilityTolerance) {
2676
+ if (col_infeasibility > 2 * max_col_infeasibility)
2677
+ highsLogUser(options.log_options, HighsLogType::kWarning,
2678
+ "Col %6d%s has infeasibility of %11.4g from "
2679
+ "[lower, value, upper] = [%15.8g; %15.8g; %15.8g]\n",
2680
+ int(iCol), name_string.c_str(), col_infeasibility, lower,
2681
+ primal, upper);
2682
+ num_col_infeasibilities++;
2683
+ }
2684
+ max_col_infeasibility =
2685
+ std::max(col_infeasibility, max_col_infeasibility);
2686
+ sum_col_infeasibilities += col_infeasibility;
2687
+ }
2688
+ if (integer_infeasibility > 0) {
2689
+ if (integer_infeasibility > options.mip_feasibility_tolerance) {
2690
+ if (integer_infeasibility > 2 * max_integer_infeasibility)
2691
+ highsLogUser(options.log_options, HighsLogType::kWarning,
2692
+ "Col %6d%s has integer infeasibility of %11.4g\n",
2693
+ (int)iCol, name_string.c_str(), integer_infeasibility);
2694
+ num_integer_infeasibilities++;
2695
+ }
2696
+ max_integer_infeasibility =
2697
+ std::max(integer_infeasibility, max_integer_infeasibility);
2698
+ sum_integer_infeasibilities += integer_infeasibility;
2699
+ }
2700
+ }
2701
+ HighsStatus return_status =
2702
+ calculateRowValuesQuad(lp, solution.col_value, row_value);
2703
+ if (return_status != HighsStatus::kOk) return return_status;
2704
+ const bool have_row_names =
2705
+ lp.row_names_.size() >= static_cast<size_t>(lp.num_row_);
2706
+ for (HighsInt iRow = 0; iRow < lp.num_row_; iRow++) {
2707
+ const double primal = solution.row_value[iRow];
2708
+ const double lower = lp.row_lower_[iRow];
2709
+ const double upper = lp.row_upper_[iRow];
2710
+ const std::string name_string =
2711
+ have_row_names ? (" (" + lp.row_names_[iRow] + ")") : "";
2712
+ // @primal_infeasibility calculation
2713
+ double row_infeasibility = 0;
2714
+ if (primal < lower - kPrimalFeasibilityTolerance) {
2715
+ row_infeasibility = lower - primal;
2716
+ } else if (primal > upper + kPrimalFeasibilityTolerance) {
2717
+ row_infeasibility = primal - upper;
2718
+ }
2719
+ if (row_infeasibility > 0) {
2720
+ if (row_infeasibility > kPrimalFeasibilityTolerance) {
2721
+ if (row_infeasibility > 2 * max_row_infeasibility)
2722
+ highsLogUser(options.log_options, HighsLogType::kWarning,
2723
+ "Row %6d%s has infeasibility of %11.4g from "
2724
+ "[lower, value, upper] = [%15.8g; %15.8g; %15.8g]\n",
2725
+ (int)iRow, name_string.c_str(), row_infeasibility, lower,
2726
+ primal, upper);
2727
+ num_row_infeasibilities++;
2728
+ }
2729
+ max_row_infeasibility =
2730
+ std::max(row_infeasibility, max_row_infeasibility);
2731
+ sum_row_infeasibilities += row_infeasibility;
2732
+ }
2733
+ double row_residual = fabs(primal - row_value[iRow]);
2734
+ if (row_residual > kRowResidualTolerance) {
2735
+ if (row_residual > 2 * max_row_residual) {
2736
+ highsLogUser(options.log_options, HighsLogType::kWarning,
2737
+ "Row %6d%s has residual of %11.4g\n",
2738
+ (int)iRow, name_string.c_str(), row_residual);
2739
+ }
2740
+ num_row_residuals++;
2741
+ }
2742
+ max_row_residual = std::max(row_residual, max_row_residual);
2743
+ sum_row_residuals += row_residual;
2744
+ }
2745
+ highsLogUser(options.log_options, HighsLogType::kInfo,
2746
+ "Solution has num max sum\n");
2747
+ highsLogUser(options.log_options, HighsLogType::kInfo,
2748
+ "Col infeasibilities %6d %11.4g %11.4g\n",
2749
+ (int)num_col_infeasibilities, max_col_infeasibility,
2750
+ sum_col_infeasibilities);
2751
+ if (lp.isMip())
2752
+ highsLogUser(options.log_options, HighsLogType::kInfo,
2753
+ "Integer infeasibilities %6d %11.4g %11.4g\n",
2754
+ (int)num_integer_infeasibilities, max_integer_infeasibility,
2755
+ sum_integer_infeasibilities);
2756
+ highsLogUser(options.log_options, HighsLogType::kInfo,
2757
+ "Row infeasibilities %6d %11.4g %11.4g\n",
2758
+ (int)num_row_infeasibilities, max_row_infeasibility,
2759
+ sum_row_infeasibilities);
2760
+ highsLogUser(options.log_options, HighsLogType::kInfo,
2761
+ "Row residuals %6d %11.4g %11.4g\n",
2762
+ (int)num_row_residuals, max_row_residual, sum_row_residuals);
2763
+ valid = num_row_residuals == 0;
2764
+ integral = valid && num_integer_infeasibilities == 0;
2765
+ feasible = valid && num_col_infeasibilities == 0 &&
2766
+ num_integer_infeasibilities == 0 && num_row_infeasibilities == 0;
2767
+ if (!(integral && feasible)) return HighsStatus::kWarning;
2768
+ return HighsStatus::kOk;
2769
+ }
2770
+
2771
+ void writeBasisFile(FILE*& file, const HighsOptions& options, const HighsLp& lp,
2772
+ const HighsBasis& basis) {
2773
+ const HighsLogOptions& log_options = options.log_options;
2774
+ std::stringstream ss;
2775
+ // Basis version line
2776
+ ss.str(std::string());
2777
+ ss << highsFormatToString("HiGHS_basis_file %s\n", kHighsBasisFileV2.c_str());
2778
+ highsFprintfString(file, log_options, ss.str());
2779
+ // Basis validity line
2780
+ ss.str(std::string());
2781
+ if (basis.valid == false) {
2782
+ ss << highsFormatToString("None\n");
2783
+ highsFprintfString(file, log_options, ss.str());
2784
+ return;
2785
+ }
2786
+ assert(basis.col_status.size() == static_cast<size_t>(lp.num_col_));
2787
+ assert(basis.row_status.size() == static_cast<size_t>(lp.num_row_));
2788
+ assert(lp.col_names_.size() == static_cast<size_t>(lp.num_col_));
2789
+ assert(lp.row_names_.size() == static_cast<size_t>(lp.num_row_));
2790
+ ss << highsFormatToString("Valid\n");
2791
+ highsFprintfString(file, log_options, ss.str());
2792
+ // Column count line
2793
+ ss.str(std::string());
2794
+ ss << highsFormatToString("# Columns %d\n", int(lp.num_col_));
2795
+ highsFprintfString(file, log_options, ss.str());
2796
+ for (HighsInt iCol = 0; iCol < lp.num_col_; iCol++) {
2797
+ const std::string& name = lp.col_names_[iCol];
2798
+ assert(name.length() != 0);
2799
+ ss.str(std::string());
2800
+ ss << highsFormatToString("%s %d\n", name.c_str(),
2801
+ int(basis.col_status[iCol]));
2802
+ highsFprintfString(file, log_options, ss.str());
2803
+ }
2804
+ // Row count line
2805
+ ss.str(std::string());
2806
+ ss << highsFormatToString("# Rows %d\n", int(lp.num_row_));
2807
+ highsFprintfString(file, log_options, ss.str());
2808
+ for (HighsInt iRow = 0; iRow < lp.num_row_; iRow++) {
2809
+ const std::string& name = lp.row_names_[iRow];
2810
+ assert(name.length() != 0);
2811
+ ss.str(std::string());
2812
+ ss << highsFormatToString("%s %d\n", name.c_str(),
2813
+ int(basis.row_status[iRow]));
2814
+ highsFprintfString(file, log_options, ss.str());
2815
+ }
2816
+ }
2817
+
2818
+ HighsStatus getIndexFromName(
2819
+ const HighsLogOptions& log_options, std::string& from_method,
2820
+ const bool is_column, const std::string& name,
2821
+ const std::unordered_map<std::string, int>& name2index, HighsInt& index,
2822
+ const std::vector<std::string>& names) {
2823
+ assert(name2index.size());
2824
+ auto search = name2index.find(name);
2825
+ if (search == name2index.end()) {
2826
+ highsLogUser(log_options, HighsLogType::kError,
2827
+ "%s: %s name %s is not found\n", from_method.c_str(),
2828
+ is_column ? "column" : "row", name.c_str());
2829
+ return HighsStatus::kError;
2830
+ }
2831
+ if (search->second == kHashIsDuplicate) {
2832
+ highsLogUser(log_options, HighsLogType::kError,
2833
+ "%s: %s name %s is duplicated\n", from_method.c_str(),
2834
+ is_column ? "column" : "row", name.c_str());
2835
+ return HighsStatus::kError;
2836
+ }
2837
+ index = search->second;
2838
+ assert(names[index] == name);
2839
+ return HighsStatus::kOk;
2840
+ }
2841
+
2842
+ HighsStatus readBasisFile(const HighsLogOptions& log_options, HighsLp& lp,
2843
+ HighsBasis& basis, const std::string& filename) {
2844
+ // Opens a basis file as an ifstream
2845
+ HighsStatus return_status = HighsStatus::kOk;
2846
+ std::ifstream in_file;
2847
+ in_file.open(filename.c_str(), std::ios::in);
2848
+ if (in_file.is_open()) {
2849
+ return_status = readBasisStream(log_options, lp, basis, in_file);
2850
+ in_file.close();
2851
+ } else {
2852
+ highsLogUser(log_options, HighsLogType::kError,
2853
+ "readBasisFile: Cannot open readable file \"%s\"\n",
2854
+ filename.c_str());
2855
+ return_status = HighsStatus::kError;
2856
+ }
2857
+ return return_status;
2858
+ }
2859
+
2860
+ HighsStatus readBasisStream(const HighsLogOptions& log_options, HighsLp& lp,
2861
+ HighsBasis& basis, std::ifstream& in_file) {
2862
+ // Reads a basis as an ifstream, returning an error if what's read is
2863
+ // inconsistent with the sizes of the HighsBasis passed in
2864
+ HighsStatus return_status = HighsStatus::kOk;
2865
+ HighsStatus call_status = HighsStatus::kOk;
2866
+ std::string from_method = "readBasisStream";
2867
+ std::string string_highs, string_version;
2868
+ in_file >> string_highs >> string_version;
2869
+ const bool v1 = string_version == kHighsBasisFileV1;
2870
+ const bool v2 = string_version == kHighsBasisFileV2;
2871
+ const bool have_col_names =
2872
+ lp.col_names_.size() == static_cast<size_t>(lp.num_col_);
2873
+ const bool have_row_names =
2874
+ lp.row_names_.size() == static_cast<size_t>(lp.num_row_);
2875
+ if (have_col_names) {
2876
+ // Ensure that the col name hash table has been formed
2877
+ if (!lp.col_hash_.name2index.size()) lp.col_hash_.form(lp.col_names_);
2878
+ }
2879
+ if (have_row_names) {
2880
+ // Ensure that the row name hash table has been formed
2881
+ if (!lp.row_hash_.name2index.size()) lp.row_hash_.form(lp.row_names_);
2882
+ }
2883
+ if (v1 || v2) {
2884
+ if (v1) {
2885
+ // Ability to read v1 basis files is deprecated
2886
+ highsLogUser(log_options, HighsLogType::kWarning,
2887
+ "readBasisFile: Basis file format %s is deprecated\n",
2888
+ kHighsBasisFileV1.c_str());
2889
+ return_status = HighsStatus::kWarning;
2890
+ }
2891
+ std::string keyword;
2892
+ in_file >> keyword;
2893
+ if (keyword == "None") {
2894
+ basis.valid = false;
2895
+ return return_status;
2896
+ }
2897
+ const HighsInt basis_num_col = (HighsInt)basis.col_status.size();
2898
+ const HighsInt basis_num_row = (HighsInt)basis.row_status.size();
2899
+ HighsInt int_status;
2900
+ std::string name;
2901
+ assert(keyword == "Valid");
2902
+ HighsInt num_col, num_row;
2903
+ // Read in the columns section
2904
+ in_file >> keyword >> keyword;
2905
+ assert(keyword == "Columns");
2906
+ in_file >> num_col;
2907
+ if (num_col != basis_num_col) {
2908
+ highsLogUser(log_options, HighsLogType::kError,
2909
+ "readBasisFile: Basis file is for %" HIGHSINT_FORMAT
2910
+ " columns, not %" HIGHSINT_FORMAT "\n",
2911
+ num_col, basis_num_col);
2912
+ return HighsStatus::kError;
2913
+ }
2914
+ bool is_column = true;
2915
+ if (v1) {
2916
+ for (HighsInt iCol = 0; iCol < num_col; iCol++) {
2917
+ in_file >> int_status;
2918
+ basis.col_status[iCol] = (HighsBasisStatus)int_status;
2919
+ }
2920
+ } else {
2921
+ HighsInt iCol;
2922
+ for (HighsInt iX = 0; iX < num_col; iX++) {
2923
+ in_file >> name >> int_status;
2924
+ if (have_col_names) {
2925
+ // Use the column name if possible
2926
+ call_status =
2927
+ getIndexFromName(log_options, from_method, is_column, name,
2928
+ lp.col_hash_.name2index, iCol, lp.col_names_);
2929
+ if (call_status != HighsStatus::kOk) return call_status;
2930
+ } else {
2931
+ // Have to assume column basis status are in the right order
2932
+ iCol = iX;
2933
+ }
2934
+ basis.col_status[iCol] = HighsBasisStatus(int_status);
2935
+ }
2936
+ }
2937
+ // Read in the rows section
2938
+ in_file >> keyword >> keyword;
2939
+ assert(keyword == "Rows");
2940
+ in_file >> num_row;
2941
+ if (num_row != basis_num_row) {
2942
+ highsLogUser(log_options, HighsLogType::kError,
2943
+ "readBasisFile: Basis file is for %" HIGHSINT_FORMAT
2944
+ " rows, not %" HIGHSINT_FORMAT "\n",
2945
+ num_row, basis_num_row);
2946
+ return HighsStatus::kError;
2947
+ }
2948
+ is_column = false;
2949
+ if (v1) {
2950
+ for (HighsInt iRow = 0; iRow < num_row; iRow++) {
2951
+ in_file >> int_status;
2952
+ basis.row_status[iRow] = (HighsBasisStatus)int_status;
2953
+ }
2954
+ } else {
2955
+ HighsInt iRow;
2956
+ for (HighsInt iX = 0; iX < num_row; iX++) {
2957
+ in_file >> name >> int_status;
2958
+ if (have_row_names) {
2959
+ // Use the row name if possible
2960
+ call_status =
2961
+ getIndexFromName(log_options, from_method, is_column, name,
2962
+ lp.row_hash_.name2index, iRow, lp.row_names_);
2963
+ if (call_status != HighsStatus::kOk) return call_status;
2964
+ } else {
2965
+ // Have to assume row solution values are in the right order
2966
+ iRow = iX;
2967
+ }
2968
+ basis.row_status[iRow] = HighsBasisStatus(int_status);
2969
+ }
2970
+ }
2971
+ } else {
2972
+ highsLogUser(log_options, HighsLogType::kError,
2973
+ "readBasisFile: Cannot read basis file for HiGHS %s\n",
2974
+ string_version.c_str());
2975
+ return_status = HighsStatus::kError;
2976
+ }
2977
+ return return_status;
2978
+ }
2979
+
2980
+ HighsStatus calculateColDualsQuad(const HighsLp& lp, HighsSolution& solution) {
2981
+ const bool correct_size = int(solution.row_dual.size()) == lp.num_row_;
2982
+ const bool is_colwise = lp.a_matrix_.isColwise();
2983
+ const bool data_error = !correct_size || !is_colwise;
2984
+ assert(!data_error);
2985
+ if (data_error) return HighsStatus::kError;
2986
+
2987
+ std::vector<HighsCDouble> col_dual_quad;
2988
+ col_dual_quad.assign(lp.num_col_, HighsCDouble{0.0});
2989
+
2990
+ for (HighsInt col = 0; col < lp.num_col_; col++) {
2991
+ for (HighsInt i = lp.a_matrix_.start_[col];
2992
+ i < lp.a_matrix_.start_[col + 1]; i++) {
2993
+ const HighsInt row = lp.a_matrix_.index_[i];
2994
+ assert(row >= 0);
2995
+ assert(row < lp.num_row_);
2996
+ col_dual_quad[col] += solution.row_dual[row] * lp.a_matrix_.value_[i];
2997
+ }
2998
+ col_dual_quad[col] += lp.col_cost_[col];
2999
+ }
3000
+
3001
+ // assign quad values to double vector
3002
+ solution.col_dual.resize(lp.num_col_);
3003
+ std::transform(col_dual_quad.begin(), col_dual_quad.end(),
3004
+ solution.col_dual.begin(),
3005
+ [](HighsCDouble x) { return double(x); });
3006
+
3007
+ return HighsStatus::kOk;
3008
+ }
3009
+
3010
+ HighsStatus calculateRowValuesQuad(const HighsLp& lp,
3011
+ const std::vector<double>& col_value,
3012
+ std::vector<double>& row_value,
3013
+ const HighsInt report_row) {
3014
+ const bool correct_size = int(col_value.size()) == lp.num_col_;
3015
+ const bool is_colwise = lp.a_matrix_.isColwise();
3016
+ const bool data_error = !correct_size || !is_colwise;
3017
+ assert(!data_error);
3018
+ if (data_error) return HighsStatus::kError;
3019
+
3020
+ std::vector<HighsCDouble> row_value_quad;
3021
+ row_value_quad.assign(lp.num_row_, HighsCDouble{0.0});
3022
+
3023
+ for (HighsInt col = 0; col < lp.num_col_; col++) {
3024
+ for (HighsInt i = lp.a_matrix_.start_[col];
3025
+ i < lp.a_matrix_.start_[col + 1]; i++) {
3026
+ const HighsInt row = lp.a_matrix_.index_[i];
3027
+ assert(row >= 0);
3028
+ assert(row < lp.num_row_);
3029
+ row_value_quad[row] += col_value[col] * lp.a_matrix_.value_[i];
3030
+ if (row == report_row) {
3031
+ printf(
3032
+ "calculateRowValuesQuad: Row %d becomes %g due to contribution of "
3033
+ ".col_value[%d] = %g\n",
3034
+ int(row), double(row_value_quad[row]), int(col), col_value[col]);
3035
+ }
3036
+ }
3037
+ }
3038
+
3039
+ // assign quad values to double vector
3040
+ row_value.resize(lp.num_row_);
3041
+ std::transform(row_value_quad.begin(), row_value_quad.end(),
3042
+ row_value.begin(), [](HighsCDouble x) { return double(x); });
3043
+
3044
+ return HighsStatus::kOk;
3045
+ }
3046
+
3047
+ HighsStatus calculateRowValuesQuad(const HighsLp& lp, HighsSolution& solution,
3048
+ const HighsInt report_row) {
3049
+ return calculateRowValuesQuad(lp, solution.col_value, solution.row_value,
3050
+ report_row);
3051
+ }
3052
+
3053
+ bool isColDataNull(const HighsLogOptions& log_options,
3054
+ const double* usr_col_cost, const double* usr_col_lower,
3055
+ const double* usr_col_upper) {
3056
+ bool null_data = false;
3057
+ null_data =
3058
+ doubleUserDataNotNull(log_options, usr_col_cost, "column costs") ||
3059
+ null_data;
3060
+ null_data = doubleUserDataNotNull(log_options, usr_col_lower,
3061
+ "column lower bounds") ||
3062
+ null_data;
3063
+ null_data = doubleUserDataNotNull(log_options, usr_col_upper,
3064
+ "column upper bounds") ||
3065
+ null_data;
3066
+ return null_data;
3067
+ }
3068
+
3069
+ bool isRowDataNull(const HighsLogOptions& log_options,
3070
+ const double* usr_row_lower, const double* usr_row_upper) {
3071
+ bool null_data = false;
3072
+ null_data =
3073
+ doubleUserDataNotNull(log_options, usr_row_lower, "row lower bounds") ||
3074
+ null_data;
3075
+ null_data =
3076
+ doubleUserDataNotNull(log_options, usr_row_upper, "row upper bounds") ||
3077
+ null_data;
3078
+ return null_data;
3079
+ }
3080
+
3081
+ bool isMatrixDataNull(const HighsLogOptions& log_options,
3082
+ const HighsInt* usr_matrix_start,
3083
+ const HighsInt* usr_matrix_index,
3084
+ const double* usr_matrix_value) {
3085
+ bool null_data = false;
3086
+ null_data =
3087
+ intUserDataNotNull(log_options, usr_matrix_start, "matrix starts") ||
3088
+ null_data;
3089
+ null_data =
3090
+ intUserDataNotNull(log_options, usr_matrix_index, "matrix indices") ||
3091
+ null_data;
3092
+ null_data =
3093
+ doubleUserDataNotNull(log_options, usr_matrix_value, "matrix values") ||
3094
+ null_data;
3095
+ return null_data;
3096
+ }
3097
+
3098
+ void reportPresolveReductions(const HighsLogOptions& log_options,
3099
+ HighsPresolveStatus presolve_status,
3100
+ const HighsLp& lp, const HighsLp& presolved_lp) {
3101
+ const HighsInt num_col_from = lp.num_col_;
3102
+ const HighsInt num_row_from = lp.num_row_;
3103
+ const HighsInt num_nz_from = lp.a_matrix_.numNz();
3104
+ HighsInt num_col_to = 0;
3105
+ HighsInt num_row_to = 0;
3106
+ HighsInt num_nz_to = 0;
3107
+ std::string message = "";
3108
+
3109
+ switch (presolve_status) {
3110
+ case HighsPresolveStatus::kNotPresolved:
3111
+ case HighsPresolveStatus::kInfeasible:
3112
+ case HighsPresolveStatus::kUnboundedOrInfeasible:
3113
+ return;
3114
+ case HighsPresolveStatus::kNotReduced: {
3115
+ num_col_to = num_col_from;
3116
+ num_row_to = num_row_from;
3117
+ num_nz_to = num_nz_from;
3118
+ message = "- Not reduced";
3119
+ break;
3120
+ }
3121
+ case HighsPresolveStatus::kReduced:
3122
+ case HighsPresolveStatus::kTimeout: {
3123
+ num_col_to = presolved_lp.num_col_;
3124
+ num_row_to = presolved_lp.num_row_;
3125
+ num_nz_to = presolved_lp.a_matrix_.numNz();
3126
+ message =
3127
+ presolve_status == HighsPresolveStatus::kTimeout ? "- Timeout" : "";
3128
+ break;
3129
+ }
3130
+ case HighsPresolveStatus::kReducedToEmpty: {
3131
+ num_col_to = 0;
3132
+ num_row_to = 0;
3133
+ num_nz_to = 0;
3134
+ message = "- Reduced to empty";
3135
+ break;
3136
+ }
3137
+ default: {
3138
+ // case HighsPresolveStatus::kOutOfMemory
3139
+ assert(presolve_status == HighsPresolveStatus::kOutOfMemory);
3140
+ return;
3141
+ }
3142
+ }
3143
+ char nz_sign_char = '-';
3144
+ HighsInt delta_nz = num_nz_from - num_nz_to;
3145
+ if (num_nz_to > num_nz_from) {
3146
+ delta_nz = -delta_nz;
3147
+ nz_sign_char = '+';
3148
+ }
3149
+ highsLogUser(log_options, HighsLogType::kInfo,
3150
+ "Presolve reductions: rows %" HIGHSINT_FORMAT
3151
+ "(-%" HIGHSINT_FORMAT "); columns %" HIGHSINT_FORMAT
3152
+ "(-%" HIGHSINT_FORMAT
3153
+ "); "
3154
+ "nonzeros %" HIGHSINT_FORMAT "(%c%" HIGHSINT_FORMAT ") %s\n",
3155
+ num_row_to, (num_row_from - num_row_to), num_col_to,
3156
+ (num_col_from - num_col_to), num_nz_to, nz_sign_char, delta_nz,
3157
+ message.c_str());
3158
+ }
3159
+
3160
+ bool isLessInfeasibleDSECandidate(const HighsLogOptions& log_options,
3161
+ const HighsLp& lp) {
3162
+ HighsInt max_col_num_en = -1;
3163
+ const HighsInt max_allowed_col_num_en = 24;
3164
+ const HighsInt max_assess_col_num_en =
3165
+ std::max(HighsInt{9}, max_allowed_col_num_en);
3166
+ const HighsInt max_average_col_num_en = 6;
3167
+ vector<HighsInt> col_length_k;
3168
+ col_length_k.resize(1 + max_assess_col_num_en, 0);
3169
+ bool LiDSE_candidate = true;
3170
+ for (HighsInt col = 0; col < lp.num_col_; col++) {
3171
+ // Check limit on number of entries in the column has not been breached
3172
+ HighsInt col_num_en =
3173
+ lp.a_matrix_.start_[col + 1] - lp.a_matrix_.start_[col];
3174
+ max_col_num_en = std::max(col_num_en, max_col_num_en);
3175
+ if (col_num_en > max_assess_col_num_en) return false;
3176
+ col_length_k[col_num_en]++;
3177
+ for (HighsInt en = lp.a_matrix_.start_[col];
3178
+ en < lp.a_matrix_.start_[col + 1]; en++) {
3179
+ double value = lp.a_matrix_.value_[en];
3180
+ // All nonzeros must be +1 or -1
3181
+ if (fabs(value) != 1) return false;
3182
+ }
3183
+ }
3184
+ double average_col_num_en = lp.a_matrix_.start_[lp.num_col_];
3185
+ average_col_num_en = average_col_num_en / lp.num_col_;
3186
+ LiDSE_candidate =
3187
+ LiDSE_candidate && average_col_num_en <= max_average_col_num_en;
3188
+ highsLogDev(log_options, HighsLogType::kInfo,
3189
+ "LP %s has all |entries|=1; max column count = %" HIGHSINT_FORMAT
3190
+ " (limit %" HIGHSINT_FORMAT
3191
+ "); average "
3192
+ "column count = %0.2g (limit %" HIGHSINT_FORMAT
3193
+ "): LP is %s a candidate for LiDSE\n",
3194
+ lp.model_name_.c_str(), max_col_num_en, max_allowed_col_num_en,
3195
+ average_col_num_en, max_average_col_num_en,
3196
+ LiDSE_candidate ? "is" : "is not");
3197
+ return LiDSE_candidate;
3198
+ }
3199
+
3200
+ HighsLp withoutSemiVariables(const HighsLp& lp_, HighsSolution& solution,
3201
+ const double primal_feasibility_tolerance) {
3202
+ HighsLp lp = lp_;
3203
+ HighsInt num_col = lp.num_col_;
3204
+ HighsInt num_row = lp.num_row_;
3205
+ HighsInt num_semi_variables = 0;
3206
+ for (HighsInt iCol = 0; iCol < num_col; iCol++) {
3207
+ if (lp.integrality_[iCol] == HighsVarType::kSemiContinuous ||
3208
+ lp.integrality_[iCol] == HighsVarType::kSemiInteger)
3209
+ num_semi_variables++;
3210
+ }
3211
+ assert(num_semi_variables);
3212
+ // Insert spaces for index/value of new coefficients for
3213
+ // semi-variables
3214
+ vector<HighsInt>& start = lp.a_matrix_.start_;
3215
+ vector<HighsInt>& index = lp.a_matrix_.index_;
3216
+ vector<double>& value = lp.a_matrix_.value_;
3217
+ HighsInt num_nz = start[num_col];
3218
+ HighsInt new_num_nz = num_nz + 2 * num_semi_variables;
3219
+ HighsInt new_el = new_num_nz;
3220
+ index.resize(new_num_nz);
3221
+ value.resize(new_num_nz);
3222
+ for (HighsInt iCol = num_col - 1; iCol >= 0; iCol--) {
3223
+ HighsInt from_el = start[iCol + 1] - 1;
3224
+ start[iCol + 1] = new_el;
3225
+ if (lp.integrality_[iCol] == HighsVarType::kSemiContinuous ||
3226
+ lp.integrality_[iCol] == HighsVarType::kSemiInteger)
3227
+ new_el -= 2;
3228
+ for (HighsInt iEl = from_el; iEl >= start[iCol]; iEl--) {
3229
+ new_el--;
3230
+ index[new_el] = index[iEl];
3231
+ value[new_el] = value[iEl];
3232
+ }
3233
+ }
3234
+ assert(new_el == 0);
3235
+ // Insert the new coefficients for semi-variables
3236
+ HighsInt row_num = num_row;
3237
+ for (HighsInt iCol = 0; iCol < num_col; iCol++) {
3238
+ if (lp.integrality_[iCol] == HighsVarType::kSemiContinuous ||
3239
+ lp.integrality_[iCol] == HighsVarType::kSemiInteger) {
3240
+ HighsInt iEl = start[iCol + 1] - 2;
3241
+ index[iEl] = row_num++;
3242
+ value[iEl] = 1;
3243
+ iEl++;
3244
+ index[iEl] = row_num++;
3245
+ value[iEl] = 1;
3246
+ }
3247
+ }
3248
+ num_nz = start[num_col];
3249
+ new_num_nz = num_nz + 2 * num_semi_variables;
3250
+ row_num = num_row;
3251
+ HighsInt semi_col_num = 0;
3252
+ HighsInt semi_row_num = 0;
3253
+ // Insert the new variables and their coefficients
3254
+ std::stringstream ss;
3255
+ const bool have_col_names =
3256
+ lp.col_names_.size() == static_cast<size_t>(lp.num_col_);
3257
+ const bool have_row_names =
3258
+ lp.row_names_.size() == static_cast<size_t>(lp.num_row_);
3259
+ const bool have_solution = solution.value_valid;
3260
+ if (have_solution) {
3261
+ // Create zeroed row values for the new rows
3262
+ assert((HighsInt)solution.row_value.size() == lp_.num_row_);
3263
+ for (HighsInt iCol = 0; iCol < 2 * num_semi_variables; iCol++)
3264
+ solution.row_value.push_back(0);
3265
+ assert((HighsInt)solution.col_value.size() == lp_.num_col_);
3266
+ assert((HighsInt)solution.row_value.size() ==
3267
+ lp_.num_row_ + 2 * num_semi_variables);
3268
+ }
3269
+ for (HighsInt iCol = 0; iCol < num_col; iCol++) {
3270
+ if (lp.integrality_[iCol] == HighsVarType::kSemiContinuous ||
3271
+ lp.integrality_[iCol] == HighsVarType::kSemiInteger) {
3272
+ // Add a binary variable with zero cost
3273
+ lp.col_cost_.push_back(0);
3274
+ lp.col_lower_.push_back(0);
3275
+ lp.col_upper_.push_back(1);
3276
+ // Complete x - l*y >= 0
3277
+ lp.row_lower_.push_back(0);
3278
+ lp.row_upper_.push_back(kHighsInf);
3279
+ if (have_col_names) {
3280
+ // Create a column name
3281
+ ss.str(std::string());
3282
+ ss << "semi_binary_" << semi_col_num++;
3283
+ lp.col_names_.push_back(ss.str());
3284
+ }
3285
+ if (have_row_names) {
3286
+ // Create a row name
3287
+ ss.str(std::string());
3288
+ ss << "semi_lb_" << semi_row_num;
3289
+ lp.row_names_.push_back(ss.str());
3290
+ }
3291
+ index.push_back(row_num++);
3292
+ value.push_back(-lp.col_lower_[iCol]);
3293
+ // Accommodate any primal solution
3294
+ if (have_solution) {
3295
+ // Record the previous solution value so any change can be
3296
+ // determined
3297
+ const double prev_primal = solution.col_value[iCol];
3298
+ if (solution.col_value[iCol] <= primal_feasibility_tolerance) {
3299
+ // Currently at or below zero, so binary is 0
3300
+ solution.col_value[iCol] = 0;
3301
+ solution.col_value.push_back(0);
3302
+ } else {
3303
+ // Otherwise, solution is at least lower bound, and binary
3304
+ // is 1
3305
+ solution.col_value[iCol] =
3306
+ std::max(lp.col_lower_[iCol], solution.col_value[iCol]);
3307
+ solution.col_value.push_back(1);
3308
+ }
3309
+ const double dl_primal = solution.col_value[iCol] - prev_primal;
3310
+ if (dl_primal) {
3311
+ // Change in primal value, so update row values. NB start
3312
+ // has been extended to incorporate the values in this
3313
+ // column for the new rows. Their solution values are zero,
3314
+ // but will be set later
3315
+ for (HighsInt iEl = start[iCol]; iEl < start[iCol + 1]; iEl++)
3316
+ solution.row_value[index[iEl]] += dl_primal * value[iEl];
3317
+ }
3318
+ const HighsInt new_col = lp.col_cost_.size() - 1;
3319
+ const double binary_value = solution.col_value[new_col];
3320
+ solution.row_value[row_num - 1] =
3321
+ solution.col_value[iCol] - lp.col_lower_[iCol] * binary_value;
3322
+ solution.row_value[row_num] =
3323
+ solution.col_value[iCol] - lp.col_upper_[iCol] * binary_value;
3324
+ }
3325
+ // Complete x - u*y <= 0
3326
+ lp.row_lower_.push_back(-kHighsInf);
3327
+ lp.row_upper_.push_back(0);
3328
+ if (have_row_names) {
3329
+ // Create a row name
3330
+ ss.str(std::string());
3331
+ ss << "semi_ub_" << semi_row_num++;
3332
+ lp.row_names_.push_back(ss.str());
3333
+ }
3334
+ index.push_back(row_num++);
3335
+ value.push_back(-lp.col_upper_[iCol]);
3336
+ // Add the next start
3337
+ start.push_back(index.size());
3338
+ lp.integrality_.push_back(HighsVarType::kInteger);
3339
+ if (lp.integrality_[iCol] == HighsVarType::kSemiContinuous) {
3340
+ lp.integrality_[iCol] = HighsVarType::kContinuous;
3341
+ } else if (lp.integrality_[iCol] == HighsVarType::kSemiInteger) {
3342
+ lp.integrality_[iCol] = HighsVarType::kInteger;
3343
+ }
3344
+ // Change the lower bound on the semi-variable to zero. Cannot
3345
+ // do this earlier, as its original value is used in constraint
3346
+ // 0 <= x-l*y
3347
+ lp.col_lower_[iCol] = 0;
3348
+ }
3349
+ }
3350
+ num_col += num_semi_variables;
3351
+ lp.num_col_ += num_semi_variables;
3352
+ lp.num_row_ += 2 * num_semi_variables;
3353
+ assert((HighsInt)index.size() == new_num_nz);
3354
+ // Ensure that the matrix dimensions are consistent with the LP
3355
+ // dimensions
3356
+ lp.a_matrix_.num_col_ = lp.num_col_;
3357
+ lp.a_matrix_.num_row_ = lp.num_row_;
3358
+ // Clear any modifications inherited from lp_
3359
+ lp.mods_.clear();
3360
+ return lp;
3361
+ }
3362
+
3363
+ void removeRowsOfCountOne(const HighsLogOptions& log_options, HighsLp& lp) {
3364
+ HighsLp row_wise_lp = lp;
3365
+ vector<HighsInt>& a_start = lp.a_matrix_.start_;
3366
+ vector<HighsInt>& a_index = lp.a_matrix_.index_;
3367
+ vector<double>& a_value = lp.a_matrix_.value_;
3368
+ vector<HighsInt> a_count;
3369
+ vector<HighsInt> ar_count;
3370
+ vector<HighsInt> ar_start;
3371
+ vector<HighsInt> ar_index;
3372
+ vector<double> ar_value;
3373
+ const bool have_name = lp.row_names_.size() > 0;
3374
+ HighsInt num_nz = a_start[lp.num_col_];
3375
+ const HighsInt original_num_nz = num_nz;
3376
+ const HighsInt original_num_row = lp.num_row_;
3377
+ HighsInt num_row_count_1 = 0;
3378
+ ar_count.assign(lp.num_row_, 0);
3379
+ for (HighsInt iCol = 0; iCol < lp.num_col_; iCol++) {
3380
+ for (HighsInt iEl = a_start[iCol]; iEl < a_start[iCol + 1]; iEl++)
3381
+ ar_count[a_index[iEl]]++;
3382
+ }
3383
+ ar_start.push_back(0);
3384
+ for (HighsInt iRow = 0; iRow < lp.num_row_; iRow++) {
3385
+ ar_start.push_back(ar_start[iRow] + ar_count[iRow]);
3386
+ ar_count[iRow] = ar_start[iRow];
3387
+ }
3388
+ ar_index.resize(num_nz);
3389
+ ar_value.resize(num_nz);
3390
+ for (HighsInt iCol = 0; iCol < lp.num_col_; iCol++) {
3391
+ for (HighsInt iEl = a_start[iCol]; iEl < a_start[iCol + 1]; iEl++) {
3392
+ HighsInt iRow = a_index[iEl];
3393
+ ar_index[ar_count[iRow]] = iCol;
3394
+ ar_value[ar_count[iRow]] = a_value[iEl];
3395
+ ar_count[iRow]++;
3396
+ }
3397
+ }
3398
+ HighsInt newRow = 0;
3399
+ HighsInt newEl = 0;
3400
+ for (HighsInt iRow = 0; iRow < lp.num_row_; iRow++) {
3401
+ const HighsInt row_count = ar_start[iRow + 1] - ar_start[iRow];
3402
+ if (row_count == 1) {
3403
+ HighsInt iCol = ar_index[ar_start[iRow]];
3404
+ double value = ar_value[ar_start[iRow]];
3405
+ assert(value);
3406
+ if (value > 0) {
3407
+ if (lp.row_lower_[iRow] > -kHighsInf)
3408
+ lp.col_lower_[iCol] =
3409
+ std::max(lp.row_lower_[iRow] / value, lp.col_lower_[iCol]);
3410
+ if (lp.row_upper_[iRow] < kHighsInf)
3411
+ lp.col_upper_[iCol] =
3412
+ std::min(lp.row_upper_[iRow] / value, lp.col_upper_[iCol]);
3413
+ } else {
3414
+ if (lp.row_lower_[iRow] > -kHighsInf)
3415
+ lp.col_upper_[iCol] =
3416
+ std::min(lp.row_lower_[iRow] / value, lp.col_upper_[iCol]);
3417
+ if (lp.row_upper_[iRow] < kHighsInf)
3418
+ lp.col_lower_[iCol] =
3419
+ std::max(lp.row_upper_[iRow] / value, lp.col_lower_[iCol]);
3420
+ }
3421
+ num_row_count_1++;
3422
+ continue;
3423
+ }
3424
+ lp.row_lower_[newRow] = lp.row_lower_[iRow];
3425
+ lp.row_upper_[newRow] = lp.row_upper_[iRow];
3426
+ if (have_name) lp.row_names_[newRow] = lp.row_names_[iRow];
3427
+ ar_start[newRow] = newEl;
3428
+ for (HighsInt iEl = ar_start[iRow]; iEl < ar_start[iRow + 1]; iEl++) {
3429
+ ar_index[newEl] = ar_index[iEl];
3430
+ ar_value[newEl] = ar_value[iEl];
3431
+ newEl++;
3432
+ }
3433
+ newRow++;
3434
+ }
3435
+ ar_start[newRow] = newEl;
3436
+ lp.num_row_ = newRow;
3437
+ lp.row_lower_.resize(newRow);
3438
+ lp.row_upper_.resize(newRow);
3439
+ if (have_name) lp.row_names_.resize(newRow);
3440
+
3441
+ num_nz = ar_start[lp.num_row_];
3442
+ a_count.assign(lp.num_col_, 0);
3443
+ for (HighsInt iRow = 0; iRow < lp.num_row_; iRow++) {
3444
+ for (HighsInt iEl = ar_start[iRow]; iEl < ar_start[iRow + 1]; iEl++)
3445
+ a_count[ar_index[iEl]]++;
3446
+ }
3447
+ a_start[0] = 0;
3448
+ for (HighsInt iCol = 0; iCol < lp.num_col_; iCol++) {
3449
+ a_start[iCol + 1] = a_start[iCol] + a_count[iCol];
3450
+ a_count[iCol] = a_start[iCol];
3451
+ }
3452
+ a_index.resize(num_nz);
3453
+ a_value.resize(num_nz);
3454
+ for (HighsInt iRow = 0; iRow < lp.num_row_; iRow++) {
3455
+ for (HighsInt iEl = ar_start[iRow]; iEl < ar_start[iRow + 1]; iEl++) {
3456
+ HighsInt iCol = ar_index[iEl];
3457
+ a_index[a_count[iCol]] = iRow;
3458
+ a_value[a_count[iCol]] = ar_value[iEl];
3459
+ a_count[iCol]++;
3460
+ }
3461
+ }
3462
+ assert(original_num_row - lp.num_row_ == num_row_count_1);
3463
+ assert(original_num_nz - num_nz == num_row_count_1);
3464
+ highsLogUser(log_options, HighsLogType::kWarning,
3465
+ "Removed %d rows of count 1\n", (int)num_row_count_1);
3466
+ }
3467
+
3468
+ void getSubVectors(const HighsIndexCollection& index_collection,
3469
+ const HighsInt data_dim, const double* data0,
3470
+ const double* data1, const double* data2,
3471
+ const HighsSparseMatrix& matrix, HighsInt& num_sub_vector,
3472
+ double* sub_vector_data0, double* sub_vector_data1,
3473
+ double* sub_vector_data2, HighsInt& sub_matrix_num_nz,
3474
+ HighsInt* sub_matrix_start, HighsInt* sub_matrix_index,
3475
+ double* sub_matrix_value) {
3476
+ // Ensure that if there's no data0 then it's not required in the
3477
+ // sub-vector
3478
+ if (data0 == nullptr) assert(sub_vector_data0 == nullptr);
3479
+ assert(ok(index_collection));
3480
+ HighsInt from_k;
3481
+ HighsInt to_k;
3482
+ limits(index_collection, from_k, to_k);
3483
+ // Surely this is checked elsewhere
3484
+ assert(0 <= from_k && to_k < data_dim);
3485
+ assert(from_k <= to_k);
3486
+ HighsInt out_from_vector;
3487
+ HighsInt out_to_vector;
3488
+ HighsInt in_from_vector;
3489
+ HighsInt in_to_vector = -1;
3490
+ HighsInt current_set_entry = 0;
3491
+ num_sub_vector = 0;
3492
+ sub_matrix_num_nz = 0;
3493
+ for (HighsInt k = from_k; k <= to_k; k++) {
3494
+ updateOutInIndex(index_collection, out_from_vector, out_to_vector,
3495
+ in_from_vector, in_to_vector, current_set_entry);
3496
+ assert(out_to_vector < data_dim);
3497
+ assert(in_to_vector < data_dim);
3498
+ for (HighsInt iVector = out_from_vector; iVector <= out_to_vector;
3499
+ iVector++) {
3500
+ if (sub_vector_data0 != nullptr)
3501
+ sub_vector_data0[num_sub_vector] = data0[iVector];
3502
+ if (sub_vector_data1 != nullptr)
3503
+ sub_vector_data1[num_sub_vector] = data1[iVector];
3504
+ if (sub_vector_data2 != nullptr)
3505
+ sub_vector_data2[num_sub_vector] = data2[iVector];
3506
+ if (sub_matrix_start != nullptr)
3507
+ sub_matrix_start[num_sub_vector] = sub_matrix_num_nz +
3508
+ matrix.start_[iVector] -
3509
+ matrix.start_[out_from_vector];
3510
+ num_sub_vector++;
3511
+ }
3512
+ for (HighsInt iEl = matrix.start_[out_from_vector];
3513
+ iEl < matrix.start_[out_to_vector + 1]; iEl++) {
3514
+ if (sub_matrix_index != nullptr)
3515
+ sub_matrix_index[sub_matrix_num_nz] = matrix.index_[iEl];
3516
+ if (sub_matrix_value != nullptr)
3517
+ sub_matrix_value[sub_matrix_num_nz] = matrix.value_[iEl];
3518
+ sub_matrix_num_nz++;
3519
+ }
3520
+ if (out_to_vector == data_dim - 1 || in_to_vector == data_dim - 1) break;
3521
+ }
3522
+ }
3523
+
3524
+ void getSubVectorsTranspose(const HighsIndexCollection& index_collection,
3525
+ const HighsInt data_dim, const double* data0,
3526
+ const double* data1, const double* data2,
3527
+ const HighsSparseMatrix& matrix,
3528
+ HighsInt& num_sub_vector, double* sub_vector_data0,
3529
+ double* sub_vector_data1, double* sub_vector_data2,
3530
+ HighsInt& sub_matrix_num_nz,
3531
+ HighsInt* sub_matrix_start,
3532
+ HighsInt* sub_matrix_index,
3533
+ double* sub_matrix_value) {
3534
+ // Ensure that if there's no data0 then it's not required in the
3535
+ // sub-vector
3536
+ if (data0 == nullptr) assert(sub_vector_data0 == nullptr);
3537
+ assert(ok(index_collection));
3538
+ HighsInt from_k;
3539
+ HighsInt to_k;
3540
+ limits(index_collection, from_k, to_k);
3541
+ // Surely this is checked elsewhere
3542
+ assert(0 <= from_k && to_k < data_dim);
3543
+ assert(from_k <= to_k);
3544
+ // "Out" means not in the set to be extracted
3545
+ // "In" means in the set to be extracted
3546
+ HighsInt out_from_vector;
3547
+ HighsInt out_to_vector;
3548
+ HighsInt in_from_vector;
3549
+ HighsInt in_to_vector = -1;
3550
+ HighsInt current_set_entry = 0;
3551
+ // Set up a mask so that entries to be got from the matrix can be
3552
+ // identified and have their correct index.
3553
+ vector<HighsInt> new_index;
3554
+ new_index.resize(data_dim);
3555
+
3556
+ num_sub_vector = 0;
3557
+ sub_matrix_num_nz = 0;
3558
+ if (!index_collection.is_mask_) {
3559
+ out_to_vector = -1;
3560
+ current_set_entry = 0;
3561
+ for (HighsInt k = from_k; k <= to_k; k++) {
3562
+ updateOutInIndex(index_collection, in_from_vector, in_to_vector,
3563
+ out_from_vector, out_to_vector, current_set_entry);
3564
+ if (k == from_k) {
3565
+ // Account for any initial vectors not being extracted
3566
+ for (HighsInt iVector = 0; iVector < in_from_vector; iVector++) {
3567
+ new_index[iVector] = -1;
3568
+ }
3569
+ }
3570
+ for (HighsInt iVector = in_from_vector; iVector <= in_to_vector;
3571
+ iVector++) {
3572
+ new_index[iVector] = num_sub_vector;
3573
+ num_sub_vector++;
3574
+ }
3575
+ for (HighsInt iVector = out_from_vector; iVector <= out_to_vector;
3576
+ iVector++) {
3577
+ new_index[iVector] = -1;
3578
+ }
3579
+ if (out_to_vector >= data_dim - 1) break;
3580
+ }
3581
+ } else {
3582
+ for (HighsInt iVector = 0; iVector < data_dim; iVector++) {
3583
+ if (index_collection.mask_[iVector]) {
3584
+ new_index[iVector] = num_sub_vector;
3585
+ num_sub_vector++;
3586
+ } else {
3587
+ new_index[iVector] = -1;
3588
+ }
3589
+ }
3590
+ }
3591
+
3592
+ // Bail out if no vectors are to be extracted
3593
+ if (num_sub_vector == 0) return;
3594
+
3595
+ for (HighsInt iVector = 0; iVector < data_dim; iVector++) {
3596
+ HighsInt new_iVector = new_index[iVector];
3597
+ if (new_iVector >= 0) {
3598
+ assert(new_iVector < num_sub_vector);
3599
+ if (sub_vector_data0 != NULL)
3600
+ sub_vector_data0[new_iVector] = data0[iVector];
3601
+ if (sub_vector_data1 != NULL)
3602
+ sub_vector_data1[new_iVector] = data1[iVector];
3603
+ if (sub_vector_data2 != NULL)
3604
+ sub_vector_data2[new_iVector] = data2[iVector];
3605
+ }
3606
+ }
3607
+ const bool extract_start = sub_matrix_start != NULL;
3608
+ const bool extract_index = sub_matrix_index != NULL;
3609
+ const bool extract_value = sub_matrix_value != NULL;
3610
+ const bool extract_matrix = extract_index || extract_value;
3611
+ // Allocate an array of lengths for the sub-matrix to be
3612
+ // extracted: necessary even if just the number of nonzeros is
3613
+ // required
3614
+ vector<HighsInt> sub_matrix_length;
3615
+ sub_matrix_length.assign(num_sub_vector, 0);
3616
+ // Identify the lengths of the vectors in the sub-matrix to be extracted
3617
+ HighsInt num_vector = matrix.start_.size() - 1;
3618
+ for (HighsInt vector = 0; vector < num_vector; vector++) {
3619
+ for (HighsInt iEl = matrix.start_[vector]; iEl < matrix.start_[vector + 1];
3620
+ iEl++) {
3621
+ HighsInt iVector = matrix.index_[iEl];
3622
+ HighsInt new_iVector = new_index[iVector];
3623
+ if (new_iVector >= 0) sub_matrix_length[new_iVector]++;
3624
+ }
3625
+ }
3626
+ if (!extract_start) {
3627
+ // bail out if no matrix starts are to be extracted, but only after
3628
+ // computing the number of nonzeros
3629
+ for (HighsInt iVector = 0; iVector < num_sub_vector; iVector++)
3630
+ sub_matrix_num_nz += sub_matrix_length[iVector];
3631
+ return;
3632
+ }
3633
+ // Allocate an array of lengths for the sub-matrix to be extracted
3634
+ sub_matrix_start[0] = 0;
3635
+ for (HighsInt iVector = 0; iVector < num_sub_vector - 1; iVector++) {
3636
+ sub_matrix_start[iVector + 1] =
3637
+ sub_matrix_start[iVector] + sub_matrix_length[iVector];
3638
+ sub_matrix_length[iVector] = sub_matrix_start[iVector];
3639
+ }
3640
+ HighsInt iVector = num_sub_vector - 1;
3641
+ sub_matrix_num_nz = sub_matrix_start[iVector] + sub_matrix_length[iVector];
3642
+ // Bail out if matrix indices and values are not required
3643
+ if (!extract_matrix) return;
3644
+ sub_matrix_length[iVector] = sub_matrix_start[iVector];
3645
+ // Fill the row-wise matrix with indices and values
3646
+ for (HighsInt vector = 0; vector < num_vector; vector++) {
3647
+ for (HighsInt iEl = matrix.start_[vector]; iEl < matrix.start_[vector + 1];
3648
+ iEl++) {
3649
+ HighsInt iVector = matrix.index_[iEl];
3650
+ HighsInt new_iVector = new_index[iVector];
3651
+ if (new_iVector >= 0) {
3652
+ HighsInt row_iEl = sub_matrix_length[new_iVector];
3653
+ if (extract_index) sub_matrix_index[row_iEl] = vector;
3654
+ if (extract_value) sub_matrix_value[row_iEl] = matrix.value_[iEl];
3655
+ sub_matrix_length[new_iVector]++;
3656
+ }
3657
+ }
3658
+ }
3659
+ }
3660
+
3661
+ std::string highsVarTypeToString(const HighsVarType type) {
3662
+ switch (type) {
3663
+ case HighsVarType::kContinuous:
3664
+ return "continuous";
3665
+ case HighsVarType::kInteger:
3666
+ return "integer";
3667
+ case HighsVarType::kSemiContinuous:
3668
+ return "semi continuous";
3669
+ case HighsVarType::kSemiInteger:
3670
+ return "semi integer";
3671
+ case HighsVarType::kImplicitInteger:
3672
+ return "implicit integer";
3673
+ default:
3674
+ return "unknown";
3675
+ }
3676
+ }
3677
+
3678
+ std::string highsVarTypeToString(const HighsInt type) {
3679
+ if (type < HighsInt(HighsVarType::kContinuous) ||
3680
+ type > HighsInt(HighsVarType::kImplicitInteger))
3681
+ return "unknown";
3682
+ HighsVarType type_ = HighsVarType(uint8_t(type));
3683
+ return highsVarTypeToString(type_);
3684
+ }
3685
+
3686
+ void initialiseUserScaleData(const HighsOptions& options,
3687
+ HighsUserScaleData& user_scale_data) {
3688
+ user_scale_data.initialise(options.user_objective_scale,
3689
+ options.user_bound_scale, options.infinite_cost,
3690
+ options.infinite_bound, options.small_matrix_value,
3691
+ options.large_matrix_value);
3692
+ }
3693
+
3694
+ void HighsUserScaleData::initialise(const HighsInt& user_objective_scale_,
3695
+ const HighsInt& user_bound_scale_,
3696
+ const double& infinite_cost_,
3697
+ const double& infinite_bound_,
3698
+ const double& small_matrix_value_,
3699
+ const double& large_matrix_value_) {
3700
+ this->user_objective_scale = user_objective_scale_;
3701
+ this->user_bound_scale = user_bound_scale_;
3702
+ this->infinite_cost = infinite_cost_;
3703
+ this->infinite_bound = infinite_bound_;
3704
+ this->small_matrix_value = small_matrix_value_;
3705
+ this->large_matrix_value = large_matrix_value_;
3706
+ this->num_infinite_costs = 0;
3707
+ this->num_infinite_hessian_values = 0;
3708
+ this->num_infinite_col_bounds = 0;
3709
+ this->num_infinite_row_bounds = 0;
3710
+ this->num_small_matrix_values = 0;
3711
+ this->num_large_matrix_values = 0;
3712
+ this->suggested_user_objective_scale = 0;
3713
+ this->suggested_user_bound_scale = 0;
3714
+ this->applied = false;
3715
+ }
3716
+
3717
+ bool HighsUserScaleData::scaleError(std::string& message) const {
3718
+ if (this->num_infinite_costs + this->num_infinite_hessian_values +
3719
+ this->num_infinite_col_bounds + this->num_infinite_row_bounds +
3720
+ this->num_large_matrix_values ==
3721
+ 0)
3722
+ return false;
3723
+ assert(this->user_objective_scale != 0 || this->user_bound_scale != 0);
3724
+ std::stringstream ss;
3725
+ ss.str(std::string());
3726
+ ss << "User scaling of";
3727
+ if (this->user_objective_scale != 0) {
3728
+ ss << " 2**(" << this->user_objective_scale << ") for costs";
3729
+ }
3730
+ if (this->user_bound_scale != 0) {
3731
+ if (this->user_objective_scale != 0) ss << " and";
3732
+ ss << " 2**(" << this->user_bound_scale << ") for bounds";
3733
+ }
3734
+ ss << " yields";
3735
+ if (this->num_infinite_costs) {
3736
+ ss << " " << this->num_infinite_costs << " infinite cost";
3737
+ if (this->num_infinite_costs > 1) ss << "s";
3738
+ }
3739
+ if (this->num_infinite_hessian_values) {
3740
+ if (this->num_infinite_costs) {
3741
+ if (this->num_infinite_col_bounds || this->num_infinite_row_bounds) {
3742
+ ss << ",";
3743
+ } else {
3744
+ ss << " and";
3745
+ }
3746
+ }
3747
+ ss << " " << this->num_infinite_hessian_values
3748
+ << " infinite Hessian values";
3749
+ if (this->num_infinite_hessian_values > 1) ss << "s";
3750
+ }
3751
+ if (this->num_infinite_col_bounds) {
3752
+ if (this->num_infinite_costs || this->num_infinite_hessian_values) {
3753
+ if (this->num_infinite_row_bounds) {
3754
+ ss << ",";
3755
+ } else {
3756
+ ss << " and";
3757
+ }
3758
+ }
3759
+ ss << " " << this->num_infinite_col_bounds << " infinite column bound";
3760
+ if (this->num_infinite_col_bounds > 1) ss << "s";
3761
+ }
3762
+ if (this->num_infinite_row_bounds) {
3763
+ if (this->num_infinite_costs || this->num_infinite_hessian_values ||
3764
+ this->num_infinite_col_bounds)
3765
+ ss << " and";
3766
+ ss << " " << this->num_infinite_row_bounds << " infinite row bound";
3767
+ if (this->num_infinite_row_bounds > 1) ss << "s";
3768
+ }
3769
+ if (this->num_large_matrix_values) {
3770
+ if (this->num_infinite_costs + this->num_infinite_hessian_values +
3771
+ this->num_infinite_col_bounds + this->num_infinite_row_bounds >
3772
+ 0)
3773
+ ss << ", and";
3774
+ ss << " " << this->num_large_matrix_values << " large matrix value";
3775
+ if (this->num_large_matrix_values > 1) ss << "s";
3776
+ }
3777
+ ss << "\n";
3778
+ message = ss.str();
3779
+ return true;
3780
+ }
3781
+
3782
+ bool HighsUserScaleData::scaleWarning(std::string& message) const {
3783
+ if (this->num_small_matrix_values == 0) return false;
3784
+ assert(this->user_bound_scale != 0);
3785
+ std::stringstream ss;
3786
+ ss.str(std::string());
3787
+ ss << "User scaling of 2**(" << this->user_bound_scale
3788
+ << ") for bounds yields " << this->num_small_matrix_values
3789
+ << " small matrix value";
3790
+ if (this->num_small_matrix_values > 1) ss << "s";
3791
+ ss << "\n";
3792
+ message = ss.str();
3793
+ return true;
3794
+ }