Skip to content

Commit ae60d7e

Browse files
committed
IISfinder progress
1 parent 81395b2 commit ae60d7e

File tree

4 files changed

+112
-52
lines changed

4 files changed

+112
-52
lines changed

src/pyscipopt/iisfinder.pxi

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
##@file iisfinder.pxi
2-
#@brief Base class of the Relaxator Plugin
3-
cdef class IISFinder:
2+
#@brief Base class of the IIS finder Plugin
3+
cdef class IISfinder:
44
cdef public Model model
55
cdef public str name
66

@@ -11,27 +11,27 @@ cdef class IISFinder:
1111
def iisfinderexec(self):
1212
'''calls execution method of iis finder'''
1313
raise NotImplementedError("iisfinderexec() is a fundamental callback and should be implemented in the derived class")
14-
1514

16-
cdef SCIP_RETCODE PyIISFinderCopy (SCIP* scip, SCIP_IISFINDER* iisfinder) noexcept with gil:
15+
16+
cdef SCIP_RETCODE PyiisfinderCopy (SCIP* scip, SCIP_IISFINDER* iisfinder) noexcept with gil:
1717
return SCIP_OKAY
1818

19-
cdef SCIP_RETCODE PyIISFinderFree (SCIP* scip, SCIP_IISFINDER* iisfinder) noexcept with gil:
19+
cdef SCIP_RETCODE PyiisfinderFree (SCIP* scip, SCIP_IISFINDER* iisfinder) noexcept with gil:
2020
cdef SCIP_IISFINDERDATA* iisfinderdata
21-
iisfinderdata = SCIPIISfinderGetData(iisfinder)
22-
PyRelax = <Relax>iisfinderdata
23-
PyRelax.iisfinderfree()
24-
Py_DECREF(PyRelax)
21+
iisfinderdata = SCIPiisfinderGetData(iisfinder)
22+
PyIIS = <IISfinder>iisfinderdata
23+
PyIIS.iisfinderfree()
24+
Py_DECREF(PyIIS)
2525
return SCIP_OKAY
2626

27-
cdef SCIP_RETCODE PyRelaxExec (SCIP* scip, SCIP_IISFINDER* iisfinder, SCIP_Real* lowerbound, SCIP_RESULT* result) noexcept with gil:
27+
cdef SCIP_RETCODE PyiisfinderExec (SCIP_IIS* iis, SCIP_IISFINDER* iisfinder, SCIP_Real timelim, SCIP_Longint nodelim, SCIP_Bool removebounds, SCIP_Bool silent, SCIP_RESULT* result) noexcept with gil:
2828
cdef SCIP_IISFINDERDATA* iisfinderdata
2929
iisfinderdata = SCIPiisfinderGetData(iisfinder)
30-
PyRelax = <Relax>iisfinderdata
31-
result_dict = PyRelax.iisfinderexec()
30+
PyIIS = <IISfinder>iisfinderdata
31+
result_dict = PyIIS.iisfinderexec()
3232
assert isinstance(result_dict, dict), "iisfinderexec() must return a dictionary."
3333
#TODO
3434
assert False
35-
lowerbound[0] = result_dict.get("lowerbound", <SCIP_Real>lowerbound[0])
36-
result[0] = result_dict.get("result", <SCIP_RESULT>result[0])
37-
return SCIP_OKAY
35+
# lowerbound[0] = result_dict.get("lowerbound", <SCIP_Real>lowerbound[0])
36+
# result[0] = result_dict.get("result", <SCIP_RESULT>result[0])
37+
# return SCIP_OKAY

src/pyscipopt/scip.pxd

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1184,15 +1184,19 @@ cdef extern from "scip/scip.h":
11841184
SCIP_HEURTIMING SCIPheurGetTimingmask(SCIP_HEUR* heur)
11851185
void SCIPheurSetTimingmask(SCIP_HEUR* heur, SCIP_HEURTIMING timingmask)
11861186

1187-
# #IIS finder plugin
1188-
# SCIP_RETCODE SCIPincludeIISFinder(SCIP* scip,
1189-
# const char* name,
1190-
# const char* desc,
1191-
# int priority,
1192-
# SCIP_RETCODE (*iisfindercopy) (SCIP* scip, SCIP_IISFINDER* iisfinder),
1193-
# SCIP_RETCODE (*iisfinderfree) (SCIP* scip, SCIP_IISFINDER* iisfinder),
1194-
# SCIP_RETCODE (*iisfinderexec) (SCIP_IIS* iis, SCIP_IISFINDER* iisfinder, SCIP_Real timelim, SCIP_Longint nodelim, SCIP_Bool removebounds, SCIP_Bool silent, SCIP_RESULT* result),
1195-
# SCIP_IISFINDERDATA* iisfinderdata)
1187+
#IIS finder plugin
1188+
SCIP_RETCODE SCIPincludeIISfinder(SCIP* scip,
1189+
const char* name,
1190+
const char* desc,
1191+
int priority,
1192+
SCIP_RETCODE (*iisfindercopy) (SCIP* scip, SCIP_IISFINDER* iisfinder),
1193+
SCIP_RETCODE (*iisfinderfree) (SCIP* scip, SCIP_IISFINDER* iisfinder),
1194+
SCIP_RETCODE (*iisfinderexec) (SCIP_IIS* iis, SCIP_IISFINDER* iisfinder, SCIP_Real timelim, SCIP_Longint nodelim, SCIP_Bool removebounds, SCIP_Bool silent, SCIP_RESULT* result),
1195+
SCIP_IISFINDERDATA* iisfinderdata)
1196+
1197+
SCIP_IISFINDERDATA* SCIPiisfinderGetData(SCIP_IISFINDER* iisfinder)
1198+
SCIP_RETCODE SCIPincludeIISfinderGreedy(SCIP* scip)
1199+
SCIP_RETCODE SCIPiisGreedyMinimize(SCIP_IIS* iis);
11961200

