Fixed a problem when setting some variables (several variables were set instead of only one)
JIRA: MATH-272 git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@781135 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
ca9d46257a
commit
ed813abf79
|
@ -23,7 +23,9 @@ import java.io.ObjectOutputStream;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.commons.math.linear.MatrixUtils;
|
import org.apache.commons.math.linear.MatrixUtils;
|
||||||
import org.apache.commons.math.linear.RealMatrix;
|
import org.apache.commons.math.linear.RealMatrix;
|
||||||
|
@ -321,38 +323,26 @@ class SimplexTableau implements Serializable {
|
||||||
*/
|
*/
|
||||||
protected RealPointValuePair getSolution() {
|
protected RealPointValuePair getSolution() {
|
||||||
double[] coefficients = new double[getOriginalNumDecisionVariables()];
|
double[] coefficients = new double[getOriginalNumDecisionVariables()];
|
||||||
double mostNegative = getDecisionVariableValue(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++) {
|
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] =
|
coefficients[i] =
|
||||||
getDecisionVariableValue(i) - (restrictToNonNegative ? 0 : mostNegative);
|
(basicRow == null ? 0 : getEntry(basicRow, getRhsOffset())) -
|
||||||
|
(restrictToNonNegative ? 0 : mostNegative);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return new RealPointValuePair(coefficients, f.getValue(coefficients));
|
return new RealPointValuePair(coefficients, f.getValue(coefficients));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the value of the given decision variable. This is not the actual
|
|
||||||
* value as it is guaranteed to be >= 0 and thus must be corrected before
|
|
||||||
* being returned to the user.
|
|
||||||
*
|
|
||||||
* @param decisionVariable The index of the decision variable
|
|
||||||
* @return The value of the given decision variable.
|
|
||||||
*/
|
|
||||||
protected double getDecisionVariableValue(final int decisionVariable) {
|
|
||||||
int col = getNumObjectiveFunctions() + decisionVariable;
|
|
||||||
Integer basicRow = getBasicRow(col);
|
|
||||||
if (basicRow == null) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
// if there are multiple variables that can take the value on the RHS
|
|
||||||
// then we'll give the first variable that value
|
|
||||||
for (int i = getNumObjectiveFunctions(); i < col; i++) {
|
|
||||||
if (tableau.getEntry(basicRow, i) == 1) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return getEntry(basicRow, getRhsOffset());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subtracts a multiple of one row from another.
|
* Subtracts a multiple of one row from another.
|
||||||
* <p>
|
* <p>
|
||||||
|
|
|
@ -39,6 +39,10 @@ The <action> type attribute can be add,update,fix,remove.
|
||||||
</properties>
|
</properties>
|
||||||
<body>
|
<body>
|
||||||
<release version="2.0" date="TBD" description="TBD">
|
<release version="2.0" date="TBD" description="TBD">
|
||||||
|
<action dev="luc" type="fix" issue="MATH-272" due-to="Benjamin McCann">
|
||||||
|
Fixed a problem when setting some variables (several variables were set
|
||||||
|
instead of only one)
|
||||||
|
</action>
|
||||||
<action dev="luc" type="add" due-to="Gilles Sadowski">
|
<action dev="luc" type="add" due-to="Gilles Sadowski">
|
||||||
Added a way to limit the number of functions evaluations in optimizers
|
Added a way to limit the number of functions evaluations in optimizers
|
||||||
(the number of iterations could already be limited)
|
(the number of iterations could already be limited)
|
||||||
|
|
|
@ -17,19 +17,38 @@
|
||||||
|
|
||||||
package org.apache.commons.math.optimization.linear;
|
package org.apache.commons.math.optimization.linear;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
|
||||||
|
|
||||||
import org.apache.commons.math.linear.RealVector;
|
import org.apache.commons.math.linear.RealVector;
|
||||||
import org.apache.commons.math.linear.RealVectorImpl;
|
import org.apache.commons.math.linear.RealVectorImpl;
|
||||||
import org.apache.commons.math.optimization.GoalType;
|
import org.apache.commons.math.optimization.GoalType;
|
||||||
import org.apache.commons.math.optimization.OptimizationException;
|
import org.apache.commons.math.optimization.OptimizationException;
|
||||||
import org.apache.commons.math.optimization.RealPointValuePair;
|
import org.apache.commons.math.optimization.RealPointValuePair;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
public class SimplexSolverTest extends TestCase {
|
public class SimplexSolverTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMath272() throws OptimizationException {
|
||||||
|
LinearObjectiveFunction f = new LinearObjectiveFunction(new double[] { 2, 2, 1 }, 0);
|
||||||
|
Collection<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
|
||||||
|
constraints.add(new LinearConstraint(new double[] { 1, 1, 0 }, Relationship.GEQ, 1));
|
||||||
|
constraints.add(new LinearConstraint(new double[] { 1, 0, 1 }, Relationship.GEQ, 1));
|
||||||
|
constraints.add(new LinearConstraint(new double[] { 0, 1, 0 }, Relationship.GEQ, 1));
|
||||||
|
|
||||||
|
SimplexSolver solver = new SimplexSolver();
|
||||||
|
RealPointValuePair solution = solver.optimize(f, constraints, GoalType.MINIMIZE, true);
|
||||||
|
|
||||||
|
assertEquals(0.0, solution.getPoint()[0], .0000001);
|
||||||
|
assertEquals(1.0, solution.getPoint()[1], .0000001);
|
||||||
|
assertEquals(1.0, solution.getPoint()[2], .0000001);
|
||||||
|
assertEquals(3.0, solution.getValue(), .0000001);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void testSimplexSolver() throws OptimizationException {
|
public void testSimplexSolver() throws OptimizationException {
|
||||||
LinearObjectiveFunction f =
|
LinearObjectiveFunction f =
|
||||||
new LinearObjectiveFunction(new double[] { 15, 10 }, 7);
|
new LinearObjectiveFunction(new double[] { 15, 10 }, 7);
|
||||||
|
@ -40,15 +59,16 @@ public class SimplexSolverTest extends TestCase {
|
||||||
|
|
||||||
SimplexSolver solver = new SimplexSolver();
|
SimplexSolver solver = new SimplexSolver();
|
||||||
RealPointValuePair solution = solver.optimize(f, constraints, GoalType.MAXIMIZE, false);
|
RealPointValuePair solution = solver.optimize(f, constraints, GoalType.MAXIMIZE, false);
|
||||||
assertEquals(2.0, solution.getPoint()[0]);
|
assertEquals(2.0, solution.getPoint()[0], 0.0);
|
||||||
assertEquals(2.0, solution.getPoint()[1]);
|
assertEquals(2.0, solution.getPoint()[1], 0.0);
|
||||||
assertEquals(57.0, solution.getValue());
|
assertEquals(57.0, solution.getValue(), 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* With no artificial variables needed (no equals and no greater than
|
* With no artificial variables needed (no equals and no greater than
|
||||||
* constraints) we can go straight to Phase 2.
|
* constraints) we can go straight to Phase 2.
|
||||||
*/
|
*/
|
||||||
|
@Test
|
||||||
public void testModelWithNoArtificialVars() throws OptimizationException {
|
public void testModelWithNoArtificialVars() throws OptimizationException {
|
||||||
LinearObjectiveFunction f = new LinearObjectiveFunction(new double[] { 15, 10 }, 0);
|
LinearObjectiveFunction f = new LinearObjectiveFunction(new double[] { 15, 10 }, 0);
|
||||||
Collection<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
|
Collection<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
|
||||||
|
@ -58,11 +78,12 @@ public class SimplexSolverTest extends TestCase {
|
||||||
|
|
||||||
SimplexSolver solver = new SimplexSolver();
|
SimplexSolver solver = new SimplexSolver();
|
||||||
RealPointValuePair solution = solver.optimize(f, constraints, GoalType.MAXIMIZE, false);
|
RealPointValuePair solution = solver.optimize(f, constraints, GoalType.MAXIMIZE, false);
|
||||||
assertEquals(2.0, solution.getPoint()[0]);
|
assertEquals(2.0, solution.getPoint()[0], 0.0);
|
||||||
assertEquals(2.0, solution.getPoint()[1]);
|
assertEquals(2.0, solution.getPoint()[1], 0.0);
|
||||||
assertEquals(50.0, solution.getValue());
|
assertEquals(50.0, solution.getValue(), 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void testMinimization() throws OptimizationException {
|
public void testMinimization() throws OptimizationException {
|
||||||
LinearObjectiveFunction f = new LinearObjectiveFunction(new double[] { -2, 1 }, -5);
|
LinearObjectiveFunction f = new LinearObjectiveFunction(new double[] { -2, 1 }, -5);
|
||||||
Collection<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
|
Collection<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
|
||||||
|
@ -72,11 +93,12 @@ public class SimplexSolverTest extends TestCase {
|
||||||
|
|
||||||
SimplexSolver solver = new SimplexSolver();
|
SimplexSolver solver = new SimplexSolver();
|
||||||
RealPointValuePair solution = solver.optimize(f, constraints, GoalType.MINIMIZE, false);
|
RealPointValuePair solution = solver.optimize(f, constraints, GoalType.MINIMIZE, false);
|
||||||
assertEquals(4.0, solution.getPoint()[0]);
|
assertEquals(4.0, solution.getPoint()[0], 0.0);
|
||||||
assertEquals(0.0, solution.getPoint()[1]);
|
assertEquals(0.0, solution.getPoint()[1], 0.0);
|
||||||
assertEquals(-13.0, solution.getValue());
|
assertEquals(-13.0, solution.getValue(), 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void testSolutionWithNegativeDecisionVariable() throws OptimizationException {
|
public void testSolutionWithNegativeDecisionVariable() throws OptimizationException {
|
||||||
LinearObjectiveFunction f = new LinearObjectiveFunction(new double[] { -2, 1 }, 0);
|
LinearObjectiveFunction f = new LinearObjectiveFunction(new double[] { -2, 1 }, 0);
|
||||||
Collection<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
|
Collection<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
|
||||||
|
@ -85,44 +107,33 @@ public class SimplexSolverTest extends TestCase {
|
||||||
|
|
||||||
SimplexSolver solver = new SimplexSolver();
|
SimplexSolver solver = new SimplexSolver();
|
||||||
RealPointValuePair solution = solver.optimize(f, constraints, GoalType.MAXIMIZE, false);
|
RealPointValuePair solution = solver.optimize(f, constraints, GoalType.MAXIMIZE, false);
|
||||||
assertEquals(-2.0, solution.getPoint()[0]);
|
assertEquals(-2.0, solution.getPoint()[0], 0.0);
|
||||||
assertEquals(8.0, solution.getPoint()[1]);
|
assertEquals(8.0, solution.getPoint()[1], 0.0);
|
||||||
assertEquals(12.0, solution.getValue());
|
assertEquals(12.0, solution.getValue(), 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testInfeasibleSolution() {
|
@Test(expected = NoFeasibleSolutionException.class)
|
||||||
|
public void testInfeasibleSolution() throws OptimizationException {
|
||||||
LinearObjectiveFunction f = new LinearObjectiveFunction(new double[] { 15 }, 0);
|
LinearObjectiveFunction f = new LinearObjectiveFunction(new double[] { 15 }, 0);
|
||||||
Collection<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
|
Collection<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
|
||||||
constraints.add(new LinearConstraint(new double[] { 1 }, Relationship.LEQ, 1));
|
constraints.add(new LinearConstraint(new double[] { 1 }, Relationship.LEQ, 1));
|
||||||
constraints.add(new LinearConstraint(new double[] { 1 }, Relationship.GEQ, 3));
|
constraints.add(new LinearConstraint(new double[] { 1 }, Relationship.GEQ, 3));
|
||||||
|
|
||||||
SimplexSolver solver = new SimplexSolver();
|
SimplexSolver solver = new SimplexSolver();
|
||||||
try {
|
|
||||||
solver.optimize(f, constraints, GoalType.MAXIMIZE, false);
|
solver.optimize(f, constraints, GoalType.MAXIMIZE, false);
|
||||||
fail("An exception should have been thrown.");
|
|
||||||
} catch (NoFeasibleSolutionException e) {
|
|
||||||
// expected;
|
|
||||||
} catch (OptimizationException e) {
|
|
||||||
fail("wrong exception caught");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testUnboundedSolution() {
|
@Test(expected = UnboundedSolutionException.class)
|
||||||
|
public void testUnboundedSolution() throws OptimizationException {
|
||||||
LinearObjectiveFunction f = new LinearObjectiveFunction(new double[] { 15, 10 }, 0);
|
LinearObjectiveFunction f = new LinearObjectiveFunction(new double[] { 15, 10 }, 0);
|
||||||
Collection<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
|
Collection<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
|
||||||
constraints.add(new LinearConstraint(new double[] { 1, 0 }, Relationship.EQ, 2));
|
constraints.add(new LinearConstraint(new double[] { 1, 0 }, Relationship.EQ, 2));
|
||||||
|
|
||||||
SimplexSolver solver = new SimplexSolver();
|
SimplexSolver solver = new SimplexSolver();
|
||||||
try {
|
|
||||||
solver.optimize(f, constraints, GoalType.MAXIMIZE, false);
|
solver.optimize(f, constraints, GoalType.MAXIMIZE, false);
|
||||||
fail("An exception should have been thrown.");
|
|
||||||
} catch (UnboundedSolutionException e) {
|
|
||||||
// expected;
|
|
||||||
} catch (OptimizationException e) {
|
|
||||||
fail("wrong exception caught");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void testRestrictVariablesToNonNegative() throws OptimizationException {
|
public void testRestrictVariablesToNonNegative() throws OptimizationException {
|
||||||
LinearObjectiveFunction f = new LinearObjectiveFunction(new double[] { 409, 523, 70, 204, 339 }, 0);
|
LinearObjectiveFunction f = new LinearObjectiveFunction(new double[] { 409, 523, 70, 204, 339 }, 0);
|
||||||
Collection<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
|
Collection<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
|
||||||
|
@ -142,6 +153,7 @@ public class SimplexSolverTest extends TestCase {
|
||||||
assertEquals(1438556.7491409, solution.getValue(), .0000001);
|
assertEquals(1438556.7491409, solution.getValue(), .0000001);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void testEpsilon() throws OptimizationException {
|
public void testEpsilon() throws OptimizationException {
|
||||||
LinearObjectiveFunction f =
|
LinearObjectiveFunction f =
|
||||||
new LinearObjectiveFunction(new double[] { 10, 5, 1 }, 0);
|
new LinearObjectiveFunction(new double[] { 10, 5, 1 }, 0);
|
||||||
|
@ -152,12 +164,13 @@ public class SimplexSolverTest extends TestCase {
|
||||||
|
|
||||||
SimplexSolver solver = new SimplexSolver();
|
SimplexSolver solver = new SimplexSolver();
|
||||||
RealPointValuePair solution = solver.optimize(f, constraints, GoalType.MAXIMIZE, false);
|
RealPointValuePair solution = solver.optimize(f, constraints, GoalType.MAXIMIZE, false);
|
||||||
assertEquals(1.0, solution.getPoint()[0]);
|
assertEquals(1.0, solution.getPoint()[0], 0.0);
|
||||||
assertEquals(1.0, solution.getPoint()[1]);
|
assertEquals(1.0, solution.getPoint()[1], 0.0);
|
||||||
assertEquals(0.0, solution.getPoint()[2]);
|
assertEquals(0.0, solution.getPoint()[2], 0.0);
|
||||||
assertEquals(15.0, solution.getValue());
|
assertEquals(15.0, solution.getValue(), 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void testTrivialModel() throws OptimizationException {
|
public void testTrivialModel() throws OptimizationException {
|
||||||
LinearObjectiveFunction f = new LinearObjectiveFunction(new double[] { 1, 1 }, 0);
|
LinearObjectiveFunction f = new LinearObjectiveFunction(new double[] { 1, 1 }, 0);
|
||||||
Collection<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
|
Collection<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
|
||||||
|
@ -168,6 +181,7 @@ public class SimplexSolverTest extends TestCase {
|
||||||
assertEquals(0, solution.getValue(), .0000001);
|
assertEquals(0, solution.getValue(), .0000001);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void testLargeModel() throws OptimizationException {
|
public void testLargeModel() throws OptimizationException {
|
||||||
double[] objective = new double[] {
|
double[] objective = new double[] {
|
||||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
|
Loading…
Reference in New Issue