Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Print names of events and current stage #769

Merged
merged 9 commits into from
Dec 30, 2023
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## Unreleased
### Added
- Added methods for getting the names of the current stage and of an event
- Added all event types and tests for checking them
- Added SCIP functions SCIPconsGetNVars, SCIPconsGetVars
- Added SCIP functions SCIPchgCoefLinear, SCIPaddCoefLinear and SCIPdelCoefLinear
Expand Down
31 changes: 31 additions & 0 deletions src/pyscipopt/scip.pxi
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ cdef class PY_SCIP_STATUS:
UNBOUNDED = SCIP_STATUS_UNBOUNDED
INFORUNBD = SCIP_STATUS_INFORUNBD

StageNames = {}

cdef class PY_SCIP_STAGE:
INIT = SCIP_STAGE_INIT
PROBLEM = SCIP_STAGE_PROBLEM
Expand Down Expand Up @@ -165,6 +167,8 @@ cdef class PY_SCIP_HEURTIMING:
DURINGPRESOLLOOP = SCIP_HEURTIMING_DURINGPRESOLLOOP
AFTERPROPLOOP = SCIP_HEURTIMING_AFTERPROPLOOP

EventNames = {}

cdef class PY_SCIP_EVENTTYPE:
DISABLED = SCIP_EVENTTYPE_DISABLED
VARADDED = SCIP_EVENTTYPE_VARADDED
Expand Down Expand Up @@ -221,6 +225,7 @@ cdef class PY_SCIP_EVENTTYPE:
ROWCHANGED = SCIP_EVENTTYPE_ROWCHANGED
ROWEVENT = SCIP_EVENTTYPE_ROWEVENT


cdef class PY_SCIP_LPSOLSTAT:
NOTSOLVED = SCIP_LPSOLSTAT_NOTSOLVED
OPTIMAL = SCIP_LPSOLSTAT_OPTIMAL
Expand Down Expand Up @@ -305,6 +310,19 @@ cdef class Event:
"""gets type of event"""
return SCIPeventGetType(self.event)

def getName(self):
"""gets name of event"""
if not EventNames:
self._getEventNames()
return EventNames[self.getType()]

def _getEventNames(self):
"""gets event names"""
for name in dir(PY_SCIP_EVENTTYPE):
attr = getattr(PY_SCIP_EVENTTYPE, name)
if isinstance(attr, int):
EventNames[attr] = name

mmghannam marked this conversation as resolved.
Show resolved Hide resolved
def __repr__(self):
return self.getType()
Joao-Dionisio marked this conversation as resolved.
Show resolved Hide resolved

Expand Down Expand Up @@ -4692,6 +4710,19 @@ cdef class Model:
def getStage(self):
"""Retrieve current SCIP stage"""
return SCIPgetStage(self._scip)

def getStageName(self):
"""Returns name of current stage as string"""
if not StageNames:
self._getStageNames()
return StageNames[self.getStage()]

def _getStageNames(self):
"""Gets names of stages"""
for name in dir(PY_SCIP_STAGE):
attr = getattr(PY_SCIP_STAGE, name)
if isinstance(attr, int):
StageNames[attr] = name

def getStatus(self):
"""Retrieve solution status."""
Expand Down
6 changes: 2 additions & 4 deletions tests/test_event.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ def eventinit(self):
# self.model.dropEvent(self.event_type, self)

def eventexec(self, event):
assert type(event.getName()) == str

calls.append('eventexec')
if self.event_type == SCIP_EVENTTYPE.LPEVENT:
assert event.getType() in [SCIP_EVENTTYPE.FIRSTLPSOLVED, SCIP_EVENTTYPE.LPSOLVED]
Expand Down Expand Up @@ -61,10 +63,6 @@ def test_event():

