cuts.c
Go to the documentation of this file.
33 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
58 /* =========================================== general static functions =========================================== */
91 SCIPquadprecProdQD(coef, coef, (sol == NULL ? SCIPvarGetLPSol(vars[cutinds[i]]) : SCIPgetSolVal(scip, sol, vars[cutinds[i]])));
97 SCIPquadprecProdQD(coef, coef, (islocal ? SCIPvarGetLbLocal(vars[cutinds[i]]) : SCIPvarGetLbGlobal(vars[cutinds[i]])));
101 SCIPquadprecProdQD(coef, coef, (islocal ? SCIPvarGetUbLocal(vars[cutinds[i]]) : SCIPvarGetUbGlobal(vars[cutinds[i]])));
125 int*RESTRICT inds, /**< pointer to array with variable problem indices of non-zeros in variable vector */
170 int*RESTRICT inds, /**< pointer to array with variable problem indices of non-zeros in variable vector */
215 int* cutinds, /**< array of the problem indices of variables with a non-zero coefficient in the cut */
273 /** calculates the efficacy norm of the given aggregation row, which depends on the "separating/efficacynorm" parameter */
277 SCIP_Real* vals, /**< array of the non-zero coefficients in the vector; this is a quad precision array! */
278 int* inds, /**< array of the problem indices of variables with a non-zero coefficient in the vector */
335 /** calculates the cut efficacy for the given solution; the cut coefs are stored densely and in quad precision */
340 SCIP_Real* cutcoefs, /**< array of the non-zero coefficients in the cut; this is a quad precision array! */
342 int* cutinds, /**< array of the problem indices of variables with a non-zero coefficient in the cut */
418 int* cutinds, /**< array of the problem indices of variables with a non-zero coefficient in the cut */
511 int* cutinds, /**< array of the problem indices of variables with a non-zero coefficient in the cut */
520 /* loop over non-zeros and remove values below minval; values above QUAD_EPSILON are cancelled with their bound
635 /** change given coefficient to new given value, adjust right hand side using the variables bound;
680 /** change given (quad) coefficient to new given value, adjust right hand side using the variables bound;
725 /** scales the cut and then tightens the coefficients of the given cut based on the maximal activity;
726 * see cons_linear.c consdataTightenCoefs() for details; the cut is given in a semi-sparse quad precision array;
736 int* cutinds, /**< array of the problem indices of variables with a non-zero coefficient in the cut */
758 /* compute maximal activity and maximal absolute coefficient values for all and for integral variables in the cut */
770 SCIP_Real lb = cutislocal ? SCIPvarGetLbLocal(vars[cutinds[i]]) : SCIPvarGetLbGlobal(vars[cutinds[i]]);
788 SCIP_Real ub = cutislocal ? SCIPvarGetUbLocal(vars[cutinds[i]]) : SCIPvarGetUbGlobal(vars[cutinds[i]]);
838 (SCIP_Longint)scip->set->sepa_maxcoefratio, scip->set->sepa_maxcoefratio, &intscalar, &success) );
859 if( chgQuadCoeffWithBound(scip, vars[cutinds[i]], QUAD(val), intval, cutislocal, QUAD(cutrhs)) )
899 SCIP_Real lb = cutislocal ? SCIPvarGetLbLocal(vars[cutinds[i]]) : SCIPvarGetLbGlobal(vars[cutinds[i]]);
909 SCIP_Real ub = cutislocal ? SCIPvarGetUbLocal(vars[cutinds[i]]) : SCIPvarGetUbGlobal(vars[cutinds[i]]);
982 /* no coefficient tightening can be performed since the precondition doesn't hold for any of the variables */
988 /* loop over the integral variables and try to tighten the coefficients; see cons_linear for more details */
1003 if( QUAD_TO_DBL(val) < 0.0 && SCIPisLE(scip, maxact + QUAD_TO_DBL(val), QUAD_TO_DBL(*cutrhs)) )
1006 SCIP_Real lb = cutislocal ? SCIPvarGetLbLocal(vars[cutinds[i]]) : SCIPvarGetLbGlobal(vars[cutinds[i]]);
1012 /* if cut is integral, the true coefficient must also be integral; thus round it to exact integral value */
1026 SCIPdebugPrintf("tightened coefficient from %g to %g; rhs changed from %g to %g; the bounds are [%g,%g]\n",
1050 else if( QUAD_TO_DBL(val) > 0.0 && SCIPisLE(scip, maxact - QUAD_TO_DBL(val), QUAD_TO_DBL(*cutrhs)) )
1053 SCIP_Real ub = cutislocal ? SCIPvarGetUbLocal(vars[cutinds[i]]) : SCIPvarGetUbGlobal(vars[cutinds[i]]);
1059 /* if cut is integral, the true coefficient must also be integral; thus round it to exact integral value */
1073 SCIPdebugPrintf("tightened coefficient from %g to %g; rhs changed from %g to %g; the bounds are [%g,%g]\n",
1097 else /* due to sorting we can stop completely if the precondition was not fulfilled for this variable */
1106 /** scales the cut and then tightens the coefficients of the given cut based on the maximal activity;
1107 * see cons_linear.c consdataTightenCoefs() for details; the cut is given in a semi-sparse array;
1115 int* cutinds, /**< array of the problem indices of variables with a non-zero coefficient in the cut */
1137 /* compute maximal activity and maximal absolute coefficient values for all and for integral variables in the cut */
1149 SCIP_Real lb = cutislocal ? SCIPvarGetLbLocal(vars[cutinds[i]]) : SCIPvarGetLbGlobal(vars[cutinds[i]]);
1166 SCIP_Real ub = cutislocal ? SCIPvarGetUbLocal(vars[cutinds[i]]) : SCIPvarGetUbGlobal(vars[cutinds[i]]);
1213 SCIP_CALL( SCIPcalcIntegralScalar(intcoeffs, *cutnnz, -SCIPsumepsilon(scip), SCIPepsilon(scip),
1214 (SCIP_Longint)scip->set->sepa_maxcoefratio, scip->set->sepa_maxcoefratio, &intscalar, &success) );
1273 SCIP_Real lb = cutislocal ? SCIPvarGetLbLocal(vars[cutinds[i]]) : SCIPvarGetLbGlobal(vars[cutinds[i]]);
1283 SCIP_Real ub = cutislocal ? SCIPvarGetUbLocal(vars[cutinds[i]]) : SCIPvarGetUbGlobal(vars[cutinds[i]]);
1344 /* no coefficient tightening can be performed since the precondition doesn't hold for any of the variables */
1350 /* loop over the integral variables and try to tighten the coefficients; see cons_linear for more details */
1368 SCIP_Real lb = cutislocal ? SCIPvarGetLbLocal(vars[cutinds[i]]) : SCIPvarGetLbGlobal(vars[cutinds[i]]);
1374 /* if cut is integral, the true coefficient must also be integral; thus round it to exact integral value */
1388 SCIPdebugPrintf("tightened coefficient from %g to %g; rhs changed from %g to %g; the bounds are [%g,%g]\n",
1414 SCIP_Real ub = cutislocal ? SCIPvarGetUbLocal(vars[cutinds[i]]) : SCIPvarGetUbGlobal(vars[cutinds[i]]);
1420 /* if cut is integral, the true coefficient must also be integral; thus round it to exact integral value */
1434 SCIPdebugPrintf("tightened coefficient from %g to %g; rhs changed from %g to %g; the bounds are [%g,%g]\n",
1457 else /* due to sorting we can stop completely if the precondition was not fulfilled for this variable */
1466 /** perform activity based coefficient tightening on the given cut; returns TRUE if the cut was detected
1476 int* cutinds, /**< array of the problem indices of variables with a non-zero coefficient in the cut */
1508 SCIP_Real lb = cutislocal ? SCIPvarGetLbLocal(vars[cutinds[i]]) : SCIPvarGetLbGlobal(vars[cutinds[i]]);
1525 SCIP_Real ub = cutislocal ? SCIPvarGetUbLocal(vars[cutinds[i]]) : SCIPvarGetUbGlobal(vars[cutinds[i]]);
1551 /* terminate, because coefficient tightening cannot be performed; also excludes the case in which no integral variable is present */
1558 /* loop over the integral variables and try to tighten the coefficients; see cons_linear for more details */
1561 /* due to sorting, we can exit if we reached a continuous variable: all further integral variables have 0 coefficents anyway */
1570 SCIP_Real lb = cutislocal ? SCIPvarGetLbLocal(vars[cutinds[i]]) : SCIPvarGetLbGlobal(vars[cutinds[i]]);
1583 SCIPdebugPrintf("tightened coefficient from %g to %g; rhs changed from %g to %g; the bounds are [%g,%g]\n",
1611 SCIP_Real ub = cutislocal ? SCIPvarGetUbLocal(vars[cutinds[i]]) : SCIPvarGetUbGlobal(vars[cutinds[i]]);
1624 SCIPdebugPrintf("tightened coefficient from %g to %g; rhs changed from %g to %g; the bounds are [%g,%g]\n",
1649 else /* due to sorting we can stop completely if the precondition was not fulfilled for this variable */
1659 /* =========================================== aggregation row =========================================== */
1745 SCIPmessageFPrintInfo(messagehdlr, file, "%+.15g<%s> ", QUAD_TO_DBL(val), SCIPvarGetName(vars[aggrrow->inds[i]]));
1768 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*aggrrow)->vals, source->vals, QUAD_ARRAY_SIZE(nvars)) );
1779 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*aggrrow)->rowsinds, source->rowsinds, source->nrows) );
1780 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*aggrrow)->slacksign, source->slacksign, source->nrows) );
1781 SCIP_CALL( SCIPduplicateBlockMemoryArray(scip, &(*aggrrow)->rowweights, source->rowweights, source->nrows) );
1824 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &aggrrow->rowsinds, aggrrow->rowssize, newsize) );
1825 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &aggrrow->slacksign, aggrrow->rowssize, newsize) );
1826 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &aggrrow->rowweights, aggrrow->rowssize, newsize) );
1844 /* Automatically decide, whether we want to use the left or the right hand side of the row in the summation.
1871 SCIP_CALL( varVecAddScaledRowCoefsQuad(aggrrow->inds, aggrrow->vals, &aggrrow->nnz, row, weight) );
1876 /** Removes a given variable @p var from position @p pos the aggregation row and updates the right-hand side according
1877 * to sign of the coefficient, i.e., rhs -= coef * bound, where bound = lb if coef >= 0 and bound = ub, otherwise.
1879 * @note: The choice of global or local bounds depend on the validity (global or local) of the aggregation row.
1881 * @note: The list of non-zero indices will be updated by swapping the last non-zero index to @p pos.
1941 /** add the objective function with right-hand side @p rhs and scaled by @p scale to the aggregation row */
2084 /** calculates the efficacy norm of the given aggregation row, which depends on the "separating/efficacynorm" parameter
2086 * @return the efficacy norm of the given aggregation row, which depends on the "separating/efficacynorm" parameter
2096 /** Adds one row to the aggregation row. Differs from SCIPaggrRowAddRow() by providing some additional
2107 int negslack, /**< should negative slack variables allowed to be used? (0: no, 1: only for integral rows, 2: yes) */
2119 if( SCIPisFeasZero(scip, weight) || SCIProwIsModifiable(row) || (SCIProwIsLocal(row) && !allowlocal) )
2138 else if( SCIPisInfinity(scip, SCIProwGetRhs(row)) || (weight < 0.0 && ! SCIPisInfinity(scip, -SCIProwGetLhs(row))) )
2143 else if( (weight < 0.0 && !SCIPisInfinity(scip, -row->lhs)) || SCIPisInfinity(scip, row->rhs) )
2183 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &aggrrow->rowsinds, aggrrow->rowssize, newsize) );
2184 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &aggrrow->slacksign, aggrrow->rowssize, newsize) );
2185 SCIP_CALL( SCIPreallocBlockMemoryArray(scip, &aggrrow->rowweights, aggrrow->rowssize, newsize) );
2195 SCIP_CALL( varVecAddScaledRowCoefsQuad(aggrrow->inds, aggrrow->vals, &aggrrow->nnz, row, weight) );
2215 int negslack, /**< should negative slack variables allowed to be used? (0: no, 1: only for integral rows, 2: yes) */
2241 SCIP_CALL( addOneRow(scip, aggrrow, rows[rowinds[k]], weights[rowinds[k]], sidetypebasis, allowlocal, negslack, maxaggrlen, &rowtoolong) );
2253 SCIP_CALL( addOneRow(scip, aggrrow, rows[k], weights[k], sidetypebasis, allowlocal, negslack, maxaggrlen, &rowtoolong) );
2278 SCIP_Bool* success /**< pointer to return whether post-processing was succesful or cut is redundant */
2306 SCIP_CALL( cutTightenCoefs(scip, cutislocal, cutcoefs, QUAD(&rhs), cutinds, nnz, &redundant) );
2325 *success = ! removeZeros(scip, minallowedcoef, cutislocal, cutcoefs, QUAD(&rhs), cutinds, nnz);
2347 SCIP_Bool* success /**< pointer to return whether the cleanup was successful or if it is useless */
2363 if( removeZerosQuad(scip, SCIPfeastol(scip), cutislocal, cutcoefs, QUAD(cutrhs), cutinds, nnz) )
2372 SCIP_CALL( cutTightenCoefsQuad(scip, cutislocal, cutcoefs, QUAD(cutrhs), cutinds, nnz, &redundant) );
2393 *success = ! removeZerosQuad(scip, minallowedcoef, cutislocal, cutcoefs, QUAD(cutrhs), cutinds, nnz);
2409 *valid = ! removeZerosQuad(scip, SCIPsumepsilon(scip), useglbbounds ? FALSE : aggrrow->local, aggrrow->vals,
2468 /** gets the array of corresponding variable problem indices for each non-zero in the aggregation row */
2518 /* =========================================== c-MIR =========================================== */
2528 int usevbds, /**< should variable bounds be used in bound transformation? (0: no, 1: only binary, 2: all) */
2529 SCIP_Bool allowlocal, /**< should local information allowed to be used, resulting in a local cut? */
2561 if( bestvlbidx >= 0 && (bestvlb > *bestlb || (*bestlbtype < 0 && SCIPisGE(scip, bestvlb, *bestlb))) )
2565 /* we have to avoid cyclic variable bound usage, so we enforce to use only variable bounds variables of smaller index */
2566 /**@todo this check is not needed for continuous variables; but allowing all but binary variables
2589 int usevbds, /**< should variable bounds be used in bound transformation? (0: no, 1: only binary, 2: all) */
2590 SCIP_Bool allowlocal, /**< should local information allowed to be used, resulting in a local cut? */
2622 if( bestvubidx >= 0 && (bestvub < *bestub || (*bestubtype < 0 && SCIPisLE(scip, bestvub, *bestub))) )
2626 /* we have to avoid cyclic variable bound usage, so we enforce to use only variable bounds variables of smaller index */
2627 /**@todo this check is not needed for continuous variables; but allowing all but binary variables
2644 /** determine the best bounds with respect to the given solution for complementing the given variable */
2650 SCIP_Real boundswitch, /**< fraction of domain up to which lower bound is used in transformation */
2651 int usevbds, /**< should variable bounds be used in bound transformation? (0: no, 1: only binary, 2: all) */
2652 SCIP_Bool allowlocal, /**< should local information allowed to be used, resulting in a local cut? */
2653 SCIP_Bool fixintegralrhs, /**< should complementation tried to be adjusted such that rhs gets fractional? */
2655 int* boundsfortrans, /**< bounds that should be used for transformed variables: vlb_idx/vub_idx,
2658 SCIP_BOUNDTYPE* boundtypesfortrans, /**< type of bounds that should be used for transformed variables;
2664 SCIP_BOUNDTYPE* selectedbound, /**< pointer to store whether the lower bound or the upper bound should be preferred */
2677 assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || ( boundsfortrans[v] == -2 || boundsfortrans[v] == -1 ));
2708 *bestlb = vlbcoefs[k] * (sol == NULL ? SCIPvarGetLPSol(vlbvars[k]) : SCIPgetSolVal(scip, sol, vlbvars[k])) + vlbconsts[k];
2714 /* find closest upper bound in standard upper bound (and variable upper bounds for continuous variables) */
2715 SCIP_CALL( findBestUb(scip, var, sol, fixintegralrhs ? usevbds : 0, allowlocal && fixintegralrhs, bestub, &simpleub, bestubtype) );
2746 /* we have to avoid cyclic variable bound usage, so we enforce to use only variable bounds variables of smaller index */
2747 *bestub = vubcoefs[k] * (sol == NULL ? SCIPvarGetLPSol(vubvars[k]) : SCIPgetSolVal(scip, sol, vubvars[k])) + vubconsts[k];
2753 /* find closest lower bound in standard lower bound (and variable lower bounds for continuous variables) */
2754 SCIP_CALL( findBestLb(scip, var, sol, fixintegralrhs ? usevbds : 0, allowlocal && fixintegralrhs, bestlb, &simplelb, bestlbtype) );
2763 /* find closest lower bound in standard lower bound (and variable lower bounds for continuous variables) */
2766 /* find closest upper bound in standard upper bound (and variable upper bounds for continuous variables) */
2796 else if( ((*bestlbtype) >= 0 || (*bestubtype) >= 0) && !SCIPisEQ(scip, *bestlb - simplelb, simpleub - *bestub) )
2843 /** performs the bound substitution step with the given variable or simple bounds for the variable with the given problem index */
2854 SCIP_Real boundval, /**< array of best bound to be used for the substitution for each nonzero index */
2856 SCIP_Bool* localbdsused /**< pointer to updated whether a local bound was used for substitution */
2923 /** performs the bound substitution step with the simple bound for the variable with the given problem index */
2931 SCIP_Real boundval, /**< array of best bound to be used for the substitution for each nonzero index */
2933 SCIP_Bool* localbdsused /**< pointer to updated whether a local bound was used for substitution */
2958 * x^\prime_j := x_j - lb_j,& x_j = x^\prime_j + lb_j,& a^\prime_j = a_j,& \mbox{if lb is used in transformation}\\
2959 * x^\prime_j := ub_j - x_j,& x_j = ub_j - x^\prime_j,& a^\prime_j = -a_j,& \mbox{if ub is used in transformation}
2967 * x^\prime_j := x_j - (bl_j\, zl_j + dl_j),& x_j = x^\prime_j + (bl_j\, zl_j + dl_j),& a^\prime_j = a_j,& \mbox{if vlb is used in transf.} \\
2968 * x^\prime_j := (bu_j\, zu_j + du_j) - x_j,& x_j = (bu_j\, zu_j + du_j) - x^\prime_j,& a^\prime_j = -a_j,& \mbox{if vub is used in transf.}
2971 * move the constant terms \f$ a_j\, dl_j \f$ or \f$ a_j\, du_j \f$ to the rhs, and update the coefficient of the VLB variable:
2983 SCIP_Real boundswitch, /**< fraction of domain up to which lower bound is used in transformation */
2985 SCIP_Bool allowlocal, /**< should local information allowed to be used, resulting in a local cut? */
2986 SCIP_Bool fixintegralrhs, /**< should complementation tried to be adjusted such that rhs gets fractional? */
2988 int* boundsfortrans, /**< bounds that should be used for transformed variables: vlb_idx/vub_idx,
2991 SCIP_BOUNDTYPE* boundtypesfortrans, /**< type of bounds that should be used for transformed variables;
3002 SCIP_Bool* freevariable, /**< stores whether a free variable was found in MIR row -> invalid summation */
3003 SCIP_Bool* localbdsused /**< pointer to store whether local bounds were used in transformation */
3033 /* start with continuous variables, because using variable bounds can affect the untransformed integral
3034 * variables, and these changes have to be incorporated in the transformation of the integral variables
3046 SCIP_CALL( determineBestBounds(scip, vars[cutinds[i]], sol, boundswitch, usevbds ? 2 : 0, allowlocal, fixintegralrhs,
3048 bestlbs + i, bestubs + i, bestlbtypes + i, bestubtypes + i, selectedbounds + i, freevariable) );
3070 performBoundSubstitution(scip, cutinds, cutcoefs, QUAD(cutrhs), nnz, varsign[i], boundtype[i], bestlbs[i], v, localbdsused);
3080 performBoundSubstitution(scip, cutinds, cutcoefs, QUAD(cutrhs), nnz, varsign[i], boundtype[i], bestubs[i], v, localbdsused);
3084 /* remove integral variables that now have a zero coefficient due to variable bound usage of continuous variables
3106 /* determine the best bounds for the integral variable, usevbd can be set to 0 here as vbds are only used for continuous variables */
3109 bestlbs + i, bestubs + i, bestlbtypes + i, bestubtypes + i, selectedbounds + i, freevariable) );
3118 /* now perform the bound substitution on the remaining integral variables which only uses standard bounds */
3133 performBoundSubstitutionSimple(scip, cutcoefs, QUAD(cutrhs), boundtype[i], bestlbs[i], v, localbdsused);
3144 performBoundSubstitutionSimple(scip, cutcoefs, QUAD(cutrhs), boundtype[i], bestubs[i], v, localbdsused);
3226 /* prefer larger violations; for equal violations, prefer smaller f0 values since then the possibility that
3229 if( SCIPisGT(scip, violgain, bestviolgain) || (SCIPisGE(scip, violgain, bestviolgain) && newf0 < bestnewf0) )
3257 assert(bestubtypes[besti] < 0); /* cannot switch to a variable bound (would lead to further coef updates) */
3264 assert(bestlbtypes[besti] < 0); /* cannot switch to a variable bound (would lead to further coef updates) */
3285 /** Calculate fractionalities \f$ f_0 := b - down(b), f_j := a^\prime_j - down(a^\prime_j) \f$, and derive MIR cut \f$ \tilde{a} \cdot x' \leq down(b) \f$
3300 * x^\prime_j := x_j - lb_j,& x_j = x^\prime_j + lb_j,& a^\prime_j = a_j,& \hat{a}_j := \tilde{a}_j,& \mbox{if lb was used in transformation} \\
3301 * x^\prime_j := ub_j - x_j,& x_j = ub_j - x^\prime_j,& a^\prime_j = -a_j,& \hat{a}_j := -\tilde{a}_j,& \mbox{if ub was used in transformation}
3316 * x^\prime_j := x_j - (bl_j \cdot zl_j + dl_j),& x_j = x^\prime_j + (bl_j\, zl_j + dl_j),& a^\prime_j = a_j,& \hat{a}_j := \tilde{a}_j,& \mbox{(vlb)} \\
3317 * x^\prime_j := (bu_j\, zu_j + du_j) - x_j,& x_j = (bu_j\, zu_j + du_j) - x^\prime_j,& a^\prime_j = -a_j,& \hat{a}_j := -\tilde{a}_j,& \mbox{(vub)}
3330 * \hat{a}_{zl_j} := \hat{a}_{zl_j} - \tilde{a}_j\, bl_j = \hat{a}_{zl_j} - \hat{a}_j\, bl_j,& \mbox{or} \\
3340 int*RESTRICT cutinds, /**< array of variables problem indices for non-zero coefficients in cut */
3343 int*RESTRICT boundtype, /**< stores the bound used for transformed variable (vlb/vub_idx or -1 for lb/ub) */
3365 /* Loop backwards to process integral variables first and be able to delete coefficients of integral variables
3373 /*in debug mode check that all continuous variables of the aggrrow come before the integral variables */
3441 /* move the constant term -a~_j * lb_j == -a^_j * lb_j , or a~_j * ub_j == -a^_j * ub_j to the rhs */
3476 /* now process the continuous variables; postpone deletetion of zeros till all continuous variables have been processed */
3500 SCIPquadprecProdQQ(cutaj, onedivoneminusf0, aj); /* cutaj = varsign[i] * aj * onedivoneminusf0; // a^_j */
3524 /* move the constant term -a~_j * lb_j == -a^_j * lb_j , or a~_j * ub_j == -a^_j * ub_j to the rhs */
3631 * The coefficient of the slack variable s_r is equal to the row's weight times the slack's sign, because the slack
3634 * Depending on the slacks type (integral or continuous), its coefficient in the cut calculates as follows:
3638 * & \hat{a}_r = \tilde{a}_r = down(a^\prime_r) + (f_r - f0)/(1 - f0),& \mbox{if}\qquad f_r > f0 \\
3644 * Substitute \f$ \hat{a}_r \cdot s_r \f$ by adding \f$ \hat{a}_r \f$ times the slack's definition to the cut.
3708 || (slacksign[i] == -1 && SCIPisFeasIntegral(scip, row->lhs - row->constant))) ) /*lint !e613*/
3790 /** calculates an MIR cut out of the weighted sum of LP rows; The weights of modifiable rows are set to 0.0, because
3793 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
3805 SCIP_Real boundswitch, /**< fraction of domain up to which lower bound is used in transformation */
3807 SCIP_Bool allowlocal, /**< should local information allowed to be used, resulting in a local cut? */
3808 SCIP_Bool fixintegralrhs, /**< should complementation tried to be adjusted such that rhs gets fractional? */
3809 int* boundsfortrans, /**< bounds that should be used for transformed variables: vlb_idx/vub_idx,
3812 SCIP_BOUNDTYPE* boundtypesfortrans, /**< type of bounds that should be used for transformed variables;
3818 SCIP_Real* cutcoefs, /**< array to store the non-zero coefficients in the cut if its efficacy improves cutefficacy */
3819 SCIP_Real* cutrhs, /**< pointer to store the right hand side of the cut if its efficacy improves cutefficacy */
3820 int* cutinds, /**< array to store the indices of non-zero coefficients in the cut if its efficacy improves cutefficacy */
3821 int* cutnnz, /**< pointer to store the number of non-zeros in the cut if its efficacy improves cutefficacy */
3823 int* cutrank, /**< pointer to return rank of generated cut or NULL if it improves cutefficacy */
3824 SCIP_Bool* cutislocal, /**< pointer to store whether the generated cut is only valid locally if it improves cutefficacy */
3825 SCIP_Bool* success /**< pointer to store whether the returned coefficients are a valid MIR cut and it improves cutefficacy */
3891 * x'_j := x_j - (bl_j * zl_j + dl_j), x_j == x'_j + (bl_j * zl_j + dl_j), a'_j == a_j, if vlb is used in transf.
3892 * x'_j := (bu_j * zu_j + du_j) - x_j, x_j == (bu_j * zu_j + du_j) - x'_j, a'_j == -a_j, if vub is used in transf.
3893 * move the constant terms "a_j * dl_j" or "a_j * du_j" to the rhs, and update the coefficient of the VLB variable:
3897 SCIP_CALL( cutsTransformMIR(scip, sol, boundswitch, usevbds, allowlocal, fixintegralrhs, FALSE,
3898 boundsfortrans, boundtypesfortrans, minfrac, maxfrac, tmpcoefs, QUAD(&rhs), tmpinds, &tmpnnz, varsign, boundtype, &freevariable, &localbdsused) );
3917 * x'_j := x_j - lb_j, x_j == x'_j + lb_j, a'_j == a_j, a^_j := a~_j, if lb was used in transformation
3918 * x'_j := ub_j - x_j, x_j == ub_j - x'_j, a'_j == -a_j, a^_j := -a~_j, if ub was used in transformation
3925 * x'_j := x_j - (bl_j * zl_j + dl_j), x_j == x'_j + (bl_j * zl_j + dl_j), a'_j == a_j, a^_j := a~_j, (vlb)
3926 * x'_j := (bu_j * zu_j + du_j) - x_j, x_j == (bu_j * zu_j + du_j) - x'_j, a'_j == -a_j, a^_j := -a~_j, (vub)
3954 SCIP_CALL( cutsRoundMIR(scip, tmpcoefs, QUAD(&rhs), tmpinds, &tmpnnz, varsign, boundtype, QUAD(f0)) );
3960 * The coefficient of the slack variable s_r is equal to the row's weight times the slack's sign, because the slack
3964 * Depending on the slacks type (integral or continuous), its coefficient in the cut calculates as follows:
3978 /* remove all nearly-zero coefficients from MIR row and relax the right hand side correspondingly in order to
3981 SCIP_CALL( postprocessCutQuad(scip, tmpislocal, tmpinds, tmpcoefs, &tmpnnz, QUAD(&rhs), success) );
3985 *success = ! removeZerosQuad(scip, SCIPsumepsilon(scip), tmpislocal, tmpcoefs, QUAD(&rhs), tmpinds, &tmpnnz);
3992 SCIP_Real mirefficacy = calcEfficacyDenseStorageQuad(scip, sol, tmpcoefs, QUAD_TO_DBL(rhs), tmpinds, tmpnnz);
3994 if( SCIPisEfficacious(scip, mirefficacy) && (cutefficacy == NULL || mirefficacy > *cutefficacy) )
4119 * Given the aggregation, it is transformed to a mixed knapsack set via complementation (using bounds or variable bounds)
4122 * so one would prefer to have integer coefficients for integer variables which are far away from their bounds in the
4125 * @return \ref SCIP_OKAY is returned if everything worked. Otherwise a suitable error code is passed. See \ref
4137 SCIP_Real boundswitch, /**< fraction of domain up to which lower bound is used in transformation */
4139 SCIP_Bool allowlocal, /**< should local information allowed to be used, resulting in a local cut? */
4141 int* boundsfortrans, /**< bounds that should be used for transformed variables: vlb_idx/vub_idx,
4144 SCIP_BOUNDTYPE* boundtypesfortrans, /**< type of bounds that should be used for transformed variables;
4151 int* cutinds, /**< array to store the problem indices of variables with a non-zero coefficient in the cut */
4153 SCIP_Real* cutefficacy, /**< pointer to store efficacy of best cut; only cuts that are strictly better than the value of
4156 SCIP_Bool* cutislocal, /**< pointer to store whether the generated cut is only valid locally */
4205 /* we only compute bound distance for integer variables; we allocate an array of length aggrrow->nnz to store this, since
4206 * this is the largest number of integer variables. (in contrast to the number of total variables which can be 2 *
4207 * aggrrow->nnz variables: if all are continuous and we use variable bounds to completement, we introduce aggrrow->nnz
4239 * x'_j := x_j - (bl_j * zl_j + dl_j), x_j == x'_j + (bl_j * zl_j + dl_j), a'_j == a_j, if vlb is used in transf.
4240 * x'_j := (bu_j * zu_j + du_j) - x_j, x_j == (bu_j * zu_j + du_j) - x'_j, a'_j == -a_j, if vub is used in transf.
4241 * move the constant terms "a_j * dl_j" or "a_j * du_j" to the rhs, and update the coefficient of the VLB variable:
4246 boundsfortrans, boundtypesfortrans, minfrac, maxfrac, mksetcoefs, QUAD(&mksetrhs), mksetinds, &mksetnnz, varsign, boundtype, &freevariable, &localbdsused) );
4254 SCIPdebug( printCutQuad(scip, sol, mksetcoefs, QUAD(mksetrhs), mksetinds, mksetnnz, FALSE, FALSE) );
4292 SCIP_CALL( SCIPcalcIntegralScalar(deltacands, nbounddist, -QUAD_EPSILON, SCIPsumepsilon(scip), (SCIP_Longint)10000, 10000.0, &intscale, &intscalesuccess) );
4362 * x'_j := x_j - lb_j, x_j == x'_j + lb_j, a'_j == a_j, a^_j := a~_j, if lb was used in transformation
4363 * x'_j := ub_j - x_j, x_j == ub_j - x'_j, a'_j == -a_j, a^_j := -a~_j, if ub was used in transformation
4370 * x'_j := x_j - (bl_j * zl_j + dl_j), x_j == x'_j + (bl_j * zl_j + dl_j), a'_j == a_j, a^_j := a~_j, (vlb)
4371 * x'_j := (bu_j * zu_j + du_j) - x_j, x_j == (bu_j * zu_j + du_j) - x'_j, a'_j == -a_j, a^_j := -a~_j, (vub)
4563 efficacy = computeMIREfficacy(scip, tmpcoefs, tmpvalues, QUAD_TO_DBL(mksetrhs), contactivity, contsqrnorm, deltacands[i], ntmpcoefs, minfrac, maxfrac);
4586 efficacy = computeMIREfficacy(scip, tmpcoefs, tmpvalues, QUAD_TO_DBL(mksetrhs), contactivity, contsqrnorm, delta, ntmpcoefs, minfrac, maxfrac);
4596 /* try to improve efficacy by switching complementation of integral variables that are not at their bounds
4613 SCIP_CALL( findBestLb(scip, vars[mksetinds[k]], sol, 0, allowlocal, &bestlb, &simplebnd, &bestlbtype) );
4618 SCIP_CALL( findBestUb(scip, vars[mksetinds[k]], sol, 0, allowlocal, &bestub, &simplebnd, &bestubtype) );
4637 tmpvalues[k - intstart] = varsign[k] == +1 ? bestub - SCIPgetSolVal(scip, sol, vars[mksetinds[k]]) : SCIPgetSolVal(scip, sol, vars[mksetinds[k]]) - bestlb;
4640 newefficacy = computeMIREfficacy(scip, tmpcoefs, tmpvalues, QUAD_TO_DBL(newrhs), contactivity, contsqrnorm, bestdelta, ntmpcoefs, minfrac, maxfrac);
4652 assert(bestubtype < 0); /* cannot switch to a variable bound (would lead to further coef updates) */
4659 assert(bestlbtype < 0); /* cannot switch to a variable bound (would lead to further coef updates) */
4699 SCIPdebug(printCutQuad(scip, sol, mksetcoefs, QUAD(mksetrhs), mksetinds, mksetnnz, FALSE, FALSE));
4703 SCIP_CALL( cutsRoundMIR(scip, mksetcoefs, QUAD(&mksetrhs), mksetinds, &mksetnnz, varsign, boundtype, QUAD(f0)) );
4706 SCIPdebug(printCutQuad(scip, sol, mksetcoefs, QUAD(mksetrhs), mksetinds, mksetnnz, FALSE, FALSE));
4710 * The coefficient of the slack variable s_r is equal to the row's weight times the slack's sign, because the slack
4714 * Depending on the slacks type (integral or continuous), its coefficient in the cut calculates as follows:
4726 SCIPdebug(printCutQuad(scip, sol, mksetcoefs, QUAD(mksetrhs), mksetinds, mksetnnz, FALSE, FALSE));
4740 SCIPdebugMessage("efficacy of cmir cut is different than expected efficacy: %f != %f\n", efficacy, bestefficacy);
4747 /* remove all nearly-zero coefficients from MIR row and relax the right hand side correspondingly in order to
4752 SCIP_CALL( postprocessCutQuad(scip, *cutislocal, mksetinds, mksetcoefs, &mksetnnz, QUAD(&mksetrhs), success) );
4756 *success = ! removeZerosQuad(scip, SCIPsumepsilon(scip), *cutislocal, mksetcoefs, QUAD(&mksetrhs), mksetinds, &mksetnnz);
4760 SCIPdebug(printCutQuad(scip, sol, mksetcoefs, QUAD(mksetrhs), mksetinds, mksetnnz, FALSE, FALSE));
4764 mirefficacy = calcEfficacyDenseStorageQuad(scip, sol, mksetcoefs, QUAD_TO_DBL(mksetrhs), mksetinds, mksetnnz);
4819 /* =========================================== flow cover =========================================== */
4831 #define MAXABSVBCOEF 1e+5 /**< maximal absolute coefficient in variable bounds used for snf relaxation */
4848 SCIP_Real d1; /**< right hand side of single-node-flow set plus the sum of all \f$ u_j \f$ for \f$ j \in C^- \f$ */
4849 SCIP_Real d2; /**< right hand side of single-node-flow set plus the sum of all \f$ u_j \f$ for \f$ j \in N^- \f$ */
4851 SCIP_Real mp; /**< smallest variable bound coefficient of variable in \f$ C^{++} (min_{j \in C++} u_j) \f$ */
4855 /** structure that contains all the data that defines the single-node-flow relaxation of an aggregation row */
4867 SCIP_Real* aggrcoefsbin; /**< aggregation coefficient of the original binary var used to define the
4869 SCIP_Real* aggrcoefscont; /**< aggregation coefficient of the original continuous var used to define the
4871 SCIP_Real* aggrconstants; /**< aggregation constant used to define the continuous variable in the relaxed set */
4874 /** get solution value and index of variable lower bound (with binary variable) which is closest to the current LP
4875 * solution value of a given variable; candidates have to meet certain criteria in order to ensure the nonnegativity
4876 * of the variable upper bound imposed on the real variable in the 0-1 single node flow relaxation associated with the
4890 SCIP_Real* closestvlb, /**< pointer to store the LP sol value of the closest variable lower bound */
4891 int* closestvlbidx /**< pointer to store the index of the closest vlb; -1 if no vlb was found */
4899 assert(bestsub == SCIPvarGetUbGlobal(var) || bestsub == SCIPvarGetUbLocal(var)); /*lint !e777*/
4944 /* if the variable is not active the problem index is -1, so we cast to unsigned int before the comparison which
4952 /* check if current variable lower bound l~_i * x_i + d_i imposed on y_j meets the following criteria:
4956 * 0. no other non-binary variable y_k has used a variable bound with x_i to get transformed variable y'_k yet
5004 /** get LP solution value and index of variable upper bound (with binary variable) which is closest to the current LP
5005 * solution value of a given variable; candidates have to meet certain criteria in order to ensure the nonnegativity
5006 * of the variable upper bound imposed on the real variable in the 0-1 single node flow relaxation associated with the
5020 SCIP_Real* closestvub, /**< pointer to store the LP sol value of the closest variable upper bound */
5021 int* closestvubidx /**< pointer to store the index of the closest vub; -1 if no vub was found */
5029 assert(bestslb == SCIPvarGetLbGlobal(var) || bestslb == SCIPvarGetLbLocal(var)); /*lint !e777*/
5074 /* if the variable is not active the problem index is -1, so we cast to unsigned int before the comparison which
5086 * 0. no other non-binary variable y_k has used a variable bound with x_i to get transformed variable y'_k
5134 /** determines the bounds to use for constructing the single-node-flow relaxation of a variable in
5144 int varposinrow, /**< position of variable in the rowinds array for which the bounds should be determined */
5148 SCIP_Bool allowlocal, /**< should local information allowed to be used, resulting in a local cut? */
5149 SCIP_Real boundswitch, /**< fraction of domain up to which lower bound is used in transformation */
5158 SCIP_BOUNDTYPE* selectedbounds, /**< pointer to store the preferred bound for the transformation */
5186 SCIP_CALL( findBestLb(scip, var, sol, 0, allowlocal, &bestslb[varposinrow], &simplebound, &bestslbtype[varposinrow]) );
5187 SCIP_CALL( findBestUb(scip, var, sol, 0, allowlocal, &bestsub[varposinrow], &simplebound, &bestsubtype[varposinrow]) );
5198 SCIPdebugMsg(scip, " %d: %g <%s, idx=%d, lp=%g, [%g(%d),%g(%d)]>:\n", varposinrow, rowcoef, SCIPvarGetName(var), probidx,
5199 solval, bestslb[varposinrow], bestslbtype[varposinrow], bestsub[varposinrow], bestsubtype[varposinrow]);
5201 /* mixed integer set cannot be relaxed to 0-1 single node flow set because both simple bounds are -infinity
5204 if( SCIPisInfinity(scip, -bestslb[varposinrow]) && SCIPisInfinity(scip, bestsub[varposinrow]) )
5210 /* get closest lower bound that can be used to define the real variable y'_j in the 0-1 single node flow
5223 SCIP_CALL( getClosestVlb(scip, var, sol, rowcoefs, binvarused, bestsub[varposinrow], rowcoef, &bestvlb, &bestvlbidx) );
5232 /* get closest upper bound that can be used to define the real variable y'_j in the 0-1 single node flow
5245 SCIP_CALL( getClosestVub(scip, var, sol, rowcoefs, binvarused, bestslb[varposinrow], rowcoef, &bestvub, &bestvubidx) );
5253 SCIPdebugMsg(scip, " bestlb=%g(%d), bestub=%g(%d)\n", bestlb[varposinrow], bestlbtype[varposinrow], bestub[varposinrow], bestubtype[varposinrow]);
5255 /* mixed integer set cannot be relaxed to 0-1 single node flow set because there are no suitable bounds
5266 /* select best upper bound if it is closer to the LP value of y_j and best lower bound otherwise and use this bound
5267 * to define the real variable y'_j with 0 <= y'_j <= u'_j x_j in the 0-1 single node flow relaxation;
5270 if( SCIPisEQ(scip, solval, (1.0 - boundswitch) * bestlb[varposinrow] + boundswitch * bestub[varposinrow]) && bestlbtype[varposinrow] >= 0 )
5274 else if( SCIPisEQ(scip, solval, (1.0 - boundswitch) * bestlb[varposinrow] + boundswitch * bestub[varposinrow])
5279 else if( SCIPisLE(scip, solval, (1.0 - boundswitch) * bestlb[varposinrow] + boundswitch * bestub[varposinrow]) )
5285 assert(SCIPisGT(scip, solval, (1.0 - boundswitch) * bestlb[varposinrow] + boundswitch * bestub[varposinrow]));
5315 /** construct a 0-1 single node flow relaxation (with some additional simple constraints) of a mixed integer set
5322 SCIP_Real boundswitch, /**< fraction of domain up to which lower bound is used in transformation */
5323 SCIP_Bool allowlocal, /**< should local information allowed to be used, resulting in a local cut? */
5330 SCIP_Bool* localbdsused /**< pointer to store whether local bounds were used in transformation */
5353 SCIPdebugMsg(scip, "--------------------- construction of SNF relaxation ------------------------------------\n");
5371 /* array to store whether a binary variable is in the row (-1) or has been used (1) due to variable bound usage */
5385 SCIP_CALL( determineBoundForSNF(scip, sol, vars, rowcoefs, rowinds, i, binvarused, allowlocal, boundswitch,
5386 bestlb, bestub, bestslb, bestsub, bestlbtype, bestubtype, bestslbtype, bestsubtype, selectedbounds, &freevariable) );
5454 /* store for y_j that bestlb is the bound used to define y'_j and that y'_j is the associated real variable
5484 /* store aggregation information for y'_j for transforming cuts for the SNF relaxation back to the problem variables later */
5513 SCIPdebugMsg(scip, " --> bestlb used for trans: ... %s y'_%d + ..., y'_%d <= %g x_%d (=1), rhs=%g-(%g*%g)=%g\n",
5514 snf->transvarcoefs[snf->ntransvars] == 1 ? "+" : "-", snf->ntransvars, snf->ntransvars, snf->transvarvubcoefs[snf->ntransvars],
5515 snf->ntransvars, QUAD_TO_DBL(transrhs) + QUAD_TO_DBL(rowcoeftimesbestsub), QUAD_TO_DBL(rowcoef), bestsub[i], QUAD_TO_DBL(transrhs));
5531 * y'_j = - ( a_j ( y_j - d_j ) + c_j x_j ) with 0 <= y'_j <= - ( a_j l~_j + c_j ) x_j if a_j > 0
5563 /* store aggregation information for y'_j for transforming cuts for the SNF relaxation back to the problem variables later */
5593 SCIPdebugMsg(scip, " --> bestlb used for trans: ... %s y'_%d + ..., y'_%d <= %g x_%d (=%s), rhs=%g-(%g*%g)=%g\n",
5594 snf->transvarcoefs[snf->ntransvars] == 1 ? "+" : "-", snf->ntransvars, snf->ntransvars, snf->transvarvubcoefs[snf->ntransvars],
5595 snf->ntransvars, SCIPvarGetName(vlbvars[bestlbtype[i]]), QUAD_TO_DBL(transrhs) + QUAD_TO_DBL(rowcoeftimesvlbconst), QUAD_TO_DBL(rowcoef),
5638 /* store aggregation information for y'_j for transforming cuts for the SNF relaxation back to the problem variables later */
5667 SCIPdebugMsg(scip, " --> bestub used for trans: ... %s y'_%d + ..., Y'_%d <= %g x_%d (=1), rhs=%g-(%g*%g)=%g\n",
5668 snf->transvarcoefs[snf->ntransvars] == 1 ? "+" : "-", snf->ntransvars, snf->ntransvars, snf->transvarvubcoefs[snf->ntransvars],
5669 snf->ntransvars, QUAD_TO_DBL(transrhs) + QUAD_TO_DBL(rowcoeftimesbestslb), QUAD_TO_DBL(rowcoef), bestslb[i], QUAD_TO_DBL(transrhs));
5686 * y'_j = - ( a_j ( y_j - d_j ) + c_j x_j ) with 0 <= y'_j <= - ( a_j u~_j + c_j ) x_j if a_j < 0,
5715 /* store aggregation information for y'_j for transforming cuts for the SNF relaxation back to the problem variables later */
5745 /* store for x_j that y'_j is the associated real variable in the 0-1 single node flow relaxation */
5747 SCIPdebugMsg(scip, " --> bestub used for trans: ... %s y'_%d + ..., y'_%d <= %g x_%d (=%s), rhs=%g-(%g*%g)=%g\n",
5748 snf->transvarcoefs[snf->ntransvars] == 1 ? "+" : "-", snf->ntransvars, snf->ntransvars, snf->transvarvubcoefs[snf->ntransvars],
5749 snf->ntransvars, SCIPvarGetName(vubvars[bestubtype[i]]), QUAD_TO_DBL(transrhs) + QUAD_TO_DBL(rowcoeftimesvubconst), QUAD_TO_DBL(rowcoef),
5793 SCIPdebugMsg(scip, " %d: %g <%s, idx=%d, lp=%g, [%g, %g]>:\n", i, QUAD_TO_DBL(rowcoef), SCIPvarGetName(var), probidx, varsolval,