diff --git a/src/highs_bindings.cpp b/src/highs_bindings.cpp index 972b8a6719..69b36310a7 100644 --- a/src/highs_bindings.cpp +++ b/src/highs_bindings.cpp @@ -577,6 +577,15 @@ std::tuple highs_getRowByName(Highs* h, } +HighsStatus highs_run(Highs* h) +{ + py::gil_scoped_release release; + HighsStatus status = h->run(); + py::gil_scoped_acquire(); + return status; +} + + PYBIND11_MODULE(_core, m) { // enum classes py::enum_(m, "ObjSense") @@ -874,7 +883,7 @@ PYBIND11_MODULE(_core, m) { .def("writeBasis", &Highs::writeBasis) .def("postsolve", &highs_postsolve) .def("postsolve", &highs_mipPostsolve) - .def("run", &Highs::run) + .def("run", &highs_run) .def("feasibilityRelaxation", [](Highs& self, double global_lower_penalty, double global_upper_penalty, double global_rhs_penalty, py::object local_lower_penalty, py::object local_upper_penalty, py::object local_rhs_penalty) { diff --git a/src/highspy/highs.py b/src/highspy/highs.py index 4d4f4e05c2..bdc1710ded 100644 --- a/src/highspy/highs.py +++ b/src/highspy/highs.py @@ -36,6 +36,13 @@ from itertools import groupby, product from operator import itemgetter from decimal import Decimal +from threading import Thread + + +class _ThreadingResult: + def __init__(self): + self.out = None + class Highs(_Highs): """HiGHS solver interface""" @@ -47,6 +54,12 @@ def __init__(self): def silent(self): """Disables solver output to the console.""" super().setOptionValue("output_flag", False) + + def _run(self, res): + res.out = super().run() + + def run(self): + return self.solve() # solve def solve(self): @@ -55,11 +68,15 @@ def solve(self): Returns: A HighsStatus object containing the solve status. """ - return super().run() + res = _ThreadingResult() + t = Thread(target=self._run, args=(res,)) + t.start() + t.join() + return res.out def optimize(self): """Alias for the solve method.""" - return super().run() + return self.solve() # reset the objective and sense, then solve def minimize(self, obj=None): @@ -91,7 +108,7 @@ def minimize(self, obj=None): super().changeObjectiveOffset(obj.constant) super().changeObjectiveSense(ObjSense.kMinimize) - return super().run() + return self.solve() # reset the objective and sense, then solve def maximize(self, obj=None): @@ -123,7 +140,7 @@ def maximize(self, obj=None): super().changeObjectiveOffset(obj.constant) super().changeObjectiveSense(ObjSense.kMaximize) - return super().run() + return self.solve() def internal_get_value(self, var_index_collection, col_value): """Internal method to get the value of a variable in the solution. Could be value or dual."""