all_events = [SCIP_EVENTTYPE.DISABLED,SCIP_EVENTTYPE.VARADDED,SCIP_EVENTTYPE.VARDELETED,SCIP_EVENTTYPE.VARFIXED,SCIP_EVENTTYPE.VARUNLOCKED,SCIP_EVENTTYPE.OBJCHANGED,SCIP_EVENTTYPE.GLBCHANGED,SCIP_EVENTTYPE.GUBCHANGED,SCIP_EVENTTYPE.LBTIGHTENED,SCIP_EVENTTYPE.LBRELAXED,SCIP_EVENTTYPE.UBTIGHTENED,SCIP_EVENTTYPE.UBRELAXED,SCIP_EVENTTYPE.GHOLEADDED,SCIP_EVENTTYPE.GHOLEREMOVED,SCIP_EVENTTYPE.LHOLEADDED,SCIP_EVENTTYPE.LHOLEREMOVED,SCIP_EVENTTYPE.IMPLADDED,SCIP_EVENTTYPE.PRESOLVEROUND,SCIP_EVENTTYPE.NODEFOCUSED,SCIP_EVENTTYPE.NODEFEASIBLE,SCIP_EVENTTYPE.NODEINFEASIBLE,SCIP_EVENTTYPE.NODEBRANCHED,SCIP_EVENTTYPE.NODEDELETE,SCIP_EVENTTYPE.FIRSTLPSOLVED,SCIP_EVENTTYPE.LPSOLVED,SCIP_EVENTTYPE.POORSOLFOUND,SCIP_EVENTTYPE.BESTSOLFOUND,SCIP_EVENTTYPE.ROWADDEDSEPA,SCIP_EVENTTYPE.ROWDELETEDSEPA,SCIP_EVENTTYPE.ROWADDEDLP,SCIP_EVENTTYPE.ROWDELETEDLP,SCIP_EVENTTYPE.ROWCOEFCHANGED,SCIP_EVENTTYPE.ROWCONSTCHANGED,SCIP_EVENTTYPE.ROWSIDECHANGED,SCIP_EVENTTYPE.SYNC,SCIP_EVENTTYPE.GBDCHANGED,SCIP_EVENTTYPE.LBCHANGED,SCIP_EVENTTYPE.UBCHANGED,SCIP_EVENTTYPE.BOUNDTIGHTENED,SCIP_EVENTTYPE.BOUNDRELAXED,SCIP_EVENTTYPE.BOUNDCHANGED,SCIP_EVENTTYPE.LHOLECHANGED,SCIP_EVENTTYPE.HOLECHANGED,SCIP_EVENTTYPE.DOMCHANGED,SCIP_EVENTTYPE.VARCHANGED,SCIP_EVENTTYPE.VAREVENT,SCIP_EVENTTYPE.NODESOLVED,SCIP_EVENTTYPE.NODEEVENT,SCIP_EVENTTYPE.LPEVENT,SCIP_EVENTTYPE.SOLFOUND,SCIP_EVENTTYPE.SOLEVENT,SCIP_EVENTTYPE.ROWCHANGED,SCIP_EVENTTYPE.ROWEVENT]


for i in [20]:
print(SCIP_EVENTTYPE.NODEINFEASIBLE)

all_event_hdlrs = []
for event in all_events:
s = Model()
Expand Down
22 changes: 20 additions & 2 deletions tests/test_model.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import pytest

from pyscipopt import Model
from pyscipopt import Model, SCIP_STAGE

def test_model():
# create solver instance
Expand Down Expand Up @@ -267,4 +267,22 @@ def test_objLim():
m.setObjlimit(2)
m.optimize()
assert m.getNLimSolsFound() == 1


def test_getStage():
m = Model()

assert m.getStage() == SCIP_STAGE.PROBLEM
assert m.getStageName() == "PROBLEM"

x = m.addVar()
m.addCons(x >= 1)

print(m.getStage())
assert m.getStage() == SCIP_STAGE.PROBLEM
assert m.getStageName() == "PROBLEM"

m.optimize()

print(m.getStage())
assert m.getStage() == SCIP_STAGE.SOLVED
assert m.getStageName() == "SOLVED"