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

Last change on this file since 1394 was 1394, checked in by bjarni, 10 years ago

Moving global variables CbcOrClpRead_mode, CbcOrClpReadCommand?, CbcOrClpEnvironmentIndex?, and noPrinting below static routines analyze(), expandKnapsack(), and checkSOS(), and add noPrinting as an argument to analyze()

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