Skip to content

Commit

Permalink
Fixed neos-911880
Browse files Browse the repository at this point in the history
  • Loading branch information
apete committed Jul 22, 2024
1 parent 1708805 commit 03821a3
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 18 deletions.
40 changes: 29 additions & 11 deletions src/main/java/org/ojalgo/optimisation/linear/SimplexSolver.java
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,8 @@ int row() {

}

private static final NumberContext ALGORITHM = NumberContext.of(8).withMode(RoundingMode.HALF_DOWN);
private static final NumberContext PIVOT = NumberContext.of(6).withMode(RoundingMode.HALF_DOWN);
private static final NumberContext RATIO = NumberContext.of(8).withMode(RoundingMode.HALF_DOWN);

static <S extends SimplexStore> S build(final ExpressionsBasedModel model, final Function<LinearStructure, S> factory) {

Expand Down Expand Up @@ -433,7 +434,7 @@ public final Collection<Equation> generateCutCandidates(final double fractionali
BasicLogger.debug("+++: {}", Arrays.toString(mySolutionShift));
}

return mySimplex.generateCutCandidates(integer, ALGORITHM, fractionality);
return mySimplex.generateCutCandidates(integer, options.feasibility, fractionality);
}

@Override
Expand Down Expand Up @@ -528,7 +529,6 @@ private boolean getDualExitCandidate(final IterDescr iteration) {

double largest = 1E-10;
int[] included = mySimplex.included;
// for (int ji = 0, limit = included.length; ji < limit; ji++) {
for (int ji = included.length - 1; ji >= 0; ji--) {
int j = included[ji];

Expand Down Expand Up @@ -837,8 +837,10 @@ private boolean testDualEnterRatio(final IterDescr iteration) {
double numer = ZERO;
double denom = ONE;
double ratio = ZERO;
double scale = ONE;

iteration.ratioDual = Double.MAX_VALUE;
double iterationScale = MACHINE_LARGEST;

int n = mySimplex.structure.countVariables();
int[] excluded = mySimplex.excluded;
Expand All @@ -847,8 +849,9 @@ private boolean testDualEnterRatio(final IterDescr iteration) {
if (j < n) {

denom = mySimplex.getCurrentElement(exit, je);
scale = Math.abs(denom);

if (!ALGORITHM.isZero(denom)) {
if (!PIVOT.isZero(denom)) {

ColumnState columnState = mySimplex.getColumnState(j);

Expand Down Expand Up @@ -881,7 +884,12 @@ private boolean testDualEnterRatio(final IterDescr iteration) {
this.log(1, "{}({}) {} / {} = {}", j, je, numer, denom, ratio);
}

if (ratio < iteration.ratioDual) {
if (ratio < iteration.ratioDual
|| scale > iterationScale && PIVOT.isDifferent(iterationScale, scale) && !RATIO.isDifferent(iteration.ratioDual, ratio)) {

if (ratio >= iteration.ratioDual) {
this.log("It happened!");
}

enter.index = je;
enter.from = columnState;
Expand All @@ -892,6 +900,7 @@ private boolean testDualEnterRatio(final IterDescr iteration) {
}

iteration.ratioDual = ratio;
iterationScale = scale;
}
}
}
Expand Down Expand Up @@ -922,17 +931,19 @@ private boolean testPrimalExitRatio(final IterDescr iteration) {
double numer = ZERO;
double denom = ONE;
double ratio = ZERO;
double scale = ONE;

iteration.ratioPrimal = range;
double iterationScale = MACHINE_LARGEST;

int[] included = mySimplex.included;
// for (int ji = 0; ji < included.length; ji++) {
for (int ji = included.length - 1; ji >= 0; ji--) {
int j = included[ji];

denom = mySimplex.getCurrentElement(ji, enter);
scale = Math.abs(denom);

if (!ALGORITHM.isZero(denom)) {
if (!PIVOT.isZero(denom)) {

if (enterDirection == Direction.INCREASE) {
// Entering variable will increase
Expand All @@ -951,7 +962,8 @@ private boolean testPrimalExitRatio(final IterDescr iteration) {
this.log(1, "{}({}) {} / {} = {}", j, ji, numer, denom, ratio);
}

if (ratio < iteration.ratioPrimal) {
if (ratio < iteration.ratioPrimal
|| scale > iterationScale && PIVOT.isDifferent(iterationScale, scale) && !RATIO.isDifferent(iteration.ratioPrimal, ratio)) {

exit.index = ji;
if (denom < ZERO) {
Expand All @@ -967,6 +979,7 @@ private boolean testPrimalExitRatio(final IterDescr iteration) {
}

iteration.ratioPrimal = ratio;
iterationScale = scale;
}

} else if (enterDirection == Direction.DECREASE) {
Expand All @@ -986,7 +999,8 @@ private boolean testPrimalExitRatio(final IterDescr iteration) {
this.log(1, "{}({}) {} / {} = {}", j, ji, numer, denom, ratio);
}

if (ratio < iteration.ratioPrimal) {
if (ratio < iteration.ratioPrimal
|| scale > iterationScale && PIVOT.isDifferent(iterationScale, scale) && !RATIO.isDifferent(iteration.ratioPrimal, ratio)) {

exit.index = ji;
if (denom > ZERO) {
Expand All @@ -1002,6 +1016,7 @@ private boolean testPrimalExitRatio(final IterDescr iteration) {
}

iteration.ratioPrimal = ratio;
iterationScale = scale;
}

} else {
Expand Down Expand Up @@ -1035,6 +1050,9 @@ private void update(final IterDescr iteration) {
this.log();
this.log("Pivoting: {}", iteration);
this.log("==>> Row: {}, Exit: {}, Column/Enter: {}.", iteration.exit.index, iteration.exit.column(), iteration.enter.column());
this.log("Cost={}, Pivot1={}, Pivot2={}, RHS={}, Inf={}", mySimplex.getReducedCost(iteration.enter.index),
mySimplex.getCurrentElement(iteration.exit, iteration.enter.index), mySimplex.getCurrentElement(iteration.exit.index, iteration.enter),
mySimplex.getCurrentRHS(iteration.exit.row()), mySimplex.getInfeasibility(iteration.exit.index));
this.log("Shift Exit: {}, Enter: {}", mySolutionShift[iteration.exit.column()], mySolutionShift[iteration.enter.column()]);
}

Expand Down Expand Up @@ -1114,7 +1132,7 @@ final void doDualIterations(final IterDescr iteration) {
done = true;
}

if (this.isLogDebug()) {
if (this.isLogDebug() && mySimplex.isPrintable()) {
this.logCurrentState();
}
}
Expand Down Expand Up @@ -1156,7 +1174,7 @@ final void doPrimalIterations(final IterDescr iteration) {
done = true;
}

if (this.isLogDebug()) {
if (this.isLogDebug() && mySimplex.isPrintable()) {
this.logCurrentState();
}

Expand Down
10 changes: 6 additions & 4 deletions src/main/java/org/ojalgo/type/context/NumberContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -355,17 +355,19 @@ public boolean isMoreThan(final BigDecimal reference, final BigDecimal value) {
public boolean isSmall(final BigDecimal comparedTo, final BigDecimal value) {
if (this.isZero(comparedTo)) {
return this.isZero(value);
} else {
BigDecimal reference = this.enforce(comparedTo);
return this.enforce(reference.add(value)).compareTo(reference) == 0;
}
BigDecimal reference = this.enforce(comparedTo);
return this.enforce(reference.add(value)).compareTo(reference) == 0;
}

public boolean isSmall(final double comparedTo, final double value) {
if (NumberContext.isZero(comparedTo, myZeroError)) {
return NumberContext.isZero(value, myZeroError);
} else {
double relative = value / comparedTo;
return NumberContext.isZero(relative, myEpsilon);
}
double relative = value / comparedTo;
return NumberContext.isZero(relative, myEpsilon);
}

public boolean isZero(final BigDecimal value) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
*/
public class IntegerUserFiles extends OptimisationIntegerTests implements ModelFileTest {

private static final NumberContext ACCURACY = NumberContext.of(8);
private static final NumberContext ACCURACY = NumberContext.of(6);

private static ExpressionsBasedModel doTest(final String modelName, final String expMinValString, final String expMaxValString,
final IntegerStrategy strategy) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
import java.util.HashMap;
import java.util.Map;

import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.ojalgo.optimisation.ExpressionsBasedModel;
import org.ojalgo.optimisation.ModelFileTest;
Expand Down Expand Up @@ -293,7 +292,6 @@ public void testNeos5() {
* </p>
*/
@Test
@Tag("new_lp_problem")
public void testNeos911880() {
RelaxedMIPCase.doTest("neos-911880.mps", "23.26", null, null);
}
Expand Down

0 comments on commit 03821a3

Please sign in to comment.