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.
- checksums.yaml +4 -4
- data/Gemfile +1 -0
- data/README.md +70 -26
- data/ext/lpsolver/Makefile +273 -0
- data/ext/lpsolver/ext.c +353 -0
- data/ext/lpsolver/ext.o +0 -0
- data/ext/lpsolver/extconf.rb +79 -0
- data/ext/lpsolver/native.so +0 -0
- data/ext/lpsolver-highs/AUTHORS +7 -0
- data/ext/lpsolver-highs/BUILD.bazel +243 -0
- data/ext/lpsolver-highs/CITATION.cff +29 -0
- data/ext/lpsolver-highs/CMakeCache.txt +406 -0
- data/ext/lpsolver-highs/CMakeFiles/3.31.4/CMakeCCompiler.cmake +81 -0
- data/ext/lpsolver-highs/CMakeFiles/3.31.4/CMakeCXXCompiler.cmake +101 -0
- data/ext/lpsolver-highs/CMakeFiles/3.31.4/CMakeDetermineCompilerABI_C.bin +0 -0
- data/ext/lpsolver-highs/CMakeFiles/3.31.4/CMakeDetermineCompilerABI_CXX.bin +0 -0
- data/ext/lpsolver-highs/CMakeFiles/3.31.4/CMakeSystem.cmake +15 -0
- data/ext/lpsolver-highs/CMakeFiles/3.31.4/CompilerIdC/CMakeCCompilerId.c +904 -0
- data/ext/lpsolver-highs/CMakeFiles/3.31.4/CompilerIdC/a.out +0 -0
- data/ext/lpsolver-highs/CMakeFiles/3.31.4/CompilerIdCXX/CMakeCXXCompilerId.cpp +919 -0
- data/ext/lpsolver-highs/CMakeFiles/3.31.4/CompilerIdCXX/a.out +0 -0
- data/ext/lpsolver-highs/CMakeFiles/CMakeConfigureLog.yaml +576 -0
- data/ext/lpsolver-highs/CMakeFiles/cmake.check_cache +1 -0
- data/ext/lpsolver-highs/CMakeLists.txt +983 -0
- data/ext/lpsolver-highs/CODE_OF_CONDUCT.md +128 -0
- data/ext/lpsolver-highs/CONTRIBUTING.md +31 -0
- data/ext/lpsolver-highs/FEATURES.md +61 -0
- data/ext/lpsolver-highs/LICENSE.txt +21 -0
- data/ext/lpsolver-highs/MODULE.bazel +38 -0
- data/ext/lpsolver-highs/README.md +281 -0
- data/ext/lpsolver-highs/THIRD_PARTY_NOTICES.md +78 -0
- data/ext/lpsolver-highs/Version.txt +4 -0
- data/ext/lpsolver-highs/WORKSPACE +33 -0
- data/ext/lpsolver-highs/app/CMakeLists.txt +110 -0
- data/ext/lpsolver-highs/app/HighsRuntimeOptions.h +292 -0
- data/ext/lpsolver-highs/app/RunHighs.cpp +147 -0
- data/ext/lpsolver-highs/app/highs_webdemo_shell.html +73 -0
- data/ext/lpsolver-highs/build/bin/highs +0 -0
- data/ext/lpsolver-highs/build/include/highs/HConfig.h +22 -0
- data/ext/lpsolver-highs/build/include/highs/Highs.h +1812 -0
- data/ext/lpsolver-highs/build/include/highs/interfaces/highs_c_api.h +2651 -0
- data/ext/lpsolver-highs/build/include/highs/io/Filereader.h +45 -0
- data/ext/lpsolver-highs/build/include/highs/io/FilereaderLp.h +49 -0
- data/ext/lpsolver-highs/build/include/highs/io/FilereaderMps.h +27 -0
- data/ext/lpsolver-highs/build/include/highs/io/HMPSIO.h +78 -0
- data/ext/lpsolver-highs/build/include/highs/io/HMpsFF.h +245 -0
- data/ext/lpsolver-highs/build/include/highs/io/HighsIO.h +118 -0
- data/ext/lpsolver-highs/build/include/highs/io/LoadOptions.h +24 -0
- data/ext/lpsolver-highs/build/include/highs/io/filereaderlp/builder.hpp +25 -0
- data/ext/lpsolver-highs/build/include/highs/io/filereaderlp/def.hpp +19 -0
- data/ext/lpsolver-highs/build/include/highs/io/filereaderlp/model.hpp +68 -0
- data/ext/lpsolver-highs/build/include/highs/io/filereaderlp/reader.hpp +10 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/IpxSolution.h +32 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/IpxWrapper.h +106 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/basiclu.h +161 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/basiclu_factorize.h +247 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/basiclu_get_factors.h +108 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/basiclu_initialize.h +119 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/basiclu_obj_factorize.h +34 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/basiclu_obj_free.h +19 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/basiclu_obj_get_factors.h +34 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/basiclu_obj_initialize.h +46 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/basiclu_obj_solve_dense.h +29 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/basiclu_obj_solve_for_update.h +42 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/basiclu_obj_solve_sparse.h +32 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/basiclu_obj_update.h +31 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/basiclu_object.h +30 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/basiclu_solve_dense.h +75 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/basiclu_solve_for_update.h +169 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/basiclu_solve_sparse.h +112 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/basiclu_update.h +125 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/lu_def.h +39 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/lu_file.h +21 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/lu_internal.h +220 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/basiclu/lu_list.h +173 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/basiclu_kernel.h +20 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/basiclu_wrapper.h +47 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/basis.h +350 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/conjugate_residuals.h +74 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/control.h +167 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/crossover.h +157 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/diagonal_precond.h +45 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/forrest_tomlin.h +102 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/guess_basis.h +21 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/indexed_vector.h +113 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/info.h +27 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/ipm.h +94 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/ipx_c.h +47 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/ipx_config.h +9 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/ipx_info.h +111 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/ipx_internal.h +89 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/ipx_parameters.h +76 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/ipx_status.h +57 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/iterate.h +331 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/kkt_solver.h +70 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/kkt_solver_basis.h +66 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/kkt_solver_diag.h +48 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/linear_operator.h +26 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/lp_solver.h +204 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/lu_factorization.h +79 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/lu_update.h +129 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/maxvolume.h +54 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/model.h +413 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/multistream.h +52 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/normal_matrix.h +44 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/power_method.h +44 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/sparse_matrix.h +195 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/sparse_utils.h +58 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/splitted_normal_matrix.h +63 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/starting_basis.h +39 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/symbolic_invert.h +29 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/timer.h +25 -0
- data/ext/lpsolver-highs/build/include/highs/ipm/ipx/utils.h +37 -0
- data/ext/lpsolver-highs/build/include/highs/lp_data/HConst.h +430 -0
- data/ext/lpsolver-highs/build/include/highs/lp_data/HStruct.h +213 -0
- data/ext/lpsolver-highs/build/include/highs/lp_data/HighsAnalysis.h +23 -0
- data/ext/lpsolver-highs/build/include/highs/lp_data/HighsCallback.h +104 -0
- data/ext/lpsolver-highs/build/include/highs/lp_data/HighsCallbackStruct.h +70 -0
- data/ext/lpsolver-highs/build/include/highs/lp_data/HighsDebug.h +34 -0
- data/ext/lpsolver-highs/build/include/highs/lp_data/HighsIis.h +139 -0
- data/ext/lpsolver-highs/build/include/highs/lp_data/HighsInfo.h +421 -0
- data/ext/lpsolver-highs/build/include/highs/lp_data/HighsInfoDebug.h +27 -0
- data/ext/lpsolver-highs/build/include/highs/lp_data/HighsLp.h +97 -0
- data/ext/lpsolver-highs/build/include/highs/lp_data/HighsLpSolverObject.h +47 -0
- data/ext/lpsolver-highs/build/include/highs/lp_data/HighsLpUtils.h +330 -0
- data/ext/lpsolver-highs/build/include/highs/lp_data/HighsModelUtils.h +129 -0
- data/ext/lpsolver-highs/build/include/highs/lp_data/HighsOptions.h +1715 -0
- data/ext/lpsolver-highs/build/include/highs/lp_data/HighsRanging.h +43 -0
- data/ext/lpsolver-highs/build/include/highs/lp_data/HighsSolution.h +179 -0
- data/ext/lpsolver-highs/build/include/highs/lp_data/HighsSolutionDebug.h +87 -0
- data/ext/lpsolver-highs/build/include/highs/lp_data/HighsSolve.h +29 -0
- data/ext/lpsolver-highs/build/include/highs/lp_data/HighsStatus.h +29 -0
- data/ext/lpsolver-highs/build/include/highs/mip/HighsCliqueTable.h +329 -0
- data/ext/lpsolver-highs/build/include/highs/mip/HighsConflictPool.h +109 -0
- data/ext/lpsolver-highs/build/include/highs/mip/HighsCutGeneration.h +108 -0
- data/ext/lpsolver-highs/build/include/highs/mip/HighsCutPool.h +168 -0
- data/ext/lpsolver-highs/build/include/highs/mip/HighsDebugSol.h +133 -0
- data/ext/lpsolver-highs/build/include/highs/mip/HighsDomain.h +657 -0
- data/ext/lpsolver-highs/build/include/highs/mip/HighsDomainChange.h +48 -0
- data/ext/lpsolver-highs/build/include/highs/mip/HighsDynamicRowMatrix.h +104 -0
- data/ext/lpsolver-highs/build/include/highs/mip/HighsGFkSolve.h +439 -0
- data/ext/lpsolver-highs/build/include/highs/mip/HighsImplications.h +194 -0
- data/ext/lpsolver-highs/build/include/highs/mip/HighsLpAggregator.h +50 -0
- data/ext/lpsolver-highs/build/include/highs/mip/HighsLpRelaxation.h +361 -0
- data/ext/lpsolver-highs/build/include/highs/mip/HighsMipAnalysis.h +71 -0
- data/ext/lpsolver-highs/build/include/highs/mip/HighsMipSolver.h +159 -0
- data/ext/lpsolver-highs/build/include/highs/mip/HighsMipSolverData.h +313 -0
- data/ext/lpsolver-highs/build/include/highs/mip/HighsModkSeparator.h +60 -0
- data/ext/lpsolver-highs/build/include/highs/mip/HighsNodeQueue.h +312 -0
- data/ext/lpsolver-highs/build/include/highs/mip/HighsObjectiveFunction.h +71 -0
- data/ext/lpsolver-highs/build/include/highs/mip/HighsPathSeparator.h +39 -0
- data/ext/lpsolver-highs/build/include/highs/mip/HighsPrimalHeuristics.h +75 -0
- data/ext/lpsolver-highs/build/include/highs/mip/HighsPseudocost.h +366 -0
- data/ext/lpsolver-highs/build/include/highs/mip/HighsRedcostFixing.h +42 -0
- data/ext/lpsolver-highs/build/include/highs/mip/HighsSearch.h +241 -0
- data/ext/lpsolver-highs/build/include/highs/mip/HighsSeparation.h +41 -0
- data/ext/lpsolver-highs/build/include/highs/mip/HighsSeparator.h +60 -0
- data/ext/lpsolver-highs/build/include/highs/mip/HighsTableauSeparator.h +34 -0
- data/ext/lpsolver-highs/build/include/highs/mip/HighsTransformedLp.h +63 -0
- data/ext/lpsolver-highs/build/include/highs/mip/MipTimer.h +544 -0
- data/ext/lpsolver-highs/build/include/highs/mip/feasibilityjump.hh +800 -0
- data/ext/lpsolver-highs/build/include/highs/model/HighsHessian.h +54 -0
- data/ext/lpsolver-highs/build/include/highs/model/HighsHessianUtils.h +47 -0
- data/ext/lpsolver-highs/build/include/highs/model/HighsModel.h +42 -0
- data/ext/lpsolver-highs/build/include/highs/parallel/HighsBinarySemaphore.h +108 -0
- data/ext/lpsolver-highs/build/include/highs/parallel/HighsCacheAlign.h +82 -0
- data/ext/lpsolver-highs/build/include/highs/parallel/HighsCombinable.h +116 -0
- data/ext/lpsolver-highs/build/include/highs/parallel/HighsMutex.h +124 -0
- data/ext/lpsolver-highs/build/include/highs/parallel/HighsParallel.h +128 -0
- data/ext/lpsolver-highs/build/include/highs/parallel/HighsRaceTimer.h +38 -0
- data/ext/lpsolver-highs/build/include/highs/parallel/HighsSchedulerConstants.h +19 -0
- data/ext/lpsolver-highs/build/include/highs/parallel/HighsSpinMutex.h +48 -0
- data/ext/lpsolver-highs/build/include/highs/parallel/HighsSplitDeque.h +606 -0
- data/ext/lpsolver-highs/build/include/highs/parallel/HighsTask.h +170 -0
- data/ext/lpsolver-highs/build/include/highs/parallel/HighsTaskExecutor.h +217 -0
- data/ext/lpsolver-highs/build/include/highs/pdlp/CupdlpWrapper.h +108 -0
- data/ext/lpsolver-highs/build/include/highs/pdlp/HiPdlpTimer.h +155 -0
- data/ext/lpsolver-highs/build/include/highs/pdlp/HiPdlpWrapper.h +26 -0
- data/ext/lpsolver-highs/build/include/highs/pdlp/cupdlp/cupdlp_cs.h +40 -0
- data/ext/lpsolver-highs/build/include/highs/pdlp/cupdlp/cupdlp_defs.h +447 -0
- data/ext/lpsolver-highs/build/include/highs/pdlp/cupdlp/cupdlp_linalg.h +189 -0
- data/ext/lpsolver-highs/build/include/highs/pdlp/cupdlp/cupdlp_proj.h +19 -0
- data/ext/lpsolver-highs/build/include/highs/pdlp/cupdlp/cupdlp_restart.h +31 -0
- data/ext/lpsolver-highs/build/include/highs/pdlp/cupdlp/cupdlp_scaling.h +26 -0
- data/ext/lpsolver-highs/build/include/highs/pdlp/cupdlp/cupdlp_solver.h +105 -0
- data/ext/lpsolver-highs/build/include/highs/pdlp/cupdlp/cupdlp_step.h +37 -0
- data/ext/lpsolver-highs/build/include/highs/pdlp/cupdlp/cupdlp_utils.c +1850 -0
- data/ext/lpsolver-highs/build/include/highs/pdlp/hipdlp/defs.hpp +222 -0
- data/ext/lpsolver-highs/build/include/highs/pdlp/hipdlp/linalg.hpp +61 -0
- data/ext/lpsolver-highs/build/include/highs/pdlp/hipdlp/logger.hpp +80 -0
- data/ext/lpsolver-highs/build/include/highs/pdlp/hipdlp/pdhg.hpp +358 -0
- data/ext/lpsolver-highs/build/include/highs/pdlp/hipdlp/restart.hpp +96 -0
- data/ext/lpsolver-highs/build/include/highs/pdlp/hipdlp/scaling.hpp +74 -0
- data/ext/lpsolver-highs/build/include/highs/pdlp/hipdlp/solver_results.hpp +65 -0
- data/ext/lpsolver-highs/build/include/highs/pdqsort/pdqsort.h +532 -0
- data/ext/lpsolver-highs/build/include/highs/presolve/HPresolve.h +505 -0
- data/ext/lpsolver-highs/build/include/highs/presolve/HPresolveAnalysis.h +52 -0
- data/ext/lpsolver-highs/build/include/highs/presolve/HighsPostsolveStack.h +943 -0
- data/ext/lpsolver-highs/build/include/highs/presolve/HighsSymmetry.h +284 -0
- data/ext/lpsolver-highs/build/include/highs/presolve/ICrash.h +124 -0
- data/ext/lpsolver-highs/build/include/highs/presolve/ICrashUtil.h +62 -0
- data/ext/lpsolver-highs/build/include/highs/presolve/ICrashX.h +23 -0
- data/ext/lpsolver-highs/build/include/highs/presolve/PresolveComponent.h +90 -0
- data/ext/lpsolver-highs/build/include/highs/qpsolver/a_asm.hpp +77 -0
- data/ext/lpsolver-highs/build/include/highs/qpsolver/a_quass.hpp +22 -0
- data/ext/lpsolver-highs/build/include/highs/qpsolver/basis.hpp +159 -0
- data/ext/lpsolver-highs/build/include/highs/qpsolver/crashsolution.hpp +20 -0
- data/ext/lpsolver-highs/build/include/highs/qpsolver/dantzigpricing.hpp +80 -0
- data/ext/lpsolver-highs/build/include/highs/qpsolver/devexpricing.hpp +108 -0
- data/ext/lpsolver-highs/build/include/highs/qpsolver/eventhandler.hpp +30 -0
- data/ext/lpsolver-highs/build/include/highs/qpsolver/factor.hpp +408 -0
- data/ext/lpsolver-highs/build/include/highs/qpsolver/feasibility_bounded.hpp +114 -0
- data/ext/lpsolver-highs/build/include/highs/qpsolver/feasibility_highs.hpp +301 -0
- data/ext/lpsolver-highs/build/include/highs/qpsolver/gradient.hpp +46 -0
- data/ext/lpsolver-highs/build/include/highs/qpsolver/instance.hpp +70 -0
- data/ext/lpsolver-highs/build/include/highs/qpsolver/matrix.hpp +342 -0
- data/ext/lpsolver-highs/build/include/highs/qpsolver/perturbation.hpp +15 -0
- data/ext/lpsolver-highs/build/include/highs/qpsolver/pricing.hpp +22 -0
- data/ext/lpsolver-highs/build/include/highs/qpsolver/qpconst.hpp +34 -0
- data/ext/lpsolver-highs/build/include/highs/qpsolver/qpvector.hpp +242 -0
- data/ext/lpsolver-highs/build/include/highs/qpsolver/quass.hpp +27 -0
- data/ext/lpsolver-highs/build/include/highs/qpsolver/ratiotest.hpp +26 -0
- data/ext/lpsolver-highs/build/include/highs/qpsolver/runtime.hpp +45 -0
- data/ext/lpsolver-highs/build/include/highs/qpsolver/scaling.hpp +15 -0
- data/ext/lpsolver-highs/build/include/highs/qpsolver/settings.hpp +84 -0
- data/ext/lpsolver-highs/build/include/highs/qpsolver/snippets.hpp +36 -0
- data/ext/lpsolver-highs/build/include/highs/qpsolver/statistics.hpp +30 -0
- data/ext/lpsolver-highs/build/include/highs/qpsolver/steepestedgepricing.hpp +173 -0
- data/ext/lpsolver-highs/build/include/highs/simplex/HApp.h +550 -0
- data/ext/lpsolver-highs/build/include/highs/simplex/HEkk.h +419 -0
- data/ext/lpsolver-highs/build/include/highs/simplex/HEkkDual.h +513 -0
- data/ext/lpsolver-highs/build/include/highs/simplex/HEkkDualRHS.h +134 -0
- data/ext/lpsolver-highs/build/include/highs/simplex/HEkkDualRow.h +201 -0
- data/ext/lpsolver-highs/build/include/highs/simplex/HEkkPrimal.h +191 -0
- data/ext/lpsolver-highs/build/include/highs/simplex/HSimplex.h +42 -0
- data/ext/lpsolver-highs/build/include/highs/simplex/HSimplexDebug.h +48 -0
- data/ext/lpsolver-highs/build/include/highs/simplex/HSimplexNla.h +158 -0
- data/ext/lpsolver-highs/build/include/highs/simplex/HSimplexReport.h +21 -0
- data/ext/lpsolver-highs/build/include/highs/simplex/HighsSimplexAnalysis.h +500 -0
- data/ext/lpsolver-highs/build/include/highs/simplex/SimplexConst.h +273 -0
- data/ext/lpsolver-highs/build/include/highs/simplex/SimplexStruct.h +263 -0
- data/ext/lpsolver-highs/build/include/highs/simplex/SimplexTimer.h +414 -0
- data/ext/lpsolver-highs/build/include/highs/test_kkt/DevKkt.h +143 -0
- data/ext/lpsolver-highs/build/include/highs/test_kkt/KktCh2.h +79 -0
- data/ext/lpsolver-highs/build/include/highs/util/FactorTimer.h +199 -0
- data/ext/lpsolver-highs/build/include/highs/util/HFactor.h +587 -0
- data/ext/lpsolver-highs/build/include/highs/util/HFactorConst.h +81 -0
- data/ext/lpsolver-highs/build/include/highs/util/HFactorDebug.h +55 -0
- data/ext/lpsolver-highs/build/include/highs/util/HSet.h +89 -0
- data/ext/lpsolver-highs/build/include/highs/util/HVector.h +22 -0
- data/ext/lpsolver-highs/build/include/highs/util/HVectorBase.h +102 -0
- data/ext/lpsolver-highs/build/include/highs/util/HighsCDouble.h +323 -0
- data/ext/lpsolver-highs/build/include/highs/util/HighsComponent.h +53 -0
- data/ext/lpsolver-highs/build/include/highs/util/HighsDataStack.h +83 -0
- data/ext/lpsolver-highs/build/include/highs/util/HighsDisjointSets.h +107 -0
- data/ext/lpsolver-highs/build/include/highs/util/HighsHash.h +1274 -0
- data/ext/lpsolver-highs/build/include/highs/util/HighsHashTree.h +1461 -0
- data/ext/lpsolver-highs/build/include/highs/util/HighsInt.h +36 -0
- data/ext/lpsolver-highs/build/include/highs/util/HighsIntegers.h +212 -0
- data/ext/lpsolver-highs/build/include/highs/util/HighsLinearSumBounds.h +203 -0
- data/ext/lpsolver-highs/build/include/highs/util/HighsMatrixPic.h +37 -0
- data/ext/lpsolver-highs/build/include/highs/util/HighsMatrixSlice.h +561 -0
- data/ext/lpsolver-highs/build/include/highs/util/HighsMatrixUtils.h +57 -0
- data/ext/lpsolver-highs/build/include/highs/util/HighsMemoryAllocation.h +63 -0
- data/ext/lpsolver-highs/build/include/highs/util/HighsRandom.h +242 -0
- data/ext/lpsolver-highs/build/include/highs/util/HighsRbTree.h +452 -0
- data/ext/lpsolver-highs/build/include/highs/util/HighsSort.h +131 -0
- data/ext/lpsolver-highs/build/include/highs/util/HighsSparseMatrix.h +151 -0
- data/ext/lpsolver-highs/build/include/highs/util/HighsSparseVectorSum.h +95 -0
- data/ext/lpsolver-highs/build/include/highs/util/HighsSplay.h +135 -0
- data/ext/lpsolver-highs/build/include/highs/util/HighsTimer.h +385 -0
- data/ext/lpsolver-highs/build/include/highs/util/HighsUtils.h +272 -0
- data/ext/lpsolver-highs/build/include/highs/util/stringutil.h +46 -0
- data/ext/lpsolver-highs/build/include/highs/zstr/strict_fstream.hpp +237 -0
- data/ext/lpsolver-highs/build/include/highs/zstr/zstr.hpp +473 -0
- data/ext/lpsolver-highs/build/include/highs_export.h +43 -0
- data/ext/lpsolver-highs/build/lib/cmake/highs/highs-config-version.cmake +65 -0
- data/ext/lpsolver-highs/build/lib/cmake/highs/highs-config.cmake +36 -0
- data/ext/lpsolver-highs/build/lib/cmake/highs/highs-targets-release.cmake +19 -0
- data/ext/lpsolver-highs/build/lib/cmake/highs/highs-targets.cmake +111 -0
- data/ext/lpsolver-highs/build/lib/libhighs.a +0 -0
- data/ext/lpsolver-highs/build/lib/pkgconfig/highs.pc +12 -0
- data/ext/lpsolver-highs/build/share/doc/HIGHS/AUTHORS +7 -0
- data/ext/lpsolver-highs/build/share/doc/HIGHS/CITATION.cff +29 -0
- data/ext/lpsolver-highs/build/share/doc/HIGHS/CODE_OF_CONDUCT.md +128 -0
- data/ext/lpsolver-highs/build/share/doc/HIGHS/CONTRIBUTING.md +31 -0
- data/ext/lpsolver-highs/build/share/doc/HIGHS/FEATURES.md +61 -0
- data/ext/lpsolver-highs/build/share/doc/HIGHS/LICENSE.txt +21 -0
- data/ext/lpsolver-highs/build/share/doc/HIGHS/README.md +281 -0
- data/ext/lpsolver-highs/build_webdemo.sh +46 -0
- data/ext/lpsolver-highs/check/Avgas.cpp +245 -0
- data/ext/lpsolver-highs/check/Avgas.h +44 -0
- data/ext/lpsolver-highs/check/CMakeLists.txt +573 -0
- data/ext/lpsolver-highs/check/HCheckConfig.h.bazel.in +6 -0
- data/ext/lpsolver-highs/check/HCheckConfig.h.in +12 -0
- data/ext/lpsolver-highs/check/HCheckConfig.h.meson.in +6 -0
- data/ext/lpsolver-highs/check/SpecialLps.h +405 -0
- data/ext/lpsolver-highs/check/TestAlienBasis.cpp +720 -0
- data/ext/lpsolver-highs/check/TestBasis.cpp +359 -0
- data/ext/lpsolver-highs/check/TestBasisSolves.cpp +669 -0
- data/ext/lpsolver-highs/check/TestCAPI.c +2513 -0
- data/ext/lpsolver-highs/check/TestCallbacks.cpp +608 -0
- data/ext/lpsolver-highs/check/TestCheckSolution.cpp +740 -0
- data/ext/lpsolver-highs/check/TestCrossover.cpp +111 -0
- data/ext/lpsolver-highs/check/TestDualize.cpp +172 -0
- data/ext/lpsolver-highs/check/TestEkk.cpp +100 -0
- data/ext/lpsolver-highs/check/TestFactor.cpp +389 -0
- data/ext/lpsolver-highs/check/TestFilereader.cpp +568 -0
- data/ext/lpsolver-highs/check/TestFortranAPI.f90 +65 -0
- data/ext/lpsolver-highs/check/TestHSet.cpp +80 -0
- data/ext/lpsolver-highs/check/TestHighsCDouble.cpp +109 -0
- data/ext/lpsolver-highs/check/TestHighsGFkSolve.cpp +102 -0
- data/ext/lpsolver-highs/check/TestHighsHash.cpp +126 -0
- data/ext/lpsolver-highs/check/TestHighsHessian.cpp +329 -0
- data/ext/lpsolver-highs/check/TestHighsIntegers.cpp +42 -0
- data/ext/lpsolver-highs/check/TestHighsModel.cpp +134 -0
- data/ext/lpsolver-highs/check/TestHighsParallel.cpp +277 -0
- data/ext/lpsolver-highs/check/TestHighsRbTree.cpp +109 -0
- data/ext/lpsolver-highs/check/TestHighsSparseMatrix.cpp +126 -0
- data/ext/lpsolver-highs/check/TestHighsVersion.cpp +61 -0
- data/ext/lpsolver-highs/check/TestHipo.cpp +122 -0
- data/ext/lpsolver-highs/check/TestICrash.cpp +46 -0
- data/ext/lpsolver-highs/check/TestIO.cpp +163 -0
- data/ext/lpsolver-highs/check/TestIis.cpp +1063 -0
- data/ext/lpsolver-highs/check/TestInfo.cpp +116 -0
- data/ext/lpsolver-highs/check/TestIpm.cpp +226 -0
- data/ext/lpsolver-highs/check/TestIpx.cpp +96 -0
- data/ext/lpsolver-highs/check/TestLPFileFormat.cpp +22 -0
- data/ext/lpsolver-highs/check/TestLogging.cpp +69 -0
- data/ext/lpsolver-highs/check/TestLpModification.cpp +2497 -0
- data/ext/lpsolver-highs/check/TestLpOrientation.cpp +121 -0
- data/ext/lpsolver-highs/check/TestLpSolvers.cpp +555 -0
- data/ext/lpsolver-highs/check/TestLpValidation.cpp +689 -0
- data/ext/lpsolver-highs/check/TestMain.cpp +6 -0
- data/ext/lpsolver-highs/check/TestMipSolver.cpp +1406 -0
- data/ext/lpsolver-highs/check/TestModelProperties.cpp +143 -0
- data/ext/lpsolver-highs/check/TestMultiObjective.cpp +198 -0
- data/ext/lpsolver-highs/check/TestNames.cpp +187 -0
- data/ext/lpsolver-highs/check/TestOptions.cpp +544 -0
- data/ext/lpsolver-highs/check/TestPdlp.cpp +327 -0
- data/ext/lpsolver-highs/check/TestPdlpHi.cpp +40 -0
- data/ext/lpsolver-highs/check/TestPresolve.cpp +912 -0
- data/ext/lpsolver-highs/check/TestQpSolver.cpp +1345 -0
- data/ext/lpsolver-highs/check/TestRanging.cpp +558 -0
- data/ext/lpsolver-highs/check/TestRays.cpp +1010 -0
- data/ext/lpsolver-highs/check/TestSemiVariables.cpp +329 -0
- data/ext/lpsolver-highs/check/TestSetup.cpp +12 -0
- data/ext/lpsolver-highs/check/TestSort.cpp +247 -0
- data/ext/lpsolver-highs/check/TestSpecialLps.cpp +775 -0
- data/ext/lpsolver-highs/check/TestThrow.cpp +83 -0
- data/ext/lpsolver-highs/check/TestTspSolver.cpp +19 -0
- data/ext/lpsolver-highs/check/TestUserScale.cpp +444 -0
- data/ext/lpsolver-highs/check/cublas_example.cpp +76 -0
- data/ext/lpsolver-highs/check/cublas_gpu_start.cpp +88 -0
- data/ext/lpsolver-highs/check/hipo_test_option_files/hipo_options_0 +1 -0
- data/ext/lpsolver-highs/check/instances/1448.lp +1 -0
- data/ext/lpsolver-highs/check/instances/1449a.lp +1 -0
- data/ext/lpsolver-highs/check/instances/1449b.lp +1 -0
- data/ext/lpsolver-highs/check/instances/1451.lp +8 -0
- data/ext/lpsolver-highs/check/instances/2122.lp +1822 -0
- data/ext/lpsolver-highs/check/instances/2171.mps +717 -0
- data/ext/lpsolver-highs/check/instances/25fv47.mps +6919 -0
- data/ext/lpsolver-highs/check/instances/2821-duplicate.mps +31 -0
- data/ext/lpsolver-highs/check/instances/2821-qmatrix.mps +31 -0
- data/ext/lpsolver-highs/check/instances/2821-quadobj.mps +29 -0
- data/ext/lpsolver-highs/check/instances/2821-summation.mps +30 -0
- data/ext/lpsolver-highs/check/instances/2821.mps +29 -0
- data/ext/lpsolver-highs/check/instances/2894.mps +89 -0
- data/ext/lpsolver-highs/check/instances/80bau3b.mps +23732 -0
- data/ext/lpsolver-highs/check/instances/WithInf.set +3 -0
- data/ext/lpsolver-highs/check/instances/adlittle.mps +335 -0
- data/ext/lpsolver-highs/check/instances/afiro.mps +83 -0
- data/ext/lpsolver-highs/check/instances/avgas.mps +51 -0
- data/ext/lpsolver-highs/check/instances/bell5.mps +384 -0
- data/ext/lpsolver-highs/check/instances/bgetam.mps +2112 -0
- data/ext/lpsolver-highs/check/instances/blending.mps +13 -0
- data/ext/lpsolver-highs/check/instances/box1.mps +1085 -0
- data/ext/lpsolver-highs/check/instances/chip.mps +13 -0
- data/ext/lpsolver-highs/check/instances/comment.mps +23 -0
- data/ext/lpsolver-highs/check/instances/cplex1.mps +9674 -0
- data/ext/lpsolver-highs/check/instances/dD2e.mps +10 -0
- data/ext/lpsolver-highs/check/instances/dcmulti.mps +2310 -0
- data/ext/lpsolver-highs/check/instances/e226.mps +1733 -0
- data/ext/lpsolver-highs/check/instances/egout-ac.mps +473 -0
- data/ext/lpsolver-highs/check/instances/egout.mps +403 -0
- data/ext/lpsolver-highs/check/instances/etamacro.mps +2084 -0
- data/ext/lpsolver-highs/check/instances/ex72a.mps +849 -0
- data/ext/lpsolver-highs/check/instances/fixed-binary.lp +11 -0
- data/ext/lpsolver-highs/check/instances/flugpl.mps +111 -0
- data/ext/lpsolver-highs/check/instances/flugpl_illegal_integer.sol +24 -0
- data/ext/lpsolver-highs/check/instances/flugpl_integer.sol +25 -0
- data/ext/lpsolver-highs/check/instances/forest6.mps +261 -0
- data/ext/lpsolver-highs/check/instances/galenet.mps +34 -0
- data/ext/lpsolver-highs/check/instances/gams10am.mps +478 -0
- data/ext/lpsolver-highs/check/instances/garbage.ems +3 -0
- data/ext/lpsolver-highs/check/instances/garbage.lp +3 -0
- data/ext/lpsolver-highs/check/instances/garbage.mps +3 -0
- data/ext/lpsolver-highs/check/instances/gas11.mps +2924 -0
- data/ext/lpsolver-highs/check/instances/gesa2.mps +5459 -0
- data/ext/lpsolver-highs/check/instances/greenbea.mps +19215 -0
- data/ext/lpsolver-highs/check/instances/gt2.mps +534 -0
- data/ext/lpsolver-highs/check/instances/infeasible-mip0.mps +140 -0
- data/ext/lpsolver-highs/check/instances/infeasible-mip1.mps +371 -0
- data/ext/lpsolver-highs/check/instances/israel.mps +1490 -0
- data/ext/lpsolver-highs/check/instances/issue-2095.mps +836 -0
- data/ext/lpsolver-highs/check/instances/issue-2173.mps +3331 -0
- data/ext/lpsolver-highs/check/instances/issue-2204.mps +143 -0
- data/ext/lpsolver-highs/check/instances/issue-2290.mps +158 -0
- data/ext/lpsolver-highs/check/instances/issue-2388.lp +76 -0
- data/ext/lpsolver-highs/check/instances/issue-2402.mps +435 -0
- data/ext/lpsolver-highs/check/instances/issue-2446.mps +9154 -0
- data/ext/lpsolver-highs/check/instances/issue-2585.lp +16 -0
- data/ext/lpsolver-highs/check/instances/issue-2874-3.mps +97 -0
- data/ext/lpsolver-highs/check/instances/klein1.mps +422 -0
- data/ext/lpsolver-highs/check/instances/lseu.mps +371 -0
- data/ext/lpsolver-highs/check/instances/model.xyz +1 -0
- data/ext/lpsolver-highs/check/instances/nan0.mps +13 -0
- data/ext/lpsolver-highs/check/instances/nan1.mps +13 -0
- data/ext/lpsolver-highs/check/instances/nan2.mps +13 -0
- data/ext/lpsolver-highs/check/instances/no-newline-eof.lp +5 -0
- data/ext/lpsolver-highs/check/instances/p01.mps +909 -0
- data/ext/lpsolver-highs/check/instances/p0548.mps +1992 -0
- data/ext/lpsolver-highs/check/instances/primal1.mps +3909 -0
- data/ext/lpsolver-highs/check/instances/qap04.mps +606 -0
- data/ext/lpsolver-highs/check/instances/qcqp.lp +8 -0
- data/ext/lpsolver-highs/check/instances/qjh.lp +9 -0
- data/ext/lpsolver-highs/check/instances/qjh.mps +18 -0
- data/ext/lpsolver-highs/check/instances/qjh_qmatrix.mps +19 -0
- data/ext/lpsolver-highs/check/instances/qjh_quadobj.mps +18 -0
- data/ext/lpsolver-highs/check/instances/qjh_quadobj_qmatrix.mps +25 -0
- data/ext/lpsolver-highs/check/instances/qjh_uncon.lp +10 -0
- data/ext/lpsolver-highs/check/instances/qjh_uncon.mps +17 -0
- data/ext/lpsolver-highs/check/instances/qpinfeasible.lp +8 -0
- data/ext/lpsolver-highs/check/instances/qptestnw.lp +7 -0
- data/ext/lpsolver-highs/check/instances/qpunbounded.lp +5 -0
- data/ext/lpsolver-highs/check/instances/refinery.mps +1882 -0
- data/ext/lpsolver-highs/check/instances/rgn.mps +559 -0
- data/ext/lpsolver-highs/check/instances/scrs8.mps +2717 -0
- data/ext/lpsolver-highs/check/instances/sctest.mps +66 -0
- data/ext/lpsolver-highs/check/instances/semi-continuous.lp +13 -0
- data/ext/lpsolver-highs/check/instances/semi-continuous.mps +24 -0
- data/ext/lpsolver-highs/check/instances/semi-integer.lp +15 -0
- data/ext/lpsolver-highs/check/instances/semi-integer.mps +22 -0
- data/ext/lpsolver-highs/check/instances/shell.mps +4039 -0
- data/ext/lpsolver-highs/check/instances/silly-names.mps +14 -0
- data/ext/lpsolver-highs/check/instances/small_mip.mps +87 -0
- data/ext/lpsolver-highs/check/instances/smalllp.mps +21 -0
- data/ext/lpsolver-highs/check/instances/sp150x300d.mps +1983 -0
- data/ext/lpsolver-highs/check/instances/stair.mps +2499 -0
- data/ext/lpsolver-highs/check/instances/standata.mps +2317 -0
- data/ext/lpsolver-highs/check/instances/standgub.mps +2428 -0
- data/ext/lpsolver-highs/check/instances/standmps.mps +2695 -0
- data/ext/lpsolver-highs/check/instances/test.mps +53 -0
- data/ext/lpsolver-highs/check/instances/vol1.mps +1895 -0
- data/ext/lpsolver-highs/check/instances/warnings.mps +68 -0
- data/ext/lpsolver-highs/check/instances/woodinfe.mps +216 -0
- data/ext/lpsolver-highs/check/matrix_multiplication.hpp +49 -0
- data/ext/lpsolver-highs/check/meson.build +92 -0
- data/ext/lpsolver-highs/check/pythontest.py +11 -0
- data/ext/lpsolver-highs/check/sample_options_file +8 -0
- data/ext/lpsolver-highs/cmake/CheckAtomic.cmake +74 -0
- data/ext/lpsolver-highs/cmake/FindCUDAConf.cmake +44 -0
- data/ext/lpsolver-highs/cmake/FindHipoDeps.cmake +351 -0
- data/ext/lpsolver-highs/cmake/README.md +243 -0
- data/ext/lpsolver-highs/cmake/cpp-highs.cmake +243 -0
- data/ext/lpsolver-highs/cmake/dotnet.cmake +94 -0
- data/ext/lpsolver-highs/cmake/highs-config.cmake.in +22 -0
- data/ext/lpsolver-highs/cmake/python-highs.cmake +74 -0
- data/ext/lpsolver-highs/cmake/set-version.cmake +26 -0
- data/ext/lpsolver-highs/cmake/sources-python.cmake +461 -0
- data/ext/lpsolver-highs/cmake/sources.cmake +618 -0
- data/ext/lpsolver-highs/docs/HiGHS_CopyrightHeader.pl +78 -0
- data/ext/lpsolver-highs/docs/HiGHS_CopyrightHeaderUpdateAll +32 -0
- data/ext/lpsolver-highs/docs/Project.toml +7 -0
- data/ext/lpsolver-highs/docs/README.md +27 -0
- data/ext/lpsolver-highs/docs/c_api_gen/HConfig.h +1 -0
- data/ext/lpsolver-highs/docs/c_api_gen/build.jl +48 -0
- data/ext/lpsolver-highs/docs/make.jl +115 -0
- data/ext/lpsolver-highs/docs/src/assets/logo.png +0 -0
- data/ext/lpsolver-highs/docs/src/callbacks.md +171 -0
- data/ext/lpsolver-highs/docs/src/executable.md +88 -0
- data/ext/lpsolver-highs/docs/src/guide/advanced.md +66 -0
- data/ext/lpsolver-highs/docs/src/guide/basic.md +116 -0
- data/ext/lpsolver-highs/docs/src/guide/further.md +193 -0
- data/ext/lpsolver-highs/docs/src/guide/gpu.md +58 -0
- data/ext/lpsolver-highs/docs/src/guide/index.md +18 -0
- data/ext/lpsolver-highs/docs/src/guide/kkt.md +219 -0
- data/ext/lpsolver-highs/docs/src/guide/numerics.md +55 -0
- data/ext/lpsolver-highs/docs/src/index.md +86 -0
- data/ext/lpsolver-highs/docs/src/installation.md +130 -0
- data/ext/lpsolver-highs/docs/src/interfaces/c_api.md +6 -0
- data/ext/lpsolver-highs/docs/src/interfaces/cpp/examples.md +1 -0
- data/ext/lpsolver-highs/docs/src/interfaces/cpp/index.md +29 -0
- data/ext/lpsolver-highs/docs/src/interfaces/cpp/library.md +107 -0
- data/ext/lpsolver-highs/docs/src/interfaces/csharp.md +55 -0
- data/ext/lpsolver-highs/docs/src/interfaces/fortran.md +11 -0
- data/ext/lpsolver-highs/docs/src/interfaces/julia/index.md +130 -0
- data/ext/lpsolver-highs/docs/src/interfaces/other.md +41 -0
- data/ext/lpsolver-highs/docs/src/interfaces/python/example-py.md +275 -0
- data/ext/lpsolver-highs/docs/src/interfaces/python/index.md +91 -0
- data/ext/lpsolver-highs/docs/src/interfaces/python/model-py.md +90 -0
- data/ext/lpsolver-highs/docs/src/options/definitions.md +529 -0
- data/ext/lpsolver-highs/docs/src/options/intro.md +46 -0
- data/ext/lpsolver-highs/docs/src/parallel.md +88 -0
- data/ext/lpsolver-highs/docs/src/solvers.md +168 -0
- data/ext/lpsolver-highs/docs/src/structures/classes/HighsHessian.md +9 -0
- data/ext/lpsolver-highs/docs/src/structures/classes/HighsIis.md +16 -0
- data/ext/lpsolver-highs/docs/src/structures/classes/HighsLp.md +19 -0
- data/ext/lpsolver-highs/docs/src/structures/classes/HighsModel.md +6 -0
- data/ext/lpsolver-highs/docs/src/structures/classes/HighsSparseMatrix.md +10 -0
- data/ext/lpsolver-highs/docs/src/structures/classes/index.md +11 -0
- data/ext/lpsolver-highs/docs/src/structures/enums.md +114 -0
- data/ext/lpsolver-highs/docs/src/structures/index.md +12 -0
- data/ext/lpsolver-highs/docs/src/structures/structs/HighsBasis.md +8 -0
- data/ext/lpsolver-highs/docs/src/structures/structs/HighsInfo.md +148 -0
- data/ext/lpsolver-highs/docs/src/structures/structs/HighsLinearObjective.md +11 -0
- data/ext/lpsolver-highs/docs/src/structures/structs/HighsSolution.md +10 -0
- data/ext/lpsolver-highs/docs/src/structures/structs/index.md +10 -0
- data/ext/lpsolver-highs/docs/src/terminology.md +163 -0
- data/ext/lpsolver-highs/examples/CMakeLists.txt +26 -0
- data/ext/lpsolver-highs/examples/Docs.py +104 -0
- data/ext/lpsolver-highs/examples/branch-and-price.py +465 -0
- data/ext/lpsolver-highs/examples/call_highs_from_c.c +685 -0
- data/ext/lpsolver-highs/examples/call_highs_from_c_minimal.c +659 -0
- data/ext/lpsolver-highs/examples/call_highs_from_cpp.cpp +178 -0
- data/ext/lpsolver-highs/examples/call_highs_from_csharp.cs +83 -0
- data/ext/lpsolver-highs/examples/call_highs_from_fortran.f90 +579 -0
- data/ext/lpsolver-highs/examples/call_highs_from_python.py +448 -0
- data/ext/lpsolver-highs/examples/call_highs_from_python_highspy.py +71 -0
- data/ext/lpsolver-highs/examples/call_highs_from_python_mps.py +59 -0
- data/ext/lpsolver-highs/examples/callback_gap.py +71 -0
- data/ext/lpsolver-highs/examples/chip.py +43 -0
- data/ext/lpsolver-highs/examples/chip0.py +29 -0
- data/ext/lpsolver-highs/examples/distillation.py +77 -0
- data/ext/lpsolver-highs/examples/knapsack.py +43 -0
- data/ext/lpsolver-highs/examples/minimal.py +11 -0
- data/ext/lpsolver-highs/examples/multi_objective.py +139 -0
- data/ext/lpsolver-highs/examples/multiple_objective.py +120 -0
- data/ext/lpsolver-highs/examples/network_flow.py +37 -0
- data/ext/lpsolver-highs/examples/nqueens.py +29 -0
- data/ext/lpsolver-highs/examples/plot_highs_log.py +134 -0
- data/ext/lpsolver-highs/extern/CLI11.hpp +11546 -0
- data/ext/lpsolver-highs/extern/LICENCE_1_0.txt +23 -0
- data/ext/lpsolver-highs/extern/amd/License.txt +35 -0
- data/ext/lpsolver-highs/extern/amd/SuiteSparse_config.c +54 -0
- data/ext/lpsolver-highs/extern/amd/SuiteSparse_config.h +56 -0
- data/ext/lpsolver-highs/extern/amd/amd.h +357 -0
- data/ext/lpsolver-highs/extern/amd/amd_1.c +172 -0
- data/ext/lpsolver-highs/extern/amd/amd_2.c +1761 -0
- data/ext/lpsolver-highs/extern/amd/amd_aat.c +179 -0
- data/ext/lpsolver-highs/extern/amd/amd_control.c +65 -0
- data/ext/lpsolver-highs/extern/amd/amd_defaults.c +37 -0
- data/ext/lpsolver-highs/extern/amd/amd_info.c +120 -0
- data/ext/lpsolver-highs/extern/amd/amd_internal.h +137 -0
- data/ext/lpsolver-highs/extern/amd/amd_order.c +195 -0
- data/ext/lpsolver-highs/extern/amd/amd_post_tree.c +105 -0
- data/ext/lpsolver-highs/extern/amd/amd_postorder.c +140 -0
- data/ext/lpsolver-highs/extern/amd/amd_preprocess.c +107 -0
- data/ext/lpsolver-highs/extern/amd/amd_valid.c +93 -0
- data/ext/lpsolver-highs/extern/amd/changes.txt +8 -0
- data/ext/lpsolver-highs/extern/catch.hpp +18861 -0
- data/ext/lpsolver-highs/extern/metis/Changes.txt +31 -0
- data/ext/lpsolver-highs/extern/metis/GKlib/GKlib.h +62 -0
- data/ext/lpsolver-highs/extern/metis/GKlib/error.c +21 -0
- data/ext/lpsolver-highs/extern/metis/GKlib/gk_arch.h +64 -0
- data/ext/lpsolver-highs/extern/metis/GKlib/gk_defs.h +19 -0
- data/ext/lpsolver-highs/extern/metis/GKlib/gk_macros.h +50 -0
- data/ext/lpsolver-highs/extern/metis/GKlib/gk_mkblas.h +51 -0
- data/ext/lpsolver-highs/extern/metis/GKlib/gk_mkmemory.h +80 -0
- data/ext/lpsolver-highs/extern/metis/GKlib/gk_mkpqueue.h +329 -0
- data/ext/lpsolver-highs/extern/metis/GKlib/gk_mkrandom.h +89 -0
- data/ext/lpsolver-highs/extern/metis/GKlib/gk_mksort.h +271 -0
- data/ext/lpsolver-highs/extern/metis/GKlib/gk_ms_inttypes.h +41 -0
- data/ext/lpsolver-highs/extern/metis/GKlib/gk_ms_stat.h +22 -0
- data/ext/lpsolver-highs/extern/metis/GKlib/gk_ms_stdint.h +41 -0
- data/ext/lpsolver-highs/extern/metis/GKlib/gk_proto.h +50 -0
- data/ext/lpsolver-highs/extern/metis/GKlib/gk_struct.h +66 -0
- data/ext/lpsolver-highs/extern/metis/GKlib/gk_types.h +15 -0
- data/ext/lpsolver-highs/extern/metis/GKlib/mcore.c +176 -0
- data/ext/lpsolver-highs/extern/metis/GKlib/memory.c +23 -0
- data/ext/lpsolver-highs/extern/metis/GKlib/random.c +37 -0
- data/ext/lpsolver-highs/extern/metis/LICENSE.txt +18 -0
- data/ext/lpsolver-highs/extern/metis/libmetis/auxapi.c +27 -0
- data/ext/lpsolver-highs/extern/metis/libmetis/balance.c +491 -0
- data/ext/lpsolver-highs/extern/metis/libmetis/bucketsort.c +44 -0
- data/ext/lpsolver-highs/extern/metis/libmetis/coarsen.c +895 -0
- data/ext/lpsolver-highs/extern/metis/libmetis/compress.c +231 -0
- data/ext/lpsolver-highs/extern/metis/libmetis/contig.c +83 -0
- data/ext/lpsolver-highs/extern/metis/libmetis/defs.h +39 -0
- data/ext/lpsolver-highs/extern/metis/libmetis/fm.c +527 -0
- data/ext/lpsolver-highs/extern/metis/libmetis/gklib.c +55 -0
- data/ext/lpsolver-highs/extern/metis/libmetis/gklib_defs.h +33 -0
- data/ext/lpsolver-highs/extern/metis/libmetis/graph.c +268 -0
- data/ext/lpsolver-highs/extern/metis/libmetis/initpart.c +385 -0
- data/ext/lpsolver-highs/extern/metis/libmetis/macros.h +59 -0
- data/ext/lpsolver-highs/extern/metis/libmetis/mcutil.c +162 -0
- data/ext/lpsolver-highs/extern/metis/libmetis/metislib.h +35 -0
- data/ext/lpsolver-highs/extern/metis/libmetis/mmd.c +598 -0
- data/ext/lpsolver-highs/extern/metis/libmetis/ometis.c +661 -0
- data/ext/lpsolver-highs/extern/metis/libmetis/options.c +260 -0
- data/ext/lpsolver-highs/extern/metis/libmetis/proto.h +172 -0
- data/ext/lpsolver-highs/extern/metis/libmetis/refine.c +99 -0
- data/ext/lpsolver-highs/extern/metis/libmetis/separator.c +57 -0
- data/ext/lpsolver-highs/extern/metis/libmetis/sfm.c +581 -0
- data/ext/lpsolver-highs/extern/metis/libmetis/srefine.c +152 -0
- data/ext/lpsolver-highs/extern/metis/libmetis/stdheaders.h +29 -0
- data/ext/lpsolver-highs/extern/metis/libmetis/struct.h +117 -0
- data/ext/lpsolver-highs/extern/metis/libmetis/util.c +59 -0
- data/ext/lpsolver-highs/extern/metis/libmetis/wspace.c +91 -0
- data/ext/lpsolver-highs/extern/metis/metis.h +271 -0
- data/ext/lpsolver-highs/extern/pdqsort/license.txt +16 -0
- data/ext/lpsolver-highs/extern/pdqsort/pdqsort.h +532 -0
- data/ext/lpsolver-highs/extern/rcm/LICENSE +19 -0
- data/ext/lpsolver-highs/extern/rcm/rcm.cpp +873 -0
- data/ext/lpsolver-highs/extern/rcm/rcm.h +22 -0
- data/ext/lpsolver-highs/extern/zstr/LICENSE +21 -0
- data/ext/lpsolver-highs/extern/zstr/strict_fstream.hpp +237 -0
- data/ext/lpsolver-highs/extern/zstr/zstr.hpp +473 -0
- data/ext/lpsolver-highs/flake.lock +61 -0
- data/ext/lpsolver-highs/flake.nix +73 -0
- data/ext/lpsolver-highs/highs/CMakeLists.txt +499 -0
- data/ext/lpsolver-highs/highs/HConfig.h.bazel.in +25 -0
- data/ext/lpsolver-highs/highs/HConfig.h.in +22 -0
- data/ext/lpsolver-highs/highs/HConfig.h.meson.in +17 -0
- data/ext/lpsolver-highs/highs/Highs.h +1812 -0
- data/ext/lpsolver-highs/highs/HighsRun.md +143 -0
- data/ext/lpsolver-highs/highs/highs_bindings.cpp +1826 -0
- data/ext/lpsolver-highs/highs/highspy/__init__.py +93 -0
- data/ext/lpsolver-highs/highs/highspy/__init__.pyi +91 -0
- data/ext/lpsolver-highs/highs/highspy/_core/__init__.pyi +1058 -0
- data/ext/lpsolver-highs/highs/highspy/_core/cb.pyi +118 -0
- data/ext/lpsolver-highs/highs/highspy/_core/simplex_constants.pyi +472 -0
- data/ext/lpsolver-highs/highs/highspy/highs.py +2430 -0
- data/ext/lpsolver-highs/highs/interfaces/highs_c_api.cpp +1812 -0
- data/ext/lpsolver-highs/highs/interfaces/highs_c_api.h +2651 -0
- data/ext/lpsolver-highs/highs/interfaces/highs_csharp_api.cs +1142 -0
- data/ext/lpsolver-highs/highs/interfaces/highs_fortran_api.f90 +873 -0
- data/ext/lpsolver-highs/highs/io/Filereader.cpp +87 -0
- data/ext/lpsolver-highs/highs/io/Filereader.h +45 -0
- data/ext/lpsolver-highs/highs/io/FilereaderLp.cpp +539 -0
- data/ext/lpsolver-highs/highs/io/FilereaderLp.h +49 -0
- data/ext/lpsolver-highs/highs/io/FilereaderMps.cpp +86 -0
- data/ext/lpsolver-highs/highs/io/FilereaderMps.h +27 -0
- data/ext/lpsolver-highs/highs/io/HMPSIO.cpp +1001 -0
- data/ext/lpsolver-highs/highs/io/HMPSIO.h +78 -0
- data/ext/lpsolver-highs/highs/io/HMpsFF.cpp +2113 -0
- data/ext/lpsolver-highs/highs/io/HMpsFF.h +245 -0
- data/ext/lpsolver-highs/highs/io/HighsIO.cpp +371 -0
- data/ext/lpsolver-highs/highs/io/HighsIO.h +118 -0
- data/ext/lpsolver-highs/highs/io/LoadOptions.cpp +60 -0
- data/ext/lpsolver-highs/highs/io/LoadOptions.h +24 -0
- data/ext/lpsolver-highs/highs/io/filereaderlp/LICENSE +19 -0
- data/ext/lpsolver-highs/highs/io/filereaderlp/builder.hpp +25 -0
- data/ext/lpsolver-highs/highs/io/filereaderlp/def.hpp +19 -0
- data/ext/lpsolver-highs/highs/io/filereaderlp/model.hpp +68 -0
- data/ext/lpsolver-highs/highs/io/filereaderlp/reader.cpp +1375 -0
- data/ext/lpsolver-highs/highs/io/filereaderlp/reader.hpp +10 -0
- data/ext/lpsolver-highs/highs/ipm/IpxSolution.h +32 -0
- data/ext/lpsolver-highs/highs/ipm/IpxWrapper.cpp +1526 -0
- data/ext/lpsolver-highs/highs/ipm/IpxWrapper.h +106 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu.h +161 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_factorize.c +132 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_factorize.h +247 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_get_factors.c +148 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_get_factors.h +108 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_initialize.c +24 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_initialize.h +119 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_obj_factorize.h +34 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_obj_free.h +19 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_obj_get_factors.h +34 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_obj_initialize.h +46 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_obj_solve_dense.h +29 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_obj_solve_for_update.h +42 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_obj_solve_sparse.h +32 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_obj_update.h +31 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_object.c +325 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_object.h +30 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_solve_dense.c +46 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_solve_dense.h +75 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_solve_for_update.c +79 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_solve_for_update.h +169 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_solve_sparse.c +63 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_solve_sparse.h +112 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_update.c +44 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/basiclu_update.h +125 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/lu_build_factors.c +441 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/lu_condest.c +124 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/lu_def.h +39 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/lu_dfs.c +141 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/lu_factorize_bump.c +56 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/lu_file.c +184 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/lu_file.h +21 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/lu_garbage_perm.c +53 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/lu_initialize.c +56 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/lu_internal.c +352 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/lu_internal.h +220 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/lu_list.h +173 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/lu_markowitz.c +188 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/lu_matrix_norm.c +51 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/lu_pivot.c +1247 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/lu_residual_test.c +155 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/lu_setup_bump.c +198 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/lu_singletons.c +511 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/lu_solve_dense.c +129 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/lu_solve_for_update.c +360 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/lu_solve_sparse.c +284 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/lu_solve_symbolic.c +48 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/lu_solve_triangular.c +140 -0
- data/ext/lpsolver-highs/highs/ipm/basiclu/lu_update.c +908 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/auxiliary/Auxiliary.cpp +301 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/auxiliary/Auxiliary.h +104 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/auxiliary/IntConfig.h +27 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/auxiliary/KrylovMethods.cpp +193 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/auxiliary/KrylovMethods.h +30 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/auxiliary/Log.cpp +60 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/auxiliary/Log.h +62 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/auxiliary/OrderingPrint.h +10 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/auxiliary/VectorOperations.cpp +117 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/auxiliary/VectorOperations.h +59 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/auxiliary/mycblas.h +85 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/Analyse.cpp +1367 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/Analyse.h +122 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/CallAndTimeBlas.cpp +114 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/CallAndTimeBlas.h +46 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/CliqueStack.cpp +82 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/CliqueStack.h +83 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/DataCollector.cpp +326 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/DataCollector.h +86 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/DenseFact.h +48 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/DenseFactHybrid.cpp +279 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/DenseFactKernel.cpp +284 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/DgemmParallel.cpp +38 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/DgemmParallel.h +32 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/FactorHiGHS.cpp +57 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/FactorHiGHS.h +112 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/FactorHiGHSSettings.h +63 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/Factorise.cpp +405 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/Factorise.h +85 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/FormatHandler.cpp +46 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/FormatHandler.h +95 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/HybridHybridFormatHandler.cpp +238 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/HybridHybridFormatHandler.h +31 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/HybridSolveHandler.cpp +272 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/HybridSolveHandler.h +26 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/KrylovMethodsIpm.cpp +83 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/KrylovMethodsIpm.h +45 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/Numeric.cpp +54 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/Numeric.h +46 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/ReturnValues.h +19 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/SolveHandler.cpp +10 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/SolveHandler.h +48 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/Swaps.cpp +70 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/Swaps.h +19 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/Symbolic.cpp +101 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/Symbolic.h +220 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/factorhighs/Timing.h +114 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/ipm/Control.cpp +38 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/ipm/Control.h +41 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/ipm/FactorHiGHSSolver.cpp +887 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/ipm/FactorHiGHSSolver.h +92 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/ipm/Info.h +58 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/ipm/IpmData.cpp +8 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/ipm/IpmData.h +37 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/ipm/Iterate.cpp +640 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/ipm/Iterate.h +172 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/ipm/LinearSolver.h +81 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/ipm/LogHighs.cpp +71 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/ipm/LogHighs.h +33 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/ipm/Model.cpp +403 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/ipm/Model.h +136 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/ipm/Options.h +35 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/ipm/Parameters.h +63 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/ipm/PreProcess.cpp +646 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/ipm/PreProcess.h +94 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/ipm/Refine.cpp +214 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/ipm/Solver.cpp +1346 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/ipm/Solver.h +338 -0
- data/ext/lpsolver-highs/highs/ipm/hipo/ipm/Status.h +88 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/basiclu_kernel.cc +71 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/basiclu_kernel.h +20 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/basiclu_wrapper.cc +299 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/basiclu_wrapper.h +47 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/basis.cc +966 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/basis.h +350 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/conjugate_residuals.cc +217 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/conjugate_residuals.h +74 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/control.cc +151 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/control.h +167 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/crossover.cc +479 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/crossover.h +157 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/diagonal_precond.cc +70 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/diagonal_precond.h +45 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/forrest_tomlin.cc +360 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/forrest_tomlin.h +102 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/guess_basis.cc +233 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/guess_basis.h +21 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/indexed_vector.cc +30 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/indexed_vector.h +113 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/info.cc +124 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/info.h +27 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/ipm.cc +897 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/ipm.h +94 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/ipx_c.cc +83 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/ipx_c.h +47 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/ipx_config.h +9 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/ipx_info.h +111 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/ipx_internal.h +89 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/ipx_parameters.h +76 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/ipx_status.h +57 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/iterate.cc +683 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/iterate.h +331 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/kkt_solver.cc +23 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/kkt_solver.h +70 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/kkt_solver_basis.cc +387 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/kkt_solver_basis.h +66 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/kkt_solver_diag.cc +120 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/kkt_solver_diag.h +48 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/linear_operator.cc +10 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/linear_operator.h +26 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/lp_solver.cc +686 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/lp_solver.h +204 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/lu_factorization.cc +131 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/lu_factorization.h +79 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/lu_update.cc +62 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/lu_update.h +129 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/maxvolume.cc +337 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/maxvolume.h +54 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/model.cc +1528 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/model.h +413 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/multistream.h +52 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/normal_matrix.cc +126 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/normal_matrix.h +44 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/power_method.h +44 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/sparse_matrix.cc +382 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/sparse_matrix.h +195 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/sparse_utils.cc +92 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/sparse_utils.h +58 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/splitted_normal_matrix.cc +117 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/splitted_normal_matrix.h +63 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/starting_basis.cc +182 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/starting_basis.h +39 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/symbolic_invert.cc +183 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/symbolic_invert.h +29 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/timer.cc +16 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/timer.h +25 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/utils.cc +95 -0
- data/ext/lpsolver-highs/highs/ipm/ipx/utils.h +37 -0
- data/ext/lpsolver-highs/highs/lp_data/HConst.h +430 -0
- data/ext/lpsolver-highs/highs/lp_data/HStruct.h +213 -0
- data/ext/lpsolver-highs/highs/lp_data/Highs.cpp +4949 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsAnalysis.h +23 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsCallback.cpp +323 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsCallback.h +104 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsCallbackStruct.h +70 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsDebug.cpp +54 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsDebug.h +34 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsDeprecated.cpp +181 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsIis.cpp +1290 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsIis.h +139 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsInfo.cpp +426 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsInfo.h +421 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsInfoDebug.cpp +175 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsInfoDebug.h +27 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsInterface.cpp +4344 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsLp.cpp +564 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsLp.h +97 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsLpSolverObject.h +47 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsLpUtils.cpp +3794 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsLpUtils.h +330 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsModelUtils.cpp +1650 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsModelUtils.h +129 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsOptions.cpp +1176 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsOptions.h +1715 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsRanging.cpp +733 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsRanging.h +43 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsSolution.cpp +2194 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsSolution.h +179 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsSolutionDebug.cpp +490 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsSolutionDebug.h +87 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsSolve.cpp +747 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsSolve.h +29 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsStatus.cpp +48 -0
- data/ext/lpsolver-highs/highs/lp_data/HighsStatus.h +29 -0
- data/ext/lpsolver-highs/highs/lp_data/Iis.md +113 -0
- data/ext/lpsolver-highs/highs/meson.build +433 -0
- data/ext/lpsolver-highs/highs/mip/HighsCliqueTable.cpp +2236 -0
- data/ext/lpsolver-highs/highs/mip/HighsCliqueTable.h +329 -0
- data/ext/lpsolver-highs/highs/mip/HighsConflictPool.cpp +201 -0
- data/ext/lpsolver-highs/highs/mip/HighsConflictPool.h +109 -0
- data/ext/lpsolver-highs/highs/mip/HighsCutGeneration.cpp +1491 -0
- data/ext/lpsolver-highs/highs/mip/HighsCutGeneration.h +108 -0
- data/ext/lpsolver-highs/highs/mip/HighsCutPool.cpp +526 -0
- data/ext/lpsolver-highs/highs/mip/HighsCutPool.h +168 -0
- data/ext/lpsolver-highs/highs/mip/HighsDebugSol.cpp +313 -0
- data/ext/lpsolver-highs/highs/mip/HighsDebugSol.h +133 -0
- data/ext/lpsolver-highs/highs/mip/HighsDomain.cpp +3861 -0
- data/ext/lpsolver-highs/highs/mip/HighsDomain.h +657 -0
- data/ext/lpsolver-highs/highs/mip/HighsDomainChange.h +48 -0
- data/ext/lpsolver-highs/highs/mip/HighsDynamicRowMatrix.cpp +199 -0
- data/ext/lpsolver-highs/highs/mip/HighsDynamicRowMatrix.h +104 -0
- data/ext/lpsolver-highs/highs/mip/HighsFeasibilityJump.cpp +139 -0
- data/ext/lpsolver-highs/highs/mip/HighsGFkSolve.cpp +106 -0
- data/ext/lpsolver-highs/highs/mip/HighsGFkSolve.h +439 -0
- data/ext/lpsolver-highs/highs/mip/HighsImplications.cpp +915 -0
- data/ext/lpsolver-highs/highs/mip/HighsImplications.h +194 -0
- data/ext/lpsolver-highs/highs/mip/HighsLpAggregator.cpp +56 -0
- data/ext/lpsolver-highs/highs/mip/HighsLpAggregator.h +50 -0
- data/ext/lpsolver-highs/highs/mip/HighsLpRelaxation.cpp +1609 -0
- data/ext/lpsolver-highs/highs/mip/HighsLpRelaxation.h +361 -0
- data/ext/lpsolver-highs/highs/mip/HighsMipAnalysis.cpp +313 -0
- data/ext/lpsolver-highs/highs/mip/HighsMipAnalysis.h +71 -0
- data/ext/lpsolver-highs/highs/mip/HighsMipSolver.cpp +1002 -0
- data/ext/lpsolver-highs/highs/mip/HighsMipSolver.h +159 -0
- data/ext/lpsolver-highs/highs/mip/HighsMipSolverData.cpp +2936 -0
- data/ext/lpsolver-highs/highs/mip/HighsMipSolverData.h +313 -0
- data/ext/lpsolver-highs/highs/mip/HighsModkSeparator.cpp +267 -0
- data/ext/lpsolver-highs/highs/mip/HighsModkSeparator.h +60 -0
- data/ext/lpsolver-highs/highs/mip/HighsNodeQueue.cpp +443 -0
- data/ext/lpsolver-highs/highs/mip/HighsNodeQueue.h +312 -0
- data/ext/lpsolver-highs/highs/mip/HighsObjectiveFunction.cpp +124 -0
- data/ext/lpsolver-highs/highs/mip/HighsObjectiveFunction.h +71 -0
- data/ext/lpsolver-highs/highs/mip/HighsPathSeparator.cpp +549 -0
- data/ext/lpsolver-highs/highs/mip/HighsPathSeparator.h +39 -0
- data/ext/lpsolver-highs/highs/mip/HighsPrimalHeuristics.cpp +1673 -0
- data/ext/lpsolver-highs/highs/mip/HighsPrimalHeuristics.h +75 -0
- data/ext/lpsolver-highs/highs/mip/HighsPseudocost.cpp +129 -0
- data/ext/lpsolver-highs/highs/mip/HighsPseudocost.h +366 -0
- data/ext/lpsolver-highs/highs/mip/HighsRedcostFixing.cpp +316 -0
- data/ext/lpsolver-highs/highs/mip/HighsRedcostFixing.h +42 -0
- data/ext/lpsolver-highs/highs/mip/HighsSearch.cpp +1881 -0
- data/ext/lpsolver-highs/highs/mip/HighsSearch.h +241 -0
- data/ext/lpsolver-highs/highs/mip/HighsSeparation.cpp +186 -0
- data/ext/lpsolver-highs/highs/mip/HighsSeparation.h +41 -0
- data/ext/lpsolver-highs/highs/mip/HighsSeparator.cpp +39 -0
- data/ext/lpsolver-highs/highs/mip/HighsSeparator.h +60 -0
- data/ext/lpsolver-highs/highs/mip/HighsTableauSeparator.cpp +244 -0
- data/ext/lpsolver-highs/highs/mip/HighsTableauSeparator.h +34 -0
- data/ext/lpsolver-highs/highs/mip/HighsTransformedLp.cpp +563 -0
- data/ext/lpsolver-highs/highs/mip/HighsTransformedLp.h +63 -0
- data/ext/lpsolver-highs/highs/mip/MipTimer.h +544 -0
- data/ext/lpsolver-highs/highs/mip/feasibilityjump.hh +800 -0
- data/ext/lpsolver-highs/highs/model/HighsHessian.cpp +263 -0
- data/ext/lpsolver-highs/highs/model/HighsHessian.h +54 -0
- data/ext/lpsolver-highs/highs/model/HighsHessianUtils.cpp +584 -0
- data/ext/lpsolver-highs/highs/model/HighsHessianUtils.h +47 -0
- data/ext/lpsolver-highs/highs/model/HighsModel.cpp +46 -0
- data/ext/lpsolver-highs/highs/model/HighsModel.h +42 -0
- data/ext/lpsolver-highs/highs/parallel/HighsBinarySemaphore.h +108 -0
- data/ext/lpsolver-highs/highs/parallel/HighsCacheAlign.h +82 -0
- data/ext/lpsolver-highs/highs/parallel/HighsCombinable.h +116 -0
- data/ext/lpsolver-highs/highs/parallel/HighsMutex.h +124 -0
- data/ext/lpsolver-highs/highs/parallel/HighsParallel.h +128 -0
- data/ext/lpsolver-highs/highs/parallel/HighsRaceTimer.h +38 -0
- data/ext/lpsolver-highs/highs/parallel/HighsSchedulerConstants.h +19 -0
- data/ext/lpsolver-highs/highs/parallel/HighsSpinMutex.h +48 -0
- data/ext/lpsolver-highs/highs/parallel/HighsSplitDeque.h +606 -0
- data/ext/lpsolver-highs/highs/parallel/HighsTask.h +170 -0
- data/ext/lpsolver-highs/highs/parallel/HighsTaskExecutor.cpp +43 -0
- data/ext/lpsolver-highs/highs/parallel/HighsTaskExecutor.h +217 -0
- data/ext/lpsolver-highs/highs/pdlp/CupdlpWrapper.cpp +848 -0
- data/ext/lpsolver-highs/highs/pdlp/CupdlpWrapper.h +108 -0
- data/ext/lpsolver-highs/highs/pdlp/HiPdlpTimer.h +155 -0
- data/ext/lpsolver-highs/highs/pdlp/HiPdlpWrapper.cpp +141 -0
- data/ext/lpsolver-highs/highs/pdlp/HiPdlpWrapper.h +26 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/Diff +12 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/Meld +7 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/Merge +2 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/README.md +95 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/cuda/CMakeLists.txt +58 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/cuda/cupdlp_cuda_kernels.cu +338 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/cuda/cupdlp_cuda_kernels.cuh +319 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/cuda/cupdlp_cudalinalg.cu +386 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/cuda/cupdlp_cudalinalg.cuh +149 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/cuda/test_cublas.c +154 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/cuda/test_cuda_linalg.c +79 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/cupdlp.h +16 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/cupdlp_cs.c +214 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/cupdlp_cs.h +40 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/cupdlp_defs.h +447 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/cupdlp_linalg.c +802 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/cupdlp_linalg.h +189 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/cupdlp_proj.c +148 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/cupdlp_proj.h +19 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/cupdlp_restart.c +124 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/cupdlp_restart.h +31 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/cupdlp_scaling.c +425 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/cupdlp_scaling.h +26 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/cupdlp_solver.c +1498 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/cupdlp_solver.h +105 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/cupdlp_step.c +478 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/cupdlp_step.h +37 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/cupdlp_utils.c +1850 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/cupdlp_utils.h +212 -0
- data/ext/lpsolver-highs/highs/pdlp/cupdlp/glbopts.h +342 -0
- data/ext/lpsolver-highs/highs/pdlp/hipdlp/defs.hpp +222 -0
- data/ext/lpsolver-highs/highs/pdlp/hipdlp/linalg.cc +231 -0
- data/ext/lpsolver-highs/highs/pdlp/hipdlp/linalg.hpp +61 -0
- data/ext/lpsolver-highs/highs/pdlp/hipdlp/logger.cc +225 -0
- data/ext/lpsolver-highs/highs/pdlp/hipdlp/logger.hpp +80 -0
- data/ext/lpsolver-highs/highs/pdlp/hipdlp/pdhg.cc +2798 -0
- data/ext/lpsolver-highs/highs/pdlp/hipdlp/pdhg.cu +497 -0
- data/ext/lpsolver-highs/highs/pdlp/hipdlp/pdhg.hpp +358 -0
- data/ext/lpsolver-highs/highs/pdlp/hipdlp/pdhg_kernels.hpp +77 -0
- data/ext/lpsolver-highs/highs/pdlp/hipdlp/pdlp_gpu_debug.hpp +62 -0
- data/ext/lpsolver-highs/highs/pdlp/hipdlp/restart.cc +132 -0
- data/ext/lpsolver-highs/highs/pdlp/hipdlp/restart.hpp +96 -0
- data/ext/lpsolver-highs/highs/pdlp/hipdlp/scaling.cc +307 -0
- data/ext/lpsolver-highs/highs/pdlp/hipdlp/scaling.hpp +74 -0
- data/ext/lpsolver-highs/highs/pdlp/hipdlp/solver_results.hpp +65 -0
- data/ext/lpsolver-highs/highs/presolve/HPresolve.cpp +8511 -0
- data/ext/lpsolver-highs/highs/presolve/HPresolve.h +505 -0
- data/ext/lpsolver-highs/highs/presolve/HPresolveAnalysis.cpp +239 -0
- data/ext/lpsolver-highs/highs/presolve/HPresolveAnalysis.h +52 -0
- data/ext/lpsolver-highs/highs/presolve/HighsPostsolveStack.cpp +1368 -0
- data/ext/lpsolver-highs/highs/presolve/HighsPostsolveStack.h +943 -0
- data/ext/lpsolver-highs/highs/presolve/HighsSymmetry.cpp +1921 -0
- data/ext/lpsolver-highs/highs/presolve/HighsSymmetry.h +284 -0
- data/ext/lpsolver-highs/highs/presolve/ICrash.cpp +474 -0
- data/ext/lpsolver-highs/highs/presolve/ICrash.h +124 -0
- data/ext/lpsolver-highs/highs/presolve/ICrashUtil.cpp +267 -0
- data/ext/lpsolver-highs/highs/presolve/ICrashUtil.h +62 -0
- data/ext/lpsolver-highs/highs/presolve/ICrashX.cpp +173 -0
- data/ext/lpsolver-highs/highs/presolve/ICrashX.h +23 -0
- data/ext/lpsolver-highs/highs/presolve/PresolveComponent.cpp +45 -0
- data/ext/lpsolver-highs/highs/presolve/PresolveComponent.h +90 -0
- data/ext/lpsolver-highs/highs/qpsolver/README.md +185 -0
- data/ext/lpsolver-highs/highs/qpsolver/a_asm.cpp +139 -0
- data/ext/lpsolver-highs/highs/qpsolver/a_asm.hpp +77 -0
- data/ext/lpsolver-highs/highs/qpsolver/a_quass.cpp +194 -0
- data/ext/lpsolver-highs/highs/qpsolver/a_quass.hpp +22 -0
- data/ext/lpsolver-highs/highs/qpsolver/basis.cpp +443 -0
- data/ext/lpsolver-highs/highs/qpsolver/basis.hpp +159 -0
- data/ext/lpsolver-highs/highs/qpsolver/crashsolution.hpp +20 -0
- data/ext/lpsolver-highs/highs/qpsolver/dantzigpricing.hpp +80 -0
- data/ext/lpsolver-highs/highs/qpsolver/devexharrispricing.hpp +98 -0
- data/ext/lpsolver-highs/highs/qpsolver/devexpricing.hpp +108 -0
- data/ext/lpsolver-highs/highs/qpsolver/eventhandler.hpp +30 -0
- data/ext/lpsolver-highs/highs/qpsolver/factor.hpp +408 -0
- data/ext/lpsolver-highs/highs/qpsolver/feasibility_bounded.hpp +114 -0
- data/ext/lpsolver-highs/highs/qpsolver/feasibility_highs.hpp +301 -0
- data/ext/lpsolver-highs/highs/qpsolver/gradient.hpp +46 -0
- data/ext/lpsolver-highs/highs/qpsolver/instance.hpp +70 -0
- data/ext/lpsolver-highs/highs/qpsolver/matrix.hpp +342 -0
- data/ext/lpsolver-highs/highs/qpsolver/perturbation.cpp +41 -0
- data/ext/lpsolver-highs/highs/qpsolver/perturbation.hpp +15 -0
- data/ext/lpsolver-highs/highs/qpsolver/pricing.hpp +22 -0
- data/ext/lpsolver-highs/highs/qpsolver/qpconst.hpp +34 -0
- data/ext/lpsolver-highs/highs/qpsolver/qpvector.hpp +242 -0
- data/ext/lpsolver-highs/highs/qpsolver/quass.cpp +551 -0
- data/ext/lpsolver-highs/highs/qpsolver/quass.hpp +27 -0
- data/ext/lpsolver-highs/highs/qpsolver/ratiotest.cpp +146 -0
- data/ext/lpsolver-highs/highs/qpsolver/ratiotest.hpp +26 -0
- data/ext/lpsolver-highs/highs/qpsolver/reducedcosts.hpp +46 -0
- data/ext/lpsolver-highs/highs/qpsolver/reducedgradient.hpp +95 -0
- data/ext/lpsolver-highs/highs/qpsolver/runtime.hpp +45 -0
- data/ext/lpsolver-highs/highs/qpsolver/scaling.cpp +123 -0
- data/ext/lpsolver-highs/highs/qpsolver/scaling.hpp +15 -0
- data/ext/lpsolver-highs/highs/qpsolver/settings.hpp +84 -0
- data/ext/lpsolver-highs/highs/qpsolver/snippets.hpp +36 -0
- data/ext/lpsolver-highs/highs/qpsolver/statistics.hpp +30 -0
- data/ext/lpsolver-highs/highs/qpsolver/steepestedgepricing.hpp +173 -0
- data/ext/lpsolver-highs/highs/simplex/HApp.h +550 -0
- data/ext/lpsolver-highs/highs/simplex/HEkk.cpp +4404 -0
- data/ext/lpsolver-highs/highs/simplex/HEkk.h +419 -0
- data/ext/lpsolver-highs/highs/simplex/HEkkControl.cpp +146 -0
- data/ext/lpsolver-highs/highs/simplex/HEkkDebug.cpp +1722 -0
- data/ext/lpsolver-highs/highs/simplex/HEkkDual.cpp +3003 -0
- data/ext/lpsolver-highs/highs/simplex/HEkkDual.h +513 -0
- data/ext/lpsolver-highs/highs/simplex/HEkkDualMulti.cpp +1020 -0
- data/ext/lpsolver-highs/highs/simplex/HEkkDualRHS.cpp +535 -0
- data/ext/lpsolver-highs/highs/simplex/HEkkDualRHS.h +134 -0
- data/ext/lpsolver-highs/highs/simplex/HEkkDualRow.cpp +697 -0
- data/ext/lpsolver-highs/highs/simplex/HEkkDualRow.h +201 -0
- data/ext/lpsolver-highs/highs/simplex/HEkkInterface.cpp +26 -0
- data/ext/lpsolver-highs/highs/simplex/HEkkPrimal.cpp +2984 -0
- data/ext/lpsolver-highs/highs/simplex/HEkkPrimal.h +191 -0
- data/ext/lpsolver-highs/highs/simplex/HSimplex.cpp +330 -0
- data/ext/lpsolver-highs/highs/simplex/HSimplex.h +42 -0
- data/ext/lpsolver-highs/highs/simplex/HSimplexDebug.cpp +145 -0
- data/ext/lpsolver-highs/highs/simplex/HSimplexDebug.h +48 -0
- data/ext/lpsolver-highs/highs/simplex/HSimplexNla.cpp +517 -0
- data/ext/lpsolver-highs/highs/simplex/HSimplexNla.h +158 -0
- data/ext/lpsolver-highs/highs/simplex/HSimplexNlaDebug.cpp +373 -0
- data/ext/lpsolver-highs/highs/simplex/HSimplexNlaFreeze.cpp +28 -0
- data/ext/lpsolver-highs/highs/simplex/HSimplexNlaProductForm.cpp +113 -0
- data/ext/lpsolver-highs/highs/simplex/HSimplexReport.cpp +77 -0
- data/ext/lpsolver-highs/highs/simplex/HSimplexReport.h +21 -0
- data/ext/lpsolver-highs/highs/simplex/HighsSimplexAnalysis.cpp +1495 -0
- data/ext/lpsolver-highs/highs/simplex/HighsSimplexAnalysis.h +500 -0
- data/ext/lpsolver-highs/highs/simplex/SimplexConst.h +273 -0
- data/ext/lpsolver-highs/highs/simplex/SimplexStruct.h +263 -0
- data/ext/lpsolver-highs/highs/simplex/SimplexTimer.h +414 -0
- data/ext/lpsolver-highs/highs/test_kkt/DevKkt.cpp +469 -0
- data/ext/lpsolver-highs/highs/test_kkt/DevKkt.h +143 -0
- data/ext/lpsolver-highs/highs/test_kkt/KktCh2.cpp +305 -0
- data/ext/lpsolver-highs/highs/test_kkt/KktCh2.h +79 -0
- data/ext/lpsolver-highs/highs/util/FactorTimer.h +199 -0
- data/ext/lpsolver-highs/highs/util/HFactor.cpp +2597 -0
- data/ext/lpsolver-highs/highs/util/HFactor.h +587 -0
- data/ext/lpsolver-highs/highs/util/HFactorConst.h +81 -0
- data/ext/lpsolver-highs/highs/util/HFactorDebug.cpp +231 -0
- data/ext/lpsolver-highs/highs/util/HFactorDebug.h +55 -0
- data/ext/lpsolver-highs/highs/util/HFactorExtend.cpp +229 -0
- data/ext/lpsolver-highs/highs/util/HFactorRefactor.cpp +304 -0
- data/ext/lpsolver-highs/highs/util/HFactorUtils.cpp +122 -0
- data/ext/lpsolver-highs/highs/util/HSet.cpp +197 -0
- data/ext/lpsolver-highs/highs/util/HSet.h +89 -0
- data/ext/lpsolver-highs/highs/util/HVector.h +22 -0
- data/ext/lpsolver-highs/highs/util/HVectorBase.cpp +271 -0
- data/ext/lpsolver-highs/highs/util/HVectorBase.h +102 -0
- data/ext/lpsolver-highs/highs/util/HighsCDouble.h +323 -0
- data/ext/lpsolver-highs/highs/util/HighsComponent.h +53 -0
- data/ext/lpsolver-highs/highs/util/HighsDataStack.h +83 -0
- data/ext/lpsolver-highs/highs/util/HighsDisjointSets.h +107 -0
- data/ext/lpsolver-highs/highs/util/HighsHash.cpp +10 -0
- data/ext/lpsolver-highs/highs/util/HighsHash.h +1274 -0
- data/ext/lpsolver-highs/highs/util/HighsHashTree.h +1461 -0
- data/ext/lpsolver-highs/highs/util/HighsInt.h +36 -0
- data/ext/lpsolver-highs/highs/util/HighsIntegers.h +212 -0
- data/ext/lpsolver-highs/highs/util/HighsLinearSumBounds.cpp +267 -0
- data/ext/lpsolver-highs/highs/util/HighsLinearSumBounds.h +203 -0
- data/ext/lpsolver-highs/highs/util/HighsMatrixPic.cpp +146 -0
- data/ext/lpsolver-highs/highs/util/HighsMatrixPic.h +37 -0
- data/ext/lpsolver-highs/highs/util/HighsMatrixSlice.h +561 -0
- data/ext/lpsolver-highs/highs/util/HighsMatrixUtils.cpp +407 -0
- data/ext/lpsolver-highs/highs/util/HighsMatrixUtils.h +57 -0
- data/ext/lpsolver-highs/highs/util/HighsMemoryAllocation.h +63 -0
- data/ext/lpsolver-highs/highs/util/HighsRandom.h +242 -0
- data/ext/lpsolver-highs/highs/util/HighsRbTree.h +452 -0
- data/ext/lpsolver-highs/highs/util/HighsSort.cpp +364 -0
- data/ext/lpsolver-highs/highs/util/HighsSort.h +131 -0
- data/ext/lpsolver-highs/highs/util/HighsSparseMatrix.cpp +1746 -0
- data/ext/lpsolver-highs/highs/util/HighsSparseMatrix.h +151 -0
- data/ext/lpsolver-highs/highs/util/HighsSparseVectorSum.h +95 -0
- data/ext/lpsolver-highs/highs/util/HighsSplay.h +135 -0
- data/ext/lpsolver-highs/highs/util/HighsTimer.h +385 -0
- data/ext/lpsolver-highs/highs/util/HighsUtils.cpp +1259 -0
- data/ext/lpsolver-highs/highs/util/HighsUtils.h +272 -0
- data/ext/lpsolver-highs/highs/util/stringutil.cpp +131 -0
- data/ext/lpsolver-highs/highs/util/stringutil.h +46 -0
- data/ext/lpsolver-highs/highs.pc.in +12 -0
- data/ext/lpsolver-highs/meson.build +198 -0
- data/ext/lpsolver-highs/meson_options.txt +31 -0
- data/ext/lpsolver-highs/nuget/HiGHS_Logo.png +0 -0
- data/ext/lpsolver-highs/nuget/Highs.csproj +25 -0
- data/ext/lpsolver-highs/nuget/Highs.csproj.in +36 -0
- data/ext/lpsolver-highs/nuget/HowToAlternative.md +77 -0
- data/ext/lpsolver-highs/nuget/README.md +38 -0
- data/ext/lpsolver-highs/nuget/arm-toolchain.cmake +15 -0
- data/ext/lpsolver-highs/nuget/build_linux-arm.sh +13 -0
- data/ext/lpsolver-highs/nuget/build_linux.sh +10 -0
- data/ext/lpsolver-highs/nuget/build_windows.ps1 +27 -0
- data/ext/lpsolver-highs/nuget/generatePackage.ps1 +28 -0
- data/ext/lpsolver-highs/pyproject.toml +221 -0
- data/ext/lpsolver-highs/subprojects/pybind11.wrap +13 -0
- data/ext/lpsolver-highs/tests/test_highspy.py +2310 -0
- data/ext/lpsolver-highs/version.rc.in +50 -0
- data/lib/lpsolver/highs +0 -0
- data/lib/lpsolver/model.rb +28 -4
- data/lib/lpsolver/native.so +0 -0
- data/lib/lpsolver/native_model.rb +261 -0
- data/lib/lpsolver/solution.rb +72 -7
- data/lib/lpsolver/version.rb +1 -1
- data/lpsolver.gemspec +4 -1
- metadata +1176 -4
|
@@ -0,0 +1,2430 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
import sys
|
|
3
|
+
import numpy as np
|
|
4
|
+
from numbers import Integral
|
|
5
|
+
from itertools import product
|
|
6
|
+
from threading import Thread, local, RLock, Lock
|
|
7
|
+
from typing import Optional, Any, overload, Callable, Sequence, Mapping, Iterable, SupportsIndex, cast, Union, Tuple
|
|
8
|
+
from weakref import proxy
|
|
9
|
+
|
|
10
|
+
from ._core import (
|
|
11
|
+
ObjSense,
|
|
12
|
+
HighsVarType,
|
|
13
|
+
HighsStatus,
|
|
14
|
+
HighsLinearObjective,
|
|
15
|
+
cb, # type: ignore
|
|
16
|
+
_Highs, # type: ignore
|
|
17
|
+
kHighsInf,
|
|
18
|
+
kHighsUndefined
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
# backwards typing support information for HighspyArray
|
|
22
|
+
np_version = tuple(map(int, np.__version__.split('.')))
|
|
23
|
+
if sys.version_info >= (3, 9) and np_version >= (1,22,0):
|
|
24
|
+
ndarray_object_type = np.ndarray[Any, np.dtype[np.object_]]
|
|
25
|
+
else:
|
|
26
|
+
ndarray_object_type = np.ndarray
|
|
27
|
+
|
|
28
|
+
class Highs(_Highs):
|
|
29
|
+
"""
|
|
30
|
+
HiGHS solver interface
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
__handle_keyboard_interrupt: bool = False
|
|
34
|
+
__handle_user_interrupt: bool = False
|
|
35
|
+
__solver_should_stop: bool = False
|
|
36
|
+
__solver_stopped: RLock = RLock()
|
|
37
|
+
__solver_started: Lock = Lock()
|
|
38
|
+
__solver_status: Optional[HighsStatus] = None
|
|
39
|
+
|
|
40
|
+
def __init__(self):
|
|
41
|
+
super().__init__()
|
|
42
|
+
self.callbacks = [HighsCallback(cb.HighsCallbackType(_), self) for _ in range(int(cb.HighsCallbackType.kCallbackMax) + 1)]
|
|
43
|
+
self.enableCallbacks()
|
|
44
|
+
|
|
45
|
+
# Silence logging
|
|
46
|
+
def silent(self, turn_off_output: bool = True):
|
|
47
|
+
"""
|
|
48
|
+
Disables solver output to the console.
|
|
49
|
+
"""
|
|
50
|
+
super().setOptionValue("output_flag", not turn_off_output)
|
|
51
|
+
|
|
52
|
+
# solve
|
|
53
|
+
def solve(self):
|
|
54
|
+
"""Runs the solver on the current problem.
|
|
55
|
+
|
|
56
|
+
Returns:
|
|
57
|
+
A HighsStatus object containing the solve status.
|
|
58
|
+
"""
|
|
59
|
+
if not self.HandleKeyboardInterrupt:
|
|
60
|
+
return super().run()
|
|
61
|
+
else:
|
|
62
|
+
return self.joinSolve(self.startSolve())
|
|
63
|
+
|
|
64
|
+
def startSolve(self):
|
|
65
|
+
"""
|
|
66
|
+
Starts the solver in a separate thread. Useful for handling KeyboardInterrupts.
|
|
67
|
+
Do not attempt to modify the model while the solver is running.
|
|
68
|
+
|
|
69
|
+
Returns:
|
|
70
|
+
A Thread object representing the solver thread.
|
|
71
|
+
"""
|
|
72
|
+
if not self.is_solver_running():
|
|
73
|
+
self.__solver_started.acquire()
|
|
74
|
+
self.__solver_should_stop = False
|
|
75
|
+
self.__solver_status = None
|
|
76
|
+
|
|
77
|
+
t = Thread(target=Highs.__solve, args=(self,), daemon=True)
|
|
78
|
+
t.start()
|
|
79
|
+
|
|
80
|
+
# wait for solver thread to start to avoid synchronization issues
|
|
81
|
+
try:
|
|
82
|
+
self.__solver_started.acquire(True)
|
|
83
|
+
finally:
|
|
84
|
+
self.__solver_started.release()
|
|
85
|
+
return t
|
|
86
|
+
else:
|
|
87
|
+
raise Exception("Solver is already running.")
|
|
88
|
+
|
|
89
|
+
def is_solver_running(self):
|
|
90
|
+
is_running = True
|
|
91
|
+
try:
|
|
92
|
+
# try to acquire lock, if we can't, solver is already running
|
|
93
|
+
is_running = not self.__solver_stopped.acquire(False)
|
|
94
|
+
return is_running
|
|
95
|
+
finally:
|
|
96
|
+
if not is_running:
|
|
97
|
+
self.__solver_stopped.release()
|
|
98
|
+
|
|
99
|
+
# internal solve method for use with threads
|
|
100
|
+
# will set the status of the solver when finished and release the shared lock
|
|
101
|
+
def __solve(self):
|
|
102
|
+
try:
|
|
103
|
+
self.__solver_stopped.acquire(True)
|
|
104
|
+
self.__solver_started.release() # allow main thread to continue
|
|
105
|
+
self.__solver_status = super().run()
|
|
106
|
+
|
|
107
|
+
# avoid potential deadlock in Windows
|
|
108
|
+
# can remove once HiGHS is updated to handle this internally
|
|
109
|
+
_Highs.resetGlobalScheduler(False)
|
|
110
|
+
finally:
|
|
111
|
+
self.__solver_stopped.release()
|
|
112
|
+
|
|
113
|
+
def joinSolve(self, solver_thread: Optional[Thread] = None, interrupt_limit: int = 5):
|
|
114
|
+
"""
|
|
115
|
+
Waits for the solver to finish. If solver_thread is provided, it will handle KeyboardInterrupts.
|
|
116
|
+
|
|
117
|
+
Args:
|
|
118
|
+
solver_thread: A Thread object representing the solver thread (optional).
|
|
119
|
+
interrupt_limit: The number of times to allow KeyboardInterrupt before forcing termination (optional).
|
|
120
|
+
|
|
121
|
+
Returns:
|
|
122
|
+
A HighsStatus object containing the solve status.
|
|
123
|
+
"""
|
|
124
|
+
if solver_thread is not None and interrupt_limit <= 0:
|
|
125
|
+
result = (False, None)
|
|
126
|
+
|
|
127
|
+
try:
|
|
128
|
+
while not result[0]:
|
|
129
|
+
result = self.wait(0.1)
|
|
130
|
+
return result[1]
|
|
131
|
+
|
|
132
|
+
except KeyboardInterrupt:
|
|
133
|
+
print("KeyboardInterrupt: Waiting for HiGHS to finish...")
|
|
134
|
+
self.cancelSolve()
|
|
135
|
+
|
|
136
|
+
elif interrupt_limit > 0:
|
|
137
|
+
result = (False, None)
|
|
138
|
+
|
|
139
|
+
for count in range(interrupt_limit):
|
|
140
|
+
try:
|
|
141
|
+
while not result[0]:
|
|
142
|
+
result = self.wait(0.1)
|
|
143
|
+
return result[1]
|
|
144
|
+
|
|
145
|
+
except KeyboardInterrupt:
|
|
146
|
+
print(f"Ctrl-C pressed {count+1} times: Waiting for HiGHS to finish. ({interrupt_limit} times to force termination)")
|
|
147
|
+
self.cancelSolve()
|
|
148
|
+
|
|
149
|
+
# if we reach this point, we should force termination
|
|
150
|
+
print("Forcing termination...")
|
|
151
|
+
exit(1)
|
|
152
|
+
|
|
153
|
+
try:
|
|
154
|
+
# wait for shared lock, i.e., solver to finish
|
|
155
|
+
self.__solver_stopped.acquire(True)
|
|
156
|
+
except KeyboardInterrupt:
|
|
157
|
+
pass # ignore additional KeyboardInterrupt here
|
|
158
|
+
finally:
|
|
159
|
+
self.__solver_stopped.release()
|
|
160
|
+
|
|
161
|
+
return self.__solver_status
|
|
162
|
+
|
|
163
|
+
def wait(self, timeout: float = -1.0):
|
|
164
|
+
result = False, None
|
|
165
|
+
|
|
166
|
+
try:
|
|
167
|
+
result = (
|
|
168
|
+
self.__solver_stopped.acquire(True, timeout=timeout),
|
|
169
|
+
self.__solver_status,
|
|
170
|
+
)
|
|
171
|
+
return result
|
|
172
|
+
finally:
|
|
173
|
+
if result[0]:
|
|
174
|
+
self.__solver_status = None # reset status
|
|
175
|
+
self.__solver_stopped.release()
|
|
176
|
+
|
|
177
|
+
def optimize(self):
|
|
178
|
+
"""
|
|
179
|
+
Alias for the solve method.
|
|
180
|
+
"""
|
|
181
|
+
return self.solve()
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def getObjective(self) -> Tuple[highs_linear_expression, ObjSense]:
|
|
185
|
+
"""
|
|
186
|
+
Retrieves the current objective function (as a linear expression) and sense.
|
|
187
|
+
"""
|
|
188
|
+
lp = super().getLp()
|
|
189
|
+
assert(isinstance(lp.col_cost_, np.ndarray))
|
|
190
|
+
nonzero_idxs = np.nonzero(lp.col_cost_)
|
|
191
|
+
|
|
192
|
+
objective = highs_linear_expression()
|
|
193
|
+
objective.idxs = nonzero_idxs[0].tolist()
|
|
194
|
+
objective.vals = lp.col_cost_[nonzero_idxs].tolist()
|
|
195
|
+
objective.constant = lp.offset_
|
|
196
|
+
|
|
197
|
+
return objective, super().getObjectiveSense()[1]
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
# reset the objective
|
|
201
|
+
def setObjective(self, obj: Optional[Union[highs_var, highs_linear_expression]] = None, sense: Optional[ObjSense] = None):
|
|
202
|
+
"""
|
|
203
|
+
Updates the costs.
|
|
204
|
+
|
|
205
|
+
Args:
|
|
206
|
+
obj: An optional highs_linear_expression representing the new objective function.
|
|
207
|
+
sense: An optional ObjSense value representing the new objective sense.
|
|
208
|
+
|
|
209
|
+
Raises:
|
|
210
|
+
Exception: If obj is an inequality or not a highs_linear_expression.
|
|
211
|
+
"""
|
|
212
|
+
if obj is not None:
|
|
213
|
+
# if we have a single variable, wrap it in a linear expression
|
|
214
|
+
expr = highs_linear_expression(obj) if isinstance(obj, highs_var) else obj
|
|
215
|
+
|
|
216
|
+
if expr.bounds is not None:
|
|
217
|
+
raise Exception("Objective cannot be an inequality")
|
|
218
|
+
|
|
219
|
+
# reset objective
|
|
220
|
+
super().changeColsCost(
|
|
221
|
+
self.numVariables,
|
|
222
|
+
np.arange(self.numVariables, dtype=np.int32),
|
|
223
|
+
np.full(self.numVariables, 0, dtype=np.float64),
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
# if we have duplicate variables, add the vals
|
|
227
|
+
idxs, vals = expr.unique_elements()
|
|
228
|
+
super().changeColsCost(len(idxs), idxs, vals)
|
|
229
|
+
super().changeObjectiveOffset(expr.constant or 0.0)
|
|
230
|
+
|
|
231
|
+
if sense is not None:
|
|
232
|
+
super().changeObjectiveSense(sense)
|
|
233
|
+
|
|
234
|
+
# reset the objective and sense, then solve
|
|
235
|
+
def minimize(self, obj: Optional[Union[highs_var, highs_linear_expression]] = None):
|
|
236
|
+
"""
|
|
237
|
+
Solves a minimization of the objective and optionally updates the costs.
|
|
238
|
+
|
|
239
|
+
Args:
|
|
240
|
+
obj: An optional highs_linear_expression representing the new objective function.
|
|
241
|
+
|
|
242
|
+
Raises:
|
|
243
|
+
Exception: If obj is an inequality or not a highs_linear_expression.
|
|
244
|
+
|
|
245
|
+
Returns:
|
|
246
|
+
A HighsStatus object containing the solve status after minimization.
|
|
247
|
+
"""
|
|
248
|
+
self.setObjective(obj, ObjSense.kMinimize)
|
|
249
|
+
return self.solve()
|
|
250
|
+
|
|
251
|
+
# reset the objective and sense, then solve
|
|
252
|
+
def maximize(self, obj: Optional[Union[highs_var, highs_linear_expression]] = None):
|
|
253
|
+
"""
|
|
254
|
+
Solves a maximization of the objective and optionally updates the costs.
|
|
255
|
+
|
|
256
|
+
Args:
|
|
257
|
+
obj: An optional highs_linear_expression representing the new objective function.
|
|
258
|
+
|
|
259
|
+
Raises:
|
|
260
|
+
Exception: If obj is an inequality or not a highs_linear_expression.
|
|
261
|
+
|
|
262
|
+
Returns:
|
|
263
|
+
A HighsStatus object containing the solve status after maximization.
|
|
264
|
+
"""
|
|
265
|
+
self.setObjective(obj, ObjSense.kMaximize)
|
|
266
|
+
return self.solve()
|
|
267
|
+
|
|
268
|
+
@staticmethod
|
|
269
|
+
def internal_get_value(
|
|
270
|
+
array_values: Union[Sequence[float], np.ndarray[Any, np.dtype[np.float64]]],
|
|
271
|
+
index_collection: Union[
|
|
272
|
+
Integral, highs_var, highs_cons, highs_linear_expression, Mapping[Any, Any], Sequence[Any], np.ndarray[Any, np.dtype[Any]]
|
|
273
|
+
],
|
|
274
|
+
) -> Union[float, bool, Mapping[Any, Any], np.ndarray[Any, np.dtype[np.float64]]]:
|
|
275
|
+
"""
|
|
276
|
+
Internal method to get the value of an index from an array of values. Could be value or dual, variable or constraint.
|
|
277
|
+
"""
|
|
278
|
+
if isinstance(index_collection, (Integral, highs_var, highs_cons)):
|
|
279
|
+
return array_values[int(index_collection)]
|
|
280
|
+
|
|
281
|
+
elif isinstance(index_collection, highs_linear_expression):
|
|
282
|
+
return index_collection.evaluate(array_values)
|
|
283
|
+
|
|
284
|
+
elif isinstance(index_collection, Mapping):
|
|
285
|
+
return {k: Highs.internal_get_value(array_values, v) for k, v in index_collection.items()}
|
|
286
|
+
|
|
287
|
+
else:
|
|
288
|
+
return np.asarray([Highs.internal_get_value(array_values, v) for v in index_collection])
|
|
289
|
+
|
|
290
|
+
@overload
|
|
291
|
+
def val(self, var: Union[Integral, highs_var, highs_cons]) -> float: ...
|
|
292
|
+
|
|
293
|
+
@overload
|
|
294
|
+
def val(self, var: highs_linear_expression) -> Union[float, bool]: ...
|
|
295
|
+
|
|
296
|
+
@overload
|
|
297
|
+
def val(self, var: Mapping[Any, Any]) -> Mapping[Any, Any]: ...
|
|
298
|
+
|
|
299
|
+
@overload
|
|
300
|
+
def val(self, var: Union[Sequence[Any], np.ndarray[Any, np.dtype[Any]]]) -> np.ndarray[Any, np.dtype[np.float64]]: ...
|
|
301
|
+
|
|
302
|
+
def val(
|
|
303
|
+
self,
|
|
304
|
+
var: Union[Integral, highs_var, highs_cons, highs_linear_expression, Mapping[Any, Any], Sequence[Any], np.ndarray[Any, np.dtype[Any]]],
|
|
305
|
+
):
|
|
306
|
+
"""
|
|
307
|
+
Gets the value of a variable/index or expression in the solution.
|
|
308
|
+
|
|
309
|
+
Args:
|
|
310
|
+
var: A highs_var/index or highs_linear_expression object representing the variable.
|
|
311
|
+
|
|
312
|
+
Returns:
|
|
313
|
+
The value of the variable in the solution.
|
|
314
|
+
"""
|
|
315
|
+
return Highs.internal_get_value(super().getSolution().col_value, var)
|
|
316
|
+
|
|
317
|
+
@overload
|
|
318
|
+
def vals(self, idxs: Union[Integral, highs_var, highs_cons]) -> float: ...
|
|
319
|
+
|
|
320
|
+
@overload
|
|
321
|
+
def vals(self, idxs: highs_linear_expression) -> Union[float, bool]: ...
|
|
322
|
+
|
|
323
|
+
@overload
|
|
324
|
+
def vals(self, idxs: Mapping[Any, Any]) -> Mapping[Any, Any]: ...
|
|
325
|
+
|
|
326
|
+
@overload
|
|
327
|
+
def vals(self, idxs: Union[Sequence[Any], np.ndarray[Any, np.dtype[Any]]]) -> np.ndarray[Any, np.dtype[np.float64]]: ...
|
|
328
|
+
|
|
329
|
+
def vals(
|
|
330
|
+
self,
|
|
331
|
+
idxs: Union[Integral, highs_var, highs_cons, highs_linear_expression, Mapping[Any, Any], Sequence[Any], np.ndarray[Any, np.dtype[Any]]],
|
|
332
|
+
):
|
|
333
|
+
"""
|
|
334
|
+
Gets the values of multiple variables in the solution.
|
|
335
|
+
|
|
336
|
+
Args:
|
|
337
|
+
idxs: A collection of highs_var objects representing the variables. Can be a Mapping (e.g., dict) where keys are variable names and values are highs_var objects, or an iterable of highs_var objects.
|
|
338
|
+
|
|
339
|
+
Returns:
|
|
340
|
+
If idxs is a Mapping, returns a dict where keys are the same keys from the input idxs and values are the solution values of the corresponding variables. If idxs is an iterable, returns a list of solution values for the variables.
|
|
341
|
+
"""
|
|
342
|
+
return Highs.internal_get_value(super().getSolution().col_value, idxs)
|
|
343
|
+
|
|
344
|
+
def variableName(self, var: Union[Integral, highs_var]):
|
|
345
|
+
"""
|
|
346
|
+
Retrieves the name of a specific variable.
|
|
347
|
+
|
|
348
|
+
Args:
|
|
349
|
+
var: A highs_var object representing the variable.
|
|
350
|
+
|
|
351
|
+
Raises:
|
|
352
|
+
Exception: If the variable name cannot be found.
|
|
353
|
+
|
|
354
|
+
Returns:
|
|
355
|
+
The name of the specified variable.
|
|
356
|
+
"""
|
|
357
|
+
[status, name] = super().getColName(int(var))
|
|
358
|
+
failed = status != HighsStatus.kOk
|
|
359
|
+
if failed:
|
|
360
|
+
raise Exception("Variable name not found")
|
|
361
|
+
return name
|
|
362
|
+
|
|
363
|
+
@overload
|
|
364
|
+
def variableNames(self, idxs: Mapping[Any, Union[highs_var, Integral]]) -> dict[Any, str]: ...
|
|
365
|
+
|
|
366
|
+
@overload
|
|
367
|
+
def variableNames(self, idxs: Iterable[Union[highs_var, Integral]]) -> list[str]: ...
|
|
368
|
+
|
|
369
|
+
def variableNames(self, idxs: Iterable[Union[highs_var, Integral]]):
|
|
370
|
+
"""
|
|
371
|
+
Retrieves the names of multiple variables.
|
|
372
|
+
|
|
373
|
+
Args:
|
|
374
|
+
idxs: An iterable of highs_var objects or a mapping where keys are identifiers and values are highs_var objects.
|
|
375
|
+
|
|
376
|
+
Raises:
|
|
377
|
+
Exception: If any variable name cannot be found.
|
|
378
|
+
|
|
379
|
+
Returns:
|
|
380
|
+
If idxs is a mapping, returns a dict where keys are the same keys from the input idxs and values are the names of the corresponding variables.
|
|
381
|
+
If idxs is an iterable, returns a list of names for the specified variables.
|
|
382
|
+
"""
|
|
383
|
+
if isinstance(idxs, Mapping):
|
|
384
|
+
convert: Mapping[Any, Union[highs_var, Integral]] = idxs
|
|
385
|
+
return {key: self.variableName(v) for key, v in convert.items()}
|
|
386
|
+
else:
|
|
387
|
+
return [self.variableName(v) for v in idxs]
|
|
388
|
+
|
|
389
|
+
def allVariableNames(self) -> list[str]:
|
|
390
|
+
"""
|
|
391
|
+
Retrieves the names of all variables in the model.
|
|
392
|
+
|
|
393
|
+
Returns:
|
|
394
|
+
A list of strings representing the names of all variables.
|
|
395
|
+
"""
|
|
396
|
+
return super().getLp().col_names_
|
|
397
|
+
|
|
398
|
+
def variableValue(
|
|
399
|
+
self,
|
|
400
|
+
var: Union[Integral, highs_var, highs_cons, highs_linear_expression, Mapping[Any, Any], np.ndarray[Any, np.dtype[Any]]],
|
|
401
|
+
):
|
|
402
|
+
"""
|
|
403
|
+
Retrieves the value of a specific variable in the solution.
|
|
404
|
+
|
|
405
|
+
Args:
|
|
406
|
+
var: A highs_var object representing the variable.
|
|
407
|
+
|
|
408
|
+
Returns:
|
|
409
|
+
The value of the specified variable in the solution.
|
|
410
|
+
"""
|
|
411
|
+
return self.val(var)
|
|
412
|
+
|
|
413
|
+
def variableValues(
|
|
414
|
+
self,
|
|
415
|
+
idxs: Union[Integral, highs_var, highs_cons, highs_linear_expression, Mapping[Any, Any], np.ndarray[Any, np.dtype[Any]]],
|
|
416
|
+
):
|
|
417
|
+
"""
|
|
418
|
+
Retrieves the values of multiple variables in the solution.
|
|
419
|
+
|
|
420
|
+
Args:
|
|
421
|
+
idxs: A collection of highs_var objects representing the variables. Can be a Mapping (e.g., dict) where keys are variable names and values are highs_var objects, or an iterable of highs_var objects.
|
|
422
|
+
|
|
423
|
+
Returns:
|
|
424
|
+
If idxs is a Mapping, returns a dict where keys are the same keys from the input idxs and values are the solution values of the corresponding variables. If idxs is an iterable, returns a list of solution values for the variables.
|
|
425
|
+
"""
|
|
426
|
+
return self.vals(idxs)
|
|
427
|
+
|
|
428
|
+
def allVariableValues(self):
|
|
429
|
+
"""
|
|
430
|
+
Retrieves the values of all variables in the solution.
|
|
431
|
+
|
|
432
|
+
Returns:
|
|
433
|
+
A list of values for all variables in the solution.
|
|
434
|
+
"""
|
|
435
|
+
return super().getSolution().col_value
|
|
436
|
+
|
|
437
|
+
def variableDual(
|
|
438
|
+
self,
|
|
439
|
+
var: Union[Integral, highs_var, highs_cons, highs_linear_expression, Mapping[Any, Any], np.ndarray[Any, np.dtype[Any]]],
|
|
440
|
+
):
|
|
441
|
+
"""
|
|
442
|
+
Retrieves the dual value of a specific variable/index or expression in the solution.
|
|
443
|
+
|
|
444
|
+
Args:
|
|
445
|
+
var: A highs_var object representing the variable.
|
|
446
|
+
|
|
447
|
+
Returns:
|
|
448
|
+
The dual value of the specified variable in the solution.
|
|
449
|
+
"""
|
|
450
|
+
return Highs.internal_get_value(super().getSolution().col_dual, var)
|
|
451
|
+
|
|
452
|
+
def variableDuals(
|
|
453
|
+
self,
|
|
454
|
+
idxs: Union[Integral, highs_var, highs_cons, highs_linear_expression, Mapping[Any, Any], np.ndarray[Any, np.dtype[Any]]],
|
|
455
|
+
):
|
|
456
|
+
"""
|
|
457
|
+
Retrieves the dual values of multiple variables in the solution.
|
|
458
|
+
|
|
459
|
+
Args:
|
|
460
|
+
idxs: A collection of highs_var objects representing the variables. Can be a Mapping (e.g., dict) where keys are variable names and values are highs_var objects, or an iterable of highs_var objects.
|
|
461
|
+
|
|
462
|
+
Returns:
|
|
463
|
+
If idxs is a Mapping, returns a dict where keys are the same keys from the input idxs and values are the dual values of the corresponding variables. If idxs is an iterable, returns a list of dual values for the variables.
|
|
464
|
+
"""
|
|
465
|
+
return Highs.internal_get_value(super().getSolution().col_dual, idxs)
|
|
466
|
+
|
|
467
|
+
def allVariableDuals(self):
|
|
468
|
+
"""
|
|
469
|
+
Retrieves the dual values of all variables in the solution.
|
|
470
|
+
|
|
471
|
+
Returns:
|
|
472
|
+
A list of dual values for all variables in the solution.
|
|
473
|
+
"""
|
|
474
|
+
return super().getSolution().col_dual
|
|
475
|
+
|
|
476
|
+
def constrValue(
|
|
477
|
+
self,
|
|
478
|
+
con: Union[Integral, highs_var, highs_cons, highs_linear_expression, Mapping[Any, Any], np.ndarray[Any, np.dtype[Any]]],
|
|
479
|
+
):
|
|
480
|
+
"""
|
|
481
|
+
Retrieves the value of a specific constraint in the solution.
|
|
482
|
+
|
|
483
|
+
Args:
|
|
484
|
+
con: A highs_con object representing the constraint.
|
|
485
|
+
|
|
486
|
+
Returns:
|
|
487
|
+
The value of the specified constraint in the solution.
|
|
488
|
+
"""
|
|
489
|
+
return Highs.internal_get_value(super().getSolution().row_value, con)
|
|
490
|
+
|
|
491
|
+
def constrValues(
|
|
492
|
+
self,
|
|
493
|
+
cons: Union[Integral, highs_var, highs_cons, highs_linear_expression, Mapping[Any, Any], np.ndarray[Any, np.dtype[Any]]],
|
|
494
|
+
):
|
|
495
|
+
"""
|
|
496
|
+
Retrieves the values of multiple constraints in the solution.
|
|
497
|
+
|
|
498
|
+
Args:
|
|
499
|
+
cons: A collection of highs_con objects representing the constraints. Can be a Mapping (e.g., dict) where keys are constraint names and values are highs_con objects, or an iterable of highs_con objects.
|
|
500
|
+
|
|
501
|
+
Returns:
|
|
502
|
+
If cons is a Mapping, returns a dict where keys are the same keys from the input cons and values are the solution values of the corresponding constraints. If cons is an iterable, returns a list of solution values for the constraints.
|
|
503
|
+
"""
|
|
504
|
+
return Highs.internal_get_value(super().getSolution().row_value, cons)
|
|
505
|
+
|
|
506
|
+
def allConstrValues(self):
|
|
507
|
+
"""
|
|
508
|
+
Retrieves the values of all constraints in the solution.
|
|
509
|
+
|
|
510
|
+
Returns:
|
|
511
|
+
A list of values for all constraints in the solution.
|
|
512
|
+
"""
|
|
513
|
+
return super().getSolution().row_value
|
|
514
|
+
|
|
515
|
+
def constrDual(
|
|
516
|
+
self,
|
|
517
|
+
con: Union[Integral, highs_var, highs_cons, highs_linear_expression, Mapping[Any, Any], np.ndarray[Any, np.dtype[Any]]],
|
|
518
|
+
):
|
|
519
|
+
"""
|
|
520
|
+
Retrieves the dual value of a specific constraint in the solution.
|
|
521
|
+
|
|
522
|
+
Args:
|
|
523
|
+
con: A highs_con object representing the constraint.
|
|
524
|
+
|
|
525
|
+
Returns:
|
|
526
|
+
The dual value of the specified constraint in the solution.
|
|
527
|
+
"""
|
|
528
|
+
return Highs.internal_get_value(super().getSolution().row_dual, con)
|
|
529
|
+
|
|
530
|
+
def constrDuals(
|
|
531
|
+
self,
|
|
532
|
+
cons: Union[Integral, highs_var, highs_cons, highs_linear_expression, Mapping[Any, Any], np.ndarray[Any, np.dtype[Any]]],
|
|
533
|
+
):
|
|
534
|
+
"""
|
|
535
|
+
Retrieves the dual values of multiple constraints in the solution.
|
|
536
|
+
|
|
537
|
+
Args:
|
|
538
|
+
cons: A collection of highs_con objects representing the constraints. Can be a Mapping (e.g., dict) where keys are constraint names and values are highs_con objects, or an iterable of highs_con objects.
|
|
539
|
+
|
|
540
|
+
Returns:
|
|
541
|
+
If cons is a Mapping, returns a dict where keys are the same keys from the input cons and values are the dual values of the corresponding constraints. If cons is an iterable, returns a list of dual values for the constraints.
|
|
542
|
+
"""
|
|
543
|
+
return Highs.internal_get_value(super().getSolution().row_dual, cons)
|
|
544
|
+
|
|
545
|
+
def allConstrDuals(self):
|
|
546
|
+
"""
|
|
547
|
+
Retrieves the dual values of all constraints in the solution.
|
|
548
|
+
|
|
549
|
+
Returns:
|
|
550
|
+
A list of dual values for all constraints in the solution.
|
|
551
|
+
"""
|
|
552
|
+
return super().getSolution().row_dual
|
|
553
|
+
|
|
554
|
+
def addVariable(
|
|
555
|
+
self,
|
|
556
|
+
lb: float = 0,
|
|
557
|
+
ub: float = kHighsInf,
|
|
558
|
+
obj: float = 0.0,
|
|
559
|
+
type: HighsVarType = HighsVarType.kContinuous,
|
|
560
|
+
name: Optional[str] = None,
|
|
561
|
+
):
|
|
562
|
+
"""
|
|
563
|
+
Adds a variable to the model.
|
|
564
|
+
|
|
565
|
+
Args:
|
|
566
|
+
lb: Lower bound of the variable (default is 0).
|
|
567
|
+
ub: Upper bound of the variable (default is infinity).
|
|
568
|
+
obj: Objective coefficient of the variable (default is 0).
|
|
569
|
+
type: Type of the variable (continuous, integer; default is continuous).
|
|
570
|
+
name: Optional name for the variable.
|
|
571
|
+
|
|
572
|
+
Returns:
|
|
573
|
+
A highs_var object representing the added variable.
|
|
574
|
+
"""
|
|
575
|
+
status = super().addCol(obj, lb, ub, 0, np.empty(0, dtype=np.int32), np.empty(0, np.float64))
|
|
576
|
+
|
|
577
|
+
if status != HighsStatus.kOk:
|
|
578
|
+
raise Exception("Failed to add variable to the model.")
|
|
579
|
+
|
|
580
|
+
var = highs_var(self.numVariables - 1, self)
|
|
581
|
+
|
|
582
|
+
if type != HighsVarType.kContinuous:
|
|
583
|
+
super().changeColIntegrality(var.index, type)
|
|
584
|
+
|
|
585
|
+
if name is not None:
|
|
586
|
+
super().passColName(var.index, name)
|
|
587
|
+
|
|
588
|
+
return var
|
|
589
|
+
|
|
590
|
+
@overload
|
|
591
|
+
def addVariables(
|
|
592
|
+
self,
|
|
593
|
+
*nvars: int,
|
|
594
|
+
**kwargs: Union[Any, HighsVarType, Mapping[Any, Any], Sequence[Any]],
|
|
595
|
+
) -> HighspyArray: ...
|
|
596
|
+
|
|
597
|
+
@overload
|
|
598
|
+
def addVariables(
|
|
599
|
+
self,
|
|
600
|
+
*nvars: Mapping[Any, Any],
|
|
601
|
+
**kwargs: Union[Any, HighsVarType, Mapping[Any, Any], Sequence[Any]],
|
|
602
|
+
) -> dict[Any, highs_var]: ...
|
|
603
|
+
|
|
604
|
+
@overload
|
|
605
|
+
def addVariables(
|
|
606
|
+
self,
|
|
607
|
+
*nvars: Sequence[Any],
|
|
608
|
+
**kwargs: Union[Any, HighsVarType, Mapping[Any, Any], Sequence[Any]],
|
|
609
|
+
) -> Union[dict[Any, highs_var], HighspyArray]: ...
|
|
610
|
+
|
|
611
|
+
@overload
|
|
612
|
+
def addVariables(
|
|
613
|
+
self,
|
|
614
|
+
*nvars: Union[int, Mapping[Any, Any], Sequence[Any]],
|
|
615
|
+
**kwargs: Union[Any, HighsVarType, Mapping[Any, Any], Sequence[Any]],
|
|
616
|
+
) -> Optional[Union[dict[Any, highs_var], HighspyArray]]: ...
|
|
617
|
+
|
|
618
|
+
def addVariables(
|
|
619
|
+
self,
|
|
620
|
+
*nvars: Union[int, Mapping[Any, Any], Sequence[Any]],
|
|
621
|
+
**kwargs: Union[Any, HighsVarType, Mapping[Any, Any], Sequence[Any]],
|
|
622
|
+
) -> Optional[Union[dict[Any, highs_var], HighspyArray]]:
|
|
623
|
+
"""
|
|
624
|
+
Adds multiple variables to the model.
|
|
625
|
+
|
|
626
|
+
Args:
|
|
627
|
+
*args: A sequence of variables to be added. Can be a collection of scalars or indices (or mix).
|
|
628
|
+
|
|
629
|
+
**kwargs: Optional keyword arguments. Can be scalars, arrays, or mappings.
|
|
630
|
+
lb: Lower bound of the variables (default is 0).
|
|
631
|
+
ub: Upper bound of the variables (default is infinity).
|
|
632
|
+
obj: Objective coefficient of the variables (default is 0).
|
|
633
|
+
type: Type of the variables (continuous, integer; default is continuous).
|
|
634
|
+
name: A collection of names for the variables (list or mapping).
|
|
635
|
+
name_prefix: Prefix for the variable names. Constructed name will be name_prefix + index.
|
|
636
|
+
out_array: Return an array of highs_var objects instead of a dictionary.
|
|
637
|
+
|
|
638
|
+
Returns:
|
|
639
|
+
A highs_var collection (array or dictionary) representing the added variables.
|
|
640
|
+
"""
|
|
641
|
+
if len(nvars) == 0:
|
|
642
|
+
return None
|
|
643
|
+
|
|
644
|
+
# if all nvars are scalars, we can assume they are the dimensions
|
|
645
|
+
shape = [n for n in nvars if isinstance(n, int)]
|
|
646
|
+
|
|
647
|
+
expanded = [range(n) if isinstance(n, int) else n for n in nvars]
|
|
648
|
+
indices: list[Any] = list(expanded[0] if len(expanded) == 1 else product(*expanded)) # unpack tuple if needed
|
|
649
|
+
N = len(indices)
|
|
650
|
+
|
|
651
|
+
if len(shape) != len(nvars):
|
|
652
|
+
shape = [N]
|
|
653
|
+
|
|
654
|
+
# parameter can be scalar, array, or mapping lookup (i.e., dictionary, custom class, etc.)
|
|
655
|
+
# scalar: repeat for all N, array: use as is, lookup: convert to array using indices
|
|
656
|
+
def ensure_real(x: Union[Any, Mapping[Any, Any], Sequence[Any]]):
|
|
657
|
+
if isinstance(x, (float, int)):
|
|
658
|
+
return np.full(N, x, dtype=np.float64)
|
|
659
|
+
|
|
660
|
+
elif isinstance(x, Mapping):
|
|
661
|
+
mt: Mapping[Any, Any] = x
|
|
662
|
+
|
|
663
|
+
if all(isinstance(v, (float, int)) for v in mt.values()):
|
|
664
|
+
m: Mapping[Any, Union[float, int]] = x
|
|
665
|
+
return np.fromiter((m[i] for i in indices), np.float64)
|
|
666
|
+
|
|
667
|
+
elif isinstance(x, Sequence) and len(x) == N and all(isinstance(v, (float, int)) for v in x):
|
|
668
|
+
return np.asarray(x, dtype=np.float64)
|
|
669
|
+
|
|
670
|
+
raise Exception("Invalid parameter.")
|
|
671
|
+
|
|
672
|
+
def ensure_HighsVarType(x: Union[Any, Mapping[Any, Any], Sequence[Any]]):
|
|
673
|
+
if x == HighsVarType.kContinuous:
|
|
674
|
+
return None
|
|
675
|
+
|
|
676
|
+
elif isinstance(x, HighsVarType):
|
|
677
|
+
return np.full(N, x, dtype=np.uint8)
|
|
678
|
+
|
|
679
|
+
elif isinstance(x, Mapping):
|
|
680
|
+
mt: Mapping[Any, Any] = x
|
|
681
|
+
|
|
682
|
+
if all(isinstance(v, HighsVarType) for v in mt.values()):
|
|
683
|
+
m: Mapping[Any, HighsVarType] = x
|
|
684
|
+
return np.fromiter((m[i] for i in indices), np.uint8)
|
|
685
|
+
|
|
686
|
+
elif isinstance(x, Sequence) and len(x) == N and all(isinstance(v, HighsVarType) for v in x):
|
|
687
|
+
return np.asarray(x, dtype=np.uint8)
|
|
688
|
+
|
|
689
|
+
raise Exception("Invalid parameter.")
|
|
690
|
+
|
|
691
|
+
def ensure_optional_str(x: Optional[Any]):
|
|
692
|
+
if x is None:
|
|
693
|
+
return None
|
|
694
|
+
elif isinstance(x, Sequence):
|
|
695
|
+
mt: Sequence[Any] = x
|
|
696
|
+
|
|
697
|
+
if len(mt) == N and all(isinstance(v, str) for v in mt):
|
|
698
|
+
m: Sequence[str] = mt
|
|
699
|
+
return m
|
|
700
|
+
|
|
701
|
+
raise Exception("Invalid parameter.")
|
|
702
|
+
|
|
703
|
+
def ensure_str_or_none(x: Any) -> Optional[str]:
|
|
704
|
+
if x is None or isinstance(x, str):
|
|
705
|
+
return x
|
|
706
|
+
else:
|
|
707
|
+
raise Exception("Invalid parameter.")
|
|
708
|
+
|
|
709
|
+
def ensure_bool(x: Any) -> bool:
|
|
710
|
+
if isinstance(x, bool):
|
|
711
|
+
return x
|
|
712
|
+
raise Exception("Invalid parameter.")
|
|
713
|
+
|
|
714
|
+
lb = ensure_real(kwargs.get("lb", 0.0))
|
|
715
|
+
ub = ensure_real(kwargs.get("ub", kHighsInf))
|
|
716
|
+
obj = ensure_real(kwargs.get("obj", 0))
|
|
717
|
+
vartype = ensure_HighsVarType(kwargs.get("type", HighsVarType.kContinuous))
|
|
718
|
+
name_prefix = ensure_str_or_none(kwargs.get("name_prefix", None))
|
|
719
|
+
name = ensure_optional_str(kwargs.get("name", None))
|
|
720
|
+
out_array = ensure_bool(kwargs.get("out_array", all(isinstance(n, int) for n in nvars)))
|
|
721
|
+
|
|
722
|
+
start_idx = self.numVariables
|
|
723
|
+
idx = np.arange(start_idx, start_idx + N, dtype=np.int32)
|
|
724
|
+
status = super().addCols(
|
|
725
|
+
N,
|
|
726
|
+
obj,
|
|
727
|
+
lb,
|
|
728
|
+
ub,
|
|
729
|
+
0,
|
|
730
|
+
np.empty(0, dtype=np.int32),
|
|
731
|
+
np.empty(0, dtype=np.int32),
|
|
732
|
+
np.empty(0, dtype=np.float64),
|
|
733
|
+
)
|
|
734
|
+
|
|
735
|
+
if status != HighsStatus.kOk:
|
|
736
|
+
raise Exception("Failed to add columns to the model.")
|
|
737
|
+
|
|
738
|
+
# only set integrality if we have non-continuous variables
|
|
739
|
+
if vartype is not None:
|
|
740
|
+
super().changeColsIntegrality(N, idx, vartype)
|
|
741
|
+
|
|
742
|
+
if name or name_prefix:
|
|
743
|
+
# Changed to fix #2887 names = name or [f"{name_prefix}{i}" for i in indices]
|
|
744
|
+
names = name or [f"{name_prefix}{i}".replace(" ", "") for i in indices]
|
|
745
|
+
for i, n in zip(idx, names):
|
|
746
|
+
super().passColName(int(i), str(n))
|
|
747
|
+
|
|
748
|
+
return (
|
|
749
|
+
HighspyArray(np.asarray([highs_var(int(i), self) for i in idx]).reshape(shape), self)
|
|
750
|
+
if out_array
|
|
751
|
+
else {index: highs_var(int(i), self) for index, i in zip(indices, idx)}
|
|
752
|
+
)
|
|
753
|
+
|
|
754
|
+
@overload
|
|
755
|
+
def addIntegrals(
|
|
756
|
+
self,
|
|
757
|
+
*nvars: int,
|
|
758
|
+
**kwargs: Union[Any, HighsVarType, Mapping[Any, Any], Sequence[Any]],
|
|
759
|
+
) -> HighspyArray: ...
|
|
760
|
+
|
|
761
|
+
@overload
|
|
762
|
+
def addIntegrals(
|
|
763
|
+
self,
|
|
764
|
+
*nvars: Mapping[Any, Any],
|
|
765
|
+
**kwargs: Union[Any, HighsVarType, Mapping[Any, Any], Sequence[Any]],
|
|
766
|
+
) -> dict[Any, highs_var]: ...
|
|
767
|
+
|
|
768
|
+
@overload
|
|
769
|
+
def addIntegrals(
|
|
770
|
+
self,
|
|
771
|
+
*nvars: Sequence[Any],
|
|
772
|
+
**kwargs: Union[Any, HighsVarType, Mapping[Any, Any], Sequence[Any]],
|
|
773
|
+
) -> Union[dict[Any, highs_var], HighspyArray]: ...
|
|
774
|
+
|
|
775
|
+
@overload
|
|
776
|
+
def addIntegrals(
|
|
777
|
+
self,
|
|
778
|
+
*nvars: Union[int, Mapping[Any, Any], Sequence[Any]],
|
|
779
|
+
**kwargs: Union[Any, HighsVarType, Mapping[Any, Any], Sequence[Any]],
|
|
780
|
+
) -> Optional[Union[dict[Any, highs_var], HighspyArray]]: ...
|
|
781
|
+
|
|
782
|
+
def addIntegrals(
|
|
783
|
+
self,
|
|
784
|
+
*nvars: Union[int, Mapping[Any, Any], Sequence[Any]],
|
|
785
|
+
**kwargs: Union[Any, HighsVarType, Mapping[Any, Any], Sequence[Any]],
|
|
786
|
+
):
|
|
787
|
+
"""
|
|
788
|
+
Alias for the addVariables method, for integer variables.
|
|
789
|
+
"""
|
|
790
|
+
kwargs.setdefault("type", HighsVarType.kInteger)
|
|
791
|
+
return self.addVariables(*nvars, **kwargs)
|
|
792
|
+
|
|
793
|
+
@overload
|
|
794
|
+
def addBinaries(
|
|
795
|
+
self,
|
|
796
|
+
*nvars: int,
|
|
797
|
+
**kwargs: Union[Any, HighsVarType, Mapping[Any, Any], Sequence[Any]],
|
|
798
|
+
) -> HighspyArray: ...
|
|
799
|
+
|
|
800
|
+
@overload
|
|
801
|
+
def addBinaries(
|
|
802
|
+
self,
|
|
803
|
+
*nvars: Mapping[Any, Any],
|
|
804
|
+
**kwargs: Union[Any, HighsVarType, Mapping[Any, Any], Sequence[Any]],
|
|
805
|
+
) -> dict[Any, highs_var]: ...
|
|
806
|
+
|
|
807
|
+
@overload
|
|
808
|
+
def addBinaries(
|
|
809
|
+
self,
|
|
810
|
+
*nvars: Sequence[Any],
|
|
811
|
+
**kwargs: Union[Any, HighsVarType, Mapping[Any, Any], Sequence[Any]],
|
|
812
|
+
) -> Union[dict[Any, highs_var], HighspyArray]: ...
|
|
813
|
+
|
|
814
|
+
@overload
|
|
815
|
+
def addBinaries(
|
|
816
|
+
self,
|
|
817
|
+
*nvars: Union[int, Mapping[Any, Any], Sequence[Any]],
|
|
818
|
+
**kwargs: Union[Any, HighsVarType, Mapping[Any, Any], Sequence[Any]],
|
|
819
|
+
) -> Optional[Union[dict[Any, highs_var], HighspyArray]]: ...
|
|
820
|
+
|
|
821
|
+
def addBinaries(
|
|
822
|
+
self,
|
|
823
|
+
*nvars: Union[int, Mapping[Any, Any], Sequence[Any]],
|
|
824
|
+
**kwargs: Union[Any, HighsVarType, Mapping[Any, Any], Sequence[Any]],
|
|
825
|
+
):
|
|
826
|
+
"""
|
|
827
|
+
Alias for the addVariables method, for binary variables.
|
|
828
|
+
"""
|
|
829
|
+
kwargs.setdefault("lb", 0)
|
|
830
|
+
kwargs.setdefault("ub", 1)
|
|
831
|
+
kwargs.setdefault("type", HighsVarType.kInteger)
|
|
832
|
+
|
|
833
|
+
return self.addVariables(*nvars, **kwargs)
|
|
834
|
+
|
|
835
|
+
def addIntegral(self, lb: float = 0.0, ub: float = kHighsInf, obj: float = 0.0, name: Optional[str] = None):
|
|
836
|
+
"""
|
|
837
|
+
Alias for the addVariable method, for integer variables.
|
|
838
|
+
"""
|
|
839
|
+
return self.addVariable(lb, ub, obj, HighsVarType.kInteger, name)
|
|
840
|
+
|
|
841
|
+
def addBinary(self, obj: float = 0.0, name: Optional[str] = None):
|
|
842
|
+
"""
|
|
843
|
+
Alias for the addVariable method, for binary variables.
|
|
844
|
+
"""
|
|
845
|
+
return self.addVariable(0, 1, obj, HighsVarType.kInteger, name)
|
|
846
|
+
|
|
847
|
+
def deleteVariable(
|
|
848
|
+
self,
|
|
849
|
+
var_or_index: Union[Integral, highs_var],
|
|
850
|
+
*args: Union[Mapping[Any, highs_var], Iterable[highs_var], highs_var],
|
|
851
|
+
):
|
|
852
|
+
"""
|
|
853
|
+
Deletes a variable from the model and updates the indices of subsequent variables in provided collections.
|
|
854
|
+
|
|
855
|
+
Args:
|
|
856
|
+
var_or_index: A highs_var object or an index representing the variable to be deleted.
|
|
857
|
+
*args: Optional collections (lists, dicts, etc.) of highs_var objects whose indices need to be updated.
|
|
858
|
+
"""
|
|
859
|
+
# Determine the index of the variable to delete
|
|
860
|
+
index = int(var_or_index)
|
|
861
|
+
|
|
862
|
+
# Delete the variable from the model if it exists
|
|
863
|
+
if index < self.numVariables:
|
|
864
|
+
super().deleteVars(1, [index])
|
|
865
|
+
|
|
866
|
+
# Update the indices of variables in the provided collections
|
|
867
|
+
for collection in args:
|
|
868
|
+
if isinstance(collection, Mapping):
|
|
869
|
+
mt: Mapping[Any, highs_var] = collection
|
|
870
|
+
|
|
871
|
+
# Update indices in a dictionary of variables
|
|
872
|
+
for _, var in mt.items():
|
|
873
|
+
if var.index > index:
|
|
874
|
+
var.index -= 1
|
|
875
|
+
elif var.index == index:
|
|
876
|
+
var.index = -1
|
|
877
|
+
|
|
878
|
+
elif isinstance(collection, Iterable):
|
|
879
|
+
# Update indices in an iterable of variables
|
|
880
|
+
for var in collection:
|
|
881
|
+
if var.index > index:
|
|
882
|
+
var.index -= 1
|
|
883
|
+
elif var.index == index:
|
|
884
|
+
var.index = -1
|
|
885
|
+
|
|
886
|
+
# If the collection is a single highs_var object, check and update if necessary
|
|
887
|
+
elif collection.index > index:
|
|
888
|
+
collection.index -= 1
|
|
889
|
+
elif collection.index == index:
|
|
890
|
+
collection.index = -1
|
|
891
|
+
|
|
892
|
+
def getVariables(self):
|
|
893
|
+
"""
|
|
894
|
+
Retrieves all variables in the model.
|
|
895
|
+
|
|
896
|
+
Returns:
|
|
897
|
+
A list of highs_var objects, each representing a variable in the model.
|
|
898
|
+
"""
|
|
899
|
+
return [highs_var(i, self) for i in range(self.numVariables)]
|
|
900
|
+
|
|
901
|
+
@property
|
|
902
|
+
def inf(self):
|
|
903
|
+
"""
|
|
904
|
+
Represents infinity in the context of the solver.
|
|
905
|
+
|
|
906
|
+
Returns:
|
|
907
|
+
The value used to represent infinity.
|
|
908
|
+
"""
|
|
909
|
+
return kHighsInf
|
|
910
|
+
|
|
911
|
+
@property
|
|
912
|
+
def numVariables(self):
|
|
913
|
+
"""
|
|
914
|
+
Gets the number of variables in the model.
|
|
915
|
+
|
|
916
|
+
Returns:
|
|
917
|
+
The number of variables.
|
|
918
|
+
"""
|
|
919
|
+
return super().getNumCol()
|
|
920
|
+
|
|
921
|
+
@property
|
|
922
|
+
def numConstrs(self):
|
|
923
|
+
"""
|
|
924
|
+
Gets the number of constraints in the model.
|
|
925
|
+
|
|
926
|
+
Returns:
|
|
927
|
+
The number of constraints.
|
|
928
|
+
"""
|
|
929
|
+
return super().getNumRow()
|
|
930
|
+
|
|
931
|
+
#
|
|
932
|
+
# add constraints
|
|
933
|
+
#
|
|
934
|
+
def addConstr(self, expr: highs_linear_expression, name: Optional[str] = None):
|
|
935
|
+
"""
|
|
936
|
+
Adds a constraint to the model.
|
|
937
|
+
|
|
938
|
+
Args:
|
|
939
|
+
expr: A highs_linear_expression to be added.
|
|
940
|
+
name: Optional name of the constraint.
|
|
941
|
+
|
|
942
|
+
Returns:
|
|
943
|
+
A highs_con object representing the added constraint.
|
|
944
|
+
"""
|
|
945
|
+
con = self.__addRow(expr, self.numConstrs)
|
|
946
|
+
|
|
947
|
+
if name is not None:
|
|
948
|
+
super().passRowName(con.index, name)
|
|
949
|
+
|
|
950
|
+
return con
|
|
951
|
+
|
|
952
|
+
@overload
|
|
953
|
+
def addConstrs(
|
|
954
|
+
self,
|
|
955
|
+
*args: highs_linear_expression,
|
|
956
|
+
**kwargs: Optional[Union[str, Sequence[str]]],
|
|
957
|
+
) -> list[highs_cons]: ...
|
|
958
|
+
|
|
959
|
+
@overload
|
|
960
|
+
def addConstrs(
|
|
961
|
+
self,
|
|
962
|
+
*args: Mapping[Any, highs_linear_expression],
|
|
963
|
+
**kwargs: Optional[Union[str, Sequence[str]]],
|
|
964
|
+
) -> dict[Any, highs_cons]: ...
|
|
965
|
+
|
|
966
|
+
@overload
|
|
967
|
+
def addConstrs(
|
|
968
|
+
self,
|
|
969
|
+
*args: Iterable[highs_linear_expression],
|
|
970
|
+
**kwargs: Optional[Union[str, Sequence[str]]],
|
|
971
|
+
) -> list[highs_cons]: ...
|
|
972
|
+
|
|
973
|
+
def addConstrs(
|
|
974
|
+
self,
|
|
975
|
+
*args: Union[highs_linear_expression, Iterable[highs_linear_expression]],
|
|
976
|
+
**kwargs: Optional[Union[str, Sequence[str]]],
|
|
977
|
+
):
|
|
978
|
+
"""
|
|
979
|
+
Adds multiple constraints to the model.
|
|
980
|
+
|
|
981
|
+
Args:
|
|
982
|
+
*args: A sequence of highs_linear_expression to be added.
|
|
983
|
+
|
|
984
|
+
**kwargs: Optional keyword arguments.
|
|
985
|
+
name_prefix: Prefix for the constraint names. Constructed name will be name_prefix + index.
|
|
986
|
+
name: A collection of names for the constraints (list or mapping).
|
|
987
|
+
|
|
988
|
+
Returns:
|
|
989
|
+
A highs_con collection array representing the added constraints.
|
|
990
|
+
"""
|
|
991
|
+
name_prefix = kwargs.get("name_prefix", None)
|
|
992
|
+
name = kwargs.get("name", None)
|
|
993
|
+
|
|
994
|
+
# unpack generator if needed
|
|
995
|
+
generator = args[0] if len(args) == 1 and isinstance(args[0], Iterable) else args
|
|
996
|
+
initial_rows = self.numConstrs
|
|
997
|
+
|
|
998
|
+
try:
|
|
999
|
+
if isinstance(generator, Mapping):
|
|
1000
|
+
mt: Mapping[Any, highs_linear_expression] = generator
|
|
1001
|
+
cons = {key: self.__addRow(expr, initial_rows + count) for count, (key, expr) in enumerate(mt.items())}
|
|
1002
|
+
else:
|
|
1003
|
+
it: Iterable[Any] = generator
|
|
1004
|
+
cons = [self.__addRow(expr, initial_rows + count) for count, expr in enumerate(it)]
|
|
1005
|
+
|
|
1006
|
+
# TODO: Mapping support with constraint names can be improved, e.g., by allowing a name collection to be passed
|
|
1007
|
+
if name or name_prefix:
|
|
1008
|
+
names = name or [f"{name_prefix}{n}" for n in range(self.numConstrs - initial_rows)]
|
|
1009
|
+
|
|
1010
|
+
for c, n in zip(range(initial_rows, self.numConstrs), names):
|
|
1011
|
+
super().passRowName(int(c), str(n))
|
|
1012
|
+
|
|
1013
|
+
except Exception as e:
|
|
1014
|
+
# rollback model if error - remove any constraints that were added
|
|
1015
|
+
status = super().deleteRows(
|
|
1016
|
+
self.numConstrs - initial_rows,
|
|
1017
|
+
np.arange(initial_rows, self.numConstrs, dtype=np.int32),
|
|
1018
|
+
)
|
|
1019
|
+
|
|
1020
|
+
if status != HighsStatus.kOk:
|
|
1021
|
+
raise Exception("Failed to rollback model after failure. Model might be in a undeterminate state.")
|
|
1022
|
+
else:
|
|
1023
|
+
raise e
|
|
1024
|
+
|
|
1025
|
+
return cons
|
|
1026
|
+
|
|
1027
|
+
def __addRow(self, expr: highs_linear_expression, idx: int):
|
|
1028
|
+
"""
|
|
1029
|
+
Internal method to add a constraint to the model.
|
|
1030
|
+
"""
|
|
1031
|
+
if expr.bounds is not None:
|
|
1032
|
+
idxs, vals = expr.unique_elements() # if we have duplicate variables, add the vals
|
|
1033
|
+
super().addRow(expr.bounds[0], expr.bounds[1], len(idxs), idxs, vals)
|
|
1034
|
+
return highs_cons(idx, self)
|
|
1035
|
+
else:
|
|
1036
|
+
raise Exception("Constraint bounds must be set via comparison (>=,==,<=).")
|
|
1037
|
+
|
|
1038
|
+
def expr(
|
|
1039
|
+
self,
|
|
1040
|
+
optional: Optional[Union[float, int, highs_var, highs_linear_expression]] = None,
|
|
1041
|
+
):
|
|
1042
|
+
"""
|
|
1043
|
+
Creates a new highs_linear_expression object.
|
|
1044
|
+
|
|
1045
|
+
Returns:
|
|
1046
|
+
A highs_linear_expression object.
|
|
1047
|
+
"""
|
|
1048
|
+
return highs_linear_expression(optional)
|
|
1049
|
+
|
|
1050
|
+
def getExpr(self, cons: Union[Integral, highs_cons]):
|
|
1051
|
+
"""
|
|
1052
|
+
Retrieves the highs_linear_expression of a constraint.
|
|
1053
|
+
|
|
1054
|
+
Args:
|
|
1055
|
+
cons: A highs_con object or index representing the constraint.
|
|
1056
|
+
|
|
1057
|
+
Returns:
|
|
1058
|
+
A highs_linear_expression object representing the expression of the constraint.
|
|
1059
|
+
"""
|
|
1060
|
+
status, lb, ub, nnz = super().getRow(int(cons)) # type: ignore
|
|
1061
|
+
|
|
1062
|
+
if status != HighsStatus.kOk:
|
|
1063
|
+
raise Exception("Error retrieving constraint expression.")
|
|
1064
|
+
|
|
1065
|
+
status, idx, val = super().getRowEntries(int(cons))
|
|
1066
|
+
|
|
1067
|
+
if status != HighsStatus.kOk:
|
|
1068
|
+
raise Exception("Error retrieving constraint expression entries.")
|
|
1069
|
+
|
|
1070
|
+
expr = highs_linear_expression()
|
|
1071
|
+
expr.bounds = (lb, ub)
|
|
1072
|
+
expr.idxs = list(idx)
|
|
1073
|
+
expr.vals = list(val)
|
|
1074
|
+
return expr
|
|
1075
|
+
|
|
1076
|
+
def chgCoeff(self, cons: Union[highs_cons, Integral], var: Union[highs_var, Integral], val: float):
|
|
1077
|
+
"""
|
|
1078
|
+
Changes the coefficient of a variable in a constraint.
|
|
1079
|
+
|
|
1080
|
+
Args:
|
|
1081
|
+
cons: A highs_con object representing the constraint.
|
|
1082
|
+
var: A highs_var object representing the variable.
|
|
1083
|
+
val: The new coefficient value for the variable in the constraint.
|
|
1084
|
+
"""
|
|
1085
|
+
super().changeCoeff(int(cons), int(var), val)
|
|
1086
|
+
|
|
1087
|
+
def getConstrs(self):
|
|
1088
|
+
"""
|
|
1089
|
+
Retrieves all constraints in the model.
|
|
1090
|
+
|
|
1091
|
+
Returns:
|
|
1092
|
+
A list of highs_cons objects, each representing a constraint in the model.
|
|
1093
|
+
"""
|
|
1094
|
+
return [highs_cons(i, self) for i in range(self.numConstrs)]
|
|
1095
|
+
|
|
1096
|
+
def removeConstr(
|
|
1097
|
+
self,
|
|
1098
|
+
cons_or_index: Union[highs_cons, Integral],
|
|
1099
|
+
*args: Union[Mapping[Any, highs_cons], Sequence[highs_cons], highs_cons],
|
|
1100
|
+
):
|
|
1101
|
+
"""
|
|
1102
|
+
Removes a constraint from the model and updates the indices of subsequent constraints in provided collections.
|
|
1103
|
+
|
|
1104
|
+
Args:
|
|
1105
|
+
cons_or_index: A highs_cons object or an index representing the constraint to be removed.
|
|
1106
|
+
*args: Optional collections (lists, dicts, etc.) of highs_cons objects whose indices need to be updated after the removal.
|
|
1107
|
+
"""
|
|
1108
|
+
# Determine the index of the constraint to delete
|
|
1109
|
+
index = int(cons_or_index)
|
|
1110
|
+
|
|
1111
|
+
# Delete the variable from the model if it exists
|
|
1112
|
+
if index < self.numConstrs:
|
|
1113
|
+
status = super().deleteRows(1, np.asarray([index], dtype=np.int32))
|
|
1114
|
+
|
|
1115
|
+
if status != HighsStatus.kOk:
|
|
1116
|
+
raise Exception("Failed to delete constraint from the model.")
|
|
1117
|
+
|
|
1118
|
+
# Update the indices of constraints in the provided collections
|
|
1119
|
+
for collection in args:
|
|
1120
|
+
if isinstance(collection, Mapping):
|
|
1121
|
+
mt: Mapping[Any, highs_cons] = collection
|
|
1122
|
+
|
|
1123
|
+
# Update indices in a dictionary of constraints
|
|
1124
|
+
for _, con in mt.items():
|
|
1125
|
+
if con.index > index:
|
|
1126
|
+
con.index -= 1
|
|
1127
|
+
elif con.index == index:
|
|
1128
|
+
con.index = -1
|
|
1129
|
+
|
|
1130
|
+
elif isinstance(collection, Sequence):
|
|
1131
|
+
# Update indices in an iterable of constraints
|
|
1132
|
+
for con in collection:
|
|
1133
|
+
if con.index > index:
|
|
1134
|
+
con.index -= 1
|
|
1135
|
+
elif con.index == index:
|
|
1136
|
+
con.index = -1
|
|
1137
|
+
|
|
1138
|
+
# If the collection is a single highs_cons object, check and update if necessary
|
|
1139
|
+
elif collection.index > index:
|
|
1140
|
+
collection.index -= 1
|
|
1141
|
+
|
|
1142
|
+
elif collection.index == index:
|
|
1143
|
+
collection.index = -1
|
|
1144
|
+
|
|
1145
|
+
def setMinimize(self):
|
|
1146
|
+
"""
|
|
1147
|
+
Sets the objective sense of the model to minimization.
|
|
1148
|
+
"""
|
|
1149
|
+
super().changeObjectiveSense(ObjSense.kMinimize)
|
|
1150
|
+
|
|
1151
|
+
def setMaximize(self):
|
|
1152
|
+
"""
|
|
1153
|
+
Sets the objective sense of the model to maximization.
|
|
1154
|
+
"""
|
|
1155
|
+
super().changeObjectiveSense(ObjSense.kMaximize)
|
|
1156
|
+
|
|
1157
|
+
def setInteger(self, var_or_collection: Union[highs_var, int, Iterable[Union[highs_var, int]]]):
|
|
1158
|
+
"""
|
|
1159
|
+
Sets a variable/collection to integer.
|
|
1160
|
+
|
|
1161
|
+
Args:
|
|
1162
|
+
var_or_collection: A highs_var object/collection representing the variable to be set as integer.
|
|
1163
|
+
"""
|
|
1164
|
+
if isinstance(var_or_collection, Iterable):
|
|
1165
|
+
idx = np.fromiter(map(int, var_or_collection), dtype=np.int32)
|
|
1166
|
+
super().changeColsIntegrality(len(idx), idx, np.full(len(idx), HighsVarType.kInteger, dtype=np.uint8))
|
|
1167
|
+
else:
|
|
1168
|
+
super().changeColIntegrality(int(var_or_collection), HighsVarType.kInteger)
|
|
1169
|
+
|
|
1170
|
+
def setContinuous(self, var_or_collection: Union[highs_var, int, Iterable[Union[highs_var, int]]]):
|
|
1171
|
+
"""
|
|
1172
|
+
Sets a variable/collection to continuous.
|
|
1173
|
+
|
|
1174
|
+
Args:
|
|
1175
|
+
var_or_collection: A highs_var object/collection representing the variable to be set as continuous.
|
|
1176
|
+
"""
|
|
1177
|
+
if isinstance(var_or_collection, Iterable):
|
|
1178
|
+
idx = np.fromiter(map(int, var_or_collection), dtype=np.int32)
|
|
1179
|
+
super().changeColsIntegrality(
|
|
1180
|
+
len(idx),
|
|
1181
|
+
idx,
|
|
1182
|
+
np.full(len(idx), HighsVarType.kContinuous, dtype=np.uint8),
|
|
1183
|
+
)
|
|
1184
|
+
else:
|
|
1185
|
+
super().changeColIntegrality(int(var_or_collection), HighsVarType.kContinuous)
|
|
1186
|
+
|
|
1187
|
+
@staticmethod
|
|
1188
|
+
def qsum(
|
|
1189
|
+
items: Union[Iterable[Union[highs_var, highs_linear_expression]], np.ndarray[Any, np.dtype[np.object_]]],
|
|
1190
|
+
initial: Optional[Union[float, int, highs_var, highs_linear_expression]] = None,
|
|
1191
|
+
):
|
|
1192
|
+
"""
|
|
1193
|
+
Performs a faster sum for highs_linear_expressions.
|
|
1194
|
+
|
|
1195
|
+
Args:
|
|
1196
|
+
items: A collection of highs_linear_expressions or highs_vars to be summed.
|
|
1197
|
+
"""
|
|
1198
|
+
expr = highs_linear_expression(initial)
|
|
1199
|
+
|
|
1200
|
+
if isinstance(items, np.ndarray):
|
|
1201
|
+
X: np.ndarray[Any, np.dtype[np.object_]] = items
|
|
1202
|
+
for v in X.flat:
|
|
1203
|
+
expr += cast(Union[highs_var, highs_linear_expression], v)
|
|
1204
|
+
else:
|
|
1205
|
+
for v in items:
|
|
1206
|
+
expr += v
|
|
1207
|
+
|
|
1208
|
+
return expr
|
|
1209
|
+
|
|
1210
|
+
##
|
|
1211
|
+
## Callback support, with optional user interrupt handling
|
|
1212
|
+
##
|
|
1213
|
+
@staticmethod
|
|
1214
|
+
def __internal_callback(
|
|
1215
|
+
callback_type: cb.HighsCallbackType,
|
|
1216
|
+
message: str,
|
|
1217
|
+
data_out: cb.HighsCallbackOutput,
|
|
1218
|
+
data_in: Optional[cb.HighsCallbackInput],
|
|
1219
|
+
user_callback_data: Any,
|
|
1220
|
+
):
|
|
1221
|
+
user_callback_data.callbacks[int(callback_type)].fire(callback_type, message, data_out, data_in)
|
|
1222
|
+
|
|
1223
|
+
def enableCallbacks(self):
|
|
1224
|
+
"""
|
|
1225
|
+
Enables callbacks, restarting them if they were previously enabled.
|
|
1226
|
+
"""
|
|
1227
|
+
super().setCallback(Highs.__internal_callback, self)
|
|
1228
|
+
|
|
1229
|
+
# restart callbacks if any exist
|
|
1230
|
+
for c in self.callbacks:
|
|
1231
|
+
if len(c.callbacks) > 0:
|
|
1232
|
+
self.startCallback(c.callback_type)
|
|
1233
|
+
|
|
1234
|
+
def clearCallbacks(self):
|
|
1235
|
+
"""
|
|
1236
|
+
Clears all callbacks.
|
|
1237
|
+
"""
|
|
1238
|
+
for c in self.callbacks:
|
|
1239
|
+
c.clear()
|
|
1240
|
+
|
|
1241
|
+
def disableCallbacks(self):
|
|
1242
|
+
"""
|
|
1243
|
+
Disables all callbacks, but does not clear them.
|
|
1244
|
+
"""
|
|
1245
|
+
status = super().setCallback(None, None) # this will also stop all callbacks
|
|
1246
|
+
|
|
1247
|
+
if status != HighsStatus.kOk:
|
|
1248
|
+
raise Exception("Failed to disable callbacks.")
|
|
1249
|
+
|
|
1250
|
+
def cancelSolve(self):
|
|
1251
|
+
"""
|
|
1252
|
+
If HandleUserInterrupt is enabled, this method will signal the solver to stop.
|
|
1253
|
+
"""
|
|
1254
|
+
self.__solver_should_stop = True
|
|
1255
|
+
|
|
1256
|
+
@property
|
|
1257
|
+
def HandleKeyboardInterrupt(self):
|
|
1258
|
+
"""
|
|
1259
|
+
Get/Set whether the solver should handle KeyboardInterrupt (i.e., cancel solve on Ctrl+C). Also enables/disables HandleUserInterrupt.
|
|
1260
|
+
"""
|
|
1261
|
+
return self.__handle_keyboard_interrupt
|
|
1262
|
+
|
|
1263
|
+
@HandleKeyboardInterrupt.setter
|
|
1264
|
+
def HandleKeyboardInterrupt(self, value: bool):
|
|
1265
|
+
self.__handle_keyboard_interrupt = value
|
|
1266
|
+
self.HandleUserInterrupt = value
|
|
1267
|
+
|
|
1268
|
+
@property
|
|
1269
|
+
def HandleUserInterrupt(self):
|
|
1270
|
+
"""
|
|
1271
|
+
Get/Set whether the solver should handle user interrupts (i.e., cancel solve on user request)
|
|
1272
|
+
"""
|
|
1273
|
+
return self.__handle_user_interrupt
|
|
1274
|
+
|
|
1275
|
+
@HandleUserInterrupt.setter
|
|
1276
|
+
def HandleUserInterrupt(self, value: bool):
|
|
1277
|
+
self.__handle_user_interrupt = value
|
|
1278
|
+
|
|
1279
|
+
if value:
|
|
1280
|
+
self.cbSimplexInterrupt += self.__user_interrupt_event
|
|
1281
|
+
self.cbIpmInterrupt += self.__user_interrupt_event
|
|
1282
|
+
self.cbMipInterrupt += self.__user_interrupt_event
|
|
1283
|
+
else:
|
|
1284
|
+
self.cbSimplexInterrupt -= self.__user_interrupt_event
|
|
1285
|
+
self.cbIpmInterrupt -= self.__user_interrupt_event
|
|
1286
|
+
self.cbMipInterrupt -= self.__user_interrupt_event
|
|
1287
|
+
|
|
1288
|
+
def __user_interrupt_event(self, e: HighsCallbackEvent):
|
|
1289
|
+
if self.__solver_should_stop:
|
|
1290
|
+
e.interrupt()
|
|
1291
|
+
|
|
1292
|
+
@property
|
|
1293
|
+
def cbLogging(self):
|
|
1294
|
+
return self.callbacks[int(cb.HighsCallbackType.kCallbackLogging)]
|
|
1295
|
+
|
|
1296
|
+
@property
|
|
1297
|
+
def cbSimplexInterrupt(self):
|
|
1298
|
+
return self.callbacks[int(cb.HighsCallbackType.kCallbackSimplexInterrupt)]
|
|
1299
|
+
|
|
1300
|
+
@property
|
|
1301
|
+
def cbIpmInterrupt(self):
|
|
1302
|
+
return self.callbacks[int(cb.HighsCallbackType.kCallbackIpmInterrupt)]
|
|
1303
|
+
|
|
1304
|
+
@property
|
|
1305
|
+
def cbMipSolution(self):
|
|
1306
|
+
return self.callbacks[int(cb.HighsCallbackType.kCallbackMipSolution)]
|
|
1307
|
+
|
|
1308
|
+
@property
|
|
1309
|
+
def cbMipImprovingSolution(self):
|
|
1310
|
+
return self.callbacks[int(cb.HighsCallbackType.kCallbackMipImprovingSolution)]
|
|
1311
|
+
|
|
1312
|
+
@property
|
|
1313
|
+
def cbMipLogging(self):
|
|
1314
|
+
return self.callbacks[int(cb.HighsCallbackType.kCallbackMipLogging)]
|
|
1315
|
+
|
|
1316
|
+
@property
|
|
1317
|
+
def cbMipInterrupt(self):
|
|
1318
|
+
return self.callbacks[int(cb.HighsCallbackType.kCallbackMipInterrupt)]
|
|
1319
|
+
|
|
1320
|
+
@property
|
|
1321
|
+
def cbMipGetCutPool(self):
|
|
1322
|
+
return self.callbacks[int(cb.HighsCallbackType.kCallbackMipGetCutPool)]
|
|
1323
|
+
|
|
1324
|
+
@property
|
|
1325
|
+
def cbMipDefineLazyConstraints(self):
|
|
1326
|
+
return self.callbacks[int(cb.HighsCallbackType.kCallbackMipDefineLazyConstraints)]
|
|
1327
|
+
|
|
1328
|
+
@property
|
|
1329
|
+
def cbMipUserSolution(self):
|
|
1330
|
+
return self.callbacks[int(cb.HighsCallbackType.kCallbackMipUserSolution)]
|
|
1331
|
+
|
|
1332
|
+
# callback setters are required for +=/-= syntax
|
|
1333
|
+
# e.g., h.cbLogging += my_callback
|
|
1334
|
+
@cbLogging.setter
|
|
1335
|
+
def cbLogging(self, value: HighsCallback):
|
|
1336
|
+
if self.cbLogging is not value:
|
|
1337
|
+
raise Exception("Cannot set callback directly. Use .subscribe(callback) instead.")
|
|
1338
|
+
|
|
1339
|
+
@cbSimplexInterrupt.setter
|
|
1340
|
+
def cbSimplexInterrupt(self, value: HighsCallback):
|
|
1341
|
+
if self.cbSimplexInterrupt is not value:
|
|
1342
|
+
raise Exception("Cannot set callback directly. Use .subscribe(callback) instead.")
|
|
1343
|
+
|
|
1344
|
+
@cbIpmInterrupt.setter
|
|
1345
|
+
def cbIpmInterrupt(self, value: HighsCallback):
|
|
1346
|
+
if self.cbIpmInterrupt is not value:
|
|
1347
|
+
raise Exception("Cannot set callback directly. Use .subscribe(callback) instead.")
|
|
1348
|
+
|
|
1349
|
+
@cbMipSolution.setter
|
|
1350
|
+
def cbMipSolution(self, value: HighsCallback):
|
|
1351
|
+
if self.cbMipSolution is not value:
|
|
1352
|
+
raise Exception("Cannot set callback directly. Use .subscribe(callback) instead.")
|
|
1353
|
+
|
|
1354
|
+
@cbMipImprovingSolution.setter
|
|
1355
|
+
def cbMipImprovingSolution(self, value: HighsCallback):
|
|
1356
|
+
if self.cbMipImprovingSolution is not value:
|
|
1357
|
+
raise Exception("Cannot set callback directly. Use .subscribe(callback) instead.")
|
|
1358
|
+
|
|
1359
|
+
@cbMipLogging.setter
|
|
1360
|
+
def cbMipLogging(self, value: HighsCallback):
|
|
1361
|
+
if self.cbMipLogging is not value:
|
|
1362
|
+
raise Exception("Cannot set callback directly. Use .subscribe(callback) instead.")
|
|
1363
|
+
|
|
1364
|
+
@cbMipInterrupt.setter
|
|
1365
|
+
def cbMipInterrupt(self, value: HighsCallback):
|
|
1366
|
+
if self.cbMipInterrupt is not value:
|
|
1367
|
+
raise Exception("Cannot set callback directly. Use .subscribe(callback) instead.")
|
|
1368
|
+
|
|
1369
|
+
@cbMipGetCutPool.setter
|
|
1370
|
+
def cbMipGetCutPool(self, value: HighsCallback):
|
|
1371
|
+
if self.cbMipGetCutPool is not value:
|
|
1372
|
+
raise Exception("Cannot set callback directly. Use .subscribe(callback) instead.")
|
|
1373
|
+
|
|
1374
|
+
@cbMipDefineLazyConstraints.setter
|
|
1375
|
+
def cbMipDefineLazyConstraints(self, value: HighsCallback):
|
|
1376
|
+
if self.cbMipDefineLazyConstraints is not value:
|
|
1377
|
+
raise Exception("Cannot set callback directly. Use .subscribe(callback) instead.")
|
|
1378
|
+
|
|
1379
|
+
@cbMipUserSolution.setter
|
|
1380
|
+
def cbMipUserSolution(self, value: HighsCallback):
|
|
1381
|
+
if self.cbMipUserSolution is not value:
|
|
1382
|
+
raise Exception("Cannot set callback directly. Use .subscribe(callback) instead.")
|
|
1383
|
+
|
|
1384
|
+
|
|
1385
|
+
|
|
1386
|
+
##
|
|
1387
|
+
## Callback support
|
|
1388
|
+
##
|
|
1389
|
+
class HighsCallbackEvent(object):
|
|
1390
|
+
__slots__ = ["callback_type", "message", "data_out", "data_in", "user_data"]
|
|
1391
|
+
|
|
1392
|
+
def __init__(
|
|
1393
|
+
self,
|
|
1394
|
+
callback_type: cb.HighsCallbackType,
|
|
1395
|
+
message: str,
|
|
1396
|
+
data_out: cb.HighsCallbackOutput,
|
|
1397
|
+
data_in: Optional[cb.HighsCallbackInput],
|
|
1398
|
+
user_data: Optional[Any]
|
|
1399
|
+
):
|
|
1400
|
+
self.callback_type = callback_type
|
|
1401
|
+
self.message = message
|
|
1402
|
+
self.data_out = data_out
|
|
1403
|
+
self.data_in = data_in
|
|
1404
|
+
self.user_data = user_data
|
|
1405
|
+
|
|
1406
|
+
def interrupt(self, interrupt_value: bool = True):
|
|
1407
|
+
"""
|
|
1408
|
+
Sets the user interrupt flag in the callback data.
|
|
1409
|
+
"""
|
|
1410
|
+
if self.data_in is not None:
|
|
1411
|
+
self.data_in.user_interrupt = interrupt_value
|
|
1412
|
+
|
|
1413
|
+
def val(
|
|
1414
|
+
self,
|
|
1415
|
+
var_expr: Union[Integral, highs_var, highs_cons, highs_linear_expression, Mapping[Any, Any], np.ndarray[Any, np.dtype[Any]]],
|
|
1416
|
+
):
|
|
1417
|
+
"""
|
|
1418
|
+
Gets the value(s) of a variable/index or expression in the callback solution.
|
|
1419
|
+
"""
|
|
1420
|
+
return Highs.internal_get_value(self.data_out.mip_solution, var_expr)
|
|
1421
|
+
|
|
1422
|
+
def cut(self, index: int):
|
|
1423
|
+
"""
|
|
1424
|
+
Gets the cut pool for the given index.
|
|
1425
|
+
"""
|
|
1426
|
+
cut = highs_linear_expression()
|
|
1427
|
+
|
|
1428
|
+
if self.data_out and index >= 0 and index < self.data_out.cutpool_num_cut:
|
|
1429
|
+
start, end = self.data_out.cutpool_start[index:index+2]
|
|
1430
|
+
cut.bounds = (self.data_out.cutpool_lower[index], self.data_out.cutpool_upper[index])
|
|
1431
|
+
cut.idxs = list(map(int, self.data_out.cutpool_index[start:end]))
|
|
1432
|
+
cut.vals = list(map(float, self.data_out.cutpool_value[start:end]))
|
|
1433
|
+
|
|
1434
|
+
return cut
|
|
1435
|
+
|
|
1436
|
+
@property
|
|
1437
|
+
def cuts(self):
|
|
1438
|
+
"""
|
|
1439
|
+
Gets all cuts in the cut pool.
|
|
1440
|
+
"""
|
|
1441
|
+
return [self.cut(i) for i in range(self.data_out.cutpool_num_cut)]
|
|
1442
|
+
|
|
1443
|
+
class HighsCallback(object):
|
|
1444
|
+
__slots__ = ["callbacks", "user_callback_data", "highs", "callback_type"]
|
|
1445
|
+
|
|
1446
|
+
def __init__(self, callback_type: cb.HighsCallbackType, highs: Highs):
|
|
1447
|
+
self.callbacks: list[Callable[[HighsCallbackEvent], None]] = []
|
|
1448
|
+
self.user_callback_data: list[Any] = []
|
|
1449
|
+
self.callback_type = callback_type
|
|
1450
|
+
self.highs = proxy(highs) # to avoid circular reference
|
|
1451
|
+
|
|
1452
|
+
def subscribe(
|
|
1453
|
+
self,
|
|
1454
|
+
callback: Callable[[HighsCallbackEvent], None],
|
|
1455
|
+
user_data: Optional[Any] = None,
|
|
1456
|
+
):
|
|
1457
|
+
"""
|
|
1458
|
+
Subscribes a callback to the event.
|
|
1459
|
+
|
|
1460
|
+
Args:
|
|
1461
|
+
callback: The callback function to be executed.
|
|
1462
|
+
user_data: Optional user data to be passed to the callback.
|
|
1463
|
+
"""
|
|
1464
|
+
if len(self.callbacks) == 0:
|
|
1465
|
+
status = self.highs.startCallback(self.callback_type)
|
|
1466
|
+
|
|
1467
|
+
if status != HighsStatus.kOk:
|
|
1468
|
+
raise Exception("Failed to start callback.")
|
|
1469
|
+
|
|
1470
|
+
self.callbacks.append(callback)
|
|
1471
|
+
self.user_callback_data.append(user_data)
|
|
1472
|
+
return self
|
|
1473
|
+
|
|
1474
|
+
def unsubscribe(self, callback: Callable[[HighsCallbackEvent], None]):
|
|
1475
|
+
"""
|
|
1476
|
+
Unsubscribes a callback from the event.
|
|
1477
|
+
|
|
1478
|
+
Args:
|
|
1479
|
+
callback: The callback function to be removed.
|
|
1480
|
+
"""
|
|
1481
|
+
try:
|
|
1482
|
+
idx = self.callbacks.index(callback)
|
|
1483
|
+
del self.callbacks[idx]
|
|
1484
|
+
del self.user_callback_data[idx]
|
|
1485
|
+
|
|
1486
|
+
if len(self.callbacks) == 0:
|
|
1487
|
+
self.highs.stopCallback(self.callback_type)
|
|
1488
|
+
|
|
1489
|
+
except ValueError:
|
|
1490
|
+
pass
|
|
1491
|
+
|
|
1492
|
+
return self
|
|
1493
|
+
|
|
1494
|
+
def unsubscribe_by_data(self, user_data: Optional[Any]):
|
|
1495
|
+
"""
|
|
1496
|
+
Unsubscribes a callback by user data.
|
|
1497
|
+
|
|
1498
|
+
Args:
|
|
1499
|
+
user_data: The user data corresponding to the callback(s) to be removed.
|
|
1500
|
+
"""
|
|
1501
|
+
idx = reversed([i for i, ud in enumerate(self.user_callback_data) if ud == user_data])
|
|
1502
|
+
|
|
1503
|
+
for i in idx:
|
|
1504
|
+
del self.callbacks[i]
|
|
1505
|
+
del self.user_callback_data[i]
|
|
1506
|
+
|
|
1507
|
+
if len(self.callbacks) == 0:
|
|
1508
|
+
self.highs.stopCallback(self.callback_type)
|
|
1509
|
+
|
|
1510
|
+
return self
|
|
1511
|
+
|
|
1512
|
+
def __iadd__(self, callback: Callable[[HighsCallbackEvent], None]):
|
|
1513
|
+
return self.subscribe(callback)
|
|
1514
|
+
|
|
1515
|
+
def __isub__(self, callback: Callable[[HighsCallbackEvent], None]):
|
|
1516
|
+
return self.unsubscribe(callback)
|
|
1517
|
+
|
|
1518
|
+
def clear(self):
|
|
1519
|
+
"""
|
|
1520
|
+
Unsubscribes all callbacks from the event.
|
|
1521
|
+
"""
|
|
1522
|
+
self.callbacks = []
|
|
1523
|
+
self.user_callback_data = []
|
|
1524
|
+
self.highs.stopCallback(self.callback_type)
|
|
1525
|
+
|
|
1526
|
+
def fire(
|
|
1527
|
+
self,
|
|
1528
|
+
callback_type: cb.HighsCallbackType,
|
|
1529
|
+
message: str,
|
|
1530
|
+
data_out: cb.HighsCallbackOutput,
|
|
1531
|
+
data_in: cb.HighsCallbackInput,
|
|
1532
|
+
):
|
|
1533
|
+
"""
|
|
1534
|
+
Fires the event, executing all subscribed callbacks.
|
|
1535
|
+
"""
|
|
1536
|
+
e = HighsCallbackEvent(callback_type, message, data_out, data_in, None)
|
|
1537
|
+
|
|
1538
|
+
for fn, user_data in zip(self.callbacks, self.user_callback_data):
|
|
1539
|
+
e.user_data = user_data
|
|
1540
|
+
fn(e)
|
|
1541
|
+
|
|
1542
|
+
|
|
1543
|
+
class HighspyArray(ndarray_object_type):
|
|
1544
|
+
"""
|
|
1545
|
+
A numpy array wrapper for highs_var/highs_linear_expression objects.
|
|
1546
|
+
|
|
1547
|
+
This provides additional type information for static analysis, and also allows faster sum operations.
|
|
1548
|
+
"""
|
|
1549
|
+
|
|
1550
|
+
def __new__(cls, input_array: np.ndarray[Any, np.dtype[np.object_]], highs: Optional[Highs]):
|
|
1551
|
+
obj = np.asarray(input_array).view(cls)
|
|
1552
|
+
obj.highs = highs
|
|
1553
|
+
return obj
|
|
1554
|
+
|
|
1555
|
+
def __array_finalize__(self, obj: Optional[Any]):
|
|
1556
|
+
self.highs = getattr(obj, "highs", None)
|
|
1557
|
+
|
|
1558
|
+
@overload
|
|
1559
|
+
def __getitem__(self, key: Union[SupportsIndex, tuple[SupportsIndex, ...]]) -> highs_linear_expression: ... # type: ignore
|
|
1560
|
+
|
|
1561
|
+
@overload
|
|
1562
|
+
def __getitem__(
|
|
1563
|
+
self,
|
|
1564
|
+
key: Union[
|
|
1565
|
+
np.ndarray[Any, np.dtype[np.integer[Any]]],
|
|
1566
|
+
np.ndarray[Any, np.dtype[np.bool_]],
|
|
1567
|
+
tuple[Union[np.ndarray[Any, np.dtype[np.integer[Any]]], np.ndarray[Any, np.dtype[np.bool_]]], ...],
|
|
1568
|
+
],
|
|
1569
|
+
) -> HighspyArray: ...
|
|
1570
|
+
|
|
1571
|
+
@overload
|
|
1572
|
+
def __getitem__(self, key: Union[None, slice, SupportsIndex, tuple[Union[None, slice, SupportsIndex], ...]]) -> HighspyArray: ...
|
|
1573
|
+
|
|
1574
|
+
@overload
|
|
1575
|
+
def __getitem__(self, key: Any) -> HighspyArray: ... # type: ignore
|
|
1576
|
+
|
|
1577
|
+
def __getitem__(self, key: Any) -> Union[HighspyArray, highs_linear_expression]: # type: ignore
|
|
1578
|
+
return super(HighspyArray, self).__getitem__(key) # type: ignore
|
|
1579
|
+
|
|
1580
|
+
def __ge__(self, other: Any) -> HighspyArray: # type: ignore
|
|
1581
|
+
return cast(HighspyArray, np.greater_equal(self, other, dtype=np.object_))
|
|
1582
|
+
|
|
1583
|
+
def __le__(self, other: Any) -> HighspyArray: # type: ignore
|
|
1584
|
+
return cast(HighspyArray, np.less_equal(self, other, dtype=np.object_))
|
|
1585
|
+
|
|
1586
|
+
def __eq__(self, other: Any) -> HighspyArray:
|
|
1587
|
+
return cast(HighspyArray, np.equal(self, other, dtype=np.object_))
|
|
1588
|
+
|
|
1589
|
+
@overload
|
|
1590
|
+
def sum(self, axis: None = None, dtype: Optional[Any] = None, out: None = ...) -> highs_linear_expression: ...
|
|
1591
|
+
|
|
1592
|
+
@overload
|
|
1593
|
+
def sum(self, axis: Any, dtype: Optional[Any] = None, out: HighspyArray = ...) -> HighspyArray: ...
|
|
1594
|
+
|
|
1595
|
+
def sum( # type: ignore
|
|
1596
|
+
self,
|
|
1597
|
+
axis: Optional[int] = None,
|
|
1598
|
+
dtype: Optional[Any] = None,
|
|
1599
|
+
out: Optional[np.ndarray[Any, np.dtype[np.object_]]] = None,
|
|
1600
|
+
**unused_kwargs: Any,
|
|
1601
|
+
) -> Union[HighspyArray, highs_linear_expression]:
|
|
1602
|
+
if self.highs is not None:
|
|
1603
|
+
if axis is not None:
|
|
1604
|
+
return HighspyArray(np.apply_along_axis(self.highs.qsum, axis, self, initial=unused_kwargs.get("initial", None)), self.highs)
|
|
1605
|
+
else:
|
|
1606
|
+
return self.highs.qsum(self, unused_kwargs.get("initial", None))
|
|
1607
|
+
else:
|
|
1608
|
+
raise Exception("Cannot sum without a Highs object.")
|
|
1609
|
+
|
|
1610
|
+
|
|
1611
|
+
# highs variable
|
|
1612
|
+
class highs_var(object):
|
|
1613
|
+
"""
|
|
1614
|
+
Variable index wrapper for HiGHS
|
|
1615
|
+
"""
|
|
1616
|
+
|
|
1617
|
+
__slots__ = ["index", "highs"]
|
|
1618
|
+
|
|
1619
|
+
def __init__(self, i: int, highs: Highs):
|
|
1620
|
+
self.index = i
|
|
1621
|
+
self.highs = proxy(highs) # to avoid circular reference
|
|
1622
|
+
|
|
1623
|
+
def __repr__(self):
|
|
1624
|
+
return f"highs_var({self.index})"
|
|
1625
|
+
|
|
1626
|
+
@property
|
|
1627
|
+
def name(self):
|
|
1628
|
+
return self.highs.variableName(self)
|
|
1629
|
+
|
|
1630
|
+
@name.setter
|
|
1631
|
+
def name(self, value: str):
|
|
1632
|
+
self.highs.passColName(self.index, value)
|
|
1633
|
+
|
|
1634
|
+
def __int__(self):
|
|
1635
|
+
return int(self.index)
|
|
1636
|
+
|
|
1637
|
+
def __hash__(self):
|
|
1638
|
+
return int(self.index)
|
|
1639
|
+
|
|
1640
|
+
def __neg__(self):
|
|
1641
|
+
expr = highs_linear_expression()
|
|
1642
|
+
expr.idxs = [self.index]
|
|
1643
|
+
expr.vals = [-1.0]
|
|
1644
|
+
return expr
|
|
1645
|
+
|
|
1646
|
+
def __add__(self, other: Union[float, int, highs_var, highs_linear_expression]):
|
|
1647
|
+
expr = highs_linear_expression(self)
|
|
1648
|
+
expr += other
|
|
1649
|
+
return expr
|
|
1650
|
+
|
|
1651
|
+
def __radd__(self, other: Union[float, int, highs_var, highs_linear_expression]):
|
|
1652
|
+
expr = highs_linear_expression(self)
|
|
1653
|
+
expr += other
|
|
1654
|
+
return expr
|
|
1655
|
+
|
|
1656
|
+
def __mul__(self, other: Union[float, int, highs_var, highs_linear_expression]):
|
|
1657
|
+
expr = highs_linear_expression(self)
|
|
1658
|
+
expr *= other
|
|
1659
|
+
return expr
|
|
1660
|
+
|
|
1661
|
+
def __rmul__(self, other: Union[float, int, highs_var, highs_linear_expression]):
|
|
1662
|
+
expr = highs_linear_expression(self)
|
|
1663
|
+
expr *= other
|
|
1664
|
+
return expr
|
|
1665
|
+
|
|
1666
|
+
def __rsub__(self, other: Union[float, int, highs_var, highs_linear_expression]):
|
|
1667
|
+
expr = highs_linear_expression(other)
|
|
1668
|
+
expr -= self
|
|
1669
|
+
return expr
|
|
1670
|
+
|
|
1671
|
+
def __sub__(self, other: Union[float, int, highs_var, highs_linear_expression]):
|
|
1672
|
+
expr = highs_linear_expression(self)
|
|
1673
|
+
expr -= other
|
|
1674
|
+
return expr
|
|
1675
|
+
|
|
1676
|
+
# self <= other
|
|
1677
|
+
def __le__(self, other: Union[float, int, highs_var, highs_linear_expression]):
|
|
1678
|
+
if isinstance(other, highs_linear_expression):
|
|
1679
|
+
return other.__ge__(self)
|
|
1680
|
+
else:
|
|
1681
|
+
return highs_linear_expression(self).__le__(other)
|
|
1682
|
+
|
|
1683
|
+
# self == other
|
|
1684
|
+
def __eq__(self, other: Any) -> highs_linear_expression: # type: ignore
|
|
1685
|
+
if isinstance(other, highs_linear_expression):
|
|
1686
|
+
return other.__eq__(self)
|
|
1687
|
+
else:
|
|
1688
|
+
return highs_linear_expression(self).__eq__(other)
|
|
1689
|
+
|
|
1690
|
+
# self != other
|
|
1691
|
+
def __ne__(self, other: Optional[Any]):
|
|
1692
|
+
if other is None:
|
|
1693
|
+
return True
|
|
1694
|
+
else:
|
|
1695
|
+
raise Exception("Invalid comparison.")
|
|
1696
|
+
|
|
1697
|
+
# self >= other
|
|
1698
|
+
def __ge__(self, other: Union[float, int, highs_var, highs_linear_expression]):
|
|
1699
|
+
if isinstance(other, highs_linear_expression):
|
|
1700
|
+
return other.__le__(self)
|
|
1701
|
+
else:
|
|
1702
|
+
return highs_linear_expression(self).__ge__(other)
|
|
1703
|
+
|
|
1704
|
+
|
|
1705
|
+
# highs constraint
|
|
1706
|
+
class highs_cons(object):
|
|
1707
|
+
"""
|
|
1708
|
+
Constraint index wrapper for HiGHS
|
|
1709
|
+
"""
|
|
1710
|
+
|
|
1711
|
+
__slots__ = ["index", "highs"]
|
|
1712
|
+
|
|
1713
|
+
def __init__(self, i: int, highs: Highs):
|
|
1714
|
+
self.index = i
|
|
1715
|
+
self.highs = proxy(highs) # to avoid circular reference
|
|
1716
|
+
|
|
1717
|
+
def __repr__(self):
|
|
1718
|
+
return f"highs_cons({self.index})"
|
|
1719
|
+
|
|
1720
|
+
def __int__(self):
|
|
1721
|
+
return int(self.index)
|
|
1722
|
+
|
|
1723
|
+
def __hash__(self):
|
|
1724
|
+
return int(self.index)
|
|
1725
|
+
|
|
1726
|
+
def expr(self):
|
|
1727
|
+
"""
|
|
1728
|
+
Retrieves the expression of the constraint.
|
|
1729
|
+
"""
|
|
1730
|
+
return self.highs.getExpr(self)
|
|
1731
|
+
|
|
1732
|
+
@property
|
|
1733
|
+
def name(self):
|
|
1734
|
+
status, name = self.highs.getRowName(self.index)
|
|
1735
|
+
|
|
1736
|
+
if status != HighsStatus.kOk:
|
|
1737
|
+
raise Exception("Error retrieving constraint name.")
|
|
1738
|
+
return name
|
|
1739
|
+
|
|
1740
|
+
@name.setter
|
|
1741
|
+
def name(self, value: str):
|
|
1742
|
+
self.highs.passRowName(self.index, value)
|
|
1743
|
+
|
|
1744
|
+
|
|
1745
|
+
# highs constraint builder
|
|
1746
|
+
#
|
|
1747
|
+
# Note: we only allow LHS/RHS to be set once via comparisons (>=,==,<=), otherwise it gets confusing!
|
|
1748
|
+
# e.g, for (0 <= x <= 1) <= 2, should this be:
|
|
1749
|
+
# 0 <= x <= 1 (i.e., tighter bound, x <= 1 and x <= 2 implies x <= 1),
|
|
1750
|
+
# or, 0 <= x <= 2 (i.e., last comparision overrides previous)?
|
|
1751
|
+
#
|
|
1752
|
+
# Throwing an error makes it obvious to the user. Note we can still set via addition,
|
|
1753
|
+
# e.g., (x <= 1) + (y <= 5) to get x + y <= 6
|
|
1754
|
+
#
|
|
1755
|
+
#
|
|
1756
|
+
# For chained comparisons, we throw an error if we have mismatched variables in the "bounds",
|
|
1757
|
+
# e.g., x <= y <= 1. This requires 2 constraints, x <= 1 and x <= y, and is not supported, whereas
|
|
1758
|
+
# x + 2 <= y <= x + 5 is supported, since we can easily rewrite this as 2 <= y - x <= 5.
|
|
1759
|
+
#
|
|
1760
|
+
# As such, trivial chaining is supported, e.g., lb <= expr <= ub, where lb and ub are numeric.
|
|
1761
|
+
#
|
|
1762
|
+
# Note: when dealing with inequalities (>=,==,<=) we need to decide which variables to move the LHS/RHS.
|
|
1763
|
+
# For consistency, we:
|
|
1764
|
+
# 1. Move variables to side with the most variables, e.g., x <= y + z -> 0 <= y + z - x <= inf
|
|
1765
|
+
# y + z >= x -> 0 <= y + z - x <= inf
|
|
1766
|
+
# x >= y + z -> -inf <= y + z - x <= 0
|
|
1767
|
+
# y + z <= x -> -inf <= y + z - x <= 0
|
|
1768
|
+
# y + z == x -> y + z - x == 0
|
|
1769
|
+
# x == y + z -> y + z - x == 0
|
|
1770
|
+
#
|
|
1771
|
+
# 2. If equal, move to side without a constant, e.g., y <= x + 2 -> -inf <= y - x <= 2
|
|
1772
|
+
# x + 2 >= y -> -inf <= y - x <= 2
|
|
1773
|
+
# x + 2 <= y -> 2 <= y - x <= inf
|
|
1774
|
+
# y >= x + 2 -> 2 <= y - x <= inf
|
|
1775
|
+
# y + 2 == x -> x - y == 2
|
|
1776
|
+
# x == y + 2 -> x - y == 2
|
|
1777
|
+
#
|
|
1778
|
+
# 3. If both have constants, move to the 'left', e.g., x + 2 <= y + 3 -> -inf <= x - y <= 1
|
|
1779
|
+
# y + 3 >= x + 2 -> -inf <= x - y <= 1
|
|
1780
|
+
# x + 2 >= y + 3 -> -inf <= y - x <= -1
|
|
1781
|
+
# y + 3 <= x + 2 -> -inf <= y - x <= -1
|
|
1782
|
+
# x + 2 == y + 3 -> x - y == 1
|
|
1783
|
+
# y + 3 == x + 2 -> y - x == -1
|
|
1784
|
+
# Hence:
|
|
1785
|
+
# 6 <= x + y <= 8 -> 6 <= x + y <= 8 #(1)
|
|
1786
|
+
# 6 + x <= y <= 8 + x -> 6 <= y - x <= 8 #(2)
|
|
1787
|
+
# 6 + x <= y + 2 <= 8 + x -> 4 <= y - x <= 6 #(3)
|
|
1788
|
+
# x <= 6 <= x -> 6 <= x <= 6 #(1)
|
|
1789
|
+
# x <= y + z <= x + 5 -> 0 <= y + z - x <= 5 #(1)
|
|
1790
|
+
class highs_linear_expression(object):
|
|
1791
|
+
"""
|
|
1792
|
+
Linear constraint builder for HiGHS
|
|
1793
|
+
"""
|
|
1794
|
+
|
|
1795
|
+
__slots__ = ["idxs", "vals", "constant", "bounds"]
|
|
1796
|
+
|
|
1797
|
+
@overload
|
|
1798
|
+
def __init__(self, other: None = None) -> None: ...
|
|
1799
|
+
|
|
1800
|
+
@overload
|
|
1801
|
+
def __init__(self, other: Union[float, int]) -> None: ...
|
|
1802
|
+
|
|
1803
|
+
@overload
|
|
1804
|
+
def __init__(self, other: highs_var) -> None: ...
|
|
1805
|
+
|
|
1806
|
+
@overload
|
|
1807
|
+
def __init__(self, other: highs_linear_expression) -> None: ...
|
|
1808
|
+
|
|
1809
|
+
def __init__(
|
|
1810
|
+
self,
|
|
1811
|
+
other: Optional[Union[float, int, highs_var, highs_linear_expression]] = None,
|
|
1812
|
+
):
|
|
1813
|
+
self.constant: Optional[float] = None # constant is only valid when bounds are None
|
|
1814
|
+
self.bounds: Optional[tuple[float, float]] = None # bounds are only valid when constant is None
|
|
1815
|
+
|
|
1816
|
+
if other is None:
|
|
1817
|
+
self.idxs: list[int] = []
|
|
1818
|
+
self.vals: list[float] = []
|
|
1819
|
+
|
|
1820
|
+
elif isinstance(other, highs_linear_expression):
|
|
1821
|
+
self.idxs = list(other.idxs)
|
|
1822
|
+
self.vals = list(other.vals)
|
|
1823
|
+
self.constant = other.constant
|
|
1824
|
+
self.bounds = other.bounds if other.bounds is not None else None
|
|
1825
|
+
|
|
1826
|
+
elif isinstance(other, highs_var):
|
|
1827
|
+
self.idxs = [other.index]
|
|
1828
|
+
self.vals = [1.0]
|
|
1829
|
+
|
|
1830
|
+
else:
|
|
1831
|
+
self.idxs = []
|
|
1832
|
+
self.vals = []
|
|
1833
|
+
self.constant = float(other)
|
|
1834
|
+
|
|
1835
|
+
def simplify(self):
|
|
1836
|
+
"""
|
|
1837
|
+
Simplifies the linear expression by combining duplicate variables.
|
|
1838
|
+
"""
|
|
1839
|
+
copy = highs_linear_expression()
|
|
1840
|
+
copy.idxs, copy.vals = (v.tolist() for v in self.unique_elements())
|
|
1841
|
+
copy.bounds = self.bounds if self.bounds is not None else None
|
|
1842
|
+
copy.constant = self.constant
|
|
1843
|
+
return copy
|
|
1844
|
+
|
|
1845
|
+
def copy(self):
|
|
1846
|
+
"""
|
|
1847
|
+
Creates a copy of the linear expression.
|
|
1848
|
+
"""
|
|
1849
|
+
return highs_linear_expression(self)
|
|
1850
|
+
|
|
1851
|
+
def evaluate(
|
|
1852
|
+
self,
|
|
1853
|
+
values: Union[Sequence[float], np.ndarray[Any, np.dtype[np.float64]]],
|
|
1854
|
+
) -> Union[float, bool]:
|
|
1855
|
+
"""
|
|
1856
|
+
Evaluates the linear expression given a solution array (values).
|
|
1857
|
+
"""
|
|
1858
|
+
result = sum(v * values[c] for c, v in zip(self.idxs, self.vals)) + (self.constant or 0.0)
|
|
1859
|
+
return result if self.bounds is None else (self.bounds[0] <= result <= self.bounds[1])
|
|
1860
|
+
|
|
1861
|
+
def __repr__(self):
|
|
1862
|
+
# display duplicate variables
|
|
1863
|
+
v = str.join(" ", [f"{c}_v{x}" for x, c in zip(self.idxs, self.vals)])
|
|
1864
|
+
|
|
1865
|
+
if self.bounds is None:
|
|
1866
|
+
return f"{v}" + (f" {self.constant}" if self.constant is not None else "")
|
|
1867
|
+
elif self.bounds[0] == self.bounds[1]:
|
|
1868
|
+
return f"{v} == {self.bounds[0] - (self.constant or 0.0)}"
|
|
1869
|
+
else:
|
|
1870
|
+
return f"{self.bounds[0]} <= {v} <= {self.bounds[1]}"
|
|
1871
|
+
|
|
1872
|
+
def __str__(self):
|
|
1873
|
+
# display unique variables (values are totaled)
|
|
1874
|
+
idxs, vals = self.unique_elements()
|
|
1875
|
+
v = str.join(" ", [f"{c}_v{x}" for x, c in zip(idxs, vals)])
|
|
1876
|
+
|
|
1877
|
+
if self.bounds is None:
|
|
1878
|
+
return f"{v}" + (f" {self.constant}" if self.constant is not None else "")
|
|
1879
|
+
elif self.bounds[0] == self.bounds[1]:
|
|
1880
|
+
return f"{v} == {self.bounds[0] - (self.constant or 0.0)}"
|
|
1881
|
+
else:
|
|
1882
|
+
return f"{self.bounds[0]} <= {v} <= {self.bounds[1]}"
|
|
1883
|
+
|
|
1884
|
+
# self != other
|
|
1885
|
+
def __ne__(self, other: Optional[Any]):
|
|
1886
|
+
if other is None:
|
|
1887
|
+
return True
|
|
1888
|
+
else:
|
|
1889
|
+
raise Exception("Invalid comparison.")
|
|
1890
|
+
|
|
1891
|
+
# self == other
|
|
1892
|
+
def __eq__(self, other: Any) -> highs_linear_expression: # type: ignore
|
|
1893
|
+
if self.bounds is not None:
|
|
1894
|
+
raise Exception("Bounds have already been set.")
|
|
1895
|
+
|
|
1896
|
+
# self == c
|
|
1897
|
+
elif isinstance(other, (float, int)):
|
|
1898
|
+
copy = highs_linear_expression(self)
|
|
1899
|
+
copy.bounds = (
|
|
1900
|
+
float(other) - (self.constant or 0.0),
|
|
1901
|
+
float(other) - (self.constant or 0.0),
|
|
1902
|
+
)
|
|
1903
|
+
copy.constant = None
|
|
1904
|
+
return copy
|
|
1905
|
+
|
|
1906
|
+
# self == other
|
|
1907
|
+
elif isinstance(other, highs_linear_expression):
|
|
1908
|
+
if other.bounds is not None:
|
|
1909
|
+
raise Exception("Bounds have already been set.")
|
|
1910
|
+
|
|
1911
|
+
copy = highs_linear_expression()
|
|
1912
|
+
|
|
1913
|
+
# prefer most idxs, constant, 'left'
|
|
1914
|
+
if len(other.idxs) > len(self.idxs) or (len(other.idxs) == len(self.idxs) and other.constant is None and self.constant is not None):
|
|
1915
|
+
copy.idxs = other.idxs + self.idxs
|
|
1916
|
+
copy.vals = other.vals + [-v for v in self.vals]
|
|
1917
|
+
copy.bounds = (
|
|
1918
|
+
(self.constant or 0.0) - (other.constant or 0.0),
|
|
1919
|
+
(self.constant or 0.0) - (other.constant or 0.0),
|
|
1920
|
+
)
|
|
1921
|
+
else:
|
|
1922
|
+
copy.idxs = self.idxs + other.idxs
|
|
1923
|
+
copy.vals = self.vals + [-v for v in other.vals]
|
|
1924
|
+
copy.bounds = (
|
|
1925
|
+
(other.constant or 0.0) - (self.constant or 0.0),
|
|
1926
|
+
(other.constant or 0.0) - (self.constant or 0.0),
|
|
1927
|
+
)
|
|
1928
|
+
|
|
1929
|
+
return copy
|
|
1930
|
+
|
|
1931
|
+
# self == x
|
|
1932
|
+
elif isinstance(other, highs_var):
|
|
1933
|
+
copy = highs_linear_expression()
|
|
1934
|
+
|
|
1935
|
+
if len(self.idxs) == 0 or len(self.idxs) == 1 and self.constant is not None:
|
|
1936
|
+
copy.idxs = [other.index] + self.idxs
|
|
1937
|
+
copy.vals = [1.0] + [-v for v in self.vals]
|
|
1938
|
+
copy.bounds = ((self.constant or 0.0), (self.constant or 0.0))
|
|
1939
|
+
else:
|
|
1940
|
+
copy.idxs = self.idxs + [other.index]
|
|
1941
|
+
copy.vals = self.vals + [-1.0]
|
|
1942
|
+
copy.bounds = (-(self.constant or 0.0), -(self.constant or 0.0))
|
|
1943
|
+
|
|
1944
|
+
return copy
|
|
1945
|
+
|
|
1946
|
+
# support expr == [lb, ub] --> lb <= expr <= ub
|
|
1947
|
+
elif hasattr(other, "__getitem__") and hasattr(other, "__len__") and len(other) == 2:
|
|
1948
|
+
if not (isinstance(other[0], (float, int)) and isinstance(other[1], (float, int))):
|
|
1949
|
+
raise Exception("Provided bounds were not valid numbers.")
|
|
1950
|
+
|
|
1951
|
+
copy = highs_linear_expression(self)
|
|
1952
|
+
copy.bounds = (
|
|
1953
|
+
float(other[0]) - (copy.constant or 0.0),
|
|
1954
|
+
float(other[1]) - (copy.constant or 0.0),
|
|
1955
|
+
)
|
|
1956
|
+
copy.constant = None
|
|
1957
|
+
return copy
|
|
1958
|
+
|
|
1959
|
+
else:
|
|
1960
|
+
raise Exception("Unknown comparison.")
|
|
1961
|
+
|
|
1962
|
+
# self <= other
|
|
1963
|
+
def __le__(self, other: Union[float, int, highs_var, highs_linear_expression]):
|
|
1964
|
+
if self.bounds is not None:
|
|
1965
|
+
raise Exception("Bounds have already been set.")
|
|
1966
|
+
|
|
1967
|
+
elif self.__is_active_chain():
|
|
1968
|
+
other = other if isinstance(other, highs_linear_expression) else highs_linear_expression(other)
|
|
1969
|
+
order = self.__get_chain(other, False) # [self, LHS, inner, RHS, other], ignores None values
|
|
1970
|
+
|
|
1971
|
+
# inner <= (self == RHS) <= other
|
|
1972
|
+
# LHS <= (self == inner) <= other
|
|
1973
|
+
if self.__is_equal_except_bounds(order[2]):
|
|
1974
|
+
return self.__compose_chain(*order[1:])
|
|
1975
|
+
|
|
1976
|
+
# self <= (other == inner) <= RHS
|
|
1977
|
+
# self <= (other == LHS) <= inner
|
|
1978
|
+
elif other.__is_equal_except_bounds(order[1]):
|
|
1979
|
+
return self.__compose_chain(*order[:-1])
|
|
1980
|
+
|
|
1981
|
+
self.__reset_chain(self, other, None)
|
|
1982
|
+
|
|
1983
|
+
# self <= c
|
|
1984
|
+
if isinstance(other, (float, int)):
|
|
1985
|
+
copy = highs_linear_expression(self)
|
|
1986
|
+
copy.bounds = (-kHighsInf, float(other) - (copy.constant or 0.0))
|
|
1987
|
+
copy.constant = None
|
|
1988
|
+
return copy
|
|
1989
|
+
|
|
1990
|
+
# self <= other
|
|
1991
|
+
elif isinstance(other, highs_linear_expression):
|
|
1992
|
+
if other.bounds is None:
|
|
1993
|
+
copy = highs_linear_expression()
|
|
1994
|
+
|
|
1995
|
+
# prefer most idxs, constant, 'left'
|
|
1996
|
+
if len(other.idxs) > len(self.idxs) or (len(other.idxs) == len(self.idxs) and other.constant is None and self.constant is not None):
|
|
1997
|
+
copy.idxs = other.idxs + self.idxs
|
|
1998
|
+
copy.vals = other.vals + [-v for v in self.vals]
|
|
1999
|
+
copy.bounds = (
|
|
2000
|
+
(self.constant or 0.0) - (other.constant or 0.0),
|
|
2001
|
+
kHighsInf,
|
|
2002
|
+
)
|
|
2003
|
+
else:
|
|
2004
|
+
copy.idxs = self.idxs + other.idxs
|
|
2005
|
+
copy.vals = self.vals + [-v for v in other.vals]
|
|
2006
|
+
copy.bounds = (
|
|
2007
|
+
-kHighsInf,
|
|
2008
|
+
(other.constant or 0.0) - (self.constant or 0.0),
|
|
2009
|
+
)
|
|
2010
|
+
|
|
2011
|
+
return copy
|
|
2012
|
+
else:
|
|
2013
|
+
raise Exception("Bounds have already been set.")
|
|
2014
|
+
|
|
2015
|
+
# self <= x
|
|
2016
|
+
else: # other is highs_var
|
|
2017
|
+
copy = highs_linear_expression()
|
|
2018
|
+
|
|
2019
|
+
if len(self.idxs) == 0 or len(self.idxs) == 1 and self.constant is not None:
|
|
2020
|
+
copy.idxs = [other.index] + self.idxs
|
|
2021
|
+
copy.vals = [1.0] + [-v for v in self.vals]
|
|
2022
|
+
copy.bounds = ((self.constant or 0.0), kHighsInf)
|
|
2023
|
+
else:
|
|
2024
|
+
copy.idxs = self.idxs + [other.index]
|
|
2025
|
+
copy.vals = self.vals + [-1.0]
|
|
2026
|
+
copy.bounds = (-kHighsInf, -(self.constant or 0.0))
|
|
2027
|
+
|
|
2028
|
+
return copy
|
|
2029
|
+
|
|
2030
|
+
# other <= self
|
|
2031
|
+
def __ge__(self, other: Union[float, int, highs_var, highs_linear_expression]):
|
|
2032
|
+
if self.bounds is not None:
|
|
2033
|
+
raise Exception("Bounds have already been set.")
|
|
2034
|
+
|
|
2035
|
+
elif self.__is_active_chain():
|
|
2036
|
+
other = other if isinstance(other, highs_linear_expression) else highs_linear_expression(other)
|
|
2037
|
+
order = self.__get_chain(other, True) # [other, LHS, inner, RHS, self], ignores None values
|
|
2038
|
+
|
|
2039
|
+
# other <= (self == LHS) <= inner
|
|
2040
|
+
# other <= (self == inner) <= RHS
|
|
2041
|
+
if self.__is_equal_except_bounds(order[1]):
|
|
2042
|
+
return self.__compose_chain(*order[:-1])
|
|
2043
|
+
|
|
2044
|
+
# LHS <= (other == inner) <= self
|
|
2045
|
+
# inner <= (other == RHS) <= self
|
|
2046
|
+
elif other.__is_equal_except_bounds(order[2]):
|
|
2047
|
+
return self.__compose_chain(*order[1:])
|
|
2048
|
+
|
|
2049
|
+
self.__reset_chain(None, other, self)
|
|
2050
|
+
|
|
2051
|
+
# c <= self
|
|
2052
|
+
if isinstance(other, (float, int)):
|
|
2053
|
+
copy = highs_linear_expression(self)
|
|
2054
|
+
copy.bounds = (float(other) - (self.constant or 0.0), kHighsInf)
|
|
2055
|
+
copy.constant = None
|
|
2056
|
+
return copy
|
|
2057
|
+
|
|
2058
|
+
# other <= self
|
|
2059
|
+
elif isinstance(other, highs_linear_expression):
|
|
2060
|
+
if other.bounds is None:
|
|
2061
|
+
copy = highs_linear_expression()
|
|
2062
|
+
|
|
2063
|
+
# prefer most idxs, constant, 'left'
|
|
2064
|
+
if len(self.idxs) > len(other.idxs) or (len(self.idxs) == len(other.idxs) and self.constant is None and other.constant is not None):
|
|
2065
|
+
copy.idxs = self.idxs + other.idxs
|
|
2066
|
+
copy.vals = self.vals + [-v for v in other.vals]
|
|
2067
|
+
copy.bounds = (
|
|
2068
|
+
(other.constant or 0.0) - (self.constant or 0.0),
|
|
2069
|
+
kHighsInf,
|
|
2070
|
+
)
|
|
2071
|
+
else:
|
|
2072
|
+
copy.idxs = other.idxs + self.idxs
|
|
2073
|
+
copy.vals = other.vals + [-v for v in self.vals]
|
|
2074
|
+
copy.bounds = (
|
|
2075
|
+
-kHighsInf,
|
|
2076
|
+
(self.constant or 0.0) - (other.constant or 0.0),
|
|
2077
|
+
)
|
|
2078
|
+
|
|
2079
|
+
return copy
|
|
2080
|
+
else:
|
|
2081
|
+
raise Exception("Bounds have already been set.")
|
|
2082
|
+
|
|
2083
|
+
# x <= self
|
|
2084
|
+
else: # other is highs_var
|
|
2085
|
+
copy = highs_linear_expression()
|
|
2086
|
+
|
|
2087
|
+
if len(self.idxs) > 1:
|
|
2088
|
+
copy.idxs = self.idxs + [other.index]
|
|
2089
|
+
copy.vals = self.vals + [-1.0]
|
|
2090
|
+
copy.bounds = (-(self.constant or 0.0), kHighsInf)
|
|
2091
|
+
else:
|
|
2092
|
+
copy.idxs = [other.index] + self.idxs
|
|
2093
|
+
copy.vals = [1.0] + [-v for v in self.vals]
|
|
2094
|
+
copy.bounds = (-kHighsInf, (self.constant or 0.0))
|
|
2095
|
+
|
|
2096
|
+
return copy
|
|
2097
|
+
|
|
2098
|
+
def __radd__(self, other: Union[float, int, highs_var, highs_linear_expression]):
|
|
2099
|
+
return self + other
|
|
2100
|
+
|
|
2101
|
+
# (LHS <= self <= RHS) + (LHS <= other <= RHS)
|
|
2102
|
+
def __add__(self, other: Union[float, int, highs_var, highs_linear_expression]):
|
|
2103
|
+
copy = highs_linear_expression(self)
|
|
2104
|
+
copy += other
|
|
2105
|
+
return copy
|
|
2106
|
+
|
|
2107
|
+
def __neg__(self):
|
|
2108
|
+
copy = highs_linear_expression()
|
|
2109
|
+
copy.idxs = list(self.idxs)
|
|
2110
|
+
copy.vals = [-v for v in self.vals]
|
|
2111
|
+
copy.constant = -self.constant if self.constant is not None else None
|
|
2112
|
+
|
|
2113
|
+
if self.bounds is not None:
|
|
2114
|
+
copy.bounds = (-self.bounds[1], -self.bounds[0])
|
|
2115
|
+
|
|
2116
|
+
return copy
|
|
2117
|
+
|
|
2118
|
+
def __rmul__(self, other: Union[float, int, highs_var, highs_linear_expression]):
|
|
2119
|
+
return self * other
|
|
2120
|
+
|
|
2121
|
+
def __mul__(self, other: Union[float, int, highs_var, highs_linear_expression]):
|
|
2122
|
+
copy = highs_linear_expression(self)
|
|
2123
|
+
copy *= other
|
|
2124
|
+
return copy
|
|
2125
|
+
|
|
2126
|
+
# other - self
|
|
2127
|
+
def __rsub__(self, other: Union[float, int, highs_var, highs_linear_expression]):
|
|
2128
|
+
copy = highs_linear_expression(other)
|
|
2129
|
+
copy -= self
|
|
2130
|
+
return copy
|
|
2131
|
+
|
|
2132
|
+
def __sub__(self, other: Union[float, int, highs_var, highs_linear_expression]):
|
|
2133
|
+
copy = highs_linear_expression(self)
|
|
2134
|
+
copy -= other
|
|
2135
|
+
return copy
|
|
2136
|
+
|
|
2137
|
+
def unique_elements(self):
|
|
2138
|
+
"""
|
|
2139
|
+
Collects unique variables and sums their corresponding values. Keeps all values (including zeros).
|
|
2140
|
+
"""
|
|
2141
|
+
# sort by groups for fast unique
|
|
2142
|
+
groups = np.asarray(self.idxs, dtype=np.int32)
|
|
2143
|
+
order = np.argsort(groups, kind="stable")
|
|
2144
|
+
groups = groups[order]
|
|
2145
|
+
|
|
2146
|
+
# get unique groups
|
|
2147
|
+
index = np.ones(len(groups), dtype=bool)
|
|
2148
|
+
index[:-1] = groups[1:] != groups[:-1]
|
|
2149
|
+
|
|
2150
|
+
if index.all():
|
|
2151
|
+
values = np.asarray(self.vals, dtype=np.float64)
|
|
2152
|
+
values = values[order]
|
|
2153
|
+
return groups, values
|
|
2154
|
+
else:
|
|
2155
|
+
values = np.asarray(self.vals, dtype=np.float64)
|
|
2156
|
+
values = np.cumsum(values[order])
|
|
2157
|
+
values = values[index]
|
|
2158
|
+
groups = groups[index]
|
|
2159
|
+
|
|
2160
|
+
# calculate the correct sum (diff of cumsum)
|
|
2161
|
+
values[1:] = values[1:] - values[:-1]
|
|
2162
|
+
return groups, values
|
|
2163
|
+
|
|
2164
|
+
def reduced_elements(self):
|
|
2165
|
+
"""
|
|
2166
|
+
Similar to unique_elements, except keeps only non-zero values
|
|
2167
|
+
"""
|
|
2168
|
+
vx, vl = self.unique_elements()
|
|
2169
|
+
zx = np.nonzero(vl)
|
|
2170
|
+
return vx[zx], vl[zx]
|
|
2171
|
+
|
|
2172
|
+
##
|
|
2173
|
+
## mutable functions
|
|
2174
|
+
##
|
|
2175
|
+
|
|
2176
|
+
# (LHS <= self <= RHS) += (LHS <= other <= RHS)
|
|
2177
|
+
def __iadd__(self, other: Union[float, int, highs_var, highs_linear_expression]):
|
|
2178
|
+
if isinstance(other, highs_var):
|
|
2179
|
+
self.idxs.append(other.index)
|
|
2180
|
+
self.vals.append(1.0)
|
|
2181
|
+
return self
|
|
2182
|
+
|
|
2183
|
+
elif isinstance(other, highs_linear_expression):
|
|
2184
|
+
if self.constant is not None and other.bounds is not None or self.bounds is not None and other.constant is not None:
|
|
2185
|
+
raise Exception("""Cannot add a bounded constraint to a constraint with a constant, i.e., (lb <= expr1 <= ub) + (expr2 + c).
|
|
2186
|
+
Unsure of your intent. Did you want: lb + c <= expr1 + expr2 <= ub + c? Try: (lb <= expr1 <= ub) + (expr2 == c) instead.""")
|
|
2187
|
+
|
|
2188
|
+
self.idxs.extend(other.idxs)
|
|
2189
|
+
self.vals.extend(other.vals)
|
|
2190
|
+
|
|
2191
|
+
if self.constant is not None or other.constant is not None:
|
|
2192
|
+
self.constant = (self.constant or 0.0) + (other.constant or 0.0)
|
|
2193
|
+
|
|
2194
|
+
# (l1 <= expr1 <= u1) + (l2 <= expr2 <= u2) --> l1 + l2 <= expr1 + expr2 <= u1 + u2
|
|
2195
|
+
if self.bounds is not None and other.bounds is not None:
|
|
2196
|
+
self.bounds = (self.bounds[0] + other.bounds[0], self.bounds[1] + other.bounds[1])
|
|
2197
|
+
|
|
2198
|
+
# (expr1) + (lb <= expr2 <= ub) --> lb <= expr1 + expr2 <= ub
|
|
2199
|
+
elif self.bounds is None and other.bounds is not None:
|
|
2200
|
+
self.bounds = other.bounds
|
|
2201
|
+
|
|
2202
|
+
return self
|
|
2203
|
+
|
|
2204
|
+
else:
|
|
2205
|
+
if self.bounds is not None:
|
|
2206
|
+
raise Exception("""Cannot add a constant to a bounded constraint, i.e., (lb <= expr <= ub) + c.
|
|
2207
|
+
Unsure of your intent. Did you want: lb + c <= expr <= ub + c? Try: (lb <= expr <= ub) + (highs_linear_expression() == c) instead.""")
|
|
2208
|
+
|
|
2209
|
+
self.constant = float(other) + (self.constant or 0.0)
|
|
2210
|
+
return self
|
|
2211
|
+
|
|
2212
|
+
def __isub__(self, other: Union[float, int, highs_var, highs_linear_expression]):
|
|
2213
|
+
if isinstance(other, highs_var):
|
|
2214
|
+
self.idxs.append(other.index)
|
|
2215
|
+
self.vals.append(-1.0)
|
|
2216
|
+
return self
|
|
2217
|
+
|
|
2218
|
+
elif isinstance(other, highs_linear_expression):
|
|
2219
|
+
if self.constant is not None and other.bounds is not None or self.bounds is not None and other.constant is not None:
|
|
2220
|
+
raise Exception("""Cannot subtract a bounded constraint to a constraint with a constant, i.e., (lb <= expr1 <= ub) - (expr2 + c).
|
|
2221
|
+
Unsure of your intent. Did you want: lb - c <= expr1 - expr2 <= ub - c? Try: (lb <= expr1 <= ub) - (expr2 == c) instead.""")
|
|
2222
|
+
|
|
2223
|
+
self.idxs.extend(other.idxs)
|
|
2224
|
+
self.vals.extend([-v for v in other.vals])
|
|
2225
|
+
|
|
2226
|
+
if self.constant is not None or other.constant is not None:
|
|
2227
|
+
self.constant = (self.constant or 0.0) - (other.constant or 0.0)
|
|
2228
|
+
|
|
2229
|
+
# (l1 <= expr1 <= u1) - (l2 <= expr2 <= u2) --> l1 - u2 <= expr1 - expr2 <= u1 - l2
|
|
2230
|
+
if self.bounds is not None and other.bounds is not None:
|
|
2231
|
+
self.bounds = (self.bounds[0] - other.bounds[1], self.bounds[1] - other.bounds[0])
|
|
2232
|
+
|
|
2233
|
+
# expr1 - (lb <= expr2 <= ub) --> -ub <= expr1 - expr2 <= -lb
|
|
2234
|
+
elif self.bounds is None and other.bounds is not None:
|
|
2235
|
+
self.bounds = (-other.bounds[1], -other.bounds[0])
|
|
2236
|
+
|
|
2237
|
+
return self
|
|
2238
|
+
|
|
2239
|
+
else:
|
|
2240
|
+
if self.bounds is not None:
|
|
2241
|
+
raise Exception("""Cannot subtract a constant to a bounded constraint, i.e., (lb <= expr <= ub) - c.
|
|
2242
|
+
Unsure of your intent. Did you want: lb - c <= expr <= ub - c? Try: (lb <= expr <= ub) - (highs_linear_expression() == c) instead.""")
|
|
2243
|
+
|
|
2244
|
+
self.constant = (self.constant or 0.0) - float(other)
|
|
2245
|
+
return self
|
|
2246
|
+
|
|
2247
|
+
def __imul__(self, other: Union[float, int, highs_var, highs_linear_expression]):
|
|
2248
|
+
if isinstance(other, (float, int)):
|
|
2249
|
+
scale = float(other)
|
|
2250
|
+
|
|
2251
|
+
# other is a constant expression, so treat as a scalar
|
|
2252
|
+
elif isinstance(other, highs_linear_expression) and other.idxs == [] and other.constant is not None:
|
|
2253
|
+
scale = float(other.constant)
|
|
2254
|
+
else:
|
|
2255
|
+
scale = None
|
|
2256
|
+
|
|
2257
|
+
if scale is not None:
|
|
2258
|
+
self.vals = [scale * v for v in self.vals]
|
|
2259
|
+
|
|
2260
|
+
if self.constant is not None:
|
|
2261
|
+
self.constant *= scale
|
|
2262
|
+
|
|
2263
|
+
if self.bounds is not None:
|
|
2264
|
+
# negative scale reverses bounds
|
|
2265
|
+
if scale >= 0:
|
|
2266
|
+
self.bounds = (scale * self.bounds[0], scale * self.bounds[1])
|
|
2267
|
+
else:
|
|
2268
|
+
self.bounds = (scale * self.bounds[1], scale * self.bounds[0])
|
|
2269
|
+
|
|
2270
|
+
return self
|
|
2271
|
+
|
|
2272
|
+
# self only has a constant, so treat as a scalar
|
|
2273
|
+
elif self.idxs == [] and self.constant is not None:
|
|
2274
|
+
scale = self.constant
|
|
2275
|
+
|
|
2276
|
+
if isinstance(other, highs_linear_expression):
|
|
2277
|
+
self.idxs = other.idxs
|
|
2278
|
+
self.vals = [scale * v for v in other.vals]
|
|
2279
|
+
|
|
2280
|
+
if other.constant is not None:
|
|
2281
|
+
self.constant = other.constant * scale
|
|
2282
|
+
else:
|
|
2283
|
+
self.constant = None
|
|
2284
|
+
|
|
2285
|
+
if other.bounds is not None:
|
|
2286
|
+
# negative scale reverses bounds
|
|
2287
|
+
if scale >= 0:
|
|
2288
|
+
self.bounds = (scale * other.bounds[0], scale * other.bounds[1])
|
|
2289
|
+
else:
|
|
2290
|
+
self.bounds = (scale * other.bounds[1], scale * other.bounds[0])
|
|
2291
|
+
|
|
2292
|
+
elif isinstance(other, highs_var):
|
|
2293
|
+
self.idxs = [other.index]
|
|
2294
|
+
self.vals = [scale]
|
|
2295
|
+
self.constant = None
|
|
2296
|
+
|
|
2297
|
+
else:
|
|
2298
|
+
raise Exception("Unexpected parameters.")
|
|
2299
|
+
|
|
2300
|
+
return self
|
|
2301
|
+
|
|
2302
|
+
elif isinstance(other, highs_var):
|
|
2303
|
+
raise Exception("Only linear expressions are allowed.")
|
|
2304
|
+
|
|
2305
|
+
else:
|
|
2306
|
+
raise Exception("Unexpected parameters.")
|
|
2307
|
+
|
|
2308
|
+
# The following is needed to support chained comparison, i.e., lb <= expr <= ub. This is interpreted
|
|
2309
|
+
# as '__bool__(lb <= expr) and (expr <= ub)'; returning (expr <= ub), since __bool__(lb <= expr) == True.
|
|
2310
|
+
#
|
|
2311
|
+
# We essentially want to "rewrite" this as '(lb <= expr) <= ub', while keeping the expr instance immutable.
|
|
2312
|
+
# As a slight hack, we can use a shared (thread local) object to keep track of the chain.
|
|
2313
|
+
#
|
|
2314
|
+
# Whenever we perform an inequality, we first check if the current expression is part of a chain.
|
|
2315
|
+
# This inner '__chain' is set by __bool__(lb <= expr) and is reset after the inequality is evaluated.
|
|
2316
|
+
#
|
|
2317
|
+
# Two potential issues:
|
|
2318
|
+
# 1. It is possible to manually construct this sequence, e.g.,
|
|
2319
|
+
# tmp = x0 + x1
|
|
2320
|
+
# bool(tmp <= 10)
|
|
2321
|
+
# print(5 <= tmp) # outputs: 5 <= 1.0_v0 + 1.0_v1 <= 10
|
|
2322
|
+
# print(5 <= tmp) # outputs: 5 <= 1.0_v0 + 1.0_v1 <= inf : chain is broken
|
|
2323
|
+
#
|
|
2324
|
+
# Note that:
|
|
2325
|
+
# bool(tmp <= 10)
|
|
2326
|
+
# tmp += x0 + x1 # changes tmp, so the chain is broken
|
|
2327
|
+
# print(5 <= tmp) # outputs: 5 <= 2.0_v0 + 2.0_v1 <= inf
|
|
2328
|
+
#
|
|
2329
|
+
# 2. The chain might "break" if run within a debugger (on same thread), i.e., "watched debugger expressions"
|
|
2330
|
+
# that evaluate any variant of highs_linear_expression inequalities.
|
|
2331
|
+
#
|
|
2332
|
+
# I believe these issues are low risk, the approach thread safe, and the performance/overhead is minimal.
|
|
2333
|
+
#
|
|
2334
|
+
__chain = local()
|
|
2335
|
+
|
|
2336
|
+
# capture the chain
|
|
2337
|
+
def __bool__(self):
|
|
2338
|
+
highs_linear_expression.__chain.check = self
|
|
2339
|
+
|
|
2340
|
+
# take copies of the chain to avoid issues with mutable expressions
|
|
2341
|
+
LHS = getattr(highs_linear_expression.__chain, "left", None)
|
|
2342
|
+
EXR = getattr(highs_linear_expression.__chain, "inner", None)
|
|
2343
|
+
RHS = getattr(highs_linear_expression.__chain, "right", None)
|
|
2344
|
+
|
|
2345
|
+
highs_linear_expression.__chain.left = highs_linear_expression(LHS) if LHS is not None else None
|
|
2346
|
+
highs_linear_expression.__chain.inner = highs_linear_expression(EXR) if EXR is not None else None
|
|
2347
|
+
highs_linear_expression.__chain.right = highs_linear_expression(RHS) if RHS is not None else None
|
|
2348
|
+
return True
|
|
2349
|
+
|
|
2350
|
+
def __is_equal_except_bounds(self, other: highs_linear_expression) -> bool:
|
|
2351
|
+
return self.idxs == other.idxs and self.vals == other.vals and self.constant == other.constant
|
|
2352
|
+
|
|
2353
|
+
def __is_active_chain(self):
|
|
2354
|
+
return getattr(highs_linear_expression.__chain, "check", None) is not None
|
|
2355
|
+
|
|
2356
|
+
def __reset_chain(
|
|
2357
|
+
self,
|
|
2358
|
+
LHS: Optional[Any] = None,
|
|
2359
|
+
inner: Optional[Any] = None,
|
|
2360
|
+
RHS: Optional[Any] = None,
|
|
2361
|
+
) -> None:
|
|
2362
|
+
highs_linear_expression.__chain.check = None
|
|
2363
|
+
highs_linear_expression.__chain.left = LHS
|
|
2364
|
+
highs_linear_expression.__chain.inner = inner
|
|
2365
|
+
highs_linear_expression.__chain.right = RHS
|
|
2366
|
+
|
|
2367
|
+
def __get_chain(self, other: highs_linear_expression, is_ge_than: bool):
|
|
2368
|
+
LHS = getattr(highs_linear_expression.__chain, "left", None)
|
|
2369
|
+
RHS = getattr(highs_linear_expression.__chain, "right", None)
|
|
2370
|
+
inner = getattr(highs_linear_expression.__chain, "inner", None)
|
|
2371
|
+
|
|
2372
|
+
# assume (LHS is None) ^ (RHS is None) == 1, i.e., only LHS or RHS is set
|
|
2373
|
+
assert (LHS is None) ^ (RHS is None) == 1
|
|
2374
|
+
order = np.asarray([expr for expr in [other, LHS, inner, RHS, self] if expr is not None])
|
|
2375
|
+
|
|
2376
|
+
if not is_ge_than: # swap order for: self <= other
|
|
2377
|
+
order[0], order[-1] = order[-1], order[0]
|
|
2378
|
+
|
|
2379
|
+
return order
|
|
2380
|
+
|
|
2381
|
+
# left <= self <= right
|
|
2382
|
+
def __compose_chain(
|
|
2383
|
+
self,
|
|
2384
|
+
left: highs_linear_expression,
|
|
2385
|
+
inner: highs_linear_expression,
|
|
2386
|
+
right: highs_linear_expression,
|
|
2387
|
+
):
|
|
2388
|
+
self.__reset_chain()
|
|
2389
|
+
assert not isinstance(inner, highs_linear_expression) or inner.bounds is None, "Bounds already set in chain comparison."
|
|
2390
|
+
|
|
2391
|
+
# check to see if we have a valid chain, i.e., left.idxs "==" right.idxs
|
|
2392
|
+
# we can assume that left and right are both highs_linear_expression
|
|
2393
|
+
LHS_vars, LHS_vals = left.reduced_elements()
|
|
2394
|
+
RHS_vars, RHS_vals = right.reduced_elements()
|
|
2395
|
+
|
|
2396
|
+
if not np.array_equal(LHS_vars, RHS_vars) or not np.array_equal(LHS_vals, RHS_vals):
|
|
2397
|
+
raise Exception("Mismatched variables in chain comparison.")
|
|
2398
|
+
|
|
2399
|
+
if len(LHS_vars) > len(inner.idxs):
|
|
2400
|
+
copy = highs_linear_expression()
|
|
2401
|
+
copy.idxs = LHS_vars.tolist() + inner.idxs
|
|
2402
|
+
copy.vals = LHS_vals.tolist() + [-v for v in inner.vals]
|
|
2403
|
+
copy.bounds = (
|
|
2404
|
+
(inner.constant or 0.0) - (right.constant or 0.0),
|
|
2405
|
+
(inner.constant or 0.0) - (left.constant or 0.0),
|
|
2406
|
+
)
|
|
2407
|
+
else:
|
|
2408
|
+
copy = highs_linear_expression(inner)
|
|
2409
|
+
copy.idxs.extend(LHS_vars)
|
|
2410
|
+
copy.vals.extend([-v for v in LHS_vals])
|
|
2411
|
+
copy.bounds = (
|
|
2412
|
+
(left.constant or 0.0) - (copy.constant or 0.0),
|
|
2413
|
+
(right.constant or 0.0) - (copy.constant or 0.0),
|
|
2414
|
+
)
|
|
2415
|
+
copy.constant = None
|
|
2416
|
+
|
|
2417
|
+
return copy
|
|
2418
|
+
|
|
2419
|
+
|
|
2420
|
+
def qsum(
|
|
2421
|
+
items: Iterable[Union[highs_var, highs_linear_expression]],
|
|
2422
|
+
initial: Optional[Union[float, int, highs_var, highs_linear_expression]] = None,
|
|
2423
|
+
):
|
|
2424
|
+
"""
|
|
2425
|
+
Performs a faster sum for highs_linear_expressions.
|
|
2426
|
+
|
|
2427
|
+
Args:
|
|
2428
|
+
items: A collection of highs_linear_expressions or highs_vars to be summed.
|
|
2429
|
+
"""
|
|
2430
|
+
return Highs.qsum(items, initial)
|