ClpSimplex.hpp
Go to the documentation of this file.
1 /* $Id: ClpSimplex.hpp 1551 2010-05-24 23:34:44Z mjs $ */
2 // Copyright (C) 2002, International Business Machines
3 // Corporation and others. All Rights Reserved.
4 
5 /*
6  Authors
7 
8  John Forrest
9 
10  */
11 #ifndef ClpSimplex_H
12 #define ClpSimplex_H
13 
14 #include <iostream>
15 #include <cfloat>
16 #include "ClpModel.hpp"
17 #include "ClpMatrixBase.hpp"
18 #include "ClpSolve.hpp"
19 class ClpDualRowPivot;
21 class ClpFactorization;
22 class CoinIndexedVector;
23 class ClpNonLinearCost;
24 class ClpNodeStuff;
25 class CoinStructuredModel;
26 class OsiClpSolverInterface;
27 class CoinWarmStartBasis;
28 class ClpDisasterHandler;
29 class ClpConstraint;
30 
49 class ClpSimplex : public ClpModel {
50  friend void ClpSimplexUnitTest(const std::string & mpsDir);
51 
52 public:
57  enum Status {
58  isFree = 0x00,
59  basic = 0x01,
60  atUpperBound = 0x02,
61  atLowerBound = 0x03,
62  superBasic = 0x04,
63  isFixed = 0x05
64  };
65  // For Dual
66  enum FakeBound {
67  noFake = 0x00,
68  lowerFake = 0x01,
69  upperFake = 0x02,
70  bothFake = 0x03
71  };
72 
75  ClpSimplex (bool emptyMessages = false );
77 
82  ClpSimplex(const ClpSimplex & rhs, int scalingMode = -1);
87  ClpSimplex(const ClpModel & rhs, int scalingMode = -1);
94  ClpSimplex (const ClpModel * wholeModel,
95  int numberRows, const int * whichRows,
96  int numberColumns, const int * whichColumns,
97  bool dropNames = true, bool dropIntegers = true,
98  bool fixOthers = false);
105  ClpSimplex (const ClpSimplex * wholeModel,
106  int numberRows, const int * whichRows,
107  int numberColumns, const int * whichColumns,
108  bool dropNames = true, bool dropIntegers = true,
109  bool fixOthers = false);
113  ClpSimplex (ClpSimplex * wholeModel,
114  int numberColumns, const int * whichColumns);
117  void originalModel(ClpSimplex * miniModel);
123  void setPersistenceFlag(int value);
125  void makeBaseModel();
127  void deleteBaseModel();
129  inline ClpSimplex * baseModel() const {
130  return baseModel_;
131  }
135  void setToBaseModel(ClpSimplex * model = NULL);
137  ClpSimplex & operator=(const ClpSimplex & rhs);
139  ~ClpSimplex ( );
140  // Ones below are just ClpModel with some changes
152  void loadProblem ( const ClpMatrixBase& matrix,
153  const double* collb, const double* colub,
154  const double* obj,
155  const double* rowlb, const double* rowub,
156  const double * rowObjective = NULL);
157  void loadProblem ( const CoinPackedMatrix& matrix,
158  const double* collb, const double* colub,
159  const double* obj,
160  const double* rowlb, const double* rowub,
161  const double * rowObjective = NULL);
162 
165  void loadProblem ( const int numcols, const int numrows,
166  const CoinBigIndex* start, const int* index,
167  const double* value,
168  const double* collb, const double* colub,
169  const double* obj,
170  const double* rowlb, const double* rowub,
171  const double * rowObjective = NULL);
173  void loadProblem ( const int numcols, const int numrows,
174  const CoinBigIndex* start, const int* index,
175  const double* value, const int * length,
176  const double* collb, const double* colub,
177  const double* obj,
178  const double* rowlb, const double* rowub,
179  const double * rowObjective = NULL);
184  int loadProblem ( CoinModel & modelObject, bool keepSolution = false);
186  int readMps(const char *filename,
187  bool keepNames = false,
188  bool ignoreErrors = false);
190  int readGMPL(const char *filename, const char * dataName,
191  bool keepNames = false);
194  int readLp(const char *filename, const double epsilon = 1e-5);
199  void borrowModel(ClpModel & otherModel);
200  void borrowModel(ClpSimplex & otherModel);
204  void getbackSolution(const ClpSimplex & smallModel, const int * whichRow, const int * whichColumn);
213  int loadNonLinear(void * info, int & numberConstraints,
214  ClpConstraint ** & constraints);
216 
222  int initialSolve(ClpSolve & options);
224  int initialSolve();
226  int initialDualSolve();
228  int initialPrimalSolve();
230  int initialBarrierSolve();
243  int dual(int ifValuesPass = 0, int startFinishOptions = 0);
244  // If using Debug
245  int dualDebug(int ifValuesPass = 0, int startFinishOptions = 0);
256  int primal(int ifValuesPass = 0, int startFinishOptions = 0);
262  int nonlinearSLP(int numberPasses, double deltaTolerance);
268  int nonlinearSLP(int numberConstraints, ClpConstraint ** constraints,
269  int numberPasses, double deltaTolerance);
272  int barrier(bool crossover = true);
275  int reducedGradient(int phase = 0);
277  int solve(CoinStructuredModel * model);
284  int loadProblem ( CoinStructuredModel & modelObject,
285  bool originalOrder = true, bool keepSolution = false);
300  int cleanup(int cleanupScaling);
321  int dualRanging(int numberCheck, const int * which,
322  double * costIncrease, int * sequenceIncrease,
323  double * costDecrease, int * sequenceDecrease,
324  double * valueIncrease = NULL, double * valueDecrease = NULL);
339  int primalRanging(int numberCheck, const int * which,
340  double * valueIncrease, int * sequenceIncrease,
341  double * valueDecrease, int * sequenceDecrease);
356  int writeBasis(const char *filename,
357  bool writeValues = false,
358  int formatType = 0) const;
361  int readBasis(const char *filename);
363  CoinWarmStartBasis * getBasis() const;
366  // Swaps factorization
379  int tightenPrimalBounds(double factor = 0.0, int doTight = 0, bool tightIntegers = false);
396  int crash(double gap, int pivot);
409  int strongBranching(int numberVariables, const int * variables,
410  double * newLower, double * newUpper,
411  double ** outputSolution,
412  int * outputStatus, int * outputIterations,
413  bool stopOnFirstInfeasible = true,
414  bool alwaysFinish = false,
415  int startFinishOptions = 0);
417  int fathom(void * stuff);
423  int fathomMany(void * stuff);
425  double doubleCheck();
427  int startFastDual2(ClpNodeStuff * stuff);
429  int fastDual2(ClpNodeStuff * stuff);
431  void stopFastDual2(ClpNodeStuff * stuff);
438  ClpSimplex * fastCrunch(ClpNodeStuff * stuff, int mode);
440 
448  int pivot();
449 
455  int primalPivotResult();
456 
463  int dualPivotResult();
464 
476  int startup(int ifValuesPass, int startFinishOptions = 0);
477  void finish(int startFinishOptions = 0);
478 
480  bool statusOfProblem(bool initial = false);
484 
487  inline bool primalFeasible() const {
489  return (numberPrimalInfeasibilities_ == 0);
490  }
492  inline bool dualFeasible() const {
493  return (numberDualInfeasibilities_ == 0);
494  }
496  inline ClpFactorization * factorization() const {
497  return factorization_;
498  }
500  bool sparseFactorization() const;
501  void setSparseFactorization(bool value);
503  int factorizationFrequency() const;
504  void setFactorizationFrequency(int value);
506  inline double dualBound() const {
507  return dualBound_;
508  }
509  void setDualBound(double value);
511  inline double infeasibilityCost() const {
512  return infeasibilityCost_;
513  }
514  void setInfeasibilityCost(double value);
531  inline int perturbation() const {
532  return perturbation_;
533  }
534  void setPerturbation(int value);
536  inline int algorithm() const {
537  return algorithm_;
538  }
540  inline void setAlgorithm(int value) {
541  algorithm_ = value;
542  }
544  bool isObjectiveLimitTestValid() const ;
546  inline double sumDualInfeasibilities() const {
548  }
549  inline void setSumDualInfeasibilities(double value) {
550  sumDualInfeasibilities_ = value;
551  }
553  inline double sumOfRelaxedDualInfeasibilities() const {
555  }
556  inline void setSumOfRelaxedDualInfeasibilities(double value) {
558  }
560  inline int numberDualInfeasibilities() const {
562  }
563  inline void setNumberDualInfeasibilities(int value) {
565  }
569  }
571  inline double sumPrimalInfeasibilities() const {
573  }
574  inline void setSumPrimalInfeasibilities(double value) {
576  }
578  inline double sumOfRelaxedPrimalInfeasibilities() const {
580  }
581  inline void setSumOfRelaxedPrimalInfeasibilities(double value) {
583  }
585  inline int numberPrimalInfeasibilities() const {
587  }
588  inline void setNumberPrimalInfeasibilities(int value) {
590  }
597  int saveModel(const char * fileName);
600  int restoreModel(const char * fileName);
601 
609  void checkSolution(int setToBounds = 0);
612  void checkSolutionInternal();
614  inline CoinIndexedVector * rowArray(int index) const {
615  return rowArray_[index];
616  }
618  inline CoinIndexedVector * columnArray(int index) const {
619  return columnArray_[index];
620  }
622 
623  /******************** End of most useful part **************/
629  int getSolution ( const double * rowActivities,
630  const double * columnActivities);
634  int getSolution ();
641  int createPiecewiseLinearCosts(const int * starts,
642  const double * lower, const double * gradient);
644  inline ClpDualRowPivot * dualRowPivot() const {
645  return dualRowPivot_;
646  }
649  return primalColumnPivot_;
650  }
652  inline bool goodAccuracy() const {
653  return (largestPrimalError_ < 1.0e-7 && largestDualError_ < 1.0e-7);
654  }
656  void returnModel(ClpSimplex & otherModel);
664  int internalFactorize(int solveType);
668  void restoreData(ClpDataSave saved);
670  void cleanStatus();
672  int factorize();
675  void computeDuals(double * givenDjs);
677  void computePrimals ( const double * rowActivities,
678  const double * columnActivities);
680  void add(double * array,
681  int column, double multiplier) const;
687  void unpack(CoinIndexedVector * rowArray) const ;
693  void unpack(CoinIndexedVector * rowArray, int sequence) const;
700  void unpackPacked(CoinIndexedVector * rowArray) ;
707  void unpackPacked(CoinIndexedVector * rowArray, int sequence);
708 protected:
713  int housekeeping(double objectiveChange);
716  void checkPrimalSolution(const double * rowActivities = NULL,
717  const double * columnActivies = NULL);
720  void checkDualSolution();
722  void checkBothSolutions();
727  double scaleObjective(double value);
729  int solveDW(CoinStructuredModel * model);
731  int solveBenders(CoinStructuredModel * model);
732 public:
743  void setValuesPassAction(double incomingInfeasibility,
744  double allowedInfeasibility);
746 
748 public:
750  inline double alphaAccuracy() const {
751  return alphaAccuracy_;
752  }
753  inline void setAlphaAccuracy(double value) {
754  alphaAccuracy_ = value;
755  }
756 public:
758  //inline double objectiveValue() const {
759  //return (objectiveValue_-bestPossibleImprovement_)*optimizationDirection_ - dblParam_[ClpObjOffset];
760  //}
762  inline void setDisasterHandler(ClpDisasterHandler * handler) {
763  disasterArea_ = handler;
764  }
767  return disasterArea_;
768  }
770  inline double largeValue() const {
771  return largeValue_;
772  }
773  void setLargeValue( double value) ;
775  inline double largestPrimalError() const {
776  return largestPrimalError_;
777  }
779  inline double largestDualError() const {
780  return largestDualError_;
781  }
783  inline void setLargestPrimalError(double value) {
784  largestPrimalError_ = value;
785  }
787  inline void setLargestDualError(double value) {
788  largestDualError_ = value;
789  }
791  inline double zeroTolerance() const {
792  return zeroTolerance_;/*factorization_->zeroTolerance();*/
793  }
795  inline void setZeroTolerance( double value) {
796  zeroTolerance_ = value;
797  }
799  inline int * pivotVariable() const {
800  return pivotVariable_;
801  }
803  inline bool automaticScaling() const {
804  return automaticScale_ != 0;
805  }
806  inline void setAutomaticScaling(bool onOff) {
807  automaticScale_ = onOff ? 1 : 0;
808  }
810  inline double currentDualTolerance() const {
811  return dualTolerance_;
812  }
813  inline void setCurrentDualTolerance(double value) {
814  dualTolerance_ = value;
815  }
817  inline double currentPrimalTolerance() const {
818  return primalTolerance_;
819  }
820  inline void setCurrentPrimalTolerance(double value) {
821  primalTolerance_ = value;
822  }
824  inline int numberRefinements() const {
825  return numberRefinements_;
826  }
827  void setNumberRefinements( int value) ;
829  inline double alpha() const {
830  return alpha_;
831  }
832  inline void setAlpha(double value) {
833  alpha_ = value;
834  }
836  inline double dualIn() const {
837  return dualIn_;
838  }
840  inline int pivotRow() const {
841  return pivotRow_;
842  }
843  inline void setPivotRow(int value) {
844  pivotRow_ = value;
845  }
847  double valueIncomingDual() const;
849 
850 protected:
856  int gutsOfSolution ( double * givenDuals,
857  const double * givenPrimals,
858  bool valuesPass = false);
860  void gutsOfDelete(int type);
862  void gutsOfCopy(const ClpSimplex & rhs);
874  bool createRim(int what, bool makeRowCopy = false, int startFinishOptions = 0);
876  void createRim1(bool initial);
878  void createRim4(bool initial);
880  void createRim5(bool initial);
885  void deleteRim(int getRidOfFactorizationData = 2);
887  bool sanityCheck();
889 public:
894  inline double * solutionRegion(int section) const {
895  if (!section) return rowActivityWork_;
896  else return columnActivityWork_;
897  }
898  inline double * djRegion(int section) const {
899  if (!section) return rowReducedCost_;
900  else return reducedCostWork_;
901  }
902  inline double * lowerRegion(int section) const {
903  if (!section) return rowLowerWork_;
904  else return columnLowerWork_;
905  }
906  inline double * upperRegion(int section) const {
907  if (!section) return rowUpperWork_;
908  else return columnUpperWork_;
909  }
910  inline double * costRegion(int section) const {
911  if (!section) return rowObjectiveWork_;
912  else return objectiveWork_;
913  }
915  inline double * solutionRegion() const {
916  return solution_;
917  }
918  inline double * djRegion() const {
919  return dj_;
920  }
921  inline double * lowerRegion() const {
922  return lower_;
923  }
924  inline double * upperRegion() const {
925  return upper_;
926  }
927  inline double * costRegion() const {
928  return cost_;
929  }
930  inline Status getStatus(int sequence) const {
931  return static_cast<Status> (status_[sequence] & 7);
932  }
933  inline void setStatus(int sequence, Status newstatus) {
934  unsigned char & st_byte = status_[sequence];
935  st_byte = static_cast<unsigned char>(st_byte & ~7);
936  st_byte = static_cast<unsigned char>(st_byte | newstatus);
937  }
939  bool startPermanentArrays();
944  void setInitialDenseFactorization(bool onOff);
945  bool initialDenseFactorization() const;
947  inline int sequenceIn() const {
948  return sequenceIn_;
949  }
950  inline int sequenceOut() const {
951  return sequenceOut_;
952  }
954  inline void setSequenceIn(int sequence) {
955  sequenceIn_ = sequence;
956  }
957  inline void setSequenceOut(int sequence) {
958  sequenceOut_ = sequence;
959  }
961  inline int directionIn() const {
962  return directionIn_;
963  }
964  inline int directionOut() const {
965  return directionOut_;
966  }
968  inline void setDirectionIn(int direction) {
969  directionIn_ = direction;
970  }
971  inline void setDirectionOut(int direction) {
972  directionOut_ = direction;
973  }
975  inline double valueOut() const {
976  return valueOut_;
977  }
979  inline void setValueOut(double value) {
980  valueOut_ = value;
981  }
983  inline void setLowerOut(double value) {
984  lowerOut_ = value;
985  }
987  inline void setUpperOut(double value) {
988  upperOut_ = value;
989  }
991  inline void setTheta(double value) {
992  theta_ = value;
993  }
995  inline int isColumn(int sequence) const {
996  return sequence < numberColumns_ ? 1 : 0;
997  }
999  inline int sequenceWithin(int sequence) const {
1000  return sequence < numberColumns_ ? sequence : sequence - numberColumns_;
1001  }
1003  inline double solution(int sequence) {
1004  return solution_[sequence];
1005  }
1007  inline double & solutionAddress(int sequence) {
1008  return solution_[sequence];
1009  }
1010  inline double reducedCost(int sequence) {
1011  return dj_[sequence];
1012  }
1013  inline double & reducedCostAddress(int sequence) {
1014  return dj_[sequence];
1015  }
1016  inline double lower(int sequence) {
1017  return lower_[sequence];
1018  }
1020  inline double & lowerAddress(int sequence) {
1021  return lower_[sequence];
1022  }
1023  inline double upper(int sequence) {
1024  return upper_[sequence];
1025  }
1027  inline double & upperAddress(int sequence) {
1028  return upper_[sequence];
1029  }
1030  inline double cost(int sequence) {
1031  return cost_[sequence];
1032  }
1034  inline double & costAddress(int sequence) {
1035  return cost_[sequence];
1036  }
1038  inline double originalLower(int iSequence) const {
1039  if (iSequence < numberColumns_) return columnLower_[iSequence];
1040  else
1041  return rowLower_[iSequence-numberColumns_];
1042  }
1044  inline double originalUpper(int iSequence) const {
1045  if (iSequence < numberColumns_) return columnUpper_[iSequence];
1046  else
1047  return rowUpper_[iSequence-numberColumns_];
1048  }
1050  inline double theta() const {
1051  return theta_;
1052  }
1055  inline double bestPossibleImprovement() const {
1056  return bestPossibleImprovement_;
1057  }
1059  inline ClpNonLinearCost * nonLinearCost() const {
1060  return nonLinearCost_;
1061  }
1074  inline int moreSpecialOptions() const {
1075  return moreSpecialOptions_;
1076  }
1089  inline void setMoreSpecialOptions(int value) {
1090  moreSpecialOptions_ = value;
1091  }
1093 
1095  inline void setFakeBound(int sequence, FakeBound fakeBound) {
1096  unsigned char & st_byte = status_[sequence];
1097  st_byte = static_cast<unsigned char>(st_byte & ~24);
1098  st_byte = static_cast<unsigned char>(st_byte | (fakeBound << 3));
1099  }
1100  inline FakeBound getFakeBound(int sequence) const {
1101  return static_cast<FakeBound> ((status_[sequence] >> 3) & 3);
1102  }
1103  inline void setRowStatus(int sequence, Status newstatus) {
1104  unsigned char & st_byte = status_[sequence+numberColumns_];
1105  st_byte = static_cast<unsigned char>(st_byte & ~7);
1106  st_byte = static_cast<unsigned char>(st_byte | newstatus);
1107  }
1108  inline Status getRowStatus(int sequence) const {
1109  return static_cast<Status> (status_[sequence+numberColumns_] & 7);
1110  }
1111  inline void setColumnStatus(int sequence, Status newstatus) {
1112  unsigned char & st_byte = status_[sequence];
1113  st_byte = static_cast<unsigned char>(st_byte & ~7);
1114  st_byte = static_cast<unsigned char>(st_byte | newstatus);
1115  }
1116  inline Status getColumnStatus(int sequence) const {
1117  return static_cast<Status> (status_[sequence] & 7);
1118  }
1119  inline void setPivoted( int sequence) {
1120  status_[sequence] = static_cast<unsigned char>(status_[sequence] | 32);
1121  }
1122  inline void clearPivoted( int sequence) {
1123  status_[sequence] = static_cast<unsigned char>(status_[sequence] & ~32);
1124  }
1125  inline bool pivoted(int sequence) const {
1126  return (((status_[sequence] >> 5) & 1) != 0);
1127  }
1129  void setFlagged( int sequence);
1130  inline void clearFlagged( int sequence) {
1131  status_[sequence] = static_cast<unsigned char>(status_[sequence] & ~64);
1132  }
1133  inline bool flagged(int sequence) const {
1134  return ((status_[sequence] & 64) != 0);
1135  }
1137  inline void setActive( int iRow) {
1138  status_[iRow] = static_cast<unsigned char>(status_[iRow] | 128);
1139  }
1140  inline void clearActive( int iRow) {
1141  status_[iRow] = static_cast<unsigned char>(status_[iRow] & ~128);
1142  }
1143  inline bool active(int iRow) const {
1144  return ((status_[iRow] & 128) != 0);
1145  }
1148  void createStatus() ;
1151  void allSlackBasis(bool resetSolution = false);
1152 
1154  inline int lastBadIteration() const {
1155  return lastBadIteration_;
1156  }
1158  inline int progressFlag() const {
1159  return (progressFlag_ & 3);
1160  }
1162  inline void forceFactorization(int value) {
1163  forceFactorization_ = value;
1164  }
1166  inline double rawObjectiveValue() const {
1167  return objectiveValue_;
1168  }
1170  void computeObjectiveValue(bool useWorkingSolution = false);
1176  inline int numberExtraRows() const {
1177  return numberExtraRows_;
1178  }
1181  inline int maximumBasic() const {
1182  return maximumBasic_;
1183  }
1185  inline int baseIteration() const {
1186  return baseIteration_;
1187  }
1189  void generateCpp( FILE * fp, bool defaultFactor = false);
1193  void setEmptyFactorization();
1195  void moveInfo(const ClpSimplex & rhs, bool justStatus = false);
1197 
1199  // These are only to be used using startFinishOptions (ClpSimplexDual, ClpSimplexPrimal)
1200  // *** At present only without scaling
1201  // *** Slacks havve -1.0 element (so == row activity) - take care
1203  void getBInvARow(int row, double* z, double * slack = NULL);
1204 
1206  void getBInvRow(int row, double* z);
1207 
1209  void getBInvACol(int col, double* vec);
1210 
1212  void getBInvCol(int col, double* vec);
1213 
1218  void getBasics(int* index);
1219 
1221  //-------------------------------------------------------------------------
1225  void setObjectiveCoefficient( int elementIndex, double elementValue );
1227  inline void setObjCoeff( int elementIndex, double elementValue ) {
1228  setObjectiveCoefficient( elementIndex, elementValue);
1229  }
1230 
1233  void setColumnLower( int elementIndex, double elementValue );
1234 
1237  void setColumnUpper( int elementIndex, double elementValue );
1238 
1240  void setColumnBounds( int elementIndex,
1241  double lower, double upper );
1242 
1251  void setColumnSetBounds(const int* indexFirst,
1252  const int* indexLast,
1253  const double* boundList);
1254 
1257  inline void setColLower( int elementIndex, double elementValue ) {
1258  setColumnLower(elementIndex, elementValue);
1259  }
1262  inline void setColUpper( int elementIndex, double elementValue ) {
1263  setColumnUpper(elementIndex, elementValue);
1264  }
1265 
1267  inline void setColBounds( int elementIndex,
1268  double newlower, double newupper ) {
1269  setColumnBounds(elementIndex, newlower, newupper);
1270  }
1271 
1278  inline void setColSetBounds(const int* indexFirst,
1279  const int* indexLast,
1280  const double* boundList) {
1281  setColumnSetBounds(indexFirst, indexLast, boundList);
1282  }
1283 
1286  void setRowLower( int elementIndex, double elementValue );
1287 
1290  void setRowUpper( int elementIndex, double elementValue ) ;
1291 
1293  void setRowBounds( int elementIndex,
1294  double lower, double upper ) ;
1295 
1302  void setRowSetBounds(const int* indexFirst,
1303  const int* indexLast,
1304  const double* boundList);
1306  void resize (int newNumberRows, int newNumberColumns);
1307 
1309 
1311 protected:
1312 
1337  double largeValue_;
1345  double dualBound_;
1347  double alpha_;
1349  double theta_;
1351  double lowerIn_;
1353  double valueIn_;
1355  double upperIn_;
1357  double dualIn_;
1359  double lowerOut_;
1361  double valueOut_;
1363  double upperOut_;
1365  double dualOut_;
1383  double * lower_;
1385  double * rowLowerWork_;
1389  double * upper_;
1391  double * rowUpperWork_;
1395  double * cost_;
1399  double * objectiveWork_;
1401  CoinIndexedVector * rowArray_[6];
1403  CoinIndexedVector * columnArray_[6];
1417  double * dj_;
1423  double * solution_;
1445  double * savedSolution_;
1466  unsigned char * saveStatus_;
1514 public:
1516  mutable int spareIntArray_[4];
1518  mutable double spareDoubleArray_[4];
1519 protected:
1523 };
1524 //#############################################################################
1533 void
1534 ClpSimplexUnitTest(const std::string & mpsDir);
1535 
1536 // For Devex stuff
1537 #define DEVEX_TRY_NORM 1.0e-4
1538 #define DEVEX_ADD_ONE 1.0
1539 #endif