Skip to content

Commit 5478572

Browse files
committed
Add basic algorithm for two tableau rows
1 parent b58075b commit 5478572

File tree

2 files changed

+53
-31
lines changed

2 files changed

+53
-31
lines changed

highs/mip/HighsLpAggregator.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,13 @@ class HighsLpAggregator {
4343
/// clear the current aggregation
4444
void clear();
4545

46+
/// swaps data with another lpAggregator
47+
void swap(HighsLpAggregator& lpAggregator) noexcept {
48+
std::swap(this->vectorsum.values, lpAggregator.vectorsum.values);
49+
std::swap(this->vectorsum.nonzeroinds,
50+
lpAggregator.vectorsum.nonzeroinds);
51+
}
52+
4653
/// checks whether the current aggregation is empty
4754
bool isEmpty() { return vectorsum.nonzeroinds.empty(); }
4855
};

highs/mip/HighsTableauSeparator.cpp

Lines changed: 46 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ void HighsTableauSeparator::separateLpSolution(HighsLpRelaxation& lpRelaxation,
186186
pdqsort_branchless(fractionalBasisvars.begin(), fractionalBasisvars.end());
187187
double bestScore = -1.0;
188188

189+
HighsLpAggregator lpMultiAggregator = lpAggregator;
189190
HighsInt numCuts = cutpool.getNumCuts();
190191
const double bestScoreFac[] = {0.0025, 0.01};
191192

@@ -197,45 +198,59 @@ void HighsTableauSeparator::separateLpSolution(HighsLpRelaxation& lpRelaxation,
197198
break;
198199

199200
assert(lpAggregator.isEmpty());
200-
for (std::pair<HighsInt, double> rowWeight : fracvar.row_ep)
201+
for (std::pair<HighsInt, double> rowWeight : fracvar.row_ep) {
201202
lpAggregator.addRow(rowWeight.first, rowWeight.second);
202-
203-
lpAggregator.getCurrentAggregation(baseRowInds, baseRowVals, false);
204-
205-
if (10 * (baseRowInds.size() - fracvar.row_ep.size()) >
206-
10000 + static_cast<size_t>(mip.numCol())) {
207-
lpAggregator.clear();
208-
continue;
203+
lpMultiAggregator.addRow(rowWeight.first, rowWeight.second);
209204
}
210205

211-
HighsInt len = baseRowInds.size();
212-
if (len > (HighsInt)fracvar.row_ep.size()) {
213-
double maxAbsVal = 0.0;
214-
double minAbsVal = kHighsInf;
215-
for (HighsInt i = 0; i < len; ++i) {
216-
if (baseRowInds[i] < mip.numCol()) {
217-
maxAbsVal = std::max(std::abs(baseRowVals[i]), maxAbsVal);
218-
minAbsVal = std::min(std::abs(baseRowVals[i]), minAbsVal);
206+
auto generateTableauCut = [&](HighsLpAggregator& aggregator) {
207+
aggregator.getCurrentAggregation(baseRowInds, baseRowVals, false);
208+
209+
if (10 * (baseRowInds.size() - fracvar.row_ep.size()) >
210+
10000 + static_cast<size_t>(mip.numCol())) {
211+
aggregator.clear();
212+
return false;
213+
}
214+
215+
HighsInt len = baseRowInds.size();
216+
if (len > (HighsInt)fracvar.row_ep.size()) {
217+
double maxAbsVal = 0.0;
218+
double minAbsVal = kHighsInf;
219+
for (HighsInt i = 0; i < len; ++i) {
220+
if (baseRowInds[i] < mip.numCol()) {
221+
maxAbsVal = std::max(std::abs(baseRowVals[i]), maxAbsVal);
222+
minAbsVal = std::min(std::abs(baseRowVals[i]), minAbsVal);
223+
}
224+
}
225+
if (maxAbsVal / minAbsVal > 1e6) {
226+
aggregator.clear();
227+
return false;
219228
}
220229
}
221-
if (maxAbsVal / minAbsVal > 1e6) {
222-
lpAggregator.clear();
223-
continue;
224-
}
225-
}
226230

227-
mip.mipdata_->debugSolution.checkRowAggregation(
228-
lpSolver.getLp(), baseRowInds.data(), baseRowVals.data(),
229-
baseRowInds.size());
231+
mip.mipdata_->debugSolution.checkRowAggregation(
232+
lpSolver.getLp(), baseRowInds.data(), baseRowVals.data(),
233+
baseRowInds.size());
234+
235+
double rhs = 0;
236+
cutGen.generateCut(transLp, baseRowInds, baseRowVals, rhs);
237+
if (mip.mipdata_->domain.infeasible()) return true;
230238

231-
double rhs = 0;
232-
cutGen.generateCut(transLp, baseRowInds, baseRowVals, rhs);
233-
if (mip.mipdata_->domain.infeasible()) break;
239+
aggregator.getCurrentAggregation(baseRowInds, baseRowVals, true);
240+
rhs = 0;
241+
cutGen.generateCut(transLp, baseRowInds, baseRowVals, rhs);
242+
if (mip.mipdata_->domain.infeasible()) return true;
243+
return false;
244+
};
234245

235-
lpAggregator.getCurrentAggregation(baseRowInds, baseRowVals, true);
236-
rhs = 0;
237-
cutGen.generateCut(transLp, baseRowInds, baseRowVals, rhs);
238-
if (mip.mipdata_->domain.infeasible()) break;
246+
bool infeasible = generateTableauCut(lpAggregator);
247+
if (infeasible) break;
248+
249+
if (bestScore != -1.0 || cutpool.getNumCuts() != numCuts) {
250+
infeasible = generateTableauCut(lpMultiAggregator);
251+
if (infeasible) break;
252+
lpAggregator.swap(lpMultiAggregator);
253+
}
239254

240255
lpAggregator.clear();
241256
if (bestScore == -1.0 && cutpool.getNumCuts() != numCuts)

0 commit comments

Comments
 (0)