@@ -589,14 +589,15 @@ bool HighsCutGeneration::cmirCutGenerationHeuristic(double minEfficacy,
589589 double oneoveroneminusf0 = 1.0 / (1.0 - f0);
590590 if (oneoveroneminusf0 > maxCMirScale) continue ;
591591
592- double sqrnorm = scale * scale * continuoussqrnorm;
593- double viol = scale * continuouscontribution * oneoveroneminusf0 - downrhs;
592+ double contscale = scale * oneoveroneminusf0;
593+ double sqrnorm = contscale * contscale * continuoussqrnorm;
594+ double viol = contscale * continuouscontribution - downrhs;
594595
595596 for (HighsInt j : integerinds) {
596597 double scalaj = vals[j] * scale;
597598 double downaj = fast_floor (scalaj + kHighsTiny );
598599 double fj = scalaj - downaj;
599- double aj = downaj + std::max (0.0 , fj - f0);
600+ double aj = downaj + std::max (0.0 , ( fj - f0) * oneoveroneminusf0 );
600601 updateViolationAndNorm (j, aj, viol, sqrnorm);
601602 }
602603
@@ -621,14 +622,15 @@ bool HighsCutGeneration::cmirCutGenerationHeuristic(double minEfficacy,
621622 double oneoveroneminusf0 = 1.0 / (1.0 - f0);
622623 if (oneoveroneminusf0 > maxCMirScale) continue ;
623624
624- double sqrnorm = scale * scale * continuoussqrnorm;
625- double viol = scale * continuouscontribution * oneoveroneminusf0 - downrhs;
625+ double contscale = scale * oneoveroneminusf0;
626+ double sqrnorm = contscale * contscale * continuoussqrnorm;
627+ double viol = contscale * continuouscontribution - downrhs;
626628
627629 for (HighsInt j : integerinds) {
628630 double scalaj = vals[j] * scale;
629631 double downaj = fast_floor (scalaj + kHighsTiny );
630632 double fj = scalaj - downaj;
631- double aj = downaj + std::max (0.0 , fj - f0);
633+ double aj = downaj + std::max (0.0 , ( fj - f0) * oneoveroneminusf0 );
632634 updateViolationAndNorm (j, aj, viol, sqrnorm);
633635 }
634636
@@ -665,14 +667,15 @@ bool HighsCutGeneration::cmirCutGenerationHeuristic(double minEfficacy,
665667 continue ;
666668 }
667669
668- double sqrnorm = scale * scale * continuoussqrnorm;
669- double viol = scale * continuouscontribution * oneoveroneminusf0 - downrhs;
670+ double contscale = scale * oneoveroneminusf0;
671+ double sqrnorm = contscale * contscale * continuoussqrnorm;
672+ double viol = contscale * continuouscontribution - downrhs;
670673
671674 for (HighsInt j : integerinds) {
672675 double scalaj = vals[j] * scale;
673676 double downaj = fast_floor (scalaj + kHighsTiny );
674677 double fj = scalaj - downaj;
675- double aj = downaj + std::max (0.0 , fj - f0);
678+ double aj = downaj + std::max (0.0 , ( fj - f0) * oneoveroneminusf0 );
676679 updateViolationAndNorm (j, aj, viol, sqrnorm);
677680 }
678681
@@ -708,12 +711,28 @@ bool HighsCutGeneration::cmirCutGenerationHeuristic(double minEfficacy,
708711 double downaj = floor (double (scalaj + kHighsTiny ));
709712 HighsCDouble fj = scalaj - downaj;
710713 HighsCDouble aj = downaj;
711- if (fj > f0) aj += fj - f0;
714+ if (fj > f0) aj += ( fj - f0) * oneoveroneminusf0 ;
712715
713716 vals[j] = double (aj * bestdelta);
714717 }
715718 }
716719
720+ #ifndef NDEBUG
721+ // Check if the computed cut has the correct efficacy
722+ {
723+ double checkviol = -downrhs * bestdelta;
724+ double checknorm = 0.0 ;
725+ for (HighsInt j = 0 ; j != rowlen; ++j) {
726+ if (vals[j] == 0.0 ) continue ;
727+ updateViolationAndNorm (j, vals[j], checkviol, checknorm);
728+ }
729+ double checkefficacy = checkviol / sqrt (checknorm);
730+ // the efficacy can become infinite if the cut 0 <= -1 is derived
731+ assert (fabs (checkefficacy - bestefficacy) < 0.001 ||
732+ fabs (checkefficacy) >= 1e30 );
733+ }
734+ #endif
735+
717736 return true ;
718737}
719738
0 commit comments