@@ -6809,6 +6809,169 @@ cdef class Model:
6809
6809
6810
6810
return pyCons
6811
6811
6812
+
6813
+ def addMatrixConsIndicator (self , cons: MatrixExprCons , binvar: Union[Variable , MatrixVariable] = None ,
6814
+ activeone: Union[bool , np.ndarray] = True , name: Union[str , np.ndarray] = "",
6815
+ initial: Union[bool , np.ndarray] = True , separate: Union[bool , np.ndarray] = True ,
6816
+ enforce: Union[bool , np.ndarray] = True , check: Union[bool , np.ndarray] = True ,
6817
+ propagate: Union[bool , np.ndarray] = True , local: Union[bool , np.ndarray] = False ,
6818
+ dynamic: Union[bool , np.ndarray] = False , removable: Union[bool , np.ndarray] = False ,
6819
+ stickingatnode: Union[bool , np.ndarray] = False ) -> MatrixConstraint:
6820
+ """Add an indicator matrix constraint for the linear inequality `cons`.
6821
+
6822
+ The `binvar` argument models the redundancy of the linear constraint. A solution
6823
+ for which `binvar` is 1 must satisfy the constraint.
6824
+
6825
+ Parameters
6826
+ ----------
6827
+ cons : MatrixExprCons
6828
+ a linear inequality of the form "<=".
6829
+ binvar : Variable or MatrixVariable , optional
6830
+ binary indicator variable / matrix variable , or None if it should be created. (Default value = None )
6831
+ activeone : bool or np.ndarray , optional
6832
+ the matrix constraint should be active if binvar is 1 (0 if activeone = False ).
6833
+ name : str or np.ndarray , optional
6834
+ name of the matrix constraint. (Default value = " " )
6835
+ initial : bool or np.ndarray , optional
6836
+ should the LP relaxation of matrix constraint be in the initial LP? (Default value = True )
6837
+ separate : bool or np.ndarray , optional
6838
+ should the matrix constraint be separated during LP processing? (Default value = True )
6839
+ enforce : bool or np.ndarray , optional
6840
+ should the matrix constraint be enforced during node processing? (Default value = True )
6841
+ check : bool or np.ndarray , optional
6842
+ should the matrix constraint be checked for feasibility? (Default value = True )
6843
+ propagate : bool or np.ndarray , optional
6844
+ should the matrix constraint be propagated during node processing? (Default value = True )
6845
+ local : bool or np.ndarray , optional
6846
+ is the matrix constraint only valid locally? (Default value = False )
6847
+ dynamic : bool or np.ndarray , optional
6848
+ is the matrix constraint subject to aging? (Default value = False )
6849
+ removable : bool or np.ndarray , optional
6850
+ should the relaxation be removed from the LP due to aging or cleanup? (Default value = False )
6851
+ stickingatnode : bool or np.ndarray , optional
6852
+ should the matrix constraint always be kept at the node where it was added ,
6853
+ even if it may be moved to a more global node? (Default value = False )
6854
+
6855
+ Returns
6856
+ -------
6857
+ MatrixConstraint
6858
+ The newly created Indicator MatrixConstraint object.
6859
+ """
6860
+
6861
+ assert isinstance(cons , MatrixExprCons ), (
6862
+ f"given constraint is not MatrixExprCons but {cons.__class__.__name__}"
6863
+ )
6864
+
6865
+ shape = cons.shape
6866
+
6867
+ if isinstance(binvar , MatrixVariable ):
6868
+ assert binvar.shape == shape
6869
+ if isinstance (activeone, np.ndarray):
6870
+ assert activeone.shape == shape
6871
+ if isinstance (name, np.ndarray):
6872
+ assert name.shape == shape
6873
+ if isinstance (initial, np.ndarray):
6874
+ assert initial.shape == shape
6875
+ if isinstance (separate, np.ndarray):
6876
+ assert separate.shape == shape
6877
+ if isinstance (enforce, np.ndarray):
6878
+ assert enforce.shape == shape
6879
+ if isinstance (check, np.ndarray):
6880
+ assert check.shape == shape
6881
+ if isinstance (propagate, np.ndarray):
6882
+ assert propagate.shape == shape
6883
+ if isinstance (local, np.ndarray):
6884
+ assert local.shape == shape
6885
+ if isinstance (dynamic, np.ndarray):
6886
+ assert dynamic.shape == shape
6887
+ if isinstance (removable, np.ndarray):
6888
+ assert removable.shape == shape
6889
+ if isinstance (stickingatnode, np.ndarray):
6890
+ assert stickingatnode.shape == shape
6891
+
6892
+ if not isinstance (binvar, MatrixVariable):
6893
+ matrix_binvar = np.full(shape, binvar, dtype = Variable)
6894
+ else :
6895
+ matrix_binvar = binvar
6896
+
6897
+ if not isinstance (activeone, np.ndarray):
6898
+ matrix_activeone = np.full(shape, activeone, dtype = bool )
6899
+ else :
6900
+ matrix_activeone = activeone
6901
+
6902
+ if isinstance (name, str ):
6903
+ matrix_names = np.full(shape, name, dtype = object )
6904
+ if name != " " :
6905
+ for idx in np.ndindex(shape):
6906
+ matrix_names[idx] = f" {name}_{'_'.join(map(str, idx))}"
6907
+ else :
6908
+ matrix_names = name
6909
+
6910
+ if not isinstance (initial, np.ndarray):
6911
+ matrix_initial = np.full(shape, initial, dtype = bool )
6912
+ else :
6913
+ matrix_initial = initial
6914
+
6915
+ if not isinstance (enforce, np.ndarray):
6916
+ matrix_enforce = np.full(shape, enforce, dtype = bool )
6917
+ else :
6918
+ matrix_enforce = enforce
6919
+
6920
+ if not isinstance (separate, np.ndarray):
6921
+ matrix_separate = np.full(shape, separate, dtype = bool )
6922
+ else :
6923
+ matrix_separate = separate
6924
+
6925
+ if not isinstance (check, np.ndarray):
6926
+ matrix_check = np.full(shape, check, dtype = bool )
6927
+ else :
6928
+ matrix_check = check
6929
+
6930
+ if not isinstance (propagate, np.ndarray):
6931
+ matrix_propagate = np.full(shape, propagate, dtype = bool )
6932
+ else :
6933
+ matrix_propagate = propagate
6934
+
6935
+ if not isinstance (local, np.ndarray):
6936
+ matrix_local = np.full(shape, local, dtype = bool )
6937
+ else :
6938
+ matrix_local = local
6939
+
6940
+ if not isinstance (dynamic, np.ndarray):
6941
+ matrix_dynamic = np.full(shape, dynamic, dtype = bool )
6942
+ else :
6943
+ matrix_dynamic = dynamic
6944
+
6945
+ if not isinstance (removable, np.ndarray):
6946
+ matrix_removable = np.full(shape, removable, dtype = bool )
6947
+ else :
6948
+ matrix_removable = removable
6949
+
6950
+ if not isinstance (stickingatnode, np.ndarray):
6951
+ matrix_stickingatnode = np.full(shape, stickingatnode, dtype = bool )
6952
+ else :
6953
+ matrix_stickingatnode = stickingatnode
6954
+
6955
+ matrix_cons = np.empty(shape, dtype = object )
6956
+ for idx in np.ndindex(shape):
6957
+ matrix_cons[idx] = self .addConsIndicator(
6958
+ cons[idx],
6959
+ binvar = matrix_binvar[idx],
6960
+ activeone = matrix_activeone[idx],
6961
+ name = matrix_names[idx],
6962
+ initial = matrix_initial[idx],
6963
+ separate = matrix_separate[idx],
6964
+ enforce = matrix_enforce[idx],
6965
+ check = matrix_check[idx],
6966
+ propagate = matrix_propagate[idx],
6967
+ local = matrix_local[idx],
6968
+ dynamic = matrix_dynamic[idx],
6969
+ removable = matrix_removable[idx],
6970
+ stickingatnode = matrix_stickingatnode[idx],
6971
+ )
6972
+
6973
+ return matrix_cons.view(MatrixConstraint)
6974
+
6812
6975
def getLinearConsIndicator (self , Constraint cons ):
6813
6976
"""
6814
6977
Get the linear constraint corresponding to the indicator constraint.
0 commit comments