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

Add _createConsBasicLinear #917

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## Unreleased
### Added
- Added transformProb but no test
- Added _createConsBasicLinear and test
- Expanded Statistics class to more problems.
- Created Statistics class
- Added parser to read .stats file
Expand Down
11 changes: 11 additions & 0 deletions src/pyscipopt/scip.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -671,6 +671,7 @@ cdef extern from "scip/scip.h":
SCIP_RETCODE SCIPsolve(SCIP* scip)
SCIP_RETCODE SCIPsolveConcurrent(SCIP* scip)
SCIP_RETCODE SCIPfreeTransform(SCIP* scip)
SCIP_RETCODE SCIPtransformProb(SCIP* scip)
SCIP_RETCODE SCIPpresolve(SCIP* scip)

# Node Methods
Expand Down Expand Up @@ -1395,6 +1396,16 @@ cdef extern from "scip/cons_linear.h":
SCIP_Bool dynamic,
SCIP_Bool removable,
SCIP_Bool stickingatnode)

SCIP_RETCODE SCIPcreateConsBasicLinear(SCIP* scip,
SCIP_CONS** cons,
char* name,
int nvars,
SCIP_VAR** vars,
SCIP_Real* vals,
SCIP_Real lhs,
SCIP_Real rhs)

SCIP_RETCODE SCIPaddCoefLinear(SCIP* scip,
SCIP_CONS* cons,
SCIP_VAR* var,
Expand Down
84 changes: 83 additions & 1 deletion src/pyscipopt/scip.pxi
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@
if rc == SCIP_OKAY:
pass
elif rc == SCIP_ERROR:
raise Exception('SCIP: unspecified error!')

Check failure on line 265 in src/pyscipopt/scip.pxi

View workflow job for this annotation

GitHub Actions / test-coverage (3.11)

SCIP: unspecified error!

Check failure on line 265 in src/pyscipopt/scip.pxi

View workflow job for this annotation

GitHub Actions / Integration-test (3.8)

SCIP: unspecified error!

Check failure on line 265 in src/pyscipopt/scip.pxi

View workflow job for this annotation

GitHub Actions / Windows-test (3.8)

SCIP: unspecified error!

Check failure on line 265 in src/pyscipopt/scip.pxi

View workflow job for this annotation

GitHub Actions / Integration-test (3.9)

SCIP: unspecified error!

Check failure on line 265 in src/pyscipopt/scip.pxi

View workflow job for this annotation

GitHub Actions / Windows-test (3.9)

SCIP: unspecified error!

Check failure on line 265 in src/pyscipopt/scip.pxi

View workflow job for this annotation

GitHub Actions / Integration-test (3.10)

SCIP: unspecified error!

Check failure on line 265 in src/pyscipopt/scip.pxi

View workflow job for this annotation

GitHub Actions / Windows-test (3.10)

SCIP: unspecified error!

Check failure on line 265 in src/pyscipopt/scip.pxi

View workflow job for this annotation

GitHub Actions / Integration-test (3.11)

SCIP: unspecified error!

Check failure on line 265 in src/pyscipopt/scip.pxi

View workflow job for this annotation

GitHub Actions / Windows-test (3.11)

SCIP: unspecified error!

Check failure on line 265 in src/pyscipopt/scip.pxi

View workflow job for this annotation

GitHub Actions / Integration-test (3.12)

SCIP: unspecified error!

Check failure on line 265 in src/pyscipopt/scip.pxi

View workflow job for this annotation

GitHub Actions / Windows-test (3.12)

SCIP: unspecified error!
elif rc == SCIP_NOMEMORY:
raise MemoryError('SCIP: insufficient memory error!')
elif rc == SCIP_READERROR:
Expand Down Expand Up @@ -2057,6 +2057,15 @@
def freeTransform(self):
"""Frees all solution process data including presolving and
transformed problem, only original problem is kept."""
if self.getStage() not in [SCIP_STAGE_INIT,
SCIP_STAGE_PROBLEM,
SCIP_STAGE_TRANSFORMED,
SCIP_STAGE_PRESOLVING,
SCIP_STAGE_PRESOLVED,
SCIP_STAGE_SOLVING,
SCIP_STAGE_SOLVED]:
raise Warning("method cannot be called in stage %i." % self.getStage())

self._modelvars = {
var: value
for var, value in self._modelvars.items()
Expand Down Expand Up @@ -4131,6 +4140,57 @@
free(coeffs_array)
return PyCons

def _createConsBasicLinear(self, ExprCons lincons, name='', **kwargs):
"""
The function for creating a basic linear constraint, but not adding it to the Model.

Parameters
----------
lincons : ExprCons
name : str, optional
name of constraint
kwargs : dict, optional

Returns
-------
Constraint

"""
assert isinstance(lincons, ExprCons), "given constraint is not ExprCons but %s" % lincons.__class__.__name__

assert lincons.expr.degree() <= 1, "given constraint is not linear, degree == %d" % lincons.expr.degree()
terms = lincons.expr.terms

cdef SCIP_CONS* scip_cons

if name == '':
name = 'c'+str(SCIPgetNConss(self._scip)+1)

kwargs = dict(name=name)
kwargs['lhs'] = -SCIPinfinity(self._scip) if lincons._lhs is None else lincons._lhs
kwargs['rhs'] = SCIPinfinity(self._scip) if lincons._rhs is None else lincons._rhs

cdef int nvars = len(terms.items())

vars_array = <SCIP_VAR**> malloc(nvars * sizeof(SCIP_VAR*))
coeffs_array = <SCIP_Real*> malloc(nvars * sizeof(SCIP_Real))

for i, (key, coeff) in enumerate(terms.items()):
vars_array[i] = <SCIP_VAR*>(<Variable>key[0]).scip_var
coeffs_array[i] = <SCIP_Real>coeff

PY_SCIP_CALL(SCIPcreateConsBasicLinear(
self._scip, &scip_cons, str_conversion(kwargs['name']), nvars, vars_array, coeffs_array,
kwargs['lhs'], kwargs['rhs']))

PyCons = Constraint.create(scip_cons)

free(vars_array)
free(coeffs_array)

PY_SCIP_CALL(SCIPreleaseCons(self._scip, &scip_cons))
return PyCons

def _createConsQuadratic(self, ExprCons quadcons, **kwargs):
"""
The function for creating a quadratic constraint, but not adding it to the Model.
Expand Down Expand Up @@ -6173,8 +6233,20 @@
PY_SCIP_CALL(SCIPsolveConcurrent(self._scip))
self._bestSol = Solution.create(self._scip, SCIPgetBestSol(self._scip))

def transformProb(self):
"""Transform the problem"""
if self.getStage() in [SCIP_STAGE_INIT, SCIP_STAGE_TRANSFORMING]:
raise Warning("method cannot be called in stage %i." % self.getStage())

PY_SCIP_CALL(SCIPtransformProb(self._scip))

def presolve(self):
"""Presolve the problem."""
if self.getStage() not in [SCIP_STAGE_PROBLEM, SCIP_STAGE_TRANSFORMED,\
SCIP_STAGE_PRESOLVING, SCIP_STAGE_PRESOLVED, \
SCIP_STAGE_SOLVED]:
raise Warning("method cannot be called in stage %i." % self.getStage())

PY_SCIP_CALL(SCIPpresolve(self._scip))
self._bestSol = Solution.create(self._scip, SCIPgetBestSol(self._scip))

Expand Down Expand Up @@ -8186,7 +8258,7 @@
min_stage_requirement = SCIP_STAGE_TRANSFORMING

if not self.getStage() >= min_stage_requirement:
raise Warning("method cannot be called in stage %i." % self.getStage)
raise Warning("method cannot be called in stage %i." % self.getStage())

return self.getSolObjVal(self._bestSol, original)

Expand Down Expand Up @@ -8977,6 +9049,16 @@

def freeReoptSolve(self):
"""Frees all solution process data and prepares for reoptimization."""

if self.getStage() not in [SCIP_STAGE_INIT,
SCIP_STAGE_PROBLEM,
SCIP_STAGE_TRANSFORMED,
SCIP_STAGE_PRESOLVING,
SCIP_STAGE_PRESOLVED,
SCIP_STAGE_SOLVING,
SCIP_STAGE_SOLVED]:
raise Warning("method cannot be called in stage %i." % self.getStage())

PY_SCIP_CALL(SCIPfreeReoptSolve(self._scip))

def chgReoptObjective(self, coeffs, sense = 'minimize'):
Expand Down
12 changes: 12 additions & 0 deletions tests/test_cons.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,18 @@ def test_addConsDisjunction_expr_init():
assert m.isEQ(m.getVal(y), 5)
assert m.isEQ(m.getVal(o), 6)

def test__createConsBasicLinear():
m = Model()
x = m.addVar()
y = m.addVar()

assert m.getNConss() == 0

c = m._createConsBasicLinear(x+y<=4)


assert m.getNConss() == 0
assert c.isLinear()

@pytest.mark.skip(reason="TODO: test getValsLinear()")
def test_getValsLinear():
Expand Down
2 changes: 1 addition & 1 deletion tests/test_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -476,4 +476,4 @@ def test_getObjVal():
assert m.getVal(x) == 0

assert m.getObjVal() == 16
assert m.getVal(x) == 0
assert m.getVal(x) == 0
Loading