source: branches/sandbox/Cbc/src/CbcSolver.cpp @ 1389

Last change on this file since 1389 was 1386, checked in by lou, 10 years ago

Yet another try at cleaning CbcSolver?. This is an intermediate commit to
reconcile Bjarni's changes with my changes.

File size: 516.6 KB
Line 
1/* $Id: CbcSolver.cpp 1240 2009-10-02 18:41:44Z forrest $ */
2// Copyright (C) 2007, International Business Machines
3// Corporation and others.  All Rights Reserved.
4
5/*! \file CbcSolver.cpp
6    \brief Second level routines for the cbc stand-alone solver.
7*/
8
9#include "CbcConfig.h"
10#include "CoinPragma.hpp"
11
12#include <cassert>
13#include <cstdio>
14#include <cstdlib>
15#include <cmath>
16#include <cfloat>
17#include <cstring>
18#include <iostream>
19
20#include "CoinPragma.hpp"
21#include "CoinHelperFunctions.hpp"
22
23#include "CoinMpsIO.hpp"
24#include "CoinModel.hpp"
25
26#include "ClpFactorization.hpp"
27#include "ClpQuadraticObjective.hpp"
28#include "CoinTime.hpp"
29#include "ClpSimplex.hpp"
30#include "ClpSimplexOther.hpp"
31#include "ClpSolve.hpp"
32#include "ClpMessage.hpp"
33#include "ClpPackedMatrix.hpp"
34#include "ClpPlusMinusOneMatrix.hpp"
35#include "ClpNetworkMatrix.hpp"
36#include "ClpDualRowSteepest.hpp"
37#include "ClpDualRowDantzig.hpp"
38#include "ClpLinearObjective.hpp"
39#include "ClpPrimalColumnSteepest.hpp"
40#include "ClpPrimalColumnDantzig.hpp"
41
42#include "ClpPresolve.hpp"
43#include "CbcOrClpParam.hpp"
44#include "OsiRowCutDebugger.hpp"
45#include "OsiChooseVariable.hpp"
46#include "OsiAuxInfo.hpp"
47
48#include "CbcSolverHeuristics.hpp"
49
50// Version
51#ifndef CBCVERSION
52#define CBCVERSION "2.4.01"
53#endif
54//#define USER_HAS_FAKE_CLP
55//#define USER_HAS_FAKE_CBC
56
57//#define CLP_MALLOC_STATISTICS
58
59#ifdef CLP_MALLOC_STATISTICS
60#include <malloc.h>
61#include <exception>
62#include <new>
63#include "stolen_from_ekk_malloc.cpp"
64static double malloc_times = 0.0;
65static double malloc_total = 0.0;
66static int malloc_amount[] = {0, 32, 128, 256, 1024, 4096, 16384, 65536, 262144, INT_MAX};
67static int malloc_n = 10;
68double malloc_counts[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
69bool malloc_counts_on = true;
70void * operator new (size_t size) throw (std::bad_alloc)
71{
72    malloc_times ++;
73    malloc_total += size;
74    int i;
75    for (i = 0; i < malloc_n; i++) {
76        if ((int) size <= malloc_amount[i]) {
77            malloc_counts[i]++;
78            break;
79        }
80    }
81# ifdef DEBUG_MALLOC
82    void *p;
83    if (malloc_counts_on)
84        p = stolen_from_ekk_mallocBase(size);
85    else
86        p = malloc(size);
87# else
88    void * p = malloc(size);
89# endif
90    //char * xx = (char *) p;
91    //memset(xx,0,size);
92    // Initialize random seed
93    //CoinSeedRandom(987654321);
94    return p;
95}
96void operator delete (void *p) throw()
97{
98# ifdef DEBUG_MALLOC
99    if (malloc_counts_on)
100        stolen_from_ekk_freeBase(p);
101    else
102        free(p);
103# else
104    free(p);
105# endif
106}
107static void malloc_stats2()
108{
109    double average = malloc_total / malloc_times;
110    printf("count %g bytes %g - average %g\n", malloc_times, malloc_total, average);
111    for (int i = 0; i < malloc_n; i++)
112        printf("%g ", malloc_counts[i]);
113    printf("\n");
114    malloc_times = 0.0;
115    malloc_total = 0.0;
116    memset(malloc_counts, 0, sizeof(malloc_counts));
117    // print results
118}
119#else   //CLP_MALLOC_STATISTICS
120//void stolen_from_ekk_memory(void * dummy,int type)
121//{
122//}
123//bool malloc_counts_on=false;
124#endif  //CLP_MALLOC_STATISTICS
125
126//#define DMALLOC
127#ifdef DMALLOC
128#include "dmalloc.h"
129#endif
130
131#ifdef WSSMP_BARRIER
132#define FOREIGN_BARRIER
133#endif
134
135#ifdef UFL_BARRIER
136#define FOREIGN_BARRIER
137#endif
138
139#ifdef TAUCS_BARRIER
140#define FOREIGN_BARRIER
141#endif
142
143static int initialPumpTune = -1;
144#include "CoinWarmStartBasis.hpp"
145
146#include "OsiSolverInterface.hpp"
147#include "OsiCuts.hpp"
148#include "OsiRowCut.hpp"
149#include "OsiColCut.hpp"
150
151#ifndef COIN_HAS_LINK
152#define COIN_HAS_LINK
153#endif
154#ifdef COIN_HAS_LINK
155#include "CbcLinked.hpp"
156#endif
157
158#include "CglPreProcess.hpp"
159#include "CglCutGenerator.hpp"
160#include "CglGomory.hpp"
161#include "CglProbing.hpp"
162#include "CglKnapsackCover.hpp"
163#include "CglRedSplit.hpp"
164#include "CglClique.hpp"
165#include "CglFlowCover.hpp"
166#include "CglMixedIntegerRounding2.hpp"
167#include "CglTwomir.hpp"
168#include "CglDuplicateRow.hpp"
169#include "CglStored.hpp"
170#include "CglLandP.hpp"
171#include "CglResidualCapacity.hpp"
172
173#ifdef ZERO_HALF_CUTS
174#include "CglZeroHalf.hpp"
175#endif
176
177#include "CbcModel.hpp"
178#include "CbcHeuristic.hpp"
179#include "CbcHeuristicLocal.hpp"
180#include "CbcHeuristicPivotAndFix.hpp"
181//#include "CbcHeuristicPivotAndComplement.hpp"
182#include "CbcHeuristicRandRound.hpp"
183#include "CbcHeuristicGreedy.hpp"
184#include "CbcHeuristicFPump.hpp"
185#include "CbcHeuristicRINS.hpp"
186#include "CbcHeuristicDiveCoefficient.hpp"
187#include "CbcHeuristicDiveFractional.hpp"
188#include "CbcHeuristicDiveGuided.hpp"
189#include "CbcHeuristicDiveVectorLength.hpp"
190#include "CbcHeuristicDivePseudoCost.hpp"
191#include "CbcHeuristicDiveLineSearch.hpp"
192#include "CbcTreeLocal.hpp"
193#include "CbcCompareActual.hpp"
194#include "CbcBranchActual.hpp"
195#include "CbcBranchLotsize.hpp"
196#include  "CbcOrClpParam.hpp"
197#include  "CbcCutGenerator.hpp"
198#include  "CbcStrategy.hpp"
199#include "CbcBranchCut.hpp"
200
201#include "OsiClpSolverInterface.hpp"
202
203#include "CbcSolver.hpp"
204
205//#define IN_BRANCH_AND_BOUND (0x01000000|262144)
206#define IN_BRANCH_AND_BOUND (0x01000000|262144|128|1024|2048)
207//#define IN_BRANCH_AND_BOUND (0x01000000|262144|128)
208
209/*
210  CbcStopNow class definitions.
211*/
212
213CbcStopNow::CbcStopNow()
214{
215}
216CbcStopNow::~CbcStopNow()
217{
218}
219// Copy constructor
220CbcStopNow::CbcStopNow ( const CbcStopNow & )
221{
222}
223// Assignment operator
224CbcStopNow &
225CbcStopNow::operator=(const CbcStopNow & rhs)
226{
227    if (this != &rhs) {
228    }
229    return *this;
230}
231// Clone
232CbcStopNow *
233CbcStopNow::clone() const
234{
235    return new CbcStopNow(*this);
236}
237
238/*
239  CbcUser class definitions.
240*/
241
242// User stuff (base class)
243CbcUser::CbcUser()
244        : coinModel_(NULL),
245        userName_("null")
246{
247}
248CbcUser::~CbcUser()
249{
250    delete coinModel_;
251}
252// Copy constructor
253CbcUser::CbcUser ( const CbcUser & rhs)
254{
255    if (rhs.coinModel_)
256        coinModel_ = new CoinModel(*rhs.coinModel_);
257    else
258        coinModel_ = NULL;
259    userName_ = rhs.userName_;
260}
261// Assignment operator
262CbcUser &
263CbcUser::operator=(const CbcUser & rhs)
264{
265    if (this != &rhs) {
266        if (rhs.coinModel_)
267            coinModel_ = new CoinModel(*rhs.coinModel_);
268        else
269            coinModel_ = NULL;
270        userName_ = rhs.userName_;
271    }
272    return *this;
273}
274
275/*
276  CbcSolver class definitions
277*/
278
279CbcSolver::CbcSolver()
280        : babModel_(NULL),
281        userFunction_(NULL),
282        statusUserFunction_(NULL),
283        originalSolver_(NULL),
284        originalCoinModel_(NULL),
285        cutGenerator_(NULL),
286        numberUserFunctions_(0),
287        numberCutGenerators_(0),
288        startTime_(CoinCpuTime()),
289        parameters_(NULL),
290        numberParameters_(0),
291        doMiplib_(false),
292        noPrinting_(false),
293        readMode_(1)
294{
295    callBack_ = new CbcStopNow();
296    fillParameters();
297}
298CbcSolver::CbcSolver(const OsiClpSolverInterface & solver)
299        : babModel_(NULL),
300        userFunction_(NULL),
301        statusUserFunction_(NULL),
302        originalSolver_(NULL),
303        originalCoinModel_(NULL),
304        cutGenerator_(NULL),
305        numberUserFunctions_(0),
306        numberCutGenerators_(0),
307        startTime_(CoinCpuTime()),
308        parameters_(NULL),
309        numberParameters_(0),
310        doMiplib_(false),
311        noPrinting_(false),
312        readMode_(1)
313{
314    callBack_ = new CbcStopNow();
315    model_ = CbcModel(solver);
316    fillParameters();
317}
318CbcSolver::CbcSolver(const CbcModel & solver)
319        : babModel_(NULL),
320        userFunction_(NULL),
321        statusUserFunction_(NULL),
322        originalSolver_(NULL),
323        originalCoinModel_(NULL),
324        cutGenerator_(NULL),
325        numberUserFunctions_(0),
326        numberCutGenerators_(0),
327        startTime_(CoinCpuTime()),
328        parameters_(NULL),
329        numberParameters_(0),
330        doMiplib_(false),
331        noPrinting_(false),
332        readMode_(1)
333{
334    callBack_ = new CbcStopNow();
335    model_ = solver;
336    fillParameters();
337}
338CbcSolver::~CbcSolver()
339{
340    int i;
341    for (i = 0; i < numberUserFunctions_; i++)
342        delete userFunction_[i];
343    delete [] userFunction_;
344    for (i = 0; i < numberCutGenerators_; i++)
345        delete cutGenerator_[i];
346    delete [] cutGenerator_;
347    delete [] statusUserFunction_;
348    delete originalSolver_;
349    delete originalCoinModel_;
350    delete babModel_;
351    delete [] parameters_;
352    delete callBack_;
353}
354// Copy constructor
355CbcSolver::CbcSolver ( const CbcSolver & rhs)
356        : model_(rhs.model_),
357        babModel_(NULL),
358        userFunction_(NULL),
359        statusUserFunction_(NULL),
360        numberUserFunctions_(rhs.numberUserFunctions_),
361        startTime_(CoinCpuTime()),
362        parameters_(NULL),
363        numberParameters_(rhs.numberParameters_),
364        doMiplib_(rhs.doMiplib_),
365        noPrinting_(rhs.noPrinting_),
366        readMode_(rhs.readMode_)
367{
368    fillParameters();
369    if (rhs.babModel_)
370        babModel_ = new CbcModel(*rhs.babModel_);
371    userFunction_ = new CbcUser * [numberUserFunctions_];
372    int i;
373    for (i = 0; i < numberUserFunctions_; i++)
374        userFunction_[i] = rhs.userFunction_[i]->clone();
375    for (i = 0; i < numberParameters_; i++)
376        parameters_[i] = rhs.parameters_[i];
377    for (i = 0; i < numberCutGenerators_; i++)
378        cutGenerator_[i] = rhs.cutGenerator_[i]->clone();
379    callBack_ = rhs.callBack_->clone();
380    originalSolver_ = NULL;
381    if (rhs.originalSolver_) {
382        OsiSolverInterface * temp = rhs.originalSolver_->clone();
383        originalSolver_ = dynamic_cast<OsiClpSolverInterface *> (temp);
384        assert (originalSolver_);
385    }
386    originalCoinModel_ = NULL;
387    if (rhs.originalCoinModel_)
388        originalCoinModel_ = new CoinModel(*rhs.originalCoinModel_);
389}
390// Assignment operator
391CbcSolver &
392CbcSolver::operator=(const CbcSolver & rhs)
393{
394    if (this != &rhs) {
395        int i;
396        for (i = 0; i < numberUserFunctions_; i++)
397            delete userFunction_[i];
398        delete [] userFunction_;
399        for (i = 0; i < numberCutGenerators_; i++)
400            delete cutGenerator_[i];
401        delete [] cutGenerator_;
402        delete [] statusUserFunction_;
403        delete originalSolver_;
404        delete originalCoinModel_;
405        statusUserFunction_ = NULL;
406        delete babModel_;
407        delete [] parameters_;
408        delete callBack_;
409        numberUserFunctions_ = rhs.numberUserFunctions_;
410        startTime_ = rhs.startTime_;
411        numberParameters_ = rhs.numberParameters_;
412        for (i = 0; i < numberParameters_; i++)
413            parameters_[i] = rhs.parameters_[i];
414        for (i = 0; i < numberCutGenerators_; i++)
415            cutGenerator_[i] = rhs.cutGenerator_[i]->clone();
416        noPrinting_ = rhs.noPrinting_;
417        readMode_ = rhs.readMode_;
418        doMiplib_ = rhs.doMiplib_;
419        model_ = rhs.model_;
420        if (rhs.babModel_)
421            babModel_ = new CbcModel(*rhs.babModel_);
422        else
423            babModel_ = NULL;
424        userFunction_ = new CbcUser * [numberUserFunctions_];
425        for (i = 0; i < numberUserFunctions_; i++)
426            userFunction_[i] = rhs.userFunction_[i]->clone();
427        callBack_ = rhs.callBack_->clone();
428        originalSolver_ = NULL;
429        if (rhs.originalSolver_) {
430            OsiSolverInterface * temp = rhs.originalSolver_->clone();
431            originalSolver_ = dynamic_cast<OsiClpSolverInterface *> (temp);
432            assert (originalSolver_);
433        }
434        originalCoinModel_ = NULL;
435        if (rhs.originalCoinModel_)
436            originalCoinModel_ = new CoinModel(*rhs.originalCoinModel_);
437    }
438    return *this;
439}
440// Get int value
441int CbcSolver::intValue(CbcOrClpParameterType type) const
442{
443    return parameters_[whichParam(type, numberParameters_, parameters_)].intValue();
444}
445// Set int value
446void CbcSolver::setIntValue(CbcOrClpParameterType type, int value)
447{
448    parameters_[whichParam(type, numberParameters_, parameters_)].setIntValue(value);
449}
450// Get double value
451double CbcSolver::doubleValue(CbcOrClpParameterType type) const
452{
453    return parameters_[whichParam(type, numberParameters_, parameters_)].doubleValue();
454}
455// Set double value
456void CbcSolver::setDoubleValue(CbcOrClpParameterType type, double value)
457{
458    parameters_[whichParam(type, numberParameters_, parameters_)].setDoubleValue(value);
459}
460// User function (NULL if no match)
461CbcUser * CbcSolver::userFunction(const char * name) const
462{
463    int i;
464    for (i = 0; i < numberUserFunctions_; i++) {
465        if (!strcmp(name, userFunction_[i]->name().c_str()))
466            break;
467    }
468    if (i < numberUserFunctions_)
469        return userFunction_[i];
470    else
471        return NULL;
472}
473void CbcSolver::fillParameters()
474{
475    int maxParam = 200;
476    CbcOrClpParam * parameters = new CbcOrClpParam [maxParam];
477    numberParameters_ = 0 ;
478    establishParams(numberParameters_, parameters) ;
479    assert (numberParameters_ <= maxParam);
480    parameters_ = new CbcOrClpParam [numberParameters_];
481    int i;
482    for (i = 0; i < numberParameters_; i++)
483        parameters_[i] = parameters[i];
484    delete [] parameters;
485    const char dirsep =  CoinFindDirSeparator();
486    std::string directory;
487    std::string dirSample;
488    std::string dirNetlib;
489    std::string dirMiplib;
490    if (dirsep == '/') {
491        directory = "./";
492        dirSample = "../../Data/Sample/";
493        dirNetlib = "../../Data/Netlib/";
494        dirMiplib = "../../Data/miplib3/";
495    } else {
496        directory = ".\\";
497        dirSample = "..\\..\\..\\..\\Data\\Sample\\";
498        dirNetlib = "..\\..\\..\\..\\Data\\Netlib\\";
499        dirMiplib = "..\\..\\..\\..\\Data\\miplib3\\";
500    }
501    std::string defaultDirectory = directory;
502    std::string importFile = "";
503    std::string exportFile = "default.mps";
504    std::string importBasisFile = "";
505    std::string importPriorityFile = "";
506    std::string debugFile = "";
507    std::string printMask = "";
508    std::string exportBasisFile = "default.bas";
509    std::string saveFile = "default.prob";
510    std::string restoreFile = "default.prob";
511    std::string solutionFile = "stdout";
512    std::string solutionSaveFile = "solution.file";
513    int doIdiot = -1;
514    int outputFormat = 2;
515    int substitution = 3;
516    int dualize = 3;
517    int preSolve = 5;
518    int doSprint = -1;
519    int testOsiParameters = -1;
520    int createSolver = 0;
521    ClpSimplex * lpSolver;
522    OsiClpSolverInterface * clpSolver;
523    if (model_.solver()) {
524        clpSolver = dynamic_cast<OsiClpSolverInterface *> (model_.solver());
525        assert (clpSolver);
526        lpSolver = clpSolver->getModelPtr();
527        assert (lpSolver);
528    } else {
529        lpSolver = new ClpSimplex();
530        clpSolver = new OsiClpSolverInterface(lpSolver, true);
531        createSolver = 1 ;
532    }
533    parameters_[whichParam(CLP_PARAM_ACTION_BASISIN, numberParameters_, parameters_)].setStringValue(importBasisFile);
534    parameters_[whichParam(CBC_PARAM_ACTION_PRIORITYIN, numberParameters_, parameters_)].setStringValue(importPriorityFile);
535    parameters_[whichParam(CLP_PARAM_ACTION_BASISOUT, numberParameters_, parameters_)].setStringValue(exportBasisFile);
536    parameters_[whichParam(CLP_PARAM_ACTION_DEBUG, numberParameters_, parameters_)].setStringValue(debugFile);
537    parameters_[whichParam(CLP_PARAM_ACTION_PRINTMASK, numberParameters_, parameters_)].setStringValue(printMask);
538    parameters_[whichParam(CLP_PARAM_ACTION_DIRECTORY, numberParameters_, parameters_)].setStringValue(directory);
539    parameters_[whichParam(CLP_PARAM_ACTION_DIRSAMPLE, numberParameters_, parameters_)].setStringValue(dirSample);
540    parameters_[whichParam(CLP_PARAM_ACTION_DIRNETLIB, numberParameters_, parameters_)].setStringValue(dirNetlib);
541    parameters_[whichParam(CBC_PARAM_ACTION_DIRMIPLIB, numberParameters_, parameters_)].setStringValue(dirMiplib);
542    parameters_[whichParam(CLP_PARAM_DBL_DUALBOUND, numberParameters_, parameters_)].setDoubleValue(lpSolver->dualBound());
543    parameters_[whichParam(CLP_PARAM_DBL_DUALTOLERANCE, numberParameters_, parameters_)].setDoubleValue(lpSolver->dualTolerance());
544    parameters_[whichParam(CLP_PARAM_ACTION_EXPORT, numberParameters_, parameters_)].setStringValue(exportFile);
545    parameters_[whichParam(CLP_PARAM_INT_IDIOT, numberParameters_, parameters_)].setIntValue(doIdiot);
546    parameters_[whichParam(CLP_PARAM_ACTION_IMPORT, numberParameters_, parameters_)].setStringValue(importFile);
547    parameters_[whichParam(CLP_PARAM_DBL_PRESOLVETOLERANCE, numberParameters_, parameters_)].setDoubleValue(1.0e-8);
548    int iParam = whichParam(CLP_PARAM_INT_SOLVERLOGLEVEL, numberParameters_, parameters_);
549    int value = 1;
550    clpSolver->messageHandler()->setLogLevel(1) ;
551    lpSolver->setLogLevel(1);
552    parameters_[iParam].setIntValue(value);
553    iParam = whichParam(CLP_PARAM_INT_LOGLEVEL, numberParameters_, parameters_);
554    model_.messageHandler()->setLogLevel(value);
555    parameters_[iParam].setIntValue(value);
556    parameters_[whichParam(CLP_PARAM_INT_MAXFACTOR, numberParameters_, parameters_)].setIntValue(lpSolver->factorizationFrequency());
557    parameters_[whichParam(CLP_PARAM_INT_MAXITERATION, numberParameters_, parameters_)].setIntValue(lpSolver->maximumIterations());
558    parameters_[whichParam(CLP_PARAM_INT_OUTPUTFORMAT, numberParameters_, parameters_)].setIntValue(outputFormat);
559    parameters_[whichParam(CLP_PARAM_INT_PRESOLVEPASS, numberParameters_, parameters_)].setIntValue(preSolve);
560    parameters_[whichParam(CLP_PARAM_INT_PERTVALUE, numberParameters_, parameters_)].setIntValue(lpSolver->perturbation());
561    parameters_[whichParam(CLP_PARAM_DBL_PRIMALTOLERANCE, numberParameters_, parameters_)].setDoubleValue(lpSolver->primalTolerance());
562    parameters_[whichParam(CLP_PARAM_DBL_PRIMALWEIGHT, numberParameters_, parameters_)].setDoubleValue(lpSolver->infeasibilityCost());
563    parameters_[whichParam(CLP_PARAM_ACTION_RESTORE, numberParameters_, parameters_)].setStringValue(restoreFile);
564    parameters_[whichParam(CLP_PARAM_ACTION_SAVE, numberParameters_, parameters_)].setStringValue(saveFile);
565    //parameters_[whichParam(CLP_PARAM_DBL_TIMELIMIT,numberParameters_,parameters_)].setDoubleValue(1.0e8);
566    parameters_[whichParam(CBC_PARAM_DBL_TIMELIMIT_BAB, numberParameters_, parameters_)].setDoubleValue(1.0e8);
567    parameters_[whichParam(CLP_PARAM_ACTION_SOLUTION, numberParameters_, parameters_)].setStringValue(solutionFile);
568    parameters_[whichParam(CLP_PARAM_ACTION_SAVESOL, numberParameters_, parameters_)].setStringValue(solutionSaveFile);
569    parameters_[whichParam(CLP_PARAM_INT_SPRINT, numberParameters_, parameters_)].setIntValue(doSprint);
570    parameters_[whichParam(CLP_PARAM_INT_SUBSTITUTION, numberParameters_, parameters_)].setIntValue(substitution);
571    parameters_[whichParam(CLP_PARAM_INT_DUALIZE, numberParameters_, parameters_)].setIntValue(dualize);
572    parameters_[whichParam(CBC_PARAM_INT_NUMBERBEFORE, numberParameters_, parameters_)].setIntValue(model_.numberBeforeTrust());
573    parameters_[whichParam(CBC_PARAM_INT_MAXNODES, numberParameters_, parameters_)].setIntValue(model_.getMaximumNodes());
574    parameters_[whichParam(CBC_PARAM_INT_STRONGBRANCHING, numberParameters_, parameters_)].setIntValue(model_.numberStrong());
575    parameters_[whichParam(CBC_PARAM_DBL_INFEASIBILITYWEIGHT, numberParameters_, parameters_)].setDoubleValue(model_.getDblParam(CbcModel::CbcInfeasibilityWeight));
576    parameters_[whichParam(CBC_PARAM_DBL_INTEGERTOLERANCE, numberParameters_, parameters_)].setDoubleValue(model_.getDblParam(CbcModel::CbcIntegerTolerance));
577    parameters_[whichParam(CBC_PARAM_DBL_INCREMENT, numberParameters_, parameters_)].setDoubleValue(model_.getDblParam(CbcModel::CbcCutoffIncrement));
578    parameters_[whichParam(CBC_PARAM_INT_TESTOSI, numberParameters_, parameters_)].setIntValue(testOsiParameters);
579    parameters_[whichParam(CBC_PARAM_INT_FPUMPTUNE, numberParameters_, parameters_)].setIntValue(1003);
580    initialPumpTune = 1003;
581#ifdef CBC_THREAD
582    parameters_[whichParam(CBC_PARAM_INT_THREADS, numberParameters_, parameters_)].setIntValue(0);
583#endif
584    // Set up likely cut generators and defaults
585    parameters_[whichParam(CBC_PARAM_STR_PREPROCESS, numberParameters_, parameters_)].setCurrentOption("sos");
586    parameters_[whichParam(CBC_PARAM_INT_MIPOPTIONS, numberParameters_, parameters_)].setIntValue(1057);
587    parameters_[whichParam(CBC_PARAM_INT_CUTPASSINTREE, numberParameters_, parameters_)].setIntValue(1);
588    parameters_[whichParam(CBC_PARAM_INT_MOREMIPOPTIONS, numberParameters_, parameters_)].setIntValue(-1);
589    parameters_[whichParam(CBC_PARAM_INT_MAXHOTITS, numberParameters_, parameters_)].setIntValue(100);
590    parameters_[whichParam(CBC_PARAM_STR_CUTSSTRATEGY, numberParameters_, parameters_)].setCurrentOption("on");
591    parameters_[whichParam(CBC_PARAM_STR_HEURISTICSTRATEGY, numberParameters_, parameters_)].setCurrentOption("on");
592    parameters_[whichParam(CBC_PARAM_STR_NODESTRATEGY, numberParameters_, parameters_)].setCurrentOption("fewest");
593    parameters_[whichParam(CBC_PARAM_STR_GOMORYCUTS, numberParameters_, parameters_)].setCurrentOption("ifmove");
594    parameters_[whichParam(CBC_PARAM_STR_PROBINGCUTS, numberParameters_, parameters_)].setCurrentOption("ifmove");
595    parameters_[whichParam(CBC_PARAM_STR_KNAPSACKCUTS, numberParameters_, parameters_)].setCurrentOption("ifmove");
596#ifdef ZERO_HALF_CUTS
597    parameters_[whichParam(CBC_PARAM_STR_ZEROHALFCUTS, numberParameters_, parameters_)].setCurrentOption("off");
598#endif
599    parameters_[whichParam(CBC_PARAM_STR_REDSPLITCUTS, numberParameters_, parameters_)].setCurrentOption("off");
600    parameters_[whichParam(CBC_PARAM_STR_CLIQUECUTS, numberParameters_, parameters_)].setCurrentOption("ifmove");
601    parameters_[whichParam(CBC_PARAM_STR_MIXEDCUTS, numberParameters_, parameters_)].setCurrentOption("ifmove");
602    parameters_[whichParam(CBC_PARAM_STR_FLOWCUTS, numberParameters_, parameters_)].setCurrentOption("ifmove");
603    parameters_[whichParam(CBC_PARAM_STR_TWOMIRCUTS, numberParameters_, parameters_)].setCurrentOption("root");
604    parameters_[whichParam(CBC_PARAM_STR_LANDPCUTS, numberParameters_, parameters_)].setCurrentOption("off");
605    parameters_[whichParam(CBC_PARAM_STR_RESIDCUTS, numberParameters_, parameters_)].setCurrentOption("off");
606    parameters_[whichParam(CBC_PARAM_STR_ROUNDING, numberParameters_, parameters_)].setCurrentOption("on");
607    parameters_[whichParam(CBC_PARAM_STR_FPUMP, numberParameters_, parameters_)].setCurrentOption("on");
608    parameters_[whichParam(CBC_PARAM_STR_GREEDY, numberParameters_, parameters_)].setCurrentOption("on");
609    parameters_[whichParam(CBC_PARAM_STR_COMBINE, numberParameters_, parameters_)].setCurrentOption("on");
610    parameters_[whichParam(CBC_PARAM_STR_CROSSOVER2, numberParameters_, parameters_)].setCurrentOption("off");
611    parameters_[whichParam(CBC_PARAM_STR_PIVOTANDCOMPLEMENT, numberParameters_, parameters_)].setCurrentOption("off");
612    parameters_[whichParam(CBC_PARAM_STR_PIVOTANDFIX, numberParameters_, parameters_)].setCurrentOption("off");
613    parameters_[whichParam(CBC_PARAM_STR_RANDROUND, numberParameters_, parameters_)].setCurrentOption("off");
614    parameters_[whichParam(CBC_PARAM_STR_NAIVE, numberParameters_, parameters_)].setCurrentOption("off");
615    parameters_[whichParam(CBC_PARAM_STR_RINS, numberParameters_, parameters_)].setCurrentOption("off");
616    parameters_[whichParam(CBC_PARAM_STR_DINS, numberParameters_, parameters_)].setCurrentOption("off");
617    parameters_[whichParam(CBC_PARAM_STR_RENS, numberParameters_, parameters_)].setCurrentOption("off");
618    parameters_[whichParam(CBC_PARAM_STR_LOCALTREE, numberParameters_, parameters_)].setCurrentOption("off");
619    parameters_[whichParam(CBC_PARAM_STR_COSTSTRATEGY, numberParameters_, parameters_)].setCurrentOption("off");
620    if (createSolver)
621        delete clpSolver;
622}
623
624/*
625  Initialise a subset of the parameters prior to processing any input from
626  the user.
627
628  Why this choice of subset?
629*/
630/*!
631  \todo Guard/replace clp-specific code
632*/
633void CbcSolver::fillValuesInSolver()
634{
635    OsiSolverInterface * solver = model_.solver();
636    OsiClpSolverInterface * clpSolver = 
637                dynamic_cast< OsiClpSolverInterface*> (solver);
638    assert (clpSolver);
639        ClpSimplex * lpSolver = clpSolver->getModelPtr();
640
641    /*
642      Why are we reaching into the underlying solver(s) for these settings?
643      Shouldn't CbcSolver have its own defaults, which are then imposed on the
644      underlying solver?
645
646      Coming at if from the other side, if CbcSolver had the capability to use
647      multiple solvers then it definitely makes sense to acquire the defaults from
648      the solver (on the assumption that we haven't processed command line
649      parameters yet, which can then override the defaults). But then it's more of
650      a challenge to avoid solver-specific coding here.
651    */
652    noPrinting_ = (lpSolver->logLevel() == 0);
653    CoinMessageHandler * generalMessageHandler = clpSolver->messageHandler();
654    generalMessageHandler->setPrefix(true);
655
656        lpSolver->setPerturbation(50);
657    lpSolver->messageHandler()->setPrefix(false);
658
659    parameters_[whichParam(CLP_PARAM_DBL_DUALBOUND, numberParameters_, parameters_)].setDoubleValue(lpSolver->dualBound());
660    parameters_[whichParam(CLP_PARAM_DBL_DUALTOLERANCE, numberParameters_, parameters_)].setDoubleValue(lpSolver->dualTolerance());
661    /*
662      Why are we doing this? We read the log level from parameters_, set it into
663      the message handlers for cbc and the underlying solver. Then we read the
664      log level back from the handlers and use it to set the values in
665      parameters_!
666    */
667    int iParam = whichParam(CLP_PARAM_INT_SOLVERLOGLEVEL, numberParameters_, parameters_);
668    int value = parameters_[iParam].intValue();
669    clpSolver->messageHandler()->setLogLevel(value) ;
670    lpSolver->setLogLevel(value);
671    iParam = whichParam(CLP_PARAM_INT_LOGLEVEL, numberParameters_, parameters_);
672    value = parameters_[iParam].intValue();
673    model_.messageHandler()->setLogLevel(value);
674    parameters_[whichParam(CLP_PARAM_INT_LOGLEVEL, numberParameters_, parameters_)].setIntValue(model_.logLevel());
675    parameters_[whichParam(CLP_PARAM_INT_SOLVERLOGLEVEL, numberParameters_, parameters_)].setIntValue(lpSolver->logLevel());
676    parameters_[whichParam(CLP_PARAM_INT_MAXFACTOR, numberParameters_, parameters_)].setIntValue(lpSolver->factorizationFrequency());
677    parameters_[whichParam(CLP_PARAM_INT_MAXITERATION, numberParameters_, parameters_)].setIntValue(lpSolver->maximumIterations());
678    parameters_[whichParam(CLP_PARAM_INT_PERTVALUE, numberParameters_, parameters_)].setIntValue(lpSolver->perturbation());
679    parameters_[whichParam(CLP_PARAM_DBL_PRIMALTOLERANCE, numberParameters_, parameters_)].setDoubleValue(lpSolver->primalTolerance());
680    parameters_[whichParam(CLP_PARAM_DBL_PRIMALWEIGHT, numberParameters_, parameters_)].setDoubleValue(lpSolver->infeasibilityCost());
681    parameters_[whichParam(CBC_PARAM_INT_NUMBERBEFORE, numberParameters_, parameters_)].setIntValue(model_.numberBeforeTrust());
682    parameters_[whichParam(CBC_PARAM_INT_MAXNODES, numberParameters_, parameters_)].setIntValue(model_.getMaximumNodes());
683    parameters_[whichParam(CBC_PARAM_INT_STRONGBRANCHING, numberParameters_, parameters_)].setIntValue(model_.numberStrong());
684    parameters_[whichParam(CBC_PARAM_DBL_INFEASIBILITYWEIGHT, numberParameters_, parameters_)].setDoubleValue(model_.getDblParam(CbcModel::CbcInfeasibilityWeight));
685    parameters_[whichParam(CBC_PARAM_DBL_INTEGERTOLERANCE, numberParameters_, parameters_)].setDoubleValue(model_.getDblParam(CbcModel::CbcIntegerTolerance));
686    parameters_[whichParam(CBC_PARAM_DBL_INCREMENT, numberParameters_, parameters_)].setDoubleValue(model_.getDblParam(CbcModel::CbcCutoffIncrement));
687}
688// Add user function
689void
690CbcSolver::addUserFunction(CbcUser * function)
691{
692    CbcUser ** temp = new CbcUser * [numberUserFunctions_+1];
693    int i;
694    for (i = 0; i < numberUserFunctions_; i++)
695        temp[i] = userFunction_[i];
696    delete [] userFunction_;
697    userFunction_ = temp;
698    userFunction_[numberUserFunctions_++] = function->clone();
699    delete [] statusUserFunction_;
700    statusUserFunction_ = NULL;
701}
702// Set user call back
703void
704CbcSolver::setUserCallBack(CbcStopNow * function)
705{
706    delete callBack_;
707    callBack_ = function->clone();
708}
709// Copy of model on initial load (will contain output solutions)
710void
711CbcSolver::setOriginalSolver(OsiClpSolverInterface * originalSolver)
712{
713    delete originalSolver_;
714    OsiSolverInterface * temp = originalSolver->clone();
715    originalSolver_ = dynamic_cast<OsiClpSolverInterface *> (temp);
716    assert (originalSolver_);
717
718}
719// Copy of model on initial load
720void
721CbcSolver::setOriginalCoinModel(CoinModel * originalCoinModel)
722{
723    delete originalCoinModel_;
724    originalCoinModel_ = new CoinModel(*originalCoinModel);
725}
726// Add cut generator
727void
728CbcSolver::addCutGenerator(CglCutGenerator * generator)
729{
730    CglCutGenerator ** temp = new CglCutGenerator * [numberCutGenerators_+1];
731    int i;
732    for (i = 0; i < numberCutGenerators_; i++)
733        temp[i] = cutGenerator_[i];
734    delete [] cutGenerator_;
735    cutGenerator_ = temp;
736    cutGenerator_[numberCutGenerators_++] = generator->clone();
737}
738
739/*
740  The only other solver that's ever been used is cplex, and the use is very
741  limited -- do the root with clp and all the cbc smarts, then give the
742  problem over to cplex to finish. Although the defines can be read in some
743  places to allow other options, nothing's been tested and success is
744  unlikely.
745
746  CBC_OTHER_SOLVER == 1 is cplex.
747*/
748
749#ifdef CPX_KEEP_RESULTS
750#define CBC_OTHER_SOLVER 1
751#endif
752
753#ifdef COIN_HAS_CPX
754#include "OsiCpxSolverInterface.hpp"
755#endif
756
757#ifdef CBC_OTHER_SOLVER
758#if CBC_OTHER_SOLVER==1
759#include "OsiCpxSolverInterface.hpp"
760#endif
761#endif
762
763#ifdef COIN_HAS_ASL
764#include "Cbc_ampl.h"
765#endif
766
767static double totalTime = 0.0;
768static void statistics(ClpSimplex * originalModel, ClpSimplex * model);
769static bool maskMatches(const int * starts, char ** masks,
770                        std::string & check);
771static void generateCode(CbcModel * model, const char * fileName, int type, int preProcess);
772
773// dummy fake main programs for UserClp and UserCbc
774void fakeMain (ClpSimplex & model, OsiSolverInterface & osiSolver, CbcModel & babSolver);
775void fakeMain2 (ClpSimplex & model, OsiClpSolverInterface & osiSolver, int options);
776
777// Allow for interrupts
778// But is this threadsafe? (so switched off by option)
779
780#include "CoinSignal.hpp"
781static CbcModel * currentBranchModel = NULL;
782
783extern "C" {
784    static void signal_handler(int /*whichSignal*/) {
785        if (currentBranchModel != NULL) {
786            currentBranchModel->setMaximumNodes(0); // stop at next node
787            currentBranchModel->setMaximumSeconds(0.0); // stop
788        }
789        return;
790    }
791}
792
793//#define CBC_SIG_TRAP
794#ifdef CBC_SIG_TRAP
795#include <setjmp.h>
796static sigjmp_buf cbc_seg_buffer;
797extern "C" {
798    static void signal_handler_error(int whichSignal) {
799        siglongjmp(cbc_seg_buffer, 1);
800    }
801}
802#endif
803
804int CbcOrClpRead_mode = 1;
805FILE * CbcOrClpReadCommand = stdin;
806extern int CbcOrClpEnvironmentIndex;
807static bool noPrinting = false;
808
809#ifndef CBC_OTHER_SOLVER
810static int * analyze(OsiClpSolverInterface * solverMod, int & numberChanged, double & increment,
811                     bool changeInt,  CoinMessageHandler * generalMessageHandler)
812{
813    bool noPrinting_ = noPrinting;
814    OsiSolverInterface * solver = solverMod->clone();
815    char generalPrint[200];
816    if (0) {
817        // just get increment
818        CbcModel model(*solver);
819        model.analyzeObjective();
820        double increment2 = model.getCutoffIncrement();
821        printf("initial cutoff increment %g\n", increment2);
822    }
823    const double *objective = solver->getObjCoefficients() ;
824    const double *lower = solver->getColLower() ;
825    const double *upper = solver->getColUpper() ;
826    int numberColumns = solver->getNumCols() ;
827    int numberRows = solver->getNumRows();
828    double direction = solver->getObjSense();
829    int iRow, iColumn;
830
831    // Row copy
832    CoinPackedMatrix matrixByRow(*solver->getMatrixByRow());
833    const double * elementByRow = matrixByRow.getElements();
834    const int * column = matrixByRow.getIndices();
835    const CoinBigIndex * rowStart = matrixByRow.getVectorStarts();
836    const int * rowLength = matrixByRow.getVectorLengths();
837
838    // Column copy
839    CoinPackedMatrix  matrixByCol(*solver->getMatrixByCol());
840    const double * element = matrixByCol.getElements();
841    const int * row = matrixByCol.getIndices();
842    const CoinBigIndex * columnStart = matrixByCol.getVectorStarts();
843    const int * columnLength = matrixByCol.getVectorLengths();
844
845    const double * rowLower = solver->getRowLower();
846    const double * rowUpper = solver->getRowUpper();
847
848    char * ignore = new char [numberRows];
849    int * changed = new int[numberColumns];
850    int * which = new int[numberRows];
851    double * changeRhs = new double[numberRows];
852    memset(changeRhs, 0, numberRows*sizeof(double));
853    memset(ignore, 0, numberRows);
854    numberChanged = 0;
855    int numberInteger = 0;
856    for (iColumn = 0; iColumn < numberColumns; iColumn++) {
857        if (upper[iColumn] > lower[iColumn] + 1.0e-8 && solver->isInteger(iColumn))
858            numberInteger++;
859    }
860    bool finished = false;
861    while (!finished) {
862        int saveNumberChanged = numberChanged;
863        for (iRow = 0; iRow < numberRows; iRow++) {
864            int numberContinuous = 0;
865            double value1 = 0.0, value2 = 0.0;
866            bool allIntegerCoeff = true;
867            double sumFixed = 0.0;
868            int jColumn1 = -1, jColumn2 = -1;
869            for (CoinBigIndex j = rowStart[iRow]; j < rowStart[iRow] + rowLength[iRow]; j++) {
870                int jColumn = column[j];
871                double value = elementByRow[j];
872                if (upper[jColumn] > lower[jColumn] + 1.0e-8) {
873                    if (!solver->isInteger(jColumn)) {
874                        if (numberContinuous == 0) {
875                            jColumn1 = jColumn;
876                            value1 = value;
877                        } else {
878                            jColumn2 = jColumn;
879                            value2 = value;
880                        }
881                        numberContinuous++;
882                    } else {
883                        if (fabs(value - floor(value + 0.5)) > 1.0e-12)
884                            allIntegerCoeff = false;
885                    }
886                } else {
887                    sumFixed += lower[jColumn] * value;
888                }
889            }
890            double low = rowLower[iRow];
891            if (low > -1.0e20) {
892                low -= sumFixed;
893                if (fabs(low - floor(low + 0.5)) > 1.0e-12)
894                    allIntegerCoeff = false;
895            }
896            double up = rowUpper[iRow];
897            if (up < 1.0e20) {
898                up -= sumFixed;
899                if (fabs(up - floor(up + 0.5)) > 1.0e-12)
900                    allIntegerCoeff = false;
901            }
902            if (!allIntegerCoeff)
903                continue; // can't do
904            if (numberContinuous == 1) {
905                // see if really integer
906                // This does not allow for complicated cases
907                if (low == up) {
908                    if (fabs(value1) > 1.0e-3) {
909                        value1 = 1.0 / value1;
910                        if (fabs(value1 - floor(value1 + 0.5)) < 1.0e-12) {
911                            // integer
912                            changed[numberChanged++] = jColumn1;
913                            solver->setInteger(jColumn1);
914                            if (upper[jColumn1] > 1.0e20)
915                                solver->setColUpper(jColumn1, 1.0e20);
916                            if (lower[jColumn1] < -1.0e20)
917                                solver->setColLower(jColumn1, -1.0e20);
918                        }
919                    }
920                } else {
921                    if (fabs(value1) > 1.0e-3) {
922                        value1 = 1.0 / value1;
923                        if (fabs(value1 - floor(value1 + 0.5)) < 1.0e-12) {
924                            // This constraint will not stop it being integer
925                            ignore[iRow] = 1;
926                        }
927                    }
928                }
929            } else if (numberContinuous == 2) {
930                if (low == up) {
931                    /* need general theory - for now just look at 2 cases -
932                       1 - +- 1 one in column and just costs i.e. matching objective
933                       2 - +- 1 two in column but feeds into G/L row which will try and minimize
934                    */
935                    if (fabs(value1) == 1.0 && value1*value2 == -1.0 && !lower[jColumn1]
936                            && !lower[jColumn2]) {
937                        int n = 0;
938                        int i;
939                        double objChange = direction * (objective[jColumn1] + objective[jColumn2]);
940                        double bound = CoinMin(upper[jColumn1], upper[jColumn2]);
941                        bound = CoinMin(bound, 1.0e20);
942                        for ( i = columnStart[jColumn1]; i < columnStart[jColumn1] + columnLength[jColumn1]; i++) {
943                            int jRow = row[i];
944                            double value = element[i];
945                            if (jRow != iRow) {
946                                which[n++] = jRow;
947                                changeRhs[jRow] = value;
948                            }
949                        }
950                        for ( i = columnStart[jColumn1]; i < columnStart[jColumn1] + columnLength[jColumn1]; i++) {
951                            int jRow = row[i];
952                            double value = element[i];
953                            if (jRow != iRow) {
954                                if (!changeRhs[jRow]) {
955                                    which[n++] = jRow;
956                                    changeRhs[jRow] = value;
957                                } else {
958                                    changeRhs[jRow] += value;
959                                }
960                            }
961                        }
962                        if (objChange >= 0.0) {
963                            // see if all rows OK
964                            bool good = true;
965                            for (i = 0; i < n; i++) {
966                                int jRow = which[i];
967                                double value = changeRhs[jRow];
968                                if (value) {
969                                    value *= bound;
970                                    if (rowLength[jRow] == 1) {
971                                        if (value > 0.0) {
972                                            double rhs = rowLower[jRow];
973                                            if (rhs > 0.0) {
974                                                double ratio = rhs / value;
975                                                if (fabs(ratio - floor(ratio + 0.5)) > 1.0e-12)
976                                                    good = false;
977                                            }
978                                        } else {
979                                            double rhs = rowUpper[jRow];
980                                            if (rhs < 0.0) {
981                                                double ratio = rhs / value;
982                                                if (fabs(ratio - floor(ratio + 0.5)) > 1.0e-12)
983                                                    good = false;
984                                            }
985                                        }
986                                    } else if (rowLength[jRow] == 2) {
987                                        if (value > 0.0) {
988                                            if (rowLower[jRow] > -1.0e20)
989                                                good = false;
990                                        } else {
991                                            if (rowUpper[jRow] < 1.0e20)
992                                                good = false;
993                                        }
994                                    } else {
995                                        good = false;
996                                    }
997                                }
998                            }
999                            if (good) {
1000                                // both can be integer
1001                                changed[numberChanged++] = jColumn1;
1002                                solver->setInteger(jColumn1);
1003                                if (upper[jColumn1] > 1.0e20)
1004                                    solver->setColUpper(jColumn1, 1.0e20);
1005                                if (lower[jColumn1] < -1.0e20)
1006                                    solver->setColLower(jColumn1, -1.0e20);
1007                                changed[numberChanged++] = jColumn2;
1008                                solver->setInteger(jColumn2);
1009                                if (upper[jColumn2] > 1.0e20)
1010                                    solver->setColUpper(jColumn2, 1.0e20);
1011                                if (lower[jColumn2] < -1.0e20)
1012                                    solver->setColLower(jColumn2, -1.0e20);
1013                            }
1014                        }
1015                        // clear
1016                        for (i = 0; i < n; i++) {
1017                            changeRhs[which[i]] = 0.0;
1018                        }
1019                    }
1020                }
1021            }
1022        }
1023        for (iColumn = 0; iColumn < numberColumns; iColumn++) {
1024            if (upper[iColumn] > lower[iColumn] + 1.0e-8 && !solver->isInteger(iColumn)) {
1025                double value;
1026                value = upper[iColumn];
1027                if (value < 1.0e20 && fabs(value - floor(value + 0.5)) > 1.0e-12)
1028                    continue;
1029                value = lower[iColumn];
1030                if (value > -1.0e20 && fabs(value - floor(value + 0.5)) > 1.0e-12)
1031                    continue;
1032                bool integer = true;
1033                for (CoinBigIndex j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) {
1034                    int iRow = row[j];
1035                    if (!ignore[iRow]) {
1036                        integer = false;
1037                        break;
1038                    }
1039                }
1040                if (integer) {
1041                    // integer
1042                    changed[numberChanged++] = iColumn;
1043                    solver->setInteger(iColumn);
1044                    if (upper[iColumn] > 1.0e20)
1045                        solver->setColUpper(iColumn, 1.0e20);
1046                    if (lower[iColumn] < -1.0e20)
1047                        solver->setColLower(iColumn, -1.0e20);
1048                }
1049            }
1050        }
1051        finished = numberChanged == saveNumberChanged;
1052    }
1053    delete [] which;
1054    delete [] changeRhs;
1055    delete [] ignore;
1056    //if (numberInteger&&!noPrinting_)
1057    //printf("%d integer variables",numberInteger);
1058    if (changeInt) {
1059        //if (!noPrinting_) {
1060        //if (numberChanged)
1061        //  printf(" and %d variables made integer\n",numberChanged);
1062        //else
1063        //  printf("\n");
1064        //}
1065        delete [] ignore;
1066        //increment=0.0;
1067        if (!numberChanged) {
1068            delete [] changed;
1069            delete solver;
1070            return NULL;
1071        } else {
1072            for (iColumn = 0; iColumn < numberColumns; iColumn++) {
1073                if (solver->isInteger(iColumn))
1074                    solverMod->setInteger(iColumn);
1075            }
1076            delete solver;
1077            return changed;
1078        }
1079    } else {
1080        //if (!noPrinting_) {
1081        //if (numberChanged)
1082        //  printf(" and %d variables could be made integer\n",numberChanged);
1083        //else
1084        //  printf("\n");
1085        //}
1086        // just get increment
1087        int logLevel = generalMessageHandler->logLevel();
1088        CbcModel model(*solver);
1089        model.passInMessageHandler(generalMessageHandler);
1090        if (noPrinting_)
1091            model.setLogLevel(0);
1092        model.analyzeObjective();
1093        generalMessageHandler->setLogLevel(logLevel);
1094        double increment2 = model.getCutoffIncrement();
1095        if (increment2 > increment && increment2 > 0.0) {
1096            if (!noPrinting_) {
1097                sprintf(generalPrint, "Cutoff increment increased from %g to %g", increment, increment2);
1098                CoinMessages generalMessages = solverMod->getModelPtr()->messages();
1099                generalMessageHandler->message(CLP_GENERAL, generalMessages)
1100                << generalPrint
1101                << CoinMessageEol;
1102            }
1103            increment = increment2;
1104        }
1105        delete solver;
1106        numberChanged = 0;
1107        delete [] changed;
1108        return NULL;
1109    }
1110}
1111#endif  // ifndef CBC_OTHER_SOLVER
1112
1113#ifdef COIN_HAS_LINK
1114/*  Returns OsiSolverInterface (User should delete)
1115    On entry numberKnapsack is maximum number of Total entries
1116*/
1117static OsiSolverInterface *
1118expandKnapsack(CoinModel & model, int * whichColumn, int * knapsackStart,
1119               int * knapsackRow, int &numberKnapsack,
1120               CglStored & stored, int logLevel,
1121               int fixedPriority, int SOSPriority, CoinModel & tightenedModel)
1122{
1123    int maxTotal = numberKnapsack;
1124    // load from coin model
1125    OsiSolverLink *si = new OsiSolverLink();
1126    OsiSolverInterface * finalModel = NULL;
1127    si->setDefaultMeshSize(0.001);
1128    // need some relative granularity
1129    si->setDefaultBound(100.0);
1130    si->setDefaultMeshSize(0.01);
1131    si->setDefaultBound(100000.0);
1132    si->setIntegerPriority(1000);
1133    si->setBiLinearPriority(10000);
1134    si->load(model, true, logLevel);
1135    // get priorities
1136    const int * priorities = model.priorities();
1137    int numberColumns = model.numberColumns();
1138    if (priorities) {
1139        OsiObject ** objects = si->objects();
1140        int numberObjects = si->numberObjects();
1141        for (int iObj = 0; iObj < numberObjects; iObj++) {
1142            int iColumn = objects[iObj]->columnNumber();
1143            if (iColumn >= 0 && iColumn < numberColumns) {
1144#ifndef NDEBUG
1145                OsiSimpleInteger * obj =
1146                    dynamic_cast <OsiSimpleInteger *>(objects[iObj]) ;
1147#endif
1148                assert (obj);
1149                int iPriority = priorities[iColumn];
1150                if (iPriority > 0)
1151                    objects[iObj]->setPriority(iPriority);
1152            }
1153        }
1154        if (fixedPriority > 0) {
1155            si->setFixedPriority(fixedPriority);
1156        }
1157        if (SOSPriority < 0)
1158            SOSPriority = 100000;
1159    }
1160    CoinModel coinModel = *si->coinModel();
1161    assert(coinModel.numberRows() > 0);
1162    tightenedModel = coinModel;
1163    int numberRows = coinModel.numberRows();
1164    // Mark variables
1165    int * whichKnapsack = new int [numberColumns];
1166    int iRow, iColumn;
1167    for (iColumn = 0; iColumn < numberColumns; iColumn++)
1168        whichKnapsack[iColumn] = -1;
1169    int kRow;
1170    bool badModel = false;
1171    // analyze
1172    if (logLevel > 1) {
1173        for (iRow = 0; iRow < numberRows; iRow++) {
1174            /* Just obvious one at first
1175            positive non unit coefficients
1176            all integer
1177            positive rowUpper
1178            for now - linear (but further down in code may use nonlinear)
1179            column bounds should be tight
1180            */
1181            //double lower = coinModel.getRowLower(iRow);
1182            double upper = coinModel.getRowUpper(iRow);
1183            if (upper < 1.0e10) {
1184                CoinModelLink triple = coinModel.firstInRow(iRow);
1185                bool possible = true;
1186                int n = 0;
1187                int n1 = 0;
1188                while (triple.column() >= 0) {
1189                    int iColumn = triple.column();
1190                    const char *  el = coinModel.getElementAsString(iRow, iColumn);
1191                    if (!strcmp("Numeric", el)) {
1192                        if (coinModel.columnLower(iColumn) == coinModel.columnUpper(iColumn)) {
1193                            triple = coinModel.next(triple);
1194                            continue; // fixed
1195                        }
1196                        double value = coinModel.getElement(iRow, iColumn);
1197                        if (value < 0.0) {
1198                            possible = false;
1199                        } else {
1200                            n++;
1201                            if (value == 1.0)
1202                                n1++;
1203                            if (coinModel.columnLower(iColumn) < 0.0)
1204                                possible = false;
1205                            if (!coinModel.isInteger(iColumn))
1206                                possible = false;
1207                            if (whichKnapsack[iColumn] >= 0)
1208                                possible = false;
1209                        }
1210                    } else {
1211                        possible = false; // non linear
1212                    }
1213                    triple = coinModel.next(triple);
1214                }
1215                if (n - n1 > 1 && possible) {
1216                    double lower = coinModel.getRowLower(iRow);
1217                    double upper = coinModel.getRowUpper(iRow);
1218                    CoinModelLink triple = coinModel.firstInRow(iRow);
1219                    while (triple.column() >= 0) {
1220                        int iColumn = triple.column();
1221                        lower -= coinModel.columnLower(iColumn) * triple.value();
1222                        upper -= coinModel.columnLower(iColumn) * triple.value();
1223                        triple = coinModel.next(triple);
1224                    }
1225                    printf("%d is possible %g <=", iRow, lower);
1226                    // print
1227                    triple = coinModel.firstInRow(iRow);
1228                    while (triple.column() >= 0) {
1229                        int iColumn = triple.column();
1230                        if (coinModel.columnLower(iColumn) != coinModel.columnUpper(iColumn))
1231                            printf(" (%d,el %g up %g)", iColumn, triple.value(),
1232                                   coinModel.columnUpper(iColumn) - coinModel.columnLower(iColumn));
1233                        triple = coinModel.next(triple);
1234                    }
1235                    printf(" <= %g\n", upper);
1236                }
1237            }
1238        }
1239    }
1240    numberKnapsack = 0;
1241    for (kRow = 0; kRow < numberRows; kRow++) {
1242        iRow = kRow;
1243        /* Just obvious one at first
1244           positive non unit coefficients
1245           all integer
1246           positive rowUpper
1247           for now - linear (but further down in code may use nonlinear)
1248           column bounds should be tight
1249        */
1250        //double lower = coinModel.getRowLower(iRow);
1251        double upper = coinModel.getRowUpper(iRow);
1252        if (upper < 1.0e10) {
1253            CoinModelLink triple = coinModel.firstInRow(iRow);
1254            bool possible = true;
1255            int n = 0;
1256            int n1 = 0;
1257            while (triple.column() >= 0) {
1258                int iColumn = triple.column();
1259                const char *  el = coinModel.getElementAsString(iRow, iColumn);
1260                if (!strcmp("Numeric", el)) {
1261                    if (coinModel.columnLower(iColumn) == coinModel.columnUpper(iColumn)) {
1262                        triple = coinModel.next(triple);
1263                        continue; // fixed
1264                    }
1265                    double value = coinModel.getElement(iRow, iColumn);
1266                    if (value < 0.0) {
1267                        possible = false;
1268                    } else {
1269                        n++;
1270                        if (value == 1.0)
1271                            n1++;
1272                        if (coinModel.columnLower(iColumn) < 0.0)
1273                            possible = false;
1274                        if (!coinModel.isInteger(iColumn))
1275                            possible = false;
1276                        if (whichKnapsack[iColumn] >= 0)
1277                            possible = false;
1278                    }
1279                } else {
1280                    possible = false; // non linear
1281                }
1282                triple = coinModel.next(triple);
1283            }
1284            if (n - n1 > 1 && possible) {
1285                // try
1286                CoinModelLink triple = coinModel.firstInRow(iRow);
1287                while (triple.column() >= 0) {
1288                    int iColumn = triple.column();
1289                    if (coinModel.columnLower(iColumn) != coinModel.columnUpper(iColumn))
1290                        whichKnapsack[iColumn] = numberKnapsack;
1291                    triple = coinModel.next(triple);
1292                }
1293                knapsackRow[numberKnapsack++] = iRow;
1294            }
1295        }
1296    }
1297    if (logLevel > 0)
1298        printf("%d out of %d candidate rows are possible\n", numberKnapsack, numberRows);
1299    // Check whether we can get rid of nonlinearities
1300    /* mark rows
1301       -2 in knapsack and other variables
1302       -1 not involved
1303       n only in knapsack n
1304    */
1305    int * markRow = new int [numberRows];
1306    for (iRow = 0; iRow < numberRows; iRow++)
1307        markRow[iRow] = -1;
1308    int canDo = 1; // OK and linear
1309    for (iColumn = 0; iColumn < numberColumns; iColumn++) {
1310        CoinModelLink triple = coinModel.firstInColumn(iColumn);
1311        int iKnapsack = whichKnapsack[iColumn];
1312        bool linear = true;
1313        // See if quadratic objective
1314        const char * expr = coinModel.getColumnObjectiveAsString(iColumn);
1315        if (strcmp(expr, "Numeric")) {
1316            linear = false;
1317        }
1318        while (triple.row() >= 0) {
1319            int iRow = triple.row();
1320            if (iKnapsack >= 0) {
1321                if (markRow[iRow] == -1) {
1322                    markRow[iRow] = iKnapsack;
1323                } else if (markRow[iRow] != iKnapsack) {
1324                    markRow[iRow] = -2;
1325                }
1326            }
1327            const char * expr = coinModel.getElementAsString(iRow, iColumn);
1328            if (strcmp(expr, "Numeric")) {
1329                linear = false;
1330            }
1331            triple = coinModel.next(triple);
1332        }
1333        if (!linear) {
1334            if (whichKnapsack[iColumn] < 0) {
1335                canDo = 0;
1336                break;
1337            } else {
1338                canDo = 2;
1339            }
1340        }
1341    }
1342    int * markKnapsack = NULL;
1343    double * coefficient = NULL;
1344    double * linear = NULL;
1345    int * whichRow = NULL;
1346    int * lookupRow = NULL;
1347    badModel = (canDo == 0);
1348    if (numberKnapsack && canDo) {
1349        /* double check - OK if
1350           no nonlinear
1351           nonlinear only on columns in knapsack
1352           nonlinear only on columns in knapsack * ONE other - same for all in knapsack
1353           AND that is only row connected to knapsack
1354           (theoretically could split knapsack if two other and small numbers)
1355           also ONE could be ONE expression - not just a variable
1356        */
1357        int iKnapsack;
1358        markKnapsack = new int [numberKnapsack];
1359        coefficient = new double [numberKnapsack];
1360        linear = new double [numberColumns];
1361        for (iKnapsack = 0; iKnapsack < numberKnapsack; iKnapsack++)
1362            markKnapsack[iKnapsack] = -1;
1363        if (canDo == 2) {
1364            for (iRow = -1; iRow < numberRows; iRow++) {
1365                int numberOdd;
1366                CoinPackedMatrix * row = coinModel.quadraticRow(iRow, linear, numberOdd);
1367                if (row) {
1368                    // see if valid
1369                    const double * element = row->getElements();
1370                    const int * column = row->getIndices();
1371                    const CoinBigIndex * columnStart = row->getVectorStarts();
1372                    const int * columnLength = row->getVectorLengths();
1373                    int numberLook = row->getNumCols();
1374                    for (int i = 0; i < numberLook; i++) {
1375                        int iKnapsack = whichKnapsack[i];
1376                        if (iKnapsack < 0) {
1377                            // might be able to swap - but for now can't have knapsack in
1378                            for (int j = columnStart[i]; j < columnStart[i] + columnLength[i]; j++) {
1379                                int iColumn = column[j];
1380                                if (whichKnapsack[iColumn] >= 0) {
1381                                    canDo = 0; // no good
1382                                    badModel = true;
1383                                    break;
1384                                }
1385                            }
1386                        } else {
1387                            // OK if in same knapsack - or maybe just one
1388                            int marked = markKnapsack[iKnapsack];
1389                            for (int j = columnStart[i]; j < columnStart[i] + columnLength[i]; j++) {
1390                                int iColumn = column[j];
1391                                if (whichKnapsack[iColumn] != iKnapsack && whichKnapsack[iColumn] >= 0) {
1392                                    canDo = 0; // no good
1393                                    badModel = true;
1394                                    break;
1395                                } else if (marked == -1) {
1396                                    markKnapsack[iKnapsack] = iColumn;
1397                                    marked = iColumn;
1398                                    coefficient[iKnapsack] = element[j];
1399                                    coinModel.associateElement(coinModel.columnName(iColumn), 1.0);
1400                                } else if (marked != iColumn) {
1401                                    badModel = true;
1402                                    canDo = 0; // no good
1403                                    break;
1404                                } else {
1405                                    // could manage with different coefficients - but for now ...
1406                                    assert(coefficient[iKnapsack] == element[j]);
1407                                }
1408                            }
1409                        }
1410                    }
1411                    delete row;
1412                }
1413            }
1414        }
1415        if (canDo) {
1416            // for any rows which are cuts
1417            whichRow = new int [numberRows];
1418            lookupRow = new int [numberRows];
1419            bool someNonlinear = false;
1420            double maxCoefficient = 1.0;
1421            for (iKnapsack = 0; iKnapsack < numberKnapsack; iKnapsack++) {
1422                if (markKnapsack[iKnapsack] >= 0) {
1423                    someNonlinear = true;
1424                    int iColumn = markKnapsack[iKnapsack];
1425                    maxCoefficient = CoinMax(maxCoefficient, fabs(coefficient[iKnapsack] * coinModel.columnUpper(iColumn)));
1426                }
1427            }
1428            if (someNonlinear) {
1429                // associate all columns to stop possible error messages
1430                for (iColumn = 0; iColumn < numberColumns; iColumn++) {
1431                    coinModel.associateElement(coinModel.columnName(iColumn), 1.0);
1432                }
1433            }
1434            ClpSimplex tempModel;
1435            tempModel.loadProblem(coinModel);
1436            // Create final model - first without knapsacks
1437            int nCol = 0;
1438            int nRow = 0;
1439            for (iRow = 0; iRow < numberRows; iRow++) {
1440                if (markRow[iRow] < 0) {
1441                    lookupRow[iRow] = nRow;
1442                    whichRow[nRow++] = iRow;
1443                } else {
1444                    lookupRow[iRow] = -1;
1445                }
1446            }
1447            for (iColumn = 0; iColumn < numberColumns; iColumn++) {
1448                if (whichKnapsack[iColumn] < 0)
1449                    whichColumn[nCol++] = iColumn;
1450            }
1451            ClpSimplex finalModelX(&tempModel, nRow, whichRow, nCol, whichColumn, false, false, false);
1452            OsiClpSolverInterface finalModelY(&finalModelX, true);
1453            finalModel = finalModelY.clone();
1454            finalModelY.releaseClp();
1455            // Put back priorities
1456            const int * priorities = model.priorities();
1457            if (priorities) {
1458                finalModel->findIntegers(false);
1459                OsiObject ** objects = finalModel->objects();
1460                int numberObjects = finalModel->numberObjects();
1461                for (int iObj = 0; iObj < numberObjects; iObj++) {
1462                    int iColumn = objects[iObj]->columnNumber();
1463                    if (iColumn >= 0 && iColumn < nCol) {
1464#ifndef NDEBUG
1465                        OsiSimpleInteger * obj =
1466                            dynamic_cast <OsiSimpleInteger *>(objects[iObj]) ;
1467#endif
1468                        assert (obj);
1469                        int iPriority = priorities[whichColumn[iColumn]];
1470                        if (iPriority > 0)
1471                            objects[iObj]->setPriority(iPriority);
1472                    }
1473                }
1474            }
1475            for (iRow = 0; iRow < numberRows; iRow++) {
1476                whichRow[iRow] = iRow;
1477            }
1478            int numberOther = finalModel->getNumCols();
1479            int nLargest = 0;
1480            int nelLargest = 0;
1481            int nTotal = 0;
1482            for (iKnapsack = 0; iKnapsack < numberKnapsack; iKnapsack++) {
1483                iRow = knapsackRow[iKnapsack];
1484                int nCreate = maxTotal;
1485                int nelCreate = coinModel.expandKnapsack(iRow, nCreate, NULL, NULL, NULL, NULL);
1486                if (nelCreate < 0)
1487                    badModel = true;
1488                nTotal += nCreate;
1489                nLargest = CoinMax(nLargest, nCreate);
1490                nelLargest = CoinMax(nelLargest, nelCreate);
1491            }
1492            if (nTotal > maxTotal)
1493                badModel = true;
1494            if (!badModel) {
1495                // Now arrays for building
1496                nelLargest = CoinMax(nelLargest, nLargest) + 1;
1497                double * buildObj = new double [nLargest];
1498                double * buildElement = new double [nelLargest];
1499                int * buildStart = new int[nLargest+1];
1500                int * buildRow = new int[nelLargest];
1501                // alow for integers in knapsacks
1502                OsiObject ** object = new OsiObject * [numberKnapsack+nTotal];
1503                int nSOS = 0;
1504                int nObj = numberKnapsack;
1505                for (iKnapsack = 0; iKnapsack < numberKnapsack; iKnapsack++) {
1506                    knapsackStart[iKnapsack] = finalModel->getNumCols();
1507                    iRow = knapsackRow[iKnapsack];
1508                    int nCreate = 10000;
1509                    coinModel.expandKnapsack(iRow, nCreate, buildObj, buildStart, buildRow, buildElement);
1510                    // Redo row numbers
1511                    for (iColumn = 0; iColumn < nCreate; iColumn++) {
1512                        for (int j = buildStart[iColumn]; j < buildStart[iColumn+1]; j++) {
1513                            int jRow = buildRow[j];
1514                            jRow = lookupRow[jRow];
1515                            assert (jRow >= 0 && jRow < nRow);
1516                            buildRow[j] = jRow;
1517                        }
1518                    }
1519                    finalModel->addCols(nCreate, buildStart, buildRow, buildElement, NULL, NULL, buildObj);
1520                    int numberFinal = finalModel->getNumCols();
1521                    for (iColumn = numberOther; iColumn < numberFinal; iColumn++) {
1522                        if (markKnapsack[iKnapsack] < 0) {
1523                            finalModel->setColUpper(iColumn, maxCoefficient);
1524                            finalModel->setInteger(iColumn);
1525                        } else {
1526                            finalModel->setColUpper(iColumn, maxCoefficient + 1.0);
1527                            finalModel->setInteger(iColumn);
1528                        }
1529                        OsiSimpleInteger * sosObject = new OsiSimpleInteger(finalModel, iColumn);
1530                        sosObject->setPriority(1000000);
1531                        object[nObj++] = sosObject;
1532                        buildRow[iColumn-numberOther] = iColumn;
1533                        buildElement[iColumn-numberOther] = 1.0;
1534                    }
1535                    if (markKnapsack[iKnapsack] < 0) {
1536                        // convexity row
1537                        finalModel->addRow(numberFinal - numberOther, buildRow, buildElement, 1.0, 1.0);
1538                    } else {
1539                        int iColumn = markKnapsack[iKnapsack];
1540                        int n = numberFinal - numberOther;
1541                        buildRow[n] = iColumn;
1542                        buildElement[n++] = -fabs(coefficient[iKnapsack]);
1543                        // convexity row (sort of)
1544                        finalModel->addRow(n, buildRow, buildElement, 0.0, 0.0);
1545                        OsiSOS * sosObject = new OsiSOS(finalModel, n - 1, buildRow, NULL, 1);
1546                        sosObject->setPriority(iKnapsack + SOSPriority);
1547                        // Say not integral even if is (switch off heuristics)
1548                        sosObject->setIntegerValued(false);
1549                        object[nSOS++] = sosObject;
1550                    }
1551                    numberOther = numberFinal;
1552                }
1553                finalModel->addObjects(nObj, object);
1554                for (iKnapsack = 0; iKnapsack < nObj; iKnapsack++)
1555                    delete object[iKnapsack];
1556                delete [] object;
1557                // Can we move any rows to cuts
1558                const int * cutMarker = coinModel.cutMarker();
1559                if (cutMarker && 0) {
1560                    printf("AMPL CUTS OFF until global cuts fixed\n");
1561                    cutMarker = NULL;
1562                }
1563                if (cutMarker) {
1564                    // Row copy
1565                    const CoinPackedMatrix * matrixByRow = finalModel->getMatrixByRow();
1566                    const double * elementByRow = matrixByRow->getElements();
1567                    const int * column = matrixByRow->getIndices();
1568                    const CoinBigIndex * rowStart = matrixByRow->getVectorStarts();
1569                    const int * rowLength = matrixByRow->getVectorLengths();
1570
1571                    const double * rowLower = finalModel->getRowLower();
1572                    const double * rowUpper = finalModel->getRowUpper();
1573                    int nDelete = 0;
1574                    for (iRow = 0; iRow < numberRows; iRow++) {
1575                        if (cutMarker[iRow] && lookupRow[iRow] >= 0) {
1576                            int jRow = lookupRow[iRow];
1577                            whichRow[nDelete++] = jRow;
1578                            int start = rowStart[jRow];
1579                            stored.addCut(rowLower[jRow], rowUpper[jRow],
1580                                          rowLength[jRow], column + start, elementByRow + start);
1581                        }
1582                    }
1583                    finalModel->deleteRows(nDelete, whichRow);
1584                }
1585                knapsackStart[numberKnapsack] = finalModel->getNumCols();
1586                delete [] buildObj;
1587                delete [] buildElement;
1588                delete [] buildStart;
1589                delete [] buildRow;
1590                finalModel->writeMps("full");
1591            }
1592        }
1593    }
1594    delete [] whichKnapsack;
1595    delete [] markRow;
1596    delete [] markKnapsack;
1597    delete [] coefficient;
1598    delete [] linear;
1599    delete [] whichRow;
1600    delete [] lookupRow;
1601    delete si;
1602    si = NULL;
1603    if (!badModel && finalModel) {
1604        finalModel->setDblParam(OsiObjOffset, coinModel.objectiveOffset());
1605        return finalModel;
1606    } else {
1607        delete finalModel;
1608        printf("can't make knapsacks - did you set fixedPriority (extra1)\n");
1609        return NULL;
1610    }
1611}
1612#endif  //COIN_HAS_LINK
1613
1614/*
1615  Debug checks on special ordered sets.
1616*/
1617#ifdef COIN_DEVELOP
1618void checkSOS(CbcModel * babModel, const OsiSolverInterface * solver)
1619#else
1620void checkSOS(CbcModel * /*babModel*/, const OsiSolverInterface * /*solver*/)
1621#endif
1622{
1623#ifdef COIN_DEVELOP
1624    if (!babModel->ownObjects())
1625        return;
1626#if COIN_DEVELOP>2
1627    //const double *objective = solver->getObjCoefficients() ;
1628    const double *columnLower = solver->getColLower() ;
1629    const double * columnUpper = solver->getColUpper() ;
1630    const double * solution = solver->getColSolution();
1631    //int numberRows = solver->getNumRows();
1632    //double direction = solver->getObjSense();
1633    //int iRow,iColumn;
1634#endif
1635
1636    // Row copy
1637    CoinPackedMatrix matrixByRow(*solver->getMatrixByRow());
1638    //const double * elementByRow = matrixByRow.getElements();
1639    //const int * column = matrixByRow.getIndices();
1640    //const CoinBigIndex * rowStart = matrixByRow.getVectorStarts();
1641    const int * rowLength = matrixByRow.getVectorLengths();
1642
1643    // Column copy
1644    CoinPackedMatrix  matrixByCol(*solver->getMatrixByCol());
1645    const double * element = matrixByCol.getElements();
1646    const int * row = matrixByCol.getIndices();
1647    const CoinBigIndex * columnStart = matrixByCol.getVectorStarts();
1648    const int * columnLength = matrixByCol.getVectorLengths();
1649
1650    const double * rowLower = solver->getRowLower();
1651    const double * rowUpper = solver->getRowUpper();
1652    OsiObject ** objects = babModel->objects();
1653    int numberObjects = babModel->numberObjects();
1654    int numberColumns = solver->getNumCols() ;
1655    for (int iObj = 0; iObj < numberObjects; iObj++) {
1656        CbcSOS * objSOS =
1657            dynamic_cast <CbcSOS *>(objects[iObj]) ;
1658        if (objSOS) {
1659            int n = objSOS->numberMembers();
1660            const int * which = objSOS->members();
1661#if COIN_DEVELOP>2
1662            const double * weight = objSOS->weights();
1663#endif
1664            int type = objSOS->sosType();
1665            // convexity row?
1666            int iColumn;
1667            iColumn = which[0];
1668            int j;
1669            int convex = -1;
1670            for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) {
1671                int iRow = row[j];
1672                double value = element[j];
1673                if (rowLower[iRow] == 1.0 && rowUpper[iRow] == 1.0 &&
1674                        value == 1.0) {
1675                    // possible
1676                    if (rowLength[iRow] == n) {
1677                        if (convex == -1)
1678                            convex = iRow;
1679                        else
1680                            convex = -2;
1681                    }
1682                }
1683            }
1684            printf ("set %d of type %d has %d members - possible convexity row %d\n",
1685                    iObj, type, n, convex);
1686            for (int i = 0; i < n; i++) {
1687                iColumn = which[i];
1688                // Column may have been added
1689                if (iColumn < numberColumns) {
1690                    int convex2 = -1;
1691                    for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) {
1692                        int iRow = row[j];
1693                        if (iRow == convex) {
1694                            double value = element[j];
1695                            if (value == 1.0) {
1696                                convex2 = iRow;
1697                            }
1698                        }
1699                    }
1700                    if (convex2<0 && convex >= 0) {
1701                        printf("odd convexity row\n");
1702                        convex = -2;
1703                    }
1704#if COIN_DEVELOP>2
1705                    printf("col %d has weight %g and value %g, bounds %g %g\n",
1706                           iColumn, weight[i], solution[iColumn], columnLower[iColumn],
1707                           columnUpper[iColumn]);
1708#endif
1709                }
1710            }
1711        }
1712    }
1713#endif  // COIN_DEVELOP
1714}
1715
1716static int dummyCallBack(CbcModel * /*model*/, int /*whereFrom*/)
1717{
1718    return 0;
1719}
1720
1721/*
1722  Various overloads of callCbc1, in rough order, followed by the main definition.
1723*/
1724
1725int callCbc1(const std::string input2, CbcModel & babSolver)
1726{
1727    char * input3 = CoinStrdup(input2.c_str());
1728    int returnCode = callCbc1(input3, babSolver);
1729    free(input3);
1730    return returnCode;
1731}
1732
1733int callCbc1(const char * input2, CbcModel & model)
1734{
1735    return callCbc1(input2, model, dummyCallBack);
1736}
1737
1738int callCbc1(const std::string input2, CbcModel & babSolver, int callBack(CbcModel * currentSolver, int whereFrom))
1739{
1740    char * input3 = CoinStrdup(input2.c_str());
1741    int returnCode = callCbc1(input3, babSolver, callBack);
1742    free(input3);
1743    return returnCode;
1744}
1745
1746int callCbc1(const char * input2, CbcModel & model, int callBack(CbcModel * currentSolver, int whereFrom))
1747{
1748    char * input = CoinStrdup(input2);
1749    int length = strlen(input);
1750    bool blank = input[0] == '0';
1751    int n = blank ? 0 : 1;
1752    for (int i = 0; i < length; i++) {
1753        if (blank) {
1754            // look for next non blank
1755            if (input[i] == ' ') {
1756                continue;
1757            } else {
1758                n++;
1759                blank = false;
1760            }
1761        } else {
1762            // look for next blank
1763            if (input[i] != ' ') {
1764                continue;
1765            } else {
1766                blank = true;
1767            }
1768        }
1769    }
1770    char ** argv = new char * [n+2];
1771    argv[0] = CoinStrdup("cbc");
1772    int i = 0;
1773    while (input[i] == ' ')
1774        i++;
1775    for (int j = 0; j < n; j++) {
1776        int saveI = i;
1777        for (; i < length; i++) {
1778            // look for next blank
1779            if (input[i] != ' ') {
1780                continue;
1781            } else {
1782                break;
1783            }
1784        }
1785        input[i] = '\0';
1786        argv[j+1] = CoinStrdup(input + saveI);
1787        while (input[i] == ' ')
1788            i++;
1789    }
1790    argv[n+1] = CoinStrdup("-quit");
1791    free(input);
1792    totalTime = 0.0;
1793    currentBranchModel = NULL;
1794    CbcOrClpRead_mode = 1;
1795    CbcOrClpReadCommand = stdin;
1796    noPrinting = false;
1797    int returnCode = CbcMain1(n + 2, const_cast<const char **>(argv), model, callBack);
1798    for (int k = 0; k < n + 2; k++)
1799        free(argv[k]);
1800    delete [] argv;
1801    return returnCode;
1802}
1803
1804
1805int callCbc(const char * input2, CbcModel & babSolver)
1806{
1807    CbcMain0(babSolver);
1808    return callCbc1(input2, babSolver);
1809}
1810
1811int callCbc(const std::string input2, CbcModel & babSolver)
1812{
1813    char * input3 = CoinStrdup(input2.c_str());
1814    CbcMain0(babSolver);
1815    int returnCode = callCbc1(input3, babSolver);
1816    free(input3);
1817    return returnCode;
1818}
1819
1820int callCbc(const char * input2, OsiClpSolverInterface& solver1)
1821{
1822    CbcModel model(solver1);
1823    return callCbc(input2, model);
1824}
1825
1826int callCbc(const char * input2)
1827{
1828    {
1829        OsiClpSolverInterface solver1;
1830        return callCbc(input2, solver1);
1831    }
1832}
1833
1834int callCbc(const std::string input2, OsiClpSolverInterface& solver1)
1835{
1836    char * input3 = CoinStrdup(input2.c_str());
1837    int returnCode = callCbc(input3, solver1);
1838    free(input3);
1839    return returnCode;
1840}
1841
1842int callCbc(const std::string input2)
1843{
1844    char * input3 = CoinStrdup(input2.c_str());
1845    OsiClpSolverInterface solver1;
1846    int returnCode = callCbc(input3, solver1);
1847    free(input3);
1848    return returnCode;
1849}
1850
1851#define CBCMAXPARAMETERS 200
1852static CbcOrClpParam parameters[CBCMAXPARAMETERS];
1853static int numberParameters = 0 ;
1854
1855int CbcClpUnitTest (const CbcModel & saveModel,
1856                    std::string& dirMiplib, int testSwitch,
1857                    double * stuff);
1858
1859int CbcMain1 (int argc, const char *argv[],
1860              CbcModel  & model)
1861{
1862    return CbcMain1(argc, argv, model, dummyCallBack);
1863}
1864
1865
1866/* Meaning of whereFrom:
1867   1 after initial solve by dualsimplex etc
1868   2 after preprocessing
1869   3 just before branchAndBound (so user can override)
1870   4 just after branchAndBound (before postprocessing)
1871   5 after postprocessing
1872   6 after a user called heuristic phase
1873*/
1874
1875int CbcMain1 (int argc, const char *argv[],
1876              CbcModel  & model,
1877              int callBack(CbcModel * currentSolver, int whereFrom))
1878{
1879    CbcOrClpParam * parameters_ = parameters;
1880    int numberParameters_ = numberParameters;
1881    CbcModel & model_ = model;
1882    CbcModel * babModel_ = NULL;
1883    int returnMode = 1;
1884    CbcOrClpRead_mode = 1;
1885    int statusUserFunction_[1];
1886    int numberUserFunctions_ = 1; // to allow for ampl
1887    // Statistics
1888    double statistics_seconds = 0.0, statistics_obj = 0.0;
1889    double statistics_sys_seconds = 0.0, statistics_elapsed_seconds = 0.0;
1890    CoinWallclockTime();
1891    double statistics_continuous = 0.0, statistics_tighter = 0.0;
1892    double statistics_cut_time = 0.0;
1893    int statistics_nodes = 0, statistics_iterations = 0;
1894    int statistics_nrows = 0, statistics_ncols = 0;
1895    int statistics_nprocessedrows = 0, statistics_nprocessedcols = 0;
1896    std::string statistics_result;
1897    int * statistics_number_cuts = NULL;
1898    const char ** statistics_name_generators = NULL;
1899    int statistics_number_generators = 0;
1900    memset(statusUserFunction_, 0, numberUserFunctions_*sizeof(int));
1901    /* Note
1902       This is meant as a stand-alone executable to do as much of coin as possible.
1903       It should only have one solver known to it.
1904    */
1905    CoinMessageHandler * generalMessageHandler = model_.messageHandler();
1906    generalMessageHandler->setPrefix(false);
1907#ifndef CBC_OTHER_SOLVER
1908    OsiClpSolverInterface * originalSolver = dynamic_cast<OsiClpSolverInterface *> (model_.solver());
1909    assert (originalSolver);
1910    // Move handler across if not default
1911    if (!originalSolver->defaultHandler() && originalSolver->getModelPtr()->defaultHandler())
1912        originalSolver->getModelPtr()->passInMessageHandler(originalSolver->messageHandler());
1913    CoinMessages generalMessages = originalSolver->getModelPtr()->messages();
1914    char generalPrint[10000];
1915    if (originalSolver->getModelPtr()->logLevel() == 0)
1916        noPrinting = true;
1917#elif CBC_OTHER_SOLVER==1
1918    OsiCpxSolverInterface * originalSolver = dynamic_cast<OsiCpxSolverInterface *> (model_.solver());
1919    assert (originalSolver);
1920    OsiClpSolverInterface dummySolver;
1921    OsiCpxSolverInterface * clpSolver = originalSolver;
1922    CoinMessages generalMessages = dummySolver.getModelPtr()->messages();
1923    char generalPrint[10000];
1924    noPrinting = true;
1925#endif
1926    bool noPrinting_ = noPrinting;
1927    // Say not in integer
1928    int integerStatus = -1;
1929    // Say no resolve after cuts
1930    model_.setResolveAfterTakeOffCuts(false);
1931    // see if log in list
1932    for (int i = 1; i < argc; i++) {
1933        if (!strncmp(argv[i], "log", 3)) {
1934            const char * equals = strchr(argv[i], '=');
1935            if (equals && atoi(equals + 1) != 0)
1936                noPrinting_ = false;
1937            else
1938                noPrinting_ = true;
1939            break;
1940        } else if (!strncmp(argv[i], "-log", 4) && i < argc - 1) {
1941            if (atoi(argv[i+1]) != 0)
1942                noPrinting_ = false;
1943            else
1944                noPrinting_ = true;
1945            break;
1946        }
1947    }
1948    double time0;
1949    {
1950        double time1 = CoinCpuTime(), time2;
1951        time0 = time1;
1952        bool goodModel = (originalSolver->getNumCols()) ? true : false;
1953
1954        // register signal handler
1955        //CoinSighandler_t saveSignal=signal(SIGINT,signal_handler);
1956        signal(SIGINT, signal_handler);
1957        // Set up all non-standard stuff
1958        int cutPass = -1234567;
1959        int cutPassInTree = -1234567;
1960        int tunePreProcess = 0;
1961        int testOsiParameters = -1;
1962        // 0 normal, 1 from ampl or MIQP etc (2 allows cuts)
1963        int complicatedInteger = 0;
1964        OsiSolverInterface * solver = model_.solver();
1965        if (noPrinting_)
1966            setCbcOrClpPrinting(false);
1967#ifndef CBC_OTHER_SOLVER
1968        OsiClpSolverInterface * clpSolver = dynamic_cast< OsiClpSolverInterface*> (solver);
1969        ClpSimplex * lpSolver = clpSolver->getModelPtr();
1970        if (noPrinting_) {
1971            lpSolver->setLogLevel(0);
1972        }
1973#else
1974        ClpSimplex * lpSolver = NULL;
1975#endif
1976        // For priorities etc
1977        int * priorities = NULL;
1978        int * branchDirection = NULL;
1979        double * pseudoDown = NULL;
1980        double * pseudoUp = NULL;
1981        double * solutionIn = NULL;
1982        int * prioritiesIn = NULL;
1983        int numberSOS = 0;
1984        int * sosStart = NULL;
1985        int * sosIndices = NULL;
1986        char * sosType = NULL;
1987        double * sosReference = NULL;
1988        int * cut = NULL;
1989        int * sosPriority = NULL;
1990        CglStored storedAmpl;
1991        CoinModel * coinModel = NULL;
1992        CoinModel saveCoinModel;
1993        CoinModel saveTightenedModel;
1994        int * whichColumn = NULL;
1995        int * knapsackStart = NULL;
1996        int * knapsackRow = NULL;
1997        int numberKnapsack = 0;
1998#ifdef COIN_HAS_ASL
1999        ampl_info info;
2000        {
2001            memset(&info, 0, sizeof(info));
2002            if (argc > 2 && !strcmp(argv[2], "-AMPL")) {
2003                statusUserFunction_[0] = 1;
2004                // see if log in list
2005                noPrinting_ = true;
2006                for (int i = 1; i < argc; i++) {
2007                    if (!strncmp(argv[i], "log", 3)) {
2008                        const char * equals = strchr(argv[i], '=');
2009                        if (equals && atoi(equals + 1) > 0) {
2010                            noPrinting_ = false;
2011                            info.logLevel = atoi(equals + 1);
2012                            int log = whichParam(CLP_PARAM_INT_LOGLEVEL, numberParameters_, parameters_);
2013                            parameters_[log].setIntValue(info.logLevel);
2014                            // mark so won't be overWritten
2015                            info.numberRows = -1234567;
2016                            break;
2017                        }
2018                    }
2019                }
2020
2021                union {
2022                    void * voidModel;
2023                    CoinModel * model;
2024                } coinModelStart;
2025                coinModelStart.model = NULL;
2026                int returnCode = readAmpl(&info, argc, const_cast<char **>(argv), & coinModelStart.voidModel);
2027                coinModel = coinModelStart.model;
2028                if (returnCode)
2029                    return returnCode;
2030                CbcOrClpRead_mode = 2; // so will start with parameters
2031                // see if log in list (including environment)
2032                for (int i = 1; i < info.numberArguments; i++) {
2033                    if (!strcmp(info.arguments[i], "log")) {
2034                        if (i < info.numberArguments - 1 && atoi(info.arguments[i+1]) > 0)
2035                            noPrinting_ = false;
2036                        break;
2037                    }
2038                }
2039                if (noPrinting_) {
2040                    model_.messageHandler()->setLogLevel(0);
2041                    setCbcOrClpPrinting(false);
2042                }
2043                if (!noPrinting_)
2044                    printf("%d rows, %d columns and %d elements\n",
2045                           info.numberRows, info.numberColumns, info.numberElements);
2046#ifdef COIN_HAS_LINK
2047                if (!coinModel) {
2048#endif
2049                    solver->loadProblem(info.numberColumns, info.numberRows, info.starts,
2050                                        info.rows, info.elements,
2051                                        info.columnLower, info.columnUpper, info.objective,
2052                                        info.rowLower, info.rowUpper);
2053                    // take off cuts if ampl wants that
2054                    if (info.cut && 0) {
2055                        printf("AMPL CUTS OFF until global cuts fixed\n");
2056                        info.cut = NULL;
2057                    }
2058                    if (info.cut) {
2059                        int numberRows = info.numberRows;
2060                        int * whichRow = new int [numberRows];
2061                        // Row copy
2062                        const CoinPackedMatrix * matrixByRow = solver->getMatrixByRow();
2063                        const double * elementByRow = matrixByRow->getElements();
2064                        const int * column = matrixByRow->getIndices();
2065                        const CoinBigIndex * rowStart = matrixByRow->getVectorStarts();
2066                        const int * rowLength = matrixByRow->getVectorLengths();
2067
2068                        const double * rowLower = solver->getRowLower();
2069                        const double * rowUpper = solver->getRowUpper();
2070                        int nDelete = 0;
2071                        for (int iRow = 0; iRow < numberRows; iRow++) {
2072                            if (info.cut[iRow]) {
2073                                whichRow[nDelete++] = iRow;
2074                                int start = rowStart[iRow];
2075                                storedAmpl.addCut(rowLower[iRow], rowUpper[iRow],
2076                                                  rowLength[iRow], column + start, elementByRow + start);
2077                            }
2078                        }
2079                        solver->deleteRows(nDelete, whichRow);
2080                        delete [] whichRow;
2081                    }
2082#ifdef COIN_HAS_LINK
2083                } else {
2084#ifndef CBC_OTHER_SOLVER
2085                    // save
2086                    saveCoinModel = *coinModel;
2087                    // load from coin model
2088                    OsiSolverLink solver1;
2089                    OsiSolverInterface * solver2 = solver1.clone();
2090                    model_.assignSolver(solver2, false);
2091                    OsiSolverLink * si =
2092                        dynamic_cast<OsiSolverLink *>(model_.solver()) ;
2093                    assert (si != NULL);
2094                    si->setDefaultMeshSize(0.001);
2095                    // need some relative granularity
2096                    si->setDefaultBound(100.0);
2097                    double dextra3 = parameters_[whichParam(CBC_PARAM_DBL_DEXTRA3, numberParameters_, parameters_)].doubleValue();
2098                    if (dextra3)
2099                        si->setDefaultMeshSize(dextra3);
2100                    si->setDefaultBound(100000.0);
2101                    si->setIntegerPriority(1000);
2102                    si->setBiLinearPriority(10000);
2103                    CoinModel * model2 = reinterpret_cast<CoinModel *> (coinModel);
2104                    int logLevel = parameters_[whichParam(CLP_PARAM_INT_LOGLEVEL, numberParameters_, parameters_)].intValue();
2105                    si->load(*model2, true, logLevel);
2106                    // redo
2107                    solver = model_.solver();
2108                    clpSolver = dynamic_cast< OsiClpSolverInterface*> (solver);
2109                    lpSolver = clpSolver->getModelPtr();
2110                    clpSolver->messageHandler()->setLogLevel(0) ;
2111                    testOsiParameters = 0;
2112                    parameters_[whichParam(CBC_PARAM_INT_TESTOSI, numberParameters_, parameters_)].setIntValue(0);
2113                    complicatedInteger = 1;
2114                    if (info.cut) {
2115                        printf("Sorry - can't do cuts with LOS as ruins delicate row order\n");
2116                        abort();
2117                        int numberRows = info.numberRows;
2118                        int * whichRow = new int [numberRows];
2119                        // Row copy
2120                        const CoinPackedMatrix * matrixByRow = solver->getMatrixByRow();
2121                        const double * elementByRow = matrixByRow->getElements();
2122                        const int * column = matrixByRow->getIndices();
2123                        const CoinBigIndex * rowStart = matrixByRow->getVectorStarts();
2124                        const int * rowLength = matrixByRow->getVectorLengths();
2125
2126                        const double * rowLower = solver->getRowLower();
2127                        const double * rowUpper = solver->getRowUpper();
2128                        int nDelete = 0;
2129                        for (int iRow = 0; iRow < numberRows; iRow++) {
2130                            if (info.cut[iRow]) {
2131                                whichRow[nDelete++] = iRow;
2132                                int start = rowStart[iRow];
2133                                storedAmpl.addCut(rowLower[iRow], rowUpper[iRow],
2134                                                  rowLength[iRow], column + start, elementByRow + start);
2135                            }
2136                        }
2137                        solver->deleteRows(nDelete, whichRow);
2138                        // and special matrix
2139                        si->cleanMatrix()->deleteRows(nDelete, whichRow);
2140                        delete [] whichRow;
2141                    }
2142#endif
2143                }
2144#endif
2145                // If we had a solution use it
2146                if (info.primalSolution) {
2147                    solver->setColSolution(info.primalSolution);
2148                }
2149                // status
2150                if (info.rowStatus) {
2151                    unsigned char * statusArray = lpSolver->statusArray();
2152                    int i;
2153                    for (i = 0; i < info.numberColumns; i++)
2154                        statusArray[i] = static_cast<unsigned char>(info.columnStatus[i]);
2155                    statusArray += info.numberColumns;
2156                    for (i = 0; i < info.numberRows; i++)
2157                        statusArray[i] = static_cast<unsigned char>(info.rowStatus[i]);
2158                    CoinWarmStartBasis * basis = lpSolver->getBasis();
2159                    solver->setWarmStart(basis);
2160                    delete basis;
2161                }
2162                freeArrays1(&info);
2163                // modify objective if necessary
2164                solver->setObjSense(info.direction);
2165                solver->setDblParam(OsiObjOffset, info.offset);
2166                if (info.offset) {
2167                    sprintf(generalPrint, "Ampl objective offset is %g",
2168                            info.offset);
2169                    generalMessageHandler->message(CLP_GENERAL, generalMessages)
2170                    << generalPrint
2171                    << CoinMessageEol;
2172                }
2173                // Set integer variables (unless nonlinear when set)
2174                if (!info.nonLinear) {
2175                    for (int i = info.numberColumns - info.numberIntegers;
2176                            i < info.numberColumns; i++)
2177                        solver->setInteger(i);
2178                }
2179                goodModel = true;
2180                // change argc etc
2181                argc = info.numberArguments;
2182                argv = const_cast<const char **>(info.arguments);
2183            }
2184        }
2185#endif
2186        // default action on import
2187        int allowImportErrors = 0;
2188        int keepImportNames = 1;
2189        int doIdiot = -1;
2190        int outputFormat = 2;
2191        int slpValue = -1;
2192        int cppValue = -1;
2193        int printOptions = 0;
2194        int printMode = 0;
2195        int presolveOptions = 0;
2196        int substitution = 3;
2197        int dualize = 3;
2198        int doCrash = 0;
2199        int doVector = 0;
2200        int doSprint = -1;
2201        int doScaling = 4;
2202        // set reasonable defaults
2203        int preSolve = 5;
2204        int preProcess = 4;
2205        bool useStrategy = false;
2206        bool preSolveFile = false;
2207        bool strongChanged = false;
2208        bool pumpChanged = false;
2209
2210        double djFix = 1.0e100;
2211        double tightenFactor = 0.0;
2212        const char dirsep =  CoinFindDirSeparator();
2213        std::string directory;
2214        std::string dirSample;
2215        std::string dirNetlib;
2216        std::string dirMiplib;
2217        if (dirsep == '/') {
2218            directory = "./";
2219            dirSample = "../../Data/Sample/";
2220            dirNetlib = "../../Data/Netlib/";
2221            dirMiplib = "../../Data/miplib3/";
2222        } else {
2223            directory = ".\\";
2224            dirSample = "..\\..\\..\\..\\Data\\Sample\\";
2225            dirNetlib = "..\\..\\..\\..\\Data\\Netlib\\";
2226            dirMiplib = "..\\..\\..\\..\\Data\\miplib3\\";
2227        }
2228        std::string defaultDirectory = directory;
2229        std::string importFile = "";
2230        std::string exportFile = "default.mps";
2231        std::string importBasisFile = "";
2232        std::string importPriorityFile = "";
2233        std::string debugFile = "";
2234        std::string printMask = "";
2235        double * debugValues = NULL;
2236        int numberDebugValues = -1;
2237        int basisHasValues = 0;
2238        std::string exportBasisFile = "default.bas";
2239        std::string saveFile = "default.prob";
2240        std::string restoreFile = "default.prob";
2241        std::string solutionFile = "stdout";
2242        std::string solutionSaveFile = "solution.file";
2243        int slog = whichParam(CLP_PARAM_INT_SOLVERLOGLEVEL, numberParameters_, parameters_);
2244        int log = whichParam(CLP_PARAM_INT_LOGLEVEL, numberParameters_, parameters_);
2245#ifndef CBC_OTHER_SOLVER
2246        double normalIncrement = model_.getCutoffIncrement();;
2247#endif
2248        if (testOsiParameters >= 0) {
2249            // trying nonlinear - switch off some stuff
2250            preProcess = 0;
2251        }
2252        // Set up likely cut generators and defaults
2253        int nodeStrategy = 0;
2254        bool dominatedCuts = false;
2255        int doSOS = 1;
2256        int verbose = 0;
2257        CglGomory gomoryGen;
2258        // try larger limit
2259        gomoryGen.setLimitAtRoot(1000);
2260        gomoryGen.setLimit(50);
2261        // set default action (0=off,1=on,2=root)
2262        int gomoryAction = 3;
2263
2264        CglProbing probingGen;
2265        probingGen.setUsingObjective(1);
2266        probingGen.setMaxPass(1);
2267        probingGen.setMaxPassRoot(1);
2268        // Number of unsatisfied variables to look at
2269        probingGen.setMaxProbe(10);
2270        probingGen.setMaxProbeRoot(50);
2271        // How far to follow the consequences
2272        probingGen.setMaxLook(10);
2273        probingGen.setMaxLookRoot(50);
2274        probingGen.setMaxLookRoot(10);
2275        // Only look at rows with fewer than this number of elements
2276        probingGen.setMaxElements(200);
2277        probingGen.setMaxElementsRoot(300);
2278        probingGen.setRowCuts(3);
2279        // set default action (0=off,1=on,2=root)
2280        int probingAction = 1;
2281
2282        CglKnapsackCover knapsackGen;
2283        //knapsackGen.switchOnExpensive();
2284        //knapsackGen.setMaxInKnapsack(100);
2285        // set default action (0=off,1=on,2=root)
2286        int knapsackAction = 3;
2287
2288        CglRedSplit redsplitGen;
2289        //redsplitGen.setLimit(100);
2290        // set default action (0=off,1=on,2=root)
2291        // Off as seems to give some bad cuts
2292        int redsplitAction = 0;
2293
2294        CglFakeClique cliqueGen(NULL, false);
2295        //CglClique cliqueGen(false,true);
2296        cliqueGen.setStarCliqueReport(false);
2297        cliqueGen.setRowCliqueReport(false);
2298        cliqueGen.setMinViolation(0.1);
2299        // set default action (0=off,1=on,2=root)
2300        int cliqueAction = 3;
2301
2302        // maxaggr,multiply,criterion(1-3)
2303        CglMixedIntegerRounding2 mixedGen(1, true, 1);
2304        // set default action (0=off,1=on,2=root)
2305        int mixedAction = 3;
2306
2307        CglFlowCover flowGen;
2308        // set default action (0=off,1=on,2=root)
2309        int flowAction = 3;
2310
2311        CglTwomir twomirGen;
2312        twomirGen.setMaxElements(250);
2313        // set default action (0=off,1=on,2=root)
2314        int twomirAction = 2;
2315#ifndef DEBUG_MALLOC
2316        CglLandP landpGen;
2317#endif
2318        // set default action (0=off,1=on,2=root)
2319        int landpAction = 0;
2320        CglResidualCapacity residualCapacityGen;
2321        // set default action (0=off,1=on,2=root)
2322        int residualCapacityAction = 0;
2323
2324#ifdef ZERO_HALF_CUTS
2325        CglZeroHalf zerohalfGen;
2326        //zerohalfGen.switchOnExpensive();
2327        // set default action (0=off,1=on,2=root)
2328        int zerohalfAction = 0;
2329#endif
2330
2331        // Stored cuts
2332        //bool storedCuts = false;
2333
2334        int useCosts = 0;
2335        // don't use input solution
2336        int useSolution = -1;
2337
2338        // total number of commands read
2339        int numberGoodCommands = 0;
2340        // Set false if user does anything advanced
2341        bool defaultSettings = true;
2342
2343        // Hidden stuff for barrier
2344        int choleskyType = 0;
2345        int gamma = 0;
2346        int scaleBarrier = 0;
2347        int doKKT = 0;
2348        int crossover = 2; // do crossover unless quadratic
2349        // For names
2350        int lengthName = 0;
2351        std::vector<std::string> rowNames;
2352        std::vector<std::string> columnNames;
2353        // Default strategy stuff
2354        {
2355            // try changing tolerance at root
2356#define MORE_CUTS
2357#ifdef MORE_CUTS
2358            gomoryGen.setAwayAtRoot(0.005);
2359            twomirGen.setAwayAtRoot(0.005);
2360            twomirGen.setAway(0.01);
2361            //twomirGen.setMirScale(1,1);
2362            //twomirGen.setTwomirScale(1,1);
2363            //twomirGen.setAMax(2);
2364#else
2365            gomoryGen.setAwayAtRoot(0.01);
2366            twomirGen.setAwayAtRoot(0.01);
2367            twomirGen.setAway(0.01);
2368#endif
2369            int iParam;
2370            iParam = whichParam(CBC_PARAM_INT_DIVEOPT, numberParameters_, parameters_);
2371            parameters_[iParam].setIntValue(3);
2372            iParam = whichParam(CBC_PARAM_INT_FPUMPITS, numberParameters_, parameters_);
2373            parameters_[iParam].setIntValue(30);
2374            iParam = whichParam(CBC_PARAM_INT_FPUMPTUNE, numberParameters_, parameters_);
2375            parameters_[iParam].setIntValue(1005043);
2376            initialPumpTune = 1005043;
2377            iParam = whichParam(CLP_PARAM_INT_PROCESSTUNE, numberParameters_, parameters_);
2378            parameters_[iParam].setIntValue(6);
2379            tunePreProcess = 6;
2380            iParam = whichParam(CBC_PARAM_STR_DIVINGC, numberParameters_, parameters_);
2381            parameters_[iParam].setCurrentOption("on");
2382            iParam = whichParam(CBC_PARAM_STR_RINS, numberParameters_, parameters_);
2383            parameters_[iParam].setCurrentOption("on");
2384            iParam = whichParam(CBC_PARAM_STR_PROBINGCUTS, numberParameters_, parameters_);
2385            parameters_[iParam].setCurrentOption("on");
2386            probingAction = 1;
2387            parameters_[iParam].setCurrentOption("forceOnStrong");
2388            probingAction = 8;
2389        }
2390        std::string field;
2391        if (!noPrinting_) {
2392            sprintf(generalPrint, "Coin Cbc and Clp Solver version %s, build %s",
2393                    CBCVERSION, __DATE__);
2394            generalMessageHandler->message(CLP_GENERAL, generalMessages)
2395            << generalPrint
2396            << CoinMessageEol;
2397            // Print command line
2398            if (argc > 1) {
2399                bool foundStrategy = false;
2400                sprintf(generalPrint, "command line - ");
2401                for (int i = 0; i < argc; i++) {
2402                    if (!argv[i])
2403                        break;
2404                    if (strstr(argv[i], "strat"))
2405                        foundStrategy = true;
2406                    sprintf(generalPrint + strlen(generalPrint), "%s ", argv[i]);
2407                }
2408                if (!foundStrategy)
2409                    sprintf(generalPrint + strlen(generalPrint), "(default strategy 1)");
2410                generalMessageHandler->message(CLP_GENERAL, generalMessages)
2411                << generalPrint
2412                << CoinMessageEol;
2413            }
2414        }
2415        while (1) {
2416            // next command
2417            field = CoinReadGetCommand(argc, argv);
2418            // Reset time
2419            time1 = CoinCpuTime();
2420            // adjust field if has odd trailing characters
2421            char temp [200];
2422            strcpy(temp, field.c_str());
2423            int length = strlen(temp);
2424            for (int k = length - 1; k >= 0; k--) {
2425                if (temp[k] < ' ')
2426                    length--;
2427                else
2428                    break;
2429            }
2430            temp[length] = '\0';
2431            field = temp;
2432            // exit if null or similar
2433            if (!field.length()) {
2434                if (numberGoodCommands == 1 && goodModel) {
2435                    // we just had file name - do branch and bound
2436                    field = "branch";
2437                } else if (!numberGoodCommands) {
2438                    // let's give the sucker a hint
2439                    std::cout
2440                        << "CoinSolver takes input from arguments ( - switches to stdin)"
2441                        << std::endl
2442                        << "Enter ? for list of commands or help" << std::endl;
2443                    field = "-";
2444                } else {
2445                    break;
2446                }
2447            }
2448
2449            // see if ? at end
2450            int numberQuery = 0;
2451            if (field != "?" && field != "???") {
2452                int length = field.length();
2453                int i;
2454                for (i = length - 1; i > 0; i--) {
2455                    if (field[i] == '?')
2456                        numberQuery++;
2457                    else
2458                        break;
2459                }
2460                field = field.substr(0, length - numberQuery);
2461            }
2462            // find out if valid command
2463            int iParam;
2464            int numberMatches = 0;
2465            int firstMatch = -1;
2466            for ( iParam = 0; iParam < numberParameters_; iParam++ ) {
2467                int match = parameters_[iParam].matches(field);
2468                if (match == 1) {
2469                    numberMatches = 1;
2470                    firstMatch = iParam;
2471                    break;
2472                } else {
2473                    if (match && firstMatch < 0)
2474                        firstMatch = iParam;
2475                    numberMatches += match >> 1;
2476                }
2477            }
2478            if (iParam < numberParameters_ && !numberQuery) {
2479                // found
2480                CbcOrClpParam found = parameters_[iParam];
2481                CbcOrClpParameterType type = found.type();
2482                int valid;
2483                numberGoodCommands++;
2484                if (type == CBC_PARAM_ACTION_BAB && goodModel) {
2485                    // check if any integers
2486#ifndef CBC_OTHER_SOLVER
2487#ifdef COIN_HAS_ASL
2488                    if (info.numberSos && doSOS && statusUserFunction_[0]) {
2489                        // SOS
2490                        numberSOS = info.numberSos;
2491                    }
2492#endif
2493                    lpSolver = clpSolver->getModelPtr();
2494                    if (!lpSolver->integerInformation() && !numberSOS &&
2495                            !clpSolver->numberSOS() && !model_.numberObjects() && !clpSolver->numberObjects())
2496                        type = CLP_PARAM_ACTION_DUALSIMPLEX;
2497#endif
2498                }
2499                if (type == CBC_PARAM_GENERALQUERY) {
2500                    bool evenHidden = false;
2501                    int printLevel =
2502                        parameters_[whichParam(CLP_PARAM_STR_ALLCOMMANDS,
2503                                               numberParameters_, parameters_)].currentOptionAsInteger();
2504                    int convertP[] = {2, 1, 0};
2505                    printLevel = convertP[printLevel];
2506                    if ((verbose&8) != 0) {
2507                        // even hidden
2508                        evenHidden = true;
2509                        verbose &= ~8;
2510                    }
2511#ifdef COIN_HAS_ASL
2512                    if (verbose < 4 && statusUserFunction_[0])
2513                        verbose += 4;
2514#endif
2515                    if (verbose < 4) {
2516                        std::cout << "In argument list keywords have leading - "
2517                                  ", -stdin or just - switches to stdin" << std::endl;
2518                        std::cout << "One command per line (and no -)" << std::endl;
2519                        std::cout << "abcd? gives list of possibilities, if only one + explanation" << std::endl;
2520                        std::cout << "abcd?? adds explanation, if only one fuller help" << std::endl;
2521                        std::cout << "abcd without value (where expected) gives current value" << std::endl;
2522                        std::cout << "abcd value sets value" << std::endl;
2523                        std::cout << "Commands are:" << std::endl;
2524                    } else {
2525                        std::cout << "Cbc options are set within AMPL with commands like:" << std::endl << std::endl;
2526                        std::cout << "         option cbc_options \"cuts=root log=2 feas=on slog=1\"" << std::endl << std::endl;
2527                        std::cout << "only maximize, dual, primal, help and quit are recognized without =" << std::endl;
2528                    }
2529                    int maxAcross = 10;
2530                    if ((verbose % 4) != 0)
2531                        maxAcross = 1;
2532                    int limits[] = {1, 51, 101, 151, 201, 251, 301, 351, 401};
2533                    std::vector<std::string> types;
2534                    types.push_back("Double parameters:");
2535                    types.push_back("Branch and Cut double parameters:");
2536                    types.push_back("Integer parameters:");
2537                    types.push_back("Branch and Cut integer parameters:");
2538                    types.push_back("Keyword parameters:");
2539                    types.push_back("Branch and Cut keyword parameters:");
2540                    types.push_back("Actions or string parameters:");
2541                    types.push_back("Branch and Cut actions:");
2542                    int iType;
2543                    for (iType = 0; iType < 8; iType++) {
2544                        int across = 0;
2545                        int lengthLine = 0;
2546                        if ((verbose % 4) != 0)
2547                            std::cout << std::endl;
2548                        std::cout << types[iType] << std::endl;
2549                        if ((verbose&2) != 0)
2550                            std::cout << std::endl;
2551                        for ( iParam = 0; iParam < numberParameters_; iParam++ ) {
2552                            int type = parameters_[iParam].type();
2553                            //printf("%d type %d limits %d %d display %d\n",iParam,
2554                            //     type,limits[iType],limits[iType+1],parameters_[iParam].displayThis());
2555                            if ((parameters_[iParam].displayThis() >= printLevel || evenHidden) &&
2556                                    type >= limits[iType]
2557                                    && type < limits[iType+1]) {
2558                                // but skip if not useful for ampl (and in ampl mode)
2559                                if (verbose >= 4 && (parameters_[iParam].whereUsed()&4) == 0)
2560                                    continue;
2561                                if (!across) {
2562                                    if ((verbose&2) != 0)
2563                                        std::cout << "Command ";
2564                                }
2565                                int length = parameters_[iParam].lengthMatchName() + 1;
2566                                if (lengthLine + length > 80) {
2567                                    std::cout << std::endl;
2568                                    across = 0;
2569                                    lengthLine = 0;
2570                                }
2571                                std::cout << " " << parameters_[iParam].matchName();
2572                                lengthLine += length;
2573                                across++;
2574                                if (across == maxAcross) {
2575                                    across = 0;
2576                                    if ((verbose % 4) != 0) {
2577                                        // put out description as well
2578                                        if ((verbose&1) != 0)
2579                                            std::cout << " " << parameters_[iParam].shortHelp();
2580                                        std::cout << std::endl;
2581                                        if ((verbose&2) != 0) {
2582                                            std::cout << "---- description" << std::endl;
2583                                            parameters_[iParam].printLongHelp();
2584                                            std::cout << "----" << std::endl << std::endl;
2585                                        }
2586                                    } else {
2587                                        std::cout << std::endl;
2588                                    }
2589                                }
2590                            }
2591                        }
2592                        if (across)
2593                            std::cout << std::endl;
2594                    }
2595                } else if (type == CBC_PARAM_FULLGENERALQUERY) {
2596                    std::cout << "Full list of commands is:" << std::endl;
2597                    int maxAcross = 5;
2598                    int limits[] = {1, 51, 101, 151, 201, 251, 301, 351, 401};
2599                    std::vector<std::string> types;
2600                    types.push_back("Double parameters:");
2601                    types.push_back("Branch and Cut double parameters:");
2602                    types.push_back("Integer parameters:");
2603                    types.push_back("Branch and Cut integer parameters:");
2604                    types.push_back("Keyword parameters:");
2605                    types.push_back("Branch and Cut keyword parameters:");
2606                    types.push_back("Actions or string parameters:");
2607                    types.push_back("Branch and Cut actions:");
2608                    int iType;
2609                    for (iType = 0; iType < 8; iType++) {
2610                        int across = 0;
2611                        std::cout << types[iType] << "  ";
2612                        for ( iParam = 0; iParam < numberParameters_; iParam++ ) {
2613                            int type = parameters_[iParam].type();
2614                            if (type >= limits[iType]
2615                                    && type < limits[iType+1]) {
2616                                if (!across)
2617                                    std::cout << "  ";
2618                                std::cout << parameters_[iParam].matchName() << "  ";
2619                                across++;
2620                                if (across == maxAcross) {
2621                                    std::cout << std::endl;
2622                                    across = 0;
2623                                }
2624                            }
2625                        }
2626                        if (across)
2627                            std::cout << std::endl;
2628                    }
2629                } else if (type < 101) {
2630                    // get next field as double
2631                    double value = CoinReadGetDoubleField(argc, argv, &valid);
2632                    if (!valid) {
2633                        if (type < 51) {
2634                            int returnCode;
2635                            const char * message =
2636                                parameters_[iParam].setDoubleParameterWithMessage(lpSolver, value, returnCode);
2637                            if (!noPrinting_ && strlen(message)) {
2638                                generalMessageHandler->message(CLP_GENERAL, generalMessages)
2639                                << message
2640                                << CoinMessageEol;
2641                            }
2642                        } else if (type < 81) {
2643                            int returnCode;
2644                            const char * message =
2645                                parameters_[iParam].setDoubleParameterWithMessage(model_, value, returnCode);
2646                            if (!noPrinting_ && strlen(message)) {
2647                                generalMessageHandler->message(CLP_GENERAL, generalMessages)
2648                                << message
2649                                << CoinMessageEol;
2650                            }
2651                        } else {
2652                            int returnCode;
2653                            const char * message =
2654                                parameters_[iParam].setDoubleParameterWithMessage(lpSolver, value, returnCode);
2655                            if (!noPrinting_ && strlen(message)) {
2656                                generalMessageHandler->message(CLP_GENERAL, generalMessages)
2657                                << message
2658                                << CoinMessageEol;
2659                            }
2660                            switch (type) {
2661                            case CBC_PARAM_DBL_DJFIX:
2662                                djFix = value;
2663#ifndef CBC_OTHER_SOLVER
2664                                if (goodModel && djFix < 1.0e20) {
2665                                    // do some fixing
2666                                    clpSolver = dynamic_cast< OsiClpSolverInterface*> (model_.solver());
2667                                    clpSolver->initialSolve();
2668                                    lpSolver = clpSolver->getModelPtr();
2669                                    int numberColumns = lpSolver->numberColumns();
2670                                    int i;
2671                                    const char * type = lpSolver->integerInformation();
2672                                    double * lower = lpSolver->columnLower();
2673                                    double * upper = lpSolver->columnUpper();
2674                                    double * solution = lpSolver->primalColumnSolution();
2675                                    double * dj = lpSolver->dualColumnSolution();
2676                                    int numberFixed = 0;
2677                                    double dextra4 = parameters_[whichParam(CBC_PARAM_DBL_DEXTRA4, numberParameters_, parameters_)].doubleValue();
2678                                    if (dextra4)
2679                                        printf("Multiple for continuous dj fixing is %g\n", dextra4);
2680                                    for (i = 0; i < numberColumns; i++) {
2681                                        double djValue = dj[i];
2682                                        if (!type[i])
2683                                            djValue *= dextra4;
2684                                        if (type[i] || dextra4) {
2685                                            double value = solution[i];
2686                                            if (value < lower[i] + 1.0e-5 && djValue > djFix) {
2687                                                solution[i] = lower[i];
2688                                                upper[i] = lower[i];
2689                                                numberFixed++;
2690                                            } else if (value > upper[i] - 1.0e-5 && djValue < -djFix) {
2691                                                solution[i] = upper[i];
2692                                                lower[i] = upper[i];
2693                                                numberFixed++;
2694                                            }
2695                                        }
2696                                    }
2697                                    sprintf(generalPrint, "%d columns fixed\n", numberFixed);
2698                                    generalMessageHandler->message(CLP_GENERAL, generalMessages)
2699                                    << generalPrint
2700                                    << CoinMessageEol;
2701                                }
2702#endif
2703                                break;
2704                            case CBC_PARAM_DBL_TIGHTENFACTOR:
2705                                tightenFactor = value;
2706                                if (!complicatedInteger)
2707                                    defaultSettings = false; // user knows what she is doing
2708                                break;
2709                            default:
2710                                break;
2711                            }
2712                        }
2713                    } else if (valid == 1) {
2714                        std::cout << " is illegal for double parameter " << parameters_[iParam].name() << " value remains " <<
2715                                  parameters_[iParam].doubleValue() << std::endl;
2716                    } else {
2717                        std::cout << parameters_[iParam].name() << " has value " <<
2718                                  parameters_[iParam].doubleValue() << std::endl;
2719                    }
2720                } else if (type < 201) {
2721                    // get next field as int
2722                    int value = CoinReadGetIntField(argc, argv, &valid);
2723                    if (!valid) {
2724                        if (type < 151) {
2725                            if (parameters_[iParam].type() == CLP_PARAM_INT_PRESOLVEPASS)
2726                                preSolve = value;
2727                            else if (parameters_[iParam].type() == CLP_PARAM_INT_IDIOT)
2728                                doIdiot = value;
2729                            else if (parameters_[iParam].type() == CLP_PARAM_INT_SPRINT)
2730                                doSprint = value;
2731                            else if (parameters_[iParam].type() == CLP_PARAM_INT_OUTPUTFORMAT)
2732                                outputFormat = value;
2733                            else if (parameters_[iParam].type() == CLP_PARAM_INT_SLPVALUE)
2734                                slpValue = value;
2735                            else if (parameters_[iParam].type() == CLP_PARAM_INT_CPP)
2736                                cppValue = value;
2737                            else if (parameters_[iParam].type() == CLP_PARAM_INT_PRESOLVEOPTIONS)
2738                                presolveOptions = value;
2739                            else if (parameters_[iParam].type() == CLP_PARAM_INT_PRINTOPTIONS)
2740                                printOptions = value;
2741                            else if (parameters_[iParam].type() == CLP_PARAM_INT_SUBSTITUTION)
2742                                substitution = value;
2743                            else if (parameters_[iParam].type() == CLP_PARAM_INT_DUALIZE)
2744                                dualize = value;
2745                            else if (parameters_[iParam].type() == CLP_PARAM_INT_PROCESSTUNE)
2746                                tunePreProcess = value;
2747                            else if (parameters_[iParam].type() == CLP_PARAM_INT_USESOLUTION)
2748                                useSolution = value;
2749                            else if (parameters_[iParam].type() == CLP_PARAM_INT_VERBOSE)
2750                                verbose = value;
2751                            int returnCode;
2752                            const char * message =
2753                                parameters_[iParam].setIntParameterWithMessage(lpSolver, value, returnCode);
2754                            if (!noPrinting_ && strlen(message)) {
2755                                generalMessageHandler->message(CLP_GENERAL, generalMessages)
2756                                << message
2757                                << CoinMessageEol;
2758                            }
2759                        } else {
2760                            if (parameters_[iParam].type() == CBC_PARAM_INT_CUTPASS)
2761                                cutPass = value;
2762                            else if (parameters_[iParam].type() == CBC_PARAM_INT_CUTPASSINTREE)
2763                                cutPassInTree = value;
2764                            else if (parameters_[iParam].type() == CBC_PARAM_INT_STRONGBRANCHING ||
2765                                     parameters_[iParam].type() == CBC_PARAM_INT_NUMBERBEFORE)
2766                                strongChanged = true;
2767                            else if (parameters_[iParam].type() == CBC_PARAM_INT_FPUMPTUNE ||
2768                                     parameters_[iParam].type() == CBC_PARAM_INT_FPUMPTUNE2 ||
2769                                     parameters_[iParam].type() == CBC_PARAM_INT_FPUMPITS)
2770                                pumpChanged = true;
2771                            else if (parameters_[iParam].type() == CBC_PARAM_INT_EXPERIMENT) {
2772                                if (value >= 1) {
2773                                    if (!noPrinting_) {
2774                                        generalMessageHandler->message(CLP_GENERAL, generalMessages)
2775                                        << "switching on global root cuts for gomory and knapsack"
2776                                        << CoinMessageEol;
2777                                        generalMessageHandler->message(CLP_GENERAL, generalMessages)
2778                                        << "using OSL factorization"
2779                                        << CoinMessageEol;
2780                                        generalMessageHandler->message(CLP_GENERAL, generalMessages)
2781                                        << "extra options - -rens on -extra4 24003 -passc 1000!"
2782                                        << CoinMessageEol;
2783                                    }
2784                                    parameters[whichParam(CBC_PARAM_STR_PROBINGCUTS, numberParameters, parameters)].setCurrentOption("forceOnStrong");
2785                                    probingAction = 8;
2786                                    parameters_[whichParam(CBC_PARAM_STR_GOMORYCUTS, numberParameters_, parameters_)].setCurrentOption("onGlobal");
2787                                    gomoryAction = 5;
2788                                    parameters_[whichParam(CBC_PARAM_STR_KNAPSACKCUTS, numberParameters_, parameters_)].setCurrentOption("onGlobal");
2789                                    knapsackAction = 5;
2790                                    parameters_[whichParam(CLP_PARAM_STR_FACTORIZATION, numberParameters_, parameters_)].setCurrentOption("osl");
2791                                    lpSolver->factorization()->forceOtherFactorization(3);
2792                                    parameters_[whichParam(CBC_PARAM_INT_MAXHOTITS, numberParameters_, parameters_)].setIntValue(100);
2793                                    parameters[whichParam(CBC_PARAM_INT_CUTPASS, numberParameters, parameters)].setIntValue(1000);
2794                                    cutPass = 1000;
2795                                    parameters[whichParam(CBC_PARAM_INT_EXTRA4, numberParameters, parameters)].setIntValue(24003);
2796                                    parameters[whichParam(CBC_PARAM_STR_RENS, numberParameters, parameters)].setCurrentOption("on");
2797                                }
2798                            } else if (parameters_[iParam].type() == CBC_PARAM_INT_STRATEGY) {
2799                                if (value == 0) {
2800                                    gomoryGen.setAwayAtRoot(0.05);
2801                                    int iParam;
2802                                    iParam = whichParam(CBC_PARAM_INT_DIVEOPT, numberParameters_, parameters_);
2803                                    parameters_[iParam].setIntValue(-1);
2804                                    iParam = whichParam(CBC_PARAM_INT_FPUMPITS, numberParameters_, parameters_);
2805                                    parameters_[iParam].setIntValue(20);
2806                                    iParam = whichParam(CBC_PARAM_INT_FPUMPTUNE, numberParameters_, parameters_);
2807                                    parameters_[iParam].setIntValue(1003);
2808                                    initialPumpTune = 1003;
2809                                    iParam = whichParam(CLP_PARAM_INT_PROCESSTUNE, numberParameters_, parameters_);
2810                                    parameters_[iParam].setIntValue(-1);
2811                                    tunePreProcess = 0;
2812                                    iParam = whichParam(CBC_PARAM_STR_DIVINGC, numberParameters_, parameters_);
2813                                    parameters_[iParam].setCurrentOption("off");
2814                                    iParam = whichParam(CBC_PARAM_STR_RINS, numberParameters_, parameters_);
2815                                    parameters_[iParam].setCurrentOption("off");
2816                                    iParam = whichParam(CBC_PARAM_STR_PROBINGCUTS, numberParameters_, parameters_);
2817                                    parameters_[iParam].setCurrentOption("on");
2818                                    probingAction = 1;
2819                                }
2820                            }
2821                            int returnCode;
2822                            const char * message =
2823                                parameters_[iParam].setIntParameterWithMessage(model_, value, returnCode);
2824                            if (!noPrinting_ && strlen(message)) {
2825                                generalMessageHandler->message(CLP_GENERAL, generalMessages)
2826                                << message
2827                                << CoinMessageEol;
2828                            }
2829                        }
2830                    } else if (valid == 1) {
2831                        std::cout << " is illegal for integer parameter " << parameters_[iParam].name() << " value remains " <<
2832                                  parameters_[iParam].intValue() << std::endl;
2833                    } else {
2834                        std::cout << parameters_[iParam].name() << " has value " <<
2835                                  parameters_[iParam].intValue() << std::endl;
2836                    }
2837                } else if (type < 301) {
2838                    // one of several strings
2839                    std::string value = CoinReadGetString(argc, argv);
2840                    int action = parameters_[iParam].parameterOption(value);
2841                    if (action < 0) {
2842                        if (value != "EOL") {
2843                            // no match
2844                            parameters_[iParam].printOptions();
2845                        } else {
2846                            // print current value
2847                            std::cout << parameters_[iParam].name() << " has value " <<
2848                                      parameters_[iParam].currentOption() << std::endl;
2849                        }
2850                    } else {
2851                        const char * message =
2852                            parameters_[iParam].setCurrentOptionWithMessage(action);
2853                        if (!noPrinting_ && strlen(message)) {
2854                            generalMessageHandler->message(CLP_GENERAL, generalMessages)
2855                            << message
2856                            << CoinMessageEol;
2857                        }
2858                        // for now hard wired
2859                        switch (type) {
2860                        case CLP_PARAM_STR_DIRECTION:
2861                            if (action == 0)
2862                                lpSolver->setOptimizationDirection(1);
2863                            else if (action == 1)
2864                                lpSolver->setOptimizationDirection(-1);
2865                            else
2866                                lpSolver->setOptimizationDirection(0);
2867                            break;
2868                        case CLP_PARAM_STR_DUALPIVOT:
2869                            if (action == 0) {
2870                                ClpDualRowSteepest steep(3);
2871                                lpSolver->setDualRowPivotAlgorithm(steep);
2872                            } else if (action == 1) {
2873                                ClpDualRowDantzig dantzig;
2874                                //ClpDualRowSteepest dantzig(5);
2875                                lpSolver->setDualRowPivotAlgorithm(dantzig);
2876                            } else if (action == 2) {
2877                                // partial steep
2878                                ClpDualRowSteepest steep(2);
2879                                lpSolver->setDualRowPivotAlgorithm(steep);
2880                            } else {
2881                                ClpDualRowSteepest steep;
2882                                lpSolver->setDualRowPivotAlgorithm(steep);
2883                            }
2884                            break;
2885                        case CLP_PARAM_STR_PRIMALPIVOT:
2886                            if (action == 0) {
2887                                ClpPrimalColumnSteepest steep(3);
2888                                lpSolver->setPrimalColumnPivotAlgorithm(steep);
2889                            } else if (action == 1) {
2890                                ClpPrimalColumnSteepest steep(0);
2891                                lpSolver->setPrimalColumnPivotAlgorithm(steep);
2892                            } else if (action == 2) {
2893                                ClpPrimalColumnDantzig dantzig;
2894                                lpSolver->setPrimalColumnPivotAlgorithm(dantzig);
2895                            } else if (action == 3) {
2896                                ClpPrimalColumnSteepest steep(4);
2897                                lpSolver->setPrimalColumnPivotAlgorithm(steep);
2898                            } else if (action == 4) {
2899                                ClpPrimalColumnSteepest steep(1);
2900                                lpSolver->setPrimalColumnPivotAlgorithm(steep);
2901                            } else if (action == 5) {
2902                                ClpPrimalColumnSteepest steep(2);
2903                                lpSolver->setPrimalColumnPivotAlgorithm(steep);
2904                            } else if (action == 6) {
2905                                ClpPrimalColumnSteepest steep(10);
2906                                lpSolver->setPrimalColumnPivotAlgorithm(steep);
2907                            }
2908                            break;
2909                        case CLP_PARAM_STR_SCALING:
2910                            lpSolver->scaling(action);
2911                            solver->setHintParam(OsiDoScale, action != 0, OsiHintTry);
2912                            doScaling = action;
2913                            break;
2914                        case CLP_PARAM_STR_AUTOSCALE:
2915                            lpSolver->setAutomaticScaling(action != 0);
2916                            break;
2917                        case CLP_PARAM_STR_SPARSEFACTOR:
2918                            lpSolver->setSparseFactorization((1 - action) != 0);
2919                            break;
2920                        case CLP_PARAM_STR_BIASLU:
2921                            lpSolver->factorization()->setBiasLU(action);
2922                            break;
2923                        case CLP_PARAM_STR_PERTURBATION:
2924                            if (action == 0)
2925                                lpSolver->setPerturbation(50);
2926                            else
2927                                lpSolver->setPerturbation(100);
2928                            break;
2929                        case CLP_PARAM_STR_ERRORSALLOWED:
2930                            allowImportErrors = action;
2931                            break;
2932                        case CLP_PARAM_STR_INTPRINT:
2933                            printMode = action;
2934                            break;
2935                            //case CLP_PARAM_NOTUSED_ALGORITHM:
2936                            //algorithm  = action;
2937                            //defaultSettings=false; // user knows what she is doing
2938                            //abort();
2939                            //break;
2940                        case CLP_PARAM_STR_KEEPNAMES:
2941                            keepImportNames = 1 - action;
2942                            break;
2943                        case CLP_PARAM_STR_PRESOLVE:
2944                            if (action == 0)
2945                                preSolve = 5;
2946                            else if (action == 1)
2947                                preSolve = 0;
2948                            else if (action == 2)
2949                                preSolve = 10;
2950                            else
2951                                preSolveFile = true;
2952                            break;
2953                        case CLP_PARAM_STR_PFI:
2954                            lpSolver->factorization()->setForrestTomlin(action == 0);
2955                            break;
2956                        case CLP_PARAM_STR_FACTORIZATION:
2957                            lpSolver->factorization()->forceOtherFactorization(action);
2958                            break;
2959                        case CLP_PARAM_STR_CRASH:
2960                            doCrash = action;
2961                            break;
2962                        case CLP_PARAM_STR_VECTOR:
2963                            doVector = action;
2964                            break;
2965                        case CLP_PARAM_STR_MESSAGES:
2966                            lpSolver->messageHandler()->setPrefix(action != 0);
2967                            break;
2968                        case CLP_PARAM_STR_CHOLESKY:
2969                            choleskyType = action;
2970                            break;
2971                        case CLP_PARAM_STR_GAMMA:
2972                            gamma = action;
2973                            break;
2974                        case CLP_PARAM_STR_BARRIERSCALE:
2975                            scaleBarrier = action;
2976                            break;
2977                        case CLP_PARAM_STR_KKT:
2978                            doKKT = action;
2979                            break;
2980                        case CLP_PARAM_STR_CROSSOVER:
2981                            crossover = action;
2982                            break;
2983                        case CBC_PARAM_STR_SOS:
2984                            doSOS = action;
2985                            break;
2986                        case CBC_PARAM_STR_GOMORYCUTS:
2987                            defaultSettings = false; // user knows what she is doing
2988                            gomoryAction = action;
2989                            break;
2990                        case CBC_PARAM_STR_PROBINGCUTS:
2991                            defaultSettings = false; // user knows what she is doing
2992                            probingAction = action;
2993                            break;
2994                        case CBC_PARAM_STR_KNAPSACKCUTS:
2995                            defaultSettings = false; // user knows what she is doing
2996                            knapsackAction = action;
2997                            break;
2998                        case CBC_PARAM_STR_REDSPLITCUTS:
2999                            defaultSettings = false; // user knows what she is doing
3000                            redsplitAction = action;
3001                            break;
3002                        case CBC_PARAM_STR_CLIQUECUTS:
3003                            defaultSettings = false; // user knows what she is doing
3004                            cliqueAction = action;
3005                            break;
3006                        case CBC_PARAM_STR_FLOWCUTS:
3007                            defaultSettings = false; // user knows what she is doing
3008                            flowAction = action;
3009                            break;
3010                        case CBC_PARAM_STR_MIXEDCUTS:
3011                            defaultSettings = false; // user knows what she is doing
3012                            mixedAction = action;
3013                            break;
3014                        case CBC_PARAM_STR_TWOMIRCUTS:
3015                            defaultSettings = false; // user knows what she is doing
3016                            twomirAction = action;
3017                            break;
3018                        case CBC_PARAM_STR_LANDPCUTS:
3019                            defaultSettings = false; // user knows what she is doing
3020                            landpAction = action;
3021                            break;
3022                        case CBC_PARAM_STR_RESIDCUTS:
3023                            defaultSettings = false; // user knows what she is doing
3024                            residualCapacityAction = action;
3025                            break;
3026#ifdef ZERO_HALF_CUTS
3027                        case CBC_PARAM_STR_ZEROHALFCUTS:
3028                            defaultSettings = false; // user knows what she is doing
3029                            zerohalfAction = action;
3030                            break;
3031#endif
3032                        case CBC_PARAM_STR_ROUNDING:
3033                            defaultSettings = false; // user knows what she is doing
3034                            break;
3035                        case CBC_PARAM_STR_FPUMP:
3036                            defaultSettings = false; // user knows what she is doing
3037                            break;
3038                        case CBC_PARAM_STR_RINS:
3039                            break;
3040                        case CBC_PARAM_STR_DINS:
3041                            break;
3042                        case CBC_PARAM_STR_RENS:
3043                            break;
3044                        case CBC_PARAM_STR_CUTSSTRATEGY:
3045                            gomoryAction = action;
3046                            probingAction = action;
3047                            knapsackAction = action;
3048#ifdef ZERO_HALF_CUTS
3049                            zerohalfAction = action;
3050#endif
3051                            cliqueAction = action;
3052                            flowAction = action;
3053                            mixedAction = action;
3054                            twomirAction = action;
3055                            //landpAction = action;
3056                            parameters_[whichParam(CBC_PARAM_STR_GOMORYCUTS, numberParameters_, parameters_)].setCurrentOption(action);
3057                            parameters_[whichParam(CBC_PARAM_STR_PROBINGCUTS, numberParameters_, parameters_)].setCurrentOption(action);
3058                            parameters_[whichParam(CBC_PARAM_STR_KNAPSACKCUTS, numberParameters_, parameters_)].setCurrentOption(action);
3059                            parameters_[whichParam(CBC_PARAM_STR_CLIQUECUTS, numberParameters_, parameters_)].setCurrentOption(action);
3060                            parameters_[whichParam(CBC_PARAM_STR_FLOWCUTS, numberParameters_, parameters_)].setCurrentOption(action);
3061                            parameters_[whichParam(CBC_PARAM_STR_MIXEDCUTS, numberParameters_, parameters_)].setCurrentOption(action);
3062                            parameters_[whichParam(CBC_PARAM_STR_TWOMIRCUTS, numberParameters_, parameters_)].setCurrentOption(action);
3063#ifdef ZERO_HALF_CUTS
3064                            parameters_[whichParam(CBC_PARAM_STR_ZEROHALFCUTS, numberParameters_, parameters_)].setCurrentOption(action);
3065#endif
3066                            if (!action) {
3067                                redsplitAction = action;
3068                                parameters_[whichParam(CBC_PARAM_STR_REDSPLITCUTS, numberParameters_, parameters_)].setCurrentOption(action);
3069                                landpAction = action;
3070                                parameters_[whichParam(CBC_PARAM_STR_LANDPCUTS, numberParameters_, parameters_)].setCurrentOption(action);
3071                                residualCapacityAction = action;
3072                                parameters_[whichParam(CBC_PARAM_STR_RESIDCUTS, numberParameters_, parameters_)].setCurrentOption(action);
3073                            }
3074                            break;
3075                        case CBC_PARAM_STR_HEURISTICSTRATEGY:
3076                            parameters_[whichParam(CBC_PARAM_STR_ROUNDING, numberParameters_, parameters_)].setCurrentOption(action);
3077                            parameters_[whichParam(CBC_PARAM_STR_GREEDY, numberParameters_, parameters_)].setCurrentOption(action);
3078                            parameters_[whichParam(CBC_PARAM_STR_COMBINE, numberParameters_, parameters_)].setCurrentOption(action);
3079                            //parameters_[whichParam(CBC_PARAM_STR_LOCALTREE,numberParameters_,parameters_)].setCurrentOption(action);
3080                            parameters_[whichParam(CBC_PARAM_STR_FPUMP, numberParameters_, parameters_)].setCurrentOption(action);
3081                            parameters_[whichParam(CBC_PARAM_STR_DIVINGC, numberParameters_, parameters_)].setCurrentOption(action);
3082                            parameters_[whichParam(CBC_PARAM_STR_RINS, numberParameters_, parameters_)].setCurrentOption(action);
3083                            break;
3084                        case CBC_PARAM_STR_GREEDY:
3085                        case CBC_PARAM_STR_DIVINGS:
3086                        case CBC_PARAM_STR_DIVINGC:
3087                        case CBC_PARAM_STR_DIVINGF:
3088                        case CBC_PARAM_STR_DIVINGG:
3089                        case CBC_PARAM_STR_DIVINGL:
3090                        case CBC_PARAM_STR_DIVINGP:
3091                        case CBC_PARAM_STR_DIVINGV:
3092                        case CBC_PARAM_STR_COMBINE:
3093                        case CBC_PARAM_STR_PIVOTANDCOMPLEMENT:
3094                        case CBC_PARAM_STR_PIVOTANDFIX:
3095                        case CBC_PARAM_STR_RANDROUND:
3096                        case CBC_PARAM_STR_LOCALTREE:
3097                        case CBC_PARAM_STR_NAIVE:
3098                        case CBC_PARAM_STR_CPX:
3099                            defaultSettings = false; // user knows what she is doing
3100                            break;
3101                        case CBC_PARAM_STR_COSTSTRATEGY:
3102                            useCosts = action;
3103                            break;
3104                        case CBC_PARAM_STR_NODESTRATEGY:
3105                            nodeStrategy = action;
3106                            break;
3107                        case CBC_PARAM_STR_PREPROCESS:
3108                            preProcess = action;
3109                            break;
3110                        default:
3111                            //abort();
3112                            break;
3113                        }
3114                    }
3115                } else {
3116                    // action
3117                    if (type == CLP_PARAM_ACTION_EXIT) {
3118#ifdef COIN_HAS_ASL
3119                        if (statusUserFunction_[0]) {
3120                            if (info.numberIntegers || info.numberBinary) {
3121                                // integer
3122                            } else {
3123                                // linear
3124                            }
3125                            writeAmpl(&info);
3126                            freeArrays2(&info);
3127                            freeArgs(&info);
3128                        }
3129#endif
3130                        break; // stop all
3131                    }
3132                    switch (type) {
3133                    case CLP_PARAM_ACTION_DUALSIMPLEX:
3134                    case CLP_PARAM_ACTION_PRIMALSIMPLEX:
3135                    case CLP_PARAM_ACTION_SOLVECONTINUOUS:
3136                    case CLP_PARAM_ACTION_BARRIER:
3137                        if (goodModel) {
3138                            // Say not in integer
3139                            integerStatus = -1;
3140                            double objScale =
3141                                parameters_[whichParam(CLP_PARAM_DBL_OBJSCALE2, numberParameters_, parameters_)].doubleValue();
3142                            if (objScale != 1.0) {
3143                                int iColumn;
3144                                int numberColumns = lpSolver->numberColumns();
3145                                double * dualColumnSolution =
3146                                    lpSolver->dualColumnSolution();
3147                                ClpObjective * obj = lpSolver->objectiveAsObject();
3148                                assert(dynamic_cast<ClpLinearObjective *> (obj));
3149                                double offset;
3150                                double * objective = obj->gradient(NULL, NULL, offset, true);
3151                                for (iColumn = 0; iColumn < numberColumns; iColumn++) {
3152                                    dualColumnSolution[iColumn] *= objScale;
3153                                    objective[iColumn] *= objScale;;
3154                                }
3155                                int iRow;
3156                                int numberRows = lpSolver->numberRows();
3157                                double * dualRowSolution =
3158                                    lpSolver->dualRowSolution();
3159                                for (iRow = 0; iRow < numberRows; iRow++)
3160                                    dualRowSolution[iRow] *= objScale;
3161                                lpSolver->setObjectiveOffset(objScale*lpSolver->objectiveOffset());
3162                            }
3163                            ClpSolve::SolveType method;
3164                            ClpSolve::PresolveType presolveType;
3165                            ClpSimplex * model2 = lpSolver;
3166                            if (dualize) {
3167                                bool tryIt = true;
3168                                double fractionColumn = 1.0;
3169                                double fractionRow = 1.0;
3170                                if (dualize == 3) {
3171                                    dualize = 1;
3172                                    int numberColumns = lpSolver->numberColumns();
3173                                    int numberRows = lpSolver->numberRows();
3174                                    if (numberRows < 50000 || 5*numberColumns > numberRows) {
3175                                        tryIt = false;
3176                                    } else {
3177                                        fractionColumn = 0.1;
3178                                        fractionRow = 0.1;
3179                                    }
3180                                }
3181                                if (tryIt) {
3182                                    model2 = static_cast<ClpSimplexOther *> (model2)->dualOfModel(fractionRow, fractionColumn);
3183                                    if (model2) {
3184                                        sprintf(generalPrint, "Dual of model has %d rows and %d columns",
3185                                                model2->numberRows(), model2->numberColumns());
3186                                        generalMessageHandler->message(CLP_GENERAL, generalMessages)
3187                                        << generalPrint
3188                                        << CoinMessageEol;
3189                                        model2->setOptimizationDirection(1.0);
3190                                    } else {
3191                                        model2 = lpSolver;
3192                                        dualize = 0;
3193                                    }
3194                                } else {
3195                                    dualize = 0;
3196                                }
3197                            }
3198                            if (noPrinting_)
3199                                lpSolver->setLogLevel(0);
3200                            ClpSolve solveOptions;
3201                            solveOptions.setPresolveActions(presolveOptions);
3202                            solveOptions.setSubstitution(substitution);
3203                            if (preSolve != 5 && preSolve) {
3204                                presolveType = ClpSolve::presolveNumber;
3205                                if (preSolve < 0) {
3206                                    preSolve = - preSolve;
3207                                    if (preSolve <= 100) {
3208                                        presolveType = ClpSolve::presolveNumber;
3209                                        sprintf(generalPrint, "Doing %d presolve passes - picking up non-costed slacks",
3210                                                preSolve);
3211                                        generalMessageHandler->message(CLP_GENERAL, generalMessages)
3212                                        << generalPrint
3213                                        << CoinMessageEol;
3214                                        solveOptions.setDoSingletonColumn(true);
3215                                    } else {
3216                                        preSolve -= 100;
3217                                        presolveType = ClpSolve::presolveNumberCost;
3218                                        sprintf(generalPrint, "Doing %d presolve passes - picking up costed slacks",
3219                                                preSolve);
3220                                        generalMessageHandler->message(CLP_GENERAL, generalMessages)
3221                                        << generalPrint
3222                                        << CoinMessageEol;
3223                                    }
3224                                }
3225                            } else if (preSolve) {
3226                                presolveType = ClpSolve::presolveOn;
3227                            } else {
3228                                presolveType = ClpSolve::presolveOff;
3229                            }
3230                            solveOptions.setPresolveType(presolveType, preSolve);
3231                            if (type == CLP_PARAM_ACTION_DUALSIMPLEX || 
3232                                                                type == CLP_PARAM_ACTION_SOLVECONTINUOUS) {
3233                                method = ClpSolve::useDual;
3234                            } else if (type == CLP_PARAM_ACTION_PRIMALSIMPLEX) {
3235                                method = ClpSolve::usePrimalorSprint;
3236                            } else {
3237                                method = ClpSolve::useBarrier;
3238                                if (crossover == 1) {
3239                                    method = ClpSolve::useBarrierNoCross;
3240                                } else if (crossover == 2) {
3241                                    ClpObjective * obj = lpSolver->objectiveAsObject();
3242                                    if (obj->type() > 1) {
3243                                        method = ClpSolve::useBarrierNoCross;
3244                                        presolveType = ClpSolve::presolveOff;
3245                                        solveOptions.setPresolveType(presolveType, preSolve);
3246                                    }
3247                                }
3248                            }
3249                            solveOptions.setSolveType(method);
3250                            if (preSolveFile)
3251                                presolveOptions |= 0x40000000;
3252                            solveOptions.setSpecialOption(4, presolveOptions);
3253                            solveOptions.setSpecialOption(5, printOptions);
3254                            if (doVector) {
3255                                ClpMatrixBase * matrix = lpSolver->clpMatrix();
3256                                if (dynamic_cast< ClpPackedMatrix*>(matrix)) {
3257                                    ClpPackedMatrix * clpMatrix = dynamic_cast< ClpPackedMatrix*>(matrix);
3258                                    clpMatrix->makeSpecialColumnCopy();
3259                                }
3260                            }
3261                            if (method == ClpSolve::useDual) {
3262                                // dual
3263                                if (doCrash)
3264                                    solveOptions.setSpecialOption(0, 1, doCrash); // crash
3265                                else if (doIdiot)
3266                                    solveOptions.setSpecialOption(0, 2, doIdiot); // possible idiot
3267                            } else if (method == ClpSolve::usePrimalorSprint) {
3268                                // primal
3269                                // if slp turn everything off
3270                                if (slpValue > 0) {
3271                                    doCrash = false;
3272                                    doSprint = 0;
3273                                    doIdiot = -1;
3274                                    solveOptions.setSpecialOption(1, 10, slpValue); // slp
3275                                    method = ClpSolve::usePrimal;
3276                                }
3277                                if (doCrash) {
3278                                    solveOptions.setSpecialOption(1, 1, doCrash); // crash
3279                                } else if (doSprint > 0) {
3280                                    // sprint overrides idiot
3281                                    solveOptions.setSpecialOption(1, 3, doSprint); // sprint
3282                                } else if (doIdiot > 0) {
3283                                    solveOptions.setSpecialOption(1, 2, doIdiot); // idiot
3284                                } else if (slpValue <= 0) {
3285                                    if (doIdiot == 0) {
3286                                        if (doSprint == 0)
3287                                            solveOptions.setSpecialOption(1, 4); // all slack
3288                                        else
3289                                            solveOptions.setSpecialOption(1, 9); // all slack or sprint
3290                                    } else {
3291                                        if (doSprint == 0)
3292                                            solveOptions.setSpecialOption(1, 8); // all slack or idiot
3293                                        else
3294                                            solveOptions.setSpecialOption(1, 7); // initiative
3295                                    }
3296                                }
3297                                if (basisHasValues == -1)
3298                                    solveOptions.setSpecialOption(1, 11); // switch off values
3299                            } else if (method == ClpSolve::useBarrier || method == ClpSolve::useBarrierNoCross) {
3300                                int barrierOptions = choleskyType;
3301                                if (scaleBarrier)
3302                                    barrierOptions |= 8;
3303                                if (doKKT)
3304                                    barrierOptions |= 16;
3305                                if (gamma)
3306                                    barrierOptions |= 32 * gamma;
3307                                if (crossover == 3)
3308                                    barrierOptions |= 256; // try presolve in crossover
3309                                solveOptions.setSpecialOption(4, barrierOptions);
3310                            }
3311                            model2->setMaximumSeconds(model_.getMaximumSeconds());
3312#ifdef COIN_HAS_LINK
3313                            OsiSolverInterface * coinSolver = model_.solver();
3314                            OsiSolverLink * linkSolver = dynamic_cast< OsiSolverLink*> (coinSolver);
3315                            if (!linkSolver) {
3316                                model2->initialSolve(solveOptions);
3317                            } else {
3318                                // special solver
3319                                int testOsiOptions = parameters_[whichParam(CBC_PARAM_INT_TESTOSI, numberParameters_, parameters_)].intValue();
3320                                double * solution = NULL;
3321                                if (testOsiOptions < 10) {
3322                                    solution = linkSolver->nonlinearSLP(slpValue > 0 ? slpValue : 20 , 1.0e-5);
3323                                } else if (testOsiOptions >= 10) {
3324                                    CoinModel coinModel = *linkSolver->coinModel();
3325                                    ClpSimplex * tempModel = approximateSolution(coinModel, slpValue > 0 ? slpValue : 50 , 1.0e-5, 0);
3326                                    assert (tempModel);
3327                                    solution = CoinCopyOfArray(tempModel->primalColumnSolution(), coinModel.numberColumns());
3328                                    model2->setObjectiveValue(tempModel->objectiveValue());
3329                                    model2->setProblemStatus(tempModel->problemStatus());
3330                                    model2->setSecondaryStatus(tempModel->secondaryStatus());
3331                                    delete tempModel;
3332                                }
3333                                if (solution) {
3334                                    memcpy(model2->primalColumnSolution(), solution,
3335                                           CoinMin(model2->numberColumns(), linkSolver->coinModel()->numberColumns())*sizeof(double));
3336                                    delete [] solution;
3337                                } else {
3338                                    printf("No nonlinear solution\n");
3339                                }
3340                            }
3341#else
3342                            model2->initialSolve(solveOptions);
3343#endif
3344                            {
3345                                // map states
3346                                /* clp status
3347                                   -1 - unknown e.g. before solve or if postSolve says not optimal
3348                                   0 - optimal
3349                                   1 - primal infeasible
3350                                   2 - dual infeasible
3351                                   3 - stopped on iterations or time
3352                                   4 - stopped due to errors
3353                                   5 - stopped by event handler (virtual int ClpEventHandler::event()) */
3354                                /* cbc status
3355                                   -1 before branchAndBound
3356                                   0 finished - check isProvenOptimal or isProvenInfeasible to see if solution found
3357                                   (or check value of best solution)
3358                                   1 stopped - on maxnodes, maxsols, maxtime
3359                                   2 difficulties so run was abandoned
3360                                   (5 event user programmed event occurred) */
3361                                /* clp secondary status of problem - may get extended
3362                                   0 - none
3363                                   1 - primal infeasible because dual limit reached OR probably primal
3364                                   infeasible but can't prove it (main status 4)
3365                                   2 - scaled problem optimal - unscaled problem has primal infeasibilities
3366                                   3 - scaled problem optimal - unscaled problem has dual infeasibilities
3367                                   4 - scaled problem optimal - unscaled problem has primal and dual infeasibilities
3368                                   5 - giving up in primal with flagged variables
3369                                   6 - failed due to empty problem check
3370                                   7 - postSolve says not optimal
3371                                   8 - failed due to bad element check
3372                                   9 - status was 3 and stopped on time
3373                                   100 up - translation of enum from ClpEventHandler
3374                                */
3375                                /* cbc secondary status of problem
3376                                   -1 unset (status_ will also be -1)
3377                                   0 search completed with solution
3378                                   1 linear relaxation not feasible (or worse than cutoff)
3379                                   2 stopped on gap
3380                                   3 stopped on nodes
3381                                   4 stopped on time
3382                                   5 stopped on user event
3383                                   6 stopped on solutions
3384                                   7 linear relaxation unbounded
3385                                */
3386                                int iStatus = model2->status();
3387                                int iStatus2 = model2->secondaryStatus();
3388                                if (iStatus == 0) {
3389                                    iStatus2 = 0;
3390                                    if (found.type() == CBC_PARAM_ACTION_BAB) {
3391                                        // set best solution in model as no integers
3392                                        model_.setBestSolution(model2->primalColumnSolution(),
3393                                                               model2->numberColumns(),
3394                                                               model2->getObjValue()*
3395                                                               model2->getObjSense());
3396                                    }
3397                                } else if (iStatus == 1) {
3398                                    iStatus = 0;
3399                                    iStatus2 = 1; // say infeasible
3400                                } else if (iStatus == 2) {
3401                                    iStatus = 0;
3402                                    iStatus2 = 7; // say unbounded
3403                                } else if (iStatus == 3) {
3404                                    iStatus = 1;
3405                                    if (iStatus2 == 9)
3406                                        iStatus2 = 4;
3407                                    else
3408                                        iStatus2 = 3; // Use nodes - as closer than solutions
3409                                } else if (iStatus == 4) {
3410                                    iStatus = 2; // difficulties
3411                                    iStatus2 = 0;
3412                                }
3413                                model_.setProblemStatus(iStatus);
3414                                model_.setSecondaryStatus(iStatus2);
3415                                //assert (lpSolver==clpSolver->getModelPtr());
3416                                assert (clpSolver == model_.solver());
3417                                clpSolver->setWarmStart(NULL);
3418                                // and in babModel if exists
3419                                if (babModel_) {
3420                                    babModel_->setProblemStatus(iStatus);
3421                                    babModel_->setSecondaryStatus(iStatus2);
3422                                }
3423                                int returnCode = callBack(&model, 1);
3424                                if (returnCode) {
3425                                    // exit if user wants
3426                                    delete babModel_;
3427                                    babModel_ = NULL;
3428                                    return returnCode;
3429                                }
3430                            }
3431                            basisHasValues = 1;
3432                            if (dualize) {
3433                                int returnCode = static_cast<ClpSimplexOther *> (lpSolver)->restoreFromDual(model2);
3434                                if (model2->status() == 3)
3435                                    returnCode = 0;
3436                                delete model2;
3437                                if (returnCode && dualize != 2)
3438                                    lpSolver->primal(1);
3439                                model2 = lpSolver;
3440                            }
3441#ifdef COIN_HAS_ASL
3442                            if (statusUserFunction_[0]) {
3443                                double value = model2->getObjValue() * model2->getObjSense();
3444                                char buf[300];
3445                                int pos = 0;
3446                                int iStat = model2->status();
3447                                if (iStat == 0) {
3448                                    pos += sprintf(buf + pos, "optimal," );
3449                                } else if (iStat == 1) {
3450                                    // infeasible
3451                                    pos += sprintf(buf + pos, "infeasible,");
3452                                } else if (iStat == 2) {
3453                                    // unbounded
3454                                    pos += sprintf(buf + pos, "unbounded,");
3455                                } else if (iStat == 3) {
3456                                    pos += sprintf(buf + pos, "stopped on iterations or time,");
3457                                } else if (iStat == 4) {
3458                                    iStat = 7;
3459                                    pos += sprintf(buf + pos, "stopped on difficulties,");
3460                                } else if (iStat == 5) {
3461                                    iStat = 3;
3462                                    pos += sprintf(buf + pos, "stopped on ctrl-c,");
3463                                } else if (iStat == 6) {
3464                                    // bab infeasible
3465                                    pos += sprintf(buf + pos, "integer infeasible,");
3466                                    iStat = 1;
3467                                } else {
3468                                    pos += sprintf(buf + pos, "status unknown,");
3469                                    iStat = 6;
3470                                }
3471                                info.problemStatus = iStat;
3472                                info.objValue = value;
3473                                pos += sprintf(buf + pos, " objective %.*g", ampl_obj_prec(),
3474                                               value);
3475                                sprintf(buf + pos, "\n%d iterations",
3476                                        model2->getIterationCount());
3477                                free(info.primalSolution);
3478                                int numberColumns = model2->numberColumns();
3479                                info.primalSolution = reinterpret_cast<double *> (malloc(numberColumns * sizeof(double)));
3480                                CoinCopyN(model2->primalColumnSolution(), numberColumns, info.primalSolution);
3481                                int numberRows = model2->numberRows();
3482                                free(info.dualSolution);
3483                                info.dualSolution = reinterpret_cast<double *> (malloc(numberRows * sizeof(double)));
3484                                CoinCopyN(model2->dualRowSolution(), numberRows, info.dualSolution);
3485                                CoinWarmStartBasis * basis = model2->getBasis();
3486                                free(info.rowStatus);
3487                                info.rowStatus = reinterpret_cast<int *> (malloc(numberRows * sizeof(int)));
3488                                free(info.columnStatus);
3489                                info.columnStatus = reinterpret_cast<int *> (malloc(numberColumns * sizeof(int)));
3490                                // Put basis in
3491                                int i;
3492                                // free,basic,ub,lb are 0,1,2,3
3493                                for (i = 0; i < numberRows; i++) {
3494                                    CoinWarmStartBasis::Status status = basis->getArtifStatus(i);
3495                                    info.rowStatus[i] = status;
3496                                }
3497                                for (i = 0; i < numberColumns; i++) {
3498                                    CoinWarmStartBasis::Status status = basis->getStructStatus(i);
3499                                    info.columnStatus[i] = status;
3500                                }
3501                                // put buffer into info
3502                                strcpy(info.buffer, buf);
3503                                delete basis;
3504                            }
3505#endif
3506                        } else {
3507#ifndef DISALLOW_PRINTING
3508                            std::cout << "** Current model not valid" << std::endl;
3509#endif
3510                        }
3511                        break;
3512                    case CLP_PARAM_ACTION_STATISTICS:
3513                        if (goodModel) {
3514                            // If presolve on look at presolved
3515                            bool deleteModel2 = false;
3516                            ClpSimplex * model2 = lpSolver;
3517                            if (preSolve) {
3518                                ClpPresolve pinfo;
3519                                int presolveOptions2 = presolveOptions&~0x40000000;
3520                                if ((presolveOptions2&0xffff) != 0)
3521                                    pinfo.setPresolveActions(presolveOptions2);
3522                                pinfo.setSubstitution(substitution);
3523                                if ((printOptions&1) != 0)
3524                                    pinfo.statistics();
3525                                double presolveTolerance =
3526                                    parameters_[whichParam(CLP_PARAM_DBL_PRESOLVETOLERANCE, numberParameters_, parameters_)].doubleValue();
3527                                model2 =
3528                                    pinfo.presolvedModel(*lpSolver, presolveTolerance,
3529                                                         true, preSolve);
3530                                if (model2) {
3531                                    printf("Statistics for presolved model\n");
3532                                    deleteModel2 = true;
3533                                } else {
3534                                    printf("Presolved model looks infeasible - will use unpresolved\n");
3535                                    model2 = lpSolver;
3536                                }
3537                            } else {
3538                                printf("Statistics for unpresolved model\n");
3539                                model2 =  lpSolver;
3540                            }
3541                            statistics(lpSolver, model2);
3542                            if (deleteModel2)
3543                                delete model2;
3544                        } else {
3545#ifndef DISALLOW_PRINTING
3546                            std::cout << "** Current model not valid" << std::endl;
3547#endif
3548                        }
3549                        break;
3550                    case CLP_PARAM_ACTION_TIGHTEN:
3551                        if (goodModel) {
3552                            int numberInfeasibilities = lpSolver->tightenPrimalBounds();
3553                            if (numberInfeasibilities)
3554                                std::cout << "** Analysis indicates model infeasible" << std::endl;
3555                        } else {
3556#ifndef DISALLOW_PRINTING
3557                            std::cout << "** Current model not valid" << std::endl;
3558#endif
3559                        }
3560                        break;
3561                    case CLP_PARAM_ACTION_PLUSMINUS:
3562                        if (goodModel) {
3563                            ClpMatrixBase * saveMatrix = lpSolver->clpMatrix();
3564                            ClpPackedMatrix* clpMatrix =
3565                                dynamic_cast< ClpPackedMatrix*>(saveMatrix);
3566                            if (clpMatrix) {
3567                                ClpPlusMinusOneMatrix * newMatrix = new ClpPlusMinusOneMatrix(*(clpMatrix->matrix()));
3568                                if (newMatrix->getIndices()) {
3569                                    lpSolver->replaceMatrix(newMatrix);
3570                                    delete saveMatrix;
3571                                    std::cout << "Matrix converted to +- one matrix" << std::endl;
3572                                } else {
3573                                    std::cout << "Matrix can not be converted to +- 1 matrix" << std::endl;
3574                                }
3575                            } else {
3576                                std::cout << "Matrix not a ClpPackedMatrix" << std::endl;
3577                            }
3578                        } else {
3579#ifndef DISALLOW_PRINTING
3580                            std::cout << "** Current model not valid" << std::endl;
3581#endif
3582                        }
3583                        break;
3584                    case CLP_PARAM_ACTION_OUTDUPROWS:
3585                        dominatedCuts = true;
3586#if 0
3587                        if (goodModel) {
3588                            int numberRows = clpSolver->getNumRows();
3589                            //int nOut = outDupRow(clpSolver);
3590                            CglDuplicateRow dupcuts(clpSolver);
3591                            storedCuts = dupcuts.outDuplicates(clpSolver) != 0;
3592                            int nOut = numberRows - clpSolver->getNumRows();
3593                            if (nOut && !noPrinting_)
3594                                sprintf(generalPrint, "%d rows eliminated", nOut);
3595                            generalMessageHandler->message(CLP_GENERAL, generalMessages)
3596                            << generalPrint
3597                            << CoinMessageEol;
3598                        } else {
3599#ifndef DISALLOW_PRINTING
3600                            std::cout << "** Current model not valid" << std::endl;
3601#endif
3602                        }
3603#endif
3604                        break;
3605                    case CLP_PARAM_ACTION_NETWORK:
3606                        if (goodModel) {
3607                            ClpMatrixBase * saveMatrix = lpSolver->clpMatrix();
3608                            ClpPackedMatrix* clpMatrix =
3609                                dynamic_cast< ClpPackedMatrix*>(saveMatrix);
3610                            if (clpMatrix) {
3611                                ClpNetworkMatrix * newMatrix = new ClpNetworkMatrix(*(clpMatrix->matrix()));
3612                                if (newMatrix->getIndices()) {
3613                                    lpSolver->replaceMatrix(newMatrix);
3614                                    delete saveMatrix;
3615                                    std::cout << "Matrix converted to network matrix" << std::endl;
3616                                } else {
3617                                    std::cout << "Matrix can not be converted to network matrix" << std::endl;
3618                                }
3619                            } else {
3620                                std::cout << "Matrix not a ClpPackedMatrix" << std::endl;
3621                            }
3622                        } else {
3623#ifndef DISALLOW_PRINTING
3624                            std::cout << "** Current model not valid" << std::endl;
3625#endif
3626                        }
3627                        break;
3628                    case CBC_PARAM_ACTION_DOHEURISTIC:
3629                        if (goodModel) {
3630                            int vubAction = parameters_[whichParam(CBC_PARAM_INT_VUBTRY, numberParameters_, parameters_)].intValue();
3631                            if (vubAction != -1) {
3632                                // look at vubs
3633                                // extra1 is number of ints to leave free
3634                                // Just ones which affect >= extra3
3635                                int extra3 = parameters_[whichParam(CBC_PARAM_INT_EXTRA3, numberParameters_, parameters_)].intValue();
3636                                /* 2 is cost above which to fix if feasible
3637                                   3 is fraction of integer variables fixed if relaxing (0.97)
3638                                   4 is fraction of all variables fixed if relaxing (0.0)
3639                                */
3640                                double dextra[6];
3641                                int extra[5];
3642                                extra[1] = parameters_[whichParam(CBC_PARAM_INT_EXTRA1, numberParameters_, parameters_)].intValue();
3643                                int exp1 = parameters_[whichParam(CBC_PARAM_INT_EXPERIMENT, numberParameters_,
3644                                                                  parameters_)].intValue();
3645                                if (exp1 == 2 && extra[1] == -1)
3646                                    extra[1] = 999998;
3647                                dextra[1] = parameters_[whichParam(CBC_PARAM_DBL_FAKEINCREMENT, numberParameters_, parameters_)].doubleValue();
3648                                dextra[2] = parameters_[whichParam(CBC_PARAM_DBL_FAKECUTOFF, numberParameters_, parameters_)].doubleValue();
3649                                dextra[3] = parameters_[whichParam(CBC_PARAM_DBL_DEXTRA3, numberParameters_, parameters_)].doubleValue();
3650                                dextra[4] = parameters_[whichParam(CBC_PARAM_DBL_DEXTRA4, numberParameters_, parameters_)].doubleValue();
3651                                dextra[5] = parameters_[whichParam(CBC_PARAM_DBL_DEXTRA5, numberParameters_, parameters_)].doubleValue();
3652                                if (!dextra[3])
3653                                    dextra[3] = 0.97;
3654                                //OsiClpSolverInterface * newSolver =
3655                                fixVubs(model_, extra3, vubAction, generalMessageHandler,
3656                                        debugValues, dextra, extra);
3657                                //assert (!newSolver);
3658                            }
3659                            // Actually do heuristics
3660                            doHeuristics(&model_,2,parameters_,
3661                                numberParameters_,noPrinting_,initialPumpTune);
3662                            if (model_.bestSolution()) {
3663                                model_.setProblemStatus(1);
3664                                model_.setSecondaryStatus(6);
3665#ifdef COIN_HAS_ASL
3666                                if (statusUserFunction_[0]) {
3667                                    double value = model_.getObjValue();
3668                                    char buf[300];
3669                                    int pos = 0;
3670                                    pos += sprintf(buf + pos, "feasible,");
3671                                    info.problemStatus = 0;
3672                                    info.objValue = value;
3673                                    pos += sprintf(buf + pos, " objective %.*g", ampl_obj_prec(),
3674                                                   value);
3675                                    sprintf(buf + pos, "\n0 iterations");
3676                                    free(info.primalSolution);
3677                                    int numberColumns = lpSolver->numberColumns();
3678                                    info.primalSolution = reinterpret_cast<double *> (malloc(numberColumns * sizeof(double)));
3679                                    CoinCopyN(model_.bestSolution(), numberColumns, info.primalSolution);
3680                                    int numberRows = lpSolver->numberRows();
3681                                    free(info.dualSolution);
3682                                    info.dualSolution = reinterpret_cast<double *> (malloc(numberRows * sizeof(double)));
3683                                    CoinZeroN(info.dualSolution, numberRows);
3684                                    CoinWarmStartBasis * basis = lpSolver->getBasis();
3685                                    free(info.rowStatus);
3686                                    info.rowStatus = reinterpret_cast<int *> (malloc(numberRows * sizeof(int)));
3687                                    free(info.columnStatus);
3688                                    info.columnStatus = reinterpret_cast<int *> (malloc(numberColumns * sizeof(int)));
3689                                    // Put basis in
3690                                    int i;
3691                                    // free,basic,ub,lb are 0,1,2,3
3692                                    for (i = 0; i < numberRows; i++) {
3693                                        CoinWarmStartBasis::Status status = basis->getArtifStatus(i);
3694                                        info.rowStatus[i] = status;
3695                                    }
3696                                    for (i = 0; i < numberColumns; i++) {
3697                                        CoinWarmStartBasis::Status status = basis->getStructStatus(i);
3698                                        info.columnStatus[i] = status;
3699                                    }
3700                                    // put buffer into info
3701                                    strcpy(info.buffer, buf);
3702                                    delete basis;
3703                                }
3704#endif
3705                            }
3706                            int returnCode = callBack(&model, 6);
3707                            if (returnCode) {
3708                                // exit if user wants
3709                                delete babModel_;
3710                                babModel_ = NULL;
3711                                return returnCode;
3712                            }
3713                        }
3714                        break;
3715                    case CBC_PARAM_ACTION_MIPLIB:
3716                        // User can set options - main difference is lack of model and CglPreProcess
3717                        goodModel = true;
3718                        /*
3719                          Run branch-and-cut. First set a few options -- node comparison, scaling.
3720                          Print elapsed time at the end.
3721                        */
3722                    case CBC_PARAM_ACTION_BAB: // branchAndBound
3723                        // obsolete case STRENGTHEN:
3724                        if (goodModel) {
3725                            bool miplib = type == CBC_PARAM_ACTION_MIPLIB;
3726                            int logLevel = parameters_[slog].intValue();
3727                            // Reduce printout
3728                            if (logLevel <= 1) {
3729                                model_.solver()->setHintParam(OsiDoReducePrint, true, OsiHintTry);
3730                            } else {
3731                                model_.solver()->setHintParam(OsiDoReducePrint, false, OsiHintTry);
3732                            }
3733                            {
3734                                OsiSolverInterface * solver = model_.solver();
3735#ifndef CBC_OTHER_SOLVER
3736                                OsiClpSolverInterface * si =
3737                                    dynamic_cast<OsiClpSolverInterface *>(solver) ;
3738                                assert (si != NULL);
3739                                si->getModelPtr()->scaling(doScaling);
3740                                ClpSimplex * lpSolver = si->getModelPtr();
3741                                if (doVector) {
3742                                    ClpMatrixBase * matrix = lpSolver->clpMatrix();
3743                                    if (dynamic_cast< ClpPackedMatrix*>(matrix)) {
3744                                        ClpPackedMatrix * clpMatrix = dynamic_cast< ClpPackedMatrix*>(matrix);
3745                                        clpMatrix->makeSpecialColumnCopy();
3746                                    }
3747                                }
3748#elif CBC_OTHER_SOLVER==1
3749                                OsiCpxSolverInterface * si =
3750                                    dynamic_cast<OsiCpxSolverInterface *>(solver) ;
3751                                assert (si != NULL);
3752#endif
3753                                statistics_nrows = si->getNumRows();
3754                                statistics_ncols = si->getNumCols();
3755                                statistics_nprocessedrows = si->getNumRows();
3756                                statistics_nprocessedcols = si->getNumCols();
3757                                // See if quadratic
3758#ifndef CBC_OTHER_SOLVER
3759#ifdef COIN_HAS_LINK
3760                                if (!complicatedInteger) {
3761                                    ClpQuadraticObjective * obj = (dynamic_cast< ClpQuadraticObjective*>(lpSolver->objectiveAsObject()));
3762                                    if (obj) {
3763                                        preProcess = 0;
3764                                        int testOsiOptions = parameters_[whichParam(CBC_PARAM_INT_TESTOSI, numberParameters_, parameters_)].intValue();
3765                                        parameters_[whichParam(CBC_PARAM_INT_TESTOSI, numberParameters_, parameters_)].setIntValue(CoinMax(0, testOsiOptions));
3766                                        // create coin model
3767                                        coinModel = lpSolver->createCoinModel();
3768                                        assert (coinModel);
3769                                        // load from coin model
3770                                        OsiSolverLink solver1;
3771                                        OsiSolverInterface * solver2 = solver1.clone();
3772                                        model_.assignSolver(solver2, false);
3773                                        OsiSolverLink * si =
3774                                            dynamic_cast<OsiSolverLink *>(model_.solver()) ;
3775                                        assert (si != NULL);
3776                                        si->setDefaultMeshSize(0.001);
3777                                        // need some relative granularity
3778                                        si->setDefaultBound(100.0);
3779                                        double dextra3 = parameters_[whichParam(CBC_PARAM_DBL_DEXTRA3, numberParameters_, parameters_)].doubleValue();
3780                                        if (dextra3)
3781                                            si->setDefaultMeshSize(dextra3);
3782                                        si->setDefaultBound(1000.0);
3783                                        si->setIntegerPriority(1000);
3784                                        si->setBiLinearPriority(10000);
3785                                        si->setSpecialOptions2(2 + 4 + 8);
3786                                        CoinModel * model2 = coinModel;
3787                                        si->load(*model2, true, parameters_[log].intValue());
3788                                        // redo
3789                                        solver = model_.solver();
3790                                        clpSolver = dynamic_cast< OsiClpSolverInterface*> (solver);
3791                                        lpSolver = clpSolver->getModelPtr();
3792                                        clpSolver->messageHandler()->setLogLevel(0) ;
3793                                        testOsiParameters = 0;
3794                                        complicatedInteger = 2;  // allow cuts
3795                                        OsiSolverInterface * coinSolver = model_.solver();
3796                                        OsiSolverLink * linkSolver = dynamic_cast< OsiSolverLink*> (coinSolver);
3797                                        if (linkSolver->quadraticModel()) {
3798                                            ClpSimplex * qp = linkSolver->quadraticModel();
3799                                            //linkSolver->nonlinearSLP(CoinMax(slpValue,10),1.0e-5);
3800                                            qp->nonlinearSLP(CoinMax(slpValue, 40), 1.0e-5);
3801                                            qp->primal(1);
3802                                            OsiSolverLinearizedQuadratic solver2(qp);
3803                                            const double * solution = NULL;
3804                                            // Reduce printout
3805                                            solver2.setHintParam(OsiDoReducePrint, true, OsiHintTry);
3806                                            CbcModel model2(solver2);
3807                                            // Now do requested saves and modifications
3808                                            CbcModel * cbcModel = & model2;
3809                                            OsiSolverInterface * osiModel = model2.solver();
3810                                            OsiClpSolverInterface * osiclpModel = dynamic_cast< OsiClpSolverInterface*> (osiModel);
3811                                            ClpSimplex * clpModel = osiclpModel->getModelPtr();
3812
3813                                            // Set changed values
3814
3815                                            CglProbing probing;
3816                                            probing.setMaxProbe(10);
3817                                            probing.setMaxLook(10);
3818                                            probing.setMaxElements(200);
3819                                            probing.setMaxProbeRoot(50);
3820                                            probing.setMaxLookRoot(10);
3821                                            probing.setRowCuts(3);
3822                                            probing.setUsingObjective(true);
3823                                            cbcModel->addCutGenerator(&probing, -1, "Probing", true, false, false, -100, -1, -1);
3824                                            cbcModel->cutGenerator(0)->setTiming(true);
3825
3826                                            CglGomory gomory;
3827                                            gomory.setLimitAtRoot(512);
3828                                            cbcModel->addCutGenerator(&gomory, -98, "Gomory", true, false, false, -100, -1, -1);
3829                                            cbcModel->cutGenerator(1)->setTiming(true);
3830
3831                                            CglKnapsackCover knapsackCover;
3832                                            cbcModel->addCutGenerator(&knapsackCover, -98, "KnapsackCover", true, false, false, -100, -1, -1);
3833                                            cbcModel->cutGenerator(2)->setTiming(true);
3834
3835                                            CglRedSplit redSplit;
3836                                            cbcModel->addCutGenerator(&redSplit, -99, "RedSplit", true, false, false, -100, -1, -1);
3837                                            cbcModel->cutGenerator(3)->setTiming(true);
3838
3839                                            CglClique clique;
3840                                            clique.setStarCliqueReport(false);
3841                                            clique.setRowCliqueReport(false);
3842                                            clique.setMinViolation(0.1);
3843                                            cbcModel->addCutGenerator(&clique, -98, "Clique", true, false, false, -100, -1, -1);
3844                                            cbcModel->cutGenerator(4)->setTiming(true);
3845
3846                                            CglMixedIntegerRounding2 mixedIntegerRounding2;
3847                                            cbcModel->addCutGenerator(&mixedIntegerRounding2, -98, "MixedIntegerRounding2", true, false, false, -100, -1, -1);
3848                                            cbcModel->cutGenerator(5)->setTiming(true);
3849
3850                                            CglFlowCover flowCover;
3851                                            cbcModel->addCutGenerator(&flowCover, -98, "FlowCover", true, false, false, -100, -1, -1);
3852                                            cbcModel->cutGenerator(6)->setTiming(true);
3853
3854                                            CglTwomir twomir;
3855                                            twomir.setMaxElements(250);
3856                                            cbcModel->addCutGenerator(&twomir, -99, "Twomir", true, false, false, -100, -1, -1);
3857                                            cbcModel->cutGenerator(7)->setTiming(true);
3858
3859                                            CbcHeuristicFPump heuristicFPump(*cbcModel);
3860                                            heuristicFPump.setWhen(13);
3861                                            heuristicFPump.setMaximumPasses(20);
3862                                            heuristicFPump.setMaximumRetries(7);
3863                                            heuristicFPump.setHeuristicName("feasibility pump");
3864                                            heuristicFPump.setInitialWeight(1);
3865                                            heuristicFPump.setFractionSmall(0.6);
3866                                            cbcModel->addHeuristic(&heuristicFPump);
3867
3868                                            CbcRounding rounding(*cbcModel);
3869                                            rounding.setHeuristicName("rounding");
3870                                            cbcModel->addHeuristic(&rounding);
3871
3872                                            CbcHeuristicLocal heuristicLocal(*cbcModel);
3873                                            heuristicLocal.setHeuristicName("combine solutions");
3874                                            heuristicLocal.setSearchType(1);
3875                                            heuristicLocal.setFractionSmall(0.6);
3876                                            cbcModel->addHeuristic(&heuristicLocal);
3877
3878                                            CbcHeuristicGreedyCover heuristicGreedyCover(*cbcModel);
3879                                            heuristicGreedyCover.setHeuristicName("greedy cover");
3880                                            cbcModel->addHeuristic(&heuristicGreedyCover);
3881
3882                                            CbcHeuristicGreedyEquality heuristicGreedyEquality(*cbcModel);
3883                                            heuristicGreedyEquality.setHeuristicName("greedy equality");
3884                                            cbcModel->addHeuristic(&heuristicGreedyEquality);
3885
3886                                            CbcCompareDefault compare;
3887                                            cbcModel->setNodeComparison(compare);
3888                                            cbcModel->setNumberBeforeTrust(5);
3889                                            cbcModel->setSpecialOptions(2);
3890                                            cbcModel->messageHandler()->setLogLevel(1);
3891                                            cbcModel->setMaximumCutPassesAtRoot(-100);
3892                                            cbcModel->setMaximumCutPasses(1);
3893                                            cbcModel->setMinimumDrop(0.05);
3894                                            // For branchAndBound this may help
3895                                            clpModel->defaultFactorizationFrequency();
3896                                            clpModel->setDualBound(1.0001e+08);
3897                                            clpModel->setPerturbation(50);
3898                                            osiclpModel->setSpecialOptions(193);
3899                                            osiclpModel->messageHandler()->setLogLevel(0);
3900                                            osiclpModel->setIntParam(OsiMaxNumIterationHotStart, 100);
3901                                            osiclpModel->setHintParam(OsiDoReducePrint, true, OsiHintTry);
3902                                            // You can save some time by switching off message building
3903                                            // clpModel->messagesPointer()->setDetailMessages(100,10000,(int *) NULL);
3904
3905                                            // Solve
3906
3907                                            cbcModel->initialSolve();
3908                                            if (clpModel->tightenPrimalBounds() != 0) {
3909#ifndef DISALLOW_PRINTING
3910                                                std::cout << "Problem is infeasible - tightenPrimalBounds!" << std::endl;
3911#endif
3912                                                break;
3913                                            }
3914                                            clpModel->dual();  // clean up
3915                                            cbcModel->initialSolve();
3916#ifdef CBC_THREAD
3917                                            int numberThreads = parameters_[whichParam(CBC_PARAM_INT_THREADS, numberParameters_, parameters_)].intValue();
3918                                            cbcModel->setNumberThreads(numberThreads % 100);
3919                                            cbcModel->setThreadMode(CoinMin(numberThreads / 100, 7));
3920#endif
3921                                            //setCutAndHeuristicOptions(*cbcModel);
3922                                            cbcModel->branchAndBound();
3923                                            OsiSolverLinearizedQuadratic * solver3 = dynamic_cast<OsiSolverLinearizedQuadratic *> (model2.solver());
3924                                            assert (solver3);
3925                                            solution = solver3->bestSolution();
3926                                            double bestObjectiveValue = solver3->bestObjectiveValue();
3927                                            linkSolver->setBestObjectiveValue(bestObjectiveValue);
3928                                            linkSolver->setBestSolution(solution, solver3->getNumCols());
3929                                            CbcHeuristicDynamic3 dynamic(model_);
3930                                            dynamic.setHeuristicName("dynamic pass thru");
3931                                            model_.addHeuristic(&dynamic);
3932                                            // if convex
3933                                            if ((linkSolver->specialOptions2()&4) != 0) {
3934                                                int numberColumns = coinModel->numberColumns();
3935                                                assert (linkSolver->objectiveVariable() == numberColumns);
3936                                                // add OA cut
3937                                                double offset;
3938                                                double * gradient = new double [numberColumns+1];
3939                                                memcpy(gradient, qp->objectiveAsObject()->gradient(qp, solution, offset, true, 2),
3940                                                       numberColumns*sizeof(double));
3941                                                double rhs = 0.0;
3942                                                int * column = new int[numberColumns+1];
3943                                                int n = 0;
3944                                                for (int i = 0; i < numberColumns; i++) {
3945                                                    double value = gradient[i];
3946                                                    if (fabs(value) > 1.0e-12) {
3947                                                        gradient[n] = value;
3948                                                        rhs += value * solution[i];
3949                                                        column[n++] = i;
3950                                                    }
3951                                                }
3952                                                gradient[n] = -1.0;
3953                                                column[n++] = numberColumns;
3954                                                storedAmpl.addCut(-COIN_DBL_MAX, offset + 1.0e-7, n, column, gradient);
3955                                                delete [] gradient;
3956                                                delete [] column;
3957                                            }
3958                                            // could do three way branching round a) continuous b) best solution
3959                                            printf("obj %g\n", bestObjectiveValue);
3960                                            linkSolver->initialSolve();
3961                                        }
3962                                    }
3963                                }
3964#endif
3965#endif
3966                                if (logLevel <= 1)
3967                                    si->setHintParam(OsiDoReducePrint, true, OsiHintTry);
3968#ifndef CBC_OTHER_SOLVER
3969                                si->setSpecialOptions(0x40000000);
3970#endif
3971                            }
3972                            if (!miplib) {
3973                                if (!preSolve) {
3974                                    model_.solver()->setHintParam(OsiDoPresolveInInitial, false, OsiHintTry);
3975                                    model_.solver()->setHintParam(OsiDoPresolveInResolve, false, OsiHintTry);
3976                                }
3977                                double time1a = CoinCpuTime();
3978                                OsiSolverInterface * solver = model_.solver();
3979#ifndef CBC_OTHER_SOLVER
3980                                OsiClpSolverInterface * si =
3981                                    dynamic_cast<OsiClpSolverInterface *>(solver) ;
3982                                if (si)
3983                                    si->setSpecialOptions(si->specialOptions() | 1024);
3984#endif
3985                                model_.initialSolve();
3986#ifndef CBC_OTHER_SOLVER
3987                                ClpSimplex * clpSolver = si->getModelPtr();
3988                                int iStatus = clpSolver->status();
3989                                int iStatus2 = clpSolver->secondaryStatus();
3990                                if (iStatus == 0) {
3991                                    iStatus2 = 0;
3992                                } else if (iStatus == 1) {
3993                                    iStatus = 0;
3994                                    iStatus2 = 1; // say infeasible
3995                                } else if (iStatus == 2) {
3996                                    iStatus = 0;
3997                                    iStatus2 = 7; // say unbounded
3998                                } else if (iStatus == 3) {
3999                                    iStatus = 1;
4000                                    if (iStatus2 == 9)
4001                                        iStatus2 = 4;
4002                                    else
4003                                        iStatus2 = 3; // Use nodes - as closer than solutions
4004                                } else if (iStatus == 4) {
4005                                    iStatus = 2; // difficulties
4006                                    iStatus2 = 0;
4007                                }
4008                                model_.setProblemStatus(iStatus);
4009                                model_.setSecondaryStatus(iStatus2);
4010                                si->setWarmStart(NULL);
4011                                int returnCode = callBack(&model_, 1);
4012                                if (returnCode) {
4013                                    // exit if user wants
4014                                    delete babModel_;
4015                                    babModel_ = NULL;
4016                                    return returnCode;
4017                                }
4018                                if (clpSolver->status() > 0) {
4019                                    // and in babModel if exists
4020                                    if (babModel_) {
4021                                        babModel_->setProblemStatus(iStatus);
4022                                        babModel_->setSecondaryStatus(iStatus2);
4023                                    }
4024                                    if (!noPrinting_) {
4025                                        iStatus = clpSolver->status();
4026                                        const char * msg[] = {"infeasible", "unbounded", "stopped",
4027                                                              "difficulties", "other"
4028                                                             };
4029                                        sprintf(generalPrint, "Problem is %s - %.2f seconds",
4030                                                msg[iStatus-1], CoinCpuTime() - time1a);
4031                                        generalMessageHandler->message(CLP_GENERAL, generalMessages)
4032                                        << generalPrint
4033                                        << CoinMessageEol;
4034                                    }
4035                                    break;
4036                                }
4037                                clpSolver->setSpecialOptions(clpSolver->specialOptions() | IN_BRANCH_AND_BOUND); // say is Cbc (and in branch and bound)
4038#elif CBC_OTHER_SOLVER==1
4039#endif
4040                                if (!noPrinting_) {
4041                                    sprintf(generalPrint, "Continuous objective value is %g - %.2f seconds",
4042                                            solver->getObjValue(), CoinCpuTime() - time1a);
4043                                    generalMessageHandler->message(CLP_GENERAL, generalMessages)
4044                                    << generalPrint
4045                                    << CoinMessageEol;
4046                                }
4047                                if (model_.getMaximumNodes() == -987654321) {
4048                                    // See if No objective!
4049                                    int numberColumns = clpSolver->getNumCols();
4050                                    const double * obj = clpSolver->getObjCoefficients();
4051                                    const double * lower = clpSolver->getColLower();
4052                                    const double * upper = clpSolver->getColUpper();
4053                                    int nObj = 0;
4054                                    for (int i = 0; i < numberColumns; i++) {
4055                                        if (upper[i] > lower[i] && obj[i])
4056                                            nObj++;
4057                                    }
4058                                    if (!nObj) {
4059                                        printf("************No objective!!\n");
4060                                        model_.setMaximumSolutions(1);
4061                                        // Column copy
4062                                        CoinPackedMatrix  matrixByCol(*model_.solver()->getMatrixByCol());
4063                                        //const double * element = matrixByCol.getElements();
4064                                        //const int * row = matrixByCol.getIndices();
4065                                        //const CoinBigIndex * columnStart = matrixByCol.getVectorStarts();
4066                                        const int * columnLength = matrixByCol.getVectorLengths();
4067                                        for (int i = 0; i < numberColumns; i++) {
4068                                            double value = (CoinDrand48() + 0.5) * 10000;
4069                                            value = 10;
4070                                            value *= columnLength[i];
4071                                            int iValue = static_cast<int> (value) / 10;
4072                                            //iValue=1;
4073                                            clpSolver->setObjCoeff(i, iValue);
4074                                        }
4075                                    }
4076                                }
4077#ifndef CBC_OTHER_SOLVER
4078                                if (!complicatedInteger && preProcess == 0 && clpSolver->tightenPrimalBounds(0.0, 0, true) != 0) {
4079#ifndef DISALLOW_PRINTING
4080                                    std::cout << "Problem is infeasible - tightenPrimalBounds!" << std::endl;
4081#endif
4082                                    model_.setProblemStatus(0);
4083                                    model_.setSecondaryStatus(1);
4084                                    // and in babModel if exists
4085                                    if (babModel_) {
4086                                        babModel_->setProblemStatus(0);
4087                                        babModel_->setSecondaryStatus(1);
4088                                    }
4089                                    break;
4090                                }
4091                                if (clpSolver->dualBound() == 1.0e10) {
4092                                    ClpSimplex temp = *clpSolver;
4093                                    temp.setLogLevel(0);
4094                                    temp.dual(0, 7);
4095                                    // user did not set - so modify
4096                                    // get largest scaled away from bound
4097                                    double largest = 1.0e-12;
4098                                    double largestScaled = 1.0e-12;
4099                                    int numberRows = temp.numberRows();
4100                                    const double * rowPrimal = temp.primalRowSolution();
4101                                    const double * rowLower = temp.rowLower();
4102                                    const double * rowUpper = temp.rowUpper();
4103                                    const double * rowScale = temp.rowScale();
4104                                    int iRow;
4105                                    for (iRow = 0; iRow < numberRows; iRow++) {
4106                                        double value = rowPrimal[iRow];
4107                                        double above = value - rowLower[iRow];
4108                                        double below = rowUpper[iRow] - value;
4109                                        if (above < 1.0e12) {
4110                                            largest = CoinMax(largest, above);
4111                                        }
4112                                        if (below < 1.0e12) {
4113                                            largest = CoinMax(largest, below);
4114                                        }
4115                                        if (rowScale) {
4116                                            double multiplier = rowScale[iRow];
4117                                            above *= multiplier;
4118                                            below *= multiplier;
4119                                        }
4120                                        if (above < 1.0e12) {
4121                                            largestScaled = CoinMax(largestScaled, above);
4122                                        }
4123                                        if (below < 1.0e12) {
4124                                            largestScaled = CoinMax(largestScaled, below);
4125                                        }
4126                                    }
4127
4128                                    int numberColumns = temp.numberColumns();
4129                                    const double * columnPrimal = temp.primalColumnSolution();
4130                                    const double * columnLower = temp.columnLower();
4131                                    const double * columnUpper = temp.columnUpper();
4132                                    const double * columnScale = temp.columnScale();
4133                                    int iColumn;
4134                                    for (iColumn = 0; iColumn < numberColumns; iColumn++) {
4135                                        double value = columnPrimal[iColumn];
4136                                        double above = value - columnLower[iColumn];
4137                                        double below = columnUpper[iColumn] - value;
4138                                        if (above < 1.0e12) {
4139                                            largest = CoinMax(largest, above);
4140                                        }
4141                                        if (below < 1.0e12) {
4142                                            largest = CoinMax(largest, below);
4143                                        }
4144                                        if (columnScale) {
4145                                            double multiplier = 1.0 / columnScale[iColumn];
4146                                            above *= multiplier;
4147                                            below *= multiplier;
4148                                        }
4149                                        if (above < 1.0e12) {
4150                                            largestScaled = CoinMax(largestScaled, above);
4151                                        }
4152                                        if (below < 1.0e12) {
4153                                            largestScaled = CoinMax(largestScaled, below);
4154                                        }
4155                                    }
4156#ifdef COIN_DEVELOP
4157                                    if (!noPrinting_)
4158                                        std::cout << "Largest (scaled) away from bound " << largestScaled
4159                                                  << " unscaled " << largest << std::endl;
4160#endif
4161                                    clpSolver->setDualBound(CoinMax(1.0001e8, CoinMin(100.0*largest, 1.00001e10)));
4162                                }
4163                                si->resolve();  // clean up
4164#endif
4165                            }
4166                            // If user made settings then use them
4167                            if (!defaultSettings) {
4168                                OsiSolverInterface * solver = model_.solver();
4169                                if (!doScaling)
4170                                    solver->setHintParam(OsiDoScale, false, OsiHintTry);
4171#ifndef CBC_OTHER_SOLVER
4172                                OsiClpSolverInterface * si =
4173                                    dynamic_cast<OsiClpSolverInterface *>(solver) ;
4174                                assert (si != NULL);
4175                                // get clp itself
4176                                ClpSimplex * modelC = si->getModelPtr();
4177                                //if (modelC->tightenPrimalBounds()!=0) {
4178                                //std::cout<<"Problem is infeasible!"<<std::endl;
4179                                //break;
4180                                //}
4181                                // bounds based on continuous
4182                                if (tightenFactor && !complicatedInteger) {
4183                                    if (modelC->tightenPrimalBounds(tightenFactor) != 0) {
4184#ifndef DISALLOW_PRINTING
4185                                        std::cout << "Problem is infeasible!" << std::endl;
4186#endif
4187                                        model_.setProblemStatus(0);
4188                                        model_.setSecondaryStatus(1);
4189                                        // and in babModel if exists
4190                                        if (babModel_) {
4191                                            babModel_->setProblemStatus(0);
4192                                            babModel_->setSecondaryStatus(1);
4193                                        }
4194                                        break;
4195                                    }
4196                                }
4197#endif
4198                            }
4199                            // See if we want preprocessing
4200                            OsiSolverInterface * saveSolver = NULL;
4201                            CglPreProcess process;
4202                            // Say integers in sync
4203                            bool integersOK = true;
4204                            delete babModel_;
4205                            babModel_ = new CbcModel(model_);
4206#ifndef CBC_OTHER_SOLVER
4207                            int numberChanged = 0;
4208                            OsiSolverInterface * solver3 = clpSolver->clone();
4209                            babModel_->assignSolver(solver3);
4210                            OsiClpSolverInterface * clpSolver2 = dynamic_cast< OsiClpSolverInterface*> (babModel_->solver());
4211                            if (clpSolver2->messageHandler()->logLevel())
4212                                clpSolver2->messageHandler()->setLogLevel(1);
4213                            if (logLevel > -1)
4214                                clpSolver2->messageHandler()->setLogLevel(logLevel);
4215                            lpSolver = clpSolver2->getModelPtr();
4216                            if (lpSolver->factorizationFrequency() == 200 && !miplib) {
4217                                // User did not touch preset
4218                                int numberRows = lpSolver->numberRows();
4219                                const int cutoff1 = 10000;
4220                                const int cutoff2 = 100000;
4221                                const int base = 75;
4222                                const int freq0 = 50;
4223                                const int freq1 = 200;
4224                                const int freq2 = 400;
4225                                const int maximum = 1000;
4226                                int frequency;
4227                                if (numberRows < cutoff1)
4228                                    frequency = base + numberRows / freq0;
4229                                else if (numberRows < cutoff2)
4230                                    frequency = base + cutoff1 / freq0 + (numberRows - cutoff1) / freq1;
4231                                else
4232                                    frequency = base + cutoff1 / freq0 + (cutoff2 - cutoff1) / freq1 + (numberRows - cutoff2) / freq2;
4233                                lpSolver->setFactorizationFrequency(CoinMin(maximum, frequency));
4234                            }
4235#elif CBC_OTHER_SOLVER==1
4236                            OsiSolverInterface * solver3 = model_.solver()->clone();
4237                            babModel_->assignSolver(solver3);
4238#endif
4239                            time2 = CoinCpuTime();
4240                            totalTime += time2 - time1;
4241                            time1 = time2;
4242                            double timeLeft = babModel_->getMaximumSeconds();
4243                            int numberOriginalColumns = babModel_->solver()->getNumCols();
4244                            if (preProcess == 7) {
4245                                // use strategy instead
4246                                preProcess = 0;
4247                                useStrategy = true;
4248#ifdef COIN_HAS_LINK
4249                                // empty out any cuts
4250                                if (storedAmpl.sizeRowCuts()) {
4251                                    printf("Emptying ampl stored cuts as internal preprocessing\n");
4252                                    CglStored temp;
4253                                    storedAmpl = temp;
4254                                }
4255#endif
4256                            }
4257                            if (type == CBC_PARAM_ACTION_BAB) {
4258                                double limit;
4259                                clpSolver->getDblParam(OsiDualObjectiveLimit, limit);
4260                                if (clpSolver->getObjValue()*clpSolver->getObjSense() >=
4261                                        limit*clpSolver->getObjSense())
4262                                    preProcess = 0;
4263                            }
4264                            if (preProcess && type == CBC_PARAM_ACTION_BAB) {
4265#ifndef CBC_OTHER_SOLVER
4266                                // See if sos from mps file
4267                                if (numberSOS == 0 && clpSolver->numberSOS() && doSOS) {
4268                                    // SOS
4269                                    numberSOS = clpSolver->numberSOS();
4270                                    const CoinSet * setInfo = clpSolver->setInfo();
4271                                    sosStart = new int [numberSOS+1];
4272                                    sosType = new char [numberSOS];
4273                                    int i;
4274                                    int nTotal = 0;
4275                                    sosStart[0] = 0;
4276                                    for ( i = 0; i < numberSOS; i++) {
4277                                        int type = setInfo[i].setType();
4278                                        int n = setInfo[i].numberEntries();
4279                                        sosType[i] = static_cast<char>(type);
4280                                        nTotal += n;
4281                                        sosStart[i+1] = nTotal;
4282                                    }
4283                                    sosIndices = new int[nTotal];
4284                                    sosReference = new double [nTotal];
4285                                    for (i = 0; i < numberSOS; i++) {
4286                                        int n = setInfo[i].numberEntries();
4287                                        const int * which = setInfo[i].which();
4288                                        const double * weights = setInfo[i].weights();
4289                                        int base = sosStart[i];
4290                                        for (int j = 0; j < n; j++) {
4291                                            int k = which[j];
4292                                            sosIndices[j+base] = k;
4293                                            sosReference[j+base] = weights ? weights[j] : static_cast<double> (j);
4294                                        }
4295                                    }
4296                                }
4297#endif
4298                                saveSolver = babModel_->solver()->clone();
4299                                /* Do not try and produce equality cliques and
4300                                   do up to 10 passes */
4301                                OsiSolverInterface * solver2;
4302                                {
4303                                    // Tell solver we are in Branch and Cut
4304                                    saveSolver->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo) ;
4305                                    // Default set of cut generators
4306                                    CglProbing generator1;
4307                                    generator1.setUsingObjective(1);
4308                                    generator1.setMaxPass(1);
4309                                    generator1.setMaxPassRoot(1);
4310                                    generator1.setMaxProbeRoot(CoinMin(3000, saveSolver->getNumCols()));
4311                                    generator1.setMaxElements(100);
4312                                    generator1.setMaxElementsRoot(200);
4313                                    generator1.setMaxLookRoot(50);
4314                                    if (saveSolver->getNumCols() > 3000)
4315                                        generator1.setMaxProbeRoot(123);
4316                                    generator1.setRowCuts(3);
4317                                    if ((tunePreProcess&1) != 0) {
4318                                        // heavy probing
4319                                        generator1.setMaxPassRoot(2);
4320                                        generator1.setMaxElements(300);
4321                                        generator1.setMaxProbeRoot(saveSolver->getNumCols());
4322                                    }
4323                                    if ((babModel_->specialOptions()&65536) != 0)
4324                                        process.setOptions(1);
4325                                    // Add in generators
4326                                    process.addCutGenerator(&generator1);
4327                                    int translate[] = {9999, 0, 0, -3, 2, 3, -2, 9999, 4, 5};
4328                                    process.passInMessageHandler(babModel_->messageHandler());
4329                                    //process.messageHandler()->setLogLevel(babModel_->logLevel());
4330#ifdef COIN_HAS_ASL
4331                                    if (info.numberSos && doSOS && statusUserFunction_[0]) {
4332                                        // SOS
4333                                        numberSOS = info.numberSos;
4334                                        sosStart = info.sosStart;
4335                                        sosIndices = info.sosIndices;
4336                                    }
4337#endif
4338                                    if (numberSOS && doSOS) {
4339                                        // SOS
4340                                        int numberColumns = saveSolver->getNumCols();
4341                                        char * prohibited = new char[numberColumns];
4342                                        memset(prohibited, 0, numberColumns);
4343                                        int n = sosStart[numberSOS];
4344                                        for (int i = 0; i < n; i++) {
4345                                            int iColumn = sosIndices[i];
4346                                            prohibited[iColumn] = 1;
4347                                        }
4348                                        process.passInProhibited(prohibited, numberColumns);
4349                                        delete [] prohibited;
4350                                    }
4351                                    if (!model_.numberObjects() && true) {
4352                                        /* model may not have created objects
4353                                           If none then create
4354                                        */
4355                                        model_.findIntegers(true);
4356                                    }
4357                                    if (model_.numberObjects()) {
4358                                        OsiObject ** oldObjects = babModel_->objects();
4359                                        int numberOldObjects = babModel_->numberObjects();
4360                                        // SOS
4361                                        int numberColumns = saveSolver->getNumCols();
4362                                        char * prohibited = new char[numberColumns];
4363                                        memset(prohibited, 0, numberColumns);
4364                                        int numberProhibited = 0;
4365                                        for (int iObj = 0; iObj < numberOldObjects; iObj++) {
4366                                            CbcSOS * obj =
4367                                                dynamic_cast <CbcSOS *>(oldObjects[iObj]) ;
4368                                            if (obj) {
4369                                                int n = obj->numberMembers();
4370                                                const int * which = obj->members();
4371                                                for (int i = 0; i < n; i++) {
4372                                                    int iColumn = which[i];
4373                                                    prohibited[iColumn] = 1;
4374                                                    numberProhibited++;
4375                                                }
4376                                            }
4377                                            CbcLotsize * obj2 =
4378                                                dynamic_cast <CbcLotsize *>(oldObjects[iObj]) ;
4379                                            if (obj2) {
4380                                                int iColumn = obj2->columnNumber();
4381                                                prohibited[iColumn] = 1;
4382                                                numberProhibited++;
4383                                            }
4384                                        }
4385                                        if (numberProhibited)
4386                                            process.passInProhibited(prohibited, numberColumns);
4387                                        delete [] prohibited;
4388                                    }
4389                                    int numberPasses = 10;
4390                                    if (tunePreProcess >= 1000000) {
4391                                        numberPasses = (tunePreProcess / 1000000) - 1;
4392                                        tunePreProcess = tunePreProcess % 1000000;
4393                                    } else if (tunePreProcess >= 1000) {
4394                                        numberPasses = (tunePreProcess / 1000) - 1;
4395                                        tunePreProcess = tunePreProcess % 1000;
4396                                    }
4397#ifndef CBC_OTHER_SOLVER
4398                                    if (doSprint > 0) {
4399                                        // Sprint for primal solves
4400                                        ClpSolve::SolveType method = ClpSolve::usePrimalorSprint;
4401                                        ClpSolve::PresolveType presolveType = ClpSolve::presolveOff;
4402                                        int numberPasses = 5;
4403                                        int options[] = {0, 3, 0, 0, 0, 0};
4404                                        int extraInfo[] = { -1, 20, -1, -1, -1, -1};
4405                                        extraInfo[1] = doSprint;
4406                                        int independentOptions[] = {0, 0, 3};
4407                                        ClpSolve clpSolve(method, presolveType, numberPasses,
4408                                                          options, extraInfo, independentOptions);
4409                                        // say use in OsiClp
4410                                        clpSolve.setSpecialOption(6, 1);
4411                                        OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (saveSolver);
4412                                        osiclp->setSolveOptions(clpSolve);
4413                                        osiclp->setHintParam(OsiDoDualInResolve, false);
4414                                        // switch off row copy
4415                                        osiclp->getModelPtr()->setSpecialOptions(osiclp->getModelPtr()->specialOptions() | 256);
4416                                        osiclp->getModelPtr()->setInfeasibilityCost(1.0e11);
4417                                    }
4418#endif
4419#ifndef CBC_OTHER_SOLVER
4420                                    {
4421                                        OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (saveSolver);
4422                                        osiclp->setSpecialOptions(osiclp->specialOptions() | 1024);
4423                                        int savePerturbation = osiclp->getModelPtr()->perturbation();
4424                                        //#define CBC_TEMP1
4425#ifdef CBC_TEMP1
4426                                        if (savePerturbation == 50)
4427                                            osiclp->getModelPtr()->setPerturbation(52); // try less
4428#endif
4429                                        solver2 = process.preProcessNonDefault(*saveSolver, translate[preProcess], numberPasses,
4430                                                                               tunePreProcess);
4431                                        /*solver2->writeMps("after");
4432                                          saveSolver->writeMps("before");*/
4433                                        osiclp->getModelPtr()->setPerturbation(savePerturbation);
4434                                    }
4435#elif CBC_OTHER_SOLVER==1
4436                                    solver2 = process.preProcessNonDefault(*saveSolver, translate[preProcess], numberPasses,
4437                                                                           tunePreProcess);
4438#endif
4439                                    integersOK = false; // We need to redo if CbcObjects exist
4440                                    // Tell solver we are not in Branch and Cut
4441                                    saveSolver->setHintParam(OsiDoInBranchAndCut, false, OsiHintDo) ;
4442                                    if (solver2)
4443                                        solver2->setHintParam(OsiDoInBranchAndCut, false, OsiHintDo) ;
4444                                }
4445#ifdef COIN_HAS_ASL
4446                                if (!solver2 && statusUserFunction_[0]) {
4447                                    // infeasible
4448                                    info.problemStatus = 1;
4449                                    info.objValue = 1.0e100;
4450                                    sprintf(info.buffer, "infeasible/unbounded by pre-processing");
4451                                    info.primalSolution = NULL;
4452                                    info.dualSolution = NULL;
4453                                    break;
4454                                }
4455#endif
4456                                if (!noPrinting_) {
4457                                    if (!solver2) {
4458                                        sprintf(generalPrint, "Pre-processing says infeasible or unbounded");
4459                                        generalMessageHandler->message(CLP_GENERAL, generalMessages)
4460                                        << generalPrint
4461                                        << CoinMessageEol;
4462                                    } else {
4463                                        //printf("processed model has %d rows, %d columns and %d elements\n",
4464                                        //     solver2->getNumRows(),solver2->getNumCols(),solver2->getNumElements());
4465                                    }
4466                                }
4467                                if (!solver2) {
4468                                    // say infeasible for solution
4469                                    integerStatus = 6;
4470                                    model_.setProblemStatus(0);
4471                                    model_.setSecondaryStatus(1);
4472                                    babModel_->setProblemStatus(0);
4473                                    babModel_->setSecondaryStatus(1);
4474                                } else {
4475                                    statistics_nprocessedrows = solver2->getNumRows();
4476                                    statistics_nprocessedcols = solver2->getNumCols();
4477                                    model_.setProblemStatus(-1);
4478                                    babModel_->setProblemStatus(-1);
4479                                }
4480                                int returnCode = callBack(babModel_, 2);
4481                                if (returnCode) {
4482                                    // exit if user wants
4483                                    delete babModel_;
4484                                    babModel_ = NULL;
4485                                    return returnCode;
4486                                }
4487                                if (!solver2)
4488                                    break;
4489                                if (model_.bestSolution()) {
4490                                    // need to redo - in case no better found in BAB
4491                                    // just get integer part right
4492                                    const int * originalColumns = process.originalColumns();
4493                                    int numberColumns = solver2->getNumCols();
4494                                    double * bestSolution = babModel_->bestSolution();
4495                                    const double * oldBestSolution = model_.bestSolution();
4496                                    for (int i = 0; i < numberColumns; i++) {
4497                                        int jColumn = originalColumns[i];
4498                                        bestSolution[i] = oldBestSolution[jColumn];
4499                                    }
4500                                }
4501                                //solver2->resolve();
4502                                if (preProcess == 2) {
4503                                    OsiClpSolverInterface * clpSolver2 = dynamic_cast< OsiClpSolverInterface*> (solver2);
4504                                    ClpSimplex * lpSolver = clpSolver2->getModelPtr();
4505                                    lpSolver->writeMps("presolved.mps", 0, 1, lpSolver->optimizationDirection());
4506                                    printf("Preprocessed model (minimization) on presolved.mps\n");
4507                                }
4508                                {
4509                                    // look at new integers
4510                                    int numberOriginalColumns =
4511                                        process.originalModel()->getNumCols();
4512                                    const int * originalColumns = process.originalColumns();
4513                                    OsiClpSolverInterface * osiclp2 = dynamic_cast< OsiClpSolverInterface*> (solver2);
4514                                    int numberColumns = osiclp2->getNumCols();
4515                                    OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (saveSolver);
4516                                    for (int i = 0; i < numberColumns; i++) {
4517                                        int iColumn = originalColumns[i];
4518                                        if (iColumn < numberOriginalColumns) {
4519                                            if (osiclp2->isInteger(i) && !osiclp->isInteger(iColumn))
4520                                                osiclp2->setOptionalInteger(i); // say optional
4521                                        }
4522                                    }
4523                                }
4524                                // we have to keep solver2 so pass clone
4525                                solver2 = solver2->clone();
4526                                babModel_->assignSolver(solver2);
4527                                babModel_->setOriginalColumns(process.originalColumns());
4528                                babModel_->initialSolve();
4529                                babModel_->setMaximumSeconds(timeLeft - (CoinCpuTime() - time1));
4530                            }
4531                            // now tighten bounds
4532                            if (!miplib) {
4533#ifndef CBC_OTHER_SOLVER
4534                                OsiClpSolverInterface * si =
4535                                    dynamic_cast<OsiClpSolverInterface *>(babModel_->solver()) ;
4536                                assert (si != NULL);
4537                                // get clp itself
4538                                ClpSimplex * modelC = si->getModelPtr();
4539                                //if (noPrinting_)
4540                                //modelC->setLogLevel(0);
4541                                if (!complicatedInteger && modelC->tightenPrimalBounds() != 0) {
4542#ifndef DISALLOW_PRINTING
4543                                    std::cout << "Problem is infeasible!" << std::endl;
4544#endif
4545                                    model_.setProblemStatus(0);
4546                                    model_.setSecondaryStatus(1);
4547                                    // and in babModel_ if exists
4548                                    if (babModel_) {
4549                                        babModel_->setProblemStatus(0);
4550                                        babModel_->setSecondaryStatus(1);
4551                                    }
4552                                    break;
4553                                }
4554                                si->resolve();
4555#elif CBC_OTHER_SOLVER==1
4556#endif
4557                            }
4558                            if (debugValues) {
4559                                // for debug
4560                                std::string problemName ;
4561                                babModel_->solver()->getStrParam(OsiProbName, problemName) ;
4562                                babModel_->solver()->activateRowCutDebugger(problemName.c_str()) ;
4563                                twomirGen.probname_ = CoinStrdup(problemName.c_str());
4564                                // checking seems odd
4565                                //redsplitGen.set_given_optsol(babModel_->solver()->getRowCutDebuggerAlways()->optimalSolution(),
4566                                //                         babModel_->getNumCols());
4567                            }
4568                            int testOsiOptions = parameters_[whichParam(CBC_PARAM_INT_TESTOSI, numberParameters_, parameters_)].intValue();
4569                            //#ifdef COIN_HAS_ASL
4570#if 1
4571                            // If linked then see if expansion wanted
4572                            {
4573                                OsiSolverLink * solver3 = dynamic_cast<OsiSolverLink *> (babModel_->solver());
4574                                int options = parameters_[whichParam(CBC_PARAM_INT_MIPOPTIONS, numberParameters_, parameters_)].intValue() / 10000;
4575                                if (solver3 || (options&16) != 0) {
4576                                    if (options) {
4577                                        /*
4578                                          1 - force mini branch and bound
4579                                          2 - set priorities high on continuous
4580                                          4 - try adding OA cuts
4581                                          8 - try doing quadratic linearization
4582                                          16 - try expanding knapsacks
4583                                        */
4584                                        if ((options&16)) {
4585                                            int numberColumns = saveCoinModel.numberColumns();
4586                                            int numberRows = saveCoinModel.numberRows();
4587                                            whichColumn = new int[numberColumns];
4588                                            knapsackStart = new int[numberRows+1];
4589                                            knapsackRow = new int[numberRows];
4590                                            numberKnapsack = 10000;
4591                                            int extra1 = parameters_[whichParam(CBC_PARAM_INT_EXTRA1, numberParameters_, parameters_)].intValue();
4592                                            int extra2 = parameters_[whichParam(CBC_PARAM_INT_EXTRA2, numberParameters_, parameters_)].intValue();
4593                                            int logLevel = parameters_[log].intValue();
4594                                            OsiSolverInterface * solver = expandKnapsack(saveCoinModel, whichColumn, knapsackStart,
4595                                                                          knapsackRow, numberKnapsack,
4596                                                                          storedAmpl, logLevel, extra1, extra2,
4597                                                                          saveTightenedModel);
4598                                            if (solver) {
4599#ifndef CBC_OTHER_SOLVER
4600                                                clpSolver = dynamic_cast< OsiClpSolverInterface*> (solver);
4601                                                assert (clpSolver);
4602                                                lpSolver = clpSolver->getModelPtr();
4603#endif
4604                                                babModel_->assignSolver(solver);
4605                                                testOsiOptions = 0;
4606                                                // allow gomory
4607                                                complicatedInteger = 0;
4608#ifdef COIN_HAS_ASL
4609                                                // Priorities already done
4610                                                free(info.priorities);
4611                                                info.priorities = NULL;
4612#endif
4613                                            } else {
4614                                                numberKnapsack = 0;
4615                                                delete [] whichColumn;
4616                                                delete [] knapsackStart;
4617                                                delete [] knapsackRow;
4618                                                whichColumn = NULL;
4619                                                knapsackStart = NULL;
4620                                                knapsackRow = NULL;
4621                                            }
4622                                        }
4623                                    }
4624                                }
4625                            }
4626#endif
4627                            if (useCosts && testOsiOptions < 0) {
4628                                int numberColumns = babModel_->getNumCols();
4629                                int * sort = new int[numberColumns];
4630                                double * dsort = new double[numberColumns];
4631                                int * priority = new int [numberColumns];
4632                                const double * objective = babModel_->getObjCoefficients();
4633                                const double * lower = babModel_->getColLower() ;
4634                                const double * upper = babModel_->getColUpper() ;
4635                                const CoinPackedMatrix * matrix = babModel_->solver()->getMatrixByCol();
4636                                const int * columnLength = matrix->getVectorLengths();
4637                                int iColumn;
4638                                int n = 0;
4639                                for (iColumn = 0; iColumn < numberColumns; iColumn++) {
4640                                    if (babModel_->isInteger(iColumn)) {
4641                                        sort[n] = n;
4642                                        if (useCosts == 1)
4643                                            dsort[n++] = -fabs(objective[iColumn]);
4644                                        else if (useCosts == 2)
4645                                            dsort[n++] = iColumn;
4646                                        else if (useCosts == 3)
4647                                            dsort[n++] = upper[iColumn] - lower[iColumn];
4648                                        else if (useCosts == 4)
4649                                            dsort[n++] = -(upper[iColumn] - lower[iColumn]);
4650                                        else if (useCosts == 5)
4651                                            dsort[n++] = -columnLength[iColumn];
4652                                    }
4653                                }
4654                                CoinSort_2(dsort, dsort + n, sort);
4655                                int level = 0;
4656                                double last = -1.0e100;
4657                                for (int i = 0; i < n; i++) {
4658                                    int iPut = sort[i];
4659                                    if (dsort[i] != last) {
4660                                        level++;
4661                                        last = dsort[i];
4662                                    }
4663                                    priority[iPut] = level;
4664                                }
4665                                babModel_->passInPriorities( priority, false);
4666                                integersOK = true;
4667                                delete [] priority;
4668                                delete [] sort;
4669                                delete [] dsort;
4670                            }
4671                            // Set up heuristics
4672                            doHeuristics(&model_,((!miplib)?1:10),parameters_,
4673                                numberParameters_,noPrinting_,initialPumpTune);
4674                            if (!miplib) {
4675                                if (parameters_[whichParam(CBC_PARAM_STR_LOCALTREE, numberParameters_, parameters_)].currentOptionAsInteger()) {
4676                                    CbcTreeLocal localTree(babModel_, NULL, 10, 0, 0, 10000, 2000);
4677                                    babModel_->passInTreeHandler(localTree);
4678                                }
4679                            }
4680                            if (type == CBC_PARAM_ACTION_MIPLIB) {
4681                                if (babModel_->numberStrong() == 5 && babModel_->numberBeforeTrust() == 5)
4682                                    babModel_->setNumberBeforeTrust(10);
4683                            }
4684                            int experimentFlag = parameters_[whichParam(CBC_PARAM_INT_EXPERIMENT, numberParameters_,
4685                                                             parameters_)].intValue();
4686                            int strategyFlag = parameters_[whichParam(CBC_PARAM_INT_STRATEGY, numberParameters_,
4687                                                           parameters_)].intValue();
4688                            int bothFlags = CoinMax(CoinMin(experimentFlag, 1), strategyFlag);
4689                            // add cut generators if wanted
4690                            int switches[20];
4691                            int accuracyFlag[20];
4692                            int numberGenerators = 0;
4693                            int translate[] = { -100, -1, -99, -98, 1, -1098, -999, 1, 1, 1, -1};
4694                            if (probingAction) {
4695                                int numberColumns = babModel_->solver()->getNumCols();
4696                                if (probingAction > 7) {
4697                                    probingGen.setMaxElements(numberColumns);
4698                                    probingGen.setMaxElementsRoot(numberColumns);
4699                                }
4700                                probingGen.setMaxProbeRoot(CoinMin(2000, numberColumns));
4701                                probingGen.setMaxProbeRoot(123);
4702                                probingGen.setMaxProbe(123);
4703                                probingGen.setMaxLookRoot(20);
4704                                if (probingAction == 7 || probingAction == 9)
4705                                    probingGen.setRowCuts(-3); // strengthening etc just at root
4706                                if (probingAction == 8 || probingAction == 9) {
4707                                    // Number of unsatisfied variables to look at
4708                                    probingGen.setMaxProbeRoot(numberColumns);
4709                                    probingGen.setMaxProbe(numberColumns);
4710                                    // How far to follow the consequences
4711                                    probingGen.setMaxLook(50);
4712                                    probingGen.setMaxLookRoot(50);
4713                                }
4714                                if (probingAction == 10) {
4715                                    probingGen.setMaxPassRoot(2);
4716                                    probingGen.setMaxProbeRoot(numberColumns);
4717                                    probingGen.setMaxLookRoot(100);
4718                                }
4719                                // If 5 then force on
4720                                int iAction = translate[probingAction];
4721                                if (probingAction == 5)
4722                                    iAction = 1;
4723                                babModel_->addCutGenerator(&probingGen, iAction, "Probing");
4724                                accuracyFlag[numberGenerators] = 5;
4725                                switches[numberGenerators++] = 0;
4726                            }
4727                            if (gomoryAction && (complicatedInteger != 1 ||
4728                                                 (gomoryAction == 1 || gomoryAction >= 4))) {
4729                                // try larger limit
4730                                int numberColumns = babModel_->getNumCols();
4731                                if (gomoryAction == 7) {
4732                                    gomoryAction = 4;
4733                                    gomoryGen.setLimitAtRoot(numberColumns);
4734                                    gomoryGen.setLimit(numberColumns);
4735                                } else if (gomoryAction == 8) {
4736                                    gomoryAction = 3;
4737                                    gomoryGen.setLimitAtRoot(numberColumns);
4738                                    gomoryGen.setLimit(200);
4739                                } else if (numberColumns > 5000) {
4740                                    //#define MORE_CUTS2
4741#ifdef MORE_CUTS2
4742                                    // try larger limit
4743                                    gomoryGen.setLimitAtRoot(numberColumns);
4744                                    gomoryGen.setLimit(200);
4745#else
4746                                    gomoryGen.setLimitAtRoot(2000);
4747                                    //gomoryGen.setLimit(200);
4748#endif
4749                                } else {
4750#ifdef MORE_CUTS2
4751                                    // try larger limit
4752                                    gomoryGen.setLimitAtRoot(numberColumns);
4753                                    gomoryGen.setLimit(200);
4754#endif
4755                                }
4756                                int cutLength =
4757                                    parameters_[whichParam(CBC_PARAM_INT_CUTLENGTH, numberParameters_, parameters_)].intValue();
4758                                if (cutLength != -1) {
4759                                    gomoryGen.setLimitAtRoot(cutLength);
4760                                    if (cutLength < 10000000) {
4761                                        gomoryGen.setLimit(cutLength);
4762                                    } else {
4763                                        gomoryGen.setLimit(cutLength % 10000000);
4764                                    }
4765                                }
4766                                babModel_->addCutGenerator(&gomoryGen, translate[gomoryAction], "Gomory");
4767                                accuracyFlag[numberGenerators] = 3;
4768                                switches[numberGenerators++] = 0;
4769                            }
4770#ifdef CLIQUE_ANALYSIS
4771                            if (miplib && !storedAmpl.sizeRowCuts()) {
4772                                printf("looking at probing\n");
4773                                babModel_->addCutGenerator(&storedAmpl, 1, "Stored");
4774                            }
4775#endif
4776                            if (knapsackAction) {
4777                                babModel_->addCutGenerator(&knapsackGen, translate[knapsackAction], "Knapsack");
4778                                accuracyFlag[numberGenerators] = 1;
4779                                switches[numberGenerators++] = -2;
4780                            }
4781                            if (redsplitAction && !complicatedInteger) {
4782                                babModel_->addCutGenerator(&redsplitGen, translate[redsplitAction], "Reduce-and-split");
4783                                accuracyFlag[numberGenerators] = 5;
4784                                switches[numberGenerators++] = 1;
4785                            }
4786                            if (cliqueAction) {
4787                                babModel_->addCutGenerator(&cliqueGen, translate[cliqueAction], "Clique");
4788                                accuracyFlag[numberGenerators] = 0;
4789                                switches[numberGenerators++] = 0;
4790                            }
4791                            if (mixedAction) {
4792                                babModel_->addCutGenerator(&mixedGen, translate[mixedAction], "MixedIntegerRounding2");
4793                                accuracyFlag[numberGenerators] = 2;
4794                                switches[numberGenerators++] = 0;
4795                            }
4796                            if (flowAction) {
4797                                babModel_->addCutGenerator(&flowGen, translate[flowAction], "FlowCover");
4798                                accuracyFlag[numberGenerators] = 2;
4799                                switches[numberGenerators++] = 1;
4800                            }
4801                            if (twomirAction && (complicatedInteger != 1 ||
4802                                                 (twomirAction == 1 || twomirAction >= 4))) {
4803                                // try larger limit
4804                                int numberColumns = babModel_->getNumCols();
4805                                if (twomirAction == 7) {
4806                                    twomirAction = 4;
4807                                    twomirGen.setMaxElements(numberColumns);
4808                                } else if (numberColumns > 5000 && twomirAction == 4) {
4809                                    twomirGen.setMaxElements(2000);
4810                                }
4811                                babModel_->addCutGenerator(&twomirGen, translate[twomirAction], "TwoMirCuts");
4812                                accuracyFlag[numberGenerators] = 4;
4813                                switches[numberGenerators++] = 1;
4814                            }
4815#ifndef DEBUG_MALLOC
4816                            if (landpAction) {
4817                                babModel_->addCutGenerator(&landpGen, translate[</