Skip to content

Commit c659b85

Browse files
committed
add disjunctive constraint with exprcons
1 parent 640e3e0 commit c659b85

File tree

1 file changed

+17
-71
lines changed

1 file changed

+17
-71
lines changed

src/pyscipopt/scip.pxi

Lines changed: 17 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -2449,11 +2449,11 @@ cdef class Model:
24492449
)
24502450

24512451
return constraints
2452-
2452+
24532453
def addConsDisjunction(self, conss, name = '', initial = True,
24542454
relaxcons = None, enforce=True, check =True,
24552455
local=False, modifiable = False, dynamic = False):
2456-
2456+
24572457
def ensure_iterable(elem, length):
24582458
if isinstance(elem, Iterable):
24592459
return elem
@@ -2463,93 +2463,39 @@ cdef class Model:
24632463

24642464
conss = list(conss)
24652465
n_conss = len(conss)
2466-
assert n_conss >= 2, "Given constraint list contains fewer than 2 items!"
24672466

24682467
cdef SCIP_CONS* disj_cons
24692468

24702469
cdef SCIP_CONS* scip_cons
2471-
2470+
24722471
cdef SCIP_EXPR* scip_expr
24732472

24742473
PY_SCIP_CALL(SCIPcreateConsDisjunction(
24752474
self._scip, &disj_cons, str_conversion(name), 0, &scip_cons, NULL,
24762475
initial, enforce, check, local, modifiable, dynamic
24772476
))
24782477

2479-
#PY_SCIP_CALL(SCIPreleaseCons(self._scip, &scip_cons))
24802478

