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

Last change on this file since 1499 was 1499, checked in by forrest, 9 years ago

a few more rens heuristics

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