@@ -48,6 +48,12 @@ std::string HighsMipSolverData::solutionSourceToString(
4848 } else if (solution_source == kSolutionSourceRandomizedRounding ) {
4949 if (code) return " R" ;
5050 return " Randomized rounding" ;
51+ } else if (solution_source == kSolutionSourceZiRound ) {
52+ if (code) return " Z" ;
53+ return " ZI Round" ;
54+ } else if (solution_source == kSolutionSourceShifting ) {
55+ if (code) return " I" ;
56+ return " Shifting" ;
5157 } else if (solution_source == kSolutionSourceSolveLp ) {
5258 if (code) return " S" ;
5359 return " Solve LP" ;
@@ -110,6 +116,32 @@ bool HighsMipSolverData::checkSolution(
110116 return true ;
111117}
112118
119+ std::vector<std::tuple<HighsInt, HighsInt, double >>
120+ HighsMipSolverData::getInfeasibleRows (
121+ const std::vector<double >& solution) const {
122+ std::vector<std::tuple<HighsInt, HighsInt, double >> infeasibleRows;
123+ for (HighsInt i = 0 ; i != mipsolver.model_ ->num_row_ ; ++i) {
124+ HighsInt start = ARstart_[i];
125+ HighsInt end = ARstart_[i + 1 ];
126+
127+ HighsCDouble row_activity_quad = 0.0 ;
128+ for (HighsInt j = start; j != end; ++j)
129+ row_activity_quad +=
130+ static_cast <HighsCDouble>(solution[ARindex_[j]]) * ARvalue_[j];
131+
132+ double row_activity = static_cast <double >(row_activity_quad);
133+ if (row_activity > mipsolver.rowUpper (i) + feastol) {
134+ double difference = std::abs (row_activity - mipsolver.rowUpper (i));
135+ infeasibleRows.push_back ({i, +1 , difference});
136+ }
137+ if (row_activity < mipsolver.rowLower (i) - feastol) {
138+ double difference = std::abs (mipsolver.rowLower (i) - row_activity);
139+ infeasibleRows.push_back ({i, -1 , difference});
140+ }
141+ }
142+ return infeasibleRows;
143+ }
144+
113145bool HighsMipSolverData::trySolution (const std::vector<double >& solution,
114146 const int solution_source) {
115147 if (int (solution.size ()) != mipsolver.model_ ->num_col_ ) return false ;
@@ -1601,6 +1633,8 @@ bool HighsMipSolverData::rootSeparationRound(
16011633
16021634 if (mipsolver.submip || incumbent.empty ()) {
16031635 heuristics.randomizedRounding (solvals);
1636+ if (mipsolver.options_mip_ ->mip_heuristic_run_shifting )
1637+ heuristics.shifting (solvals);
16041638 heuristics.flushStatistics ();
16051639 status = evaluateRootLp ();
16061640 if (status == HighsLpRelaxation::Status::kInfeasible ) return true ;
@@ -1680,6 +1714,11 @@ HighsLpRelaxation::Status HighsMipSolverData::evaluateRootLp() {
16801714 num_leaves += 1 ;
16811715 return HighsLpRelaxation::Status::kInfeasible ;
16821716 }
1717+
1718+ if (status == HighsLpRelaxation::Status::kOptimal &&
1719+ mipsolver.options_mip_ ->mip_heuristic_run_zi_round )
1720+ heuristics.ziRound (lp.getLpSolver ().getSolution ().col_value );
1721+
16831722 } else
16841723 status = lp.getStatus ();
16851724
@@ -1876,9 +1915,14 @@ void HighsMipSolverData::evaluateRootNode() {
18761915 last_disptime = -kHighsInf ;
18771916 disptime = 0 ;
18781917
1918+ if (mipsolver.options_mip_ ->mip_heuristic_run_zi_round )
1919+ heuristics.ziRound (firstlpsol);
18791920 analysis.mipTimerStart (kMipClockRandomizedRounding );
18801921 heuristics.randomizedRounding (firstlpsol);
18811922 analysis.mipTimerStop (kMipClockRandomizedRounding );
1923+ if (mipsolver.options_mip_ ->mip_heuristic_run_shifting )
1924+ heuristics.shifting (firstlpsol);
1925+
18821926 heuristics.flushStatistics ();
18831927
18841928 analysis.mipTimerStart (kMipClockEvaluateRootLp );
@@ -2068,6 +2112,15 @@ void HighsMipSolverData::evaluateRootNode() {
20682112 rootlpsolobj = lp.getObjective ();
20692113 lp.setIterationLimit (std::max (10000 , int (10 * avgrootlpiters)));
20702114
2115+ if (mipsolver.options_mip_ ->mip_heuristic_run_zi_round ) {
2116+ heuristics.ziRound (firstlpsol);
2117+ heuristics.flushStatistics ();
2118+ }
2119+ if (mipsolver.options_mip_ ->mip_heuristic_run_shifting ) {
2120+ heuristics.shifting (rootlpsol);
2121+ heuristics.flushStatistics ();
2122+ }
2123+
20712124 if (!analyticCenterComputed && compute_analytic_centre) {
20722125 if (checkLimits ()) return clockOff (analysis);
20732126
@@ -2122,10 +2175,12 @@ void HighsMipSolverData::evaluateRootNode() {
21222175 if (rootlpsol.empty ()) break ;
21232176 if (upper_limit != kHighsInf && !moreHeuristicsAllowed ()) break ;
21242177
2125- analysis.mipTimerStart (kMipClockRootHeuristicsReducedCost );
2126- heuristics.rootReducedCost ();
2127- analysis.mipTimerStop (kMipClockRootHeuristicsReducedCost );
2128- heuristics.flushStatistics ();
2178+ if (mipsolver.options_mip_ ->mip_heuristic_run_root_reduced_cost ) {
2179+ analysis.mipTimerStart (kMipClockRootHeuristicsReducedCost );
2180+ heuristics.rootReducedCost ();
2181+ analysis.mipTimerStop (kMipClockRootHeuristicsReducedCost );
2182+ heuristics.flushStatistics ();
2183+ }
21292184
21302185 if (checkLimits ()) return clockOff (analysis);
21312186
@@ -2151,10 +2206,12 @@ void HighsMipSolverData::evaluateRootNode() {
21512206 if (upper_limit != kHighsInf && !moreHeuristicsAllowed ()) break ;
21522207
21532208 if (checkLimits ()) return clockOff (analysis);
2154- analysis.mipTimerStart (kMipClockRootHeuristicsRens );
2155- heuristics.RENS (rootlpsol);
2156- analysis.mipTimerStop (kMipClockRootHeuristicsRens );
2157- heuristics.flushStatistics ();
2209+ if (mipsolver.options_mip_ ->mip_heuristic_run_rens ) {
2210+ analysis.mipTimerStart (kMipClockRootHeuristicsRens );
2211+ heuristics.RENS (rootlpsol);
2212+ analysis.mipTimerStop (kMipClockRootHeuristicsRens );
2213+ heuristics.flushStatistics ();
2214+ }
21582215
21592216 if (checkLimits ()) return clockOff (analysis);
21602217 // if there are new global bound changes we re-evaluate the LP and do one
0 commit comments