@@ -975,6 +975,128 @@ cdef class Constraint:
975
975
return (self .__class__ == other.__class__
976
976
and self .scip_cons == (< Constraint> other).scip_cons)
977
977
978
+ cdef class Decomposition:
979
+ """ Base class holding a pointer to SCIP decomposition"""
980
+
981
+ @staticmethod
982
+ cdef create(SCIP_DECOMP* scip_decomp):
983
+ if scip_decomp == NULL :
984
+ raise Warning (" cannot create Constraint with SCIP_CONS* == NULL" )
985
+ decomp = Decomposition()
986
+ decomp.scip_decomp = scip_decomp
987
+ return decomp
988
+
989
+ def isOriginal (self ):
990
+ return SCIPdecompIsOriginal(self .scip_decomp)
991
+
992
+ def getAreaScore (self ):
993
+ return SCIPdecompGetAreaScore(self .scip_decomp)
994
+
995
+ def getModularity (self ):
996
+ return SCIPdecompGetModularity(self .scip_decomp)
997
+
998
+ def getNBorderVars (self ):
999
+ return SCIPdecompGetNBorderVars(self .scip_decomp)
1000
+
1001
+ def getNBorderConss (self ):
1002
+ return SCIPdecompGetNBorderConss(self .scip_decomp)
1003
+
1004
+ def getNBlockGraphEdges (self ):
1005
+ return SCIPdecompGetNBlockGraphEdges(self .scip_decomp)
1006
+
1007
+ def getNBlockGraphComponents (self ):
1008
+ return SCIPdecompGetNBlockGraphComponents(self .scip_decomp)
1009
+
1010
+ def getNblockGraphArticulations (self ):
1011
+ return SCIPdecompGetNBlockGraphArticulations(self .scip_decomp)
1012
+
1013
+ def getBlockGraphMaxDegree (self ):
1014
+ return SCIPdecompGetBlockGraphMaxDegree(self .scip_decomp)
1015
+
1016
+ def getBlockGraphMinDegree (self ):
1017
+ return SCIPdecompGetBlockGraphMinDegree(self .scip_decomp)
1018
+
1019
+ def getConsLabels (self , conss ):
1020
+ """ get {cons: label} pair for python constraints conss"""
1021
+ cdef int nconss = < int > len (conss)
1022
+ cdef int * labels = < int * > malloc(nconss * sizeof(int ))
1023
+ cdef SCIP_CONS** scip_conss = < SCIP_CONS** > malloc(nconss * sizeof(SCIP_CONS* ))
1024
+
1025
+ for i in range (nconss):
1026
+ scip_conss[i] = (< Constraint> conss[i]).scip_cons
1027
+
1028
+ PY_SCIP_CALL(SCIPdecompGetConsLabels(self .scip_decomp, scip_conss, labels, nconss))
1029
+
1030
+ cons_labels = {}
1031
+ for i in range (nconss):
1032
+ cons_labels[conss[i]] = labels[i]
1033
+ free(labels)
1034
+ free(scip_conss)
1035
+ return cons_labels
1036
+
1037
+ def setConsLabels (self , cons_labels ):
1038
+ """ applies labels to constraints in decomposition.
1039
+ :param cons_labels dict of {constraint: label} pairs to be applied
1040
+ """
1041
+ cons_labels = cons_labels.items()
1042
+
1043
+ cdef int nconss = len (cons_labels)
1044
+ cdef SCIP_CONS** scip_conss = < SCIP_CONS** > malloc(nconss* sizeof(SCIP_CONS* ))
1045
+ cdef int * labels = < int * > malloc(nconss * sizeof(int ))
1046
+
1047
+ for i in range (nconss):
1048
+ scip_conss[i] = (< Constraint> cons_labels[i][0 ]).scip_cons
1049
+ labels[i] = cons_labels[i][1 ]
1050
+
1051
+ PY_SCIP_CALL(SCIPdecompSetConsLabels(self .scip_decomp, scip_conss, labels, nconss))
1052
+
1053
+ free(scip_conss)
1054
+ free(labels)
1055
+
1056
+ def getVarsLabels (self , vrs ):
1057
+ """ get {var: label} pairs for python variables vrs"""
1058
+
1059
+ cdef int nvars = < int > len (vrs)
1060
+ cdef int * labels = < int * > malloc(nvars * sizeof(int ))
1061
+ cdef SCIP_VAR** scip_vars = < SCIP_VAR** > malloc(nvars * sizeof(SCIP_VAR* ))
1062
+
1063
+ for i in range (nvars):
1064
+ scip_vars[i] = (< Variable> vrs[i]).scip_var
1065
+
1066
+ PY_SCIP_CALL(SCIPdecompGetVarsLabels(self .scip_decomp, scip_vars, labels, nvars))
1067
+
1068
+ var_labels = {}
1069
+ for i in range (nvars):
1070
+ var_labels[vrs[i]] = labels[i]
1071
+
1072
+ free(labels)
1073
+ free(scip_vars)
1074
+ return var_labels
1075
+
1076
+ def setVarLabels (self , var_labels ):
1077
+ """ set {var: label} pairs in decomposition"""
1078
+ var_labels = var_labels.items()
1079
+
1080
+ cdef int nvars= len (var_labels)
1081
+ cdef SCIP_VAR** scip_vars = < SCIP_VAR** > malloc(nvars * sizeof(SCIP_VAR* ))
1082
+ cdef int * labels = < int * > malloc(nvars * sizeof(int ))
1083
+
1084
+ for i in range (nvars):
1085
+ scip_vars[i] = (< Variable> var_labels[i][0 ]).scip_var
1086
+ labels[i] = var_labels[i][1 ]
1087
+
1088
+ PY_SCIP_CALL(SCIPdecompSetVarsLabels(self .scip_decomp, scip_vars, labels, nvars))
1089
+
1090
+ free(scip_vars)
1091
+ free(labels)
1092
+
1093
+ def clear (self , varlabels = True , conslabels = True ):
1094
+ """ clears variable and/or constraint labels from decomposition"""
1095
+
1096
+ if not (varlabels or conslabels):
1097
+ ... # TODO does decomp clear do anything if both options are false?
1098
+ else :
1099
+ PY_SCIP_CALL(SCIPdecompClear(self .scip_decomp, varlabels, conslabels))
978
1100
979
1101
cdef void relayMessage(SCIP_MESSAGEHDLR * messagehdlr, FILE * file , const char * msg) noexcept:
980
1102
sys.stdout.write(msg.decode(' UTF-8' ))
@@ -3422,6 +3544,9 @@ cdef class Model:
3422
3544
""" Presolve the problem."""
3423
3545
PY_SCIP_CALL(SCIPpresolve(self ._scip))
3424
3546
3547
+ def addDecomposition (self , Decomposition decomp ):
3548
+ PY_SCIP_CALL(SCIPaddDecomp(self ._scip, decomp.scip_decomp))
3549
+
3425
3550
# Benders' decomposition methods
3426
3551
def initBendersDefault (self , subproblems ):
3427
3552
""" initialises the default Benders' decomposition with a dictionary of subproblems
0 commit comments