source: trunk/Test/ClpMain.cpp @ 383

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

add barrier

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 74.2 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.7"
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[],int algorithm,
53              ClpSimplex empty, bool doPresolve,int doIdiot);
54enum ClpParameterType {
55  GENERALQUERY=-100,FULLGENERALQUERY,
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,NETLIB_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("???","For help",FULLGENERALQUERY,-1,false);
900    parameters[numberParameters++]=
901      ClpItem("-","From stdin",
902              STDIN,299,false);
903    parameters[numberParameters++]=
904      ClpItem("allS!lack","Set basis back to all slack",
905              ALLSLACK,false);
906    parameters[numberParameters-1].setLonghelp
907      (
908       "Useful for playing around"
909       ); 
910    parameters[numberParameters++]=
911      ClpItem("auto!Scale","Whether to scale objective, rhs and bounds of problem if they look odd",
912              "off",AUTOSCALE,false);
913    parameters[numberParameters-1].append("on");
914    parameters[numberParameters-1].setLonghelp
915      (
916       "If you think you may get odd objective values or large equality rows etc then\
917 it may be worth setting this true.  It is still experimental and you may prefer\
918 to use objective!Scale and rhs!Scale"
919       ); 
920    parameters[numberParameters++]=
921      ClpItem("barr!ier","Solve using primal dual predictor corrector algorithm",
922              BARRIER);
923    parameters[numberParameters-1].setLonghelp
924      (
925       "This command solves the current model using the  primal dual predictor \
926corrector algorithm.  This is not a sophisticated version just something JJF \
927knocked up"
928
929       ); 
930    parameters[numberParameters++]=
931      ClpItem("biasLU","Whether factorization biased towards U",
932              "UU",BIASLU,2,false);
933    parameters[numberParameters-1].append("UX");
934    parameters[numberParameters-1].append("LX");
935    parameters[numberParameters-1].append("LL");
936    parameters[numberParameters++]=
937      ClpItem("crash","Whether to create basis for problem",
938              "off",CRASH);
939    parameters[numberParameters-1].append("on");
940    parameters[numberParameters-1].setLonghelp
941      (
942       "If crash is set on and there is an all slack basis then Clp will put structural\
943 variables into basis with the aim of getting dual feasible.  On the whole dual seems to be\
944 better without it and there alernative types of 'crash' for primal e.g. 'idiot' or 'sprint'."
945       ); 
946    parameters[numberParameters++]=
947      ClpItem("direction","Minimize or Maximize",
948              "min!imize",DIRECTION);
949    parameters[numberParameters-1].append("max!imize");
950    parameters[numberParameters-1].append("zero");
951    parameters[numberParameters-1].setLonghelp
952      (
953       "The default is minimize - use 'direction maximize' for maximization.\n\
954You can also use the parameters 'maximize' or 'minimize'."
955       ); 
956    parameters[numberParameters++]=
957      ClpItem("directory","Set Default directory for import etc.",
958              DIRECTORY,299);
959    parameters[numberParameters-1].setLonghelp
960      (
961       "This sets the directory which import, export, saveModel and restoreModel will use.\
962  It is initialized to './'"
963       ); 
964    parameters[numberParameters-1].setStringValue(directory);
965    parameters[numberParameters++]=
966      ClpItem("dualB!ound","Initially algorithm acts as if no \
967gap between bounds exceeds this value",
968              1.0e-20,1.0e12,DUALBOUND);
969    parameters[numberParameters-1].setLonghelp
970      (
971       "The dual algorithm in Clp is a single phase algorithm as opposed to a two phase\
972 algorithm where you first get feasible then optimal.  If a problem has both upper and\
973 lower bounds then it is trivial to get dual feasible by setting non basic variables\
974 to correct bound.  If the gap between the upper and lower bounds of a variable is more\
975 than the value of dualBound Clp introduces fake bounds so that it can make the problem\
976 dual feasible.  This has the same effect as a composite objective function in the\
977 primal algorithm.  Too high a value may mean more iterations, while too low a bound means\
978 the code may go all the way and then have to increase the bounds.  OSL had a heuristic to\
979 adjust bounds, maybe we need that here."
980       );
981    parameters[numberParameters-1].setDoubleValue(models->dualBound());
982    parameters[numberParameters++]=
983      ClpItem("dualP!ivot","Dual pivot choice algorithm",
984              "auto!matic",DUALPIVOT);
985    parameters[numberParameters-1].append("dant!zig");
986    parameters[numberParameters-1].append("partial");
987    parameters[numberParameters-1].append("steep!est");
988    parameters[numberParameters-1].setLonghelp
989      (
990       "Clp can use any pivot selection algorithm which the user codes as long as it\
991 implements the features in the abstract pivot base class.  The Dantzig method is implemented\
992 to show a simple method but its use is deprecated.  Steepest is the method of choice and there\
993 are two variants which keep all weights updated but only scan a subset each iteration.\
994 Partial switches this on while automatic decides at each iteration based on information\
995 about the factorization."
996       ); 
997    parameters[numberParameters++]=
998      ClpItem("dualS!implex","Do dual simplex algorithm",
999              DUALSIMPLEX);
1000    parameters[numberParameters-1].setLonghelp
1001      (
1002       "This command solves the current model using the dual steepest algorithm.\
1003The time and iterations may be affected by settings such as presolve, scaling, crash\
1004 and also by dual pivot method, fake bound on variables and dual and primal tolerances."
1005       ); 
1006    parameters[numberParameters++]=
1007      ClpItem("dualT!olerance","For an optimal solution \
1008no dual infeasibility may exceed this value",
1009              1.0e-20,1.0e12,DUALTOLERANCE);
1010    parameters[numberParameters-1].setLonghelp
1011      (
1012       "Normally the default tolerance is fine, but you may want to increase it a\
1013 bit if a dual run seems to be having a hard time"
1014       ); 
1015    parameters[numberParameters-1].setDoubleValue(models->dualTolerance());
1016    parameters[numberParameters++]=
1017      ClpItem("end","Stops clp execution",
1018              EXIT);
1019    parameters[numberParameters-1].setLonghelp
1020      (
1021       "This stops the execution of Clp, end, exit, quit and stop are synonyms"
1022       ); 
1023    parameters[numberParameters++]=
1024      ClpItem("error!sAllowed","Whether to allow import errors",
1025              "off",ERRORSALLOWED);
1026    parameters[numberParameters-1].append("on");
1027    parameters[numberParameters-1].setLonghelp
1028      (
1029       "The default is not to use any model which had errors when reading the mps file.\
1030  Setting this to 'on' will allow all errors from which the code can recover\
1031 by ignoring the error."
1032       );
1033    parameters[numberParameters++]=
1034      ClpItem("exit","Stops clp execution",
1035              EXIT);
1036    parameters[numberParameters-1].setLonghelp
1037      (
1038       "This stops the execution of Clp, end, exit, quit and stop are synonyms"
1039       ); 
1040    parameters[numberParameters++]=
1041      ClpItem("export","Export model as mps file",
1042              EXPORT);
1043    parameters[numberParameters-1].setLonghelp
1044      (
1045       "This will write an MPS format file to the given file name.  It will use the default\
1046 directory given by 'directory'.  A name of '$' will use the previous value for the name.  This\
1047 is initialized to 'default.mps'."
1048       ); 
1049    parameters[numberParameters-1].setStringValue(exportFile);
1050    parameters[numberParameters++]=
1051      ClpItem("fakeB!ound","All bounds <= this value - DEBUG",
1052              1.0,1.0e15,FAKEBOUND,false);
1053    parameters[numberParameters++]=
1054      ClpItem("help","Print out version, non-standard options and some help",
1055              HELP);
1056    parameters[numberParameters++]=
1057      ClpItem("idiot!Crash","Whether to try idiot crash",
1058              -1,200,IDIOT);
1059    parameters[numberParameters-1].setLonghelp
1060      (
1061       "This is a type of 'crash' which works well on some homogeneous problems.\
1062 It works best on problems with unit elements and rhs but will do something to any model.  It should only be\
1063 used before primal.  It can be set to -1 when the code decides for itself whether to use it,\
1064 0 to switch off or n > 0 to do n passes."
1065       ); 
1066    parameters[numberParameters-1].setIntValue(doIdiot);
1067    parameters[numberParameters++]=
1068      ClpItem("import","Import model from mps file",
1069              IMPORT);
1070    parameters[numberParameters-1].setLonghelp
1071      (
1072       "This will read an MPS format file from the given file name.  It will use the default\
1073 directory given by 'directory'.  A name of '$' will use the previous value for the name.  This\
1074 is initialized to '', i.e. it must be set.  If you have libgz then it can read compressed\
1075 files 'xxxxxxxx.gz'.."
1076       ); 
1077    parameters[numberParameters-1].setStringValue(importFile);
1078    parameters[numberParameters++]=
1079      ClpItem("keepN!ames","Whether to keep names from import",
1080              "on",KEEPNAMES);
1081    parameters[numberParameters-1].append("off");
1082    parameters[numberParameters-1].setLonghelp
1083      (
1084       "It saves space to get rid of names so if you need to you can set this to off."
1085       ); 
1086    parameters[numberParameters++]=
1087      ClpItem("log!Level","Level of detail in output",
1088              -1,63,LOGLEVEL);
1089    parameters[numberParameters-1].setLonghelp
1090      (
1091       "If 0 then there should be no output in normal circumstances.  1 is probably the best\
1092 value for most uses, while 2 and 3 give more information."
1093       ); 
1094    parameters[numberParameters-1].setIntValue(models->logLevel());
1095    parameters[numberParameters++]=
1096      ClpItem("max!imize","Set optimization direction to maximize",
1097              MAXIMIZE,299);
1098    parameters[numberParameters-1].setLonghelp
1099      (
1100       "The default is minimize - use 'maximize' for maximization.\n\
1101You can also use the parameters 'direction maximize'."
1102       ); 
1103    parameters[numberParameters++]=
1104      ClpItem("maxF!actor","Maximum number of iterations between \
1105refactorizations",
1106              1,999999,MAXFACTOR);
1107    parameters[numberParameters-1].setLonghelp
1108      (
1109       "If this is at its default value of 200 then in this executable clp will guess at a\
1110 value to use.  Otherwise the user can set a value.  The code may decide to re-factorize\
1111 earlier."
1112       ); 
1113    parameters[numberParameters-1].setIntValue(models->factorizationFrequency());
1114    parameters[numberParameters++]=
1115      ClpItem("maxIt!erations","Maximum number of iterations before \
1116stopping",
1117              0,99999999,MAXITERATION);
1118    parameters[numberParameters-1].setLonghelp
1119      (
1120       "This can be used for testing purposes.  The corresponding library call\n\
1121      \tsetMaximumIterations(value)\n can be useful.  If the code stops on\
1122 seconds or by an interrupt this will be treated as stopping on maximum iterations"
1123       ); 
1124    parameters[numberParameters-1].setIntValue(models->maximumIterations());
1125    parameters[numberParameters++]=
1126      ClpItem("min!imize","Set optimization direction to minimize",
1127              MINIMIZE,299);
1128    parameters[numberParameters-1].setLonghelp
1129      (
1130       "The default is minimize - use 'maximize' for maximization.\n\
1131This should only be necessary if you have previously set maximization \
1132You can also use the parameters 'direction minimize'."
1133       ); 
1134    parameters[numberParameters++]=
1135      ClpItem("mess!ages","Controls if Clpnnnn is printed",
1136              "off",MESSAGES);
1137    parameters[numberParameters-1].append("on");
1138    parameters[numberParameters-1].setLonghelp
1139      ("The default for the Clp library is to put out messages such as:\n\
1140   Clp0005 2261  Objective 109.024 Primal infeas 944413 (758)\n\
1141but this program turns this off to make it look more friendly.  It can be useful\
1142 to turn them back on if you want to be able 'grep' for particular messages or if\
1143 you intend to override the behavior of a particular message."
1144       ); 
1145    parameters[numberParameters++]=
1146      ClpItem("netlib","Solve entire netlib test set",
1147              NETLIB_DUAL);
1148    parameters[numberParameters-1].setLonghelp
1149      (
1150       "This exercises the unit test for clp and then solves the netlib test set using dual.\
1151The user can set options before e.g. clp -presolve off -netlib"
1152       ); 
1153#ifdef REAL_BARRIER
1154    parameters[numberParameters++]=
1155      ClpItem("netlibB!arrier","Solve entire netlib test set with barrier",
1156              NETLIB_BARRIER);
1157    parameters[numberParameters-1].setLonghelp
1158      (
1159       "This exercises the unit test for clp and then solves the netlib test set using barrier.\
1160The user can set options before e.g. clp -presolve off -netlib"
1161       ); 
1162#endif
1163    parameters[numberParameters++]=
1164      ClpItem("netlibP!rimal","Solve entire netlib test set (primal)",
1165              NETLIB_PRIMAL);
1166    parameters[numberParameters-1].setLonghelp
1167      (
1168       "This exercises the unit test for clp and then solves the netlib test set using primal.\
1169The user can set options before e.g. clp -presolve off -netlibp"
1170       ); 
1171    parameters[numberParameters++]=
1172      ClpItem("network","Tries to make network matrix",
1173              NETWORK,-1,false);
1174    parameters[numberParameters-1].setLonghelp
1175      (
1176       "Clp will go faster if the matrix can be converted to a network.  The matrix\
1177 operations may be a bit faster with more efficient storage, but the main advantage\
1178 comes from using a network factorization.  It will probably not be as fast as a \
1179specialized network code."
1180       ); 
1181    parameters[numberParameters++]=
1182      ClpItem("objective!Scale","Scale factor to apply to objective",
1183              -1.0e20,1.0e20,OBJSCALE,false);
1184    parameters[numberParameters-1].setLonghelp
1185      (
1186       "If the objective function has some very large values, you may wish to scale them\
1187 internally by this amount.  It can also be set by autoscale.  It is applied after scaling"
1188       ); 
1189    parameters[numberParameters-1].setDoubleValue(1.0);
1190    parameters[numberParameters++]=
1191      ClpItem("output!Format","Which output format to use",
1192              1,6,OUTPUTFORMAT);
1193    parameters[numberParameters-1].setLonghelp
1194      (
1195       "Normally export will be done using normal representation for numbers and two values\
1196 per line.  You may want to do just one per line (for grep or suchlike) and you may wish\
1197 to save with absolute accuracy using a coded version of the IEEE value. A value of 2 is normal.\
1198 otherwise odd values gives one value per line, even two.  Values 1,2 give normal format, 3,4\
1199 gives greater precision, while 5,6 give IEEE values."
1200       ); 
1201    parameters[numberParameters-1].setIntValue(outputFormat);
1202    parameters[numberParameters++]=
1203      ClpItem("passP!resolve","How many passes in presolve",
1204              0,100,PRESOLVEPASS);
1205    parameters[numberParameters-1].setLonghelp
1206      (
1207       "Normally Presolve does 5 passes but you may want to do less to make it\
1208 more lightweight or do more if improvements are still being made.  As Presolve will return\
1209 if nothing is being taken out, then you should not need to use this fine tuning."
1210       ); 
1211    parameters[numberParameters-1].setIntValue(preSolve);
1212    parameters[numberParameters++]=
1213      ClpItem("pertV!alue","Method of perturbation",
1214              -5000,102,PERTVALUE,false);
1215    parameters[numberParameters-1].setIntValue(models->perturbation());
1216    parameters[numberParameters++]=
1217      ClpItem("perturb!ation","Whether to perturb problem",
1218              "on",PERTURBATION);
1219    parameters[numberParameters-1].append("off");
1220    parameters[numberParameters-1].setLonghelp
1221      (
1222       "Perturbation helps to stop cycling, but Clp uses other measures for this.\
1223  However large problems and especially ones with unit elements and unit rhs or costs\
1224 benefit from perturbation.  Normally Clp tries to be intelligent, but you can switch this off.\
1225  The Clp library has this off by default.  This program has it on."
1226       ); 
1227    parameters[numberParameters++]=
1228      ClpItem("plus!Minus","Tries to make +- 1 matrix",
1229              PLUSMINUS,-1,false);
1230    parameters[numberParameters-1].setLonghelp
1231      (
1232       "Clp will go slightly faster if the matrix can be converted so that the elements are\
1233 not stored and are known to be unit.  The main advantage is memory use.  Clp may automatically\
1234 see if it can convert the problem so you should not need to use this."
1235       ); 
1236    parameters[numberParameters++]=
1237      ClpItem("presolve","Whether to presolve problem",
1238              "on",PRESOLVE);
1239    parameters[numberParameters-1].append("off");
1240    parameters[numberParameters-1].append("more");
1241    parameters[numberParameters-1].setLonghelp
1242      (
1243       "Presolve analyzes the model to find such things as redundant equations, equations\
1244 which fix some variables, equations which can be transformed into bounds etc etc.  For the\
1245 initial solve of any problem this is worth doing unless you know that it will have no effect."
1246       ); 
1247    parameters[numberParameters++]=
1248      ClpItem("primalP!ivot","Primal pivot choice algorithm",
1249              "auto!matic",PRIMALPIVOT);
1250    parameters[numberParameters-1].append("exa!ct");
1251    parameters[numberParameters-1].append("dant!zig");
1252    parameters[numberParameters-1].append("part!ial");
1253    parameters[numberParameters-1].append("steep!est");
1254    parameters[numberParameters-1].append("change");
1255    parameters[numberParameters-1].append("sprint");
1256    parameters[numberParameters-1].setLonghelp
1257      (
1258       "Clp can use any pivot selection algorithm which the user codes as long as it\
1259 implements the features in the abstract pivot base class.  The Dantzig method is implemented\
1260 to show a simple method but its use is deprecated.  Exact devex is the method of choice and there\
1261 are two variants which keep all weights updated but only scan a subset each iteration.\
1262 Partial switches this on while change initially does dantzig until the factorization\
1263 becomes denser.  This is still a work in progress."
1264       ); 
1265    parameters[numberParameters++]=
1266      ClpItem("primalS!implex","Do primal simplex algorithm",
1267              PRIMALSIMPLEX);
1268    parameters[numberParameters-1].setLonghelp
1269      (
1270       "This command solves the current model using the primal algorithm.\
1271  The default is to use exact devex.\
1272 The time and iterations may be affected by settings such as presolve, scaling, crash\
1273 and also by column selection  method, infeasibility weight and dual and primal tolerances."
1274       ); 
1275    parameters[numberParameters++]=
1276      ClpItem("primalT!olerance","For an optimal solution \
1277no primal infeasibility may exceed this value",
1278              1.0e-20,1.0e12,PRIMALTOLERANCE);
1279    parameters[numberParameters-1].setLonghelp
1280      (
1281       "Normally the default tolerance is fine, but you may want to increase it a\
1282 bit if a primal run seems to be having a hard time"
1283       ); 
1284    parameters[numberParameters-1].setDoubleValue(models->primalTolerance());
1285    parameters[numberParameters++]=
1286      ClpItem("primalW!eight","Initially algorithm acts as if it \
1287costs this much to be infeasible",
1288              1.0e-20,1.0e20,PRIMALWEIGHT);
1289    parameters[numberParameters-1].setLonghelp
1290      (
1291       "The primal algorithm in Clp is a single phase algorithm as opposed to a two phase\
1292 algorithm where you first get feasible then optimal.  So Clp is minimizing this weight times\
1293 the sum of primal infeasibilities plus the true objective function (in minimization sense).\
1294  Too high a value may mean more iterations, while too low a bound means\
1295 the code may go all the way and then have to increase the weight in order to get feasible.\
1296  OSL had a heuristic to\
1297 adjust bounds, maybe we need that here."
1298       ); 
1299    parameters[numberParameters-1].setDoubleValue(models->infeasibilityCost());
1300    parameters[numberParameters++]=
1301      ClpItem("quit","Stops clp execution",
1302              EXIT);
1303    parameters[numberParameters-1].setLonghelp
1304      (
1305       "This stops the execution of Clp, end, exit, quit and stop are synonyms"
1306       ); 
1307    parameters[numberParameters++]=
1308      ClpItem("restore!Model","Restore model from binary file",
1309              RESTORE);
1310    parameters[numberParameters-1].setLonghelp
1311      (
1312       "This reads data save by saveModel from the given file.  It will use the default\
1313 directory given by 'directory'.  A name of '$' will use the previous value for the name.  This\
1314 is initialized to 'default.prob'."
1315       ); 
1316    parameters[numberParameters-1].setStringValue(restoreFile);
1317    parameters[numberParameters++]=
1318      ClpItem("reverse","Reverses sign of objective",
1319              REVERSE,false);
1320    parameters[numberParameters-1].setLonghelp
1321      (
1322       "Useful for testing if maximization works correctly"
1323       ); 
1324    parameters[numberParameters++]=
1325      ClpItem("rhs!Scale","Scale factor to apply to rhs and bounds",
1326              -1.0e20,1.0e20,RHSSCALE,false);
1327    parameters[numberParameters-1].setLonghelp
1328      (
1329       "If the rhs or bounds have some very large meaningful values, you may wish to scale them\
1330 internally by this amount.  It can also be set by autoscale"
1331       ); 
1332    parameters[numberParameters-1].setDoubleValue(1.0);
1333    parameters[numberParameters++]=
1334      ClpItem("save!Model","Save model to binary file",
1335              SAVE);
1336    parameters[numberParameters-1].setLonghelp
1337      (
1338       "This will save the problem to the given file name for future use\
1339 by restoreModel.  It will use the default\
1340 directory given by 'directory'.  A name of '$' will use the previous value for the name.  This\
1341 is initialized to 'default.prob'."
1342       ); 
1343    parameters[numberParameters-1].setStringValue(saveFile);
1344    parameters[numberParameters++]=
1345      ClpItem("scal!ing","Whether to scale problem",
1346              "off",SCALING);
1347    parameters[numberParameters-1].append("equi!librium");
1348    parameters[numberParameters-1].append("geo!metric");
1349    parameters[numberParameters-1].append("auto!matic");
1350    parameters[numberParameters-1].setLonghelp
1351      (
1352       "Scaling can help in solving problems which might otherwise fail because of lack of\
1353 accuracy.  It can also reduce the number of iterations.  It is not applied if the range\
1354 of elements is small.  When unscaled it is possible that there may be small primal and/or\
1355 infeasibilities."
1356       ); 
1357    parameters[numberParameters-1].setCurrentOption(3); // say auto
1358    parameters[numberParameters++]=
1359      ClpItem("sec!onds","maximum seconds",
1360              0.0,1.0e12,MAXTIME);
1361    parameters[numberParameters-1].setLonghelp
1362      (
1363       "After this many seconds clp will act as if maximum iterations had been reached.\
1364  In this program it is really only useful for testing but the library function\n\
1365      \tsetMaximumSeconds(value)\n can be useful."
1366       ); 
1367    parameters[numberParameters-1].setDoubleValue(models->maximumSeconds());
1368    parameters[numberParameters++]=
1369      ClpItem("sol!ution","Prints solution to file",
1370              SOLUTION);
1371    parameters[numberParameters-1].setLonghelp
1372      (
1373       "This will write a primitive solution file to the given file name.  It will use the default\
1374 directory given by 'directory'.  A name of '$' will use the previous value for the name.  This\
1375 is initialized to 'stdout'."
1376       ); 
1377    parameters[numberParameters-1].setStringValue(solutionFile);
1378    parameters[numberParameters++]=
1379      ClpItem("spars!eFactor","Whether factorization treated as sparse",
1380              "on",SPARSEFACTOR,0,false);
1381    parameters[numberParameters-1].append("off");
1382    parameters[numberParameters-1].append("on");
1383    parameters[numberParameters++]=
1384      ClpItem("sprint!Crash","Whether to try sprint crash",
1385              -1,500,SPRINT);
1386    parameters[numberParameters-1].setLonghelp
1387      (
1388       "For long and thin problems this program may solve a series of small problems\
1389 created by taking a subset of the columns.  I introduced the idea as 'Sprint' after\
1390 an LP code of that name of the 60's which tried the same tactic (not totally successfully).\
1391  Cplex calls it 'sifting'.  -1 is automatic choice, 0 is off, n is number of passes"
1392       ); 
1393    parameters[numberParameters-1].setIntValue(doSprint);
1394      ClpItem("stdin","From stdin",
1395              STDIN,-1,false);
1396    parameters[numberParameters++]=
1397      ClpItem("stop","Stops clp execution",
1398              EXIT);
1399    parameters[numberParameters-1].setLonghelp
1400      (
1401       "This stops the execution of Clp, end, exit, quit and stop are synonyms"
1402       ); 
1403    parameters[numberParameters++]=
1404      ClpItem("tight!en","Poor person's preSolve for now",
1405              TIGHTEN,-1,false);
1406    parameters[numberParameters++]=
1407      ClpItem("unitTest","Do unit test",
1408              UNITTEST);
1409    parameters[numberParameters-1].setLonghelp
1410      (
1411       "This exercises the unit test for clp"
1412       ); 
1413    assert(numberParameters<MAXPARAMETERS);
1414   
1415    // total number of commands read
1416    int numberGoodCommands=0;
1417    bool * goodModels = new bool[1];
1418   
1419   
1420    int iModel=0;
1421    goodModels[0]=false;
1422    //models[0].scaling(1);
1423    //models[0].setDualBound(1.0e6);
1424    //models[0].setDualTolerance(1.0e-7);
1425    //ClpDualRowSteepest steep;
1426    //models[0].setDualRowPivotAlgorithm(steep);
1427    //models[0].setPrimalTolerance(1.0e-7);
1428    //ClpPrimalColumnSteepest steepP;
1429    //models[0].setPrimalColumnPivotAlgorithm(steepP);
1430    std::string field;
1431    std::cout<<"Coin LP version "<<CLPVERSION
1432             <<", build "<<__DATE__<<std::endl;
1433   
1434    while (1) {
1435      // next command
1436      field=getCommand(argc,argv);
1437     
1438      // exit if null or similar
1439      if (!field.length()) {
1440        if (numberGoodCommands==1&&goodModels[0]) {
1441          // we just had file name - do dual
1442          field="duals";
1443        } else if (!numberGoodCommands) {
1444          // let's give the sucker a hint
1445          std::cout
1446            <<"Clp takes input from arguments ( - switches to stdin)"
1447            <<std::endl
1448            <<"Enter ? for list of commands or help"<<std::endl;
1449          field="-";
1450        } else {
1451          break;
1452        }
1453      }
1454     
1455      // see if ? at end
1456      int numberQuery=0;
1457      if (field!="?"&&field!="???") {
1458        int length = field.length();
1459        int i;
1460        for (i=length-1;i>0;i--) {
1461          if (field[i]=='?') 
1462            numberQuery++;
1463          else
1464            break;
1465        }
1466        field=field.substr(0,length-numberQuery);
1467      }
1468      // find out if valid command
1469      int iParam;
1470      int numberMatches=0;
1471      int firstMatch=-1;
1472      for ( iParam=0; iParam<numberParameters; iParam++ ) {
1473        int match = parameters[iParam].matches(field);
1474        if (match==1) {
1475          numberMatches = 1;
1476          firstMatch=iParam;
1477          break;
1478        } else {
1479          if (match&&firstMatch<0)
1480            firstMatch=iParam;
1481          numberMatches += match>>1;
1482        }
1483      }
1484      if (iParam<numberParameters&&!numberQuery) {
1485        // found
1486        ClpItem found = parameters[iParam];
1487        ClpParameterType type = found.type();
1488        int valid;
1489        numberGoodCommands++;
1490        if (type==GENERALQUERY) {
1491          std::cout<<"In argument list keywords have leading - "
1492            ", -stdin or just - switches to stdin"<<std::endl;
1493          std::cout<<"One command per line (and no -)"<<std::endl;
1494          std::cout<<"abcd? gives list of possibilities, if only one + explanation"<<std::endl;
1495          std::cout<<"abcd?? adds explanation, if only one fuller help"<<std::endl;
1496          std::cout<<"abcd without value (where expected) gives current value"<<std::endl;
1497          std::cout<<"abcd value sets value"<<std::endl;
1498          std::cout<<"Commands are:"<<std::endl;
1499          int maxAcross=5;
1500          int limits[]={1,101,201,301,401};
1501          std::vector<std::string> types;
1502          types.push_back("Double parameters:");
1503          types.push_back("Int parameters:");
1504          types.push_back("Keyword parameters and others:");
1505          types.push_back("Actions:");
1506          int iType;
1507          for (iType=0;iType<4;iType++) {
1508            int across=0;
1509            std::cout<<types[iType]<<std::endl;
1510            for ( iParam=0; iParam<numberParameters; iParam++ ) {
1511              int type = parameters[iParam].indexNumber();
1512              if (parameters[iParam].displayThis()&&type>=limits[iType]
1513                  &&type<limits[iType+1]) {
1514                if (!across)
1515                  std::cout<<"  ";
1516                std::cout<<parameters[iParam].matchName()<<"  ";
1517                across++;
1518                if (across==maxAcross) {
1519                  std::cout<<std::endl;
1520                  across=0;
1521                }
1522              }
1523            }
1524            if (across)
1525              std::cout<<std::endl;
1526          }
1527        } else if (type==FULLGENERALQUERY) {
1528          std::cout<<"Full list of ommands is:"<<std::endl;
1529          int maxAcross=5;
1530          int limits[]={1,101,201,301,401};
1531          std::vector<std::string> types;
1532          types.push_back("Double parameters:");
1533          types.push_back("Int parameters:");
1534          types.push_back("Keyword parameters and others:");
1535          types.push_back("Actions:");
1536          int iType;
1537          for (iType=0;iType<4;iType++) {
1538            int across=0;
1539            std::cout<<types[iType]<<std::endl;
1540            for ( iParam=0; iParam<numberParameters; iParam++ ) {
1541              int type = parameters[iParam].indexNumber();
1542              if (type>=limits[iType]
1543                  &&type<limits[iType+1]) {
1544                if (!across)
1545                  std::cout<<"  ";
1546                std::cout<<parameters[iParam].matchName()<<"  ";
1547                across++;
1548                if (across==maxAcross) {
1549                  std::cout<<std::endl;
1550                  across=0;
1551                }
1552              }
1553            }
1554            if (across)
1555              std::cout<<std::endl;
1556          }
1557        } else if (type<101) {
1558          // get next field as double
1559          double value = getDoubleField(argc,argv,&valid);
1560          if (!valid) {
1561            parameters[iParam].setDoubleValue(value);
1562            parameters[iParam].setDoubleParameter(models+iModel,value);
1563          } else if (valid==1) {
1564            abort();
1565          } else {
1566            std::cout<<parameters[iParam].name()<<" has value "<<
1567              parameters[iParam].doubleValue()<<std::endl;
1568          }
1569        } else if (type<201) {
1570          // get next field as int
1571          int value = getIntField(argc,argv,&valid);
1572          if (!valid) {
1573            parameters[iParam].setIntValue(value);
1574            if (parameters[iParam].type()==PRESOLVEPASS)
1575              preSolve = value;
1576            else if (parameters[iParam].type()==IDIOT)
1577              doIdiot = value;
1578            else if (parameters[iParam].type()==SPRINT)
1579              doSprint = value;
1580            else if (parameters[iParam].type()==OUTPUTFORMAT)
1581              outputFormat = value;
1582            else
1583              parameters[iParam].setIntParameter(models+iModel,value);
1584          } else if (valid==1) {
1585            abort();
1586          } else {
1587            std::cout<<parameters[iParam].name()<<" has value "<<
1588              parameters[iParam].intValue()<<std::endl;
1589          }
1590        } else if (type<301) {
1591          // one of several strings
1592          std::string value = getString(argc,argv);
1593          int action = parameters[iParam].parameterOption(value);
1594          if (action<0) {
1595            if (value!="EOL") {
1596              // no match
1597              parameters[iParam].printOptions();
1598            } else {
1599              // print current value
1600              std::cout<<parameters[iParam].name()<<" has value "<<
1601                parameters[iParam].currentOption()<<std::endl;
1602            }
1603          } else {
1604            parameters[iParam].setCurrentOption(action);
1605            // for now hard wired
1606            switch (type) {
1607            case DIRECTION:
1608              if (action==0)
1609                models[iModel].setOptimizationDirection(1);
1610              else if (action==1)
1611                models[iModel].setOptimizationDirection(-1);
1612              else
1613                models[iModel].setOptimizationDirection(0);
1614              break;
1615            case DUALPIVOT:
1616              if (action==0) {
1617                ClpDualRowSteepest steep(3);
1618                models[iModel].setDualRowPivotAlgorithm(steep);
1619              } else if (action==1) {
1620                //ClpDualRowDantzig dantzig;
1621                ClpDualRowSteepest dantzig(5);
1622                models[iModel].setDualRowPivotAlgorithm(dantzig);
1623              } else if (action==2) {
1624                // partial steep
1625                ClpDualRowSteepest steep(2);
1626                models[iModel].setDualRowPivotAlgorithm(steep);
1627              } else {
1628                ClpDualRowSteepest steep;
1629                models[iModel].setDualRowPivotAlgorithm(steep);
1630              }
1631              break;
1632            case PRIMALPIVOT:
1633              if (action==0) {
1634                ClpPrimalColumnSteepest steep(3);
1635                models[iModel].setPrimalColumnPivotAlgorithm(steep);
1636              } else if (action==1) {
1637                ClpPrimalColumnSteepest steep(0);
1638                models[iModel].setPrimalColumnPivotAlgorithm(steep);
1639              } else if (action==2) {
1640                ClpPrimalColumnDantzig dantzig;
1641                models[iModel].setPrimalColumnPivotAlgorithm(dantzig);
1642              } else if (action==3) {
1643                ClpPrimalColumnSteepest steep(2);
1644                models[iModel].setPrimalColumnPivotAlgorithm(steep);
1645              } else if (action==4) {
1646                ClpPrimalColumnSteepest steep(1);
1647                models[iModel].setPrimalColumnPivotAlgorithm(steep);
1648              } else if (action==5) {
1649                ClpPrimalColumnSteepest steep(4);
1650                models[iModel].setPrimalColumnPivotAlgorithm(steep);
1651              } else if (action==6) {
1652                ClpPrimalColumnSteepest steep(10);
1653                models[iModel].setPrimalColumnPivotAlgorithm(steep);
1654              }
1655              break;
1656            case SCALING:
1657              models[iModel].scaling(action);
1658              break;
1659            case AUTOSCALE:
1660              models[iModel].setAutomaticScaling(action!=0);
1661              break;
1662            case SPARSEFACTOR:
1663              models[iModel].setSparseFactorization((1-action)!=0);
1664              break;
1665            case BIASLU:
1666              models[iModel].factorization()->setBiasLU(action);
1667              break;
1668            case PERTURBATION:
1669              if (action==0)
1670                models[iModel].setPerturbation(50);
1671              else
1672                models[iModel].setPerturbation(100);
1673              break;
1674            case ERRORSALLOWED:
1675              allowImportErrors = action;
1676              break;
1677            case KEEPNAMES:
1678              keepImportNames = 1-action;
1679              break;
1680            case PRESOLVE:
1681              if (action==0)
1682                preSolve = 5;
1683              else if (action==1)
1684                preSolve=0;
1685              else
1686                preSolve=10;
1687              break;
1688            case CRASH:
1689              doCrash=action;
1690              break;
1691            case MESSAGES:
1692              models[iModel].messageHandler()->setPrefix(action!=0);
1693              break;
1694            default:
1695              abort();
1696            }
1697          }
1698        } else {
1699          // action
1700          if (type==EXIT)
1701            break; // stop all
1702          switch (type) {
1703          case DUALSIMPLEX:
1704          case PRIMALSIMPLEX:
1705          case BARRIER:
1706            if (goodModels[iModel]) {
1707              ClpSolve::SolveType method;
1708              ClpSolve::PresolveType presolveType;
1709              ClpSimplex * model2 = models+iModel;
1710              ClpSolve solveOptions;
1711              if (preSolve!=5&&preSolve)
1712                presolveType=ClpSolve::presolveNumber;
1713              else if (preSolve)
1714                presolveType=ClpSolve::presolveOn;
1715              else
1716                presolveType=ClpSolve::presolveOff;
1717              solveOptions.setPresolveType(presolveType,preSolve);
1718              if (type==DUALSIMPLEX)
1719                method=ClpSolve::useDual;
1720              else if (type==PRIMALSIMPLEX)
1721                method=ClpSolve::usePrimalorSprint;
1722              else
1723                method = ClpSolve::useBarrier;
1724              solveOptions.setSolveType(method);
1725              if (method==ClpSolve::useDual) {
1726                // dual
1727                if (doCrash)
1728                  solveOptions.setSpecialOption(0,1); // crash
1729                else if (doIdiot)
1730                  solveOptions.setSpecialOption(0,2,doIdiot); // possible idiot
1731              } else if (method==ClpSolve::usePrimalorSprint) {
1732                // primal
1733                if (doCrash) {
1734                  solveOptions.setSpecialOption(1,1); // crash
1735                } else if (doSprint>0) {
1736                  // sprint overrides idiot
1737                  solveOptions.setSpecialOption(1,3,doSprint); // sprint
1738                } else if (doIdiot>0) {
1739                  solveOptions.setSpecialOption(1,2,doIdiot); // idiot
1740                } else {
1741                  if (doIdiot==0) {
1742                    if (doSprint==0)
1743                      solveOptions.setSpecialOption(1,4); // all slack
1744                    else
1745                      solveOptions.setSpecialOption(1,9); // all slack or sprint
1746                  } else {
1747                    if (doSprint==0)
1748                      solveOptions.setSpecialOption(1,8); // all slack or idiot
1749                    else
1750                      solveOptions.setSpecialOption(1,7); // initiative
1751                  }
1752                }
1753              }
1754              model2->initialSolve(solveOptions);
1755            } else {
1756              std::cout<<"** Current model not valid"<<std::endl;
1757            }
1758            break;
1759          case TIGHTEN:
1760            if (goodModels[iModel]) {
1761              int numberInfeasibilities = models[iModel].tightenPrimalBounds();
1762              if (numberInfeasibilities)
1763                std::cout<<"** Analysis indicates model infeasible"<<std::endl;
1764            } else {
1765              std::cout<<"** Current model not valid"<<std::endl;
1766            }
1767            break;
1768          case PLUSMINUS:
1769            if (goodModels[iModel]) {
1770              ClpMatrixBase * saveMatrix = models[iModel].clpMatrix();
1771              ClpPackedMatrix* clpMatrix =
1772                dynamic_cast< ClpPackedMatrix*>(saveMatrix);
1773              if (clpMatrix) {
1774                ClpPlusMinusOneMatrix * newMatrix = new ClpPlusMinusOneMatrix(*(clpMatrix->matrix()));
1775                if (newMatrix->getIndices()) {
1776                  models[iModel].replaceMatrix(newMatrix);
1777                  delete saveMatrix;
1778                  std::cout<<"Matrix converted to +- one matrix"<<std::endl;
1779                } else {
1780                  std::cout<<"Matrix can not be converted to +- 1 matrix"<<std::endl;
1781                }
1782              } else {
1783                std::cout<<"Matrix not a ClpPackedMatrix"<<std::endl;
1784              }
1785            } else {
1786              std::cout<<"** Current model not valid"<<std::endl;
1787            }
1788            break;
1789          case NETWORK:
1790            if (goodModels[iModel]) {
1791              ClpMatrixBase * saveMatrix = models[iModel].clpMatrix();
1792              ClpPackedMatrix* clpMatrix =
1793                dynamic_cast< ClpPackedMatrix*>(saveMatrix);
1794              if (clpMatrix) {
1795                ClpNetworkMatrix * newMatrix = new ClpNetworkMatrix(*(clpMatrix->matrix()));
1796                if (newMatrix->getIndices()) {
1797                  models[iModel].replaceMatrix(newMatrix);
1798                  delete saveMatrix;
1799                  std::cout<<"Matrix converted to network matrix"<<std::endl;
1800                } else {
1801                  std::cout<<"Matrix can not be converted to network matrix"<<std::endl;
1802                }
1803              } else {
1804                std::cout<<"Matrix not a ClpPackedMatrix"<<std::endl;
1805              }
1806            } else {
1807              std::cout<<"** Current model not valid"<<std::endl;
1808            }
1809            break;
1810          case IMPORT:
1811            {
1812              // get next field
1813              field = getString(argc,argv);
1814              if (field=="$") {
1815                field = parameters[iParam].stringValue();
1816              } else if (field=="EOL") {
1817                parameters[iParam].printString();
1818                break;
1819              } else {
1820                parameters[iParam].setStringValue(field);
1821              }
1822              std::string fileName;
1823              bool canOpen=false;
1824              if (field=="-") {
1825                // stdin
1826                canOpen=true;
1827                fileName = "-";
1828              } else {
1829                if (field[0]=='/'||field[0]=='~'||field[0]=='\\')
1830                  fileName = field;
1831                else
1832                  fileName = directory+field;
1833                FILE *fp=fopen(fileName.c_str(),"r");
1834                if (fp) {
1835                  // can open - lets go for it
1836                  fclose(fp);
1837                  canOpen=true;
1838                } else {
1839                  std::cout<<"Unable to open file "<<fileName<<std::endl;
1840                }
1841              }
1842              if (canOpen) {
1843                int status =models[iModel].readMps(fileName.c_str(),
1844                                                   keepImportNames!=0,
1845                                                   allowImportErrors!=0);
1846                if (!status||(status>0&&allowImportErrors)) {
1847                  goodModels[iModel]=true;
1848                  // sets to all slack (not necessary?)
1849                  models[iModel].createStatus();
1850                  time2 = CoinCpuTime();
1851                  totalTime += time2-time1;
1852                  time1=time2;
1853                  // Go to canned file if just input file
1854                  if (read_mode==2&&argc==2) {
1855                    // only if ends .mps
1856                    char * find = strstr(fileName.c_str(),".mps");
1857                    if (find&&find[4]=='\0') {
1858                      find[1]='p'; find[2]='a';find[3]='r';
1859                      FILE *fp=fopen(fileName.c_str(),"r");
1860                      if (fp) {
1861                        readCommand=fp; // Read from that file
1862                        read_mode=-1;
1863                      }
1864                    }
1865                  }
1866                } else {
1867                  // errors
1868                  std::cout<<"There were "<<status<<
1869                    " errors on input"<<std::endl;
1870                }
1871              }
1872            }
1873            break;
1874          case EXPORT:
1875            {
1876              // get next field
1877              field = getString(argc,argv);
1878              if (field=="$") {
1879                field = parameters[iParam].stringValue();
1880              } else if (field=="EOL") {
1881                parameters[iParam].printString();
1882                break;
1883              } else {
1884                parameters[iParam].setStringValue(field);
1885              }
1886              std::string fileName;
1887              bool canOpen=false;
1888              if (field[0]=='/'||field[0]=='~')
1889                fileName = field;
1890              else
1891                fileName = directory+field;
1892              FILE *fp=fopen(fileName.c_str(),"w");
1893              if (fp) {
1894                // can open - lets go for it
1895                fclose(fp);
1896                canOpen=true;
1897              } else {
1898                std::cout<<"Unable to open file "<<fileName<<std::endl;
1899              }
1900              if (canOpen) {
1901                // If presolve on then save presolved
1902                bool deleteModel2=false;
1903                ClpSimplex * model2 = models+iModel;
1904                if (preSolve) {
1905                  ClpPresolve pinfo;
1906                  model2 = 
1907                    pinfo.presolvedModel(models[iModel],1.0e-8,
1908                                         true,preSolve);
1909                  if (model2) {
1910                    printf("Saving presolved model on %s\n",
1911                           fileName.c_str());
1912                    deleteModel2=true;
1913                  } else {
1914                    printf("Presolved model looks infeasible - saving original on %s\n",
1915                           fileName.c_str());
1916                    deleteModel2=false;
1917                    model2 = models+iModel;
1918
1919                  }
1920                } else {
1921                  printf("Saving model on %s\n",
1922                           fileName.c_str());
1923                }
1924#if 0
1925                // Convert names
1926                int iRow;
1927                int numberRows=model2->numberRows();
1928                int iColumn;
1929                int numberColumns=model2->numberColumns();
1930
1931                char ** rowNames = NULL;
1932                char ** columnNames = NULL;
1933                if (model2->lengthNames()) {
1934                  rowNames = new char * [numberRows];
1935                  for (iRow=0;iRow<numberRows;iRow++) {
1936                    rowNames[iRow] =
1937                      strdup(model2->rowName(iRow).c_str());
1938#ifdef STRIPBLANKS
1939                    char * xx = rowNames[iRow];
1940                    int i;
1941                    int length = strlen(xx);
1942                    int n=0;
1943                    for (i=0;i<length;i++) {
1944                      if (xx[i]!=' ')
1945                        xx[n++]=xx[i];
1946                    }
1947                    xx[n]='\0';
1948#endif
1949                  }
1950                 
1951                  columnNames = new char * [numberColumns];
1952                  for (iColumn=0;iColumn<numberColumns;iColumn++) {
1953                    columnNames[iColumn] =
1954                      strdup(model2->columnName(iColumn).c_str());
1955#ifdef STRIPBLANKS
1956                    char * xx = columnNames[iColumn];
1957                    int i;
1958                    int length = strlen(xx);
1959                    int n=0;
1960                    for (i=0;i<length;i++) {
1961                      if (xx[i]!=' ')
1962                        xx[n++]=xx[i];
1963                    }
1964                    xx[n]='\0';
1965#endif
1966                  }
1967                }
1968                CoinMpsIO writer;
1969                writer.setMpsData(*model2->matrix(), COIN_DBL_MAX,
1970                                  model2->getColLower(), model2->getColUpper(),
1971                                  model2->getObjCoefficients(),
1972                                  (const char*) 0 /*integrality*/,
1973                                  model2->getRowLower(), model2->getRowUpper(),
1974                                  columnNames, rowNames);
1975                // Pass in array saying if each variable integer
1976                writer.copyInIntegerInformation(model2->integerInformation());
1977                writer.setObjectiveOffset(model2->objectiveOffset());
1978                writer.writeMps(fileName.c_str(),0,1,1);
1979                if (rowNames) {
1980                  for (iRow=0;iRow<numberRows;iRow++) {
1981                    free(rowNames[iRow]);
1982                  }
1983                  delete [] rowNames;
1984                  for (iColumn=0;iColumn<numberColumns;iColumn++) {
1985                    free(columnNames[iColumn]);
1986                  }
1987                  delete [] columnNames;
1988                }
1989#else
1990                model2->writeMps(fileName.c_str(),(outputFormat-1)/2,1+((outputFormat-1)&1));
1991#endif
1992                if (deleteModel2)
1993                  delete model2;
1994                time2 = CoinCpuTime();
1995                totalTime += time2-time1;
1996                time1=time2;
1997              }
1998            }
1999            break;
2000          case SAVE:
2001            {
2002              // get next field
2003              field = getString(argc,argv);
2004              if (field=="$") {
2005                field = parameters[iParam].stringValue();
2006              } else if (field=="EOL") {
2007                parameters[iParam].printString();
2008                break;
2009              } else {
2010                parameters[iParam].setStringValue(field);
2011              }
2012              std::string fileName;
2013              bool canOpen=false;
2014              if (field[0]=='/'||field[0]=='~')
2015                fileName = field;
2016              else
2017                fileName = directory+field;
2018              FILE *fp=fopen(fileName.c_str(),"wb");
2019              if (fp) {
2020                // can open - lets go for it
2021                fclose(fp);
2022                canOpen=true;
2023              } else {
2024                std::cout<<"Unable to open file "<<fileName<<std::endl;
2025              }
2026              if (canOpen) {
2027                int status;
2028                // If presolve on then save presolved
2029                bool deleteModel2=false;
2030                ClpSimplex * model2 = models+iModel;
2031                if (preSolve) {
2032                  ClpPresolve pinfo;
2033                  model2 = 
2034                    pinfo.presolvedModel(models[iModel],1.0e-8,
2035                                         false,preSolve);
2036                  if (model2) {
2037                    printf("Saving presolved model on %s\n",
2038                           fileName.c_str());
2039                    deleteModel2=true;
2040                  } else {
2041                    printf("Presolved model looks infeasible - saving original on %s\n",
2042                           fileName.c_str());
2043                    deleteModel2=false;
2044                    model2 = models+iModel;
2045
2046                  }
2047                } else {
2048                  printf("Saving model on %s\n",
2049                           fileName.c_str());
2050                }
2051                status =model2->saveModel(fileName.c_str());
2052                if (deleteModel2)
2053                  delete model2;
2054                if (!status) {
2055                  goodModels[iModel]=true;
2056                  time2 = CoinCpuTime();
2057                  totalTime += time2-time1;
2058                  time1=time2;
2059                } else {
2060                  // errors
2061                  std::cout<<"There were errors on output"<<std::endl;
2062                }
2063              }
2064            }
2065            break;
2066          case RESTORE:
2067            {
2068              // get next field
2069              field = getString(argc,argv);
2070              if (field=="$") {
2071                field = parameters[iParam].stringValue();
2072              } else if (field=="EOL") {
2073                parameters[iParam].printString();
2074                break;
2075              } else {
2076                parameters[iParam].setStringValue(field);
2077              }
2078              std::string fileName;
2079              bool canOpen=false;
2080              if (field[0]=='/'||field[0]=='~')
2081                fileName = field;
2082              else
2083                fileName = directory+field;
2084              FILE *fp=fopen(fileName.c_str(),"rb");
2085              if (fp) {
2086                // can open - lets go for it
2087                fclose(fp);
2088                canOpen=true;
2089              } else {
2090                std::cout<<"Unable to open file "<<fileName<<std::endl;
2091              }
2092              if (canOpen) {
2093                int status =models[iModel].restoreModel(fileName.c_str());
2094                if (!status) {
2095                  goodModels[iModel]=true;
2096                  time2 = CoinCpuTime();
2097                  totalTime += time2-time1;
2098                  time1=time2;
2099                } else {
2100                  // errors
2101                  std::cout<<"There were errors on input"<<std::endl;
2102                }
2103              }
2104            }
2105            break;
2106          case MAXIMIZE:
2107            models[iModel].setOptimizationDirection(-1);
2108            break;
2109          case MINIMIZE:
2110            models[iModel].setOptimizationDirection(1);
2111            break;
2112          case ALLSLACK:
2113            models[iModel].createStatus();
2114            {
2115              // and do solution
2116              int iColumn;
2117              double * solution = models[iModel].primalColumnSolution();
2118              const double * lower = models[iModel].columnLower();
2119              const double * upper = models[iModel].columnUpper();
2120              int numberColumns = models[iModel].numberColumns();
2121              for (iColumn=0;iColumn<numberColumns;iColumn++) {
2122                if (lower[iColumn]>0.0) {
2123                  solution[iColumn]=lower[iColumn];
2124                } else if (upper[iColumn]<0.0) {
2125                  solution[iColumn]=upper[iColumn];
2126                } else {
2127                  solution[iColumn]=0.0;
2128                }
2129              }
2130            }
2131            break;
2132          case REVERSE:
2133            if (goodModels[iModel]) {
2134              int iColumn;
2135              int numberColumns=models[iModel].numberColumns();
2136              double * dualColumnSolution = 
2137                models[iModel].dualColumnSolution();
2138              ClpObjective * obj = models[iModel].objectiveAsObject();
2139              assert(dynamic_cast<ClpLinearObjective *> (obj));
2140              double offset;
2141              double * objective = obj->gradient(NULL,offset,true);
2142              for (iColumn=0;iColumn<numberColumns;iColumn++) {
2143                dualColumnSolution[iColumn] = dualColumnSolution[iColumn];
2144                objective[iColumn] = -objective[iColumn];
2145              }
2146              int iRow;
2147              int numberRows=models[iModel].numberRows();
2148              double * dualRowSolution = 
2149                models[iModel].dualRowSolution();
2150              for (iRow=0;iRow<numberRows;iRow++) 
2151                dualRowSolution[iRow] = dualRowSolution[iRow];
2152            }
2153            break;
2154          case DIRECTORY:
2155            {
2156              std::string name = getString(argc,argv);
2157              if (name!="EOL") {
2158                int length=name.length();
2159                if (name[length-1]=='/')
2160                  directory=name;
2161                else
2162                  directory = name+"/";
2163                parameters[iParam].setStringValue(directory);
2164              } else {
2165                parameters[iParam].printString();
2166              }
2167            }
2168            break;
2169          case STDIN:
2170            read_mode=-1;
2171            break;
2172          case NETLIB_DUAL:
2173          case NETLIB_BARRIER:
2174          case NETLIB_PRIMAL:
2175            {
2176              // create fields for unitTest
2177              const char * fields[4];
2178              int nFields=2;
2179              fields[0]="fake main from unitTest";
2180              fields[1]="-netlib";
2181              if (directory!="./") {
2182                fields[2]="-netlibDir";
2183                fields[3]=directory.c_str();
2184                nFields=4;
2185              }
2186              int algorithm;
2187              if (type==NETLIB_DUAL) {
2188                std::cerr<<"Doing netlib with dual agorithm"<<std::endl;
2189                algorithm =0;
2190              } else if (type==NETLIB_BARRIER) {
2191                std::cerr<<"Doing netlib with barrier agorithm"<<std::endl;
2192                algorithm =2;
2193              } else {
2194                std::cerr<<"Doing netlib with primal agorithm"<<std::endl;
2195                algorithm=1;
2196              }
2197              mainTest(nFields,fields,algorithm,models[iModel],
2198                       (preSolve!=0),doIdiot);
2199            }
2200            break;
2201          case UNITTEST:
2202            {
2203              // create fields for unitTest
2204              const char * fields[3];
2205              int nFields=1;
2206              fields[0]="fake main from unitTest";
2207              if (directory!="./") {
2208                fields[1]="-mpsDir";
2209                fields[2]=directory.c_str();
2210                nFields=3;
2211              }
2212              mainTest(nFields,fields,false,models[iModel],(preSolve!=0),
2213                       false);
2214            }
2215            break;
2216          case FAKEBOUND:
2217            if (goodModels[iModel]) {
2218              // get bound
2219              double value = getDoubleField(argc,argv,&valid);
2220              if (!valid) {
2221                std::cout<<"Setting "<<parameters[iParam].name()<<
2222                  " to DEBUG "<<value<<std::endl;
2223                int iRow;
2224                int numberRows=models[iModel].numberRows();
2225                double * rowLower = models[iModel].rowLower();
2226                double * rowUpper = models[iModel].rowUpper();
2227                for (iRow=0;iRow<numberRows;iRow++) {
2228                  // leave free ones for now
2229                  if (rowLower[iRow]>-1.0e20||rowUpper[iRow]<1.0e20) {
2230                    rowLower[iRow]=max(rowLower[iRow],-value);
2231                    rowUpper[iRow]=min(rowUpper[iRow],value);
2232                  }
2233                }
2234                int iColumn;
2235                int numberColumns=models[iModel].numberColumns();
2236                double * columnLower = models[iModel].columnLower();
2237                double * columnUpper = models[iModel].columnUpper();
2238                for (iColumn=0;iColumn<numberColumns;iColumn++) {
2239                  // leave free ones for now
2240                  if (columnLower[iColumn]>-1.0e20||
2241                      columnUpper[iColumn]<1.0e20) {
2242                    columnLower[iColumn]=max(columnLower[iColumn],-value);
2243                    columnUpper[iColumn]=min(columnUpper[iColumn],value);
2244                  }
2245                }
2246              } else if (valid==1) {
2247                abort();
2248              } else {
2249                std::cout<<"enter value for "<<parameters[iParam].name()<<
2250                  std::endl;
2251              }
2252            }
2253            break;
2254          case HELP:
2255            std::cout<<"Coin LP version "<<CLPVERSION
2256                     <<", build "<<__DATE__<<std::endl;
2257            std::cout<<"Non default values:-"<<std::endl;
2258            std::cout<<"Perturbation "<<models[0].perturbation()<<" (default 100)"
2259                     <<std::endl;
2260            printit(
2261                    "Presolve being done with 5 passes\n\
2262Dual steepest edge steep/partial on matrix shape and factorization density\n\
2263Clpnnnn taken out of messages\n\
2264If Factorization frequency default then done on size of matrix\n\n\
2265(-)unitTest, (-)netlib or (-)netlibp will do standard tests\n\n\
2266You can switch to interactive mode at any time so\n\
2267clp watson.mps -scaling off -primalsimplex\nis the same as\n\
2268clp watson.mps -\nscaling off\nprimalsimplex"
2269                    );
2270            break;
2271          case SOLUTION:
2272            if (goodModels[iModel]) {
2273              // get next field
2274              field = getString(argc,argv);
2275              if (field=="$") {
2276                field = parameters[iParam].stringValue();
2277              } else if (field=="EOL") {
2278                parameters[iParam].printString();
2279                break;
2280              } else {
2281                parameters[iParam].setStringValue(field);
2282              }
2283              std::string fileName;
2284              FILE *fp=NULL;
2285              if (field=="-"||field=="EOL"||field=="stdout") {
2286                // stdout
2287                fp=stdout;
2288              } else if (field=="stderr") {
2289                // stderr
2290                fp=stderr;
2291              } else {
2292                if (field[0]=='/'||field[0]=='~')
2293                  fileName = field;
2294                else
2295                  fileName = directory+field;
2296                fp=fopen(fileName.c_str(),"w");
2297              }
2298              if (fp) {
2299                // make fancy later on
2300                int iRow;
2301                int numberRows=models[iModel].numberRows();
2302                int lengthName = models[iModel].lengthNames(); // 0 if no names
2303                // in general I don't want to pass around massive
2304                // amounts of data but seems simpler here
2305                std::vector<std::string> rowNames =
2306                  *(models[iModel].rowNames());
2307                std::vector<std::string> columnNames =
2308                  *(models[iModel].columnNames());
2309
2310                double * dualRowSolution = models[iModel].dualRowSolution();
2311                double * primalRowSolution = 
2312                  models[iModel].primalRowSolution();
2313                double * rowLower = models[iModel].rowLower();
2314                double * rowUpper = models[iModel].rowUpper();
2315                double primalTolerance = models[iModel].primalTolerance();
2316                char format[6];
2317                sprintf(format,"%%-%ds",max(lengthName,8));
2318                for (iRow=0;iRow<numberRows;iRow++) {
2319                  int type=0;
2320                  if (primalRowSolution[iRow]>rowUpper[iRow]+primalTolerance||
2321                      primalRowSolution[iRow]<rowLower[iRow]-primalTolerance) {
2322                    fprintf(fp,"** ");
2323                    type=2;
2324                  } else if (fabs(primalRowSolution[iRow])>1.0e-8) {
2325                    type=1;
2326                  } else if (numberRows<50) {
2327                    type=3;
2328                  }
2329                  if (type) {
2330                    fprintf(fp,"%7d ",iRow);
2331                    if (lengthName)
2332                      fprintf(fp,format,rowNames[iRow].c_str());
2333                    fprintf(fp,"%15.8g        %15.8g\n",primalRowSolution[iRow],
2334                            dualRowSolution[iRow]);
2335                  }
2336                }
2337                int iColumn;
2338                int numberColumns=models[iModel].numberColumns();
2339                double * dualColumnSolution = 
2340                  models[iModel].dualColumnSolution();
2341                double * primalColumnSolution = 
2342                  models[iModel].primalColumnSolution();
2343                double * columnLower = models[iModel].columnLower();
2344                double * columnUpper = models[iModel].columnUpper();
2345                for (iColumn=0;iColumn<numberColumns;iColumn++) {
2346                  int type=0;
2347                  if (primalColumnSolution[iColumn]>columnUpper[iColumn]+primalTolerance||
2348                      primalColumnSolution[iColumn]<columnLower[iColumn]-primalTolerance) {
2349                    fprintf(fp,"** ");
2350                    type=2;
2351                  } else if (fabs(primalColumnSolution[iColumn])>1.0e-8) {
2352                    type=1;
2353                  } else if (numberColumns<50) {
2354                    type=3;
2355                  }
2356                  if (type) {
2357                    fprintf(fp,"%7d ",iColumn);
2358                    if (lengthName)
2359                      fprintf(fp,format,columnNames[iColumn].c_str());
2360                    fprintf(fp,"%15.8g        %15.8g\n",
2361                            primalColumnSolution[iColumn],
2362                            dualColumnSolution[iColumn]);
2363                  }
2364                }
2365                if (fp!=stdout)
2366                  fclose(fp);
2367              } else {
2368                std::cout<<"Unable to open file "<<fileName<<std::endl;
2369              }
2370            } else {
2371              std::cout<<"** Current model not valid"<<std::endl;
2372             
2373            }
2374            break;
2375          default:
2376            abort();
2377          }
2378        } 
2379      } else if (!numberMatches) {
2380        std::cout<<"No match for "<<field<<" - ? for list of commands"
2381                 <<std::endl;
2382      } else if (numberMatches==1) {
2383        if (!numberQuery) {
2384          std::cout<<"Short match for "<<field<<" - completion: ";
2385          std::cout<<parameters[firstMatch].matchName()<<std::endl;
2386        } else if (numberQuery) {
2387          std::cout<<parameters[firstMatch].matchName()<<" : ";
2388          std::cout<<parameters[firstMatch].shortHelp()<<std::endl;
2389          if (numberQuery>=2) 
2390            parameters[firstMatch].printLongHelp();
2391        }
2392      } else {
2393        if (!numberQuery) 
2394          std::cout<<"Multiple matches for "<<field<<" - possible completions:"
2395                   <<std::endl;
2396        else
2397          std::cout<<"Completions of "<<field<<":"<<std::endl;
2398        for ( iParam=0; iParam<numberParameters; iParam++ ) {
2399          int match = parameters[iParam].matches(field);
2400          if (match&&parameters[iParam].displayThis()) {
2401            std::cout<<parameters[iParam].matchName();
2402            if (numberQuery>=2) 
2403              std::cout<<" : "<<parameters[iParam].shortHelp();
2404            std::cout<<std::endl;
2405          }
2406        }
2407      }
2408    }
2409    delete [] models;
2410    delete [] goodModels;
2411  }
2412  // By now all memory should be freed
2413#ifdef DMALLOC
2414  dmalloc_log_unfreed();
2415  dmalloc_shutdown();
2416#endif
2417  return 0;
2418}   
Note: See TracBrowser for help on using the repository browser.