@@ -4929,8 +4929,7 @@ HPresolve::Result HPresolve::enumerateSolutions(
49294929 std::vector<double > worstCaseUpperBound (model->num_col_ , -kHighsInf );
49304930
49314931 // lambda for branching (just performs initial lower branch)
4932- auto doBranch = [&](HighsDomain& domain, const std::vector<HighsInt>& vars,
4933- std::vector<branch>& branches, HighsInt& numBranches) {
4932+ auto doBranch = [&](HighsInt& numBranches) {
49344933 // find variable for branching
49354934 HighsInt branchvar = -1 ;
49364935 for (HighsInt j : vars) {
@@ -4948,8 +4947,7 @@ HPresolve::Result HPresolve::enumerateSolutions(
49484947 };
49494948
49504949 // lambda for backtracking
4951- auto doBacktrack = [&](HighsDomain& domain, std::vector<branch>& branches,
4952- HighsInt& numBranches) {
4950+ auto doBacktrack = [&](HighsInt& numBranches) {
49534951 while (numBranches >= 0 ) {
49544952 // get column index
49554953 const auto & domchg =
@@ -4974,17 +4972,15 @@ HPresolve::Result HPresolve::enumerateSolutions(
49744972 };
49754973
49764974 // lambda for checking if a solution was found
4977- auto solutionFound = [&](const HighsDomain& domain,
4978- std::vector<HighsInt>& vars) {
4975+ auto solutionFound = [&]() {
49794976 for (HighsInt j : vars)
49804977 if (!domain.isFixed (j)) return false ;
49814978 return true ;
49824979 };
49834980
49844981 // lambda for checking whether the values of two binary variables are
49854982 // identical in all feasible solutions
4986- auto identicalVars = [&](const std::vector<std::vector<HighsInt>>& solutions,
4987- size_t index1, size_t index2) {
4983+ auto identicalVars = [&](size_t index1, size_t index2) {
49884984 for (size_t sol = 0 ; sol < solutions[index1].size (); sol++) {
49894985 if (solutions[index1][sol] != solutions[index2][sol]) return false ;
49904986 }
@@ -4993,15 +4989,12 @@ HPresolve::Result HPresolve::enumerateSolutions(
49934989
49944990 // lambda for checking whether the values of two binary variables are
49954991 // complementary in all feasible solutions
4996- auto complementaryVars =
4997- [&](const std::vector<std::vector<HighsInt>>& solutions, size_t index1,
4998- size_t index2) {
4999- for (size_t sol = 0 ; sol < solutions[index1].size (); sol++) {
5000- if (solutions[index1][sol] != 1 - solutions[index2][sol])
5001- return false ;
5002- }
5003- return true ;
5004- };
4992+ auto complementaryVars = [&](size_t index1, size_t index2) {
4993+ for (size_t sol = 0 ; sol < solutions[index1].size (); sol++) {
4994+ if (solutions[index1][sol] != 1 - solutions[index2][sol]) return false ;
4995+ }
4996+ return true ;
4997+ };
50054998
50064999 auto handleInfeasibility = [&](bool infeasible) {
50075000 if (infeasible) {
@@ -5011,7 +5004,49 @@ HPresolve::Result HPresolve::enumerateSolutions(
50115004 return Result::kOk ;
50125005 };
50135006
5014- // loop over candiate rows
5007+ auto handleSolution = [&](size_t & numWorstCaseBounds) {
5008+ // propagate
5009+ domain.propagate ();
5010+ if (domain.infeasible ()) return ;
5011+ // handling of worst-case bounds
5012+ if (solutions[0 ].empty ()) {
5013+ // initialize
5014+ for (HighsInt col : domain.getChangedCols ()) {
5015+ worstCaseBounds[numWorstCaseBounds++] = col;
5016+ worstCaseLowerBound[col] =
5017+ std::min (worstCaseLowerBound[col], domain.col_lower_ [col]);
5018+ worstCaseUpperBound[col] =
5019+ std::max (worstCaseUpperBound[col], domain.col_upper_ [col]);
5020+ }
5021+ } else {
5022+ size_t i = 0 ;
5023+ while (i < numWorstCaseBounds) {
5024+ HighsInt col = worstCaseBounds[i];
5025+ if (!domain.isChangedCol (col)) {
5026+ // no bound changes for this variable -> reset worst-case
5027+ // bounds and remove variable
5028+ worstCaseLowerBound[col] = kHighsInf ;
5029+ worstCaseUpperBound[col] = -kHighsInf ;
5030+ worstCaseBounds[i] = worstCaseBounds[numWorstCaseBounds - 1 ];
5031+ worstCaseBounds[numWorstCaseBounds - 1 ] = 0 ;
5032+ numWorstCaseBounds--;
5033+ } else {
5034+ // update worst-case bounds
5035+ worstCaseLowerBound[col] =
5036+ std::min (worstCaseLowerBound[col], domain.col_lower_ [col]);
5037+ worstCaseUpperBound[col] =
5038+ std::max (worstCaseUpperBound[col], domain.col_upper_ [col]);
5039+ i++;
5040+ }
5041+ }
5042+ }
5043+ // store solution
5044+ for (size_t i = 0 ; i < vars.size (); i++)
5045+ solutions[i].push_back (domain.col_lower_ [vars[i]] == 0.0 ? HighsInt{0 }
5046+ : HighsInt{1 });
5047+ };
5048+
5049+ // loop over candidate rows
50155050 HighsInt numRowsChecked = 0 ;
50165051 for (const auto & r : rows) {
50175052 // get row index
@@ -5051,55 +5086,13 @@ HPresolve::Result HPresolve::enumerateSolutions(
50515086 while (true ) {
50525087 bool backtrack = domain.infeasible ();
50535088 if (!backtrack) {
5054- backtrack = solutionFound (domain, vars);
5055- if (backtrack) {
5056- // propagate
5057- domain.propagate ();
5058- if (!domain.infeasible ()) {
5059- // handling of worst-case bounds
5060- if (solutions[0 ].empty ()) {
5061- for (HighsInt col : domain.getChangedCols ()) {
5062- // initialize
5063- worstCaseBounds[numWorstCaseBounds++] = col;
5064- worstCaseLowerBound[col] =
5065- std::min (worstCaseLowerBound[col], domain.col_lower_ [col]);
5066- worstCaseUpperBound[col] =
5067- std::max (worstCaseUpperBound[col], domain.col_upper_ [col]);
5068- }
5069- } else {
5070- size_t i = 0 ;
5071- while (i < numWorstCaseBounds) {
5072- HighsInt col = worstCaseBounds[i];
5073- if (!domain.isChangedCol (col)) {
5074- // no bound changes for this variable -> reset worst-case
5075- // bounds and remove variable
5076- worstCaseLowerBound[col] = kHighsInf ;
5077- worstCaseUpperBound[col] = -kHighsInf ;
5078- worstCaseBounds[i] = worstCaseBounds[numWorstCaseBounds - 1 ];
5079- worstCaseBounds[numWorstCaseBounds - 1 ] = 0 ;
5080- numWorstCaseBounds--;
5081- } else {
5082- // update worst-case bounds
5083- worstCaseLowerBound[col] = std::min (worstCaseLowerBound[col],
5084- domain.col_lower_ [col]);
5085- worstCaseUpperBound[col] = std::max (worstCaseUpperBound[col],
5086- domain.col_upper_ [col]);
5087- i++;
5088- }
5089- }
5090- }
5091- // store solution
5092- for (size_t i = 0 ; i < vars.size (); i++)
5093- solutions[i].push_back (domain.col_lower_ [vars[i]] == 0.0
5094- ? HighsInt{0 }
5095- : HighsInt{1 });
5096- }
5097- }
5089+ backtrack = solutionFound ();
5090+ if (backtrack) handleSolution (numWorstCaseBounds);
50985091 }
50995092 // branch or backtrack
51005093 if (!backtrack)
5101- doBranch (domain, vars, branches, numBranches);
5102- else if (!doBacktrack (domain, branches, numBranches))
5094+ doBranch (numBranches);
5095+ else if (!doBacktrack (numBranches))
51035096 break ;
51045097 }
51055098
@@ -5146,13 +5139,13 @@ HPresolve::Result HPresolve::enumerateSolutions(
51465139 if (domain.isFixed (col2)) continue ;
51475140 // check if two binary variables take identical or complementary
51485141 // values in all feasible solutions
5149- if (identicalVars (solutions, i, ii)) {
5142+ if (identicalVars (i, ii)) {
51505143 // add clique x_1 + (1 - x_2) = 1 to clique table
51515144 std::array<HighsCliqueTable::CliqueVar, 2 > clique;
51525145 clique[0 ] = HighsCliqueTable::CliqueVar (col, 0 );
51535146 clique[1 ] = HighsCliqueTable::CliqueVar (col2, 1 );
51545147 cliquetable.addClique (*mipsolver, clique.data (), 2 , true );
5155- } else if (complementaryVars (solutions, i, ii)) {
5148+ } else if (complementaryVars (i, ii)) {
51565149 // add clique x_1 + x_2 = 1 to clique table
51575150 std::array<HighsCliqueTable::CliqueVar, 2 > clique;
51585151 clique[0 ] = HighsCliqueTable::CliqueVar (col, 0 );
0 commit comments