source: trunk/Test/ClpMain.cpp @ 374

Last change on this file since 374 was 374, checked in by forrest, 16 years ago

ver

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 72.7 KB
Line 
1// Copyright (C) 2002, International Business Machines
2// Corporation and others.  All Rights Reserved.
3   
4#include "CoinPragma.hpp"
5
6#include <cassert>
7#include <cstdio>
8#include <cmath>
9#include <cfloat>
10#include <string>
11#include <iostream>
12
13
14#include "CoinPragma.hpp"
15#include "CoinHelperFunctions.hpp"
16#define CLPVERSION "0.99.6"
17
18#include "CoinMpsIO.hpp"
19
20#include "ClpFactorization.hpp"
21#include "CoinTime.hpp"
22#include "ClpSimplex.hpp"
23#include "ClpSolve.hpp"
24#include "ClpPackedMatrix.hpp"
25#include "ClpPlusMinusOneMatrix.hpp"
26#include "ClpNetworkMatrix.hpp"
27#include "ClpDualRowSteepest.hpp"
28#include "ClpDualRowDantzig.hpp"
29#include "ClpLinearObjective.hpp"
30#include "ClpPrimalColumnSteepest.hpp"
31#include "ClpPrimalColumnDantzig.hpp"
32#include "ClpPresolve.hpp"
33
34// For Branch and bound
35//  #include "OsiClpSolverInterface.hpp"
36//  #include "OsiCuts.hpp"
37//  #include "OsiRowCut.hpp"
38//  #include "OsiColCut.hpp"
39
40#ifdef DMALLOC
41#include "dmalloc.h"
42#endif
43
44static double totalTime=0.0;
45
46//#############################################################################
47
48#ifdef NDEBUG
49#undef NDEBUG
50#endif
51
52int mainTest (int argc, const char *argv[],bool doDual,
53              ClpSimplex empty, bool doPresolve,int doIdiot);
54enum ClpParameterType {
55  GENERALQUERY=-100,
56 
57  DUALTOLERANCE=1,PRIMALTOLERANCE,DUALBOUND,PRIMALWEIGHT,MAXTIME,OBJSCALE,
58  RHSSCALE,
59
60  LOGLEVEL=101,MAXFACTOR,PERTVALUE,MAXITERATION,PRESOLVEPASS,IDIOT,SPRINT,
61  OUTPUTFORMAT,
62 
63  DIRECTION=201,DUALPIVOT,SCALING,ERRORSALLOWED,KEEPNAMES,SPARSEFACTOR,
64  PRIMALPIVOT,PRESOLVE,CRASH,BIASLU,PERTURBATION,MESSAGES,AUTOSCALE,
65 
66  DIRECTORY=301,IMPORT,EXPORT,RESTORE,SAVE,DUALSIMPLEX,PRIMALSIMPLEX,
67  MAXIMIZE,MINIMIZE,EXIT,STDIN,UNITTEST,NETLIB_DUAL,NETLIB_PRIMAL,SOLUTION,
68  TIGHTEN,FAKEBOUND,HELP,PLUSMINUS,NETWORK,ALLSLACK,REVERSE,BARRIER,
69
70  INVALID=1000
71};
72static void printit(const char * input)
73{
74  int length =strlen(input);
75  char temp[101];
76  int i;
77  int n=0;
78  for (i=0;i<length;i++) {
79    if (input[i]=='\n') {
80      temp[n]='\0';
81      std::cout<<temp<<std::endl;
82      n=0;
83    } else if (n>=65&&input[i]==' ') {
84      temp[n]='\0';
85      std::cout<<temp<<std::endl;
86      n=0;
87    } else if (n||input[i]!=' ') {
88      temp[n++]=input[i];
89    }
90  }
91  if (n) {
92    temp[n]='\0';
93    std::cout<<temp<<std::endl;
94  }
95}
96/// Very simple class for setting parameters
97class ClpItem {
98
99public:
100
101  /**@name Constructor and destructor */
102  //@{
103  /// Constructors
104  ClpItem (  );
105  ClpItem (std::string name, std::string help,
106           double lower, double upper, ClpParameterType type,bool display=true);
107  ClpItem (std::string name, std::string help,
108           int lower, int upper, ClpParameterType type,bool display=true);
109  // Other strings will be added by insert
110  ClpItem (std::string name, std::string help, std::string firstValue,
111           ClpParameterType type,int defaultIndex=0,bool display=true);
112  // Action
113  ClpItem (std::string name, std::string help,
114           ClpParameterType type,int indexNumber=-1,bool display=true);
115  /// Copy constructor.
116  ClpItem(const ClpItem &);
117  /// Assignment operator. This copies the data
118    ClpItem & operator=(const ClpItem & rhs);
119  /// Destructor
120  ~ClpItem (  );
121  //@}
122
123  /**@name stuff */
124  //@{
125  /// Insert string (only valid for keywords)
126  void append(std::string keyWord);
127  /// Adds one help line
128  void addHelp(std::string keyWord);
129  /// Returns name
130  inline std::string  name(  ) const {
131    return name_;
132  };
133  /// Returns short help
134  inline std::string  shortHelp(  ) const {
135    return shortHelp_;
136  };
137  /// Sets a double parameter (nonzero code if error)
138  int setDoubleParameter(ClpSimplex * model, double value) const;
139  /// Gets a double parameter
140  double doubleParameter(ClpSimplex * model) const;
141  /// Sets a int parameter (nonzero code if error)
142  int setIntParameter(ClpSimplex * model, int value) const;
143  /// Gets a int parameter
144  int intParameter(ClpSimplex * model) const;
145  /// Returns name which could match
146  std::string matchName (  ) const;
147  /// Returns parameter option which matches (-1 if none)
148  int parameterOption ( std::string check ) const;
149  /// Prints parameter options
150  void printOptions (  ) const;
151  /// Returns current parameter option
152  inline std::string currentOption (  ) const
153  { return definedKeyWords_[currentKeyWord_]; };
154  /// Sets current parameter option
155  inline void setCurrentOption ( int value )
156  { currentKeyWord_=value; };
157  /// Sets int value
158  inline void setIntValue ( int value )
159  { intValue_=value; };
160  inline int intValue () const
161  { return intValue_; };
162  /// Sets double value
163  inline void setDoubleValue ( double value )
164  { doubleValue_=value; };
165  inline double doubleValue () const
166  { return doubleValue_; };
167  /// Sets string value
168  inline void setStringValue ( std::string value )
169  { stringValue_=value; };
170  inline std::string stringValue () const
171  { return stringValue_; };
172  /// Returns 1 if matches minimum, 2 if matches less, 0 if not matched
173  int matches (std::string input) const;
174  /// type
175  inline ClpParameterType type() const
176  { return type_;};
177  /// whether to display
178  inline bool displayThis() const
179  { return display_;};
180  /// Set Long help
181  inline void setLonghelp(const std::string help) 
182  {longHelp_=help;};
183  /// Print Long help
184  void printLongHelp() const;
185  /// Print action and string
186  void printString() const;
187  /// type for classification
188  inline int indexNumber() const
189  { return indexNumber_;};
190private:
191  /// gutsOfConstructor
192  void gutsOfConstructor();
193  //@}
194////////////////// data //////////////////
195private:
196
197  /**@name data
198   We might as well throw all type data in - could derive?
199  */
200  //@{
201  // Type see ClpParameterType
202  ClpParameterType type_;
203  /// If double == okay
204  double lowerDoubleValue_;
205  double upperDoubleValue_;
206  /// If int == okay
207  int lowerIntValue_;
208  int upperIntValue_;
209  // Length of name
210  unsigned int lengthName_;
211  // Minimum match
212  unsigned int lengthMatch_;
213  /// set of valid strings
214  std::vector<std::string> definedKeyWords_;
215  /// Name
216  std::string name_;
217  /// Short help
218  std::string shortHelp_;
219  /// Long help
220  std::string longHelp_;
221  /// Action
222  ClpParameterType action_;
223  /// Current keyWord (if a keyword parameter)
224  int currentKeyWord_;
225  /// Display on ?
226  bool display_;
227  /// Integer parameter - current value
228  int intValue_;
229  /// Double parameter - current value
230  double doubleValue_;
231  /// String parameter - current value
232  std::string stringValue_;
233  /// index number to use for display purposes
234  int indexNumber_;
235  //@}
236};
237//#############################################################################
238// Constructors / Destructor / Assignment
239//#############################################################################
240
241//-------------------------------------------------------------------
242// Default Constructor
243//-------------------------------------------------------------------
244ClpItem::ClpItem () 
245  : type_(INVALID),
246    lowerDoubleValue_(0.0),
247    upperDoubleValue_(0.0),
248    lowerIntValue_(0),
249    upperIntValue_(0),
250    lengthName_(0),
251    lengthMatch_(0),
252    definedKeyWords_(),
253    name_(),
254    shortHelp_(),
255    longHelp_(),
256    action_(INVALID),
257    currentKeyWord_(-1),
258    display_(false),
259    intValue_(-1),
260    doubleValue_(-1.0),
261    stringValue_(""),
262    indexNumber_(INVALID)
263{
264}
265// Other constructors
266ClpItem::ClpItem (std::string name, std::string help,
267           double lower, double upper, ClpParameterType type,bool display)
268  : type_(type),
269    lowerIntValue_(0),
270    upperIntValue_(0),
271    definedKeyWords_(),
272    name_(name),
273    shortHelp_(help),
274    longHelp_(),
275    action_(type),
276    currentKeyWord_(-1),
277    display_(display),
278    intValue_(-1),
279    doubleValue_(-1.0),
280    stringValue_(""),
281    indexNumber_(type)
282{
283  lowerDoubleValue_ = lower;
284  upperDoubleValue_ = upper;
285  gutsOfConstructor();
286}
287ClpItem::ClpItem (std::string name, std::string help,
288           int lower, int upper, ClpParameterType type,bool display)
289  : type_(type),
290    lowerDoubleValue_(0.0),
291    upperDoubleValue_(0.0),
292    definedKeyWords_(),
293    name_(name),
294    shortHelp_(help),
295    longHelp_(),
296    action_(type),
297    currentKeyWord_(-1),
298    display_(display),
299    intValue_(-1),
300    doubleValue_(-1.0),
301    stringValue_(""),
302    indexNumber_(type)
303{
304  gutsOfConstructor();
305  lowerIntValue_ = lower;
306  upperIntValue_ = upper;
307}
308// Other strings will be added by append
309ClpItem::ClpItem (std::string name, std::string help, 
310                  std::string firstValue,
311                  ClpParameterType type,
312                  int defaultIndex,bool display)
313  : type_(type),
314    lowerDoubleValue_(0.0),
315    upperDoubleValue_(0.0),
316    lowerIntValue_(0),
317    upperIntValue_(0),
318    definedKeyWords_(),
319    name_(name),
320    shortHelp_(help),
321    longHelp_(),
322    action_(type),
323    currentKeyWord_(defaultIndex),
324    display_(display),
325    intValue_(-1),
326    doubleValue_(-1.0),
327    stringValue_(""),
328    indexNumber_(type)
329{
330  gutsOfConstructor();
331  definedKeyWords_.push_back(firstValue);
332}
333// Action
334ClpItem::ClpItem (std::string name, std::string help,
335           ClpParameterType type,int indexNumber,bool display)
336  : type_(type),
337    lowerDoubleValue_(0.0),
338    upperDoubleValue_(0.0),
339    lowerIntValue_(0),
340    upperIntValue_(0),
341    definedKeyWords_(),
342    name_(name),
343    shortHelp_(help),
344    longHelp_(),
345    action_(type),
346    currentKeyWord_(-1),
347    display_(display),
348    intValue_(-1),
349    doubleValue_(-1.0),
350    stringValue_("")
351{
352  if (indexNumber<0)
353    indexNumber_=type;
354  else
355    indexNumber_=indexNumber;
356  gutsOfConstructor();
357}
358
359//-------------------------------------------------------------------
360// Copy constructor
361//-------------------------------------------------------------------
362ClpItem::ClpItem (const ClpItem & rhs) 
363{ 
364  type_ = rhs.type_;
365  lowerDoubleValue_ = rhs.lowerDoubleValue_;
366  upperDoubleValue_ = rhs.upperDoubleValue_;
367  lowerIntValue_ = rhs.lowerIntValue_;
368  upperIntValue_ = rhs.upperIntValue_;
369  lengthName_ = rhs.lengthName_;
370  lengthMatch_ = rhs.lengthMatch_;
371  definedKeyWords_ = rhs.definedKeyWords_;
372  name_ = rhs.name_;
373  shortHelp_ = rhs.shortHelp_;
374  longHelp_ = rhs.longHelp_;
375  action_ = rhs.action_;
376  currentKeyWord_ = rhs.currentKeyWord_;
377  display_=rhs.display_;
378  intValue_=rhs.intValue_;
379  doubleValue_=rhs.doubleValue_;
380  stringValue_=rhs.stringValue_;
381  indexNumber_=rhs.indexNumber_;
382}
383
384//-------------------------------------------------------------------
385// Destructor
386//-------------------------------------------------------------------
387ClpItem::~ClpItem ()
388{
389}
390
391//----------------------------------------------------------------
392// Assignment operator
393//-------------------------------------------------------------------
394ClpItem &
395ClpItem::operator=(const ClpItem& rhs)
396{
397  if (this != &rhs) {
398    type_ = rhs.type_;
399    lowerDoubleValue_ = rhs.lowerDoubleValue_;
400    upperDoubleValue_ = rhs.upperDoubleValue_;
401    lowerIntValue_ = rhs.lowerIntValue_;
402    upperIntValue_ = rhs.upperIntValue_;
403    lengthName_ = rhs.lengthName_;
404    lengthMatch_ = rhs.lengthMatch_;
405    definedKeyWords_ = rhs.definedKeyWords_;
406    name_ = rhs.name_;
407    shortHelp_ = rhs.shortHelp_;
408    longHelp_ = rhs.longHelp_;
409    action_ = rhs.action_;
410    currentKeyWord_ = rhs.currentKeyWord_;
411    display_=rhs.display_;
412    intValue_=rhs.intValue_;
413    doubleValue_=rhs.doubleValue_;
414    stringValue_=rhs.stringValue_;
415    indexNumber_=rhs.indexNumber_;
416  }
417  return *this;
418}
419void 
420ClpItem::gutsOfConstructor()
421{
422  std::string::size_type  shriekPos = name_.find('!');
423  lengthName_ = name_.length();
424  if ( shriekPos==std::string::npos ) {
425    //does not contain '!'
426    lengthMatch_= lengthName_;
427  } else {
428    lengthMatch_=shriekPos;
429    name_ = name_.substr(0,shriekPos)+name_.substr(shriekPos+1);
430    lengthName_--;
431  }
432}
433// Insert string (only valid for keywords)
434void 
435ClpItem::append(std::string keyWord)
436{
437  definedKeyWords_.push_back(keyWord);
438}
439
440int 
441ClpItem::matches (std::string input) const
442{
443  // look up strings to do more elegantly
444  if (input.length()>lengthName_) {
445    return 0;
446  } else {
447    unsigned int i;
448    for (i=0;i<input.length();i++) {
449      if (tolower(name_[i])!=tolower(input[i])) 
450        break;
451    }
452    if (i<input.length()) {
453      return 0;
454    } else if (i>=lengthMatch_) {
455      return 1;
456    } else {
457      // matched but too short
458      return 2;
459    }
460  }
461}
462// Returns name which could match
463std::string
464ClpItem::matchName (  ) const
465{ 
466  if (lengthMatch_==lengthName_) 
467    return name_;
468  else
469    return name_.substr(0,lengthMatch_)+"("+name_.substr(lengthMatch_)+")";
470}
471
472// Returns parameter option which matches (-1 if none)
473int 
474ClpItem::parameterOption ( std::string check ) const
475{
476  int numberItems = definedKeyWords_.size();
477  if (!numberItems) {
478    return -1;
479  } else {
480    int whichItem=0;
481    unsigned int it;
482    for (it=0;it<definedKeyWords_.size();it++) {
483      std::string thisOne = definedKeyWords_[it];
484      std::string::size_type  shriekPos = thisOne.find('!');
485      unsigned int length1 = thisOne.length();
486      unsigned int length2 = length1;
487      if ( shriekPos!=std::string::npos ) {
488        //contains '!'
489        length2 = shriekPos;
490        thisOne = thisOne.substr(0,shriekPos)+
491          thisOne.substr(shriekPos+1);
492        length1 = thisOne.length();
493      }
494      if (check.length()<=length1) {
495        unsigned int i;
496        for (i=0;i<check.length();i++) {
497          if (tolower(thisOne[i])!=tolower(check[i])) 
498            break;
499        }
500        if (i<check.length()) {
501          whichItem++;
502        } else if (i>=length2) {
503          break;
504        } 
505      } else {
506        whichItem++;
507      }
508    }
509    if (whichItem<numberItems)
510      return whichItem;
511    else
512      return -1;
513  }
514}
515// Prints parameter options
516void 
517ClpItem::printOptions (  ) const
518{
519  std::cout<<"Possible options for "<<name_<<" are:"<<std::endl;
520  unsigned int it;
521  for (it=0;it<definedKeyWords_.size();it++) {
522    std::string thisOne = definedKeyWords_[it];
523    std::string::size_type  shriekPos = thisOne.find('!');
524    if ( shriekPos!=std::string::npos ) {
525      //contains '!'
526      thisOne = thisOne.substr(0,shriekPos)+
527        "("+thisOne.substr(shriekPos+1)+")";
528    }
529    std::cout<<thisOne<<std::endl;
530  }
531}
532// Print action and string
533void 
534ClpItem::printString() const
535{
536  if (name_=="directory")
537    std::cout<<"Current working directory is "<<stringValue_<<std::endl;
538  else
539    std::cout<<"Current default (if $ as parameter) for "<<name_
540             <<" is "<<stringValue_<<std::endl;
541}
542int
543ClpItem::setDoubleParameter (ClpSimplex * model,double value) const
544{
545  double oldValue = doubleParameter(model);
546  if (value<lowerDoubleValue_||value>upperDoubleValue_) {
547    std::cout<<value<<" was provided for "<<name_<<
548      " - valid range is "<<lowerDoubleValue_<<" to "<<
549      upperDoubleValue_<<std::endl;
550    return 1;
551  } else {
552    std::cout<<name_<<" was changed from "<<oldValue<<" to "
553             <<value<<std::endl;
554    switch(type_) {
555    case DUALTOLERANCE:
556      model->setDualTolerance(value);
557      break;
558    case PRIMALTOLERANCE:
559      model->setPrimalTolerance(value);
560      break;
561    case DUALBOUND:
562      model->setDualBound(value);
563      break;
564    case PRIMALWEIGHT:
565      model->setInfeasibilityCost(value);
566      break;
567    case MAXTIME:
568      model->setMaximumSeconds(value);
569      break;
570    case OBJSCALE:
571      model->setObjectiveScale(value);
572      break;
573    case RHSSCALE:
574      model->setRhsScale(value);
575      break;
576    default:
577      abort();
578    }
579    return 0;
580  }
581}
582double 
583ClpItem::doubleParameter (ClpSimplex * model) const
584{
585  double value;
586  switch(type_) {
587  case DUALTOLERANCE:
588    value=model->dualTolerance();
589    break;
590  case PRIMALTOLERANCE:
591    value=model->primalTolerance();
592    break;
593  case DUALBOUND:
594    value=model->dualBound();
595    break;
596  case PRIMALWEIGHT:
597    value=model->infeasibilityCost();
598    break;
599  case MAXTIME:
600    value=model->maximumSeconds();
601    break;
602  case OBJSCALE:
603    value=model->objectiveScale();
604    break;
605  case RHSSCALE:
606    value=model->rhsScale();
607    break;
608  default:
609    abort();
610  }
611  return value;
612}
613int 
614ClpItem::setIntParameter (ClpSimplex * model,int value) const
615{
616  int oldValue = intParameter(model);
617  if (value<lowerIntValue_||value>upperIntValue_) {
618    std::cout<<value<<" was provided for "<<name_<<
619      " - valid range is "<<lowerIntValue_<<" to "<<
620      upperIntValue_<<std::endl;
621    return 1;
622  } else {
623    std::cout<<name_<<" was changed from "<<oldValue<<" to "
624             <<value<<std::endl;
625    switch(type_) {
626    case LOGLEVEL:
627      model->setLogLevel(value);
628      if (value>2)
629        model->factorization()->messageLevel(8);
630      else
631        model->factorization()->messageLevel(0);
632      break;
633    case MAXFACTOR:
634      model->factorization()->maximumPivots(value);
635      break;
636    case PERTVALUE:
637      model->setPerturbation(value);
638      break;
639    case MAXITERATION:
640      model->setMaximumIterations(value);
641      break;
642    default:
643      abort();
644    }
645    return 0;
646  }
647}
648int 
649ClpItem::intParameter (ClpSimplex * model) const
650{
651  int value;
652  switch(type_) {
653  case LOGLEVEL:
654    value=model->logLevel();
655    break;
656  case MAXFACTOR:
657    value=model->factorization()->maximumPivots();
658    break;
659    break;
660  case PERTVALUE:
661    value=model->perturbation();
662    break;
663  case MAXITERATION:
664    value=model->maximumIterations();
665    break;
666  default:
667    value=-1;
668    break;
669  }
670  return value;
671}
672// Print Long help
673void 
674ClpItem::printLongHelp() const
675{
676  if (type_>=1&&type_<400) {
677    if (type_<LOGLEVEL) {
678      printf("Range of values is %g to %g\n",lowerDoubleValue_,upperDoubleValue_);
679    } else if (type_<DIRECTION) {
680      printf("Range of values is %d to %d\n",lowerIntValue_,upperIntValue_);
681    } else if (type_<DIRECTORY) {
682      printOptions();
683    }
684    printit(longHelp_.c_str());
685  }
686}
687#ifdef COIN_USE_READLINE     
688#include <readline/readline.h>
689#include <readline/history.h>
690#endif
691// Returns next valid field
692static int read_mode=1;
693static char line[1000];
694static char * where=NULL;
695static FILE * readCommand=stdin;
696std::string
697nextField()
698{
699  std::string field;
700  if (!where) {
701    // need new line
702#ifdef COIN_USE_READLINE     
703    if (readCommand==stdin) {
704      // Get a line from the user.
705      where = readline ("Clp:");
706     
707      // If the line has any text in it, save it on the history.
708      if (where) {
709        if ( *where)
710          add_history (where);
711        strcpy(line,where);
712        free(where);
713      }
714    } else {
715      where = fgets(line,1000,readCommand);
716    }
717#else
718    if (readCommand==stdin) {
719      fprintf(stdout,"Clp:");
720      fflush(stdout);
721    }
722    where = fgets(line,1000,readCommand);
723#endif
724    if (!where)
725      return field; // EOF
726    where = line;
727    // clean image
728    char * lastNonBlank = line-1;
729    while ( *where != '\0' ) {
730      if ( *where != '\t' && *where < ' ' ) {
731        break;
732      } else if ( *where != '\t' && *where != ' ') {
733        lastNonBlank = where;
734      }
735      where++;
736    }
737    where=line;
738    *(lastNonBlank+1)='\0';
739  }
740  // munch white space
741  while(*where==' '||*where=='\t')
742    where++;
743  char * saveWhere = where;
744  while (*where!=' '&&*where!='\t'&&*where!='\0')
745    where++;
746  if (where!=saveWhere) {
747    char save = *where;
748    *where='\0';
749    //convert to string
750    field=saveWhere;
751    *where=save;
752  } else {
753    where=NULL;
754    field="EOL";
755  }
756  return field;
757}
758
759std::string
760getCommand(int argc, const char *argv[])
761{
762  std::string field="EOL";
763  while (field=="EOL") {
764    if (read_mode>0) {
765      if (read_mode<argc) {
766        field = argv[read_mode++];
767        if (field=="-") {
768          std::cout<<"Switching to line mode"<<std::endl;
769          read_mode=-1;
770          field=nextField();
771        } else if (field[0]!='-') {
772          if (read_mode!=2) {
773            std::cout<<"skipping non-command "<<field<<std::endl;
774            field="EOL"; // skip
775          } else {
776            // special dispensation - taken as -import name
777            read_mode--;
778            field="import";
779          }
780        } else {
781          if (field!="--") {
782            // take off -
783            field = field.substr(1);
784          } else {
785            // special dispensation - taken as -import --
786            read_mode--;
787            field="import";
788          }
789        }
790      } else {
791        field="";
792      }
793    } else {
794      field=nextField();
795    }
796  }
797  //std::cout<<field<<std::endl;
798  return field;
799}
800std::string
801getString(int argc, const char *argv[])
802{
803  std::string field="EOL";
804  if (read_mode>0) {
805    if (read_mode<argc) {
806      if (argv[read_mode][0]!='-') { 
807        field = argv[read_mode++];
808      } else if (!strcmp(argv[read_mode],"--")) {
809        field = argv[read_mode++];
810        // -- means import from stdin
811        field = "-";
812      }
813    }
814  } else {
815    field=nextField();
816  }
817  //std::cout<<field<<std::endl;
818  return field;
819}
820// valid 0 - okay, 1 bad, 2 not there
821int
822getIntField(int argc, const char *argv[],int * valid)
823{
824  std::string field="EOL";
825  if (read_mode>0) {
826    if (read_mode<argc) {
827      // may be negative value so do not check for -
828      field = argv[read_mode++];
829    }
830  } else {
831    field=nextField();
832  }
833  int value=0;
834  //std::cout<<field<<std::endl;
835  if (field!="EOL") {
836    // how do I check valid
837    value =  atoi(field.c_str());
838    *valid=0;
839  } else {
840    *valid=2;
841  }
842  return value;
843}
844double
845getDoubleField(int argc, const char *argv[],int * valid)
846{
847  std::string field="EOL";
848  if (read_mode>0) {
849    if (read_mode<argc) {
850      // may be negative value so do not check for -
851      field = argv[read_mode++];
852    }
853  } else {
854    field=nextField();
855  }
856  double value=0.0;
857  //std::cout<<field<<std::endl;
858  if (field!="EOL") {
859    // how do I check valid
860    value = atof(field.c_str());
861    *valid=0;
862  } else {
863    *valid=2;
864  }
865  return value;
866}
867int main (int argc, const char *argv[])
868{
869  // next {} is just to make sure all memory should be freed - for debug
870  {
871    double time1 = CoinCpuTime(),time2;
872    // Set up all non-standard stuff
873    //int numberModels=1;
874    ClpSimplex * models = new ClpSimplex[1];
875   
876    // default action on import
877    int allowImportErrors=0;
878    int keepImportNames=1;
879    int doIdiot=-1;
880    int outputFormat=2;
881    int doCrash=0;
882    int doSprint=-1;
883    // set reasonable defaults
884    int preSolve=5;
885    models->setPerturbation(50);
886    models->messageHandler()->setPrefix(false);
887    std::string directory ="./";
888    std::string importFile ="";
889    std::string exportFile ="default.mps";
890    std::string saveFile ="default.prob";
891    std::string restoreFile ="default.prob";
892    std::string solutionFile ="stdout";
893#define MAXPARAMETERS 100
894    ClpItem parameters[MAXPARAMETERS];
895    int numberParameters=0;
896    parameters[numberParameters++]=
897      ClpItem("?","For help",GENERALQUERY,-1,false);
898    parameters[numberParameters++]=
899      ClpItem("-","From stdin",
900              STDIN,299,false);
901    parameters[numberParameters++]=
902      ClpItem("allS!lack","Set basis back to all slack",
903              ALLSLACK,false);
904    parameters[numberParameters-1].setLonghelp
905      (
906       "Useful for playing around"
907       ); 
908    parameters[numberParameters++]=
909      ClpItem("auto!Scale","Whether to scale objective, rhs and bounds of problem if they look odd",
910              "off",AUTOSCALE,false);
911    parameters[numberParameters-1].append("on");
912    parameters[numberParameters-1].setLonghelp
913      (
914       "If you think you may get odd objective values or large equality rows etc then\
915 it may be worth setting this true.  It is still experimental and you may prefer\
916 to use objective!Scale and rhs!Scale"
917       ); 
918    parameters[numberParameters++]=
919      ClpItem("barr!ier","Solve using primal dual predictor corrector algorithm",
920              BARRIER);
921    parameters[numberParameters-1].setLonghelp
922      (
923       "This command solves the current model using the  primal dual predictor \
924corrector algorithm.  This is not a sophisticated version just something JJF\
925knocked up\
926** another slight drawback (early December) is that it does not work"
927
928       ); 
929    parameters[numberParameters++]=
930      ClpItem("biasLU","Whether factorization biased towards U",
931              "UU",BIASLU,2,false);
932    parameters[numberParameters-1].append("UX");
933    parameters[numberParameters-1].append("LX");
934    parameters[numberParameters-1].append("LL");
935    parameters[numberParameters++]=
936      ClpItem("crash","Whether to create basis for problem",
937              "off",CRASH);
938    parameters[numberParameters-1].append("on");
939    parameters[numberParameters-1].setLonghelp
940      (
941       "If crash is set on and there is an all slack basis then Clp will put structural\
942 variables into basis with the aim of getting dual feasible.  On the whole dual seems to be\
943 better without it and there alernative types of 'crash' for primal e.g. 'idiot' or 'sprint'."
944       ); 
945    parameters[numberParameters++]=
946      ClpItem("direction","Minimize or Maximize",
947              "min!imize",DIRECTION);
948    parameters[numberParameters-1].append("max!imize");
949    parameters[numberParameters-1].append("zero");
950    parameters[numberParameters-1].setLonghelp
951      (
952       "The default is minimize - use 'direction maximize' for maximization.\n\
953You can also use the parameters 'maximize' or 'minimize'."
954       ); 
955    parameters[numberParameters++]=
956      ClpItem("directory","Set Default directory for import etc.",
957              DIRECTORY,299);
958    parameters[numberParameters-1].setLonghelp
959      (
960       "This sets the directory which import, export, saveModel and restoreModel will use.\
961  It is initialized to './'"
962       ); 
963    parameters[numberParameters-1].setStringValue(directory);
964    parameters[numberParameters++]=
965      ClpItem("dualB!ound","Initially algorithm acts as if no \
966gap between bounds exceeds this value",
967              1.0e-20,1.0e12,DUALBOUND);
968    parameters[numberParameters-1].setLonghelp
969      (
970       "The dual algorithm in Clp is a single phase algorithm as opposed to a two phase\
971 algorithm where you first get feasible then optimal.  If a problem has both upper and\
972 lower bounds then it is trivial to get dual feasible by setting non basic variables\
973 to correct bound.  If the gap between the upper and lower bounds of a variable is more\
974 than the value of dualBound Clp introduces fake bounds so that it can make the problem\
975 dual feasible.  This has the same effect as a composite objective function in the\
976 primal algorithm.  Too high a value may mean more iterations, while too low a bound means\
977 the code may go all the way and then have to increase the bounds.  OSL had a heuristic to\
978 adjust bounds, maybe we need that here."
979       );
980    parameters[numberParameters-1].setDoubleValue(models->dualBound());
981    parameters[numberParameters++]=
982      ClpItem("dualP!ivot","Dual pivot choice algorithm",
983              "auto!matic",DUALPIVOT);
984    parameters[numberParameters-1].append("dant!zig");
985    parameters[numberParameters-1].append("partial");
986    parameters[numberParameters-1].append("steep!est");
987    parameters[numberParameters-1].setLonghelp
988      (
989       "Clp can use any pivot selection algorithm which the user codes as long as it\
990 implements the features in the abstract pivot base class.  The Dantzig method is implemented\
991 to show a simple method but its use is deprecated.  Steepest is the method of choice and there\
992 are two variants which keep all weights updated but only scan a subset each iteration.\
993 Partial switches this on while automatic decides at each iteration based on information\
994 about the factorization."
995       ); 
996    parameters[numberParameters++]=
997      ClpItem("dualS!implex","Do dual simplex algorithm",
998              DUALSIMPLEX);
999    parameters[numberParameters-1].setLonghelp
1000      (
1001       "This command solves the current model using the dual steepest algorithm.\
1002The time and iterations may be affected by settings such as presolve, scaling, crash\
1003 and also by dual pivot method, fake bound on variables and dual and primal tolerances."
1004       ); 
1005    parameters[numberParameters++]=
1006      ClpItem("dualT!olerance","For an optimal solution \
1007no dual infeasibility may exceed this value",
1008              1.0e-20,1.0e12,DUALTOLERANCE);
1009    parameters[numberParameters-1].setLonghelp
1010      (
1011       "Normally the default tolerance is fine, but you may want to increase it a\
1012 bit if a dual run seems to be having a hard time"
1013       ); 
1014    parameters[numberParameters-1].setDoubleValue(models->dualTolerance());
1015    parameters[numberParameters++]=
1016      ClpItem("end","Stops clp execution",
1017              EXIT);
1018    parameters[numberParameters-1].setLonghelp
1019      (
1020       "This stops the execution of Clp, end, exit, quit and stop are synonyms"
1021       ); 
1022    parameters[numberParameters++]=
1023      ClpItem("error!sAllowed","Whether to allow import errors",
1024              "off",ERRORSALLOWED);
1025    parameters[numberParameters-1].append("on");
1026    parameters[numberParameters-1].setLonghelp
1027      (
1028       "The default is not to use any model which had errors when reading the mps file.\
1029  Setting this to 'on' will allow all errors from which the code can recover\
1030 by ignoring the error."
1031       );
1032    parameters[numberParameters++]=
1033      ClpItem("exit","Stops clp execution",
1034              EXIT);
1035    parameters[numberParameters-1].setLonghelp
1036      (
1037       "This stops the execution of Clp, end, exit, quit and stop are synonyms"
1038       ); 
1039    parameters[numberParameters++]=
1040      ClpItem("export","Export model as mps file",
1041              EXPORT);
1042    parameters[numberParameters-1].setLonghelp
1043      (
1044       "This will write an MPS format file to the given file name.  It will use the default\
1045 directory given by 'directory'.  A name of '$' will use the previous value for the name.  This\
1046 is initialized to 'default.mps'."
1047       ); 
1048    parameters[numberParameters-1].setStringValue(exportFile);
1049    parameters[numberParameters++]=
1050      ClpItem("fakeB!ound","All bounds <= this value - DEBUG",
1051              1.0,1.0e15,FAKEBOUND,false);
1052    parameters[numberParameters++]=
1053      ClpItem("help","Print out version, non-standard options and some help",
1054              HELP);
1055    parameters[numberParameters++]=
1056      ClpItem("idiot!Crash","Whether to try idiot crash",
1057              -1,200,IDIOT);
1058    parameters[numberParameters-1].setLonghelp
1059      (
1060       "This is a type of 'crash' which works well on some homogeneous problems.\
1061 It works best on problems with unit elements and rhs but will do something to any model.  It should only be\
1062 used before primal.  It can be set to -1 when the code decides for itself whether to use it,\
1063 0 to switch off or n > 0 to do n passes."
1064       ); 
1065    parameters[numberParameters-1].setIntValue(doIdiot);
1066    parameters[numberParameters++]=
1067      ClpItem("import","Import model from mps file",
1068              IMPORT);
1069    parameters[numberParameters-1].setLonghelp
1070      (
1071       "This will read an MPS format file from the given file name.  It will use the default\
1072 directory given by 'directory'.  A name of '$' will use the previous value for the name.  This\
1073 is initialized to '', i.e. it must be set.  If you have libgz then it can read compressed\
1074 files 'xxxxxxxx.gz'.."
1075       ); 
1076    parameters[numberParameters-1].setStringValue(importFile);
1077    parameters[numberParameters++]=
1078      ClpItem("keepN!ames","Whether to keep names from import",
1079              "on",KEEPNAMES);
1080    parameters[numberParameters-1].append("off");
1081    parameters[numberParameters-1].setLonghelp
1082      (
1083       "It saves space to get rid of names so if you need to you can set this to off."
1084       ); 
1085    parameters[numberParameters++]=
1086      ClpItem("log!Level","Level of detail in output",
1087              -1,63,LOGLEVEL);
1088    parameters[numberParameters-1].setLonghelp
1089      (
1090       "If 0 then there should be no output in normal circumstances.  1 is probably the best\
1091 value for most uses, while 2 and 3 give more information."
1092       ); 
1093    parameters[numberParameters-1].setIntValue(models->logLevel());
1094    parameters[numberParameters++]=
1095      ClpItem("max!imize","Set optimization direction to maximize",
1096              MAXIMIZE,299);
1097    parameters[numberParameters-1].setLonghelp
1098      (
1099       "The default is minimize - use 'maximize' for maximization.\n\
1100You can also use the parameters 'direction maximize'."
1101       ); 
1102    parameters[numberParameters++]=
1103      ClpItem("maxF!actor","Maximum number of iterations between \
1104refactorizations",
1105              1,999999,MAXFACTOR);
1106    parameters[numberParameters-1].setLonghelp
1107      (
1108       "If this is at its default value of 200 then in this executable clp will guess at a\
1109 value to use.  Otherwise the user can set a value.  The code may decide to re-factorize\
1110 earlier."
1111       ); 
1112    parameters[numberParameters-1].setIntValue(models->factorizationFrequency());
1113    parameters[numberParameters++]=
1114      ClpItem("maxIt!erations","Maximum number of iterations before \
1115stopping",
1116              0,99999999,MAXITERATION);
1117    parameters[numberParameters-1].setLonghelp
1118      (
1119       "This can be used for testing purposes.  The corresponding library call\n\
1120      \tsetMaximumIterations(value)\n can be useful.  If the code stops on\
1121 seconds or by an interrupt this will be treated as stopping on maximum iterations"
1122       ); 
1123    parameters[numberParameters-1].setIntValue(models->maximumIterations());
1124    parameters[numberParameters++]=
1125      ClpItem("min!imize","Set optimization direction to minimize",
1126              MINIMIZE,299);
1127    parameters[numberParameters-1].setLonghelp
1128      (
1129       "The default is minimize - use 'maximize' for maximization.\n\
1130This should only be necessary if you have previously set maximization \
1131You can also use the parameters 'direction minimize'."
1132       ); 
1133    parameters[numberParameters++]=
1134      ClpItem("mess!ages","Controls if Clpnnnn is printed",
1135              "off",MESSAGES);
1136    parameters[numberParameters-1].append("on");
1137    parameters[numberParameters-1].setLonghelp
1138      ("The default for the Clp library is to put out messages such as:\n\
1139   Clp0005 2261  Objective 109.024 Primal infeas 944413 (758)\n\
1140but this program turns this off to make it look more friendly.  It can be useful\
1141 to turn them back on if you want to be able 'grep' for particular messages or if\
1142 you intend to override the behavior of a particular message."
1143       ); 
1144    parameters[numberParameters++]=
1145      ClpItem("netlib","Solve entire netlib test set",
1146              NETLIB_DUAL);
1147    parameters[numberParameters-1].setLonghelp
1148      (
1149       "This exercises the unit test for clp and then solves the netlib test set using dual.\
1150The user can set options before e.g. clp -presolve off -netlib"
1151       ); 
1152    parameters[numberParameters++]=
1153      ClpItem("netlibP!rimal","Solve entire netlib test set (primal)",
1154              NETLIB_PRIMAL);
1155    parameters[numberParameters-1].setLonghelp
1156      (
1157       "This exercises the unit test for clp and then solves the netlib test set using primal.\
1158The user can set options before e.g. clp -presolve off -netlibp"
1159       ); 
1160    parameters[numberParameters++]=
1161      ClpItem("network","Tries to make network matrix",
1162              NETWORK,-1,false);
1163    parameters[numberParameters-1].setLonghelp
1164      (
1165       "Clp will go faster if the matrix can be converted to a network.  The matrix\
1166 operations may be a bit faster with more efficient storage, but the main advantage\
1167 comes from using a network factorization.  It will probably not be as fast as a \
1168specialized network code."
1169       ); 
1170    parameters[numberParameters++]=
1171      ClpItem("objective!Scale","Scale factor to apply to objective",
1172              -1.0e20,1.0e20,OBJSCALE,false);
1173    parameters[numberParameters-1].setLonghelp
1174      (
1175       "If the objective function has some very large values, you may wish to scale them\
1176 internally by this amount.  It can also be set by autoscale.  It is applied after scaling"
1177       ); 
1178    parameters[numberParameters-1].setDoubleValue(1.0);
1179    parameters[numberParameters++]=
1180      ClpItem("output!Format","Which output format to use",
1181              1,6,OUTPUTFORMAT);
1182    parameters[numberParameters-1].setLonghelp
1183      (
1184       "Normally export will be done using normal representation for numbers and two values\
1185 per line.  You may want to do just one per line (for grep or suchlike) and you may wish\
1186 to save with absolute accuracy using a coded version of the IEEE value. A value of 2 is normal.\
1187 otherwise odd values gives one value per line, even two.  Values 1,2 give normal format, 3,4\
1188 gives greater precision, while 5,6 give IEEE values."
1189       ); 
1190    parameters[numberParameters-1].setIntValue(outputFormat);
1191    parameters[numberParameters++]=
1192      ClpItem("passP!resolve","How many passes in presolve",
1193              0,100,PRESOLVEPASS);
1194    parameters[numberParameters-1].setLonghelp
1195      (
1196       "Normally Presolve does 5 passes but you may want to do less to make it\
1197 more lightweight or do more if improvements are still being made.  As Presolve will return\
1198 if nothing is being taken out, then you should not need to use this fine tuning."
1199       ); 
1200    parameters[numberParameters-1].setIntValue(preSolve);
1201    parameters[numberParameters++]=
1202      ClpItem("pertV!alue","Method of perturbation",
1203              -5000,102,PERTVALUE,false);
1204    parameters[numberParameters-1].setIntValue(models->perturbation());
1205    parameters[numberParameters++]=
1206      ClpItem("perturb!ation","Whether to perturb problem",
1207              "on",PERTURBATION);
1208    parameters[numberParameters-1].append("off");
1209    parameters[numberParameters-1].setLonghelp
1210      (
1211       "Perturbation helps to stop cycling, but Clp uses other measures for this.\
1212  However large problems and especially ones with unit elements and unit rhs or costs\
1213 benefit from perturbation.  Normally Clp tries to be intelligent, but you can switch this off.\
1214  The Clp library has this off by default.  This program has it on."
1215       ); 
1216    parameters[numberParameters++]=
1217      ClpItem("plus!Minus","Tries to make +- 1 matrix",
1218              PLUSMINUS,-1,false);
1219    parameters[numberParameters-1].setLonghelp
1220      (
1221       "Clp will go slightly faster if the matrix can be converted so that the elements are\
1222 not stored and are known to be unit.  The main advantage is memory use.  Clp may automatically\
1223 see if it can convert the problem so you should not need to use this."
1224       ); 
1225    parameters[numberParameters++]=
1226      ClpItem("presolve","Whether to presolve problem",
1227              "on",PRESOLVE);
1228    parameters[numberParameters-1].append("off");
1229    parameters[numberParameters-1].append("more");
1230    parameters[numberParameters-1].setLonghelp
1231      (
1232       "Presolve analyzes the model to find such things as redundant equations, equations\
1233 which fix some variables, equations which can be transformed into bounds etc etc.  For the\
1234 initial solve of any problem this is worth doing unless you know that it will have no effect."
1235       ); 
1236    parameters[numberParameters++]=
1237      ClpItem("primalP!ivot","Primal pivot choice algorithm",
1238              "auto!matic",PRIMALPIVOT);
1239    parameters[numberParameters-1].append("exa!ct");
1240    parameters[numberParameters-1].append("dant!zig");
1241    parameters[numberParameters-1].append("part!ial");
1242    parameters[numberParameters-1].append("steep!est");
1243    parameters[numberParameters-1].append("change");
1244    parameters[numberParameters-1].append("sprint");
1245    parameters[numberParameters-1].setLonghelp
1246      (
1247       "Clp can use any pivot selection algorithm which the user codes as long as it\
1248 implements the features in the abstract pivot base class.  The Dantzig method is implemented\
1249 to show a simple method but its use is deprecated.  Exact devex is the method of choice and there\
1250 are two variants which keep all weights updated but only scan a subset each iteration.\
1251 Partial switches this on while change initially does dantzig until the factorization\
1252 becomes denser.  This is still a work in progress."
1253       ); 
1254    parameters[numberParameters++]=
1255      ClpItem("primalS!implex","Do primal simplex algorithm",
1256              PRIMALSIMPLEX);
1257    parameters[numberParameters-1].setLonghelp
1258      (
1259       "This command solves the current model using the primal algorithm.\
1260  The default is to use exact devex.\
1261 The time and iterations may be affected by settings such as presolve, scaling, crash\
1262 and also by column selection  method, infeasibility weight and dual and primal tolerances."
1263       ); 
1264    parameters[numberParameters++]=
1265      ClpItem("primalT!olerance","For an optimal solution \
1266no primal infeasibility may exceed this value",
1267              1.0e-20,1.0e12,PRIMALTOLERANCE);
1268    parameters[numberParameters-1].setLonghelp
1269      (
1270       "Normally the default tolerance is fine, but you may want to increase it a\
1271 bit if a primal run seems to be having a hard time"
1272       ); 
1273    parameters[numberParameters-1].setDoubleValue(models->primalTolerance());
1274    parameters[numberParameters++]=
1275      ClpItem("primalW!eight","Initially algorithm acts as if it \
1276costs this much to be infeasible",
1277              1.0e-20,1.0e20,PRIMALWEIGHT);
1278    parameters[numberParameters-1].setLonghelp
1279      (
1280       "The primal algorithm in Clp is a single phase algorithm as opposed to a two phase\
1281 algorithm where you first get feasible then optimal.  So Clp is minimizing this weight times\
1282 the sum of primal infeasibilities plus the true objective function (in minimization sense).\
1283  Too high a value may mean more iterations, while too low a bound means\
1284 the code may go all the way and then have to increase the weight in order to get feasible.\
1285  OSL had a heuristic to\
1286 adjust bounds, maybe we need that here."
1287       ); 
1288    parameters[numberParameters-1].setDoubleValue(models->infeasibilityCost());
1289    parameters[numberParameters++]=
1290      ClpItem("quit","Stops clp execution",
1291              EXIT);
1292    parameters[numberParameters-1].setLonghelp
1293      (
1294       "This stops the execution of Clp, end, exit, quit and stop are synonyms"
1295       ); 
1296    parameters[numberParameters++]=
1297      ClpItem("restore!Model","Restore model from binary file",
1298              RESTORE);
1299    parameters[numberParameters-1].setLonghelp
1300      (
1301       "This reads data save by saveModel from the given file.  It will use the default\
1302 directory given by 'directory'.  A name of '$' will use the previous value for the name.  This\
1303 is initialized to 'default.prob'."
1304       ); 
1305    parameters[numberParameters-1].setStringValue(restoreFile);
1306    parameters[numberParameters++]=
1307      ClpItem("reverse","Reverses sign of objective",
1308              REVERSE,false);
1309    parameters[numberParameters-1].setLonghelp
1310      (
1311       "Useful for testing if maximization works correctly"
1312       ); 
1313    parameters[numberParameters++]=
1314      ClpItem("rhs!Scale","Scale factor to apply to rhs and bounds",
1315              -1.0e20,1.0e20,RHSSCALE,false);
1316    parameters[numberParameters-1].setLonghelp
1317      (
1318       "If the rhs or bounds have some very large meaningful values, you may wish to scale them\
1319 internally by this amount.  It can also be set by autoscale"
1320       ); 
1321    parameters[numberParameters-1].setDoubleValue(1.0);
1322    parameters[numberParameters++]=
1323      ClpItem("save!Model","Save model to binary file",
1324              SAVE);
1325    parameters[numberParameters-1].setLonghelp
1326      (
1327       "This will save the problem to the given file name for future use\
1328 by restoreModel.  It will use the default\
1329 directory given by 'directory'.  A name of '$' will use the previous value for the name.  This\
1330 is initialized to 'default.prob'."
1331       ); 
1332    parameters[numberParameters-1].setStringValue(saveFile);
1333    parameters[numberParameters++]=
1334      ClpItem("scal!ing","Whether to scale problem",
1335              "off",SCALING);
1336    parameters[numberParameters-1].append("equi!librium");
1337    parameters[numberParameters-1].append("geo!metric");
1338    parameters[numberParameters-1].append("auto!matic");
1339    parameters[numberParameters-1].setLonghelp
1340      (
1341       "Scaling can help in solving problems which might otherwise fail because of lack of\
1342 accuracy.  It can also reduce the number of iterations.  It is not applied if the range\
1343 of elements is small.  When unscaled it is possible that there may be small primal and/or\
1344 infeasibilities."
1345       ); 
1346    parameters[numberParameters-1].setCurrentOption(3); // say auto
1347    parameters[numberParameters++]=
1348      ClpItem("sec!onds","maximum seconds",
1349              0.0,1.0e12,MAXTIME);
1350    parameters[numberParameters-1].setLonghelp
1351      (
1352       "After this many seconds clp will act as if maximum iterations had been reached.\
1353  In this program it is really only useful for testing but the library function\n\
1354      \tsetMaximumSeconds(value)\n can be useful."
1355       ); 
1356    parameters[numberParameters-1].setDoubleValue(models->maximumSeconds());
1357    parameters[numberParameters++]=
1358      ClpItem("sol!ution","Prints solution to file",
1359              SOLUTION);
1360    parameters[numberParameters-1].setLonghelp
1361      (
1362       "This will write a primitive solution file to the given file name.  It will use the default\
1363 directory given by 'directory'.  A name of '$' will use the previous value for the name.  This\
1364 is initialized to 'stdout'."
1365       ); 
1366    parameters[numberParameters-1].setStringValue(solutionFile);
1367    parameters[numberParameters++]=
1368      ClpItem("spars!eFactor","Whether factorization treated as sparse",
1369              "on",SPARSEFACTOR,0,false);
1370    parameters[numberParameters-1].append("off");
1371    parameters[numberParameters-1].append("on");
1372    parameters[numberParameters++]=
1373      ClpItem("sprint!Crash","Whether to try sprint crash",
1374              -1,500,SPRINT);
1375    parameters[numberParameters-1].setLonghelp
1376      (
1377       "For long and thin problems this program may solve a series of small problems\
1378 created by taking a subset of the columns.  I introduced the idea as 'Sprint' after\
1379 an LP code of that name of the 60's which tried the same tactic (not totally successfully).\
1380  Cplex calls it 'sifting'.  -1 is automatic choice, 0 is off, n is number of passes"
1381       ); 
1382    parameters[numberParameters-1].setIntValue(doSprint);
1383      ClpItem("stdin","From stdin",
1384              STDIN,-1,false);
1385    parameters[numberParameters++]=
1386      ClpItem("stop","Stops clp execution",
1387              EXIT);
1388    parameters[numberParameters-1].setLonghelp
1389      (
1390       "This stops the execution of Clp, end, exit, quit and stop are synonyms"
1391       ); 
1392    parameters[numberParameters++]=
1393      ClpItem("tight!en","Poor person's preSolve for now",
1394              TIGHTEN,-1,false);
1395    parameters[numberParameters++]=
1396      ClpItem("unitTest","Do unit test",
1397              UNITTEST);
1398    parameters[numberParameters-1].setLonghelp
1399      (
1400       "This exercises the unit test for clp"
1401       ); 
1402    assert(numberParameters<MAXPARAMETERS);
1403   
1404    // total number of commands read
1405    int numberGoodCommands=0;
1406    bool * goodModels = new bool[1];
1407   
1408   
1409    int iModel=0;
1410    goodModels[0]=false;
1411    //models[0].scaling(1);
1412    //models[0].setDualBound(1.0e6);
1413    //models[0].setDualTolerance(1.0e-7);
1414    //ClpDualRowSteepest steep;
1415    //models[0].setDualRowPivotAlgorithm(steep);
1416    //models[0].setPrimalTolerance(1.0e-7);
1417    //ClpPrimalColumnSteepest steepP;
1418    //models[0].setPrimalColumnPivotAlgorithm(steepP);
1419    std::string field;
1420    std::cout<<"Coin LP version "<<CLPVERSION
1421             <<", build "<<__DATE__<<std::endl;
1422   
1423    while (1) {
1424      // next command
1425      field=getCommand(argc,argv);
1426     
1427      // exit if null or similar
1428      if (!field.length()) {
1429        if (numberGoodCommands==1&&goodModels[0]) {
1430          // we just had file name - do dual
1431          field="duals";
1432        } else if (!numberGoodCommands) {
1433          // let's give the sucker a hint
1434          std::cout
1435            <<"Clp takes input from arguments ( - switches to stdin)"
1436            <<std::endl
1437            <<"Enter ? for list of commands or help"<<std::endl;
1438          field="-";
1439        } else {
1440          break;
1441        }
1442      }
1443     
1444      // see if ? at end
1445      int numberQuery=0;
1446      if (field!="?") {
1447        int length = field.length();
1448        int i;
1449        for (i=length-1;i>0;i--) {
1450          if (field[i]=='?') 
1451            numberQuery++;
1452          else
1453            break;
1454        }
1455        field=field.substr(0,length-numberQuery);
1456      }
1457      // find out if valid command
1458      int iParam;
1459      int numberMatches=0;
1460      int firstMatch=-1;
1461      for ( iParam=0; iParam<numberParameters; iParam++ ) {
1462        int match = parameters[iParam].matches(field);
1463        if (match==1) {
1464          numberMatches = 1;
1465          firstMatch=iParam;
1466          break;
1467        } else {
1468          if (match&&firstMatch<0)
1469            firstMatch=iParam;
1470          numberMatches += match>>1;
1471        }
1472      }
1473      if (iParam<numberParameters&&!numberQuery) {
1474        // found
1475        ClpItem found = parameters[iParam];
1476        ClpParameterType type = found.type();
1477        int valid;
1478        numberGoodCommands++;
1479        if (type==GENERALQUERY) {
1480          std::cout<<"In argument list keywords have leading - "
1481            ", -stdin or just - switches to stdin"<<std::endl;
1482          std::cout<<"One command per line (and no -)"<<std::endl;
1483          std::cout<<"abcd? gives list of possibilities, if only one + explanation"<<std::endl;
1484          std::cout<<"abcd?? adds explanation, if only one fuller help"<<std::endl;
1485          std::cout<<"abcd without value (where expected) gives current value"<<std::endl;
1486          std::cout<<"abcd value sets value"<<std::endl;
1487          std::cout<<"Commands are:"<<std::endl;
1488          int maxAcross=5;
1489          int limits[]={1,101,201,301,401};
1490          std::vector<std::string> types;
1491          types.push_back("Double parameters:");
1492          types.push_back("Int parameters:");
1493          types.push_back("Keyword parameters and others:");
1494          types.push_back("Actions:");
1495          int iType;
1496          for (iType=0;iType<4;iType++) {
1497            int across=0;
1498            std::cout<<types[iType]<<std::endl;
1499            for ( iParam=0; iParam<numberParameters; iParam++ ) {
1500              int type = parameters[iParam].indexNumber();
1501              if (parameters[iParam].displayThis()&&type>=limits[iType]
1502                  &&type<limits[iType+1]) {
1503                if (!across)
1504                  std::cout<<"  ";
1505                std::cout<<parameters[iParam].matchName()<<"  ";
1506                across++;
1507                if (across==maxAcross) {
1508                  std::cout<<std::endl;
1509                  across=0;
1510                }
1511              }
1512            }
1513            if (across)
1514              std::cout<<std::endl;
1515          }
1516        } else if (type<101) {
1517          // get next field as double
1518          double value = getDoubleField(argc,argv,&valid);
1519          if (!valid) {
1520            parameters[iParam].setDoubleValue(value);
1521            parameters[iParam].setDoubleParameter(models+iModel,value);
1522          } else if (valid==1) {
1523            abort();
1524          } else {
1525            std::cout<<parameters[iParam].name()<<" has value "<<
1526              parameters[iParam].doubleValue()<<std::endl;
1527          }
1528        } else if (type<201) {
1529          // get next field as int
1530          int value = getIntField(argc,argv,&valid);
1531          if (!valid) {
1532            parameters[iParam].setIntValue(value);
1533            if (parameters[iParam].type()==PRESOLVEPASS)
1534              preSolve = value;
1535            else if (parameters[iParam].type()==IDIOT)
1536              doIdiot = value;
1537            else if (parameters[iParam].type()==SPRINT)
1538              doSprint = value;
1539            else if (parameters[iParam].type()==OUTPUTFORMAT)
1540              outputFormat = value;
1541            else
1542              parameters[iParam].setIntParameter(models+iModel,value);
1543          } else if (valid==1) {
1544            abort();
1545          } else {
1546            std::cout<<parameters[iParam].name()<<" has value "<<
1547              parameters[iParam].intValue()<<std::endl;
1548          }
1549        } else if (type<301) {
1550          // one of several strings
1551          std::string value = getString(argc,argv);
1552          int action = parameters[iParam].parameterOption(value);
1553          if (action<0) {
1554            if (value!="EOL") {
1555              // no match
1556              parameters[iParam].printOptions();
1557            } else {
1558              // print current value
1559              std::cout<<parameters[iParam].name()<<" has value "<<
1560                parameters[iParam].currentOption()<<std::endl;
1561            }
1562          } else {
1563            parameters[iParam].setCurrentOption(action);
1564            // for now hard wired
1565            switch (type) {
1566            case DIRECTION:
1567              if (action==0)
1568                models[iModel].setOptimizationDirection(1);
1569              else if (action==1)
1570                models[iModel].setOptimizationDirection(-1);
1571              else
1572                models[iModel].setOptimizationDirection(0);
1573              break;
1574            case DUALPIVOT:
1575              if (action==0) {
1576                ClpDualRowSteepest steep(3);
1577                models[iModel].setDualRowPivotAlgorithm(steep);
1578              } else if (action==1) {
1579                //ClpDualRowDantzig dantzig;
1580                ClpDualRowSteepest dantzig(5);
1581                models[iModel].setDualRowPivotAlgorithm(dantzig);
1582              } else if (action==2) {
1583                // partial steep
1584                ClpDualRowSteepest steep(2);
1585                models[iModel].setDualRowPivotAlgorithm(steep);
1586              } else {
1587                ClpDualRowSteepest steep;
1588                models[iModel].setDualRowPivotAlgorithm(steep);
1589              }
1590              break;
1591            case PRIMALPIVOT:
1592              if (action==0) {
1593                ClpPrimalColumnSteepest steep(3);
1594                models[iModel].setPrimalColumnPivotAlgorithm(steep);
1595              } else if (action==1) {
1596                ClpPrimalColumnSteepest steep(0);
1597                models[iModel].setPrimalColumnPivotAlgorithm(steep);
1598              } else if (action==2) {
1599                ClpPrimalColumnDantzig dantzig;
1600                models[iModel].setPrimalColumnPivotAlgorithm(dantzig);
1601              } else if (action==3) {
1602                ClpPrimalColumnSteepest steep(2);
1603                models[iModel].setPrimalColumnPivotAlgorithm(steep);
1604              } else if (action==4) {
1605                ClpPrimalColumnSteepest steep(1);
1606                models[iModel].setPrimalColumnPivotAlgorithm(steep);
1607              } else if (action==5) {
1608                ClpPrimalColumnSteepest steep(4);
1609                models[iModel].setPrimalColumnPivotAlgorithm(steep);
1610              } else if (action==6) {
1611                ClpPrimalColumnSteepest steep(10);
1612                models[iModel].setPrimalColumnPivotAlgorithm(steep);
1613              }
1614              break;
1615            case SCALING:
1616              models[iModel].scaling(action);
1617              break;
1618            case AUTOSCALE:
1619              models[iModel].setAutomaticScaling(action!=0);
1620              break;
1621            case SPARSEFACTOR:
1622              models[iModel].setSparseFactorization((1-action)!=0);
1623              break;
1624            case BIASLU:
1625              models[iModel].factorization()->setBiasLU(action);
1626              break;
1627            case PERTURBATION:
1628              if (action==0)
1629                models[iModel].setPerturbation(50);
1630              else
1631                models[iModel].setPerturbation(100);
1632              break;
1633            case ERRORSALLOWED:
1634              allowImportErrors = action;
1635              break;
1636            case KEEPNAMES:
1637              keepImportNames = 1-action;
1638              break;
1639            case PRESOLVE:
1640              if (action==0)
1641                preSolve = 5;
1642              else if (action==1)
1643                preSolve=0;
1644              else
1645                preSolve=10;
1646              break;
1647            case CRASH:
1648              doCrash=action;
1649              break;
1650            case MESSAGES:
1651              models[iModel].messageHandler()->setPrefix(action!=0);
1652              break;
1653            default:
1654              abort();
1655            }
1656          }
1657        } else {
1658          // action
1659          if (type==EXIT)
1660            break; // stop all
1661          switch (type) {
1662          case DUALSIMPLEX:
1663          case PRIMALSIMPLEX:
1664          case BARRIER:
1665            if (goodModels[iModel]) {
1666              ClpSolve::SolveType method;
1667              ClpSolve::PresolveType presolveType;
1668              ClpSimplex * model2 = models+iModel;
1669              ClpSolve solveOptions;
1670              if (preSolve!=5&&preSolve)
1671                presolveType=ClpSolve::presolveNumber;
1672              else if (preSolve)
1673                presolveType=ClpSolve::presolveOn;
1674              else
1675                presolveType=ClpSolve::presolveOff;
1676              solveOptions.setPresolveType(presolveType,preSolve);
1677              if (type==DUALSIMPLEX)
1678                method=ClpSolve::useDual;
1679              else if (type==PRIMALSIMPLEX)
1680                method=ClpSolve::usePrimalorSprint;
1681              else
1682                method = ClpSolve::useBarrier;
1683              solveOptions.setSolveType(method);
1684              if (method==ClpSolve::useDual) {
1685                // dual
1686                if (doCrash)
1687                  solveOptions.setSpecialOption(0,1); // crash
1688                else if (doIdiot)
1689                  solveOptions.setSpecialOption(0,2,doIdiot); // possible idiot
1690              } else if (method==ClpSolve::usePrimalorSprint) {
1691                // primal
1692                if (doCrash) {
1693                  solveOptions.setSpecialOption(1,1); // crash
1694                } else if (doSprint>0) {
1695                  // sprint overrides idiot
1696                  solveOptions.setSpecialOption(1,3,doSprint); // sprint
1697                } else if (doIdiot>0) {
1698                  solveOptions.setSpecialOption(1,2,doIdiot); // idiot
1699                } else {
1700                  if (doIdiot==0) {
1701                    if (doSprint==0)
1702                      solveOptions.setSpecialOption(1,4); // all slack
1703                    else
1704                      solveOptions.setSpecialOption(1,9); // all slack or sprint
1705                  } else {
1706                    if (doSprint==0)
1707                      solveOptions.setSpecialOption(1,8); // all slack or idiot
1708                    else
1709                      solveOptions.setSpecialOption(1,7); // initiative
1710                  }
1711                }
1712              }
1713              model2->initialSolve(solveOptions);
1714            } else {
1715              std::cout<<"** Current model not valid"<<std::endl;
1716            }
1717            break;
1718          case TIGHTEN:
1719            if (goodModels[iModel]) {
1720              int numberInfeasibilities = models[iModel].tightenPrimalBounds();
1721              if (numberInfeasibilities)
1722                std::cout<<"** Analysis indicates model infeasible"<<std::endl;
1723            } else {
1724              std::cout<<"** Current model not valid"<<std::endl;
1725            }
1726            break;
1727          case PLUSMINUS:
1728            if (goodModels[iModel]) {
1729              ClpMatrixBase * saveMatrix = models[iModel].clpMatrix();
1730              ClpPackedMatrix* clpMatrix =
1731                dynamic_cast< ClpPackedMatrix*>(saveMatrix);
1732              if (clpMatrix) {
1733                ClpPlusMinusOneMatrix * newMatrix = new ClpPlusMinusOneMatrix(*(clpMatrix->matrix()));
1734                if (newMatrix->getIndices()) {
1735                  models[iModel].replaceMatrix(newMatrix);
1736                  delete saveMatrix;
1737                  std::cout<<"Matrix converted to +- one matrix"<<std::endl;
1738                } else {
1739                  std::cout<<"Matrix can not be converted to +- 1 matrix"<<std::endl;
1740                }
1741              } else {
1742                std::cout<<"Matrix not a ClpPackedMatrix"<<std::endl;
1743              }
1744            } else {
1745              std::cout<<"** Current model not valid"<<std::endl;
1746            }
1747            break;
1748          case NETWORK:
1749            if (goodModels[iModel]) {
1750              ClpMatrixBase * saveMatrix = models[iModel].clpMatrix();
1751              ClpPackedMatrix* clpMatrix =
1752                dynamic_cast< ClpPackedMatrix*>(saveMatrix);
1753              if (clpMatrix) {
1754                ClpNetworkMatrix * newMatrix = new ClpNetworkMatrix(*(clpMatrix->matrix()));
1755                if (newMatrix->getIndices()) {
1756                  models[iModel].replaceMatrix(newMatrix);
1757                  delete saveMatrix;
1758                  std::cout<<"Matrix converted to network matrix"<<std::endl;
1759                } else {
1760                  std::cout<<"Matrix can not be converted to network matrix"<<std::endl;
1761                }
1762              } else {
1763                std::cout<<"Matrix not a ClpPackedMatrix"<<std::endl;
1764              }
1765            } else {
1766              std::cout<<"** Current model not valid"<<std::endl;
1767            }
1768            break;
1769          case IMPORT:
1770            {
1771              // get next field
1772              field = getString(argc,argv);
1773              if (field=="$") {
1774                field = parameters[iParam].stringValue();
1775              } else if (field=="EOL") {
1776                parameters[iParam].printString();
1777                break;
1778              } else {
1779                parameters[iParam].setStringValue(field);
1780              }
1781              std::string fileName;
1782              bool canOpen=false;
1783              if (field=="-") {
1784                // stdin
1785                canOpen=true;
1786                fileName = "-";
1787              } else {
1788                if (field[0]=='/'||field[0]=='~'||field[0]=='\\')
1789                  fileName = field;
1790                else
1791                  fileName = directory+field;
1792                FILE *fp=fopen(fileName.c_str(),"r");
1793                if (fp) {
1794                  // can open - lets go for it
1795                  fclose(fp);
1796                  canOpen=true;
1797                } else {
1798                  std::cout<<"Unable to open file "<<fileName<<std::endl;
1799                }
1800              }
1801              if (canOpen) {
1802                int status =models[iModel].readMps(fileName.c_str(),
1803                                                   keepImportNames!=0,
1804                                                   allowImportErrors!=0);
1805                if (!status||(status>0&&allowImportErrors)) {
1806                  goodModels[iModel]=true;
1807                  // sets to all slack (not necessary?)
1808                  models[iModel].createStatus();
1809                  time2 = CoinCpuTime();
1810                  totalTime += time2-time1;
1811                  time1=time2;
1812                  // Go to canned file if just input file
1813                  if (read_mode==2&&argc==2) {
1814                    // only if ends .mps
1815                    char * find = strstr(fileName.c_str(),".mps");
1816                    if (find&&find[4]=='\0') {
1817                      find[1]='p'; find[2]='a';find[3]='r';
1818                      FILE *fp=fopen(fileName.c_str(),"r");
1819                      if (fp) {
1820                        readCommand=fp; // Read from that file
1821                        read_mode=-1;
1822                      }
1823                    }
1824                  }
1825                } else {
1826                  // errors
1827                  std::cout<<"There were "<<status<<
1828                    " errors on input"<<std::endl;
1829                }
1830              }
1831            }
1832            break;
1833          case EXPORT:
1834            {
1835              // get next field
1836              field = getString(argc,argv);
1837              if (field=="$") {
1838                field = parameters[iParam].stringValue();
1839              } else if (field=="EOL") {
1840                parameters[iParam].printString();
1841                break;
1842              } else {
1843                parameters[iParam].setStringValue(field);
1844              }
1845              std::string fileName;
1846              bool canOpen=false;
1847              if (field[0]=='/'||field[0]=='~')
1848                fileName = field;
1849              else
1850                fileName = directory+field;
1851              FILE *fp=fopen(fileName.c_str(),"w");
1852              if (fp) {
1853                // can open - lets go for it
1854                fclose(fp);
1855                canOpen=true;
1856              } else {
1857                std::cout<<"Unable to open file "<<fileName<<std::endl;
1858              }
1859              if (canOpen) {
1860                // If presolve on then save presolved
1861                bool deleteModel2=false;
1862                ClpSimplex * model2 = models+iModel;
1863                if (preSolve) {
1864                  ClpPresolve pinfo;
1865                  model2 = 
1866                    pinfo.presolvedModel(models[iModel],1.0e-8,
1867                                         true,preSolve);
1868                  if (model2) {
1869                    printf("Saving presolved model on %s\n",
1870                           fileName.c_str());
1871                    deleteModel2=true;
1872                  } else {
1873                    printf("Presolved model looks infeasible - saving original on %s\n",
1874                           fileName.c_str());
1875                    deleteModel2=false;
1876                    model2 = models+iModel;
1877
1878                  }
1879                } else {
1880                  printf("Saving model on %s\n",
1881                           fileName.c_str());
1882                }
1883#if 0
1884                // Convert names
1885                int iRow;
1886                int numberRows=model2->numberRows();
1887                int iColumn;
1888                int numberColumns=model2->numberColumns();
1889
1890                char ** rowNames = NULL;
1891                char ** columnNames = NULL;
1892                if (model2->lengthNames()) {
1893                  rowNames = new char * [numberRows];
1894                  for (iRow=0;iRow<numberRows;iRow++) {
1895                    rowNames[iRow] =
1896                      strdup(model2->rowName(iRow).c_str());
1897#ifdef STRIPBLANKS
1898                    char * xx = rowNames[iRow];
1899                    int i;
1900                    int length = strlen(xx);
1901                    int n=0;
1902                    for (i=0;i<length;i++) {
1903                      if (xx[i]!=' ')
1904                        xx[n++]=xx[i];
1905                    }
1906                    xx[n]='\0';
1907#endif
1908                  }
1909                 
1910                  columnNames = new char * [numberColumns];
1911                  for (iColumn=0;iColumn<numberColumns;iColumn++) {
1912                    columnNames[iColumn] =
1913                      strdup(model2->columnName(iColumn).c_str());
1914#ifdef STRIPBLANKS
1915                    char * xx = columnNames[iColumn];
1916                    int i;
1917                    int length = strlen(xx);
1918                    int n=0;
1919                    for (i=0;i<length;i++) {
1920                      if (xx[i]!=' ')
1921                        xx[n++]=xx[i];
1922                    }
1923                    xx[n]='\0';
1924#endif
1925                  }
1926                }
1927                CoinMpsIO writer;
1928                writer.setMpsData(*model2->matrix(), COIN_DBL_MAX,
1929                                  model2->getColLower(), model2->getColUpper(),
1930                                  model2->getObjCoefficients(),
1931                                  (const char*) 0 /*integrality*/,
1932                                  model2->getRowLower(), model2->getRowUpper(),
1933                                  columnNames, rowNames);
1934                // Pass in array saying if each variable integer
1935                writer.copyInIntegerInformation(model2->integerInformation());
1936                writer.setObjectiveOffset(model2->objectiveOffset());
1937                writer.writeMps(fileName.c_str(),0,1,1);
1938                if (rowNames) {
1939                  for (iRow=0;iRow<numberRows;iRow++) {
1940                    free(rowNames[iRow]);
1941                  }
1942                  delete [] rowNames;
1943                  for (iColumn=0;iColumn<numberColumns;iColumn++) {
1944                    free(columnNames[iColumn]);
1945                  }
1946                  delete [] columnNames;
1947                }
1948#else
1949                model2->writeMps(fileName.c_str(),(outputFormat-1)/2,1+((outputFormat-1)&1));
1950#endif
1951                if (deleteModel2)
1952                  delete model2;
1953                time2 = CoinCpuTime();
1954                totalTime += time2-time1;
1955                time1=time2;
1956              }
1957            }
1958            break;
1959          case SAVE:
1960            {
1961              // get next field
1962              field = getString(argc,argv);
1963              if (field=="$") {
1964                field = parameters[iParam].stringValue();
1965              } else if (field=="EOL") {
1966                parameters[iParam].printString();
1967                break;
1968              } else {
1969                parameters[iParam].setStringValue(field);
1970              }
1971              std::string fileName;
1972              bool canOpen=false;
1973              if (field[0]=='/'||field[0]=='~')
1974                fileName = field;
1975              else
1976                fileName = directory+field;
1977              FILE *fp=fopen(fileName.c_str(),"wb");
1978              if (fp) {
1979                // can open - lets go for it
1980                fclose(fp);
1981                canOpen=true;
1982              } else {
1983                std::cout<<"Unable to open file "<<fileName<<std::endl;
1984              }
1985              if (canOpen) {
1986                int status;
1987                // If presolve on then save presolved
1988                bool deleteModel2=false;
1989                ClpSimplex * model2 = models+iModel;
1990                if (preSolve) {
1991                  ClpPresolve pinfo;
1992                  model2 = 
1993                    pinfo.presolvedModel(models[iModel],1.0e-8,
1994                                         false,preSolve);
1995                  if (model2) {
1996                    printf("Saving presolved model on %s\n",
1997                           fileName.c_str());
1998                    deleteModel2=true;
1999                  } else {
2000                    printf("Presolved model looks infeasible - saving original on %s\n",
2001                           fileName.c_str());
2002                    deleteModel2=false;
2003                    model2 = models+iModel;
2004
2005                  }
2006                } else {
2007                  printf("Saving model on %s\n",
2008                           fileName.c_str());
2009                }
2010                status =model2->saveModel(fileName.c_str());
2011                if (deleteModel2)
2012                  delete model2;
2013                if (!status) {
2014                  goodModels[iModel]=true;
2015                  time2 = CoinCpuTime();
2016                  totalTime += time2-time1;
2017                  time1=time2;
2018                } else {
2019                  // errors
2020                  std::cout<<"There were errors on output"<<std::endl;
2021                }
2022              }
2023            }
2024            break;
2025          case RESTORE:
2026            {
2027              // get next field
2028              field = getString(argc,argv);
2029              if (field=="$") {
2030                field = parameters[iParam].stringValue();
2031              } else if (field=="EOL") {
2032                parameters[iParam].printString();
2033                break;
2034              } else {
2035                parameters[iParam].setStringValue(field);
2036              }
2037              std::string fileName;
2038              bool canOpen=false;
2039              if (field[0]=='/'||field[0]=='~')
2040                fileName = field;
2041              else
2042                fileName = directory+field;
2043              FILE *fp=fopen(fileName.c_str(),"rb");
2044              if (fp) {
2045                // can open - lets go for it
2046                fclose(fp);
2047                canOpen=true;
2048              } else {
2049                std::cout<<"Unable to open file "<<fileName<<std::endl;
2050              }
2051              if (canOpen) {
2052                int status =models[iModel].restoreModel(fileName.c_str());
2053                if (!status) {
2054                  goodModels[iModel]=true;
2055                  time2 = CoinCpuTime();
2056                  totalTime += time2-time1;
2057                  time1=time2;
2058                } else {
2059                  // errors
2060                  std::cout<<"There were errors on input"<<std::endl;
2061                }
2062              }
2063            }
2064            break;
2065          case MAXIMIZE:
2066            models[iModel].setOptimizationDirection(-1);
2067            break;
2068          case MINIMIZE:
2069            models[iModel].setOptimizationDirection(1);
2070            break;
2071          case ALLSLACK:
2072            models[iModel].createStatus();
2073            {
2074              // and do solution
2075              int iColumn;
2076              double * solution = models[iModel].primalColumnSolution();
2077              const double * lower = models[iModel].columnLower();
2078              const double * upper = models[iModel].columnUpper();
2079              int numberColumns = models[iModel].numberColumns();
2080              for (iColumn=0;iColumn<numberColumns;iColumn++) {
2081                if (lower[iColumn]>0.0) {
2082                  solution[iColumn]=lower[iColumn];
2083                } else if (upper[iColumn]<0.0) {
2084                  solution[iColumn]=upper[iColumn];
2085                } else {
2086                  solution[iColumn]=0.0;
2087                }
2088              }
2089            }
2090            break;
2091          case REVERSE:
2092            if (goodModels[iModel]) {
2093              int iColumn;
2094              int numberColumns=models[iModel].numberColumns();
2095              double * dualColumnSolution = 
2096                models[iModel].dualColumnSolution();
2097              ClpObjective * obj = models[iModel].objectiveAsObject();
2098              assert(dynamic_cast<ClpLinearObjective *> (obj));
2099              double offset;
2100              double * objective = obj->gradient(NULL,offset,true);
2101              for (iColumn=0;iColumn<numberColumns;iColumn++) {
2102                dualColumnSolution[iColumn] = dualColumnSolution[iColumn];
2103                objective[iColumn] = -objective[iColumn];
2104              }
2105              int iRow;
2106              int numberRows=models[iModel].numberRows();
2107              double * dualRowSolution = 
2108                models[iModel].dualRowSolution();
2109              for (iRow=0;iRow<numberRows;iRow++) 
2110                dualRowSolution[iRow] = dualRowSolution[iRow];
2111            }
2112            break;
2113          case DIRECTORY:
2114            {
2115              std::string name = getString(argc,argv);
2116              if (name!="EOL") {
2117                int length=name.length();
2118                if (name[length-1]=='/')
2119                  directory=name;
2120                else
2121                  directory = name+"/";
2122                parameters[iParam].setStringValue(directory);
2123              } else {
2124                parameters[iParam].printString();
2125              }
2126            }
2127            break;
2128          case STDIN:
2129            read_mode=-1;
2130            break;
2131          case NETLIB_DUAL:
2132          case NETLIB_PRIMAL:
2133            {
2134              // create fields for unitTest
2135              const char * fields[4];
2136              int nFields=2;
2137              fields[0]="fake main from unitTest";
2138              fields[1]="-netlib";
2139              if (directory!="./") {
2140                fields[2]="-netlibDir";
2141                fields[3]=directory.c_str();
2142                nFields=4;
2143              }
2144              if (type==NETLIB_DUAL)
2145                std::cerr<<"Doing netlib with dual agorithm"<<std::endl;
2146              else
2147                std::cerr<<"Doing netlib with primal agorithm"<<std::endl;
2148              mainTest(nFields,fields,(type==NETLIB_DUAL),models[iModel],
2149                       (preSolve!=0),doIdiot);
2150            }
2151            break;
2152          case UNITTEST:
2153            {
2154              // create fields for unitTest
2155              const char * fields[3];
2156              int nFields=1;
2157              fields[0]="fake main from unitTest";
2158              if (directory!="./") {
2159                fields[1]="-mpsDir";
2160                fields[2]=directory.c_str();
2161                nFields=3;
2162              }
2163              mainTest(nFields,fields,false,models[iModel],(preSolve!=0),
2164                       false);
2165            }
2166            break;
2167          case FAKEBOUND:
2168            if (goodModels[iModel]) {
2169              // get bound
2170              double value = getDoubleField(argc,argv,&valid);
2171              if (!valid) {
2172                std::cout<<"Setting "<<parameters[iParam].name()<<
2173                  " to DEBUG "<<value<<std::endl;
2174                int iRow;
2175                int numberRows=models[iModel].numberRows();
2176                double * rowLower = models[iModel].rowLower();
2177                double * rowUpper = models[iModel].rowUpper();
2178                for (iRow=0;iRow<numberRows;iRow++) {
2179                  // leave free ones for now
2180                  if (rowLower[iRow]>-1.0e20||rowUpper[iRow]<1.0e20) {
2181                    rowLower[iRow]=max(rowLower[iRow],-value);
2182                    rowUpper[iRow]=min(rowUpper[iRow],value);
2183                  }
2184                }
2185                int iColumn;
2186                int numberColumns=models[iModel].numberColumns();
2187                double * columnLower = models[iModel].columnLower();
2188                double * columnUpper = models[iModel].columnUpper();
2189                for (iColumn=0;iColumn<numberColumns;iColumn++) {
2190                  // leave free ones for now
2191                  if (columnLower[iColumn]>-1.0e20||
2192                      columnUpper[iColumn]<1.0e20) {
2193                    columnLower[iColumn]=max(columnLower[iColumn],-value);
2194                    columnUpper[iColumn]=min(columnUpper[iColumn],value);
2195                  }
2196                }
2197              } else if (valid==1) {
2198                abort();
2199              } else {
2200                std::cout<<"enter value for "<<parameters[iParam].name()<<
2201                  std::endl;
2202              }
2203            }
2204            break;
2205          case HELP:
2206            std::cout<<"Coin LP version "<<CLPVERSION
2207                     <<", build "<<__DATE__<<std::endl;
2208            std::cout<<"Non default values:-"<<std::endl;
2209            std::cout<<"Perturbation "<<models[0].perturbation()<<" (default 100)"
2210                     <<std::endl;
2211            printit(
2212                    "Presolve being done with 5 passes\n\
2213Dual steepest edge steep/partial on matrix shape and factorization density\n\
2214Clpnnnn taken out of messages\n\
2215If Factorization frequency default then done on size of matrix\n\n\
2216(-)unitTest, (-)netlib or (-)netlibp will do standard tests\n\n\
2217You can switch to interactive mode at any time so\n\
2218clp watson.mps -scaling off -primalsimplex\nis the same as\n\
2219clp watson.mps -\nscaling off\nprimalsimplex"
2220                    );
2221            break;
2222          case SOLUTION:
2223            if (goodModels[iModel]) {
2224              // get next field
2225              field = getString(argc,argv);
2226              if (field=="$") {
2227                field = parameters[iParam].stringValue();
2228              } else if (field=="EOL") {
2229                parameters[iParam].printString();
2230                break;
2231              } else {
2232                parameters[iParam].setStringValue(field);
2233              }
2234              std::string fileName;
2235              FILE *fp=NULL;
2236              if (field=="-"||field=="EOL"||field=="stdout") {
2237                // stdout
2238                fp=stdout;
2239              } else if (field=="stderr") {
2240                // stderr
2241                fp=stderr;
2242              } else {
2243                if (field[0]=='/'||field[0]=='~')
2244                  fileName = field;
2245                else
2246                  fileName = directory+field;
2247                fp=fopen(fileName.c_str(),"w");
2248              }
2249              if (fp) {
2250                // make fancy later on
2251                int iRow;
2252                int numberRows=models[iModel].numberRows();
2253                int lengthName = models[iModel].lengthNames(); // 0 if no names
2254                // in general I don't want to pass around massive
2255                // amounts of data but seems simpler here
2256                std::vector<std::string> rowNames =
2257                  *(models[iModel].rowNames());
2258                std::vector<std::string> columnNames =
2259                  *(models[iModel].columnNames());
2260
2261                double * dualRowSolution = models[iModel].dualRowSolution();
2262                double * primalRowSolution = 
2263                  models[iModel].primalRowSolution();
2264                double * rowLower = models[iModel].rowLower();
2265                double * rowUpper = models[iModel].rowUpper();
2266                double primalTolerance = models[iModel].primalTolerance();
2267                char format[6];
2268                sprintf(format,"%%-%ds",max(lengthName,8));
2269                for (iRow=0;iRow<numberRows;iRow++) {
2270                  int type=0;
2271                  if (primalRowSolution[iRow]>rowUpper[iRow]+primalTolerance||
2272                      primalRowSolution[iRow]<rowLower[iRow]-primalTolerance) {
2273                    fprintf(fp,"** ");
2274                    type=2;
2275                  } else if (fabs(primalRowSolution[iRow])>1.0e-8) {
2276                    type=1;
2277                  } else if (numberRows<50) {
2278                    type=3;
2279                  }
2280                  if (type) {
2281                    fprintf(fp,"%7d ",iRow);
2282                    if (lengthName)
2283                      fprintf(fp,format,rowNames[iRow].c_str());
2284                    fprintf(fp,"%15.8g        %15.8g\n",primalRowSolution[iRow],
2285                            dualRowSolution[iRow]);
2286                  }
2287                }
2288                int iColumn;
2289                int numberColumns=models[iModel].numberColumns();
2290                double * dualColumnSolution = 
2291                  models[iModel].dualColumnSolution();
2292                double * primalColumnSolution = 
2293                  models[iModel].primalColumnSolution();
2294                double * columnLower = models[iModel].columnLower();
2295                double * columnUpper = models[iModel].columnUpper();
2296                for (iColumn=0;iColumn<numberColumns;iColumn++) {
2297                  int type=0;
2298                  if (primalColumnSolution[iColumn]>columnUpper[iColumn]+primalTolerance||
2299                      primalColumnSolution[iColumn]<columnLower[iColumn]-primalTolerance) {
2300                    fprintf(fp,"** ");
2301                    type=2;
2302                  } else if (fabs(primalColumnSolution[iColumn])>1.0e-8) {
2303                    type=1;
2304                  } else if (numberColumns<50) {
2305                    type=3;
2306                  }
2307                  if (type) {
2308                    fprintf(fp,"%7d ",iColumn);
2309                    if (lengthName)
2310                      fprintf(fp,format,columnNames[iColumn].c_str());
2311                    fprintf(fp,"%15.8g        %15.8g\n",
2312                            primalColumnSolution[iColumn],
2313                            dualColumnSolution[iColumn]);
2314                  }
2315                }
2316                if (fp!=stdout)
2317                  fclose(fp);
2318              } else {
2319                std::cout<<"Unable to open file "<<fileName<<std::endl;
2320              }
2321            } else {
2322              std::cout<<"** Current model not valid"<<std::endl;
2323             
2324            }
2325            break;
2326          default:
2327            abort();
2328          }
2329        } 
2330      } else if (!numberMatches) {
2331        std::cout<<"No match for "<<field<<" - ? for list of commands"
2332                 <<std::endl;
2333      } else if (numberMatches==1) {
2334        if (!numberQuery) {
2335          std::cout<<"Short match for "<<field<<" - completion: ";
2336          std::cout<<parameters[firstMatch].matchName()<<std::endl;
2337        } else if (numberQuery) {
2338          std::cout<<parameters[firstMatch].matchName()<<" : ";
2339          std::cout<<parameters[firstMatch].shortHelp()<<std::endl;
2340          if (numberQuery>=2) 
2341            parameters[firstMatch].printLongHelp();
2342        }
2343      } else {
2344        if (!numberQuery) 
2345          std::cout<<"Multiple matches for "<<field<<" - possible completions:"
2346                   <<std::endl;
2347        else
2348          std::cout<<"Completions of "<<field<<":"<<std::endl;
2349        for ( iParam=0; iParam<numberParameters; iParam++ ) {
2350          int match = parameters[iParam].matches(field);
2351          if (match&&parameters[iParam].displayThis()) {
2352            std::cout<<parameters[iParam].matchName();
2353            if (numberQuery>=2) 
2354              std::cout<<" : "<<parameters[iParam].shortHelp();
2355            std::cout<<std::endl;
2356          }
2357        }
2358      }
2359    }
2360    delete [] models;
2361    delete [] goodModels;
2362  }
2363  // By now all memory should be freed
2364#ifdef DMALLOC
2365  dmalloc_log_unfreed();
2366  dmalloc_shutdown();
2367#endif
2368  return 0;
2369}   
Note: See TracBrowser for help on using the repository browser.