2479+
# TODO add constraints to disjunction
24812480
for i, cons in enumerate(conss):
2482-
deg = cons.expr.degree()
2483-
assert isinstance(cons, ExprCons), "given constraint is not ExprCons but %s" % cons.__class__.__name__
2484-
2485-
kwargs = dict(name='c'+str(SCIPgetNConss(self._scip)+1),initial=True,separate=True,
2486-
enforce=True, check=True, propagate=True, local=False,
2487-
modifiable=False, dynamic=False, removable=False,
2488-
stickingatnode=False)
2489-
2490-
kwargs['lhs'] = -SCIPinfinity(self._scip) if cons._lhs is None else cons._lhs
2491-
kwargs['rhs'] = SCIPinfinity(self._scip) if cons._rhs is None else cons._rhs
2492-
terms = cons.expr.terms
2493-
2494-
if deg <= 1:
2495-
nvars = len(terms.items())
2496-
vars_array = <SCIP_VAR**> malloc(nvars * sizeof(SCIP_VAR*))
2497-
coeffs_array = <SCIP_Real*> malloc(nvars * sizeof(SCIP_Real))
2498-
2499-
for i, (key, coeff) in enumerate(terms.items()):
2500-
vars_array[i] = <SCIP_VAR*>(<Variable>key[0]).scip_var
2501-
coeffs_array[i] = <SCIP_Real>coeff
2502-
2503-
PY_SCIP_CALL(SCIPcreateConsLinear(
2504-
self._scip, &scip_cons, str_conversion(kwargs['name']), nvars, vars_array, coeffs_array,
2505-
kwargs['lhs'], kwargs['rhs'], kwargs['initial'],
2506-
kwargs['separate'], kwargs['enforce'], kwargs['check'],
2507-
kwargs['propagate'], kwargs['local'], kwargs['modifiable'],
2508-
kwargs['dynamic'], kwargs['removable'], kwargs['stickingatnode']))
2509-
PY_SCIP_CALL(SCIPaddConsElemDisjunction(self._scip, disj_cons, scip_cons))
2510-
PY_SCIP_CALL(SCIPreleaseCons(self._scip, &scip_cons))
2511-
free(vars_array)
2512-
free(coeffs_array)
2513-
2514-
elif deg <=2:
2515-
PY_SCIP_CALL(SCIPcreateConsQuadraticNonlinear(
2516-
self._scip, &scip_cons, str_conversion(kwargs['name']),
2517-
0, NULL, NULL, # linear
2518-
0, NULL, NULL, NULL, # quadratc
2519-
kwargs['lhs'], kwargs['rhs'],
2520-
kwargs['initial'], kwargs['separate'], kwargs['enforce'],
2521-
kwargs['check'], kwargs['propagate'], kwargs['local'],
2522-
kwargs['modifiable'], kwargs['dynamic'], kwargs['removable']))
2523-
for v, c in terms.items():
2524-
if len(v) == 1: # linear
2525-
var = <Variable>v[0]
2526-
PY_SCIP_CALL(SCIPaddLinearVarNonlinear(self._scip, scip_cons, var.scip_var, c))
2527-
else: # quadratic
2528-
assert len(v) == 2, 'term length must be 1 or 2 but it is %s' % len(v)
2529-
2530-
varexprs = <SCIP_EXPR**> malloc(2 * sizeof(SCIP_EXPR*))
2531-
var1, var2 = <Variable>v[0], <Variable>v[1]
2532-
PY_SCIP_CALL( SCIPcreateExprVar(self._scip, &varexprs[0], var1.scip_var, NULL, NULL) )
2533-
PY_SCIP_CALL( SCIPcreateExprVar(self._scip, &varexprs[1], var2.scip_var, NULL, NULL) )
2534-
PY_SCIP_CALL( SCIPcreateExprProduct(self._scip, &scip_expr, 2, varexprs, 1.0, NULL, NULL) )
2535-
2536-
PY_SCIP_CALL( SCIPaddExprNonlinear(self._scip, scip_cons, scip_expr, c) )
2537-
2538-
PY_SCIP_CALL(SCIPaddConsElemDisjunction(self._scip, disj_cons, scip_cons))
2539-
PY_SCIP_CALL( SCIPreleaseExpr(self._scip, &scip_expr) )
2540-
PY_SCIP_CALL(SCIPreleaseCons(self._scip, &scip_cons))
2541-
PY_SCIP_CALL( SCIPreleaseExpr(self._scip, &varexprs[1]) )
2542-
PY_SCIP_CALL( SCIPreleaseExpr(self._scip, &varexprs[0]) )
2543-
free(varexprs)
2544-
else:
2545-
raise NotImplementedError("Only Linear Expressions are currently supported")
2546-
2547-
2481+
pycons = self.createExprCons(cons, name=name, initial = initial,
2482+
enforce=enforce, check=check,
2483+
local=local, modifiable=modifiable, dynamic=dynamic
2484+
)
2485+
PY_SCIP_CALL(SCIPaddConsElemDisjunction(self._scip,disj_cons, (<Constraint>pycons).scip_cons))
2486+
PY_SCIP_CALL(SCIPreleaseCons(self._scip, &(<Constraint>pycons).scip_cons))
25482487
PY_SCIP_CALL(SCIPaddCons(self._scip, disj_cons))
25492488
PyCons = Constraint.create(disj_cons)
25502489
PY_SCIP_CALL(SCIPreleaseCons(self._scip, &disj_cons))
25512490
return PyCons
25522491

2492+
def addConsElemDisjunction(self, Constraint disj_cons, Constraint cons):
2493+
PY_SCIP_CALL(SCIPaddConsElemDisjunction(self._scip, disj_cons.scip_cons, cons.scip_cons))
2494+
PY_SCIP_CALL(SCIPreleaseCons(self._scip, &((<Constraint>disj_cons).scip_cons)))
2495+
PY_SCIP_CALL(SCIPreleaseCons(self._scip, &((<Constraint>cons).scip_cons)))
2496+
2497+
return disj_cons
2498+
25532499

25542500
def getConsNVars(self, Constraint constraint):
25552501
"""

0 commit comments

Comments
 (0)