From c3c2d3ac022d7017ad30f5b4c55f177f55204a10 Mon Sep 17 00:00:00 2001 From: Arnaud Baguet Date: Thu, 5 Dec 2024 19:32:17 -0500 Subject: [PATCH] fix #1947 --- src/Highs.h | 8 ++++++-- src/highs_bindings.cpp | 28 +++++++++++++++++----------- src/simplex/HEkk.cpp | 8 ++++++-- src/simplex/HEkk.h | 9 +++++---- 4 files changed, 34 insertions(+), 19 deletions(-) diff --git a/src/Highs.h b/src/Highs.h index 34d1044f5f..c9a6088f48 100644 --- a/src/Highs.h +++ b/src/Highs.h @@ -456,9 +456,13 @@ class Highs { const HighsModel& getModel() const { return model_; } /** - * @brief Return a const reference to the internal HighsSolution instance + * @brief Get the status of both primal and dual solutions + * @return A pair containing the primal solution status (first) and dual + * solution status (second) */ - const HighsSolution& getSolution() const { return solution_; } + std::pair getSolutionStatus() const { + return ekk_instance_.getSolutionStatus(); + } /** * @brief Zero all clocks in the internal HighsTimer instance diff --git a/src/highs_bindings.cpp b/src/highs_bindings.cpp index b8f7e249cf..2d8232bd8c 100644 --- a/src/highs_bindings.cpp +++ b/src/highs_bindings.cpp @@ -537,8 +537,8 @@ highs_getColsEntries(Highs* h, HighsInt num_set_entries, py::cast(value)); } -std::tuple -highs_getColIntegrality(Highs* h, HighsInt col) { +std::tuple highs_getColIntegrality(Highs* h, + HighsInt col) { HighsInt col_ = static_cast(col); HighsVarType integrality; HighsStatus status = h->getColIntegrality(col_, integrality); @@ -621,19 +621,23 @@ std::tuple highs_getRowByName(Highs* h, } // Wrap the setCallback function to appropriately handle user data. -// pybind11 automatically ensures GIL is re-acquired when the callback is called. +// pybind11 automatically ensures GIL is re-acquired when the callback is +// called. HighsStatus highs_setCallback( Highs* h, - std::function fn, + std::function + fn, py::handle data) { if (static_cast(fn) == false) return h->setCallback((HighsCallbackFunctionType) nullptr, nullptr); else return h->setCallback( [fn](int callbackType, const std::string& msg, - const HighsCallbackDataOut* dataOut, - HighsCallbackDataIn* dataIn, void* d) { - return fn(callbackType, msg, dataOut, dataIn, py::handle(reinterpret_cast(d))); + const HighsCallbackDataOut* dataOut, HighsCallbackDataIn* dataIn, + void* d) { + return fn(callbackType, msg, dataOut, dataIn, + py::handle(reinterpret_cast(d))); }, data.ptr()); } @@ -749,7 +753,8 @@ PYBIND11_MODULE(_core, m) { .value("kHighsDebugLevelNone", HighsDebugLevel::kHighsDebugLevelNone) .value("kHighsDebugLevelCheap", HighsDebugLevel::kHighsDebugLevelCheap) .value("kHighsDebugLevelCostly", HighsDebugLevel::kHighsDebugLevelCostly) - .value("kHighsDebugLevelExpensive", HighsDebugLevel::kHighsDebugLevelExpensive) + .value("kHighsDebugLevelExpensive", + HighsDebugLevel::kHighsDebugLevelExpensive) .value("kHighsDebugLevelMin", HighsDebugLevel::kHighsDebugLevelMin) .value("kHighsDebugLevelMax", HighsDebugLevel::kHighsDebugLevelMax) .export_values(); @@ -833,8 +838,7 @@ PYBIND11_MODULE(_core, m) { &HighsInfo::max_complementarity_violation) .def_readwrite("sum_complementarity_violations", &HighsInfo::sum_complementarity_violations) - .def_readwrite("primal_dual_integral", - &HighsInfo::primal_dual_integral); + .def_readwrite("primal_dual_integral", &HighsInfo::primal_dual_integral); py::class_(m, "HighsOptions") .def(py::init<>()) .def_readwrite("presolve", &HighsOptions::presolve) @@ -982,7 +986,8 @@ PYBIND11_MODULE(_core, m) { py::arg("local_upper_penalty") = py::none(), py::arg("local_rhs_penalty") = py::none()) .def("getIis", &Highs::getIis) - .def("presolve", &Highs::presolve, py::call_guard()) + .def("presolve", &Highs::presolve, + py::call_guard()) .def("writeSolution", &highs_writeSolution) .def("readSolution", &Highs::readSolution) .def("setOptionValue", @@ -1027,6 +1032,7 @@ PYBIND11_MODULE(_core, m) { // &highs_getModelStatus not needed once getModelStatus(const bool // scaled_model) disappears from, Highs.h .def("getModelStatus", &highs_getModelStatus) //&Highs::getModelStatus) + .def("getSolutionStatus", &Highs::getSolutionStatus) .def("getModelPresolveStatus", &Highs::getModelPresolveStatus) .def("getRanging", &highs_getRanging) .def("getObjectiveValue", &Highs::getObjectiveValue) diff --git a/src/simplex/HEkk.cpp b/src/simplex/HEkk.cpp index dc30e2cc7e..a1ca0404a1 100644 --- a/src/simplex/HEkk.cpp +++ b/src/simplex/HEkk.cpp @@ -140,8 +140,8 @@ void HEkk::clearEkkData() { this->solve_bailout_ = false; this->called_return_from_solve_ = false; this->exit_algorithm_ = SimplexAlgorithm::kNone; - this->return_primal_solution_status_ = 0; - this->return_dual_solution_status_ = 0; + this->return_primal_solution_status_ = SolutionStatus::kSolutionStatusNone; + this->return_dual_solution_status_ = SolutionStatus::kSolutionStatusNone; this->proof_index_.clear(); this->proof_value_.clear(); @@ -1413,6 +1413,10 @@ HighsSolution HEkk::getSolution() { return solution; } +std::pair HEkk::getSolutionStatus() const { + return {return_primal_solution_status_, return_dual_solution_status_}; +} + HighsBasis HEkk::getHighsBasis(HighsLp& use_lp) const { HighsInt num_col = use_lp.num_col_; HighsInt num_row = use_lp.num_row_; diff --git a/src/simplex/HEkk.h b/src/simplex/HEkk.h index 3b3da389da..98d7bccdbc 100644 --- a/src/simplex/HEkk.h +++ b/src/simplex/HEkk.h @@ -42,8 +42,8 @@ class HEkk { solve_bailout_(false), called_return_from_solve_(false), exit_algorithm_(SimplexAlgorithm::kNone), - return_primal_solution_status_(0), - return_dual_solution_status_(0), + return_primal_solution_status_(SolutionStatus::kSolutionStatusNone), + return_dual_solution_status_(SolutionStatus::kSolutionStatusNone), original_num_col_(0), original_num_row_(0), original_num_nz_(0), @@ -131,6 +131,7 @@ class HEkk { HVector& residual, double& residual_norm); HighsSolution getSolution(); + std::pair getSolutionStatus() const; HighsBasis getHighsBasis(HighsLp& use_lp) const; const SimplexBasis& getSimplexBasis() { return basis_; } @@ -206,8 +207,8 @@ class HEkk { bool solve_bailout_; bool called_return_from_solve_; SimplexAlgorithm exit_algorithm_; - HighsInt return_primal_solution_status_; - HighsInt return_dual_solution_status_; + SolutionStatus return_primal_solution_status_; + SolutionStatus return_dual_solution_status_; // Data to be retained after proving primal infeasibility vector proof_index_;