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

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

lots of stuff

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 65.1 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 ="default.sol";
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\
901variables into basis with the aim of getting dual feasible.  On the whole dual seems to be\
902better 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       ""
1067       ); 
1068    parameters[numberParameters-1].setIntValue(models->factorizationFrequency());
1069    parameters[numberParameters++]=
1070      ClpItem("maxIt!erations","Maximum number of iterations before \
1071stopping",
1072              0,99999999,MAXITERATION);
1073    parameters[numberParameters-1].setLonghelp
1074      (
1075       ""
1076       ); 
1077    parameters[numberParameters-1].setIntValue(models->maximumIterations());
1078    parameters[numberParameters++]=
1079      ClpItem("min!imize","Set optimization direction to minimize",
1080              MINIMIZE,299);
1081    parameters[numberParameters-1].setLonghelp
1082      (
1083       "The default is minimize - use 'maximize' for maximization.\n\
1084This should only be necessary if you have previously set maximization \
1085You can also use the parameters 'direction minimize'."
1086       ); 
1087    parameters[numberParameters++]=
1088      ClpItem("mess!ages","Controls if Clpnnnn is printed",
1089              "off",MESSAGES);
1090    parameters[numberParameters-1].append("on");
1091    parameters[numberParameters-1].setLonghelp
1092      ("The default for the Clp library is to put out messages such as:\n\
1093   Clp0005 2261  Objective 109.024 Primal infeas 944413 (758)\n\
1094but this program turns this off to make it look more friendly.  It can be useful\
1095 to turn them back on if you want to be able 'grep' for particular messages or if\
1096 you intend to override the behavior of a particular message."
1097       ); 
1098    parameters[numberParameters++]=
1099      ClpItem("netlib","Solve entire netlib test set",
1100              NETLIB_DUAL,-1,false);
1101    parameters[numberParameters++]=
1102      ClpItem("netlibP!rimal","Solve entire netlib test set (primal)",
1103              NETLIB_PRIMAL,-1,false);
1104    parameters[numberParameters++]=
1105      ClpItem("network","Tries to make network matrix",
1106              NETWORK,-1,false);
1107    parameters[numberParameters-1].setLonghelp
1108      (
1109       "Clp will go faster if the matrix can be converted to a network.  The matrix\
1110 operations may be a bit faster with more efficient storage, but the main advantage\
1111 comes from using a network factorization.  It will probably not be as fast as a \
1112specialized network code."
1113       ); 
1114    parameters[numberParameters++]=
1115      ClpItem("objective!Scale","Scale factor to apply to objective",
1116              -1.0e20,1.0e20,OBJSCALE,false);
1117    parameters[numberParameters-1].setDoubleValue(models->optimizationDirection());
1118    parameters[numberParameters++]=
1119      ClpItem("passP!resolve","How many passes in presolve",
1120              0,100,PRESOLVEPASS);
1121    parameters[numberParameters-1].setLonghelp
1122      (
1123       "Normally Presolve does 5 passes but you may want to do less to make it\
1124 more lightweight or do more if improvements are still being made.  As Presolve will return\
1125 if nothing is being taken out, then you should not need to use this fine tuning."
1126       ); 
1127    parameters[numberParameters-1].setIntValue(preSolve);
1128    parameters[numberParameters++]=
1129      ClpItem("pertV!alue","Method of perturbation",
1130              -5000,102,PERTVALUE,false);
1131    parameters[numberParameters-1].setIntValue(models->perturbation());
1132    parameters[numberParameters++]=
1133      ClpItem("perturb!ation","Whether to perturb problem",
1134              "on",PERTURBATION);
1135    parameters[numberParameters-1].append("off");
1136    parameters[numberParameters-1].setLonghelp
1137      (
1138       "Perturbation helps to stop cycling, but Clp uses other measures for this.\
1139  However large problems and especially ones with unit elements and unit rhs or costs\
1140 benefit from perturbation.  Normally Clp tries to be intelligent, but you can switch this off.\
1141  The Clp library has this off by default.  This program has it on."
1142       ); 
1143    parameters[numberParameters++]=
1144      ClpItem("plus!Minus","Tries to make +- 1 matrix",
1145              PLUSMINUS,-1,false);
1146    parameters[numberParameters-1].setLonghelp
1147      (
1148       "Clp will go slightly faster if the matrix can be converted so that the elements are\
1149 not stored and are known to be unit.  The main advantage is memory use.  Clp may automatically\
1150 see if it can convert the problem so you should not need to use this."
1151       ); 
1152    parameters[numberParameters++]=
1153      ClpItem("presolve","Whether to presolve problem",
1154              "on",PRESOLVE);
1155    parameters[numberParameters-1].append("off");
1156    parameters[numberParameters-1].append("more");
1157    parameters[numberParameters-1].setLonghelp
1158      (
1159       ""
1160       ); 
1161    parameters[numberParameters++]=
1162      ClpItem("primalP!ivot","Primal pivot choice algorithm",
1163              "auto!matic",PRIMALPIVOT);
1164    parameters[numberParameters-1].append("exa!ct");
1165    parameters[numberParameters-1].append("dant!zig");
1166    parameters[numberParameters-1].append("part!ial");
1167    parameters[numberParameters-1].append("steep!est");
1168    parameters[numberParameters-1].append("change");
1169    parameters[numberParameters-1].setLonghelp
1170      (
1171       ""
1172       ); 
1173    parameters[numberParameters++]=
1174      ClpItem("primalS!implex","Do primal simplex algorithm",
1175              PRIMALSIMPLEX);
1176    parameters[numberParameters-1].setLonghelp
1177      (
1178       ""
1179       ); 
1180    parameters[numberParameters++]=
1181      ClpItem("primalT!olerance","For an optimal solution \
1182no primal infeasibility may exceed this value",
1183              1.0e-20,1.0e12,PRIMALTOLERANCE);
1184    parameters[numberParameters-1].setLonghelp
1185      (
1186       ""
1187       ); 
1188    parameters[numberParameters-1].setDoubleValue(models->primalTolerance());
1189    parameters[numberParameters++]=
1190      ClpItem("primalW!eight","Initially algorithm acts as if it \
1191costs this much to be infeasible",
1192              1.0e-20,1.0e12,PRIMALWEIGHT);
1193    parameters[numberParameters-1].setLonghelp
1194      (
1195       ""
1196       ); 
1197    parameters[numberParameters-1].setDoubleValue(models->infeasibilityCost());
1198    parameters[numberParameters++]=
1199      ClpItem("quit","Stops clp execution",
1200              EXIT);
1201    parameters[numberParameters-1].setLonghelp
1202      (
1203       "This stops the execution of Clp, end, exit, quit and stop are synonyms"
1204       ); 
1205    parameters[numberParameters++]=
1206      ClpItem("restore!Model","Restore model from binary file",
1207              RESTORE);
1208    parameters[numberParameters-1].setLonghelp
1209      (
1210       "This will write an MPS format file to the given file name.  It will use the default\
1211 directory given by 'directory'.  A name of '$' will use the previous value for the name.  This\
1212 is initialized to 'default.mps'."
1213       ""
1214       ); 
1215    parameters[numberParameters-1].setStringValue(restoreFile);
1216    parameters[numberParameters++]=
1217      ClpItem("reverse","Reverses sign of objective",
1218              REVERSE,false);
1219    parameters[numberParameters-1].setLonghelp
1220      (
1221       "Useful for testing if maximization works correctly"
1222       ); 
1223    parameters[numberParameters++]=
1224      ClpItem("save!Model","Save model to binary file",
1225              SAVE);
1226    parameters[numberParameters-1].setLonghelp
1227      (
1228       "This will write an MPS format file to the given file name.  It will use the default\
1229 directory given by 'directory'.  A name of '$' will use the previous value for the name.  This\
1230 is initialized to 'default.mps'."
1231       ""
1232       ); 
1233    parameters[numberParameters-1].setStringValue(saveFile);
1234    parameters[numberParameters++]=
1235      ClpItem("scal!ing","Whether to scale problem",
1236              "on",SCALING);
1237    parameters[numberParameters-1].append("off");
1238    parameters[numberParameters-1].append("geo!metric");
1239    parameters[numberParameters-1].append("auto!matic");
1240    parameters[numberParameters-1].setLonghelp
1241      (
1242       ""
1243       ); 
1244    parameters[numberParameters++]=
1245      ClpItem("sec!onds","maximum seconds",
1246              0.0,1.0e12,MAXTIME);
1247    parameters[numberParameters-1].setLonghelp
1248      (
1249       ""
1250       ); 
1251    parameters[numberParameters-1].setDoubleValue(models->maximumSeconds());
1252    parameters[numberParameters++]=
1253      ClpItem("sol!ution","Prints solution to file",
1254              SOLUTION);
1255    parameters[numberParameters-1].setLonghelp
1256      (
1257       "This will write an MPS format file to the given file name.  It will use the default\
1258 directory given by 'directory'.  A name of '$' will use the previous value for the name.  This\
1259 is initialized to 'default.mps'."
1260       ""
1261       ); 
1262    parameters[numberParameters-1].setStringValue(solutionFile);
1263    parameters[numberParameters++]=
1264      ClpItem("spars!eFactor","Whether factorization treated as sparse",
1265              "on",SPARSEFACTOR,0,false);
1266    parameters[numberParameters-1].append("off");
1267    parameters[numberParameters-1].append("on");
1268    parameters[numberParameters++]=
1269      ClpItem("sprint!Crash","Whether to try sprint crash",
1270              0,200,SPRINT);
1271    parameters[numberParameters-1].setLonghelp
1272      (
1273       ""
1274       ); 
1275    parameters[numberParameters-1].setIntValue(doSprint);
1276      ClpItem("stdin","From stdin",
1277              STDIN,-1,false);
1278    parameters[numberParameters++]=
1279      ClpItem("stop","Stops clp execution",
1280              EXIT);
1281    parameters[numberParameters-1].setLonghelp
1282      (
1283       "This stops the execution of Clp, end, exit, quit and stop are synonyms"
1284       ); 
1285    parameters[numberParameters++]=
1286      ClpItem("tight!en","Poor person's preSolve for now",
1287              TIGHTEN,-1,false);
1288    parameters[numberParameters++]=
1289      ClpItem("unitTest","Do unit test",
1290              UNITTEST,-1,false);
1291    assert(numberParameters<MAXPARAMETERS);
1292   
1293    // total number of commands read
1294    int numberGoodCommands=0;
1295    bool * goodModels = new bool[1];
1296   
1297   
1298    int iModel=0;
1299    goodModels[0]=false;
1300    //models[0].scaling(1);
1301    //models[0].setDualBound(1.0e6);
1302    //models[0].setDualTolerance(1.0e-7);
1303    //ClpDualRowSteepest steep;
1304    //models[0].setDualRowPivotAlgorithm(steep);
1305    //models[0].setPrimalTolerance(1.0e-7);
1306    //ClpPrimalColumnSteepest steepP;
1307    //models[0].setPrimalColumnPivotAlgorithm(steepP);
1308    std::string field;
1309    std::cout<<"Coin LP version "<<CLPVERSION
1310             <<", build "<<__DATE__<<std::endl;
1311   
1312    while (1) {
1313      // next command
1314      field=getCommand(argc,argv);
1315     
1316      // exit if null or similar
1317      if (!field.length()) {
1318        if (numberGoodCommands==1&&goodModels[0]) {
1319          // we just had file name - do dual
1320          field="duals";
1321        } else if (!numberGoodCommands) {
1322          // let's give the sucker a hint
1323          std::cout
1324            <<"Clp takes input from arguments ( - switches to stdin)"
1325            <<std::endl
1326            <<"Enter ? for list of commands or help"<<std::endl;
1327          field="-";
1328        } else {
1329          break;
1330        }
1331      }
1332     
1333      // see if ? at end
1334      int numberQuery=0;
1335      if (field!="?") {
1336        int length = field.length();
1337        int i;
1338        for (i=length-1;i>0;i--) {
1339          if (field[i]=='?') 
1340            numberQuery++;
1341          else
1342            break;
1343        }
1344        field=field.substr(0,length-numberQuery);
1345      }
1346      // find out if valid command
1347      int iParam;
1348      int numberMatches=0;
1349      int firstMatch=-1;
1350      for ( iParam=0; iParam<numberParameters; iParam++ ) {
1351        int match = parameters[iParam].matches(field);
1352        if (match==1) {
1353          numberMatches = 1;
1354          firstMatch=iParam;
1355          break;
1356        } else {
1357          if (match&&firstMatch<0)
1358            firstMatch=iParam;
1359          numberMatches += match>>1;
1360        }
1361      }
1362      if (iParam<numberParameters&&!numberQuery) {
1363        // found
1364        ClpItem found = parameters[iParam];
1365        ClpParameterType type = found.type();
1366        int valid;
1367        numberGoodCommands++;
1368        if (type==GENERALQUERY) {
1369          std::cout<<"In argument list keywords have leading - "
1370            ", -stdin or just - switches to stdin"<<std::endl;
1371          std::cout<<"One command per line (and no -)"<<std::endl;
1372          std::cout<<"abcd? gives list of possibilities, if only one + explanation"<<std::endl;
1373          std::cout<<"abcd?? adds explanation, if only one fuller help(LATER)"<<std::endl;
1374          std::cout<<"abcd without value (where expected) gives current value"<<std::endl;
1375          std::cout<<"abcd value sets value"<<std::endl;
1376          std::cout<<"Commands are:"<<std::endl;
1377          int maxAcross=5;
1378          int limits[]={1,101,201,301,401};
1379          std::vector<std::string> types;
1380          types.push_back("Double parameters:");
1381          types.push_back("Int parameters:");
1382          types.push_back("Keyword parameters and others:");
1383          types.push_back("Actions:");
1384          int iType;
1385          for (iType=0;iType<4;iType++) {
1386            int across=0;
1387            std::cout<<types[iType]<<std::endl;
1388            for ( iParam=0; iParam<numberParameters; iParam++ ) {
1389              int type = parameters[iParam].indexNumber();
1390              if (parameters[iParam].displayThis()&&type>=limits[iType]
1391                  &&type<limits[iType+1]) {
1392                if (!across)
1393                  std::cout<<"  ";
1394                std::cout<<parameters[iParam].matchName()<<"  ";
1395                across++;
1396                if (across==maxAcross) {
1397                  std::cout<<std::endl;
1398                  across=0;
1399                }
1400              }
1401            }
1402            if (across)
1403              std::cout<<std::endl;
1404          }
1405        } else if (type<101) {
1406          // get next field as double
1407          double value = getDoubleField(argc,argv,&valid);
1408          if (!valid) {
1409            parameters[iParam].setDoubleValue(value);
1410            parameters[iParam].setDoubleParameter(models+iModel,value);
1411          } else if (valid==1) {
1412            abort();
1413          } else {
1414            std::cout<<parameters[iParam].name()<<" has value "<<
1415              parameters[iParam].doubleValue()<<std::endl;
1416          }
1417        } else if (type<201) {
1418          // get next field as int
1419          int value = getIntField(argc,argv,&valid);
1420          if (!valid) {
1421            parameters[iParam].setIntValue(value);
1422            if (parameters[iParam].type()==PRESOLVEPASS)
1423              preSolve = value;
1424            else if (parameters[iParam].type()==IDIOT)
1425              doIdiot = value;
1426            else if (parameters[iParam].type()==SPRINT)
1427              doSprint = value;
1428            else
1429              parameters[iParam].setIntParameter(models+iModel,value);
1430          } else if (valid==1) {
1431            abort();
1432          } else {
1433            std::cout<<parameters[iParam].name()<<" has value "<<
1434              parameters[iParam].intValue()<<std::endl;
1435          }
1436        } else if (type<301) {
1437          // one of several strings
1438          std::string value = getString(argc,argv);
1439          int action = parameters[iParam].parameterOption(value);
1440          if (action<0) {
1441            if (value!="EOL") {
1442              // no match
1443              parameters[iParam].printOptions();
1444            } else {
1445              // print current value
1446              std::cout<<parameters[iParam].name()<<" has value "<<
1447                parameters[iParam].currentOption()<<std::endl;
1448            }
1449          } else {
1450            parameters[iParam].setCurrentOption(action);
1451            // for now hard wired
1452            switch (type) {
1453            case DIRECTION:
1454              if (action==0)
1455                models[iModel].setOptimizationDirection(1);
1456              else if (action==1)
1457                models[iModel].setOptimizationDirection(-1);
1458              else
1459                models[iModel].setOptimizationDirection(0);
1460              break;
1461            case DUALPIVOT:
1462              if (action==0) {
1463                ClpDualRowSteepest steep(3);
1464                models[iModel].setDualRowPivotAlgorithm(steep);
1465              } else if (action==1) {
1466                ClpDualRowDantzig dantzig;
1467                models[iModel].setDualRowPivotAlgorithm(dantzig);
1468              } else if (action==2) {
1469                // partial steep
1470                ClpDualRowSteepest steep(2);
1471                models[iModel].setDualRowPivotAlgorithm(steep);
1472              } else {
1473                ClpDualRowSteepest steep;
1474                models[iModel].setDualRowPivotAlgorithm(steep);
1475              }
1476              break;
1477            case PRIMALPIVOT:
1478              if (action==0) {
1479                ClpPrimalColumnSteepest steep(3);
1480                models[iModel].setPrimalColumnPivotAlgorithm(steep);
1481              } else if (action==1) {
1482                ClpPrimalColumnSteepest steep(0);
1483                models[iModel].setPrimalColumnPivotAlgorithm(steep);
1484              } else if (action==2) {
1485                ClpPrimalColumnDantzig dantzig;
1486                models[iModel].setPrimalColumnPivotAlgorithm(dantzig);
1487              } else if (action==3) {
1488                ClpPrimalColumnSteepest steep(2);
1489                models[iModel].setPrimalColumnPivotAlgorithm(steep);
1490              } else if (action==4) {
1491                ClpPrimalColumnSteepest steep(1);
1492                models[iModel].setPrimalColumnPivotAlgorithm(steep);
1493              } else if (action==5) {
1494                ClpPrimalColumnSteepest steep(4);
1495                models[iModel].setPrimalColumnPivotAlgorithm(steep);
1496              }
1497              break;
1498            case SCALING:
1499              if (action<2)
1500                models[iModel].scaling(1-action);
1501              else
1502                models[iModel].scaling(action);
1503              break;
1504            case SPARSEFACTOR:
1505              models[iModel].setSparseFactorization((1-action)!=0);
1506              break;
1507            case BIASLU:
1508              models[iModel].factorization()->setBiasLU(action);
1509              break;
1510            case PERTURBATION:
1511              if (action==0)
1512                models[iModel].setPerturbation(50);
1513              else
1514                models[iModel].setPerturbation(100);
1515              break;
1516            case ERRORSALLOWED:
1517              allowImportErrors = action;
1518              break;
1519            case KEEPNAMES:
1520              keepImportNames = 1-action;
1521              break;
1522            case PRESOLVE:
1523              if (action==0)
1524                preSolve = 5;
1525              else if (action==1)
1526                preSolve=0;
1527              else
1528                preSolve=10;
1529              break;
1530            case CRASH:
1531              doCrash=action;
1532              break;
1533            case MESSAGES:
1534              models[iModel].messageHandler()->setPrefix(action!=0);
1535              break;
1536            default:
1537              abort();
1538            }
1539          }
1540        } else {
1541          // action
1542          if (type==EXIT)
1543            break; // stop all
1544          switch (type) {
1545          case DUALSIMPLEX:
1546          case PRIMALSIMPLEX:
1547            if (goodModels[iModel]) {
1548              ClpSolve::SolveType method;
1549              ClpSolve::PresolveType presolveType;
1550              ClpSimplex * model2 = models+iModel;
1551              ClpSolve solveOptions;
1552              if (preSolve!=5&&preSolve)
1553                presolveType=ClpSolve::presolveNumber;
1554              else if (preSolve)
1555                presolveType=ClpSolve::presolveOn;
1556              else
1557                presolveType=ClpSolve::presolveOff;
1558              solveOptions.setPresolveType(presolveType,preSolve);
1559              if (type==DUALSIMPLEX)
1560                method=ClpSolve::useDual;
1561              else
1562                method=ClpSolve::usePrimalorSprint;
1563              solveOptions.setSolveType(method);
1564              if (method==ClpSolve::useDual) {
1565                // dual
1566                if (doCrash)
1567                  solveOptions.setSpecialOption(0,1); // crash
1568              } else {
1569                // primal
1570                if (doCrash) {
1571                  solveOptions.setSpecialOption(0,1); // crash
1572                } else if (doSprint>0) {
1573                  // sprint overrides idiot
1574                  solveOptions.setSpecialOption(1,3,doSprint); // sprint
1575                } else if (doIdiot>0) {
1576                  solveOptions.setSpecialOption(1,2,doIdiot); // idiot
1577                } else {
1578                  if (doIdiot==0) {
1579                    if (doSprint==0)
1580                      solveOptions.setSpecialOption(1,4); // all slack
1581                    else
1582                      solveOptions.setSpecialOption(1,9); // all slack or sprint
1583                  } else {
1584                    if (doSprint==0)
1585                      solveOptions.setSpecialOption(1,8); // all slack or idiot
1586                    else
1587                      solveOptions.setSpecialOption(1,7); // initiative
1588                  }
1589                }
1590              }
1591              model2->initialSolve(solveOptions);
1592            } else {
1593              std::cout<<"** Current model not valid"<<std::endl;
1594            }
1595            break;
1596          case TIGHTEN:
1597            if (goodModels[iModel]) {
1598              int numberInfeasibilities = models[iModel].tightenPrimalBounds();
1599              if (numberInfeasibilities)
1600                std::cout<<"** Analysis indicates model infeasible"<<std::endl;
1601            } else {
1602              std::cout<<"** Current model not valid"<<std::endl;
1603            }
1604            break;
1605          case PLUSMINUS:
1606            if (goodModels[iModel]) {
1607              ClpMatrixBase * saveMatrix = models[iModel].clpMatrix();
1608              ClpPackedMatrix* clpMatrix =
1609                dynamic_cast< ClpPackedMatrix*>(saveMatrix);
1610              if (clpMatrix) {
1611                ClpPlusMinusOneMatrix * newMatrix = new ClpPlusMinusOneMatrix(*(clpMatrix->matrix()));
1612                if (newMatrix->getIndices()) {
1613                  models[iModel].replaceMatrix(newMatrix);
1614                  delete saveMatrix;
1615                  std::cout<<"Matrix converted to +- one matrix"<<std::endl;
1616                } else {
1617                  std::cout<<"Matrix can not be converted to +- 1 matrix"<<std::endl;
1618                }
1619              } else {
1620                std::cout<<"Matrix not a ClpPackedMatrix"<<std::endl;
1621              }
1622            } else {
1623              std::cout<<"** Current model not valid"<<std::endl;
1624            }
1625            break;
1626          case NETWORK:
1627            if (goodModels[iModel]) {
1628              ClpMatrixBase * saveMatrix = models[iModel].clpMatrix();
1629              ClpPackedMatrix* clpMatrix =
1630                dynamic_cast< ClpPackedMatrix*>(saveMatrix);
1631              if (clpMatrix) {
1632                ClpNetworkMatrix * newMatrix = new ClpNetworkMatrix(*(clpMatrix->matrix()));
1633                if (newMatrix->getIndices()) {
1634                  models[iModel].replaceMatrix(newMatrix);
1635                  delete saveMatrix;
1636                  std::cout<<"Matrix converted to network matrix"<<std::endl;
1637                } else {
1638                  std::cout<<"Matrix can not be converted to network matrix"<<std::endl;
1639                }
1640              } else {
1641                std::cout<<"Matrix not a ClpPackedMatrix"<<std::endl;
1642              }
1643            } else {
1644              std::cout<<"** Current model not valid"<<std::endl;
1645            }
1646            break;
1647          case IMPORT:
1648            {
1649              // get next field
1650              field = getString(argc,argv);
1651              if (field=="$") {
1652                field = parameters[iParam].stringValue();
1653              } else if (field=="EOL") {
1654                parameters[iParam].printString();
1655                break;
1656              } else {
1657                parameters[iParam].setStringValue(field);
1658              }
1659              std::string fileName;
1660              bool canOpen=false;
1661              if (field=="-") {
1662                // stdin
1663                canOpen=true;
1664                fileName = "-";
1665              } else {
1666                if (field[0]=='/'||field[0]=='~')
1667                  fileName = field;
1668                else
1669                  fileName = directory+field;
1670                FILE *fp=fopen(fileName.c_str(),"r");
1671                if (fp) {
1672                  // can open - lets go for it
1673                  fclose(fp);
1674                  canOpen=true;
1675                } else {
1676                  std::cout<<"Unable to open file "<<fileName<<std::endl;
1677                }
1678              }
1679              if (canOpen) {
1680                int status =models[iModel].readMps(fileName.c_str(),
1681                                                   keepImportNames!=0,
1682                                                   allowImportErrors!=0);
1683                if (!status||(status>0&&allowImportErrors)) {
1684                  goodModels[iModel]=true;
1685                  // sets to all slack (not necessary?)
1686                  models[iModel].createStatus();
1687                  time2 = CoinCpuTime();
1688                  totalTime += time2-time1;
1689                  time1=time2;
1690                } else {
1691                  // errors
1692                  std::cout<<"There were "<<status<<
1693                    " errors on input"<<std::endl;
1694                }
1695              }
1696            }
1697            break;
1698          case EXPORT:
1699            {
1700              // get next field
1701              field = getString(argc,argv);
1702              if (field=="$") {
1703                field = parameters[iParam].stringValue();
1704              } else if (field=="EOL") {
1705                parameters[iParam].printString();
1706                break;
1707              } else {
1708                parameters[iParam].setStringValue(field);
1709              }
1710              std::string fileName;
1711              bool canOpen=false;
1712              if (field[0]=='/'||field[0]=='~')
1713                fileName = field;
1714              else
1715                fileName = directory+field;
1716              FILE *fp=fopen(fileName.c_str(),"w");
1717              if (fp) {
1718                // can open - lets go for it
1719                fclose(fp);
1720                canOpen=true;
1721              } else {
1722                std::cout<<"Unable to open file "<<fileName<<std::endl;
1723              }
1724              if (canOpen) {
1725                // If presolve on then save presolved
1726                bool deleteModel2=false;
1727                ClpSimplex * model2 = models+iModel;
1728#ifdef USE_PRESOLVE
1729                if (preSolve) {
1730                  ClpPresolve pinfo;
1731                  model2 = 
1732                    pinfo.presolvedModel(models[iModel],1.0e-8,
1733                                         false,preSolve);
1734                  if (model2) {
1735                    printf("Saving presolved model on %s\n",
1736                           fileName.c_str());
1737                    deleteModel2=true;
1738                  } else {
1739                    printf("Presolved model looks infeasible - saving original on %s\n",
1740                           fileName.c_str());
1741                    deleteModel2=false;
1742                    model2 = models+iModel;
1743
1744                  }
1745                } else {
1746#endif
1747                  printf("Saving model on %s\n",
1748                           fileName.c_str());
1749#ifdef USE_PRESOLVE
1750                }
1751#endif
1752                // Convert names
1753                int iRow;
1754                int numberRows=model2->numberRows();
1755                int iColumn;
1756                int numberColumns=model2->numberColumns();
1757
1758                char ** rowNames = NULL;
1759                char ** columnNames = NULL;
1760                if (model2->lengthNames()) {
1761                  rowNames = new char * [numberRows];
1762                  for (iRow=0;iRow<numberRows;iRow++) {
1763                    rowNames[iRow] = 
1764                      strdup(model2->rowName(iRow).c_str());
1765#ifdef STRIPBLANKS
1766                    char * xx = rowNames[iRow];
1767                    int i;
1768                    int length = strlen(xx);
1769                    int n=0;
1770                    for (i=0;i<length;i++) {
1771                      if (xx[i]!=' ')
1772                        xx[n++]=xx[i];
1773                    }
1774                    xx[n]='\0';
1775#endif
1776                  }
1777                 
1778                  columnNames = new char * [numberColumns];
1779                  for (iColumn=0;iColumn<numberColumns;iColumn++) {
1780                    columnNames[iColumn] = 
1781                      strdup(model2->columnName(iColumn).c_str());
1782#ifdef STRIPBLANKS
1783                    char * xx = columnNames[iColumn];
1784                    int i;
1785                    int length = strlen(xx);
1786                    int n=0;
1787                    for (i=0;i<length;i++) {
1788                      if (xx[i]!=' ')
1789                        xx[n++]=xx[i];
1790                    }
1791                    xx[n]='\0';
1792#endif
1793                  }
1794                }
1795
1796                CoinMpsIO writer;
1797                writer.setMpsData(*model2->matrix(), COIN_DBL_MAX,
1798                                  model2->getColLower(), model2->getColUpper(),
1799                                  model2->getObjCoefficients(),
1800                                  (const char*) 0 /*integrality*/,
1801                                  model2->getRowLower(), model2->getRowUpper(),
1802                                  columnNames, rowNames);
1803                // Pass in array saying if each variable integer
1804                writer.copyInIntegerInformation(model2->integerInformation());
1805                writer.writeMps(fileName.c_str());
1806                if (rowNames) {
1807                  for (iRow=0;iRow<numberRows;iRow++) {
1808                    free(rowNames[iRow]);
1809                  }
1810                  delete [] rowNames;
1811                  for (iColumn=0;iColumn<numberColumns;iColumn++) {
1812                    free(columnNames[iColumn]);
1813                  }
1814                  delete [] columnNames;
1815                }
1816                if (deleteModel2)
1817                  delete model2;
1818                time2 = CoinCpuTime();
1819                totalTime += time2-time1;
1820                time1=time2;
1821              }
1822            }
1823            break;
1824          case SAVE:
1825            {
1826              // get next field
1827              field = getString(argc,argv);
1828              if (field=="$") {
1829                field = parameters[iParam].stringValue();
1830              } else if (field=="EOL") {
1831                parameters[iParam].printString();
1832                break;
1833              } else {
1834                parameters[iParam].setStringValue(field);
1835              }
1836              std::string fileName;
1837              bool canOpen=false;
1838              if (field[0]=='/'||field[0]=='~')
1839                fileName = field;
1840              else
1841                fileName = directory+field;
1842              FILE *fp=fopen(fileName.c_str(),"wb");
1843              if (fp) {
1844                // can open - lets go for it
1845                fclose(fp);
1846                canOpen=true;
1847              } else {
1848                std::cout<<"Unable to open file "<<fileName<<std::endl;
1849              }
1850              if (canOpen) {
1851                int status;
1852                // If presolve on then save presolved
1853                bool deleteModel2=false;
1854                ClpSimplex * model2 = models+iModel;
1855#ifdef USE_PRESOLVE
1856                if (preSolve) {
1857                  ClpPresolve pinfo;
1858                  model2 = 
1859                    pinfo.presolvedModel(models[iModel],1.0e-8,
1860                                         false,preSolve);
1861                  if (model2) {
1862                    printf("Saving presolved model on %s\n",
1863                           fileName.c_str());
1864                    deleteModel2=true;
1865                  } else {
1866                    printf("Presolved model looks infeasible - saving original on %s\n",
1867                           fileName.c_str());
1868                    deleteModel2=false;
1869                    model2 = models+iModel;
1870
1871                  }
1872                } else {
1873#endif
1874                  printf("Saving model on %s\n",
1875                           fileName.c_str());
1876#ifdef USE_PRESOLVE
1877                }
1878#endif
1879                status =model2->saveModel(fileName.c_str());
1880                if (deleteModel2)
1881                  delete model2;
1882                if (!status) {
1883                  goodModels[iModel]=true;
1884                  time2 = CoinCpuTime();
1885                  totalTime += time2-time1;
1886                  time1=time2;
1887                } else {
1888                  // errors
1889                  std::cout<<"There were errors on output"<<std::endl;
1890                }
1891              }
1892            }
1893            break;
1894          case RESTORE:
1895            {
1896              // get next field
1897              field = getString(argc,argv);
1898              if (field=="$") {
1899                field = parameters[iParam].stringValue();
1900              } else if (field=="EOL") {
1901                parameters[iParam].printString();
1902                break;
1903              } else {
1904                parameters[iParam].setStringValue(field);
1905              }
1906              std::string fileName;
1907              bool canOpen=false;
1908              if (field[0]=='/'||field[0]=='~')
1909                fileName = field;
1910              else
1911                fileName = directory+field;
1912              FILE *fp=fopen(fileName.c_str(),"rb");
1913              if (fp) {
1914                // can open - lets go for it
1915                fclose(fp);
1916                canOpen=true;
1917              } else {
1918                std::cout<<"Unable to open file "<<fileName<<std::endl;
1919              }
1920              if (canOpen) {
1921                int status =models[iModel].restoreModel(fileName.c_str());
1922                if (!status) {
1923                  goodModels[iModel]=true;
1924                  time2 = CoinCpuTime();
1925                  totalTime += time2-time1;
1926                  time1=time2;
1927                } else {
1928                  // errors
1929                  std::cout<<"There were errors on input"<<std::endl;
1930                }
1931              }
1932            }
1933            break;
1934          case MAXIMIZE:
1935            models[iModel].setOptimizationDirection(-1);
1936            break;
1937          case MINIMIZE:
1938            models[iModel].setOptimizationDirection(1);
1939            break;
1940          case ALLSLACK:
1941            models[iModel].createStatus();
1942            {
1943              // and do solution
1944              int iColumn;
1945              double * solution = models[iModel].primalColumnSolution();
1946              const double * lower = models[iModel].columnLower();
1947              const double * upper = models[iModel].columnUpper();
1948              int numberColumns = models[iModel].numberColumns();
1949              for (iColumn=0;iColumn<numberColumns;iColumn++) {
1950                if (lower[iColumn]>0.0) {
1951                  solution[iColumn]=lower[iColumn];
1952                } else if (upper[iColumn]<0.0) {
1953                  solution[iColumn]=upper[iColumn];
1954                } else {
1955                  solution[iColumn]=0.0;
1956                }
1957              }
1958            }
1959            break;
1960          case REVERSE:
1961            if (goodModels[iModel]) {
1962              int iColumn;
1963              int numberColumns=models[iModel].numberColumns();
1964              double * dualColumnSolution = 
1965                models[iModel].dualColumnSolution();
1966              ClpObjective * obj = models[iModel].objectiveAsObject();
1967              assert(dynamic_cast<ClpLinearObjective *> (obj));
1968              double offset;
1969              double * objective = obj->gradient(NULL,offset,true);
1970              for (iColumn=0;iColumn<numberColumns;iColumn++) {
1971                dualColumnSolution[iColumn] = dualColumnSolution[iColumn];
1972                objective[iColumn] = -objective[iColumn];
1973              }
1974              int iRow;
1975              int numberRows=models[iModel].numberRows();
1976              double * dualRowSolution = 
1977                models[iModel].dualRowSolution();
1978              for (iRow=0;iRow<numberRows;iRow++) 
1979                dualRowSolution[iRow] = dualRowSolution[iRow];
1980            }
1981            break;
1982          case DIRECTORY:
1983            {
1984              std::string name = getString(argc,argv);
1985              if (name!="EOL") {
1986                int length=name.length();
1987                if (name[length-1]=='/')
1988                  directory=name;
1989                else
1990                  directory = name+"/";
1991                parameters[iParam].setStringValue(directory);
1992              } else {
1993                parameters[iParam].printString();
1994              }
1995            }
1996            break;
1997          case STDIN:
1998            read_mode=-1;
1999            break;
2000          case NETLIB_DUAL:
2001          case NETLIB_PRIMAL:
2002            {
2003              // create fields for unitTest
2004              const char * fields[4];
2005              int nFields=2;
2006              fields[0]="fake main from unitTest";
2007              fields[1]="-netlib";
2008              if (directory!="./") {
2009                fields[2]="-netlibDir";
2010                fields[3]=directory.c_str();
2011                nFields=4;
2012              }
2013              if (type==NETLIB_DUAL)
2014                std::cerr<<"Doing netlib with dual agorithm"<<std::endl;
2015              else
2016                std::cerr<<"Doing netlib with primal agorithm"<<std::endl;
2017              mainTest(nFields,fields,(type==NETLIB_DUAL),models[iModel],
2018                       (preSolve!=0),doIdiot);
2019            }
2020            break;
2021          case UNITTEST:
2022            {
2023              // create fields for unitTest
2024              const char * fields[3];
2025              int nFields=1;
2026              fields[0]="fake main from unitTest";
2027              if (directory!="./") {
2028                fields[1]="-mpsDir";
2029                fields[2]=directory.c_str();
2030                nFields=3;
2031              }
2032              mainTest(nFields,fields,false,models[iModel],(preSolve!=0),
2033                       false);
2034            }
2035            break;
2036          case FAKEBOUND:
2037            if (goodModels[iModel]) {
2038              // get bound
2039              double value = getDoubleField(argc,argv,&valid);
2040              if (!valid) {
2041                std::cout<<"Setting "<<parameters[iParam].name()<<
2042                  " to DEBUG "<<value<<std::endl;
2043                int iRow;
2044                int numberRows=models[iModel].numberRows();
2045                double * rowLower = models[iModel].rowLower();
2046                double * rowUpper = models[iModel].rowUpper();
2047                for (iRow=0;iRow<numberRows;iRow++) {
2048                  // leave free ones for now
2049                  if (rowLower[iRow]>-1.0e20||rowUpper[iRow]<1.0e20) {
2050                    rowLower[iRow]=max(rowLower[iRow],-value);
2051                    rowUpper[iRow]=min(rowUpper[iRow],value);
2052                  }
2053                }
2054                int iColumn;
2055                int numberColumns=models[iModel].numberColumns();
2056                double * columnLower = models[iModel].columnLower();
2057                double * columnUpper = models[iModel].columnUpper();
2058                for (iColumn=0;iColumn<numberColumns;iColumn++) {
2059                  // leave free ones for now
2060                  if (columnLower[iColumn]>-1.0e20||
2061                      columnUpper[iColumn]<1.0e20) {
2062                    columnLower[iColumn]=max(columnLower[iColumn],-value);
2063                    columnUpper[iColumn]=min(columnUpper[iColumn],value);
2064                  }
2065                }
2066              } else if (valid==1) {
2067                abort();
2068              } else {
2069                std::cout<<"enter value for "<<parameters[iParam].name()<<
2070                  std::endl;
2071              }
2072            }
2073            break;
2074          case HELP:
2075            std::cout<<"Coin LP version "<<CLPVERSION
2076                     <<", build "<<__DATE__<<std::endl;
2077            std::cout<<"Non default values:-"<<std::endl;
2078            std::cout<<"Perturbation "<<models[0].perturbation()<<" (default 100)"
2079                     <<std::endl;
2080            printit(
2081                    "Presolve being done with 5 passes\n\
2082Dual steepest edge steep/partial on matrix shape and factorization density\n\
2083Clpnnnn taken out of messages\n\
2084If Factorization frequency default then done on size of matrix\n\n\
2085(-)unitTest, (-)netlib or (-)netlibp will do standard tests\n\n\
2086You can switch to interactive mode at any time so\n\
2087clp watson.mps -scaling off -primalsimplex\nis the same as\n\
2088clp watson.mps -\nscaling off\nprimalsimplex"
2089                    );
2090            break;
2091          case SOLUTION:
2092            if (goodModels[iModel]) {
2093              // get next field
2094              field = getString(argc,argv);
2095              if (field=="$") {
2096                field = parameters[iParam].stringValue();
2097              } else if (field=="EOL") {
2098                parameters[iParam].printString();
2099                break;
2100              } else {
2101                parameters[iParam].setStringValue(field);
2102              }
2103              std::string fileName;
2104              FILE *fp=NULL;
2105              if (field=="-"||field=="EOL") {
2106                // stdout
2107                fp=stdout;
2108              } else {
2109                if (field[0]=='/'||field[0]=='~')
2110                  fileName = field;
2111                else
2112                  fileName = directory+field;
2113                fp=fopen(fileName.c_str(),"w");
2114              }
2115              if (fp) {
2116                // make fancy later on
2117                int iRow;
2118                int numberRows=models[iModel].numberRows();
2119                int lengthName = models[iModel].lengthNames(); // 0 if no names
2120                // in general I don't want to pass around massive
2121                // amounts of data but seems simpler here
2122                std::vector<std::string> rowNames =
2123                  *(models[iModel].rowNames());
2124                std::vector<std::string> columnNames =
2125                  *(models[iModel].columnNames());
2126
2127                double * dualRowSolution = models[iModel].dualRowSolution();
2128                double * primalRowSolution = 
2129                  models[iModel].primalRowSolution();
2130                double * rowLower = models[iModel].rowLower();
2131                double * rowUpper = models[iModel].rowUpper();
2132                double primalTolerance = models[iModel].primalTolerance();
2133                char format[6];
2134                sprintf(format,"%%-%ds",max(lengthName,8));
2135                for (iRow=0;iRow<numberRows;iRow++) {
2136                  if (primalRowSolution[iRow]>rowUpper[iRow]+primalTolerance||
2137                      primalRowSolution[iRow]<rowLower[iRow]-primalTolerance)
2138                    fprintf(fp,"** ");
2139                  fprintf(fp,"%7d ",iRow);
2140                  if (lengthName)
2141                    fprintf(fp,format,rowNames[iRow].c_str());
2142                  fprintf(fp,"%15.8g        %15.8g\n",primalRowSolution[iRow],
2143                          dualRowSolution[iRow]);
2144                }
2145                int iColumn;
2146                int numberColumns=models[iModel].numberColumns();
2147                double * dualColumnSolution = 
2148                  models[iModel].dualColumnSolution();
2149                double * primalColumnSolution = 
2150                  models[iModel].primalColumnSolution();
2151                double * columnLower = models[iModel].columnLower();
2152                double * columnUpper = models[iModel].columnUpper();
2153                for (iColumn=0;iColumn<numberColumns;iColumn++) {
2154                  if (primalColumnSolution[iColumn]>columnUpper[iColumn]+primalTolerance||
2155                      primalColumnSolution[iColumn]<columnLower[iColumn]-primalTolerance)
2156                    fprintf(fp,"** ");
2157                  fprintf(fp,"%7d ",iColumn);
2158                  if (lengthName)
2159                    fprintf(fp,format,columnNames[iColumn].c_str());
2160                  fprintf(fp,"%15.8g        %15.8g\n",
2161                          primalColumnSolution[iColumn],
2162                          dualColumnSolution[iColumn]);
2163                }
2164                if (fp!=stdout)
2165                  fclose(fp);
2166              } else {
2167                std::cout<<"Unable to open file "<<fileName<<std::endl;
2168              }
2169            } else {
2170              std::cout<<"** Current model not valid"<<std::endl;
2171             
2172            }
2173            break;
2174          default:
2175            abort();
2176          }
2177        } 
2178      } else if (!numberMatches) {
2179        std::cout<<"No match for "<<field<<" - ? for list of commands"
2180                 <<std::endl;
2181      } else if (numberMatches==1) {
2182        if (!numberQuery) {
2183          std::cout<<"Short match for "<<field<<" - completion: ";
2184          std::cout<<parameters[firstMatch].matchName()<<std::endl;
2185        } else if (numberQuery) {
2186          std::cout<<parameters[firstMatch].matchName()<<" : ";
2187          std::cout<<parameters[firstMatch].shortHelp()<<std::endl;
2188          if (numberQuery>=2) 
2189            parameters[firstMatch].printLongHelp();
2190        }
2191      } else {
2192        if (!numberQuery) 
2193          std::cout<<"Multiple matches for "<<field<<" - possible completions:"
2194                   <<std::endl;
2195        else
2196          std::cout<<"Completions of "<<field<<":"<<std::endl;
2197        for ( iParam=0; iParam<numberParameters; iParam++ ) {
2198          int match = parameters[iParam].matches(field);
2199          if (match&&parameters[iParam].displayThis()) {
2200            std::cout<<parameters[iParam].matchName();
2201            if (numberQuery>=2) 
2202              std::cout<<" : "<<parameters[iParam].shortHelp();
2203            std::cout<<std::endl;
2204          }
2205        }
2206      }
2207    }
2208    delete [] models;
2209    delete [] goodModels;
2210  }
2211  // By now all memory should be freed
2212#ifdef DMALLOC
2213  dmalloc_log_unfreed();
2214  dmalloc_shutdown();
2215#endif
2216  return 0;
2217}   
Note: See TracBrowser for help on using the repository browser.