From db549777e27b8ff7196fea50f441cd84a5debc39 Mon Sep 17 00:00:00 2001 From: Matthias Miltenberger Date: Sat, 30 Oct 2021 13:39:36 +0200 Subject: [PATCH 1/2] fix concurrent solve test --- tests/test_lp_concurrent.py | 25 ------------------------- tests/test_model.py | 13 +++++++++++++ 2 files changed, 13 insertions(+), 25 deletions(-) delete mode 100644 tests/test_lp_concurrent.py diff --git a/tests/test_lp_concurrent.py b/tests/test_lp_concurrent.py deleted file mode 100644 index 42004f473..000000000 --- a/tests/test_lp_concurrent.py +++ /dev/null @@ -1,25 +0,0 @@ -from pyscipopt import LP - -def test_lp(): - # create LP instance, minimizing by default - myLP = LP() - - # create cols w/o coefficients, 0 objective coefficient and 0,\infty bounds - myLP.addCols(2 * [[]]) - - # create rows - myLP.addRow(entries = [(0,1),(1,2)] ,lhs = 5) - lhs, rhs = myLP.getSides() - assert lhs[0] == 5.0 - assert rhs[0] == myLP.infinity() - - assert(myLP.ncols() == 2) - myLP.chgObj(0, 1.0) - myLP.chgObj(1, 4.0) - - solval = myLP.solveConcurrent() - - assert round(5.0 == solval) - -if __name__ == "__main__": - test_lp() diff --git a/tests/test_model.py b/tests/test_model.py index 0eaf655b8..f86fac33b 100644 --- a/tests/test_model.py +++ b/tests/test_model.py @@ -78,6 +78,15 @@ def test_model(): assert s.getStatus() == 'unbounded' +def test_solve_concurrent(): + s = Model() + x = s.addVar("x", vtype = 'C', obj = 1.0) + y = s.addVar("y", vtype = 'C', obj = 2.0) + c = s.addCons(x + y <= 10.0) + s.setMaximize() + s.solveConcurrent() + assert s.getStatus() == 'optimal' + assert s.getObjVal() == 20.0 def test_multiple_cons_simple(): def assert_conss_eq(a, b): @@ -177,4 +186,8 @@ def test_model_ptr(): if __name__ == "__main__": test_model() + test_solve_concurrent() + test_multiple_cons_simple() + test_multiple_cons_names() + test_multiple_cons_params() test_model_ptr() From 62445e65178550eec222a2b585f232c6a80e749f Mon Sep 17 00:00:00 2001 From: Matthias Miltenberger Date: Sat, 30 Oct 2021 14:02:01 +0200 Subject: [PATCH 2/2] add check for available TPI for concurrent solve --- src/pyscipopt/scip.pxd | 3 +++ src/pyscipopt/scip.pyx | 8 ++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/pyscipopt/scip.pxd b/src/pyscipopt/scip.pxd index 8e39c1a82..d2bfbfdfe 100644 --- a/src/pyscipopt/scip.pxd +++ b/src/pyscipopt/scip.pxd @@ -1681,6 +1681,9 @@ cdef extern from "scip/scip_tree.h": cdef extern from "scip/scip_var.h": SCIP_RETCODE SCIPchgVarBranchPriority(SCIP* scip, SCIP_VAR* var, int branchpriority) +cdef extern from "tpi/tpi.h": + int SCIPtpiGetNumThreads() + cdef class Expr: cdef public terms diff --git a/src/pyscipopt/scip.pyx b/src/pyscipopt/scip.pyx index 17da39408..78ad7d24f 100644 --- a/src/pyscipopt/scip.pyx +++ b/src/pyscipopt/scip.pyx @@ -3096,8 +3096,12 @@ cdef class Model: def solveConcurrent(self): """Transforms, presolves, and solves problem using additional solvers which emphasize on finding solutions.""" - PY_SCIP_CALL(SCIPsolveConcurrent(self._scip)) - self._bestSol = Solution.create(self._scip, SCIPgetBestSol(self._scip)) + if SCIPtpiGetNumThreads() == 1: + warnings.warn("SCIP was compiled without task processing interface. Parallel solve not possible - using optimize() instead of solveConcurrent()") + self.optimize() + else: + PY_SCIP_CALL(SCIPsolveConcurrent(self._scip)) + self._bestSol = Solution.create(self._scip, SCIPgetBestSol(self._scip)) def presolve(self): """Presolve the problem."""