source: branches/pre/Test/ClpMain.cpp @ 223

Last change on this file since 223 was 223, checked in by forrest, 17 years ago

Stuff

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