@@ -1676,7 +1676,7 @@ cdef class Variable(Expr):
16761676
16771677 """
16781678 return SCIPvarGetAvgSol(self .scip_var)
1679-
1679+
16801680 def markRelaxationOnly (self ):
16811681 """
16821682 marks that this variable has only been introduced to define a relaxation
@@ -6841,6 +6841,169 @@ cdef class Model:
68416841
68426842 return pyCons
68436843
6844+
6845+ def addMatrixConsIndicator (self , cons: MatrixExprCons , binvar: Union[Variable , MatrixVariable] = None ,
6846+ activeone: Union[bool , np.ndarray] = True , name: Union[str , np.ndarray] = "",
6847+ initial: Union[bool , np.ndarray] = True , separate: Union[bool , np.ndarray] = True ,
6848+ enforce: Union[bool , np.ndarray] = True , check: Union[bool , np.ndarray] = True ,
6849+ propagate: Union[bool , np.ndarray] = True , local: Union[bool , np.ndarray] = False ,
6850+ dynamic: Union[bool , np.ndarray] = False , removable: Union[bool , np.ndarray] = False ,
6851+ stickingatnode: Union[bool , np.ndarray] = False ) -> MatrixConstraint:
6852+ """Add an indicator matrix constraint for the linear inequality `cons`.
6853+
6854+ The `binvar` argument models the redundancy of the linear constraint. A solution
6855+ for which `binvar` is 1 must satisfy the constraint.
6856+
6857+ Parameters
6858+ ----------
6859+ cons : MatrixExprCons
6860+ a linear inequality of the form "<=".
6861+ binvar : Variable or MatrixVariable , optional
6862+ binary indicator variable / matrix variable , or None if it should be created. (Default value = None )
6863+ activeone : bool or np.ndarray , optional
6864+ the matrix constraint should be active if binvar is 1 (0 if activeone = False ).
6865+ name : str or np.ndarray , optional
6866+ name of the matrix constraint. (Default value = " " )
6867+ initial : bool or np.ndarray , optional
6868+ should the LP relaxation of matrix constraint be in the initial LP? (Default value = True )
6869+ separate : bool or np.ndarray , optional
6870+ should the matrix constraint be separated during LP processing? (Default value = True )
6871+ enforce : bool or np.ndarray , optional
6872+ should the matrix constraint be enforced during node processing? (Default value = True )
6873+ check : bool or np.ndarray , optional
6874+ should the matrix constraint be checked for feasibility? (Default value = True )
6875+ propagate : bool or np.ndarray , optional
6876+ should the matrix constraint be propagated during node processing? (Default value = True )
6877+ local : bool or np.ndarray , optional
6878+ is the matrix constraint only valid locally? (Default value = False )
6879+ dynamic : bool or np.ndarray , optional
6880+ is the matrix constraint subject to aging? (Default value = False )
6881+ removable : bool or np.ndarray , optional
6882+ should the relaxation be removed from the LP due to aging or cleanup? (Default value = False )
6883+ stickingatnode : bool or np.ndarray , optional
6884+ should the matrix constraint always be kept at the node where it was added ,
6885+ even if it may be moved to a more global node? (Default value = False )
6886+
6887+ Returns
6888+ -------
6889+ MatrixConstraint
6890+ The newly created Indicator MatrixConstraint object.
6891+ """
6892+
6893+ assert isinstance(cons , MatrixExprCons ), (
6894+ f"given constraint is not MatrixExprCons but {cons.__class__.__name__}"
6895+ )
6896+
6897+ shape = cons.shape
6898+
6899+ if isinstance(binvar , MatrixVariable ):
6900+ assert binvar.shape == shape
6901+ if isinstance (activeone, np.ndarray):
6902+ assert activeone.shape == shape
6903+ if isinstance (name, np.ndarray):
6904+ assert name.shape == shape
6905+ if isinstance (initial, np.ndarray):
6906+ assert initial.shape == shape
6907+ if isinstance (separate, np.ndarray):
6908+ assert separate.shape == shape
6909+ if isinstance (enforce, np.ndarray):
6910+ assert enforce.shape == shape
6911+ if isinstance (check, np.ndarray):
6912+ assert check.shape == shape
6913+ if isinstance (propagate, np.ndarray):
6914+ assert propagate.shape == shape
6915+ if isinstance (local, np.ndarray):
6916+ assert local.shape == shape
6917+ if isinstance (dynamic, np.ndarray):
6918+ assert dynamic.shape == shape
6919+ if isinstance (removable, np.ndarray):
6920+ assert removable.shape == shape
6921+ if isinstance (stickingatnode, np.ndarray):
6922+ assert stickingatnode.shape == shape
6923+
6924+ if not isinstance (binvar, MatrixVariable):
6925+ matrix_binvar = np.full(shape, binvar, dtype = Variable)
6926+ else :
6927+ matrix_binvar = binvar
6928+
6929+ if not isinstance (activeone, np.ndarray):
6930+ matrix_activeone = np.full(shape, activeone, dtype = bool )
6931+ else :
6932+ matrix_activeone = activeone
6933+
6934+ if isinstance (name, str ):
6935+ matrix_names = np.full(shape, name, dtype = object )
6936+ if name != " " :
6937+ for idx in np.ndindex(shape):
6938+ matrix_names[idx] = f" {name}_{'_'.join(map(str, idx))}"
6939+ else :
6940+ matrix_names = name
6941+
6942+ if not isinstance (initial, np.ndarray):
6943+ matrix_initial = np.full(shape, initial, dtype = bool )
6944+ else :
6945+ matrix_initial = initial
6946+
6947+ if not isinstance (enforce, np.ndarray):
6948+ matrix_enforce = np.full(shape, enforce, dtype = bool )
6949+ else :
6950+ matrix_enforce = enforce
6951+
6952+ if not isinstance (separate, np.ndarray):
6953+ matrix_separate = np.full(shape, separate, dtype = bool )
6954+ else :
6955+ matrix_separate = separate
6956+
6957+ if not isinstance (check, np.ndarray):
6958+ matrix_check = np.full(shape, check, dtype = bool )
6959+ else :
6960+ matrix_check = check
6961+
6962+ if not isinstance (propagate, np.ndarray):
6963+ matrix_propagate = np.full(shape, propagate, dtype = bool )
6964+ else :
6965+ matrix_propagate = propagate
6966+
6967+ if not isinstance (local, np.ndarray):
6968+ matrix_local = np.full(shape, local, dtype = bool )
6969+ else :
6970+ matrix_local = local
6971+
6972+ if not isinstance (dynamic, np.ndarray):
6973+ matrix_dynamic = np.full(shape, dynamic, dtype = bool )
6974+ else :
6975+ matrix_dynamic = dynamic
6976+
6977+ if not isinstance (removable, np.ndarray):
6978+ matrix_removable = np.full(shape, removable, dtype = bool )
6979+ else :
6980+ matrix_removable = removable
6981+
6982+ if not isinstance (stickingatnode, np.ndarray):
6983+ matrix_stickingatnode = np.full(shape, stickingatnode, dtype = bool )
6984+ else :
6985+ matrix_stickingatnode = stickingatnode
6986+
6987+ matrix_cons = np.empty(shape, dtype = object )
6988+ for idx in np.ndindex(shape):
6989+ matrix_cons[idx] = self .addConsIndicator(
6990+ cons[idx],
6991+ binvar = matrix_binvar[idx],
6992+ activeone = matrix_activeone[idx],
6993+ name = matrix_names[idx],
6994+ initial = matrix_initial[idx],
6995+ separate = matrix_separate[idx],
6996+ enforce = matrix_enforce[idx],
6997+ check = matrix_check[idx],
6998+ propagate = matrix_propagate[idx],
6999+ local = matrix_local[idx],
7000+ dynamic = matrix_dynamic[idx],
7001+ removable = matrix_removable[idx],
7002+ stickingatnode = matrix_stickingatnode[idx],
7003+ )
7004+
7005+ return matrix_cons.view(MatrixConstraint)
7006+
68447007 def getLinearConsIndicator (self , Constraint cons ):
68457008 """
68467009 Get the linear constraint corresponding to the indicator constraint.
0 commit comments