fixed an error leading the simplex solver to compute the right solution but return another one
JIRA: MATH-286 git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@806753 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
3f9613be38
commit
dbdff0758b
|
@ -270,8 +270,27 @@ class SimplexTableau implements Serializable {
|
|||
* @return the row that the variable is basic in. null if the column is not basic
|
||||
*/
|
||||
private Integer getBasicRow(final int col) {
|
||||
return getBasicRow(col, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given column is basic.
|
||||
* @param col index of the column to check
|
||||
* @return the row that the variable is basic in. null if the column is not basic
|
||||
*/
|
||||
private Integer getBasicRowForSolution(final int col) {
|
||||
return getBasicRow(col, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given column is basic.
|
||||
* @param col index of the column to check
|
||||
* @return the row that the variable is basic in. null if the column is not basic
|
||||
*/
|
||||
private Integer getBasicRow(final int col, boolean ignoreObjectiveRows) {
|
||||
Integer row = null;
|
||||
for (int i = getNumObjectiveFunctions(); i < getHeight(); i++) {
|
||||
int start = ignoreObjectiveRows ? getNumObjectiveFunctions() : 0;
|
||||
for (int i = start; i < getHeight(); i++) {
|
||||
if (MathUtils.equals(getEntry(i, col), 1.0, epsilon) && (row == null)) {
|
||||
row = i;
|
||||
} else if (!MathUtils.equals(getEntry(i, col), 0.0, epsilon)) {
|
||||
|
@ -318,24 +337,23 @@ class SimplexTableau implements Serializable {
|
|||
* @return current solution
|
||||
*/
|
||||
protected RealPointValuePair getSolution() {
|
||||
double[] coefficients = new double[getOriginalNumDecisionVariables()];
|
||||
Integer basicRow =
|
||||
getBasicRow(getNumObjectiveFunctions() + getOriginalNumDecisionVariables());
|
||||
double mostNegative = basicRow == null ? 0 : getEntry(basicRow, getRhsOffset());
|
||||
Set<Integer> basicRows = new HashSet<Integer>();
|
||||
for (int i = 0; i < coefficients.length; i++) {
|
||||
basicRow = getBasicRow(getNumObjectiveFunctions() + i);
|
||||
if (basicRows.contains(basicRow)) {
|
||||
// if multiple variables can take a given value
|
||||
// then we choose the first and set the rest equal to 0
|
||||
coefficients[i] = 0;
|
||||
} else {
|
||||
basicRows.add(basicRow);
|
||||
coefficients[i] =
|
||||
(basicRow == null ? 0 : getEntry(basicRow, getRhsOffset())) -
|
||||
(restrictToNonNegative ? 0 : mostNegative);
|
||||
}
|
||||
}
|
||||
double[] coefficients = new double[getOriginalNumDecisionVariables()];
|
||||
Integer negativeVarBasicRow = getBasicRowForSolution(getNegativeDecisionVariableOffset());
|
||||
double mostNegative = negativeVarBasicRow == null ? 0 : getEntry(negativeVarBasicRow, getRhsOffset());
|
||||
Set<Integer> basicRows = new HashSet<Integer>();
|
||||
for (int i = 0; i < coefficients.length; i++) {
|
||||
Integer basicRow = getBasicRowForSolution(getNumObjectiveFunctions() + i);
|
||||
if (basicRows.contains(basicRow)) {
|
||||
// if multiple variables can take a given value
|
||||
// then we choose the first and set the rest equal to 0
|
||||
coefficients[i] = 0;
|
||||
} else {
|
||||
basicRows.add(basicRow);
|
||||
coefficients[i] =
|
||||
(basicRow == null ? 0 : getEntry(basicRow, getRhsOffset())) -
|
||||
(restrictToNonNegative ? 0 : mostNegative);
|
||||
}
|
||||
}
|
||||
return new RealPointValuePair(coefficients, f.getValue(coefficients));
|
||||
}
|
||||
|
||||
|
@ -430,6 +448,15 @@ class SimplexTableau implements Serializable {
|
|||
protected final int getRhsOffset() {
|
||||
return getWidth() - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the offset of the extra decision variable added when there is a
|
||||
* negative decision variable in the original problem.
|
||||
* @return the offset of x-
|
||||
*/
|
||||
protected final int getNegativeDecisionVariableOffset() {
|
||||
return getNumObjectiveFunctions() + getOriginalNumDecisionVariables();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of decision variables.
|
||||
|
|
|
@ -39,6 +39,10 @@ The <action> type attribute can be add,update,fix,remove.
|
|||
</properties>
|
||||
<body>
|
||||
<release version="2.1" date="TBD" description="TBD">
|
||||
<action dev="luc" type="fix" issue="MATH-286" due-to="Benjamin McCann">
|
||||
Fixed an error leading the simplex solver to compute the right solution
|
||||
but return another one
|
||||
</action>
|
||||
<action dev="luc" type="fix" issue="MATH-283" due-to="Michael Nischt">
|
||||
Prevent infinite loops in multi-directional direct optimization method when
|
||||
the start point is exactly at the optimal point
|
||||
|
|
|
@ -46,8 +46,18 @@ public class SimplexSolverTest {
|
|||
assertEquals(1.0, solution.getPoint()[1], .0000001);
|
||||
assertEquals(1.0, solution.getPoint()[2], .0000001);
|
||||
assertEquals(3.0, solution.getValue(), .0000001);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMath286() throws OptimizationException {
|
||||
LinearObjectiveFunction f = new LinearObjectiveFunction(new double[] { 0.2, 0.3 }, 0 );
|
||||
Collection<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
|
||||
constraints.add(new LinearConstraint(new double[] { 1, 1 }, Relationship.EQ, 23.0));
|
||||
|
||||
RealPointValuePair solution = new SimplexSolver().optimize(f, constraints, GoalType.MAXIMIZE, true);
|
||||
assertEquals(6.9, solution.getValue(), .0000001);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimplexSolver() throws OptimizationException {
|
||||
LinearObjectiveFunction f =
|
||||
|
|
Loading…
Reference in New Issue