@@ -1343,8 +1343,7 @@ bool HighsCutGeneration::generateCut(HighsTransformedLp& transLp,
13431343 }
13441344#endif
13451345
1346- // Try to generate a lifted simple generalized flow cover cut
1347- bool flowCoverSuccess = false ;
1346+ // Copy data to later generate lifted simple generalized flow cover cut
13481347 std::vector<double > flowCoverVals;
13491348 std::vector<HighsInt> flowCoverInds;
13501349 double flowCoverRhs = rhs_;
@@ -1354,30 +1353,26 @@ bool HighsCutGeneration::generateCut(HighsTransformedLp& transLp,
13541353 lpRelaxation.getMipSolver ().options_mip_ ->mip_cut_flow_cover ) {
13551354 flowCoverVals = vals_;
13561355 flowCoverInds = inds_;
1357- flowCoverSuccess = tryGenerateFlowCoverCut (
1358- transLp, flowCoverInds, flowCoverVals, flowCoverRhs, flowCoverEfficacy);
1356+ genFlowCover = true ;
1357+ } else {
1358+ genFlowCover = false ;
13591359 }
13601360
1361- bool cmirSuccess = false ;
13621361 bool intsPositive = true ;
1363- bool hasUnboundedInts = false ;
1364- bool hasGeneralInts = false ;
1365- bool hasContinuous = false ;
1366- if (!transLp.transform (vals_, upper, solval, inds_, rhs_, intsPositive)) {
1367- cmirSuccess = false ;
1368- goto postprocess;
1369- }
1362+ if (!transLp.transform (vals_, upper, solval, inds_, rhs_, intsPositive))
1363+ return false ;
13701364
13711365 rowlen = inds_.size ();
13721366 this ->inds = inds_.data ();
13731367 this ->vals = vals_.data ();
13741368 this ->rhs = rhs_;
13751369 complementation.clear ();
1370+ bool hasUnboundedInts = false ;
1371+ bool hasGeneralInts = false ;
1372+ bool hasContinuous = false ;
13761373 if (!preprocessBaseInequality (hasUnboundedInts, hasGeneralInts,
1377- hasContinuous)) {
1378- cmirSuccess = false ;
1379- goto postprocess;
1380- }
1374+ hasContinuous))
1375+ return false ;
13811376
13821377 // it can happen that there is an unbounded integer variable during the
13831378 // transform call so that the integers are not transformed to positive values.
@@ -1397,13 +1392,9 @@ bool HighsCutGeneration::generateCut(HighsTransformedLp& transLp,
13971392 }
13981393
13991394 // try to generate a cut
1400- if (!tryGenerateCut (
1401- inds_, vals_, hasUnboundedInts, hasGeneralInts, hasContinuous,
1402- std::max (0.9 * flowCoverEfficacy, 10 * feastol),
1403- onlyInitialCMIRScale)) {
1404- cmirSuccess = false ;
1405- goto postprocess;
1406- }
1395+ if (!tryGenerateCut (inds_, vals_, hasUnboundedInts, hasGeneralInts,
1396+ hasContinuous, 10 * feastol, onlyInitialCMIRScale))
1397+ return false ;
14071398
14081399 // remove the complementation if exists
14091400 removeComplementation ();
@@ -1416,24 +1407,53 @@ bool HighsCutGeneration::generateCut(HighsTransformedLp& transLp,
14161407 vals[i] = vals[rowlen];
14171408 }
14181409 }
1419- cmirSuccess = true ;
1420-
1421- postprocess:
1422- if (!cmirSuccess && !flowCoverSuccess) return false ;
14231410
14241411 // transform the cut back into the original space, i.e. remove the bound
14251412 // substitution and replace implicit slack variables
1426- if (cmirSuccess) {
1427- rhs_ = (double )rhs;
1428- vals_.resize (rowlen);
1429- inds_.resize (rowlen);
1430- if (!transLp.untransform (vals_, inds_, rhs_)) return false ;
1431- } else {
1432- rhs_ = flowCoverRhs;
1433- std::swap (vals_, flowCoverVals);
1434- std::swap (inds_, flowCoverInds);
1435- integralSupport = false ;
1436- integralCoefficients = false ;
1413+ rhs_ = (double )rhs;
1414+ vals_.resize (rowlen);
1415+ inds_.resize (rowlen);
1416+ if (!transLp.untransform (vals_, inds_, rhs_)) return false ;
1417+
1418+ const auto & sol = lpRelaxation.getSolution ().col_value ;
1419+
1420+ // Try to generate a lifted simple generalized flow cover cut
1421+ if (genFlowCover) {
1422+ bool flowCoverSuccess = tryGenerateFlowCoverCut (
1423+ transLp, flowCoverInds, flowCoverVals, flowCoverRhs, flowCoverEfficacy);
1424+ if (flowCoverSuccess) {
1425+ HighsInt rowlen_ = inds_.size ();
1426+ double viol = -rhs_;
1427+ double sqrnorm = 0 ;
1428+ double efficacy = 0 ;
1429+ for (HighsInt i = 0 ; i != rowlen_; ++i) {
1430+ HighsInt col = inds_[i];
1431+ viol += vals_[i] * sol[col];
1432+ if (vals_[i] >= 0 &&
1433+ sol[col] <=
1434+ lpRelaxation.getMipSolver ().mipdata_ ->domain .col_lower_ [col] +
1435+ lpRelaxation.getMipSolver ().mipdata_ ->feastol )
1436+ continue ;
1437+ if (vals_[i] < 0 &&
1438+ sol[col] >=
1439+ lpRelaxation.getMipSolver ().mipdata_ ->domain .col_upper_ [col] -
1440+ lpRelaxation.getMipSolver ().mipdata_ ->feastol )
1441+ continue ;
1442+ sqrnorm += vals_[i] * vals_[i];
1443+ }
1444+ if (sqrnorm == 0 ) {
1445+ efficacy = 0 ;
1446+ } else {
1447+ efficacy = viol / sqrt (sqrnorm);
1448+ }
1449+ if (flowCoverSuccess && flowCoverEfficacy > 1.2 * efficacy) {
1450+ rhs_ = flowCoverRhs;
1451+ std::swap (vals_, flowCoverVals);
1452+ std::swap (inds_, flowCoverInds);
1453+ integralSupport = false ;
1454+ integralCoefficients = false ;
1455+ }
1456+ }
14371457 }
14381458
14391459 rowlen = inds_.size ();
@@ -1455,7 +1475,6 @@ bool HighsCutGeneration::generateCut(HighsTransformedLp& transLp,
14551475
14561476 // finally determine the violation of the cut in the original space
14571477 HighsCDouble violation = -rhs_;
1458- const auto & sol = lpRelaxation.getSolution ().col_value ;
14591478 for (HighsInt i = 0 ; i != rowlen; ++i) violation += sol[inds[i]] * vals_[i];
14601479
14611480 if (violation <= 10 * feastol) return false ;
@@ -1973,11 +1992,7 @@ bool HighsCutGeneration::tryGenerateCut(std::vector<HighsInt>& inds_,
19731992 rhs = tmpRhs;
19741993 } else {
19751994 // accept cut and increase minimum efficiency requirement for cmir cut
1976- if (minEfficacy > 10 * feastol) {
1977- minMirEfficacy = std::max (minEfficacy, efficacy + 10 * feastol);
1978- } else {
1979- minMirEfficacy += efficacy;
1980- }
1995+ minMirEfficacy += efficacy;
19811996 std::swap (tmpRhs, rhs);
19821997 }
19831998 }
0 commit comments