source: trunk/Test/CbcOrClpParam.cpp @ 169

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

for solve

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 61.0 KB
Line 
1// Copyright (C) 2002, International Business Machines
2// Corporation and others.  All Rights Reserved.
3#if defined(_MSC_VER)
4// Turn off compiler warning about long names
5#  pragma warning(disable:4786)
6#endif
7
8#include <string>
9#include <iostream>
10#include <cassert>
11
12#include "CbcOrClpParam.hpp"
13#ifdef COIN_USE_CBC
14#include "OsiSolverInterface.hpp"
15#include "CbcModel.hpp"
16#endif
17#ifdef COIN_USE_CLP
18#include "ClpSimplex.hpp"
19#include "ClpFactorization.hpp"
20#endif
21#ifdef COIN_USE_READLINE     
22#include <readline/readline.h>
23#include <readline/history.h>
24#endif
25
26//#############################################################################
27// Constructors / Destructor / Assignment
28//#############################################################################
29
30//-------------------------------------------------------------------
31// Default Constructor
32//-------------------------------------------------------------------
33CbcOrClpParam::CbcOrClpParam () 
34  : type_(INVALID),
35    lowerDoubleValue_(0.0),
36    upperDoubleValue_(0.0),
37    lowerIntValue_(0),
38    upperIntValue_(0),
39    lengthName_(0),
40    lengthMatch_(0),
41    definedKeyWords_(),
42    name_(),
43    shortHelp_(),
44    longHelp_(),
45    action_(INVALID),
46    currentKeyWord_(-1),
47    display_(false),
48    intValue_(-1),
49    doubleValue_(-1.0),
50    stringValue_(""),
51    indexNumber_(INVALID)
52{
53}
54// Other constructors
55CbcOrClpParam::CbcOrClpParam (std::string name, std::string help,
56           double lower, double upper, CbcOrClpParameterType type,
57                    bool display)
58  : type_(type),
59    lowerIntValue_(0),
60    upperIntValue_(0),
61    definedKeyWords_(),
62    name_(name),
63    shortHelp_(help),
64    longHelp_(),
65    action_(type),
66    currentKeyWord_(-1),
67    display_(display),
68    intValue_(-1),
69    doubleValue_(-1.0),
70    stringValue_(""),
71    indexNumber_(type)
72{
73  lowerDoubleValue_ = lower;
74  upperDoubleValue_ = upper;
75  gutsOfConstructor();
76}
77CbcOrClpParam::CbcOrClpParam (std::string name, std::string help,
78           int lower, int upper, CbcOrClpParameterType type,
79                    bool display)
80  : type_(type),
81    lowerDoubleValue_(0.0),
82    upperDoubleValue_(0.0),
83    definedKeyWords_(),
84    name_(name),
85    shortHelp_(help),
86    longHelp_(),
87    action_(type),
88    currentKeyWord_(-1),
89    display_(display),
90    intValue_(-1),
91    doubleValue_(-1.0),
92    stringValue_(""),
93    indexNumber_(type)
94{
95  gutsOfConstructor();
96  lowerIntValue_ = lower;
97  upperIntValue_ = upper;
98}
99// Other strings will be added by append
100CbcOrClpParam::CbcOrClpParam (std::string name, std::string help, 
101                    std::string firstValue,
102                    CbcOrClpParameterType type,int defaultIndex,
103                    bool display)
104  : type_(type),
105    lowerDoubleValue_(0.0),
106    upperDoubleValue_(0.0),
107    lowerIntValue_(0),
108    upperIntValue_(0),
109    definedKeyWords_(),
110    name_(name),
111    shortHelp_(help),
112    longHelp_(),
113    action_(type),
114    currentKeyWord_(defaultIndex),
115    display_(display),
116    intValue_(-1),
117    doubleValue_(-1.0),
118    stringValue_(""),
119    indexNumber_(type)
120{
121  gutsOfConstructor();
122  definedKeyWords_.push_back(firstValue);
123}
124// Action
125CbcOrClpParam::CbcOrClpParam (std::string name, std::string help,
126                    CbcOrClpParameterType type,int indexNumber,
127                    bool display)
128  : type_(type),
129    lowerDoubleValue_(0.0),
130    upperDoubleValue_(0.0),
131    lowerIntValue_(0),
132    upperIntValue_(0),
133    definedKeyWords_(),
134    name_(name),
135    shortHelp_(help),
136    longHelp_(),
137    action_(type),
138    currentKeyWord_(-1),
139    display_(display),
140    intValue_(-1),
141    doubleValue_(-1.0),
142    stringValue_("")
143{
144  if (indexNumber<0)
145    indexNumber_=type;
146  else
147    indexNumber_=indexNumber;
148  gutsOfConstructor();
149}
150
151//-------------------------------------------------------------------
152// Copy constructor
153//-------------------------------------------------------------------
154CbcOrClpParam::CbcOrClpParam (const CbcOrClpParam & rhs) 
155{ 
156  type_ = rhs.type_;
157  lowerDoubleValue_ = rhs.lowerDoubleValue_;
158  upperDoubleValue_ = rhs.upperDoubleValue_;
159  lowerIntValue_ = rhs.lowerIntValue_;
160  upperIntValue_ = rhs.upperIntValue_;
161  lengthName_ = rhs.lengthName_;
162  lengthMatch_ = rhs.lengthMatch_;
163  definedKeyWords_ = rhs.definedKeyWords_;
164  name_ = rhs.name_;
165  shortHelp_ = rhs.shortHelp_;
166  longHelp_ = rhs.longHelp_;
167  action_ = rhs.action_;
168  currentKeyWord_ = rhs.currentKeyWord_;
169  display_=rhs.display_;
170  intValue_=rhs.intValue_;
171  doubleValue_=rhs.doubleValue_;
172  stringValue_=rhs.stringValue_;
173  indexNumber_=rhs.indexNumber_;
174}
175
176//-------------------------------------------------------------------
177// Destructor
178//-------------------------------------------------------------------
179CbcOrClpParam::~CbcOrClpParam ()
180{
181}
182
183//----------------------------------------------------------------
184// Assignment operator
185//-------------------------------------------------------------------
186CbcOrClpParam &
187CbcOrClpParam::operator=(const CbcOrClpParam& rhs)
188{
189  if (this != &rhs) {
190    type_ = rhs.type_;
191    lowerDoubleValue_ = rhs.lowerDoubleValue_;
192    upperDoubleValue_ = rhs.upperDoubleValue_;
193    lowerIntValue_ = rhs.lowerIntValue_;
194    upperIntValue_ = rhs.upperIntValue_;
195    lengthName_ = rhs.lengthName_;
196    lengthMatch_ = rhs.lengthMatch_;
197    definedKeyWords_ = rhs.definedKeyWords_;
198    name_ = rhs.name_;
199    shortHelp_ = rhs.shortHelp_;
200    longHelp_ = rhs.longHelp_;
201    action_ = rhs.action_;
202    currentKeyWord_ = rhs.currentKeyWord_;
203    display_=rhs.display_;
204    intValue_=rhs.intValue_;
205    doubleValue_=rhs.doubleValue_;
206    stringValue_=rhs.stringValue_;
207    indexNumber_=rhs.indexNumber_;
208  }
209  return *this;
210}
211void 
212CbcOrClpParam::gutsOfConstructor()
213{
214  std::string::size_type  shriekPos = name_.find('!');
215  lengthName_ = name_.length();
216  if ( shriekPos==std::string::npos ) {
217    //does not contain '!'
218    lengthMatch_= lengthName_;
219  } else {
220    lengthMatch_=shriekPos;
221    name_ = name_.substr(0,shriekPos)+name_.substr(shriekPos+1);
222    lengthName_--;
223  }
224}
225// Insert string (only valid for keywords)
226void 
227CbcOrClpParam::append(std::string keyWord)
228{
229  definedKeyWords_.push_back(keyWord);
230}
231
232int 
233CbcOrClpParam::matches (std::string input) const
234{
235  // look up strings to do more elegantly
236  if (input.length()>lengthName_) {
237    return 0;
238  } else {
239    unsigned int i;
240    for (i=0;i<input.length();i++) {
241      if (tolower(name_[i])!=tolower(input[i])) 
242        break;
243    }
244    if (i<input.length()) {
245      return 0;
246    } else if (i>=lengthMatch_) {
247      return 1;
248    } else {
249      // matched but too short
250      return 2;
251    }
252  }
253}
254// Returns name which could match
255std::string
256CbcOrClpParam::matchName (  ) const
257{ 
258  if (lengthMatch_==lengthName_) 
259    return name_;
260  else
261    return name_.substr(0,lengthMatch_)+"("+name_.substr(lengthMatch_)+")";
262}
263
264// Returns parameter option which matches (-1 if none)
265int 
266CbcOrClpParam::parameterOption ( std::string check ) const
267{
268  int numberItems = definedKeyWords_.size();
269  if (!numberItems) {
270    return -1;
271  } else {
272    int whichItem=0;
273    unsigned int it;
274    for (it=0;it<definedKeyWords_.size();it++) {
275      std::string thisOne = definedKeyWords_[it];
276      std::string::size_type  shriekPos = thisOne.find('!');
277      unsigned int length1 = thisOne.length();
278      unsigned int length2 = length1;
279      if ( shriekPos!=std::string::npos ) {
280        //contains '!'
281        length2 = shriekPos;
282        thisOne = thisOne.substr(0,shriekPos)+
283          thisOne.substr(shriekPos+1);
284        length1 = thisOne.length();
285      }
286      if (check.length()<=length1&&length2<=check.length()) {
287        unsigned int i;
288        for (i=0;i<check.length();i++) {
289          if (tolower(thisOne[i])!=tolower(check[i])) 
290            break;
291        }
292        if (i<check.length()) {
293          whichItem++;
294        } else if (i>=length2) {
295          break;
296        } 
297      } else {
298        whichItem++;
299      }
300    }
301    if (whichItem<numberItems)
302      return whichItem;
303    else
304      return -1;
305  }
306}
307// Prints parameter options
308void 
309CbcOrClpParam::printOptions (  ) const
310{
311  std::cout<<"Possible options for "<<name_<<" are:"<<std::endl;
312  unsigned int it;
313  for (it=0;it<definedKeyWords_.size();it++) {
314    std::string thisOne = definedKeyWords_[it];
315    std::string::size_type  shriekPos = thisOne.find('!');
316    if ( shriekPos!=std::string::npos ) {
317      //contains '!'
318      thisOne = thisOne.substr(0,shriekPos)+
319        "("+thisOne.substr(shriekPos+1)+")";
320    }
321    std::cout<<thisOne<<std::endl;
322  }
323}
324// Print action and string
325void 
326CbcOrClpParam::printString() const
327{
328  if (name_=="directory")
329    std::cout<<"Current working directory is "<<stringValue_<<std::endl;
330  else
331    std::cout<<"Current default (if $ as parameter) for "<<name_
332             <<" is "<<stringValue_<<std::endl;
333}
334void CoinReadPrintit(const char * input)
335{
336  int length =strlen(input);
337  char temp[101];
338  int i;
339  int n=0;
340  for (i=0;i<length;i++) {
341    if (input[i]=='\n') {
342      temp[n]='\0';
343      std::cout<<temp<<std::endl;
344      n=0;
345    } else if (n>=65&&input[i]==' ') {
346      temp[n]='\0';
347      std::cout<<temp<<std::endl;
348      n=0;
349    } else if (n||input[i]!=' ') {
350      temp[n++]=input[i];
351    }
352  }
353  if (n) {
354    temp[n]='\0';
355    std::cout<<temp<<std::endl;
356  }
357}
358// Print Long help
359void 
360CbcOrClpParam::printLongHelp() const
361{
362  if (type_>=1&&type_<400) {
363    if (type_<LOGLEVEL) {
364      printf("Range of values is %g to %g\n",lowerDoubleValue_,upperDoubleValue_);
365    } else if (type_<DIRECTION) {
366      printf("Range of values is %d to %d\n",lowerIntValue_,upperIntValue_);
367    } else if (type_<DIRECTORY) {
368      printOptions();
369    }
370    CoinReadPrintit(longHelp_.c_str());
371  }
372}
373#ifdef COIN_USE_CBC
374int
375CbcOrClpParam::setDoubleParameter (OsiSolverInterface * model,double value) 
376{
377  if (value<lowerDoubleValue_||value>upperDoubleValue_) {
378    std::cout<<value<<" was provided for "<<name_<<
379      " - valid range is "<<lowerDoubleValue_<<" to "<<
380      upperDoubleValue_<<std::endl;
381    return 1;
382  } else {
383    double oldValue;
384    switch(type_) {
385    case DUALTOLERANCE:
386      model->getDblParam(OsiDualTolerance,oldValue);
387      model->setDblParam(OsiDualTolerance,value);
388      break;
389    case PRIMALTOLERANCE:
390      model->getDblParam(OsiPrimalTolerance,oldValue);
391      model->setDblParam(OsiPrimalTolerance,value);
392      break;
393    default:
394      oldValue=0.0; // to avoid compiler message
395      abort();
396    }
397    std::cout<<name_<<" was changed from "<<oldValue<<" to "
398             <<value<<std::endl;
399    return 0;
400  }
401}
402#endif
403#ifdef COIN_USE_CLP
404int
405CbcOrClpParam::setDoubleParameter (ClpSimplex * model,double value) 
406{
407  double oldValue = doubleParameter(model);
408  if (value<lowerDoubleValue_||value>upperDoubleValue_) {
409    std::cout<<value<<" was provided for "<<name_<<
410      " - valid range is "<<lowerDoubleValue_<<" to "<<
411      upperDoubleValue_<<std::endl;
412    return 1;
413  } else {
414    std::cout<<name_<<" was changed from "<<oldValue<<" to "
415             <<value<<std::endl;
416    switch(type_) {
417#ifndef COIN_USE_CBC
418    case DUALTOLERANCE:
419      model->setDualTolerance(value);
420      break;
421    case PRIMALTOLERANCE:
422      model->setPrimalTolerance(value);
423      break;
424#endif
425    case DUALBOUND:
426      model->setDualBound(value);
427      break;
428    case PRIMALWEIGHT:
429      model->setInfeasibilityCost(value);
430      break;
431    case TIMELIMIT:
432      model->setMaximumSeconds(value);
433      break;
434    case OBJSCALE:
435      model->setObjectiveScale(value);
436      break;
437    case RHSSCALE:
438      model->setRhsScale(value);
439      break;
440    default:
441      abort();
442    }
443    return 0;
444  }
445}
446double 
447CbcOrClpParam::doubleParameter (ClpSimplex * model) const
448{
449  double value;
450  switch(type_) {
451#ifndef COIN_USE_CBC
452  case DUALTOLERANCE:
453    value=model->dualTolerance();
454    break;
455  case PRIMALTOLERANCE:
456    value=model->primalTolerance();
457    break;
458#endif
459  case DUALBOUND:
460    value=model->dualBound();
461    break;
462  case PRIMALWEIGHT:
463    value=model->infeasibilityCost();
464    break;
465  case TIMELIMIT:
466    value=model->maximumSeconds();
467    break;
468  case OBJSCALE:
469    value=model->objectiveScale();
470    break;
471  case RHSSCALE:
472    value=model->rhsScale();
473    break;
474  default:
475    abort();
476  }
477  return value;
478}
479int 
480CbcOrClpParam::setIntParameter (ClpSimplex * model,int value) 
481{
482  int oldValue = intParameter(model);
483  if (value<lowerIntValue_||value>upperIntValue_) {
484    std::cout<<value<<" was provided for "<<name_<<
485      " - valid range is "<<lowerIntValue_<<" to "<<
486      upperIntValue_<<std::endl;
487    return 1;
488  } else {
489    std::cout<<name_<<" was changed from "<<oldValue<<" to "
490             <<value<<std::endl;
491    switch(type_) {
492    case SOLVERLOGLEVEL:
493      model->setLogLevel(value);
494      if (value>2)
495        model->factorization()->messageLevel(8);
496      else
497        model->factorization()->messageLevel(0);
498      break;
499    case MAXFACTOR:
500      model->factorization()->maximumPivots(value);
501      break;
502    case PERTVALUE:
503      model->setPerturbation(value);
504      break;
505    case MAXITERATION:
506      model->setMaximumIterations(value);
507      break;
508    case SPECIALOPTIONS:
509      model->setSpecialOptions(value);
510      break;
511    default:
512      abort();
513    }
514    return 0;
515  }
516}
517int 
518CbcOrClpParam::intParameter (ClpSimplex * model) const
519{
520  int value;
521  switch(type_) {
522#ifndef COIN_USE_CBC
523  case SOLVERLOGLEVEL:
524    value=model->logLevel();
525    break;
526#endif
527  case MAXFACTOR:
528    value=model->factorization()->maximumPivots();
529    break;
530    break;
531  case PERTVALUE:
532    value=model->perturbation();
533    break;
534  case MAXITERATION:
535    value=model->maximumIterations();
536    break;
537  case SPECIALOPTIONS:
538    value=model->specialOptions();
539    break;
540  default:
541    value=-1;
542    break;
543  }
544  return value;
545}
546#endif
547int
548CbcOrClpParam::checkDoubleParameter (double value) const
549{
550  if (value<lowerDoubleValue_||value>upperDoubleValue_) {
551    std::cout<<value<<" was provided for "<<name_<<
552      " - valid range is "<<lowerDoubleValue_<<" to "<<
553      upperDoubleValue_<<std::endl;
554    return 1;
555  } else {
556    return 0;
557  }
558}
559#ifdef COIN_USE_CBC
560double 
561CbcOrClpParam::doubleParameter (OsiSolverInterface * model) const
562{
563  double value;
564  switch(type_) {
565  case DUALTOLERANCE:
566    assert(model->getDblParam(OsiDualTolerance,value));
567    break;
568  case PRIMALTOLERANCE:
569    assert(model->getDblParam(OsiPrimalTolerance,value));
570    break;
571  default:
572    abort();
573  }
574  return value;
575}
576int 
577CbcOrClpParam::setIntParameter (OsiSolverInterface * model,int value) 
578{
579  if (value<lowerIntValue_||value>upperIntValue_) {
580    std::cout<<value<<" was provided for "<<name_<<
581      " - valid range is "<<lowerIntValue_<<" to "<<
582      upperIntValue_<<std::endl;
583    return 1;
584  } else {
585    int oldValue;
586    switch(type_) {
587    case SOLVERLOGLEVEL:
588      model->messageHandler()->setLogLevel(value);
589      break;
590    default:
591      oldValue=0; // to avoid compiler message
592      abort();
593    }
594    std::cout<<name_<<" was changed from "<<oldValue<<" to "
595             <<value<<std::endl;
596    return 0;
597  }
598}
599int 
600CbcOrClpParam::intParameter (OsiSolverInterface * model) const
601{
602  int value=0;
603  switch(type_) {
604  case SOLVERLOGLEVEL:
605    value=model->messageHandler()->logLevel();
606    break;
607  default:
608    abort();
609  }
610  return value;
611}
612int
613CbcOrClpParam::setDoubleParameter (CbcModel &model,double value) 
614{
615  if (value<lowerDoubleValue_||value>upperDoubleValue_) {
616    std::cout<<value<<" was provided for "<<name_<<
617      " - valid range is "<<lowerDoubleValue_<<" to "<<
618      upperDoubleValue_<<std::endl;
619    return 1;
620  } else {
621    double oldValue;
622    setDoubleValue(value);
623    switch(type_) {
624    case INFEASIBILITYWEIGHT:
625      oldValue=model.getDblParam(CbcModel::CbcInfeasibilityWeight);
626      model.setDblParam(CbcModel::CbcInfeasibilityWeight,value);
627      break;
628    case INTEGERTOLERANCE:
629      oldValue=model.getDblParam(CbcModel::CbcIntegerTolerance);
630      model.setDblParam(CbcModel::CbcIntegerTolerance,value);
631      break;
632    case INCREMENT:
633      oldValue=model.getDblParam(CbcModel::CbcCutoffIncrement);
634      model.setDblParam(CbcModel::CbcCutoffIncrement,value);
635    case ALLOWABLEGAP:
636      oldValue=model.getDblParam(CbcModel::CbcAllowableGap);
637      model.setDblParam(CbcModel::CbcAllowableGap,value);
638      break;
639    case TIMELIMIT:
640    { oldValue = model.getDblParam(CbcModel::CbcMaximumSeconds) ;
641      model.setDblParam(CbcModel::CbcMaximumSeconds,value) ;
642      break ; }
643    case DUALTOLERANCE:
644    case PRIMALTOLERANCE:
645      setDoubleParameter(model.solver(),value);
646      return 0; // to avoid message
647    default:
648      oldValue=0.0; // to avoid compiler message
649      break;
650    }
651    std::cout<<name_<<" was changed from "<<oldValue<<" to "
652             <<value<<std::endl;
653    return 0;
654  }
655}
656double 
657CbcOrClpParam::doubleParameter (CbcModel &model) const
658{
659  double value;
660  switch(type_) {
661  case INFEASIBILITYWEIGHT:
662    value=model.getDblParam(CbcModel::CbcInfeasibilityWeight);
663    break;
664  case INTEGERTOLERANCE:
665    value=model.getDblParam(CbcModel::CbcIntegerTolerance);
666    break;
667  case INCREMENT:
668    value=model.getDblParam(CbcModel::CbcCutoffIncrement);
669  case ALLOWABLEGAP:
670    value=model.getDblParam(CbcModel::CbcAllowableGap);
671    break;
672  case TIMELIMIT:
673  { value = model.getDblParam(CbcModel::CbcMaximumSeconds) ;
674    break ; }
675  case DUALTOLERANCE:
676  case PRIMALTOLERANCE:
677    value=doubleParameter(model.solver());
678    break;
679  default:
680    abort();
681  }
682  return value;
683}
684int 
685CbcOrClpParam::setIntParameter (CbcModel &model,int value) 
686{
687  if (value<lowerIntValue_||value>upperIntValue_) {
688    std::cout<<value<<" was provided for "<<name_<<
689      " - valid range is "<<lowerIntValue_<<" to "<<
690      upperIntValue_<<std::endl;
691    return 1;
692  } else {
693    setIntValue(value);
694    int oldValue;
695    switch(type_) {
696    case LOGLEVEL:
697      oldValue = model.messageHandler()->logLevel();
698      model.messageHandler()->setLogLevel(value);
699      break;
700    case SOLVERLOGLEVEL:
701      oldValue = model.solver()->messageHandler()->logLevel();
702      model.solver()->messageHandler()->setLogLevel(value);
703      break;
704    case MAXNODES:
705      oldValue=model.getIntParam(CbcModel::CbcMaxNumNode);
706      model.setIntParam(CbcModel::CbcMaxNumNode,value);
707      break;
708    case STRONGBRANCHING:
709      oldValue=model.numberStrong();
710      model.setNumberStrong(value);
711      break;
712    case NUMBERBEFORE:
713      oldValue=model.numberBeforeTrust();
714      model.setNumberBeforeTrust(value);
715      break;
716    default:
717      oldValue=0; // to avoid compiler message
718      break;
719    }
720    std::cout<<name_<<" was changed from "<<oldValue<<" to "
721             <<value<<std::endl;
722    return 0;
723  }
724}
725int 
726CbcOrClpParam::intParameter (CbcModel &model) const
727{
728  int value;
729  switch(type_) {
730  case LOGLEVEL:
731    value = model.messageHandler()->logLevel();
732      break;
733  case SOLVERLOGLEVEL:
734    value = model.solver()->messageHandler()->logLevel();
735      break;
736  case MAXNODES:
737    value = model.getIntParam(CbcModel::CbcMaxNumNode);
738    break;
739  case STRONGBRANCHING:
740    value=model.numberStrong();
741    break;
742  case NUMBERBEFORE:
743    value=model.numberBeforeTrust();
744    break;
745  default:
746    abort();
747  }
748  return value;
749}
750#endif
751void 
752CbcOrClpParam::setIntValue ( int value )
753{ 
754  if (value<lowerIntValue_||value>upperIntValue_) {
755    std::cout<<value<<" was provided for "<<name_<<
756      " - valid range is "<<lowerIntValue_<<" to "<<
757      upperIntValue_<<std::endl;
758  } else {
759    intValue_=value;
760  }
761}
762void 
763CbcOrClpParam::setDoubleValue ( double value )
764{ 
765  if (value<lowerDoubleValue_||value>upperDoubleValue_) {
766    std::cout<<value<<" was provided for "<<name_<<
767      " - valid range is "<<lowerDoubleValue_<<" to "<<
768      upperDoubleValue_<<std::endl;
769  } else {
770    doubleValue_=value;
771  }
772}
773void 
774CbcOrClpParam::setStringValue ( std::string value )
775{ 
776  stringValue_=value;
777}
778static char line[1000];
779static char * where=NULL;
780extern int CbcOrClpRead_mode;
781extern FILE * CbcOrClpReadCommand;
782// Simple read stuff
783std::string
784CoinReadNextField()
785{
786  std::string field;
787  if (!where) {
788    // need new line
789#ifdef COIN_USE_READLINE     
790    if (CbcOrClpReadCommand==stdin) {
791      // Get a line from the user.
792      where = readline ("Clp:");
793     
794      // If the line has any text in it, save it on the history.
795      if (where) {
796        if ( *where)
797          add_history (where);
798        strcpy(line,where);
799        free(where);
800      }
801    } else {
802      where = fgets(line,1000,CbcOrClpReadCommand);
803    }
804#else
805    if (CbcOrClpReadCommand==stdin) {
806      fprintf(stdout,"Clp:");
807      fflush(stdout);
808    }
809    where = fgets(line,1000,CbcOrClpReadCommand);
810#endif
811    if (!where)
812      return field; // EOF
813    where = line;
814    // clean image
815    char * lastNonBlank = line-1;
816    while ( *where != '\0' ) {
817      if ( *where != '\t' && *where < ' ' ) {
818        break;
819      } else if ( *where != '\t' && *where != ' ') {
820        lastNonBlank = where;
821      }
822      where++;
823    }
824    where=line;
825    *(lastNonBlank+1)='\0';
826  }
827  // munch white space
828  while(*where==' '||*where=='\t')
829    where++;
830  char * saveWhere = where;
831  while (*where!=' '&&*where!='\t'&&*where!='\0')
832    where++;
833  if (where!=saveWhere) {
834    char save = *where;
835    *where='\0';
836    //convert to string
837    field=saveWhere;
838    *where=save;
839  } else {
840    where=NULL;
841    field="EOL";
842  }
843  return field;
844}
845
846std::string
847CoinReadGetCommand(int argc, const char *argv[])
848{
849  std::string field="EOL";
850  while (field=="EOL") {
851    if (CbcOrClpRead_mode>0) {
852      if (CbcOrClpRead_mode<argc) {
853        field = argv[CbcOrClpRead_mode++];
854        if (field=="-") {
855          std::cout<<"Switching to line mode"<<std::endl;
856          CbcOrClpRead_mode=-1;
857          field=CoinReadNextField();
858        } else if (field[0]!='-') {
859          if (CbcOrClpRead_mode!=2) {
860            std::cout<<"skipping non-command "<<field<<std::endl;
861            field="EOL"; // skip
862          } else {
863            // special dispensation - taken as -import name
864            CbcOrClpRead_mode--;
865            field="import";
866          }
867        } else {
868          if (field!="--") {
869            // take off -
870            field = field.substr(1);
871          } else {
872            // special dispensation - taken as -import --
873            CbcOrClpRead_mode--;
874            field="import";
875          }
876        }
877      } else {
878        field="";
879      }
880    } else {
881      field=CoinReadNextField();
882    }
883  }
884  //std::cout<<field<<std::endl;
885  return field;
886}
887std::string
888CoinReadGetString(int argc, const char *argv[])
889{
890  std::string field="EOL";
891  if (CbcOrClpRead_mode>0) {
892    if (CbcOrClpRead_mode<argc) {
893      if (argv[CbcOrClpRead_mode][0]!='-') { 
894        field = argv[CbcOrClpRead_mode++];
895      } else if (!strcmp(argv[CbcOrClpRead_mode],"--")) {
896        field = argv[CbcOrClpRead_mode++];
897        // -- means import from stdin
898        field = "-";
899      }
900    }
901  } else {
902    field=CoinReadNextField();
903  }
904  //std::cout<<field<<std::endl;
905  return field;
906}
907// valid 0 - okay, 1 bad, 2 not there
908int
909CoinReadGetIntField(int argc, const char *argv[],int * valid)
910{
911  std::string field="EOL";
912  if (CbcOrClpRead_mode>0) {
913    if (CbcOrClpRead_mode<argc) {
914      // may be negative value so do not check for -
915      field = argv[CbcOrClpRead_mode++];
916    }
917  } else {
918    field=CoinReadNextField();
919  }
920  int value=0;
921  //std::cout<<field<<std::endl;
922  if (field!="EOL") {
923    // how do I check valid
924    value =  atoi(field.c_str());
925    *valid=0;
926  } else {
927    *valid=2;
928  }
929  return value;
930}
931double
932CoinReadGetDoubleField(int argc, const char *argv[],int * valid)
933{
934  std::string field="EOL";
935  if (CbcOrClpRead_mode>0) {
936    if (CbcOrClpRead_mode<argc) {
937      // may be negative value so do not check for -
938      field = argv[CbcOrClpRead_mode++];
939    }
940  } else {
941    field=CoinReadNextField();
942  }
943  double value=0.0;
944  //std::cout<<field<<std::endl;
945  if (field!="EOL") {
946    // how do I check valid
947    value = atof(field.c_str());
948    *valid=0;
949  } else {
950    *valid=2;
951  }
952  return value;
953}
954/*
955  Subroutine to establish the cbc parameter array. See the description of
956  class CbcOrClpParam for details. Pulled from C..Main() for clarity.
957*/
958void 
959establishParams (int &numberParameters, CbcOrClpParam *const parameters)
960{
961  numberParameters=0;
962  parameters[numberParameters++]=
963    CbcOrClpParam("?","For help",GENERALQUERY,-1,false);
964  parameters[numberParameters++]=
965    CbcOrClpParam("???","For help",FULLGENERALQUERY,-1,false);
966  parameters[numberParameters++]=
967    CbcOrClpParam("-","From stdin",
968                  STDIN,299,false);
969#ifdef COIN_USE_CBC
970    parameters[numberParameters++]=
971      CbcOrClpParam("allow!ableGap","Stop when gap between best possible and \
972best less than this",
973              0.0,1.0e20,ALLOWABLEGAP);
974  parameters[numberParameters-1].setLonghelp
975    (
976     "TODO"
977     ); 
978#endif
979#ifdef COIN_USE_CLP
980  parameters[numberParameters++]=
981    CbcOrClpParam("allS!lack","Set basis back to all slack and reset solution",
982                  ALLSLACK,false);
983  parameters[numberParameters-1].setLonghelp
984    (
985     "Useful for playing around"
986     ); 
987  parameters[numberParameters++]=
988    CbcOrClpParam("auto!Scale","Whether to scale objective, rhs and bounds of problem if they look odd",
989                  "off",AUTOSCALE,0,false);
990  parameters[numberParameters-1].append("on");
991  parameters[numberParameters-1].setLonghelp
992    (
993     "If you think you may get odd objective values or large equality rows etc then\
994 it may be worth setting this true.  It is still experimental and you may prefer\
995 to use objective!Scale and rhs!Scale"
996     ); 
997  parameters[numberParameters++]=
998    CbcOrClpParam("barr!ier","Solve using primal dual predictor corrector algorithm",
999                  BARRIER);
1000  parameters[numberParameters-1].setLonghelp
1001    (
1002     "This command solves the current model using the  primal dual predictor \
1003corrector algorithm."
1004     
1005     ); 
1006  parameters[numberParameters++]=
1007    CbcOrClpParam("basisI!n","Import basis from bas file",
1008                  BASISIN);
1009  parameters[numberParameters-1].setLonghelp
1010    (
1011     "This will read an MPS format basis file from the given file name.  It will use the default\
1012 directory given by 'directory'.  A name of '$' will use the previous value for the name.  This\
1013 is initialized to '', i.e. it must be set.  If you have libgz then it can read compressed\
1014 files 'xxxxxxxx.gz'.."
1015     ); 
1016  parameters[numberParameters++]=
1017    CbcOrClpParam("basisO!ut","Export basis as bas file",
1018                  BASISOUT);
1019  parameters[numberParameters-1].setLonghelp
1020    (
1021     "This will write an MPS format basis file to the given file name.  It will use the default\
1022 directory given by 'directory'.  A name of '$' will use the previous value for the name.  This\
1023 is initialized to 'default.bas'."
1024     ); 
1025  parameters[numberParameters++]=
1026    CbcOrClpParam("biasLU","Whether factorization biased towards U",
1027                  "UU",BIASLU,2,false);
1028  parameters[numberParameters-1].append("UX");
1029  parameters[numberParameters-1].append("LX");
1030  parameters[numberParameters-1].append("LL");
1031#endif
1032#ifdef COIN_USE_CBC
1033  parameters[numberParameters++]=
1034    CbcOrClpParam("branch!AndCut","Do Branch and Cut",
1035                  BAB);
1036  parameters[numberParameters-1].setLonghelp
1037    (
1038     "This does branch and cut.  Far too many parameters apply to give a full description here.  \
1039the main thing is to think about which cuts to apply.  .. expand ..."
1040     ); 
1041#endif
1042  parameters[numberParameters++]=
1043    CbcOrClpParam("bscale","Whether to scale in barrier",
1044                  "off",BARRIERSCALE,0,false);
1045  parameters[numberParameters-1].append("on");
1046  parameters[numberParameters++]=
1047    CbcOrClpParam("chol!esky","Which cholesky algorithm",
1048                  "native",CHOLESKY,false);
1049  parameters[numberParameters-1].append("dense");
1050  //#ifdef FOREIGN_BARRIER
1051#ifdef WSSMP_BARRIER
1052  parameters[numberParameters-1].append("fudge!Long");
1053  parameters[numberParameters-1].append("wssmp");
1054#define REAL_BARRIER
1055#else
1056  parameters[numberParameters-1].append("fudge!Long_dummy");
1057  parameters[numberParameters-1].append("wssmp_dummy");
1058#endif
1059#ifdef UFL_BARRIER
1060  parameters[numberParameters-1].append("Uni!versityOfFlorida");
1061#define REAL_BARRIER
1062#else
1063  parameters[numberParameters-1].append("Uni!versityOfFlorida_dummy");
1064#endif
1065#ifdef TAUCS_BARRIER
1066  parameters[numberParameters-1].append("Taucs");
1067#define REAL_BARRIER
1068#else
1069  parameters[numberParameters-1].append("Taucs_dummy");
1070#endif
1071  //#endif
1072#ifdef COIN_USE_CBC
1073  parameters[numberParameters++]=
1074    CbcOrClpParam("clique!Cuts","Whether to use Clique cuts",
1075                  "off",CLIQUECUTS);
1076  parameters[numberParameters-1].append("on");
1077  parameters[numberParameters-1].append("root");
1078  parameters[numberParameters-1].setLonghelp
1079    (
1080     "TODO"
1081     ); 
1082  parameters[numberParameters++]=
1083    CbcOrClpParam("cost!Strategy","How to use costs",
1084                  "off",COSTSTRATEGY);
1085  parameters[numberParameters-1].append("pri!orities");
1086  parameters[numberParameters-1].append("pseudo!costs(not implemented yet)");
1087  parameters[numberParameters-1].setLonghelp
1088    (
1089     "TODO"
1090     ); 
1091#endif
1092#ifdef COIN_USE_CLP
1093  parameters[numberParameters++]=
1094    CbcOrClpParam("crash","Whether to create basis for problem",
1095                  "off",CRASH);
1096  parameters[numberParameters-1].append("on");
1097  parameters[numberParameters-1].append("so!low_halim");
1098  parameters[numberParameters-1].append("ha!lim_solow(JJF mods)");
1099  parameters[numberParameters-1].append("4");
1100  parameters[numberParameters-1].append("5");
1101  parameters[numberParameters-1].setLonghelp
1102    (
1103     "If crash is set on and there is an all slack basis then Clp will flip or put structural\
1104 variables into basis with the aim of getting dual feasible.  On the whole dual seems to be\
1105 better without it and there alernative types of 'crash' for primal e.g. 'idiot' or 'sprint'. \
1106I have also added a variant due to Solow and Halim which is as on but just flip."); 
1107  parameters[numberParameters++]=
1108    CbcOrClpParam("cross!over","Whether to get a basic solution after barrier",
1109                  "on",CROSSOVER);
1110  parameters[numberParameters-1].append("off");
1111  parameters[numberParameters-1].append("maybe");
1112  parameters[numberParameters-1].setLonghelp
1113    (
1114     "Interior point algorithms do not obtain a basic solution (and \
1115the feasibility criterion is a bit suspect (JJF)).  This option will crossover \
1116to a basic solution suitable for ranging or branch and cut.  With the current state \
1117of quadratic it may be a good idea to switch off crossover for quadratic (and maybe \
1118presolve as well) - the option maybe does this."
1119     );
1120#endif
1121#ifdef COIN_USE_CBC
1122  parameters[numberParameters++]=
1123    CbcOrClpParam("cutD!epth","Depth in tree at which to do cuts",
1124                  -1,999999,CUTDEPTH);
1125  parameters[numberParameters-1].setLonghelp
1126    (
1127     "Cut generators may be - off, on only at root, on if they look possible \
1128and on.  If they are done every node then that is that, but it may be worth doing them \
1129every so often.  The original method was every so many node but it may be more logical \
1130to do it whenever depth in tree is a multiple of K.  This option does that and defaults \
1131to 5."
1132     );
1133  parameters[numberParameters-1].setIntValue(5);
1134#endif
1135  parameters[numberParameters++]=
1136    CbcOrClpParam("direction","Minimize or Maximize",
1137                  "min!imize",DIRECTION);
1138  parameters[numberParameters-1].append("max!imize");
1139  parameters[numberParameters-1].append("zero");
1140  parameters[numberParameters-1].setLonghelp
1141    (
1142     "The default is minimize - use 'direction maximize' for maximization.\n\
1143You can also use the parameters 'maximize' or 'minimize'."
1144     ); 
1145  parameters[numberParameters++]=
1146    CbcOrClpParam("directory","Set Default directory for import etc.",
1147                  DIRECTORY,299);
1148  parameters[numberParameters-1].setLonghelp
1149    (
1150     "This sets the directory which import, export, saveModel and restoreModel will use.\
1151  It is initialized to './'"
1152     ); 
1153#ifdef COIN_USE_CLP
1154  parameters[numberParameters++]=
1155    CbcOrClpParam("dualB!ound","Initially algorithm acts as if no \
1156gap between bounds exceeds this value",
1157                  1.0e-20,1.0e12,DUALBOUND);
1158  parameters[numberParameters-1].setLonghelp
1159    (
1160     "The dual algorithm in Clp is a single phase algorithm as opposed to a two phase\
1161 algorithm where you first get feasible then optimal.  If a problem has both upper and\
1162 lower bounds then it is trivial to get dual feasible by setting non basic variables\
1163 to correct bound.  If the gap between the upper and lower bounds of a variable is more\
1164 than the value of dualBound Clp introduces fake bounds so that it can make the problem\
1165 dual feasible.  This has the same effect as a composite objective function in the\
1166 primal algorithm.  Too high a value may mean more iterations, while too low a bound means\
1167 the code may go all the way and then have to increase the bounds.  OSL had a heuristic to\
1168 adjust bounds, maybe we need that here."
1169     );
1170  parameters[numberParameters++]=
1171    CbcOrClpParam("dualize","Solves dual reformulation",
1172                  0,1,DUALIZE,false);
1173  parameters[numberParameters-1].setLonghelp
1174    (
1175     "Don't even think about it."
1176     ); 
1177  parameters[numberParameters++]=
1178    CbcOrClpParam("dualP!ivot","Dual pivot choice algorithm",
1179                  "auto!matic",DUALPIVOT);
1180  parameters[numberParameters-1].append("dant!zig");
1181  parameters[numberParameters-1].append("partial");
1182  parameters[numberParameters-1].append("steep!est");
1183  parameters[numberParameters-1].setLonghelp
1184    (
1185     "Clp can use any pivot selection algorithm which the user codes as long as it\
1186 implements the features in the abstract pivot base class.  The Dantzig method is implemented\
1187 to show a simple method but its use is deprecated.  Steepest is the method of choice and there\
1188 are two variants which keep all weights updated but only scan a subset each iteration.\
1189 Partial switches this on while automatic decides at each iteration based on information\
1190 about the factorization."
1191     ); 
1192  parameters[numberParameters++]=
1193    CbcOrClpParam("dualS!implex","Do dual simplex algorithm",
1194                  DUALSIMPLEX);
1195  parameters[numberParameters-1].setLonghelp
1196    (
1197     "This command solves the current model using the dual steepest algorithm.\
1198The time and iterations may be affected by settings such as presolve, scaling, crash\
1199 and also by dual pivot method, fake bound on variables and dual and primal tolerances."
1200     );
1201#endif
1202  parameters[numberParameters++]=
1203    CbcOrClpParam("dualT!olerance","For an optimal solution \
1204no dual infeasibility may exceed this value",
1205                  1.0e-20,1.0e12,DUALTOLERANCE);
1206  parameters[numberParameters-1].setLonghelp
1207    (
1208     "Normally the default tolerance is fine, but you may want to increase it a\
1209 bit if a dual run seems to be having a hard time"
1210     ); 
1211#ifdef COIN_USE_CLP
1212  parameters[numberParameters++]=
1213    CbcOrClpParam("either!Simplex","Do dual or primal simplex algorithm",
1214                  EITHERSIMPLEX);
1215  parameters[numberParameters-1].setLonghelp
1216    (
1217     "This command solves the current model using the dual or primal algorithm,\
1218 based on a dubious analysis of model."
1219     );
1220#endif
1221  parameters[numberParameters++]=
1222    CbcOrClpParam("end","Stops clp execution",
1223                  EXIT);
1224  parameters[numberParameters-1].setLonghelp
1225    (
1226     "This stops execution ; end, exit, quit and stop are synonyms"
1227     ); 
1228  parameters[numberParameters++]=
1229    CbcOrClpParam("error!sAllowed","Whether to allow import errors",
1230                  "off",ERRORSALLOWED);
1231  parameters[numberParameters-1].append("on");
1232  parameters[numberParameters-1].setLonghelp
1233    (
1234     "The default is not to use any model which had errors when reading the mps file.\
1235  Setting this to 'on' will allow all errors from which the code can recover\
1236 by ignoring the error."
1237     );
1238  parameters[numberParameters++]=
1239    CbcOrClpParam("exit","Stops clp execution",
1240                  EXIT);
1241  parameters[numberParameters-1].setLonghelp
1242    (
1243     "This stops the execution of Clp, end, exit, quit and stop are synonyms"
1244     ); 
1245  parameters[numberParameters++]=
1246    CbcOrClpParam("export","Export model as mps file",
1247                  EXPORT);
1248  parameters[numberParameters-1].setLonghelp
1249    (
1250     "This will write an MPS format file to the given file name.  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.mps'."
1253     ); 
1254#ifdef COIN_USE_CLP
1255  parameters[numberParameters++]=
1256    CbcOrClpParam("fakeB!ound","All bounds <= this value - DEBUG",
1257                  1.0,1.0e15,FAKEBOUND,false);
1258#ifdef COIN_USE_CBC
1259  parameters[numberParameters++]=
1260    CbcOrClpParam("fix!OnDj","Try heuristic based on fixing variables with \
1261reduced costs greater than this",
1262                  -1.0e20,1.0e20,DJFIX,false);
1263  parameters[numberParameters-1].setLonghelp
1264    (
1265     "TODO"
1266     ); 
1267    parameters[numberParameters++]=
1268      CbcOrClpParam("flow!CoverCuts","Whether to use Flow Cover cuts",
1269                    "off",FLOWCUTS);
1270    parameters[numberParameters-1].append("on");
1271    parameters[numberParameters-1].append("root");
1272  parameters[numberParameters-1].setLonghelp
1273    (
1274     "TODO"
1275     ); 
1276#endif
1277  parameters[numberParameters++]=
1278    CbcOrClpParam("gamma","Whether to regularize barrier",
1279                  "off",GAMMA,0,false);
1280  parameters[numberParameters-1].append("on");
1281#endif
1282#ifdef COIN_USE_CBC
1283  parameters[numberParameters++]=
1284    CbcOrClpParam("gap!Ratio","Stop when gap between best possible and \
1285best less than this fraction of larger of two",
1286                  0.0,1.0e20,GAPRATIO);
1287  parameters[numberParameters-1].setLonghelp
1288    (
1289     "TODO"
1290     ); 
1291  parameters[numberParameters++]=
1292    CbcOrClpParam("gomory!Cuts","Whether to use Gomory cuts",
1293                  "off",GOMORYCUTS);
1294  parameters[numberParameters-1].append("on");
1295  parameters[numberParameters-1].append("root");
1296  parameters[numberParameters-1].setLonghelp
1297    (
1298     "The original cuts - beware of imitations!  Having gone out of favo(u)r, they are now more \
1299fashionable as LP solvers are more robust and they interact well with other cuts.  They will almost always \
1300give cuts (although in this executable they are limited as to number of variables in cut)."
1301     ); 
1302#endif
1303  parameters[numberParameters++]=
1304    CbcOrClpParam("help","Print out version, non-standard options and some help",
1305                  HELP);
1306#ifdef COIN_USE_CLP
1307  parameters[numberParameters++]=
1308    CbcOrClpParam("idiot!Crash","Whether to try idiot crash",
1309                  -1,999999,IDIOT);
1310  parameters[numberParameters-1].setLonghelp
1311    (
1312     "This is a type of 'crash' which works well on some homogeneous problems.\
1313 It works best on problems with unit elements and rhs but will do something to any model.  It should only be\
1314 used before primal.  It can be set to -1 when the code decides for itself whether to use it,\
1315 0 to switch off or n > 0 to do n passes."
1316     ); 
1317#endif
1318  parameters[numberParameters++]=
1319    CbcOrClpParam("import","Import model from mps file",
1320                  IMPORT);
1321  parameters[numberParameters-1].setLonghelp
1322    (
1323     "This will read an MPS format file from the given file name.  It will use the default\
1324 directory given by 'directory'.  A name of '$' will use the previous value for the name.  This\
1325 is initialized to '', i.e. it must be set.  If you have libgz then it can read compressed\
1326 files 'xxxxxxxx.gz'.."
1327     );
1328#ifdef COIN_USE_CBC
1329  parameters[numberParameters++]=
1330    CbcOrClpParam("inc!rement","A valid solution must be at least this \
1331much better than last integer solution",
1332                  -1.0e20,1.0e20,INCREMENT);
1333  parameters[numberParameters-1].setLonghelp
1334    (
1335     "TODO"
1336     ); 
1337  parameters[numberParameters++]=
1338    CbcOrClpParam("inf!easibilityWeight","Each integer infeasibility is expected \
1339to cost this much",
1340                  0.0,1.0e20,INFEASIBILITYWEIGHT);
1341  parameters[numberParameters-1].setLonghelp
1342    (
1343     "TODO"
1344     ); 
1345  parameters[numberParameters++]=
1346    CbcOrClpParam("initialS!olve","Solve to continuous",
1347                  SOLVECONTINUOUS);
1348  parameters[numberParameters-1].setLonghelp
1349    (
1350     "TODO"
1351     ); 
1352  parameters[numberParameters++]=
1353    CbcOrClpParam("integerT!olerance","For an optimal solution \
1354no integer variable may be this away from an integer value",
1355              1.0e-20,0.5,INTEGERTOLERANCE);
1356  parameters[numberParameters-1].setLonghelp
1357    (
1358     "TODO"
1359     ); 
1360#endif
1361#ifdef COIN_USE_CLP
1362  parameters[numberParameters++]=
1363    CbcOrClpParam("keepN!ames","Whether to keep names from import",
1364                  "on",KEEPNAMES);
1365  parameters[numberParameters-1].append("off");
1366  parameters[numberParameters-1].setLonghelp
1367    (
1368     "It saves space to get rid of names so if you need to you can set this to off."
1369     ); 
1370  parameters[numberParameters++]=
1371    CbcOrClpParam("KKT","Whether to use KKT factorization",
1372                  "off",KKT,0,false);
1373  parameters[numberParameters-1].append("on");
1374#endif
1375#ifdef COIN_USE_CBC
1376  parameters[numberParameters++]=
1377    CbcOrClpParam("knapsack!Cuts","Whether to use Knapsack cuts",
1378                  "off",KNAPSACKCUTS);
1379  parameters[numberParameters-1].append("on");
1380  parameters[numberParameters-1].append("root");
1381  parameters[numberParameters-1].setLonghelp
1382    (
1383     "TODO"
1384     ); 
1385#endif
1386#ifndef COIN_USE_CBC
1387  parameters[numberParameters++]=
1388    CbcOrClpParam("log!Level","Level of detail in Solver output",
1389                  -1,63,SOLVERLOGLEVEL);
1390#else
1391  parameters[numberParameters++]=
1392    CbcOrClpParam("log!Level","Level of detail in Coin branch and Cut output",
1393                  -1,63,LOGLEVEL);
1394  parameters[numberParameters-1].setIntValue(1);
1395#endif
1396  parameters[numberParameters-1].setLonghelp
1397    (
1398     "If 0 then there should be no output in normal circumstances.  1 is probably the best\
1399 value for most uses, while 2 and 3 give more information."
1400     ); 
1401  parameters[numberParameters++]=
1402    CbcOrClpParam("max!imize","Set optimization direction to maximize",
1403                  MAXIMIZE,299);
1404  parameters[numberParameters-1].setLonghelp
1405    (
1406     "The default is minimize - use 'maximize' for maximization.\n\
1407You can also use the parameters 'direction maximize'."
1408     ); 
1409#ifdef COIN_USE_CLP
1410  parameters[numberParameters++]=
1411    CbcOrClpParam("maxF!actor","Maximum number of iterations between \
1412refactorizations",
1413                  1,999999,MAXFACTOR);
1414  parameters[numberParameters-1].setLonghelp
1415    (
1416     "If this is at its initial value of 201 then in this executable clp will guess at a\
1417 value to use.  Otherwise the user can set a value.  The code may decide to re-factorize\
1418 earlier."
1419     ); 
1420  parameters[numberParameters++]=
1421    CbcOrClpParam("maxIt!erations","Maximum number of iterations before \
1422stopping",
1423                  0,99999999,MAXITERATION);
1424  parameters[numberParameters-1].setLonghelp
1425    (
1426     "This can be used for testing purposes.  The corresponding library call\n\
1427      \tsetMaximumIterations(value)\n can be useful.  If the code stops on\
1428 seconds or by an interrupt this will be treated as stopping on maximum iterations"
1429     ); 
1430#endif
1431#ifdef COIN_USE_CBC
1432  parameters[numberParameters++]=
1433    CbcOrClpParam("maxN!odes","Maximum number of nodes to do",
1434                  1,999999,MAXNODES);
1435  parameters[numberParameters-1].setLonghelp
1436    (
1437     "TODO"
1438     ); 
1439#endif
1440  parameters[numberParameters++]=
1441    CbcOrClpParam("min!imize","Set optimization direction to minimize",
1442                  MINIMIZE,299);
1443  parameters[numberParameters-1].setLonghelp
1444    (
1445     "The default is minimize - use 'maximize' for maximization.\n\
1446This should only be necessary if you have previously set maximization \
1447You can also use the parameters 'direction minimize'."
1448     );
1449#ifdef COIN_USE_CBC
1450  parameters[numberParameters++]=
1451    CbcOrClpParam("mixed!IntegerRoundingCuts","Whether to use Mixed Integer Rounding cuts",
1452                  "off",MIXEDCUTS);
1453  parameters[numberParameters-1].append("on");
1454  parameters[numberParameters-1].append("root");
1455  parameters[numberParameters-1].setLonghelp
1456    (
1457     "TODO"
1458     ); 
1459#endif
1460  parameters[numberParameters++]=
1461    CbcOrClpParam("mess!ages","Controls if Clpnnnn is printed",
1462                  "off",MESSAGES);
1463  parameters[numberParameters-1].append("on");
1464  parameters[numberParameters-1].setLonghelp
1465    ("The default for the Clp library is to put out messages such as:\n\
1466   Clp0005 2261  Objective 109.024 Primal infeas 944413 (758)\n\
1467but this program turns this off to make it look more friendly.  It can be useful\
1468 to turn them back on if you want to be able 'grep' for particular messages or if\
1469 you intend to override the behavior of a particular message."
1470     );
1471#ifdef COIN_USE_CBC
1472  parameters[numberParameters++]=
1473    CbcOrClpParam("miplib","Do some of miplib test set",
1474                  MIPLIB);
1475#endif
1476#ifdef COIN_USE_CLP
1477  parameters[numberParameters++]=
1478    CbcOrClpParam("netlib","Solve entire netlib test set",
1479                  NETLIB_EITHER);
1480  parameters[numberParameters-1].setLonghelp
1481    (
1482     "This exercises the unit test for clp and then solves the netlib test set using dual or primal.\
1483The user can set options before e.g. clp -presolve off -netlib"
1484     ); 
1485#ifdef REAL_BARRIER
1486  parameters[numberParameters++]=
1487    CbcOrClpParam("netlibB!arrier","Solve entire netlib test set with barrier",
1488                  NETLIB_BARRIER);
1489  parameters[numberParameters-1].setLonghelp
1490    (
1491     "This exercises the unit test for clp and then solves the netlib test set using barrier.\
1492The user can set options before e.g. clp -kkt on -netlib"
1493     ); 
1494#endif
1495  parameters[numberParameters++]=
1496    CbcOrClpParam("netlibD!ual","Solve entire netlib test set (dual)",
1497                  NETLIB_DUAL);
1498  parameters[numberParameters-1].setLonghelp
1499    (
1500     "This exercises the unit test for clp and then solves the netlib test set using dual.\
1501The user can set options before e.g. clp -presolve off -netlib"
1502     ); 
1503  parameters[numberParameters++]=
1504    CbcOrClpParam("netlibP!rimal","Solve entire netlib test set (primal)",
1505                  NETLIB_PRIMAL);
1506  parameters[numberParameters-1].setLonghelp
1507    (
1508     "This exercises the unit test for clp and then solves the netlib test set using primal.\
1509The user can set options before e.g. clp -presolve off -netlibp"
1510     ); 
1511  parameters[numberParameters++]=
1512    CbcOrClpParam("netlibT!une","Solve entire netlib test set with 'best' algorithm",
1513                  NETLIB_TUNE);
1514  parameters[numberParameters-1].setLonghelp
1515    (
1516     "This exercises the unit test for clp and then solves the netlib test set using whatever \
1517works best.  I know this is cheating but it also stresses the code better by doing a \
1518mixture of stuff.  The best algorithm was chosen on a Linux ThinkPad using native cholesky \
1519with University of Florida ordering."
1520     ); 
1521  parameters[numberParameters++]=
1522    CbcOrClpParam("network","Tries to make network matrix",
1523                  NETWORK,-1,false);
1524  parameters[numberParameters-1].setLonghelp
1525    (
1526     "Clp will go faster if the matrix can be converted to a network.  The matrix\
1527 operations may be a bit faster with more efficient storage, but the main advantage\
1528 comes from using a network factorization.  It will probably not be as fast as a \
1529specialized network code."
1530     ); 
1531  parameters[numberParameters++]=
1532    CbcOrClpParam("objective!Scale","Scale factor to apply to objective",
1533                  -1.0e20,1.0e20,OBJSCALE,false);
1534  parameters[numberParameters-1].setLonghelp
1535    (
1536     "If the objective function has some very large values, you may wish to scale them\
1537 internally by this amount.  It can also be set by autoscale.  It is applied after scaling"
1538     ); 
1539  parameters[numberParameters-1].setDoubleValue(1.0);
1540#endif
1541  parameters[numberParameters++]=
1542    CbcOrClpParam("output!Format","Which output format to use",
1543                  1,6,OUTPUTFORMAT);
1544  parameters[numberParameters-1].setLonghelp
1545    (
1546     "Normally export will be done using normal representation for numbers and two values\
1547 per line.  You may want to do just one per line (for grep or suchlike) and you may wish\
1548 to save with absolute accuracy using a coded version of the IEEE value. A value of 2 is normal.\
1549 otherwise odd values gives one value per line, even two.  Values 1,2 give normal format, 3,4\
1550 gives greater precision, while 5,6 give IEEE values.  When used for exporting a basis 1 does not save \
1551values, 2 saves values, 3 with greater accuracy and 4 in IEEE."
1552     ); 
1553#ifdef COIN_USE_CLP
1554  parameters[numberParameters++]=
1555    CbcOrClpParam("passP!resolve","How many passes in presolve",
1556                  -200,100,PRESOLVEPASS,false);
1557  parameters[numberParameters-1].setLonghelp
1558    (
1559     "Normally Presolve does 5 passes but you may want to do less to make it\
1560 more lightweight or do more if improvements are still being made.  As Presolve will return\
1561 if nothing is being taken out, then you should not need to use this fine tuning."
1562     ); 
1563  parameters[numberParameters++]=
1564    CbcOrClpParam("pertV!alue","Method of perturbation",
1565                  -5000,102,PERTVALUE,false);
1566  parameters[numberParameters++]=
1567    CbcOrClpParam("perturb!ation","Whether to perturb problem",
1568                  "on",PERTURBATION);
1569  parameters[numberParameters-1].append("off");
1570  parameters[numberParameters-1].setLonghelp
1571    (
1572     "Perturbation helps to stop cycling, but Clp uses other measures for this.\
1573  However large problems and especially ones with unit elements and unit rhs or costs\
1574 benefit from perturbation.  Normally Clp tries to be intelligent, but you can switch this off.\
1575  The Clp library has this off by default.  This program has it on."
1576     ); 
1577  parameters[numberParameters++]=
1578    CbcOrClpParam("PFI","Whether to use Product Form of Inverse in simplex",
1579                  "off",PFI,0,false);
1580  parameters[numberParameters-1].append("on");
1581  parameters[numberParameters-1].setLonghelp
1582    (
1583     "By default clp uses Forrest-Tomlin L-U update.  If you are masochistic you can switch it off."
1584     ); 
1585  parameters[numberParameters++]=
1586    CbcOrClpParam("plus!Minus","Tries to make +- 1 matrix",
1587                  PLUSMINUS,-1,false);
1588  parameters[numberParameters-1].setLonghelp
1589    (
1590     "Clp will go slightly faster if the matrix can be converted so that the elements are\
1591 not stored and are known to be unit.  The main advantage is memory use.  Clp may automatically\
1592 see if it can convert the problem so you should not need to use this."
1593     ); 
1594  parameters[numberParameters++]=
1595    CbcOrClpParam("preO!pt","Presolve options",
1596                  0,INT_MAX,PRESOLVEOPTIONS,false);
1597#endif
1598  parameters[numberParameters++]=
1599    CbcOrClpParam("presolve","Whether to presolve problem",
1600                  "on",PRESOLVE);
1601  parameters[numberParameters-1].append("off");
1602  parameters[numberParameters-1].append("more");
1603  parameters[numberParameters-1].append("file");
1604  parameters[numberParameters-1].setLonghelp
1605    (
1606     "Presolve analyzes the model to find such things as redundant equations, equations\
1607 which fix some variables, equations which can be transformed into bounds etc etc.  For the\
1608 initial solve of any problem this is worth doing unless you know that it will have no effect."
1609     ); 
1610#ifdef COIN_USE_CBC
1611  parameters[numberParameters++]=
1612    CbcOrClpParam("preprocess","Whether to use integer preprocessing",
1613                  "on",PREPROCESS);
1614  parameters[numberParameters-1].append("off");
1615  parameters[numberParameters-1].setLonghelp
1616    (
1617     "TODO"
1618     ); 
1619#endif
1620#ifdef COIN_USE_CLP
1621  parameters[numberParameters++]=
1622    CbcOrClpParam("primalP!ivot","Primal pivot choice algorithm",
1623                  "auto!matic",PRIMALPIVOT);
1624  parameters[numberParameters-1].append("exa!ct");
1625  parameters[numberParameters-1].append("dant!zig");
1626  parameters[numberParameters-1].append("part!ial");
1627  parameters[numberParameters-1].append("steep!est");
1628  parameters[numberParameters-1].append("change");
1629  parameters[numberParameters-1].append("sprint");
1630  parameters[numberParameters-1].setLonghelp
1631    (
1632     "Clp can use any pivot selection algorithm which the user codes as long as it\
1633 implements the features in the abstract pivot base class.  The Dantzig method is implemented\
1634 to show a simple method but its use is deprecated.  Exact devex is the method of choice and there\
1635 are two variants which keep all weights updated but only scan a subset each iteration.\
1636 Partial switches this on while change initially does dantzig until the factorization\
1637 becomes denser.  This is still a work in progress."
1638     ); 
1639  parameters[numberParameters++]=
1640    CbcOrClpParam("primalS!implex","Do primal simplex algorithm",
1641                  PRIMALSIMPLEX);
1642  parameters[numberParameters-1].setLonghelp
1643    (
1644     "This command solves the current model using the primal algorithm.\
1645  The default is to use exact devex.\
1646 The time and iterations may be affected by settings such as presolve, scaling, crash\
1647 and also by column selection  method, infeasibility weight and dual and primal tolerances."
1648     );
1649#endif
1650  parameters[numberParameters++]=
1651    CbcOrClpParam("primalT!olerance","For an optimal solution \
1652no primal infeasibility may exceed this value",
1653                  1.0e-20,1.0e12,PRIMALTOLERANCE);
1654  parameters[numberParameters-1].setLonghelp
1655    (
1656     "Normally the default tolerance is fine, but you may want to increase it a\
1657 bit if a primal run seems to be having a hard time"
1658     ); 
1659#ifdef COIN_USE_CLP
1660  parameters[numberParameters++]=
1661    CbcOrClpParam("primalW!eight","Initially algorithm acts as if it \
1662costs this much to be infeasible",
1663                  1.0e-20,1.0e20,PRIMALWEIGHT);
1664  parameters[numberParameters-1].setLonghelp
1665    (
1666     "The primal algorithm in Clp is a single phase algorithm as opposed to a two phase\
1667 algorithm where you first get feasible then optimal.  So Clp is minimizing this weight times\
1668 the sum of primal infeasibilities plus the true objective function (in minimization sense).\
1669  Too high a value may mean more iterations, while too low a bound means\
1670 the code may go all the way and then have to increase the weight in order to get feasible.\
1671  OSL had a heuristic to\
1672 adjust bounds, maybe we need that here."
1673     ); 
1674  parameters[numberParameters++]=
1675    CbcOrClpParam("printO!ptions","Print options",
1676                  0,INT_MAX,PRINTOPTIONS,false);
1677#endif
1678#ifdef COIN_USE_CBC
1679  parameters[numberParameters++]=
1680    CbcOrClpParam("probing!Cuts","Whether to use Probing cuts",
1681                  "off",PROBINGCUTS);
1682  parameters[numberParameters-1].append("on");
1683  parameters[numberParameters-1].append("root");
1684  parameters[numberParameters-1].setLonghelp
1685    (
1686     "TODO"
1687     ); 
1688#endif
1689  parameters[numberParameters++]=
1690    CbcOrClpParam("quit","Stops clp execution",
1691                  EXIT);
1692  parameters[numberParameters-1].setLonghelp
1693    (
1694     "This stops the execution of Clp, end, exit, quit and stop are synonyms"
1695     ); 
1696#ifdef COIN_USE_CLP
1697  parameters[numberParameters++]=
1698    CbcOrClpParam("reallyS!cale","Scales model in place",
1699                  REALLY_SCALE,false);
1700#endif
1701#ifdef COIN_USE_CBC
1702    parameters[numberParameters++]=
1703      CbcOrClpParam("reduce!AndSplitCuts","Whether to use Reduce-and-Split cuts",
1704              "off",REDSPLITCUTS);
1705    parameters[numberParameters-1].append("on");
1706    parameters[numberParameters-1].append("root");
1707  parameters[numberParameters-1].setLonghelp
1708    (
1709     "TODO"
1710     ); 
1711#endif
1712#ifdef COIN_USE_CLP
1713  parameters[numberParameters++]=
1714    CbcOrClpParam("restore!Model","Restore model from binary file",
1715                  RESTORE);
1716  parameters[numberParameters-1].setLonghelp
1717    (
1718     "This reads data save by saveModel from the given file.  It will use the default\
1719 directory given by 'directory'.  A name of '$' will use the previous value for the name.  This\
1720 is initialized to 'default.prob'."
1721     ); 
1722  parameters[numberParameters++]=
1723    CbcOrClpParam("reverse","Reverses sign of objective",
1724                  REVERSE,false);
1725  parameters[numberParameters-1].setLonghelp
1726    (
1727     "Useful for testing if maximization works correctly"
1728     ); 
1729  parameters[numberParameters++]=
1730    CbcOrClpParam("rhs!Scale","Scale factor to apply to rhs and bounds",
1731                  -1.0e20,1.0e20,RHSSCALE,false);
1732  parameters[numberParameters-1].setLonghelp
1733    (
1734     "If the rhs or bounds have some very large meaningful values, you may wish to scale them\
1735 internally by this amount.  It can also be set by autoscale"
1736     ); 
1737  parameters[numberParameters-1].setDoubleValue(1.0);
1738#endif
1739#ifdef COIN_USE_CBC
1740  parameters[numberParameters++]=
1741    CbcOrClpParam("round!ingHeuristic","Whether to use Rounding heuristic",
1742                  "off",ROUNDING);
1743  parameters[numberParameters-1].append("on");
1744  parameters[numberParameters-1].setLonghelp
1745    (
1746     "TODO"
1747     ); 
1748#endif
1749  parameters[numberParameters++]=
1750    CbcOrClpParam("save!Model","Save model to binary file",
1751                  SAVE);
1752  parameters[numberParameters-1].setLonghelp
1753    (
1754     "This will save the problem to the given file name for future use\
1755 by restoreModel.  It will use the default\
1756 directory given by 'directory'.  A name of '$' will use the previous value for the name.  This\
1757 is initialized to 'default.prob'."
1758     ); 
1759  parameters[numberParameters++]=
1760    CbcOrClpParam("scal!ing","Whether to scale problem",
1761                  "off",SCALING);
1762  parameters[numberParameters-1].append("equi!librium");
1763  parameters[numberParameters-1].append("geo!metric");
1764  parameters[numberParameters-1].append("auto!matic");
1765  parameters[numberParameters-1].setLonghelp
1766    (
1767     "Scaling can help in solving problems which might otherwise fail because of lack of\
1768 accuracy.  It can also reduce the number of iterations.  It is not applied if the range\
1769 of elements is small.  When unscaled it is possible that there may be small primal and/or\
1770 infeasibilities."
1771     ); 
1772  parameters[numberParameters-1].setCurrentOption(3); // say auto
1773#ifndef COIN_USE_CBC
1774  parameters[numberParameters++]=
1775    CbcOrClpParam("sec!onds","maximum seconds",
1776                  -1.0,1.0e12,TIMELIMIT);
1777  parameters[numberParameters-1].setLonghelp
1778    (
1779     "After this many seconds clp will act as if maximum iterations had been reached.\
1780  In this program it is really only useful for testing but the library function\n\
1781      \tsetMaximumSeconds(value)\n can be useful."
1782     ); 
1783#endif
1784#ifdef COIN_USE_CLP
1785  parameters[numberParameters++]=
1786    CbcOrClpParam("slp!Value","Number of slp passes before primal",
1787                  -1,50000,SLPVALUE,false);
1788#endif
1789  parameters[numberParameters++]=
1790    CbcOrClpParam("solu!tion","Prints solution to file",
1791                  SOLUTION);
1792  parameters[numberParameters-1].setLonghelp
1793    (
1794     "This will write a primitive solution file to the given file name.  It will use the default\
1795 directory given by 'directory'.  A name of '$' will use the previous value for the name.  This\
1796 is initialized to 'stdout'."
1797     ); 
1798#ifdef COIN_USE_CBC
1799#ifdef COIN_USE_CLP
1800  parameters[numberParameters++]=
1801    CbcOrClpParam("solv!e","Solve problem",
1802                  BAB);
1803  parameters[numberParameters-1].setLonghelp
1804    (
1805     "If there are no integer variables then this just solves LP.  If there are integer variables \
1806this does branch and cut.  Far too many parameters apply to give a full description here.  \
1807the main thing is to think about which cuts to apply.  .. expand ..."
1808     ); 
1809  parameters[numberParameters++]=
1810    CbcOrClpParam("slog!Level","Level of detail in Solver output",
1811                  -1,63,SOLVERLOGLEVEL);
1812  parameters[numberParameters-1].setLonghelp
1813    (
1814     "If 0 then there should be no output in normal circumstances.  1 is probably the best\
1815 value for most uses, while 2 and 3 give more information."
1816     ); 
1817#endif
1818#endif
1819#ifdef COIN_USE_CLP
1820  parameters[numberParameters++]=
1821    CbcOrClpParam("spars!eFactor","Whether factorization treated as sparse",
1822                  "on",SPARSEFACTOR,0,false);
1823  parameters[numberParameters-1].append("off");
1824  parameters[numberParameters++]=
1825    CbcOrClpParam("special!Options","Dubious options for Simplex - see ClpSimplex.hpp",
1826                  0,INT_MAX,SPECIALOPTIONS,false);
1827  parameters[numberParameters++]=
1828    CbcOrClpParam("sprint!Crash","Whether to try sprint crash",
1829                  -1,500,SPRINT);
1830  parameters[numberParameters-1].setLonghelp
1831    (
1832     "For long and thin problems this program may solve a series of small problems\
1833 created by taking a subset of the columns.  I introduced the idea as 'Sprint' after\
1834 an LP code of that name of the 60's which tried the same tactic (not totally successfully).\
1835  Cplex calls it 'sifting'.  -1 is automatic choice, 0 is off, n is number of passes"
1836     ); 
1837  parameters[numberParameters++]=
1838    CbcOrClpParam("stat!istics","Print some statistics",
1839                  STATISTICS);
1840  parameters[numberParameters-1].setLonghelp
1841    (
1842     "This command prints crude statistics for the current model.\
1843 If log level >1 then more is printed.\
1844 These are for presolved model if presolve on (and unscaled)."
1845     );
1846#endif
1847  CbcOrClpParam("stdin","From stdin",
1848                STDIN,-1,false);
1849  parameters[numberParameters++]=
1850    CbcOrClpParam("stop","Stops clp execution",
1851                  EXIT);
1852  parameters[numberParameters-1].setLonghelp
1853    (
1854     "This stops the execution of Clp, end, exit, quit and stop are synonyms"
1855     ); 
1856#ifdef COIN_USE_CBC
1857  parameters[numberParameters++]=
1858    CbcOrClpParam("strong!Branching","Number of variables to look at in strong branching",
1859                  0,999999,STRONGBRANCHING);
1860  parameters[numberParameters-1].setLonghelp
1861    (
1862     "TODO"
1863     ); 
1864#endif
1865#ifdef COIN_USE_CLP
1866  parameters[numberParameters++]=
1867    CbcOrClpParam("subs!titution","How long a column to substitute for in presolve",
1868                  0,10000,SUBSTITUTION,false);
1869  parameters[numberParameters-1].setLonghelp
1870    (
1871     "Normally Presolve gets rid of 'free' variables when there are no more than 3 \
1872 variables in column.  If you increase this the number of rows may decrease but number of \
1873 elements may increase."
1874     ); 
1875#endif
1876#ifdef COIN_USE_CBC
1877  parameters[numberParameters++]=
1878    CbcOrClpParam("tighten!Factor","Tighten bounds using this times largest \
1879activity at continuous solution",
1880                  1.0,1.0e20,TIGHTENFACTOR,false);
1881  parameters[numberParameters++] =
1882    CbcOrClpParam("time!Limit","Set a time limit for solving this problem",
1883                  -1.0,(double)(60*60*24*365*10),TIMELIMIT) ;
1884  parameters[numberParameters-1].setLonghelp
1885    (
1886     "TODO"
1887     ); 
1888#endif
1889#ifdef COIN_USE_CLP
1890  parameters[numberParameters++]=
1891    CbcOrClpParam("tightLP","Poor person's preSolve for now",
1892                  TIGHTEN,-1,false);
1893#endif
1894#ifdef COIN_USE_CBC
1895  parameters[numberParameters++]=
1896    CbcOrClpParam("trust!PseudoCosts","Number of branches before we trust pseudocosts",
1897                  0,999999,NUMBERBEFORE);
1898  parameters[numberParameters-1].setLonghelp
1899    (
1900     "TODO"
1901     ); 
1902#endif
1903#ifdef COIN_USE_CBC
1904  parameters[numberParameters++]=
1905    CbcOrClpParam("two!MirCuts","Whether to use Two phase Mixed Integer Rounding cuts",
1906                  "off",TWOMIRCUTS);
1907  parameters[numberParameters-1].append("on");
1908  parameters[numberParameters-1].append("root");
1909  parameters[numberParameters-1].setLonghelp
1910    (
1911     "TODO"
1912     ); 
1913#endif
1914  parameters[numberParameters++]=
1915    CbcOrClpParam("unitTest","Do unit test",
1916                  UNITTEST);
1917  parameters[numberParameters-1].setLonghelp
1918    (
1919     "This exercises the unit test for clp"
1920     ); 
1921  assert(numberParameters<CBCMAXPARAMETERS);
1922}
1923// Given a parameter type - returns its number in list
1924int whichParam (CbcOrClpParameterType name, 
1925                int numberParameters, CbcOrClpParam *const parameters)
1926{
1927  int i;
1928  for (i=0;i<numberParameters;i++) {
1929    if (parameters[i].type()==name)
1930      break;
1931  }
1932  assert (i<numberParameters);
1933  return i;
1934}
Note: See TracBrowser for help on using the repository browser.