source: stable/1.15/Clp/src/CbcOrClpParam.cpp @ 1989

Last change on this file since 1989 was 1989, checked in by forrest, 5 years ago

Minor stability fixes and an option to allow perturbation after presolve

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 165.9 KB
Line 
1/* $Id: CbcOrClpParam.cpp 1989 2013-11-11 17:27:32Z forrest $ */
2// Copyright (C) 2002, International Business Machines
3// Corporation and others.  All Rights Reserved.
4// This code is licensed under the terms of the Eclipse Public License (EPL).
5
6#include "CoinPragma.hpp"
7#include "CoinTime.hpp"
8#include "CbcOrClpParam.hpp"
9
10#include <string>
11#include <iostream>
12#include <cassert>
13
14#ifdef COIN_HAS_CBC
15#ifdef COIN_HAS_CLP
16#include "OsiClpSolverInterface.hpp"
17#include "ClpSimplex.hpp"
18#endif
19#include "CbcModel.hpp"
20#endif
21#include "CoinHelperFunctions.hpp"
22#ifdef COIN_HAS_CLP
23#include "ClpSimplex.hpp"
24#include "ClpFactorization.hpp"
25#endif
26#ifdef COIN_HAS_READLINE
27#include <readline/readline.h>
28#include <readline/history.h>
29#endif
30#ifdef COIN_HAS_CBC
31// from CoinSolve
32static char coin_prompt[] = "Coin:";
33#else
34static char coin_prompt[] = "Clp:";
35#endif
36#ifdef CLP_CILK
37#ifndef CBC_THREAD
38#define CBC_THREAD
39#endif
40#endif
41#if defined(COIN_HAS_WSMP) && ! defined(USE_EKKWSSMP)
42#ifndef CBC_THREAD
43#define CBC_THREAD
44#endif
45#endif
46#include "ClpConfig.h"
47#ifdef CLP_HAS_ABC
48#include "AbcCommon.hpp"
49#endif
50static bool doPrinting = true;
51std::string afterEquals = "";
52static char printArray[200];
53void setCbcOrClpPrinting(bool yesNo)
54{
55     doPrinting = yesNo;
56}
57//#############################################################################
58// Constructors / Destructor / Assignment
59//#############################################################################
60
61//-------------------------------------------------------------------
62// Default Constructor
63//-------------------------------------------------------------------
64CbcOrClpParam::CbcOrClpParam ()
65     : type_(CBC_PARAM_NOTUSED_INVALID),
66       lowerDoubleValue_(0.0),
67       upperDoubleValue_(0.0),
68       lowerIntValue_(0),
69       upperIntValue_(0),
70       lengthName_(0),
71       lengthMatch_(0),
72       definedKeyWords_(),
73       name_(),
74       shortHelp_(),
75       longHelp_(),
76       action_(CBC_PARAM_NOTUSED_INVALID),
77       currentKeyWord_(-1),
78       display_(0),
79       intValue_(-1),
80       doubleValue_(-1.0),
81       stringValue_(""),
82       whereUsed_(7)
83{
84}
85// Other constructors
86CbcOrClpParam::CbcOrClpParam (std::string name, std::string help,
87                              double lower, double upper, CbcOrClpParameterType type,
88                              int display)
89     : type_(type),
90       lowerIntValue_(0),
91       upperIntValue_(0),
92       definedKeyWords_(),
93       name_(name),
94       shortHelp_(help),
95       longHelp_(),
96       action_(type),
97       currentKeyWord_(-1),
98       display_(display),
99       intValue_(-1),
100       doubleValue_(-1.0),
101       stringValue_(""),
102       whereUsed_(7)
103{
104     lowerDoubleValue_ = lower;
105     upperDoubleValue_ = upper;
106     gutsOfConstructor();
107}
108CbcOrClpParam::CbcOrClpParam (std::string name, std::string help,
109                              int lower, int upper, CbcOrClpParameterType type,
110                              int display)
111     : type_(type),
112       lowerDoubleValue_(0.0),
113       upperDoubleValue_(0.0),
114       definedKeyWords_(),
115       name_(name),
116       shortHelp_(help),
117       longHelp_(),
118       action_(type),
119       currentKeyWord_(-1),
120       display_(display),
121       intValue_(-1),
122       doubleValue_(-1.0),
123       stringValue_(""),
124       whereUsed_(7)
125{
126     gutsOfConstructor();
127     lowerIntValue_ = lower;
128     upperIntValue_ = upper;
129}
130// Other strings will be added by append
131CbcOrClpParam::CbcOrClpParam (std::string name, std::string help,
132                              std::string firstValue,
133                              CbcOrClpParameterType type, int whereUsed,
134                              int display)
135     : type_(type),
136       lowerDoubleValue_(0.0),
137       upperDoubleValue_(0.0),
138       lowerIntValue_(0),
139       upperIntValue_(0),
140       definedKeyWords_(),
141       name_(name),
142       shortHelp_(help),
143       longHelp_(),
144       action_(type),
145       currentKeyWord_(0),
146       display_(display),
147       intValue_(-1),
148       doubleValue_(-1.0),
149       stringValue_(""),
150       whereUsed_(whereUsed)
151{
152     gutsOfConstructor();
153     definedKeyWords_.push_back(firstValue);
154}
155// Action
156CbcOrClpParam::CbcOrClpParam (std::string name, std::string help,
157                              CbcOrClpParameterType type, int whereUsed,
158                              int display)
159     : type_(type),
160       lowerDoubleValue_(0.0),
161       upperDoubleValue_(0.0),
162       lowerIntValue_(0),
163       upperIntValue_(0),
164       definedKeyWords_(),
165       name_(name),
166       shortHelp_(help),
167       longHelp_(),
168       action_(type),
169       currentKeyWord_(-1),
170       display_(display),
171       intValue_(-1),
172       doubleValue_(-1.0),
173       stringValue_("")
174{
175     whereUsed_ = whereUsed;
176     gutsOfConstructor();
177}
178
179//-------------------------------------------------------------------
180// Copy constructor
181//-------------------------------------------------------------------
182CbcOrClpParam::CbcOrClpParam (const CbcOrClpParam & rhs)
183{
184     type_ = rhs.type_;
185     lowerDoubleValue_ = rhs.lowerDoubleValue_;
186     upperDoubleValue_ = rhs.upperDoubleValue_;
187     lowerIntValue_ = rhs.lowerIntValue_;
188     upperIntValue_ = rhs.upperIntValue_;
189     lengthName_ = rhs.lengthName_;
190     lengthMatch_ = rhs.lengthMatch_;
191     definedKeyWords_ = rhs.definedKeyWords_;
192     name_ = rhs.name_;
193     shortHelp_ = rhs.shortHelp_;
194     longHelp_ = rhs.longHelp_;
195     action_ = rhs.action_;
196     currentKeyWord_ = rhs.currentKeyWord_;
197     display_ = rhs.display_;
198     intValue_ = rhs.intValue_;
199     doubleValue_ = rhs.doubleValue_;
200     stringValue_ = rhs.stringValue_;
201     whereUsed_ = rhs.whereUsed_;
202}
203
204//-------------------------------------------------------------------
205// Destructor
206//-------------------------------------------------------------------
207CbcOrClpParam::~CbcOrClpParam ()
208{
209}
210
211//----------------------------------------------------------------
212// Assignment operator
213//-------------------------------------------------------------------
214CbcOrClpParam &
215CbcOrClpParam::operator=(const CbcOrClpParam & rhs)
216{
217     if (this != &rhs) {
218          type_ = rhs.type_;
219          lowerDoubleValue_ = rhs.lowerDoubleValue_;
220          upperDoubleValue_ = rhs.upperDoubleValue_;
221          lowerIntValue_ = rhs.lowerIntValue_;
222          upperIntValue_ = rhs.upperIntValue_;
223          lengthName_ = rhs.lengthName_;
224          lengthMatch_ = rhs.lengthMatch_;
225          definedKeyWords_ = rhs.definedKeyWords_;
226          name_ = rhs.name_;
227          shortHelp_ = rhs.shortHelp_;
228          longHelp_ = rhs.longHelp_;
229          action_ = rhs.action_;
230          currentKeyWord_ = rhs.currentKeyWord_;
231          display_ = rhs.display_;
232          intValue_ = rhs.intValue_;
233          doubleValue_ = rhs.doubleValue_;
234          stringValue_ = rhs.stringValue_;
235          whereUsed_ = rhs.whereUsed_;
236     }
237     return *this;
238}
239void
240CbcOrClpParam::gutsOfConstructor()
241{
242     std::string::size_type  shriekPos = name_.find('!');
243     lengthName_ = static_cast<unsigned int>(name_.length());
244     if ( shriekPos == std::string::npos ) {
245          //does not contain '!'
246          lengthMatch_ = lengthName_;
247     } else {
248          lengthMatch_ = static_cast<unsigned int>(shriekPos);
249          name_ = name_.substr(0, shriekPos) + name_.substr(shriekPos + 1);
250          lengthName_--;
251     }
252}
253// Returns length of name for printing
254int
255CbcOrClpParam::lengthMatchName (  ) const
256{
257     if (lengthName_ == lengthMatch_)
258          return lengthName_;
259     else
260          return lengthName_ + 2;
261}
262// Insert string (only valid for keywords)
263void
264CbcOrClpParam::append(std::string keyWord)
265{
266     definedKeyWords_.push_back(keyWord);
267}
268
269int
270CbcOrClpParam::matches (std::string input) const
271{
272     // look up strings to do more elegantly
273     if (input.length() > lengthName_) {
274          return 0;
275     } else {
276          unsigned int i;
277          for (i = 0; i < input.length(); i++) {
278               if (tolower(name_[i]) != tolower(input[i]))
279                    break;
280          }
281          if (i < input.length()) {
282               return 0;
283          } else if (i >= lengthMatch_) {
284               return 1;
285          } else {
286               // matched but too short
287               return 2;
288          }
289     }
290}
291// Returns name which could match
292std::string
293CbcOrClpParam::matchName (  ) const
294{
295     if (lengthMatch_ == lengthName_)
296          return name_;
297     else
298          return name_.substr(0, lengthMatch_) + "(" + name_.substr(lengthMatch_) + ")";
299}
300
301// Returns parameter option which matches (-1 if none)
302int
303CbcOrClpParam::parameterOption ( std::string check ) const
304{
305     int numberItems = static_cast<int>(definedKeyWords_.size());
306     if (!numberItems) {
307          return -1;
308     } else {
309          int whichItem = 0;
310          unsigned int it;
311          for (it = 0; it < definedKeyWords_.size(); it++) {
312               std::string thisOne = definedKeyWords_[it];
313               std::string::size_type  shriekPos = thisOne.find('!');
314               size_t length1 = thisOne.length();
315               size_t length2 = length1;
316               if ( shriekPos != std::string::npos ) {
317                    //contains '!'
318                    length2 = shriekPos;
319                    thisOne = thisOne.substr(0, shriekPos) +
320                              thisOne.substr(shriekPos + 1);
321                    length1 = thisOne.length();
322               }
323               if (check.length() <= length1 && length2 <= check.length()) {
324                    unsigned int i;
325                    for (i = 0; i < check.length(); i++) {
326                         if (tolower(thisOne[i]) != tolower(check[i]))
327                              break;
328                    }
329                    if (i < check.length()) {
330                         whichItem++;
331                    } else if (i >= length2) {
332                         break;
333                    }
334               } else {
335                    whichItem++;
336               }
337          }
338          if (whichItem < numberItems)
339               return whichItem;
340          else
341               return -1;
342     }
343}
344// Prints parameter options
345void
346CbcOrClpParam::printOptions (  ) const
347{
348     std::cout << "<Possible options for " << name_ << " are:";
349     unsigned int it;
350     for (it = 0; it < definedKeyWords_.size(); it++) {
351          std::string thisOne = definedKeyWords_[it];
352          std::string::size_type  shriekPos = thisOne.find('!');
353          if ( shriekPos != std::string::npos ) {
354               //contains '!'
355               thisOne = thisOne.substr(0, shriekPos) +
356                         "(" + thisOne.substr(shriekPos + 1) + ")";
357          }
358          std::cout << " " << thisOne;
359     }
360     assert (currentKeyWord_ >= 0 && currentKeyWord_ < static_cast<int>(definedKeyWords_.size()));
361     std::string current = definedKeyWords_[currentKeyWord_];
362     std::string::size_type  shriekPos = current.find('!');
363     if ( shriekPos != std::string::npos ) {
364          //contains '!'
365          current = current.substr(0, shriekPos) +
366                    "(" + current.substr(shriekPos + 1) + ")";
367     }
368     std::cout << ";\n\tcurrent  " << current << ">" << std::endl;
369}
370// Print action and string
371void
372CbcOrClpParam::printString() const
373{
374     if (name_ == "directory")
375          std::cout << "Current working directory is " << stringValue_ << std::endl;
376     else if (name_.substr(0, 6) == "printM")
377          std::cout << "Current value of printMask is " << stringValue_ << std::endl;
378     else
379          std::cout << "Current default (if $ as parameter) for " << name_
380                    << " is " << stringValue_ << std::endl;
381}
382void CoinReadPrintit(const char * input)
383{
384     int length = static_cast<int>(strlen(input));
385     char temp[101];
386     int i;
387     int n = 0;
388     for (i = 0; i < length; i++) {
389          if (input[i] == '\n') {
390               temp[n] = '\0';
391               std::cout << temp << std::endl;
392               n = 0;
393          } else if (n >= 65 && input[i] == ' ') {
394               temp[n] = '\0';
395               std::cout << temp << std::endl;
396               n = 0;
397          } else if (n || input[i] != ' ') {
398               temp[n++] = input[i];
399          }
400     }
401     if (n) {
402          temp[n] = '\0';
403          std::cout << temp << std::endl;
404     }
405}
406// Print Long help
407void
408CbcOrClpParam::printLongHelp() const
409{
410     if (type_ >= 1 && type_ < 400) {
411          CoinReadPrintit(longHelp_.c_str());
412          if (type_ < CLP_PARAM_INT_SOLVERLOGLEVEL) {
413               printf("<Range of values is %g to %g;\n\tcurrent %g>\n", lowerDoubleValue_, upperDoubleValue_, doubleValue_);
414               assert (upperDoubleValue_ > lowerDoubleValue_);
415          } else if (type_ < CLP_PARAM_STR_DIRECTION) {
416               printf("<Range of values is %d to %d;\n\tcurrent %d>\n", lowerIntValue_, upperIntValue_, intValue_);
417               assert (upperIntValue_ > lowerIntValue_);
418          } else if (type_ < CLP_PARAM_ACTION_DIRECTORY) {
419               printOptions();
420          }
421     }
422}
423#ifdef COIN_HAS_CBC
424int
425CbcOrClpParam::setDoubleParameter (OsiSolverInterface * model, double value)
426{
427     int returnCode;
428     setDoubleParameterWithMessage(model, value, returnCode);
429     if (doPrinting && strlen(printArray))
430          std::cout << printArray << std::endl;
431     return returnCode;
432}
433// Sets double parameter and returns printable string and error code
434const char *
435CbcOrClpParam::setDoubleParameterWithMessage ( OsiSolverInterface * model, double  value , int & returnCode)
436{
437     if (value < lowerDoubleValue_ || value > upperDoubleValue_) {
438          sprintf(printArray, "%g was provided for %s - valid range is %g to %g",
439                  value, name_.c_str(), lowerDoubleValue_, upperDoubleValue_);
440          std::cout << value << " was provided for " << name_ <<
441                    " - valid range is " << lowerDoubleValue_ << " to " <<
442                    upperDoubleValue_ << std::endl;
443          returnCode = 1;
444     } else {
445          double oldValue = doubleValue_;
446          doubleValue_ = value;
447          switch (type_) {
448          case CLP_PARAM_DBL_DUALTOLERANCE:
449               model->getDblParam(OsiDualTolerance, oldValue);
450               model->setDblParam(OsiDualTolerance, value);
451               break;
452          case CLP_PARAM_DBL_PRIMALTOLERANCE:
453               model->getDblParam(OsiPrimalTolerance, oldValue);
454               model->setDblParam(OsiPrimalTolerance, value);
455               break;
456          default:
457               break;
458          }
459          sprintf(printArray, "%s was changed from %g to %g",
460                  name_.c_str(), oldValue, value);
461          returnCode = 0;
462     }
463     return printArray;
464}
465#endif
466#ifdef COIN_HAS_CLP
467int
468CbcOrClpParam::setDoubleParameter (ClpSimplex * model, double value)
469{
470     int returnCode;
471     setDoubleParameterWithMessage(model, value, returnCode);
472     if (doPrinting && strlen(printArray))
473          std::cout << printArray << std::endl;
474     return returnCode;
475}
476// Sets int parameter and returns printable string and error code
477const char *
478CbcOrClpParam::setDoubleParameterWithMessage ( ClpSimplex * model, double value , int & returnCode)
479{
480     double oldValue = doubleValue_;
481     if (value < lowerDoubleValue_ || value > upperDoubleValue_) {
482          sprintf(printArray, "%g was provided for %s - valid range is %g to %g",
483                  value, name_.c_str(), lowerDoubleValue_, upperDoubleValue_);
484          returnCode = 1;
485     } else {
486          sprintf(printArray, "%s was changed from %g to %g",
487                  name_.c_str(), oldValue, value);
488          returnCode = 0;
489          doubleValue_ = value;
490          switch (type_) {
491          case CLP_PARAM_DBL_DUALTOLERANCE:
492               model->setDualTolerance(value);
493               break;
494          case CLP_PARAM_DBL_PRIMALTOLERANCE:
495               model->setPrimalTolerance(value);
496               break;
497          case CLP_PARAM_DBL_ZEROTOLERANCE:
498               model->setSmallElementValue(value);
499               break;
500          case CLP_PARAM_DBL_DUALBOUND:
501               model->setDualBound(value);
502               break;
503          case CLP_PARAM_DBL_PRIMALWEIGHT:
504               model->setInfeasibilityCost(value);
505               break;
506#ifndef COIN_HAS_CBC
507          case CLP_PARAM_DBL_TIMELIMIT:
508               model->setMaximumSeconds(value);
509               break;
510#endif
511          case CLP_PARAM_DBL_OBJSCALE:
512               model->setObjectiveScale(value);
513               break;
514          case CLP_PARAM_DBL_RHSSCALE:
515               model->setRhsScale(value);
516               break;
517          case CLP_PARAM_DBL_PRESOLVETOLERANCE:
518               model->setDblParam(ClpPresolveTolerance, value);
519               break;
520          default:
521               break;
522          }
523     }
524     return printArray;
525}
526double
527CbcOrClpParam::doubleParameter (ClpSimplex * model) const
528{
529     double value;
530     switch (type_) {
531#ifndef COIN_HAS_CBC
532     case CLP_PARAM_DBL_DUALTOLERANCE:
533          value = model->dualTolerance();
534          break;
535     case CLP_PARAM_DBL_PRIMALTOLERANCE:
536          value = model->primalTolerance();
537          break;
538#endif
539     case CLP_PARAM_DBL_ZEROTOLERANCE:
540          value = model->getSmallElementValue();
541          break;
542     case CLP_PARAM_DBL_DUALBOUND:
543          value = model->dualBound();
544          break;
545     case CLP_PARAM_DBL_PRIMALWEIGHT:
546          value = model->infeasibilityCost();
547          break;
548#ifndef COIN_HAS_CBC
549     case CLP_PARAM_DBL_TIMELIMIT:
550          value = model->maximumSeconds();
551          break;
552#endif
553     case CLP_PARAM_DBL_OBJSCALE:
554          value = model->objectiveScale();
555          break;
556     case CLP_PARAM_DBL_RHSSCALE:
557          value = model->rhsScale();
558          break;
559     default:
560          value = doubleValue_;
561          break;
562     }
563     return value;
564}
565int
566CbcOrClpParam::setIntParameter (ClpSimplex * model, int value)
567{
568     int returnCode;
569     setIntParameterWithMessage(model, value, returnCode);
570     if (doPrinting && strlen(printArray))
571          std::cout << printArray << std::endl;
572     return returnCode;
573}
574// Sets int parameter and returns printable string and error code
575const char *
576CbcOrClpParam::setIntParameterWithMessage ( ClpSimplex * model, int value , int & returnCode)
577{
578     int oldValue = intValue_;
579     if (value < lowerIntValue_ || value > upperIntValue_) {
580          sprintf(printArray, "%d was provided for %s - valid range is %d to %d",
581                  value, name_.c_str(), lowerIntValue_, upperIntValue_);
582          returnCode = 1;
583     } else {
584          intValue_ = value;
585          sprintf(printArray, "%s was changed from %d to %d",
586                  name_.c_str(), oldValue, value);
587          returnCode = 0;
588          switch (type_) {
589          case CLP_PARAM_INT_SOLVERLOGLEVEL:
590               model->setLogLevel(value);
591               if (value > 2)
592                    model->factorization()->messageLevel(8);
593               else
594                    model->factorization()->messageLevel(0);
595               break;
596          case CLP_PARAM_INT_MAXFACTOR:
597               model->factorization()->maximumPivots(value);
598               break;
599          case CLP_PARAM_INT_PERTVALUE:
600               model->setPerturbation(value);
601               break;
602          case CLP_PARAM_INT_MAXITERATION:
603               model->setMaximumIterations(value);
604               break;
605          case CLP_PARAM_INT_SPECIALOPTIONS:
606               model->setSpecialOptions(value);
607               break;
608          case CLP_PARAM_INT_RANDOMSEED:
609            {
610              if (value==0) {
611                double time = fabs(CoinGetTimeOfDay());
612                while (time>=COIN_INT_MAX)
613                  time *= 0.5;
614                value = static_cast<int>(time);
615                sprintf(printArray, "using time of day %s was changed from %d to %d",
616                  name_.c_str(), oldValue, value);
617              }
618              model->setRandomSeed(value);
619            }
620               break;
621          case CLP_PARAM_INT_MORESPECIALOPTIONS:
622               model->setMoreSpecialOptions(value);
623               break;
624#ifndef COIN_HAS_CBC
625#ifdef CBC_THREAD
626          case CBC_PARAM_INT_THREADS:
627               model->setNumberThreads(value);
628               break;
629#endif
630#endif
631          default:
632               break;
633          }
634     }
635     return printArray;
636}
637int
638CbcOrClpParam::intParameter (ClpSimplex * model) const
639{
640     int value;
641     switch (type_) {
642#ifndef COIN_HAS_CBC
643     case CLP_PARAM_INT_SOLVERLOGLEVEL:
644          value = model->logLevel();
645          break;
646#endif
647     case CLP_PARAM_INT_MAXFACTOR:
648          value = model->factorization()->maximumPivots();
649          break;
650          break;
651     case CLP_PARAM_INT_PERTVALUE:
652          value = model->perturbation();
653          break;
654     case CLP_PARAM_INT_MAXITERATION:
655          value = model->maximumIterations();
656          break;
657     case CLP_PARAM_INT_SPECIALOPTIONS:
658          value = model->specialOptions();
659          break;
660     case CLP_PARAM_INT_RANDOMSEED:
661          value = model->randomNumberGenerator()->getSeed();
662          break;
663     case CLP_PARAM_INT_MORESPECIALOPTIONS:
664          value = model->moreSpecialOptions();
665          break;
666#ifndef COIN_HAS_CBC
667#ifdef CBC_THREAD
668     case CBC_PARAM_INT_THREADS:
669          value = model->numberThreads();
670          break;
671#endif
672#endif
673     default:
674          value = intValue_;
675          break;
676     }
677     return value;
678}
679#endif
680int
681CbcOrClpParam::checkDoubleParameter (double value) const
682{
683     if (value < lowerDoubleValue_ || value > upperDoubleValue_) {
684          std::cout << value << " was provided for " << name_ <<
685                    " - valid range is " << lowerDoubleValue_ << " to " <<
686                    upperDoubleValue_ << std::endl;
687          return 1;
688     } else {
689          return 0;
690     }
691}
692#ifdef COIN_HAS_CBC
693double
694CbcOrClpParam::doubleParameter (OsiSolverInterface *
695#ifndef NDEBUG
696                                model
697#endif
698                               ) const
699{
700     double value = 0.0;
701     switch (type_) {
702     case CLP_PARAM_DBL_DUALTOLERANCE:
703          assert(model->getDblParam(OsiDualTolerance, value));
704          break;
705     case CLP_PARAM_DBL_PRIMALTOLERANCE:
706          assert(model->getDblParam(OsiPrimalTolerance, value));
707          break;
708     default:
709          return doubleValue_;
710          break;
711     }
712     return value;
713}
714int
715CbcOrClpParam::setIntParameter (OsiSolverInterface * model, int value)
716{
717     int returnCode;
718     setIntParameterWithMessage(model, value, returnCode);
719     if (doPrinting && strlen(printArray))
720          std::cout << printArray << std::endl;
721     return returnCode;
722}
723// Sets int parameter and returns printable string and error code
724const char *
725CbcOrClpParam::setIntParameterWithMessage ( OsiSolverInterface * model, int  value , int & returnCode)
726{
727     if (value < lowerIntValue_ || value > upperIntValue_) {
728          sprintf(printArray, "%d was provided for %s - valid range is %d to %d",
729                  value, name_.c_str(), lowerIntValue_, upperIntValue_);
730          returnCode = 1;
731     } else {
732          int oldValue = intValue_;
733          intValue_ = oldValue;
734          switch (type_) {
735          case CLP_PARAM_INT_SOLVERLOGLEVEL:
736               model->messageHandler()->setLogLevel(value);
737               break;
738          default:
739               break;
740          }
741          sprintf(printArray, "%s was changed from %d to %d",
742                  name_.c_str(), oldValue, value);
743          returnCode = 0;
744     }
745     return printArray;
746}
747int
748CbcOrClpParam::intParameter (OsiSolverInterface * model) const
749{
750     int value = 0;
751     switch (type_) {
752     case CLP_PARAM_INT_SOLVERLOGLEVEL:
753          value = model->messageHandler()->logLevel();
754          break;
755     default:
756          value = intValue_;
757          break;
758     }
759     return value;
760}
761int
762CbcOrClpParam::setDoubleParameter (CbcModel &model, double value)
763{
764     int returnCode;
765     setDoubleParameterWithMessage(model, value, returnCode);
766     if (doPrinting && strlen(printArray))
767          std::cout << printArray << std::endl;
768     return returnCode;
769}
770// Sets double parameter and returns printable string and error code
771const char *
772CbcOrClpParam::setDoubleParameterWithMessage ( CbcModel & model, double  value , int & returnCode)
773{
774     if (value < lowerDoubleValue_ || value > upperDoubleValue_) {
775          sprintf(printArray, "%g was provided for %s - valid range is %g to %g",
776                  value, name_.c_str(), lowerDoubleValue_, upperDoubleValue_);
777          returnCode = 1;
778     } else {
779          double oldValue = doubleValue_;
780          doubleValue_ = value;
781          switch (type_) {
782          case CBC_PARAM_DBL_INFEASIBILITYWEIGHT:
783               oldValue = model.getDblParam(CbcModel::CbcInfeasibilityWeight);
784               model.setDblParam(CbcModel::CbcInfeasibilityWeight, value);
785               break;
786          case CBC_PARAM_DBL_INTEGERTOLERANCE:
787               oldValue = model.getDblParam(CbcModel::CbcIntegerTolerance);
788               model.setDblParam(CbcModel::CbcIntegerTolerance, value);
789               break;
790          case CBC_PARAM_DBL_INCREMENT:
791               oldValue = model.getDblParam(CbcModel::CbcCutoffIncrement);
792               model.setDblParam(CbcModel::CbcCutoffIncrement, value);
793          case CBC_PARAM_DBL_ALLOWABLEGAP:
794               oldValue = model.getDblParam(CbcModel::CbcAllowableGap);
795               model.setDblParam(CbcModel::CbcAllowableGap, value);
796               break;
797          case CBC_PARAM_DBL_GAPRATIO:
798               oldValue = model.getDblParam(CbcModel::CbcAllowableFractionGap);
799               model.setDblParam(CbcModel::CbcAllowableFractionGap, value);
800               break;
801          case CBC_PARAM_DBL_CUTOFF:
802               oldValue = model.getCutoff();
803               model.setCutoff(value);
804               break;
805          case CBC_PARAM_DBL_TIMELIMIT_BAB:
806               oldValue = model.getDblParam(CbcModel::CbcMaximumSeconds) ;
807               {
808                    //OsiClpSolverInterface * clpSolver = dynamic_cast< OsiClpSolverInterface*> (model.solver());
809                    //ClpSimplex * lpSolver = clpSolver->getModelPtr();
810                    //lpSolver->setMaximumSeconds(value);
811                    model.setDblParam(CbcModel::CbcMaximumSeconds, value) ;
812               }
813               break ;
814          case CLP_PARAM_DBL_DUALTOLERANCE:
815          case CLP_PARAM_DBL_PRIMALTOLERANCE:
816               setDoubleParameter(model.solver(), value);
817               return 0; // to avoid message
818          default:
819               break;
820          }
821          sprintf(printArray, "%s was changed from %g to %g",
822                  name_.c_str(), oldValue, value);
823          returnCode = 0;
824     }
825     return printArray;
826}
827double
828CbcOrClpParam::doubleParameter (CbcModel &model) const
829{
830     double value;
831     switch (type_) {
832     case CBC_PARAM_DBL_INFEASIBILITYWEIGHT:
833          value = model.getDblParam(CbcModel::CbcInfeasibilityWeight);
834          break;
835     case CBC_PARAM_DBL_INTEGERTOLERANCE:
836          value = model.getDblParam(CbcModel::CbcIntegerTolerance);
837          break;
838     case CBC_PARAM_DBL_INCREMENT:
839          value = model.getDblParam(CbcModel::CbcCutoffIncrement);
840          break;
841     case CBC_PARAM_DBL_ALLOWABLEGAP:
842          value = model.getDblParam(CbcModel::CbcAllowableGap);
843          break;
844     case CBC_PARAM_DBL_GAPRATIO:
845          value = model.getDblParam(CbcModel::CbcAllowableFractionGap);
846          break;
847     case CBC_PARAM_DBL_CUTOFF:
848          value = model.getCutoff();
849          break;
850     case CBC_PARAM_DBL_TIMELIMIT_BAB:
851          value = model.getDblParam(CbcModel::CbcMaximumSeconds) ;
852          break ;
853     case CLP_PARAM_DBL_DUALTOLERANCE:
854     case CLP_PARAM_DBL_PRIMALTOLERANCE:
855          value = doubleParameter(model.solver());
856          break;
857     default:
858          value = doubleValue_;
859          break;
860     }
861     return value;
862}
863int
864CbcOrClpParam::setIntParameter (CbcModel &model, int value)
865{
866     int returnCode;
867     setIntParameterWithMessage(model, value, returnCode);
868     if (doPrinting && strlen(printArray))
869          std::cout << printArray << std::endl;
870     return returnCode;
871}
872// Sets int parameter and returns printable string and error code
873const char *
874CbcOrClpParam::setIntParameterWithMessage ( CbcModel & model, int value , int & returnCode)
875{
876     if (value < lowerIntValue_ || value > upperIntValue_) {
877          sprintf(printArray, "%d was provided for %s - valid range is %d to %d",
878                  value, name_.c_str(), lowerIntValue_, upperIntValue_);
879          returnCode = 1;
880     } else {
881          int oldValue = intValue_;
882          intValue_ = value;
883          switch (type_) {
884          case CLP_PARAM_INT_LOGLEVEL:
885               oldValue = model.messageHandler()->logLevel();
886               model.messageHandler()->setLogLevel(CoinAbs(value));
887               break;
888          case CLP_PARAM_INT_SOLVERLOGLEVEL:
889               oldValue = model.solver()->messageHandler()->logLevel();
890               model.solver()->messageHandler()->setLogLevel(value);
891               break;
892          case CBC_PARAM_INT_MAXNODES:
893               oldValue = model.getIntParam(CbcModel::CbcMaxNumNode);
894               model.setIntParam(CbcModel::CbcMaxNumNode, value);
895               break;
896          case CBC_PARAM_INT_MAXSOLS:
897               oldValue = model.getIntParam(CbcModel::CbcMaxNumSol);
898               model.setIntParam(CbcModel::CbcMaxNumSol, value);
899               break;
900          case CBC_PARAM_INT_MAXSAVEDSOLS:
901               oldValue = model.maximumSavedSolutions();
902               model.setMaximumSavedSolutions(value);
903               break;
904          case CBC_PARAM_INT_STRONGBRANCHING:
905               oldValue = model.numberStrong();
906               model.setNumberStrong(value);
907               break;
908          case CBC_PARAM_INT_NUMBERBEFORE:
909               oldValue = model.numberBeforeTrust();
910               model.setNumberBeforeTrust(value);
911               break;
912          case CBC_PARAM_INT_NUMBERANALYZE:
913               oldValue = model.numberAnalyzeIterations();
914               model.setNumberAnalyzeIterations(value);
915               break;
916          case CBC_PARAM_INT_CUTPASSINTREE:
917               oldValue = model.getMaximumCutPasses();
918               model.setMaximumCutPasses(value);
919               break;
920          case CBC_PARAM_INT_CUTPASS:
921               oldValue = model.getMaximumCutPassesAtRoot();
922               model.setMaximumCutPassesAtRoot(value);
923               break;
924#ifdef COIN_HAS_CBC
925#ifdef CBC_THREAD
926          case CBC_PARAM_INT_THREADS:
927               oldValue = model.getNumberThreads();
928               model.setNumberThreads(value);
929               break;
930#endif
931          case CBC_PARAM_INT_RANDOMSEED:
932               oldValue = model.getRandomSeed();
933               model.setRandomSeed(value);
934               break;
935#endif
936          default:
937               break;
938          }
939          sprintf(printArray, "%s was changed from %d to %d",
940                  name_.c_str(), oldValue, value);
941          returnCode = 0;
942     }
943     return printArray;
944}
945int
946CbcOrClpParam::intParameter (CbcModel &model) const
947{
948     int value;
949     switch (type_) {
950     case CLP_PARAM_INT_LOGLEVEL:
951          value = model.messageHandler()->logLevel();
952          break;
953     case CLP_PARAM_INT_SOLVERLOGLEVEL:
954          value = model.solver()->messageHandler()->logLevel();
955          break;
956     case CBC_PARAM_INT_MAXNODES:
957          value = model.getIntParam(CbcModel::CbcMaxNumNode);
958          break;
959     case CBC_PARAM_INT_MAXSOLS:
960          value = model.getIntParam(CbcModel::CbcMaxNumSol);
961          break;
962     case CBC_PARAM_INT_MAXSAVEDSOLS:
963          value = model.maximumSavedSolutions();
964          break;
965     case CBC_PARAM_INT_STRONGBRANCHING:
966          value = model.numberStrong();
967          break;
968     case CBC_PARAM_INT_NUMBERBEFORE:
969          value = model.numberBeforeTrust();
970          break;
971     case CBC_PARAM_INT_NUMBERANALYZE:
972          value = model.numberAnalyzeIterations();
973          break;
974     case CBC_PARAM_INT_CUTPASSINTREE:
975          value = model.getMaximumCutPasses();
976          break;
977     case CBC_PARAM_INT_CUTPASS:
978          value = model.getMaximumCutPassesAtRoot();
979          break;
980#ifdef COIN_HAS_CBC
981#ifdef CBC_THREAD
982     case CBC_PARAM_INT_THREADS:
983          value = model.getNumberThreads();
984#endif
985     case CBC_PARAM_INT_RANDOMSEED:
986          value = model.getRandomSeed();
987          break;
988#endif
989     default:
990          value = intValue_;
991          break;
992     }
993     return value;
994}
995#endif
996// Sets current parameter option using string
997void
998CbcOrClpParam::setCurrentOption ( const std::string value )
999{
1000     int action = parameterOption(value);
1001     if (action >= 0)
1002          currentKeyWord_ = action;
1003}
1004// Sets current parameter option
1005void
1006CbcOrClpParam::setCurrentOption ( int value , bool printIt)
1007{
1008     if (printIt && value != currentKeyWord_)
1009          std::cout << "Option for " << name_ << " changed from "
1010                    << definedKeyWords_[currentKeyWord_] << " to "
1011                    << definedKeyWords_[value] << std::endl;
1012
1013     currentKeyWord_ = value;
1014}
1015// Sets current parameter option and returns printable string
1016const char *
1017CbcOrClpParam::setCurrentOptionWithMessage ( int value )
1018{
1019     if (value != currentKeyWord_) {
1020          sprintf(printArray, "Option for %s changed from %s to %s",
1021                  name_.c_str(), definedKeyWords_[currentKeyWord_].c_str(),
1022                  definedKeyWords_[value].c_str());
1023
1024          currentKeyWord_ = value;
1025     } else {
1026          printArray[0] = '\0';
1027     }
1028     return printArray;
1029}
1030void
1031CbcOrClpParam::setIntValue ( int value )
1032{
1033     if (value < lowerIntValue_ || value > upperIntValue_) {
1034          std::cout << value << " was provided for " << name_ <<
1035                    " - valid range is " << lowerIntValue_ << " to " <<
1036                    upperIntValue_ << std::endl;
1037     } else {
1038          intValue_ = value;
1039     }
1040}
1041void
1042CbcOrClpParam::setDoubleValue ( double value )
1043{
1044     if (value < lowerDoubleValue_ || value > upperDoubleValue_) {
1045          std::cout << value << " was provided for " << name_ <<
1046                    " - valid range is " << lowerDoubleValue_ << " to " <<
1047                    upperDoubleValue_ << std::endl;
1048     } else {
1049          doubleValue_ = value;
1050     }
1051}
1052void
1053CbcOrClpParam::setStringValue ( std::string value )
1054{
1055     stringValue_ = value;
1056}
1057static char line[1000];
1058static char * where = NULL;
1059extern int CbcOrClpRead_mode;
1060int CbcOrClpEnvironmentIndex = -1;
1061static size_t fillEnv()
1062{
1063#if defined(_MSC_VER) || defined(__MSVCRT__)
1064     return 0;
1065#else
1066     // Don't think it will work on Windows
1067     char * environ = getenv("CBC_CLP_ENVIRONMENT");
1068     size_t length = 0;
1069     if (environ) {
1070          length = strlen(environ);
1071          if (CbcOrClpEnvironmentIndex < static_cast<int>(length)) {
1072               // find next non blank
1073               char * whereEnv = environ + CbcOrClpEnvironmentIndex;
1074               // munch white space
1075               while (*whereEnv == ' ' || *whereEnv == '\t' || *whereEnv < ' ')
1076                    whereEnv++;
1077               // copy
1078               char * put = line;
1079               while ( *whereEnv != '\0' ) {
1080                    if ( *whereEnv == ' ' || *whereEnv == '\t' || *whereEnv < ' ' ) {
1081                         break;
1082                    }
1083                    *put = *whereEnv;
1084                    put++;
1085                    assert (put - line < 1000);
1086                    whereEnv++;
1087               }
1088               CbcOrClpEnvironmentIndex = static_cast<int>(whereEnv - environ);
1089               *put = '\0';
1090               length = strlen(line);
1091          } else {
1092               length = 0;
1093          }
1094     }
1095     if (!length)
1096          CbcOrClpEnvironmentIndex = -1;
1097     return length;
1098#endif
1099}
1100extern FILE * CbcOrClpReadCommand;
1101// Simple read stuff
1102std::string
1103CoinReadNextField()
1104{
1105     std::string field;
1106     if (!where) {
1107          // need new line
1108#ifdef COIN_HAS_READLINE
1109          if (CbcOrClpReadCommand == stdin) {
1110               // Get a line from the user.
1111               where = readline (coin_prompt);
1112
1113               // If the line has any text in it, save it on the history.
1114               if (where) {
1115                    if ( *where)
1116                         add_history (where);
1117                    strcpy(line, where);
1118                    free(where);
1119               }
1120          } else {
1121               where = fgets(line, 1000, CbcOrClpReadCommand);
1122          }
1123#else
1124          if (CbcOrClpReadCommand == stdin) {
1125               fputs(coin_prompt,stdout);
1126               fflush(stdout);
1127          }
1128          where = fgets(line, 1000, CbcOrClpReadCommand);
1129#endif
1130          if (!where)
1131               return field; // EOF
1132          where = line;
1133          // clean image
1134          char * lastNonBlank = line - 1;
1135          while ( *where != '\0' ) {
1136               if ( *where != '\t' && *where < ' ' ) {
1137                    break;
1138               } else if ( *where != '\t' && *where != ' ') {
1139                    lastNonBlank = where;
1140               }
1141               where++;
1142          }
1143          where = line;
1144          *(lastNonBlank + 1) = '\0';
1145     }
1146     // munch white space
1147     while (*where == ' ' || *where == '\t')
1148          where++;
1149     char * saveWhere = where;
1150     while (*where != ' ' && *where != '\t' && *where != '\0')
1151          where++;
1152     if (where != saveWhere) {
1153          char save = *where;
1154          *where = '\0';
1155          //convert to string
1156          field = saveWhere;
1157          *where = save;
1158     } else {
1159          where = NULL;
1160          field = "EOL";
1161     }
1162     return field;
1163}
1164
1165std::string
1166CoinReadGetCommand(int argc, const char *argv[])
1167{
1168     std::string field = "EOL";
1169     // say no =
1170     afterEquals = "";
1171     while (field == "EOL") {
1172          if (CbcOrClpRead_mode > 0) {
1173               if ((CbcOrClpRead_mode < argc && argv[CbcOrClpRead_mode]) ||
1174                         CbcOrClpEnvironmentIndex >= 0) {
1175                    if (CbcOrClpEnvironmentIndex < 0) {
1176                         field = argv[CbcOrClpRead_mode++];
1177                    } else {
1178                         if (fillEnv()) {
1179                              field = line;
1180                         } else {
1181                              // not there
1182                              continue;
1183                         }
1184                    }
1185                    if (field == "-") {
1186                         std::cout << "Switching to line mode" << std::endl;
1187                         CbcOrClpRead_mode = -1;
1188                         field = CoinReadNextField();
1189                    } else if (field[0] != '-') {
1190                         if (CbcOrClpRead_mode != 2) {
1191                              // now allow std::cout<<"skipping non-command "<<field<<std::endl;
1192                              // field="EOL"; // skip
1193                         } else if (CbcOrClpEnvironmentIndex < 0) {
1194                              // special dispensation - taken as -import name
1195                              CbcOrClpRead_mode--;
1196                              field = "import";
1197                         }
1198                    } else {
1199                         if (field != "--") {
1200                              // take off -
1201                              field = field.substr(1);
1202                         } else {
1203                              // special dispensation - taken as -import --
1204                              CbcOrClpRead_mode--;
1205                              field = "import";
1206                         }
1207                    }
1208               } else {
1209                    field = "";
1210               }
1211          } else {
1212               field = CoinReadNextField();
1213          }
1214     }
1215     // if = then modify and save
1216     std::string::size_type found = field.find('=');
1217     if (found != std::string::npos) {
1218          afterEquals = field.substr(found + 1);
1219          field = field.substr(0, found);
1220     }
1221     //std::cout<<field<<std::endl;
1222     return field;
1223}
1224std::string
1225CoinReadGetString(int argc, const char *argv[])
1226{
1227     std::string field = "EOL";
1228     if (afterEquals == "") {
1229          if (CbcOrClpRead_mode > 0) {
1230               if (CbcOrClpRead_mode < argc || CbcOrClpEnvironmentIndex >= 0) {
1231                    if (CbcOrClpEnvironmentIndex < 0) {
1232                         if (argv[CbcOrClpRead_mode][0] != '-') {
1233                              field = argv[CbcOrClpRead_mode++];
1234                         } else if (!strcmp(argv[CbcOrClpRead_mode], "--")) {
1235                              field = argv[CbcOrClpRead_mode++];
1236                              // -- means import from stdin
1237                              field = "-";
1238                         }
1239                    } else {
1240                         fillEnv();
1241                         field = line;
1242                    }
1243               }
1244          } else {
1245               field = CoinReadNextField();
1246          }
1247     } else {
1248          field = afterEquals;
1249          afterEquals = "";
1250     }
1251     //std::cout<<field<<std::endl;
1252     return field;
1253}
1254// valid 0 - okay, 1 bad, 2 not there
1255int
1256CoinReadGetIntField(int argc, const char *argv[], int * valid)
1257{
1258     std::string field = "EOL";
1259     if (afterEquals == "") {
1260          if (CbcOrClpRead_mode > 0) {
1261               if (CbcOrClpRead_mode < argc || CbcOrClpEnvironmentIndex >= 0) {
1262                    if (CbcOrClpEnvironmentIndex < 0) {
1263                         // may be negative value so do not check for -
1264                         field = argv[CbcOrClpRead_mode++];
1265                    } else {
1266                         fillEnv();
1267                         field = line;
1268                    }
1269               }
1270          } else {
1271               field = CoinReadNextField();
1272          }
1273     } else {
1274          field = afterEquals;
1275          afterEquals = "";
1276     }
1277     long int value = 0;
1278     //std::cout<<field<<std::endl;
1279     if (field != "EOL") {
1280          const char * start = field.c_str();
1281          char * endPointer = NULL;
1282          // check valid
1283          value =  strtol(start, &endPointer, 10);
1284          if (*endPointer == '\0') {
1285               *valid = 0;
1286          } else {
1287               *valid = 1;
1288               std::cout << "String of " << field;
1289          }
1290     } else {
1291          *valid = 2;
1292     }
1293     return static_cast<int>(value);
1294}
1295double
1296CoinReadGetDoubleField(int argc, const char *argv[], int * valid)
1297{
1298     std::string field = "EOL";
1299     if (afterEquals == "") {
1300          if (CbcOrClpRead_mode > 0) {
1301               if (CbcOrClpRead_mode < argc || CbcOrClpEnvironmentIndex >= 0) {
1302                    if (CbcOrClpEnvironmentIndex < 0) {
1303                         // may be negative value so do not check for -
1304                         field = argv[CbcOrClpRead_mode++];
1305                    } else {
1306                         fillEnv();
1307                         field = line;
1308                    }
1309               }
1310          } else {
1311               field = CoinReadNextField();
1312          }
1313     } else {
1314          field = afterEquals;
1315          afterEquals = "";
1316     }
1317     double value = 0.0;
1318     //std::cout<<field<<std::endl;
1319     if (field != "EOL") {
1320          const char * start = field.c_str();
1321          char * endPointer = NULL;
1322          // check valid
1323          value =  strtod(start, &endPointer);
1324          if (*endPointer == '\0') {
1325               *valid = 0;
1326          } else {
1327               *valid = 1;
1328               std::cout << "String of " << field;
1329          }
1330     } else {
1331          *valid = 2;
1332     }
1333     return value;
1334}
1335/*
1336  Subroutine to establish the cbc parameter array. See the description of
1337  class CbcOrClpParam for details. Pulled from C..Main() for clarity.
1338*/
1339void
1340establishParams (int &numberParameters, CbcOrClpParam *const parameters)
1341{
1342     numberParameters = 0;
1343     parameters[numberParameters++] =
1344          CbcOrClpParam("?", "For help", CBC_PARAM_GENERALQUERY, 7, 0);
1345     parameters[numberParameters++] =
1346          CbcOrClpParam("???", "For help", CBC_PARAM_FULLGENERALQUERY, 7, 0);
1347     parameters[numberParameters++] =
1348          CbcOrClpParam("-", "From stdin",
1349                        CLP_PARAM_ACTION_STDIN, 3, 0);
1350#ifdef ABC_INHERIT
1351      parameters[numberParameters++] =
1352          CbcOrClpParam("abc", "Whether to visit Aboca",
1353                        "off", CLP_PARAM_STR_ABCWANTED, 7, 0);
1354     parameters[numberParameters-1].append("one");
1355     parameters[numberParameters-1].append("two");
1356     parameters[numberParameters-1].append("three");
1357     parameters[numberParameters-1].append("four");
1358     parameters[numberParameters-1].append("five");
1359     parameters[numberParameters-1].append("six");
1360     parameters[numberParameters-1].append("seven");
1361     parameters[numberParameters-1].append("eight");
1362     parameters[numberParameters-1].append("on");
1363     parameters[numberParameters-1].append("decide");
1364     parameters[numberParameters-1].setLonghelp
1365     (
1366          "Decide whether to use A Basic Optimization Code (Accelerated?) \
1367and whether to try going parallel!"
1368     );
1369#endif
1370     parameters[numberParameters++] =
1371          CbcOrClpParam("allC!ommands", "Whether to print less used commands",
1372                        "no", CLP_PARAM_STR_ALLCOMMANDS);
1373     parameters[numberParameters-1].append("more");
1374     parameters[numberParameters-1].append("all");
1375     parameters[numberParameters-1].setLonghelp
1376     (
1377          "For the sake of your sanity, only the more useful and simple commands \
1378are printed out on ?."
1379     );
1380#ifdef COIN_HAS_CBC
1381     parameters[numberParameters++] =
1382          CbcOrClpParam("allow!ableGap", "Stop when gap between best possible and \
1383best less than this",
1384                        0.0, 1.0e20, CBC_PARAM_DBL_ALLOWABLEGAP);
1385     parameters[numberParameters-1].setDoubleValue(0.0);
1386     parameters[numberParameters-1].setLonghelp
1387     (
1388          "If the gap between best solution and best possible solution is less than this \
1389then the search will be terminated.  Also see ratioGap."
1390     );
1391#endif
1392#ifdef COIN_HAS_CLP
1393     parameters[numberParameters++] =
1394          CbcOrClpParam("allS!lack", "Set basis back to all slack and reset solution",
1395                        CLP_PARAM_ACTION_ALLSLACK, 3);
1396     parameters[numberParameters-1].setLonghelp
1397     (
1398          "Mainly useful for tuning purposes.  Normally the first dual or primal will be using an all slack \
1399basis anyway."
1400     );
1401#endif
1402#ifdef COIN_HAS_CBC
1403     parameters[numberParameters++] =
1404          CbcOrClpParam("artif!icialCost", "Costs >= this treated as artificials in feasibility pump",
1405                        0.0, COIN_DBL_MAX, CBC_PARAM_DBL_ARTIFICIALCOST, 1);
1406     parameters[numberParameters-1].setDoubleValue(0.0);
1407     parameters[numberParameters-1].setLonghelp
1408     (
1409          "0.0 off - otherwise variables with costs >= this are treated as artificials and fixed to lower bound in feasibility pump"
1410     );
1411#endif
1412#ifdef COIN_HAS_CLP
1413     parameters[numberParameters++] =
1414          CbcOrClpParam("auto!Scale", "Whether to scale objective, rhs and bounds of problem if they look odd",
1415                        "off", CLP_PARAM_STR_AUTOSCALE, 7, 0);
1416     parameters[numberParameters-1].append("on");
1417     parameters[numberParameters-1].setLonghelp
1418     (
1419          "If you think you may get odd objective values or large equality rows etc then\
1420 it may be worth setting this true.  It is still experimental and you may prefer\
1421 to use objective!Scale and rhs!Scale."
1422     );
1423     parameters[numberParameters++] =
1424          CbcOrClpParam("barr!ier", "Solve using primal dual predictor corrector algorithm",
1425                        CLP_PARAM_ACTION_BARRIER);
1426     parameters[numberParameters-1].setLonghelp
1427     (
1428          "This command solves the current model using the  primal dual predictor \
1429corrector algorithm.  You may want to link in an alternative \
1430ordering and factorization.  It will also solve models \
1431with quadratic objectives."
1432
1433     );
1434     parameters[numberParameters++] =
1435          CbcOrClpParam("basisI!n", "Import basis from bas file",
1436                        CLP_PARAM_ACTION_BASISIN, 3);
1437     parameters[numberParameters-1].setLonghelp
1438     (
1439          "This will read an MPS format basis file from the given file name.  It will use the default\
1440 directory given by 'directory'.  A name of '$' will use the previous value for the name.  This\
1441 is initialized to '', i.e. it must be set.  If you have libz then it can read compressed\
1442 files 'xxxxxxxx.gz' or xxxxxxxx.bz2."
1443     );
1444     parameters[numberParameters++] =
1445          CbcOrClpParam("basisO!ut", "Export basis as bas file",
1446                        CLP_PARAM_ACTION_BASISOUT);
1447     parameters[numberParameters-1].setLonghelp
1448     (
1449          "This will write an MPS format basis file to the given file name.  It will use the default\
1450 directory given by 'directory'.  A name of '$' will use the previous value for the name.  This\
1451 is initialized to 'default.bas'."
1452     );
1453     parameters[numberParameters++] =
1454          CbcOrClpParam("biasLU", "Whether factorization biased towards U",
1455                        "UU", CLP_PARAM_STR_BIASLU, 2, 0);
1456     parameters[numberParameters-1].append("UX");
1457     parameters[numberParameters-1].append("LX");
1458     parameters[numberParameters-1].append("LL");
1459     parameters[numberParameters-1].setCurrentOption("LX");
1460#endif
1461#ifdef COIN_HAS_CBC
1462     parameters[numberParameters++] =
1463          CbcOrClpParam("branch!AndCut", "Do Branch and Cut",
1464                        CBC_PARAM_ACTION_BAB);
1465     parameters[numberParameters-1].setLonghelp
1466     (
1467          "This does branch and cut.  There are many parameters which can affect the performance.  \
1468First just try with default settings and look carefully at the log file.  Did cuts help?  Did they take too long?  \
1469Look at output to see which cuts were effective and then do some tuning.  You will see that the \
1470options for cuts are off, on, root and ifmove, forceon.  Off is \
1471obvious, on means that this cut generator will be tried in the branch and cut tree (you can fine tune using \
1472'depth').  Root means just at the root node while 'ifmove' means that cuts will be used in the tree if they \
1473look as if they are doing some good and moving the objective value.  Forceon is same as on but forces code to use \
1474cut generator at every node.  For probing forceonbut just does fixing probing in tree - not strengthening etc.  \
1475If pre-processing reduced the size of the \
1476problem or strengthened many coefficients then it is probably wise to leave it on.  Switch off heuristics \
1477which did not provide solutions.  The other major area to look at is the search.  Hopefully good solutions \
1478were obtained fairly early in the search so the important point is to select the best variable to branch on.  \
1479See whether strong branching did a good job - or did it just take a lot of iterations.  Adjust the strongBranching \
1480and trustPseudoCosts parameters.  If cuts did a good job, then you may wish to \
1481have more rounds of cuts - see passC!uts and passT!ree."
1482     );
1483#endif
1484     parameters[numberParameters++] =
1485          CbcOrClpParam("bscale", "Whether to scale in barrier (and ordering speed)",
1486                        "off", CLP_PARAM_STR_BARRIERSCALE, 7, 0);
1487     parameters[numberParameters-1].append("on");
1488     parameters[numberParameters-1].append("off1");
1489     parameters[numberParameters-1].append("on1");
1490     parameters[numberParameters-1].append("off2");
1491     parameters[numberParameters-1].append("on2");
1492     parameters[numberParameters++] =
1493          CbcOrClpParam("chol!esky", "Which cholesky algorithm",
1494                        "native", CLP_PARAM_STR_CHOLESKY, 7);
1495     parameters[numberParameters-1].append("dense");
1496     //#ifdef FOREIGN_BARRIER
1497#ifdef COIN_HAS_WSMP
1498     parameters[numberParameters-1].append("fudge!Long");
1499     parameters[numberParameters-1].append("wssmp");
1500#else
1501     parameters[numberParameters-1].append("fudge!Long_dummy");
1502     parameters[numberParameters-1].append("wssmp_dummy");
1503#endif
1504#if defined(COIN_HAS_AMD) || defined(COIN_HAS_CHOLMOD) || defined(COIN_HAS_GLPK)
1505     parameters[numberParameters-1].append("Uni!versityOfFlorida");
1506#else
1507     parameters[numberParameters-1].append("Uni!versityOfFlorida_dummy");
1508#endif
1509#ifdef TAUCS_BARRIER
1510     parameters[numberParameters-1].append("Taucs");
1511#else
1512     parameters[numberParameters-1].append("Taucs_dummy");
1513#endif
1514#ifdef COIN_HAS_MUMPS
1515     parameters[numberParameters-1].append("Mumps");
1516#else
1517     parameters[numberParameters-1].append("Mumps_dummy");
1518#endif
1519     parameters[numberParameters-1].setLonghelp
1520     (
1521          "For a barrier code to be effective it needs a good Cholesky ordering and factorization.  \
1522The native ordering and factorization is not state of the art, although acceptable.  \
1523You may want to link in one from another source.  See Makefile.locations for some \
1524possibilities."
1525     );
1526     //#endif
1527#ifdef COIN_HAS_CBC
1528     parameters[numberParameters++] =
1529          CbcOrClpParam("clique!Cuts", "Whether to use Clique cuts",
1530                        "off", CBC_PARAM_STR_CLIQUECUTS);
1531     parameters[numberParameters-1].append("on");
1532     parameters[numberParameters-1].append("root");
1533     parameters[numberParameters-1].append("ifmove");
1534     parameters[numberParameters-1].append("forceOn");
1535     parameters[numberParameters-1].append("onglobal");
1536     parameters[numberParameters-1].setLonghelp
1537     (
1538          "This switches on clique cuts (either at root or in entire tree) \
1539See branchAndCut for information on options."
1540     );
1541     parameters[numberParameters++] =
1542          CbcOrClpParam("combine!Solutions", "Whether to use combine solution heuristic",
1543                        "off", CBC_PARAM_STR_COMBINE);
1544     parameters[numberParameters-1].append("on");
1545     parameters[numberParameters-1].append("both");
1546     parameters[numberParameters-1].append("before");
1547     parameters[numberParameters-1].setLonghelp
1548     (
1549          "This switches on a heuristic which does branch and cut on the problem given by just \
1550using variables which have appeared in one or more solutions. \
1551It obviously only tries after two or more solutions. \
1552See Rounding for meaning of on,both,before"
1553     );
1554     parameters[numberParameters++] =
1555          CbcOrClpParam("combine2!Solutions", "Whether to use crossover solution heuristic",
1556                        "off", CBC_PARAM_STR_CROSSOVER2);
1557     parameters[numberParameters-1].append("on");
1558     parameters[numberParameters-1].append("both");
1559     parameters[numberParameters-1].append("before");
1560     parameters[numberParameters-1].setLonghelp
1561     (
1562          "This switches on a heuristic which does branch and cut on the problem given by \
1563fixing variables which have same value in two or more solutions. \
1564It obviously only tries after two or more solutions. \
1565See Rounding for meaning of on,both,before"
1566     );
1567     parameters[numberParameters++] =
1568          CbcOrClpParam("constraint!fromCutoff", "Whether to use cutoff as constraint",
1569                        "off", CBC_PARAM_STR_CUTOFF_CONSTRAINT);
1570     parameters[numberParameters-1].append("on");
1571     parameters[numberParameters-1].setLonghelp
1572     (
1573          "This adds the objective as a constraint with best solution as RHS"
1574     );
1575     parameters[numberParameters++] =
1576          CbcOrClpParam("cost!Strategy", "How to use costs as priorities",
1577                        "off", CBC_PARAM_STR_COSTSTRATEGY);
1578     parameters[numberParameters-1].append("pri!orities");
1579     parameters[numberParameters-1].append("column!Order?");
1580     parameters[numberParameters-1].append("01f!irst?");
1581     parameters[numberParameters-1].append("01l!ast?");
1582     parameters[numberParameters-1].append("length!?");
1583     parameters[numberParameters-1].append("singletons");
1584     parameters[numberParameters-1].append("nonzero");
1585     parameters[numberParameters-1].setLonghelp
1586     (
1587          "This orders the variables in order of their absolute costs - with largest cost ones being branched on \
1588first.  This primitive strategy can be surprsingly effective.  The column order\
1589 option is obviously not on costs but easy to code here."
1590     );
1591     parameters[numberParameters++] =
1592          CbcOrClpParam("cplex!Use", "Whether to use Cplex!",
1593                        "off", CBC_PARAM_STR_CPX);
1594     parameters[numberParameters-1].append("on");
1595     parameters[numberParameters-1].setLonghelp
1596     (
1597          " If the user has Cplex, but wants to use some of Cbc's heuristics \
1598then you can!  If this is on, then Cbc will get to the root node and then \
1599hand over to Cplex.  If heuristics find a solution this can be significantly \
1600quicker.  You will probably want to switch off Cbc's cuts as Cplex thinks \
1601they are genuine constraints.  It is also probable that you want to switch \
1602off preprocessing, although for difficult problems it is worth trying \
1603both."
1604     );
1605#endif
1606     parameters[numberParameters++] =
1607          CbcOrClpParam("cpp!Generate", "Generates C++ code",
1608                        -1, 50000, CLP_PARAM_INT_CPP, 1);
1609     parameters[numberParameters-1].setLonghelp
1610     (
1611          "Once you like what the stand-alone solver does then this allows \
1612you to generate user_driver.cpp which approximates the code.  \
16130 gives simplest driver, 1 generates saves and restores, 2 \
1614generates saves and restores even for variables at default value. \
16154 bit in cbc generates size dependent code rather than computed values.  \
1616This is now deprecated as you can call stand-alone solver - see \
1617Cbc/examples/driver4.cpp."
1618     );
1619#ifdef COIN_HAS_CLP
1620     parameters[numberParameters++] =
1621          CbcOrClpParam("crash", "Whether to create basis for problem",
1622                        "off", CLP_PARAM_STR_CRASH);
1623     parameters[numberParameters-1].append("on");
1624     parameters[numberParameters-1].append("so!low_halim");
1625     parameters[numberParameters-1].append("lots");
1626#ifdef ABC_INHERIT
1627     parameters[numberParameters-1].append("dual");
1628     parameters[numberParameters-1].append("dw");
1629     parameters[numberParameters-1].append("idiot");
1630#endif
1631     parameters[numberParameters-1].setLonghelp
1632     (
1633          "If crash is set on and there is an all slack basis then Clp will flip or put structural\
1634 variables into basis with the aim of getting dual feasible.  On the whole dual seems to be\
1635 better without it and there are alternative types of 'crash' for primal e.g. 'idiot' or 'sprint'. \
1636I have also added a variant due to Solow and Halim which is as on but just flip.");
1637     parameters[numberParameters++] =
1638          CbcOrClpParam("cross!over", "Whether to get a basic solution after barrier",
1639                        "on", CLP_PARAM_STR_CROSSOVER);
1640     parameters[numberParameters-1].append("off");
1641     parameters[numberParameters-1].append("maybe");
1642     parameters[numberParameters-1].append("presolve");
1643     parameters[numberParameters-1].setLonghelp
1644     (
1645          "Interior point algorithms do not obtain a basic solution (and \
1646the feasibility criterion is a bit suspect (JJF)).  This option will crossover \
1647to a basic solution suitable for ranging or branch and cut.  With the current state \
1648of quadratic it may be a good idea to switch off crossover for quadratic (and maybe \
1649presolve as well) - the option maybe does this."
1650     );
1651#endif
1652#ifdef COIN_HAS_CBC
1653     parameters[numberParameters++] =
1654          CbcOrClpParam("csv!Statistics", "Create one line of statistics",
1655                        CLP_PARAM_ACTION_CSVSTATISTICS, 2, 1);
1656     parameters[numberParameters-1].setLonghelp
1657     (
1658          "This appends statistics to given file name.  It will use the default\
1659 directory given by 'directory'.  A name of '$' will use the previous value for the name.  This\
1660 is initialized to '', i.e. it must be set.  Adds header if file empty or does not exist."
1661     );
1662     parameters[numberParameters++] =
1663          CbcOrClpParam("cutD!epth", "Depth in tree at which to do cuts",
1664                        -1, 999999, CBC_PARAM_INT_CUTDEPTH);
1665     parameters[numberParameters-1].setLonghelp
1666     (
1667          "Cut generators may be - off, on only at root, on if they look possible \
1668and on.  If they are done every node then that is that, but it may be worth doing them \
1669every so often.  The original method was every so many nodes but it is more logical \
1670to do it whenever depth in tree is a multiple of K.  This option does that and defaults \
1671to -1 (off -> code decides)."
1672     );
1673     parameters[numberParameters-1].setIntValue(-1);
1674     parameters[numberParameters++] =
1675          CbcOrClpParam("cutL!ength", "Length of a cut",
1676                        -1, COIN_INT_MAX, CBC_PARAM_INT_CUTLENGTH);
1677     parameters[numberParameters-1].setLonghelp
1678     (
1679          "At present this only applies to Gomory cuts. -1 (default) leaves as is. \
1680Any value >0 says that all cuts <= this length can be generated both at \
1681root node and in tree. 0 says to use some dynamic lengths.  If value >=10,000,000 \
1682then the length in tree is value%10000000 - so 10000100 means unlimited length \
1683at root and 100 in tree."
1684     );
1685     parameters[numberParameters-1].setIntValue(-1);
1686     parameters[numberParameters++] =
1687          CbcOrClpParam("cuto!ff", "All solutions must be better than this",
1688                        -1.0e60, 1.0e60, CBC_PARAM_DBL_CUTOFF);
1689     parameters[numberParameters-1].setDoubleValue(1.0e50);
1690     parameters[numberParameters-1].setLonghelp
1691     (
1692          "All solutions must be better than this value (in a minimization sense).  \
1693This is also set by code whenever it obtains a solution and is set to value of \
1694objective for solution minus cutoff increment."
1695     );
1696     parameters[numberParameters++] =
1697          CbcOrClpParam("cuts!OnOff", "Switches all cuts on or off",
1698                        "off", CBC_PARAM_STR_CUTSSTRATEGY);
1699     parameters[numberParameters-1].append("on");
1700     parameters[numberParameters-1].append("root");
1701     parameters[numberParameters-1].append("ifmove");
1702     parameters[numberParameters-1].append("forceOn");
1703     parameters[numberParameters-1].setLonghelp
1704     (
1705          "This can be used to switch on or off all cuts (apart from Reduce and Split).  Then you can do \
1706individual ones off or on \
1707See branchAndCut for information on options."
1708     );
1709     parameters[numberParameters++] =
1710          CbcOrClpParam("debug!In", "read valid solution from file",
1711                        CLP_PARAM_ACTION_DEBUG, 7, 1);
1712     parameters[numberParameters-1].setLonghelp
1713     (
1714          "This will read a solution file from the given file name.  It will use the default\
1715 directory given by 'directory'.  A name of '$' will use the previous value for the name.  This\
1716 is initialized to '', i.e. it must be set.\n\n\
1717If set to create it will create a file called debug.file  after search.\n\n\
1718The idea is that if you suspect a bad cut generator \
1719you can do a good run with debug set to 'create' and then switch on the cuts you suspect and \
1720re-run with debug set to 'debug.file'  The create case has same effect as saveSolution."
1721     );
1722#endif
1723#ifdef COIN_HAS_CLP
1724#if CLP_MULTIPLE_FACTORIZATIONS >0
1725     parameters[numberParameters++] =
1726          CbcOrClpParam("dense!Threshold", "Whether to use dense factorization",
1727                        -1, 10000, CBC_PARAM_INT_DENSE, 1);
1728     parameters[numberParameters-1].setLonghelp
1729     (
1730          "If processed problem <= this use dense factorization"
1731     );
1732     parameters[numberParameters-1].setIntValue(-1);
1733#endif
1734#endif
1735#ifdef COIN_HAS_CBC
1736     parameters[numberParameters++] =
1737          CbcOrClpParam("depth!MiniBab", "Depth at which to try mini BAB",
1738                        -COIN_INT_MAX, COIN_INT_MAX, CBC_PARAM_INT_DEPTHMINIBAB);
1739     parameters[numberParameters-1].setIntValue(-1);
1740     parameters[numberParameters-1].setLonghelp
1741     (
1742          "Rather a complicated parameter but can be useful. -1 means off for large problems but on as if -12 for problems where rows+columns<500, -2 \
1743means use Cplex if it is linked in.  Otherwise if negative then go into depth first complete search fast branch and bound when depth>= -value-2 (so -3 will use this at depth>=1).  This mode is only switched on after 500 nodes.  If you really want to switch it off for small problems then set this to -999.  If >=0 the value doesn't matter very much.  The code will do approximately 100 nodes of fast branch and bound every now and then at depth>=5.  The actual logic is too twisted to describe here."
1744     );
1745     parameters[numberParameters++] =
1746          CbcOrClpParam("dextra3", "Extra double parameter 3",
1747                        -COIN_DBL_MAX, COIN_DBL_MAX, CBC_PARAM_DBL_DEXTRA3, 0);
1748     parameters[numberParameters-1].setDoubleValue(0.0);
1749     parameters[numberParameters++] =
1750          CbcOrClpParam("dextra4", "Extra double parameter 4",
1751                        -COIN_DBL_MAX, COIN_DBL_MAX, CBC_PARAM_DBL_DEXTRA4, 0);
1752     parameters[numberParameters-1].setDoubleValue(0.0);
1753     parameters[numberParameters++] =
1754          CbcOrClpParam("dextra5", "Extra double parameter 5",
1755                        -COIN_DBL_MAX, COIN_DBL_MAX, CBC_PARAM_DBL_DEXTRA5, 0);
1756     parameters[numberParameters-1].setDoubleValue(0.0);
1757     parameters[numberParameters++] =
1758          CbcOrClpParam("Dins", "Whether to try Distance Induced Neighborhood Search",
1759                        "off", CBC_PARAM_STR_DINS);
1760     parameters[numberParameters-1].append("on");
1761     parameters[numberParameters-1].append("both");
1762     parameters[numberParameters-1].append("before");
1763     parameters[numberParameters-1].append("often");
1764     parameters[numberParameters-1].setLonghelp
1765     (
1766          "This switches on Distance induced neighborhood Search. \
1767See Rounding for meaning of on,both,before"
1768     );
1769#endif
1770     parameters[numberParameters++] =
1771          CbcOrClpParam("direction", "Minimize or Maximize",
1772                        "min!imize", CLP_PARAM_STR_DIRECTION);
1773     parameters[numberParameters-1].append("max!imize");
1774     parameters[numberParameters-1].append("zero");
1775     parameters[numberParameters-1].setLonghelp
1776     (
1777          "The default is minimize - use 'direction maximize' for maximization.\n\
1778You can also use the parameters 'maximize' or 'minimize'."
1779     );
1780     parameters[numberParameters++] =
1781          CbcOrClpParam("directory", "Set Default directory for import etc.",
1782                        CLP_PARAM_ACTION_DIRECTORY);
1783     parameters[numberParameters-1].setLonghelp
1784     (
1785          "This sets the directory which import, export, saveModel, restoreModel etc will use.\
1786  It is initialized to './'"
1787     );
1788     parameters[numberParameters++] =
1789          CbcOrClpParam("dirSample", "Set directory where the COIN-OR sample problems are.",
1790                        CLP_PARAM_ACTION_DIRSAMPLE, 7, 1);
1791     parameters[numberParameters-1].setLonghelp
1792     (
1793          "This sets the directory where the COIN-OR sample problems reside. It is\
1794 used only when -unitTest is passed to clp. clp will pick up the test problems\
1795 from this directory.\
1796 It is initialized to '../../Data/Sample'"
1797     );
1798     parameters[numberParameters++] =
1799          CbcOrClpParam("dirNetlib", "Set directory where the netlib problems are.",
1800                        CLP_PARAM_ACTION_DIRNETLIB, 7, 1);
1801     parameters[numberParameters-1].setLonghelp
1802     (
1803          "This sets the directory where the netlib problems reside. One can get\
1804 the netlib problems from COIN-OR or from the main netlib site. This\
1805 parameter is used only when -netlib is passed to clp. clp will pick up the\
1806 netlib problems from this directory. If clp is built without zlib support\
1807 then the problems must be uncompressed.\
1808 It is initialized to '../../Data/Netlib'"
1809     );
1810     parameters[numberParameters++] =
1811          CbcOrClpParam("dirMiplib", "Set directory where the miplib 2003 problems are.",
1812                        CBC_PARAM_ACTION_DIRMIPLIB, 7, 1);
1813     parameters[numberParameters-1].setLonghelp
1814     (
1815          "This sets the directory where the miplib 2003 problems reside. One can\
1816 get the miplib problems from COIN-OR or from the main miplib site. This\
1817 parameter is used only when -miplib is passed to cbc. cbc will pick up the\
1818 miplib problems from this directory. If cbc is built without zlib support\
1819 then the problems must be uncompressed.\
1820 It is initialized to '../../Data/miplib3'"
1821     );
1822#ifdef COIN_HAS_CBC
1823     parameters[numberParameters++] =
1824          CbcOrClpParam("diveO!pt", "Diving options",
1825                        -1, 200000, CBC_PARAM_INT_DIVEOPT, 1);
1826     parameters[numberParameters-1].setLonghelp
1827     (
1828          "If >2 && <8 then modify diving options - \
1829         \n\t3 only at root and if no solution,  \
1830         \n\t4 only at root and if this heuristic has not got solution, \
1831         \n\t5 only at depth <4, \
1832         \n\t6 decay, \
1833         \n\t7 run up to 2 times if solution found 4 otherwise."
1834     );
1835     parameters[numberParameters-1].setIntValue(-1);
1836     parameters[numberParameters++] =
1837          CbcOrClpParam("DivingS!ome", "Whether to try Diving heuristics",
1838                        "off", CBC_PARAM_STR_DIVINGS);
1839     parameters[numberParameters-1].append("on");
1840     parameters[numberParameters-1].append("both");
1841     parameters[numberParameters-1].append("before");
1842     parameters[numberParameters-1].setLonghelp
1843     (
1844          "This switches on a random diving heuristic at various times. \
1845C - Coefficient, F - Fractional, G - Guided, L - LineSearch, P - PseudoCost, V - VectorLength. \
1846You may prefer to use individual on/off \
1847See Rounding for meaning of on,both,before"
1848     );
1849     parameters[numberParameters++] =
1850          CbcOrClpParam("DivingC!oefficient", "Whether to try DiveCoefficient",
1851                        "off", CBC_PARAM_STR_DIVINGC);
1852     parameters[numberParameters-1].append("on");
1853     parameters[numberParameters-1].append("both");
1854     parameters[numberParameters-1].append("before");
1855     parameters[numberParameters++] =
1856          CbcOrClpParam("DivingF!ractional", "Whether to try DiveFractional",
1857                        "off", CBC_PARAM_STR_DIVINGF);
1858     parameters[numberParameters-1].append("on");
1859     parameters[numberParameters-1].append("both");
1860     parameters[numberParameters-1].append("before");
1861     parameters[numberParameters++] =
1862          CbcOrClpParam("DivingG!uided", "Whether to try DiveGuided",
1863                        "off", CBC_PARAM_STR_DIVINGG);
1864     parameters[numberParameters-1].append("on");
1865     parameters[numberParameters-1].append("both");
1866     parameters[numberParameters-1].append("before");
1867     parameters[numberParameters++] =
1868          CbcOrClpParam("DivingL!ineSearch", "Whether to try DiveLineSearch",
1869                        "off", CBC_PARAM_STR_DIVINGL);
1870     parameters[numberParameters-1].append("on");
1871     parameters[numberParameters-1].append("both");
1872     parameters[numberParameters-1].append("before");
1873     parameters[numberParameters++] =
1874          CbcOrClpParam("DivingP!seudoCost", "Whether to try DivePseudoCost",
1875                        "off", CBC_PARAM_STR_DIVINGP);
1876     parameters[numberParameters-1].append("on");
1877     parameters[numberParameters-1].append("both");
1878     parameters[numberParameters-1].append("before");
1879     parameters[numberParameters++] =
1880          CbcOrClpParam("DivingV!ectorLength", "Whether to try DiveVectorLength",
1881                        "off", CBC_PARAM_STR_DIVINGV);
1882     parameters[numberParameters-1].append("on");
1883     parameters[numberParameters-1].append("both");
1884     parameters[numberParameters-1].append("before");
1885     parameters[numberParameters++] =
1886          CbcOrClpParam("doH!euristic", "Do heuristics before any preprocessing",
1887                        CBC_PARAM_ACTION_DOHEURISTIC, 3);
1888     parameters[numberParameters-1].setLonghelp
1889     (
1890          "Normally heuristics are done in branch and bound.  It may be useful to do them outside. \
1891Only those heuristics with 'both' or 'before' set will run.  \
1892Doing this may also set cutoff, which can help with preprocessing."
1893     );
1894#endif
1895#ifdef COIN_HAS_CLP
1896     parameters[numberParameters++] =
1897          CbcOrClpParam("dualB!ound", "Initially algorithm acts as if no \
1898gap between bounds exceeds this value",
1899                        1.0e-20, 1.0e12, CLP_PARAM_DBL_DUALBOUND);
1900     parameters[numberParameters-1].setLonghelp
1901     (
1902          "The dual algorithm in Clp is a single phase algorithm as opposed to a two phase\
1903 algorithm where you first get feasible then optimal.  If a problem has both upper and\
1904 lower bounds then it is trivial to get dual feasible by setting non basic variables\
1905 to correct bound.  If the gap between the upper and lower bounds of a variable is more\
1906 than the value of dualBound Clp introduces fake bounds so that it can make the problem\
1907 dual feasible.  This has the same effect as a composite objective function in the\
1908 primal algorithm.  Too high a value may mean more iterations, while too low a bound means\
1909 the code may go all the way and then have to increase the bounds.  OSL had a heuristic to\
1910 adjust bounds, maybe we need that here."
1911     );
1912     parameters[numberParameters++] =
1913          CbcOrClpParam("dualize", "Solves dual reformulation",
1914                        0, 4, CLP_PARAM_INT_DUALIZE, 1);
1915     parameters[numberParameters-1].setLonghelp
1916     (
1917          "Don't even think about it."
1918     );
1919     parameters[numberParameters++] =
1920          CbcOrClpParam("dualP!ivot", "Dual pivot choice algorithm",
1921                        "auto!matic", CLP_PARAM_STR_DUALPIVOT, 7, 1);
1922     parameters[numberParameters-1].append("dant!zig");
1923     parameters[numberParameters-1].append("partial");
1924     parameters[numberParameters-1].append("steep!est");
1925     parameters[numberParameters-1].setLonghelp
1926     (
1927          "Clp can use any pivot selection algorithm which the user codes as long as it\
1928 implements the features in the abstract pivot base class.  The Dantzig method is implemented\
1929 to show a simple method but its use is deprecated.  Steepest is the method of choice and there\
1930 are two variants which keep all weights updated but only scan a subset each iteration.\
1931 Partial switches this on while automatic decides at each iteration based on information\
1932 about the factorization."
1933     );
1934     parameters[numberParameters++] =
1935          CbcOrClpParam("dualS!implex", "Do dual simplex algorithm",
1936                        CLP_PARAM_ACTION_DUALSIMPLEX);
1937     parameters[numberParameters-1].setLonghelp
1938     (
1939          "This command solves the continuous relaxation of the current model using the dual steepest edge algorithm.\
1940The time and iterations may be affected by settings such as presolve, scaling, crash\
1941 and also by dual pivot method, fake bound on variables and dual and primal tolerances."
1942     );
1943#endif
1944     parameters[numberParameters++] =
1945          CbcOrClpParam("dualT!olerance", "For an optimal solution \
1946no dual infeasibility may exceed this value",
1947                        1.0e-20, 1.0e12, CLP_PARAM_DBL_DUALTOLERANCE);
1948     parameters[numberParameters-1].setLonghelp
1949     (
1950          "Normally the default tolerance is fine, but you may want to increase it a\
1951 bit if a dual run seems to be having a hard time.  One method which can be faster is \
1952to use a large tolerance e.g. 1.0e-4 and dual and then clean up problem using primal and the \
1953correct tolerance (remembering to switch off presolve for this final short clean up phase)."
1954     );
1955#ifdef COIN_HAS_CLP
1956     parameters[numberParameters++] =
1957          CbcOrClpParam("either!Simplex", "Do dual or primal simplex algorithm",
1958                        CLP_PARAM_ACTION_EITHERSIMPLEX);
1959     parameters[numberParameters-1].setLonghelp
1960     (
1961          "This command solves the continuous relaxation of the current model using the dual or primal algorithm,\
1962 based on a dubious analysis of model."
1963     );
1964#endif
1965     parameters[numberParameters++] =
1966          CbcOrClpParam("end", "Stops clp execution",
1967                        CLP_PARAM_ACTION_EXIT);
1968     parameters[numberParameters-1].setLonghelp
1969     (
1970          "This stops execution ; end, exit, quit and stop are synonyms"
1971     );
1972     parameters[numberParameters++] =
1973          CbcOrClpParam("environ!ment", "Read commands from environment",
1974                        CLP_PARAM_ACTION_ENVIRONMENT, 7, 0);
1975     parameters[numberParameters-1].setLonghelp
1976     (
1977          "This starts reading from environment variable CBC_CLP_ENVIRONMENT."
1978     );
1979     parameters[numberParameters++] =
1980          CbcOrClpParam("error!sAllowed", "Whether to allow import errors",
1981                        "off", CLP_PARAM_STR_ERRORSALLOWED, 3);
1982     parameters[numberParameters-1].append("on");
1983     parameters[numberParameters-1].setLonghelp
1984     (
1985          "The default is not to use any model which had errors when reading the mps file.\
1986  Setting this to 'on' will allow all errors from which the code can recover\
1987 simply by ignoring the error.  There are some errors from which the code can not recover \
1988e.g. no ENDATA.  This has to be set before import i.e. -errorsAllowed on -import xxxxxx.mps."
1989     );
1990     parameters[numberParameters++] =
1991          CbcOrClpParam("exit", "Stops clp execution",
1992                        CLP_PARAM_ACTION_EXIT);
1993     parameters[numberParameters-1].setLonghelp
1994     (
1995          "This stops the execution of Clp, end, exit, quit and stop are synonyms"
1996     );
1997#ifdef COIN_HAS_CBC
1998     parameters[numberParameters++] =
1999          CbcOrClpParam("exper!iment", "Whether to use testing features",
2000                        -1, 200, CBC_PARAM_INT_EXPERIMENT, 0);
2001     parameters[numberParameters-1].setLonghelp
2002     (
2003          "Defines how adventurous you want to be in using new ideas. \
20040 then no new ideas, 1 fairly sensible, 2 a bit dubious, 3 you are on your own!"
2005     );
2006     parameters[numberParameters-1].setIntValue(0);
2007     parameters[numberParameters++] =
2008          CbcOrClpParam("expensive!Strong", "Whether to do even more strong branching",
2009                        0, COIN_INT_MAX, CBC_PARAM_INT_STRONG_STRATEGY, 0);
2010     parameters[numberParameters-1].setLonghelp
2011     (
2012      "Strategy for extra strong branching \n\
2013\n\t0 - normal\n\
2014\n\twhen to do all fractional\n\
2015\n\t1 - root node\n\
2016\n\t2 - depth less than modifier\n\
2017\n\t4 - if objective == best possible\n\
2018\n\t6 - as 2+4\n\
2019\n\twhen to do all including satisfied\n\
2020\n\t10 - root node etc.\n\
2021\n\tIf >=100 then do when depth <= strategy/100 (otherwise 5)"
2022     );
2023     parameters[numberParameters-1].setIntValue(0);
2024#endif
2025     parameters[numberParameters++] =
2026          CbcOrClpParam("export", "Export model as mps file",
2027                        CLP_PARAM_ACTION_EXPORT);
2028     parameters[numberParameters-1].setLonghelp
2029     (
2030          "This will write an MPS format file to the given file name.  It will use the default\
2031 directory given by 'directory'.  A name of '$' will use the previous value for the name.  This\
2032 is initialized to 'default.mps'.  \
2033It can be useful to get rid of the original names and go over to using Rnnnnnnn and Cnnnnnnn.  This can be done by setting 'keepnames' off before importing mps file."
2034     );
2035#ifdef COIN_HAS_CBC
2036     parameters[numberParameters++] =
2037          CbcOrClpParam("extra1", "Extra integer parameter 1",
2038                        -COIN_INT_MAX, COIN_INT_MAX, CBC_PARAM_INT_EXTRA1, 0);
2039     parameters[numberParameters-1].setIntValue(-1);
2040     parameters[numberParameters++] =
2041          CbcOrClpParam("extra2", "Extra integer parameter 2",
2042                        -100, COIN_INT_MAX, CBC_PARAM_INT_EXTRA2, 0);
2043     parameters[numberParameters-1].setIntValue(-1);
2044     parameters[numberParameters++] =
2045          CbcOrClpParam("extra3", "Extra integer parameter 3",
2046                        -1, COIN_INT_MAX, CBC_PARAM_INT_EXTRA3, 0);
2047     parameters[numberParameters-1].setIntValue(-1);
2048     parameters[numberParameters++] =
2049          CbcOrClpParam("extra4", "Extra integer parameter 4",
2050                        -1, COIN_INT_MAX, CBC_PARAM_INT_EXTRA4, 0);
2051     parameters[numberParameters-1].setIntValue(-1);
2052     parameters[numberParameters-1].setLonghelp
2053     (
2054          "This switches on yet more special options!! \
2055The bottom digit is a strategy when to used shadow price stuff e.g. 3 \
2056means use until a solution is found.  The next two digits say what sort \
2057of dual information to use.  After that it goes back to powers of 2 so -\n\
2058\n\t1000 - switches on experimental hotstart\n\
2059\n\t2,4,6000 - switches on experimental methods of stopping cuts\n\
2060\n\t8000 - increase minimum drop gradually\n\
2061\n\t16000 - switches on alternate gomory criterion"
2062     );
2063     parameters[numberParameters++] =
2064       CbcOrClpParam("extraV!ariables", "Allow creation of extra integer variables",
2065                     -COIN_INT_MAX, COIN_INT_MAX, CBC_PARAM_INT_EXTRA_VARIABLES, 0);
2066     parameters[numberParameters-1].setIntValue(0);
2067     parameters[numberParameters-1].setLonghelp
2068     (
2069          "This switches on creation of extra integer variables \
2070to gather all variables with same cost."
2071     );
2072#endif
2073#ifdef COIN_HAS_CLP
2074     parameters[numberParameters++] =
2075          CbcOrClpParam("fact!orization", "Which factorization to use",
2076                        "normal", CLP_PARAM_STR_FACTORIZATION);
2077     parameters[numberParameters-1].append("dense");
2078     parameters[numberParameters-1].append("simple");
2079     parameters[numberParameters-1].append("osl");
2080     parameters[numberParameters-1].setLonghelp
2081     (
2082#ifndef ABC_INHERIT
2083          "The default is to use the normal CoinFactorization, but \
2084other choices are a dense one, osl's or one designed for small problems."
2085#else
2086          "Normally the default is to use the normal CoinFactorization, but \
2087other choices are a dense one, osl's or one designed for small problems. \
2088However if at Aboca then the default is CoinAbcFactorization and other choices are \
2089a dense one, one designed for small problems or if enabled a long factorization."
2090#endif
2091     );
2092     parameters[numberParameters++] =
2093          CbcOrClpParam("fakeB!ound", "All bounds <= this value - DEBUG",
2094                        1.0, 1.0e15, CLP_PARAM_ACTION_FAKEBOUND, 0);
2095#ifdef COIN_HAS_CBC
2096     parameters[numberParameters++] =
2097          CbcOrClpParam("feas!ibilityPump", "Whether to try Feasibility Pump",
2098                        "off", CBC_PARAM_STR_FPUMP);
2099     parameters[numberParameters-1].append("on");
2100     parameters[numberParameters-1].append("both");
2101     parameters[numberParameters-1].append("before");
2102     parameters[numberParameters-1].setLonghelp
2103     (
2104          "This switches on feasibility pump heuristic at root. This is due to Fischetti, Lodi and Glover \
2105and uses a sequence of Lps to try and get an integer feasible solution. \
2106Some fine tuning is available by passFeasibilityPump and also pumpTune. \
2107See Rounding for meaning of on,both,before"
2108     );
2109     parameters[numberParameters++] =
2110          CbcOrClpParam("fix!OnDj", "Try heuristic based on fixing variables with \
2111reduced costs greater than this",
2112                        -1.0e20, 1.0e20, CBC_PARAM_DBL_DJFIX, 1);
2113     parameters[numberParameters-1].setLonghelp
2114     (
2115          "If this is set integer variables with reduced costs greater than this will be fixed \
2116before branch and bound - use with extreme caution!"
2117     );
2118     parameters[numberParameters++] =
2119          CbcOrClpParam("flow!CoverCuts", "Whether to use Flow Cover cuts",
2120                        "off", CBC_PARAM_STR_FLOWCUTS);
2121     parameters[numberParameters-1].append("on");
2122     parameters[numberParameters-1].append("root");
2123     parameters[numberParameters-1].append("ifmove");
2124     parameters[numberParameters-1].append("forceOn");
2125     parameters[numberParameters-1].append("onglobal");
2126     parameters[numberParameters-1].setLonghelp
2127     (
2128          "This switches on flow cover cuts (either at root or in entire tree) \
2129See branchAndCut for information on options."
2130     );
2131     parameters[numberParameters++] =
2132          CbcOrClpParam("force!Solution", "Whether to use given solution as crash for BAB",
2133                        -1, 20000000, CLP_PARAM_INT_USESOLUTION);
2134     parameters[numberParameters-1].setIntValue(-1);
2135     parameters[numberParameters-1].setLonghelp
2136     (
2137          "-1 off.  If 1 then tries to branch to solution given by AMPL or priorities file. \
2138If 0 then just tries to set as best solution \
2139If >1 then also does that many nodes on fixed problem."
2140     );
2141     parameters[numberParameters++] =
2142          CbcOrClpParam("fraction!forBAB", "Fraction in feasibility pump",
2143                        1.0e-5, 1.1, CBC_PARAM_DBL_SMALLBAB, 1);
2144     parameters[numberParameters-1].setDoubleValue(0.5);
2145     parameters[numberParameters-1].setLonghelp
2146     (
2147          "After a pass in feasibility pump, variables which have not moved \
2148about are fixed and if the preprocessed model is small enough a few nodes \
2149of branch and bound are done on reduced problem.  Small problem has to be less than this fraction of original."
2150     );
2151#endif
2152     parameters[numberParameters++] =
2153          CbcOrClpParam("gamma!(Delta)", "Whether to regularize barrier",
2154                        "off", CLP_PARAM_STR_GAMMA, 7, 1);
2155     parameters[numberParameters-1].append("on");
2156     parameters[numberParameters-1].append("gamma");
2157     parameters[numberParameters-1].append("delta");
2158     parameters[numberParameters-1].append("onstrong");
2159     parameters[numberParameters-1].append("gammastrong");
2160     parameters[numberParameters-1].append("deltastrong");
2161#endif
2162#ifdef COIN_HAS_CBC
2163      parameters[numberParameters++] =
2164          CbcOrClpParam("GMI!Cuts", "Whether to use alternative Gomory cuts",
2165                        "off", CBC_PARAM_STR_GMICUTS);
2166     parameters[numberParameters-1].append("on");
2167     parameters[numberParameters-1].append("root");
2168     parameters[numberParameters-1].append("ifmove");
2169     parameters[numberParameters-1].append("forceOn");
2170     parameters[numberParameters-1].append("endonly");
2171     parameters[numberParameters-1].append("long");
2172     parameters[numberParameters-1].append("longroot");
2173     parameters[numberParameters-1].append("longifmove");
2174     parameters[numberParameters-1].append("forceLongOn");
2175     parameters[numberParameters-1].append("longendonly");
2176     parameters[numberParameters-1].setLonghelp
2177     (
2178          "This switches on an alternative Gomory cut generator (either at root or in entire tree) \
2179This version is by Giacomo Nannicini and may be more robust \
2180See branchAndCut for information on options."
2181     );
2182     parameters[numberParameters++] =
2183          CbcOrClpParam("GMI!Cuts", "Whether to use alternative Gomory cuts",
2184                        "off", CBC_PARAM_STR_GMICUTS);
2185     parameters[numberParameters-1].append("on");
2186     parameters[numberParameters-1].append("root");
2187     parameters[numberParameters-1].append("ifmove");
2188     parameters[numberParameters-1].append("forceOn");
2189     parameters[numberParameters-1].append("endonly");
2190     parameters[numberParameters-1].append("long");
2191     parameters[numberParameters-1].append("longroot");
2192     parameters[numberParameters-1].append("longifmove");
2193     parameters[numberParameters-1].append("forceLongOn");
2194     parameters[numberParameters-1].append("longendonly");
2195     parameters[numberParameters-1].setLonghelp
2196     (
2197          "This switches on an alternative Gomory cut generator (either at root or in entire tree) \
2198This version is by Giacomo Nannicini and may be more robust \
2199See branchAndCut for information on options."
2200     );
2201     parameters[numberParameters++] =
2202          CbcOrClpParam("gomory!Cuts", "Whether to use Gomory cuts",
2203                        "off", CBC_PARAM_STR_GOMORYCUTS);
2204     parameters[numberParameters-1].append("on");
2205     parameters[numberParameters-1].append("root");
2206     parameters[numberParameters-1].append("ifmove");
2207     parameters[numberParameters-1].append("forceOn");
2208     parameters[numberParameters-1].append("onglobal");
2209     parameters[numberParameters-1].append("forceandglobal");
2210     parameters[numberParameters-1].append("forceLongOn");
2211     parameters[numberParameters-1].append("long");
2212     parameters[numberParameters-1].setLonghelp
2213     (
2214          "The original cuts - beware of imitations!  Having gone out of favor, they are now more \
2215fashionable as LP solvers are more robust and they interact well with other cuts.  They will almost always \
2216give cuts (although in this executable they are limited as to number of variables in cut).  \
2217However the cuts may be dense so it is worth experimenting (Long allows any length). \
2218See branchAndCut for information on options."
2219     );
2220     parameters[numberParameters++] =
2221          CbcOrClpParam("greedy!Heuristic", "Whether to use a greedy heuristic",
2222                        "off", CBC_PARAM_STR_GREEDY);
2223     parameters[numberParameters-1].append("on");
2224     parameters[numberParameters-1].append("both");
2225     parameters[numberParameters-1].append("before");
2226     //parameters[numberParameters-1].append("root");
2227     parameters[numberParameters-1].setLonghelp
2228     (
2229          "Switches on a greedy heuristic which will try and obtain a solution.  It may just fix a \
2230percentage of variables and then try a small branch and cut run. \
2231See Rounding for meaning of on,both,before"
2232     );
2233#endif
2234     parameters[numberParameters++] =
2235          CbcOrClpParam("gsolu!tion", "Puts glpk solution to file",
2236                        CLP_PARAM_ACTION_GMPL_SOLUTION);
2237     parameters[numberParameters-1].setLonghelp
2238     (
2239          "Will write a glpk solution file to the given file name.  It will use the default\
2240 directory given by 'directory'.  A name of '$' will use the previous value for the name.  This\
2241 is initialized to 'stdout' (this defaults to ordinary solution if stdout). \
2242If problem created from gmpl model - will do any reports."
2243     );
2244#ifdef COIN_HAS_CBC
2245     parameters[numberParameters++] =
2246          CbcOrClpParam("heur!isticsOnOff", "Switches most heuristics on or off",
2247                        "off", CBC_PARAM_STR_HEURISTICSTRATEGY);
2248     parameters[numberParameters-1].append("on");
2249     parameters[numberParameters-1].setLonghelp
2250     (
2251          "This can be used to switch on or off all heuristics.  Then you can do \
2252individual ones off or on.  CbcTreeLocal is not included as it dramatically \
2253alters search."
2254     );
2255#endif
2256     parameters[numberParameters++] =
2257          CbcOrClpParam("help", "Print out version, non-standard options and some help",
2258                        CLP_PARAM_ACTION_HELP, 3);
2259     parameters[numberParameters-1].setLonghelp
2260     (
2261          "This prints out some help to get user started.  If you have printed this then \
2262you should be past that stage:-)"
2263     );
2264#ifdef COIN_HAS_CBC
2265     parameters[numberParameters++] =
2266          CbcOrClpParam("hOp!tions", "Heuristic options",
2267                        -9999999, 9999999, CBC_PARAM_INT_HOPTIONS, 1);
2268     parameters[numberParameters-1].setLonghelp
2269     (
2270          "1 says stop heuristic immediately allowable gap reached. \
2271Others are for feasibility pump - \
22722 says do exact number of passes given, \
22734 only applies if initial cutoff given and says relax after 50 passes, \
2274while 8 will adapt cutoff rhs after first solution if it looks as if code is stalling."
2275     );
2276     parameters[numberParameters-1].setIntValue(0);
2277     parameters[numberParameters++] =
2278          CbcOrClpParam("hot!StartMaxIts", "Maximum iterations on hot start",
2279                        0, COIN_INT_MAX, CBC_PARAM_INT_MAXHOTITS);
2280#endif
2281#ifdef COIN_HAS_CLP
2282     parameters[numberParameters++] =
2283          CbcOrClpParam("idiot!Crash", "Whether to try idiot crash",
2284                        -1, 99999999, CLP_PARAM_INT_IDIOT);
2285     parameters[numberParameters-1].setLonghelp
2286     (
2287          "This is a type of 'crash' which works well on some homogeneous problems.\
2288 It works best on problems with unit elements and rhs but will do something to any model.  It should only be\
2289 used before primal.  It can be set to -1 when the code decides for itself whether to use it,\
2290 0 to switch off or n > 0 to do n passes."
2291     );
2292#endif
2293     parameters[numberParameters++] =
2294          CbcOrClpParam("import", "Import model from mps file",
2295                        CLP_PARAM_ACTION_IMPORT, 3);
2296     parameters[numberParameters-1].setLonghelp
2297     (
2298          "This will read an MPS format file from the given file name.  It will use the default\
2299 directory given by 'directory'.  A name of '$' will use the previous value for the name.  This\
2300 is initialized to '', i.e. it must be set.  If you have libgz then it can read compressed\
2301 files 'xxxxxxxx.gz' or 'xxxxxxxx.bz2'.  \
2302If 'keepnames' is off, then names are dropped -> Rnnnnnnn and Cnnnnnnn."
2303     );
2304#ifdef COIN_HAS_CBC
2305     parameters[numberParameters++] =
2306          CbcOrClpParam("inc!rement", "A valid solution must be at least this \
2307much better than last integer solution",
2308                        -1.0e20, 1.0e20, CBC_PARAM_DBL_INCREMENT);
2309     parameters[numberParameters-1].setLonghelp
2310     (
2311          "Whenever a solution is found the bound on solutions is set to solution (in a minimization\
2312sense) plus this.  If it is not set then the code will try and work one out e.g. if \
2313all objective coefficients are multiples of 0.01 and only integer variables have entries in \
2314objective then this can be set to 0.01.  Be careful if you set this negative!"
2315     );
2316     parameters[numberParameters++] =
2317          CbcOrClpParam("inf!easibilityWeight", "Each integer infeasibility is expected \
2318to cost this much",
2319                        0.0, 1.0e20, CBC_PARAM_DBL_INFEASIBILITYWEIGHT, 1);
2320     parameters[numberParameters-1].setLonghelp
2321     (
2322          "A primitive way of deciding which node to explore next.  Satisfying each integer infeasibility is \
2323expected to cost this much."
2324     );
2325     parameters[numberParameters++] =
2326          CbcOrClpParam("initialS!olve", "Solve to continuous",
2327                        CLP_PARAM_ACTION_SOLVECONTINUOUS);
2328     parameters[numberParameters-1].setLonghelp
2329     (
2330          "This just solves the problem to continuous - without adding any cuts"
2331     );
2332     parameters[numberParameters++] =
2333          CbcOrClpParam("integerT!olerance", "For an optimal solution \
2334no integer variable may be this away from an integer value",
2335                        1.0e-20, 0.5, CBC_PARAM_DBL_INTEGERTOLERANCE);
2336     parameters[numberParameters-1].setLonghelp
2337     (
2338          "Beware of setting this smaller than the primal tolerance."
2339     );
2340#endif
2341#ifdef COIN_HAS_CLP
2342     parameters[numberParameters++] =
2343          CbcOrClpParam("keepN!ames", "Whether to keep names from import",
2344                        "on", CLP_PARAM_STR_KEEPNAMES);
2345     parameters[numberParameters-1].append("off");
2346     parameters[numberParameters-1].setLonghelp
2347     (
2348          "It saves space to get rid of names so if you need to you can set this to off.  \
2349This needs to be set before the import of model - so -keepnames off -import xxxxx.mps."
2350     );
2351     parameters[numberParameters++] =
2352          CbcOrClpParam("KKT", "Whether to use KKT factorization",
2353                        "off", CLP_PARAM_STR_KKT, 7, 1);
2354     parameters[numberParameters-1].append("on");
2355#endif
2356#ifdef COIN_HAS_CBC
2357     parameters[numberParameters++] =
2358          CbcOrClpParam("knapsack!Cuts", "Whether to use Knapsack cuts",
2359                        "off", CBC_PARAM_STR_KNAPSACKCUTS);
2360     parameters[numberParameters-1].append("on");
2361     parameters[numberParameters-1].append("root");
2362     parameters[numberParameters-1].append("ifmove");
2363     parameters[numberParameters-1].append("forceOn");
2364     parameters[numberParameters-1].append("onglobal");
2365     parameters[numberParameters-1].append("forceandglobal");
2366     parameters[numberParameters-1].setLonghelp
2367     (
2368          "This switches on knapsack cuts (either at root or in entire tree) \
2369See branchAndCut for information on options."
2370     );
2371     parameters[numberParameters++] =
2372          CbcOrClpParam("lagomory!Cuts", "Whether to use Lagrangean Gomory cuts",
2373                        "off", CBC_PARAM_STR_LAGOMORYCUTS);
2374     parameters[numberParameters-1].append("endonlyroot");
2375     parameters[numberParameters-1].append("endcleanroot");
2376     parameters[numberParameters-1].append("endbothroot");
2377     parameters[numberParameters-1].append("endonly");
2378     parameters[numberParameters-1].append("endclean");
2379     parameters[numberParameters-1].append("endboth");
2380     parameters[numberParameters-1].append("onlyaswell");
2381     parameters[numberParameters-1].append("cleanaswell");
2382     parameters[numberParameters-1].append("bothaswell");
2383     parameters[numberParameters-1].append("onlyinstead");
2384     parameters[numberParameters-1].append("cleaninstead");
2385     parameters[numberParameters-1].append("bothinstead");
2386     parameters[numberParameters-1].setLonghelp
2387     (
2388          "This is a gross simplification of 'A Relax-and-Cut Framework for Gomory's Mixed-Integer Cuts' \
2389by Matteo Fischetti & Domenico Salvagnin.  This simplification \
2390just uses original constraints while modifying objective using other cuts. \
2391So you don't use messy constraints generated by Gomory etc. \
2392A variant is to allow non messy cuts e.g. clique cuts. \
2393So 'only' does this while clean also allows integral valued cuts.  \
2394'End' is recommended which waits until other cuts have finished and then \
2395does a few passes. \
2396The length options for gomory cuts are used."
2397     );
2398     parameters[numberParameters++] =
2399          CbcOrClpParam("latwomir!Cuts", "Whether to use Lagrangean TwoMir cuts",
2400                        "off", CBC_PARAM_STR_LATWOMIRCUTS);
2401     parameters[numberParameters-1].append("endonlyroot");
2402     parameters[numberParameters-1].append("endcleanroot");
2403     parameters[numberParameters-1].append("endbothroot");
2404     parameters[numberParameters-1].append("endonly");
2405     parameters[numberParameters-1].append("endclean");
2406     parameters[numberParameters-1].append("endboth");
2407     parameters[numberParameters-1].append("onlyaswell");
2408     parameters[numberParameters-1].append("cleanaswell");
2409     parameters[numberParameters-1].append("bothaswell");
2410     parameters[numberParameters-1].append("onlyinstead");
2411     parameters[numberParameters-1].append("cleaninstead");
2412     parameters[numberParameters-1].append("bothinstead");
2413     parameters[numberParameters-1].setLonghelp
2414     (
2415          "This is a lagrangean relaxation for TwoMir cuts.  See \
2416lagomoryCuts for description of options."
2417     );
2418     parameters[numberParameters++] =
2419          CbcOrClpParam("lift!AndProjectCuts", "Whether to use Lift and Project cuts",
2420                        "off", CBC_PARAM_STR_LANDPCUTS);
2421     parameters[numberParameters-1].append("on");
2422     parameters[numberParameters-1].append("root");
2423     parameters[numberParameters-1].append("ifmove");
2424     parameters[numberParameters-1].append("forceOn");
2425     parameters[numberParameters-1].setLonghelp
2426     (
2427          "Lift and project cuts. \
2428May be slow \
2429See branchAndCut for information on options."
2430     );
2431     parameters[numberParameters++] =
2432          CbcOrClpParam("local!TreeSearch", "Whether to use local treesearch",
2433                        "off", CBC_PARAM_STR_LOCALTREE);
2434     parameters[numberParameters-1].append("on");
2435     parameters[numberParameters-1].setLonghelp
2436     (
2437          "This switches on a local search algorithm when a solution is found.  This is from \
2438Fischetti and Lodi and is not really a heuristic although it can be used as one. \
2439When used from Coin solve it has limited functionality.  It is not switched on when \
2440heuristics are switched on."
2441     );
2442#endif
2443#ifndef COIN_HAS_CBC
2444     parameters[numberParameters++] =
2445          CbcOrClpParam("log!Level", "Level of detail in Solver output",
2446                        -1, 999999, CLP_PARAM_INT_SOLVERLOGLEVEL);
2447#else
2448     parameters[numberParameters++] =
2449          CbcOrClpParam("log!Level", "Level of detail in Coin branch and Cut output",
2450                        -63, 63, CLP_PARAM_INT_LOGLEVEL);
2451     parameters[numberParameters-1].setIntValue(1);
2452#endif
2453     parameters[numberParameters-1].setLonghelp
2454     (
2455          "If 0 then there should be no output in normal circumstances.  1 is probably the best\
2456 value for most uses, while 2 and 3 give more information."
2457     );
2458     parameters[numberParameters++] =
2459          CbcOrClpParam("max!imize", "Set optimization direction to maximize",
2460                        CLP_PARAM_ACTION_MAXIMIZE, 7);
2461     parameters[numberParameters-1].setLonghelp
2462     (
2463          "The default is minimize - use 'maximize' for maximization.\n\
2464You can also use the parameters 'direction maximize'."
2465     );
2466#ifdef COIN_HAS_CLP
2467     parameters[numberParameters++] =
2468          CbcOrClpParam("maxF!actor", "Maximum number of iterations between \
2469refactorizations",
2470                        1, 999999, CLP_PARAM_INT_MAXFACTOR);
2471     parameters[numberParameters-1].setLonghelp
2472     (
2473          "If this is at its initial value of 200 then in this executable clp will guess at a\
2474 value to use.  Otherwise the user can set a value.  The code may decide to re-factorize\
2475 earlier for accuracy."
2476     );
2477     parameters[numberParameters++] =
2478          CbcOrClpParam("maxIt!erations", "Maximum number of iterations before \
2479stopping",
2480                        0, 2147483647, CLP_PARAM_INT_MAXITERATION);
2481     parameters[numberParameters-1].setLonghelp
2482     (
2483          "This can be used for testing purposes.  The corresponding library call\n\
2484      \tsetMaximumIterations(value)\n can be useful.  If the code stops on\
2485 seconds or by an interrupt this will be treated as stopping on maximum iterations.  This is ignored in branchAndCut - use maxN!odes."
2486     );
2487#endif
2488#ifdef COIN_HAS_CBC
2489     parameters[numberParameters++] =
2490          CbcOrClpParam("maxN!odes", "Maximum number of nodes to do",
2491                        -1, 2147483647, CBC_PARAM_INT_MAXNODES);
2492     parameters[numberParameters-1].setLonghelp
2493     (
2494          "This is a repeatable way to limit search.  Normally using time is easier \
2495but then the results may not be repeatable."
2496     );
2497     parameters[numberParameters++] =
2498          CbcOrClpParam("maxSaved!Solutions", "Maximum number of solutions to save",
2499                        0, 2147483647, CBC_PARAM_INT_MAXSAVEDSOLS);
2500     parameters[numberParameters-1].setLonghelp
2501     (
2502          "Number of solutions to save."
2503     );
2504     parameters[numberParameters++] =
2505          CbcOrClpParam("maxSo!lutions", "Maximum number of solutions to get",
2506                        1, 2147483647, CBC_PARAM_INT_MAXSOLS);
2507     parameters[numberParameters-1].setLonghelp
2508     (
2509          "You may want to stop after (say) two solutions or an hour.  \
2510This is checked every node in tree, so it is possible to get more solutions from heuristics."
2511     );
2512#endif
2513     parameters[numberParameters++] =
2514          CbcOrClpParam("min!imize", "Set optimization direction to minimize",
2515                        CLP_PARAM_ACTION_MINIMIZE, 7);
2516     parameters[numberParameters-1].setLonghelp
2517     (
2518          "The default is minimize - use 'maximize' for maximization.\n\
2519This should only be necessary if you have previously set maximization \
2520You can also use the parameters 'direction minimize'."
2521     );
2522#ifdef COIN_HAS_CBC
2523     parameters[numberParameters++] =
2524          CbcOrClpParam("mipO!ptions", "Dubious options for mip",
2525                        0, COIN_INT_MAX, CBC_PARAM_INT_MIPOPTIONS, 0);
2526     parameters[numberParameters++] =
2527          CbcOrClpParam("more!MipOptions", "More dubious options for mip",
2528                        -1, COIN_INT_MAX, CBC_PARAM_INT_MOREMIPOPTIONS, 0);
2529     parameters[numberParameters++] =
2530          CbcOrClpParam("mixed!IntegerRoundingCuts", "Whether to use Mixed Integer Rounding cuts",
2531                        "off", CBC_PARAM_STR_MIXEDCUTS);
2532     parameters[numberParameters-1].append("on");
2533     parameters[numberParameters-1].append("root");
2534     parameters[numberParameters-1].append("ifmove");
2535     parameters[numberParameters-1].append("forceOn");
2536     parameters[numberParameters-1].append("onglobal");
2537     parameters[numberParameters-1].setLonghelp
2538     (
2539          "This switches on mixed integer rounding cuts (either at root or in entire tree) \
2540See branchAndCut for information on options."
2541     );
2542#endif
2543     parameters[numberParameters++] =
2544          CbcOrClpParam("mess!ages", "Controls if Clpnnnn is printed",
2545                        "off", CLP_PARAM_STR_MESSAGES);
2546     parameters[numberParameters-1].append("on");
2547     parameters[numberParameters-1].setLonghelp
2548     ("The default behavior is to put out messages such as:\n\
2549   Clp0005 2261  Objective 109.024 Primal infeas 944413 (758)\n\
2550but this program turns this off to make it look more friendly.  It can be useful\
2551 to turn them back on if you want to be able to 'grep' for particular messages or if\
2552 you intend to override the behavior of a particular message.  This only affects Clp not Cbc."
2553     );
2554     parameters[numberParameters++] =
2555          CbcOrClpParam("miplib", "Do some of miplib test set",
2556                        CBC_PARAM_ACTION_MIPLIB, 3, 1);
2557#ifdef COIN_HAS_CBC
2558      parameters[numberParameters++] =
2559          CbcOrClpParam("mips!tart", "reads an initial feasible solution from file",
2560                        CBC_PARAM_ACTION_MIPSTART);
2561     parameters[numberParameters-1].setLonghelp
2562     ("\
2563The MIPStart allows one to enter an initial integer feasible solution \
2564to CBC. Values of the main decision variables which are active (have \
2565non-zero values) in this solution are specified in a text  file. The \
2566text file format used is the same of the solutions saved by CBC, but \
2567not all fields are required to be filled. First line may contain the \
2568solution status and will be ignored, remaining lines contain column \
2569indexes, names and values as in this example:\n\
2570\n\
2571Stopped on iterations - objective value 57597.00000000\n\
2572      0  x(1,1,2,2)               1 \n\
2573      1  x(3,1,3,2)               1 \n\
2574      5  v(5,1)                   2 \n\
2575      33 x(8,1,5,2)               1 \n\
2576      ...\n\
2577\n\
2578Column indexes are also ignored since pre-processing can change them. \
2579There is no need to include values for continuous or integer auxiliary \
2580variables, since they can be computed based on main decision variables. \
2581Starting CBC with an integer feasible solution can dramatically improve \
2582its performance: several MIP heuristics (e.g. RINS) rely on having at \
2583least one feasible solution available and can start immediately if the \
2584user provides one. Feasibility Pump (FP) is a heuristic which tries to \
2585overcome the problem of taking too long to find feasible solution (or \
2586not finding at all), but it not always succeeds. If you provide one \
2587starting solution you will probably save some time by disabling FP. \
2588\n\n\
2589Knowledge specific to your problem can be considered to write an \
2590external module to quickly produce an initial feasible solution - some \
2591alternatives are the implementation of simple greedy heuristics or the \
2592solution (by CBC for example) of a simpler model created just to find \
2593a feasible solution. \
2594\n\n\
2595Question and suggestions regarding MIPStart can be directed to\n\
2596haroldo.santos@gmail.com.\
2597");
2598#endif
2599     parameters[numberParameters++] =
2600          CbcOrClpParam("moreS!pecialOptions", "Yet more dubious options for Simplex - see ClpSimplex.hpp",
2601                        0, COIN_INT_MAX, CLP_PARAM_INT_MORESPECIALOPTIONS, 0);
2602#ifdef COIN_HAS_CBC
2603     parameters[numberParameters++] =
2604          CbcOrClpParam("moreT!une", "Yet more dubious ideas for feasibility pump",
2605                        0, 100000000, CBC_PARAM_INT_FPUMPTUNE2, 0);
2606     parameters[numberParameters-1].setLonghelp
2607     (
2608          "Yet more ideas for Feasibility Pump \n\
2609\t/100000 == 1 use box constraints and original obj in cleanup\n\
2610\t/1000 == 1 Pump will run twice if no solution found\n\
2611\t/1000 == 2 Pump will only run after root cuts if no solution found\n\
2612\t/1000 >10 as above but even if solution found\n\
2613\t/100 == 1,3.. exact 1.0 for objective values\n\
2614\t/100 == 2,3.. allow more iterations per pass\n\
2615\t n fix if value of variable same for last n iterations."
2616     );
2617     parameters[numberParameters-1].setIntValue(0);
2618     parameters[numberParameters++] =
2619          CbcOrClpParam("multiple!RootPasses", "Do multiple root passes to collect cuts and solutions",
2620                        0, 100000000, CBC_PARAM_INT_MULTIPLEROOTS, 0);
2621     parameters[numberParameters-1].setIntValue(0);
2622     parameters[numberParameters-1].setLonghelp
2623     (
2624          "Do (in parallel if threads enabled) the root phase this number of times \
2625 and collect all solutions and cuts generated.  The actual format is aabbcc \
2626where aa is number of extra passes, if bb is non zero \
2627then it is number of threads to use (otherwise uses threads setting) and \
2628cc is number of times to do root phase.  Yet another one from the Italian idea factory \
2629(This time - Andrea Lodi , Matteo Fischetti , Michele Monaci , Domenico Salvagnin , \
2630and Andrea Tramontani). \
2631The solvers do not interact with each other.  However if extra passes are specified \
2632then cuts are collected and used in later passes - so there is interaction there." 
2633     );
2634     parameters[numberParameters++] =
2635          CbcOrClpParam("naive!Heuristics", "Whether to try some stupid heuristic",
2636                        "off", CBC_PARAM_STR_NAIVE, 7, 1);
2637     parameters[numberParameters-1].append("on");
2638     parameters[numberParameters-1].append("both");
2639     parameters[numberParameters-1].append("before");
2640     parameters[numberParameters-1].setLonghelp
2641     (
2642          "Really silly stuff e.g. fix all integers with costs to zero!. \
2643Doh option does heuristic before preprocessing"     );
2644#endif
2645#ifdef COIN_HAS_CLP
2646     parameters[numberParameters++] =
2647          CbcOrClpParam("netlib", "Solve entire netlib test set",
2648                        CLP_PARAM_ACTION_NETLIB_EITHER, 3, 1);
2649     parameters[numberParameters-1].setLonghelp
2650     (
2651          "This exercises the unit test for clp and then solves the netlib test set using dual or primal.\
2652The user can set options before e.g. clp -presolve off -netlib"
2653     );
2654     parameters[numberParameters++] =
2655          CbcOrClpParam("netlibB!arrier", "Solve entire netlib test set with barrier",
2656                        CLP_PARAM_ACTION_NETLIB_BARRIER, 3, 1);
2657     parameters[numberParameters-1].setLonghelp
2658     (
2659          "This exercises the unit test for clp and then solves the netlib test set using barrier.\
2660The user can set options before e.g. clp -kkt on -netlib"
2661     );
2662     parameters[numberParameters++] =
2663          CbcOrClpParam("netlibD!ual", "Solve entire netlib test set (dual)",
2664                        CLP_PARAM_ACTION_NETLIB_DUAL, 3, 1);
2665     parameters[numberParameters-1].setLonghelp
2666     (
2667          "This exercises the unit test for clp and then solves the netlib test set using dual.\
2668The user can set options before e.g. clp -presolve off -netlib"
2669     );
2670     parameters[numberParameters++] =
2671          CbcOrClpParam("netlibP!rimal", "Solve entire netlib test set (primal)",
2672                        CLP_PARAM_ACTION_NETLIB_PRIMAL, 3, 1);
2673     parameters[numberParameters-1].setLonghelp
2674     (
2675          "This exercises the unit test for clp and then solves the netlib test set using primal.\
2676The user can set options before e.g. clp -presolve off -netlibp"
2677     );
2678     parameters[numberParameters++] =
2679          CbcOrClpParam("netlibT!une", "Solve entire netlib test set with 'best' algorithm",
2680                        CLP_PARAM_ACTION_NETLIB_TUNE, 3, 1);
2681     parameters[numberParameters-1].setLonghelp
2682     (
2683          "This exercises the unit test for clp and then solves the netlib test set using whatever \
2684works best.  I know this is cheating but it also stresses the code better by doing a \
2685mixture of stuff.  The best algorithm was chosen on a Linux ThinkPad using native cholesky \
2686with University of Florida ordering."
2687     );
2688     parameters[numberParameters++] =
2689          CbcOrClpParam("network", "Tries to make network matrix",
2690                        CLP_PARAM_ACTION_NETWORK, 7, 0);
2691     parameters[numberParameters-1].setLonghelp
2692     (
2693          "Clp will go faster if the matrix can be converted to a network.  The matrix\
2694 operations may be a bit faster with more efficient storage, but the main advantage\
2695 comes from using a network factorization.  It will probably not be as fast as a \
2696specialized network code."
2697     );
2698#ifdef COIN_HAS_CBC
2699     parameters[numberParameters++] =
2700          CbcOrClpParam("nextB!estSolution", "Prints next best saved solution to file",
2701                        CLP_PARAM_ACTION_NEXTBESTSOLUTION);
2702     parameters[numberParameters-1].setLonghelp
2703     (
2704          "To write best solution, just use solution.  This prints next best (if exists) \
2705 and then deletes it. \
2706 This will write a primitive solution file to the given file name.  It will use the default\
2707 directory given by 'directory'.  A name of '$' will use the previous value for the name.  This\
2708 is initialized to 'stdout'.  The amount of output can be varied using printi!ngOptions or printMask."
2709     );
2710     parameters[numberParameters++] =
2711          CbcOrClpParam("node!Strategy", "What strategy to use to select nodes",
2712                        "hybrid", CBC_PARAM_STR_NODESTRATEGY);
2713     parameters[numberParameters-1].append("fewest");
2714     parameters[numberParameters-1].append("depth");
2715     parameters[numberParameters-1].append("upfewest");
2716     parameters[numberParameters-1].append("downfewest");
2717     parameters[numberParameters-1].append("updepth");
2718     parameters[numberParameters-1].append("downdepth");
2719     parameters[numberParameters-1].setLonghelp
2720     (
2721          "Normally before a solution the code will choose node with fewest infeasibilities. \
2722You can choose depth as the criterion.  You can also say if up or down branch must \
2723be done first (the up down choice will carry on after solution). \
2724Default has now been changed to hybrid which is breadth first on small depth nodes then fewest."
2725     );
2726     parameters[numberParameters++] =
2727          CbcOrClpParam("numberA!nalyze", "Number of analysis iterations",
2728                        -COIN_INT_MAX, COIN_INT_MAX, CBC_PARAM_INT_NUMBERANALYZE, 0);
2729     parameters[numberParameters-1].setLonghelp
2730     (
2731          "This says how many iterations to spend at root node analyzing problem. \
2732This is a first try and will hopefully become more sophisticated."
2733     );
2734#endif
2735     parameters[numberParameters++] =
2736          CbcOrClpParam("objective!Scale", "Scale factor to apply to objective",
2737                        -1.0e20, 1.0e20, CLP_PARAM_DBL_OBJSCALE, 1);
2738     parameters[numberParameters-1].setLonghelp
2739     (
2740          "If the objective function has some very large values, you may wish to scale them\
2741 internally by this amount.  It can also be set by autoscale.  It is applied after scaling.  You are unlikely to need this."
2742     );
2743     parameters[numberParameters-1].setDoubleValue(1.0);
2744#endif
2745#ifdef COIN_HAS_CBC
2746     parameters[numberParameters++] =
2747          CbcOrClpParam("outDup!licates", "takes duplicate rows etc out of integer model",
2748                        CLP_PARAM_ACTION_OUTDUPROWS, 7, 0);
2749#endif
2750     parameters[numberParameters++] =
2751          CbcOrClpParam("output!Format", "Which output format to use",
2752                        1, 6, CLP_PARAM_INT_OUTPUTFORMAT);
2753     parameters[numberParameters-1].setLonghelp
2754     (
2755          "Normally export will be done using normal representation for numbers and two values\
2756 per line.  You may want to do just one per line (for grep or suchlike) and you may wish\
2757 to save with absolute accuracy using a coded version of the IEEE value. A value of 2 is normal.\
2758 otherwise odd values gives one value per line, even two.  Values 1,2 give normal format, 3,4\
2759 gives greater precision, while 5,6 give IEEE values.  When used for exporting a basis 1 does not save \
2760values, 2 saves values, 3 with greater accuracy and 4 in IEEE."
2761     );
2762#ifdef COIN_HAS_CLP
2763     parameters[numberParameters++] =
2764          CbcOrClpParam("para!metrics", "Import data from file and do parametrics",
2765                        CLP_PARAM_ACTION_PARAMETRICS, 3);
2766     parameters[numberParameters-1].setLonghelp
2767     (
2768          "This will read a file with parametric data from the given file name \
2769and then do parametrics.  It will use the default\
2770 directory given by 'directory'.  A name of '$' will use the previous value for the name.  This\
2771 is initialized to '', i.e. it must be set.  This can not read from compressed files. \
2772File is in modified csv format - a line ROWS will be followed by rows data \
2773while a line COLUMNS will be followed by column data.  The last line \
2774should be ENDATA. The ROWS line must exist and is in the format \
2775ROWS, inital theta, final theta, interval theta, n where n is 0 to get \
2776CLPI0062 message at interval or at each change of theta \
2777and 1 to get CLPI0063 message at each iteration.  If interval theta is 0.0 \
2778or >= final theta then no interval reporting.  n may be missed out when it is \
2779taken as 0.  If there is Row data then \
2780there is a headings line with allowed headings - name, number, \
2781lower(rhs change), upper(rhs change), rhs(change).  Either the lower and upper \
2782fields should be given or the rhs field. \
2783The optional COLUMNS line is followed by a headings line with allowed \
2784headings - name, number, objective(change), lower(change), upper(change). \
2785 Exactly one of name and number must be given for either section and \
2786missing ones have value 0.0."
2787     );
2788#endif
2789#ifdef COIN_HAS_CBC
2790     parameters[numberParameters++] =
2791          CbcOrClpParam("passC!uts", "Number of cut passes at root node",
2792                        -9999999, 9999999, CBC_PARAM_INT_CUTPASS);
2793     parameters[numberParameters-1].setLonghelp
2794     (
2795          "The default is 100 passes if less than 500 columns, 100 passes (but \
2796stop if drop small if less than 5000 columns, 20 otherwise"
2797     );
2798     parameters[numberParameters++] =
2799          CbcOrClpParam("passF!easibilityPump", "How many passes in feasibility pump",
2800                        0, 10000, CBC_PARAM_INT_FPUMPITS);
2801     parameters[numberParameters-1].setLonghelp
2802     (
2803          "This fine tunes Feasibility Pump by doing more or fewer passes."
2804     );
2805     parameters[numberParameters-1].setIntValue(20);
2806#endif
2807#ifdef COIN_HAS_CLP
2808     parameters[numberParameters++] =
2809          CbcOrClpParam("passP!resolve", "How many passes in presolve",
2810                        -200, 100, CLP_PARAM_INT_PRESOLVEPASS, 1);
2811     parameters[numberParameters-1].setLonghelp
2812     (
2813          "Normally Presolve does 5 passes but you may want to do less to make it\
2814 more lightweight or do more if improvements are still being made.  As Presolve will return\
2815 if nothing is being taken out, you should not normally need to use this fine tuning."
2816     );
2817#endif
2818#ifdef COIN_HAS_CBC
2819     parameters[numberParameters++] =
2820          CbcOrClpParam("passT!reeCuts", "Number of cut passes in tree",
2821                        -9999999, 9999999, CBC_PARAM_INT_CUTPASSINTREE);
2822     parameters[numberParameters-1].setLonghelp
2823     (
2824          "The default is one pass"
2825     );
2826#endif
2827#ifdef COIN_HAS_CLP
2828     parameters[numberParameters++] =
2829          CbcOrClpParam("pertV!alue", "Method of perturbation",
2830                        -5000, 102, CLP_PARAM_INT_PERTVALUE, 1);
2831     parameters[numberParameters++] =
2832          CbcOrClpParam("perturb!ation", "Whether to perturb problem",
2833                        "on", CLP_PARAM_STR_PERTURBATION);
2834     parameters[numberParameters-1].append("off");
2835     parameters[numberParameters-1].setLonghelp
2836     (
2837          "Perturbation helps to stop cycling, but Clp uses other measures for this.\
2838  However large problems and especially ones with unit elements and unit rhs or costs\
2839 benefit from perturbation.  Normally Clp tries to be intelligent, but you can switch this off.\
2840  The Clp library has this off by default.  This program has it on by default."
2841     );
2842     parameters[numberParameters++] =
2843          CbcOrClpParam("PFI", "Whether to use Product Form of Inverse in simplex",
2844                        "off", CLP_PARAM_STR_PFI, 7, 0);
2845     parameters[numberParameters-1].append("on");
2846     parameters[numberParameters-1].setLonghelp
2847     (
2848          "By default clp uses Forrest-Tomlin L-U update.  If you are masochistic you can switch it off."
2849     );
2850#endif
2851#ifdef COIN_HAS_CBC
2852     parameters[numberParameters++] =
2853          CbcOrClpParam("pivotAndC!omplement", "Whether to try Pivot and Complement heuristic",
2854                        "off", CBC_PARAM_STR_PIVOTANDCOMPLEMENT);
2855     parameters[numberParameters-1].append("on");
2856     parameters[numberParameters-1].append("both");
2857     parameters[numberParameters-1].append("before");
2858     parameters[numberParameters-1].setLonghelp
2859     (
2860          "stuff needed. \
2861Doh option does heuristic before preprocessing"     );
2862     parameters[numberParameters++] =
2863          CbcOrClpParam("pivotAndF!ix", "Whether to try Pivot and Fix heuristic",
2864                        "off", CBC_PARAM_STR_PIVOTANDFIX);
2865     parameters[numberParameters-1].append("on");
2866     parameters[numberParameters-1].append("both");
2867     parameters[numberParameters-1].append("before");
2868     parameters[numberParameters-1].setLonghelp
2869     (
2870          "stuff needed. \
2871Doh option does heuristic before preprocessing"     );
2872#endif
2873#ifdef COIN_HAS_CLP
2874     parameters[numberParameters++] =
2875          CbcOrClpParam("plus!Minus", "Tries to make +- 1 matrix",
2876                        CLP_PARAM_ACTION_PLUSMINUS, 7, 0);
2877     parameters[numberParameters-1].setLonghelp
2878     (
2879          "Clp will go slightly faster if the matrix can be converted so that the elements are\
2880 not stored and are known to be unit.  The main advantage is memory use.  Clp may automatically\
2881 see if it can convert the problem so you should not need to use this."
2882     );
2883     parameters[numberParameters++] =
2884          CbcOrClpParam("pO!ptions", "Dubious print options",
2885                        0, COIN_INT_MAX, CLP_PARAM_INT_PRINTOPTIONS, 1);
2886     parameters[numberParameters-1].setIntValue(0);
2887     parameters[numberParameters-1].setLonghelp
2888     (
2889          "If this is > 0 then presolve will give more information and branch and cut will give statistics"
2890     );
2891     parameters[numberParameters++] =
2892          CbcOrClpParam("preO!pt", "Presolve options",
2893                        0, COIN_INT_MAX, CLP_PARAM_INT_PRESOLVEOPTIONS, 0);
2894#endif
2895     parameters[numberParameters++] =
2896          CbcOrClpParam("presolve", "Whether to presolve problem",
2897                        "on", CLP_PARAM_STR_PRESOLVE);
2898     parameters[numberParameters-1].append("off");
2899     parameters[numberParameters-1].append("more");
2900     parameters[numberParameters-1].append("file");
2901     parameters[numberParameters-1].setLonghelp
2902     (
2903          "Presolve analyzes the model to find such things as redundant equations, equations\
2904 which fix some variables, equations which can be transformed into bounds etc etc.  For the\
2905 initial solve of any problem this is worth doing unless you know that it will have no effect.  \
2906on will normally do 5 passes while using 'more' will do 10.  If the problem is very large you may need \
2907to write the original to file using 'file'."
2908     );
2909#ifdef COIN_HAS_CBC
2910     parameters[numberParameters++] =
2911          CbcOrClpParam("preprocess", "Whether to use integer preprocessing",
2912                        "off", CBC_PARAM_STR_PREPROCESS);
2913     parameters[numberParameters-1].append("on");
2914     parameters[numberParameters-1].append("save");
2915     parameters[numberParameters-1].append("equal");
2916     parameters[numberParameters-1].append("sos");
2917     parameters[numberParameters-1].append("trysos");
2918     parameters[numberParameters-1].append("equalall");
2919     parameters[numberParameters-1].append("strategy");
2920     parameters[numberParameters-1].append("aggregate");
2921     parameters[numberParameters-1].append("forcesos");
2922     parameters[numberParameters-1].setLonghelp
2923     (
2924          "This tries to reduce size of model in a similar way to presolve and \
2925it also tries to strengthen the model - this can be very useful and is worth trying. \
2926 Save option saves on file presolved.mps.  equal will turn <= cliques into \
2927==.  sos will create sos sets if all 0-1 in sets (well one extra is allowed) \
2928and no overlaps.  trysos is same but allows any number extra.  equalall will turn all \
2929valid inequalities into equalities with integer slacks.  strategy is as \
2930on but uses CbcStrategy."
2931     );
2932#endif
2933#ifdef COIN_HAS_CLP
2934     parameters[numberParameters++] =
2935          CbcOrClpParam("preT!olerance", "Tolerance to use in presolve",
2936                        1.0e-20, 1.0e12, CLP_PARAM_DBL_PRESOLVETOLERANCE);
2937     parameters[numberParameters-1].setLonghelp
2938     (
2939          "The default is 1.0e-8 - you may wish to try 1.0e-7 if presolve says the problem is \
2940infeasible and you have awkward numbers and you are sure the problem is really feasible."
2941     );
2942     parameters[numberParameters++] =
2943          CbcOrClpParam("primalP!ivot", "Primal pivot choice algorithm",
2944                        "auto!matic", CLP_PARAM_STR_PRIMALPIVOT, 7, 1);
2945     parameters[numberParameters-1].append("exa!ct");
2946     parameters[numberParameters-1].append("dant!zig");
2947     parameters[numberParameters-1].append("part!ial");
2948     parameters[numberParameters-1].append("steep!est");
2949     parameters[numberParameters-1].append("change");
2950     parameters[numberParameters-1].append("sprint");
2951     parameters[numberParameters-1].setLonghelp
2952     (
2953          "Clp can use any pivot selection algorithm which the user codes as long as it\
2954 implements the features in the abstract pivot base class.  The Dantzig method is implemented\
2955 to show a simple method but its use is deprecated.  Exact devex is the method of choice and there\
2956 are two variants which keep all weights updated but only scan a subset each iteration.\
2957 Partial switches this on while change initially does dantzig until the factorization\
2958 becomes denser.  This is still a work in progress."
2959     );
2960     parameters[numberParameters++] =
2961          CbcOrClpParam("primalS!implex", "Do primal simplex algorithm",
2962                        CLP_PARAM_ACTION_PRIMALSIMPLEX);
2963     parameters[numberParameters-1].setLonghelp
2964     (
2965          "This command solves the continuous relaxation of the current model using the primal algorithm.\
2966  The default is to use exact devex.\
2967 The time and iterations may be affected by settings such as presolve, scaling, crash\
2968 and also by column selection  method, infeasibility weight and dual and primal tolerances."
2969     );
2970#endif
2971     parameters[numberParameters++] =
2972          CbcOrClpParam("primalT!olerance", "For an optimal solution \
2973no primal infeasibility may exceed this value",
2974                        1.0e-20, 1.0e12, CLP_PARAM_DBL_PRIMALTOLERANCE);
2975     parameters[numberParameters-1].setLonghelp
2976     (
2977          "Normally the default tolerance is fine, but you may want to increase it a\
2978 bit if a primal run seems to be having a hard time"
2979     );
2980#ifdef COIN_HAS_CLP
2981     parameters[numberParameters++] =
2982          CbcOrClpParam("primalW!eight", "Initially algorithm acts as if it \
2983costs this much to be infeasible",
2984                        1.0e-20, 1.0e20, CLP_PARAM_DBL_PRIMALWEIGHT);
2985     parameters[numberParameters-1].setLonghelp
2986     (
2987          "The primal algorithm in Clp is a single phase algorithm as opposed to a two phase\
2988 algorithm where you first get feasible then optimal.  So Clp is minimizing this weight times\
2989 the sum of primal infeasibilities plus the true objective function (in minimization sense).\
2990  Too high a value may mean more iterations, while too low a bound means\
2991 the code may go all the way and then have to increase the weight in order to get feasible.\
2992  OSL had a heuristic to\
2993 adjust bounds, maybe we need that here."
2994     );
2995#endif
2996     parameters[numberParameters++] =
2997          CbcOrClpParam("printi!ngOptions", "Print options",
2998                        "normal", CLP_PARAM_STR_INTPRINT, 3);
2999     parameters[numberParameters-1].append("integer");
3000     parameters[numberParameters-1].append("special");
3001     parameters[numberParameters-1].append("rows");
3002     parameters[numberParameters-1].append("all");
3003     parameters[numberParameters-1].append("csv");
3004     parameters[numberParameters-1].append("bound!ranging");
3005     parameters[numberParameters-1].append("rhs!ranging");
3006     parameters[numberParameters-1].append("objective!ranging");
3007     parameters[numberParameters-1].append("stats");
3008     parameters[numberParameters-1].append("boundsint");
3009     parameters[numberParameters-1].append("boundsall");
3010     parameters[numberParameters-1].setLonghelp
3011     (
3012          "This changes the amount and format of printing a solution:\nnormal - nonzero column variables \n\
3013integer - nonzero integer column variables\n\
3014special - in format suitable for OsiRowCutDebugger\n\
3015rows - nonzero column variables and row activities\n\
3016all - all column variables and row activities.\n\
3017\nFor non-integer problems 'integer' and 'special' act like 'normal'.  \
3018Also see printMask for controlling output."
3019     );
3020     parameters[numberParameters++] =
3021          CbcOrClpParam("printM!ask", "Control printing of solution on a  mask",
3022                        CLP_PARAM_ACTION_PRINTMASK, 3);
3023     parameters[numberParameters-1].setLonghelp
3024     (
3025          "If set then only those names which match mask are printed in a solution. \
3026'?' matches any character and '*' matches any set of characters. \
3027 The default is '' i.e. unset so all variables are printed. \
3028This is only active if model has names."
3029     );
3030#ifdef COIN_HAS_CBC
3031     parameters[numberParameters++] =
3032          CbcOrClpParam("prio!rityIn", "Import priorities etc from file",
3033                        CBC_PARAM_ACTION_PRIORITYIN, 3);
3034     parameters[numberParameters-1].setLonghelp
3035     (
3036          "This will read a file with priorities from the given file name.  It will use the default\
3037 directory given by 'directory'.  A name of '$' will use the previous value for the name.  This\
3038 is initialized to '', i.e. it must be set.  This can not read from compressed files. \
3039File is in csv format with allowed headings - name, number, priority, direction, up, down, solution.  Exactly one of\
3040 name and number must be given."
3041     );
3042     parameters[numberParameters++] =
3043          CbcOrClpParam("probing!Cuts", "Whether to use Probing cuts",
3044                        "off", CBC_PARAM_STR_PROBINGCUTS);
3045     parameters[numberParameters-1].append("on");
3046     parameters[numberParameters-1].append("root");
3047     parameters[numberParameters-1].append("ifmove");
3048     parameters[numberParameters-1].append("forceOn");
3049     parameters[numberParameters-1].append("onglobal");
3050     parameters[numberParameters-1].append("forceonglobal");
3051     parameters[numberParameters-1].append("forceOnBut");
3052     parameters[numberParameters-1].append("forceOnStrong");
3053     parameters[numberParameters-1].append("forceOnButStrong");
3054     parameters[numberParameters-1].append("strongRoot");
3055     parameters[numberParameters-1].setLonghelp
3056     (
3057          "This switches on probing cuts (either at root or in entire tree) \
3058See branchAndCut for information on options. \
3059but strong options do more probing"
3060     );
3061     parameters[numberParameters++] =
3062          CbcOrClpParam("proximity!Search", "Whether to do proximity search heuristic",
3063                        "off", CBC_PARAM_STR_PROXIMITY);
3064     parameters[numberParameters-1].append("on");
3065     parameters[numberParameters-1].append("both");
3066     parameters[numberParameters-1].append("before");
3067     parameters[numberParameters-1].append("10");
3068     parameters[numberParameters-1].append("100");
3069     parameters[numberParameters-1].append("300");
3070     parameters[numberParameters-1].setLonghelp
3071     (
3072          "This switches on a heuristic which looks for a solution close \
3073to incumbent solution (Fischetti and Monaci). \
3074See Rounding for meaning of on,both,before. \
3075The ones at end have different maxNode settings (and are 'on'(on==30))."
3076     );
3077     parameters[numberParameters++] =
3078          CbcOrClpParam("pumpC!utoff", "Fake cutoff for use in feasibility pump",
3079                        -COIN_DBL_MAX, COIN_DBL_MAX, CBC_PARAM_DBL_FAKECUTOFF);
3080     parameters[numberParameters-1].setDoubleValue(0.0);
3081     parameters[numberParameters-1].setLonghelp
3082     (
3083          "0.0 off - otherwise add a constraint forcing objective below this value\
3084 in feasibility pump"
3085     );
3086     parameters[numberParameters++] =
3087          CbcOrClpParam("pumpI!ncrement", "Fake increment for use in feasibility pump",
3088                        -COIN_DBL_MAX, COIN_DBL_MAX, CBC_PARAM_DBL_FAKEINCREMENT, 1);
3089     parameters[numberParameters-1].setDoubleValue(0.0);
3090     parameters[numberParameters-1].setLonghelp
3091     (
3092          "0.0 off - otherwise use as absolute increment to cutoff \
3093when solution found in feasibility pump"
3094     );
3095     parameters[numberParameters++] =
3096          CbcOrClpParam("pumpT!une", "Dubious ideas for feasibility pump",
3097                        0, 100000000, CBC_PARAM_INT_FPUMPTUNE);
3098     parameters[numberParameters-1].setLonghelp
3099     (
3100          "This fine tunes Feasibility Pump \n\
3101\t>=10000000 use as objective weight switch\n\
3102\t>=1000000 use as accumulate switch\n\
3103\t>=1000 use index+1 as number of large loops\n\
3104\t==100 use objvalue +0.05*fabs(objvalue) as cutoff OR fakeCutoff if set\n\
3105\t%100 == 10,20 affects how each solve is done\n\
3106\t1 == fix ints at bounds, 2 fix all integral ints, 3 and continuous at bounds. \
3107If accumulate is on then after a major pass, variables which have not moved \
3108are fixed and a small branch and bound is tried."
3109     );
3110     parameters[numberParameters-1].setIntValue(0);
3111#endif
3112     parameters[numberParameters++] =
3113          CbcOrClpParam("quit", "Stops clp execution",
3114                        CLP_PARAM_ACTION_EXIT);
3115     parameters[numberParameters-1].setLonghelp
3116     (
3117          "This stops the execution of Clp, end, exit, quit and stop are synonyms"
3118     );
3119#ifdef COIN_HAS_CBC
3120     parameters[numberParameters++] =
3121          CbcOrClpParam("randomC!bcSeed", "Random seed for Cbc",
3122                        -1, COIN_INT_MAX, CBC_PARAM_INT_RANDOMSEED);
3123     parameters[numberParameters-1].setLonghelp
3124     (
3125          "This sets a random seed for Cbc \
3126- 0 says use time of day, -1 is as now."
3127     );
3128     parameters[numberParameters-1].setIntValue(-1);
3129     parameters[numberParameters++] =
3130          CbcOrClpParam("randomi!zedRounding", "Whether to try randomized rounding heuristic",
3131                        "off", CBC_PARAM_STR_RANDROUND);
3132     parameters[numberParameters-1].append("on");
3133     parameters[numberParameters-1].append("both");
3134     parameters[numberParameters-1].append("before");
3135     parameters[numberParameters-1].setLonghelp
3136     (
3137          "stuff needed. \
3138Doh option does heuristic before preprocessing"     );
3139#endif
3140#ifdef COIN_HAS_CLP
3141     parameters[numberParameters++] =
3142          CbcOrClpParam("randomS!eed", "Random seed for Clp",
3143                        0, COIN_INT_MAX, CLP_PARAM_INT_RANDOMSEED);
3144     parameters[numberParameters-1].setLonghelp
3145     (
3146          "This sets a random seed for Clp \
3147- 0 says use time of day."
3148     );
3149     parameters[numberParameters-1].setIntValue(1234567);
3150#endif
3151#ifdef COIN_HAS_CBC
3152     parameters[numberParameters++] =
3153          CbcOrClpParam("ratio!Gap", "Stop when gap between best possible and \
3154best less than this fraction of larger of two",
3155                        0.0, 1.0e20, CBC_PARAM_DBL_GAPRATIO);
3156     parameters[numberParameters-1].setDoubleValue(0.0);
3157     parameters[numberParameters-1].setLonghelp
3158     (
3159          "If the gap between best solution and best possible solution is less than this fraction \
3160of the objective value at the root node then the search will terminate.  See 'allowableGap' for a \
3161way of using absolute value rather than fraction."
3162     );
3163     parameters[numberParameters++] =
3164          CbcOrClpParam("readS!tored", "Import stored cuts from file",
3165                        CLP_PARAM_ACTION_STOREDFILE, 3, 0);
3166#endif
3167#ifdef COIN_HAS_CLP
3168     parameters[numberParameters++] =
3169          CbcOrClpParam("reallyO!bjectiveScale", "Scale factor to apply to objective in place",
3170                        -1.0e20, 1.0e20, CLP_PARAM_DBL_OBJSCALE2, 0);
3171     parameters[numberParameters-1].setLonghelp
3172     (
3173          "You can set this to -1.0 to test maximization or other to stress code"
3174     );
3175     parameters[numberParameters-1].setDoubleValue(1.0);
3176     parameters[numberParameters++] =
3177          CbcOrClpParam("reallyS!cale", "Scales model in place",
3178                        CLP_PARAM_ACTION_REALLY_SCALE, 7, 0);
3179#endif
3180#ifdef COIN_HAS_CBC
3181     parameters[numberParameters++] =
3182          CbcOrClpParam("reduce!AndSplitCuts", "Whether to use Reduce-and-Split cuts",
3183                        "off", CBC_PARAM_STR_REDSPLITCUTS);
3184     parameters[numberParameters-1].append("on");
3185     parameters[numberParameters-1].append("root");
3186     parameters[numberParameters-1].append("ifmove");
3187     parameters[numberParameters-1].append("forceOn");
3188     parameters[numberParameters-1].setLonghelp
3189     (
3190          "This switches on reduce and split  cuts (either at root or in entire tree). \
3191May be slow \
3192See branchAndCut for information on options."
3193     );
3194      parameters[numberParameters++] =
3195          CbcOrClpParam("reduce2!AndSplitCuts", "Whether to use Reduce-and-Split cuts - style 2",
3196                        "off", CBC_PARAM_STR_REDSPLIT2CUTS);
3197     parameters[numberParameters-1].append("on");
3198     parameters[numberParameters-1].append("root");
3199     parameters[numberParameters-1].append("longOn");
3200     parameters[numberParameters-1].append("longRoot");
3201     parameters[numberParameters-1].setLonghelp
3202     (
3203          "This switches on reduce and split  cuts (either at root or in entire tree) \
3204This version is by Giacomo Nannicini based on Francois Margot's version \
3205Standard setting only uses rows in tableau <=256, long uses all \
3206May be slow \
3207See branchAndCut for information on options."
3208     );
3209     parameters[numberParameters++] =
3210          CbcOrClpParam("reduce2!AndSplitCuts", "Whether to use Reduce-and-Split cuts - style 2",
3211                        "off", CBC_PARAM_STR_REDSPLIT2CUTS);
3212     parameters[numberParameters-1].append("on");
3213     parameters[numberParameters-1].append("root");
3214     parameters[numberParameters-1].append("longOn");
3215     parameters[numberParameters-1].append("longRoot");
3216     parameters[numberParameters-1].setLonghelp
3217     (
3218          "This switches on reduce and split  cuts (either at root or in entire tree) \
3219This version is by Giacomo Nannicini based on Francois Margot's version \
3220Standard setting only uses rows in tableau <=256, long uses all \
3221See branchAndCut for information on options."
3222     );
3223     parameters[numberParameters++] =
3224          CbcOrClpParam("residual!CapacityCuts", "Whether to use Residual Capacity cuts",
3225                        "off", CBC_PARAM_STR_RESIDCUTS);
3226     parameters[numberParameters-1].append("on");
3227     parameters[numberParameters-1].append("root");
3228     parameters[numberParameters-1].append("ifmove");
3229     parameters[numberParameters-1].append("forceOn");
3230     parameters[numberParameters-1].setLonghelp
3231     (
3232          "Residual capacity cuts. \
3233See branchAndCut for information on options."
3234     );
3235#endif
3236#ifdef COIN_HAS_CLP
3237     parameters[numberParameters++] =
3238          CbcOrClpParam("restore!Model", "Restore model from binary file",
3239                        CLP_PARAM_ACTION_RESTORE, 7, 1);
3240     parameters[numberParameters-1].setLonghelp
3241     (
3242          "This reads data save by saveModel from the given file.  It will use the default\
3243 directory given by 'directory'.  A name of '$' will use the previous value for the name.  This\
3244 is initialized to 'default.prob'."
3245     );
3246     parameters[numberParameters++] =
3247          CbcOrClpParam("reverse", "Reverses sign of objective",
3248                        CLP_PARAM_ACTION_REVERSE, 7, 0);
3249     parameters[numberParameters-1].setLonghelp
3250     (
3251          "Useful for testing if maximization works correctly"
3252     );
3253     parameters[numberParameters++] =
3254          CbcOrClpParam("rhs!Scale", "Scale factor to apply to rhs and bounds",
3255                        -1.0e20, 1.0e20, CLP_PARAM_DBL_RHSSCALE, 0);
3256     parameters[numberParameters-1].setLonghelp
3257     (
3258          "If the rhs or bounds have some very large meaningful values, you may wish to scale them\
3259 internally by this amount.  It can also be set by autoscale.  This should not be needed."
3260     );
3261     parameters[numberParameters-1].setDoubleValue(1.0);
3262#endif
3263#ifdef COIN_HAS_CBC
3264     parameters[numberParameters++] =
3265          CbcOrClpParam("Rens", "Whether to try Relaxation Enforced Neighborhood Search",
3266                        "off", CBC_PARAM_STR_RENS);
3267     parameters[numberParameters-1].append("on");
3268     parameters[numberParameters-1].append("both");
3269     parameters[numberParameters-1].append("before");
3270     parameters[numberParameters-1].append("200");
3271     parameters[numberParameters-1].append("1000");
3272     parameters[numberParameters-1].append("10000");
3273     parameters[numberParameters-1].append("dj");
3274     parameters[numberParameters-1].append("djbefore");
3275     parameters[numberParameters-1].setLonghelp
3276     (
3277          "This switches on Relaxation enforced neighborhood Search. \
3278on just does 50 nodes \
3279200 or 1000 does that many nodes. \
3280Doh option does heuristic before preprocessing"     );
3281     parameters[numberParameters++] =
3282          CbcOrClpParam("Rins", "Whether to try Relaxed Induced Neighborhood Search",
3283                        "off", CBC_PARAM_STR_RINS);
3284     parameters[numberParameters-1].append("on");
3285     parameters[numberParameters-1].append("both");
3286     parameters[numberParameters-1].append("before");
3287     parameters[numberParameters-1].append("often");
3288     parameters[numberParameters-1].setLonghelp
3289     (
3290          "This switches on Relaxed induced neighborhood Search. \
3291Doh option does heuristic before preprocessing"     );
3292     parameters[numberParameters++] =
3293          CbcOrClpParam("round!ingHeuristic", "Whether to use Rounding heuristic",
3294                        "off", CBC_PARAM_STR_ROUNDING);
3295     parameters[numberParameters-1].append("on");
3296     parameters[numberParameters-1].append("both");
3297     parameters[numberParameters-1].append("before");
3298     parameters[numberParameters-1].setLonghelp
3299     (
3300          "This switches on a simple (but effective) rounding heuristic at each node of tree.  \
3301On means do in solve i.e. after preprocessing, \
3302Before means do if doHeuristics used, off otherwise, \
3303and both means do if doHeuristics and in solve."
3304     );
3305
3306#endif
3307     parameters[numberParameters++] =
3308          CbcOrClpParam("saveM!odel", "Save model to binary file",
3309                        CLP_PARAM_ACTION_SAVE, 7, 1);
3310     parameters[numberParameters-1].setLonghelp
3311     (
3312          "This will save the problem to the given file name for future use\
3313 by restoreModel.  It will use the default\
3314 directory given by 'directory'.  A name of '$' will use the previous value for the name.  This\
3315 is initialized to 'default.prob'."
3316     );
3317     parameters[numberParameters++] =
3318          CbcOrClpParam("saveS!olution", "saves solution to file",
3319                        CLP_PARAM_ACTION_SAVESOL);
3320     parameters[numberParameters-1].setLonghelp
3321     (
3322          "This will write a binary solution file to the given file name.  It will use the default\
3323 directory given by 'directory'.  A name of '$' will use the previous value for the name.  This\
3324 is initialized to 'solution.file'.  To read the file use fread(int) twice to pick up number of rows \
3325and columns, then fread(double) to pick up objective value, then pick up row activities, row duals, column \
3326activities and reduced costs - see bottom of CbcOrClpParam.cpp for code that reads or writes file. \
3327If name contains '_fix_read_' then does not write but reads and will fix all variables"
3328     );
3329     parameters[numberParameters++] =
3330          CbcOrClpParam("scal!ing", "Whether to scale problem",
3331                        "off", CLP_PARAM_STR_SCALING);
3332     parameters[numberParameters-1].append("equi!librium");
3333     parameters[numberParameters-1].append("geo!metric");
3334     parameters[numberParameters-1].append("auto!matic");
3335     parameters[numberParameters-1].append("dynamic");
3336     parameters[numberParameters-1].append("rows!only");
3337     parameters[numberParameters-1].setLonghelp
3338     (
3339          "Scaling can help in solving problems which might otherwise fail because of lack of\
3340 accuracy.  It can also reduce the number of iterations.  It is not applied if the range\
3341 of elements is small.  When unscaled it is possible that there may be small primal and/or\
3342 infeasibilities."
3343     );
3344     parameters[numberParameters-1].setCurrentOption(3); // say auto
3345#ifndef COIN_HAS_CBC
3346     parameters[numberParameters++] =
3347          CbcOrClpParam("sec!onds", "Maximum seconds",
3348                        -1.0, 1.0e12, CLP_PARAM_DBL_TIMELIMIT);
3349     parameters[numberParameters-1].setLonghelp
3350     (
3351          "After this many seconds clp will act as if maximum iterations had been reached \
3352(if value >=0)."
3353     );
3354#else
3355     parameters[numberParameters++] =
3356          CbcOrClpParam("sec!onds", "maximum seconds",
3357                        -1.0, 1.0e12, CBC_PARAM_DBL_TIMELIMIT_BAB);
3358     parameters[numberParameters-1].setLonghelp
3359     (
3360          "After this many seconds coin solver will act as if maximum nodes had been reached."
3361     );
3362#endif
3363     parameters[numberParameters++] =
3364          CbcOrClpParam("sleep", "for debug",
3365                        CLP_PARAM_ACTION_DUMMY, 7, 0);
3366     parameters[numberParameters-1].setLonghelp
3367     (
3368          "If passed to solver fom ampl, then ampl will wait so that you can copy .nl file for debug."
3369     );
3370#ifdef COIN_HAS_CBC
3371     parameters[numberParameters++] =
3372          CbcOrClpParam("slow!cutpasses", "Maximum number of tries for slower cuts",
3373                        -1, COIN_INT_MAX, CBC_PARAM_INT_MAX_SLOW_CUTS);
3374     parameters[numberParameters-1].setLonghelp
3375     (
3376          "Some cut generators are fairly slow - this limits the number of times they are tried."
3377     );
3378     parameters[numberParameters-1].setIntValue(10);
3379#endif
3380#ifdef COIN_HAS_CLP
3381     parameters[numberParameters++] =
3382          CbcOrClpParam("slp!Value", "Number of slp passes before primal",
3383                        -1, 50000, CLP_PARAM_INT_SLPVALUE, 1);
3384     parameters[numberParameters-1].setLonghelp
3385     (
3386          "If you are solving a quadratic problem using primal then it may be helpful to do some \
3387sequential Lps to get a good approximate solution."
3388     );
3389#if CLP_MULTIPLE_FACTORIZATIONS > 0
3390     parameters[numberParameters++] =
3391          CbcOrClpParam("small!Factorization", "Whether to use small factorization",
3392                        -1, 10000, CBC_PARAM_INT_SMALLFACT, 1);
3393     parameters[numberParameters-1].setLonghelp
3394     (
3395          "If processed problem <= this use small factorization"
3396     );
3397     parameters[numberParameters-1].setIntValue(-1);
3398#endif
3399#endif
3400     parameters[numberParameters++] =
3401          CbcOrClpParam("solu!tion", "Prints solution to file",
3402                        CLP_PARAM_ACTION_SOLUTION);
3403     parameters[numberParameters-1].setLonghelp
3404     (
3405          "This will write a primitive solution file to the given file name.  It will use the default\
3406 directory given by 'directory'.  A name of '$' will use the previous value for the name.  This\
3407 is initialized to 'stdout'.  The amount of output can be varied using printi!ngOptions or printMask."
3408     );
3409#ifdef COIN_HAS_CLP
3410#ifdef COIN_HAS_CBC
3411     parameters[numberParameters++] =
3412          CbcOrClpParam("solv!e", "Solve problem",
3413                        CBC_PARAM_ACTION_BAB);
3414     parameters[numberParameters-1].setLonghelp
3415     (
3416          "If there are no integer variables then this just solves LP.  If there are integer variables \
3417this does branch and cut."
3418     );
3419     parameters[numberParameters++] =
3420          CbcOrClpParam("sos!Options", "Whether to use SOS from AMPL",
3421                        "off", CBC_PARAM_STR_SOS);
3422     parameters[numberParameters-1].append("on");
3423     parameters[numberParameters-1].setCurrentOption("on");
3424     parameters[numberParameters-1].setLonghelp
3425     (
3426          "Normally if AMPL says there are SOS variables they should be used, but sometime sthey should\
3427 be turned off - this does so."
3428     );
3429     parameters[numberParameters++] =
3430          CbcOrClpParam("slog!Level", "Level of detail in (LP) Solver output",
3431                        -1, 63, CLP_PARAM_INT_SOLVERLOGLEVEL);
3432     parameters[numberParameters-1].setLonghelp
3433     (
3434          "If 0 then there should be no output in normal circumstances.  1 is probably the best\
3435 value for most uses, while 2 and 3 give more information.  This parameter is only used inside MIP - for Clp use 'log'"
3436     );
3437#else
3438     // allow solve as synonym for possible dual
3439     parameters[numberParameters++] =
3440       CbcOrClpParam("solv!e", "Solve problem using dual simplex (probably)",
3441                        CLP_PARAM_ACTION_EITHERSIMPLEX);
3442     parameters[numberParameters-1].setLonghelp
3443     (
3444          "Just so can use solve for clp as well as in cbc"
3445     );
3446#endif
3447#endif
3448#ifdef COIN_HAS_CLP
3449     parameters[numberParameters++] =
3450          CbcOrClpParam("spars!eFactor", "Whether factorization treated as sparse",
3451                        "on", CLP_PARAM_STR_SPARSEFACTOR, 7, 0);
3452     parameters[numberParameters-1].append("off");
3453     parameters[numberParameters++] =
3454          CbcOrClpParam("special!Options", "Dubious options for Simplex - see ClpSimplex.hpp",
3455                        0, COIN_INT_MAX, CLP_PARAM_INT_SPECIALOPTIONS, 0);
3456     parameters[numberParameters++] =
3457          CbcOrClpParam("sprint!Crash", "Whether to try sprint crash",
3458                        -1, 5000000, CLP_PARAM_INT_SPRINT);
3459     parameters[numberParameters-1].setLonghelp
3460     (
3461          "For long and thin problems this program may solve a series of small problems\
3462 created by taking a subset of the columns.  I introduced the idea as 'Sprint' after\
3463 an LP code of that name of the 60's which tried the same tactic (not totally successfully).\
3464  Cplex calls it 'sifting'.  -1 is automatic choice, 0 is off, n is number of passes"
3465     );
3466     parameters[numberParameters++] =
3467          CbcOrClpParam("stat!istics", "Print some statistics",
3468                        CLP_PARAM_ACTION_STATISTICS);
3469     parameters[numberParameters-1].setLonghelp
3470     (
3471          "This command prints some statistics for the current model.\
3472 If log level >1 then more is printed.\
3473 These are for presolved model if presolve on (and unscaled)."
3474     );
3475#endif
3476     parameters[numberParameters++] =
3477          CbcOrClpParam("stop", "Stops clp execution",
3478                        CLP_PARAM_ACTION_EXIT);
3479     parameters[numberParameters-1].setLonghelp
3480     (
3481          "This stops the execution of Clp, end, exit, quit and stop are synonyms"
3482     );
3483#ifdef COIN_HAS_CBC
3484     parameters[numberParameters++] =
3485          CbcOrClpParam("strat!egy", "Switches on groups of features",
3486                        0, 2, CBC_PARAM_INT_STRATEGY);
3487     parameters[numberParameters-1].setLonghelp
3488     (
3489          "This turns on newer features. \
3490Use 0 for easy problems, 1 is default, 2 is aggressive. \
34911 uses Gomory cuts using tolerance of 0.01 at root, \
3492does a possible restart after 100 nodes if can fix many \
3493and activates a diving and RINS heuristic and makes feasibility pump \
3494more aggressive. \
3495This does not apply to unit tests (where 'experiment' may have similar effects)."
3496     );
3497     parameters[numberParameters-1].setIntValue(1);
3498#ifdef CBC_KEEP_DEPRECATED
3499     parameters[numberParameters++] =
3500          CbcOrClpParam("strengthen", "Create strengthened problem",
3501                        CBC_PARAM_ACTION_STRENGTHEN, 3);
3502     parameters[numberParameters-1].setLonghelp
3503     (
3504          "This creates a new problem by applying the root node cuts.  All tight constraints \
3505will be in resulting problem"
3506     );
3507#endif
3508     parameters[numberParameters++] =
3509          CbcOrClpParam("strong!Branching", "Number of variables to look at in strong branching",
3510                        0, COIN_INT_MAX, CBC_PARAM_INT_STRONGBRANCHING);
3511     parameters[numberParameters-1].setLonghelp
3512     (
3513          "In order to decide which variable to branch on, the code will choose up to this number \
3514of unsatisfied variables to do mini up and down branches on.  Then the most effective one is chosen. \
3515If a variable is branched on many times then the previous average up and down costs may be used - \
3516see number before trust."
3517     );
3518#endif
3519#ifdef COIN_HAS_CLP
3520     parameters[numberParameters++] =
3521          CbcOrClpParam("subs!titution", "How long a column to substitute for in presolve",
3522                        0, 10000, CLP_PARAM_INT_SUBSTITUTION, 0);
3523     parameters[numberParameters-1].setLonghelp
3524     (
3525          "Normally Presolve gets rid of 'free' variables when there are no more than 3 \
3526 variables in column.  If you increase this the number of rows may decrease but number of \
3527 elements may increase."
3528     );
3529#endif
3530#ifdef COIN_HAS_CBC
3531     parameters[numberParameters++] =
3532          CbcOrClpParam("testO!si", "Test OsiObject stuff",
3533                        -1, COIN_INT_MAX, CBC_PARAM_INT_TESTOSI, 0);
3534#endif
3535#ifdef CBC_THREAD
3536     parameters[numberParameters++] =
3537          CbcOrClpParam("thread!s", "Number of threads to try and use",
3538                        -100, 100000, CBC_PARAM_INT_THREADS, 1);
3539     parameters[numberParameters-1].setLonghelp
3540     (
3541          "To use multiple threads, set threads to number wanted.  It may be better \
3542to use one or two more than number of cpus available.  If 100+n then n threads and \
3543search is repeatable (maybe be somewhat slower), \
3544if 200+n use threads for root cuts, 400+n threads used in sub-trees."
3545     );
3546#endif
3547#ifdef COIN_HAS_CBC
3548     parameters[numberParameters++] =
3549          CbcOrClpParam("tighten!Factor", "Tighten bounds using this times largest \
3550activity at continuous solution",
3551                        1.0e-3, 1.0e20, CBC_PARAM_DBL_TIGHTENFACTOR, 0);
3552     parameters[numberParameters-1].setLonghelp
3553     (
3554          "This sleazy trick can help on some problems."
3555     );
3556#endif
3557#ifdef COIN_HAS_CLP
3558     parameters[numberParameters++] =
3559          CbcOrClpParam("tightLP", "Poor person's preSolve for now",
3560                        CLP_PARAM_ACTION_TIGHTEN, 7, 0);
3561#endif
3562     parameters[numberParameters++] =
3563          CbcOrClpParam("timeM!ode", "Whether to use CPU or elapsed time",
3564                        "cpu", CLP_PARAM_STR_TIME_MODE);
3565     parameters[numberParameters-1].append("elapsed");
3566     parameters[numberParameters-1].setLonghelp
3567     (
3568          "cpu uses CPU time for stopping, while elapsed uses elapsed time. \
3569(On Windows, elapsed time is always used)."
3570     );
3571#ifdef COIN_HAS_CBC
3572     parameters[numberParameters++] =
3573          CbcOrClpParam("trust!PseudoCosts", "Number of branches before we trust pseudocosts",
3574                        -3, 2000000000, CBC_PARAM_INT_NUMBERBEFORE);
3575     parameters[numberParameters-1].setLonghelp
3576     (
3577          "Using strong branching computes pseudo-costs.  After this many times for a variable we just \
3578trust the pseudo costs and do not do any more strong branching."
3579     );
3580#endif
3581#ifdef COIN_HAS_CBC
3582     parameters[numberParameters++] =
3583          CbcOrClpParam("tune!PreProcess", "Dubious tuning parameters",
3584                        0, 20000000, CLP_PARAM_INT_PROCESSTUNE, 1);
3585     parameters[numberParameters-1].setLonghelp
3586     (
3587          "For making equality cliques this is minimumsize.  Also for adding \
3588integer slacks.  May be used for more later \
3589If <10000 that is what it does.  If <1000000 - numberPasses is (value/10000)-1 and tune is tune %10000. \
3590If >= 1000000! - numberPasses is (value/1000000)-1 and tune is tune %1000000.  In this case if tune is now still >=10000 \
3591numberPassesPerInnerLoop is changed from 10 to (tune-10000)-1 and tune becomes tune % 10000!!!!! - happy? - \
3592so to keep normal limit on cliques of 5, do 3 major passes (include presolves) but only doing one tightening pass per major pass - \
3593you would use 3010005 (I think)"
3594     );
3595     parameters[numberParameters++] =
3596          CbcOrClpParam("two!MirCuts", "Whether to use Two phase Mixed Integer Rounding cuts",
3597                        "off", CBC_PARAM_STR_TWOMIRCUTS);
3598     parameters[numberParameters-1].append("on");
3599     parameters[numberParameters-1].append("root");
3600     parameters[numberParameters-1].append("ifmove");
3601     parameters[numberParameters-1].append("forceOn");
3602     parameters[numberParameters-1].append("onglobal");
3603     parameters[numberParameters-1].append("forceandglobal");
3604     parameters[numberParameters-1].append("forceLongOn");
3605     parameters[numberParameters-1].setLonghelp
3606     (
3607          "This switches on two phase mixed integer rounding  cuts (either at root or in entire tree) \
3608See branchAndCut for information on options."
3609     );
3610#endif
3611     parameters[numberParameters++] =
3612          CbcOrClpParam("unitTest", "Do unit test",
3613                        CLP_PARAM_ACTION_UNITTEST, 3, 1);
3614     parameters[numberParameters-1].setLonghelp
3615     (
3616          "This exercises the unit test for clp"
3617     );
3618     parameters[numberParameters++] =
3619          CbcOrClpParam("userClp", "Hand coded Clp stuff",
3620                        CLP_PARAM_ACTION_USERCLP, 0, 0);
3621     parameters[numberParameters-1].setLonghelp
3622     (
3623          "There are times e.g. when using AMPL interface when you may wish to do something unusual.  \
3624Look for USERCLP in main driver and modify sample code."
3625     );
3626#ifdef COIN_HAS_CBC
3627     parameters[numberParameters++] =
3628          CbcOrClpParam("userCbc", "Hand coded Cbc stuff",
3629                        CBC_PARAM_ACTION_USERCBC, 0, 0);
3630     parameters[numberParameters-1].setLonghelp
3631     (
3632          "There are times e.g. when using AMPL interface when you may wish to do something unusual.  \
3633Look for USERCBC in main driver and modify sample code. \
3634It is possible you can get same effect by using example driver4.cpp."
3635     );
3636     parameters[numberParameters++] =
3637          CbcOrClpParam("Vnd!VariableNeighborhoodSearch", "Whether to try Variable Neighborhood Search",
3638                        "off", CBC_PARAM_STR_VND);
3639     parameters[numberParameters-1].append("on");
3640     parameters[numberParameters-1].append("both");
3641     parameters[numberParameters-1].append("before");
3642     parameters[numberParameters-1].append("intree");
3643     parameters[numberParameters-1].setLonghelp
3644     (
3645          "This switches on variable neighborhood Search. \
3646Doh option does heuristic before preprocessing"     );
3647#endif
3648     parameters[numberParameters++] =
3649          CbcOrClpParam("vector", "Whether to use vector? Form of matrix in simplex",
3650                        "off", CLP_PARAM_STR_VECTOR, 7, 0);
3651     parameters[numberParameters-1].append("on");
3652     parameters[numberParameters-1].setLonghelp
3653     (
3654          "If this is on ClpPackedMatrix uses extra column copy in odd format."
3655     );
3656     parameters[numberParameters++] =
3657          CbcOrClpParam("verbose", "Switches on longer help on single ?",
3658                        0, 31, CLP_PARAM_INT_VERBOSE, 0);
3659     parameters[numberParameters-1].setLonghelp
3660     (
3661          "Set to 1 to get short help with ? list, 2 to get long help, 3 for both.  (add 4 to just get ampl ones)."
3662     );
3663     parameters[numberParameters-1].setIntValue(0);
3664#ifdef COIN_HAS_CBC
3665     parameters[numberParameters++] =
3666          CbcOrClpParam("vub!heuristic", "Type of vub heuristic",
3667                        -2, 20, CBC_PARAM_INT_VUBTRY, 0);
3668     parameters[numberParameters-1].setLonghelp
3669     (
3670          "If set will try and fix some integer variables"
3671     );
3672     parameters[numberParameters-1].setIntValue(-1);
3673     parameters[numberParameters++] =
3674          CbcOrClpParam("zero!HalfCuts", "Whether to use zero half cuts",
3675                        "off", CBC_PARAM_STR_ZEROHALFCUTS);
3676     parameters[numberParameters-1].append("on");
3677     parameters[numberParameters-1].append("root");
3678     parameters[numberParameters-1].append("ifmove");
3679     parameters[numberParameters-1].append("forceOn");
3680     parameters[numberParameters-1].append("onglobal");
3681     parameters[numberParameters-1].setLonghelp
3682     (
3683          "This switches on zero-half cuts (either at root or in entire tree) \
3684See branchAndCut for information on options.  This implementation was written by \
3685Alberto Caprara."
3686     );
3687#endif
3688     parameters[numberParameters++] =
3689          CbcOrClpParam("zeroT!olerance", "Kill all coefficients \
3690whose absolute value is less than this value",
3691                        1.0e-100, 1.0e-5, CLP_PARAM_DBL_ZEROTOLERANCE);
3692     parameters[numberParameters-1].setLonghelp
3693     (
3694          "This applies to reading mps files (and also lp files \
3695if KILL_ZERO_READLP defined)"
3696     );
3697     parameters[numberParameters-1].setDoubleValue(1.0e-20);
3698     assert(numberParameters < CBCMAXPARAMETERS);
3699}
3700// Given a parameter type - returns its number in list
3701int whichParam (CbcOrClpParameterType name,
3702                int numberParameters, CbcOrClpParam *const parameters)
3703{
3704     int i;
3705     for (i = 0; i < numberParameters; i++) {
3706          if (parameters[i].type() == name)
3707               break;
3708     }
3709     assert (i < numberParameters);
3710     return i;
3711}
3712#ifdef COIN_HAS_CLP
3713/* Restore a solution from file.
3714   mode 0 normal, 1 swap rows and columns and primal and dual
3715   if 2 set then also change signs
3716*/
3717void restoreSolution(ClpSimplex * lpSolver, std::string fileName, int mode)
3718{
3719     FILE * fp = fopen(fileName.c_str(), "rb");
3720     if (fp) {
3721          int numberRows = lpSolver->numberRows();
3722          int numberColumns = lpSolver->numberColumns();
3723          int numberRowsFile;
3724          int numberColumnsFile;
3725          double objectiveValue;
3726          size_t nRead;
3727          nRead = fread(&numberRowsFile, sizeof(int), 1, fp);
3728          if (nRead != 1)
3729               throw("Error in fread");
3730          nRead = fread(&numberColumnsFile, sizeof(int), 1, fp);
3731          if (nRead != 1)
3732               throw("Error in fread");
3733          nRead = fread(&objectiveValue, sizeof(double), 1, fp);
3734          if (nRead != 1)
3735               throw("Error in fread");
3736          double * dualRowSolution = lpSolver->dualRowSolution();
3737          double * primalRowSolution = lpSolver->primalRowSolution();
3738          double * dualColumnSolution = lpSolver->dualColumnSolution();
3739          double * primalColumnSolution = lpSolver->primalColumnSolution();
3740          if (mode) {
3741               // swap
3742               int k = numberRows;
3743               numberRows = numberColumns;
3744               numberColumns = k;
3745               double * temp;
3746               temp = dualRowSolution;
3747               dualRowSolution = primalColumnSolution;
3748               primalColumnSolution = temp;
3749               temp = dualColumnSolution;
3750               dualColumnSolution = primalRowSolution;
3751               primalRowSolution = temp;
3752          }
3753          if (numberRows > numberRowsFile || numberColumns > numberColumnsFile) {
3754               std::cout << "Mismatch on rows and/or columns - giving up" << std::endl;
3755          } else {
3756               lpSolver->setObjectiveValue(objectiveValue);
3757               if (numberRows == numberRowsFile && numberColumns == numberColumnsFile) {
3758                    nRead = fread(primalRowSolution, sizeof(double), numberRows, fp);
3759                    if (nRead != static_cast<size_t>(numberRows))
3760                         throw("Error in fread");
3761                    nRead = fread(dualRowSolution, sizeof(double), numberRows, fp);
3762                    if (nRead != static_cast<size_t>(numberRows))
3763                         throw("Error in fread");
3764                    nRead = fread(primalColumnSolution, sizeof(double), numberColumns, fp);
3765                    if (nRead != static_cast<size_t>(numberColumns))
3766                         throw("Error in fread");
3767                    nRead = fread(dualColumnSolution, sizeof(double), numberColumns, fp);
3768                    if (nRead != static_cast<size_t>(numberColumns))
3769                         throw("Error in fread");
3770               } else {
3771                    std::cout << "Mismatch on rows and/or columns - truncating" << std::endl;
3772                    double * temp = new double [CoinMax(numberRowsFile, numberColumnsFile)];
3773                    nRead = fread(temp, sizeof(double), numberRowsFile, fp);
3774                    if (nRead != static_cast<size_t>(numberRowsFile))
3775                         throw("Error in fread");
3776                    CoinMemcpyN(temp, numberRows, primalRowSolution);
3777                    nRead = fread(temp, sizeof(double), numberRowsFile, fp);
3778                    if (nRead != static_cast<size_t>(numberRowsFile))
3779                         throw("Error in fread");
3780                    CoinMemcpyN(temp, numberRows, dualRowSolution);
3781                    nRead = fread(temp, sizeof(double), numberColumnsFile, fp);
3782                    if (nRead != static_cast<size_t>(numberColumnsFile))
3783                         throw("Error in fread");
3784                    CoinMemcpyN(temp, numberColumns, primalColumnSolution);
3785                    nRead = fread(temp, sizeof(double), numberColumnsFile, fp);
3786                    if (nRead != static_cast<size_t>(numberColumnsFile))
3787                         throw("Error in fread");
3788                    CoinMemcpyN(temp, numberColumns, dualColumnSolution);
3789                    delete [] temp;
3790                           }
3791               if (mode == 3) {
3792                    int i;
3793                    for (i = 0; i < numberRows; i++) {
3794                         primalRowSolution[i] = -primalRowSolution[i];
3795                         dualRowSolution[i] = -dualRowSolution[i];
3796                    }
3797                    for (i = 0; i < numberColumns; i++) {
3798                         primalColumnSolution[i] = -primalColumnSolution[i];
3799                         dualColumnSolution[i] = -dualColumnSolution[i];
3800                    }
3801               }
3802          }
3803          fclose(fp);
3804     } else {
3805          std::cout << "Unable to open file " << fileName << std::endl;
3806     }
3807}
3808// Dump a solution to file
3809void saveSolution(const ClpSimplex * lpSolver, std::string fileName)
3810{
3811     if (strstr(fileName.c_str(), "_fix_read_")) {
3812          FILE * fp = fopen(fileName.c_str(), "rb");
3813          if (fp) {
3814               ClpSimplex * solver = const_cast<ClpSimplex *>(lpSolver);
3815               restoreSolution(solver, fileName, 0);
3816               // fix all
3817               int logLevel = solver->logLevel();
3818               int iColumn;
3819               int numberColumns = solver->numberColumns();
3820               double * primalColumnSolution =
3821                    solver->primalColumnSolution();
3822               double * columnLower = solver->columnLower();
3823               double * columnUpper = solver->columnUpper();
3824               for (iColumn = 0; iColumn < numberColumns; iColumn++) {
3825                    double value = primalColumnSolution[iColumn];
3826                    if (value > columnUpper[iColumn]) {
3827                         if (value > columnUpper[iColumn] + 1.0e-6 && logLevel > 1)
3828                              printf("%d value of %g - bounds %g %g\n",
3829                                     iColumn, value, columnLower[iColumn], columnUpper[iColumn]);
3830                         value = columnUpper[iColumn];
3831                    } else if (value < columnLower[iColumn]) {
3832                         if (value < columnLower[iColumn] - 1.0e-6 && logLevel > 1)
3833                              printf("%d value of %g - bounds %g %g\n",
3834                                     iColumn, value, columnLower[iColumn], columnUpper[iColumn]);
3835                         value = columnLower[iColumn];
3836                    }
3837                    columnLower[iColumn] = value;
3838                    columnUpper[iColumn] = value;
3839               }
3840               return;
3841          }
3842     }
3843     FILE * fp = fopen(fileName.c_str(), "wb");
3844     if (fp) {
3845          int numberRows = lpSolver->numberRows();
3846          int numberColumns = lpSolver->numberColumns();
3847          double objectiveValue = lpSolver->objectiveValue();
3848          size_t nWrite;
3849          nWrite = fwrite(&numberRows, sizeof(int), 1, fp);
3850          if (nWrite != 1)
3851               throw("Error in fwrite");
3852          nWrite = fwrite(&numberColumns, sizeof(int), 1, fp);
3853          if (nWrite != 1)
3854               throw("Error in fwrite");
3855          nWrite = fwrite(&objectiveValue, sizeof(double), 1, fp);
3856          if (nWrite != 1)
3857               throw("Error in fwrite");
3858          double * dualRowSolution = lpSolver->dualRowSolution();
3859          double * primalRowSolution = lpSolver->primalRowSolution();
3860          nWrite = fwrite(primalRowSolution, sizeof(double), numberRows, fp);
3861          if (nWrite != static_cast<size_t>(numberRows))
3862               throw("Error in fwrite");
3863          nWrite = fwrite(dualRowSolution, sizeof(double), numberRows, fp);
3864          if (nWrite != static_cast<size_t>(numberRows))
3865               throw("Error in fwrite");
3866          double * dualColumnSolution = lpSolver->dualColumnSolution();
3867          double * primalColumnSolution = lpSolver->primalColumnSolution();
3868          nWrite = fwrite(primalColumnSolution, sizeof(double), numberColumns, fp);
3869          if (nWrite != static_cast<size_t>(numberColumns))
3870               throw("Error in fwrite");
3871          nWrite = fwrite(dualColumnSolution, sizeof(double), numberColumns, fp);
3872          if (nWrite != static_cast<size_t>(numberColumns))
3873               throw("Error in fwrite");
3874          fclose(fp);
3875     } else {
3876          std::cout << "Unable to open file " << fileName << std::endl;
3877     }
3878}
3879#endif
Note: See TracBrowser for help on using the repository browser.