Coverage Report - net.sourceforge.combean.adapters.drasys.lp.SizableProblemIAsLPSolver
 
Classes in this File Line Coverage Branch Coverage Complexity
SizableProblemIAsLPSolver
72%
80/111
81%
13/16
0
 
 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 22.04.2005
 20  
  *
 21  
  */
 22  
 package net.sourceforge.combean.adapters.drasys.lp;
 23  
 
 24  
 import java.util.Enumeration;
 25  
 
 26  
 import net.sourceforge.combean.interfaces.mathprog.linalg.SparseVector;
 27  
 import net.sourceforge.combean.interfaces.mathprog.linalg.VectorIterator;
 28  
 import net.sourceforge.combean.interfaces.mathprog.linalg.VectorValue;
 29  
 import net.sourceforge.combean.interfaces.mathprog.lp.LPConstraint;
 30  
 import net.sourceforge.combean.interfaces.mathprog.lp.LPSolver;
 31  
 import net.sourceforge.combean.interfaces.mathprog.lp.LPVariable;
 32  
 import net.sourceforge.combean.interfaces.mathprog.lp.model.NoLabel;
 33  
 import net.sourceforge.combean.util.except.IllegalParameterException;
 34  
 import drasys.or.matrix.VectorI;
 35  
 import drasys.or.mp.ConstraintI;
 36  
 import drasys.or.mp.ConvergenceException;
 37  
 import drasys.or.mp.DuplicateException;
 38  
 import drasys.or.mp.InfeasibleException;
 39  
 import drasys.or.mp.InvalidException;
 40  
 import drasys.or.mp.NoSolutionException;
 41  
 import drasys.or.mp.Problem;
 42  
 import drasys.or.mp.ScaleException;
 43  
 import drasys.or.mp.SizableProblemI;
 44  
 import drasys.or.mp.UnboundedException;
 45  
 import drasys.or.mp.VariableI;
 46  
 import drasys.or.mp.lp.DenseSimplex;
 47  
 import drasys.or.mp.lp.LinearProgrammingI;
 48  
 
 49  
 /**
 50  
  * @author schickin
 51  
  *
 52  
  */
 53  
 public class SizableProblemIAsLPSolver implements LPSolver {
 54  
     
 55  
     private static final int DEFAULT_DIMENSION = 100;
 56  
     
 57  38
     private LinearProgrammingI draLP = null;
 58  38
     private SizableProblemI draProblem = null;
 59  
 
 60  38
     private byte objective = LPSolver.LPOBJ_UNDEFINED;
 61  
     
 62  38
     private byte lpStatus = LPSolver.LPOBJ_UNDEFINED;
 63  
     
 64  
     /**
 65  
      * 
 66  
      */
 67  
     public SizableProblemIAsLPSolver() {
 68  38
         super();
 69  
         
 70  38
         this.draLP = new DenseSimplex();
 71  38
         this.draProblem = new Problem(DEFAULT_DIMENSION, DEFAULT_DIMENSION);
 72  38
     }
 73  
     
 74  
     /**
 75  
      * 
 76  
      */
 77  
     public SizableProblemIAsLPSolver(LinearProgrammingI draLP) {
 78  0
         super();
 79  
         
 80  0
         this.draLP = draLP;
 81  0
         this.draProblem = new Problem(DEFAULT_DIMENSION, DEFAULT_DIMENSION);
 82  0
     }
 83  
     
 84  
     /**
 85  
      * 
 86  
      * 
 87  
      */
 88  
     public SizableProblemIAsLPSolver(
 89  
             LinearProgrammingI draLP,
 90  
             SizableProblemI draProblem) {
 91  0
         super();
 92  
         
 93  0
         this.draLP = draLP;
 94  0
         this.draProblem = draProblem;
 95  0
     }
 96  
 
 97  
     /* (non-Javadoc)
 98  
      * @see net.sourceforge.combean.interfaces.mathprog.lp.LPSolver#setInitialDimensions(int, int)
 99  
      */
 100  
     public void setInitialDimensions(int numRows, int numColumns) {
 101  38
         this.draProblem.setCapacity(numRows, numColumns);
 102  38
     }
 103  
 
 104  
     /* (non-Javadoc)
 105  
      * @see net.sourceforge.combean.interfaces.mathprog.lp.LPSolver#addVariable(net.sourceforge.combean.interfaces.mathprog.lp.LPVariable)
 106  
      */
 107  
     public int addVariable(LPVariable variable) {
 108  141
         VariableI draVar = null;
 109  
         try {
 110  141
             draVar = this.draProblem.newVariable(variable.getName());
 111  141
             draVar.setObjectiveCoefficient(variable.getCoeff());
 112  141
             if (variable.getLowerBound() != 0 ||
 113  
                     variable.getUpperBound() != Double.POSITIVE_INFINITY) {
 114  0
                 throw new IllegalParameterException(
 115  
                         "OR-Objects simplex only supports variables with bounds [0, infinity]");
 116  
             }
 117  141
             draVar.setLowerBound(variable.getLowerBound());
 118  141
             draVar.setUpperBound(variable.getUpperBound());
 119  0
         } catch (DuplicateException e) {
 120  0
             throw new IllegalParameterException("duplicate variable id", e);
 121  141
         }
 122  141
         return draVar.getColumnIndex();
 123  
     }
 124  
     
 125  5
     private static final byte[] relationCodeToDrasys =
 126  
         new byte[LPConstraint.REL_COUNT];
 127  
     
 128  
     static {
 129  5
         relationCodeToDrasys[LPConstraint.REL_EQUAL] = ConstraintI.EQUAL;
 130  5
         relationCodeToDrasys[LPConstraint.REL_GREATER] = ConstraintI.GREATER;
 131  5
         relationCodeToDrasys[LPConstraint.REL_LESS] = ConstraintI.LESS;
 132  5
     }
 133  
 
 134  
     /* (non-Javadoc)
 135  
      * @see net.sourceforge.combean.interfaces.mathprog.lp.LPSolver#addConstraint(net.sourceforge.combean.interfaces.mathprog.lp.LPConstraint)
 136  
      */
 137  
     public int addConstraint(LPConstraint constraint) {
 138  106
         ConstraintI draConstr = null;
 139  
         try {
 140  106
             draConstr = this.draProblem.newConstraint(constraint.getName());
 141  106
             draConstr.setRightHandSide(constraint.getRhs());
 142  106
             draConstr.setType(
 143  
                     relationCodeToDrasys[constraint.getRelation()]);
 144  106
             draConstr.setUpperRange(Double.POSITIVE_INFINITY);
 145  106
             draConstr.setLowerRange(Double.NEGATIVE_INFINITY);
 146  0
         } catch (DuplicateException e) {
 147  0
             throw new IllegalParameterException("duplicate constraint id", e);
 148  106
         }
 149  106
         return draConstr.getRowIndex();
 150  
     }
 151  
 
 152  
     /* (non-Javadoc)
 153  
      * @see net.sourceforge.combean.interfaces.mathprog.lp.LPSolver#addRow(net.sourceforge.combean.interfaces.mathprog.lp.LPRow)
 154  
      */
 155  
     public int addRow(LPConstraint constraint, SparseVector rowVec) {
 156  88
         int rowIdx = addConstraint(constraint);
 157  
         
 158  88
         VectorIterator<NoLabel> itRowVec = rowVec.iterator();
 159  334
         while (itRowVec.hasNext()) {
 160  246
             VectorValue<NoLabel> val = itRowVec.next();
 161  246
             this.draProblem.setCoefficientAt(rowIdx, val.index(),
 162  
                     val.doubleValue());
 163  246
         }
 164  
         
 165  88
         return rowIdx;
 166  
     }
 167  
 
 168  
     /* (non-Javadoc)
 169  
      * @see net.sourceforge.combean.interfaces.mathprog.lp.LPSolver#addColumn(net.sourceforge.combean.interfaces.mathprog.lp.LPColumn)
 170  
      */
 171  
     public int addColumn(LPVariable variable, SparseVector colVec) {
 172  12
         int colIdx = addVariable(variable);
 173  
         
 174  12
         VectorIterator<NoLabel> itColVec = colVec.iterator();
 175  36
         while (itColVec.hasNext()) {
 176  24
             VectorValue<NoLabel> val = itColVec.next();
 177  24
             this.draProblem.setCoefficientAt(val.index(), colIdx,
 178  
                     val.doubleValue());
 179  24
         }
 180  
         
 181  12
         return colIdx;
 182  
     }
 183  
 
 184  
     /* (non-Javadoc)
 185  
      * @see net.sourceforge.combean.interfaces.mathprog.lp.LPSolver#setObjective(byte)
 186  
      */
 187  
     public void setObjective(byte objective) {
 188  26
         this.objective = objective;
 189  26
     }
 190  
     
 191  
     /* (non-Javadoc)
 192  
      * @see net.sourceforge.combean.interfaces.mathprog.lp.LPSolver#freeze()
 193  
      */
 194  
     public void freeze() {
 195  26
         if (this.objective == LPSolver.LPOBJ_UNDEFINED) {
 196  0
             throw new IllegalParameterException("objective (min/max) must be set");
 197  
         }
 198  
         
 199  26
         if (this.objective == LPSolver.LPOBJ_MAX) {
 200  15
             adaptObjectiveFunction();
 201  
         }
 202  
 
 203  
         try {
 204  26
             this.draLP.setProblem(this.draProblem);
 205  
         }
 206  0
         catch (InvalidException e) {
 207  0
             throw new IllegalParameterException(
 208  
                     "OR-Objects LinearProgrammingI object can handle problem",
 209  
                     e);
 210  26
         }
 211  26
     }
 212  
 
 213  
     /* (non-Javadoc)
 214  
      * @see net.sourceforge.combean.interfaces.mathprog.lp.LPSolver#getNumColumns()
 215  
      */
 216  
     public int getNumColumns() {
 217  61
          return this.draProblem.sizeOfVariables();
 218  
     }
 219  
     
 220  
     /* (non-Javadoc)
 221  
      * @see net.sourceforge.combean.interfaces.mathprog.lp.LPSolver#getNumRows()
 222  
      */
 223  
     public int getNumRows() {
 224  76
          return this.draProblem.sizeOfConstraints();
 225  
     }
 226  
     
 227  
     /* (non-Javadoc)
 228  
      * @see net.sourceforge.combean.interfaces.mathprog.lp.LPSolver#getSolutionStatus()
 229  
      */
 230  
     public byte getSolutionStatus() {
 231  26
          return this.lpStatus;
 232  
     }
 233  
     
 234  
     /* (non-Javadoc)
 235  
      * @see net.sourceforge.combean.interfaces.mathprog.lp.LPSolver#getSolutionValue()
 236  
      */
 237  
     public double getSolutionValue() {
 238  15
          double result = 0.0;
 239  
          try {
 240  15
              result = this.draLP.getObjectiveValue();
 241  
          }
 242  0
          catch (NoSolutionException e) {
 243  0
              throw new IllegalParameterException(
 244  
                      "OR-Objects LinearProgrammingI object can not find a solution",
 245  
                      e);
 246  15
          }
 247  15
          if (this.objective == LPSolver.LPOBJ_MAX) {
 248  12
              result = -result;
 249  
          }
 250  15
          return result;
 251  
     }
 252  
     
 253  
     /* (non-Javadoc)
 254  
      * @see net.sourceforge.combean.interfaces.mathprog.lp.LPSolver#solve()
 255  
      */
 256  
     public void solve() {
 257  
         try {
 258  26
             this.draLP.solve();
 259  20
             this.lpStatus = LPSolver.LPSTAT_SOLVED;
 260  
         }
 261  3
         catch (InfeasibleException e) {
 262  3
             this.lpStatus = LPSolver.LPSTAT_INFEASIBLE;
 263  
         }
 264  3
         catch (UnboundedException e) {
 265  3
             this.lpStatus = LPSolver.LPSTAT_UNBOUNDED;
 266  
         }
 267  0
         catch (InvalidException e) {
 268  0
             throw new IllegalParameterException(
 269  
                     "OR-Objects LinearProgrammingI object can handle problem",
 270  
                     e);
 271  
         }
 272  0
         catch (NoSolutionException e) {
 273  0
             throw new IllegalParameterException(
 274  
                     "OR-Objects LinearProgrammingI object can not find a solution",
 275  
                     e);
 276  
         }
 277  0
         catch (ScaleException e) {
 278  0
             throw new IllegalParameterException(
 279  
                     "value out of numerically feasible bounds",
 280  
                     e);
 281  
         }
 282  0
         catch (ConvergenceException e) {
 283  0
             throw new IllegalParameterException(
 284  
                     "algorithm does not converge after max. number of iterations",
 285  
                     e);
 286  26
         }
 287  26
     }
 288  
 
 289  
     /* (non-Javadoc)
 290  
      * @see net.sourceforge.combean.interfaces.mathprog.lp.LPSolver#getSolution()
 291  
      */
 292  
     public SparseVector getSolution() {
 293  20
         VectorI solVec = null;
 294  
         try {
 295  20
             solVec = this.draLP.getSolution();
 296  
         }
 297  0
         catch (NoSolutionException e) {
 298  0
             throw new IllegalParameterException(
 299  
                     "OR-Objects LinearProgrammingI object cannot find a solution",
 300  
                     e);
 301  20
         }
 302  
         
 303  20
         return new VectorIAsSparseVector(solVec);
 304  
     }
 305  
 
 306  
     /**
 307  
      * @return Returns the draLP.
 308  
      */
 309  
     public LinearProgrammingI getDraLP() {
 310  0
         return this.draLP;
 311  
     }
 312  
     
 313  
     /**
 314  
      * @return Returns the draProblem.
 315  
      */
 316  
     public SizableProblemI getDraProblem() {
 317  0
         return this.draProblem;
 318  
     }
 319  
     
 320  
     public String toString() {
 321  0
         return getClass().getName() +
 322  
         " with embedded DRA-Problem: " + this.draProblem.toString();
 323  
     }
 324  
     
 325  
     private void adaptObjectiveFunction() {
 326  15
         Enumeration variables = this.draProblem.variables();
 327  51
         while (variables.hasMoreElements()) {
 328  36
             VariableI var = (VariableI) variables.nextElement();
 329  36
             var.setObjectiveCoefficient(-var.getObjectiveCoefficient());
 330  36
         }
 331  15
     }
 332  
 }