1515#include " mip/HighsLpRelaxation.h"
1616#include " mip/HighsMipSolverData.h"
1717#include " mip/HighsTransformedLp.h"
18+ #include " pdqsort.h"
1819
1920enum class RowType : int8_t {
2021 kUnusuable = -2 ,
@@ -58,10 +59,7 @@ void HighsPathSeparator::separateLpSolution(HighsLpRelaxation& lpRelaxation,
5859 }
5960
6061 std::vector<HighsInt> numContinuous (lp.num_row_ );
61- // Score will be used for deciding order in which rows get aggregated
62- // TODO: The second entry is currently a hacky way to store the norm
63- std::vector<std::pair<double , double >> rowscore (lp.num_row_ ,
64- std::make_pair (0.0 , 0.0 ));
62+
6563 size_t maxAggrRowSize = 0 ;
6664 for (HighsInt col : mip.mipdata_ ->continuous_cols ) {
6765 if (transLp.boundDistance (col) == 0.0 ) continue ;
@@ -70,10 +68,6 @@ void HighsPathSeparator::separateLpSolution(HighsLpRelaxation& lpRelaxation,
7068 for (HighsInt i = lp.a_matrix_ .start_ [col];
7169 i != lp.a_matrix_ .start_ [col + 1 ]; ++i) {
7270 ++numContinuous[lp.a_matrix_ .index_ [i]];
73- // Add the fractional score of the row
74- rowscore[i].first +=
75- lp.a_matrix_ .value_ [i] * transLp.getFracVbEstimate (col);
76- rowscore[i].second += lp.a_matrix_ .value_ [i];
7771 }
7872 }
7973
@@ -114,6 +108,25 @@ void HighsPathSeparator::separateLpSolution(HighsLpRelaxation& lpRelaxation,
114108 rowtype[i] = RowType::kUnusuable ;
115109 }
116110
111+ // Score will be used for deciding order in which rows get aggregated
112+ std::vector<std::pair<double , double >> rowscore (lp.num_row_ ,
113+ std::make_pair (0.0 , 0.0 ));
114+ for (HighsInt col = 0 ; col != lp.num_col_ ; ++col) {
115+ for (HighsInt i = lp.a_matrix_ .start_ [col];
116+ i != lp.a_matrix_ .start_ [col + 1 ]; ++i) {
117+ HighsInt row = lp.a_matrix_ .index_ [i];
118+ double val = lp.a_matrix_ .value_ [i];
119+ rowscore[row].first += std::abs (val * transLp.getColFractionality (col));
120+ rowscore[row].second += std::abs (val);
121+ }
122+ }
123+ for (HighsInt row = 0 ; row != lp.num_row_ ; ++row) {
124+ if (rowscore[row].second > 0 ) {
125+ rowscore[row].first /= rowscore[row].second ;
126+ rowscore[row].second = 1 ;
127+ }
128+ }
129+
117130 // for each continuous variable with nonzero transformed solution value
118131 // remember the <= and == rows where it is present with a positive coefficient
119132 // in its set of in-arc rows. Treat >= rows as <= rows with reversed sign
@@ -170,6 +183,20 @@ void HighsPathSeparator::separateLpSolution(HighsLpRelaxation& lpRelaxation,
170183
171184 colInArcs[col].second = inArcRows.size ();
172185 colOutArcs[col].second = outArcRows.size ();
186+
187+ // Sort the in and outgoing arcs by their scores
188+ pdqsort (inArcRows.begin () + colInArcs[col].first ,
189+ inArcRows.begin () + colInArcs[col].second ,
190+ [&](const std::pair<HighsInt, double >& i,
191+ const std::pair<HighsInt, double >& j) {
192+ return rowscore[i.first ] > rowscore[j.first ];
193+ });
194+ pdqsort (outArcRows.begin () + colOutArcs[col].first ,
195+ outArcRows.begin () + colOutArcs[col].second ,
196+ [&](const std::pair<HighsInt, double >& i,
197+ const std::pair<HighsInt, double >& j) {
198+ return rowscore[i.first ] > rowscore[j.first ];
199+ });
173200 }
174201
175202 HighsCutGeneration cutGen (lpRelaxation, cutpool);
@@ -266,31 +293,9 @@ void HighsPathSeparator::separateLpSolution(HighsLpRelaxation& lpRelaxation,
266293 const std::vector<std::pair<HighsInt, HighsInt>>& colArcs,
267294 const std::vector<std::pair<HighsInt, double >>& arcRows,
268295 HighsInt& row, double & weight) {
269- HighsInt arcRow = randgen.integer (colArcs[bestArcCol].first ,
270- colArcs[bestArcCol].second );
271- HighsInt r = arcRows[arcRow].first ;
272- double w = -val / arcRows[arcRow].second ;
273- if (!isRowInCurrentPath (r) && checkWeight (w)) {
274- row = r;
275- weight = w;
276- return true ;
277- }
278-
279- for (HighsInt nextRow = arcRow + 1 ;
280- nextRow < colArcs[bestArcCol].second ; ++nextRow) {
281- r = arcRows[nextRow].first ;
282- w = -val / arcRows[nextRow].second ;
283- if (!isRowInCurrentPath (r) && checkWeight (w)) {
284- row = r;
285- weight = w;
286- return true ;
287- }
288- }
289-
290- for (HighsInt nextRow = colArcs[bestArcCol].first ; nextRow < arcRow;
291- ++nextRow) {
292- r = arcRows[nextRow].first ;
293- w = -val / arcRows[nextRow].second ;
296+ for (HighsInt arcRow = colArcs[bestArcCol].first ; arcRow != colArcs[bestArcCol].second ; ++arcRow) {
297+ HighsInt r = arcRows[arcRow].first ;
298+ double w = -val / arcRows[arcRow].second ;
294299 if (!isRowInCurrentPath (r) && checkWeight (w)) {
295300 row = r;
296301 weight = w;
0 commit comments