41 #include "scip/scip.h"
42 #include "scip/scipdefplugins.h"
52 #include <gsl/gsl_matrix.h>
53 #include <gsl/gsl_permutation.h>
54 #include <gsl/gsl_linalg.h>
57 #define SEPA_NAME "basis"
58 #define SEPA_DESC "separator calculates a basis of the orig problem to generate cuts, which cut off the master lp sol"
59 #define SEPA_PRIORITY 100
61 #define SEPA_MAXBOUNDDIST 1.0
62 #define SEPA_USESSUBSCIP FALSE
63 #define SEPA_DELAY TRUE
65 #define STARTMAXCUTS 50
115 SCIP_SEPADATA* sepadata,
119 assert(scip != NULL);
120 assert(sepadata != NULL);
121 assert(sepadata->mastercuts != NULL);
122 assert(sepadata->origcuts != NULL);
123 assert(sepadata->norigcuts <= sepadata->maxcuts);
124 assert(sepadata->norigcuts >= 0);
125 assert(sepadata->nmastercuts <= sepadata->maxcuts);
126 assert(sepadata->nmastercuts >= 0);
128 if( sepadata->maxcuts < size )
130 int newmaxcuts = SCIPcalcMemGrowSize(scip, size);
131 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &(sepadata->mastercuts), sepadata->maxcuts, newmaxcuts) );
132 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &(sepadata->origcuts), sepadata->maxcuts, newmaxcuts) );
133 sepadata->maxcuts = newmaxcuts;
135 assert(sepadata->maxcuts >= size);
144 SCIP_SEPADATA* sepadata,
148 assert(scip != NULL);
149 assert(sepadata != NULL);
150 assert(sepadata->newcuts != NULL);
151 assert(sepadata->nnewcuts <= sepadata->maxnewcuts);
152 assert(sepadata->nnewcuts >= 0);
154 if( sepadata->maxnewcuts < size )
156 int newmaxnewcuts = SCIPcalcMemGrowSize(scip, size);
157 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &(sepadata->newcuts), sepadata->maxnewcuts, newmaxnewcuts) );
158 sepadata->maxnewcuts = newmaxnewcuts;
160 assert(sepadata->maxnewcuts >= size);
167 SCIP_Real exponentiate(
175 assert(exponent >= 0);
178 for( i = 0; i < exponent; ++i )
188 SCIP_RETCODE initProbingObjWithOrigObj(
201 assert(SCIPinProbing(origscip));
203 origvars = SCIPgetVars(origscip);
204 norigvars = SCIPgetNVars(origscip);
207 for( i = 0; i < norigvars; ++i )
210 origvar = origvars[i];
215 newobj = objfactor * SCIPvarGetObj(origvar);
217 SCIP_CALL( SCIPchgVarObjProbing(origscip, origvar, newobj) );
226 SCIP_RETCODE chgProbingObjAddingOrigObj(
239 assert(SCIPinProbing(origscip));
241 origvars = SCIPgetVars(origscip);
242 norigvars = SCIPgetNVars(origscip);
245 for( i = 0; i < norigvars; ++i )
248 origvar = origvars[i];
250 newobj = SCIPgetVarObjProbing(origscip, origvar) + (objfactor * SCIPvarGetObj(origvar))/ objdivisor ;
252 SCIP_CALL( SCIPchgVarObjProbing(origscip, origvar, newobj) );
264 SCIP_RETCODE initProbingObjUsingVarBounds(
266 SCIP_SEPADATA* sepadata,
272 SCIP_Bool enableposslack;
287 origvars = SCIPgetVars(origscip);
288 norigvars = SCIPgetNVars(origscip);
290 enableposslack = sepadata->enableposslack;
291 posslackexp = sepadata->posslackexp;
294 for( i = 0; i < norigvars; ++i )
297 origvar = origvars[i];
298 lb = SCIPvarGetLbLocal(origvar);
299 ub = SCIPvarGetUbLocal(origvar);
300 solval = SCIPgetSolVal(origscip, origsol, origvar);
302 assert(SCIPisFeasLE(origscip, solval, ub));
303 assert(SCIPisFeasGE(origscip, solval, lb));
308 if( SCIPisFeasEQ(origscip, lb, ub) )
312 else if( SCIPisLT(origscip, ub, SCIPinfinity(origscip)) && SCIPisFeasLE(origscip, ub, solval) )
316 else if( SCIPisGT(origscip, lb, -SCIPinfinity(origscip)) && SCIPisFeasGE(origscip, lb, solval) )
320 else if( enableposslack )
323 distance = MIN(solval - lb, ub - solval);
325 assert(SCIPisFeasPositive(origscip, distance));
328 if( SCIPisLT(origscip, distance, 1.0) )
330 newobj = exponentiate(MAX(0.0, 1.0 - distance), posslackexp);
333 if( SCIPisLT(origscip, distance, solval - lb) )
348 newobj = newobj + SCIPvarGetObj(origvar);
350 SCIP_CALL( SCIPchgVarObjProbing(origscip, origvar, objfactor*newobj) );
364 SCIP_SEPADATA* sepadata,
370 SCIP_Bool enableposslack;
394 rows = SCIPgetLPRows(origscip);
395 nrows = SCIPgetNLPRows(origscip);
397 enableposslack = sepadata->enableposslack;
398 posslackexp = sepadata->posslackexp;
400 assert(SCIPinProbing(origscip));
402 SCIP_CALL( SCIPallocBufferArray(origscip, &solvals, SCIPgetNVars(origscip)) );
403 SCIP_CALL( SCIPallocBufferArray(origscip, &vars, SCIPgetNVars(origscip)) );
406 for( i = 0; i < nrows; ++i )
409 lhs = SCIProwGetLhs(row);
410 rhs = SCIProwGetRhs(row);
412 nvars = SCIProwGetNNonz(row);
413 if( nvars == 0 || (sepadata->objrow != NULL && strcmp(SCIProwGetName(row),SCIProwGetName(sepadata->objrow)) == 0 ) )
417 vals = SCIProwGetVals(row);
418 cols = SCIProwGetCols(row);
419 for( j = 0; j < nvars; ++j )
421 vars[j] = SCIPcolGetVar(cols[j]);
424 activity = SCIPgetRowSolActivity(origscip, row, origsol);
426 if( SCIPisFeasEQ(origscip, rhs, lhs) )
430 if( SCIPisLT(origscip, rhs, SCIPinfinity(origscip)) && SCIPisFeasLE(origscip, rhs, activity) )
434 else if( SCIPisGT(origscip, lhs, -SCIPinfinity(origscip)) && SCIPisFeasGE(origscip, lhs, activity) )
438 else if( enableposslack )
440 assert(!(SCIPisInfinity(origscip, rhs) && SCIPisInfinity(origscip, lhs)));
441 assert(!(SCIPisInfinity(origscip, activity) && SCIPisInfinity(origscip, -activity)));
444 if( SCIPisInfinity(origscip, rhs) && SCIPisGT(origscip, lhs, -SCIPinfinity(origscip)) )
445 distance = activity - lhs;
446 else if( SCIPisInfinity(origscip, lhs) && SCIPisLT(origscip, rhs, SCIPinfinity(origscip)) )
447 distance = rhs - activity;
449 distance = MIN(activity - lhs, rhs - activity);
451 assert(SCIPisFeasPositive(origscip, distance) || !SCIPisCutEfficacious(origscip, origsol, row));
454 if( SCIPisLT(origscip, distance, 1.0) )
456 factor = exponentiate(MAX(0.0, 1.0 - distance), posslackexp);
459 if( SCIPisLT(origscip, distance, activity - lhs) )
460 factor = -1.0*factor;
472 norm = SCIProwGetNorm(row);
475 for( j = 0; j < nvars; ++j )
477 obj = SCIPgetVarObjProbing(origscip, vars[j]);
478 objadd = (factor * vals[j]) / norm;
480 SCIP_CALL( SCIPchgVarObjProbing(origscip, vars[j], obj + (objfactor * objadd) / objdivisor) );
484 SCIPfreeBufferArray(origscip, &solvals);
485 SCIPfreeBufferArray(origscip, &vars);
493 SCIP_RETCODE getEqualityMatrixGsl(
517 *ncols = SCIPgetNLPCols(scip);
518 nlprows = SCIPgetNLPRows(scip);
519 lprows = SCIPgetLPRows(scip);
520 nlpcols = SCIPgetNLPCols(scip);
521 lpcols = SCIPgetLPCols(scip);
528 SCIP_CALL( SCIPallocBufferArray(scip, &var2col, nlpcols) );
529 SCIP_CALL( SCIPallocBufferArray(scip, &delvars, nlpcols) );
532 for( i = 0; i < nlpcols; ++i )
539 lpvar = SCIPcolGetVar(lpcol);
541 if( SCIPisEQ(scip, SCIPgetSolVal(scip, sol, lpvar), SCIPcolGetUb(lpcol) )
542 || SCIPisEQ(scip, SCIPgetSolVal(scip, sol, lpvar), SCIPcolGetLb(lpcol)) )
546 ind = SCIPcolGetIndex(lpcol);
548 delvars[ndelvars] = ind;
558 ind = SCIPcolGetIndex(lpcol);
560 var2col[ind] = nvar2col;
566 SCIPsortInt(delvars, ndelvars);
568 *matrix = gsl_matrix_calloc(nlprows, nvar2col);
573 for( i = 0; i < nlprows; ++i )
580 if( SCIPisEQ(scip, SCIPgetRowSolFeasibility(scip, lprow, sol), 0.0) )
586 cols = SCIProwGetCols(lprow);
587 vals = SCIProwGetVals(lprow);
588 nnonz = SCIProwGetNNonz(lprow);
591 for( j = 0; j < nnonz; ++j )
596 ind = SCIPcolGetIndex(cols[j]);
597 assert(ind >= 0 && ind < nlpcols);
599 if( !SCIPsortedvecFindInt(delvars, ind, ndelvars, &pos) )
601 gsl_matrix_set(*matrix, *nrows, var2col[ind], vals[j]);
610 SCIPfreeBufferArray(scip, &delvars);
611 SCIPfreeBufferArray(scip, &var2col);
618 SCIP_RETCODE getRank(
631 gsl_permutation* permutation;
638 matrixq = gsl_matrix_alloc(nrows, nrows);
639 matrixr = gsl_matrix_alloc(nrows, ncols);
641 norm = gsl_vector_alloc(ncols);
642 tau = gsl_vector_alloc(MIN(nrows, ncols));
644 permutation = gsl_permutation_alloc(ncols);
646 gsl_linalg_QRPT_decomp(matrix, tau, permutation, &signum, norm);
648 gsl_linalg_QR_unpack(matrix, tau, matrixq, matrixr);
652 for( i = 0; i < MIN(nrows, ncols); ++i )
656 val = gsl_matrix_get(matrixr, i, i);
658 if( SCIPisZero(scip, val) )
667 gsl_matrix_free(matrixq);
668 gsl_matrix_free(matrixr);
670 gsl_vector_free(tau);
671 gsl_vector_free(norm);
673 gsl_permutation_free(permutation);
681 SCIP_RETCODE getEqualityRankGsl(
694 SCIP_CALL( getEqualityMatrixGsl(scip, sol, &matrix, &nrows, &ncols, &prerank) );
696 SCIP_CALL( getRank(scip, matrix, nrows, ncols, &rowrank) );
698 gsl_matrix_free(matrix);
700 *equalityrank = rowrank + prerank;
713 SCIP_Real dualsolconv,
718 SCIP_SEPADATA* sepadata;
722 SCIP_VAR** pricingvars;
728 char name[SCIP_MAXSTRLEN];
736 sepadata = SCIPsepaGetData(sepa);
740 pricingvars = SCIPgetOrigVars(pricingscip);
741 npricingvars = SCIPgetNOrigVars(pricingscip);
747 rhs = SCIPinfinity(scip);
753 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN,
"newconstraint_%d_%d_%d", SCIPsepaGetNCalls(sepa), ppnumber, k);
755 SCIP_CALL( SCIPcreateEmptyRowUnspec(scip, &origcut, name, lhs, rhs, FALSE, FALSE, TRUE) );
759 for( j = 0; j < npricingvars ; ++j )
763 if( !SCIPisEQ(scip, SCIPvarGetObj(pricingvars[j]), 0.0) )
767 SCIP_CALL( SCIPaddVarToRow(scip, origcut, var, SCIPvarGetObj(pricingvars[j])) );
778 sepadata->newcuts[sepadata->nnewcuts] = origcut;
779 SCIP_CALL( SCIPcaptureRow(scip, sepadata->newcuts[sepadata->nnewcuts]) );
780 ++(sepadata->nnewcuts);
782 SCIPdebugMessage(
"cut added to new cuts in relaxdata\n");
786 SCIP_CALL( SCIPaddPoolCut(scip, origcut) );
787 SCIPdebugMessage(
"cut added to orig cut pool\n");
792 SCIP_CALL( SCIPaddRowProbing(scip, origcut) );
793 SCIPdebugMessage(
"cut added to probing\n");
798 SCIP_CALL( SCIPreleaseRow(scip, &origcut) );
808 #define sepaCopyBasis NULL
814 SCIP_SEPADATA* sepadata;
816 sepadata = SCIPsepaGetData(sepa);
817 assert(sepadata != NULL);
819 SCIPfreeBlockMemory(scip, &sepadata);
829 SCIP_SEPADATA* sepadata;
834 char name[SCIP_MAXSTRLEN];
842 assert(scip != NULL);
845 assert(origscip != NULL);
847 sepadata = SCIPsepaGetData(sepa);
848 assert(sepadata != NULL);
850 origvars = SCIPgetVars(origscip);
851 norigvars = SCIPgetNVars(origscip);
853 SCIPdebugMessage(
"sepaInitBasis\n");
855 enable = sepadata->enable;
856 enableobj = sepadata->enableobj;
858 sepadata->maxcuts = SCIPcalcMemGrowSize(scip,
STARTMAXCUTS);
859 sepadata->norigcuts = 0;
860 sepadata->nmastercuts = 0;
861 sepadata->maxnewcuts = SCIPcalcMemGrowSize(scip,
STARTMAXCUTS);
862 sepadata->nnewcuts = 0;
863 sepadata->objrow = NULL;
870 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(sepadata->origcuts), sepadata->maxcuts) );
871 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(sepadata->mastercuts), sepadata->maxcuts) );
872 SCIP_CALL( SCIPallocBlockMemoryArray(scip, &(sepadata->newcuts), sepadata->maxnewcuts) );
877 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN,
"objrow");
878 SCIP_CALL( SCIPcreateEmptyRowUnspec(origscip, &(sepadata->objrow), name, -SCIPinfinity(origscip), SCIPinfinity(origscip), TRUE, FALSE, TRUE) );
880 for( i = 0; i < norigvars; ++i )
882 obj = SCIPvarGetObj(origvars[i]);
883 SCIP_CALL( SCIPaddVarToRow(origscip, sepadata->objrow, origvars[i], obj) );
896 SCIP_SEPADATA* sepadata;
901 sepadata = SCIPsepaGetData(sepa);
902 assert(sepadata != NULL);
903 enableobj = sepadata->enableobj;
904 assert(sepadata->nmastercuts == sepadata->norigcuts);
907 assert(origscip != NULL);
909 for( i = 0; i < sepadata->norigcuts; i++ )
911 SCIP_CALL( SCIPreleaseRow(origscip, &(sepadata->origcuts[i])) );
914 for( i = 0; i < sepadata->nnewcuts; ++i )
916 if( sepadata->newcuts[i] != NULL )
917 SCIP_CALL( SCIPreleaseRow(origscip, &(sepadata->newcuts[i])) );
921 SCIP_CALL( SCIPreleaseRow(origscip, &(sepadata->objrow)) );
923 SCIPfreeBlockMemoryArrayNull(scip, &(sepadata->origcuts), sepadata->maxcuts);
924 SCIPfreeBlockMemoryArrayNull(scip, &(sepadata->mastercuts), sepadata->maxcuts);
925 SCIPfreeBlockMemoryArrayNull(scip, &(sepadata->newcuts), sepadata->maxnewcuts);
934 SCIP_SEPADATA* sepadata;
936 sepadata = SCIPsepaGetData(sepa);
937 assert(sepadata != NULL);
939 sepadata->nmastercuts = 0;
949 SCIP_SEPADATA* sepadata;
952 sepadata = SCIPsepaGetData(sepa);
953 assert(sepadata != NULL);
954 assert(sepadata->nmastercuts == sepadata->norigcuts);
958 for( i = 0; i < sepadata->nmastercuts; i++ )
960 SCIP_CALL( SCIPreleaseRow(scip, &(sepadata->mastercuts[i])) );
971 SCIP_SEPADATA* sepadata,
981 SCIP_CALL( getEqualityRankGsl(origscip, origsol, &rank) );
983 *convex = 1.0* rank/nbasis;
985 SCIPdebugMessage(
"use generic coefficient %d/%d = %f\n", rank, nbasis, *convex);
988 SCIPwarningMessage(origscip,
"Gnu Scientific Library is not enabled! \n"
989 "either set sepa/basis/genobjconvex = FALSE sepa/basis/posslackexpgen = FALSE \n"
990 "or compile with GSL=true and include Gnu Scientific Library\n");
991 *convex = sepadata->objconvex;
1002 SCIP_SEPADATA* sepadata,
1005 SCIP_Bool genericconv
1008 SCIP_Real objnormnull;
1009 SCIP_Real objnormcurrent;
1012 objnormcurrent = 1.0;
1015 if( SCIPisEQ(origscip, convex, 0.0) )
1017 SCIP_CALL( initProbingObjWithOrigObj(origscip, TRUE, 1.0) );
1020 else if( SCIPisLT(origscip, convex, 1.0) )
1022 SCIP_CALL( initProbingObjWithOrigObj(origscip, TRUE, 1.0) );
1023 objnormnull = SCIPgetObjNorm(origscip);
1025 SCIP_CALL( initProbingObjUsingVarBounds(origscip, sepadata, origsol, FALSE, convex) );
1028 objnormcurrent = SCIPgetObjNorm(origscip)/(convex);
1030 if( SCIPisEQ(origscip, objnormcurrent, 0.0) )
1031 SCIP_CALL( initProbingObjWithOrigObj(origscip, TRUE, 1.0) );
1032 else if( SCIPisGT(origscip, objnormnull, 0.0) )
1033 SCIP_CALL( chgProbingObjAddingOrigObj(origscip, (1.0 - convex) * objnormcurrent, objnormnull) );
1036 else if( SCIPisEQ(origscip, convex, 1.0) )
1038 SCIP_CALL( initProbingObjUsingVarBounds(origscip, sepadata, origsol, !genericconv && sepadata->enableobj, 1.0) );
1051 SCIP_SEPADATA* sepadata;
1054 SCIP_ROW* mastercut;
1057 SCIP_VAR** roworigvars;
1058 SCIP_VAR** mastervars;
1059 SCIP_Real* mastervals;
1069 SCIP_Bool infeasible;
1073 SCIP_Bool enableobj;
1074 SCIP_Bool enableobjround;
1075 SCIP_Bool enableppobjconss;
1077 char name[SCIP_MAXSTRLEN];
1091 SCIP_RESULT resultdummy;
1093 SCIP_Bool enoughcuts;
1096 int maxnsepastallrounds;
1098 SCIP_Real objreldiff;
1100 SCIP_Real stalllpobjval;
1103 int nsepastallrounds;
1105 SCIP_LPSOLSTAT stalllpsolstat;
1108 assert(scip != NULL);
1109 assert(result != NULL);
1112 assert(origscip != NULL);
1114 sepadata = SCIPsepaGetData(sepa);
1115 assert(sepadata != NULL);
1117 SCIPdebugMessage(
"calling sepaExeclpBasis\n");
1119 *result = SCIP_DIDNOTFIND;
1121 enable = sepadata->enable;
1122 enableobj = sepadata->enableobj;
1123 enableobjround = sepadata->enableobjround;
1124 enableppobjconss = sepadata->enableppobjconss;
1129 SCIPdebugMessage(
"separator is not enabled\n");
1130 *result = SCIP_DIDNOTRUN;
1135 if( SCIPgetLPSolstat(scip) != SCIP_LPSOLSTAT_OPTIMAL )
1137 SCIPdebugMessage(
"master LP not solved to optimality, do no separation!\n");
1138 *result = SCIP_DIDNOTRUN;
1145 SCIPdebugMessage(
"aggregated pricing problems, do no separation!\n");
1146 *result = SCIP_DIDNOTRUN;
1156 SCIPdebugMessage(
"Current solution is feasible, no separation necessary!\n");
1157 *result = SCIP_DIDNOTRUN;
1162 if( sepadata->currentnodenr != SCIPnodeGetNumber(SCIPgetCurrentNode(scip)) )
1164 sepadata->currentnodenr = SCIPnodeGetNumber(SCIPgetCurrentNode(scip));
1165 sepadata->round = 0;
1168 isroot = SCIPgetCurrentNode(scip) == SCIPgetRootNode(scip);
1171 maxrounds = (isroot ? sepadata->maxroundsroot : sepadata->maxrounds);
1174 if( maxrounds == -1 )
1175 maxrounds = INT_MAX;
1181 obj = SCIPgetSolTransObj(origscip, origsol);
1184 nbasis = SCIPgetNLPCols(origscip);
1186 *result = SCIP_DIDNOTFIND;
1192 SCIP_CALL( SCIPsetSeparating(origscip, (SCIP_PARAMSETTING) sepadata->separationsetting, TRUE) );
1195 SCIP_CALL( SCIPsetIntParam(origscip,
"separating/rapidlearning/freq", -1) );
1198 SCIP_CALL( SCIPstartProbing(origscip) );
1199 SCIP_CALL( SCIPnewProbingNode(origscip) );
1200 SCIP_CALL( SCIPconstructLP(origscip, &cutoff) );
1210 for( i = 0; i < sepadata->nnewcuts; ++i )
1212 if( SCIProwGetLPPos(sepadata->newcuts[i]) == -1 )
1213 SCIP_CALL( SCIPaddRowProbing(origscip, sepadata->newcuts[i]) );
1217 nlprowsstart = SCIPgetNLPRows(origscip);
1219 nsepastallrounds = 0;
1220 stalllpobjval = SCIP_REAL_MIN;
1221 stallnfracs = INT_MAX;
1226 SCIP_CALL( SCIPgetIntParam(origscip,
"separating/maxcutsroot", &maxcuts) );
1228 SCIP_CALL( SCIPgetIntParam(origscip,
"separating/maxcuts", &maxcuts) );
1230 maxnsepastallrounds = 0;
1232 SCIP_CALL( SCIPgetIntParam(origscip,
"separating/maxstallroundsroot", &maxnsepastallrounds) );
1234 SCIP_CALL( SCIPgetIntParam(origscip,
"separating/maxstallrounds", &maxnsepastallrounds) );
1236 if( maxnsepastallrounds == -1 )
1237 maxnsepastallrounds = INT_MAX;
1239 stalllpsolstat = SCIP_LPSOLSTAT_NOTSOLVED;
1244 while( sepadata->round < maxrounds && nsepastallrounds < maxnsepastallrounds )
1246 SCIPdebugMessage(
"round %d of at most %d rounds\n", sepadata->round + 1, maxrounds);
1248 SCIP_CALL( SCIPapplyCutsProbing(origscip, &cutoff) );
1251 if( enableppobjconss && iteration == 0 )
1253 SCIP_Real* dualsolconv;
1255 SCIPdebugMessage(
"add reduced cost cut for relevant pricing problems\n");
1262 SCIP_CALL(
addPPObjConss(origscip, sepa, i, dualsolconv[i], FALSE, TRUE) );
1265 SCIPfreeBufferArray(scip, &dualsolconv);
1269 if( sepadata->chgobj && (iteration == 0 || sepadata->chgobjallways) )
1271 SCIPdebugMessage(
"initialize objective function\n");
1272 if( sepadata->genobjconvex )
1274 SCIP_Real genconvex;
1276 SCIP_CALL(
initGenconv(origscip, sepadata, origsol, nbasis, &genconvex) );
1278 SCIP_CALL(
initConvObj(origscip, sepadata, origsol, genconvex, TRUE) );
1282 SCIPdebugMessage(
"use given coefficient %g\n", sepadata->objconvex);
1284 if( sepadata->enableposslack && sepadata->posslackexpgen )
1286 SCIP_Real genconvex;
1289 factor = sepadata->posslackexpgenfactor;
1291 SCIP_CALL(
initGenconv(origscip, sepadata, origsol, nbasis, &genconvex) );
1293 sepadata->posslackexp = (int) (SCIPceil(origscip, factor/(1.0 - genconvex)) + 0.5);
1295 SCIPdebugMessage(
"exponent = %d\n", sepadata->posslackexp);
1298 SCIP_CALL(
initConvObj(origscip, sepadata, origsol, sepadata->objconvex, FALSE) );
1303 if( enableobj && iteration == 0 )
1305 SCIPdebugMessage(
"initialize original objective cut\n");
1308 if( SCIPisObjIntegral(origscip) && enableobjround )
1310 SCIPdebugMessage(
"round lhs up\n");
1311 obj = SCIPceil(origscip, obj);
1314 SCIP_CALL( SCIPchgRowLhs(origscip, sepadata->objrow, obj) );
1315 SCIP_CALL( SCIPchgRowRhs(origscip, sepadata->objrow, SCIPinfinity(origscip)) );
1317 SCIPdebugMessage(
"add original objective cut to probing LP\n");
1320 SCIP_CALL( SCIPaddRowProbing(origscip, sepadata->objrow) );
1323 SCIPdebugMessage(
"solve probing LP\n");
1326 SCIP_CALL( SCIPsolveProbingLP(origscip, -1, &lperror, &cutoff) );
1335 if( SCIPgetLPSolstat(origscip) == SCIP_LPSOLSTAT_OPTIMAL )
1337 SCIP_CALL( SCIPgetLPBranchCands(origscip, NULL, NULL, NULL, &nfracs, NULL, NULL) );
1338 lpobjval = SCIPgetLPObjval(origscip);
1340 objreldiff = SCIPrelDiff(lpobjval, stalllpobjval);
1341 SCIPdebugMessage(
" -> LP bound moved from %g to %g (reldiff: %g)\n",
1342 stalllpobjval, lpobjval, objreldiff);
1344 stalling = (objreldiff <= 1e-04 &&
1345 nfracs >= (0.9 - 0.1 * nsepastallrounds) * stallnfracs);
1347 stalllpobjval = lpobjval;
1348 stallnfracs = nfracs;
1352 stalling = (stalllpsolstat == SCIPgetLPSolstat(origscip));
1357 nsepastallrounds = 0;
1363 stalllpsolstat = SCIPgetLPSolstat(origscip);
1366 SCIPdebugMessage(
"separate current LP sol in cutpool\n");
1367 SCIP_CALL( SCIPseparateSolCutpool(origscip, SCIPgetGlobalCutpool(origscip), NULL, isroot, &resultdummy) );
1369 enoughcuts = (SCIPgetNCuts(origscip) >= 2 * (SCIP_Longint)maxcuts) || (resultdummy == SCIP_NEWROUND);
1374 SCIPdebugMessage(
"separate current LP solution\n");
1375 SCIP_CALL( SCIPseparateSol(origscip, NULL, isroot, isroot, FALSE, &delayed, &cutoff) );
1377 enoughcuts = enoughcuts || (SCIPgetNCuts(origscip) >= 2 * (SCIP_Longint)maxcuts) || (resultdummy == SCIP_NEWROUND);
1380 if( !enoughcuts && delayed && !cutoff && nsepastallrounds >= maxnsepastallrounds-1)
1382 SCIPdebugMessage(
"call delayed separators\n");
1383 SCIP_CALL( SCIPseparateSol(origscip, NULL, isroot, isroot, TRUE, &delayed, &cutoff) );
1387 if( !enoughcuts && !cutoff )
1390 SCIPdebugMessage(
"separate current LP sol in cutpool\n");
1391 SCIP_CALL( SCIPseparateSolCutpool(origscip, SCIPgetGlobalCutpool(origscip), NULL, isroot, &resultdummy) );
1393 enoughcuts = enoughcuts || (SCIPgetNCuts(origscip) >= 2 * (SCIP_Longint)maxcuts) || (resultdummy == SCIP_NEWROUND);
1396 if( SCIPgetNCuts(origscip) == 0 && !cutoff )
1399 SCIPdebugMessage(
"separate current LP sol in delayed cutpool\n");
1400 SCIP_CALL( SCIPseparateSolCutpool(origscip, SCIPgetDelayedGlobalCutpool(origscip), NULL, isroot, &resultdummy) );
1402 enoughcuts = enoughcuts || (SCIPgetNCuts(origscip) >= 2 * (SCIP_Longint)maxcuts) || (resultdummy == SCIP_NEWROUND);
1408 *result = SCIP_CUTOFF;
1409 SCIP_CALL( SCIPendProbing(origscip) );
1412 SCIP_CALL( SCIPsetSeparating(origscip, SCIP_PARAMSETTING_OFF, TRUE) );
1418 SCIP_CALL( SCIPseparateSolCutpool(origscip, SCIPgetGlobalCutpool(origscip), origsol, isroot, &resultdummy) );
1419 SCIP_CALL( SCIPseparateSolCutpool(origscip, SCIPgetDelayedGlobalCutpool(origscip), origsol, isroot, &resultdummy) );
1421 assert(sepadata->norigcuts == sepadata->nmastercuts);
1423 SCIPdebugMessage(
"%d cuts are in the original sepastore!\n", SCIPgetNCuts(origscip));
1426 cuts = SCIPgetCuts(origscip);
1427 ncuts = SCIPgetNCuts(origscip);
1429 SCIP_CALL(
ensureSizeCuts(scip, sepadata, sepadata->norigcuts + ncuts) );
1431 mastervars = SCIPgetVars(scip);
1432 nmastervars = SCIPgetNVars(scip);
1433 SCIP_CALL( SCIPallocBufferArray(scip, &mastervals, nmastervars) );
1444 for( i = 0; i < ncuts; i++ )
1446 SCIP_Bool colvarused;
1453 if( SCIPisCutEfficacious(origscip, NULL, origcut) )
1459 ncols = SCIProwGetNNonz(origcut);
1460 cols = SCIProwGetCols(origcut);
1461 vals = SCIProwGetVals(origcut);
1464 SCIP_CALL( SCIPallocBufferArray(scip, &roworigvars, ncols) );
1465 for( j = 0; j < ncols; j++ )
1467 roworigvars[j] = SCIPcolGetVar(cols[j]);
1468 assert(roworigvars[j] != NULL);
1478 SCIPwarningMessage(origscip,
"colvar used in original cut %s\n", SCIProwGetName(origcut));
1479 SCIPfreeBufferArray(scip, &roworigvars);
1483 if( !SCIPisCutEfficacious(origscip, origsol, origcut) )
1485 if( !SCIProwIsLocal(origcut) )
1486 SCIP_CALL( SCIPaddPoolCut(origscip, origcut) );
1488 SCIPfreeBufferArray(scip, &roworigvars);
1494 sepadata->origcuts[sepadata->norigcuts] = origcut;
1495 SCIP_CALL( SCIPcaptureRow(origscip, sepadata->origcuts[sepadata->norigcuts]) );
1496 sepadata->norigcuts++;
1502 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN,
"mc_basis_%s", SCIProwGetName(origcut));
1503 SCIP_CALL( SCIPcreateEmptyRowSepa(scip, &mastercut, sepa, name,
1504 ( SCIPisInfinity(scip, -SCIProwGetLhs(origcut)) ?
1505 SCIProwGetLhs(origcut) : SCIProwGetLhs(origcut) - SCIProwGetConstant(origcut) - shift),
1506 ( SCIPisInfinity(scip, SCIProwGetRhs(origcut)) ?
1507 SCIProwGetRhs(origcut) : SCIProwGetRhs(origcut) - SCIProwGetConstant(origcut) - shift),
1508 SCIProwIsLocal(origcut), TRUE, FALSE) );
1511 SCIP_CALL( SCIPaddVarsToRow(scip, mastercut, nmastervars, mastervars, mastervals) );
1514 SCIP_CALL( SCIPaddRow(scip, mastercut, sepadata->forcecuts, &infeasible) );
1515 sepadata->mastercuts[sepadata->nmastercuts] = mastercut;
1516 SCIP_CALL( SCIPcaptureRow(scip, sepadata->mastercuts[sepadata->nmastercuts]) );
1517 sepadata->nmastercuts++;
1520 SCIP_CALL( SCIPreleaseRow(scip, &mastercut) );
1521 SCIPfreeBufferArray(scip, &roworigvars);
1524 SCIPdebugMessage(
"%d cuts are in the master sepastore!\n", SCIPgetNCuts(scip));
1529 if( SCIPgetNCuts(scip) >= sepadata->mincuts )
1531 *result = SCIP_SEPARATED;
1533 SCIPfreeBufferArray(scip, &mastervals);
1538 else if( nviolatedcuts == 0 )
1540 SCIPfreeBufferArray(scip, &mastervals);
1544 SCIPfreeBufferArray(scip, &mastervals);
1546 assert(sepadata->norigcuts == sepadata->nmastercuts );
1549 SCIP_CALL( SCIPclearCuts(origscip) );
1551 lprows = SCIPgetLPRows(origscip);
1552 nlprows = SCIPgetNLPRows(origscip);
1554 assert(nlprowsstart <= nlprows);
1556 SCIP_CALL(
ensureSizeNewCuts(scip, sepadata, sepadata->nnewcuts + nlprows - nlprowsstart) );
1558 for( i = nlprowsstart; i < nlprows; ++i )
1560 if( SCIProwGetOrigintype(lprows[i]) == SCIP_ROWORIGINTYPE_SEPA )
1562 sepadata->newcuts[sepadata->nnewcuts] = lprows[i];
1563 SCIP_CALL( SCIPcaptureRow(origscip, sepadata->newcuts[sepadata->nnewcuts]) );
1564 ++(sepadata->nnewcuts);
1569 SCIP_CALL( SCIPendProbing(origscip) );
1571 if( SCIPgetNCuts(scip) > 0 )
1573 *result = SCIP_SEPARATED;
1577 SCIP_CALL( SCIPsetSeparating(origscip, SCIP_PARAMSETTING_OFF, TRUE) );
1579 SCIPdebugMessage(
"exiting sepaExeclpBasis\n");
1585 #define sepaExecsolBasis NULL
1596 SCIP_SEPADATA* sepadata;
1599 SCIP_CALL( SCIPallocBlockMemory(scip, &sepadata) );
1601 sepadata->mastercuts = NULL;
1602 sepadata->origcuts = NULL;
1603 sepadata->norigcuts = 0;
1604 sepadata->nmastercuts = 0;
1605 sepadata->maxcuts = 0;
1606 sepadata->newcuts = NULL;
1607 sepadata->nnewcuts = 0;
1608 sepadata->maxnewcuts = 0;
1609 sepadata->objrow = NULL;
1610 sepadata->round = 0;
1611 sepadata->currentnodenr = -1;
1621 &(sepadata->enable), FALSE, TRUE, NULL, NULL) );
1624 &(sepadata->enableobj), FALSE, FALSE, NULL, NULL) );
1626 SCIP_CALL( SCIPaddBoolParam(
GCGmasterGetOrigprob(scip),
"sepa/" SEPA_NAME "/enableobjround",
"round obj rhs/lhs of obj constraint if obj is int?",
1627 &(sepadata->enableobjround), FALSE, FALSE, NULL, NULL) );
1629 SCIP_CALL( SCIPaddBoolParam(
GCGmasterGetOrigprob(scip),
"sepa/" SEPA_NAME "/enableppcuts",
"add cuts generated during pricing to newconss array?",
1630 &(sepadata->enableppcuts), FALSE, FALSE, NULL, NULL) );
1632 SCIP_CALL( SCIPaddBoolParam(
GCGmasterGetOrigprob(scip),
"sepa/" SEPA_NAME "/enableppobjconss",
"is objective constraint for redcost of each pp of "
1633 "separator enabled?", &(sepadata->enableppobjconss), FALSE, FALSE, NULL, NULL) );
1635 SCIP_CALL( SCIPaddBoolParam(
GCGmasterGetOrigprob(scip),
"sepa/" SEPA_NAME "/enableppobjcg",
"is objective constraint for redcost of each pp during "
1636 "pricing of separator enabled?", &(sepadata->enableppobjcg), FALSE, FALSE, NULL, NULL) );
1639 &(sepadata->genobjconvex), FALSE, FALSE, NULL, NULL) );
1641 SCIP_CALL( SCIPaddBoolParam(
GCGmasterGetOrigprob(scip),
"sepa/" SEPA_NAME "/enableposslack",
"should positive slack influence the probing objective "
1642 "function?", &(sepadata->enableposslack), FALSE, FALSE, NULL, NULL) );
1645 &(sepadata->posslackexp), FALSE, 1, 1, INT_MAX, NULL, NULL) );
1648 &(sepadata->posslackexpgen), FALSE, FALSE, NULL, NULL) );
1650 SCIP_CALL( SCIPaddRealParam(
GCGmasterGetOrigprob(scip),
"sepa/" SEPA_NAME "/posslackexpgenfactor",
"factor for automatically generated exponent",
1654 SCIP_CALL( SCIPaddRealParam(
GCGmasterGetOrigprob(scip),
"sepa/" SEPA_NAME "/objconvex",
"convex combination factor (= 0.0, use original objective; = 1.0, use face objective)",
1655 &(sepadata->objconvex), FALSE, 0.0, 0.0, 1.0, NULL, NULL) );
1657 SCIP_CALL( SCIPaddIntParam(
GCGmasterGetOrigprob(scip),
"sepa/" SEPA_NAME "/paramsetting",
"parameter returns which parameter setting is used for "
1658 "separation (default = 0, aggressive = 1, fast = 2", &(sepadata->separationsetting), FALSE, 0, 0, 2, NULL, NULL) );
1660 SCIP_CALL( SCIPaddBoolParam(
GCGmasterGetOrigprob(scip),
"sepa/" SEPA_NAME "/chgobj",
"parameter returns if basis is searched with different objective",
1661 &(sepadata->chgobj), FALSE, TRUE, NULL, NULL) );
1663 SCIP_CALL( SCIPaddIntParam(
GCGmasterGetOrigprob(scip),
"sepa/" SEPA_NAME "/maxrounds",
"parameter returns maximum number of separation rounds in probing LP (-1 if unlimited)",
1664 &(sepadata->maxrounds), FALSE, -1, -1, INT_MAX , NULL, NULL) );
1666 SCIP_CALL( SCIPaddIntParam(
GCGmasterGetOrigprob(scip),
"sepa/" SEPA_NAME "/maxroundsroot",
"parameter returns maximum number of separation rounds in probing LP in root node (-1 if unlimited)",
1667 &(sepadata->maxroundsroot), FALSE, -1, -1, INT_MAX , NULL, NULL) );
1670 "return *result = SCIP_Separated", &(sepadata->mincuts), FALSE, 50, 1, INT_MAX, NULL, NULL) );
1672 SCIP_CALL( SCIPaddBoolParam(
GCGmasterGetOrigprob(scip),
"sepa/" SEPA_NAME "/chgobjallways",
"parameter returns if obj is changed not only in the "
1673 "first round", &(sepadata->chgobjallways), FALSE, FALSE, NULL, NULL) );
1675 SCIP_CALL( SCIPaddBoolParam(
GCGmasterGetOrigprob(scip),
"sepa/" SEPA_NAME "/forcecuts",
"parameter returns if cuts are forced to enter the LP ",
1676 &(sepadata->forcecuts), FALSE, FALSE, NULL, NULL) );
1688 SCIP_SEPADATA* sepadata;
1690 assert(scip != NULL);
1693 assert(sepa != NULL);
1695 sepadata = SCIPsepaGetData(sepa);
1696 assert(sepadata != NULL);
1698 return sepadata->origcuts;
1707 SCIP_SEPADATA* sepadata;
1709 assert(scip != NULL);
1712 assert(sepa != NULL);
1714 sepadata = SCIPsepaGetData(sepa);
1715 assert(sepadata != NULL);
1717 return sepadata->norigcuts;
1726 SCIP_SEPADATA* sepadata;
1728 assert(scip != NULL);
1731 assert(sepa != NULL);
1733 sepadata = SCIPsepaGetData(sepa);
1734 assert(sepadata != NULL);
1736 return sepadata->mastercuts;
1745 SCIP_SEPADATA* sepadata;
1747 assert(scip != NULL);
1750 assert(sepa != NULL);
1752 sepadata = SCIPsepaGetData(sepa);
1753 assert(sepadata != NULL);
1755 return sepadata->nmastercuts;
1767 SCIP_SEPADATA* sepadata;
1772 SCIP_VAR** pricingvars;
1779 char name[SCIP_MAXSTRLEN];
1787 SCIPerrorMessage(
"sepa basis not found\n");
1791 sepadata = SCIPsepaGetData(sepa);
1795 if( !sepadata->enableppcuts )
1800 assert(!SCIProwIsLocal(cut));
1802 nvars = SCIProwGetNNonz(cut);
1803 cols = SCIProwGetCols(cut);
1804 vals = SCIProwGetVals(cut);
1811 SCIP_CALL( SCIPallocBufferArray(scip, &pricingvars, nvars) );
1813 for( i = 0; i < nvars; ++i )
1815 pricingvars[i] = SCIPcolGetVar(cols[i]);
1816 assert(pricingvars[i] != NULL);
1823 (void) SCIPsnprintf(name, SCIP_MAXSTRLEN,
"ppcut_%d_%d_%d", SCIPsepaGetNCalls(sepa), ppnumber, k);
1825 SCIP_CALL( SCIPcreateEmptyRowUnspec(origscip, &origcut, name,
1826 ( SCIPisInfinity(pricingprob, -SCIProwGetLhs(cut)) ?
1827 -SCIPinfinity(origscip) : SCIProwGetLhs(cut) - SCIProwGetConstant(cut)),
1828 ( SCIPisInfinity(pricingprob, SCIProwGetRhs(cut)) ?
1829 SCIPinfinity(origscip) : SCIProwGetRhs(cut) - SCIProwGetConstant(cut)),
1830 FALSE, FALSE, TRUE) );
1832 for( j = 0; j < nvars ; ++j )
1844 assert(var != NULL);
1846 SCIP_CALL( SCIPaddVarToRow(origscip, origcut, var, vals[j]) );
1853 sepadata->newcuts[sepadata->nnewcuts] = origcut;
1854 SCIP_CALL( SCIPcaptureRow(scip, sepadata->newcuts[sepadata->nnewcuts]) );
1855 ++(sepadata->nnewcuts);
1857 SCIPdebugMessage(
"cut added to orig cut pool\n");
1859 SCIP_CALL( SCIPreleaseRow(origscip, &origcut) );
1862 SCIPfreeBufferArray(scip, &pricingvars);
1872 SCIP_Real dualsolconv,
1884 SCIPerrorMessage(
"sepa basis not found\n");