source: trunk/Cbc/src/CbcSolver.cpp @ 1433

Last change on this file since 1433 was 1433, checked in by tkr, 10 years ago

Changing version string to 2.5devel

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