source: trunk/Clp/src/CbcOrClpParam.cpp @ 1502

Last change on this file since 1502 was 1502, checked in by forrest, 10 years ago

moving sandbox stuff to trunk

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