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    *      http://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  package org.apache.commons.math.optimization.linear;
19  
20  import org.junit.Assert;
21  
22  import java.util.ArrayList;
23  import java.util.Collection;
24  
25  import org.apache.commons.math.optimization.GoalType;
26  import org.apache.commons.math.optimization.OptimizationException;
27  import org.apache.commons.math.optimization.RealPointValuePair;
28  import org.junit.Test;
29  
30  public class SimplexSolverTest {
31  
32      @Test
33      public void testMath272() throws OptimizationException {
34          LinearObjectiveFunction f = new LinearObjectiveFunction(new double[] { 2, 2, 1 }, 0);
35          Collection<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
36          constraints.add(new LinearConstraint(new double[] { 1, 1, 0 }, Relationship.GEQ,  1));
37          constraints.add(new LinearConstraint(new double[] { 1, 0, 1 }, Relationship.GEQ,  1));
38          constraints.add(new LinearConstraint(new double[] { 0, 1, 0 }, Relationship.GEQ,  1));
39  
40          SimplexSolver solver = new SimplexSolver();
41          RealPointValuePair solution = solver.optimize(f, constraints, GoalType.MINIMIZE, true);
42  
43          Assert.assertEquals(0.0, solution.getPoint()[0], .0000001);
44          Assert.assertEquals(1.0, solution.getPoint()[1], .0000001);
45          Assert.assertEquals(1.0, solution.getPoint()[2], .0000001);
46          Assert.assertEquals(3.0, solution.getValue(), .0000001);
47      }
48  
49      @Test
50      public void testMath286() throws OptimizationException {
51          LinearObjectiveFunction f = new LinearObjectiveFunction(new double[] { 0.8, 0.2, 0.7, 0.3, 0.6, 0.4 }, 0 );
52          Collection<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
53          constraints.add(new LinearConstraint(new double[] { 1, 0, 1, 0, 1, 0 }, Relationship.EQ, 23.0));
54          constraints.add(new LinearConstraint(new double[] { 0, 1, 0, 1, 0, 1 }, Relationship.EQ, 23.0));
55          constraints.add(new LinearConstraint(new double[] { 1, 0, 0, 0, 0, 0 }, Relationship.GEQ, 10.0));
56          constraints.add(new LinearConstraint(new double[] { 0, 0, 1, 0, 0, 0 }, Relationship.GEQ, 8.0));
57          constraints.add(new LinearConstraint(new double[] { 0, 0, 0, 0, 1, 0 }, Relationship.GEQ, 5.0));
58  
59          SimplexSolver solver = new SimplexSolver();
60          RealPointValuePair solution = solver.optimize(f, constraints, GoalType.MAXIMIZE, true);
61  
62          Assert.assertEquals(25.8, solution.getValue(), .0000001);
63          Assert.assertEquals(23.0, solution.getPoint()[0] + solution.getPoint()[2] + solution.getPoint()[4], 0.0000001);
64          Assert.assertEquals(23.0, solution.getPoint()[1] + solution.getPoint()[3] + solution.getPoint()[5], 0.0000001);
65          Assert.assertTrue(solution.getPoint()[0] >= 10.0 - 0.0000001);
66          Assert.assertTrue(solution.getPoint()[2] >= 8.0 - 0.0000001);
67          Assert.assertTrue(solution.getPoint()[4] >= 5.0 - 0.0000001);
68      }
69  
70      @Test
71      public void testDegeneracy() throws OptimizationException {
72          LinearObjectiveFunction f = new LinearObjectiveFunction(new double[] { 0.8, 0.7 }, 0 );
73          Collection<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
74          constraints.add(new LinearConstraint(new double[] { 1, 1 }, Relationship.LEQ, 18.0));
75          constraints.add(new LinearConstraint(new double[] { 1, 0 }, Relationship.GEQ, 10.0));
76          constraints.add(new LinearConstraint(new double[] { 0, 1 }, Relationship.GEQ, 8.0));
77  
78          SimplexSolver solver = new SimplexSolver();
79          RealPointValuePair solution = solver.optimize(f, constraints, GoalType.MAXIMIZE, true);
80          Assert.assertEquals(13.6, solution.getValue(), .0000001);
81      }
82  
83      @Test
84      public void testMath288() throws OptimizationException {
85          LinearObjectiveFunction f = new LinearObjectiveFunction(new double[] { 7, 3, 0, 0 }, 0 );
86          Collection<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
87          constraints.add(new LinearConstraint(new double[] { 3, 0, -5, 0 }, Relationship.LEQ, 0.0));
88          constraints.add(new LinearConstraint(new double[] { 2, 0, 0, -5 }, Relationship.LEQ, 0.0));
89          constraints.add(new LinearConstraint(new double[] { 0, 3, 0, -5 }, Relationship.LEQ, 0.0));
90          constraints.add(new LinearConstraint(new double[] { 1, 0, 0, 0 }, Relationship.LEQ, 1.0));
91          constraints.add(new LinearConstraint(new double[] { 0, 1, 0, 0 }, Relationship.LEQ, 1.0));
92  
93          SimplexSolver solver = new SimplexSolver();
94          RealPointValuePair solution = solver.optimize(f, constraints, GoalType.MAXIMIZE, true);
95          Assert.assertEquals(10.0, solution.getValue(), .0000001);
96      }
97  
98      @Test
99      public void testMath290GEQ() throws OptimizationException {
100         LinearObjectiveFunction f = new LinearObjectiveFunction(new double[] { 1, 5 }, 0 );
101         Collection<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
102         constraints.add(new LinearConstraint(new double[] { 2, 0 }, Relationship.GEQ, -1.0));
103         SimplexSolver solver = new SimplexSolver();
104         RealPointValuePair solution = solver.optimize(f, constraints, GoalType.MINIMIZE, true);
105         Assert.assertEquals(0, solution.getValue(), .0000001);
106         Assert.assertEquals(0, solution.getPoint()[0], .0000001);
107         Assert.assertEquals(0, solution.getPoint()[1], .0000001);
108     }
109 
110     @Test(expected=NoFeasibleSolutionException.class)
111     public void testMath290LEQ() throws OptimizationException {
112         LinearObjectiveFunction f = new LinearObjectiveFunction(new double[] { 1, 5 }, 0 );
113         Collection<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
114         constraints.add(new LinearConstraint(new double[] { 2, 0 }, Relationship.LEQ, -1.0));
115         SimplexSolver solver = new SimplexSolver();
116         solver.optimize(f, constraints, GoalType.MINIMIZE, true);
117     }
118 
119     @Test
120     public void testMath293() throws OptimizationException {
121       LinearObjectiveFunction f = new LinearObjectiveFunction(new double[] { 0.8, 0.2, 0.7, 0.3, 0.4, 0.6}, 0 );
122       Collection<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
123       constraints.add(new LinearConstraint(new double[] { 1, 0, 1, 0, 1, 0 }, Relationship.EQ, 30.0));
124       constraints.add(new LinearConstraint(new double[] { 0, 1, 0, 1, 0, 1 }, Relationship.EQ, 30.0));
125       constraints.add(new LinearConstraint(new double[] { 0.8, 0.2, 0.0, 0.0, 0.0, 0.0 }, Relationship.GEQ, 10.0));
126       constraints.add(new LinearConstraint(new double[] { 0.0, 0.0, 0.7, 0.3, 0.0, 0.0 }, Relationship.GEQ, 10.0));
127       constraints.add(new LinearConstraint(new double[] { 0.0, 0.0, 0.0, 0.0, 0.4, 0.6 }, Relationship.GEQ, 10.0));
128 
129       SimplexSolver solver = new SimplexSolver();
130       RealPointValuePair solution1 = solver.optimize(f, constraints, GoalType.MAXIMIZE, true);
131 
132       Assert.assertEquals(15.7143, solution1.getPoint()[0], .0001);
133       Assert.assertEquals(0.0, solution1.getPoint()[1], .0001);
134       Assert.assertEquals(14.2857, solution1.getPoint()[2], .0001);
135       Assert.assertEquals(0.0, solution1.getPoint()[3], .0001);
136       Assert.assertEquals(0.0, solution1.getPoint()[4], .0001);
137       Assert.assertEquals(30.0, solution1.getPoint()[5], .0001);
138       Assert.assertEquals(40.57143, solution1.getValue(), .0001);
139 
140       double valA = 0.8 * solution1.getPoint()[0] + 0.2 * solution1.getPoint()[1];
141       double valB = 0.7 * solution1.getPoint()[2] + 0.3 * solution1.getPoint()[3];
142       double valC = 0.4 * solution1.getPoint()[4] + 0.6 * solution1.getPoint()[5];
143 
144       f = new LinearObjectiveFunction(new double[] { 0.8, 0.2, 0.7, 0.3, 0.4, 0.6}, 0 );
145       constraints = new ArrayList<LinearConstraint>();
146       constraints.add(new LinearConstraint(new double[] { 1, 0, 1, 0, 1, 0 }, Relationship.EQ, 30.0));
147       constraints.add(new LinearConstraint(new double[] { 0, 1, 0, 1, 0, 1 }, Relationship.EQ, 30.0));
148       constraints.add(new LinearConstraint(new double[] { 0.8, 0.2, 0.0, 0.0, 0.0, 0.0 }, Relationship.GEQ, valA));
149       constraints.add(new LinearConstraint(new double[] { 0.0, 0.0, 0.7, 0.3, 0.0, 0.0 }, Relationship.GEQ, valB));
150       constraints.add(new LinearConstraint(new double[] { 0.0, 0.0, 0.0, 0.0, 0.4, 0.6 }, Relationship.GEQ, valC));
151 
152       RealPointValuePair solution2 = solver.optimize(f, constraints, GoalType.MAXIMIZE, true);
153       Assert.assertEquals(40.57143, solution2.getValue(), .0001);
154     }
155 
156     @Test
157     public void testSimplexSolver() throws OptimizationException {
158         LinearObjectiveFunction f =
159             new LinearObjectiveFunction(new double[] { 15, 10 }, 7);
160         Collection<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
161         constraints.add(new LinearConstraint(new double[] { 1, 0 }, Relationship.LEQ, 2));
162         constraints.add(new LinearConstraint(new double[] { 0, 1 }, Relationship.LEQ, 3));
163         constraints.add(new LinearConstraint(new double[] { 1, 1 }, Relationship.EQ, 4));
164 
165         SimplexSolver solver = new SimplexSolver();
166         RealPointValuePair solution = solver.optimize(f, constraints, GoalType.MAXIMIZE, false);
167         Assert.assertEquals(2.0, solution.getPoint()[0], 0.0);
168         Assert.assertEquals(2.0, solution.getPoint()[1], 0.0);
169         Assert.assertEquals(57.0, solution.getValue(), 0.0);
170     }
171 
172     @Test
173     public void testSingleVariableAndConstraint() throws OptimizationException {
174         LinearObjectiveFunction f = new LinearObjectiveFunction(new double[] { 3 }, 0);
175         Collection<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
176         constraints.add(new LinearConstraint(new double[] { 1 }, Relationship.LEQ, 10));
177 
178         SimplexSolver solver = new SimplexSolver();
179         RealPointValuePair solution = solver.optimize(f, constraints, GoalType.MAXIMIZE, false);
180         Assert.assertEquals(10.0, solution.getPoint()[0], 0.0);
181         Assert.assertEquals(30.0, solution.getValue(), 0.0);
182     }
183 
184     /**
185      * With no artificial variables needed (no equals and no greater than
186      * constraints) we can go straight to Phase 2.
187      */
188     @Test
189     public void testModelWithNoArtificialVars() throws OptimizationException {
190         LinearObjectiveFunction f = new LinearObjectiveFunction(new double[] { 15, 10 }, 0);
191         Collection<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
192         constraints.add(new LinearConstraint(new double[] { 1, 0 }, Relationship.LEQ, 2));
193         constraints.add(new LinearConstraint(new double[] { 0, 1 }, Relationship.LEQ, 3));
194         constraints.add(new LinearConstraint(new double[] { 1, 1 }, Relationship.LEQ, 4));
195 
196         SimplexSolver solver = new SimplexSolver();
197         RealPointValuePair solution = solver.optimize(f, constraints, GoalType.MAXIMIZE, false);
198         Assert.assertEquals(2.0, solution.getPoint()[0], 0.0);
199         Assert.assertEquals(2.0, solution.getPoint()[1], 0.0);
200         Assert.assertEquals(50.0, solution.getValue(), 0.0);
201     }
202 
203     @Test
204     public void testMinimization() throws OptimizationException {
205         LinearObjectiveFunction f = new LinearObjectiveFunction(new double[] { -2, 1 }, -5);
206         Collection<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
207         constraints.add(new LinearConstraint(new double[] { 1, 2 }, Relationship.LEQ, 6));
208         constraints.add(new LinearConstraint(new double[] { 3, 2 }, Relationship.LEQ, 12));
209         constraints.add(new LinearConstraint(new double[] { 0, 1 }, Relationship.GEQ, 0));
210 
211         SimplexSolver solver = new SimplexSolver();
212         RealPointValuePair solution = solver.optimize(f, constraints, GoalType.MINIMIZE, false);
213         Assert.assertEquals(4.0, solution.getPoint()[0], 0.0);
214         Assert.assertEquals(0.0, solution.getPoint()[1], 0.0);
215         Assert.assertEquals(-13.0, solution.getValue(), 0.0);
216     }
217 
218     @Test
219     public void testSolutionWithNegativeDecisionVariable() throws OptimizationException {
220         LinearObjectiveFunction f = new LinearObjectiveFunction(new double[] { -2, 1 }, 0);
221         Collection<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
222         constraints.add(new LinearConstraint(new double[] { 1, 1 }, Relationship.GEQ, 6));
223         constraints.add(new LinearConstraint(new double[] { 1, 2 }, Relationship.LEQ, 14));
224 
225         SimplexSolver solver = new SimplexSolver();
226         RealPointValuePair solution = solver.optimize(f, constraints, GoalType.MAXIMIZE, false);
227         Assert.assertEquals(-2.0, solution.getPoint()[0], 0.0);
228         Assert.assertEquals(8.0, solution.getPoint()[1], 0.0);
229         Assert.assertEquals(12.0, solution.getValue(), 0.0);
230     }
231 
232     @Test(expected = NoFeasibleSolutionException.class)
233     public void testInfeasibleSolution() throws OptimizationException {
234         LinearObjectiveFunction f = new LinearObjectiveFunction(new double[] { 15 }, 0);
235         Collection<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
236         constraints.add(new LinearConstraint(new double[] { 1 }, Relationship.LEQ, 1));
237         constraints.add(new LinearConstraint(new double[] { 1 }, Relationship.GEQ, 3));
238 
239         SimplexSolver solver = new SimplexSolver();
240         solver.optimize(f, constraints, GoalType.MAXIMIZE, false);
241     }
242 
243     @Test(expected = UnboundedSolutionException.class)
244     public void testUnboundedSolution() throws OptimizationException {
245         LinearObjectiveFunction f = new LinearObjectiveFunction(new double[] { 15, 10 }, 0);
246         Collection<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
247         constraints.add(new LinearConstraint(new double[] { 1, 0 }, Relationship.EQ, 2));
248 
249         SimplexSolver solver = new SimplexSolver();
250         solver.optimize(f, constraints, GoalType.MAXIMIZE, false);
251     }
252 
253     @Test
254     public void testRestrictVariablesToNonNegative() throws OptimizationException {
255         LinearObjectiveFunction f = new LinearObjectiveFunction(new double[] { 409, 523, 70, 204, 339 }, 0);
256         Collection<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
257         constraints.add(new LinearConstraint(new double[] {    43,   56, 345,  56,    5 }, Relationship.LEQ,  4567456));
258         constraints.add(new LinearConstraint(new double[] {    12,   45,   7,  56,   23 }, Relationship.LEQ,    56454));
259         constraints.add(new LinearConstraint(new double[] {     8,  768,   0,  34, 7456 }, Relationship.LEQ,  1923421));
260         constraints.add(new LinearConstraint(new double[] { 12342, 2342,  34, 678, 2342 }, Relationship.GEQ,     4356));
261         constraints.add(new LinearConstraint(new double[] {    45,  678,  76,  52,   23 }, Relationship.EQ,    456356));
262 
263         SimplexSolver solver = new SimplexSolver();
264         RealPointValuePair solution = solver.optimize(f, constraints, GoalType.MAXIMIZE, true);
265         Assert.assertEquals(2902.92783505155, solution.getPoint()[0], .0000001);
266         Assert.assertEquals(480.419243986254, solution.getPoint()[1], .0000001);
267         Assert.assertEquals(0.0, solution.getPoint()[2], .0000001);
268         Assert.assertEquals(0.0, solution.getPoint()[3], .0000001);
269         Assert.assertEquals(0.0, solution.getPoint()[4], .0000001);
270         Assert.assertEquals(1438556.7491409, solution.getValue(), .0000001);
271     }
272 
273     @Test
274     public void testEpsilon() throws OptimizationException {
275       LinearObjectiveFunction f =
276           new LinearObjectiveFunction(new double[] { 10, 5, 1 }, 0);
277       Collection<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
278       constraints.add(new LinearConstraint(new double[] {  9, 8, 0 }, Relationship.EQ,  17));
279       constraints.add(new LinearConstraint(new double[] {  0, 7, 8 }, Relationship.LEQ,  7));
280       constraints.add(new LinearConstraint(new double[] { 10, 0, 2 }, Relationship.LEQ, 10));
281 
282       SimplexSolver solver = new SimplexSolver();
283       RealPointValuePair solution = solver.optimize(f, constraints, GoalType.MAXIMIZE, false);
284       Assert.assertEquals(1.0, solution.getPoint()[0], 0.0);
285       Assert.assertEquals(1.0, solution.getPoint()[1], 0.0);
286       Assert.assertEquals(0.0, solution.getPoint()[2], 0.0);
287       Assert.assertEquals(15.0, solution.getValue(), 0.0);
288   }
289 
290     @Test
291     public void testTrivialModel() throws OptimizationException {
292         LinearObjectiveFunction f = new LinearObjectiveFunction(new double[] { 1, 1 }, 0);
293         Collection<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
294         constraints.add(new LinearConstraint(new double[] { 1, 1 }, Relationship.EQ,  0));
295 
296         SimplexSolver solver = new SimplexSolver();
297         RealPointValuePair solution = solver.optimize(f, constraints, GoalType.MAXIMIZE, true);
298         Assert.assertEquals(0, solution.getValue(), .0000001);
299     }
300 
301     @Test
302     public void testLargeModel() throws OptimizationException {
303         double[] objective = new double[] {
304                                            1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
305                                            1, 1, 12, 1, 1, 1, 1, 1, 1, 1,
306                                            1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
307                                            1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
308                                            12, 1, 1, 1, 1, 1, 1, 1, 1, 1,
309                                            1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
310                                            1, 1, 1, 1, 1, 1, 1, 1, 12, 1,
311                                            1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
312                                            1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
313                                            1, 1, 1, 1, 1, 1, 12, 1, 1, 1,
314                                            1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
315                                            1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
316                                            1, 1, 1, 1, 12, 1, 1, 1, 1, 1,
317                                            1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
318                                            1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
319                                            1, 1, 12, 1, 1, 1, 1, 1, 1, 1,
320                                            1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
321                                            1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
322                                            1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
323                                            1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
324                                            1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
325                                            1, 1, 1, 1, 1, 1};
326 
327         LinearObjectiveFunction f = new LinearObjectiveFunction(objective, 0);
328         Collection<LinearConstraint> constraints = new ArrayList<LinearConstraint>();
329         constraints.add(equationFromString(objective.length, "x0 + x1 + x2 + x3 - x12 = 0"));
330         constraints.add(equationFromString(objective.length, "x4 + x5 + x6 + x7 + x8 + x9 + x10 + x11 - x13 = 0"));
331         constraints.add(equationFromString(objective.length, "x4 + x5 + x6 + x7 + x8 + x9 + x10 + x11 >= 49"));
332         constraints.add(equationFromString(objective.length, "x0 + x1 + x2 + x3 >= 42"));
333         constraints.add(equationFromString(objective.length, "x14 + x15 + x16 + x17 - x26 = 0"));
334         constraints.add(equationFromString(objective.length, "x18 + x19 + x20 + x21 + x22 + x23 + x24 + x25 - x27 = 0"));
335         constraints.add(equationFromString(objective.length, "x14 + x15 + x16 + x17 - x12 = 0"));
336         constraints.add(equationFromString(objective.length, "x18 + x19 + x20 + x21 + x22 + x23 + x24 + x25 - x13 = 0"));
337         constraints.add(equationFromString(objective.length, "x28 + x29 + x30 + x31 - x40 = 0"));
338         constraints.add(equationFromString(objective.length, "x32 + x33 + x34 + x35 + x36 + x37 + x38 + x39 - x41 = 0"));
339         constraints.add(equationFromString(objective.length, "x32 + x33 + x34 + x35 + x36 + x37 + x38 + x39 >= 49"));
340         constraints.add(equationFromString(objective.length, "x28 + x29 + x30 + x31 >= 42"));
341         constraints.add(equationFromString(objective.length, "x42 + x43 + x44 + x45 - x54 = 0"));
342         constraints.add(equationFromString(objective.length, "x46 + x47 + x48 + x49 + x50 + x51 + x52 + x53 - x55 = 0"));
343         constraints.add(equationFromString(objective.length, "x42 + x43 + x44 + x45 - x40 = 0"));
344         constraints.add(equationFromString(objective.length, "x46 + x47 + x48 + x49 + x50 + x51 + x52 + x53 - x41 = 0"));
345         constraints.add(equationFromString(objective.length, "x56 + x57 + x58 + x59 - x68 = 0"));
346         constraints.add(equationFromString(objective.length, "x60 + x61 + x62 + x63 + x64 + x65 + x66 + x67 - x69 = 0"));
347         constraints.add(equationFromString(objective.length, "x60 + x61 + x62 + x63 + x64 + x65 + x66 + x67 >= 51"));
348         constraints.add(equationFromString(objective.length, "x56 + x57 + x58 + x59 >= 44"));
349         constraints.add(equationFromString(objective.length, "x70 + x71 + x72 + x73 - x82 = 0"));
350         constraints.add(equationFromString(objective.length, "x74 + x75 + x76 + x77 + x78 + x79 + x80 + x81 - x83 = 0"));
351         constraints.add(equationFromString(objective.length, "x70 + x71 + x72 + x73 - x68 = 0"));
352         constraints.add(equationFromString(objective.length, "x74 + x75 + x76 + x77 + x78 + x79 + x80 + x81 - x69 = 0"));
353         constraints.add(equationFromString(objective.length, "x84 + x85 + x86 + x87 - x96 = 0"));
354         constraints.add(equationFromString(objective.length, "x88 + x89 + x90 + x91 + x92 + x93 + x94 + x95 - x97 = 0"));
355         constraints.add(equationFromString(objective.length, "x88 + x89 + x90 + x91 + x92 + x93 + x94 + x95 >= 51"));
356         constraints.add(equationFromString(objective.length, "x84 + x85 + x86 + x87 >= 44"));
357         constraints.add(equationFromString(objective.length, "x98 + x99 + x100 + x101 - x110 = 0"));
358         constraints.add(equationFromString(objective.length, "x102 + x103 + x104 + x105 + x106 + x107 + x108 + x109 - x111 = 0"));
359         constraints.add(equationFromString(objective.length, "x98 + x99 + x100 + x101 - x96 = 0"));
360         constraints.add(equationFromString(objective.length, "x102 + x103 + x104 + x105 + x106 + x107 + x108 + x109 - x97 = 0"));
361         constraints.add(equationFromString(objective.length, "x112 + x113 + x114 + x115 - x124 = 0"));
362         constraints.add(equationFromString(objective.length, "x116 + x117 + x118 + x119 + x120 + x121 + x122 + x123 - x125 = 0"));
363         constraints.add(equationFromString(objective.length, "x116 + x117 + x118 + x119 + x120 + x121 + x122 + x123 >= 49"));
364         constraints.add(equationFromString(objective.length, "x112 + x113 + x114 + x115 >= 42"));
365         constraints.add(equationFromString(objective.length, "x126 + x127 + x128 + x129 - x138 = 0"));
366         constraints.add(equationFromString(objective.length, "x130 + x131 + x132 + x133 + x134 + x135 + x136 + x137 - x139 = 0"));
367         constraints.add(equationFromString(objective.length, "x126 + x127 + x128 + x129 - x124 = 0"));
368         constraints.add(equationFromString(objective.length, "x130 + x131 + x132 + x133 + x134 + x135 + x136 + x137 - x125 = 0"));
369         constraints.add(equationFromString(objective.length, "x140 + x141 + x142 + x143 - x152 = 0"));
370         constraints.add(equationFromString(objective.length, "x144 + x145 + x146 + x147 + x148 + x149 + x150 + x151 - x153 = 0"));
371         constraints.add(equationFromString(objective.length, "x144 + x145 + x146 + x147 + x148 + x149 + x150 + x151 >= 59"));
372         constraints.add(equationFromString(objective.length, "x140 + x141 + x142 + x143 >= 42"));
373         constraints.add(equationFromString(objective.length, "x154 + x155 + x156 + x157 - x166 = 0"));
374         constraints.add(equationFromString(objective.length, "x158 + x159 + x160 + x161 + x162 + x163 + x164 + x165 - x167 = 0"));
375         constraints.add(equationFromString(objective.length, "x154 + x155 + x156 + x157 - x152 = 0"));
376         constraints.add(equationFromString(objective.length, "x158 + x159 + x160 + x161 + x162 + x163 + x164 + x165 - x153 = 0"));
377         constraints.add(equationFromString(objective.length, "x83 + x82 - x168 = 0"));
378         constraints.add(equationFromString(objective.length, "x111 + x110 - x169 = 0"));
379         constraints.add(equationFromString(objective.length, "x170 - x182 = 0"));
380         constraints.add(equationFromString(objective.length, "x171 - x183 = 0"));
381         constraints.add(equationFromString(objective.length, "x172 - x184 = 0"));
382         constraints.add(equationFromString(objective.length, "x173 - x185 = 0"));
383         constraints.add(equationFromString(objective.length, "x174 - x186 = 0"));
384         constraints.add(equationFromString(objective.length, "x175 + x176 - x187 = 0"));
385         constraints.add(equationFromString(objective.length, "x177 - x188 = 0"));
386         constraints.add(equationFromString(objective.length, "x178 - x189 = 0"));
387         constraints.add(equationFromString(objective.length, "x179 - x190 = 0"));
388         constraints.add(equationFromString(objective.length, "x180 - x191 = 0"));
389         constraints.add(equationFromString(objective.length, "x181 - x192 = 0"));
390         constraints.add(equationFromString(objective.length, "x170 - x26 = 0"));
391         constraints.add(equationFromString(objective.length, "x171 - x27 = 0"));
392         constraints.add(equationFromString(objective.length, "x172 - x54 = 0"));
393         constraints.add(equationFromString(objective.length, "x173 - x55 = 0"));
394         constraints.add(equationFromString(objective.length, "x174 - x168 = 0"));
395         constraints.add(equationFromString(objective.length, "x177 - x169 = 0"));
396         constraints.add(equationFromString(objective.length, "x178 - x138 = 0"));
397         constraints.add(equationFromString(objective.length, "x179 - x139 = 0"));
398         constraints.add(equationFromString(objective.length, "x180 - x166 = 0"));
399         constraints.add(equationFromString(objective.length, "x181 - x167 = 0"));
400         constraints.add(equationFromString(objective.length, "x193 - x205 = 0"));
401         constraints.add(equationFromString(objective.length, "x194 - x206 = 0"));
402         constraints.add(equationFromString(objective.length, "x195 - x207 = 0"));
403         constraints.add(equationFromString(objective.length, "x196 - x208 = 0"));
404         constraints.add(equationFromString(objective.length, "x197 - x209 = 0"));
405         constraints.add(equationFromString(objective.length, "x198 + x199 - x210 = 0"));
406         constraints.add(equationFromString(objective.length, "x200 - x211 = 0"));
407         constraints.add(equationFromString(objective.length, "x201 - x212 = 0"));
408         constraints.add(equationFromString(objective.length, "x202 - x213 = 0"));
409         constraints.add(equationFromString(objective.length, "x203 - x214 = 0"));
410         constraints.add(equationFromString(objective.length, "x204 - x215 = 0"));
411         constraints.add(equationFromString(objective.length, "x193 - x182 = 0"));
412         constraints.add(equationFromString(objective.length, "x194 - x183 = 0"));
413         constraints.add(equationFromString(objective.length, "x195 - x184 = 0"));
414         constraints.add(equationFromString(objective.length, "x196 - x185 = 0"));
415         constraints.add(equationFromString(objective.length, "x197 - x186 = 0"));
416         constraints.add(equationFromString(objective.length, "x198 + x199 - x187 = 0"));
417         constraints.add(equationFromString(objective.length, "x200 - x188 = 0"));
418         constraints.add(equationFromString(objective.length, "x201 - x189 = 0"));
419         constraints.add(equationFromString(objective.length, "x202 - x190 = 0"));
420         constraints.add(equationFromString(objective.length, "x203 - x191 = 0"));
421         constraints.add(equationFromString(objective.length, "x204 - x192 = 0"));
422 
423         SimplexSolver solver = new SimplexSolver();
424         RealPointValuePair solution = solver.optimize(f, constraints, GoalType.MINIMIZE, true);
425         Assert.assertEquals(7518.0, solution.getValue(), .0000001);
426     }
427 
428     /**
429      * Converts a test string to a {@link LinearConstraint}.
430      * Ex: x0 + x1 + x2 + x3 - x12 = 0
431      */
432     private LinearConstraint equationFromString(int numCoefficients, String s) {
433         Relationship relationship;
434         if (s.contains(">=")) {
435             relationship = Relationship.GEQ;
436         } else if (s.contains("<=")) {
437             relationship = Relationship.LEQ;
438         } else if (s.contains("=")) {
439             relationship = Relationship.EQ;
440         } else {
441             throw new IllegalArgumentException();
442         }
443 
444         String[] equationParts = s.split("[>|<]?=");
445         double rhs = Double.parseDouble(equationParts[1].trim());
446 
447         double[] lhs = new double[numCoefficients];
448         String left = equationParts[0].replaceAll(" ?x", "");
449         String[] coefficients = left.split(" ");
450         for (String coefficient : coefficients) {
451             double value = coefficient.charAt(0) == '-' ? -1 : 1;
452             int index = Integer.parseInt(coefficient.replaceFirst("[+|-]", "").trim());
453             lhs[index] = value;
454         }
455         return new LinearConstraint(lhs, relationship, rhs);
456     }
457 
458 }