@@ -4880,6 +4880,7 @@ HPresolve::Result HPresolve::enumerateSolutions(
48804880 // maximum size of a row and maximum number of rows that will be checked
48814881 const size_t maxRowSize = 8 ;
48824882 const HighsInt maxNumRowsChecked = 400 ;
4883+ const size_t maxNumSolutions = 1 << maxRowSize;
48834884
48844885 // check rows
48854886 struct candidaterow {
@@ -4921,22 +4922,22 @@ HPresolve::Result HPresolve::enumerateSolutions(
49214922 size_t numDomainChanges;
49224923 size_t numChangedCols;
49234924 };
4924- std::vector<std::vector <HighsInt>> solutions;
4925- std::vector<HighsInt> vars;
4926- std::vector<branch> branches;
4925+ std::vector<std::array <HighsInt, maxNumSolutions >> solutions (maxRowSize) ;
4926+ std::vector<HighsInt> vars (maxRowSize) ;
4927+ std::vector<branch> branches (maxRowSize) ;
49274928 std::vector<HighsInt> worstCaseBounds (model->num_col_ );
49284929 std::vector<double > worstCaseLowerBound (model->num_col_ , kHighsInf );
49294930 std::vector<double > worstCaseUpperBound (model->num_col_ , -kHighsInf );
49304931 std::vector<double > col_lower (domain.col_lower_ );
49314932 std::vector<double > col_upper (domain.col_upper_ );
49324933
49334934 // lambda for branching (just performs initial lower branch)
4934- auto doBranch = [&](HighsInt& numBranches) {
4935+ auto doBranch = [&](size_t numVars, HighsInt& numBranches) {
49354936 // find variable for branching
49364937 HighsInt branchvar = -1 ;
4937- for (HighsInt j : vars ) {
4938- if (!domain.isFixed (j )) {
4939- branchvar = j ;
4938+ for (size_t i = 0 ; i < numVars; i++ ) {
4939+ if (!domain.isFixed (vars[i] )) {
4940+ branchvar = vars[i] ;
49404941 break ;
49414942 }
49424943 }
@@ -4974,25 +4975,26 @@ HPresolve::Result HPresolve::enumerateSolutions(
49744975 };
49754976
49764977 // lambda for checking if a solution was found
4977- auto solutionFound = [&]() {
4978- for (HighsInt j : vars )
4979- if (!domain.isFixed (j )) return false ;
4978+ auto solutionFound = [&](size_t numVars ) {
4979+ for (size_t i = 0 ; i < numVars; i++ )
4980+ if (!domain.isFixed (vars[i] )) return false ;
49804981 return true ;
49814982 };
49824983
49834984 // lambda for checking whether the values of two binary variables are
49844985 // identical in all feasible solutions
4985- auto identicalVars = [&](size_t index1, size_t index2) {
4986- for (size_t sol = 0 ; sol < solutions[index1]. size () ; sol++) {
4986+ auto identicalVars = [&](size_t numSolutions, size_t index1, size_t index2) {
4987+ for (size_t sol = 0 ; sol < numSolutions ; sol++) {
49874988 if (solutions[index1][sol] != solutions[index2][sol]) return false ;
49884989 }
49894990 return true ;
49904991 };
49914992
49924993 // lambda for checking whether the values of two binary variables are
49934994 // complementary in all feasible solutions
4994- auto complementaryVars = [&](size_t index1, size_t index2) {
4995- for (size_t sol = 0 ; sol < solutions[index1].size (); sol++) {
4995+ auto complementaryVars = [&](size_t numSolutions, size_t index1,
4996+ size_t index2) {
4997+ for (size_t sol = 0 ; sol < numSolutions; sol++) {
49964998 if (solutions[index1][sol] != 1 - solutions[index2][sol]) return false ;
49974999 }
49985000 return true ;
@@ -5014,12 +5016,13 @@ HPresolve::Result HPresolve::enumerateSolutions(
50145016 numWorstCaseBounds--;
50155017 };
50165018
5017- auto handleSolution = [&](size_t & numWorstCaseBounds, bool & noReductions) {
5019+ auto handleSolution = [&](size_t numVars, size_t & numSolutions,
5020+ size_t & numWorstCaseBounds, bool & noReductions) {
50185021 // propagate
50195022 domain.propagate ();
50205023 if (domain.infeasible ()) return ;
50215024 // handling of worst-case bounds
5022- if (solutions[ 0 ]. empty () ) {
5025+ if (numSolutions == 0 ) {
50235026 // initialize
50245027 for (HighsInt col : domain.getChangedCols ()) {
50255028 worstCaseBounds[numWorstCaseBounds++] = col;
@@ -5052,17 +5055,18 @@ HPresolve::Result HPresolve::enumerateSolutions(
50525055 }
50535056 }
50545057 // store solution
5055- for (size_t i = 0 ; i < vars.size (); i++)
5056- solutions[i].push_back (domain.col_lower_ [vars[i]] == 0.0 ? HighsInt{0 }
5057- : HighsInt{1 });
5058+ for (size_t i = 0 ; i < numVars; i++)
5059+ solutions[i][numSolutions] =
5060+ (domain.col_lower_ [vars[i]] == 0.0 ? HighsInt{0 } : HighsInt{1 });
5061+ numSolutions++;
50585062
50595063 // if no reductions are possible, stop enumerating solutions
50605064 noReductions = numWorstCaseBounds == 0 ;
50615065 if (noReductions) {
5062- for (size_t i = 0 ; i < vars. size () - 1 ; i++) {
5063- for (size_t ii = i + 1 ; ii < vars. size () ; ii++) {
5064- noReductions = noReductions && !identicalVars (i, ii) &&
5065- !complementaryVars (i, ii);
5066+ for (size_t i = 0 ; i < numVars - 1 ; i++) {
5067+ for (size_t ii = i + 1 ; ii < numVars ; ii++) {
5068+ noReductions = noReductions && !identicalVars (numSolutions, i, ii) &&
5069+ !complementaryVars (numSolutions, i, ii);
50665070 if (!noReductions) break ;
50675071 }
50685072 if (!noReductions) break ;
@@ -5082,44 +5086,39 @@ HPresolve::Result HPresolve::enumerateSolutions(
50825086 // check if maximum is reached
50835087 if (numRowsChecked > maxNumRowsChecked) break ;
50845088 // check row
5085- vars.clear ();
5086- vars.reserve (rowsize[row]);
5089+ size_t numVars = 0 ;
50875090 for (HighsInt j = mipsolver->mipdata_ ->ARstart_ [row];
50885091 j < mipsolver->mipdata_ ->ARstart_ [row + 1 ]; j++) {
50895092 // get index
50905093 HighsInt col = mipsolver->mipdata_ ->ARindex_ [j];
50915094 // skip fixed variables
50925095 if (domain.isFixed (col)) continue ;
50935096 // store index of binary variable
5094- vars. push_back ( col) ;
5097+ vars[numVars++] = col;
50955098 }
5096- if (vars. empty () ) continue ;
5099+ if (numVars == 0 ) continue ;
50975100
50985101 // clear changed cols
50995102 domain.clearChangedCols ();
51005103
5101- // vectors for storing variable status and solutions
5102- branches.clear ();
5103- solutions.clear ();
5104- branches.resize (vars.size ());
5105- solutions.resize (vars.size ());
5106-
51075104 // main loop
51085105 HighsInt numBranches = -1 ;
51095106 size_t numWorstCaseBounds = 0 ;
5107+ size_t numSolutions = 0 ;
51105108 bool noReductions = false ;
51115109 while (true ) {
51125110 bool backtrack = domain.infeasible ();
51135111 if (!backtrack) {
5114- backtrack = solutionFound ();
5112+ backtrack = solutionFound (numVars );
51155113 if (backtrack) {
5116- handleSolution (numWorstCaseBounds, noReductions);
5114+ handleSolution (numVars, numSolutions, numWorstCaseBounds,
5115+ noReductions);
51175116 if (noReductions) break ;
51185117 }
51195118 }
51205119 // branch or backtrack
51215120 if (!backtrack)
5122- doBranch (numBranches);
5121+ doBranch (numVars, numBranches);
51235122 else if (!doBacktrack (numBranches))
51245123 break ;
51255124 }
@@ -5131,7 +5130,7 @@ HPresolve::Result HPresolve::enumerateSolutions(
51315130 }
51325131
51335132 // no solutions -> infeasible
5134- HPRESOLVE_CHECKED_CALL (handleInfeasibility (solutions[ 0 ]. empty () ));
5133+ HPRESOLVE_CHECKED_CALL (handleInfeasibility (numSolutions == 0 ));
51355134
51365135 // analyse worst-case bounds
51375136 for (size_t i = 0 ; i < numWorstCaseBounds; i++) {
@@ -5160,26 +5159,26 @@ HPresolve::Result HPresolve::enumerateSolutions(
51605159 worstCaseBounds[i] = 0 ;
51615160 }
51625161
5163- for (size_t i = 0 ; i < vars. size () - 1 ; i++) {
5162+ for (size_t i = 0 ; i < numVars - 1 ; i++) {
51645163 // get column index
51655164 HighsInt col = vars[i];
51665165 // skip already fixed columns
51675166 if (domain.isFixed (col)) continue ;
5168- for (size_t ii = i + 1 ; ii < vars. size () ; ii++) {
5167+ for (size_t ii = i + 1 ; ii < numVars ; ii++) {
51695168 // get column index
51705169 HighsInt col2 = vars[ii];
51715170 // skip already fixed columns
51725171 if (domain.isFixed (col2)) continue ;
51735172 // check if two binary variables take identical or complementary
51745173 // values in all feasible solutions
5175- if (identicalVars (i, ii)) {
5174+ if (identicalVars (numSolutions, i, ii)) {
51765175 // add clique x_1 + (1 - x_2) = 1 to clique table
51775176 std::array<HighsCliqueTable::CliqueVar, 2 > clique;
51785177 clique[0 ] = HighsCliqueTable::CliqueVar (col, 0 );
51795178 clique[1 ] = HighsCliqueTable::CliqueVar (col2, 1 );
51805179 cliquetable.addClique (*mipsolver, clique.data (), 2 , true );
51815180 HPRESOLVE_CHECKED_CALL (handleInfeasibility (domain.infeasible ()));
5182- } else if (complementaryVars (i, ii)) {
5181+ } else if (complementaryVars (numSolutions, i, ii)) {
51835182 // add clique x_1 + x_2 = 1 to clique table
51845183 std::array<HighsCliqueTable::CliqueVar, 2 > clique;
51855184 clique[0 ] = HighsCliqueTable::CliqueVar (col, 0 );
0 commit comments