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,1921 @@
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 HighsSymmetry.cpp
9
+ * @brief Facilities for symmetry detection
10
+ * @author Leona Gottwald
11
+ */
12
+
13
+ #include "presolve/HighsSymmetry.h"
14
+
15
+ #include <algorithm>
16
+ #include <numeric>
17
+
18
+ #include "../extern/pdqsort/pdqsort.h"
19
+ #include "mip/HighsCliqueTable.h"
20
+ #include "mip/HighsDomain.h"
21
+ #include "parallel/HighsParallel.h"
22
+ #include "util/HighsDisjointSets.h"
23
+
24
+ void HighsSymmetryDetection::removeFixPoints() {
25
+ Gend.resize(numVertices);
26
+ for (HighsInt i = 0; i < numVertices; ++i) {
27
+ Gend[i] =
28
+ std::partition(Gedge.begin() + Gstart[i], Gedge.begin() + Gstart[i + 1],
29
+ [&](const std::pair<HighsInt, HighsUInt>& edge) {
30
+ return cellSize(vertexToCell[edge.first]) > 1;
31
+ }) -
32
+ Gedge.begin();
33
+ assert(Gend[i] >= Gstart[i] && Gend[i] <= Gstart[i + 1]);
34
+ }
35
+
36
+ HighsInt unitCellIndex = numVertices;
37
+ currentPartition.erase(
38
+ std::remove_if(currentPartition.begin(), currentPartition.end(),
39
+ [&](HighsInt vertex) {
40
+ if (cellSize(vertexToCell[vertex]) == 1) {
41
+ --unitCellIndex;
42
+ vertexToCell[vertex] = unitCellIndex;
43
+ return true;
44
+ }
45
+ return false;
46
+ }),
47
+ currentPartition.end());
48
+
49
+ for (HighsInt i = 0; i < numVertices; ++i) {
50
+ if (Gend[i] == Gstart[i + 1]) continue;
51
+
52
+ for (HighsInt j = Gend[i]; j < Gstart[i + 1]; ++j)
53
+ Gedge[j].first = vertexToCell[Gedge[j].first];
54
+ }
55
+
56
+ if ((HighsInt)currentPartition.size() < numVertices) {
57
+ numVertices = currentPartition.size();
58
+ if (numVertices == 0) {
59
+ numActiveCols = 0;
60
+ return;
61
+ }
62
+ currentPartitionLinks.resize(numVertices);
63
+ cellInRefinementQueue.assign(numVertices, false);
64
+ assert(refinementQueue.empty());
65
+ refinementQueue.clear();
66
+ HighsInt cellStart = 0;
67
+ HighsInt cellNumber = 0;
68
+ for (HighsInt i = 0; i < numVertices; ++i) {
69
+ HighsInt vertex = currentPartition[i];
70
+ // if the cell number is different to the current cell number this is the
71
+ // start of a new cell
72
+ if (cellNumber != vertexToCell[vertex]) {
73
+ // remember the number of this cell to identify its end
74
+ cellNumber = vertexToCell[vertex];
75
+ // set the link of the cell start to point to its end
76
+ currentPartitionLinks[cellStart] = i;
77
+ // remember start of this cell
78
+ cellStart = i;
79
+ }
80
+
81
+ // correct the vertexToCell array to store the start index of the
82
+ // cell, not its number
83
+ updateCellMembership(i, cellStart, false);
84
+ }
85
+
86
+ // set the column partition link of the last started cell to point past the
87
+ // end
88
+ assert((int)currentPartitionLinks.size() > 0);
89
+ currentPartitionLinks[cellStart] = numVertices;
90
+
91
+ numActiveCols =
92
+ std::partition_point(currentPartition.begin(), currentPartition.end(),
93
+ [&](HighsInt v) { return v < numCol; }) -
94
+ currentPartition.begin();
95
+ } else
96
+ numActiveCols = numCol;
97
+ }
98
+
99
+ void HighsSymmetries::clear() {
100
+ permutationColumns.clear();
101
+ permutations.clear();
102
+ orbitPartition.clear();
103
+ orbitSize.clear();
104
+ columnPosition.clear();
105
+ linkCompressionStack.clear();
106
+ columnToOrbitope.clear();
107
+ orbitopes.clear();
108
+ numPerms = 0;
109
+ numGenerators = 0;
110
+ }
111
+
112
+ void HighsSymmetries::mergeOrbits(HighsInt v1, HighsInt v2) {
113
+ if (v1 == v2) return;
114
+
115
+ HighsInt orbit1 = getOrbit(v1);
116
+ HighsInt orbit2 = getOrbit(v2);
117
+
118
+ if (orbit1 == orbit2) return;
119
+
120
+ if (orbitSize[orbit2] < orbitSize[orbit1]) {
121
+ orbitPartition[orbit2] = orbit1;
122
+ orbitSize[orbit1] += orbitSize[orbit2];
123
+ } else {
124
+ orbitPartition[orbit1] = orbit2;
125
+ orbitSize[orbit2] += orbitSize[orbit1];
126
+ }
127
+
128
+ return;
129
+ }
130
+
131
+ HighsInt HighsSymmetries::getOrbit(HighsInt col) {
132
+ HighsInt i = columnPosition[col];
133
+ if (i == -1) return -1;
134
+ HighsInt orbit = orbitPartition[i];
135
+ if (orbit != orbitPartition[orbit]) {
136
+ do {
137
+ linkCompressionStack.push_back(i);
138
+ i = orbit;
139
+ orbit = orbitPartition[orbit];
140
+ } while (orbit != orbitPartition[orbit]);
141
+
142
+ do {
143
+ i = linkCompressionStack.back();
144
+ linkCompressionStack.pop_back();
145
+ orbitPartition[i] = orbit;
146
+ } while (!linkCompressionStack.empty());
147
+ }
148
+
149
+ return orbit;
150
+ }
151
+
152
+ HighsInt HighsSymmetries::propagateOrbitopes(HighsDomain& domain) const {
153
+ if (columnToOrbitope.size() == 0 || domain.getBranchDepth() == 0) return 0;
154
+
155
+ std::set<HighsInt> propagationOrbitopes;
156
+ const auto& domchgstack = domain.getDomainChangeStack();
157
+ for (HighsInt pos : domain.getBranchingPositions()) {
158
+ const HighsInt* orbitope = columnToOrbitope.find(domchgstack[pos].column);
159
+ if (orbitope) propagationOrbitopes.insert(*orbitope);
160
+ }
161
+
162
+ HighsInt numFixed = 0;
163
+ for (HighsInt i : propagationOrbitopes) {
164
+ numFixed += orbitopes[i].orbitalFixing(domain);
165
+ if (domain.infeasible()) break;
166
+ }
167
+
168
+ // if (numFixed)
169
+ // printf("orbital fixing for full orbitope found %d fixings\n", numFixed);
170
+
171
+ return numFixed;
172
+ }
173
+
174
+ std::shared_ptr<const StabilizerOrbits>
175
+ HighsSymmetries::computeStabilizerOrbits(const HighsDomain& localdom) {
176
+ const auto& domchgStack = localdom.getDomainChangeStack();
177
+ const auto& branchingPos = localdom.getBranchingPositions();
178
+
179
+ StabilizerOrbits stabilizerOrbits;
180
+ stabilizerOrbits.stabilizedCols.reserve(permutationColumns.size());
181
+ for (HighsInt i : branchingPos) {
182
+ HighsInt col = domchgStack[i].column;
183
+ if (columnPosition[col] == -1) continue;
184
+
185
+ assert(localdom.variableType(col) != HighsVarType::kContinuous);
186
+
187
+ // if we branch a variable upwards it is either binary and branched to one
188
+ // and needs to be stabilized or it is a general integer and needs to be
189
+ // stabilized regardless of branching direction.
190
+ // if we branch downwards we only need to stabilize on this
191
+ // branching column if it is a general integer
192
+ if (domchgStack[i].boundtype == HighsBoundType::kLower ||
193
+ !localdom.isGlobalBinary(col))
194
+ stabilizerOrbits.stabilizedCols.push_back(columnPosition[col]);
195
+ }
196
+
197
+ HighsInt permLength = permutationColumns.size();
198
+ orbitPartition.resize(permLength);
199
+ std::iota(orbitPartition.begin(), orbitPartition.end(), 0);
200
+ orbitSize.assign(permLength, 1);
201
+
202
+ for (HighsInt i = 0; i < numPerms; ++i) {
203
+ const HighsInt* perm = permutations.data() + i * permutationColumns.size();
204
+
205
+ bool permRespectsBranchings = true;
206
+ for (HighsInt i : stabilizerOrbits.stabilizedCols) {
207
+ if (permutationColumns[i] != perm[i]) {
208
+ permRespectsBranchings = false;
209
+ break;
210
+ }
211
+ }
212
+
213
+ if (!permRespectsBranchings) continue;
214
+
215
+ for (HighsInt j = 0; j < permLength; ++j) {
216
+ mergeOrbits(permutationColumns[j], perm[j]);
217
+ }
218
+ }
219
+
220
+ stabilizerOrbits.stabilizedCols.clear();
221
+
222
+ stabilizerOrbits.orbitCols.reserve(permLength);
223
+ for (HighsInt i = 0; i < permLength; ++i) {
224
+ if (localdom.variableType(permutationColumns[i]) ==
225
+ HighsVarType::kContinuous)
226
+ continue;
227
+ HighsInt orbit = getOrbit(permutationColumns[i]);
228
+ if (orbitSize[orbit] == 1)
229
+ stabilizerOrbits.stabilizedCols.push_back(permutationColumns[i]);
230
+ else if (localdom.isGlobalBinary(permutationColumns[i]))
231
+ stabilizerOrbits.orbitCols.push_back(permutationColumns[i]);
232
+ }
233
+ stabilizerOrbits.symmetries = this;
234
+ pdqsort(stabilizerOrbits.stabilizedCols.begin(),
235
+ stabilizerOrbits.stabilizedCols.end());
236
+ if (!stabilizerOrbits.orbitCols.empty()) {
237
+ pdqsort(stabilizerOrbits.orbitCols.begin(),
238
+ stabilizerOrbits.orbitCols.end(),
239
+ [&](HighsInt col1, HighsInt col2) {
240
+ return getOrbit(col1) < getOrbit(col2);
241
+ });
242
+ HighsInt numOrbitCols = stabilizerOrbits.orbitCols.size();
243
+ stabilizerOrbits.orbitStarts.reserve(numOrbitCols + 1);
244
+ stabilizerOrbits.orbitStarts.push_back(0);
245
+
246
+ for (HighsInt i = 1; i < numOrbitCols; ++i) {
247
+ if (getOrbit(stabilizerOrbits.orbitCols[i]) !=
248
+ getOrbit(stabilizerOrbits.orbitCols[i - 1]))
249
+ stabilizerOrbits.orbitStarts.push_back(i);
250
+ }
251
+ stabilizerOrbits.orbitStarts.push_back(numOrbitCols);
252
+ }
253
+
254
+ return std::make_shared<const StabilizerOrbits>(std::move(stabilizerOrbits));
255
+ }
256
+
257
+ HighsInt StabilizerOrbits::orbitalFixing(HighsDomain& domain) const {
258
+ HighsInt numFixed = symmetries->propagateOrbitopes(domain);
259
+ if (domain.infeasible() || orbitCols.empty()) return numFixed;
260
+
261
+ HighsInt numOrbits = orbitStarts.size() - 1;
262
+ for (HighsInt i = 0; i < numOrbits; ++i) {
263
+ HighsInt fixcol = -1;
264
+ for (HighsInt j = orbitStarts[i]; j < orbitStarts[i + 1]; ++j) {
265
+ if (domain.isFixed(orbitCols[j])) {
266
+ fixcol = orbitCols[j];
267
+ break;
268
+ }
269
+ }
270
+
271
+ if (fixcol != -1) {
272
+ HighsInt oldNumFixed = numFixed;
273
+ auto oldSize = domain.getDomainChangeStack().size();
274
+ if (domain.col_lower_[fixcol] == 1.0) {
275
+ for (HighsInt j = orbitStarts[i]; j < orbitStarts[i + 1]; ++j) {
276
+ if (domain.col_lower_[orbitCols[j]] == 1.0) continue;
277
+ ++numFixed;
278
+ domain.changeBound(HighsBoundType::kLower, orbitCols[j], 1.0,
279
+ HighsDomain::Reason::unspecified());
280
+ if (domain.infeasible()) return numFixed;
281
+ }
282
+ } else {
283
+ for (HighsInt j = orbitStarts[i]; j < orbitStarts[i + 1]; ++j) {
284
+ if (domain.col_upper_[orbitCols[j]] == 0.0) continue;
285
+ ++numFixed;
286
+ domain.changeBound(HighsBoundType::kUpper, orbitCols[j], 0.0,
287
+ HighsDomain::Reason::unspecified());
288
+ if (domain.infeasible()) return numFixed;
289
+ }
290
+ }
291
+
292
+ HighsInt newFixed = numFixed - oldNumFixed;
293
+
294
+ if (newFixed != 0) {
295
+ domain.propagate();
296
+ if (domain.infeasible()) return numFixed;
297
+ if ((HighsInt)(domain.getDomainChangeStack().size() - oldSize) >
298
+ newFixed)
299
+ i = -1;
300
+ }
301
+ }
302
+ }
303
+
304
+ return numFixed;
305
+ }
306
+
307
+ bool StabilizerOrbits::isStabilized(HighsInt col) const {
308
+ return symmetries->columnPosition[col] == -1 ||
309
+ std::binary_search(stabilizedCols.begin(), stabilizedCols.end(), col);
310
+ }
311
+
312
+ void HighsOrbitopeMatrix::determineOrbitopeType(HighsCliqueTable& cliquetable) {
313
+ for (HighsInt j = 0; j < rowLength; ++j) {
314
+ for (HighsInt i = 0; i < numRows; ++i) {
315
+ columnToRow.insert(entry(i, j), i);
316
+ }
317
+ }
318
+
319
+ rowIsSetPacking.assign(numRows, -1);
320
+ numSetPackingRows = 0;
321
+
322
+ for (HighsInt j = 1; j < rowLength; ++j) {
323
+ HighsInt* colj1 = &entry(0, j);
324
+
325
+ for (HighsInt j0 = 0; j0 < j; ++j0) {
326
+ HighsInt* colj0 = &entry(0, j0);
327
+
328
+ for (HighsInt i = 0; i < numRows; ++i) {
329
+ if (rowIsSetPacking[i] != -1) continue;
330
+
331
+ HighsInt xj0 = colj0[i];
332
+ HighsInt xj1 = colj1[i];
333
+
334
+ auto commonClique = cliquetable.findCommonClique({xj0, 1}, {xj1, 1});
335
+
336
+ if (commonClique.first == nullptr) {
337
+ rowIsSetPacking[i] = false;
338
+ continue;
339
+ }
340
+
341
+ HighsInt overlap = 0;
342
+
343
+ for (HighsInt k = 0; k < commonClique.second; ++k) {
344
+ if (commonClique.first[k].val == 0) continue;
345
+
346
+ HighsInt* cliqueColRow = columnToRow.find(commonClique.first[k].col);
347
+ if (cliqueColRow && *cliqueColRow == i) ++overlap;
348
+ }
349
+
350
+ if (overlap == rowLength) {
351
+ rowIsSetPacking[i] = true;
352
+ ++numSetPackingRows;
353
+ if (numSetPackingRows == numRows) break;
354
+ }
355
+ }
356
+
357
+ if (numSetPackingRows == numRows) break;
358
+ }
359
+
360
+ if (numSetPackingRows == numRows) break;
361
+ }
362
+
363
+ // now for the rows that do not have a set packing structure check
364
+ // if we have such structure when all columns in the row are negated
365
+
366
+ for (HighsInt i = 0; i < numRows; ++i) {
367
+ if (!rowIsSetPacking[i]) rowIsSetPacking[i] = -1;
368
+ }
369
+
370
+ for (HighsInt j = 1; j < rowLength; ++j) {
371
+ HighsInt* colj1 = &entry(0, j);
372
+
373
+ for (HighsInt j0 = 0; j0 < j; ++j0) {
374
+ HighsInt* colj0 = &entry(0, j0);
375
+
376
+ for (HighsInt i = 0; i < numRows; ++i) {
377
+ if (rowIsSetPacking[i] != -1) continue;
378
+
379
+ HighsInt xj0 = colj0[i];
380
+ HighsInt xj1 = colj1[i];
381
+
382
+ // now look for cliques with value 0
383
+ auto commonClique = cliquetable.findCommonClique({xj0, 0}, {xj1, 0});
384
+
385
+ if (commonClique.first == nullptr) {
386
+ rowIsSetPacking[i] = false;
387
+ continue;
388
+ }
389
+
390
+ HighsInt overlap = 0;
391
+
392
+ for (HighsInt k = 0; k < commonClique.second; ++k) {
393
+ // skip clique variables with values of 1
394
+ if (commonClique.first[k].val == 1) continue;
395
+
396
+ HighsInt* cliqueColRow = columnToRow.find(commonClique.first[k].col);
397
+ if (cliqueColRow && *cliqueColRow == i) ++overlap;
398
+ }
399
+
400
+ if (overlap == rowLength) {
401
+ // mark with value 2, for negated set packing row with at most one
402
+ // zero
403
+ rowIsSetPacking[i] = 2;
404
+ ++numSetPackingRows;
405
+ if (numSetPackingRows == numRows) break;
406
+ }
407
+ }
408
+
409
+ if (numSetPackingRows == numRows) break;
410
+ }
411
+
412
+ if (numSetPackingRows == numRows) break;
413
+ }
414
+ }
415
+
416
+ HighsInt HighsOrbitopeMatrix::getBranchingColumn(
417
+ const std::vector<double>& colLower, const std::vector<double>& colUpper,
418
+ HighsInt col) const {
419
+ const HighsInt* i = columnToRow.find(col);
420
+ if (i && rowIsSetPacking[*i]) {
421
+ for (HighsInt j = 0; j < rowLength; ++j) {
422
+ HighsInt branchCol = entry(*i, j);
423
+ if (branchCol == col) break;
424
+ if (colLower[branchCol] != colUpper[branchCol]) return branchCol;
425
+ }
426
+ }
427
+
428
+ return col;
429
+ }
430
+
431
+ HighsInt HighsOrbitopeMatrix::orbitalFixingForPackingOrbitope(
432
+ const std::vector<HighsInt>& rows, HighsDomain& domain) const {
433
+ HighsInt numDynamicRows = rows.size();
434
+
435
+ // printf("propagate packing orbitope\n");
436
+
437
+ std::vector<HighsInt> firstOneInRow(numDynamicRows, -1);
438
+
439
+ for (HighsInt j = 0; j < rowLength; ++j) {
440
+ for (HighsInt i = 0; i < numDynamicRows; ++i) {
441
+ if (firstOneInRow[i] != -1) continue;
442
+ HighsInt r = rows[i];
443
+ HighsInt colrj = entry(r, j);
444
+ if (rowIsSetPacking[r] == 1) {
445
+ if (domain.col_lower_[colrj] > 0.5) firstOneInRow[i] = j;
446
+ } else {
447
+ assert(rowIsSetPacking[r] == 2);
448
+ if (domain.col_upper_[colrj] < 0.5) firstOneInRow[i] = j;
449
+ }
450
+ }
451
+ }
452
+
453
+ // we start looping over the rows and keep the index j at the column that
454
+ // is the right most possible location for a 1 entry.
455
+ // For the first row this position is 0.
456
+
457
+ HighsInt j = 0;
458
+ HighsInt numFixed = 0;
459
+ for (HighsInt i = 0; i < numDynamicRows; ++i) {
460
+ // at this position we know that the last possible position
461
+ // of a 1-entry in this row is j. If we have a 1 behind j
462
+ // the face of the orbitope intersecting the set of initial fixings is empty
463
+ if (firstOneInRow[i] > j) {
464
+ domain.markInfeasible();
465
+ // printf("packing orbitope propagation found infeasibility\n");
466
+ return numFixed;
467
+ }
468
+ HighsInt col_ij = entry(rows[i], j);
469
+
470
+ bool negate_i = rowIsSetPacking[rows[i]] == 2;
471
+
472
+ bool notZeroFixed = negate_i ? domain.col_lower_[col_ij] < 0.5
473
+ : domain.col_upper_[col_ij] > 0.5;
474
+
475
+ // as long as the entry is fixed to zero
476
+ // the frontier stays at the same column
477
+ // if we encounter an entry that is not fixed to zero
478
+ // we need to proceed with the next column and found a frontier step
479
+ if (notZeroFixed) {
480
+ // found a frontier step. Now we first check for the current column
481
+ // if it can be fixed to 1.
482
+ // For this we check if we find an infeasibility in the case where this
483
+ // column was fixed to zero in which case the frontier would have stayed
484
+ // at j for the following rows.
485
+ HighsInt j0 = j;
486
+ for (HighsInt k = i + 1; k < numDynamicRows; ++k) {
487
+ if (firstOneInRow[k] > j0) {
488
+ if (negate_i)
489
+ domain.changeBound(HighsBoundType::kUpper, col_ij, 0.0,
490
+ HighsDomain::Reason::unspecified());
491
+ else
492
+ domain.changeBound(HighsBoundType::kLower, col_ij, 1.0,
493
+ HighsDomain::Reason::unspecified());
494
+
495
+ ++numFixed;
496
+ if (domain.infeasible()) {
497
+ // printf("packing orbitope propagation found infeasibility\n");
498
+ return numFixed;
499
+ }
500
+ break;
501
+ }
502
+
503
+ bool negate_k = rowIsSetPacking[rows[k]] == 2;
504
+ bool notZeroFixed = negate_k
505
+ ? domain.col_lower_[entry(rows[k], j0)] < 0.5
506
+ : domain.col_upper_[entry(rows[k], j0)] > 0.5;
507
+
508
+ if (notZeroFixed) {
509
+ ++j0;
510
+ if (j0 == rowLength) break;
511
+ }
512
+ }
513
+
514
+ ++j;
515
+ if (j == rowLength) break;
516
+
517
+ for (HighsInt k = 0; k <= i; ++k) {
518
+ // we should have checked this row at the frontier position
519
+ assert(firstOneInRow[k] < j);
520
+
521
+ HighsInt col_kj = entry(rows[k], j);
522
+ bool negate_k = rowIsSetPacking[rows[k]] == 2;
523
+
524
+ if (negate_k) {
525
+ if (domain.col_lower_[col_kj] > 0.5) continue;
526
+
527
+ domain.changeBound(HighsBoundType::kLower, col_kj, 1.0,
528
+ HighsDomain::Reason::unspecified());
529
+ } else {
530
+ if (domain.col_upper_[col_kj] < 0.5) continue;
531
+
532
+ domain.changeBound(HighsBoundType::kUpper, col_kj, 0.0,
533
+ HighsDomain::Reason::unspecified());
534
+ }
535
+
536
+ ++numFixed;
537
+ if (domain.infeasible()) {
538
+ // this can happen due to deductions from earlier fixings
539
+ // otherwise it would have been caught by the infeasibility
540
+ // check within the next loop that goes over i
541
+ // printf("packing orbitope propagation found infeasibility\n");
542
+ return numFixed;
543
+ }
544
+ }
545
+ }
546
+ }
547
+
548
+ // check if there are more columns that can be completely fixed to zero
549
+ while (++j < rowLength) {
550
+ for (HighsInt k = 0; k < numDynamicRows; ++k) {
551
+ // we should have checked this row at the frontier position
552
+ assert(firstOneInRow[k] < j);
553
+
554
+ HighsInt col_kj = entry(rows[k], j);
555
+ bool negate_k = rowIsSetPacking[rows[k]] == 2;
556
+
557
+ if (negate_k) {
558
+ if (domain.col_lower_[col_kj] > 0.5) continue;
559
+
560
+ domain.changeBound(HighsBoundType::kLower, col_kj, 1.0,
561
+ HighsDomain::Reason::unspecified());
562
+ } else {
563
+ if (domain.col_upper_[col_kj] < 0.5) continue;
564
+
565
+ domain.changeBound(HighsBoundType::kUpper, col_kj, 0.0,
566
+ HighsDomain::Reason::unspecified());
567
+ }
568
+ // printf("new fixed\n");
569
+ ++numFixed;
570
+ if (domain.infeasible()) {
571
+ // this can happen due to deductions from earlier fixings
572
+ // otherwise it would have been caught by the infeasibility
573
+ // check within the next loop that goes over i
574
+ // printf("packing orbitope propagation found infeasibility\n");
575
+ return numFixed;
576
+ }
577
+ }
578
+ }
579
+
580
+ if (!domain.infeasible() && numFixed) domain.propagate();
581
+
582
+ // if (numFixed)
583
+ // printf("orbital fixing for packing case fixed %d columns\n", numFixed);
584
+
585
+ return numFixed;
586
+ }
587
+
588
+ HighsInt HighsOrbitopeMatrix::orbitalFixingForFullOrbitope(
589
+ const std::vector<HighsInt>& rows, HighsDomain& domain) const {
590
+ HighsInt numDynamicRows = rows.size();
591
+ std::vector<int8_t> Mminimal(numDynamicRows * rowLength, -1);
592
+
593
+ for (HighsInt j = 0; j < rowLength; ++j) {
594
+ for (HighsInt i = 0; i < numDynamicRows; ++i) {
595
+ HighsInt r = rows[i];
596
+ HighsInt colij = matrix[r + j * numRows];
597
+ if (domain.col_lower_[colij] == 1.0)
598
+ Mminimal[i + j * numDynamicRows] = 1;
599
+ else if (domain.col_upper_[colij] == 0.0)
600
+ Mminimal[i + j * numDynamicRows] = 0;
601
+ }
602
+ }
603
+
604
+ std::vector<int8_t> Mmaximal = Mminimal;
605
+
606
+ int8_t* MminimaljLast = Mminimal.data() + numDynamicRows * (rowLength - 1);
607
+ int8_t* MmaximaljFirst = Mmaximal.data();
608
+ for (HighsInt k = 0; k < numDynamicRows; ++k) {
609
+ if (MminimaljLast[k] == -1) MminimaljLast[k] = 0;
610
+ if (MmaximaljFirst[k] == -1) MmaximaljFirst[k] = 1;
611
+ }
612
+
613
+ auto i_fixed = [&](const int8_t* colj0, const int8_t* colj1) {
614
+ for (HighsInt i = 0; i < numDynamicRows; ++i) {
615
+ if (colj0[i] != -1 && colj1[i] != -1 && colj0[i] != colj1[i]) return i;
616
+ }
617
+
618
+ return numDynamicRows;
619
+ };
620
+
621
+ auto i_discr = [&](const int8_t* colj0, const int8_t* colj1, HighsInt i_f) {
622
+ for (HighsInt i = i_f; i >= 0; --i) {
623
+ if (colj0[i] != 0 && colj1[i] != 1) return i;
624
+ }
625
+
626
+ return HighsInt{-1};
627
+ };
628
+
629
+ for (HighsInt j = rowLength - 2; j >= 0; --j) {
630
+ int8_t* colj0 = Mminimal.data() + j * numDynamicRows;
631
+ int8_t* colj1 = colj0 + numDynamicRows;
632
+ HighsInt i_f = i_fixed(colj0, colj1);
633
+
634
+ if (i_f == numDynamicRows) {
635
+ for (HighsInt k = 0; k < numDynamicRows; ++k) {
636
+ int8_t isFree = (colj0[k] == -1);
637
+ colj0[k] += (isFree & colj1[k]) + isFree;
638
+ }
639
+ } else {
640
+ HighsInt i_d = i_discr(colj0, colj1, i_f);
641
+ if (i_d == -1) {
642
+ domain.markInfeasible();
643
+ return 0;
644
+ }
645
+
646
+ for (HighsInt k = 0; k < i_d; ++k) {
647
+ int8_t isFree = (colj0[k] == -1);
648
+ colj0[k] += (isFree & colj1[k]) + isFree;
649
+ }
650
+ colj0[i_d] = 1;
651
+ for (HighsInt k = i_d + 1; k < numDynamicRows; ++k)
652
+ colj0[k] += (colj0[k] == -1);
653
+ }
654
+ }
655
+
656
+ for (HighsInt j = 1; j < rowLength; ++j) {
657
+ int8_t* colj0 = Mmaximal.data() + j * numDynamicRows;
658
+ int8_t* colj1 = colj0 - numDynamicRows;
659
+ HighsInt i_f = i_fixed(colj1, colj0);
660
+
661
+ if (i_f == numDynamicRows) {
662
+ for (HighsInt k = 0; k < numDynamicRows; ++k) {
663
+ int8_t isFree = (colj0[k] == -1);
664
+ colj0[k] += (isFree & colj1[k]) + isFree;
665
+ }
666
+ } else {
667
+ HighsInt i_d = i_discr(colj1, colj0, i_f);
668
+ if (i_d == -1) {
669
+ domain.markInfeasible();
670
+ return 0;
671
+ }
672
+ for (HighsInt k = 0; k < i_d; ++k) {
673
+ int8_t isFree = (colj0[k] == -1);
674
+ colj0[k] += (isFree & colj1[k]) + isFree;
675
+ }
676
+ colj0[i_d] = 0;
677
+ for (HighsInt k = i_d + 1; k < numDynamicRows; ++k)
678
+ colj0[k] += 2 * (colj0[k] == -1);
679
+ }
680
+ }
681
+
682
+ HighsInt numFixed = 0;
683
+
684
+ for (HighsInt j = 0; j < rowLength; ++j) {
685
+ const int8_t* colMaximal = Mmaximal.data() + j * numDynamicRows;
686
+ const int8_t* colMinimal = Mminimal.data() + j * numDynamicRows;
687
+
688
+ for (HighsInt i = 0; i < numDynamicRows; ++i) {
689
+ if (colMinimal[i] != colMaximal[i]) {
690
+ assert(colMinimal[i] < colMaximal[i]);
691
+ break;
692
+ }
693
+
694
+ HighsInt r = rows[i];
695
+ HighsInt colrj = matrix[r + j * numRows];
696
+ if (domain.isFixed(colrj)) continue;
697
+
698
+ ++numFixed;
699
+ if (colMinimal[i] == 1)
700
+ domain.changeBound(HighsBoundType::kLower, colrj, 1.0,
701
+ HighsDomain::Reason::unspecified());
702
+ else
703
+ domain.changeBound(HighsBoundType::kUpper, colrj, 0.0,
704
+ HighsDomain::Reason::unspecified());
705
+ if (domain.infeasible()) break;
706
+ }
707
+ if (domain.infeasible()) break;
708
+ }
709
+
710
+ if (!domain.infeasible()) domain.propagate();
711
+
712
+ return numFixed;
713
+ }
714
+
715
+ HighsInt HighsOrbitopeMatrix::orbitalFixing(HighsDomain& domain) const {
716
+ std::vector<HighsInt> rows;
717
+ std::vector<uint8_t> rowUsed(numRows);
718
+
719
+ rows.reserve(numRows);
720
+
721
+ const auto& branchpos = domain.getBranchingPositions();
722
+ const auto& domchgstack = domain.getDomainChangeStack();
723
+
724
+ bool isPacking = true;
725
+ for (HighsInt pos : branchpos) {
726
+ const HighsInt* i = columnToRow.find(domchgstack[pos].column);
727
+ if (i && !rowUsed[*i]) {
728
+ rowUsed[*i] = true;
729
+ isPacking = isPacking && rowIsSetPacking[*i] != 0;
730
+ rows.push_back(*i);
731
+ }
732
+ }
733
+
734
+ if (rows.empty()) return 0;
735
+
736
+ if (isPacking) return orbitalFixingForPackingOrbitope(rows, domain);
737
+
738
+ return orbitalFixingForFullOrbitope(rows, domain);
739
+ }
740
+
741
+ void HighsSymmetryDetection::initializeGroundSet() {
742
+ vertexGroundSet = currentPartition;
743
+ pdqsort(vertexGroundSet.begin(), vertexGroundSet.end());
744
+ vertexPosition.resize(vertexToCell.size(), -1);
745
+ for (HighsInt i = 0; i < numVertices; ++i)
746
+ vertexPosition[vertexGroundSet[i]] = i;
747
+
748
+ orbitPartition.resize(numVertices);
749
+ std::iota(orbitPartition.begin(), orbitPartition.end(), 0);
750
+ orbitSize.assign(numVertices, 1);
751
+
752
+ automorphisms.resize(numVertices * 64);
753
+ numAutomorphisms = 0;
754
+ currNodeCertificate.reserve(numVertices);
755
+ }
756
+
757
+ bool HighsSymmetryDetection::mergeOrbits(HighsInt v1, HighsInt v2) {
758
+ if (v1 == v2) return false;
759
+
760
+ HighsInt orbit1 = getOrbit(v1);
761
+ HighsInt orbit2 = getOrbit(v2);
762
+
763
+ if (orbit1 == orbit2) return false;
764
+
765
+ if (orbit1 < orbit2) {
766
+ orbitPartition[orbit2] = orbit1;
767
+ orbitSize[orbit1] += orbitSize[orbit2];
768
+ } else {
769
+ orbitPartition[orbit1] = orbit2;
770
+ orbitSize[orbit2] += orbitSize[orbit1];
771
+ }
772
+
773
+ return true;
774
+ }
775
+
776
+ HighsInt HighsSymmetryDetection::getOrbit(HighsInt vertex) {
777
+ HighsInt i = vertexPosition[vertex];
778
+ HighsInt orbit = orbitPartition[i];
779
+ if (orbit != orbitPartition[orbit]) {
780
+ do {
781
+ linkCompressionStack.push_back(i);
782
+ i = orbit;
783
+ orbit = orbitPartition[orbit];
784
+ } while (orbit != orbitPartition[orbit]);
785
+
786
+ do {
787
+ i = linkCompressionStack.back();
788
+ linkCompressionStack.pop_back();
789
+ orbitPartition[i] = orbit;
790
+ } while (!linkCompressionStack.empty());
791
+ }
792
+
793
+ return orbit;
794
+ }
795
+
796
+ void HighsSymmetryDetection::initializeHashValues() {
797
+ for (HighsInt i = 0; i != numVertices; ++i) {
798
+ HighsInt cell = vertexToCell[i];
799
+ for (HighsInt j = Gstart[i]; j != Gend[i]; ++j) {
800
+ HighsHashHelpers::sparse_combine32(vertexHash[Gedge[j].first], cell,
801
+ Gedge[j].second);
802
+ }
803
+ markCellForRefinement(cell);
804
+ }
805
+ }
806
+
807
+ bool HighsSymmetryDetection::updateCellMembership(HighsInt i, HighsInt cell,
808
+ bool markForRefinement) {
809
+ HighsInt vertex = currentPartition[i];
810
+ if (vertexToCell[vertex] != cell) {
811
+ // set new cell id
812
+ vertexToCell[vertex] = cell;
813
+ if (i != cell) currentPartitionLinks[i] = cell;
814
+
815
+ // update hashes of affected rows
816
+ if (markForRefinement) {
817
+ for (HighsInt j = Gstart[vertex]; j != Gend[vertex]; ++j) {
818
+ HighsInt edgeDestinationCell = vertexToCell[Gedge[j].first];
819
+ if (cellSize(edgeDestinationCell) == 1) continue;
820
+ HighsHashHelpers::sparse_combine32(vertexHash[Gedge[j].first], cell,
821
+ Gedge[j].second);
822
+ markCellForRefinement(edgeDestinationCell);
823
+ }
824
+ }
825
+
826
+ return true;
827
+ }
828
+
829
+ return false;
830
+ }
831
+
832
+ bool HighsSymmetryDetection::splitCell(HighsInt cell, HighsInt splitPoint) {
833
+ u32 hSplit = getVertexHash(currentPartition[splitPoint]);
834
+ u32 hCell = getVertexHash(currentPartition[cell]);
835
+
836
+ u32 certificateVal =
837
+ (HighsHashHelpers::pair_hash<0>(hSplit, hCell) +
838
+ HighsHashHelpers::pair_hash<1>(
839
+ cell, currentPartitionLinks[cell] - splitPoint) +
840
+ HighsHashHelpers::pair_hash<2>(splitPoint, splitPoint - cell)) >>
841
+ 32;
842
+
843
+ // employ prefix pruning scheme as in bliss
844
+ if (!firstLeaveCertificate.empty()) {
845
+ firstLeavePrefixLen +=
846
+ (firstLeavePrefixLen == (HighsInt)currNodeCertificate.size()) *
847
+ (certificateVal == firstLeaveCertificate[currNodeCertificate.size()]);
848
+ bestLeavePrefixLen +=
849
+ (bestLeavePrefixLen == (HighsInt)currNodeCertificate.size()) *
850
+ (certificateVal == bestLeaveCertificate[currNodeCertificate.size()]);
851
+
852
+ // if the node certificate is not a prefix of the first leave's certificate
853
+ // and it comes lexicographically after the certificate value of the
854
+ // lexicographically smallest leave certificate we prune the node
855
+ if (firstLeavePrefixLen <= (HighsInt)currNodeCertificate.size() &&
856
+ bestLeavePrefixLen <= (HighsInt)currNodeCertificate.size()) {
857
+ u32 diffVal = bestLeavePrefixLen == (HighsInt)currNodeCertificate.size()
858
+ ? certificateVal
859
+ : currNodeCertificate[bestLeavePrefixLen];
860
+ if (diffVal > bestLeaveCertificate[bestLeavePrefixLen]) return false;
861
+ }
862
+ }
863
+
864
+ currentPartitionLinks[splitPoint] = currentPartitionLinks[cell];
865
+ currentPartitionLinks[cell] = splitPoint;
866
+ cellCreationStack.push_back(splitPoint);
867
+ currNodeCertificate.push_back(certificateVal);
868
+
869
+ return true;
870
+ }
871
+
872
+ void HighsSymmetryDetection::markCellForRefinement(HighsInt cell) {
873
+ if (cellSize(cell) == 1 || cellInRefinementQueue[cell]) return;
874
+
875
+ cellInRefinementQueue[cell] = true;
876
+ refinementQueue.push_back(cell);
877
+ std::push_heap(refinementQueue.begin(), refinementQueue.end(),
878
+ std::greater<HighsInt>());
879
+ }
880
+
881
+ HighsSymmetryDetection::u32 HighsSymmetryDetection::getVertexHash(HighsInt v) {
882
+ const u32* h = vertexHash.find(v);
883
+ if (h) return *h;
884
+ return 0;
885
+ }
886
+
887
+ bool HighsSymmetryDetection::partitionRefinement() {
888
+ while (!refinementQueue.empty()) {
889
+ std::pop_heap(refinementQueue.begin(), refinementQueue.end(),
890
+ std::greater<HighsInt>());
891
+
892
+ HighsInt cellStart = refinementQueue.back();
893
+ HighsInt firstCellStart = cellStart;
894
+ refinementQueue.pop_back();
895
+ cellInRefinementQueue[cellStart] = false;
896
+
897
+ if (cellSize(cellStart) == 1) continue;
898
+ HighsInt cellEnd = currentPartitionLinks[cellStart];
899
+ assert(cellEnd >= cellStart);
900
+
901
+ // first check which vertices do have updated hash values and put them to
902
+ // the end of the partition
903
+ HighsInt refineStart =
904
+ std::partition(
905
+ currentPartition.begin() + cellStart,
906
+ currentPartition.begin() + cellEnd,
907
+ [&](HighsInt v) { return vertexHash.find(v) == nullptr; }) -
908
+ currentPartition.begin();
909
+
910
+ // if there are none there is nothing to refine
911
+ if (refineStart == cellEnd) continue;
912
+
913
+ // sort the vertices that have updated hash values by their hash values
914
+ pdqsort(currentPartition.begin() + refineStart,
915
+ currentPartition.begin() + cellEnd, [&](HighsInt v1, HighsInt v2) {
916
+ return vertexHash[v1] < vertexHash[v2];
917
+ });
918
+
919
+ // if not all vertices have updated hash values directly create the first
920
+ // new cell at the start of the range that we want to refine
921
+ if (refineStart != cellStart) {
922
+ assert(refineStart != cellStart);
923
+ assert(refineStart != cellEnd);
924
+ if (!splitCell(cellStart, refineStart)) {
925
+ // node can be pruned, make sure hash values are cleared and queue is
926
+ // empty
927
+ for (HighsInt c : refinementQueue) cellInRefinementQueue[c] = false;
928
+ refinementQueue.clear();
929
+ vertexHash.clear();
930
+ return false;
931
+ }
932
+ cellStart = refineStart;
933
+ updateCellMembership(cellStart, cellStart);
934
+ }
935
+
936
+ // now update the remaining vertices
937
+ bool prune = false;
938
+ HighsInt i;
939
+ assert(vertexHash.find(currentPartition[cellStart]) != nullptr);
940
+ // store value of first hash
941
+ u64 lastHash = vertexHash[currentPartition[cellStart]];
942
+ for (i = cellStart + 1; i < cellEnd; ++i) {
943
+ HighsInt vertex = currentPartition[i];
944
+ // get this vertex hash value
945
+ u64 hash = vertexHash[vertex];
946
+
947
+ if (hash != lastHash) {
948
+ // hash values do not match -> start of new cell
949
+ if (!splitCell(cellStart, i)) {
950
+ // refinement process yielded bad prefix of certificate
951
+ // -> node can be pruned
952
+ prune = true;
953
+ break;
954
+ }
955
+ cellStart = i;
956
+ // remember hash value of this new cell under lastHash
957
+ lastHash = hash;
958
+ }
959
+
960
+ // update membership of vertex to new cell
961
+ updateCellMembership(i, cellStart);
962
+ }
963
+
964
+ if (prune) {
965
+ // node can be pruned, make sure hash values are cleared and queue is
966
+ // empty
967
+ for (HighsInt c : refinementQueue) cellInRefinementQueue[c] = false;
968
+ refinementQueue.clear();
969
+ vertexHash.clear();
970
+ currentPartitionLinks[firstCellStart] = cellEnd;
971
+
972
+ // undo possibly incomplete changes done to the cells
973
+ for (--i; i >= refineStart; --i)
974
+ updateCellMembership(i, firstCellStart, false);
975
+
976
+ return false;
977
+ }
978
+
979
+ assert(currentPartitionLinks[cellStart] == cellEnd);
980
+ }
981
+
982
+ vertexHash.clear();
983
+
984
+ return true;
985
+ }
986
+
987
+ HighsInt HighsSymmetryDetection::selectTargetCell() const {
988
+ HighsInt i = 0;
989
+ if (nodeStack.size() > 1) i = nodeStack[nodeStack.size() - 2].targetCell;
990
+
991
+ while (i < numVertices) {
992
+ if (cellSize(i) > 1) return i;
993
+
994
+ ++i;
995
+ }
996
+
997
+ return -1;
998
+ }
999
+
1000
+ bool HighsSymmetryDetection::checkStoredAutomorphism(HighsInt vertex) const {
1001
+ HighsInt numCheck = std::min(numAutomorphisms, (HighsInt)64);
1002
+
1003
+ for (HighsInt i = 0; i < numCheck; ++i) {
1004
+ const HighsInt* automorphism = automorphisms.data() + i * numVertices;
1005
+ bool automorphismUseful = true;
1006
+ for (HighsInt j = nodeStack.size() - 2; j >= firstPathDepth; --j) {
1007
+ HighsInt fixPos = vertexPosition[nodeStack[j].lastDistiguished];
1008
+
1009
+ if (automorphism[fixPos] != vertexGroundSet[fixPos]) {
1010
+ automorphismUseful = false;
1011
+ break;
1012
+ }
1013
+ }
1014
+
1015
+ if (!automorphismUseful) continue;
1016
+
1017
+ if (automorphism[vertexPosition[vertex]] < vertex) return false;
1018
+ }
1019
+
1020
+ return true;
1021
+ }
1022
+
1023
+ bool HighsSymmetryDetection::determineNextToDistinguish() {
1024
+ Node& currNode = nodeStack.back();
1025
+ distinguishCands.clear();
1026
+ std::vector<HighsInt>::iterator cellStart;
1027
+ std::vector<HighsInt>::iterator cellEnd;
1028
+ cellStart = currentPartition.begin() + currNode.targetCell;
1029
+ cellEnd =
1030
+ currentPartition.begin() + currentPartitionLinks[currNode.targetCell];
1031
+
1032
+ if (currNode.lastDistiguished == -1) {
1033
+ auto nextDistinguishPos = std::min_element(cellStart, cellEnd);
1034
+ distinguishCands.push_back(&*nextDistinguishPos);
1035
+ } else if ((HighsInt)nodeStack.size() > firstPathDepth) {
1036
+ for (auto i = cellStart; i != cellEnd; ++i) {
1037
+ if (*i > currNode.lastDistiguished && checkStoredAutomorphism(*i))
1038
+ distinguishCands.push_back(&*i);
1039
+ }
1040
+ if (distinguishCands.empty()) return false;
1041
+ auto nextDistinguishPos =
1042
+ std::min_element(distinguishCands.begin(), distinguishCands.end(),
1043
+ [](HighsInt* a, HighsInt* b) { return *a < *b; });
1044
+ std::swap(*distinguishCands.begin(), *nextDistinguishPos);
1045
+ distinguishCands.resize(1);
1046
+ } else {
1047
+ for (auto i = cellStart; i != cellEnd; ++i) {
1048
+ if (*i > currNode.lastDistiguished && vertexGroundSet[getOrbit(*i)] == *i)
1049
+ distinguishCands.push_back(&*i);
1050
+ }
1051
+ if (distinguishCands.empty()) return false;
1052
+ auto nextDistinguishPos =
1053
+ std::min_element(distinguishCands.begin(), distinguishCands.end(),
1054
+ [](HighsInt* a, HighsInt* b) { return *a < *b; });
1055
+ std::swap(*distinguishCands.begin(), *nextDistinguishPos);
1056
+ distinguishCands.resize(1);
1057
+ }
1058
+
1059
+ return true;
1060
+ }
1061
+
1062
+ bool HighsSymmetryDetection::distinguishVertex(HighsInt targetCell) {
1063
+ assert(distinguishCands.size() == 1u);
1064
+ HighsInt targetCellEnd = currentPartitionLinks[targetCell];
1065
+ HighsInt newCell = targetCellEnd - 1;
1066
+ std::swap(*distinguishCands[0], currentPartition[newCell]);
1067
+ nodeStack.back().lastDistiguished = currentPartition[newCell];
1068
+
1069
+ if (!splitCell(targetCell, newCell)) return false;
1070
+
1071
+ updateCellMembership(newCell, newCell);
1072
+
1073
+ return true;
1074
+ }
1075
+
1076
+ void HighsSymmetryDetection::backtrack(HighsInt backtrackStackNewEnd,
1077
+ HighsInt backtrackStackEnd) {
1078
+ // we assume that we always backtrack from a leaf node, i.e. a discrete
1079
+ // partition therefore we do not need to remember the values of the hash
1080
+ // contributions as it is the indentity for each position and all new cells
1081
+ // are on the cell creation stack.
1082
+ for (HighsInt stackPos = backtrackStackEnd - 1;
1083
+ stackPos >= backtrackStackNewEnd; --stackPos) {
1084
+ HighsInt cell = cellCreationStack[stackPos];
1085
+ // look up the cell start of the preceding cell with link compression
1086
+ HighsInt newStart = getCellStart(cell - 1);
1087
+ // remember the current end
1088
+ HighsInt currEnd = currentPartitionLinks[cell];
1089
+ // change the link to point to the start of the preceding cell
1090
+ currentPartitionLinks[cell] = newStart;
1091
+ // change the link of the start pointer of the preceding cell to point to
1092
+ // the end of this cell
1093
+ currentPartitionLinks[newStart] = currEnd;
1094
+ }
1095
+ }
1096
+
1097
+ void HighsSymmetryDetection::cleanupBacktrack(HighsInt cellCreationStackPos) {
1098
+ // the links have been updated. Even though they might still not be fully
1099
+ // compressed the cell starts will all point to the correct cell end and the
1100
+ // lookup with path compression will give the correct start
1101
+ for (HighsInt stackPos = cellCreationStack.size() - 1;
1102
+ stackPos >= cellCreationStackPos; --stackPos) {
1103
+ HighsInt cell = cellCreationStack[stackPos];
1104
+
1105
+ HighsInt cellStart = getCellStart(cell);
1106
+ HighsInt cellEnd = currentPartitionLinks[cellStart];
1107
+
1108
+ for (HighsInt v = cell;
1109
+ v < cellEnd && vertexToCell[currentPartition[v]] == cell; ++v)
1110
+ updateCellMembership(v, cellStart, false);
1111
+ }
1112
+
1113
+ cellCreationStack.resize(cellCreationStackPos);
1114
+ }
1115
+
1116
+ HighsInt HighsSymmetryDetection::getCellStart(HighsInt pos) {
1117
+ HighsInt startPos = currentPartitionLinks[pos];
1118
+ if (startPos > pos) return pos;
1119
+ if (currentPartitionLinks[startPos] < startPos) {
1120
+ do {
1121
+ linkCompressionStack.push_back(pos);
1122
+ pos = startPos;
1123
+ startPos = currentPartitionLinks[startPos];
1124
+ } while (currentPartitionLinks[startPos] < startPos);
1125
+
1126
+ do {
1127
+ currentPartitionLinks[linkCompressionStack.back()] = startPos;
1128
+ linkCompressionStack.pop_back();
1129
+ } while (!linkCompressionStack.empty());
1130
+ }
1131
+
1132
+ return startPos;
1133
+ }
1134
+
1135
+ void HighsSymmetryDetection::createNode() {
1136
+ nodeStack.emplace_back();
1137
+ nodeStack.back().stackStart = cellCreationStack.size();
1138
+ nodeStack.back().certificateEnd = currNodeCertificate.size();
1139
+ nodeStack.back().targetCell = -1;
1140
+ nodeStack.back().lastDistiguished = -1;
1141
+ }
1142
+
1143
+ struct MatrixColumn {
1144
+ uint32_t cost;
1145
+ uint32_t lb;
1146
+ uint32_t ub;
1147
+ uint32_t integral;
1148
+ uint32_t len;
1149
+
1150
+ bool operator==(const MatrixColumn& other) const {
1151
+ return std::memcmp(this, &other, sizeof(MatrixColumn)) == 0;
1152
+ }
1153
+ };
1154
+
1155
+ struct MatrixRow {
1156
+ uint32_t lb;
1157
+ uint32_t ub;
1158
+ uint32_t len;
1159
+
1160
+ bool operator==(const MatrixRow& other) const {
1161
+ return std::memcmp(this, &other, sizeof(MatrixRow)) == 0;
1162
+ }
1163
+ };
1164
+
1165
+ void HighsSymmetryDetection::loadModelAsGraph(const HighsLp& model,
1166
+ double epsilon) {
1167
+ this->model = &model;
1168
+ numCol = model.num_col_;
1169
+ numRow = model.num_row_;
1170
+ numVertices = numRow + numCol;
1171
+
1172
+ cellInRefinementQueue.resize(numVertices);
1173
+ vertexToCell.resize(numVertices);
1174
+ refinementQueue.reserve(numVertices);
1175
+ currNodeCertificate.reserve(numVertices);
1176
+
1177
+ HighsHashTable<MatrixColumn, HighsInt> columnSet;
1178
+ HighsHashTable<MatrixRow, HighsInt> rowSet;
1179
+ HighsMatrixColoring coloring(epsilon);
1180
+ edgeBuffer.resize(numVertices);
1181
+ // set up row and column based incidence matrix
1182
+ HighsInt numNz = model.a_matrix_.index_.size();
1183
+ Gedge.resize(2 * numNz);
1184
+ std::transform(model.a_matrix_.index_.begin(), model.a_matrix_.index_.end(),
1185
+ Gedge.begin(), [&](HighsInt rowIndex) {
1186
+ return std::make_pair(rowIndex + numCol, HighsUInt{0});
1187
+ });
1188
+
1189
+ Gstart.resize(numVertices + 1);
1190
+ std::copy(model.a_matrix_.start_.begin(), model.a_matrix_.start_.end(),
1191
+ Gstart.begin());
1192
+
1193
+ // set up the column colors and count row sizes
1194
+ std::vector<HighsInt> rowSizes(numRow);
1195
+ for (HighsInt i = 0; i < numCol; ++i) {
1196
+ for (HighsInt j = Gstart[i]; j < Gstart[i + 1]; ++j) {
1197
+ Gedge[j].second = coloring.color(model.a_matrix_.value_[j]);
1198
+ rowSizes[model.a_matrix_.index_[j]] += 1;
1199
+ }
1200
+ }
1201
+
1202
+ // next set up the row starts using the computed row sizes
1203
+ HighsInt offset = numNz;
1204
+ for (HighsInt i = 0; i < numRow; ++i) {
1205
+ Gstart[numCol + i] = offset;
1206
+ offset += rowSizes[i];
1207
+ }
1208
+ Gstart[numCol + numRow] = offset;
1209
+
1210
+ Gend.assign(Gstart.begin() + 1, Gstart.end());
1211
+
1212
+ // finally add the nonzeros to the row major matrix
1213
+ for (HighsInt i = 0; i < numCol; ++i) {
1214
+ for (HighsInt j = Gstart[i]; j < Gstart[i + 1]; ++j) {
1215
+ HighsInt row = model.a_matrix_.index_[j];
1216
+ HighsInt ARpos = Gstart[numCol + row + 1] - rowSizes[row];
1217
+ rowSizes[row] -= 1;
1218
+ Gedge[ARpos].first = i;
1219
+ Gedge[ARpos].second = Gedge[j].second;
1220
+ }
1221
+ }
1222
+
1223
+ // loop over the columns and assign them a number that is distinct based on
1224
+ // their upper/lower bounds, cost, and integrality status. Use the columnSet
1225
+ // hash table to look up whether a column with similar properties exists and
1226
+ // use the previous number in that case. The number is stored in the
1227
+ // colToCell array which is subsequently used to sort an initial column
1228
+ // permutation.
1229
+ HighsInt indexOffset = numCol + 1;
1230
+ for (HighsInt i = 0; i < numCol; ++i) {
1231
+ MatrixColumn matrixCol;
1232
+
1233
+ matrixCol.cost = coloring.color(model.col_cost_[i]);
1234
+ matrixCol.lb = coloring.color(model.col_lower_[i]);
1235
+ matrixCol.ub = coloring.color(model.col_upper_[i]);
1236
+ matrixCol.integral = (u32)model.integrality_[i];
1237
+ matrixCol.len = Gstart[i + 1] - Gstart[i];
1238
+
1239
+ HighsInt* columnCell = &columnSet[matrixCol];
1240
+
1241
+ if (*columnCell == 0) {
1242
+ *columnCell = columnSet.size();
1243
+ if (model.col_lower_[i] != 0.0 || model.col_upper_[i] != 1.0 ||
1244
+ model.integrality_[i] == HighsVarType::kContinuous)
1245
+ *columnCell += indexOffset;
1246
+ }
1247
+
1248
+ vertexToCell[i] = *columnCell;
1249
+ }
1250
+
1251
+ indexOffset = 2 * numCol + 1;
1252
+ for (HighsInt i = 0; i < numRow; ++i) {
1253
+ MatrixRow matrixRow;
1254
+
1255
+ matrixRow.lb = coloring.color(model.row_lower_[i]);
1256
+ matrixRow.ub = coloring.color(model.row_upper_[i]);
1257
+ matrixRow.len = Gstart[numCol + i + 1] - Gstart[numCol + i];
1258
+
1259
+ HighsInt* rowCell = &rowSet[matrixRow];
1260
+
1261
+ if (*rowCell == 0) *rowCell = rowSet.size();
1262
+
1263
+ vertexToCell[numCol + i] = indexOffset + *rowCell;
1264
+ }
1265
+
1266
+ // set up the initial partition array, sort by the colToCell value
1267
+ // assigned above
1268
+ currentPartition.resize(numVertices);
1269
+ std::iota(currentPartition.begin(), currentPartition.end(), 0);
1270
+ pdqsort(currentPartition.begin(), currentPartition.end(),
1271
+ [&](HighsInt v1, HighsInt v2) {
1272
+ return vertexToCell[v1] < vertexToCell[v2];
1273
+ });
1274
+
1275
+ // now set up partition links and correct the colToCell array to the
1276
+ // correct cell index
1277
+ currentPartitionLinks.resize(numVertices);
1278
+ HighsInt cellStart = 0;
1279
+ HighsInt cellNumber = 0;
1280
+ for (HighsInt i = 0; i < numVertices; ++i) {
1281
+ HighsInt vertex = currentPartition[i];
1282
+ // if the cell number is different to the current cell number this is the
1283
+ // start of a new cell
1284
+ if (cellNumber != vertexToCell[vertex]) {
1285
+ // remember the number of this cell to identify its end
1286
+ cellNumber = vertexToCell[vertex];
1287
+ // set the link of the cell start to point to its end
1288
+ currentPartitionLinks[cellStart] = i;
1289
+ // remember start of this cell
1290
+ cellStart = i;
1291
+ }
1292
+
1293
+ // correct the colToCell array to not store the start index of the
1294
+ // cell, not its number
1295
+ vertexToCell[vertex] = cellStart;
1296
+ // set the link of the column to the cellStart
1297
+ currentPartitionLinks[i] = cellStart;
1298
+ }
1299
+
1300
+ // set the column partition link of the last started cell to point past the
1301
+ // end
1302
+ currentPartitionLinks[cellStart] = numVertices;
1303
+ }
1304
+
1305
+ HighsHashTable<std::tuple<HighsInt, HighsInt, HighsUInt>>
1306
+ HighsSymmetryDetection::dumpCurrentGraph() {
1307
+ HighsHashTable<std::tuple<HighsInt, HighsInt, HighsUInt>> graphTriplets;
1308
+
1309
+ for (HighsInt i = 0; i < numCol; ++i) {
1310
+ HighsInt colCell = vertexToCell[i];
1311
+ for (HighsInt j = Gstart[i]; j != Gend[i]; ++j)
1312
+ graphTriplets.insert(vertexToCell[Gedge[j].first], colCell,
1313
+ Gedge[j].second);
1314
+ for (HighsInt j = Gend[i]; j != Gstart[i + 1]; ++j)
1315
+ graphTriplets.insert(Gedge[j].first, colCell, Gedge[j].second);
1316
+ }
1317
+
1318
+ return graphTriplets;
1319
+ }
1320
+
1321
+ void HighsSymmetryDetection::switchToNextNode(HighsInt backtrackDepth) {
1322
+ HighsInt stackEnd = cellCreationStack.size();
1323
+ // we need to backtrack the datastructures
1324
+ nodeStack.resize(backtrackDepth);
1325
+ if (backtrackDepth == 0) return;
1326
+ do {
1327
+ Node& currNode = nodeStack.back();
1328
+ backtrack(currNode.stackStart, stackEnd);
1329
+ stackEnd = currNode.stackStart;
1330
+ firstPathDepth = std::min((HighsInt)nodeStack.size(), firstPathDepth);
1331
+ bestPathDepth = std::min((HighsInt)nodeStack.size(), bestPathDepth);
1332
+ firstLeavePrefixLen =
1333
+ std::min(currNode.certificateEnd, firstLeavePrefixLen);
1334
+ bestLeavePrefixLen = std::min(currNode.certificateEnd, bestLeavePrefixLen);
1335
+ currNodeCertificate.resize(currNode.certificateEnd);
1336
+ if (!determineNextToDistinguish()) {
1337
+ nodeStack.pop_back();
1338
+ continue;
1339
+ }
1340
+
1341
+ // call cleanup backtrack with the final stackEnd
1342
+ // so that all hashes are up to date and the link arrays do not contain
1343
+ // chains anymore
1344
+ cleanupBacktrack(stackEnd);
1345
+ HighsInt targetCell = currNode.targetCell;
1346
+
1347
+ if (!distinguishVertex(targetCell)) {
1348
+ // if distinguishing the next vertex fails, it means that its certificate
1349
+ // value is lexicographically larger than that of the best leave
1350
+ nodeStack.pop_back();
1351
+ continue;
1352
+ }
1353
+
1354
+ if (!partitionRefinement()) {
1355
+ stackEnd = cellCreationStack.size();
1356
+ continue;
1357
+ }
1358
+
1359
+ createNode();
1360
+ break;
1361
+ } while (!nodeStack.empty());
1362
+ }
1363
+
1364
+ bool HighsSymmetryDetection::compareCurrentGraph(
1365
+ const HighsHashTable<std::tuple<HighsInt, HighsInt, HighsUInt>>& otherGraph,
1366
+ HighsInt& wrongCell) const {
1367
+ for (HighsInt i = 0; i < numCol; ++i) {
1368
+ HighsInt colCell = vertexToCell[i];
1369
+
1370
+ for (HighsInt j = Gstart[i]; j != Gend[i]; ++j)
1371
+ if (!otherGraph.find(std::make_tuple(vertexToCell[Gedge[j].first],
1372
+ colCell, Gedge[j].second))) {
1373
+ // return which cell does not match in its neighbourhood as this should
1374
+ // have been detected with the hashing it can very rarely happen due to
1375
+ // a hash collision. In such a case we want to backtrack to the last
1376
+ // time where we targeted this particular cell. Otherwise we could spent
1377
+ // a long time searching for a matching leave value until every
1378
+ // combination is exhausted and for each leave in this subtree the graph
1379
+ // comparison will fail on this edge.
1380
+ wrongCell = colCell;
1381
+ return false;
1382
+ }
1383
+ for (HighsInt j = Gend[i]; j != Gstart[i + 1]; ++j)
1384
+ if (!otherGraph.find(
1385
+ std::make_tuple(Gedge[j].first, colCell, Gedge[j].second))) {
1386
+ wrongCell = colCell;
1387
+ return false;
1388
+ }
1389
+ }
1390
+
1391
+ return true;
1392
+ }
1393
+
1394
+ bool HighsSymmetryDetection::isFromBinaryColumn(HighsInt pos) const {
1395
+ if (pos >= numActiveCols) return false;
1396
+
1397
+ HighsInt col = currentPartition[pos];
1398
+
1399
+ if (model->col_lower_[col] != 0.0 || model->col_upper_[col] != 1.0 ||
1400
+ model->integrality_[col] == HighsVarType::kContinuous)
1401
+ return false;
1402
+
1403
+ return true;
1404
+ }
1405
+
1406
+ HighsSymmetryDetection::ComponentData
1407
+ HighsSymmetryDetection::computeComponentData(
1408
+ const HighsSymmetries& symmetries) {
1409
+ ComponentData componentData;
1410
+
1411
+ componentData.components.reset(numActiveCols);
1412
+ componentData.firstUnfixed.assign(symmetries.numPerms, -1);
1413
+ componentData.numUnfixed.assign(symmetries.numPerms, 0);
1414
+ for (HighsInt i = 0; i < symmetries.numPerms; ++i) {
1415
+ const HighsInt* perm = symmetries.permutations.data() + i * numActiveCols;
1416
+
1417
+ for (HighsInt j = 0; j < numActiveCols; ++j) {
1418
+ if (perm[j] != vertexGroundSet[j]) {
1419
+ HighsInt pos = vertexPosition[perm[j]];
1420
+ componentData.numUnfixed[i] += 1;
1421
+ if (componentData.firstUnfixed[i] != -1)
1422
+ componentData.components.merge(componentData.firstUnfixed[i], pos);
1423
+ else
1424
+ componentData.firstUnfixed[i] = pos;
1425
+ }
1426
+ }
1427
+ }
1428
+
1429
+ componentData.componentSets.assign(vertexGroundSet.begin(),
1430
+ vertexGroundSet.begin() + numActiveCols);
1431
+ pdqsort(componentData.componentSets.begin(),
1432
+ componentData.componentSets.end(), [&](HighsInt u, HighsInt v) {
1433
+ HighsInt uComp = componentData.components.getSet(vertexPosition[u]);
1434
+ HighsInt vComp = componentData.components.getSet(vertexPosition[v]);
1435
+ return std::make_pair(
1436
+ componentData.components.getSetSize(uComp) == 1, uComp) <
1437
+ std::make_pair(
1438
+ componentData.components.getSetSize(vComp) == 1, vComp);
1439
+ });
1440
+
1441
+ HighsInt currentComponentStart = -1;
1442
+ HighsInt currentComponent = -1;
1443
+ HighsHashTable<HighsInt> currComponentOrbits;
1444
+ for (HighsInt i = 0; i < numActiveCols; ++i) {
1445
+ HighsInt comp = componentData.components.getSet(
1446
+ vertexPosition[componentData.componentSets[i]]);
1447
+ if (componentData.components.getSetSize(comp) == 1) break;
1448
+ if (comp != currentComponent) {
1449
+ currentComponent = comp;
1450
+ currentComponentStart = i;
1451
+ componentData.componentStarts.push_back(currentComponentStart);
1452
+ componentData.componentNumber.push_back(currentComponent);
1453
+ componentData.componentNumOrbits.emplace_back();
1454
+ currComponentOrbits.clear();
1455
+ }
1456
+
1457
+ if (currComponentOrbits.insert(getOrbit(componentData.componentSets[i]))) {
1458
+ ++componentData.componentNumOrbits.back();
1459
+ }
1460
+ }
1461
+
1462
+ componentData.permComponents.reserve(symmetries.numPerms);
1463
+
1464
+ for (HighsInt i = 0; i < symmetries.numPerms; ++i) {
1465
+ if (componentData.firstUnfixed[i] == -1) continue;
1466
+ componentData.permComponents.push_back(i);
1467
+ }
1468
+
1469
+ pdqsort(componentData.permComponents.begin(),
1470
+ componentData.permComponents.end(), [&](HighsInt i, HighsInt j) {
1471
+ HighsInt seti =
1472
+ componentData.components.getSet(componentData.firstUnfixed[i]);
1473
+ HighsInt setj =
1474
+ componentData.components.getSet(componentData.firstUnfixed[j]);
1475
+ return std::make_pair(seti, componentData.numUnfixed[i]) <
1476
+ std::make_pair(setj, componentData.numUnfixed[j]);
1477
+ });
1478
+
1479
+ currentComponentStart = -1;
1480
+ currentComponent = -1;
1481
+
1482
+ HighsInt numUsedPerms = componentData.permComponents.size();
1483
+
1484
+ for (HighsInt i = 0; i < numUsedPerms; ++i) {
1485
+ HighsInt p = componentData.permComponents[i];
1486
+ HighsInt comp =
1487
+ componentData.components.getSet(componentData.firstUnfixed[p]);
1488
+ if (comp != currentComponent) {
1489
+ currentComponent = comp;
1490
+ currentComponentStart = i;
1491
+ componentData.permComponentStarts.push_back(currentComponentStart);
1492
+ }
1493
+ }
1494
+
1495
+ assert(componentData.permComponentStarts.size() ==
1496
+ componentData.componentStarts.size());
1497
+ componentData.permComponentStarts.push_back(numUsedPerms);
1498
+
1499
+ // HighsInt numComponents = componentData.componentStarts.size();
1500
+ // printf("found %d components\n", numComponents);
1501
+ componentData.componentStarts.push_back(numActiveCols);
1502
+
1503
+ return componentData;
1504
+ }
1505
+
1506
+ bool HighsSymmetryDetection::isFullOrbitope(const ComponentData& componentData,
1507
+ HighsInt component,
1508
+ HighsSymmetries& symmetries) {
1509
+ HighsInt componentSize = componentData.componentStarts[component + 1] -
1510
+ componentData.componentStarts[component];
1511
+ if (componentSize == 1) return false;
1512
+
1513
+ // check that component acts only on binary variables
1514
+ for (HighsInt i = componentData.componentStarts[component];
1515
+ i < componentData.componentStarts[component + 1]; ++i) {
1516
+ HighsInt col = componentData.componentSets[i];
1517
+ if (model->integrality_[col] == HighsVarType::kContinuous ||
1518
+ model->col_lower_[col] != 0.0 || model->col_upper_[col] != 1.0)
1519
+ return false;
1520
+ }
1521
+
1522
+ // check that the number of unfixed variables in the first permutation is even
1523
+ HighsInt p0 =
1524
+ componentData
1525
+ .permComponents[componentData.permComponentStarts[component]];
1526
+ if (componentData.numUnfixed[p0] & 1) return false;
1527
+
1528
+ // check that the other permutations in the component have the same number of
1529
+ // unfixed variables as the first one
1530
+ for (HighsInt k = componentData.permComponentStarts[component] + 1;
1531
+ k < componentData.permComponentStarts[component + 1]; ++k) {
1532
+ HighsInt p = componentData.permComponents[k];
1533
+ if (componentData.numUnfixed[p] != componentData.numUnfixed[p0]) {
1534
+ // printf("number of unfixed cols in perm %d: %d\n", p,
1535
+ // componentData.numUnfixed[p]);
1536
+ // printf("wrong number of unfixed columns in permutation\n");
1537
+ return false;
1538
+ }
1539
+ }
1540
+
1541
+ // all unfixed variables in the permutation must be part of a two cycle
1542
+ // and each two cycle defines one row of the orbitope. Hence the number
1543
+ // of unfixed variables in each permutation must be even and the number of
1544
+ // rows is the number of unfixed variables divided by two
1545
+ HighsInt orbitopeNumRows = componentData.numUnfixed[p0] >> 1;
1546
+
1547
+ // if this component is a full orbitope the component size must be
1548
+ // divisible by the number of orbits and the result is the size of each
1549
+ // orbit
1550
+ HighsInt orbitopeOrbitSize = componentSize / orbitopeNumRows;
1551
+ if (orbitopeOrbitSize * orbitopeNumRows != componentSize) {
1552
+ // printf("wrong number of orbits (%d orbits for component of size %d)\n",
1553
+ // orbitopeNumRows, componentSize);
1554
+ return false;
1555
+ }
1556
+
1557
+ // the number of permutations must be n-1 where n is the size of the
1558
+ // orbits in the orbitope
1559
+ HighsInt componentNumPerms =
1560
+ componentData.permComponentStarts[component + 1] -
1561
+ componentData.permComponentStarts[component];
1562
+ if (componentNumPerms != (orbitopeOrbitSize - 1)) {
1563
+ // printf("wrong number of perms\n");
1564
+ return false;
1565
+ }
1566
+
1567
+ // set up the first two columns of the orbitope matrix based on the first
1568
+ // permutation.
1569
+ HighsOrbitopeMatrix orbitopeMatrix;
1570
+ orbitopeMatrix.matrix.resize(componentSize, -1);
1571
+ orbitopeMatrix.numRows = orbitopeNumRows;
1572
+ orbitopeMatrix.rowLength = orbitopeOrbitSize;
1573
+ assert(componentSize == orbitopeMatrix.numRows * orbitopeMatrix.rowLength);
1574
+
1575
+ const HighsInt* perm = symmetries.permutations.data() + p0 * numActiveCols;
1576
+ HighsHashTable<HighsInt> colSet;
1577
+ HighsInt m = 0;
1578
+ for (HighsInt j = 0; j < numActiveCols; ++j) {
1579
+ HighsInt jImagePos = vertexPosition[perm[j]];
1580
+ if (jImagePos <= j) continue;
1581
+ if (m == orbitopeNumRows) return false;
1582
+
1583
+ // permutation should consist of two cycles
1584
+ if (perm[jImagePos] != vertexGroundSet[j]) return false;
1585
+
1586
+ orbitopeMatrix.matrix[m] = vertexGroundSet[j];
1587
+ orbitopeMatrix.matrix[orbitopeMatrix.numRows + m] = perm[j];
1588
+
1589
+ // Remember set of variables of the orbtiope matrix. Each variable should
1590
+ // occur only once, otherwise the permutation do not work out. Since we
1591
+
1592
+ if (!colSet.insert(vertexGroundSet[j])) return false;
1593
+ if (!colSet.insert(perm[j])) return false;
1594
+ ++m;
1595
+ }
1596
+
1597
+ // printf("set up first two columns of possible orbitope with permutation
1598
+ // %d\n",
1599
+ // p0);
1600
+
1601
+ HighsInt numColsAdded = 2;
1602
+ bool triedLeftExtension = false;
1603
+
1604
+ while (numColsAdded < orbitopeMatrix.rowLength) {
1605
+ if (colSet.size() != numColsAdded * orbitopeMatrix.numRows) return false;
1606
+
1607
+ HighsInt* thisCol = &orbitopeMatrix(0, numColsAdded);
1608
+ HighsInt* prevCol = &orbitopeMatrix(0, numColsAdded - 1);
1609
+
1610
+ bool foundCand = false;
1611
+
1612
+ while (true) {
1613
+ HighsInt movePos = vertexPosition[prevCol[0]];
1614
+ perm = nullptr;
1615
+
1616
+ for (HighsInt k = componentData.permComponentStarts[component] + 1;
1617
+ k < componentData.permComponentStarts[component + 1]; ++k) {
1618
+ HighsInt p = componentData.permComponents[k];
1619
+ perm = symmetries.permutations.data() + p * numActiveCols;
1620
+
1621
+ if (perm[movePos] != vertexGroundSet[movePos] &&
1622
+ !colSet.find(perm[movePos])) {
1623
+ foundCand = true;
1624
+ break;
1625
+ }
1626
+ }
1627
+
1628
+ if (!foundCand && !triedLeftExtension) {
1629
+ // if we fail to find a permutation extending the last column directly
1630
+ // after we set up the first two columns we might try to extend column
1631
+ // zero instead of the previous one
1632
+ prevCol = &orbitopeMatrix(0, 0);
1633
+ triedLeftExtension = true;
1634
+ continue;
1635
+ }
1636
+
1637
+ break;
1638
+ }
1639
+
1640
+ if (!foundCand) {
1641
+ // printf("did not find next permutation moving col %d\n", prevCol[0]);
1642
+ return false;
1643
+ }
1644
+
1645
+ for (HighsInt j = 0; j < orbitopeMatrix.numRows; ++j) {
1646
+ HighsInt nextVertex = perm[vertexPosition[prevCol[j]]];
1647
+
1648
+ thisCol[j] = nextVertex;
1649
+
1650
+ // check if this is a two cycle
1651
+ if (perm[vertexPosition[nextVertex]] != prevCol[j]) return false;
1652
+
1653
+ if (!colSet.insert(thisCol[j])) {
1654
+ // printf("col already exists\n");
1655
+ return false;
1656
+ }
1657
+ }
1658
+
1659
+ ++numColsAdded;
1660
+ }
1661
+
1662
+ if (colSet.size() != componentSize) {
1663
+ // printf("not all columns of component are mapped\n");
1664
+ return false;
1665
+ }
1666
+
1667
+ for (HighsInt col : orbitopeMatrix.matrix)
1668
+ symmetries.columnToOrbitope.insert(col, symmetries.orbitopes.size());
1669
+
1670
+ symmetries.orbitopes.emplace_back(std::move(orbitopeMatrix));
1671
+
1672
+ // printf("component %d is full orbitope: size %d and %d orbits\n", component,
1673
+ // componentSize, componentData.componentNumOrbits[component]);
1674
+ return true;
1675
+ }
1676
+
1677
+ bool HighsSymmetryDetection::initializeDetection() {
1678
+ initializeHashValues();
1679
+ partitionRefinement();
1680
+ removeFixPoints();
1681
+ if (numActiveCols == 0) return false;
1682
+ return true;
1683
+ }
1684
+
1685
+ void HighsSymmetryDetection::run(HighsSymmetries& symmetries) {
1686
+ assert(numActiveCols != 0);
1687
+ initializeGroundSet();
1688
+ currNodeCertificate.clear();
1689
+ cellCreationStack.clear();
1690
+ createNode();
1691
+ HighsInt maxPerms = 64000000 / numActiveCols;
1692
+ HighsSplitDeque* workerDeque = HighsTaskExecutor::getThisWorkerDeque();
1693
+ while (!nodeStack.empty()) {
1694
+ HighsInt targetCell = selectTargetCell();
1695
+ if (targetCell == -1) {
1696
+ if (firstLeavePartition.empty()) {
1697
+ firstLeavePartition = currentPartition;
1698
+ firstLeaveCertificate = currNodeCertificate;
1699
+ bestLeaveCertificate = currNodeCertificate;
1700
+ firstLeaveGraph = dumpCurrentGraph();
1701
+ firstPathDepth = nodeStack.size();
1702
+ bestPathDepth = nodeStack.size();
1703
+ firstLeavePrefixLen = currNodeCertificate.size();
1704
+ bestLeavePrefixLen = currNodeCertificate.size();
1705
+
1706
+ HighsInt backtrackDepth = firstPathDepth - 1;
1707
+ while (backtrackDepth > 0 &&
1708
+ !isFromBinaryColumn(nodeStack[backtrackDepth - 1].targetCell))
1709
+ --backtrackDepth;
1710
+ switchToNextNode(backtrackDepth);
1711
+ } else {
1712
+ HighsInt wrongCell = -1;
1713
+ HighsInt backtrackDepth = nodeStack.size() - 1;
1714
+ assert(currNodeCertificate.size() == firstLeaveCertificate.size());
1715
+ if (firstLeavePrefixLen == (HighsInt)currNodeCertificate.size() ||
1716
+ bestLeavePrefixLen == (HighsInt)currNodeCertificate.size()) {
1717
+ if (firstLeavePrefixLen == (HighsInt)currNodeCertificate.size() &&
1718
+ compareCurrentGraph(firstLeaveGraph, wrongCell)) {
1719
+ HighsInt k = (numAutomorphisms++) & 63;
1720
+ HighsInt* permutation = automorphisms.data() + k * numVertices;
1721
+ for (HighsInt i = 0; i < numVertices; ++i) {
1722
+ HighsInt firstLeaveCol = firstLeavePartition[i];
1723
+ permutation[vertexPosition[currentPartition[i]]] = firstLeaveCol;
1724
+ }
1725
+
1726
+ bool report = false;
1727
+ for (HighsInt i = 0; i < numVertices; ++i) {
1728
+ if (mergeOrbits(permutation[i], vertexGroundSet[i]) &&
1729
+ i < numActiveCols) {
1730
+ assert(permutation[i] < numCol);
1731
+ report = true;
1732
+ }
1733
+ }
1734
+
1735
+ if (report) {
1736
+ symmetries.permutations.insert(symmetries.permutations.end(),
1737
+ permutation,
1738
+ permutation + numActiveCols);
1739
+ ++symmetries.numPerms;
1740
+ if (symmetries.numPerms == maxPerms) break;
1741
+ }
1742
+ backtrackDepth = std::min(backtrackDepth, firstPathDepth);
1743
+ } else if (!bestLeavePartition.empty() &&
1744
+ bestLeavePrefixLen ==
1745
+ (HighsInt)currNodeCertificate.size() &&
1746
+ compareCurrentGraph(bestLeaveGraph, wrongCell)) {
1747
+ HighsInt k = (numAutomorphisms++) & 63;
1748
+ HighsInt* permutation = automorphisms.data() + k * numVertices;
1749
+ for (HighsInt i = 0; i < numVertices; ++i) {
1750
+ HighsInt bestLeaveCol = bestLeavePartition[i];
1751
+ permutation[vertexPosition[currentPartition[i]]] = bestLeaveCol;
1752
+ }
1753
+
1754
+ bool report = false;
1755
+ for (HighsInt i = 0; i < numVertices; ++i) {
1756
+ if (mergeOrbits(permutation[i], vertexGroundSet[i]) &&
1757
+ i < numActiveCols) {
1758
+ assert(permutation[i] < numCol);
1759
+ report = true;
1760
+ }
1761
+ }
1762
+
1763
+ if (report) {
1764
+ symmetries.permutations.insert(symmetries.permutations.end(),
1765
+ permutation,
1766
+ permutation + numActiveCols);
1767
+ ++symmetries.numPerms;
1768
+ if (symmetries.numPerms == maxPerms) break;
1769
+ }
1770
+
1771
+ backtrackDepth = std::min(backtrackDepth, bestPathDepth);
1772
+ } else if (bestLeavePrefixLen <
1773
+ (HighsInt)currNodeCertificate.size() &&
1774
+ currNodeCertificate[bestLeavePrefixLen] >
1775
+ bestLeaveCertificate[bestLeavePrefixLen]) {
1776
+ // certificate value is lexicographically above the smallest one
1777
+ // seen so far, so we might be able to backtrack to a higher level
1778
+ HighsInt possibleBacktrackDepth = firstPathDepth - 1;
1779
+ while (nodeStack[possibleBacktrackDepth].certificateEnd <=
1780
+ bestLeavePrefixLen)
1781
+ ++possibleBacktrackDepth;
1782
+
1783
+ backtrackDepth = std::min(possibleBacktrackDepth, backtrackDepth);
1784
+ } else {
1785
+ // This case can be caused by a hash collision which was now
1786
+ // detected in the graph comparison call. The graph comparison call
1787
+ // will return the cell where the vertex neighbourhood caused a
1788
+ // mismatch on the edges. This would have been detected by
1789
+ // an exact partition refinement when we targeted that cell the last
1790
+ // time, so that is where we can backtrack to.
1791
+ HighsInt possibleBacktrackDepth;
1792
+ for (possibleBacktrackDepth = backtrackDepth;
1793
+ possibleBacktrackDepth >= 0; --possibleBacktrackDepth) {
1794
+ if (nodeStack[possibleBacktrackDepth].targetCell == wrongCell) {
1795
+ backtrackDepth = possibleBacktrackDepth;
1796
+ break;
1797
+ }
1798
+ }
1799
+ }
1800
+ } else {
1801
+ // leave must have a lexicographically smaller certificate value
1802
+ // than the current best leave, because its prefix length is smaller
1803
+ // than the best leaves and it would have been already pruned if
1804
+ // it's certificate value was larger unless it is equal to the first
1805
+ // leaf nodes certificate value which is caught by the first case
1806
+ // of the if condition. Hence, having a lexicographically smaller
1807
+ // certificate value than the best leave is the only way to get
1808
+ // here.
1809
+ assert(bestLeaveCertificate[bestLeavePrefixLen] >
1810
+ currNodeCertificate[bestLeavePrefixLen] &&
1811
+ std::memcmp(bestLeaveCertificate.data(),
1812
+ currNodeCertificate.data(),
1813
+ bestLeavePrefixLen * sizeof(u32)) == 0);
1814
+ bestLeaveCertificate = currNodeCertificate;
1815
+ bestLeaveGraph = dumpCurrentGraph();
1816
+ bestLeavePartition = currentPartition;
1817
+ bestPathDepth = nodeStack.size();
1818
+ bestLeavePrefixLen = currNodeCertificate.size();
1819
+ }
1820
+
1821
+ switchToNextNode(backtrackDepth);
1822
+ }
1823
+
1824
+ workerDeque->checkInterrupt();
1825
+ } else {
1826
+ Node& currNode = nodeStack.back();
1827
+ currNode.targetCell = targetCell;
1828
+ bool success = determineNextToDistinguish();
1829
+ assert(success);
1830
+ if (!distinguishVertex(targetCell)) {
1831
+ switchToNextNode(nodeStack.size() - 1);
1832
+ continue;
1833
+ }
1834
+ if (!partitionRefinement()) {
1835
+ switchToNextNode(nodeStack.size());
1836
+ continue;
1837
+ }
1838
+
1839
+ createNode();
1840
+ }
1841
+ }
1842
+
1843
+ symmetries.numGenerators = symmetries.numPerms;
1844
+ if (symmetries.numPerms > 0) {
1845
+ vertexPosition.resize(numCol);
1846
+
1847
+ ComponentData componentData = computeComponentData(symmetries);
1848
+ HighsInt numComponents = componentData.numComponents();
1849
+
1850
+ for (HighsInt i = 0; i < numComponents; ++i) {
1851
+ if (componentData.componentSize(i) == 1) continue;
1852
+
1853
+ isFullOrbitope(componentData, i, symmetries);
1854
+ }
1855
+
1856
+ HighsHashTable<HighsInt> deletedPerms;
1857
+ for (HighsInt p = 0; p < symmetries.numPerms; ++p) {
1858
+ HighsInt* perm = symmetries.permutations.data() + p * numActiveCols;
1859
+ for (HighsInt i = 0; i < numActiveCols; ++i) {
1860
+ if (perm[i] != vertexGroundSet[i] &&
1861
+ symmetries.columnToOrbitope.find(perm[i])) {
1862
+ deletedPerms.insert(p);
1863
+ break;
1864
+ }
1865
+ }
1866
+ }
1867
+
1868
+ // check which columns have non-trivial orbits
1869
+ HighsInt numFixed = 0;
1870
+ for (HighsInt i = 0; i < numActiveCols; ++i) {
1871
+ if (orbitSize[getOrbit(vertexGroundSet[i])] == 1 ||
1872
+ symmetries.columnToOrbitope.find(vertexGroundSet[i])) {
1873
+ vertexPosition[vertexGroundSet[i]] = -1;
1874
+ vertexGroundSet[i] = -1;
1875
+ numFixed += 1;
1876
+ }
1877
+ }
1878
+
1879
+ if (numFixed != 0) {
1880
+ // now compress symmetries and the groundset to only contain the unfixed
1881
+ // columns and columns not handled by full orbitopes
1882
+ HighsInt p = 0;
1883
+ HighsInt* perms = symmetries.permutations.data();
1884
+ HighsInt* permEnd =
1885
+ symmetries.permutations.data() + symmetries.numPerms * numActiveCols;
1886
+ HighsInt* permOutput = symmetries.permutations.data();
1887
+ while (perms != permEnd) {
1888
+ if (!deletedPerms.find(p)) {
1889
+ for (HighsInt i = 0; i < numActiveCols; ++i) {
1890
+ if (vertexGroundSet[i] == -1) continue;
1891
+
1892
+ *permOutput = perms[i];
1893
+ ++permOutput;
1894
+ }
1895
+ } else {
1896
+ --symmetries.numPerms;
1897
+ }
1898
+ perms += numActiveCols;
1899
+ ++p;
1900
+ }
1901
+
1902
+ HighsInt outPos = 0;
1903
+ for (HighsInt i = 0; i < numActiveCols; ++i) {
1904
+ if (vertexGroundSet[i] == -1) continue;
1905
+
1906
+ vertexGroundSet[outPos] = vertexGroundSet[i];
1907
+ vertexPosition[vertexGroundSet[outPos]] = outPos;
1908
+ outPos += 1;
1909
+ }
1910
+
1911
+ numActiveCols -= numFixed;
1912
+ assert(permOutput == symmetries.permutations.data() +
1913
+ symmetries.numPerms * numActiveCols);
1914
+ }
1915
+
1916
+ vertexGroundSet.resize(numActiveCols);
1917
+ symmetries.permutationColumns = std::move(vertexGroundSet);
1918
+ symmetries.columnPosition = std::move(vertexPosition);
1919
+ symmetries.permutations.resize(symmetries.numPerms * numActiveCols);
1920
+ }
1921
+ }