11971201
#Relaxation plugin
11981202
SCIP_RETCODE SCIPincludeRelax(SCIP* scip,

src/pyscipopt/scip.pxi

Lines changed: 50 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ include "conshdlr.pxi"
3131
include "cutsel.pxi"
3232
include "event.pxi"
3333
include "heuristic.pxi"
34-
# include "iisfinder.pxi"
34+
include "iisfinder.pxi"
3535
include "presol.pxi"
3636
include "pricer.pxi"
3737
include "propagator.pxi"
@@ -8545,7 +8545,10 @@ cdef class Model:
85458545
maxdepth : int, optional
85468546
maximal depth level to call heuristic at (Default value = -1)
85478547
timingmask : PY_SCIP_HEURTIMING, optional
8548-
positions in the node solving loop where heuristic should be executed
8548+
positions in the node solvingreturn {
8549+
'result': SCIP_RESULT.SUCCESS,
8550+
'lowerbound': 10e4
8551+
} loop where heuristic should be executed
85498552
(Default value = SCIP_HEURTIMING_BEFORENODE)
85508553
usessubscip : bool, optional
85518554
does the heuristic use a secondary SCIP instance? (Default value = False)
@@ -8564,32 +8567,51 @@ cdef class Model:
85648567
heur.name = name
85658568
Py_INCREF(heur)
85668569

8567-
# def includeIISFinder(self, IISfinder iisfinder, name, desc, priority=10000, freq=1):
8568-
# """
8569-
# Include an IIS (Irreducible Infeasible Set) finder handler.
8570-
8571-
# Parameters
8572-
# ----------
8573-
# iisfinder : IISfinder
8574-
# IIS finder
8575-
# name : str
8576-
# name of IIS finder
8577-
# desc : str
8578-
# description of IIS finder
8579-
# priority : int, optional
8580-
# priority of the IISfinder (#todo description)
8581-
# freq : int, optional
8582-
# frequency for calling IIS finder
8583-
8584-
# """
8585-
# nam = str_conversion(name)
8586-
# des = str_conversion(desc)
8587-
# PY_SCIP_CALL(SCIPincludeIISFinder(self._scip, nam, des, priority, freq, PyIISFinderCopy, PyIISFinderFree,
8588-
# PyIISFinderExec, <SCIP_IISFinderDATA*> iisfinder))
8589-
# iisfinder.model = <Model>weakref.proxy(self)
8590-
# iisfinder.name = name
8591-
8592-
# Py_INCREF(iisfinder)
8570+
def includeIISfinder(self, IISfinder iisfinder, name, desc, priority=10000, freq=1):
8571+
"""
8572+
Include an IIS (Irreducible Infeasible Set) finder handler.
8573+
8574+
Parameters
8575+
----------
8576+
iisfinder : IISfinder
8577+
IIS finder
8578+
name : str
8579+
name of IIS finder
8580+
desc : str
8581+
description of IIS finder
8582+
priority : int, optional
8583+
priority of the IISfinder (#todo description)
8584+
freq : int, optional
8585+
frequency for calling IIS finder
8586+
8587+
"""
8588+
nam = str_conversion(name)
8589+
des = str_conversion(desc)
8590+
PY_SCIP_CALL(SCIPincludeIISfinder(self._scip, nam, des, priority, PyiisfinderCopy, PyiisfinderFree,
8591+
PyiisfinderExec, <SCIP_IISFINDERDATA*> iisfinder))
8592+
iisfinder.model = <Model>weakref.proxy(self)
8593+
iisfinder.name = name
8594+
8595+
Py_INCREF(iisfinder)
8596+
8597+
def includeIISfinderGreedy(self):
8598+
"""
8599+
Include the default greedy IIS finder.
8600+
8601+
Returns
8602+
-------
8603+
IISfinder
8604+
the greedy IIS finder
8605+
8606+
"""
8607+
PY_SCIP_CALL(SCIPincludeIISfinderGreedy(self._scip))
8608+
8609+
# def iisGreedyMinimize(self, IISfinder iisfinder):
8610+
# """
8611+
# Perform the greedy deletion algorithm with singleton batches to obtain an irreducible infeasible subsystem (IIS)
8612+
# """
8613+
8614+
# PY_SCIP_CALL(SCIPiisGreedyMinimize(iisfinder._iisfinder))
85938615

85948616
def includeRelax(self, Relax relax, name, desc, priority=10000, freq=1):
85958617
"""

tests/test_iis.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import pytest
2+
3+
from pyscipopt import Model
4+
from pyscipopt.scip import IISfinder
5+
6+
calls = []
7+
class myIISfinder(IISfinder):
8+
def iisfinderexec(self):
9+
calls.append('relaxexec')
10+
11+
def test_iis_custom():
12+
from helpers.utils import random_mip_1
13+
14+
m = random_mip_1()
15+
x = m.addVar()
16+
m.addCons(x >= 1, "inf1")
17+
m.addCons(x <= 0, "inf2")
18+
19+
iis = myIISfinder()
20+
m.includeIISfinder(iis, name="custom", desc="test")
21+
m.optimize()
22+
assert calls != []
23+
24+
def test_iis_greedy():
25+
m = Model()
26+
x = m.addVar()
27+
m.addCons(x >= 1, "inf1")
28+
m.addCons(x <= 0, "inf2")
29+
30+
m.includeIISfinderGreedy()
31+
m.optimize()
32+
33+
test_iis_greedy()
34+
test_iis_custom()

0 commit comments

Comments
 (0)