View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      https://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  /*
19   * This is not the original file distributed by the Apache Software Foundation
20   * It has been modified by the Hipparchus project
21   */
22  package org.hipparchus.optim.linear;
23  
24  import java.util.ArrayList;
25  import java.util.Collection;
26  import java.util.List;
27  
28  import org.hipparchus.exception.MathIllegalArgumentException;
29  import org.hipparchus.exception.MathIllegalStateException;
30  import org.hipparchus.optim.MaxIter;
31  import org.hipparchus.optim.PointValuePair;
32  import org.hipparchus.optim.nonlinear.scalar.GoalType;
33  import org.hipparchus.util.Precision;
34  import org.junit.Assert;
35  import org.junit.Test;
36  
37  public class SimplexSolverTest {
38      private static final MaxIter DEFAULT_MAX_ITER = new MaxIter(100);
39  
40      @Test
41      public void testMath842Cycle() {
42          // from http://www.math.toronto.edu/mpugh/Teaching/APM236_04/bland
43          //      maximize 10 x1 - 57 x2 - 9 x3 - 24 x4
44          //      subject to
45          //          1/2 x1 - 11/2 x2 - 5/2 x3 + 9 x4  <= 0
46          //          1/2 x1 -  3/2 x2 - 1/2 x3 +   x4  <= 0
47          //              x1                  <= 1
48          //      x1,x2,x3,x4 >= 0
49  
50          LinearObjectiveFunction f = new LinearObjectiveFunction(new double[] { 10, -57, -9, -24}, 0);
51  
52          ArrayList<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
53  
54          constraints.add(new LinearConstraint(new double[] {0.5, -5.5, -2.5, 9}, Relationship.LEQ, 0));
55          constraints.add(new LinearConstraint(new double[] {0.5, -1.5, -0.5, 1}, Relationship.LEQ, 0));
56          constraints.add(new LinearConstraint(new double[] {  1,    0,    0, 0}, Relationship.LEQ, 1));
57  
58          double epsilon = 1e-6;
59          SimplexSolver solver = new SimplexSolver();
60          PointValuePair solution = solver.optimize(f, new LinearConstraintSet(constraints),
61                                                    GoalType.MAXIMIZE,
62                                                    new NonNegativeConstraint(true),
63                                                    PivotSelectionRule.BLAND);
64          Assert.assertEquals(1.0d, solution.getValue(), epsilon);
65          Assert.assertTrue(validSolution(solution, constraints, epsilon));
66      }
67  
68      @Test
69      public void testMath828() {
70          LinearObjectiveFunction f = new LinearObjectiveFunction(
71                  new double[] { 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, 0.0);
72  
73          ArrayList <LinearConstraint>constraints = new ArrayList<LinearConstraint>();
74  
75          constraints.add(new LinearConstraint(new double[] {0.0, 39.0, 23.0, 96.0, 15.0, 48.0, 9.0, 21.0, 48.0, 36.0, 76.0, 19.0, 88.0, 17.0, 16.0, 36.0,}, Relationship.GEQ, 15.0));
76          constraints.add(new LinearConstraint(new double[] {0.0, 59.0, 93.0, 12.0, 29.0, 78.0, 73.0, 87.0, 32.0, 70.0, 68.0, 24.0, 11.0, 26.0, 65.0, 25.0,}, Relationship.GEQ, 29.0));
77          constraints.add(new LinearConstraint(new double[] {0.0, 74.0, 5.0, 82.0, 6.0, 97.0, 55.0, 44.0, 52.0, 54.0, 5.0, 93.0, 91.0, 8.0, 20.0, 97.0,}, Relationship.GEQ, 6.0));
78          constraints.add(new LinearConstraint(new double[] {8.0, -3.0, -28.0, -72.0, -8.0, -31.0, -31.0, -74.0, -47.0, -59.0, -24.0, -57.0, -56.0, -16.0, -92.0, -59.0,}, Relationship.GEQ, 0.0));
79          constraints.add(new LinearConstraint(new double[] {25.0, -7.0, -99.0, -78.0, -25.0, -14.0, -16.0, -89.0, -39.0, -56.0, -53.0, -9.0, -18.0, -26.0, -11.0, -61.0,}, Relationship.GEQ, 0.0));
80          constraints.add(new LinearConstraint(new double[] {33.0, -95.0, -15.0, -4.0, -33.0, -3.0, -20.0, -96.0, -27.0, -13.0, -80.0, -24.0, -3.0, -13.0, -57.0, -76.0,}, Relationship.GEQ, 0.0));
81          constraints.add(new LinearConstraint(new double[] {7.0, -95.0, -39.0, -93.0, -7.0, -94.0, -94.0, -62.0, -76.0, -26.0, -53.0, -57.0, -31.0, -76.0, -53.0, -52.0,}, Relationship.GEQ, 0.0));
82  
83          double epsilon = 1e-6;
84          PointValuePair solution = new SimplexSolver().optimize(DEFAULT_MAX_ITER, f, new LinearConstraintSet(constraints),
85                                                                 GoalType.MINIMIZE, new NonNegativeConstraint(true));
86          Assert.assertEquals(1.0d, solution.getValue(), epsilon);
87          Assert.assertTrue(validSolution(solution, constraints, epsilon));
88      }
89  
90      @Test
91      public void testMath828Cycle() {
92          LinearObjectiveFunction f = new LinearObjectiveFunction(
93                  new double[] { 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, 0.0);
94  
95          ArrayList <LinearConstraint>constraints = new ArrayList<LinearConstraint>();
96  
97          constraints.add(new LinearConstraint(new double[] {0.0, 16.0, 14.0, 69.0, 1.0, 85.0, 52.0, 43.0, 64.0, 97.0, 14.0, 74.0, 89.0, 28.0, 94.0, 58.0, 13.0, 22.0, 21.0, 17.0, 30.0, 25.0, 1.0, 59.0, 91.0, 78.0, 12.0, 74.0, 56.0, 3.0, 88.0,}, Relationship.GEQ, 91.0));
98          constraints.add(new LinearConstraint(new double[] {0.0, 60.0, 40.0, 81.0, 71.0, 72.0, 46.0, 45.0, 38.0, 48.0, 40.0, 17.0, 33.0, 85.0, 64.0, 32.0, 84.0, 3.0, 54.0, 44.0, 71.0, 67.0, 90.0, 95.0, 54.0, 99.0, 99.0, 29.0, 52.0, 98.0, 9.0,}, Relationship.GEQ, 54.0));
99          constraints.add(new LinearConstraint(new double[] {0.0, 41.0, 12.0, 86.0, 90.0, 61.0, 31.0, 41.0, 23.0, 89.0, 17.0, 74.0, 44.0, 27.0, 16.0, 47.0, 80.0, 32.0, 11.0, 56.0, 68.0, 82.0, 11.0, 62.0, 62.0, 53.0, 39.0, 16.0, 48.0, 1.0, 63.0,}, Relationship.GEQ, 62.0));
100         constraints.add(new LinearConstraint(new double[] {83.0, -76.0, -94.0, -19.0, -15.0, -70.0, -72.0, -57.0, -63.0, -65.0, -22.0, -94.0, -22.0, -88.0, -86.0, -89.0, -72.0, -16.0, -80.0, -49.0, -70.0, -93.0, -95.0, -17.0, -83.0, -97.0, -31.0, -47.0, -31.0, -13.0, -23.0,}, Relationship.GEQ, 0.0));
101         constraints.add(new LinearConstraint(new double[] {41.0, -96.0, -41.0, -48.0, -70.0, -43.0, -43.0, -43.0, -97.0, -37.0, -85.0, -70.0, -45.0, -67.0, -87.0, -69.0, -94.0, -54.0, -54.0, -92.0, -79.0, -10.0, -35.0, -20.0, -41.0, -41.0, -65.0, -25.0, -12.0, -8.0, -46.0,}, Relationship.GEQ, 0.0));
102         constraints.add(new LinearConstraint(new double[] {27.0, -42.0, -65.0, -49.0, -53.0, -42.0, -17.0, -2.0, -61.0, -31.0, -76.0, -47.0, -8.0, -93.0, -86.0, -62.0, -65.0, -63.0, -22.0, -43.0, -27.0, -23.0, -32.0, -74.0, -27.0, -63.0, -47.0, -78.0, -29.0, -95.0, -73.0,}, Relationship.GEQ, 0.0));
103         constraints.add(new LinearConstraint(new double[] {15.0, -46.0, -41.0, -83.0, -98.0, -99.0, -21.0, -35.0, -7.0, -14.0, -80.0, -63.0, -18.0, -42.0, -5.0, -34.0, -56.0, -70.0, -16.0, -18.0, -74.0, -61.0, -47.0, -41.0, -15.0, -79.0, -18.0, -47.0, -88.0, -68.0, -55.0,}, Relationship.GEQ, 0.0));
104 
105         double epsilon = 1e-6;
106         PointValuePair solution = new SimplexSolver().optimize(DEFAULT_MAX_ITER, f,
107                                                                new LinearConstraintSet(constraints),
108                                                                GoalType.MINIMIZE, new NonNegativeConstraint(true),
109                                                                PivotSelectionRule.BLAND);
110         Assert.assertEquals(1.0d, solution.getValue(), epsilon);
111         Assert.assertTrue(validSolution(solution, constraints, epsilon));
112     }
113 
114     @Test
115     public void testMath781() {
116         LinearObjectiveFunction f = new LinearObjectiveFunction(new double[] { 2, 6, 7 }, 0);
117 
118         ArrayList<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
119         constraints.add(new LinearConstraint(new double[] { 1, 2, 1 }, Relationship.LEQ, 2));
120         constraints.add(new LinearConstraint(new double[] { -1, 1, 1 }, Relationship.LEQ, -1));
121         constraints.add(new LinearConstraint(new double[] { 2, -3, 1 }, Relationship.LEQ, -1));
122 
123         double epsilon = 1e-6;
124         SimplexSolver solver = new SimplexSolver();
125         PointValuePair solution = solver.optimize(DEFAULT_MAX_ITER, f, new LinearConstraintSet(constraints),
126                                                   GoalType.MAXIMIZE, new NonNegativeConstraint(false));
127 
128         Assert.assertTrue(Precision.compareTo(solution.getPoint()[0], 0.0d, epsilon) > 0);
129         Assert.assertTrue(Precision.compareTo(solution.getPoint()[1], 0.0d, epsilon) > 0);
130         Assert.assertTrue(Precision.compareTo(solution.getPoint()[2], 0.0d, epsilon) < 0);
131         Assert.assertEquals(2.0d, solution.getValue(), epsilon);
132     }
133 
134     @Test
135     public void testMath713NegativeVariable() {
136         LinearObjectiveFunction f = new LinearObjectiveFunction(new double[] {1.0, 1.0}, 0.0d);
137         ArrayList<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
138         constraints.add(new LinearConstraint(new double[] {1, 0}, Relationship.EQ, 1));
139 
140         double epsilon = 1e-6;
141         SimplexSolver solver = new SimplexSolver();
142         PointValuePair solution = solver.optimize(DEFAULT_MAX_ITER, f, new LinearConstraintSet(constraints),
143                                                   GoalType.MINIMIZE, new NonNegativeConstraint(true));
144 
145         Assert.assertTrue(Precision.compareTo(solution.getPoint()[0], 0.0d, epsilon) >= 0);
146         Assert.assertTrue(Precision.compareTo(solution.getPoint()[1], 0.0d, epsilon) >= 0);
147     }
148 
149     @Test
150     public void testMath434NegativeVariable() {
151         LinearObjectiveFunction f = new LinearObjectiveFunction(new double[] {0.0, 0.0, 1.0}, 0.0d);
152         ArrayList<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
153         constraints.add(new LinearConstraint(new double[] {1, 1, 0}, Relationship.EQ, 5));
154         constraints.add(new LinearConstraint(new double[] {0, 0, 1}, Relationship.GEQ, -10));
155 
156         double epsilon = 1e-6;
157         SimplexSolver solver = new SimplexSolver();
158         PointValuePair solution = solver.optimize(DEFAULT_MAX_ITER, f, new LinearConstraintSet(constraints),
159                                                   GoalType.MINIMIZE, new NonNegativeConstraint(false));
160 
161         Assert.assertEquals(5.0, solution.getPoint()[0] + solution.getPoint()[1], epsilon);
162         Assert.assertEquals(-10.0, solution.getPoint()[2], epsilon);
163         Assert.assertEquals(-10.0, solution.getValue(), epsilon);
164 
165     }
166 
167     @Test(expected = MathIllegalStateException.class)
168     public void testMath434UnfeasibleSolution() {
169         double epsilon = 1e-6;
170 
171         LinearObjectiveFunction f = new LinearObjectiveFunction(new double[] {1.0, 0.0}, 0.0);
172         ArrayList<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
173         constraints.add(new LinearConstraint(new double[] {epsilon/2, 0.5}, Relationship.EQ, 0));
174         constraints.add(new LinearConstraint(new double[] {1e-3, 0.1}, Relationship.EQ, 10));
175 
176         SimplexSolver solver = new SimplexSolver();
177         // allowing only non-negative values, no feasible solution shall be found
178         solver.optimize(DEFAULT_MAX_ITER, f, new LinearConstraintSet(constraints),
179                         GoalType.MINIMIZE, new NonNegativeConstraint(true));
180     }
181 
182     @Test
183     public void testMath434PivotRowSelection() {
184         LinearObjectiveFunction f = new LinearObjectiveFunction(new double[] {1.0}, 0.0);
185 
186         double epsilon = 1e-6;
187         ArrayList<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
188         constraints.add(new LinearConstraint(new double[] {200}, Relationship.GEQ, 1));
189         constraints.add(new LinearConstraint(new double[] {100}, Relationship.GEQ, 0.499900001));
190 
191         SimplexSolver solver = new SimplexSolver();
192         PointValuePair solution = solver.optimize(DEFAULT_MAX_ITER, f, new LinearConstraintSet(constraints),
193                                                   GoalType.MINIMIZE, new NonNegativeConstraint(false));
194 
195         Assert.assertTrue(Precision.compareTo(solution.getPoint()[0] * 200.d, 1.d, epsilon) >= 0);
196         Assert.assertEquals(0.0050, solution.getValue(), epsilon);
197     }
198 
199     @Test
200     public void testMath434PivotRowSelection2() {
201         LinearObjectiveFunction f = new LinearObjectiveFunction(new double[] {0.0d, 1.0d, 1.0d, 0.0d, 0.0d, 0.0d, 0.0d}, 0.0d);
202 
203         ArrayList<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
204         constraints.add(new LinearConstraint(new double[] {1.0d, -0.1d, 0.0d, 0.0d, 0.0d, 0.0d, 0.0d}, Relationship.EQ, -0.1d));
205         constraints.add(new LinearConstraint(new double[] {1.0d, 0.0d, 0.0d, 0.0d, 0.0d, 0.0d, 0.0d}, Relationship.GEQ, -1e-18d));
206         constraints.add(new LinearConstraint(new double[] {0.0d, 1.0d, 0.0d, 0.0d, 0.0d, 0.0d, 0.0d}, Relationship.GEQ, 0.0d));
207         constraints.add(new LinearConstraint(new double[] {0.0d, 0.0d, 0.0d, 1.0d, 0.0d, -0.0128588d, 1e-5d}, Relationship.EQ, 0.0d));
208         constraints.add(new LinearConstraint(new double[] {0.0d, 0.0d, 0.0d, 0.0d, 1.0d, 1e-5d, -0.0128586d}, Relationship.EQ, 1e-10d));
209         constraints.add(new LinearConstraint(new double[] {0.0d, 0.0d, 1.0d, -1.0d, 0.0d, 0.0d, 0.0d}, Relationship.GEQ, 0.0d));
210         constraints.add(new LinearConstraint(new double[] {0.0d, 0.0d, 1.0d, 1.0d, 0.0d, 0.0d, 0.0d}, Relationship.GEQ, 0.0d));
211         constraints.add(new LinearConstraint(new double[] {0.0d, 0.0d, 1.0d, 0.0d, -1.0d, 0.0d, 0.0d}, Relationship.GEQ, 0.0d));
212         constraints.add(new LinearConstraint(new double[] {0.0d, 0.0d, 1.0d, 0.0d, 1.0d, 0.0d, 0.0d}, Relationship.GEQ, 0.0d));
213 
214         double epsilon = 1e-7;
215         SimplexSolver simplex = new SimplexSolver();
216         PointValuePair solution = simplex.optimize(DEFAULT_MAX_ITER, f, new LinearConstraintSet(constraints),
217                                                    GoalType.MINIMIZE, new NonNegativeConstraint(false));
218 
219         Assert.assertTrue(Precision.compareTo(solution.getPoint()[0], -1e-18d, epsilon) >= 0);
220         Assert.assertEquals(1.0d, solution.getPoint()[1], epsilon);
221         Assert.assertEquals(0.0d, solution.getPoint()[2], epsilon);
222         Assert.assertEquals(1.0d, solution.getValue(), epsilon);
223     }
224 
225     @Test
226     public void testMath272() {
227         LinearObjectiveFunction f = new LinearObjectiveFunction(new double[] { 2, 2, 1 }, 0);
228         Collection<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
229         constraints.add(new LinearConstraint(new double[] { 1, 1, 0 }, Relationship.GEQ,  1));
230         constraints.add(new LinearConstraint(new double[] { 1, 0, 1 }, Relationship.GEQ,  1));
231         constraints.add(new LinearConstraint(new double[] { 0, 1, 0 }, Relationship.GEQ,  1));
232 
233         SimplexSolver solver = new SimplexSolver();
234         PointValuePair solution = solver.optimize(DEFAULT_MAX_ITER, f, new LinearConstraintSet(constraints),
235                                                   GoalType.MINIMIZE, new NonNegativeConstraint(true));
236 
237         Assert.assertEquals(0.0, solution.getPoint()[0], .0000001);
238         Assert.assertEquals(1.0, solution.getPoint()[1], .0000001);
239         Assert.assertEquals(1.0, solution.getPoint()[2], .0000001);
240         Assert.assertEquals(3.0, solution.getValue(), .0000001);
241     }
242 
243     @Test
244     public void testMath286() {
245         LinearObjectiveFunction f = new LinearObjectiveFunction(new double[] { 0.8, 0.2, 0.7, 0.3, 0.6, 0.4 }, 0 );
246         Collection<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
247         constraints.add(new LinearConstraint(new double[] { 1, 0, 1, 0, 1, 0 }, Relationship.EQ, 23.0));
248         constraints.add(new LinearConstraint(new double[] { 0, 1, 0, 1, 0, 1 }, Relationship.EQ, 23.0));
249         constraints.add(new LinearConstraint(new double[] { 1, 0, 0, 0, 0, 0 }, Relationship.GEQ, 10.0));
250         constraints.add(new LinearConstraint(new double[] { 0, 0, 1, 0, 0, 0 }, Relationship.GEQ, 8.0));
251         constraints.add(new LinearConstraint(new double[] { 0, 0, 0, 0, 1, 0 }, Relationship.GEQ, 5.0));
252 
253         SimplexSolver solver = new SimplexSolver();
254         PointValuePair solution = solver.optimize(DEFAULT_MAX_ITER, f, new LinearConstraintSet(constraints),
255                                                   GoalType.MAXIMIZE, new NonNegativeConstraint(true));
256 
257         Assert.assertEquals(25.8, solution.getValue(), .0000001);
258         Assert.assertEquals(23.0, solution.getPoint()[0] + solution.getPoint()[2] + solution.getPoint()[4], 0.0000001);
259         Assert.assertEquals(23.0, solution.getPoint()[1] + solution.getPoint()[3] + solution.getPoint()[5], 0.0000001);
260         Assert.assertTrue(solution.getPoint()[0] >= 10.0 - 0.0000001);
261         Assert.assertTrue(solution.getPoint()[2] >= 8.0 - 0.0000001);
262         Assert.assertTrue(solution.getPoint()[4] >= 5.0 - 0.0000001);
263     }
264 
265     @Test
266     public void testDegeneracy() {
267         LinearObjectiveFunction f = new LinearObjectiveFunction(new double[] { 0.8, 0.7 }, 0 );
268         Collection<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
269         constraints.add(new LinearConstraint(new double[] { 1, 1 }, Relationship.LEQ, 18.0));
270         constraints.add(new LinearConstraint(new double[] { 1, 0 }, Relationship.GEQ, 10.0));
271         constraints.add(new LinearConstraint(new double[] { 0, 1 }, Relationship.GEQ, 8.0));
272 
273         SimplexSolver solver = new SimplexSolver();
274         PointValuePair solution = solver.optimize(DEFAULT_MAX_ITER, f, new LinearConstraintSet(constraints),
275                                                   GoalType.MINIMIZE, new NonNegativeConstraint(true));
276         Assert.assertEquals(13.6, solution.getValue(), .0000001);
277     }
278 
279     @Test
280     public void testMath288() {
281         LinearObjectiveFunction f = new LinearObjectiveFunction(new double[] { 7, 3, 0, 0 }, 0 );
282         Collection<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
283         constraints.add(new LinearConstraint(new double[] { 3, 0, -5, 0 }, Relationship.LEQ, 0.0));
284         constraints.add(new LinearConstraint(new double[] { 2, 0, 0, -5 }, Relationship.LEQ, 0.0));
285         constraints.add(new LinearConstraint(new double[] { 0, 3, 0, -5 }, Relationship.LEQ, 0.0));
286         constraints.add(new LinearConstraint(new double[] { 1, 0, 0, 0 }, Relationship.LEQ, 1.0));
287         constraints.add(new LinearConstraint(new double[] { 0, 1, 0, 0 }, Relationship.LEQ, 1.0));
288 
289         SimplexSolver solver = new SimplexSolver();
290         PointValuePair solution = solver.optimize(DEFAULT_MAX_ITER, f, new LinearConstraintSet(constraints),
291                                                   GoalType.MAXIMIZE, new NonNegativeConstraint(true));
292         Assert.assertEquals(10.0, solution.getValue(), .0000001);
293     }
294 
295     @Test
296     public void testMath290GEQ() {
297         LinearObjectiveFunction f = new LinearObjectiveFunction(new double[] { 1, 5 }, 0 );
298         Collection<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
299         constraints.add(new LinearConstraint(new double[] { 2, 0 }, Relationship.GEQ, -1.0));
300         SimplexSolver solver = new SimplexSolver();
301         PointValuePair solution = solver.optimize(DEFAULT_MAX_ITER, f, new LinearConstraintSet(constraints),
302                                                   GoalType.MINIMIZE, new NonNegativeConstraint(true));
303         Assert.assertEquals(0, solution.getValue(), .0000001);
304         Assert.assertEquals(0, solution.getPoint()[0], .0000001);
305         Assert.assertEquals(0, solution.getPoint()[1], .0000001);
306     }
307 
308     @Test(expected=MathIllegalStateException.class)
309     public void testMath290LEQ() {
310         LinearObjectiveFunction f = new LinearObjectiveFunction(new double[] { 1, 5 }, 0 );
311         Collection<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
312         constraints.add(new LinearConstraint(new double[] { 2, 0 }, Relationship.LEQ, -1.0));
313         SimplexSolver solver = new SimplexSolver();
314         solver.optimize(DEFAULT_MAX_ITER, f, new LinearConstraintSet(constraints),
315                         GoalType.MINIMIZE, new NonNegativeConstraint(true));
316     }
317 
318     @Test
319     public void testMath293() {
320       LinearObjectiveFunction f = new LinearObjectiveFunction(new double[] { 0.8, 0.2, 0.7, 0.3, 0.4, 0.6}, 0 );
321       Collection<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
322       constraints.add(new LinearConstraint(new double[] { 1, 0, 1, 0, 1, 0 }, Relationship.EQ, 30.0));
323       constraints.add(new LinearConstraint(new double[] { 0, 1, 0, 1, 0, 1 }, Relationship.EQ, 30.0));
324       constraints.add(new LinearConstraint(new double[] { 0.8, 0.2, 0.0, 0.0, 0.0, 0.0 }, Relationship.GEQ, 10.0));
325       constraints.add(new LinearConstraint(new double[] { 0.0, 0.0, 0.7, 0.3, 0.0, 0.0 }, Relationship.GEQ, 10.0));
326       constraints.add(new LinearConstraint(new double[] { 0.0, 0.0, 0.0, 0.0, 0.4, 0.6 }, Relationship.GEQ, 10.0));
327 
328       SimplexSolver solver = new SimplexSolver();
329       PointValuePair solution1 = solver.optimize(DEFAULT_MAX_ITER, f, new LinearConstraintSet(constraints),
330                                                  GoalType.MAXIMIZE, new NonNegativeConstraint(true));
331 
332       Assert.assertEquals(15.7143, solution1.getPoint()[0], .0001);
333       Assert.assertEquals(0.0, solution1.getPoint()[1], .0001);
334       Assert.assertEquals(14.2857, solution1.getPoint()[2], .0001);
335       Assert.assertEquals(0.0, solution1.getPoint()[3], .0001);
336       Assert.assertEquals(0.0, solution1.getPoint()[4], .0001);
337       Assert.assertEquals(30.0, solution1.getPoint()[5], .0001);
338       Assert.assertEquals(40.57143, solution1.getValue(), .0001);
339 
340       double valA = 0.8 * solution1.getPoint()[0] + 0.2 * solution1.getPoint()[1];
341       double valB = 0.7 * solution1.getPoint()[2] + 0.3 * solution1.getPoint()[3];
342       double valC = 0.4 * solution1.getPoint()[4] + 0.6 * solution1.getPoint()[5];
343 
344       f = new LinearObjectiveFunction(new double[] { 0.8, 0.2, 0.7, 0.3, 0.4, 0.6}, 0 );
345       constraints = new ArrayList<LinearConstraint>();
346       constraints.add(new LinearConstraint(new double[] { 1, 0, 1, 0, 1, 0 }, Relationship.EQ, 30.0));
347       constraints.add(new LinearConstraint(new double[] { 0, 1, 0, 1, 0, 1 }, Relationship.EQ, 30.0));
348       constraints.add(new LinearConstraint(new double[] { 0.8, 0.2, 0.0, 0.0, 0.0, 0.0 }, Relationship.GEQ, valA));
349       constraints.add(new LinearConstraint(new double[] { 0.0, 0.0, 0.7, 0.3, 0.0, 0.0 }, Relationship.GEQ, valB));
350       constraints.add(new LinearConstraint(new double[] { 0.0, 0.0, 0.0, 0.0, 0.4, 0.6 }, Relationship.GEQ, valC));
351 
352       PointValuePair solution2 = solver.optimize(DEFAULT_MAX_ITER, f, new LinearConstraintSet(constraints),
353                                                  GoalType.MAXIMIZE, new NonNegativeConstraint(true));
354       Assert.assertEquals(40.57143, solution2.getValue(), .0001);
355     }
356 
357     @Test
358     public void testMath930() {
359         Collection<LinearConstraint> constraints = createMath930Constraints();
360 
361         double[] objFunctionCoeff = new double[33];
362         objFunctionCoeff[3] = 1;
363         LinearObjectiveFunction f = new LinearObjectiveFunction(objFunctionCoeff, 0);
364         SimplexSolver solver = new SimplexSolver(1e-4, 10, 1e-6);
365 
366         PointValuePair solution = solver.optimize(new MaxIter(1000), f, new LinearConstraintSet(constraints),
367                                                   GoalType.MINIMIZE, new NonNegativeConstraint(true));
368         Assert.assertEquals(0.3752298, solution.getValue(), 1e-4);
369     }
370 
371     private List<LinearConstraint> createMath930Constraints() {
372         List<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
373         constraints.add(new LinearConstraint(new double[] {1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, -1, 0}, Relationship.GEQ, 0.0));
374         constraints.add(new LinearConstraint(new double[] {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, Relationship.GEQ, 0.0));
375         constraints.add(new LinearConstraint(new double[] {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, Relationship.LEQ, 0.0));
376         constraints.add(new LinearConstraint(new double[] {0, 1, 0, -1, 0, -1, 0, 1, 0, -1, 0, 1, 0, 1, 0, -1, 0, -1, 0, 1, 0, 1, 0, -1, 0, 1, 0, -1, 0, -1, 0, 1, 0}, Relationship.GEQ, 0.0));
377         constraints.add(new LinearConstraint(new double[] {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.628803}, Relationship.GEQ, 0.0));
378         constraints.add(new LinearConstraint(new double[] {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.676993}, Relationship.LEQ, 0.0));
379         constraints.add(new LinearConstraint(new double[] {0, 0, 1, -1, 0, 0, -1, 1, 0, 0, -1, 1, 0, 0, 1, -1, 0, 0, -1, 1, 0, 0, 1, -1, 0, 0, 1, -1, 0, 0, -1, 1, 0}, Relationship.GEQ, 0.0));
380         constraints.add(new LinearConstraint(new double[] {0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.136677}, Relationship.GEQ, 0.0));
381         constraints.add(new LinearConstraint(new double[] {0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.444434}, Relationship.LEQ, 0.0));
382         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 1, 0, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, -1, 0}, Relationship.GEQ, 0.0));
383         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.254028}, Relationship.GEQ, 0.0));
384         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.302218}, Relationship.LEQ, 0.0));
385         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 1, -1, -1, 1, 0, 0, 0, 0, -1, 1, 1, -1, 0, 0, 0, 0, -1, 1, 1, -1, 0, 0, 0, 0, 1, -1, -1, 1, 0}, Relationship.GEQ, 0.0));
386         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.653981}, Relationship.GEQ, 0.0));
387         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.690437}, Relationship.LEQ, 0.0));
388         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 1, 0, -1, 0, 0, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 0, 1, 0, -1, 0}, Relationship.GEQ, 0.0));
389         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.423786}, Relationship.GEQ, 0.0));
390         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.486717}, Relationship.LEQ, 0.0));
391         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 1, -1, 0}, Relationship.GEQ, 0.0));
392         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.049232}, Relationship.GEQ, 0.0));
393         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.304747}, Relationship.LEQ, 0.0));
394         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 1, 0}, Relationship.GEQ, 0.0));
395         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.129826}, Relationship.GEQ, 0.0));
396         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.205625}, Relationship.LEQ, 0.0));
397         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 1, -1, -1, 1, -1, 1, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 1, -1, 1, -1, -1, 1, 0}, Relationship.GEQ, 0.0));
398         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.621944}, Relationship.GEQ, 0.0));
399         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.764385}, Relationship.LEQ, 0.0));
400         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -1, 0, -1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, 1, 0, -1, 0}, Relationship.GEQ, 0.0));
401         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.432572}, Relationship.GEQ, 0.0));
402         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.480762}, Relationship.LEQ, 0.0));
403         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0, 0, 1, -1, 0}, Relationship.GEQ, 0.0));
404         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.055983}, Relationship.GEQ, 0.0));
405         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.11378}, Relationship.LEQ, 0.0));
406         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 1, 0}, Relationship.GEQ, 0.0));
407         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.009607}, Relationship.GEQ, 0.0));
408         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.057797}, Relationship.LEQ, 0.0));
409         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 1, -1, 0}, Relationship.GEQ, 0.0));
410         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.407308}, Relationship.GEQ, 0.0));
411         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.452749}, Relationship.LEQ, 0.0));
412         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0}, Relationship.GEQ, 0.0));
413         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.269677}, Relationship.GEQ, 0.0));
414         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.321806}, Relationship.LEQ, 0.0));
415         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 1, 0}, Relationship.GEQ, 0.0));
416         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.049232}, Relationship.GEQ, 0.0));
417         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.06902}, Relationship.LEQ, 0.0));
418         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0}, Relationship.GEQ, 0.0));
419         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0}, Relationship.GEQ, 0.0));
420         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.028754}, Relationship.LEQ, 0.0));
421         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, 0}, Relationship.GEQ, 0.0));
422         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.484254}, Relationship.GEQ, 0.0));
423         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.524607}, Relationship.LEQ, 0.0));
424         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -1, 0, -1, 0, 1, 0, -1, 0, 1, 0, 1, 0, -1, 0}, Relationship.GEQ, 0.0));
425         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.385492}, Relationship.GEQ, 0.0));
426         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.430134}, Relationship.LEQ, 0.0));
427         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, -1, 1, 0, 0, -1, 1, 0, 0, 1, -1, 0}, Relationship.GEQ, 0.0));
428         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.34983}, Relationship.GEQ, 0.0));
429         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.375781}, Relationship.LEQ, 0.0));
430         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, 1, 0}, Relationship.GEQ, 0.0));
431         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.254028}, Relationship.GEQ, 0.0));
432         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.281308}, Relationship.LEQ, 0.0));
433         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, -1, 1, 0, 0, 0, 0, -1, 1, 1, -1, 0}, Relationship.GEQ, 0.0));
434         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.304995}, Relationship.GEQ, 0.0));
435         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.345347}, Relationship.LEQ, 0.0));
436         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -1, 0, 0, 0, 0, 0, -1, 0, 1, 0}, Relationship.GEQ, 0.0));
437         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.288899}, Relationship.GEQ, 0.0));
438         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.332212}, Relationship.LEQ, 0.0));
439         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 0, 0, 0, -1, 1, 0}, Relationship.GEQ, 0.0));
440         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.14351}, Relationship.GEQ, 0.0));
441         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.17057}, Relationship.LEQ, 0.0));
442         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, -1, 0}, Relationship.GEQ, 0.0));
443         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, -0.129826}, Relationship.GEQ, 0.0));
444         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, -0.157435}, Relationship.LEQ, 0.0));
445         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, -1, 1, -1, 1, 1, -1, 0}, Relationship.GEQ, 0.0));
446         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, -0}, Relationship.GEQ, 0.0));
447         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, -1}, Relationship.LEQ, 0.0));
448         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -1, 0, -1, 0, 1, 0}, Relationship.GEQ, 0.0));
449         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, -0.141071}, Relationship.GEQ, 0.0));
450         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, -0.232574}, Relationship.LEQ, 0.0));
451         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, -1, 1, 0}, Relationship.GEQ, 0.0));
452         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, -0}, Relationship.GEQ, 0.0));
453         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, -1}, Relationship.LEQ, 0.0));
454         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, -1, 0}, Relationship.GEQ, 0.0));
455         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, -0.009607}, Relationship.GEQ, 0.0));
456         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, -0.057797}, Relationship.LEQ, 0.0));
457         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, -1, 1, 0}, Relationship.GEQ, 0.0));
458         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, -0}, Relationship.GEQ, 0.0));
459         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, -1}, Relationship.LEQ, 0.0));
460         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -1, 0}, Relationship.GEQ, 0.0));
461         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, -0.091644}, Relationship.GEQ, 0.0));
462         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, -0.203531}, Relationship.LEQ, 0.0));
463         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0}, Relationship.GEQ, 0.0));
464         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -0}, Relationship.GEQ, 0.0));
465         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, -1}, Relationship.LEQ, 0.0));
466         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0}, Relationship.GEQ, 0.0));
467         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0}, Relationship.GEQ, 0.0));
468         constraints.add(new LinearConstraint(new double[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -0.028754}, Relationship.LEQ, 0.0));
469         constraints.add(new LinearConstraint(new double[] {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, Relationship.EQ, 1.0));
470         return constraints;
471     }
472 
473     @Test
474     public void testSimplexSolver() {
475         LinearObjectiveFunction f =
476             new LinearObjectiveFunction(new double[] { 15, 10 }, 7);
477         Collection<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
478         constraints.add(new LinearConstraint(new double[] { 1, 0 }, Relationship.LEQ, 2));
479         constraints.add(new LinearConstraint(new double[] { 0, 1 }, Relationship.LEQ, 3));
480         constraints.add(new LinearConstraint(new double[] { 1, 1 }, Relationship.EQ, 4));
481 
482         SimplexSolver solver = new SimplexSolver();
483         PointValuePair solution = solver.optimize(DEFAULT_MAX_ITER, f, new LinearConstraintSet(constraints),
484                                                   GoalType.MAXIMIZE, new NonNegativeConstraint(true));
485         Assert.assertEquals(2.0, solution.getPoint()[0], 0.0);
486         Assert.assertEquals(2.0, solution.getPoint()[1], 0.0);
487         Assert.assertEquals(57.0, solution.getValue(), 0.0);
488     }
489 
490     @Test
491     public void testSingleVariableAndConstraint() {
492         LinearObjectiveFunction f = new LinearObjectiveFunction(new double[] { 3 }, 0);
493         Collection<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
494         constraints.add(new LinearConstraint(new double[] { 1 }, Relationship.LEQ, 10));
495 
496         SimplexSolver solver = new SimplexSolver();
497         PointValuePair solution = solver.optimize(DEFAULT_MAX_ITER, f, new LinearConstraintSet(constraints),
498                                                   GoalType.MAXIMIZE, new NonNegativeConstraint(false));
499         Assert.assertEquals(10.0, solution.getPoint()[0], 0.0);
500         Assert.assertEquals(30.0, solution.getValue(), 0.0);
501     }
502 
503     /**
504      * With no artificial variables needed (no equals and no greater than
505      * constraints) we can go straight to Phase 2.
506      */
507     @Test
508     public void testModelWithNoArtificialVars() {
509         LinearObjectiveFunction f = new LinearObjectiveFunction(new double[] { 15, 10 }, 0);
510         Collection<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
511         constraints.add(new LinearConstraint(new double[] { 1, 0 }, Relationship.LEQ, 2));
512         constraints.add(new LinearConstraint(new double[] { 0, 1 }, Relationship.LEQ, 3));
513         constraints.add(new LinearConstraint(new double[] { 1, 1 }, Relationship.LEQ, 4));
514 
515         SimplexSolver solver = new SimplexSolver();
516         PointValuePair solution = solver.optimize(DEFAULT_MAX_ITER, f, new LinearConstraintSet(constraints),
517                                                   GoalType.MAXIMIZE, new NonNegativeConstraint(false));
518         Assert.assertEquals(2.0, solution.getPoint()[0], 0.0);
519         Assert.assertEquals(2.0, solution.getPoint()[1], 0.0);
520         Assert.assertEquals(50.0, solution.getValue(), 0.0);
521     }
522 
523     @Test
524     public void testMinimization() {
525         LinearObjectiveFunction f = new LinearObjectiveFunction(new double[] { -2, 1 }, -5);
526         Collection<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
527         constraints.add(new LinearConstraint(new double[] { 1, 2 }, Relationship.LEQ, 6));
528         constraints.add(new LinearConstraint(new double[] { 3, 2 }, Relationship.LEQ, 12));
529         constraints.add(new LinearConstraint(new double[] { 0, 1 }, Relationship.GEQ, 0));
530 
531         SimplexSolver solver = new SimplexSolver();
532         PointValuePair solution = solver.optimize(DEFAULT_MAX_ITER, f, new LinearConstraintSet(constraints),
533                                                   GoalType.MINIMIZE, new NonNegativeConstraint(false));
534         Assert.assertEquals(4.0, solution.getPoint()[0], 0.0);
535         Assert.assertEquals(0.0, solution.getPoint()[1], 0.0);
536         Assert.assertEquals(-13.0, solution.getValue(), 0.0);
537     }
538 
539     @Test
540     public void testSolutionWithNegativeDecisionVariable() {
541         LinearObjectiveFunction f = new LinearObjectiveFunction(new double[] { -2, 1 }, 0);
542         Collection<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
543         constraints.add(new LinearConstraint(new double[] { 1, 1 }, Relationship.GEQ, 6));
544         constraints.add(new LinearConstraint(new double[] { 1, 2 }, Relationship.LEQ, 14));
545 
546         SimplexSolver solver = new SimplexSolver();
547         PointValuePair solution = solver.optimize(DEFAULT_MAX_ITER, f, new LinearConstraintSet(constraints),
548                                                   GoalType.MAXIMIZE, new NonNegativeConstraint(false));
549         Assert.assertEquals(-2.0, solution.getPoint()[0], 0.0);
550         Assert.assertEquals(8.0, solution.getPoint()[1], 0.0);
551         Assert.assertEquals(12.0, solution.getValue(), 0.0);
552     }
553 
554     @Test(expected = MathIllegalStateException.class)
555     public void testInfeasibleSolution() {
556         LinearObjectiveFunction f = new LinearObjectiveFunction(new double[] { 15 }, 0);
557         Collection<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
558         constraints.add(new LinearConstraint(new double[] { 1 }, Relationship.LEQ, 1));
559         constraints.add(new LinearConstraint(new double[] { 1 }, Relationship.GEQ, 3));
560 
561         SimplexSolver solver = new SimplexSolver();
562         solver.optimize(DEFAULT_MAX_ITER, f, new LinearConstraintSet(constraints),
563                         GoalType.MAXIMIZE, new NonNegativeConstraint(false));
564     }
565 
566     @Test(expected = MathIllegalStateException.class)
567     public void testUnboundedSolution() {
568         LinearObjectiveFunction f = new LinearObjectiveFunction(new double[] { 15, 10 }, 0);
569         Collection<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
570         constraints.add(new LinearConstraint(new double[] { 1, 0 }, Relationship.EQ, 2));
571 
572         SimplexSolver solver = new SimplexSolver();
573         solver.optimize(DEFAULT_MAX_ITER, f, new LinearConstraintSet(constraints),
574                         GoalType.MAXIMIZE, new NonNegativeConstraint(false));
575     }
576 
577     @Test
578     public void testRestrictVariablesToNonNegative() {
579         LinearObjectiveFunction f = new LinearObjectiveFunction(new double[] { 409, 523, 70, 204, 339 }, 0);
580         Collection<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
581         constraints.add(new LinearConstraint(new double[] {    43,   56, 345,  56,    5 }, Relationship.LEQ,  4567456));
582         constraints.add(new LinearConstraint(new double[] {    12,   45,   7,  56,   23 }, Relationship.LEQ,    56454));
583         constraints.add(new LinearConstraint(new double[] {     8,  768,   0,  34, 7456 }, Relationship.LEQ,  1923421));
584         constraints.add(new LinearConstraint(new double[] { 12342, 2342,  34, 678, 2342 }, Relationship.GEQ,     4356));
585         constraints.add(new LinearConstraint(new double[] {    45,  678,  76,  52,   23 }, Relationship.EQ,    456356));
586 
587         SimplexSolver solver = new SimplexSolver();
588         PointValuePair solution = solver.optimize(DEFAULT_MAX_ITER, f, new LinearConstraintSet(constraints),
589                                                   GoalType.MAXIMIZE, new NonNegativeConstraint(true));
590         Assert.assertEquals(2902.92783505155, solution.getPoint()[0], .0000001);
591         Assert.assertEquals(480.419243986254, solution.getPoint()[1], .0000001);
592         Assert.assertEquals(0.0, solution.getPoint()[2], .0000001);
593         Assert.assertEquals(0.0, solution.getPoint()[3], .0000001);
594         Assert.assertEquals(0.0, solution.getPoint()[4], .0000001);
595         Assert.assertEquals(1438556.7491409, solution.getValue(), .0000001);
596     }
597 
598     @Test
599     public void testEpsilon() {
600       LinearObjectiveFunction f =
601           new LinearObjectiveFunction(new double[] { 10, 5, 1 }, 0);
602       Collection<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
603       constraints.add(new LinearConstraint(new double[] {  9, 8, 0 }, Relationship.EQ,  17));
604       constraints.add(new LinearConstraint(new double[] {  0, 7, 8 }, Relationship.LEQ,  7));
605       constraints.add(new LinearConstraint(new double[] { 10, 0, 2 }, Relationship.LEQ, 10));
606 
607       SimplexSolver solver = new SimplexSolver();
608       PointValuePair solution = solver.optimize(DEFAULT_MAX_ITER, f, new LinearConstraintSet(constraints),
609                                                 GoalType.MAXIMIZE, new NonNegativeConstraint(false));
610       Assert.assertEquals(1.0, solution.getPoint()[0], 0.0);
611       Assert.assertEquals(1.0, solution.getPoint()[1], 0.0);
612       Assert.assertEquals(0.0, solution.getPoint()[2], 0.0);
613       Assert.assertEquals(15.0, solution.getValue(), 0.0);
614   }
615 
616     @Test
617     public void testTrivialModel() {
618         LinearObjectiveFunction f = new LinearObjectiveFunction(new double[] { 1, 1 }, 0);
619         Collection<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
620         constraints.add(new LinearConstraint(new double[] { 1, 1 }, Relationship.EQ,  0));
621 
622         SimplexSolver solver = new SimplexSolver();
623         PointValuePair solution = solver.optimize(DEFAULT_MAX_ITER, f, new LinearConstraintSet(constraints),
624                                                   GoalType.MAXIMIZE, new NonNegativeConstraint(true));
625         Assert.assertEquals(0, solution.getValue(), .0000001);
626     }
627 
628     @Test
629     public void testLargeModel() {
630         double[] objective = new double[] {
631                                            1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
632                                            1, 1, 12, 1, 1, 1, 1, 1, 1, 1,
633                                            1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
634                                            1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
635                                            12, 1, 1, 1, 1, 1, 1, 1, 1, 1,
636                                            1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
637                                            1, 1, 1, 1, 1, 1, 1, 1, 12, 1,
638                                            1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
639                                            1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
640                                            1, 1, 1, 1, 1, 1, 12, 1, 1, 1,
641                                            1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
642                                            1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
643                                            1, 1, 1, 1, 12, 1, 1, 1, 1, 1,
644                                            1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
645                                            1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
646                                            1, 1, 12, 1, 1, 1, 1, 1, 1, 1,
647                                            1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
648                                            1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
649                                            1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
650                                            1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
651                                            1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
652                                            1, 1, 1, 1, 1, 1};
653 
654         LinearObjectiveFunction f = new LinearObjectiveFunction(objective, 0);
655         Collection<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
656         constraints.add(equationFromString(objective.length, "x0 + x1 + x2 + x3 - x12 = 0"));
657         constraints.add(equationFromString(objective.length, "x4 + x5 + x6 + x7 + x8 + x9 + x10 + x11 - x13 = 0"));
658         constraints.add(equationFromString(objective.length, "x4 + x5 + x6 + x7 + x8 + x9 + x10 + x11 >= 49"));
659         constraints.add(equationFromString(objective.length, "x0 + x1 + x2 + x3 >= 42"));
660         constraints.add(equationFromString(objective.length, "x14 + x15 + x16 + x17 - x26 = 0"));
661         constraints.add(equationFromString(objective.length, "x18 + x19 + x20 + x21 + x22 + x23 + x24 + x25 - x27 = 0"));
662         constraints.add(equationFromString(objective.length, "x14 + x15 + x16 + x17 - x12 = 0"));
663         constraints.add(equationFromString(objective.length, "x18 + x19 + x20 + x21 + x22 + x23 + x24 + x25 - x13 = 0"));
664         constraints.add(equationFromString(objective.length, "x28 + x29 + x30 + x31 - x40 = 0"));
665         constraints.add(equationFromString(objective.length, "x32 + x33 + x34 + x35 + x36 + x37 + x38 + x39 - x41 = 0"));
666         constraints.add(equationFromString(objective.length, "x32 + x33 + x34 + x35 + x36 + x37 + x38 + x39 >= 49"));
667         constraints.add(equationFromString(objective.length, "x28 + x29 + x30 + x31 >= 42"));
668         constraints.add(equationFromString(objective.length, "x42 + x43 + x44 + x45 - x54 = 0"));
669         constraints.add(equationFromString(objective.length, "x46 + x47 + x48 + x49 + x50 + x51 + x52 + x53 - x55 = 0"));
670         constraints.add(equationFromString(objective.length, "x42 + x43 + x44 + x45 - x40 = 0"));
671         constraints.add(equationFromString(objective.length, "x46 + x47 + x48 + x49 + x50 + x51 + x52 + x53 - x41 = 0"));
672         constraints.add(equationFromString(objective.length, "x56 + x57 + x58 + x59 - x68 = 0"));
673         constraints.add(equationFromString(objective.length, "x60 + x61 + x62 + x63 + x64 + x65 + x66 + x67 - x69 = 0"));
674         constraints.add(equationFromString(objective.length, "x60 + x61 + x62 + x63 + x64 + x65 + x66 + x67 >= 51"));
675         constraints.add(equationFromString(objective.length, "x56 + x57 + x58 + x59 >= 44"));
676         constraints.add(equationFromString(objective.length, "x70 + x71 + x72 + x73 - x82 = 0"));
677         constraints.add(equationFromString(objective.length, "x74 + x75 + x76 + x77 + x78 + x79 + x80 + x81 - x83 = 0"));
678         constraints.add(equationFromString(objective.length, "x70 + x71 + x72 + x73 - x68 = 0"));
679         constraints.add(equationFromString(objective.length, "x74 + x75 + x76 + x77 + x78 + x79 + x80 + x81 - x69 = 0"));
680         constraints.add(equationFromString(objective.length, "x84 + x85 + x86 + x87 - x96 = 0"));
681         constraints.add(equationFromString(objective.length, "x88 + x89 + x90 + x91 + x92 + x93 + x94 + x95 - x97 = 0"));
682         constraints.add(equationFromString(objective.length, "x88 + x89 + x90 + x91 + x92 + x93 + x94 + x95 >= 51"));
683         constraints.add(equationFromString(objective.length, "x84 + x85 + x86 + x87 >= 44"));
684         constraints.add(equationFromString(objective.length, "x98 + x99 + x100 + x101 - x110 = 0"));
685         constraints.add(equationFromString(objective.length, "x102 + x103 + x104 + x105 + x106 + x107 + x108 + x109 - x111 = 0"));
686         constraints.add(equationFromString(objective.length, "x98 + x99 + x100 + x101 - x96 = 0"));
687         constraints.add(equationFromString(objective.length, "x102 + x103 + x104 + x105 + x106 + x107 + x108 + x109 - x97 = 0"));
688         constraints.add(equationFromString(objective.length, "x112 + x113 + x114 + x115 - x124 = 0"));
689         constraints.add(equationFromString(objective.length, "x116 + x117 + x118 + x119 + x120 + x121 + x122 + x123 - x125 = 0"));
690         constraints.add(equationFromString(objective.length, "x116 + x117 + x118 + x119 + x120 + x121 + x122 + x123 >= 49"));
691         constraints.add(equationFromString(objective.length, "x112 + x113 + x114 + x115 >= 42"));
692         constraints.add(equationFromString(objective.length, "x126 + x127 + x128 + x129 - x138 = 0"));
693         constraints.add(equationFromString(objective.length, "x130 + x131 + x132 + x133 + x134 + x135 + x136 + x137 - x139 = 0"));
694         constraints.add(equationFromString(objective.length, "x126 + x127 + x128 + x129 - x124 = 0"));
695         constraints.add(equationFromString(objective.length, "x130 + x131 + x132 + x133 + x134 + x135 + x136 + x137 - x125 = 0"));
696         constraints.add(equationFromString(objective.length, "x140 + x141 + x142 + x143 - x152 = 0"));
697         constraints.add(equationFromString(objective.length, "x144 + x145 + x146 + x147 + x148 + x149 + x150 + x151 - x153 = 0"));
698         constraints.add(equationFromString(objective.length, "x144 + x145 + x146 + x147 + x148 + x149 + x150 + x151 >= 59"));
699         constraints.add(equationFromString(objective.length, "x140 + x141 + x142 + x143 >= 42"));
700         constraints.add(equationFromString(objective.length, "x154 + x155 + x156 + x157 - x166 = 0"));
701         constraints.add(equationFromString(objective.length, "x158 + x159 + x160 + x161 + x162 + x163 + x164 + x165 - x167 = 0"));
702         constraints.add(equationFromString(objective.length, "x154 + x155 + x156 + x157 - x152 = 0"));
703         constraints.add(equationFromString(objective.length, "x158 + x159 + x160 + x161 + x162 + x163 + x164 + x165 - x153 = 0"));
704         constraints.add(equationFromString(objective.length, "x83 + x82 - x168 = 0"));
705         constraints.add(equationFromString(objective.length, "x111 + x110 - x169 = 0"));
706         constraints.add(equationFromString(objective.length, "x170 - x182 = 0"));
707         constraints.add(equationFromString(objective.length, "x171 - x183 = 0"));
708         constraints.add(equationFromString(objective.length, "x172 - x184 = 0"));
709         constraints.add(equationFromString(objective.length, "x173 - x185 = 0"));
710         constraints.add(equationFromString(objective.length, "x174 - x186 = 0"));
711         constraints.add(equationFromString(objective.length, "x175 + x176 - x187 = 0"));
712         constraints.add(equationFromString(objective.length, "x177 - x188 = 0"));
713         constraints.add(equationFromString(objective.length, "x178 - x189 = 0"));
714         constraints.add(equationFromString(objective.length, "x179 - x190 = 0"));
715         constraints.add(equationFromString(objective.length, "x180 - x191 = 0"));
716         constraints.add(equationFromString(objective.length, "x181 - x192 = 0"));
717         constraints.add(equationFromString(objective.length, "x170 - x26 = 0"));
718         constraints.add(equationFromString(objective.length, "x171 - x27 = 0"));
719         constraints.add(equationFromString(objective.length, "x172 - x54 = 0"));
720         constraints.add(equationFromString(objective.length, "x173 - x55 = 0"));
721         constraints.add(equationFromString(objective.length, "x174 - x168 = 0"));
722         constraints.add(equationFromString(objective.length, "x177 - x169 = 0"));
723         constraints.add(equationFromString(objective.length, "x178 - x138 = 0"));
724         constraints.add(equationFromString(objective.length, "x179 - x139 = 0"));
725         constraints.add(equationFromString(objective.length, "x180 - x166 = 0"));
726         constraints.add(equationFromString(objective.length, "x181 - x167 = 0"));
727         constraints.add(equationFromString(objective.length, "x193 - x205 = 0"));
728         constraints.add(equationFromString(objective.length, "x194 - x206 = 0"));
729         constraints.add(equationFromString(objective.length, "x195 - x207 = 0"));
730         constraints.add(equationFromString(objective.length, "x196 - x208 = 0"));
731         constraints.add(equationFromString(objective.length, "x197 - x209 = 0"));
732         constraints.add(equationFromString(objective.length, "x198 + x199 - x210 = 0"));
733         constraints.add(equationFromString(objective.length, "x200 - x211 = 0"));
734         constraints.add(equationFromString(objective.length, "x201 - x212 = 0"));
735         constraints.add(equationFromString(objective.length, "x202 - x213 = 0"));
736         constraints.add(equationFromString(objective.length, "x203 - x214 = 0"));
737         constraints.add(equationFromString(objective.length, "x204 - x215 = 0"));
738         constraints.add(equationFromString(objective.length, "x193 - x182 = 0"));
739         constraints.add(equationFromString(objective.length, "x194 - x183 = 0"));
740         constraints.add(equationFromString(objective.length, "x195 - x184 = 0"));
741         constraints.add(equationFromString(objective.length, "x196 - x185 = 0"));
742         constraints.add(equationFromString(objective.length, "x197 - x186 = 0"));
743         constraints.add(equationFromString(objective.length, "x198 + x199 - x187 = 0"));
744         constraints.add(equationFromString(objective.length, "x200 - x188 = 0"));
745         constraints.add(equationFromString(objective.length, "x201 - x189 = 0"));
746         constraints.add(equationFromString(objective.length, "x202 - x190 = 0"));
747         constraints.add(equationFromString(objective.length, "x203 - x191 = 0"));
748         constraints.add(equationFromString(objective.length, "x204 - x192 = 0"));
749 
750         SimplexSolver solver = new SimplexSolver();
751         PointValuePair solution = solver.optimize(DEFAULT_MAX_ITER, f, new LinearConstraintSet(constraints),
752                                                   GoalType.MINIMIZE, new NonNegativeConstraint(true));
753         Assert.assertEquals(7518.0, solution.getValue(), .0000001);
754     }
755 
756     @Test
757     public void testSolutionCallback() {
758         // re-use the problem from testcase for MATH-288
759         // it normally requires 5 iterations
760 
761         LinearObjectiveFunction f = new LinearObjectiveFunction(new double[] { 7, 3, 0, 0 }, 0 );
762 
763         List<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
764         constraints.add(new LinearConstraint(new double[] { 3, 0, -5, 0 }, Relationship.LEQ, 0.0));
765         constraints.add(new LinearConstraint(new double[] { 2, 0, 0, -5 }, Relationship.LEQ, 0.0));
766         constraints.add(new LinearConstraint(new double[] { 0, 3, 0, -5 }, Relationship.LEQ, 0.0));
767         constraints.add(new LinearConstraint(new double[] { 1, 0, 0, 0 }, Relationship.LEQ, 1.0));
768         constraints.add(new LinearConstraint(new double[] { 0, 1, 0, 0 }, Relationship.LEQ, 1.0));
769 
770         final SimplexSolver solver = new SimplexSolver();
771         final SolutionCallback callback = new SolutionCallback();
772 
773         Assert.assertNull(callback.getSolution());
774         Assert.assertFalse(callback.isSolutionOptimal());
775 
776         try {
777             solver.optimize(new MaxIter(3), f, new LinearConstraintSet(constraints),
778                             GoalType.MAXIMIZE, new NonNegativeConstraint(true), callback);
779             Assert.fail("expected MathIllegalStateException");
780         } catch (MathIllegalStateException ex) {
781             // expected
782         }
783 
784         final PointValuePair solution = callback.getSolution();
785         Assert.assertNotNull(solution);
786         Assert.assertTrue(validSolution(solution, constraints, 1e-4));
787         Assert.assertFalse(callback.isSolutionOptimal());
788         // the solution is clearly not optimal: optimal = 10.0
789         Assert.assertEquals(7.0, solution.getValue(), 1e-4);
790     }
791 
792     @Test(expected=MathIllegalArgumentException.class)
793     public void testDimensionMatch() {
794         // min 2x1 +15x2 +18x3
795         // Subject to
796         //   -x1 +2x2 -6x3  <=-10
797         //         x2 +2x3  <= 6
798         //   2x1      +10x3 <= 19
799         //   -x1  +x2       <= -2
800         // x1,x2,x3 >= 0
801 
802         LinearObjectiveFunction f = new LinearObjectiveFunction(new double[] { 2, 15, 18 }, 0);
803         Collection<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
804         // this constraint is wrong, the dimension is less than expected one
805         constraints.add(new LinearConstraint(new double[] { -1, 2 - 6 }, Relationship.LEQ, -10));
806         constraints.add(new LinearConstraint(new double[] { 0, 1, 2 }, Relationship.LEQ, 6));
807         constraints.add(new LinearConstraint(new double[] { 2, 0, 10 }, Relationship.LEQ, 19));
808         constraints.add(new LinearConstraint(new double[] { -1, 1, 0 }, Relationship.LEQ, -2));
809 
810         SimplexSolver solver = new SimplexSolver();
811         solver.optimize(f,
812                         new LinearConstraintSet(constraints),
813                         new NonNegativeConstraint(true),
814                         PivotSelectionRule.BLAND);
815     }
816 
817     /**
818      * Converts a test string to a {@link LinearConstraint}.
819      * Ex: x0 + x1 + x2 + x3 - x12 = 0
820      */
821     private LinearConstraint equationFromString(int numCoefficients, String s) {
822         Relationship relationship;
823         if (s.contains(">=")) {
824             relationship = Relationship.GEQ;
825         } else if (s.contains("<=")) {
826             relationship = Relationship.LEQ;
827         } else if (s.contains("=")) {
828             relationship = Relationship.EQ;
829         } else {
830             throw new IllegalArgumentException();
831         }
832 
833         String[] equationParts = s.split("[>|<]?=");
834         double rhs = Double.parseDouble(equationParts[1].trim());
835 
836         double[] lhs = new double[numCoefficients];
837         String left = equationParts[0].replaceAll(" ?x", "");
838         String[] coefficients = left.split(" ");
839         for (String coefficient : coefficients) {
840             double value = coefficient.charAt(0) == '-' ? -1 : 1;
841             int index = Integer.parseInt(coefficient.replaceFirst("[+|-]", "").trim());
842             lhs[index] = value;
843         }
844         return new LinearConstraint(lhs, relationship, rhs);
845     }
846 
847     private static boolean validSolution(PointValuePair solution, List<LinearConstraint> constraints, double epsilon) {
848         double[] vals = solution.getPoint();
849         for (LinearConstraint c : constraints) {
850             double[] coeffs = c.getCoefficients().toArray();
851             double result = 0.0d;
852             for (int i = 0; i < vals.length; i++) {
853                 result += vals[i] * coeffs[i];
854             }
855 
856             switch (c.getRelationship()) {
857             case EQ:
858                 if (!Precision.equals(result, c.getValue(), epsilon)) {
859                     return false;
860                 }
861                 break;
862 
863             case GEQ:
864                 if (Precision.compareTo(result, c.getValue(), epsilon) < 0) {
865                     return false;
866                 }
867                 break;
868 
869             case LEQ:
870                 if (Precision.compareTo(result, c.getValue(), epsilon) > 0) {
871                     return false;
872                 }
873                 break;
874             }
875         }
876 
877         return true;
878     }
879 
880 }