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
8 changes: 1 addition & 7 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,7 @@

## Unreleased
### Added
- Add getConshdlrName to class Constraint
mmghannam marked this conversation as resolved.
Show resolved Hide resolved
### Fixed
### Changed
### Removed

## 4.4.0 - 2023-12-04
### 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
36 changes: 35 additions & 1 deletion src/pyscipopt/scip.pxi
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@
UNBOUNDED = SCIP_STATUS_UNBOUNDED
INFORUNBD = SCIP_STATUS_INFORUNBD

StageNames = {}

Check warning on line 113 in src/pyscipopt/scip.pxi

View check run for this annotation

Codecov / codecov/patch

src/pyscipopt/scip.pxi#L113

Added line #L113 was not covered by tests

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

EventNames = {}

Check warning on line 170 in src/pyscipopt/scip.pxi

View check run for this annotation

Codecov / codecov/patch

src/pyscipopt/scip.pxi#L170

Added line #L170 was not covered by tests

cdef class PY_SCIP_EVENTTYPE:
DISABLED = SCIP_EVENTTYPE_DISABLED
VARADDED = SCIP_EVENTTYPE_VARADDED
Expand Down Expand Up @@ -221,6 +225,7 @@
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,8 +310,24 @@
"""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()
return str(self.getType())

Check warning on line 327 in src/pyscipopt/scip.pxi

View check run for this annotation

Codecov / codecov/patch

src/pyscipopt/scip.pxi#L327

Added line #L327 was not covered by tests

def __str__(self):
return self.getName()

def getNewBound(self):
"""gets new bound for a bound change event"""
Expand Down Expand Up @@ -4702,6 +4723,19 @@
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
7 changes: 3 additions & 4 deletions tests/test_event.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ def eventinit(self):
# self.model.dropEvent(self.event_type, self)

def eventexec(self, event):
assert str(event) == event.getName()
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 +64,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"
Loading