@@ -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