Skip to content

Commit b81f554

Browse files
committed
Add getBase and setBase methods to LP class
1 parent ffb41fb commit b81f554

4 files changed

Lines changed: 86 additions & 0 deletions

File tree

src/pyscipopt/lp.pxi

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,70 @@ cdef class LP:
531531

532532
return binds
533533

534+
def getBase(self):
535+
"""Returns the basis status of columns and rows.
536+
537+
Column status values: SCIP_BASESTAT_LOWER (0), SCIP_BASESTAT_BASIC (1),
538+
SCIP_BASESTAT_UPPER (2), SCIP_BASESTAT_ZERO (3).
539+
540+
Row status values: SCIP_BASESTAT_LOWER (0), SCIP_BASESTAT_BASIC (1),
541+
SCIP_BASESTAT_UPPER (2).
542+
543+
Returns
544+
-------
545+
tuple of (list of int, list of int)
546+
Column basis statuses and row basis statuses.
547+
548+
"""
549+
cdef int ncols = self.ncols()
550+
cdef int nrows = self.nrows()
551+
cdef int* c_cstat = <int*> malloc(ncols * sizeof(int))
552+
cdef int* c_rstat = <int*> malloc(nrows * sizeof(int))
553+
cdef int i
554+
555+
PY_SCIP_CALL(SCIPlpiGetBase(self.lpi, c_cstat, c_rstat))
556+
557+
cstat = [c_cstat[i] for i in range(ncols)]
558+
rstat = [c_rstat[i] for i in range(nrows)]
559+
560+
free(c_rstat)
561+
free(c_cstat)
562+
563+
return cstat, rstat
564+
565+
def setBase(self, cstat, rstat):
566+
"""Sets the basis status of columns and rows.
567+
568+
Column status values: SCIP_BASESTAT_LOWER (0), SCIP_BASESTAT_BASIC (1),
569+
SCIP_BASESTAT_UPPER (2), SCIP_BASESTAT_ZERO (3).
570+
571+
Row status values: SCIP_BASESTAT_LOWER (0), SCIP_BASESTAT_BASIC (1),
572+
SCIP_BASESTAT_UPPER (2).
573+
574+
Parameters
575+
----------
576+
cstat : list of int
577+
Column basis statuses (length must equal ncols).
578+
rstat : list of int
579+
Row basis statuses (length must equal nrows).
580+
581+
"""
582+
cdef int ncols = len(cstat)
583+
cdef int nrows = len(rstat)
584+
cdef int* c_cstat = <int*> malloc(ncols * sizeof(int))
585+
cdef int* c_rstat = <int*> malloc(nrows * sizeof(int))
586+
cdef int i
587+
588+
for i in range(ncols):
589+
c_cstat[i] = cstat[i]
590+
for i in range(nrows):
591+
c_rstat[i] = rstat[i]
592+
593+
PY_SCIP_CALL(SCIPlpiSetBase(self.lpi, c_cstat, c_rstat))
594+
595+
free(c_rstat)
596+
free(c_cstat)
597+
534598
# Parameter Methods
535599

536600
def setIntParam(self, param, value):

src/pyscipopt/scip.pxd

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1532,6 +1532,8 @@ cdef extern from "scip/scip.h":
15321532
SCIP_RETCODE SCIPlpiGetPrimalRay(SCIP_LPI* lpi, SCIP_Real* ray)
15331533
SCIP_RETCODE SCIPlpiGetDualfarkas(SCIP_LPI* lpi, SCIP_Real* dualfarkas)
15341534
SCIP_RETCODE SCIPlpiGetBasisInd(SCIP_LPI* lpi, int* bind)
1535+
SCIP_RETCODE SCIPlpiGetBase(SCIP_LPI* lpi, int* cstat, int* rstat)
1536+
SCIP_RETCODE SCIPlpiSetBase(SCIP_LPI* lpi, const int* cstat, const int* rstat)
15351537
SCIP_RETCODE SCIPlpiGetRealSolQuality(SCIP_LPI* lpi, SCIP_LPSOLQUALITY qualityindicator, SCIP_Real* quality)
15361538
SCIP_RETCODE SCIPlpiGetIntpar(SCIP_LPI* lpi, SCIP_LPPARAM type, int* ival)
15371539
SCIP_RETCODE SCIPlpiGetRealpar(SCIP_LPI* lpi, SCIP_LPPARAM type, SCIP_Real* dval)

src/pyscipopt/scip.pyi

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,7 @@ class LP:
467467
def delCols(self, firstcol: Incomplete, lastcol: Incomplete) -> Incomplete: ...
468468
def delRows(self, firstrow: Incomplete, lastrow: Incomplete) -> Incomplete: ...
469469
def getActivity(self) -> Incomplete: ...
470+
def getBase(self) -> Incomplete: ...
470471
def getBasisInds(self) -> Incomplete: ...
471472
def getBounds(
472473
self, firstcol: Incomplete = ..., lastcol: Incomplete = ...
@@ -491,6 +492,7 @@ class LP:
491492
def ncols(self) -> Incomplete: ...
492493
def nrows(self) -> Incomplete: ...
493494
def readLP(self, filename: Incomplete) -> Incomplete: ...
495+
def setBase(self, cstat: Incomplete, rstat: Incomplete) -> Incomplete: ...
494496
def setIntParam(self, param: Incomplete, value: Incomplete) -> Incomplete: ...
495497
def setRealParam(self, param: Incomplete, value: Incomplete) -> Incomplete: ...
496498
def solve(self, dual: Incomplete = ...) -> Incomplete: ...

tests/test_lp.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,21 @@ def test_lp():
8989

9090
assert round(myLP.getObjVal() == solval)
9191
assert round(5.0 == solval)
92+
93+
# test basis get/set
94+
binds = myLP.getBasisInds()
95+
assert len(binds) == myLP.nrows()
96+
97+
cstat, rstat = myLP.getBase()
98+
assert len(cstat) == myLP.ncols()
99+
assert len(rstat) == myLP.nrows()
100+
101+
# set the same basis back and re-solve
102+
myLP.setBase(cstat, rstat)
103+
solval2 = myLP.solve()
104+
assert round(solval2, 10) == round(solval, 10)
105+
106+
# verify basis is preserved after set
107+
cstat2, rstat2 = myLP.getBase()
108+
assert cstat2 == cstat
109+
assert rstat2 == rstat

0 commit comments

Comments
 (0)