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

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

Add comments for callCbc, callCbc1 shells.

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