Coverage Report - net.sourceforge.combean.test.mathprog.lp.AbstractTestLPSolver
 
Classes in this File Line Coverage Branch Coverage Complexity
AbstractTestLPSolver
100%
158/158
100%
12/12
1,207
 
 1  
 /*
 2  
     This file is part of Combean.
 3  
 
 4  
     Combean is free software; you can redistribute it and/or modify
 5  
     it under the terms of the GNU General Public License as published by
 6  
     the Free Software Foundation; either version 2 of the License, or
 7  
     (at your option) any later version.
 8  
 
 9  
     Combean is distributed in the hope that it will be useful,
 10  
     but WITHOUT ANY WARRANTY; without even the implied warranty of
 11  
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 12  
     GNU General Public License for more details.
 13  
 
 14  
     You should have received a copy of the GNU General Public License
 15  
     along with Combean; if not, write to the Free Software
 16  
     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 17  
 */
 18  
 /*
 19  
  * Created on 23.04.2005
 20  
  *
 21  
  */
 22  
 package net.sourceforge.combean.test.mathprog.lp;
 23  
 
 24  
 import junit.framework.TestCase;
 25  
 import net.sourceforge.combean.interfaces.mathprog.linalg.SparseVector;
 26  
 import net.sourceforge.combean.interfaces.mathprog.lp.LPConstraint;
 27  
 import net.sourceforge.combean.interfaces.mathprog.lp.LPSolver;
 28  
 import net.sourceforge.combean.interfaces.mathprog.lp.LPVariable;
 29  
 import net.sourceforge.combean.mathprog.linalg.DoubleVector;
 30  
 import net.sourceforge.combean.mathprog.linalg.SparseDoubleVector;
 31  
 import net.sourceforge.combean.mathprog.linalg.statics.SparseVectorConverter;
 32  
 import net.sourceforge.combean.mathprog.lp.DoubleLPConstraint;
 33  
 import net.sourceforge.combean.mathprog.lp.DoubleLPVariable;
 34  
 import net.sourceforge.combean.test.helpers.checks.Check;
 35  
 
 36  
 /**
 37  
  * @author schickin
 38  
  *
 39  
  */
 40  
 public abstract class AbstractTestLPSolver extends TestCase {
 41  
 
 42  
     /*
 43  
      * @see TestCase#setUp()
 44  
      */
 45  
     protected void setUp() throws Exception {
 46  99
         super.setUp();
 47  
         
 48  99
         this.lp = createEmptyLPProblem();
 49  99
     }
 50  
 
 51  
     /*
 52  
      * @see TestCase#tearDown()
 53  
      */
 54  
     protected void tearDown() throws Exception {
 55  99
         super.tearDown();
 56  99
     }
 57  
 
 58  
     /**
 59  
      * Constructor for AbstractTestLPSolver.
 60  
      * @param name
 61  
      */
 62  
     public AbstractTestLPSolver(String name) {
 63  99
         super(name);
 64  99
     }
 65  
     
 66  
     protected abstract LPSolver createEmptyLPProblem();
 67  
 
 68  99
     private LPSolver lp = null;
 69  
     
 70  3
     private static final byte[] codeToRelation = {
 71  
                 LPConstraint.REL_LESS,
 72  
                 LPConstraint.REL_EQUAL,
 73  
                 LPConstraint.REL_GREATER
 74  
         };
 75  
     
 76  
     /* Static data for feasible problem 1 */
 77  
     
 78  3
     private static final double[][] constrFeas1 = {
 79  
                 {2, 1, -1 , 200},
 80  
                 {2, 3, -1 , 300}
 81  
         };
 82  
     // variant with maximization
 83  3
     private static final double[] varsFeas1Max = {4.0, 3.0};
 84  
     private static final double zFeas1Max = 450;
 85  3
     private static final double[] solFeas1Max = {75, 50};
 86  
     
 87  
     // variant with minimization
 88  3
     private static final double[] varsFeas1Min = {-4.0, 3.0};
 89  
     private static final double zFeas1Min = -400;
 90  3
     private static final double[] solFeas1Min = {100, 0};
 91  
     
 92  
     // columnwise representation
 93  3
     private static final double[][] colFeas1 = {
 94  
             {2, 2},
 95  
             {1, 3}
 96  
     };
 97  
     
 98  
     /* Static data for feasible problem 2 (sparse representation) */
 99  
 
 100  3
     private static final double[][] constrFeas2 = {
 101  
             {-1, 100},
 102  
             {-1, 50},
 103  
             {-1, 80}
 104  
     };
 105  3
     private static final int[][] rowIndFeas2 = {
 106  
             {0, 1},
 107  
             {1, 2},
 108  
             {0, 2}
 109  
     };
 110  3
     private static final double[][] rowValFeas2 = {
 111  
             {2, 4},
 112  
             {8, 4},
 113  
             {10, 6}
 114  
     };
 115  3
     private static final double[] varsFeas2 = {4.0, 12.0, 6.0};
 116  
     private static final double zFeas2 = 107.0;
 117  3
     private static final double[] solFeas2 = {8, 6.25, 0};
 118  
     
 119  
     // variant with unsorted indices
 120  3
     private static final int[][] rowIndFeas2Unordered = {
 121  
             {1, 0},
 122  
             {1, 2},
 123  
             {2, 0}
 124  
     };
 125  3
     private static final double[][] rowValFeas2Unordered = {
 126  
             {4, 2},
 127  
             {8, 4},
 128  
             {6, 10}
 129  
     };
 130  
 
 131  
     /* Static data for an unbounded problem */
 132  
     
 133  3
     private static final double[][] constrUnbounded = {
 134  
                 {2, 1, 1 , 200},
 135  
                 {2, 3, 1 , 300}
 136  
         };
 137  3
     private static final double[] varsUnbounded = {-4.0, 3.0};
 138  
     
 139  
     /* Static data for an infeasible problem */
 140  
     
 141  3
     private static final double[][] constrInfeas = {
 142  
                 {2, 3, -1 , 200},
 143  
                 {2, 1, 1 , 300}
 144  
         };
 145  3
     private static final double[] varsInfeas = {4.0, 3.0};
 146  
     
 147  
     // dummy array (whenever we need an array but the content does not matter)
 148  3
     private static final double[] dummyArr = {1.0, 2.0};
 149  
 
 150  
     
 151  
     protected double getPrecision() {
 152  60
         return 0.0;
 153  
     }
 154  
 
 155  
     private void solveAndCheckLP(byte expectedStatus, double expectedZ, double[] expectedSol) {
 156  45
         solveAndCheckLP(expectedStatus);
 157  
         
 158  45
         double z = this.lp.getSolutionValue();
 159  45
         assertEquals(expectedZ, z, getPrecision());
 160  
         
 161  45
         SparseVector solution = this.lp.getSolution();
 162  45
         double[] solutionAsDoubles =
 163  
             SparseVectorConverter.convertToDoubleArray(
 164  
                     this.lp.getNumColumns(), solution);
 165  45
         Check.compareDoubleArrays(expectedSol, solutionAsDoubles,
 166  
                 getPrecision());
 167  45
     }
 168  
 
 169  
     private void solveAndCheckLP(byte expectedStatus) {
 170  63
         this.lp.freeze();
 171  
         
 172  63
         this.lp.solve();
 173  
         
 174  63
         byte solutionStatus = this.lp.getSolutionStatus();
 175  63
         assertEquals(expectedStatus, solutionStatus);
 176  63
     }
 177  
 
 178  
     private void setupLP(LPSolver lp, byte objective,
 179  
             double[][] constraints, double[] variables) {
 180  36
         lp.setInitialDimensions(constraints.length, variables.length);
 181  36
         lp.setObjective(objective);
 182  
         
 183  36
         setupVariables(lp, variables, 0, Double.POSITIVE_INFINITY);
 184  36
         setupConstraintsAndRows(lp, constraints);
 185  36
     }
 186  
 
 187  
     private void setupSparseLP(LPSolver lp, byte objective,
 188  
             double[][] constraints,
 189  
             int[][] rowIndices, double[][] rowValues,
 190  
             double[] variables) {
 191  18
         lp.setInitialDimensions(constraints.length, variables.length);
 192  18
         lp.setObjective(objective);
 193  
         
 194  18
         setupVariables(lp, variables, 0, Double.POSITIVE_INFINITY);
 195  18
         setupConstraintsAndSparseRows(lp, constraints,
 196  
                 variables.length, rowIndices, rowValues);
 197  18
     }
 198  
 /*
 199  
     private void setupLPColumnwise(LPSolver lp, byte objective,
 200  
             double[][] constraints, double[][] variables, double[][] columns) {
 201  
         lp.setInitialDimensions(constraints.length, variables.length);
 202  
         lp.setObjective(objective);
 203  
         
 204  
         setupConstraints(lp, constraints);
 205  
         setupVariablesAndColumns(lp, variables, columns);
 206  
     }
 207  
 */
 208  
     private void setupLPColumnwise(LPSolver lp, byte objective,
 209  
             double[][] constraints, double[] variables, double[][] columns) {
 210  9
         lp.setInitialDimensions(constraints.length, variables.length);
 211  9
         lp.setObjective(objective);
 212  
         
 213  9
         setupConstraints(lp, constraints);
 214  9
         setupVariablesAndColumns(lp, variables, columns);
 215  9
     }
 216  
 /*
 217  
     private void setupVariables(LPSolver lpToSetup, double[][] variables) {
 218  
         for (int i = 0; i < variables.length; i++) {
 219  
             LPVariable var = new DoubleLPVariable("var" + i,
 220  
                     variables[i][0], variables[i][1], variables[i][2]);
 221  
             lpToSetup.addVariable(var);
 222  
         }
 223  
     }
 224  
 */
 225  
     private void setupVariables(LPSolver lpToSetup, double[] variables, double uniformLowerBound, double uniformUpperBound) {
 226  180
         for (int i = 0; i < variables.length; i++) {
 227  126
             LPVariable var = new DoubleLPVariable("var" + i,
 228  
                     variables[i], uniformLowerBound, uniformUpperBound);
 229  126
             lpToSetup.addVariable(var);
 230  
         }
 231  54
     }
 232  
 /*
 233  
     private void setupVariablesAndColumns(LPSolver lpToSetup, double[][] variables, double[][] columns) {
 234  
         for (int i = 0; i < variables.length; i++) {
 235  
             LPVariable variable = new DoubleLPVariable("var" + i,
 236  
                     variables[i][0], variables[i][1], variables[i][2]);
 237  
             SparseVector colVec = new DoubleVector(columns[i]);
 238  
             lpToSetup.addColumn(variable, colVec);
 239  
         }
 240  
     }
 241  
 */
 242  
     private void setupVariablesAndColumns(LPSolver lpToSetup, double[] variables, double[][] columns) {
 243  27
         for (int i = 0; i < variables.length; i++) {
 244  18
             LPVariable variable = new DoubleLPVariable("var" + i,
 245  
                     variables[i], 0, Double.POSITIVE_INFINITY);
 246  18
             SparseVector colVec = new DoubleVector(columns[i]);
 247  18
             lpToSetup.addColumn(variable, colVec);
 248  
         }
 249  9
     }
 250  
 
 251  
     private void setupConstraintsAndRows(LPSolver lpToSetup,
 252  
             double[][] constraints) {
 253  108
       for (int i = 0; i < constraints.length; i++) {
 254  72
           LPConstraint constraint = new DoubleLPConstraint("constr" + i,
 255  
                   calcRelation(constraints[i]),
 256  
                   calcRhs(constraints[i]));
 257  72
           SparseVector rowVec =
 258  
               new DoubleVector(calcRow(constraints[i]));
 259  72
           lpToSetup.addRow(constraint, rowVec);
 260  
       }
 261  36
     }
 262  
 
 263  
     private void setupConstraintsAndSparseRows(LPSolver lpToSetup,
 264  
             double[][] constraints,
 265  
             int numColumns, int[][] rowIndices, double[][] rowValues) {
 266  72
       for (int i = 0; i < constraints.length; i++) {
 267  54
           LPConstraint constraint = new DoubleLPConstraint("constr" + i,
 268  
                   calcRelation(constraints[i]),
 269  
                   calcRhs(constraints[i]));
 270  54
           SparseVector rowVec =
 271  
               new SparseDoubleVector(numColumns, rowIndices[i], rowValues[i]);
 272  54
           lpToSetup.addRow(constraint, rowVec);
 273  
       }
 274  18
     }
 275  
 
 276  
     private void setupConstraints(LPSolver lpToSetup, double[][] constraints) {
 277  27
       for (int i = 0; i < constraints.length; i++) {
 278  18
           LPConstraint constr = new DoubleLPConstraint("constr" + i,
 279  
                   calcRelation(constraints[i]),
 280  
                   calcRhs(constraints[i]));
 281  18
           lpToSetup.addConstraint(constr);
 282  
       }
 283  9
     }
 284  
 
 285  
     private byte calcRelation(double[] constraint) {
 286  144
         int code = (int) constraint[constraint.length-2];
 287  144
         return codeToRelation[code+1];
 288  
     }
 289  
 
 290  
     private double calcRhs(double[] constraint) {
 291  144
         return constraint[constraint.length-1];
 292  
     }
 293  
 
 294  
     private double[] calcRow(double[] constraint) {
 295  72
         double[] result = new double[constraint.length-2];
 296  216
         for (int i = 0; i < result.length; i++) {
 297  144
             result[i] = constraint[i];
 298  
         }
 299  72
         return result;
 300  
     }
 301  
 
 302  
     public void testAddVariable() {
 303  9
         this.lp.setInitialDimensions(2, 2);
 304  9
         assertEquals(0, this.lp.getNumColumns());
 305  9
         assertEquals(0, this.lp.getNumRows());
 306  
         
 307  9
         int columnIndex = this.lp.addVariable(
 308  
                 new DoubleLPVariable("a", 0.0, 0, Double.POSITIVE_INFINITY));
 309  9
         assertEquals("numbering of columns starts with 0", 0, columnIndex);
 310  9
         assertEquals(1, this.lp.getNumColumns());
 311  9
         assertEquals(0, this.lp.getNumRows());
 312  
         
 313  9
         columnIndex = this.lp.addVariable(
 314  
                 new DoubleLPVariable("b", 0.0, 0, Double.POSITIVE_INFINITY));
 315  9
         assertEquals("numbering of columns continues with 1", 1, columnIndex);
 316  9
         assertEquals(2, this.lp.getNumColumns());
 317  9
         assertEquals(0, this.lp.getNumRows());
 318  9
     }
 319  
 
 320  
     public void testAddConstraint() {
 321  9
         this.lp.setInitialDimensions(2, 2);
 322  9
         assertEquals(0, this.lp.getNumColumns());
 323  9
         assertEquals(0, this.lp.getNumRows());
 324  
         
 325  9
         int constrIndex =
 326  
             this.lp.addConstraint(new DoubleLPConstraint("a",
 327  
                     LPConstraint.REL_EQUAL, 1.0));
 328  9
         assertEquals("numbering of rows starts with 0", 0, constrIndex);
 329  9
         assertEquals(0, this.lp.getNumColumns());
 330  9
         assertEquals(1, this.lp.getNumRows());
 331  
         
 332  9
         constrIndex =
 333  
             this.lp.addConstraint(new DoubleLPConstraint("b",
 334  
                     LPConstraint.REL_LESS, -1.0));
 335  9
         assertEquals("numbering of rows continues with 1", 1, constrIndex);
 336  9
         assertEquals(0, this.lp.getNumColumns());
 337  9
         assertEquals(2, this.lp.getNumRows());
 338  9
     }
 339  
 
 340  
     public void testAddRow() {
 341  9
         this.lp.setInitialDimensions(2, 2);
 342  9
         this.lp.addVariable(
 343  
                 new DoubleLPVariable("a", 0.0, 0, Double.POSITIVE_INFINITY));
 344  9
         this.lp.addVariable(
 345  
                 new DoubleLPVariable("b", 0.0, 0, Double.POSITIVE_INFINITY));
 346  9
         assertEquals(2, this.lp.getNumColumns());
 347  9
         assertEquals(0, this.lp.getNumRows());
 348  
     
 349  9
         int rowIndex = this.lp.addRow(
 350  
                 new DoubleLPConstraint("a", LPConstraint.REL_EQUAL, 0.0),
 351  
                 new DoubleVector(dummyArr));
 352  9
         assertEquals("numbering of columns starts with 0", 0, rowIndex);
 353  9
         assertEquals(2, this.lp.getNumColumns());
 354  9
         assertEquals(1, this.lp.getNumRows());
 355  
     
 356  9
         rowIndex = this.lp.addRow(
 357  
                 new DoubleLPConstraint("b", LPConstraint.REL_LESS, 1.0),
 358  
                 new DoubleVector(dummyArr));
 359  9
         assertEquals("numbering of columns starts with 0", 1, rowIndex);
 360  9
         assertEquals(2, this.lp.getNumColumns());
 361  9
         assertEquals(2, this.lp.getNumRows());
 362  9
     }
 363  
 
 364  
     public void testAddColumn() {
 365  9
         this.lp.setInitialDimensions(2, 2);
 366  9
         this.lp.addConstraint(new DoubleLPConstraint("a",
 367  
                 LPConstraint.REL_EQUAL, 1.0));
 368  9
         this.lp.addConstraint(new DoubleLPConstraint("b",
 369  
                 LPConstraint.REL_LESS, -1.0));
 370  9
         assertEquals(0, this.lp.getNumColumns());
 371  9
         assertEquals(2, this.lp.getNumRows());
 372  
     
 373  9
         int columnIndex =
 374  
             this.lp.addColumn(new DoubleLPVariable("a", 0.0,
 375  
                     0, Double.POSITIVE_INFINITY),
 376  
                     new DoubleVector(dummyArr));
 377  9
         assertEquals("numbering of columns starts with 0", 0, columnIndex);
 378  9
         assertEquals(1, this.lp.getNumColumns());
 379  9
         assertEquals(2, this.lp.getNumRows());
 380  
     
 381  9
         columnIndex =
 382  
             this.lp.addColumn(new DoubleLPVariable("b", 1.0,
 383  
                     0, Double.POSITIVE_INFINITY),
 384  
                     new DoubleVector(dummyArr));
 385  9
         assertEquals("numbering of columns starts with 0", 1, columnIndex);
 386  9
         assertEquals(2, this.lp.getNumColumns());
 387  9
         assertEquals(2, this.lp.getNumRows());
 388  9
     }
 389  
 
 390  
     public void testSolveFeasibleLPMax() {
 391  9
         setupLP(this.lp, LPSolver.LPOBJ_MAX, constrFeas1, varsFeas1Max);
 392  9
         solveAndCheckLP(LPSolver.LPSTAT_SOLVED, zFeas1Max, solFeas1Max);
 393  9
     }
 394  
 
 395  
     public void testSolveFeasibleLPMin() {
 396  9
         setupLP(this.lp, LPSolver.LPOBJ_MIN, constrFeas1, varsFeas1Min);
 397  9
         solveAndCheckLP(LPSolver.LPSTAT_SOLVED, zFeas1Min, solFeas1Min);
 398  9
     }
 399  
     
 400  
     public void testSolveSparseLP() {
 401  9
         setupSparseLP(this.lp, LPSolver.LPOBJ_MAX, constrFeas2,
 402  
                 rowIndFeas2, rowValFeas2, varsFeas2);
 403  9
         solveAndCheckLP(LPSolver.LPSTAT_SOLVED, zFeas2, solFeas2);
 404  9
     }
 405  
 
 406  
     public void testSolveSparseLPWithUnsortedIndices() {
 407  9
         setupSparseLP(this.lp, LPSolver.LPOBJ_MAX, constrFeas2,
 408  
                 rowIndFeas2Unordered, rowValFeas2Unordered, varsFeas2);
 409  9
         solveAndCheckLP(LPSolver.LPSTAT_SOLVED, zFeas2, solFeas2);
 410  9
     }
 411  
 
 412  
     public void testSolveUnboundedLP() {
 413  9
         setupLP(this.lp, LPSolver.LPOBJ_MIN, constrUnbounded, varsUnbounded);
 414  9
         solveAndCheckLP(LPSolver.LPSTAT_UNBOUNDED);
 415  9
     }
 416  
 
 417  
     public void testSolveInfeasibleLP() {
 418  9
         setupLP(this.lp, LPSolver.LPOBJ_MAX, constrInfeas, varsInfeas);
 419  9
         solveAndCheckLP(LPSolver.LPSTAT_INFEASIBLE);
 420  9
     }
 421  
 
 422  
     public void testSolveFeasibleLPBuildColumnWise() {
 423  9
         setupLPColumnwise(this.lp, LPSolver.LPOBJ_MAX,
 424  
                 constrFeas1, varsFeas1Max, colFeas1);
 425  9
         solveAndCheckLP(LPSolver.LPSTAT_SOLVED, zFeas1Max, solFeas1Max);
 426  9
     }
 427  
 
 428  
 }