Skip to content

Commit 8135f9c

Browse files
committed
Feasibility jump fixes
* Correct sign of objective contribution * Handle jump candidates with negative coefficient values * Remove double-counting for equality constraints in jump candidate handling * Amend comments
1 parent fd860f9 commit 8135f9c

1 file changed

Lines changed: 18 additions & 8 deletions

File tree

highs/mip/feasibilityjump.hh

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,6 @@ class JumpMove {
350350
else {
351351
constraintBounds.emplace_back(-std::numeric_limits<double>::infinity(),
352352
constraint.rhs);
353-
constraintBounds.emplace_back(constraint.rhs, constraint.rhs);
354353
constraintBounds.emplace_back(constraint.rhs,
355354
std::numeric_limits<double>::infinity());
356355
}
@@ -359,9 +358,17 @@ class JumpMove {
359358
double residualIncumbent =
360359
constraint.incumbentLhs - cell.coeff * varIncumbentValue;
361360

361+
double boundForValidLower, boundForValidUpper;
362+
if (cell.coeff < 0.) {
363+
boundForValidLower = bound.second;
364+
boundForValidUpper = bound.first;
365+
} else {
366+
boundForValidLower = bound.first;
367+
boundForValidUpper = bound.second;
368+
}
362369
std::pair<double, double> validRange = {
363-
((1.0 / cell.coeff) * (bound.first - residualIncumbent)),
364-
((1.0 / cell.coeff) * (bound.second - residualIncumbent)),
370+
((1.0 / cell.coeff) * (boundForValidLower - residualIncumbent)),
371+
((1.0 / cell.coeff) * (boundForValidUpper - residualIncumbent)),
365372
};
366373

367374
if (problem.vars[varIdx].vartype == VarType::Integer)
@@ -370,8 +377,6 @@ class JumpMove {
370377
std::floor(validRange.second + equalityTolerance),
371378
};
372379

373-
if (validRange.first > validRange.second) continue;
374-
375380
if (validRange.first > currentValue) {
376381
currentSlope -= constraint.weight;
377382
if (validRange.first < upper)
@@ -415,6 +420,9 @@ class JumpMove {
415420
if (eq(bestValue, varIncumbentValue, equalityTolerance) ||
416421
(!eq(currentValue, varIncumbentValue, equalityTolerance) &&
417422
currentScore < bestScore)) {
423+
// Different to everywhere else (!)
424+
// Here the score represents infeasibility (not improvement)
425+
// Hence the minimization
418426
bestScore = currentScore;
419427
bestValue = currentValue;
420428
}
@@ -549,7 +557,7 @@ class FeasibilityJumpSolver {
549557
if (problem.vars.size() == 0) break;
550558

551559
uint32_t var = selectVariable();
552-
if (var == UINT_MAX){
560+
if (var == UINT_MAX) {
553561
break;
554562
}
555563
doVariableMove(var);
@@ -653,7 +661,8 @@ class FeasibilityJumpSolver {
653661
dt += problem.vars.size();
654662
for (size_t varIdx = 0; varIdx < problem.vars.size(); varIdx += 1)
655663
forEachMove(varIdx, [&](Move& move) {
656-
move.score += weightUpdateIncrement *
664+
// -= to align objective minimization with score maximization
665+
move.score -= weightUpdateIncrement *
657666
problem.vars[varIdx].objectiveCoeff *
658667
(move.value - problem.incumbentAssignment[varIdx]);
659668
});
@@ -754,7 +763,8 @@ class FeasibilityJumpSolver {
754763

755764
forEachMove(varIdx, [&](Move& move) {
756765
move.score = 0.0;
757-
move.score += objectiveWeight * problem.vars[varIdx].objectiveCoeff *
766+
// -= to align objective minimization with score maximization
767+
move.score -= objectiveWeight * problem.vars[varIdx].objectiveCoeff *
758768
(move.value - problem.incumbentAssignment[varIdx]);
759769

760770
for (auto& cell : problem.vars[varIdx].coeffs) {

0 commit comments

Comments
 (0)