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,2798 @@
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 pdlp/hipdlp/pdhg.cc
9
+ * @brief
10
+ */
11
+ #include "pdhg.hpp"
12
+
13
+ #include <cmath>
14
+ #include <iostream>
15
+ #include <random>
16
+ #include <tuple>
17
+
18
+ #ifdef CUPDLP_GPU
19
+ #include <cublas_v2.h>
20
+ #include <cuda_runtime.h>
21
+ #include <cusparse.h>
22
+ #endif
23
+
24
+ #include "defs.hpp"
25
+ #include "linalg.hpp"
26
+ #include "lp_data/HConst.h"
27
+ #include "pdhg_kernels.hpp"
28
+ #include "pdlp/cupdlp/cupdlp.h" // For pdlpLogging
29
+ #include "pdlp_gpu_debug.hpp"
30
+ #include "restart.hpp"
31
+
32
+ #define PDHG_CHECK_INTERVAL 40
33
+ static constexpr double kDivergentMovement = 1e10;
34
+
35
+ using namespace std;
36
+
37
+ void PDLPSolver::printConstraintInfo() {
38
+ if (original_lp_ == nullptr) return;
39
+
40
+ HighsInt nRows = original_lp_->num_row_;
41
+ HighsInt nCols = original_lp_->num_col_;
42
+
43
+ // Count constraint types BEFORE preprocessing
44
+ HighsInt eq_count = 0, leq_count = 0, geq_count = 0, bound_count = 0,
45
+ free_count = 0;
46
+
47
+ for (HighsInt i = 0; i < nRows; ++i) {
48
+ bool has_lower = original_lp_->row_lower_[i] > -kHighsInf;
49
+ bool has_upper = original_lp_->row_upper_[i] < kHighsInf;
50
+
51
+ if (has_lower && has_upper) {
52
+ if (original_lp_->row_lower_[i] == original_lp_->row_upper_[i]) {
53
+ eq_count++;
54
+ } else {
55
+ bound_count++;
56
+ }
57
+ } else if (has_lower) {
58
+ geq_count++;
59
+ } else if (has_upper) {
60
+ leq_count++;
61
+ } else {
62
+ free_count++;
63
+ }
64
+ }
65
+
66
+ // Count variable bound types
67
+ HighsInt var_fixed = 0, var_lower_only = 0, var_upper_only = 0;
68
+ HighsInt var_boxed = 0, var_free = 0;
69
+
70
+ for (HighsInt i = 0; i < nCols; ++i) {
71
+ bool has_lower = original_lp_->col_lower_[i] > -kHighsInf;
72
+ bool has_upper = original_lp_->col_upper_[i] < kHighsInf;
73
+
74
+ if (has_lower && has_upper) {
75
+ if (original_lp_->col_lower_[i] == original_lp_->col_upper_[i]) {
76
+ var_fixed++;
77
+ } else {
78
+ var_boxed++;
79
+ }
80
+ } else if (has_lower) {
81
+ var_lower_only++;
82
+ } else if (has_upper) {
83
+ var_upper_only++;
84
+ } else {
85
+ var_free++;
86
+ }
87
+ }
88
+
89
+ logger_.detailed("=== BEFORE PREPROCESSING ===");
90
+ logger_.detailed("Rows: " + std::to_string(nRows) +
91
+ ", Cols: " + std::to_string(nCols));
92
+ logger_.detailed("\nConstraint types:");
93
+ logger_.detailed(" Equality constraints (=): " + std::to_string(eq_count));
94
+ logger_.detailed(" One-sided inequality (>=): " + std::to_string(geq_count));
95
+ logger_.detailed(" One-sided inequality (<=): " + std::to_string(leq_count));
96
+ logger_.detailed(" Two-sided inequality: " + std::to_string(bound_count));
97
+ logger_.detailed(" Free constraints: " + std::to_string(free_count));
98
+
99
+ logger_.detailed("\nVariable bound types:");
100
+ logger_.detailed(" Fixed variables (l = u): " + std::to_string(var_fixed));
101
+ logger_.detailed(" Boxed variables (l <= x <= u): " +
102
+ std::to_string(var_boxed));
103
+ logger_.detailed(" Lower bounded only (l <= x): " +
104
+ std::to_string(var_lower_only));
105
+ logger_.detailed(" Upper bounded only (x <= u): " +
106
+ std::to_string(var_upper_only));
107
+ logger_.detailed(" Free variables: " + std::to_string(var_free));
108
+
109
+ logger_.detailed("\n=== AFTER PREPROCESSING ===");
110
+ logger_.detailed("Rows: " + std::to_string(lp_.num_row_) +
111
+ ", Cols: " + std::to_string(lp_.num_col_));
112
+ logger_.detailed("Equality rows (first " + std::to_string(num_eq_rows_) +
113
+ " rows)");
114
+ logger_.detailed("Inequality rows (remaining " +
115
+ std::to_string(lp_.num_row_ - num_eq_rows_) + " rows)");
116
+ logger_.detailed("Slack variables added: " +
117
+ std::to_string(lp_.num_col_ - nCols));
118
+
119
+ // Count variable bounds in processed LP
120
+ HighsInt proc_var_fixed = 0, proc_var_lower_only = 0, proc_var_upper_only = 0;
121
+ HighsInt proc_var_boxed = 0, proc_var_free = 0;
122
+
123
+ for (HighsInt i = 0; i < lp_.num_col_; ++i) {
124
+ bool has_lower = lp_.col_lower_[i] > -kHighsInf;
125
+ bool has_upper = lp_.col_upper_[i] < kHighsInf;
126
+
127
+ if (has_lower && has_upper) {
128
+ if (lp_.col_lower_[i] == lp_.col_upper_[i]) {
129
+ proc_var_fixed++;
130
+ } else {
131
+ proc_var_boxed++;
132
+ }
133
+ } else if (has_lower) {
134
+ proc_var_lower_only++;
135
+ } else if (has_upper) {
136
+ proc_var_upper_only++;
137
+ } else {
138
+ proc_var_free++;
139
+ }
140
+ }
141
+
142
+ logger_.detailed("\nProcessed variable bound types:");
143
+ logger_.detailed(" Fixed variables: " + std::to_string(proc_var_fixed));
144
+ logger_.detailed(" Boxed variables: " + std::to_string(proc_var_boxed));
145
+ logger_.detailed(" Lower bounded only: " +
146
+ std::to_string(proc_var_lower_only));
147
+ logger_.detailed(" Upper bounded only: " +
148
+ std::to_string(proc_var_upper_only));
149
+ logger_.detailed(" Free variables: " + std::to_string(proc_var_free));
150
+ }
151
+
152
+ void PDLPSolver::preprocessLp() {
153
+ #if PDLP_PROFILE
154
+ hipdlpTimerStart(kHipdlpClockPreprocess);
155
+ #endif
156
+ logger_.detailed(
157
+ "Preprocessing LP using cupdlp formulation (slack variables for "
158
+ "bounds)...");
159
+
160
+ HighsInt nRows_orig = original_lp_->num_row_;
161
+ HighsInt nCols_orig = original_lp_->num_col_;
162
+
163
+ if (original_lp_->a_matrix_.isRowwise()) {
164
+ logger_.info("Original LP matrix must be in column-wise format,");
165
+ }
166
+
167
+ lp_.offset_ = original_lp_->offset_;
168
+
169
+ HighsInt num_new_cols = 0;
170
+ HighsInt nEqs = 0;
171
+ sense_origin_ = (original_lp_->sense_ == ObjSense::kMinimize) ? 1 : -1;
172
+ constraint_types_.resize(nRows_orig);
173
+
174
+ // 1. First pass: Classify constraints and count slack variables needed
175
+ for (HighsInt i = 0; i < nRows_orig; ++i) {
176
+ bool has_lower = original_lp_->row_lower_[i] > -kHighsInf;
177
+ bool has_upper = original_lp_->row_upper_[i] < kHighsInf;
178
+
179
+ if (has_lower && has_upper) {
180
+ if (original_lp_->row_lower_[i] == original_lp_->row_upper_[i]) {
181
+ constraint_types_[i] = EQ;
182
+ nEqs++;
183
+ } else {
184
+ constraint_types_[i] = BOUND;
185
+ num_new_cols++;
186
+ nEqs++;
187
+ }
188
+ } else if (has_lower) {
189
+ constraint_types_[i] = GEQ;
190
+ } else if (has_upper) {
191
+ constraint_types_[i] = LEQ;
192
+ } else {
193
+ constraint_types_[i] = FREE;
194
+ num_new_cols++;
195
+ nEqs++;
196
+ }
197
+ }
198
+
199
+ // 2. Set new dimensions
200
+ HighsLp& processed_lp = lp_;
201
+ processed_lp.num_col_ = nCols_orig + num_new_cols;
202
+ processed_lp.num_row_ = nRows_orig;
203
+ original_num_col_ = nCols_orig;
204
+ constraint_new_idx_.resize(nRows_orig);
205
+
206
+ processed_lp.col_cost_.resize(processed_lp.num_col_);
207
+ processed_lp.col_lower_.resize(processed_lp.num_col_);
208
+ processed_lp.col_upper_.resize(processed_lp.num_col_);
209
+ processed_lp.row_lower_.resize(processed_lp.num_row_);
210
+ processed_lp.row_upper_.resize(processed_lp.num_row_);
211
+
212
+ // 3. Determine row permutation: EQ/BOUND/FREE first, then LEQ/GEQ
213
+ HighsInt eq_idx = 0;
214
+ HighsInt ineq_idx = nEqs;
215
+ for (HighsInt i = 0; i < nRows_orig; ++i) {
216
+ if (constraint_types_[i] == EQ || constraint_types_[i] == BOUND ||
217
+ constraint_types_[i] == FREE) {
218
+ constraint_new_idx_[i] = eq_idx++;
219
+ } else {
220
+ constraint_new_idx_[i] = ineq_idx++;
221
+ }
222
+ }
223
+
224
+ // 4. Create is_equality_row_ vector based on NEW ordering
225
+ is_equality_row_.resize(nRows_orig, false);
226
+ for (HighsInt i = 0; i < nRows_orig; ++i) {
227
+ HighsInt new_row_idx = constraint_new_idx_[i];
228
+ is_equality_row_[new_row_idx] =
229
+ (constraint_types_[i] == EQ || constraint_types_[i] == BOUND ||
230
+ constraint_types_[i] == FREE);
231
+ }
232
+
233
+ // 5. Populate costs and bounds for original and new slack variables
234
+ for (HighsInt i = 0; i < nCols_orig; ++i) {
235
+ processed_lp.col_cost_[i] = original_lp_->col_cost_[i];
236
+ processed_lp.col_lower_[i] = original_lp_->col_lower_[i];
237
+ processed_lp.col_upper_[i] = original_lp_->col_upper_[i];
238
+ }
239
+
240
+ HighsInt current_slack_col = nCols_orig;
241
+ for (HighsInt i = 0; i < nRows_orig; ++i) {
242
+ if (constraint_types_[i] == BOUND || constraint_types_[i] == FREE) {
243
+ processed_lp.col_cost_[current_slack_col] = 0.0;
244
+ processed_lp.col_lower_[current_slack_col] = original_lp_->row_lower_[i];
245
+ processed_lp.col_upper_[current_slack_col] = original_lp_->row_upper_[i];
246
+ current_slack_col++;
247
+ }
248
+ }
249
+
250
+ // 6. Set the new RHS (row bounds) in PERMUTED order
251
+ for (HighsInt i = 0; i < nRows_orig; ++i) {
252
+ HighsInt new_row_idx = constraint_new_idx_[i];
253
+ switch (constraint_types_[i]) {
254
+ case EQ:
255
+ processed_lp.row_lower_[new_row_idx] = original_lp_->row_lower_[i];
256
+ processed_lp.row_upper_[new_row_idx] = original_lp_->row_upper_[i];
257
+ break;
258
+ case GEQ:
259
+ processed_lp.row_lower_[new_row_idx] = original_lp_->row_lower_[i];
260
+ processed_lp.row_upper_[new_row_idx] = kHighsInf;
261
+ break;
262
+ case LEQ:
263
+ // Becomes -ax >= -b
264
+ processed_lp.row_lower_[new_row_idx] = -original_lp_->row_upper_[i];
265
+ processed_lp.row_upper_[new_row_idx] = kHighsInf;
266
+ break;
267
+ case BOUND:
268
+ case FREE:
269
+ // Becomes ax - z = 0
270
+ processed_lp.row_lower_[new_row_idx] = 0.0;
271
+ processed_lp.row_upper_[new_row_idx] = 0.0;
272
+ break;
273
+ }
274
+ }
275
+
276
+ // 7. Build the constraint matrix with proper row ordering
277
+ // First, get the original matrix in column-wise format
278
+ HighsSparseMatrix original_matrix = original_lp_->a_matrix_;
279
+ original_matrix.ensureColwise();
280
+
281
+ // Create new matrix
282
+ HighsSparseMatrix& processed_matrix = processed_lp.a_matrix_;
283
+ processed_matrix.clear();
284
+ processed_matrix.format_ = MatrixFormat::kColwise;
285
+ processed_matrix.num_col_ = processed_lp.num_col_;
286
+ processed_matrix.num_row_ = processed_lp.num_row_;
287
+
288
+ // Reserve space
289
+ processed_matrix.start_.resize(processed_lp.num_col_ + 1);
290
+ processed_matrix.index_.reserve(original_matrix.numNz() + num_new_cols);
291
+ processed_matrix.value_.reserve(original_matrix.numNz() + num_new_cols);
292
+
293
+ // Build column by column
294
+ processed_matrix.start_[0] = 0;
295
+ for (HighsInt col = 0; col < nCols_orig; ++col) {
296
+ // For each column, add entries in the new row order
297
+ std::vector<std::pair<HighsInt, double>> col_entries;
298
+
299
+ for (HighsInt el = original_matrix.start_[col];
300
+ el < original_matrix.start_[col + 1]; ++el) {
301
+ HighsInt old_row = original_matrix.index_[el];
302
+ HighsInt new_row = constraint_new_idx_[old_row];
303
+ double val = original_matrix.value_[el];
304
+
305
+ // Apply scaling for LEQ constraints
306
+ if (constraint_types_[old_row] == LEQ) {
307
+ val = -val;
308
+ }
309
+
310
+ col_entries.push_back({new_row, val});
311
+ }
312
+
313
+ // Sort by row index to maintain proper sparse matrix format
314
+ std::sort(col_entries.begin(), col_entries.end());
315
+
316
+ // Add to matrix
317
+ for (const auto& entry : col_entries) {
318
+ processed_matrix.index_.push_back(entry.first);
319
+ processed_matrix.value_.push_back(entry.second);
320
+ }
321
+
322
+ processed_matrix.start_[col + 1] = processed_matrix.index_.size();
323
+ }
324
+
325
+ // Add slack variable columns
326
+ current_slack_col = nCols_orig;
327
+ for (HighsInt i = 0; i < nRows_orig; ++i) {
328
+ if (constraint_types_[i] == BOUND || constraint_types_[i] == FREE) {
329
+ HighsInt row_idx = constraint_new_idx_[i];
330
+ processed_matrix.index_.push_back(row_idx);
331
+ processed_matrix.value_.push_back(-1.0);
332
+ processed_matrix.start_[current_slack_col + 1] =
333
+ processed_matrix.index_.size();
334
+ current_slack_col++;
335
+ }
336
+ }
337
+
338
+ num_eq_rows_ = nEqs;
339
+ scaling_.passLp(&processed_lp);
340
+ unscaled_processed_lp_ = processed_lp;
341
+
342
+ // 8. Compute and store norms of unscaled cost and rhs
343
+ unscaled_c_norm_ = linalg::vectorNorm(processed_lp.col_cost_);
344
+ unscaled_rhs_norm_ = linalg::vectorNorm(processed_lp.row_lower_);
345
+
346
+ logger_.detailed("Preprocessing complete. New dimensions: " +
347
+ std::to_string(processed_lp.num_row_) + " rows, " +
348
+ std::to_string(processed_lp.num_col_) + " cols.");
349
+ logger_.detailed(
350
+ "Unscaled norms: ||c|| = " + std::to_string(unscaled_c_norm_) +
351
+ ", ||b|| = " + std::to_string(unscaled_rhs_norm_));
352
+
353
+ printConstraintInfo();
354
+ #if PDLP_PROFILE
355
+ hipdlpTimerStop(kHipdlpClockPreprocess);
356
+ #endif
357
+ }
358
+
359
+ PostSolveRetcode PDLPSolver::postprocess(HighsSolution& solution) {
360
+ logger_.detailed("Post-solving the solution...");
361
+
362
+ #if PDLP_PROFILE
363
+ hipdlpTimerStart(kHipdlpClockPostprocess);
364
+ #endif
365
+ if (original_lp_ == nullptr) {
366
+ return PostSolveRetcode::DIMENSION_MISMATCH;
367
+ }
368
+
369
+ if (x_current_.empty() || y_current_.empty()) {
370
+ return PostSolveRetcode::INVALID_SOLUTION;
371
+ }
372
+
373
+ if (x_current_.size() != static_cast<size_t>(lp_.num_col_) ||
374
+ y_current_.size() != static_cast<size_t>(lp_.num_row_)) {
375
+ logger_.info("Solution dimension mismatch: x_current size=" +
376
+ std::to_string(x_current_.size()) +
377
+ " vs expected=" + std::to_string(lp_.num_col_) +
378
+ ", y_current size=" + std::to_string(y_current_.size()) +
379
+ " vs expected=" + std::to_string(lp_.num_row_));
380
+ return PostSolveRetcode::DIMENSION_MISMATCH;
381
+ }
382
+
383
+ // 2. Resize solution object to original dimensions
384
+ solution.col_value.resize(original_num_col_);
385
+ solution.row_value.resize(original_lp_->num_row_);
386
+ solution.col_dual.resize(original_num_col_);
387
+ solution.row_dual.resize(original_lp_->num_row_);
388
+
389
+ // 3. Recover Primal Column Values (x)
390
+ for (HighsInt i = 0; i < original_lp_->num_col_; ++i) {
391
+ if (i >= (HighsInt)x_current_.size()) {
392
+ logger_.info("Index " + std::to_string(i) +
393
+ " out of bounds for x_current_ of size " +
394
+ std::to_string(x_current_.size()));
395
+ return PostSolveRetcode::DIMENSION_MISMATCH;
396
+ }
397
+
398
+ solution.col_value[i] = x_current_[i];
399
+
400
+ if (!std::isfinite(solution.col_value[i])) {
401
+ logger_.info("Non-finite primal variable value at index " +
402
+ std::to_string(i) + ": " +
403
+ std::to_string(solution.col_value[i]));
404
+ return PostSolveRetcode::NUMERICAL_ERROR;
405
+ }
406
+ }
407
+
408
+ double final_primal_objective = original_lp_->offset_;
409
+ for (HighsInt i = 0; i < original_num_col_; ++i) {
410
+ final_primal_objective +=
411
+ original_lp_->col_cost_[i] * solution.col_value[i];
412
+ }
413
+ results_.primal_obj = final_primal_objective;
414
+
415
+ // 4. Recover Dual Row Values (y)
416
+ std::vector<double> y_reordered = y_current_;
417
+ for (HighsInt orig_row = 0; orig_row < original_lp_->num_row_; ++orig_row) {
418
+ HighsInt reordered_row = constraint_new_idx_[orig_row];
419
+
420
+ // Get the dual value from the reordered position
421
+ double dual_value = y_reordered[reordered_row];
422
+
423
+ // Apply sign correction for LEQ constraints
424
+ if (constraint_types_[orig_row] == LEQ) {
425
+ solution.row_dual[orig_row] = -dual_value;
426
+ } else {
427
+ solution.row_dual[orig_row] = dual_value;
428
+ }
429
+ }
430
+
431
+ // 5. Recover Primal Row Values (ax)
432
+ const std::vector<double>& row_scale = scaling_.getRowScaling();
433
+ const std::vector<double>& col_scale = scaling_.getColScaling();
434
+ if (scaling_.isScaled()) {
435
+ // Unscale matrix, costs, and rhs
436
+ for (HighsInt iCol = 0; iCol < unscaled_processed_lp_.num_col_; ++iCol) {
437
+ unscaled_processed_lp_.col_cost_[iCol] /= col_scale[iCol];
438
+ for (HighsInt iEl = unscaled_processed_lp_.a_matrix_.start_[iCol];
439
+ iEl < unscaled_processed_lp_.a_matrix_.start_[iCol + 1]; ++iEl) {
440
+ HighsInt iRow = unscaled_processed_lp_.a_matrix_.index_[iEl];
441
+ unscaled_processed_lp_.a_matrix_.value_[iEl] /=
442
+ (row_scale[iRow] * col_scale[iCol]);
443
+ }
444
+ }
445
+ }
446
+
447
+ std::vector<double> ax_original(original_lp_->num_row_, 0.0);
448
+
449
+ // Get original matrix in column-wise format
450
+ HighsSparseMatrix orig_matrix = original_lp_->a_matrix_;
451
+ orig_matrix.ensureColwise();
452
+
453
+ // Compute ax using only the original columns (not slack variables)
454
+ for (HighsInt col = 0; col < original_num_col_; ++col) {
455
+ double x_val = x_current_[col]; // Use unscaled x values
456
+
457
+ for (HighsInt el = orig_matrix.start_[col];
458
+ el < orig_matrix.start_[col + 1]; ++el) {
459
+ HighsInt row = orig_matrix.index_[el];
460
+ double a_val = orig_matrix.value_[el];
461
+ ax_original[row] += a_val * x_val;
462
+ }
463
+ }
464
+
465
+ // Now ax_original contains the correct row activity values
466
+ for (HighsInt orig_row = 0; orig_row < original_lp_->num_row_; ++orig_row) {
467
+ solution.row_value[orig_row] = ax_original[orig_row];
468
+ }
469
+
470
+ // 6. Recover Dual Column Values (Reduced Costs)
471
+ // The duals on the variable bounds l <= x <= u are the reduced costs.
472
+ // In the PDLP framework, these are given by dSlackPos - dSlackNeg.
473
+ for (HighsInt i = 0; i < original_num_col_; ++i) {
474
+ if (i >= (HighsInt)dSlackPos_.size() || i >= (HighsInt)dSlackNeg_.size()) {
475
+ logger_.info("Index " + std::to_string(i) +
476
+ " out of bounds for dSlackPos/Neg of size " +
477
+ std::to_string(dSlackPos_.size()));
478
+ return PostSolveRetcode::DIMENSION_MISMATCH;
479
+ }
480
+ solution.col_dual[i] = dSlackPos_[i] - dSlackNeg_[i];
481
+ solution.col_dual[i] *= sense_origin_;
482
+ }
483
+
484
+ solution.value_valid = true; // to do
485
+ solution.dual_valid = true;
486
+ logger_.detailed("Post-solve complete.");
487
+
488
+ #if PDLP_PROFILE
489
+ hipdlpTimerStop(kHipdlpClockPostprocess);
490
+ #endif
491
+ return PostSolveRetcode::OK;
492
+ }
493
+
494
+ void PDLPSolver::solve(std::vector<double>& x, std::vector<double>& y) {
495
+ #if PDLP_PROFILE
496
+ hipdlpTimerStart(kHipdlpClockSolve);
497
+ #endif
498
+
499
+ // 1. Initialization and setup
500
+ #ifdef CUPDLP_GPU
501
+ setupGpu();
502
+ #endif
503
+ initializeStepSizes();
504
+ initialize(); // Resets vectors, caches, and sets initial x_current,
505
+ // y_current
506
+ best_primal_weight_ = primal_weight_;
507
+ best_primal_dual_residual_gap_ = std::numeric_limits<double>::infinity();
508
+
509
+ // initialize internal solver state
510
+ restart_scheme_.passParams(&params_);
511
+ restart_scheme_.initialize(results_);
512
+
513
+ // Copy initial input x,y to internal state
514
+ x_current_ = x;
515
+ y_current_ = y;
516
+
517
+ if (params_.use_halpern_restart) {
518
+ x_anchor_ = x_current_;
519
+ y_anchor_ = y_current_;
520
+ halpern_iteration_ = 0;
521
+ #ifdef CUPDLP_GPU
522
+ CUDA_CHECK(cudaMemcpy(d_x_anchor_, d_x_current_,
523
+ lp_.num_col_ * sizeof(double),
524
+ cudaMemcpyDeviceToDevice));
525
+ CUDA_CHECK(cudaMemcpy(d_y_anchor_, d_y_current_,
526
+ lp_.num_row_ * sizeof(double),
527
+ cudaMemcpyDeviceToDevice));
528
+ #endif
529
+ }
530
+
531
+ // Pre-calculate ax and aTy for current iterate
532
+ #ifdef CUPDLP_GPU
533
+ CUDA_CHECK(cudaMemset(d_x_sum_, 0, lp_.num_col_ * sizeof(double)));
534
+ CUDA_CHECK(cudaMemset(d_y_sum_, 0, lp_.num_row_ * sizeof(double)));
535
+ CUDA_CHECK(cudaMemset(d_x_avg_, 0, lp_.num_col_ * sizeof(double)));
536
+ CUDA_CHECK(cudaMemset(d_y_avg_, 0, lp_.num_row_ * sizeof(double)));
537
+ sum_weights_gpu_ = 0.0;
538
+ CUDA_CHECK(cudaMemcpy(d_x_current_, x.data(), lp_.num_col_ * sizeof(double),
539
+ cudaMemcpyHostToDevice));
540
+ CUDA_CHECK(cudaMemcpy(d_y_current_, y.data(), lp_.num_row_ * sizeof(double),
541
+ cudaMemcpyHostToDevice));
542
+ linalgGpuAx(d_x_current_, d_ax_current_);
543
+ linalgGpuATy(d_y_current_, d_aty_current_);
544
+ #else
545
+ linalg::projectBounds(lp_, x_current_);
546
+ linalg::ax(lp_, x_current_, Ax_cache_);
547
+ linalg::aTy(lp_, y_current_, ATy_cache_);
548
+ #endif
549
+
550
+ TerminationStatus termination_status = TerminationStatus::NOTSET;
551
+ bool do_restart = false;
552
+ double last_trial_fpe = std::numeric_limits<double>::infinity();
553
+ final_iter_count_ = 0;
554
+
555
+ // =========================================================================
556
+ // INITIAL CONVERGENCE CHECK (ITERATION 0)
557
+ // =========================================================================
558
+ bool should_terminate =
559
+ runConvergenceCheck(final_iter_count_, x, y, termination_status);
560
+
561
+ if (should_terminate) {
562
+ solveReturn(termination_status);
563
+ return;
564
+ }
565
+
566
+ #ifdef CUPDLP_GPU
567
+ bool graph_created = false;
568
+ cudaGraphExec_t graphExec = nullptr;
569
+ #endif
570
+
571
+ // 2. Main cuPDLPx-style Loop
572
+ while (final_iter_count_ < params_.max_iterations) {
573
+ // check global time limit
574
+ if (highs_timer_p_->read() > params_.time_limit) {
575
+ logger_.info("Time limit reached.");
576
+ termination_status = TerminationStatus::TIMEOUT;
577
+ break;
578
+ }
579
+
580
+ // -- Step 1 (Major, isolated for restart-FPE check) --
581
+ #ifdef CUPDLP_GPU
582
+ CUDA_CHECK(cudaMemcpyAsync(d_primal_step_size_, &stepsize_.primal_step,
583
+ sizeof(double), cudaMemcpyHostToDevice,
584
+ gpu_stream_));
585
+ CUDA_CHECK(cudaMemcpyAsync(d_dual_step_size_, &stepsize_.dual_step,
586
+ sizeof(double), cudaMemcpyHostToDevice,
587
+ gpu_stream_));
588
+ CUDA_CHECK(cudaMemcpyAsync(d_halpern_iteration_, &halpern_iteration_,
589
+ sizeof(int), cudaMemcpyHostToDevice,
590
+ gpu_stream_));
591
+ performHalpernPdhgStepGpu(true, 1);
592
+ #else
593
+ performHalpernPdhgStep(true, 1);
594
+ #endif
595
+
596
+ if (do_restart) {
597
+ #ifdef CUPDLP_GPU
598
+ fpe_ = computeFixedPointErrorGpu();
599
+ #else
600
+ fpe_ = computeFixedPointError();
601
+ #endif
602
+ initial_fpe_ = fpe_;
603
+ do_restart = false;
604
+ }
605
+ // -- Steps 2 to PDHG_CHECK_INTERVAL - 1 (Minor) --
606
+ #ifdef CUPDLP_GPU
607
+ if (!graph_created) {
608
+ CUDA_CHECK(
609
+ cudaStreamBeginCapture(gpu_stream_, cudaStreamCaptureModeGlobal));
610
+
611
+ for (int i = 2; i <= PDHG_CHECK_INTERVAL - 1; i++) {
612
+ performHalpernPdhgStepGpu(false, i);
613
+ }
614
+ performHalpernPdhgStepGpu(true, PDHG_CHECK_INTERVAL);
615
+
616
+ cudaGraph_t graph;
617
+ CUDA_CHECK(cudaStreamEndCapture(gpu_stream_, &graph));
618
+ CUDA_CHECK(cudaGraphInstantiate(&graphExec, graph, NULL, NULL, 0));
619
+ CUDA_CHECK(cudaGraphDestroy(graph));
620
+ graph_created = true;
621
+ }
622
+
623
+ CUDA_CHECK(cudaGraphLaunch(graphExec, gpu_stream_));
624
+ #else
625
+ for (int i = 2; i <= PDHG_CHECK_INTERVAL - 1; i++) {
626
+ performHalpernPdhgStep(false, i);
627
+ }
628
+ performHalpernPdhgStep(true, PDHG_CHECK_INTERVAL);
629
+ #endif
630
+
631
+ // Compute Error for Restart Check
632
+ #ifdef CUPDLP_GPU
633
+ fpe_ = computeFixedPointErrorGpu();
634
+ #else
635
+ fpe_ = computeFixedPointError();
636
+ #endif
637
+ halpern_iteration_ += PDHG_CHECK_INTERVAL;
638
+ final_iter_count_ += PDHG_CHECK_INTERVAL;
639
+
640
+ // =======================================================================
641
+ // CONVERGENCE CHECK
642
+ // =======================================================================
643
+ TerminationStatus check_status;
644
+ should_terminate =
645
+ runConvergenceCheck(final_iter_count_, x, y, check_status);
646
+ if (should_terminate) {
647
+ termination_status = check_status;
648
+ break;
649
+ }
650
+
651
+ // =======================================================================
652
+ // RESTART CHECK
653
+ // =======================================================================
654
+ do_restart = checkRestartCriteria(fpe_, initial_fpe_, last_trial_fpe,
655
+ halpern_iteration_, final_iter_count_);
656
+ last_trial_fpe = fpe_;
657
+
658
+ // -- Perform Restart --
659
+ if (do_restart) {
660
+ if (params_.step_size_strategy == StepSizeStrategy::PID) {
661
+ updatePrimalWeightAtRestart(results_);
662
+ }
663
+ #ifdef CUPDLP_GPU
664
+ CUDA_CHECK(cudaMemcpy(d_x_anchor_, d_pdhg_primal_,
665
+ lp_.num_col_ * sizeof(double),
666
+ cudaMemcpyDeviceToDevice));
667
+ CUDA_CHECK(cudaMemcpy(d_y_anchor_, d_pdhg_dual_,
668
+ lp_.num_row_ * sizeof(double),
669
+ cudaMemcpyDeviceToDevice));
670
+ CUDA_CHECK(cudaMemcpy(d_x_current_, d_pdhg_primal_,
671
+ lp_.num_col_ * sizeof(double),
672
+ cudaMemcpyDeviceToDevice));
673
+ CUDA_CHECK(cudaMemcpy(d_y_current_, d_pdhg_dual_,
674
+ lp_.num_row_ * sizeof(double),
675
+ cudaMemcpyDeviceToDevice));
676
+ #else
677
+ x_anchor_ = x_next_;
678
+ y_anchor_ = y_next_;
679
+ x_current_ = x_next_;
680
+ y_current_ = y_next_;
681
+ linalg::ax(lp_, x_current_, Ax_cache_);
682
+ linalg::aTy(lp_, y_current_, ATy_cache_);
683
+ #endif
684
+
685
+ halpern_iteration_ = 0;
686
+ last_trial_fpe = std::numeric_limits<double>::infinity();
687
+ }
688
+ }
689
+
690
+ #ifdef CUPDLP_GPU
691
+ if (graphExec) {
692
+ CUDA_CHECK(cudaGraphExecDestroy(graphExec));
693
+ }
694
+ #endif
695
+
696
+ // 3. Loop Finished
697
+ if (termination_status == TerminationStatus::NOTSET) {
698
+ logger_.info("Iteration limit reached without convergence");
699
+ termination_status = TerminationStatus::MAXITER;
700
+ }
701
+
702
+ solveReturn(termination_status);
703
+ }
704
+
705
+ double PDLPSolver::computeFixedPointError() {
706
+ double primal_norm_sq = 0.0;
707
+ double dual_norm_sq = 0.0;
708
+ double cross_term = 0.0;
709
+
710
+ std::vector<double> delta_x(lp_.num_col_);
711
+ std::vector<double> delta_y(lp_.num_row_);
712
+
713
+ for (int i = 0; i < lp_.num_col_; ++i) {
714
+ delta_x[i] = x_next_[i] - reflected_x_[i];
715
+ primal_norm_sq += delta_x[i] * delta_x[i];
716
+ }
717
+
718
+ for (int i = 0; i < lp_.num_row_; ++i) {
719
+ delta_y[i] = y_next_[i] - reflected_y_[i];
720
+ dual_norm_sq += delta_y[i] * delta_y[i];
721
+ }
722
+
723
+ std::vector<double> AT_delta_y(lp_.num_col_, 0.0);
724
+ linalg::aTy(lp_, delta_y, AT_delta_y);
725
+
726
+ for (int i = 0; i < lp_.num_col_; ++i) {
727
+ cross_term += delta_x[i] * AT_delta_y[i];
728
+ }
729
+
730
+ double movement =
731
+ primal_norm_sq * params_.omega + dual_norm_sq / params_.omega;
732
+ double interaction = 2.0 * params_.eta * cross_term;
733
+
734
+ return std::sqrt(std::max(0.0, movement + interaction));
735
+ }
736
+
737
+ #ifdef CUPDLP_GPU
738
+ double PDLPSolver::computeFixedPointErrorGpu() {
739
+ double alpha_minus_one = -1.0;
740
+
741
+ // 1. delta_x = x_next_ - reflected_x_
742
+ // (Assuming d_pdhg_primal_ maps to x_next_ and d_x_next_ is used as
743
+ // reflected_x_ in your minor/major steps)
744
+ CUDA_CHECK(cudaMemcpy(d_delta_x_, d_pdhg_primal_,
745
+ a_num_cols_ * sizeof(double),
746
+ cudaMemcpyDeviceToDevice));
747
+ CUBLAS_CHECK(cublasDaxpy(cublas_handle_, a_num_cols_, &alpha_minus_one,
748
+ d_x_next_, 1, d_delta_x_, 1));
749
+
750
+ // 2. delta_y = y_next_ - reflected_y_
751
+ CUDA_CHECK(cudaMemcpy(d_delta_y_, d_pdhg_dual_, a_num_rows_ * sizeof(double),
752
+ cudaMemcpyDeviceToDevice));
753
+ CUBLAS_CHECK(cublasDaxpy(cublas_handle_, a_num_rows_, &alpha_minus_one,
754
+ d_y_next_, 1, d_delta_y_, 1));
755
+
756
+ // 3. AT_delta_y = A^T * delta_y
757
+ linalgGpuATy(d_delta_y_, d_AT_delta_y_);
758
+
759
+ // 4. Compute norms and cross term
760
+ double primal_norm = 0.0, dual_norm = 0.0, cross_term = 0.0;
761
+
762
+ CUBLAS_CHECK(
763
+ cublasDnrm2(cublas_handle_, a_num_cols_, d_delta_x_, 1, &primal_norm));
764
+ CUBLAS_CHECK(
765
+ cublasDnrm2(cublas_handle_, a_num_rows_, d_delta_y_, 1, &dual_norm));
766
+ CUBLAS_CHECK(cublasDdot(cublas_handle_, a_num_cols_, d_delta_x_, 1,
767
+ d_AT_delta_y_, 1, &cross_term));
768
+
769
+ double primal_norm_sq = primal_norm * primal_norm;
770
+ double dual_norm_sq = dual_norm * dual_norm;
771
+
772
+ double movement =
773
+ primal_norm_sq * params_.omega + dual_norm_sq / params_.omega;
774
+ double interaction = 2.0 * params_.eta * cross_term;
775
+
776
+ return std::sqrt(std::max(0.0, movement + interaction));
777
+ }
778
+ #endif
779
+
780
+ bool PDLPSolver::runConvergenceCheck(size_t iter, std::vector<double>& output_x,
781
+ std::vector<double>& output_y,
782
+ TerminationStatus& status) {
783
+ // 1. Compute Average Iterate (GPU or CPU)
784
+ #ifdef CUPDLP_GPU
785
+ computeAverageIterateGpu();
786
+ #else
787
+ computeAverageIterate(Ax_avg_, ATy_avg_);
788
+ #endif
789
+
790
+ SolverResults current_results;
791
+ SolverResults average_results;
792
+ bool current_converged = false;
793
+ bool average_converged = false;
794
+
795
+ // 2. Check Convergence (GPU or CPU)
796
+ #ifdef CUPDLP_GPU
797
+ // Only use Halpern PDHG slack/iterates if we have performed at least one
798
+ // iteration
799
+ if (params_.use_halpern_restart && d_pdhg_primal_ != nullptr && iter > 0) {
800
+ linalgGpuAx(d_pdhg_primal_, d_ax_next_);
801
+ linalgGpuATy(d_pdhg_dual_, d_aty_next_);
802
+ current_converged =
803
+ checkConvergenceGpu(iter, d_pdhg_primal_, d_pdhg_dual_, d_ax_next_,
804
+ d_aty_next_, params_.tolerance, current_results,
805
+ "[L-GPU]", d_dSlackPos_, d_dSlackNeg_, true);
806
+ } else {
807
+ current_converged =
808
+ checkConvergenceGpu(iter, d_x_current_, d_y_current_, d_ax_current_,
809
+ d_aty_current_, params_.tolerance, current_results,
810
+ "[L-GPU]", d_dSlackPos_, d_dSlackNeg_, false);
811
+ average_converged = checkConvergenceGpu(
812
+ iter, d_x_avg_, d_y_avg_, d_ax_avg_, d_aty_avg_, params_.tolerance,
813
+ average_results, "[A-GPU]", d_dSlackPosAvg_, d_dSlackNegAvg_, false);
814
+ }
815
+
816
+ #else
817
+ if (params_.use_halpern_restart && iter > 0) {
818
+ std::vector<double> Ax_pdhg(lp_.num_row_);
819
+ std::vector<double> ATy_pdhg(lp_.num_col_);
820
+ linalg::ax(lp_, x_next_, Ax_pdhg);
821
+ linalg::aTy(lp_, y_next_, ATy_pdhg);
822
+ current_converged = checkConvergence(
823
+ iter, x_next_, y_next_, Ax_pdhg, ATy_pdhg, params_.tolerance,
824
+ current_results, "[L]", dSlackPos_, dSlackNeg_);
825
+ } else {
826
+ current_converged = checkConvergence(
827
+ iter, x_current_, y_current_, Ax_cache_, ATy_cache_, params_.tolerance,
828
+ current_results, "[L]", dSlackPos_, dSlackNeg_);
829
+ }
830
+ average_converged = checkConvergence(iter, x_avg_, y_avg_, Ax_avg_, ATy_avg_,
831
+ params_.tolerance, average_results,
832
+ "[A]", dSlackPosAvg_, dSlackNegAvg_);
833
+ #endif
834
+
835
+ // 3. Handle Convergence Success
836
+ if (current_converged || average_converged) {
837
+ bool prefer_avg = average_converged;
838
+
839
+ // Copy result to output vectors
840
+ #ifdef CUPDLP_GPU
841
+ double* src_x = prefer_avg ? d_x_avg_
842
+ : (params_.use_halpern_restart ? d_pdhg_primal_
843
+ : d_x_current_);
844
+ double* src_y = prefer_avg ? d_y_avg_
845
+ : (params_.use_halpern_restart ? d_pdhg_dual_
846
+ : d_y_current_);
847
+ double* src_sp = prefer_avg ? d_dSlackPosAvg_ : d_dSlackPos_;
848
+ double* src_sn = prefer_avg ? d_dSlackNegAvg_ : d_dSlackNeg_;
849
+
850
+ CUDA_CHECK(cudaMemcpy(output_x.data(), src_x, lp_.num_col_ * sizeof(double),
851
+ cudaMemcpyDeviceToHost));
852
+ CUDA_CHECK(cudaMemcpy(output_y.data(), src_y, lp_.num_row_ * sizeof(double),
853
+ cudaMemcpyDeviceToHost));
854
+ CUDA_CHECK(cudaMemcpy(dSlackPos_.data(), src_sp,
855
+ lp_.num_col_ * sizeof(double),
856
+ cudaMemcpyDeviceToHost));
857
+ CUDA_CHECK(cudaMemcpy(dSlackNeg_.data(), src_sn,
858
+ lp_.num_col_ * sizeof(double),
859
+ cudaMemcpyDeviceToHost));
860
+ #else
861
+ if (prefer_avg) {
862
+ output_x = x_avg_;
863
+ output_y = y_avg_;
864
+ dSlackPos_ = dSlackPosAvg_;
865
+ dSlackNeg_ = dSlackNegAvg_;
866
+ } else if (params_.use_halpern_restart && iter > 0) {
867
+ output_x = x_next_;
868
+ output_y = y_next_;
869
+ } else {
870
+ output_x = x_current_;
871
+ output_y = y_current_;
872
+ }
873
+ #endif
874
+
875
+ final_iter_count_ = iter;
876
+ results_ = prefer_avg ? average_results : current_results;
877
+ // Final logging on optimality
878
+ const bool forced = true;
879
+ logger_.printIterationStats(final_iter_count_, results_, primal_weight_,
880
+ forced);
881
+ logger_.info((prefer_avg ? "Average" : "Current") +
882
+ std::string(" solution converged"));
883
+
884
+ status = TerminationStatus::OPTIMAL;
885
+ return true; // Stop
886
+ } else {
887
+ // Log the iteration if not converged
888
+ logger_.printIterationStats(iter, current_results, primal_weight_);
889
+ }
890
+
891
+ results_ = current_results;
892
+ return false;
893
+ }
894
+
895
+ bool PDLPSolver::checkRestartCriteria(double current_fpe, double initial_fpe,
896
+ double last_trial_fpe,
897
+ int halpern_iteration,
898
+ int final_iter_count) {
899
+ if (final_iter_count == PDHG_CHECK_INTERVAL) {
900
+ return true;
901
+ }
902
+
903
+ if (final_iter_count > PDHG_CHECK_INTERVAL) {
904
+ if (current_fpe <=
905
+ restart_scheme_.getSufficientDecayFactor() * initial_fpe) {
906
+ return true;
907
+ }
908
+ if (current_fpe <=
909
+ restart_scheme_.getNecessaryDecayFactor() * initial_fpe) {
910
+ if (current_fpe > last_trial_fpe) {
911
+ return true;
912
+ }
913
+ }
914
+ if (halpern_iteration >=
915
+ restart_scheme_.getArtificialRestartThreshold() * final_iter_count) {
916
+ return true;
917
+ }
918
+ }
919
+
920
+ return false;
921
+ }
922
+
923
+ // ----------------------------------------------------------------------------
924
+ // Helper: Perform PDHG Step
925
+ // ----------------------------------------------------------------------------
926
+ void PDLPSolver::performPdhgStep() {
927
+ #if PDLP_PROFILE
928
+ hipdlpTimerStart(kHipdlpClockIterateUpdate);
929
+ #endif
930
+
931
+ // CPU/GPU agnostic logic for step strategy
932
+ switch (params_.step_size_strategy) {
933
+ case StepSizeStrategy::FIXED:
934
+ updateIteratesFixed();
935
+ break;
936
+ case StepSizeStrategy::ADAPTIVE:
937
+ updateIteratesAdaptive();
938
+ break;
939
+ case StepSizeStrategy::MALITSKY_POCK:
940
+ // Note: Error handling for MP failure simplified for brevity
941
+ updateIteratesMalitskyPock(false);
942
+ break;
943
+ case StepSizeStrategy::PID:
944
+ assert(111 == 999);
945
+ }
946
+
947
+ #if PDLP_PROFILE
948
+ hipdlpTimerStop(kHipdlpClockIterateUpdate);
949
+ #endif
950
+ }
951
+
952
+ // ----------------------------------------------------------------------------
953
+ // Helper: Perform Halpern Step
954
+ // ----------------------------------------------------------------------------
955
+ void PDLPSolver::performHalpernPdhgStep(bool is_major, int k_offset) {
956
+ double primal_step = stepsize_.primal_step;
957
+ double dual_step = stepsize_.dual_step;
958
+ double rho = params_.halpern_gamma;
959
+
960
+ int current_k = halpern_iteration_ + k_offset;
961
+ double w = static_cast<double>(current_k) / (current_k + 1.0);
962
+
963
+ // --- STEP 1: Primal projection + reflection ---
964
+ if (is_major) {
965
+ if (halpern_dual_slack_next_.size() != static_cast<size_t>(lp_.num_col_)) {
966
+ halpern_dual_slack_next_.resize(lp_.num_col_, 0.0);
967
+ }
968
+ halpern_dual_slack_next_valid_ = true;
969
+ }
970
+ for (HighsInt i = 0; i < lp_.num_col_; i++) {
971
+ double temp =
972
+ x_current_[i] - primal_step * (lp_.col_cost_[i] - ATy_cache_[i]);
973
+ double temp_proj =
974
+ linalg::projectBox(temp, lp_.col_lower_[i], lp_.col_upper_[i]);
975
+ if (is_major) {
976
+ x_next_[i] = temp_proj; // pdhg_primal (for convergence check)
977
+ halpern_dual_slack_next_[i] = (temp_proj - temp) / primal_step;
978
+ }
979
+ reflected_x_[i] = 2.0 * temp_proj - x_current_[i];
980
+ }
981
+
982
+ // --- STEP 2: SpMV on reflected primal ---
983
+ linalg::ax(lp_, reflected_x_, Ax_next_);
984
+
985
+ // --- STEP 3: Dual projection + reflection ---
986
+ for (HighsInt j = 0; j < lp_.num_row_; j++) {
987
+ double temp = y_current_[j] / dual_step - Ax_next_[j];
988
+ double lower_proj = -lp_.row_upper_[j];
989
+ double upper_proj = -lp_.row_lower_[j];
990
+ double temp_proj = std::max(lower_proj, std::min(temp, upper_proj));
991
+
992
+ double pdhg_dual_j = (temp - temp_proj) * dual_step;
993
+
994
+ if (is_major) {
995
+ y_next_[j] = pdhg_dual_j;
996
+ }
997
+ reflected_y_[j] = 2.0 * pdhg_dual_j - y_current_[j];
998
+ }
999
+
1000
+ // --- STEP 4: Halpern blend ---
1001
+ for (HighsInt i = 0; i < lp_.num_col_; i++) {
1002
+ double blended = rho * reflected_x_[i] + (1.0 - rho) * x_current_[i];
1003
+ x_current_[i] = w * blended + (1.0 - w) * x_anchor_[i];
1004
+ }
1005
+ for (HighsInt j = 0; j < lp_.num_row_; j++) {
1006
+ double blended = rho * reflected_y_[j] + (1.0 - rho) * y_current_[j];
1007
+ y_current_[j] = w * blended + (1.0 - w) * y_anchor_[j];
1008
+ }
1009
+
1010
+ // --- STEP 5: Recompute aTy ---
1011
+ linalg::aTy(lp_, y_current_, ATy_cache_);
1012
+ }
1013
+
1014
+ // ----------------------------------------------------------------------------
1015
+ // Helper: Accumulate Averages
1016
+ // ----------------------------------------------------------------------------
1017
+ void PDLPSolver::accumulateAverages(size_t iter) {
1018
+ #if PDLP_PROFILE
1019
+ hipdlpTimerStart(kHipdlpClockAverageIterate);
1020
+ #endif
1021
+
1022
+ HighsInt inner_iter = iter - restart_scheme_.getLastRestartIter();
1023
+ double dMeanStepSize = std::sqrt(stepsize_.primal_step * stepsize_.dual_step);
1024
+
1025
+ #ifdef CUPDLP_GPU
1026
+ if (params_.use_halpern_restart) {
1027
+ // If Halpern, we average the 'current' blended iterate
1028
+ launchKernelUpdateAverages_wrapper(d_x_sum_, d_y_sum_, d_x_current_,
1029
+ d_y_current_, dMeanStepSize,
1030
+ lp_.num_col_, lp_.num_row_, gpu_stream_);
1031
+ sum_weights_gpu_ += dMeanStepSize;
1032
+ } else {
1033
+ // If standard, we average the 'next' iterate computed by PDHG
1034
+ updateAverageIteratesGpu(inner_iter);
1035
+ }
1036
+ #else
1037
+ if (params_.use_halpern_restart) {
1038
+ updateAverageIterates(x_current_, y_current_, inner_iter);
1039
+ } else {
1040
+ updateAverageIterates(x_next_, y_next_, inner_iter);
1041
+ }
1042
+ #endif
1043
+
1044
+ #if PDLP_PROFILE
1045
+ hipdlpTimerStop(kHipdlpClockAverageIterate);
1046
+ #endif
1047
+ }
1048
+
1049
+ // ----------------------------------------------------------------------------
1050
+ // Helper: Prepare for Next Iteration
1051
+ // ----------------------------------------------------------------------------
1052
+ void PDLPSolver::prepareNextIteration() {
1053
+ if (params_.use_halpern_restart) {
1054
+ // Halpern update already wrote into x_current_, no swap needed
1055
+ // Just ensure caches are correct if not done in PerformHalpernStep
1056
+ return;
1057
+ } else {
1058
+ // Standard PDHG: x_current becomes x_next
1059
+ #ifdef CUPDLP_GPU
1060
+ CUDA_CHECK(cudaMemcpy(d_x_current_, d_x_next_,
1061
+ lp_.num_col_ * sizeof(double),
1062
+ cudaMemcpyDeviceToDevice));
1063
+ CUDA_CHECK(cudaMemcpy(d_y_current_, d_y_next_,
1064
+ lp_.num_row_ * sizeof(double),
1065
+ cudaMemcpyDeviceToDevice));
1066
+ CUDA_CHECK(cudaMemcpy(d_ax_current_, d_ax_next_,
1067
+ lp_.num_row_ * sizeof(double),
1068
+ cudaMemcpyDeviceToDevice));
1069
+ CUDA_CHECK(cudaMemcpy(d_aty_current_, d_aty_next_,
1070
+ lp_.num_col_ * sizeof(double),
1071
+ cudaMemcpyDeviceToDevice));
1072
+ #else
1073
+ x_current_ = x_next_;
1074
+ y_current_ = y_next_;
1075
+ Ax_cache_ = Ax_next_;
1076
+ ATy_cache_ = ATy_next_;
1077
+ #endif
1078
+ }
1079
+ }
1080
+ #ifdef CUPDLP_GPU
1081
+ void PDLPSolver::performHalpernPdhgStepGpu(bool is_major, int k_offset) {
1082
+ linalgGpuATy(d_y_current_, d_aty_current_);
1083
+
1084
+ if (is_major) {
1085
+ launchKernelHalpernPrimalMajor_wrapper(
1086
+ d_x_current_, d_pdhg_primal_, d_x_next_ /*reflected*/,
1087
+ d_aty_current_ /*dual_product*/, d_col_cost_, d_col_lower_,
1088
+ d_col_upper_, d_primal_step_size_, a_num_cols_,
1089
+ d_dSlackPos_ /*dual_slack*/, gpu_stream_);
1090
+ } else {
1091
+ launchKernelHalpernPrimalMinor_wrapper(
1092
+ d_x_current_, d_x_next_ /*reflected*/, d_aty_current_ /*dual_product*/,
1093
+ d_col_cost_, d_col_lower_, d_col_upper_, d_primal_step_size_,
1094
+ a_num_cols_, gpu_stream_);
1095
+ }
1096
+
1097
+ linalgGpuAx(d_x_next_, d_ax_next_);
1098
+
1099
+ if (is_major) {
1100
+ launchKernelHalpernDualMajor_wrapper(
1101
+ d_y_current_, d_pdhg_dual_, d_y_next_ /*reflected*/,
1102
+ d_ax_next_ /*primal_product*/, d_row_lower_, d_is_equality_row_,
1103
+ d_dual_step_size_, a_num_rows_, gpu_stream_);
1104
+ } else {
1105
+ launchKernelHalpernDualMinor_wrapper(
1106
+ d_y_current_, d_y_next_ /*reflected*/, d_ax_next_ /*primal_product*/,
1107
+ d_row_lower_, d_is_equality_row_, d_dual_step_size_, a_num_rows_,
1108
+ gpu_stream_);
1109
+ }
1110
+
1111
+ double rho = params_.halpern_gamma;
1112
+
1113
+ launchKernelHalpernBlend_wrapper(d_x_current_, d_x_next_ /*reflected*/,
1114
+ d_x_anchor_, d_halpern_iteration_, k_offset,
1115
+ rho, a_num_cols_, gpu_stream_);
1116
+ launchKernelHalpernBlend_wrapper(d_y_current_, d_y_next_ /*reflected*/,
1117
+ d_y_anchor_, d_halpern_iteration_, k_offset,
1118
+ rho, a_num_rows_, gpu_stream_);
1119
+ }
1120
+ #endif
1121
+
1122
+ void PDLPSolver::solveReturn(const TerminationStatus term_code) {
1123
+ #ifdef CUPDLP_GPU
1124
+ cleanupGpu();
1125
+ #endif
1126
+ results_.term_code = term_code;
1127
+ #if PDLP_PROFILE
1128
+ hipdlpTimerStop(kHipdlpClockSolve);
1129
+ #endif
1130
+ }
1131
+
1132
+ void PDLPSolver::initialize() {
1133
+ // initialize x and y based on the LP problem
1134
+ x_current_.resize(lp_.num_col_, 0.0);
1135
+ y_current_.resize(lp_.num_row_, 0.0);
1136
+ x_next_.resize(lp_.num_col_, 0.0);
1137
+ y_next_.resize(lp_.num_row_, 0.0);
1138
+
1139
+ x_at_last_restart_ = x_current_;
1140
+ y_at_last_restart_ = y_current_;
1141
+ x_sum_.resize(lp_.num_col_, 0.0);
1142
+ y_sum_.resize(lp_.num_row_, 0.0);
1143
+
1144
+ sum_weights_ = 0.0;
1145
+
1146
+ x_avg_.resize(lp_.num_col_, 0.0);
1147
+ y_avg_.resize(lp_.num_row_, 0.0);
1148
+
1149
+ reflected_x_.resize(lp_.num_col_, 0.0);
1150
+ reflected_y_.resize(lp_.num_row_, 0.0);
1151
+ x_anchor_.resize(lp_.num_col_, 0.0);
1152
+ y_anchor_.resize(lp_.num_row_, 0.0);
1153
+ halpern_iteration_ = 0;
1154
+
1155
+ Ax_cache_.resize(lp_.num_row_, 0.0);
1156
+ ATy_cache_.resize(lp_.num_col_, 0.0);
1157
+ Ax_next_.resize(lp_.num_row_, 0.0);
1158
+ ATy_next_.resize(lp_.num_col_, 0.0);
1159
+
1160
+ // Member variables added back in HPP:
1161
+ Ax_avg_.resize(lp_.num_row_, 0.0);
1162
+ ATy_avg_.resize(lp_.num_col_, 0.0);
1163
+ K_times_x_diff_.resize(lp_.num_row_, 0.0);
1164
+
1165
+ dSlackPos_.resize(lp_.num_col_, 0.0);
1166
+ dSlackNeg_.resize(lp_.num_col_, 0.0);
1167
+ dSlackPosAvg_.resize(lp_.num_col_, 0.0);
1168
+ dSlackNegAvg_.resize(lp_.num_col_, 0.0);
1169
+ halpern_dual_slack_next_.resize(lp_.num_col_, 0.0);
1170
+ halpern_dual_slack_next_valid_ = false;
1171
+ }
1172
+
1173
+ // Update primal weight
1174
+ void PDLPSolver::computeStepSizeRatio(PrimalDualParams& working_params) {
1175
+ // 1. Calculate the L2 norm of the difference between current and last-restart
1176
+ // iterates.
1177
+ double primal_diff_norm = linalg::diffTwoNorm(x_at_last_restart_, x_current_);
1178
+ double dual_diff_norm = linalg::diffTwoNorm(y_at_last_restart_, y_current_);
1179
+
1180
+ double dMeanStepSize = std::sqrt(stepsize_.primal_step * stepsize_.dual_step);
1181
+
1182
+ // 2. Update the primal weight (beta = omega^2) if movements are significant.
1183
+ if (std::min(primal_diff_norm, dual_diff_norm) > 1e-10) {
1184
+ double beta_update_ratio = dual_diff_norm / primal_diff_norm;
1185
+ double old_beta = stepsize_.beta;
1186
+
1187
+ double dLogBetaUpdate =
1188
+ 0.5 * std::log(beta_update_ratio) + 0.5 * std::log(std::sqrt(old_beta));
1189
+ stepsize_.beta = std::exp(2.0 * dLogBetaUpdate);
1190
+ }
1191
+
1192
+ stepsize_.primal_step = dMeanStepSize / std::sqrt(stepsize_.beta);
1193
+ stepsize_.dual_step = stepsize_.primal_step * stepsize_.beta;
1194
+ working_params.eta = std::sqrt(stepsize_.primal_step * stepsize_.dual_step);
1195
+ working_params.omega = std::sqrt(stepsize_.beta);
1196
+ restart_scheme_.updateBeta(stepsize_.beta);
1197
+ }
1198
+
1199
+ void PDLPSolver::updateAverageIterates(const std::vector<double>& x,
1200
+ const std::vector<double>& y,
1201
+ HighsInt inner_iter) {
1202
+ double dMeanStepSize = std::sqrt(stepsize_.primal_step * stepsize_.dual_step);
1203
+
1204
+ #if PDLP_PROFILE
1205
+ hipdlpTimerStart(kHipdlpClockAverageIterateUpdateX);
1206
+ #endif
1207
+ for (size_t i = 0; i < x.size(); ++i) x_sum_[i] += x[i] * dMeanStepSize;
1208
+ #if PDLP_PROFILE
1209
+ hipdlpTimerStop(kHipdlpClockAverageIterateUpdateX);
1210
+ #endif
1211
+
1212
+ #if PDLP_PROFILE
1213
+ hipdlpTimerStart(kHipdlpClockAverageIterateUpdateY);
1214
+ #endif
1215
+ for (size_t i = 0; i < y.size(); ++i) y_sum_[i] += y[i] * dMeanStepSize;
1216
+ #if PDLP_PROFILE
1217
+ hipdlpTimerStop(kHipdlpClockAverageIterateUpdateY);
1218
+ #endif
1219
+
1220
+ sum_weights_ += dMeanStepSize;
1221
+ }
1222
+
1223
+ void PDLPSolver::computeAverageIterate(std::vector<double>& ax_avg,
1224
+ std::vector<double>& aty_avg) {
1225
+ double dPrimalScale = sum_weights_ > 1e-10 ? 1.0 / sum_weights_ : 1.0;
1226
+ double dDualScale = sum_weights_ > 1e-10 ? 1.0 / sum_weights_ : 1.0;
1227
+
1228
+ #if PDLP_PROFILE
1229
+ hipdlpTimerStart(kHipdlpClockAverageIterateComputeX);
1230
+ #endif
1231
+ for (size_t i = 0; i < x_avg_.size(); ++i)
1232
+ x_avg_[i] = x_sum_[i] * dPrimalScale;
1233
+ #if PDLP_PROFILE
1234
+ hipdlpTimerStop(kHipdlpClockAverageIterateComputeX);
1235
+ #endif
1236
+
1237
+ #if PDLP_PROFILE
1238
+ hipdlpTimerStart(kHipdlpClockAverageIterateComputeY);
1239
+ #endif
1240
+ for (size_t i = 0; i < y_avg_.size(); ++i) y_avg_[i] = y_sum_[i] * dDualScale;
1241
+ #if PDLP_PROFILE
1242
+ hipdlpTimerStop(kHipdlpClockAverageIterateComputeY);
1243
+ #endif
1244
+
1245
+ #if PDLP_DEBUG_LOG
1246
+ debug_pdlp_data_.x_average_norm = linalg::vectorNormSquared(x_avg_);
1247
+ #endif
1248
+
1249
+ #if PDLP_PROFILE
1250
+ hipdlpTimerStart(kHipdlpClockAverageIterateMatrixMultiply);
1251
+ #endif
1252
+ linalg::ax(lp_, x_avg_, ax_avg);
1253
+ #if PDLP_PROFILE
1254
+ hipdlpTimerStop(kHipdlpClockAverageIterateMatrixMultiply);
1255
+ #endif
1256
+
1257
+ #if PDLP_PROFILE
1258
+ hipdlpTimerStart(kHipdlpClockAverageIterateMatrixTransposeMultiply);
1259
+ #endif
1260
+ linalg::aTy(lp_, y_avg_, aty_avg);
1261
+ #if PDLP_PROFILE
1262
+ hipdlpTimerStop(kHipdlpClockAverageIterateMatrixTransposeMultiply);
1263
+ #endif
1264
+
1265
+ #if PDLP_DEBUG_LOG
1266
+ debug_pdlp_data_.ax_average_norm = linalg::vectorNormSquared(ax_avg);
1267
+ debug_pdlp_data_.aty_average_norm = linalg::vectorNormSquared(aty_avg);
1268
+ #endif
1269
+ }
1270
+
1271
+ // lambda = c - proj_{\Lambda}(c - K^T y)
1272
+ std::vector<double> PDLPSolver::computeLambda(
1273
+ const std::vector<double>& y, const std::vector<double>& ATy_vector) {
1274
+ std::vector<double> lambda(lp_.num_col_, 0.0);
1275
+ for (HighsInt i = 0; i < lp_.num_col_; ++i) {
1276
+ double residual = lp_.col_cost_[i] - ATy_vector[i];
1277
+
1278
+ if (lp_.col_lower_[i] <= -kHighsInf && lp_.col_upper_[i] >= kHighsInf) {
1279
+ lambda[i] = 0;
1280
+ } else if (lp_.col_lower_[i] <= -kHighsInf) {
1281
+ lambda[i] = std::min(0.0, residual);
1282
+ } else if (lp_.col_upper_[i] >= kHighsInf) {
1283
+ lambda[i] = std::max(0.0, residual);
1284
+ } else {
1285
+ lambda[i] = residual;
1286
+ }
1287
+ }
1288
+ return lambda;
1289
+ }
1290
+
1291
+ double PDLPSolver::computePrimalFeasibility(
1292
+ const std::vector<double>& Ax_vector) {
1293
+ std::vector<double> primal_residual(lp_.num_row_, 0.0);
1294
+
1295
+ // Compute ax - rhs
1296
+ for (HighsInt i = 0; i < lp_.num_row_; ++i) {
1297
+ primal_residual[i] = Ax_vector[i] - lp_.row_lower_[i];
1298
+
1299
+ // For inequality constraints, project to negative part
1300
+ if (!is_equality_row_[i]) {
1301
+ primal_residual[i] = std::min(0.0, primal_residual[i]);
1302
+ }
1303
+ }
1304
+
1305
+ // Apply scaling if needed
1306
+ if (scaling_.isScaled()) {
1307
+ const auto& row_scale = scaling_.getRowScaling();
1308
+ for (HighsInt i = 0; i < lp_.num_row_; ++i) {
1309
+ primal_residual[i] *= row_scale[i];
1310
+ }
1311
+ }
1312
+
1313
+ return linalg::vectorNorm(primal_residual);
1314
+ }
1315
+
1316
+ void PDLPSolver::computeDualSlacks(const std::vector<double>& dualResidual,
1317
+ std::vector<double>& dSlackPos,
1318
+ std::vector<double>& dSlackNeg) {
1319
+ // Ensure vectors are correctly sized
1320
+ if (dSlackPos.size() != static_cast<size_t>(lp_.num_col_))
1321
+ dSlackPos.resize(lp_.num_col_);
1322
+ if (dSlackNeg.size() != static_cast<size_t>(lp_.num_col_))
1323
+ dSlackNeg.resize(lp_.num_col_);
1324
+
1325
+ for (HighsInt i = 0; i < lp_.num_col_; ++i) {
1326
+ if (params_.use_halpern_restart) {
1327
+ // For Halpern current iterate checks, use major-step dual slack:
1328
+ // dual_slack = (proj(temp) - temp) / primal_step.
1329
+ // For other cases (e.g. average iterate), fall back to sign/bounds
1330
+ // projection.
1331
+ const bool use_cached_halpern_slack = (&dSlackPos == &dSlackPos_) &&
1332
+ (&dSlackNeg == &dSlackNeg_) &&
1333
+ halpern_dual_slack_next_valid_ &&
1334
+ (halpern_dual_slack_next_.size() ==
1335
+ static_cast<size_t>(lp_.num_col_));
1336
+
1337
+ double dual_slack = 0.0;
1338
+ if (use_cached_halpern_slack) {
1339
+ dual_slack = halpern_dual_slack_next_[i];
1340
+ } else {
1341
+ const bool has_lower = lp_.col_lower_[i] > -kHighsInf;
1342
+ const bool has_upper = lp_.col_upper_[i] < kHighsInf;
1343
+ if (has_lower && has_upper) {
1344
+ dual_slack = dualResidual[i];
1345
+ } else if (has_lower) {
1346
+ dual_slack = std::max(0.0, dualResidual[i]);
1347
+ } else if (has_upper) {
1348
+ dual_slack = std::min(0.0, dualResidual[i]);
1349
+ }
1350
+ }
1351
+
1352
+ dSlackPos[i] = std::max(0.0, dual_slack);
1353
+ dSlackNeg[i] = std::max(0.0, -dual_slack);
1354
+ } else {
1355
+ // Compute positive slack (for lower bounds)
1356
+ // CUPDLP: max(dual_residual, 0) * hasLower
1357
+ if (lp_.col_lower_[i] > -kHighsInf) {
1358
+ dSlackPos[i] = std::max(0.0, dualResidual[i]);
1359
+ } else {
1360
+ dSlackPos[i] = 0.0;
1361
+ }
1362
+
1363
+ // Compute negative slack (for upper bounds)
1364
+ // CUPDLP: -min(dual_residual, 0) * hasUpper
1365
+ if (lp_.col_upper_[i] < kHighsInf) {
1366
+ dSlackNeg[i] = std::max(0.0, -dualResidual[i]);
1367
+ } else {
1368
+ dSlackNeg[i] = 0.0;
1369
+ }
1370
+ }
1371
+ }
1372
+ }
1373
+
1374
+ double PDLPSolver::computeDualFeasibility(const std::vector<double>& ATy_vector,
1375
+ std::vector<double>& dSlackPos,
1376
+ std::vector<double>& dSlackNeg) {
1377
+ std::vector<double> dualResidual(lp_.num_col_, 0.0);
1378
+ // dualResidual = c-A'y
1379
+ dualResidual = linalg::vectorSubtract(lp_.col_cost_, ATy_vector);
1380
+
1381
+ // Call the refactored function to populate dSlackPos and dSlackNeg
1382
+ computeDualSlacks(dualResidual, dSlackPos, dSlackNeg);
1383
+
1384
+ std::vector<double> dual_residual(lp_.num_col_);
1385
+
1386
+ for (HighsInt i = 0; i < lp_.num_col_; ++i) {
1387
+ // Matching CUPDLP: c - A'y - dSlackPos + dSlackNeg
1388
+ dual_residual[i] = dualResidual[i] - dSlackPos[i] + dSlackNeg[i];
1389
+ }
1390
+
1391
+ // Apply scaling if needed
1392
+ if (scaling_.isScaled()) {
1393
+ const auto& col_scale = scaling_.getColScaling();
1394
+ for (HighsInt i = 0; i < lp_.num_col_; ++i) {
1395
+ dual_residual[i] *= col_scale[i];
1396
+ }
1397
+ }
1398
+
1399
+ double dual_feasibility = linalg::vectorNorm(dual_residual);
1400
+
1401
+ return dual_feasibility;
1402
+ }
1403
+
1404
+ std::tuple<double, double, double, double, double>
1405
+ PDLPSolver::computeDualityGap(const std::vector<double>& x,
1406
+ const std::vector<double>& y,
1407
+ const std::vector<double>& lambda) {
1408
+ double qTy = 0.0;
1409
+ for (HighsInt i = 0; i < lp_.num_row_; ++i) {
1410
+ if (lp_.row_lower_[i] > -kHighsInf) {
1411
+ qTy += lp_.row_lower_[i] * y[i];
1412
+ } else {
1413
+ qTy += lp_.row_upper_[i] * y[i];
1414
+ }
1415
+ }
1416
+
1417
+ double lT_lambda_plus = 0.0;
1418
+ double uT_lambda_minus = 0.0;
1419
+
1420
+ for (HighsInt i = 0; i < lp_.num_col_; ++i) {
1421
+ if (lp_.col_lower_[i] > -kHighsInf) {
1422
+ lT_lambda_plus += lp_.col_lower_[i] * std::max(0.0, lambda[i]);
1423
+ }
1424
+ if (lp_.col_upper_[i] < kHighsInf) {
1425
+ uT_lambda_minus += lp_.col_upper_[i] * std::max(0.0, -lambda[i]);
1426
+ }
1427
+ }
1428
+
1429
+ double dual_objective = qTy + lT_lambda_plus - uT_lambda_minus;
1430
+
1431
+ double cTx = 0.0;
1432
+ for (HighsInt i = 0; i < lp_.num_col_; ++i) {
1433
+ cTx += lp_.col_cost_[i] * x[i];
1434
+ }
1435
+
1436
+ double duality_gap = abs(dual_objective - cTx);
1437
+ return std::make_tuple(duality_gap, qTy, lT_lambda_plus, uT_lambda_minus,
1438
+ cTx);
1439
+ }
1440
+
1441
+ double PDLPSolver::computeDualObjective(const std::vector<double>& y,
1442
+ const std::vector<double>& dSlackPos,
1443
+ const std::vector<double>& dSlackNeg) {
1444
+ double dual_obj = lp_.offset_;
1445
+
1446
+ // Compute b'y (or rhs'y in cuPDLP notation)
1447
+ for (HighsInt i = 0; i < lp_.num_row_; ++i) {
1448
+ dual_obj += lp_.row_lower_[i] * y[i];
1449
+ }
1450
+
1451
+ // Add contribution from lower bounds: l'*slackPos
1452
+ for (HighsInt i = 0; i < lp_.num_col_; ++i) {
1453
+ if (lp_.col_lower_[i] > -kHighsInf) {
1454
+ dual_obj += lp_.col_lower_[i] * dSlackPos[i];
1455
+ }
1456
+ }
1457
+
1458
+ // Subtract contribution from upper bounds: u'*slackNeg
1459
+ for (HighsInt i = 0; i < lp_.num_col_; ++i) {
1460
+ if (lp_.col_upper_[i] < kHighsInf) {
1461
+ dual_obj -= lp_.col_upper_[i] * dSlackNeg[i];
1462
+ }
1463
+ }
1464
+
1465
+ return dual_obj;
1466
+ }
1467
+
1468
+ bool PDLPSolver::checkConvergence(
1469
+ const HighsInt iter, const std::vector<double>& x,
1470
+ const std::vector<double>& y, const std::vector<double>& ax_vector,
1471
+ const std::vector<double>& aty_vector, double epsilon,
1472
+ SolverResults& results, const char* type,
1473
+ // Add slack vectors as non-const references
1474
+ std::vector<double>& dSlackPos, std::vector<double>& dSlackNeg) {
1475
+ // computeDualSlacks is now called inside computeDualFeasibility
1476
+
1477
+ // Compute primal feasibility
1478
+ double primal_feasibility = computePrimalFeasibility(ax_vector);
1479
+ results.primal_feasibility = primal_feasibility;
1480
+
1481
+ // Compute dual feasibility
1482
+ // This will populate dSlackPos and dSlackNeg
1483
+ double dual_feasibility =
1484
+ computeDualFeasibility(aty_vector, dSlackPos, dSlackNeg);
1485
+ results.dual_feasibility = dual_feasibility;
1486
+
1487
+ // Compute objectives
1488
+ double primal_obj = lp_.offset_;
1489
+ for (HighsInt i = 0; i < lp_.num_col_; ++i) {
1490
+ primal_obj += lp_.col_cost_[i] * x[i];
1491
+ }
1492
+ results.primal_obj = primal_obj;
1493
+
1494
+ // Pass the now-populated slack vectors to computeDualObjective
1495
+ double dual_obj = computeDualObjective(y, dSlackPos, dSlackNeg);
1496
+ results.dual_obj = dual_obj;
1497
+
1498
+ // Compute duality gap
1499
+ double duality_gap = primal_obj - dual_obj;
1500
+ results.duality_gap = std::abs(duality_gap);
1501
+
1502
+ // Compute relative gap (matching cuPDLP formula)
1503
+ double relative_obj_gap =
1504
+ std::abs(duality_gap) / (1.0 + std::abs(primal_obj) + std::abs(dual_obj));
1505
+ results.relative_obj_gap = relative_obj_gap;
1506
+
1507
+ #if PDLP_DEBUG_LOG
1508
+ debugPdlpFeasOptLog(debug_pdlp_log_file_, iter, primal_obj, dual_obj,
1509
+ relative_obj_gap,
1510
+ primal_feasibility / (1.0 + unscaled_rhs_norm_),
1511
+ dual_feasibility / (1.0 + unscaled_c_norm_), type);
1512
+ #endif
1513
+
1514
+ // check convergence criteria (matching cuPDLP)
1515
+ bool primal_feasible =
1516
+ primal_feasibility < epsilon * (1.0 + unscaled_rhs_norm_);
1517
+ bool dual_feasible = dual_feasibility < epsilon * (1.0 + unscaled_c_norm_);
1518
+ bool gap_small = relative_obj_gap < epsilon;
1519
+
1520
+ return primal_feasible && dual_feasible && gap_small;
1521
+ }
1522
+
1523
+ double PDLPSolver::powerMethod() {
1524
+ const HighsLp& lp = lp_;
1525
+ double op_norm_sq = 1.0;
1526
+ if (lp.num_col_ == 0 || lp.num_row_ == 0) return op_norm_sq;
1527
+
1528
+ // Parameters for the power method
1529
+ const HighsInt max_iter = 20;
1530
+ const double tol = 1e-6;
1531
+
1532
+ // initialize a random vector x
1533
+ std::vector<double> x_vec(lp.num_col_);
1534
+ std::random_device rd;
1535
+ std::mt19937 engine_fixed_seed(12345); // gen(rd());
1536
+ std::uniform_real_distribution<> dis(-1.0, 1.0);
1537
+ for (HighsInt i = 0; i < lp.num_col_; ++i) {
1538
+ x_vec[i] = dis(engine_fixed_seed);
1539
+ }
1540
+ linalg::normalize(x_vec); // Assumes a Normalize function in linalg
1541
+
1542
+ const HighsInt kYanyuPowerMethod = 0;
1543
+ const HighsInt kYanyuPowerMethodDev = 1;
1544
+ const HighsInt kCuPdlpAATPowerMethod = 2;
1545
+
1546
+ const HighsInt power_method =
1547
+ // kYanyuPowerMethod;
1548
+ // kYanyuPowerMethodDev;
1549
+ kCuPdlpAATPowerMethod;
1550
+ highsLogDev(params_.log_options_, HighsLogType::kInfo, "Power method: %s\n",
1551
+ power_method == kYanyuPowerMethod ? "Yanyu"
1552
+ : power_method == kYanyuPowerMethodDev ? "Yanyu dev"
1553
+ : "CuPdlp-C");
1554
+ // Dev version of Yanyu power method (based on A'A) has
1555
+ //
1556
+ // * First iterate as vector of ones
1557
+ //
1558
+ // * No "convergence" check
1559
+
1560
+ // cuPDLP-C version of power method is based on AA'
1561
+ //
1562
+ // Allocate memory for matrix-vector products
1563
+ std::vector<double> y_vec;
1564
+ std::vector<double> z_vec;
1565
+ if (power_method < kCuPdlpAATPowerMethod) {
1566
+ y_vec.resize(lp.num_row_);
1567
+ z_vec.resize(lp.num_col_);
1568
+ } else {
1569
+ y_vec.resize(lp.num_col_);
1570
+ z_vec.resize(lp.num_row_);
1571
+ }
1572
+
1573
+ double op_norm_sq_old = 0.0;
1574
+ LogLevel log_level = logger_.getLogLevel();
1575
+ HighsInt log_iters =
1576
+ log_level == LogLevel::kVerbose || log_level == LogLevel::kDebug;
1577
+
1578
+ if (log_iters)
1579
+ highsLogUser(params_.log_options_, HighsLogType::kInfo,
1580
+ "It lambda dl_lambda\n");
1581
+
1582
+ if (power_method == kYanyuPowerMethodDev) {
1583
+ // Start from a vector
1584
+ x_vec.assign(lp.num_col_, 1);
1585
+ } else if (power_method == kCuPdlpAATPowerMethod) {
1586
+ x_vec.assign(lp.num_row_, 1);
1587
+ }
1588
+ const HighsSparseMatrix& matrix = lp.a_matrix_;
1589
+ double lambda = 0.0;
1590
+ double previous_lambda = lambda;
1591
+ for (HighsInt iter = 0; iter < max_iter; ++iter) {
1592
+ if (power_method == kYanyuPowerMethod) {
1593
+ // Original Yanyu power method
1594
+ //
1595
+ // Compute A'ax = A'(ax)
1596
+ linalg::ax(lp, x_vec, y_vec);
1597
+ linalg::aTy(lp, y_vec, z_vec); // Note: aTy computes A' * vector
1598
+
1599
+ // Estimate the squared operator norm (largest eigenvalue of A'A)
1600
+ op_norm_sq = linalg::dot(
1601
+ x_vec, z_vec); // Assumes a Dot product function in linalg
1602
+
1603
+ // check for convergence
1604
+ if (std::abs(op_norm_sq - op_norm_sq_old) < tol * op_norm_sq) {
1605
+ return op_norm_sq;
1606
+ }
1607
+ double dl_op_norm_sq = std::fabs(op_norm_sq - op_norm_sq_old);
1608
+ op_norm_sq_old = op_norm_sq;
1609
+
1610
+ // Prepare for the next iteration
1611
+ linalg::normalize(z_vec); // Normalize the result
1612
+ x_vec = z_vec;
1613
+ if (log_iters)
1614
+ highsLogUser(params_.log_options_, HighsLogType::kInfo,
1615
+ "%2d %12.6g %11.4g\n", HighsInt(iter), op_norm_sq,
1616
+ dl_op_norm_sq);
1617
+ } else {
1618
+ if (power_method == kYanyuPowerMethodDev) {
1619
+ // Yanyu power method without "convergence" check
1620
+ //
1621
+ // Compute z = A'ax = A'(ax)
1622
+ matrix.product(y_vec, x_vec);
1623
+ matrix.productTranspose(z_vec, y_vec);
1624
+ // Compute the Rayleigh quotient of x which, since x'x=1, is
1625
+ //
1626
+ // lambda = x'A'ax = x'(A'ax) = x'z
1627
+ lambda = linalg::dot(x_vec, z_vec);
1628
+ // x = z / norm(z)
1629
+ double z_norm = std::sqrt(linalg::dot(z_vec, z_vec));
1630
+ for (HighsInt iCol = 0; iCol < lp.num_col_; iCol++)
1631
+ x_vec[iCol] = z_vec[iCol] / z_norm;
1632
+
1633
+ } else {
1634
+ // cuPDLP-C power method
1635
+ //
1636
+ // Compute z = AA'x = A(A'x)
1637
+ matrix.productTranspose(y_vec, x_vec);
1638
+ matrix.product(z_vec, y_vec);
1639
+ // q = z / norm(z)
1640
+ double z_norm = std::sqrt(linalg::dot(z_vec, z_vec));
1641
+ for (HighsInt iRow = 0; iRow < lp.num_row_; iRow++)
1642
+ z_vec[iRow] /= z_norm;
1643
+ // Compute the Rayleigh quotient of q which, since q'q=1, is
1644
+ //
1645
+ // lambda = q'AA'q = w^Tw = ||w||_2
1646
+ //
1647
+ // where w = A'q
1648
+ //
1649
+ // y_vec is no longer needed, so w is stored in it
1650
+ matrix.productTranspose(y_vec, z_vec);
1651
+ lambda = linalg::dot(y_vec, y_vec);
1652
+ x_vec = z_vec;
1653
+ }
1654
+ double dl_lambda = std::fabs(lambda - previous_lambda);
1655
+ previous_lambda = lambda;
1656
+ if (log_iters)
1657
+ highsLogUser(params_.log_options_, HighsLogType::kInfo,
1658
+ "%2d %12.6g %11.4g\n", HighsInt(iter), lambda, dl_lambda);
1659
+ }
1660
+ }
1661
+ if (power_method != kYanyuPowerMethod) op_norm_sq = lambda;
1662
+ // If the method did not converge within max_iter
1663
+ return op_norm_sq;
1664
+ }
1665
+
1666
+ void PDLPSolver::setup(const HighsOptions& options, HighsTimer& timer) {
1667
+ logger_.initialise(options.log_dev_level, options.log_options, &timer);
1668
+ logger_.printHeader();
1669
+ highs_timer_p_ = &timer;
1670
+ highsLogUser(options.log_options, HighsLogType::kInfo,
1671
+ "Using HiPDLP first order PDLP solver on a %s\n",
1672
+ #ifdef CUPDLP_GPU
1673
+ "GPU"
1674
+ #else
1675
+ "CPU: performance may be disappointing!"
1676
+ #endif
1677
+ );
1678
+ #ifdef CUPDLP_GPU
1679
+ HighsInt n_devices = 0;
1680
+ cudaGetDeviceCount(&n_devices);
1681
+ if (n_devices != 1)
1682
+ highsLogUser(
1683
+ options.log_options, HighsLogType::kInfo,
1684
+ "Number of CUDA-enabled devices is %d: device 0 will be used\n",
1685
+ n_devices);
1686
+ cudaDeviceProp prop;
1687
+ cudaGetDeviceProperties(&prop, 0);
1688
+ highsLogUser(options.log_options, HighsLogType::kInfo, "Cuda device: %s\n",
1689
+ prop.name);
1690
+ highsLogUser(options.log_options, HighsLogType::kInfo,
1691
+ "Global memory available on device (GB): %f\n",
1692
+ (float(prop.totalGlobalMem)) / 1e9);
1693
+ #endif
1694
+
1695
+ #if PDLP_PROFILE
1696
+ hipdlp_clocks_.timer_pointer_ = &timer;
1697
+ hipdlp_timer_.initialiseHipdlpClocks(hipdlp_clocks_);
1698
+ #endif
1699
+
1700
+ #if PDLP_DEBUG_LOG
1701
+ debug_pdlp_log_file_ = fopen("HiPDLP.log", "w");
1702
+ #endif
1703
+
1704
+ params_.initialise();
1705
+ // params.eta = 0; Not set in parse_options_file
1706
+ // params.omega = 0; Not set in parse_options_file
1707
+ params_.tolerance = options.pdlp_optimality_tolerance;
1708
+ if (options.kkt_tolerance != kDefaultKktTolerance)
1709
+ params_.tolerance = options.kkt_tolerance;
1710
+ params_.max_iterations = options.pdlp_iteration_limit;
1711
+ params_.device_type = Device::CPU;
1712
+ params_.time_limit = options.time_limit;
1713
+
1714
+ params_.use_ruiz_scaling = false;
1715
+ params_.use_pc_scaling = false;
1716
+ params_.use_l2_scaling = false;
1717
+ if ((options.pdlp_features_off & kPdlpScalingOff) == 0) {
1718
+ // Use scaling: now see which
1719
+ params_.use_ruiz_scaling = options.pdlp_scaling_mode & kPdlpScalingRuiz;
1720
+ params_.use_pc_scaling = options.pdlp_scaling_mode & kPdlpScalingPC;
1721
+ params_.use_l2_scaling = options.pdlp_scaling_mode & kPdlpScalingL2;
1722
+ }
1723
+ params_.ruiz_iterations = options.pdlp_ruiz_iterations;
1724
+ // params_.ruiz_norm = INFINITY; Not set in parse_options_file
1725
+ // params_.pc_alpha = 1.0; Not set in parse_options_file
1726
+
1727
+ // HiPDLP solve loop is Halpern-only.
1728
+ params_.restart_strategy = RestartStrategy::ADAPTIVE_RESTART;
1729
+ params_.use_halpern_restart = true;
1730
+ if ((options.pdlp_features_off & kPdlpRestartOff) != 0 ||
1731
+ options.pdlp_restart_strategy != kPdlpRestartStrategyHalpern) {
1732
+ logger_.info(
1733
+ "HiPDLP uses Halpern restart only; ignoring pdlp_restart_strategy "
1734
+ "and restart-off feature flag.");
1735
+ }
1736
+ // params_.fixed_restart_interval = 0; Not set in parse_options_file
1737
+
1738
+ params_.step_size_strategy = StepSizeStrategy::FIXED;
1739
+ if (options.pdlp_step_size_strategy == kPdlpStepSizeStrategyPid) {
1740
+ params_.step_size_strategy = StepSizeStrategy::PID;
1741
+ } else if (options.pdlp_step_size_strategy != kPdlpStepSizeStrategyFixed) {
1742
+ logger_.info(
1743
+ "HiPDLP only supports pdlp_step_size_strategy in {0: fixed, "
1744
+ "3: PID}; using PID for unsupported values.");
1745
+ params_.step_size_strategy = StepSizeStrategy::PID;
1746
+ }
1747
+
1748
+ // params_.malitsky_pock_params.initialise(); Not set in parse_options_file
1749
+ // params_.adaptive_linesearch_params.initialise(); Not set in
1750
+ // parse_options_file
1751
+ scaling_.passParams(&params_);
1752
+ restart_scheme_.passParams(&params_);
1753
+ // Copy what's needed to use HiGHS logging
1754
+ params_.log_options_ = options.log_options;
1755
+ // log the options
1756
+ logger_.printParams(params_);
1757
+ }
1758
+
1759
+ void PDLPSolver::scaleProblem() {
1760
+ scaling_.passLp(&lp_);
1761
+ scaling_.passParams(&params_);
1762
+ scaling_.initialize(lp_);
1763
+ scaling_.scaleProblem();
1764
+ }
1765
+
1766
+ void PDLPSolver::unscaleSolution(std::vector<double>& x,
1767
+ std::vector<double>& y) {
1768
+ scaling_.unscaleSolution(x, y);
1769
+
1770
+ x_current_ = x;
1771
+ y_current_ = y;
1772
+
1773
+ const std::vector<double>& col_scale = scaling_.getColScaling();
1774
+ if (!dSlackPos_.empty() && col_scale.size() == dSlackPos_.size()) {
1775
+ for (size_t i = 0; i < dSlackPos_.size(); ++i) {
1776
+ dSlackPos_[i] *= col_scale[i];
1777
+ dSlackNeg_[i] *= col_scale[i];
1778
+ }
1779
+ }
1780
+ }
1781
+
1782
+ void PDLPSolver::logSummary() {
1783
+ logger_.printSummary(results_, final_iter_count_, highs_timer_p_->read());
1784
+ }
1785
+
1786
+ void PrimalDualParams::initialise() {
1787
+ this->eta = 0;
1788
+ this->omega = 0;
1789
+ this->tolerance = 0;
1790
+ this->max_iterations = 0;
1791
+ this->device_type = Device::CPU;
1792
+ this->time_limit = kHighsInf;
1793
+ this->restart_strategy = RestartStrategy::NO_RESTART;
1794
+ this->fixed_restart_interval = 0;
1795
+ this->use_halpern_restart = false;
1796
+ this->halpern_gamma = 1.0;
1797
+ this->use_ruiz_scaling = false;
1798
+ this->use_pc_scaling = false;
1799
+ this->use_l2_scaling = false;
1800
+ this->ruiz_iterations = 10;
1801
+ this->ruiz_norm = INFINITY;
1802
+ this->pc_alpha = 1.0;
1803
+ this->k_p = 0.99;
1804
+ this->k_i = 0.01;
1805
+ this->k_d = 0.0;
1806
+ this->step_size_strategy = StepSizeStrategy::FIXED;
1807
+ this->malitsky_pock_params.initialise();
1808
+ this->adaptive_linesearch_params.initialise();
1809
+ this->log_options_.clear();
1810
+ }
1811
+
1812
+ void MalitskyPockParams::initialise() {
1813
+ this->step_size_interpolation = 0.5; // Between 0 and 1
1814
+ this->step_size_downscaling_factor = 0.7;
1815
+ this->linesearch_contraction_factor = 0.99;
1816
+ }
1817
+
1818
+ void AdaptiveLinesearchParams::initialise() {
1819
+ this->step_size_reduction_exponent = 0.3;
1820
+ this->step_size_growth_exponent = 0.6;
1821
+ }
1822
+
1823
+ // =============================================================================
1824
+ // SECTION 4: Step Update Methods (from step.cc)
1825
+ // =============================================================================
1826
+
1827
+ void PDLPSolver::initializeStepSizes() {
1828
+ double cost_norm_sq = linalg::vectorNormSquared(lp_.col_cost_);
1829
+ double rhs_norm_sq = linalg::vectorNormSquared(lp_.row_lower_);
1830
+
1831
+ if (std::min(cost_norm_sq, rhs_norm_sq) > 1e-6) {
1832
+ stepsize_.beta = cost_norm_sq / rhs_norm_sq;
1833
+ } else {
1834
+ stepsize_.beta = 1.0;
1835
+ }
1836
+
1837
+ // Match initial primal weight calculation from cuPDLPx
1838
+ params_.omega = (unscaled_c_norm_ + 1.0) / (unscaled_rhs_norm_ + 1.0);
1839
+ primal_weight_ = params_.omega;
1840
+
1841
+ if (params_.step_size_strategy != StepSizeStrategy::FIXED &&
1842
+ params_.step_size_strategy != StepSizeStrategy::PID) {
1843
+ logger_.info(
1844
+ "HiPDLP only supports fixed/PID step size; falling back to fixed.");
1845
+ params_.step_size_strategy = StepSizeStrategy::FIXED;
1846
+ }
1847
+
1848
+ // Use power method for fixed/PID step size initialization.
1849
+ double op_norm_sq = powerMethod();
1850
+
1851
+ stepsize_.power_method_lambda = op_norm_sq;
1852
+
1853
+ const double safety_factor = 0.998;
1854
+ double base_step = safety_factor / std::sqrt(op_norm_sq);
1855
+
1856
+ params_.eta = base_step;
1857
+ stepsize_.primal_step = base_step / params_.omega;
1858
+ stepsize_.dual_step = base_step * params_.omega;
1859
+
1860
+ highsLogDev(params_.log_options_, HighsLogType::kInfo,
1861
+ "Initial step sizes from power method lambda = %g: primal step= "
1862
+ "%g; dual step = %g, eta = %g, omega = %g\n",
1863
+ op_norm_sq, stepsize_.primal_step, stepsize_.dual_step,
1864
+ params_.eta, params_.omega);
1865
+ }
1866
+
1867
+ void PDLPSolver::updatePrimalWeightAtRestart(const SolverResults& results) {
1868
+ // Compute delta = pdhg_iterate - anchor
1869
+ double primal_dist = 0.0;
1870
+ double dual_dist = 0.0;
1871
+
1872
+ #ifdef CUPDLP_GPU
1873
+ primal_dist = computeDiffNormCuBLAS(d_pdhg_primal_, d_x_anchor_, a_num_cols_);
1874
+ dual_dist = computeDiffNormCuBLAS(d_pdhg_dual_, d_y_anchor_, a_num_rows_);
1875
+ #else
1876
+ // CPU version
1877
+ for (HighsInt i = 0; i < lp_.num_col_; ++i) {
1878
+ double diff = x_next_[i] - x_anchor_[i];
1879
+ primal_dist += diff * diff;
1880
+ }
1881
+ for (HighsInt j = 0; j < lp_.num_row_; ++j) {
1882
+ double diff = y_next_[j] - y_anchor_[j];
1883
+ dual_dist += diff * diff;
1884
+ }
1885
+ primal_dist = std::sqrt(primal_dist);
1886
+ dual_dist = std::sqrt(dual_dist);
1887
+ #endif
1888
+
1889
+ double rel_primal = results.primal_feasibility / (1.0 + unscaled_rhs_norm_);
1890
+ double rel_dual = results.dual_feasibility / (1.0 + unscaled_c_norm_);
1891
+ double ratio_infeas = (rel_primal > 0.0) ? (rel_dual / rel_primal) : 1e300;
1892
+
1893
+ const bool silent = true;
1894
+ // cuPDLPx-style weight update (PID control)
1895
+ if (primal_dist > 1e-16 && dual_dist > 1e-16 && primal_dist < 1e12 &&
1896
+ dual_dist < 1e12 && ratio_infeas > 1e-8 && ratio_infeas < 1e8) {
1897
+ double error =
1898
+ std::log(dual_dist) - std::log(primal_dist) - std::log(primal_weight_);
1899
+
1900
+ primal_weight_error_sum_ =
1901
+ params_.i_smooth * primal_weight_error_sum_ + error;
1902
+ double delta_error = error - primal_weight_last_error_;
1903
+
1904
+ primal_weight_ *=
1905
+ std::exp(params_.k_p * error + params_.k_i * primal_weight_error_sum_ +
1906
+ params_.k_d * delta_error);
1907
+
1908
+ primal_weight_last_error_ = error;
1909
+ if (!silent)
1910
+ logger_.info("Primal weight updated: " + std::to_string(primal_weight_));
1911
+ } else {
1912
+ // Revert to best known weight
1913
+ primal_weight_ = best_primal_weight_;
1914
+ primal_weight_error_sum_ = 0.0;
1915
+ primal_weight_last_error_ = 0.0;
1916
+ if (!silent)
1917
+ logger_.info(
1918
+ "Weight update failed (bad norms/ratio), reverted to best: " +
1919
+ std::to_string(primal_weight_));
1920
+ }
1921
+
1922
+ // Track best weight
1923
+ double gap = (rel_primal > 0.0 && rel_dual > 0.0)
1924
+ ? std::abs(std::log10(rel_dual / rel_primal))
1925
+ : best_primal_dual_residual_gap_;
1926
+ if (gap < best_primal_dual_residual_gap_) {
1927
+ best_primal_dual_residual_gap_ = gap;
1928
+ best_primal_weight_ = primal_weight_;
1929
+ }
1930
+
1931
+ double eta =
1932
+ std::sqrt(stepsize_.primal_step * stepsize_.dual_step); // invariant
1933
+ stepsize_.beta = primal_weight_ * primal_weight_;
1934
+ stepsize_.primal_step = eta / primal_weight_;
1935
+ stepsize_.dual_step = eta * primal_weight_;
1936
+ params_.omega = primal_weight_;
1937
+ restart_scheme_.updateBeta(stepsize_.beta);
1938
+ }
1939
+
1940
+ std::vector<double> PDLPSolver::updateX(const std::vector<double>& x,
1941
+ const std::vector<double>& aty,
1942
+ double primal_step) {
1943
+ std::vector<double> x_new(lp_.num_col_);
1944
+ for (HighsInt i = 0; i < lp_.num_col_; i++) {
1945
+ double gradient = lp_.col_cost_[i] - aty[i];
1946
+ x_new[i] = linalg::projectBox(x[i] - primal_step * gradient,
1947
+ lp_.col_lower_[i], lp_.col_upper_[i]);
1948
+ }
1949
+ return x_new;
1950
+ }
1951
+
1952
+ std::vector<double> PDLPSolver::updateY(const std::vector<double>& y,
1953
+ const std::vector<double>& ax,
1954
+ const std::vector<double>& ax_next,
1955
+ double dual_step) {
1956
+ std::vector<double> y_new(lp_.num_row_);
1957
+ for (HighsInt j = 0; j < lp_.num_row_; j++) {
1958
+ double extr_ax = 2 * ax_next[j] - ax[j];
1959
+ bool is_equality = (lp_.row_lower_[j] == lp_.row_upper_[j]);
1960
+ double q = lp_.row_lower_[j];
1961
+ double dual_update = y[j] + dual_step * (q - extr_ax);
1962
+ y_new[j] =
1963
+ is_equality ? dual_update : linalg::projectNonNegative(dual_update);
1964
+ }
1965
+ return y_new;
1966
+ }
1967
+
1968
+ void PDLPSolver::updateIteratesFixed() {
1969
+ #if PDLP_PROFILE
1970
+ hipdlpTimerStart(kHipdlpClockProjectX);
1971
+ #endif
1972
+ x_next_ = updateX(x_current_, ATy_cache_, stepsize_.primal_step);
1973
+ #if PDLP_PROFILE
1974
+ hipdlpTimerStop(kHipdlpClockProjectX);
1975
+ #endif
1976
+
1977
+ #if PDLP_PROFILE
1978
+ hipdlpTimerStart(kHipdlpClockMatrixMultiply);
1979
+ #endif
1980
+ linalg::ax(lp_, x_next_, Ax_next_);
1981
+ #if PDLP_PROFILE
1982
+ hipdlpTimerStop(kHipdlpClockMatrixMultiply);
1983
+ #endif
1984
+
1985
+ #if PDLP_PROFILE
1986
+ hipdlpTimerStart(kHipdlpClockProjectY);
1987
+ #endif
1988
+ y_next_ = updateY(y_current_, Ax_cache_, Ax_next_, stepsize_.dual_step);
1989
+ #if PDLP_PROFILE
1990
+ hipdlpTimerStop(kHipdlpClockProjectY);
1991
+ #endif
1992
+
1993
+ #if PDLP_PROFILE
1994
+ hipdlpTimerStart(kHipdlpClockMatrixTransposeMultiply);
1995
+ #endif
1996
+ linalg::aTy(lp_, y_next_, ATy_next_);
1997
+ #if PDLP_PROFILE
1998
+ hipdlpTimerStop(kHipdlpClockMatrixTransposeMultiply);
1999
+ #endif
2000
+
2001
+ #ifdef CUPDLP_GPU
2002
+ // Add this check before the memcpy
2003
+ if (d_x_next_ == nullptr) {
2004
+ std::cerr << "Error1: d_x_next_ is null!" << std::endl;
2005
+ return;
2006
+ }
2007
+ launchKernelUpdateX(stepsize_.primal_step);
2008
+ CUDA_CHECK(cudaDeviceSynchronize());
2009
+ linalgGpuAx(d_x_next_, d_ax_next_);
2010
+ CUDA_CHECK(cudaDeviceSynchronize());
2011
+ launchKernelUpdateY(stepsize_.dual_step);
2012
+ CUDA_CHECK(cudaDeviceSynchronize());
2013
+ linalgGpuATy(d_y_next_, d_aty_next_);
2014
+ CUDA_CHECK(cudaDeviceSynchronize());
2015
+
2016
+ // Add this check before the memcpy
2017
+ if (d_x_next_ == nullptr) {
2018
+ std::cerr << "Error2: d_x_next_ is null!" << std::endl;
2019
+ return;
2020
+ }
2021
+ #endif
2022
+ }
2023
+
2024
+ void PDLPSolver::updateIteratesAdaptive() {
2025
+ #if PDLP_PROFILE
2026
+ hipdlpTimerStart(kHipdlpClockStepSizeAdjustment);
2027
+ #endif
2028
+
2029
+ const double MIN_ETA = 1e-6;
2030
+ const double MAX_ETA = 1.0;
2031
+
2032
+ bool accepted_step = false;
2033
+ HighsInt inner_iterations = 0;
2034
+ HighsInt num_rejected_steps = 0;
2035
+
2036
+ double dStepSizeUpdate =
2037
+ std::sqrt(stepsize_.primal_step * stepsize_.dual_step);
2038
+
2039
+ // Compute candidate solution
2040
+ std::vector<double> x_candidate = x_current_; // Start from current x
2041
+ std::vector<double> y_candidate = y_current_; // Start from current y
2042
+ std::vector<double> ax_candidate = Ax_cache_; // Start from current ax
2043
+ std::vector<double> aty_candidate = ATy_cache_; // Start from current aTy
2044
+ std::vector<double> xupdate = x_next_;
2045
+ std::vector<double> yupdate = y_next_;
2046
+ std::vector<double> axupdate = Ax_next_;
2047
+ std::vector<double> atyupdate = ATy_next_;
2048
+ while (!accepted_step) {
2049
+ stepsize_.step_size_iter++; // nStepSizeIter
2050
+ inner_iterations++;
2051
+ /* cupdlp does not have a max iteration limit here
2052
+ if (inner_iterations >= 60) {
2053
+ std::cerr << "Warning: Adaptive line search exceeded 60 iterations."
2054
+ << std::endl;
2055
+ // Force accept the last candidate
2056
+ break;
2057
+ }
2058
+ */
2059
+ // Calculate step sizes for this iteration
2060
+ double primal_step_update = dStepSizeUpdate / std::sqrt(stepsize_.beta);
2061
+ double dual_step_update = dStepSizeUpdate * std::sqrt(stepsize_.beta);
2062
+
2063
+ #ifdef CUPDLP_GPU
2064
+ launchKernelUpdateX_wrapper(d_x_next_, // Output (Trial)
2065
+ d_x_current_, // Input (Base)
2066
+ d_aty_current_, // Input (Base aTy)
2067
+ d_col_cost_, d_col_lower_, d_col_upper_,
2068
+ primal_step_update, a_num_cols_, gpu_stream_);
2069
+ linalgGpuAx(d_x_next_, d_ax_next_);
2070
+ launchKernelUpdateY_wrapper(d_y_next_, // Output (Trial)
2071
+ d_y_current_, // Input (Base)
2072
+ d_ax_current_, // Input (Base ax)
2073
+ d_ax_next_, // Input (Trial ax)
2074
+ d_row_lower_, d_is_equality_row_,
2075
+ dual_step_update, a_num_rows_, gpu_stream_);
2076
+ linalgGpuATy(d_y_next_, d_aty_next_);
2077
+ double movement =
2078
+ computeMovementGpu(d_x_next_, d_x_current_, d_y_next_, d_y_current_);
2079
+ double nonlinearity = computeNonlinearityGpu(d_x_next_, d_x_current_,
2080
+ d_aty_next_, d_aty_current_);
2081
+ #else
2082
+ // Primal update
2083
+ #if PDLP_PROFILE
2084
+ hipdlpTimerStart(kHipdlpClockProjectX);
2085
+ #endif
2086
+ xupdate = updateX(x_candidate, aty_candidate, primal_step_update);
2087
+ #if PDLP_PROFILE
2088
+ hipdlpTimerStop(kHipdlpClockProjectX);
2089
+ #endif
2090
+
2091
+ #if PDLP_PROFILE
2092
+ hipdlpTimerStart(kHipdlpClockMatrixMultiply);
2093
+ #endif
2094
+ linalg::ax(lp_, xupdate, axupdate);
2095
+ #if PDLP_PROFILE
2096
+ hipdlpTimerStop(kHipdlpClockMatrixMultiply);
2097
+ #endif
2098
+
2099
+ // Dual update with timing
2100
+ #if PDLP_PROFILE
2101
+ hipdlpTimerStart(kHipdlpClockProjectY);
2102
+ #endif
2103
+ yupdate = updateY(y_candidate, ax_candidate, axupdate, dual_step_update);
2104
+ #if PDLP_PROFILE
2105
+ hipdlpTimerStop(kHipdlpClockProjectY);
2106
+ #endif
2107
+
2108
+ #if PDLP_PROFILE
2109
+ hipdlpTimerStart(kHipdlpClockMatrixTransposeMultiply);
2110
+ #endif
2111
+ linalg::aTy(lp_, yupdate, atyupdate);
2112
+ #if PDLP_PROFILE
2113
+ hipdlpTimerStop(kHipdlpClockMatrixTransposeMultiply);
2114
+ #endif
2115
+
2116
+ // Compute deltas
2117
+ std::vector<double> delta_x(lp_.num_col_);
2118
+ std::vector<double> delta_y(lp_.num_row_);
2119
+ std::vector<double> delta_aty(lp_.num_col_);
2120
+
2121
+ for (size_t i = 0; i < x_candidate.size(); ++i) {
2122
+ delta_x[i] = xupdate[i] - x_candidate[i];
2123
+ }
2124
+ for (size_t i = 0; i < y_candidate.size(); ++i) {
2125
+ delta_y[i] = yupdate[i] - y_candidate[i];
2126
+ }
2127
+ for (size_t i = 0; i < aty_candidate.size(); ++i) {
2128
+ delta_aty[i] = atyupdate[i] - aty_candidate[i];
2129
+ }
2130
+
2131
+ // check numerical stability
2132
+ /*
2133
+ if (!checkNumericalStability(delta_x, delta_y)) {
2134
+ std::cerr << "Numerical instability detected" << std::endl;
2135
+ dStepSizeUpdate *= 0.5; // Drastically reduce step size
2136
+ continue;
2137
+ }
2138
+ */
2139
+
2140
+ // Compute movement and nonlinearity
2141
+ double movement = computeMovement(delta_x, delta_y);
2142
+ double nonlinearity = computeNonlinearity(delta_x, delta_aty);
2143
+ #endif
2144
+ // Compute step size limit
2145
+ double step_size_limit = (nonlinearity != 0.0)
2146
+ ? (movement / std::fabs(nonlinearity))
2147
+ : std::numeric_limits<double>::infinity();
2148
+
2149
+ /*
2150
+ highsLogDev(*log_options_, HighsLogType::kInfo,
2151
+ "Iteration %d: eta = %g, movement = %g nonlinearity = %g, limit
2152
+ = %g\n", HighsInt(inner_iterations), current_eta, movement, nonlinearity.
2153
+ step_size_limit);
2154
+ */
2155
+ if (dStepSizeUpdate <= step_size_limit) {
2156
+ accepted_step = true;
2157
+ } else {
2158
+ num_rejected_steps++;
2159
+ }
2160
+
2161
+ // Compute new step size
2162
+ double first_term =
2163
+ (std::isinf(step_size_limit))
2164
+ ? step_size_limit
2165
+ : (1.0 - std::pow(stepsize_.step_size_iter + 1.0,
2166
+ -params_.adaptive_linesearch_params
2167
+ .step_size_reduction_exponent)) *
2168
+ step_size_limit;
2169
+
2170
+ double second_term =
2171
+ (1.0 +
2172
+ std::pow(
2173
+ stepsize_.step_size_iter + 1.0,
2174
+ -params_.adaptive_linesearch_params.step_size_growth_exponent)) *
2175
+ dStepSizeUpdate;
2176
+
2177
+ dStepSizeUpdate = std::min(first_term, second_term);
2178
+ // current_eta_ = std::max(MIN_ETA, std::min(MAX_ETA, current_eta_));
2179
+ }
2180
+
2181
+ x_next_ = xupdate;
2182
+ y_next_ = yupdate;
2183
+ Ax_next_ = axupdate;
2184
+ ATy_next_ = atyupdate;
2185
+
2186
+ current_eta_ = dStepSizeUpdate;
2187
+ stepsize_.primal_step = dStepSizeUpdate / std::sqrt(stepsize_.beta);
2188
+ stepsize_.dual_step = dStepSizeUpdate * std::sqrt(stepsize_.beta);
2189
+
2190
+ #if PDLP_PROFILE
2191
+ hipdlpTimerStop(kHipdlpClockStepSizeAdjustment);
2192
+ #endif
2193
+ }
2194
+
2195
+ bool PDLPSolver::updateIteratesMalitskyPock(bool first_iteration) {
2196
+ std::vector<double> x_candidate(lp_.num_col_);
2197
+ return true;
2198
+ }
2199
+
2200
+ // =============================================================================
2201
+ // SECTION 5: Step Helper Methods (from step.cc)
2202
+ // =============================================================================
2203
+
2204
+ bool PDLPSolver::checkNumericalStability(const std::vector<double>& delta_x,
2205
+ const std::vector<double>& delta_y) {
2206
+ double movement = computeMovement(delta_x, delta_y);
2207
+
2208
+ if (movement == 0.0) {
2209
+ highsLogUser(log_options_, HighsLogType::kInfo,
2210
+ "Warning: Zero movement detected - numerical termination\n");
2211
+ return false;
2212
+ }
2213
+
2214
+ if (movement > kDivergentMovement) {
2215
+ highsLogUser(log_options_, HighsLogType::kInfo,
2216
+ "Warning: Divergent movement detected: %g\n", movement);
2217
+ return false;
2218
+ }
2219
+ return true; // Placeholder
2220
+ }
2221
+
2222
+ double PDLPSolver::computeMovement(const std::vector<double>& delta_primal,
2223
+ const std::vector<double>& delta_dual) {
2224
+ double primal_squared_norm = 0.0;
2225
+ for (const auto& val : delta_primal) {
2226
+ primal_squared_norm += val * val;
2227
+ }
2228
+
2229
+ double dual_squared_norm = 0.0;
2230
+ for (const auto& val : delta_dual) {
2231
+ dual_squared_norm += val * val;
2232
+ }
2233
+
2234
+ double primal_weight = std::sqrt(stepsize_.beta);
2235
+ return (0.5 * primal_weight * primal_squared_norm) +
2236
+ (0.5 / primal_weight) * dual_squared_norm;
2237
+ }
2238
+
2239
+ double PDLPSolver::computeNonlinearity(const std::vector<double>& delta_primal,
2240
+ const std::vector<double>& delta_aty) {
2241
+ // Nonlinearity = |Dx' * D(A'y)|
2242
+ double nonlinearity = 0.0;
2243
+ for (size_t i = 0; i < delta_primal.size(); ++i) {
2244
+ nonlinearity += delta_primal[i] * delta_aty[i];
2245
+ }
2246
+ return nonlinearity; // cupdlp does not take absolute value
2247
+ }
2248
+
2249
+ #if PDLP_PROFILE
2250
+ void PDLPSolver::reportHipdlpTimer() {
2251
+ hipdlp_timer_.reportHipdlpCoreClock(hipdlp_clocks_);
2252
+ hipdlp_timer_.reportHipdlpSolveClock(hipdlp_clocks_);
2253
+ hipdlp_timer_.reportHipdlpIterateUpdateClock(hipdlp_clocks_);
2254
+ hipdlp_timer_.reportHipdlpAverageIterateClock(hipdlp_clocks_);
2255
+ hipdlp_timer_.reportHipdlpMatrixMultiplyClock(hipdlp_clocks_);
2256
+ }
2257
+ #endif
2258
+
2259
+ #if PDLP_PROFILE
2260
+ void PDLPSolver::hipdlpTimerStart(const HighsInt hipdlp_clock) {
2261
+ HighsInt highs_timer_clock = hipdlp_clocks_.clock_[hipdlp_clock];
2262
+ hipdlp_clocks_.timer_pointer_->start(highs_timer_clock);
2263
+ }
2264
+ #endif
2265
+
2266
+ #if PDLP_PROFILE
2267
+ void PDLPSolver::hipdlpTimerStop(const HighsInt hipdlp_clock) {
2268
+ HighsInt highs_timer_clock = hipdlp_clocks_.clock_[hipdlp_clock];
2269
+ hipdlp_clocks_.timer_pointer_->stop(highs_timer_clock);
2270
+ }
2271
+ #endif
2272
+
2273
+ #if PDLP_DEBUG_LOG
2274
+ void PDLPSolver::closeDebugLog() {
2275
+ if (debug_pdlp_log_file_) fclose(debug_pdlp_log_file_);
2276
+ }
2277
+ #endif
2278
+
2279
+ // =============================================================================
2280
+ // SECTION 5: GPU Part
2281
+ // =============================================================================
2282
+ #ifdef CUPDLP_GPU
2283
+ void PDLPSolver::setupGpu() {
2284
+ CUDA_CHECK(cudaStreamCreate(&gpu_stream_));
2285
+
2286
+ // 1. initialize cuSPARSE
2287
+ CUSPARSE_CHECK(cusparseCreate(&cusparse_handle_));
2288
+ CUBLAS_CHECK(cublasCreate(&cublas_handle_));
2289
+ CUSPARSE_CHECK(cusparseSetStream(cusparse_handle_, gpu_stream_));
2290
+ CUBLAS_CHECK(cublasSetStream(cublas_handle_, gpu_stream_));
2291
+ // 2. Get matrix data from lp_ (CSC)
2292
+ a_num_rows_ = lp_.num_row_;
2293
+ a_num_cols_ = lp_.num_col_;
2294
+ a_nnz_ = lp_.a_matrix_.numNz();
2295
+
2296
+ HighsSparseMatrix lp_csr = lp_.a_matrix_;
2297
+ lp_csr.ensureRowwise();
2298
+
2299
+ const std::vector<HighsInt>& h_a_row_ptr = lp_csr.start_;
2300
+ const std::vector<HighsInt>& h_a_col_ind = lp_csr.index_;
2301
+ const std::vector<double>& h_a_val = lp_csr.value_;
2302
+
2303
+ // 3. Allocate and copy A's CSR data to GPU
2304
+ CUDA_CHECK(
2305
+ cudaMalloc((void**)&d_a_row_ptr_, (a_num_rows_ + 1) * sizeof(HighsInt)));
2306
+ CUDA_CHECK(cudaMalloc((void**)&d_a_col_ind_, a_nnz_ * sizeof(HighsInt)));
2307
+ CUDA_CHECK(cudaMalloc((void**)&d_a_val_, a_nnz_ * sizeof(double)));
2308
+ CUDA_CHECK(cudaMemcpy(d_a_row_ptr_, h_a_row_ptr.data(),
2309
+ (a_num_rows_ + 1) * sizeof(HighsInt),
2310
+ cudaMemcpyHostToDevice));
2311
+ CUDA_CHECK(cudaMemcpy(d_a_col_ind_, h_a_col_ind.data(),
2312
+ a_nnz_ * sizeof(HighsInt), cudaMemcpyHostToDevice));
2313
+ CUDA_CHECK(cudaMemcpy(d_a_val_, h_a_val.data(), a_nnz_ * sizeof(double),
2314
+ cudaMemcpyHostToDevice));
2315
+
2316
+ CUSPARSE_CHECK(cusparseCreateCsr(&mat_a_csr_, a_num_rows_, a_num_cols_,
2317
+ a_nnz_, d_a_row_ptr_, d_a_col_ind_, d_a_val_,
2318
+ CUSPARSE_INDEX_32I, CUSPARSE_INDEX_32I,
2319
+ CUSPARSE_INDEX_BASE_ZERO, CUDA_R_64F));
2320
+
2321
+ // 4. Create matrix AT in CSR format = A in CSC
2322
+ const std::vector<HighsInt>& h_at_row_ptr = lp_.a_matrix_.start_;
2323
+ const std::vector<HighsInt>& h_at_col_ind = lp_.a_matrix_.index_;
2324
+ const std::vector<double>& h_at_val = lp_.a_matrix_.value_;
2325
+
2326
+ CUDA_CHECK(cudaMalloc((void**)&d_at_row_ptr_,
2327
+ (a_num_cols_ + 1) * sizeof(HighsInt))); // Fixed!
2328
+ CUDA_CHECK(cudaMalloc((void**)&d_at_col_ind_, a_nnz_ * sizeof(HighsInt)));
2329
+ CUDA_CHECK(cudaMalloc((void**)&d_at_val_, a_nnz_ * sizeof(double)));
2330
+
2331
+ CUDA_CHECK(cudaMemcpy(d_at_row_ptr_, h_at_row_ptr.data(),
2332
+ (a_num_cols_ + 1) * sizeof(HighsInt),
2333
+ cudaMemcpyHostToDevice));
2334
+ CUDA_CHECK(cudaMemcpy(d_at_col_ind_, h_at_col_ind.data(),
2335
+ a_nnz_ * sizeof(HighsInt), cudaMemcpyHostToDevice));
2336
+ CUDA_CHECK(cudaMemcpy(d_at_val_, h_at_val.data(), a_nnz_ * sizeof(double),
2337
+ cudaMemcpyHostToDevice));
2338
+ CUDA_CHECK(cudaMalloc(&d_halpern_iteration_, sizeof(int)));
2339
+ CUDA_CHECK(cudaMemset(d_halpern_iteration_, 0, sizeof(int)));
2340
+ CUDA_CHECK(cudaMalloc(&d_primal_step_size_, sizeof(double)));
2341
+ CUDA_CHECK(cudaMalloc(&d_dual_step_size_, sizeof(double)));
2342
+
2343
+ // Create AT descriptor with swapped dimensions
2344
+ CUSPARSE_CHECK(cusparseCreateCsr(
2345
+ &mat_a_T_csr_, a_num_cols_, a_num_rows_, a_nnz_, // Dimensions swapped!
2346
+ d_at_row_ptr_, d_at_col_ind_, d_at_val_, CUSPARSE_INDEX_32I,
2347
+ CUSPARSE_INDEX_32I, CUSPARSE_INDEX_BASE_ZERO, CUDA_R_64F));
2348
+
2349
+ CUDA_CHECK(cudaMalloc(&d_col_cost_, a_num_cols_ * sizeof(double)));
2350
+ CUDA_CHECK(cudaMalloc(&d_col_lower_, a_num_cols_ * sizeof(double)));
2351
+ CUDA_CHECK(cudaMalloc(&d_col_upper_, a_num_cols_ * sizeof(double)));
2352
+ CUDA_CHECK(cudaMalloc(&d_row_lower_, a_num_rows_ * sizeof(double)));
2353
+ CUDA_CHECK(cudaMalloc(&d_is_equality_row_, a_num_rows_ * sizeof(bool)));
2354
+ CUDA_CHECK(cudaMalloc(&d_x_current_, a_num_cols_ * sizeof(double)));
2355
+ CUDA_CHECK(cudaMalloc(&d_y_current_, a_num_rows_ * sizeof(double)));
2356
+ CUDA_CHECK(cudaMalloc(&d_x_avg_, a_num_cols_ * sizeof(double)));
2357
+ CUDA_CHECK(cudaMalloc(&d_y_avg_, a_num_rows_ * sizeof(double)));
2358
+ CUDA_CHECK(cudaMalloc(&d_x_next_, a_num_cols_ * sizeof(double)));
2359
+ CUDA_CHECK(cudaMalloc(&d_y_next_, a_num_rows_ * sizeof(double)));
2360
+ CUDA_CHECK(cudaMalloc(&d_x_at_last_restart_, a_num_cols_ * sizeof(double)));
2361
+ CUDA_CHECK(cudaMalloc(&d_y_at_last_restart_, a_num_rows_ * sizeof(double)));
2362
+ CUDA_CHECK(cudaMalloc(&d_x_anchor_, a_num_cols_ * sizeof(double)));
2363
+ CUDA_CHECK(cudaMalloc(&d_y_anchor_, a_num_rows_ * sizeof(double)));
2364
+ CUDA_CHECK(
2365
+ cudaMalloc(&d_x_temp_diff_norm_result_, a_num_cols_ * sizeof(double)));
2366
+ CUDA_CHECK(
2367
+ cudaMalloc(&d_y_temp_diff_norm_result_, a_num_rows_ * sizeof(double)));
2368
+ if (params_.use_halpern_restart) {
2369
+ CUDA_CHECK(cudaMalloc(&d_pdhg_primal_, a_num_cols_ * sizeof(double)));
2370
+ CUDA_CHECK(cudaMalloc(&d_pdhg_dual_, a_num_rows_ * sizeof(double)));
2371
+ CUDA_CHECK(cudaMemset(d_pdhg_primal_, 0, a_num_cols_ * sizeof(double)));
2372
+ CUDA_CHECK(cudaMemset(d_pdhg_dual_, 0, a_num_rows_ * sizeof(double)));
2373
+ }
2374
+ CUDA_CHECK(cudaMalloc(&d_delta_x_, a_num_cols_ * sizeof(double)));
2375
+ CUDA_CHECK(cudaMalloc(&d_delta_y_, a_num_rows_ * sizeof(double)));
2376
+ CUDA_CHECK(cudaMalloc(&d_AT_delta_y_, a_num_cols_ * sizeof(double)));
2377
+ CUDA_CHECK(cudaMalloc(&d_ax_current_, a_num_rows_ * sizeof(double)));
2378
+ CUDA_CHECK(cudaMalloc(&d_aty_current_, a_num_cols_ * sizeof(double)));
2379
+ CUDA_CHECK(cudaMalloc(&d_ax_next_, a_num_rows_ * sizeof(double)));
2380
+ CUDA_CHECK(cudaMalloc(&d_aty_next_, a_num_cols_ * sizeof(double)));
2381
+ CUDA_CHECK(cudaMalloc(&d_ax_avg_, a_num_rows_ * sizeof(double)));
2382
+ CUDA_CHECK(cudaMalloc(&d_aty_avg_, a_num_cols_ * sizeof(double)));
2383
+ CUDA_CHECK(cudaMalloc(&d_x_sum_, a_num_cols_ * sizeof(double)));
2384
+ CUDA_CHECK(cudaMalloc(&d_y_sum_, a_num_rows_ * sizeof(double)));
2385
+ CUDA_CHECK(cudaMalloc(&d_convergence_results_, 4 * sizeof(double)));
2386
+ CUDA_CHECK(cudaMalloc(&d_dSlackPos_, a_num_cols_ * sizeof(double)));
2387
+ CUDA_CHECK(cudaMalloc(&d_dSlackNeg_, a_num_cols_ * sizeof(double)));
2388
+ CUDA_CHECK(cudaMalloc(&d_dSlackPosAvg_, a_num_cols_ * sizeof(double)));
2389
+ CUDA_CHECK(cudaMalloc(&d_dSlackNegAvg_, a_num_cols_ * sizeof(double)));
2390
+ CUDA_CHECK(cudaMalloc(&d_col_scale_, a_num_cols_ * sizeof(double)));
2391
+ CUDA_CHECK(cudaMalloc(&d_row_scale_, a_num_rows_ * sizeof(double)));
2392
+
2393
+ CUSPARSE_CHECK(
2394
+ cusparseCreateDnVec(&vec_x_desc_, a_num_cols_, d_x_current_, CUDA_R_64F));
2395
+ CUSPARSE_CHECK(
2396
+ cusparseCreateDnVec(&vec_y_desc_, a_num_rows_, d_y_current_, CUDA_R_64F));
2397
+ CUSPARSE_CHECK(cusparseCreateDnVec(&vec_ax_desc_, a_num_rows_, d_ax_current_,
2398
+ CUDA_R_64F));
2399
+ CUSPARSE_CHECK(cusparseCreateDnVec(&vec_aty_desc_, a_num_cols_,
2400
+ d_aty_current_, CUDA_R_64F));
2401
+
2402
+ CUDA_CHECK(cudaMemcpy(d_col_cost_, lp_.col_cost_.data(),
2403
+ a_num_cols_ * sizeof(double), cudaMemcpyHostToDevice));
2404
+ CUDA_CHECK(cudaMemcpy(d_col_lower_, lp_.col_lower_.data(),
2405
+ a_num_cols_ * sizeof(double), cudaMemcpyHostToDevice));
2406
+ CUDA_CHECK(cudaMemcpy(d_col_upper_, lp_.col_upper_.data(),
2407
+ a_num_cols_ * sizeof(double), cudaMemcpyHostToDevice));
2408
+ CUDA_CHECK(cudaMemcpy(d_row_lower_, lp_.row_lower_.data(),
2409
+ a_num_rows_ * sizeof(double), cudaMemcpyHostToDevice));
2410
+ std::vector<uint8_t> temp_equality(a_num_rows_);
2411
+ for (HighsInt i = 0; i < a_num_rows_; ++i) {
2412
+ temp_equality[i] = is_equality_row_[i] ? 1 : 0;
2413
+ }
2414
+
2415
+ // Copy to device
2416
+ CUDA_CHECK(cudaMemcpy(d_is_equality_row_, temp_equality.data(),
2417
+ a_num_rows_ * sizeof(uint8_t), cudaMemcpyHostToDevice));
2418
+
2419
+ // 6. Preallocate buffer for cuSPARSE SpMV
2420
+ // Buffer for ax
2421
+ double alpha = 1.0;
2422
+ double beta = 0.0;
2423
+ cusparseDnVecDescr_t vec_x, vec_ax;
2424
+ CUSPARSE_CHECK(
2425
+ cusparseCreateDnVec(&vec_x, a_num_cols_, d_x_current_, CUDA_R_64F));
2426
+ CUSPARSE_CHECK(
2427
+ cusparseCreateDnVec(&vec_ax, a_num_rows_, d_ax_current_, CUDA_R_64F));
2428
+
2429
+ CUSPARSE_CHECK(cusparseSpMV_bufferSize(
2430
+ cusparse_handle_, CUSPARSE_OPERATION_NON_TRANSPOSE, &alpha, mat_a_csr_,
2431
+ vec_x, &beta, vec_ax, CUDA_R_64F, CUSPARSE_SPMV_CSR_ALG2,
2432
+ &spmv_buffer_size_ax_));
2433
+ CUDA_CHECK(cudaMalloc(&d_spmv_buffer_ax_, spmv_buffer_size_ax_));
2434
+
2435
+ CUSPARSE_CHECK(cusparseSpMV_preprocess(
2436
+ cusparse_handle_, CUSPARSE_OPERATION_NON_TRANSPOSE, &alpha, mat_a_csr_,
2437
+ vec_x_desc_, &beta, vec_ax_desc_, CUDA_R_64F, CUSPARSE_SPMV_CSR_ALG2,
2438
+ d_spmv_buffer_ax_));
2439
+
2440
+ CUSPARSE_CHECK(cusparseDestroyDnVec(vec_x));
2441
+ CUSPARSE_CHECK(cusparseDestroyDnVec(vec_ax));
2442
+
2443
+ // Buffer for aTy
2444
+ cusparseDnVecDescr_t vec_y, vec_aty;
2445
+ CUSPARSE_CHECK(
2446
+ cusparseCreateDnVec(&vec_y, a_num_rows_, d_y_current_, CUDA_R_64F));
2447
+ CUSPARSE_CHECK(
2448
+ cusparseCreateDnVec(&vec_aty, a_num_cols_, d_aty_current_, CUDA_R_64F));
2449
+ CUSPARSE_CHECK(cusparseSpMV_bufferSize(
2450
+ cusparse_handle_, CUSPARSE_OPERATION_NON_TRANSPOSE, &alpha, mat_a_T_csr_,
2451
+ vec_y, &beta, vec_aty, CUDA_R_64F, CUSPARSE_SPMV_CSR_ALG2,
2452
+ &spmv_buffer_size_aty_));
2453
+ CUDA_CHECK(cudaMalloc(&d_spmv_buffer_aty_, spmv_buffer_size_aty_));
2454
+
2455
+ CUSPARSE_CHECK(cusparseSpMV_preprocess(
2456
+ cusparse_handle_, CUSPARSE_OPERATION_NON_TRANSPOSE, &alpha, mat_a_T_csr_,
2457
+ vec_y_desc_, &beta, vec_aty_desc_, CUDA_R_64F, CUSPARSE_SPMV_CSR_ALG2,
2458
+ d_spmv_buffer_aty_));
2459
+
2460
+ CUSPARSE_CHECK(cusparseDestroyDnVec(vec_y));
2461
+ CUSPARSE_CHECK(cusparseDestroyDnVec(vec_aty));
2462
+
2463
+ CUDA_CHECK(cudaMemset(d_x_current_, 0, a_num_cols_ * sizeof(double)));
2464
+ CUDA_CHECK(cudaMemset(d_y_current_, 0, a_num_rows_ * sizeof(double)));
2465
+ CUDA_CHECK(cudaMemset(d_x_avg_, 0, a_num_cols_ * sizeof(double)));
2466
+ CUDA_CHECK(cudaMemset(d_y_avg_, 0, a_num_rows_ * sizeof(double)));
2467
+ CUDA_CHECK(cudaMemset(d_x_next_, 0, a_num_cols_ * sizeof(double)));
2468
+ CUDA_CHECK(cudaMemset(d_y_next_, 0, a_num_rows_ * sizeof(double)));
2469
+ CUDA_CHECK(cudaMemset(d_ax_current_, 0, a_num_rows_ * sizeof(double)));
2470
+ CUDA_CHECK(cudaMemset(d_ax_next_, 0, a_num_rows_ * sizeof(double)));
2471
+ CUDA_CHECK(cudaMemset(d_ax_avg_, 0, a_num_rows_ * sizeof(double)));
2472
+ CUDA_CHECK(cudaMemset(d_aty_avg_, 0, a_num_cols_ * sizeof(double)));
2473
+ CUDA_CHECK(cudaMemset(d_x_sum_, 0, a_num_cols_ * sizeof(double)));
2474
+ CUDA_CHECK(cudaMemset(d_y_sum_, 0, a_num_rows_ * sizeof(double)));
2475
+ CUDA_CHECK(cudaMemset(d_aty_current_, 0, a_num_cols_ * sizeof(double)));
2476
+ sum_weights_gpu_ = 0.0;
2477
+
2478
+ if (scaling_.isScaled()) {
2479
+ CUDA_CHECK(cudaMemcpy(d_col_scale_, scaling_.getColScaling().data(),
2480
+ a_num_cols_ * sizeof(double),
2481
+ cudaMemcpyHostToDevice));
2482
+ CUDA_CHECK(cudaMemcpy(d_row_scale_, scaling_.getRowScaling().data(),
2483
+ a_num_rows_ * sizeof(double),
2484
+ cudaMemcpyHostToDevice));
2485
+ } else {
2486
+ cudaFree(d_col_scale_);
2487
+ d_col_scale_ = nullptr;
2488
+ cudaFree(d_row_scale_);
2489
+ d_row_scale_ = nullptr;
2490
+ }
2491
+
2492
+ size_t max_size = std::max(a_num_cols_, a_num_rows_);
2493
+ CUDA_CHECK(cudaMalloc(&d_buffer_, max_size * sizeof(double)));
2494
+ CUDA_CHECK(cudaMalloc(&d_buffer2_, max_size * sizeof(double)));
2495
+
2496
+ highsLogDev(params_.log_options_, HighsLogType::kInfo,
2497
+ "GPU setup complete. Matrix A (CSR) and A^T (CSR) transferred "
2498
+ "to device.\n");
2499
+ }
2500
+
2501
+ void PDLPSolver::cleanupGpu() {
2502
+ if (gpu_stream_) CUDA_CHECK(cudaStreamDestroy(gpu_stream_));
2503
+ if (cusparse_handle_) CUSPARSE_CHECK(cusparseDestroy(cusparse_handle_));
2504
+ if (cublas_handle_) CUBLAS_CHECK(cublasDestroy(cublas_handle_));
2505
+ if (mat_a_csr_) CUSPARSE_CHECK(cusparseDestroySpMat(mat_a_csr_));
2506
+ if (mat_a_T_csr_) CUSPARSE_CHECK(cusparseDestroySpMat(mat_a_T_csr_));
2507
+ CUDA_CHECK(cudaFree(d_a_row_ptr_));
2508
+ CUDA_CHECK(cudaFree(d_a_col_ind_));
2509
+ CUDA_CHECK(cudaFree(d_a_val_));
2510
+ CUDA_CHECK(cudaFree(d_at_row_ptr_));
2511
+ CUDA_CHECK(cudaFree(d_at_col_ind_));
2512
+ CUDA_CHECK(cudaFree(d_at_val_));
2513
+ CUDA_CHECK(cudaFree(d_col_cost_));
2514
+ CUDA_CHECK(cudaFree(d_col_lower_));
2515
+ CUDA_CHECK(cudaFree(d_col_upper_));
2516
+ CUDA_CHECK(cudaFree(d_row_lower_));
2517
+ CUDA_CHECK(cudaFree(d_is_equality_row_));
2518
+ CUDA_CHECK(cudaFree(d_x_at_last_restart_));
2519
+ CUDA_CHECK(cudaFree(d_y_at_last_restart_));
2520
+ CUDA_CHECK(cudaFree(d_halpern_iteration_));
2521
+ CUDA_CHECK(cudaFree(d_primal_step_size_));
2522
+ CUDA_CHECK(cudaFree(d_dual_step_size_));
2523
+ if (d_x_anchor_) CUDA_CHECK(cudaFree(d_x_anchor_));
2524
+ if (d_y_anchor_) CUDA_CHECK(cudaFree(d_y_anchor_));
2525
+ if (d_pdhg_primal_) CUDA_CHECK(cudaFree(d_pdhg_primal_));
2526
+ if (d_pdhg_dual_) CUDA_CHECK(cudaFree(d_pdhg_dual_));
2527
+ CUDA_CHECK(cudaFree(d_delta_x_));
2528
+ CUDA_CHECK(cudaFree(d_delta_y_));
2529
+ CUDA_CHECK(cudaFree(d_AT_delta_y_));
2530
+ CUDA_CHECK(cudaFree(d_x_temp_diff_norm_result_));
2531
+ CUDA_CHECK(cudaFree(d_y_temp_diff_norm_result_));
2532
+ CUDA_CHECK(cudaFree(d_x_current_));
2533
+ CUDA_CHECK(cudaFree(d_y_current_));
2534
+ CUDA_CHECK(cudaFree(d_x_next_));
2535
+ CUDA_CHECK(cudaFree(d_y_next_));
2536
+ CUDA_CHECK(cudaFree(d_ax_current_));
2537
+ CUDA_CHECK(cudaFree(d_aty_current_));
2538
+ CUDA_CHECK(cudaFree(d_ax_avg_));
2539
+ CUDA_CHECK(cudaFree(d_aty_avg_));
2540
+ CUDA_CHECK(cudaFree(d_ax_next_));
2541
+ CUDA_CHECK(cudaFree(d_aty_next_));
2542
+ CUDA_CHECK(cudaFree(d_x_sum_));
2543
+ CUDA_CHECK(cudaFree(d_y_sum_));
2544
+ CUDA_CHECK(cudaFree(d_spmv_buffer_ax_));
2545
+ CUDA_CHECK(cudaFree(d_spmv_buffer_aty_));
2546
+ CUDA_CHECK(cudaFree(d_convergence_results_));
2547
+ CUDA_CHECK(cudaFree(d_dSlackPos_));
2548
+ CUDA_CHECK(cudaFree(d_dSlackNeg_));
2549
+ CUDA_CHECK(cudaFree(d_dSlackPosAvg_));
2550
+ CUDA_CHECK(cudaFree(d_dSlackNegAvg_));
2551
+ if (d_col_scale_) CUDA_CHECK(cudaFree(d_col_scale_));
2552
+ if (d_row_scale_) CUDA_CHECK(cudaFree(d_row_scale_));
2553
+ CUDA_CHECK(cudaFree(d_buffer_));
2554
+ CUDA_CHECK(cudaFree(d_buffer2_));
2555
+ if (vec_x_desc_) CUSPARSE_CHECK(cusparseDestroyDnVec(vec_x_desc_));
2556
+ if (vec_y_desc_) CUSPARSE_CHECK(cusparseDestroyDnVec(vec_y_desc_));
2557
+ if (vec_ax_desc_) CUSPARSE_CHECK(cusparseDestroyDnVec(vec_ax_desc_));
2558
+ if (vec_aty_desc_) CUSPARSE_CHECK(cusparseDestroyDnVec(vec_aty_desc_));
2559
+ }
2560
+
2561
+ void PDLPSolver::linalgGpuAx(const double* d_x_in, double* d_ax_out) {
2562
+ // ax = 1.0 * A * x + 0.0 * ax
2563
+ double alpha = 1.0;
2564
+ double beta = 0.0;
2565
+
2566
+ CUSPARSE_CHECK(cusparseDnVecSetValues(vec_x_desc_, (void*)d_x_in));
2567
+ CUSPARSE_CHECK(cusparseDnVecSetValues(vec_ax_desc_, (void*)d_ax_out));
2568
+ if (spmv_buffer_size_ax_ == 0) {
2569
+ CUSPARSE_CHECK(cusparseSpMV_bufferSize(
2570
+ cusparse_handle_, CUSPARSE_OPERATION_NON_TRANSPOSE, &alpha, mat_a_csr_,
2571
+ vec_x_desc_, &beta, vec_ax_desc_, CUDA_R_64F, CUSPARSE_SPMV_CSR_ALG2,
2572
+ &spmv_buffer_size_ax_));
2573
+ CUDA_CHECK(cudaMalloc(&d_spmv_buffer_ax_, spmv_buffer_size_ax_));
2574
+ }
2575
+
2576
+ CUSPARSE_CHECK(
2577
+ cusparseSpMV(cusparse_handle_, CUSPARSE_OPERATION_NON_TRANSPOSE, &alpha,
2578
+ mat_a_csr_, vec_x_desc_, &beta, vec_ax_desc_, CUDA_R_64F,
2579
+ CUSPARSE_SPMV_CSR_ALG2, d_spmv_buffer_ax_));
2580
+ }
2581
+
2582
+ void PDLPSolver::linalgGpuATy(const double* d_y_in, double* d_aty_out) {
2583
+ // aTy = 1.0 * A^T * y + 0.0 * aty
2584
+ double alpha = 1.0;
2585
+ double beta = 0.0;
2586
+
2587
+ CUSPARSE_CHECK(cusparseDnVecSetValues(vec_y_desc_, (void*)d_y_in));
2588
+ CUSPARSE_CHECK(cusparseDnVecSetValues(vec_aty_desc_, (void*)d_aty_out));
2589
+ if (spmv_buffer_size_aty_ == 0) {
2590
+ CUSPARSE_CHECK(cusparseSpMV_bufferSize(
2591
+ cusparse_handle_, CUSPARSE_OPERATION_NON_TRANSPOSE, &alpha,
2592
+ mat_a_T_csr_, vec_y_desc_, &beta, vec_aty_desc_, CUDA_R_64F,
2593
+ CUSPARSE_SPMV_CSR_ALG2, &spmv_buffer_size_aty_));
2594
+ CUDA_CHECK(cudaMalloc(&d_spmv_buffer_aty_, spmv_buffer_size_aty_));
2595
+ }
2596
+ CUSPARSE_CHECK(
2597
+ cusparseSpMV(cusparse_handle_, CUSPARSE_OPERATION_NON_TRANSPOSE, &alpha,
2598
+ mat_a_T_csr_, vec_y_desc_, &beta, vec_aty_desc_, CUDA_R_64F,
2599
+ CUSPARSE_SPMV_CSR_ALG2, d_spmv_buffer_aty_));
2600
+ }
2601
+
2602
+ void PDLPSolver::launchKernelUpdateX(double primal_step) {
2603
+ launchKernelUpdateX_wrapper(d_x_next_, d_x_current_, d_aty_current_,
2604
+ d_col_cost_, d_col_lower_, d_col_upper_,
2605
+ primal_step, a_num_cols_, gpu_stream_);
2606
+ CUDA_CHECK(cudaGetLastError());
2607
+ }
2608
+
2609
+ void PDLPSolver::launchKernelUpdateY(double dual_step) {
2610
+ launchKernelUpdateY_wrapper(d_y_next_, d_y_current_, d_ax_current_,
2611
+ d_ax_next_, d_row_lower_, d_is_equality_row_,
2612
+ dual_step, a_num_rows_, gpu_stream_);
2613
+ CUDA_CHECK(cudaGetLastError());
2614
+ }
2615
+
2616
+ void PDLPSolver::launchKernelUpdateAverages(double weight) {
2617
+ launchKernelUpdateAverages_wrapper(d_x_sum_, d_y_sum_, d_x_next_, d_y_next_,
2618
+ weight, a_num_cols_, a_num_rows_,
2619
+ gpu_stream_);
2620
+ CUDA_CHECK(cudaGetLastError());
2621
+ }
2622
+
2623
+ void PDLPSolver::launchKernelScaleVector(double* d_out, const double* d_in,
2624
+ double Scale, int n) {
2625
+ launchKernelScaleVector_wrapper(d_out, d_in, Scale, n, gpu_stream_);
2626
+ CUDA_CHECK(cudaGetLastError());
2627
+ }
2628
+
2629
+ bool PDLPSolver::checkConvergenceGpu(const HighsInt iter, const double* d_x,
2630
+ const double* d_y, const double* d_ax,
2631
+ const double* d_aty, double epsilon,
2632
+ SolverResults& results, const char* type,
2633
+ double* d_slackPos_out,
2634
+ double* d_slackNeg_out,
2635
+ bool use_halpern_slack) {
2636
+ launchCheckConvergenceKernels_wrapper(
2637
+ d_convergence_results_, d_slackPos_out, d_slackNeg_out, d_x, d_y, d_ax,
2638
+ d_aty, d_col_cost_, d_row_lower_, d_col_lower_, d_col_upper_,
2639
+ d_is_equality_row_, d_col_scale_, d_row_scale_, lp_.num_col_,
2640
+ lp_.num_row_, use_halpern_slack, gpu_stream_);
2641
+
2642
+ // copy 4 doubles back to CPU
2643
+
2644
+ double h_results[4];
2645
+ CUDA_CHECK(cudaMemcpy(h_results, d_convergence_results_, 4 * sizeof(double),
2646
+ cudaMemcpyDeviceToHost));
2647
+
2648
+ double primal_feas_sq = h_results[0];
2649
+ double dual_feas_sq = h_results[1];
2650
+ double primal_obj = h_results[2] + lp_.offset_;
2651
+ double dual_obj = h_results[3] + lp_.offset_;
2652
+
2653
+ results.primal_feasibility = std::sqrt(primal_feas_sq);
2654
+ results.dual_feasibility = std::sqrt(dual_feas_sq);
2655
+ results.primal_obj = primal_obj;
2656
+ results.dual_obj = dual_obj;
2657
+
2658
+ double duality_gap = primal_obj - dual_obj;
2659
+ results.duality_gap = std::abs(duality_gap);
2660
+ results.relative_obj_gap =
2661
+ std::abs(duality_gap) / (1.0 + std::abs(primal_obj) + std::abs(dual_obj));
2662
+
2663
+ #if PDLP_DEBUG_LOG
2664
+ debugPdlpFeasOptLog(debug_pdlp_log_file_, iter, primal_obj, dual_obj,
2665
+ results.relative_obj_gap,
2666
+ results.primal_feasibility / (1.0 + unscaled_rhs_norm_),
2667
+ results.dual_feasibility / (1.0 + unscaled_c_norm_),
2668
+ type);
2669
+ #endif
2670
+
2671
+ bool primal_feasible =
2672
+ results.primal_feasibility < epsilon * (1.0 + unscaled_rhs_norm_);
2673
+ bool dual_feasible =
2674
+ results.dual_feasibility < epsilon * (1.0 + unscaled_c_norm_);
2675
+ bool gap_small = results.relative_obj_gap < epsilon;
2676
+
2677
+ return primal_feasible && dual_feasible && gap_small;
2678
+ }
2679
+
2680
+ void PDLPSolver::computeStepSizeRatioGpu(PrimalDualParams& working_params) {
2681
+ // 1. Compute ||x_last - x_current||^2 using cuBLAS
2682
+ double primal_diff_norm =
2683
+ computeDiffNormCuBLAS(d_x_at_last_restart_, d_x_current_, a_num_cols_);
2684
+
2685
+ // 2. Compute ||y_last - y_current||^2 using cuBLAS
2686
+ double dual_diff_norm =
2687
+ computeDiffNormCuBLAS(d_y_at_last_restart_, d_y_current_, a_num_rows_);
2688
+
2689
+ double dMeanStepSize = std::sqrt(stepsize_.primal_step * stepsize_.dual_step);
2690
+
2691
+ // 3. Update beta (same CPU logic)
2692
+ if (std::min(primal_diff_norm, dual_diff_norm) > 1e-10) {
2693
+ double beta_update_ratio = dual_diff_norm / primal_diff_norm;
2694
+ double old_beta = stepsize_.beta;
2695
+ double dLogBetaUpdate =
2696
+ 0.5 * std::log(beta_update_ratio) + 0.5 * std::log(std::sqrt(old_beta));
2697
+ stepsize_.beta = std::exp(2.0 * dLogBetaUpdate);
2698
+ }
2699
+
2700
+ // Update step sizes
2701
+ stepsize_.primal_step = dMeanStepSize / std::sqrt(stepsize_.beta);
2702
+ stepsize_.dual_step = stepsize_.primal_step * stepsize_.beta;
2703
+ working_params.eta = std::sqrt(stepsize_.primal_step * stepsize_.dual_step);
2704
+ working_params.omega = std::sqrt(stepsize_.beta);
2705
+ restart_scheme_.updateBeta(stepsize_.beta);
2706
+ }
2707
+
2708
+ void PDLPSolver::updateAverageIteratesGpu(HighsInt inner_iter) {
2709
+ double dMeanStepSize = std::sqrt(stepsize_.primal_step * stepsize_.dual_step);
2710
+
2711
+ launchKernelUpdateAverages(dMeanStepSize);
2712
+
2713
+ sum_weights_gpu_ += dMeanStepSize;
2714
+ }
2715
+
2716
+ void PDLPSolver::computeAverageIterateGpu() {
2717
+ double dScale = sum_weights_gpu_ > 1e-10 ? 1.0 / sum_weights_gpu_ : 1.0;
2718
+
2719
+ // x_avg = x_sum * Scale
2720
+ launchKernelScaleVector(d_x_avg_, d_x_sum_, dScale, a_num_cols_);
2721
+
2722
+ // y_avg = y_sum * Scale
2723
+ launchKernelScaleVector(d_y_avg_, d_y_sum_, dScale, a_num_rows_);
2724
+
2725
+ // Recompute Ax_avg and ATy_avg on GPU
2726
+ linalgGpuAx(d_x_avg_, d_ax_avg_);
2727
+ linalgGpuATy(d_y_avg_, d_aty_avg_);
2728
+
2729
+ #if PDLP_DEBUG_LOG
2730
+ // copy x_avg to host
2731
+ CUDA_CHECK(cudaMemcpy(x_avg_.data(), d_x_avg_, a_num_cols_ * sizeof(double),
2732
+ cudaMemcpyDeviceToHost));
2733
+ debug_pdlp_data_.x_average_norm = linalg::vectorNormSquared(x_avg_);
2734
+ #endif
2735
+ }
2736
+
2737
+ double PDLPSolver::computeMovementGpu(const double* d_x_new,
2738
+ const double* d_x_old,
2739
+ const double* d_y_new,
2740
+ const double* d_y_old) {
2741
+ // 1. Compute ||x_new - x_old|| using cuBLAS
2742
+ double primal_diff_norm =
2743
+ computeDiffNormCuBLAS(d_x_new, d_x_old, a_num_cols_);
2744
+
2745
+ // 2. Compute ||y_new - y_old|| using cuBLAS
2746
+ double dual_diff_norm = computeDiffNormCuBLAS(d_y_new, d_y_old, a_num_rows_);
2747
+
2748
+ // 3. Combine on CPU
2749
+ double primal_weight = std::sqrt(stepsize_.beta);
2750
+ double primal_diff_sq = primal_diff_norm * primal_diff_norm;
2751
+ double dual_diff_sq = dual_diff_norm * dual_diff_norm;
2752
+
2753
+ return (0.5 * primal_weight * primal_diff_sq) +
2754
+ (0.5 / primal_weight * dual_diff_sq);
2755
+ }
2756
+
2757
+ double PDLPSolver::computeNonlinearityGpu(const double* d_x_new,
2758
+ const double* d_x_old,
2759
+ const double* d_aty_new,
2760
+ const double* d_aty_old) {
2761
+ // 1. Compute delta_x = x_new - x_old
2762
+ CUDA_CHECK(cudaMemcpy(d_buffer_, d_x_new, a_num_cols_ * sizeof(double),
2763
+ cudaMemcpyDeviceToDevice));
2764
+ double alpha = -1.0;
2765
+ CUBLAS_CHECK(cublasDaxpy(cublas_handle_, a_num_cols_, &alpha, d_x_old, 1,
2766
+ d_buffer_, 1));
2767
+
2768
+ // 2. Compute delta_aty = aty_new - aty_old
2769
+ CUDA_CHECK(cudaMemcpy(d_buffer2_, d_aty_new, a_num_cols_ * sizeof(double),
2770
+ cudaMemcpyDeviceToDevice));
2771
+ CUBLAS_CHECK(cublasDaxpy(cublas_handle_, a_num_cols_, &alpha, d_aty_old, 1,
2772
+ d_buffer2_, 1));
2773
+
2774
+ // 3. Compute Dot product: delta_x' * delta_aty
2775
+ double result;
2776
+ CUBLAS_CHECK(cublasDdot(cublas_handle_, a_num_cols_, d_buffer_, 1, d_buffer2_,
2777
+ 1, &result));
2778
+
2779
+ return result;
2780
+ }
2781
+
2782
+ double PDLPSolver::computeDiffNormCuBLAS(const double* d_a, const double* d_b,
2783
+ HighsInt n) {
2784
+ // 1. Copy a to buffer: buffer = a
2785
+ CUDA_CHECK(
2786
+ cudaMemcpy(d_buffer_, d_a, n * sizeof(double), cudaMemcpyDeviceToDevice));
2787
+
2788
+ // 2. buffer = buffer - b (using cuBLAS axpy)
2789
+ double alpha = -1.0;
2790
+ CUBLAS_CHECK(cublasDaxpy(cublas_handle_, n, &alpha, d_b, 1, d_buffer_, 1));
2791
+
2792
+ // 3. result = ||buffer||_2 (using cuBLAS Norm2)
2793
+ double norm;
2794
+ CUBLAS_CHECK(cublasDnrm2(cublas_handle_, n, d_buffer_, 1, &norm));
2795
+
2796
+ return norm;
2797
+ }
2798
+ #endif