Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members

ClpMain.cpp

00001 // Copyright (C) 2002, International Business Machines
00002 // Corporation and others.  All Rights Reserved.
00003    
00004 #include "CoinPragma.hpp"
00005 
00006 #include <cassert>
00007 #include <cstdio>
00008 #include <cmath>
00009 #include <cfloat>
00010 #include <string>
00011 #include <iostream>
00012 
00013 
00014 #include "CoinPragma.hpp"
00015 #include "CoinHelperFunctions.hpp"
00016 #define CLPVERSION "0.99.1"
00017 
00018 #include "CoinMpsIO.hpp"
00019 
00020 #include "ClpFactorization.hpp"
00021 #include "CoinTime.hpp"
00022 #include "ClpSimplex.hpp"
00023 #include "ClpSolve.hpp"
00024 #include "ClpPackedMatrix.hpp"
00025 #include "ClpPlusMinusOneMatrix.hpp"
00026 #include "ClpNetworkMatrix.hpp"
00027 #include "ClpDualRowSteepest.hpp"
00028 #include "ClpDualRowDantzig.hpp"
00029 #include "ClpLinearObjective.hpp"
00030 #include "ClpPrimalColumnSteepest.hpp"
00031 #include "ClpPrimalColumnDantzig.hpp"
00032 #include "ClpPresolve.hpp"
00033 
00034 // For Branch and bound
00035 //  #include "OsiClpSolverInterface.hpp"
00036 //  #include "OsiCuts.hpp"
00037 //  #include "OsiRowCut.hpp"
00038 //  #include "OsiColCut.hpp"
00039 
00040 #ifdef DMALLOC
00041 #include "dmalloc.h"
00042 #endif
00043 
00044 static double totalTime=0.0;
00045 
00046 //#############################################################################
00047 
00048 #ifdef NDEBUG
00049 #undef NDEBUG
00050 #endif
00051 
00052 int mainTest (int argc, const char *argv[],bool doDual,
00053               ClpSimplex empty, bool doPresolve,int doIdiot);
00054 enum ClpParameterType {
00055   GENERALQUERY=-100,
00056   
00057   DUALTOLERANCE=1,PRIMALTOLERANCE,DUALBOUND,PRIMALWEIGHT,MAXTIME,OBJSCALE,
00058 
00059   LOGLEVEL=101,MAXFACTOR,PERTVALUE,MAXITERATION,PRESOLVEPASS,IDIOT,SPRINT,
00060   
00061   DIRECTION=201,DUALPIVOT,SCALING,ERRORSALLOWED,KEEPNAMES,SPARSEFACTOR,
00062   PRIMALPIVOT,PRESOLVE,CRASH,BIASLU,PERTURBATION,MESSAGES,
00063   
00064   DIRECTORY=301,IMPORT,EXPORT,RESTORE,SAVE,DUALSIMPLEX,PRIMALSIMPLEX,
00065   MAXIMIZE,MINIMIZE,EXIT,STDIN,UNITTEST,NETLIB_DUAL,NETLIB_PRIMAL,SOLUTION,
00066   TIGHTEN,FAKEBOUND,HELP,PLUSMINUS,NETWORK,ALLSLACK,REVERSE,BARRIER,
00067 
00068   INVALID=1000
00069 };
00070 static void printit(const char * input)
00071 {
00072   int length =strlen(input);
00073   char temp[101];
00074   int i;
00075   int n=0;
00076   for (i=0;i<length;i++) {
00077     if (input[i]=='\n') {
00078       temp[n]='\0';
00079       std::cout<<temp<<std::endl;
00080       n=0;
00081     } else if (n>=65&&input[i]==' ') {
00082       temp[n]='\0';
00083       std::cout<<temp<<std::endl;
00084       n=0;
00085     } else if (n||input[i]!=' ') {
00086       temp[n++]=input[i];
00087     }
00088   }
00089   if (n) {
00090     temp[n]='\0';
00091     std::cout<<temp<<std::endl;
00092   }
00093 }
00095 class ClpItem {
00096 
00097 public:
00098 
00101 
00102   ClpItem (  );
00103   ClpItem (std::string name, std::string help,
00104            double lower, double upper, ClpParameterType type,bool display=true);
00105   ClpItem (std::string name, std::string help,
00106            int lower, int upper, ClpParameterType type,bool display=true);
00107   // Other strings will be added by insert
00108   ClpItem (std::string name, std::string help, std::string firstValue,
00109            ClpParameterType type,int defaultIndex=0,bool display=true);
00110   // Action
00111   ClpItem (std::string name, std::string help,
00112            ClpParameterType type,int indexNumber=-1,bool display=true);
00114   ClpItem(const ClpItem &);
00116     ClpItem & operator=(const ClpItem & rhs);
00118   ~ClpItem (  );
00120 
00123 
00124   void append(std::string keyWord);
00126   void addHelp(std::string keyWord);
00128   inline std::string  name(  ) const {
00129     return name_;
00130   };
00132   inline std::string  shortHelp(  ) const {
00133     return shortHelp_;
00134   };
00136   int setDoubleParameter(ClpSimplex * model, double value) const;
00138   double doubleParameter(ClpSimplex * model) const;
00140   int setIntParameter(ClpSimplex * model, int value) const;
00142   int intParameter(ClpSimplex * model) const;
00144   std::string matchName (  ) const;
00146   int parameterOption ( std::string check ) const;
00148   void printOptions (  ) const;
00150   inline std::string currentOption (  ) const
00151   { return definedKeyWords_[currentKeyWord_]; };
00153   inline void setCurrentOption ( int value )
00154   { currentKeyWord_=value; };
00156   inline void setIntValue ( int value )
00157   { intValue_=value; };
00158   inline int intValue () const
00159   { return intValue_; };
00161   inline void setDoubleValue ( double value )
00162   { doubleValue_=value; };
00163   inline double doubleValue () const
00164   { return doubleValue_; };
00166   inline void setStringValue ( std::string value )
00167   { stringValue_=value; };
00168   inline std::string stringValue () const
00169   { return stringValue_; };
00171   int matches (std::string input) const;
00173   inline ClpParameterType type() const
00174   { return type_;};
00176   inline bool displayThis() const
00177   { return display_;};
00179   inline void setLonghelp(const std::string help) 
00180   {longHelp_=help;};
00182   void printLongHelp() const;
00184   void printString() const;
00186   inline int indexNumber() const
00187   { return indexNumber_;};
00188 private:
00190   void gutsOfConstructor();
00192 
00193 private:
00194 
00199   // Type see ClpParameterType
00200   ClpParameterType type_;
00202   double lowerDoubleValue_;
00203   double upperDoubleValue_;
00205   int lowerIntValue_;
00206   int upperIntValue_;
00207   // Length of name
00208   unsigned int lengthName_;
00209   // Minimum match
00210   unsigned int lengthMatch_;
00212   std::vector<std::string> definedKeyWords_;
00214   std::string name_;
00216   std::string shortHelp_;
00218   std::string longHelp_;
00220   ClpParameterType action_;
00222   int currentKeyWord_;
00224   bool display_;
00226   int intValue_;
00228   double doubleValue_;
00230   std::string stringValue_;
00232   int indexNumber_;
00234 };
00235 //#############################################################################
00236 // Constructors / Destructor / Assignment
00237 //#############################################################################
00238 
00239 //-------------------------------------------------------------------
00240 // Default Constructor 
00241 //-------------------------------------------------------------------
00242 ClpItem::ClpItem () 
00243   : type_(INVALID),
00244     lowerDoubleValue_(0.0),
00245     upperDoubleValue_(0.0),
00246     lowerIntValue_(0),
00247     upperIntValue_(0),
00248     lengthName_(0),
00249     lengthMatch_(0),
00250     definedKeyWords_(),
00251     name_(),
00252     shortHelp_(),
00253     longHelp_(),
00254     action_(INVALID),
00255     currentKeyWord_(-1),
00256     display_(false),
00257     intValue_(-1),
00258     doubleValue_(-1.0),
00259     stringValue_(""),
00260     indexNumber_(INVALID)
00261 {
00262 }
00263 // Other constructors
00264 ClpItem::ClpItem (std::string name, std::string help,
00265            double lower, double upper, ClpParameterType type,bool display)
00266   : type_(type),
00267     lowerIntValue_(0),
00268     upperIntValue_(0),
00269     definedKeyWords_(),
00270     name_(name),
00271     shortHelp_(help),
00272     longHelp_(),
00273     action_(type),
00274     currentKeyWord_(-1),
00275     display_(display),
00276     intValue_(-1),
00277     doubleValue_(-1.0),
00278     stringValue_(""),
00279     indexNumber_(type)
00280 {
00281   lowerDoubleValue_ = lower;
00282   upperDoubleValue_ = upper;
00283   gutsOfConstructor();
00284 }
00285 ClpItem::ClpItem (std::string name, std::string help,
00286            int lower, int upper, ClpParameterType type,bool display)
00287   : type_(type),
00288     lowerDoubleValue_(0.0),
00289     upperDoubleValue_(0.0),
00290     definedKeyWords_(),
00291     name_(name),
00292     shortHelp_(help),
00293     longHelp_(),
00294     action_(type),
00295     currentKeyWord_(-1),
00296     display_(display),
00297     intValue_(-1),
00298     doubleValue_(-1.0),
00299     stringValue_(""),
00300     indexNumber_(type)
00301 {
00302   gutsOfConstructor();
00303   lowerIntValue_ = lower;
00304   upperIntValue_ = upper;
00305 }
00306 // Other strings will be added by append
00307 ClpItem::ClpItem (std::string name, std::string help, 
00308                   std::string firstValue,
00309                   ClpParameterType type,
00310                   int defaultIndex,bool display)
00311   : type_(type),
00312     lowerDoubleValue_(0.0),
00313     upperDoubleValue_(0.0),
00314     lowerIntValue_(0),
00315     upperIntValue_(0),
00316     definedKeyWords_(),
00317     name_(name),
00318     shortHelp_(help),
00319     longHelp_(),
00320     action_(type),
00321     currentKeyWord_(defaultIndex),
00322     display_(display),
00323     intValue_(-1),
00324     doubleValue_(-1.0),
00325     stringValue_(""),
00326     indexNumber_(type)
00327 {
00328   gutsOfConstructor();
00329   definedKeyWords_.push_back(firstValue);
00330 }
00331 // Action
00332 ClpItem::ClpItem (std::string name, std::string help,
00333            ClpParameterType type,int indexNumber,bool display)
00334   : type_(type),
00335     lowerDoubleValue_(0.0),
00336     upperDoubleValue_(0.0),
00337     lowerIntValue_(0),
00338     upperIntValue_(0),
00339     definedKeyWords_(),
00340     name_(name),
00341     shortHelp_(help),
00342     longHelp_(),
00343     action_(type),
00344     currentKeyWord_(-1),
00345     display_(display),
00346     intValue_(-1),
00347     doubleValue_(-1.0),
00348     stringValue_("")
00349 {
00350   if (indexNumber<0)
00351     indexNumber_=type;
00352   else
00353     indexNumber_=indexNumber;
00354   gutsOfConstructor();
00355 }
00356 
00357 //-------------------------------------------------------------------
00358 // Copy constructor 
00359 //-------------------------------------------------------------------
00360 ClpItem::ClpItem (const ClpItem & rhs) 
00361 {  
00362   type_ = rhs.type_;
00363   lowerDoubleValue_ = rhs.lowerDoubleValue_;
00364   upperDoubleValue_ = rhs.upperDoubleValue_;
00365   lowerIntValue_ = rhs.lowerIntValue_;
00366   upperIntValue_ = rhs.upperIntValue_;
00367   lengthName_ = rhs.lengthName_;
00368   lengthMatch_ = rhs.lengthMatch_;
00369   definedKeyWords_ = rhs.definedKeyWords_;
00370   name_ = rhs.name_;
00371   shortHelp_ = rhs.shortHelp_;
00372   longHelp_ = rhs.longHelp_;
00373   action_ = rhs.action_;
00374   currentKeyWord_ = rhs.currentKeyWord_;
00375   display_=rhs.display_;
00376   intValue_=rhs.intValue_;
00377   doubleValue_=rhs.doubleValue_;
00378   stringValue_=rhs.stringValue_;
00379   indexNumber_=rhs.indexNumber_;
00380 }
00381 
00382 //-------------------------------------------------------------------
00383 // Destructor 
00384 //-------------------------------------------------------------------
00385 ClpItem::~ClpItem ()
00386 {
00387 }
00388 
00389 //----------------------------------------------------------------
00390 // Assignment operator 
00391 //-------------------------------------------------------------------
00392 ClpItem &
00393 ClpItem::operator=(const ClpItem& rhs)
00394 {
00395   if (this != &rhs) {
00396     type_ = rhs.type_;
00397     lowerDoubleValue_ = rhs.lowerDoubleValue_;
00398     upperDoubleValue_ = rhs.upperDoubleValue_;
00399     lowerIntValue_ = rhs.lowerIntValue_;
00400     upperIntValue_ = rhs.upperIntValue_;
00401     lengthName_ = rhs.lengthName_;
00402     lengthMatch_ = rhs.lengthMatch_;
00403     definedKeyWords_ = rhs.definedKeyWords_;
00404     name_ = rhs.name_;
00405     shortHelp_ = rhs.shortHelp_;
00406     longHelp_ = rhs.longHelp_;
00407     action_ = rhs.action_;
00408     currentKeyWord_ = rhs.currentKeyWord_;
00409     display_=rhs.display_;
00410     intValue_=rhs.intValue_;
00411     doubleValue_=rhs.doubleValue_;
00412     stringValue_=rhs.stringValue_;
00413     indexNumber_=rhs.indexNumber_;
00414   }
00415   return *this;
00416 }
00417 void 
00418 ClpItem::gutsOfConstructor()
00419 {
00420   unsigned int  shriekPos = name_.find('!');
00421   lengthName_ = name_.length();
00422   if ( shriekPos==std::string::npos ) {
00423     //does not contain '!'
00424     lengthMatch_= lengthName_;
00425   } else {
00426     lengthMatch_=shriekPos;
00427     name_ = name_.substr(0,shriekPos)+name_.substr(shriekPos+1);
00428     lengthName_--;
00429   }
00430 }
00431 // Insert string (only valid for keywords)
00432 void 
00433 ClpItem::append(std::string keyWord)
00434 {
00435   definedKeyWords_.push_back(keyWord);
00436 }
00437 
00438 int 
00439 ClpItem::matches (std::string input) const
00440 {
00441   // look up strings to do more elegantly
00442   if (input.length()>lengthName_) {
00443     return 0;
00444   } else {
00445     unsigned int i;
00446     for (i=0;i<input.length();i++) {
00447       if (tolower(name_[i])!=tolower(input[i])) 
00448         break;
00449     }
00450     if (i<input.length()) {
00451       return 0;
00452     } else if (i>=lengthMatch_) {
00453       return 1;
00454     } else {
00455       // matched but too short
00456       return 2;
00457     }
00458   }
00459 }
00460 // Returns name which could match
00461 std::string 
00462 ClpItem::matchName (  ) const
00463 { 
00464   if (lengthMatch_==lengthName_) 
00465     return name_;
00466   else
00467     return name_.substr(0,lengthMatch_)+"("+name_.substr(lengthMatch_)+")";
00468 }
00469 
00470 // Returns parameter option which matches (-1 if none)
00471 int 
00472 ClpItem::parameterOption ( std::string check ) const
00473 {
00474   int numberItems = definedKeyWords_.size();
00475   if (!numberItems) {
00476     return -1;
00477   } else {
00478     int whichItem=0;
00479     unsigned int it;
00480     for (it=0;it<definedKeyWords_.size();it++) {
00481       std::string thisOne = definedKeyWords_[it];
00482       unsigned int  shriekPos = thisOne.find('!');
00483       unsigned int length1 = thisOne.length();
00484       unsigned int length2 = length1;
00485       if ( shriekPos!=std::string::npos ) {
00486         //contains '!'
00487         length2 = shriekPos;
00488         thisOne = thisOne.substr(0,shriekPos)+
00489           thisOne.substr(shriekPos+1);
00490         length1 = thisOne.length();
00491       }
00492       if (check.length()<=length1) {
00493         unsigned int i;
00494         for (i=0;i<check.length();i++) {
00495           if (tolower(thisOne[i])!=tolower(check[i])) 
00496             break;
00497         }
00498         if (i<check.length()) {
00499           whichItem++;
00500         } else if (i>=length2) {
00501           break;
00502         } 
00503       } else {
00504         whichItem++;
00505       }
00506     }
00507     if (whichItem<numberItems)
00508       return whichItem;
00509     else
00510       return -1;
00511   }
00512 }
00513 // Prints parameter options
00514 void 
00515 ClpItem::printOptions (  ) const
00516 {
00517   std::cout<<"Possible options for "<<name_<<" are:"<<std::endl;
00518   unsigned int it;
00519   for (it=0;it<definedKeyWords_.size();it++) {
00520     std::string thisOne = definedKeyWords_[it];
00521     unsigned int  shriekPos = thisOne.find('!');
00522     if ( shriekPos!=std::string::npos ) {
00523       //contains '!'
00524       thisOne = thisOne.substr(0,shriekPos)+
00525         "("+thisOne.substr(shriekPos+1)+")";
00526     }
00527     std::cout<<thisOne<<std::endl;
00528   }
00529 }
00530 // Print action and string
00531 void 
00532 ClpItem::printString() const
00533 {
00534   if (name_=="directory")
00535     std::cout<<"Current working directory is "<<stringValue_<<std::endl;
00536   else
00537     std::cout<<"Current default (if $ as parameter) for "<<name_
00538              <<" is "<<stringValue_<<std::endl;
00539 }
00540 int
00541 ClpItem::setDoubleParameter (ClpSimplex * model,double value) const
00542 {
00543   double oldValue = doubleParameter(model);
00544   if (value<lowerDoubleValue_||value>upperDoubleValue_) {
00545     std::cout<<value<<" was provided for "<<name_<<
00546       " - valid range is "<<lowerDoubleValue_<<" to "<<
00547       upperDoubleValue_<<std::endl;
00548     return 1;
00549   } else {
00550     std::cout<<name_<<" was changed from "<<oldValue<<" to "
00551              <<value<<std::endl;
00552     switch(type_) {
00553     case DUALTOLERANCE:
00554       model->setDualTolerance(value);
00555       break;
00556     case PRIMALTOLERANCE:
00557       model->setPrimalTolerance(value);
00558       break;
00559     case DUALBOUND:
00560       model->setDualBound(value);
00561       break;
00562     case PRIMALWEIGHT:
00563       model->setInfeasibilityCost(value);
00564       break;
00565     case MAXTIME:
00566       model->setMaximumSeconds(value);
00567       break;
00568     case OBJSCALE:
00569       model->setOptimizationDirection(value);
00570       break;
00571     default:
00572       abort();
00573     }
00574     return 0;
00575   }
00576 }
00577 double 
00578 ClpItem::doubleParameter (ClpSimplex * model) const
00579 {
00580   double value;
00581   switch(type_) {
00582   case DUALTOLERANCE:
00583     value=model->dualTolerance();
00584     break;
00585   case PRIMALTOLERANCE:
00586     value=model->primalTolerance();
00587     break;
00588   case DUALBOUND:
00589     value=model->dualBound();
00590     break;
00591   case PRIMALWEIGHT:
00592     value=model->infeasibilityCost();
00593     break;
00594   case MAXTIME:
00595     value=model->maximumSeconds();
00596     break;
00597   case OBJSCALE:
00598     value=model->optimizationDirection();
00599     break;
00600   default:
00601     abort();
00602   }
00603   return value;
00604 }
00605 int 
00606 ClpItem::setIntParameter (ClpSimplex * model,int value) const
00607 {
00608   int oldValue = intParameter(model);
00609   if (value<lowerIntValue_||value>upperIntValue_) {
00610     std::cout<<value<<" was provided for "<<name_<<
00611       " - valid range is "<<lowerIntValue_<<" to "<<
00612       upperIntValue_<<std::endl;
00613     return 1;
00614   } else {
00615     std::cout<<name_<<" was changed from "<<oldValue<<" to "
00616              <<value<<std::endl;
00617     switch(type_) {
00618     case LOGLEVEL:
00619       model->setLogLevel(value);
00620       break;
00621     case MAXFACTOR:
00622       model->factorization()->maximumPivots(value);
00623       break;
00624     case PERTVALUE:
00625       model->setPerturbation(value);
00626       break;
00627     case MAXITERATION:
00628       model->setMaximumIterations(value);
00629       break;
00630     default:
00631       abort();
00632     }
00633     return 0;
00634   }
00635 }
00636 int 
00637 ClpItem::intParameter (ClpSimplex * model) const
00638 {
00639   int value;
00640   switch(type_) {
00641   case LOGLEVEL:
00642     value=model->logLevel();
00643     break;
00644   case MAXFACTOR:
00645     value=model->factorization()->maximumPivots();
00646     break;
00647     break;
00648   case PERTVALUE:
00649     value=model->perturbation();
00650     break;
00651   case MAXITERATION:
00652     value=model->maximumIterations();
00653     break;
00654   default:
00655     value=-1;
00656     break;
00657   }
00658   return value;
00659 }
00660 // Print Long help
00661 void 
00662 ClpItem::printLongHelp() const
00663 {
00664   if (type_>=1&&type_<400) {
00665     if (type_<LOGLEVEL) {
00666       printf("Range of values is %g to %g\n",lowerDoubleValue_,upperDoubleValue_);
00667     } else if (type_<DIRECTION) {
00668       printf("Range of values is %d to %d\n",lowerIntValue_,upperIntValue_);
00669     } else if (type_<DIRECTORY) {
00670       printOptions();
00671     }
00672     printit(longHelp_.c_str());
00673   }
00674 }
00675 #ifdef READLINE     
00676 #include <readline/readline.h>
00677 #include <readline/history.h>
00678 #endif
00679 // Returns next valid field
00680 static int read_mode=1;
00681 static char line[1000];
00682 static char * where=NULL;
00683 
00684 std::string
00685 nextField()
00686 {
00687   std::string field;
00688   if (!where) {
00689     // need new line
00690 #ifdef READLINE     
00691     // Get a line from the user. 
00692     where = readline ("Clp:");
00693      
00694     // If the line has any text in it, save it on the history.
00695     if (where) {
00696       if ( *where)
00697         add_history (where);
00698       strcpy(line,where);
00699     }
00700 #else
00701     fprintf(stdout,"Clp:");
00702     fflush(stdout);
00703     where = fgets(line,1000,stdin);
00704 #endif
00705     if (!where)
00706       return field; // EOF
00707     where = line;
00708     // clean image
00709     char * lastNonBlank = line-1;
00710     while ( *where != '\0' ) {
00711       if ( *where != '\t' && *where < ' ' ) {
00712         break;
00713       } else if ( *where != '\t' && *where != ' ') {
00714         lastNonBlank = where;
00715       }
00716       where++;
00717     }
00718     where=line;
00719     *(lastNonBlank+1)='\0';
00720   }
00721   // munch white space
00722   while(*where==' '||*where=='\t')
00723     where++;
00724   char * saveWhere = where;
00725   while (*where!=' '&&*where!='\t'&&*where!='\0')
00726     where++;
00727   if (where!=saveWhere) {
00728     char save = *where;
00729     *where='\0';
00730     //convert to string
00731     field=saveWhere;
00732     *where=save;
00733   } else {
00734     where=NULL;
00735     field="EOL";
00736   }
00737   return field;
00738 }
00739 
00740 std::string
00741 getCommand(int argc, const char *argv[])
00742 {
00743   std::string field="EOL";
00744   while (field=="EOL") {
00745     if (read_mode>0) {
00746       if (read_mode<argc) {
00747         field = argv[read_mode++];
00748         if (field=="-") {
00749           std::cout<<"Switching to line mode"<<std::endl;
00750           read_mode=-1;
00751           field=nextField();
00752         } else if (field[0]!='-') {
00753           if (read_mode!=2) {
00754             std::cout<<"skipping non-command "<<field<<std::endl;
00755             field="EOL"; // skip
00756           } else {
00757             // special dispensation - taken as -import name
00758             read_mode--;
00759             field="import";
00760           }
00761         } else {
00762           if (field!="--") {
00763             // take off -
00764             field = field.substr(1);
00765           } else {
00766             // special dispensation - taken as -import --
00767             read_mode--;
00768             field="import";
00769           }
00770         }
00771       } else {
00772         field="";
00773       }
00774     } else {
00775       field=nextField();
00776     }
00777   }
00778   //std::cout<<field<<std::endl;
00779   return field;
00780 }
00781 std::string
00782 getString(int argc, const char *argv[])
00783 {
00784   std::string field="EOL";
00785   if (read_mode>0) {
00786     if (read_mode<argc) {
00787       if (argv[read_mode][0]!='-') { 
00788         field = argv[read_mode++];
00789       } else if (!strcmp(argv[read_mode],"--")) {
00790         field = argv[read_mode++];
00791         // -- means import from stdin
00792         field = "-";
00793       }
00794     }
00795   } else {
00796     field=nextField();
00797   }
00798   //std::cout<<field<<std::endl;
00799   return field;
00800 }
00801 // valid 0 - okay, 1 bad, 2 not there
00802 int
00803 getIntField(int argc, const char *argv[],int * valid)
00804 {
00805   std::string field="EOL";
00806   if (read_mode>0) {
00807     if (read_mode<argc) {
00808       // may be negative value so do not check for -
00809       field = argv[read_mode++];
00810     }
00811   } else {
00812     field=nextField();
00813   }
00814   int value=0;
00815   //std::cout<<field<<std::endl;
00816   if (field!="EOL") {
00817     // how do I check valid
00818     value =  atoi(field.c_str());
00819     *valid=0;
00820   } else {
00821     *valid=2;
00822   }
00823   return value;
00824 }
00825 double
00826 getDoubleField(int argc, const char *argv[],int * valid)
00827 {
00828   std::string field="EOL";
00829   if (read_mode>0) {
00830     if (read_mode<argc) {
00831       // may be negative value so do not check for -
00832       field = argv[read_mode++];
00833     }
00834   } else {
00835     field=nextField();
00836   }
00837   double value=0.0;
00838   //std::cout<<field<<std::endl;
00839   if (field!="EOL") {
00840     // how do I check valid
00841     value = atof(field.c_str());
00842     *valid=0;
00843   } else {
00844     *valid=2;
00845   }
00846   return value;
00847 }
00848 int main (int argc, const char *argv[])
00849 {
00850   // next {} is just to make sure all memory should be freed - for debug
00851   {
00852     double time1 = CoinCpuTime(),time2;
00853     // Set up all non-standard stuff
00854     //int numberModels=1;
00855     ClpSimplex * models = new ClpSimplex[1];
00856     
00857     // default action on import
00858     int allowImportErrors=0;
00859     int keepImportNames=1;
00860     int doIdiot=-1;
00861     int doCrash=0;
00862     int doSprint=-1;
00863     // set reasonable defaults
00864     int preSolve=5;
00865     models->setPerturbation(50);
00866     models->messageHandler()->setPrefix(false);
00867     std::string directory ="./";
00868     std::string importFile ="";
00869     std::string exportFile ="default.mps";
00870     std::string saveFile ="default.prob";
00871     std::string restoreFile ="default.prob";
00872     std::string solutionFile ="stdout";
00873 #define MAXPARAMETERS 100
00874     ClpItem parameters[MAXPARAMETERS];
00875     int numberParameters=0;
00876     parameters[numberParameters++]=
00877       ClpItem("?","For help",GENERALQUERY,-1,false);
00878     parameters[numberParameters++]=
00879       ClpItem("-","From stdin",
00880               STDIN,299,false);
00881     parameters[numberParameters++]=
00882       ClpItem("allS!lack","Set basis back to all slack",
00883               ALLSLACK,false);
00884     parameters[numberParameters-1].setLonghelp
00885       (
00886        "Useful for playing around"
00887        ); 
00888     parameters[numberParameters++]=
00889       ClpItem("barr!ier","Solve using primal dual predictor corrector algorithm",
00890               BARRIER);
00891     parameters[numberParameters-1].setLonghelp
00892       (
00893        "This command solves the current model using the  primal dual predictor \
00894 corrector algorithm.  This is not a sophisticated version just something JJF\
00895 knocked up\
00896 ** another slight drawback (early December) is that it does not work"
00897 
00898        ); 
00899     parameters[numberParameters++]=
00900       ClpItem("biasLU","Whether factorization biased towards U",
00901               "UU",BIASLU,2,false);
00902     parameters[numberParameters-1].append("UX");
00903     parameters[numberParameters-1].append("LX");
00904     parameters[numberParameters-1].append("LL");
00905     parameters[numberParameters++]=
00906       ClpItem("crash","Whether to create basis for problem",
00907               "off",CRASH);
00908     parameters[numberParameters-1].append("on");
00909     parameters[numberParameters-1].setLonghelp
00910       (
00911        "If crash is set on and there is an all slack basis then Clp will put structural\
00912  variables into basis with the aim of getting dual feasible.  On the whole dual seems to be\
00913  better without it and there alernative types of 'crash' for primal e.g. 'idiot' or 'sprint'."
00914        ); 
00915     parameters[numberParameters++]=
00916       ClpItem("direction","Minimize or Maximize",
00917               "min!imize",DIRECTION);
00918     parameters[numberParameters-1].append("max!imize");
00919     parameters[numberParameters-1].append("zero");
00920     parameters[numberParameters-1].setLonghelp
00921       (
00922        "The default is minimize - use 'direction maximize' for maximization.\n\
00923 You can also use the parameters 'maximize' or 'minimize'."
00924        ); 
00925     parameters[numberParameters++]=
00926       ClpItem("directory","Set Default directory for import etc.",
00927               DIRECTORY,299);
00928     parameters[numberParameters-1].setLonghelp
00929       (
00930        "This sets the directory which import, export, saveModel and restoreModel will use.\
00931   It is initialized to './'"
00932        ); 
00933     parameters[numberParameters-1].setStringValue(directory);
00934     parameters[numberParameters++]=
00935       ClpItem("dualB!ound","Initially algorithm acts as if no \
00936 gap between bounds exceeds this value",
00937               1.0e-20,1.0e12,DUALBOUND);
00938     parameters[numberParameters-1].setLonghelp
00939       (
00940        "The dual algorithm in Clp is a single phase algorithm as opposed to a two phase\
00941  algorithm where you first get feasible then optimal.  If a problem has both upper and\
00942  lower bounds then it is trivial to get dual feasible by setting non basic variables\
00943  to correct bound.  If the gap between the upper and lower bounds of a variable is more\
00944  than the value of dualBound Clp introduces fake bounds so that it can make the problem\
00945  dual feasible.  This has the same effect as a composite objective function in the\
00946  primal algorithm.  Too high a value may mean more iterations, while too low a bound means\
00947  the code may go all the way and then have to increase the bounds.  OSL had a heuristic to\
00948  adjust bounds, maybe we need that here."
00949        );
00950     parameters[numberParameters-1].setDoubleValue(models->dualBound());
00951     parameters[numberParameters++]=
00952       ClpItem("dualP!ivot","Dual pivot choice algorithm",
00953               "auto!matic",DUALPIVOT);
00954     parameters[numberParameters-1].append("dant!zig");
00955     parameters[numberParameters-1].append("partial");
00956     parameters[numberParameters-1].append("steep!est");
00957     parameters[numberParameters-1].setLonghelp
00958       (
00959        "Clp can use any pivot selection algorithm which the user codes as long as it\
00960  implements the features in the abstract pivot base class.  The Dantzig method is implemented\
00961  to show a simple method but its use is deprecated.  Steepest is the method of choice and there\
00962  are two variants which keep all weights updated but only scan a subset each iteration.\
00963  Partial switches this on while automatic decides at each iteration based on information\
00964  about the factorization."
00965        ); 
00966     parameters[numberParameters++]=
00967       ClpItem("dualS!implex","Do dual simplex algorithm",
00968               DUALSIMPLEX);
00969     parameters[numberParameters-1].setLonghelp
00970       (
00971        "This command solves the current model using the dual steepest algorithm.\
00972 The time and iterations may be affected by settings such as presolve, scaling, crash\
00973  and also by dual pivot method, fake bound on variables and dual and primal tolerances."
00974        ); 
00975     parameters[numberParameters++]=
00976       ClpItem("dualT!olerance","For an optimal solution \
00977 no dual infeasibility may exceed this value",
00978               1.0e-20,1.0e12,DUALTOLERANCE);
00979     parameters[numberParameters-1].setLonghelp
00980       (
00981        "Normally the default tolerance is fine, but you may want to increase it a\
00982  bit if a dual run seems to be having a hard time"
00983        ); 
00984     parameters[numberParameters-1].setDoubleValue(models->dualTolerance());
00985     parameters[numberParameters++]=
00986       ClpItem("end","Stops clp execution",
00987               EXIT);
00988     parameters[numberParameters-1].setLonghelp
00989       (
00990        "This stops the execution of Clp, end, exit, quit and stop are synonyms"
00991        ); 
00992     parameters[numberParameters++]=
00993       ClpItem("error!sAllowed","Whether to allow import errors",
00994               "off",ERRORSALLOWED);
00995     parameters[numberParameters-1].append("on");
00996     parameters[numberParameters-1].setLonghelp
00997       (
00998        "The default is not to use any model which had errors when reading the mps file.\
00999   Setting this to 'on' will allow all errors from which the code can recover\
01000  by ignoring the error."
01001        );
01002     parameters[numberParameters++]=
01003       ClpItem("exit","Stops clp execution",
01004               EXIT);
01005     parameters[numberParameters-1].setLonghelp
01006       (
01007        "This stops the execution of Clp, end, exit, quit and stop are synonyms"
01008        ); 
01009     parameters[numberParameters++]=
01010       ClpItem("export","Export model as mps file",
01011               EXPORT);
01012     parameters[numberParameters-1].setLonghelp
01013       (
01014        "This will write an MPS format file to the given file name.  It will use the default\
01015  directory given by 'directory'.  A name of '$' will use the previous value for the name.  This\
01016  is initialized to 'default.mps'."
01017        ); 
01018     parameters[numberParameters-1].setStringValue(exportFile);
01019     parameters[numberParameters++]=
01020       ClpItem("fakeB!ound","All bounds <= this value - DEBUG",
01021               1.0,1.0e15,FAKEBOUND,false);
01022     parameters[numberParameters++]=
01023       ClpItem("help","Print out version, non-standard options and some help",
01024               HELP);
01025     parameters[numberParameters++]=
01026       ClpItem("idiot!Crash","Whether to try idiot crash",
01027               -1,200,IDIOT);
01028     parameters[numberParameters-1].setLonghelp
01029       (
01030        "This is a type of 'crash' which works well on some homogeneous problems.\
01031  It works best on problems with unit elements and rhs but will do something to any model.  It should only be\
01032  used before primal.  It can be set to -1 when the code decides for itself whether to use it,\
01033  0 to switch off or n > 0 to do n passes."
01034        ); 
01035     parameters[numberParameters-1].setIntValue(doIdiot);
01036     parameters[numberParameters++]=
01037       ClpItem("import","Import model from mps file",
01038               IMPORT);
01039     parameters[numberParameters-1].setLonghelp
01040       (
01041        "This will read an MPS format file from the given file name.  It will use the default\
01042  directory given by 'directory'.  A name of '$' will use the previous value for the name.  This\
01043  is initialized to '', i.e. it must be set.  If you have libgz then it can read compressed\
01044  files 'xxxxxxxx.gz'.."
01045        ); 
01046     parameters[numberParameters-1].setStringValue(importFile);
01047     parameters[numberParameters++]=
01048       ClpItem("keepN!ames","Whether to keep names from import",
01049               "on",KEEPNAMES);
01050     parameters[numberParameters-1].append("off");
01051     parameters[numberParameters-1].setLonghelp
01052       (
01053        "It saves space to get rid of names so if you need to you can set this to off."
01054        ); 
01055     parameters[numberParameters++]=
01056       ClpItem("log!Level","Level of detail in output",
01057               0,63,LOGLEVEL);
01058     parameters[numberParameters-1].setLonghelp
01059       (
01060        "If 0 then there should be no output in normal circumstances.  1 is probably the best\
01061  value for most uses, while 2 and 3 give more information."
01062        ); 
01063     parameters[numberParameters-1].setIntValue(models->logLevel());
01064     parameters[numberParameters++]=
01065       ClpItem("max!imize","Set optimization direction to maximize",
01066               MAXIMIZE,299);
01067     parameters[numberParameters-1].setLonghelp
01068       (
01069        "The default is minimize - use 'maximize' for maximization.\n\
01070 You can also use the parameters 'direction maximize'."
01071        ); 
01072     parameters[numberParameters++]=
01073       ClpItem("maxF!actor","Maximum number of iterations between \
01074 refactorizations",
01075               1,999999,MAXFACTOR);
01076     parameters[numberParameters-1].setLonghelp
01077       (
01078        "If this is at its default value of 200 then in this executable clp will guess at a\
01079  value to use.  Otherwise the user can set a value.  The code may decide to re-factorize\
01080  earlier."
01081        ); 
01082     parameters[numberParameters-1].setIntValue(models->factorizationFrequency());
01083     parameters[numberParameters++]=
01084       ClpItem("maxIt!erations","Maximum number of iterations before \
01085 stopping",
01086               0,99999999,MAXITERATION);
01087     parameters[numberParameters-1].setLonghelp
01088       (
01089        "This can be used for testing purposes.  The corresponding library call\n\
01090       \tsetMaximumIterations(value)\n can be useful.  If the code stops on\
01091  seconds or by an interrupt this will be treated as stopping on maximum iterations"
01092        ); 
01093     parameters[numberParameters-1].setIntValue(models->maximumIterations());
01094     parameters[numberParameters++]=
01095       ClpItem("min!imize","Set optimization direction to minimize",
01096               MINIMIZE,299);
01097     parameters[numberParameters-1].setLonghelp
01098       (
01099        "The default is minimize - use 'maximize' for maximization.\n\
01100 This should only be necessary if you have previously set maximization \
01101 You can also use the parameters 'direction minimize'."
01102        ); 
01103     parameters[numberParameters++]=
01104       ClpItem("mess!ages","Controls if Clpnnnn is printed",
01105               "off",MESSAGES);
01106     parameters[numberParameters-1].append("on");
01107     parameters[numberParameters-1].setLonghelp
01108       ("The default for the Clp library is to put out messages such as:\n\
01109    Clp0005 2261  Objective 109.024 Primal infeas 944413 (758)\n\
01110 but this program turns this off to make it look more friendly.  It can be useful\
01111  to turn them back on if you want to be able 'grep' for particular messages or if\
01112  you intend to override the behavior of a particular message."
01113        ); 
01114     parameters[numberParameters++]=
01115       ClpItem("netlib","Solve entire netlib test set",
01116               NETLIB_DUAL,-1,false);
01117     parameters[numberParameters++]=
01118       ClpItem("netlibP!rimal","Solve entire netlib test set (primal)",
01119               NETLIB_PRIMAL,-1,false);
01120     parameters[numberParameters++]=
01121       ClpItem("network","Tries to make network matrix",
01122               NETWORK,-1,false);
01123     parameters[numberParameters-1].setLonghelp
01124       (
01125        "Clp will go faster if the matrix can be converted to a network.  The matrix\
01126  operations may be a bit faster with more efficient storage, but the main advantage\
01127  comes from using a network factorization.  It will probably not be as fast as a \
01128 specialized network code."
01129        ); 
01130     parameters[numberParameters++]=
01131       ClpItem("objective!Scale","Scale factor to apply to objective",
01132               -1.0e20,1.0e20,OBJSCALE,false);
01133     parameters[numberParameters-1].setDoubleValue(models->optimizationDirection());
01134     parameters[numberParameters++]=
01135       ClpItem("passP!resolve","How many passes in presolve",
01136               0,100,PRESOLVEPASS);
01137     parameters[numberParameters-1].setLonghelp
01138       (
01139        "Normally Presolve does 5 passes but you may want to do less to make it\
01140  more lightweight or do more if improvements are still being made.  As Presolve will return\
01141  if nothing is being taken out, then you should not need to use this fine tuning."
01142        ); 
01143     parameters[numberParameters-1].setIntValue(preSolve);
01144     parameters[numberParameters++]=
01145       ClpItem("pertV!alue","Method of perturbation",
01146               -5000,102,PERTVALUE,false);
01147     parameters[numberParameters-1].setIntValue(models->perturbation());
01148     parameters[numberParameters++]=
01149       ClpItem("perturb!ation","Whether to perturb problem",
01150               "on",PERTURBATION);
01151     parameters[numberParameters-1].append("off");
01152     parameters[numberParameters-1].setLonghelp
01153       (
01154        "Perturbation helps to stop cycling, but Clp uses other measures for this.\
01155   However large problems and especially ones with unit elements and unit rhs or costs\
01156  benefit from perturbation.  Normally Clp tries to be intelligent, but you can switch this off.\
01157   The Clp library has this off by default.  This program has it on."
01158        ); 
01159     parameters[numberParameters++]=
01160       ClpItem("plus!Minus","Tries to make +- 1 matrix",
01161               PLUSMINUS,-1,false);
01162     parameters[numberParameters-1].setLonghelp
01163       (
01164        "Clp will go slightly faster if the matrix can be converted so that the elements are\
01165  not stored and are known to be unit.  The main advantage is memory use.  Clp may automatically\
01166  see if it can convert the problem so you should not need to use this."
01167        ); 
01168     parameters[numberParameters++]=
01169       ClpItem("presolve","Whether to presolve problem",
01170               "on",PRESOLVE);
01171     parameters[numberParameters-1].append("off");
01172     parameters[numberParameters-1].append("more");
01173     parameters[numberParameters-1].setLonghelp
01174       (
01175        "Presolve analyzes the model to find such things as redundant equations, equations\
01176  which fix some variables, equations which can be transformed into bounds etc etc.  For the\
01177  initial solve of any problem this is worth doing unless you know that it will have no effect."
01178        ); 
01179     parameters[numberParameters++]=
01180       ClpItem("primalP!ivot","Primal pivot choice algorithm",
01181               "auto!matic",PRIMALPIVOT);
01182     parameters[numberParameters-1].append("exa!ct");
01183     parameters[numberParameters-1].append("dant!zig");
01184     parameters[numberParameters-1].append("part!ial");
01185     parameters[numberParameters-1].append("steep!est");
01186     parameters[numberParameters-1].append("change");
01187     parameters[numberParameters-1].append("sprint");
01188     parameters[numberParameters-1].setLonghelp
01189       (
01190        "Clp can use any pivot selection algorithm which the user codes as long as it\
01191  implements the features in the abstract pivot base class.  The Dantzig method is implemented\
01192  to show a simple method but its use is deprecated.  Exact devex is the method of choice and there\
01193  are two variants which keep all weights updated but only scan a subset each iteration.\
01194  Partial switches this on while change initially does dantzig until the factorization\
01195  becomes denser.  This is still a work in progress."
01196        ); 
01197     parameters[numberParameters++]=
01198       ClpItem("primalS!implex","Do primal simplex algorithm",
01199               PRIMALSIMPLEX);
01200     parameters[numberParameters-1].setLonghelp
01201       (
01202        "This command solves the current model using the primal algorithm.\
01203   The default is to use exact devex.\
01204  The time and iterations may be affected by settings such as presolve, scaling, crash\
01205  and also by column selection  method, infeasibility weight and dual and primal tolerances."
01206        ); 
01207     parameters[numberParameters++]=
01208       ClpItem("primalT!olerance","For an optimal solution \
01209 no primal infeasibility may exceed this value",
01210               1.0e-20,1.0e12,PRIMALTOLERANCE);
01211     parameters[numberParameters-1].setLonghelp
01212       (
01213        "Normally the default tolerance is fine, but you may want to increase it a\
01214  bit if a primal run seems to be having a hard time"
01215        ); 
01216     parameters[numberParameters-1].setDoubleValue(models->primalTolerance());
01217     parameters[numberParameters++]=
01218       ClpItem("primalW!eight","Initially algorithm acts as if it \
01219 costs this much to be infeasible",
01220               1.0e-20,1.0e20,PRIMALWEIGHT);
01221     parameters[numberParameters-1].setLonghelp
01222       (
01223        "The primal algorithm in Clp is a single phase algorithm as opposed to a two phase\
01224  algorithm where you first get feasible then optimal.  So Clp is minimizing this weight times\
01225  the sum of primal infeasibilities plus the true objective function (in minimization sense).\
01226   Too high a value may mean more iterations, while too low a bound means\
01227  the code may go all the way and then have to increase the weight in order to get feasible.\
01228   OSL had a heuristic to\
01229  adjust bounds, maybe we need that here."
01230        ); 
01231     parameters[numberParameters-1].setDoubleValue(models->infeasibilityCost());
01232     parameters[numberParameters++]=
01233       ClpItem("quit","Stops clp execution",
01234               EXIT);
01235     parameters[numberParameters-1].setLonghelp
01236       (
01237        "This stops the execution of Clp, end, exit, quit and stop are synonyms"
01238        ); 
01239     parameters[numberParameters++]=
01240       ClpItem("restore!Model","Restore model from binary file",
01241               RESTORE);
01242     parameters[numberParameters-1].setLonghelp
01243       (
01244        "This reads data save by saveModel from the given file.  It will use the default\
01245  directory given by 'directory'.  A name of '$' will use the previous value for the name.  This\
01246  is initialized to 'default.prob'."
01247        ); 
01248     parameters[numberParameters-1].setStringValue(restoreFile);
01249     parameters[numberParameters++]=
01250       ClpItem("reverse","Reverses sign of objective",
01251               REVERSE,false);
01252     parameters[numberParameters-1].setLonghelp
01253       (
01254        "Useful for testing if maximization works correctly"
01255        ); 
01256     parameters[numberParameters++]=
01257       ClpItem("save!Model","Save model to binary file",
01258               SAVE);
01259     parameters[numberParameters-1].setLonghelp
01260       (
01261        "This will save the problem to the given file name for future use\
01262  by restoreModel.  It will use the default\
01263  directory given by 'directory'.  A name of '$' will use the previous value for the name.  This\
01264  is initialized to 'default.prob'."
01265        ); 
01266     parameters[numberParameters-1].setStringValue(saveFile);
01267     parameters[numberParameters++]=
01268       ClpItem("scal!ing","Whether to scale problem",
01269               "off",SCALING);
01270     parameters[numberParameters-1].append("equi!librium");
01271     parameters[numberParameters-1].append("geo!metric");
01272     parameters[numberParameters-1].append("auto!matic");
01273     parameters[numberParameters-1].setLonghelp
01274       (
01275        "Scaling can help in solving problems which might otherwise fail because of lack of\
01276  accuracy.  It can also reduce the number of iterations.  It is not applied if the range\
01277  of elements is small.  When unscaled it is possible that there may be small primal and/or\
01278  infeasibilities."
01279        ); 
01280     parameters[numberParameters-1].setCurrentOption(3); // say auto
01281     parameters[numberParameters++]=
01282       ClpItem("sec!onds","maximum seconds",
01283               0.0,1.0e12,MAXTIME);
01284     parameters[numberParameters-1].setLonghelp
01285       (
01286        "After this many seconds clp will act as if maximum iterations had been reached.\
01287   In this program it is really only useful for testing but the library function\n\
01288       \tsetMaximumSeconds(value)\n can be useful."
01289        ); 
01290     parameters[numberParameters-1].setDoubleValue(models->maximumSeconds());
01291     parameters[numberParameters++]=
01292       ClpItem("sol!ution","Prints solution to file",
01293               SOLUTION);
01294     parameters[numberParameters-1].setLonghelp
01295       (
01296        "This will write a primitive solution file to the given file name.  It will use the default\
01297  directory given by 'directory'.  A name of '$' will use the previous value for the name.  This\
01298  is initialized to 'stdout'."
01299        ); 
01300     parameters[numberParameters-1].setStringValue(solutionFile);
01301     parameters[numberParameters++]=
01302       ClpItem("spars!eFactor","Whether factorization treated as sparse",
01303               "on",SPARSEFACTOR,0,false);
01304     parameters[numberParameters-1].append("off");
01305     parameters[numberParameters-1].append("on");
01306     parameters[numberParameters++]=
01307       ClpItem("sprint!Crash","Whether to try sprint crash",
01308               -1,500,SPRINT);
01309     parameters[numberParameters-1].setLonghelp
01310       (
01311        "For long and thin problems this program may solve a series of small problems\
01312  created by taking a subset of the columns.  I introduced the idea as 'Sprint' after\
01313  an LP code of that name of the 60's which tried the same tactic (not totally successfully).\
01314   Cplex calls it 'sifting'.  -1 is automatic choice, 0 is off, n is number of passes"
01315        ); 
01316     parameters[numberParameters-1].setIntValue(doSprint);
01317       ClpItem("stdin","From stdin",
01318               STDIN,-1,false);
01319     parameters[numberParameters++]=
01320       ClpItem("stop","Stops clp execution",
01321               EXIT);
01322     parameters[numberParameters-1].setLonghelp
01323       (
01324        "This stops the execution of Clp, end, exit, quit and stop are synonyms"
01325        ); 
01326     parameters[numberParameters++]=
01327       ClpItem("tight!en","Poor person's preSolve for now",
01328               TIGHTEN,-1,false);
01329     parameters[numberParameters++]=
01330       ClpItem("unitTest","Do unit test",
01331               UNITTEST,-1,false);
01332     assert(numberParameters<MAXPARAMETERS);
01333     
01334     // total number of commands read
01335     int numberGoodCommands=0;
01336     bool * goodModels = new bool[1];
01337     
01338     
01339     int iModel=0;
01340     goodModels[0]=false;
01341     //models[0].scaling(1);
01342     //models[0].setDualBound(1.0e6);
01343     //models[0].setDualTolerance(1.0e-7);
01344     //ClpDualRowSteepest steep;
01345     //models[0].setDualRowPivotAlgorithm(steep);
01346     //models[0].setPrimalTolerance(1.0e-7);
01347     //ClpPrimalColumnSteepest steepP;
01348     //models[0].setPrimalColumnPivotAlgorithm(steepP);
01349     std::string field;
01350     std::cout<<"Coin LP version "<<CLPVERSION
01351              <<", build "<<__DATE__<<std::endl;
01352     
01353     while (1) {
01354       // next command
01355       field=getCommand(argc,argv);
01356       
01357       // exit if null or similar
01358       if (!field.length()) {
01359         if (numberGoodCommands==1&&goodModels[0]) {
01360           // we just had file name - do dual
01361           field="duals";
01362         } else if (!numberGoodCommands) {
01363           // let's give the sucker a hint
01364           std::cout
01365             <<"Clp takes input from arguments ( - switches to stdin)"
01366             <<std::endl
01367             <<"Enter ? for list of commands or help"<<std::endl;
01368           field="-";
01369         } else {
01370           break;
01371         }
01372       }
01373       
01374       // see if ? at end
01375       int numberQuery=0;
01376       if (field!="?") {
01377         int length = field.length();
01378         int i;
01379         for (i=length-1;i>0;i--) {
01380           if (field[i]=='?') 
01381             numberQuery++;
01382           else
01383             break;
01384         }
01385         field=field.substr(0,length-numberQuery);
01386       }
01387       // find out if valid command
01388       int iParam;
01389       int numberMatches=0;
01390       int firstMatch=-1;
01391       for ( iParam=0; iParam<numberParameters; iParam++ ) {
01392         int match = parameters[iParam].matches(field);
01393         if (match==1) {
01394           numberMatches = 1;
01395           firstMatch=iParam;
01396           break;
01397         } else {
01398           if (match&&firstMatch<0)
01399             firstMatch=iParam;
01400           numberMatches += match>>1;
01401         }
01402       }
01403       if (iParam<numberParameters&&!numberQuery) {
01404         // found
01405         ClpItem found = parameters[iParam];
01406         ClpParameterType type = found.type();
01407         int valid;
01408         numberGoodCommands++;
01409         if (type==GENERALQUERY) {
01410           std::cout<<"In argument list keywords have leading - "
01411             ", -stdin or just - switches to stdin"<<std::endl;
01412           std::cout<<"One command per line (and no -)"<<std::endl;
01413           std::cout<<"abcd? gives list of possibilities, if only one + explanation"<<std::endl;
01414           std::cout<<"abcd?? adds explanation, if only one fuller help"<<std::endl;
01415           std::cout<<"abcd without value (where expected) gives current value"<<std::endl;
01416           std::cout<<"abcd value sets value"<<std::endl;
01417           std::cout<<"Commands are:"<<std::endl;
01418           int maxAcross=5;
01419           int limits[]={1,101,201,301,401};
01420           std::vector<std::string> types;
01421           types.push_back("Double parameters:");
01422           types.push_back("Int parameters:");
01423           types.push_back("Keyword parameters and others:");
01424           types.push_back("Actions:");
01425           int iType;
01426           for (iType=0;iType<4;iType++) {
01427             int across=0;
01428             std::cout<<types[iType]<<std::endl;
01429             for ( iParam=0; iParam<numberParameters; iParam++ ) {
01430               int type = parameters[iParam].indexNumber();
01431               if (parameters[iParam].displayThis()&&type>=limits[iType]
01432                   &&type<limits[iType+1]) {
01433                 if (!across)
01434                   std::cout<<"  ";
01435                 std::cout<<parameters[iParam].matchName()<<"  ";
01436                 across++;
01437                 if (across==maxAcross) {
01438                   std::cout<<std::endl;
01439                   across=0;
01440                 }
01441               }
01442             }
01443             if (across)
01444               std::cout<<std::endl;
01445           }
01446         } else if (type<101) {
01447           // get next field as double
01448           double value = getDoubleField(argc,argv,&valid);
01449           if (!valid) {
01450             parameters[iParam].setDoubleValue(value);
01451             parameters[iParam].setDoubleParameter(models+iModel,value);
01452           } else if (valid==1) {
01453             abort();
01454           } else {
01455             std::cout<<parameters[iParam].name()<<" has value "<<
01456               parameters[iParam].doubleValue()<<std::endl;
01457           }
01458         } else if (type<201) {
01459           // get next field as int
01460           int value = getIntField(argc,argv,&valid);
01461           if (!valid) {
01462             parameters[iParam].setIntValue(value);
01463             if (parameters[iParam].type()==PRESOLVEPASS)
01464               preSolve = value;
01465             else if (parameters[iParam].type()==IDIOT)
01466               doIdiot = value;
01467             else if (parameters[iParam].type()==SPRINT)
01468               doSprint = value;
01469             else
01470               parameters[iParam].setIntParameter(models+iModel,value);
01471           } else if (valid==1) {
01472             abort();
01473           } else {
01474             std::cout<<parameters[iParam].name()<<" has value "<<
01475               parameters[iParam].intValue()<<std::endl;
01476           }
01477         } else if (type<301) {
01478           // one of several strings
01479           std::string value = getString(argc,argv);
01480           int action = parameters[iParam].parameterOption(value);
01481           if (action<0) {
01482             if (value!="EOL") {
01483               // no match
01484               parameters[iParam].printOptions();
01485             } else {
01486               // print current value
01487               std::cout<<parameters[iParam].name()<<" has value "<<
01488                 parameters[iParam].currentOption()<<std::endl;
01489             }
01490           } else {
01491             parameters[iParam].setCurrentOption(action);
01492             // for now hard wired
01493             switch (type) {
01494             case DIRECTION:
01495               if (action==0)
01496                 models[iModel].setOptimizationDirection(1);
01497               else if (action==1)
01498                 models[iModel].setOptimizationDirection(-1);
01499               else
01500                 models[iModel].setOptimizationDirection(0);
01501               break;
01502             case DUALPIVOT:
01503               if (action==0) {
01504                 ClpDualRowSteepest steep(3);
01505                 models[iModel].setDualRowPivotAlgorithm(steep);
01506               } else if (action==1) {
01507                 ClpDualRowDantzig dantzig;
01508                 models[iModel].setDualRowPivotAlgorithm(dantzig);
01509               } else if (action==2) {
01510                 // partial steep
01511                 ClpDualRowSteepest steep(2);
01512                 models[iModel].setDualRowPivotAlgorithm(steep);
01513               } else {
01514                 ClpDualRowSteepest steep;
01515                 models[iModel].setDualRowPivotAlgorithm(steep);
01516               }
01517               break;
01518             case PRIMALPIVOT:
01519               if (action==0) {
01520                 ClpPrimalColumnSteepest steep(3);
01521                 models[iModel].setPrimalColumnPivotAlgorithm(steep);
01522               } else if (action==1) {
01523                 ClpPrimalColumnSteepest steep(0);
01524                 models[iModel].setPrimalColumnPivotAlgorithm(steep);
01525               } else if (action==2) {
01526                 ClpPrimalColumnDantzig dantzig;
01527                 models[iModel].setPrimalColumnPivotAlgorithm(dantzig);
01528               } else if (action==3) {
01529                 ClpPrimalColumnSteepest steep(2);
01530                 models[iModel].setPrimalColumnPivotAlgorithm(steep);
01531               } else if (action==4) {
01532                 ClpPrimalColumnSteepest steep(1);
01533                 models[iModel].setPrimalColumnPivotAlgorithm(steep);
01534               } else if (action==5) {
01535                 ClpPrimalColumnSteepest steep(4);
01536                 models[iModel].setPrimalColumnPivotAlgorithm(steep);
01537               } else if (action==6) {
01538                 ClpPrimalColumnSteepest steep(10);
01539                 models[iModel].setPrimalColumnPivotAlgorithm(steep);
01540               }
01541               break;
01542             case SCALING:
01543               models[iModel].scaling(action);
01544               break;
01545             case SPARSEFACTOR:
01546               models[iModel].setSparseFactorization((1-action)!=0);
01547               break;
01548             case BIASLU:
01549               models[iModel].factorization()->setBiasLU(action);
01550               break;
01551             case PERTURBATION:
01552               if (action==0)
01553                 models[iModel].setPerturbation(50);
01554               else
01555                 models[iModel].setPerturbation(100);
01556               break;
01557             case ERRORSALLOWED:
01558               allowImportErrors = action;
01559               break;
01560             case KEEPNAMES:
01561               keepImportNames = 1-action;
01562               break;
01563             case PRESOLVE:
01564               if (action==0)
01565                 preSolve = 5;
01566               else if (action==1)
01567                 preSolve=0;
01568               else
01569                 preSolve=10;
01570               break;
01571             case CRASH:
01572               doCrash=action;
01573               break;
01574             case MESSAGES:
01575               models[iModel].messageHandler()->setPrefix(action!=0);
01576               break;
01577             default:
01578               abort();
01579             }
01580           }
01581         } else {
01582           // action
01583           if (type==EXIT)
01584             break; // stop all
01585           switch (type) {
01586           case DUALSIMPLEX:
01587           case PRIMALSIMPLEX:
01588           case BARRIER:
01589             if (goodModels[iModel]) {
01590               ClpSolve::SolveType method;
01591               ClpSolve::PresolveType presolveType;
01592               ClpSimplex * model2 = models+iModel;
01593               ClpSolve solveOptions;
01594               if (preSolve!=5&&preSolve)
01595                 presolveType=ClpSolve::presolveNumber;
01596               else if (preSolve)
01597                 presolveType=ClpSolve::presolveOn;
01598               else
01599                 presolveType=ClpSolve::presolveOff;
01600               solveOptions.setPresolveType(presolveType,preSolve);
01601               if (type==DUALSIMPLEX)
01602                 method=ClpSolve::useDual;
01603               else if (type==PRIMALSIMPLEX)
01604                 method=ClpSolve::usePrimalorSprint;
01605               else
01606                 method = ClpSolve::useBarrier;
01607               solveOptions.setSolveType(method);
01608               if (method==ClpSolve::useDual) {
01609                 // dual
01610                 if (doCrash)
01611                   solveOptions.setSpecialOption(0,1); // crash
01612                 else if (doIdiot)
01613                   solveOptions.setSpecialOption(0,2,doIdiot); // possible idiot
01614               } else if (method==ClpSolve::usePrimalorSprint) {
01615                 // primal
01616                 if (doCrash) {
01617                   solveOptions.setSpecialOption(1,1); // crash
01618                 } else if (doSprint>0) {
01619                   // sprint overrides idiot
01620                   solveOptions.setSpecialOption(1,3,doSprint); // sprint
01621                 } else if (doIdiot>0) {
01622                   solveOptions.setSpecialOption(1,2,doIdiot); // idiot
01623                 } else {
01624                   if (doIdiot==0) {
01625                     if (doSprint==0)
01626                       solveOptions.setSpecialOption(1,4); // all slack
01627                     else
01628                       solveOptions.setSpecialOption(1,9); // all slack or sprint
01629                   } else {
01630                     if (doSprint==0)
01631                       solveOptions.setSpecialOption(1,8); // all slack or idiot
01632                     else
01633                       solveOptions.setSpecialOption(1,7); // initiative
01634                   }
01635                 }
01636               }
01637               model2->initialSolve(solveOptions);
01638             } else {
01639               std::cout<<"** Current model not valid"<<std::endl;
01640             }
01641             break;
01642           case TIGHTEN:
01643             if (goodModels[iModel]) {
01644               int numberInfeasibilities = models[iModel].tightenPrimalBounds();
01645               if (numberInfeasibilities)
01646                 std::cout<<"** Analysis indicates model infeasible"<<std::endl;
01647             } else {
01648               std::cout<<"** Current model not valid"<<std::endl;
01649             }
01650             break;
01651           case PLUSMINUS:
01652             if (goodModels[iModel]) {
01653               ClpMatrixBase * saveMatrix = models[iModel].clpMatrix();
01654               ClpPackedMatrix* clpMatrix =
01655                 dynamic_cast< ClpPackedMatrix*>(saveMatrix);
01656               if (clpMatrix) {
01657                 ClpPlusMinusOneMatrix * newMatrix = new ClpPlusMinusOneMatrix(*(clpMatrix->matrix()));
01658                 if (newMatrix->getIndices()) {
01659                   models[iModel].replaceMatrix(newMatrix);
01660                   delete saveMatrix;
01661                   std::cout<<"Matrix converted to +- one matrix"<<std::endl;
01662                 } else {
01663                   std::cout<<"Matrix can not be converted to +- 1 matrix"<<std::endl;
01664                 }
01665               } else {
01666                 std::cout<<"Matrix not a ClpPackedMatrix"<<std::endl;
01667               }
01668             } else {
01669               std::cout<<"** Current model not valid"<<std::endl;
01670             }
01671             break;
01672           case NETWORK:
01673             if (goodModels[iModel]) {
01674               ClpMatrixBase * saveMatrix = models[iModel].clpMatrix();
01675               ClpPackedMatrix* clpMatrix =
01676                 dynamic_cast< ClpPackedMatrix*>(saveMatrix);
01677               if (clpMatrix) {
01678                 ClpNetworkMatrix * newMatrix = new ClpNetworkMatrix(*(clpMatrix->matrix()));
01679                 if (newMatrix->getIndices()) {
01680                   models[iModel].replaceMatrix(newMatrix);
01681                   delete saveMatrix;
01682                   std::cout<<"Matrix converted to network matrix"<<std::endl;
01683                 } else {
01684                   std::cout<<"Matrix can not be converted to network matrix"<<std::endl;
01685                 }
01686               } else {
01687                 std::cout<<"Matrix not a ClpPackedMatrix"<<std::endl;
01688               }
01689             } else {
01690               std::cout<<"** Current model not valid"<<std::endl;
01691             }
01692             break;
01693           case IMPORT:
01694             {
01695               // get next field
01696               field = getString(argc,argv);
01697               if (field=="$") {
01698                 field = parameters[iParam].stringValue();
01699               } else if (field=="EOL") {
01700                 parameters[iParam].printString();
01701                 break;
01702               } else {
01703                 parameters[iParam].setStringValue(field);
01704               }
01705               std::string fileName;
01706               bool canOpen=false;
01707               if (field=="-") {
01708                 // stdin
01709                 canOpen=true;
01710                 fileName = "-";
01711               } else {
01712                 if (field[0]=='/'||field[0]=='~'||field[0]=='\\')
01713                   fileName = field;
01714                 else
01715                   fileName = directory+field;
01716                 FILE *fp=fopen(fileName.c_str(),"r");
01717                 if (fp) {
01718                   // can open - lets go for it
01719                   fclose(fp);
01720                   canOpen=true;
01721                 } else {
01722                   std::cout<<"Unable to open file "<<fileName<<std::endl;
01723                 }
01724               }
01725               if (canOpen) {
01726                 int status =models[iModel].readMps(fileName.c_str(),
01727                                                    keepImportNames!=0,
01728                                                    allowImportErrors!=0);
01729                 if (!status||(status>0&&allowImportErrors)) {
01730                   goodModels[iModel]=true;
01731                   // sets to all slack (not necessary?)
01732                   models[iModel].createStatus();
01733                   time2 = CoinCpuTime();
01734                   totalTime += time2-time1;
01735                   time1=time2;
01736                 } else {
01737                   // errors
01738                   std::cout<<"There were "<<status<<
01739                     " errors on input"<<std::endl;
01740                 }
01741               }
01742             }
01743             break;
01744           case EXPORT:
01745             {
01746               // get next field
01747               field = getString(argc,argv);
01748               if (field=="$") {
01749                 field = parameters[iParam].stringValue();
01750               } else if (field=="EOL") {
01751                 parameters[iParam].printString();
01752                 break;
01753               } else {
01754                 parameters[iParam].setStringValue(field);
01755               }
01756               std::string fileName;
01757               bool canOpen=false;
01758               if (field[0]=='/'||field[0]=='~')
01759                 fileName = field;
01760               else
01761                 fileName = directory+field;
01762               FILE *fp=fopen(fileName.c_str(),"w");
01763               if (fp) {
01764                 // can open - lets go for it
01765                 fclose(fp);
01766                 canOpen=true;
01767               } else {
01768                 std::cout<<"Unable to open file "<<fileName<<std::endl;
01769               }
01770               if (canOpen) {
01771                 // If presolve on then save presolved
01772                 bool deleteModel2=false;
01773                 ClpSimplex * model2 = models+iModel;
01774                 if (preSolve) {
01775                   ClpPresolve pinfo;
01776                   model2 = 
01777                     pinfo.presolvedModel(models[iModel],1.0e-8,
01778                                          false,preSolve);
01779                   if (model2) {
01780                     printf("Saving presolved model on %s\n",
01781                            fileName.c_str());
01782                     deleteModel2=true;
01783                   } else {
01784                     printf("Presolved model looks infeasible - saving original on %s\n",
01785                            fileName.c_str());
01786                     deleteModel2=false;
01787                     model2 = models+iModel;
01788 
01789                   }
01790                 } else {
01791                   printf("Saving model on %s\n",
01792                            fileName.c_str());
01793                 }
01794                 // Convert names
01795                 int iRow;
01796                 int numberRows=model2->numberRows();
01797                 int iColumn;
01798                 int numberColumns=model2->numberColumns();
01799 
01800                 char ** rowNames = NULL;
01801                 char ** columnNames = NULL;
01802                 if (model2->lengthNames()) {
01803                   rowNames = new char * [numberRows];
01804                   for (iRow=0;iRow<numberRows;iRow++) {
01805                     rowNames[iRow] = 
01806                       strdup(model2->rowName(iRow).c_str());
01807 #ifdef STRIPBLANKS
01808                     char * xx = rowNames[iRow];
01809                     int i;
01810                     int length = strlen(xx);
01811                     int n=0;
01812                     for (i=0;i<length;i++) {
01813                       if (xx[i]!=' ')
01814                         xx[n++]=xx[i];
01815                     }
01816                     xx[n]='\0';
01817 #endif
01818                   }
01819                   
01820                   columnNames = new char * [numberColumns];
01821                   for (iColumn=0;iColumn<numberColumns;iColumn++) {
01822                     columnNames[iColumn] = 
01823                       strdup(model2->columnName(iColumn).c_str());
01824 #ifdef STRIPBLANKS
01825                     char * xx = columnNames[iColumn];
01826                     int i;
01827                     int length = strlen(xx);
01828                     int n=0;
01829                     for (i=0;i<length;i++) {
01830                       if (xx[i]!=' ')
01831                         xx[n++]=xx[i];
01832                     }
01833                     xx[n]='\0';
01834 #endif
01835                   }
01836                 }
01837 
01838                 CoinMpsIO writer;
01839                 writer.setMpsData(*model2->matrix(), COIN_DBL_MAX,
01840                                   model2->getColLower(), model2->getColUpper(),
01841                                   model2->getObjCoefficients(),
01842                                   (const char*) 0 /*integrality*/,
01843                                   model2->getRowLower(), model2->getRowUpper(),
01844                                   columnNames, rowNames);
01845                 // Pass in array saying if each variable integer
01846                 writer.copyInIntegerInformation(model2->integerInformation());
01847                 writer.writeMps(fileName.c_str(),0,0,1);
01848                 if (rowNames) {
01849                   for (iRow=0;iRow<numberRows;iRow++) {
01850                     free(rowNames[iRow]);
01851                   }
01852                   delete [] rowNames;
01853                   for (iColumn=0;iColumn<numberColumns;iColumn++) {
01854                     free(columnNames[iColumn]);
01855                   }
01856                   delete [] columnNames;
01857                 }
01858                 if (deleteModel2)
01859                   delete model2;
01860                 time2 = CoinCpuTime();
01861                 totalTime += time2-time1;
01862                 time1=time2;
01863               }
01864             }
01865             break;
01866           case SAVE:
01867             {
01868               // get next field
01869               field = getString(argc,argv);
01870               if (field=="$") {
01871                 field = parameters[iParam].stringValue();
01872               } else if (field=="EOL") {
01873                 parameters[iParam].printString();
01874                 break;
01875               } else {
01876                 parameters[iParam].setStringValue(field);
01877               }
01878               std::string fileName;
01879               bool canOpen=false;
01880               if (field[0]=='/'||field[0]=='~')
01881                 fileName = field;
01882               else
01883                 fileName = directory+field;
01884               FILE *fp=fopen(fileName.c_str(),"wb");
01885               if (fp) {
01886                 // can open - lets go for it
01887                 fclose(fp);
01888                 canOpen=true;
01889               } else {
01890                 std::cout<<"Unable to open file "<<fileName<<std::endl;
01891               }
01892               if (canOpen) {
01893                 int status;
01894                 // If presolve on then save presolved
01895                 bool deleteModel2=false;
01896                 ClpSimplex * model2 = models+iModel;
01897                 if (preSolve) {
01898                   ClpPresolve pinfo;
01899                   model2 = 
01900                     pinfo.presolvedModel(models[iModel],1.0e-8,
01901                                          false,preSolve);
01902                   if (model2) {
01903                     printf("Saving presolved model on %s\n",
01904                            fileName.c_str());
01905                     deleteModel2=true;
01906                   } else {
01907                     printf("Presolved model looks infeasible - saving original on %s\n",
01908                            fileName.c_str());
01909                     deleteModel2=false;
01910                     model2 = models+iModel;
01911 
01912                   }
01913                 } else {
01914                   printf("Saving model on %s\n",
01915                            fileName.c_str());
01916                 }
01917                 status =model2->saveModel(fileName.c_str());
01918                 if (deleteModel2)
01919                   delete model2;
01920                 if (!status) {
01921                   goodModels[iModel]=true;
01922                   time2 = CoinCpuTime();
01923                   totalTime += time2-time1;
01924                   time1=time2;
01925                 } else {
01926                   // errors
01927                   std::cout<<"There were errors on output"<<std::endl;
01928                 }
01929               }
01930             }
01931             break;
01932           case RESTORE:
01933             {
01934               // get next field
01935               field = getString(argc,argv);
01936               if (field=="$") {
01937                 field = parameters[iParam].stringValue();
01938               } else if (field=="EOL") {
01939                 parameters[iParam].printString();
01940                 break;
01941               } else {
01942                 parameters[iParam].setStringValue(field);
01943               }
01944               std::string fileName;
01945               bool canOpen=false;
01946               if (field[0]=='/'||field[0]=='~')
01947                 fileName = field;
01948               else
01949                 fileName = directory+field;
01950               FILE *fp=fopen(fileName.c_str(),"rb");
01951               if (fp) {
01952                 // can open - lets go for it
01953                 fclose(fp);
01954                 canOpen=true;
01955               } else {
01956                 std::cout<<"Unable to open file "<<fileName<<std::endl;
01957               }
01958               if (canOpen) {
01959                 int status =models[iModel].restoreModel(fileName.c_str());
01960                 if (!status) {
01961                   goodModels[iModel]=true;
01962                   time2 = CoinCpuTime();
01963                   totalTime += time2-time1;
01964                   time1=time2;
01965                 } else {
01966                   // errors
01967                   std::cout<<"There were errors on input"<<std::endl;
01968                 }
01969               }
01970             }
01971             break;
01972           case MAXIMIZE:
01973             models[iModel].setOptimizationDirection(-1);
01974             break;
01975           case MINIMIZE:
01976             models[iModel].setOptimizationDirection(1);
01977             break;
01978           case ALLSLACK:
01979             models[iModel].createStatus();
01980             {
01981               // and do solution
01982               int iColumn;
01983               double * solution = models[iModel].primalColumnSolution();
01984               const double * lower = models[iModel].columnLower();
01985               const double * upper = models[iModel].columnUpper();
01986               int numberColumns = models[iModel].numberColumns();
01987               for (iColumn=0;iColumn<numberColumns;iColumn++) {
01988                 if (lower[iColumn]>0.0) {
01989                   solution[iColumn]=lower[iColumn];
01990                 } else if (upper[iColumn]<0.0) {
01991                   solution[iColumn]=upper[iColumn];
01992                 } else {
01993                   solution[iColumn]=0.0;
01994                 }
01995               }
01996             }
01997             break;
01998           case REVERSE:
01999             if (goodModels[iModel]) {
02000               int iColumn;
02001               int numberColumns=models[iModel].numberColumns();
02002               double * dualColumnSolution = 
02003                 models[iModel].dualColumnSolution();
02004               ClpObjective * obj = models[iModel].objectiveAsObject();
02005               assert(dynamic_cast<ClpLinearObjective *> (obj));
02006               double offset;
02007               double * objective = obj->gradient(NULL,offset,true);
02008               for (iColumn=0;iColumn<numberColumns;iColumn++) {
02009                 dualColumnSolution[iColumn] = dualColumnSolution[iColumn];
02010                 objective[iColumn] = -objective[iColumn];
02011               }
02012               int iRow;
02013               int numberRows=models[iModel].numberRows();
02014               double * dualRowSolution = 
02015                 models[iModel].dualRowSolution();
02016               for (iRow=0;iRow<numberRows;iRow++) 
02017                 dualRowSolution[iRow] = dualRowSolution[iRow];
02018             }
02019             break;
02020           case DIRECTORY:
02021             {
02022               std::string name = getString(argc,argv);
02023               if (name!="EOL") {
02024                 int length=name.length();
02025                 if (name[length-1]=='/')
02026                   directory=name;
02027                 else
02028                   directory = name+"/";
02029                 parameters[iParam].setStringValue(directory);
02030               } else {
02031                 parameters[iParam].printString();
02032               }
02033             }
02034             break;
02035           case STDIN:
02036             read_mode=-1;
02037             break;
02038           case NETLIB_DUAL:
02039           case NETLIB_PRIMAL:
02040             {
02041               // create fields for unitTest
02042               const char * fields[4];
02043               int nFields=2;
02044               fields[0]="fake main from unitTest";
02045               fields[1]="-netlib";
02046               if (directory!="./") {
02047                 fields[2]="-netlibDir";
02048                 fields[3]=directory.c_str();
02049                 nFields=4;
02050               }
02051               if (type==NETLIB_DUAL)
02052                 std::cerr<<"Doing netlib with dual agorithm"<<std::endl;
02053               else
02054                 std::cerr<<"Doing netlib with primal agorithm"<<std::endl;
02055               mainTest(nFields,fields,(type==NETLIB_DUAL),models[iModel],
02056                        (preSolve!=0),doIdiot);
02057             }
02058             break;
02059           case UNITTEST:
02060             {
02061               // create fields for unitTest
02062               const char * fields[3];
02063               int nFields=1;
02064               fields[0]="fake main from unitTest";
02065               if (directory!="./") {
02066                 fields[1]="-mpsDir";
02067                 fields[2]=directory.c_str();
02068                 nFields=3;
02069               }
02070               mainTest(nFields,fields,false,models[iModel],(preSolve!=0),
02071                        false);
02072             }
02073             break;
02074           case FAKEBOUND:
02075             if (goodModels[iModel]) {
02076               // get bound
02077               double value = getDoubleField(argc,argv,&valid);
02078               if (!valid) {
02079                 std::cout<<"Setting "<<parameters[iParam].name()<<
02080                   " to DEBUG "<<value<<std::endl;
02081                 int iRow;
02082                 int numberRows=models[iModel].numberRows();
02083                 double * rowLower = models[iModel].rowLower();
02084                 double * rowUpper = models[iModel].rowUpper();
02085                 for (iRow=0;iRow<numberRows;iRow++) {
02086                   // leave free ones for now
02087                   if (rowLower[iRow]>-1.0e20||rowUpper[iRow]<1.0e20) {
02088                     rowLower[iRow]=max(rowLower[iRow],-value);
02089                     rowUpper[iRow]=min(rowUpper[iRow],value);
02090                   }
02091                 }
02092                 int iColumn;
02093                 int numberColumns=models[iModel].numberColumns();
02094                 double * columnLower = models[iModel].columnLower();
02095                 double * columnUpper = models[iModel].columnUpper();
02096                 for (iColumn=0;iColumn<numberColumns;iColumn++) {
02097                   // leave free ones for now
02098                   if (columnLower[iColumn]>-1.0e20||
02099                       columnUpper[iColumn]<1.0e20) {
02100                     columnLower[iColumn]=max(columnLower[iColumn],-value);
02101                     columnUpper[iColumn]=min(columnUpper[iColumn],value);
02102                   }
02103                 }
02104               } else if (valid==1) {
02105                 abort();
02106               } else {
02107                 std::cout<<"enter value for "<<parameters[iParam].name()<<
02108                   std::endl;
02109               }
02110             }
02111             break;
02112           case HELP:
02113             std::cout<<"Coin LP version "<<CLPVERSION
02114                      <<", build "<<__DATE__<<std::endl;
02115             std::cout<<"Non default values:-"<<std::endl;
02116             std::cout<<"Perturbation "<<models[0].perturbation()<<" (default 100)"
02117                      <<std::endl;
02118             printit(
02119                     "Presolve being done with 5 passes\n\
02120 Dual steepest edge steep/partial on matrix shape and factorization density\n\
02121 Clpnnnn taken out of messages\n\
02122 If Factorization frequency default then done on size of matrix\n\n\
02123 (-)unitTest, (-)netlib or (-)netlibp will do standard tests\n\n\
02124 You can switch to interactive mode at any time so\n\
02125 clp watson.mps -scaling off -primalsimplex\nis the same as\n\
02126 clp watson.mps -\nscaling off\nprimalsimplex"
02127                     );
02128             break;
02129           case SOLUTION:
02130             if (goodModels[iModel]) {
02131               // get next field
02132               field = getString(argc,argv);
02133               if (field=="$") {
02134                 field = parameters[iParam].stringValue();
02135               } else if (field=="EOL") {
02136                 parameters[iParam].printString();
02137                 break;
02138               } else {
02139                 parameters[iParam].setStringValue(field);
02140               }
02141               std::string fileName;
02142               FILE *fp=NULL;
02143               if (field=="-"||field=="EOL"||field=="stdout") {
02144                 // stdout
02145                 fp=stdout;
02146               } else if (field=="stderr") {
02147                 // stderr
02148                 fp=stderr;
02149               } else {
02150                 if (field[0]=='/'||field[0]=='~')
02151                   fileName = field;
02152                 else
02153                   fileName = directory+field;
02154                 fp=fopen(fileName.c_str(),"w");
02155               }
02156               if (fp) {
02157                 // make fancy later on
02158                 int iRow;
02159                 int numberRows=models[iModel].numberRows();
02160                 int lengthName = models[iModel].lengthNames(); // 0 if no names
02161                 // in general I don't want to pass around massive
02162                 // amounts of data but seems simpler here
02163                 std::vector<std::string> rowNames =
02164                   *(models[iModel].rowNames());
02165                 std::vector<std::string> columnNames =
02166                   *(models[iModel].columnNames());
02167 
02168                 double * dualRowSolution = models[iModel].dualRowSolution();
02169                 double * primalRowSolution = 
02170                   models[iModel].primalRowSolution();
02171                 double * rowLower = models[iModel].rowLower();
02172                 double * rowUpper = models[iModel].rowUpper();
02173                 double primalTolerance = models[iModel].primalTolerance();
02174                 char format[6];
02175                 sprintf(format,"%%-%ds",max(lengthName,8));
02176                 for (iRow=0;iRow<numberRows;iRow++) {
02177                   if (primalRowSolution[iRow]>rowUpper[iRow]+primalTolerance||
02178                       primalRowSolution[iRow]<rowLower[iRow]-primalTolerance)
02179                     fprintf(fp,"** ");
02180                   fprintf(fp,"%7d ",iRow);
02181                   if (lengthName)
02182                     fprintf(fp,format,rowNames[iRow].c_str());
02183                   fprintf(fp,"%15.8g        %15.8g\n",primalRowSolution[iRow],
02184                           dualRowSolution[iRow]);
02185                 }
02186                 int iColumn;
02187                 int numberColumns=models[iModel].numberColumns();
02188                 double * dualColumnSolution = 
02189                   models[iModel].dualColumnSolution();
02190                 double * primalColumnSolution = 
02191                   models[iModel].primalColumnSolution();
02192                 double * columnLower = models[iModel].columnLower();
02193                 double * columnUpper = models[iModel].columnUpper();
02194                 for (iColumn=0;iColumn<numberColumns;iColumn++) {
02195                   if (primalColumnSolution[iColumn]>columnUpper[iColumn]+primalTolerance||
02196                       primalColumnSolution[iColumn]<columnLower[iColumn]-primalTolerance)
02197                     fprintf(fp,"** ");
02198                   fprintf(fp,"%7d ",iColumn);
02199                   if (lengthName)
02200                     fprintf(fp,format,columnNames[iColumn].c_str());
02201                   fprintf(fp,"%15.8g        %15.8g\n",
02202                           primalColumnSolution[iColumn],
02203                           dualColumnSolution[iColumn]);
02204                 }
02205                 if (fp!=stdout)
02206                   fclose(fp);
02207               } else {
02208                 std::cout<<"Unable to open file "<<fileName<<std::endl;
02209               }
02210             } else {
02211               std::cout<<"** Current model not valid"<<std::endl;
02212               
02213             }
02214             break;
02215           default:
02216             abort();
02217           }
02218         } 
02219       } else if (!numberMatches) {
02220         std::cout<<"No match for "<<field<<" - ? for list of commands"
02221                  <<std::endl;
02222       } else if (numberMatches==1) {
02223         if (!numberQuery) {
02224           std::cout<<"Short match for "<<field<<" - completion: ";
02225           std::cout<<parameters[firstMatch].matchName()<<std::endl;
02226         } else if (numberQuery) {
02227           std::cout<<parameters[firstMatch].matchName()<<" : ";
02228           std::cout<<parameters[firstMatch].shortHelp()<<std::endl;
02229           if (numberQuery>=2) 
02230             parameters[firstMatch].printLongHelp();
02231         }
02232       } else {
02233         if (!numberQuery) 
02234           std::cout<<"Multiple matches for "<<field<<" - possible completions:"
02235                    <<std::endl;
02236         else
02237           std::cout<<"Completions of "<<field<<":"<<std::endl;
02238         for ( iParam=0; iParam<numberParameters; iParam++ ) {
02239           int match = parameters[iParam].matches(field);
02240           if (match&&parameters[iParam].displayThis()) {
02241             std::cout<<parameters[iParam].matchName();
02242             if (numberQuery>=2) 
02243               std::cout<<" : "<<parameters[iParam].shortHelp();
02244             std::cout<<std::endl;
02245           }
02246         }
02247       }
02248     }
02249     delete [] models;
02250     delete [] goodModels;
02251   }
02252   // By now all memory should be freed
02253 #ifdef DMALLOC
02254   dmalloc_log_unfreed();
02255   dmalloc_shutdown();
02256 #endif
02257   return 0;
02258 }    

Generated on Wed Dec 3 14:37:26 2003 for CLP by doxygen 1.3.5