/* $Id: CbcSolver.cpp 2417 2018-11-14 12:19:56Z forrest $ */
// Copyright (C) 2007, International Business Machines
// Corporation and others.  All Rights Reserved.
// This code is licensed under the terms of the Eclipse Public License (EPL).

/*! \file CbcSolver.cpp
    \brief Second level routines for the cbc stand-alone solver.
*/

#include "CbcConfig.h"
#include "CoinPragma.hpp"

#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cfloat>
#include <cstring>
#include <iostream>

#include "CoinPragma.hpp"
#include "CoinHelperFunctions.hpp"

#include "CoinMpsIO.hpp"
#include "CoinModel.hpp"

#include "ClpFactorization.hpp"
#include "ClpQuadraticObjective.hpp"
#include "CoinTime.hpp"
#include "ClpSimplex.hpp"
#include "ClpSimplexOther.hpp"
#include "ClpSolve.hpp"
#include "ClpMessage.hpp"
#include "ClpPackedMatrix.hpp"
#include "ClpPlusMinusOneMatrix.hpp"
#include "ClpNetworkMatrix.hpp"
#include "ClpDualRowSteepest.hpp"
#include "ClpDualRowDantzig.hpp"
#include "ClpLinearObjective.hpp"
#include "ClpPrimalColumnSteepest.hpp"
#include "ClpPrimalColumnDantzig.hpp"

#include "ClpPresolve.hpp"
#ifndef COIN_HAS_CBC
#define COIN_HAS_CBC
#endif
#include "CbcOrClpParam.hpp"
#include "OsiRowCutDebugger.hpp"
#include "OsiChooseVariable.hpp"
#include "OsiAuxInfo.hpp"
#include "CbcMipStartIO.hpp"
// for printing
#ifndef CLP_OUTPUT_FORMAT
#define CLP_OUTPUT_FORMAT %15.8g
#endif
#define CLP_QUOTE(s) CLP_STRING(s)
#define CLP_STRING(s) #s

#include "CbcSolverHeuristics.hpp"
#ifdef COIN_HAS_GLPK
#include "glpk.h"
extern glp_tran* cbc_glp_tran;
extern glp_prob* cbc_glp_prob;
#else
#define GLP_UNDEF 1
#define GLP_FEAS 2
#define GLP_INFEAS 3
#define GLP_NOFEAS 4
#define GLP_OPT 5
#endif

#ifndef CBC_QUIET
#define CBC_QUIET 0
#endif

//#define USER_HAS_FAKE_CLP
//#define USER_HAS_FAKE_CBC

//#define CLP_MALLOC_STATISTICS

#ifdef CLP_MALLOC_STATISTICS
#include <malloc.h>
#include <exception>
#include <new>
#include "stolen_from_ekk_malloc.cpp"
static double malloc_times = 0.0;
static double malloc_total = 0.0;
static int malloc_amount[] = {0, 32, 128, 256, 1024, 4096, 16384, 65536, 262144, INT_MAX};
static int malloc_n = 10;
double malloc_counts[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
bool malloc_counts_on = true;
void * operator new (size_t size) throw (std::bad_alloc)
{
    malloc_times ++;
    malloc_total += size;
    int i;
    for (i = 0; i < malloc_n; i++) {
        if ((int) size <= malloc_amount[i]) {
            malloc_counts[i]++;
            break;
        }
    }
# ifdef DEBUG_MALLOC
    void *p;
    if (malloc_counts_on)
        p = stolen_from_ekk_mallocBase(size);
    else
        p = malloc(size);
# else
    void * p = malloc(size);
# endif
    //char * xx = (char *) p;
    //memset(xx,0,size);
    // Initialize random seed
    //CoinSeedRandom(987654321);
    return p;
}
void operator delete (void *p) throw()
{
# ifdef DEBUG_MALLOC
    if (malloc_counts_on)
        stolen_from_ekk_freeBase(p);
    else
        free(p);
# else
    free(p);
# endif
}
static void malloc_stats2()
{
    double average = malloc_total / malloc_times;
    printf("count %g bytes %g - average %g\n", malloc_times, malloc_total, average);
    for (int i = 0; i < malloc_n; i++)
        printf("%g ", malloc_counts[i]);
    printf("\n");
    malloc_times = 0.0;
    malloc_total = 0.0;
    memset(malloc_counts, 0, sizeof(malloc_counts));
    // print results
}
#else	//CLP_MALLOC_STATISTICS
//void stolen_from_ekk_memory(void * dummy,int type)
//{
//}
//bool malloc_counts_on=false;
#endif	//CLP_MALLOC_STATISTICS

//#define DMALLOC
#ifdef DMALLOC
#include "dmalloc.h"
#endif

#ifdef WSSMP_BARRIER
#define FOREIGN_BARRIER
#endif

#ifdef UFL_BARRIER
#define FOREIGN_BARRIER
#endif

#ifdef TAUCS_BARRIER
#define FOREIGN_BARRIER
#endif

static int initialPumpTune = -1;
#include "CoinWarmStartBasis.hpp"

#include "OsiSolverInterface.hpp"
#include "OsiCuts.hpp"
#include "OsiRowCut.hpp"
#include "OsiColCut.hpp"

#ifndef COIN_HAS_LINK
#define COIN_HAS_LINK
#endif
#ifdef COIN_HAS_LINK
#include "CbcLinked.hpp"
#endif

#include "CglPreProcess.hpp"
#include "CglCutGenerator.hpp"
#include "CglGomory.hpp"
#include "CglProbing.hpp"
#include "CglKnapsackCover.hpp"
#include "CglRedSplit.hpp"
#include "CglRedSplit2.hpp"
#include "CglGMI.hpp"
#include "CglClique.hpp"
#include "CglFlowCover.hpp"
#include "CglMixedIntegerRounding2.hpp"
#include "CglTwomir.hpp"
#include "CglDuplicateRow.hpp"
#include "CglStored.hpp"
#include "CglLandP.hpp"
#include "CglResidualCapacity.hpp"
#include "CglZeroHalf.hpp"
//#define CGL_WRITEMPS 
#ifdef CGL_WRITEMPS
extern double * debugSolution;
extern int debugNumberColumns;
#endif
#include "CbcModel.hpp"
#include "CbcHeuristic.hpp"
#include "CbcHeuristicLocal.hpp"
#include "CbcHeuristicPivotAndFix.hpp"
//#include "CbcHeuristicPivotAndComplement.hpp"
#include "CbcHeuristicRandRound.hpp"
#include "CbcHeuristicGreedy.hpp"
#include "CbcHeuristicFPump.hpp"
#include "CbcHeuristicRINS.hpp"
#include "CbcHeuristicDiveCoefficient.hpp"
#include "CbcHeuristicDiveFractional.hpp"
#include "CbcHeuristicDiveGuided.hpp"
#include "CbcHeuristicDiveVectorLength.hpp"
#include "CbcHeuristicDivePseudoCost.hpp"
#include "CbcHeuristicDiveLineSearch.hpp"
#include "CbcTreeLocal.hpp"
#include "CbcCompareActual.hpp"
#include "CbcBranchActual.hpp"
#include "CbcBranchLotsize.hpp"
#include  "CbcOrClpParam.hpp"
#include  "CbcCutGenerator.hpp"
#include  "CbcStrategy.hpp"
#include "CbcBranchCut.hpp"

#include "OsiClpSolverInterface.hpp"

#include "CbcSolverAnalyze.hpp"
#include "CbcSolverExpandKnapsack.hpp"

#include "CbcSolver.hpp"

//#define IN_BRANCH_AND_BOUND (0x01000000|262144)
#define IN_BRANCH_AND_BOUND (0x01000000|262144|128|1024|2048)
//#define IN_BRANCH_AND_BOUND (0x01000000|262144|128)

/*
  CbcStopNow class definitions.
*/

CbcStopNow::CbcStopNow()
{
}
CbcStopNow::~CbcStopNow()
{
}
// Copy constructor
CbcStopNow::CbcStopNow ( const CbcStopNow & )
{
}
// Assignment operator
CbcStopNow &
CbcStopNow::operator=(const CbcStopNow & rhs)
{
    if (this != &rhs) {
    }
    return *this;
}
// Clone
CbcStopNow *
CbcStopNow::clone() const
{
    return new CbcStopNow(*this);
}

/*
  CbcUser class definitions.
*/

// User stuff (base class)
CbcUser::CbcUser()
        : coinModel_(NULL),
        userName_("null")
{
}
CbcUser::~CbcUser()
{
    delete coinModel_;
}
// Copy constructor
CbcUser::CbcUser ( const CbcUser & rhs)
{
    if (rhs.coinModel_)
        coinModel_ = new CoinModel(*rhs.coinModel_);
    else
        coinModel_ = NULL;
    userName_ = rhs.userName_;
}
// Assignment operator
CbcUser &
CbcUser::operator=(const CbcUser & rhs)
{
    if (this != &rhs) {
        if (rhs.coinModel_)
            coinModel_ = new CoinModel(*rhs.coinModel_);
        else
            coinModel_ = NULL;
        userName_ = rhs.userName_;
    }
    return *this;
}

static void putBackOtherSolutions(CbcModel * presolvedModel, CbcModel * model,
			   CglPreProcess * preProcess)
{
  int numberSolutions=presolvedModel->numberSavedSolutions();
  int numberColumns=presolvedModel->getNumCols();
  if (numberSolutions>1) {
    model->deleteSolutions();
    double * bestSolution = CoinCopyOfArray(presolvedModel->bestSolution(),numberColumns);
    //double cutoff = presolvedModel->getCutoff();
    double objectiveValue=presolvedModel->getObjValue();
    //model->createSpaceForSavedSolutions(numberSolutions-1);
    for (int iSolution=numberSolutions-1;iSolution>=0;iSolution--) {
      presolvedModel->setCutoff(COIN_DBL_MAX);
      presolvedModel->solver()->setColSolution(presolvedModel->savedSolution(iSolution));
      //presolvedModel->savedSolutionObjective(iSolution));
      preProcess->postProcess(*presolvedModel->solver(),false);
      model->setBestSolution(preProcess->originalModel()->getColSolution(),model->solver()->getNumCols(),
			     presolvedModel->savedSolutionObjective(iSolution));
    }
    presolvedModel->setBestObjectiveValue(objectiveValue);
    presolvedModel->solver()->setColSolution(bestSolution);
    //presolvedModel->setBestSolution(bestSolution,numberColumns,objectiveValue);
    delete [] bestSolution;
  }
}

/*
  CbcSolver class definitions
*/

CbcSolver::CbcSolver()
        : babModel_(NULL),
        userFunction_(NULL),
        statusUserFunction_(NULL),
        originalSolver_(NULL),
        originalCoinModel_(NULL),
        cutGenerator_(NULL),
        numberUserFunctions_(0),
        numberCutGenerators_(0),
        startTime_(CoinCpuTime()),
        parameters_(NULL),
        numberParameters_(0),
        doMiplib_(false),
        noPrinting_(false),
        readMode_(1)
{
    callBack_ = new CbcStopNow();
    fillParameters();
}
CbcSolver::CbcSolver(const OsiClpSolverInterface & solver)
        : babModel_(NULL),
        userFunction_(NULL),
        statusUserFunction_(NULL),
        originalSolver_(NULL),
        originalCoinModel_(NULL),
        cutGenerator_(NULL),
        numberUserFunctions_(0),
        numberCutGenerators_(0),
        startTime_(CoinCpuTime()),
        parameters_(NULL),
        numberParameters_(0),
        doMiplib_(false),
        noPrinting_(false),
        readMode_(1)
{
    callBack_ = new CbcStopNow();
    model_ = CbcModel(solver);
    fillParameters();
}
CbcSolver::CbcSolver(const CbcModel & solver)
        : babModel_(NULL),
        userFunction_(NULL),
        statusUserFunction_(NULL),
        originalSolver_(NULL),
        originalCoinModel_(NULL),
        cutGenerator_(NULL),
        numberUserFunctions_(0),
        numberCutGenerators_(0),
        startTime_(CoinCpuTime()),
        parameters_(NULL),
        numberParameters_(0),
        doMiplib_(false),
        noPrinting_(false),
        readMode_(1)
{
    callBack_ = new CbcStopNow();
    model_ = solver;
    fillParameters();
}
CbcSolver::~CbcSolver()
{
    int i;
    for (i = 0; i < numberUserFunctions_; i++)
        delete userFunction_[i];
    delete [] userFunction_;
    for (i = 0; i < numberCutGenerators_; i++)
        delete cutGenerator_[i];
    delete [] cutGenerator_;
    delete [] statusUserFunction_;
    delete originalSolver_;
    delete originalCoinModel_;
    delete babModel_;
    delete [] parameters_;
    delete callBack_;
}
// Copy constructor
CbcSolver::CbcSolver ( const CbcSolver & rhs)
        : model_(rhs.model_),
        babModel_(NULL),
        userFunction_(NULL),
        statusUserFunction_(NULL),
        numberUserFunctions_(rhs.numberUserFunctions_),
        startTime_(CoinCpuTime()),
        parameters_(NULL),
        numberParameters_(rhs.numberParameters_),
        doMiplib_(rhs.doMiplib_),
        noPrinting_(rhs.noPrinting_),
        readMode_(rhs.readMode_)
{
    fillParameters();
    if (rhs.babModel_)
        babModel_ = new CbcModel(*rhs.babModel_);
    userFunction_ = new CbcUser * [numberUserFunctions_];
    int i;
    for (i = 0; i < numberUserFunctions_; i++)
        userFunction_[i] = rhs.userFunction_[i]->clone();
    for (i = 0; i < numberParameters_; i++)
        parameters_[i] = rhs.parameters_[i];
    for (i = 0; i < numberCutGenerators_; i++)
        cutGenerator_[i] = rhs.cutGenerator_[i]->clone();
    callBack_ = rhs.callBack_->clone();
    originalSolver_ = NULL;
    if (rhs.originalSolver_) {
        OsiSolverInterface * temp = rhs.originalSolver_->clone();
        originalSolver_ = dynamic_cast<OsiClpSolverInterface *> (temp);
        assert (originalSolver_);
    }
    originalCoinModel_ = NULL;
    if (rhs.originalCoinModel_)
        originalCoinModel_ = new CoinModel(*rhs.originalCoinModel_);
}
// Assignment operator
CbcSolver &
CbcSolver::operator=(const CbcSolver & rhs)
{
    if (this != &rhs) {
        int i;
        for (i = 0; i < numberUserFunctions_; i++)
            delete userFunction_[i];
        delete [] userFunction_;
        for (i = 0; i < numberCutGenerators_; i++)
            delete cutGenerator_[i];
        delete [] statusUserFunction_;
        delete originalSolver_;
        delete originalCoinModel_;
        statusUserFunction_ = NULL;
        delete babModel_;
        delete callBack_;
        numberUserFunctions_ = rhs.numberUserFunctions_;
        startTime_ = rhs.startTime_;
        numberParameters_ = rhs.numberParameters_;
        for (i = 0; i < numberParameters_; i++)
            parameters_[i] = rhs.parameters_[i];
        for (i = 0; i < numberCutGenerators_; i++)
            cutGenerator_[i] = rhs.cutGenerator_[i]->clone();
        noPrinting_ = rhs.noPrinting_;
        readMode_ = rhs.readMode_;
        doMiplib_ = rhs.doMiplib_;
        model_ = rhs.model_;
        if (rhs.babModel_)
            babModel_ = new CbcModel(*rhs.babModel_);
        else
            babModel_ = NULL;
        userFunction_ = new CbcUser * [numberUserFunctions_];
        for (i = 0; i < numberUserFunctions_; i++)
            userFunction_[i] = rhs.userFunction_[i]->clone();
        callBack_ = rhs.callBack_->clone();
        originalSolver_ = NULL;
        if (rhs.originalSolver_) {
            OsiSolverInterface * temp = rhs.originalSolver_->clone();
            originalSolver_ = dynamic_cast<OsiClpSolverInterface *> (temp);
            assert (originalSolver_);
        }
        originalCoinModel_ = NULL;
        if (rhs.originalCoinModel_)
            originalCoinModel_ = new CoinModel(*rhs.originalCoinModel_);
    }
    return *this;
}
// Get int value
int CbcSolver::intValue(CbcOrClpParameterType type) const
{
    return parameters_[whichParam(type, numberParameters_, parameters_)].intValue();
}
// Set int value
void CbcSolver::setIntValue(CbcOrClpParameterType type, int value)
{
    parameters_[whichParam(type, numberParameters_, parameters_)].setIntValue(value);
}
// Get double value
double CbcSolver::doubleValue(CbcOrClpParameterType type) const
{
    return parameters_[whichParam(type, numberParameters_, parameters_)].doubleValue();
}
// Set double value
void CbcSolver::setDoubleValue(CbcOrClpParameterType type, double value)
{
    parameters_[whichParam(type, numberParameters_, parameters_)].setDoubleValue(value);
}
// User function (NULL if no match)
CbcUser * CbcSolver::userFunction(const char * name) const
{
    int i;
    for (i = 0; i < numberUserFunctions_; i++) {
        if (!strcmp(name, userFunction_[i]->name().c_str()))
            break;
    }
    if (i < numberUserFunctions_)
        return userFunction_[i];
    else
        return NULL;
}
void CbcSolver::fillParameters()
{
    int maxParam = 200;
    CbcOrClpParam * parameters = new CbcOrClpParam [maxParam];
    numberParameters_ = 0 ;
    establishParams(numberParameters_, parameters) ;
    assert (numberParameters_ <= maxParam);
    parameters_ = new CbcOrClpParam [numberParameters_];
    int i;
    for (i = 0; i < numberParameters_; i++)
        parameters_[i] = parameters[i];
    delete [] parameters;
    const char dirsep =  CoinFindDirSeparator();
    std::string directory;
    std::string dirSample;
    std::string dirNetlib;
    std::string dirMiplib;
    if (dirsep == '/') {
        directory = "./";
        dirSample = "../../Data/Sample/";
        dirNetlib = "../../Data/Netlib/";
        dirMiplib = "../../Data/miplib3/";
    } else {
        directory = ".\\";
        dirSample = "..\\..\\..\\..\\Data\\Sample\\";
        dirNetlib = "..\\..\\..\\..\\Data\\Netlib\\";
        dirMiplib = "..\\..\\..\\..\\Data\\miplib3\\";
    }
    std::string defaultDirectory = directory;
    std::string importFile = "";
    std::string exportFile = "default.mps";
    std::string importBasisFile = "";
    std::string importPriorityFile = "";
    std::string mipStartFile = "";
    std::string debugFile = "";
    std::string printMask = "";
    std::string exportBasisFile = "default.bas";
    std::string saveFile = "default.prob";
    std::string restoreFile = "default.prob";
    std::string solutionFile = "stdout";
    std::string solutionSaveFile = "solution.file";
    int doIdiot = -1;
    int outputFormat = 2;
    int substitution = 3;
    int dualize = 3;
    int preSolve = 5;
    int doSprint = -1;
    int testOsiParameters = -1;
    int createSolver = 0;
    ClpSimplex * lpSolver;
    OsiClpSolverInterface * clpSolver;
    if (model_.solver()) {
        clpSolver = dynamic_cast<OsiClpSolverInterface *> (model_.solver());
        assert (clpSolver);
        lpSolver = clpSolver->getModelPtr();
        assert (lpSolver);
    } else {
        lpSolver = new ClpSimplex();
        clpSolver = new OsiClpSolverInterface(lpSolver, true);
        createSolver = 1 ;
    }
    parameters_[whichParam(CLP_PARAM_ACTION_BASISIN, numberParameters_, parameters_)].setStringValue(importBasisFile);
    parameters_[whichParam(CBC_PARAM_ACTION_PRIORITYIN, numberParameters_, parameters_)].setStringValue(importPriorityFile);
    parameters_[whichParam(CBC_PARAM_ACTION_MIPSTART, numberParameters_, parameters_)].setStringValue(mipStartFile);
    parameters_[whichParam(CLP_PARAM_ACTION_BASISOUT, numberParameters_, parameters_)].setStringValue(exportBasisFile);
    parameters_[whichParam(CLP_PARAM_ACTION_DEBUG, numberParameters_, parameters_)].setStringValue(debugFile);
    parameters_[whichParam(CLP_PARAM_ACTION_PRINTMASK, numberParameters_, parameters_)].setStringValue(printMask);
    parameters_[whichParam(CLP_PARAM_ACTION_DIRECTORY, numberParameters_, parameters_)].setStringValue(directory);
    parameters_[whichParam(CLP_PARAM_ACTION_DIRSAMPLE, numberParameters_, parameters_)].setStringValue(dirSample);
    parameters_[whichParam(CLP_PARAM_ACTION_DIRNETLIB, numberParameters_, parameters_)].setStringValue(dirNetlib);
    parameters_[whichParam(CBC_PARAM_ACTION_DIRMIPLIB, numberParameters_, parameters_)].setStringValue(dirMiplib);
    parameters_[whichParam(CLP_PARAM_DBL_DUALBOUND, numberParameters_, parameters_)].setDoubleValue(lpSolver->dualBound());
    parameters_[whichParam(CLP_PARAM_DBL_DUALTOLERANCE, numberParameters_, parameters_)].setDoubleValue(lpSolver->dualTolerance());
    parameters_[whichParam(CLP_PARAM_ACTION_EXPORT, numberParameters_, parameters_)].setStringValue(exportFile);
    parameters_[whichParam(CLP_PARAM_INT_IDIOT, numberParameters_, parameters_)].setIntValue(doIdiot);
    parameters_[whichParam(CLP_PARAM_ACTION_IMPORT, numberParameters_, parameters_)].setStringValue(importFile);
    parameters_[whichParam(CLP_PARAM_DBL_PRESOLVETOLERANCE, numberParameters_, parameters_)].setDoubleValue(1.0e-8);
    int iParam = whichParam(CLP_PARAM_INT_SOLVERLOGLEVEL, numberParameters_, parameters_);
    int value = 1;
    clpSolver->messageHandler()->setLogLevel(1) ;
    lpSolver->setLogLevel(1);
    parameters_[iParam].setIntValue(value);
    iParam = whichParam(CLP_PARAM_INT_LOGLEVEL, numberParameters_, parameters_);
    model_.messageHandler()->setLogLevel(value);
    parameters_[iParam].setIntValue(value);
    parameters_[whichParam(CLP_PARAM_INT_MAXFACTOR, numberParameters_, parameters_)].setIntValue(lpSolver->factorizationFrequency());
    parameters_[whichParam(CLP_PARAM_INT_MAXITERATION, numberParameters_, parameters_)].setIntValue(lpSolver->maximumIterations());
    parameters_[whichParam(CLP_PARAM_INT_OUTPUTFORMAT, numberParameters_, parameters_)].setIntValue(outputFormat);
    parameters_[whichParam(CLP_PARAM_INT_PRESOLVEPASS, numberParameters_, parameters_)].setIntValue(preSolve);
    parameters_[whichParam(CLP_PARAM_INT_PERTVALUE, numberParameters_, parameters_)].setIntValue(lpSolver->perturbation());
    parameters_[whichParam(CLP_PARAM_DBL_PRIMALTOLERANCE, numberParameters_, parameters_)].setDoubleValue(lpSolver->primalTolerance());
    parameters_[whichParam(CLP_PARAM_DBL_PRIMALWEIGHT, numberParameters_, parameters_)].setDoubleValue(lpSolver->infeasibilityCost());
    parameters_[whichParam(CLP_PARAM_ACTION_RESTORE, numberParameters_, parameters_)].setStringValue(restoreFile);
    parameters_[whichParam(CLP_PARAM_ACTION_SAVE, numberParameters_, parameters_)].setStringValue(saveFile);
    //parameters_[whichParam(CLP_PARAM_DBL_TIMELIMIT,numberParameters_,parameters_)].setDoubleValue(1.0e8);
    parameters_[whichParam(CBC_PARAM_DBL_TIMELIMIT_BAB, numberParameters_, parameters_)].setDoubleValue(1.0e8);
    parameters_[whichParam(CLP_PARAM_ACTION_SOLUTION, numberParameters_, parameters_)].setStringValue(solutionFile);
    parameters_[whichParam(CLP_PARAM_ACTION_NEXTBESTSOLUTION, numberParameters_, parameters_)].setStringValue(solutionFile);
    parameters_[whichParam(CLP_PARAM_ACTION_SAVESOL, numberParameters_, parameters_)].setStringValue(solutionSaveFile);
    parameters_[whichParam(CLP_PARAM_INT_SPRINT, numberParameters_, parameters_)].setIntValue(doSprint);
    parameters_[whichParam(CLP_PARAM_INT_SUBSTITUTION, numberParameters_, parameters_)].setIntValue(substitution);
    parameters_[whichParam(CLP_PARAM_INT_DUALIZE, numberParameters_, parameters_)].setIntValue(dualize);
    parameters_[whichParam(CBC_PARAM_INT_NUMBERBEFORE, numberParameters_, parameters_)].setIntValue(model_.numberBeforeTrust());
    parameters_[whichParam(CBC_PARAM_INT_MAXNODES, numberParameters_, parameters_)].setIntValue(model_.getMaximumNodes());
    parameters_[whichParam(CBC_PARAM_INT_STRONGBRANCHING, numberParameters_, parameters_)].setIntValue(model_.numberStrong());
    parameters_[whichParam(CBC_PARAM_DBL_INFEASIBILITYWEIGHT, numberParameters_, parameters_)].setDoubleValue(model_.getDblParam(CbcModel::CbcInfeasibilityWeight));
    parameters_[whichParam(CBC_PARAM_DBL_INTEGERTOLERANCE, numberParameters_, parameters_)].setDoubleValue(model_.getDblParam(CbcModel::CbcIntegerTolerance));
    parameters_[whichParam(CBC_PARAM_DBL_INCREMENT, numberParameters_, parameters_)].setDoubleValue(model_.getDblParam(CbcModel::CbcCutoffIncrement));
    parameters_[whichParam(CBC_PARAM_INT_TESTOSI, numberParameters_, parameters_)].setIntValue(testOsiParameters);
    parameters_[whichParam(CBC_PARAM_INT_FPUMPTUNE, numberParameters_, parameters_)].setIntValue(1003);
    initialPumpTune = 1003;
#ifdef CBC_THREAD
    parameters_[whichParam(CBC_PARAM_INT_THREADS, numberParameters_, parameters_)].setIntValue(0);
#endif
    // Set up likely cut generators and defaults
    parameters_[whichParam(CBC_PARAM_STR_PREPROCESS, numberParameters_, parameters_)].setCurrentOption("sos");
    parameters_[whichParam(CBC_PARAM_INT_MIPOPTIONS, numberParameters_, parameters_)].setIntValue(1057);
    parameters_[whichParam(CBC_PARAM_INT_CUTPASSINTREE, numberParameters_, parameters_)].setIntValue(1);
    parameters_[whichParam(CBC_PARAM_INT_MOREMIPOPTIONS, numberParameters_, parameters_)].setIntValue(-1);
    parameters_[whichParam(CBC_PARAM_INT_MAXHOTITS, numberParameters_, parameters_)].setIntValue(100);
    parameters_[whichParam(CBC_PARAM_STR_CUTSSTRATEGY, numberParameters_, parameters_)].setCurrentOption("on");
    parameters_[whichParam(CBC_PARAM_STR_HEURISTICSTRATEGY, numberParameters_, parameters_)].setCurrentOption("on");
    parameters_[whichParam(CBC_PARAM_STR_NODESTRATEGY, numberParameters_, parameters_)].setCurrentOption("fewest");
    parameters_[whichParam(CBC_PARAM_STR_GOMORYCUTS, numberParameters_, parameters_)].setCurrentOption("ifmove");
    parameters_[whichParam(CBC_PARAM_STR_PROBINGCUTS, numberParameters_, parameters_)].setCurrentOption("ifmove");
    parameters_[whichParam(CBC_PARAM_STR_KNAPSACKCUTS, numberParameters_, parameters_)].setCurrentOption("ifmove");
    parameters_[whichParam(CBC_PARAM_STR_ZEROHALFCUTS, numberParameters_, parameters_)].setCurrentOption("off");
    parameters_[whichParam(CBC_PARAM_STR_REDSPLITCUTS, numberParameters_, parameters_)].setCurrentOption("off");
    parameters_[whichParam(CBC_PARAM_STR_REDSPLIT2CUTS, numberParameters_, parameters_)].setCurrentOption("off");
    parameters_[whichParam(CBC_PARAM_STR_GMICUTS, numberParameters_, parameters_)].setCurrentOption("off");
    parameters_[whichParam(CBC_PARAM_STR_CLIQUECUTS, numberParameters_, parameters_)].setCurrentOption("ifmove");
    parameters_[whichParam(CBC_PARAM_STR_MIXEDCUTS, numberParameters_, parameters_)].setCurrentOption("ifmove");
    parameters_[whichParam(CBC_PARAM_STR_FLOWCUTS, numberParameters_, parameters_)].setCurrentOption("ifmove");
    parameters_[whichParam(CBC_PARAM_STR_TWOMIRCUTS, numberParameters_, parameters_)].setCurrentOption("ifmove");
    parameters_[whichParam(CBC_PARAM_STR_LANDPCUTS, numberParameters_, parameters_)].setCurrentOption("off");
    parameters_[whichParam(CBC_PARAM_STR_RESIDCUTS, numberParameters_, parameters_)].setCurrentOption("off");
    parameters_[whichParam(CBC_PARAM_STR_ROUNDING, numberParameters_, parameters_)].setCurrentOption("on");
    parameters_[whichParam(CBC_PARAM_STR_FPUMP, numberParameters_, parameters_)].setCurrentOption("on");
    parameters_[whichParam(CBC_PARAM_STR_GREEDY, numberParameters_, parameters_)].setCurrentOption("on");
    parameters_[whichParam(CBC_PARAM_STR_COMBINE, numberParameters_, parameters_)].setCurrentOption("on");
    parameters_[whichParam(CBC_PARAM_STR_CROSSOVER2, numberParameters_, parameters_)].setCurrentOption("off");
    parameters_[whichParam(CBC_PARAM_STR_PIVOTANDCOMPLEMENT, numberParameters_, parameters_)].setCurrentOption("off");
    parameters_[whichParam(CBC_PARAM_STR_PIVOTANDFIX, numberParameters_, parameters_)].setCurrentOption("off");
    parameters_[whichParam(CBC_PARAM_STR_RANDROUND, numberParameters_, parameters_)].setCurrentOption("off");
    parameters_[whichParam(CBC_PARAM_STR_NAIVE, numberParameters_, parameters_)].setCurrentOption("off");
    parameters_[whichParam(CBC_PARAM_STR_RINS, numberParameters_, parameters_)].setCurrentOption("off");
    parameters_[whichParam(CBC_PARAM_STR_DINS, numberParameters_, parameters_)].setCurrentOption("off");
    parameters_[whichParam(CBC_PARAM_STR_RENS, numberParameters_, parameters_)].setCurrentOption("off");
    parameters_[whichParam(CBC_PARAM_STR_LOCALTREE, numberParameters_, parameters_)].setCurrentOption("off");
    parameters_[whichParam(CBC_PARAM_STR_COSTSTRATEGY, numberParameters_, parameters_)].setCurrentOption("off");
    if (createSolver)
        delete clpSolver;
}

/*
  Initialise a subset of the parameters prior to processing any input from
  the user.

  Why this choice of subset?
*/
/*!
  \todo Guard/replace clp-specific code
*/
void CbcSolver::fillValuesInSolver()
{
    OsiSolverInterface * solver = model_.solver();
    OsiClpSolverInterface * clpSolver =
        dynamic_cast< OsiClpSolverInterface*> (solver);
    assert (clpSolver);
    ClpSimplex * lpSolver = clpSolver->getModelPtr();

    /*
      Why are we reaching into the underlying solver(s) for these settings?
      Shouldn't CbcSolver have its own defaults, which are then imposed on the
      underlying solver?

      Coming at if from the other side, if CbcSolver had the capability to use
      multiple solvers then it definitely makes sense to acquire the defaults from
      the solver (on the assumption that we haven't processed command line
      parameters yet, which can then override the defaults). But then it's more of
      a challenge to avoid solver-specific coding here.
    */
    noPrinting_ = (lpSolver->logLevel() == 0);
    CoinMessageHandler * generalMessageHandler = clpSolver->messageHandler();
    generalMessageHandler->setPrefix(true);

    lpSolver->setPerturbation(50);
    lpSolver->messageHandler()->setPrefix(false);

    parameters_[whichParam(CLP_PARAM_DBL_DUALBOUND, numberParameters_, parameters_)].setDoubleValue(lpSolver->dualBound());
    parameters_[whichParam(CLP_PARAM_DBL_DUALTOLERANCE, numberParameters_, parameters_)].setDoubleValue(lpSolver->dualTolerance());
    /*
      Why are we doing this? We read the log level from parameters_, set it into
      the message handlers for cbc and the underlying solver. Then we read the
      log level back from the handlers and use it to set the values in
      parameters_!
    */
    int iParam = whichParam(CLP_PARAM_INT_SOLVERLOGLEVEL, numberParameters_, parameters_);
    int value = parameters_[iParam].intValue();
    clpSolver->messageHandler()->setLogLevel(value) ;
    lpSolver->setLogLevel(value);
    iParam = whichParam(CLP_PARAM_INT_LOGLEVEL, numberParameters_, parameters_);
    value = parameters_[iParam].intValue();
    model_.messageHandler()->setLogLevel(value);
    parameters_[whichParam(CLP_PARAM_INT_LOGLEVEL, numberParameters_, parameters_)].setIntValue(model_.logLevel());
    parameters_[whichParam(CLP_PARAM_INT_SOLVERLOGLEVEL, numberParameters_, parameters_)].setIntValue(lpSolver->logLevel());
    parameters_[whichParam(CLP_PARAM_INT_MAXFACTOR, numberParameters_, parameters_)].setIntValue(lpSolver->factorizationFrequency());
    parameters_[whichParam(CLP_PARAM_INT_MAXITERATION, numberParameters_, parameters_)].setIntValue(lpSolver->maximumIterations());
    parameters_[whichParam(CLP_PARAM_INT_PERTVALUE, numberParameters_, parameters_)].setIntValue(lpSolver->perturbation());
    parameters_[whichParam(CLP_PARAM_DBL_PRIMALTOLERANCE, numberParameters_, parameters_)].setDoubleValue(lpSolver->primalTolerance());
    parameters_[whichParam(CLP_PARAM_DBL_PRIMALWEIGHT, numberParameters_, parameters_)].setDoubleValue(lpSolver->infeasibilityCost());
    parameters_[whichParam(CBC_PARAM_INT_NUMBERBEFORE, numberParameters_, parameters_)].setIntValue(model_.numberBeforeTrust());
    parameters_[whichParam(CBC_PARAM_INT_MAXNODES, numberParameters_, parameters_)].setIntValue(model_.getMaximumNodes());
    parameters_[whichParam(CBC_PARAM_INT_STRONGBRANCHING, numberParameters_, parameters_)].setIntValue(model_.numberStrong());
    parameters_[whichParam(CBC_PARAM_DBL_INFEASIBILITYWEIGHT, numberParameters_, parameters_)].setDoubleValue(model_.getDblParam(CbcModel::CbcInfeasibilityWeight));
    parameters_[whichParam(CBC_PARAM_DBL_INTEGERTOLERANCE, numberParameters_, parameters_)].setDoubleValue(model_.getDblParam(CbcModel::CbcIntegerTolerance));
    parameters_[whichParam(CBC_PARAM_DBL_INCREMENT, numberParameters_, parameters_)].setDoubleValue(model_.getDblParam(CbcModel::CbcCutoffIncrement));
}
// Add user function
void
CbcSolver::addUserFunction(CbcUser * function)
{
    CbcUser ** temp = new CbcUser * [numberUserFunctions_+1];
    int i;
    for (i = 0; i < numberUserFunctions_; i++)
        temp[i] = userFunction_[i];
    delete [] userFunction_;
    userFunction_ = temp;
    userFunction_[numberUserFunctions_++] = function->clone();
    delete [] statusUserFunction_;
    statusUserFunction_ = NULL;
}
// Set user call back
void
CbcSolver::setUserCallBack(CbcStopNow * function)
{
    delete callBack_;
    callBack_ = function->clone();
}
// Copy of model on initial load (will contain output solutions)
void
CbcSolver::setOriginalSolver(OsiClpSolverInterface * originalSolver)
{
    delete originalSolver_;
    OsiSolverInterface * temp = originalSolver->clone();
    originalSolver_ = dynamic_cast<OsiClpSolverInterface *> (temp);
    assert (originalSolver_);

}
// Copy of model on initial load
void
CbcSolver::setOriginalCoinModel(CoinModel * originalCoinModel)
{
    delete originalCoinModel_;
    originalCoinModel_ = new CoinModel(*originalCoinModel);
}
// Add cut generator
void
CbcSolver::addCutGenerator(CglCutGenerator * generator)
{
    CglCutGenerator ** temp = new CglCutGenerator * [numberCutGenerators_+1];
    int i;
    for (i = 0; i < numberCutGenerators_; i++)
        temp[i] = cutGenerator_[i];
    delete [] cutGenerator_;
    cutGenerator_ = temp;
    cutGenerator_[numberCutGenerators_++] = generator->clone();
}

/*
  The only other solver that's ever been used is cplex, and the use is
  limited -- do the root with clp and all the cbc smarts, then give the
  problem over to cplex to finish. Although the defines can be read in some
  places to allow other options, nothing's been tested and success is
  unlikely.

  CBC_OTHER_SOLVER == 1 is cplex.
*/

#if CBC_OTHER_SOLVER==1
#  ifndef COIN_HAS_CPX
#    error "Configuration did not detect cplex installation."
#  else
#    include "OsiCpxSolverInterface.hpp"
#  endif
#endif

#ifdef COIN_HAS_ASL
#include "Cbc_ampl.h"
#endif

static void statistics(ClpSimplex * originalModel, ClpSimplex * model);
static bool maskMatches(const int * starts, char ** masks,
                        std::string & check);
static void generateCode(CbcModel * model, const char * fileName, int type, int preProcess);

// dummy fake main programs for UserClp and UserCbc
void fakeMain (ClpSimplex & model, OsiSolverInterface & osiSolver, CbcModel & babSolver);
void fakeMain2 (ClpSimplex & model, OsiClpSolverInterface & osiSolver, int options);

// Allow for interrupts
// But is this threadsafe? (so switched off by option)

#include "CoinSignal.hpp"
static CbcModel * currentBranchModel = NULL;

extern "C" {
    static void signal_handler(int whichSignal) {
      if (currentBranchModel != NULL) {
	currentBranchModel->sayEventHappened(); // say why stopped
	if (currentBranchModel->heuristicModel())
	  currentBranchModel->heuristicModel()->sayEventHappened();
      }
        return;
    }
}

//#define CBC_SIG_TRAP
#ifdef CBC_SIG_TRAP
#include <setjmp.h>
static sigjmp_buf cbc_seg_buffer;
extern "C" {
    static void signal_handler_error(int whichSignal) {
        siglongjmp(cbc_seg_buffer, 1);
    }
}
#endif


/*
  Debug checks on special ordered sets.

  This is active only for debugging. The entire body of the routine becomes
  a noop when COIN_DEVELOP is not defined. To avoid compiler warnings, the
  formal parameters also need to go away.
*/
#ifdef COIN_DEVELOP
void checkSOS(CbcModel * babModel, const OsiSolverInterface * solver)
#else
void checkSOS(CbcModel * /*babModel*/, const OsiSolverInterface * /*solver*/)
#endif
{
#ifdef COIN_DEVELOP
    if (!babModel->ownObjects())
        return;
#if COIN_DEVELOP>2
    //const double *objective = solver->getObjCoefficients() ;
    const double *columnLower = solver->getColLower() ;
    const double * columnUpper = solver->getColUpper() ;
    const double * solution = solver->getColSolution();
    //int numberRows = solver->getNumRows();
    //double direction = solver->getObjSense();
    //int iRow,iColumn;
#endif

    // Row copy
    CoinPackedMatrix matrixByRow(*solver->getMatrixByRow());
    //const double * elementByRow = matrixByRow.getElements();
    //const int * column = matrixByRow.getIndices();
    //const CoinBigIndex * rowStart = matrixByRow.getVectorStarts();
    const int * rowLength = matrixByRow.getVectorLengths();

    // Column copy
    CoinPackedMatrix  matrixByCol(*solver->getMatrixByCol());
    const double * element = matrixByCol.getElements();
    const int * row = matrixByCol.getIndices();
    const CoinBigIndex * columnStart = matrixByCol.getVectorStarts();
    const int * columnLength = matrixByCol.getVectorLengths();

    const double * rowLower = solver->getRowLower();
    const double * rowUpper = solver->getRowUpper();
    OsiObject ** objects = babModel->objects();
    int numberObjects = babModel->numberObjects();
    int numberColumns = solver->getNumCols() ;
    for (int iObj = 0; iObj < numberObjects; iObj++) {
        CbcSOS * objSOS =
            dynamic_cast <CbcSOS *>(objects[iObj]) ;
        if (objSOS) {
            int n = objSOS->numberMembers();
            const int * which = objSOS->members();
#if COIN_DEVELOP>2
            const double * weight = objSOS->weights();
#endif
            int type = objSOS->sosType();
            // convexity row?
            int iColumn;
            iColumn = which[0];
            int j;
            int convex = -1;
            for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) {
                int iRow = row[j];
                double value = element[j];
                if (rowLower[iRow] == 1.0 && rowUpper[iRow] == 1.0 &&
                        value == 1.0) {
                    // possible
                    if (rowLength[iRow] == n) {
                        if (convex == -1)
                            convex = iRow;
                        else
                            convex = -2;
                    }
                }
            }
            printf ("set %d of type %d has %d members - possible convexity row %d\n",
                    iObj, type, n, convex);
            for (int i = 0; i < n; i++) {
                iColumn = which[i];
                // Column may have been added
                if (iColumn < numberColumns) {
                    int convex2 = -1;
                    for (j = columnStart[iColumn]; j < columnStart[iColumn] + columnLength[iColumn]; j++) {
                        int iRow = row[j];
                        if (iRow == convex) {
                            double value = element[j];
                            if (value == 1.0) {
                                convex2 = iRow;
                            }
                        }
                    }
                    if (convex2<0 && convex >= 0) {
                        printf("odd convexity row\n");
                        convex = -2;
                    }
#if COIN_DEVELOP>2
                    printf("col %d has weight %g and value %g, bounds %g %g\n",
                           iColumn, weight[i], solution[iColumn], columnLower[iColumn],
                           columnUpper[iColumn]);
#endif
                }
            }
        }
    }
#endif	// COIN_DEVELOP
}

static int dummyCallBack(CbcModel * /*model*/, int /*whereFrom*/)
{
    return 0;
}


/*
  Global parameters for command processing.

  These will need to be moved into an object of some sort in order to make
  this set of calls thread-safe.
*/

int CbcOrClpRead_mode = 1;
FILE * CbcOrClpReadCommand = stdin;
extern int CbcOrClpEnvironmentIndex;

int callCbc1(const char * input2, CbcModel & model,
             int callBack(CbcModel * currentSolver, int whereFrom),
	     CbcSolverUsefulData & parameterData);

/*
  Wrappers for CbcMain0, CbcMain1. The various forms of callCbc will eventually
  resolve to a call to CbcMain0 followed by a call to callCbc1.
*/
/*
  Simplest calling form: supply just a string with the command options. The
  wrapper creates an OsiClpSolverInterface and calls the next wrapper.
*/
int callCbc(const std::string input2)
{
    char * input3 = CoinStrdup(input2.c_str());
    OsiClpSolverInterface solver1;
    int returnCode = callCbc(input3, solver1);
    free(input3);
    return returnCode;
}

int callCbc(const char * input2)
{
    {
        OsiClpSolverInterface solver1;
        return callCbc(input2, solver1);
    }
}

/*
  Second calling form: supply the command line and an OsiClpSolverInterface.
  the wrapper will create a CbcModel and call the next wrapper.
*/

int callCbc(const std::string input2, OsiClpSolverInterface& solver1)
{
    char * input3 = CoinStrdup(input2.c_str());
    int returnCode = callCbc(input3, solver1);
    free(input3);
    return returnCode;
}

int callCbc(const char * input2, OsiClpSolverInterface& solver1)
{
    CbcModel model(solver1);
    return callCbc(input2, model);
}

/*
  Third calling form: supply the command line and a CbcModel. This wrapper will
  actually call CbcMain0 and then call the next set of wrappers (callCbc1) to
  handle the call to CbcMain1.
*/
int callCbc(const char * input2, CbcModel & babSolver)
{
  CbcSolverUsefulData data;
#ifndef CBC_NO_INTERRUPT
    data.useSignalHandler_=true;
#endif
#ifndef CBC_NO_PRINTING
    data.noPrinting_ = false;
#endif
  CbcMain0(babSolver, data);
  return callCbc1(input2, babSolver, dummyCallBack, data);
}

int callCbc(const std::string input2, CbcModel & babSolver)
{
    char * input3 = CoinStrdup(input2.c_str());
    CbcMain0(babSolver);
    int returnCode = callCbc1(input3, babSolver);
    free(input3);
    return returnCode;
}


/*
  Various overloads of callCbc1. The first pair accepts just a CbcModel and
  supplements it with a dummy callback routine. The second pair allows the
  user to supply a callback. See CbcMain1 for further explanation of the
  callback. The various overloads of callCbc1 resolve to the final version,
  which breaks the string into individual parameter strings (i.e., creates
  something that looks like a standard argv vector).
*/

int callCbc1(const std::string input2, CbcModel & babSolver)
{
    char * input3 = CoinStrdup(input2.c_str());
    int returnCode = callCbc1(input3, babSolver);
    free(input3);
    return returnCode;
}

int callCbc1(const char * input2, CbcModel & model)
{
    return callCbc1(input2, model, dummyCallBack);
}

int callCbc1(const std::string input2, CbcModel & babSolver,
             int callBack(CbcModel * currentSolver, int whereFrom))
{
    char * input3 = CoinStrdup(input2.c_str());
    int returnCode = callCbc1(input3, babSolver, callBack);
    free(input3);
    return returnCode;
}
int callCbc1(const char * input2, CbcModel & model,
             int callBack(CbcModel * currentSolver, int whereFrom),
	     CbcSolverUsefulData & parameterData)
{
    char * input = CoinStrdup(input2 ? input2 : "") ;
    size_t length = strlen(input);
    bool blank = input[0] == ' ';
    int n = blank ? 0 : 1;
    for (size_t i = 0; i < length; i++) {
        if (blank) {
            // look for next non blank
            if (input[i] == ' ') {
                continue;
            } else {
                n++;
                blank = false;
            }
        } else {
            // look for next blank
            if (input[i] != ' ') {
                continue;
            } else {
                blank = true;
            }
        }
    }
    char ** argv = new char * [n+2];
    argv[0] = CoinStrdup("cbc");
    size_t i = 0;
    while (input[i] == ' ')
        i++;
    for (int j = 0; j < n; j++) {
        size_t saveI = i;
        for (; i < length; i++) {
            // look for next blank
            if (input[i] != ' ') {
                continue;
            } else {
                break;
            }
        }
        input[i++] = '\0';
        argv[j+1] = CoinStrdup(input + saveI);
        while (input[i] == ' ')
            i++;
    }
    argv[n+1] = CoinStrdup("-quit");
    free(input);
    currentBranchModel = NULL;
    CbcOrClpRead_mode = 1;
    CbcOrClpReadCommand = stdin;
    int returnCode = CbcMain1(n + 2, const_cast<const char **>(argv),
                              model, callBack,parameterData);
    for (int k = 0; k < n + 2; k++)
        free(argv[k]);
    delete [] argv;
    return returnCode;
}
static CbcSolverUsefulData staticParameterData;
int callCbc1(const char * input2, CbcModel & model,
             int callBack(CbcModel * currentSolver, int whereFrom))
{
  // allow interrupts and printing
#ifndef CBC_NO_INTERRUPT
  staticParameterData.useSignalHandler_=true;
#endif
#ifndef CBC_NO_PRINTING
  staticParameterData.noPrinting_ = false;
#endif
  return callCbc1(input2,model,callBack,staticParameterData);
}

CglPreProcess * cbcPreProcessPointer=NULL;

int CbcClpUnitTest (const CbcModel & saveModel,
                    const std::string& dirMiplib, int testSwitch,
                    const double * stuff);

int CbcMain1 (int argc, const char *argv[],
              CbcModel  & model)
{
    return CbcMain1(argc, argv, model, dummyCallBack);
}

#ifdef CBC_THREAD_SAFE
// Copies of some input decoding

static std::string
CoinReadGetCommand(int &whichArgument, int argc, const char *argv[])
{
  std::string field;
  if (whichArgument < argc) 
    field = argv[whichArgument++];
  else
    field = "quit";
  if (field[0] == '-') 
    field = field.substr(1);
  return field;
}
static std::string
CoinReadGetString(int &whichArgument, int argc, const char *argv[])
{
  std::string field;
  if (whichArgument < argc) 
    field = argv[whichArgument++];
  else
    field = "";
  return field;
}
// valid 0 - okay, 1 bad, 2 not there
static int
CoinReadGetIntField(int &whichArgument, int argc, const char *argv[], int * valid)
{
  std::string field;
  if (whichArgument < argc) 
    field = argv[whichArgument++];
  else
    field = "0";
  long int value = 0;
  const char * start = field.c_str();
  char * endPointer = NULL;
  // check valid
  value =  strtol(start, &endPointer, 10);
  if (*endPointer == '\0') {
    *valid = 0;
  } else {
    *valid = 1;
    std::cout << "String of " << field;
  }
  return static_cast<int>(value);
}
static double
CoinReadGetDoubleField(int &whichArgument, int argc, const char *argv[], int * valid)
{
  std::string field;
  if (whichArgument < argc) 
    field = argv[whichArgument++];
  else
    field = "0.0";
  double value = 0.0;
  const char * start = field.c_str();
  char * endPointer = NULL;
  // check valid
  value =  strtod(start, &endPointer);
  if (*endPointer == '\0') {
    *valid = 0;
  } else {
    *valid = 1;
    std::cout << "String of " << field;
  }
  return value;
}
// Redefine all
#define CoinReadGetCommand(x,y) CoinReadGetCommand(whichArgument,x,y)
#define CoinReadGetString(x,y) CoinReadGetString(whichArgument,x,y)
#define CoinReadGetIntField(x,y,z) CoinReadGetIntField(whichArgument,x,y,z)
#define CoinReadGetDoubleField(x,y,z) CoinReadGetDoubleField(whichArgument,x,y,z)
#endif
// Default Constructor
CbcSolverUsefulData::CbcSolverUsefulData()
{
  totalTime_ = 0.0;
  noPrinting_ = true;
  useSignalHandler_ = false;
  establishParams(numberParameters_,parameters_);
}

/* Copy constructor .
 */
CbcSolverUsefulData::CbcSolverUsefulData(const CbcSolverUsefulData & rhs)
{
  totalTime_ = rhs.totalTime_;
  noPrinting_ = rhs.noPrinting_;
  useSignalHandler_ = rhs.useSignalHandler_;
  numberParameters_ = rhs.numberParameters_;
  memcpy(parameters_,rhs.parameters_,sizeof(parameters_));
}

// Assignment operator
CbcSolverUsefulData & CbcSolverUsefulData::operator=(const CbcSolverUsefulData& rhs)
{
  if (this != &rhs) {
    totalTime_ = rhs.totalTime_;
    noPrinting_ = rhs.noPrinting_;
    useSignalHandler_ = rhs.useSignalHandler_;
    numberParameters_ = rhs.numberParameters_;
    memcpy(parameters_,rhs.parameters_,sizeof(parameters_));
  }
  return *this;
}

// Destructor
CbcSolverUsefulData::~CbcSolverUsefulData ()
{
}

/*
  Meaning of whereFrom:
    1 after initial solve by dualsimplex etc
    2 after preprocessing
    3 just before branchAndBound (so user can override)
    4 just after branchAndBound (before postprocessing)
    5 after postprocessing
    6 after a user called heuristic phase
*/

int CbcMain1 (int argc, const char *argv[],
              CbcModel  & model,
              int callBack(CbcModel * currentSolver, int whereFrom))
{
  // allow interrupts and printing
  staticParameterData.noPrinting_ = false;
  staticParameterData.useSignalHandler_=true;
  return CbcMain1(argc,argv,model,callBack,staticParameterData);
}
static void printGeneralMessage(CbcModel &model,const char * message);
/*
  Meaning of whereFrom:
    1 after initial solve by dualsimplex etc
    2 after preprocessing
    3 just before branchAndBound (so user can override)
    4 just after branchAndBound (before postprocessing)
    5 after postprocessing
    6 after a user called heuristic phase
*/
int CbcMain1 (int argc, const char *argv[],
              CbcModel  & model,
              int callBack(CbcModel * currentSolver, int whereFrom),
	      CbcSolverUsefulData & parameterData)
{
    CbcOrClpParam * parameters_ = parameterData.parameters_;
    int numberParameters_ = parameterData.numberParameters_;
    double totalTime = parameterData.totalTime_;
    bool noPrinting = parameterData.noPrinting_;
    bool useSignalHandler = parameterData.useSignalHandler_;
    CbcModel & model_ = model;
#ifdef CBC_THREAD_SAFE
    // Initialize argument
    int whichArgument=1;
#endif
#ifdef CBC_USE_INITIAL_TIME
    if (model_.useElapsedTime())
      model_.setDblParam(CbcModel::CbcStartSeconds, CoinGetTimeOfDay());
    else
      model_.setDblParam(CbcModel::CbcStartSeconds, CoinCpuTime());
#endif
    CbcModel * babModel_ = NULL;
    int returnMode = 1;
    CbcOrClpRead_mode = 1;
    int statusUserFunction_[1];
    int numberUserFunctions_ = 1; // to allow for ampl
    // Statistics
    double statistics_seconds = 0.0, statistics_obj = 0.0;
    double statistics_sys_seconds = 0.0, statistics_elapsed_seconds = 0.0;
    CoinWallclockTime();
    double statistics_continuous = 0.0, statistics_tighter = 0.0;
    double statistics_cut_time = 0.0;
    int statistics_nodes = 0, statistics_iterations = 0;
    int statistics_nrows = 0, statistics_ncols = 0;
    int statistics_nprocessedrows = 0, statistics_nprocessedcols = 0;
    std::string statistics_result;
    int *statistics_number_cuts = NULL;
    const char ** statistics_name_generators = NULL;
    int statistics_number_generators = 0;
    memset(statusUserFunction_, 0, numberUserFunctions_*sizeof(int));
    /* Note
       This is meant as a stand-alone executable to do as much of coin as possible.
       It should only have one solver known to it.
    */
    CoinMessageHandler * generalMessageHandler = model_.messageHandler();
    generalMessageHandler->setPrefix(false);
#ifndef CBC_OTHER_SOLVER
    OsiClpSolverInterface * originalSolver = dynamic_cast<OsiClpSolverInterface *> (model_.solver());
    assert (originalSolver);
    // Move handler across if not default
    if (!originalSolver->defaultHandler() && originalSolver->getModelPtr()->defaultHandler())
        originalSolver->getModelPtr()->passInMessageHandler(originalSolver->messageHandler());
    CoinMessages generalMessages = originalSolver->getModelPtr()->messages();
    char generalPrint[10000];
    if (originalSolver->getModelPtr()->logLevel() == 0)
        noPrinting = true;
#elif CBC_OTHER_SOLVER==1
    OsiCpxSolverInterface * originalSolver = dynamic_cast<OsiCpxSolverInterface *> (model_.solver());
    assert (originalSolver);
    OsiClpSolverInterface dummySolver;
    OsiCpxSolverInterface * clpSolver = originalSolver;
    CoinMessages generalMessages = dummySolver.getModelPtr()->messages();
    char generalPrint[10000];
    noPrinting = true;
#endif
    bool noPrinting_ = noPrinting;
    // Say not in integer
    int integerStatus = -1;
    // Say no resolve after cuts
    model_.setResolveAfterTakeOffCuts(false);
    // see if log in list
    for (int i = 1; i < argc; i++) {
        if (!strncmp(argv[i], "log", 3)) {
            const char * equals = strchr(argv[i], '=');
            if (equals && atoi(equals + 1) != 0)
                noPrinting_ = false;
            else
                noPrinting_ = true;
            break;
        } else if (!strncmp(argv[i], "-log", 4) && i < argc - 1) {
            if (atoi(argv[i+1]) != 0)
                noPrinting_ = false;
            else
                noPrinting_ = true;
            break;
        }
    }
    double time0;
    double time0Elapsed = CoinGetTimeOfDay();
    {
        double time1 = CoinCpuTime(), time2;
        time0 = time1;
	double time1Elapsed = time0Elapsed;
        bool goodModel = (originalSolver->getNumCols()) ? true : false;

        // register signal handler
        //CoinSighandler_t saveSignal=signal(SIGINT,signal_handler);
#if CBC_QUIET < 2
	if (useSignalHandler)
	  signal(SIGINT, signal_handler);
#endif
        // Set up all non-standard stuff
        int cutPass = -1234567;
        int cutPassInTree = -1234567;
        int tunePreProcess = 0;
        int testOsiParameters = -1;
        // 0 normal, 1 from ampl or MIQP etc (2 allows cuts)
        int complicatedInteger = 0;
        OsiSolverInterface * solver = model_.solver();
        if (noPrinting_)
            setCbcOrClpPrinting(false);
#ifndef CBC_OTHER_SOLVER
        OsiClpSolverInterface * clpSolver = dynamic_cast< OsiClpSolverInterface*> (solver);
        ClpSimplex * lpSolver = clpSolver->getModelPtr();
        if (noPrinting_) {
            lpSolver->setLogLevel(0);
        }
#else
        ClpSimplex * lpSolver = NULL;
#endif
        // For priorities etc
        int * priorities = NULL;
        int * branchDirection = NULL;
        double * pseudoDown = NULL;
        double * pseudoUp = NULL;
        double * solutionIn = NULL;
        int * prioritiesIn = NULL;
        std::vector< std::pair< std::string, double > > mipStart;
        std::vector< std::pair< std::string, double > > mipStartBefore;
        int numberSOS = 0;
        int * sosStart = NULL;
        int * sosIndices = NULL;
        char * sosType = NULL;
        double * sosReference = NULL;
        int * cut = NULL;
        int * sosPriority = NULL;
        CglStored storedAmpl;
        CoinModel * coinModel = NULL;
        CoinModel saveCoinModel;
        CoinModel saveTightenedModel;
        int * whichColumn = NULL;
        int * knapsackStart = NULL;
        int * knapsackRow = NULL;
        int numberKnapsack = 0;
#ifdef COIN_HAS_ASL
        ampl_info info;
        {
            memset(&info, 0, sizeof(info));
            if (argc > 2 && !strcmp(argv[2], "-AMPL")) {
                statusUserFunction_[0] = 1;
                // see if log in list
                noPrinting_ = true;
                for (int i = 1; i < argc; i++) {
                    if (!strncmp(argv[i], "log", 3)) {
                        const char * equals = strchr(argv[i], '=');
                        if (equals && atoi(equals + 1) > 0) {
                            noPrinting_ = false;
                            info.logLevel = atoi(equals + 1);
                            int log = whichParam(CLP_PARAM_INT_LOGLEVEL, numberParameters_, parameters_);
                            parameters_[log].setIntValue(info.logLevel);
                            // mark so won't be overWritten
                            info.numberRows = -1234567;
                            break;
                        }
                    }
                }

                union {
                    void * voidModel;
                    CoinModel * model;
                } coinModelStart;
                coinModelStart.model = NULL;
                int returnCode = readAmpl(&info, argc, const_cast<char **>(argv), & coinModelStart.voidModel);
                coinModel = coinModelStart.model;
                if (returnCode)
                    return returnCode;
                CbcOrClpRead_mode = 2; // so will start with parameters
                // see if log in list (including environment)
                for (int i = 1; i < info.numberArguments; i++) {
                    if (!strcmp(info.arguments[i], "log")) {
                        if (i < info.numberArguments - 1 && atoi(info.arguments[i+1]) > 0)
                            noPrinting_ = false;
                        break;
                    }
                }
                if (noPrinting_) {
                    model_.messageHandler()->setLogLevel(0);
                    setCbcOrClpPrinting(false);
                }
                if (!noPrinting_)
                    printf("%d rows, %d columns and %d elements\n",
                           info.numberRows, info.numberColumns, info.numberElements);
#ifdef COIN_HAS_LINK
                if (!coinModel) {
#endif
                    solver->loadProblem(info.numberColumns, info.numberRows, info.starts,
                                        info.rows, info.elements,
                                        info.columnLower, info.columnUpper, info.objective,
                                        info.rowLower, info.rowUpper);
                    // take off cuts if ampl wants that
                    if (info.cut && 0) {
                        printf("AMPL CUTS OFF until global cuts fixed\n");
                        info.cut = NULL;
                    }
                    if (info.cut) {
                        int numberRows = info.numberRows;
                        int * whichRow = new int [numberRows];
                        // Row copy
                        const CoinPackedMatrix * matrixByRow = solver->getMatrixByRow();
                        const double * elementByRow = matrixByRow->getElements();
                        const int * column = matrixByRow->getIndices();
                        const CoinBigIndex * rowStart = matrixByRow->getVectorStarts();
                        const int * rowLength = matrixByRow->getVectorLengths();

                        const double * rowLower = solver->getRowLower();
                        const double * rowUpper = solver->getRowUpper();
                        int nDelete = 0;
                        for (int iRow = 0; iRow < numberRows; iRow++) {
                            if (info.cut[iRow]) {
                                whichRow[nDelete++] = iRow;
                                int start = rowStart[iRow];
                                storedAmpl.addCut(rowLower[iRow], rowUpper[iRow],
                                                  rowLength[iRow], column + start, elementByRow + start);
                            }
                        }
                        solver->deleteRows(nDelete, whichRow);
                        delete [] whichRow;
                    }
#ifdef COIN_HAS_LINK
                } else {
#ifndef CBC_OTHER_SOLVER
                    // save
                    saveCoinModel = *coinModel;
                    // load from coin model
                    OsiSolverLink solver1;
                    OsiSolverInterface * solver2 = solver1.clone();
                    model_.assignSolver(solver2, false);
                    OsiSolverLink * si =
                        dynamic_cast<OsiSolverLink *>(model_.solver()) ;
                    assert (si != NULL);
                    si->setDefaultMeshSize(0.001);
                    // need some relative granularity
                    si->setDefaultBound(100.0);
                    double dextra3 = parameters_[whichParam(CBC_PARAM_DBL_DEXTRA3, numberParameters_, parameters_)].doubleValue();
                    if (dextra3)
                        si->setDefaultMeshSize(dextra3);
                    si->setDefaultBound(100000.0);
                    si->setIntegerPriority(1000);
                    si->setBiLinearPriority(10000);
                    CoinModel * model2 = reinterpret_cast<CoinModel *> (coinModel);
                    int logLevel = parameters_[whichParam(CLP_PARAM_INT_LOGLEVEL, numberParameters_, parameters_)].intValue();
                    si->load(*model2, true, logLevel);
                    // redo
                    solver = model_.solver();
                    clpSolver = dynamic_cast< OsiClpSolverInterface*> (solver);
                    lpSolver = clpSolver->getModelPtr();
                    clpSolver->messageHandler()->setLogLevel(0) ;
                    testOsiParameters = 0;
                    parameters_[whichParam(CBC_PARAM_INT_TESTOSI, numberParameters_, parameters_)].setIntValue(0);
                    complicatedInteger = 1;
                    if (info.cut) {
                        printf("Sorry - can't do cuts with LOS as ruins delicate row order\n");
                        abort();
                        int numberRows = info.numberRows;
                        int * whichRow = new int [numberRows];
                        // Row copy
                        const CoinPackedMatrix * matrixByRow = solver->getMatrixByRow();
                        const double * elementByRow = matrixByRow->getElements();
                        const int * column = matrixByRow->getIndices();
                        const CoinBigIndex * rowStart = matrixByRow->getVectorStarts();
                        const int * rowLength = matrixByRow->getVectorLengths();

                        const double * rowLower = solver->getRowLower();
                        const double * rowUpper = solver->getRowUpper();
                        int nDelete = 0;
                        for (int iRow = 0; iRow < numberRows; iRow++) {
                            if (info.cut[iRow]) {
                                whichRow[nDelete++] = iRow;
                                int start = rowStart[iRow];
                                storedAmpl.addCut(rowLower[iRow], rowUpper[iRow],
                                                  rowLength[iRow], column + start, elementByRow + start);
                            }
                        }
                        solver->deleteRows(nDelete, whichRow);
                        // and special matrix
                        si->cleanMatrix()->deleteRows(nDelete, whichRow);
                        delete [] whichRow;
                    }
#endif
                }
#endif
                // If we had a solution use it
                if (info.primalSolution) {
                    solver->setColSolution(info.primalSolution);
                }
                // status
                if (info.rowStatus) {
                    unsigned char * statusArray = lpSolver->statusArray();
                    int i;
                    for (i = 0; i < info.numberColumns; i++)
                        statusArray[i] = static_cast<unsigned char>(info.columnStatus[i]);
                    statusArray += info.numberColumns;
                    for (i = 0; i < info.numberRows; i++)
                        statusArray[i] = static_cast<unsigned char>(info.rowStatus[i]);
                    CoinWarmStartBasis * basis = lpSolver->getBasis();
                    solver->setWarmStart(basis);
                    delete basis;
                }
                freeArrays1(&info);
                // modify objective if necessary
                solver->setObjSense(info.direction);
                solver->setDblParam(OsiObjOffset, -info.offset);
                if (info.offset) {
                    sprintf(generalPrint, "Ampl objective offset is %g",
                            info.offset);
                    generalMessageHandler->message(CLP_GENERAL, generalMessages)
                    << generalPrint
                    << CoinMessageEol;
                }
                // Set integer variables (unless nonlinear when set)
                if (!info.nonLinear) {
                    for (int i = info.numberColumns - info.numberIntegers;
                            i < info.numberColumns; i++)
                        solver->setInteger(i);
                }
                goodModel = true;
                // change argc etc
                argc = info.numberArguments;
                argv = const_cast<const char **>(info.arguments);
            }
        }
#endif
        // default action on import
        int allowImportErrors = 0;
        int keepImportNames = 1;
        int doIdiot = -1;
        int outputFormat = 2;
        int slpValue = -1;
        int cppValue = -1;
        int printOptions = 0;
        int printMode = 0;
        int presolveOptions = 0;
        int substitution = 3;
        int dualize = 3;
        int doCrash = 0;
        int doVector = 0;
        int doSprint = -1;
        int doScaling = 4;
        // set reasonable defaults
        int preSolve = 5;
        int preProcess = 4;
        bool useStrategy = false;
        bool preSolveFile = false;
        bool strongChanged = false;
        bool pumpChanged = false;

        double djFix = 1.0e100;
        double tightenFactor = 0.0;
        const char dirsep =  CoinFindDirSeparator();
        std::string directory;
        std::string dirSample;
        std::string dirNetlib;
        std::string dirMiplib;
        if (dirsep == '/') {
            directory = "./";
            dirSample = "../../Data/Sample/";
            dirNetlib = "../../Data/Netlib/";
            dirMiplib = "../../Data/miplib3/";
        } else {
            directory = ".\\";
            dirSample = "..\\..\\..\\..\\Data\\Sample\\";
            dirNetlib = "..\\..\\..\\..\\Data\\Netlib\\";
            dirMiplib = "..\\..\\..\\..\\Data\\miplib3\\";
        }
        std::string defaultDirectory = directory;
        std::string importFile = "";
        std::string exportFile = "default.mps";
        std::string importBasisFile = "";
        std::string importPriorityFile = "";
        std::string debugFile = "";
        std::string printMask = "";
        double * debugValues = NULL;
        int numberDebugValues = -1;
        int basisHasValues = 0;
        std::string exportBasisFile = "default.bas";
        std::string saveFile = "default.prob";
        std::string restoreFile = "default.prob";
        std::string solutionFile = "stdout";
        std::string solutionSaveFile = "solution.file";
        int slog = whichParam(CLP_PARAM_INT_SOLVERLOGLEVEL, numberParameters_, parameters_);
        int log = whichParam(CLP_PARAM_INT_LOGLEVEL, numberParameters_, parameters_);
#ifndef CBC_OTHER_SOLVER
        double normalIncrement = model_.getCutoffIncrement();;
#endif
        if (testOsiParameters >= 0) {
            // trying nonlinear - switch off some stuff
            preProcess = 0;
        }
        // Set up likely cut generators and defaults
        int nodeStrategy = 0;
        bool dominatedCuts = false;
        int doSOS = 1;
        int verbose = 0;
        CglGomory gomoryGen;
        // try larger limit
        gomoryGen.setLimitAtRoot(1000);
        gomoryGen.setLimit(50);
        // set default action (0=off,1=on,2=root)
#ifdef SWAP_GOMORY
        int gomoryAction = 0;
#else
        int gomoryAction = 3;
#endif

        CglProbing probingGen;
        probingGen.setUsingObjective(1);
        probingGen.setMaxPass(1);
        probingGen.setMaxPassRoot(1);
        // Number of unsatisfied variables to look at
        probingGen.setMaxProbe(10);
        probingGen.setMaxProbeRoot(50);
        // How far to follow the consequences
        probingGen.setMaxLook(10);
        probingGen.setMaxLookRoot(50);
        probingGen.setMaxLookRoot(10);
        // Only look at rows with fewer than this number of elements
        probingGen.setMaxElements(200);
        probingGen.setMaxElementsRoot(300);
        probingGen.setRowCuts(3);
        // set default action (0=off,1=on,2=root)
        int probingAction = 1;

        CglKnapsackCover knapsackGen;
        //knapsackGen.switchOnExpensive();
        //knapsackGen.setMaxInKnapsack(100);
        // set default action (0=off,1=on,2=root)
        int knapsackAction = 3;

        CglRedSplit redsplitGen;
        //redsplitGen.setLimit(100);
        // set default action (0=off,1=on,2=root)
        // Off as seems to give some bad cuts
        int redsplitAction = 0;

        CglRedSplit2 redsplit2Gen;
        //redsplit2Gen.setLimit(100);
        // set default action (0=off,1=on,2=root)
        // Off
        int redsplit2Action = 0;

        CglGMI GMIGen;
        //GMIGen.setLimit(100);
        // set default action (0=off,1=on,2=root)
#ifdef SWAP_GOMORY
        int GMIAction = 3;
#else
        // Off 
        int GMIAction = 0;
#endif

        CglFakeClique cliqueGen(NULL, false);
        //CglClique cliqueGen(false,true);
        cliqueGen.setStarCliqueReport(false);
        cliqueGen.setRowCliqueReport(false);
        cliqueGen.setMinViolation(0.1);
        // set default action (0=off,1=on,2=root)
        int cliqueAction = 3;

        // maxaggr,multiply,criterion(1-3)
        CglMixedIntegerRounding2 mixedGen(1, true, 1);
        // set default action (0=off,1=on,2=root)
        int mixedAction = 3;
	mixedGen.setDoPreproc(1); // safer (and better)

        CglFlowCover flowGen;
        // set default action (0=off,1=on,2=root)
        int flowAction = 3;

        CglTwomir twomirGen;
        twomirGen.setMaxElements(250);
        // set default action (0=off,1=on,2=root)
        int twomirAction = 3;
#ifndef DEBUG_MALLOC
        CglLandP landpGen;
	landpGen.validator().setMinViolation(1.0e-4);
#endif
        // set default action (0=off,1=on,2=root)
        int landpAction = 0;
        CglResidualCapacity residualCapacityGen;
        residualCapacityGen.setDoPreproc(1); // always preprocess
        // set default action (0=off,1=on,2=root)
        int residualCapacityAction = 0;

        CglZeroHalf zerohalfGen;
        //zerohalfGen.switchOnExpensive();
        // set default action (0=off,1=on,2=root)
        int zerohalfAction = 0;

        // Stored cuts
        //bool storedCuts = false;

        int useCosts = 0;
        // don't use input solution
        int useSolution = -1;

        // total number of commands read
        int numberGoodCommands = 0;
        // Set false if user does anything advanced
        bool defaultSettings = true;

        // Hidden stuff for barrier
        int choleskyType = 0;
        int gamma = 0;
        int scaleBarrier = 0;
        int doKKT = 0;
        int crossover = 2; // do crossover unless quadratic
	bool biLinearProblem=false;
        // For names
        int lengthName = 0;
        std::vector<std::string> rowNames;
        std::vector<std::string> columnNames;
        // Default strategy stuff
        {
            // try changing tolerance at root
#define MORE_CUTS
#ifdef MORE_CUTS
            gomoryGen.setAwayAtRoot(0.005);
            twomirGen.setAwayAtRoot(0.005);
            twomirGen.setAway(0.01);
            //twomirGen.setMirScale(1,1);
            //twomirGen.setTwomirScale(1,1);
            //twomirGen.setAMax(2);
#else
            gomoryGen.setAwayAtRoot(0.01);
            twomirGen.setAwayAtRoot(0.01);
            twomirGen.setAway(0.01);
#endif
            int iParam;
            iParam = whichParam(CBC_PARAM_INT_DIVEOPT, numberParameters_, parameters_);
            parameters_[iParam].setIntValue(2);
            iParam = whichParam(CBC_PARAM_INT_FPUMPITS, numberParameters_, parameters_);
            parameters_[iParam].setIntValue(30);
            iParam = whichParam(CBC_PARAM_INT_FPUMPTUNE, numberParameters_, parameters_);
            parameters_[iParam].setIntValue(1005043);
            initialPumpTune = 1005043;
            iParam = whichParam(CLP_PARAM_INT_PROCESSTUNE, numberParameters_, parameters_);
            parameters_[iParam].setIntValue(6);
            tunePreProcess = 6;
            iParam = whichParam(CBC_PARAM_STR_DIVINGC, numberParameters_, parameters_);
            parameters_[iParam].setCurrentOption("on");
            iParam = whichParam(CBC_PARAM_STR_RINS, numberParameters_, parameters_);
            parameters_[iParam].setCurrentOption("on");
            iParam = whichParam(CBC_PARAM_STR_PROBINGCUTS, numberParameters_, parameters_);
            parameters_[iParam].setCurrentOption("on");
            probingAction = 3;
            //parameters_[iParam].setCurrentOption("forceOnStrong");
            //probingAction = 8;
        }
        std::string field;
#if CBC_QUIET == 0
        if (!noPrinting_) {
	   sprintf(generalPrint,
		   "Welcome to the CBC MILP Solver \n");
	    if (strcmp(CBC_VERSION, "trunk")){
	       sprintf(generalPrint + strlen(generalPrint),
		       "Version: %s \n", CBC_VERSION);
	    }else{
	       sprintf(generalPrint + strlen(generalPrint),
		       "Version: Trunk (unstable) \n");
	    }
	    sprintf(generalPrint + strlen(generalPrint),
		    "Build Date: %s \n", __DATE__);
#ifdef CBC_SVN_REV
	    sprintf(generalPrint + strlen(generalPrint),
		    "Revision Number: %d \n", CBC_SVN_REV);
#endif
            generalMessageHandler->message(CLP_GENERAL, generalMessages)
            << generalPrint
            << CoinMessageEol;
            // Print command line
            if (argc > 1) {
                bool foundStrategy = false;
                sprintf(generalPrint, "command line - ");
                for (int i = 0; i < argc; i++) {
                    if (!argv[i])
                        break;
                    if (strstr(argv[i], "strat"))
                        foundStrategy = true;
                    sprintf(generalPrint + strlen(generalPrint), "%s ", argv[i]);
                }
                if (!foundStrategy)
                    sprintf(generalPrint + strlen(generalPrint), "(default strategy 1)");
                generalMessageHandler->message(CLP_GENERAL, generalMessages)
                << generalPrint
                << CoinMessageEol;
            }
        }
#endif
        while (1) {
            // next command
            field = CoinReadGetCommand(argc, argv);
            // Reset time
            time1 = CoinCpuTime();
	    time1Elapsed = CoinGetTimeOfDay();
            // adjust field if has odd trailing characters
            char temp [200];
            strcpy(temp, field.c_str());
            int length = static_cast<int>(strlen(temp));
            for (int k = length - 1; k >= 0; k--) {
                if (temp[k] < ' ')
                    length--;
                else
                    break;
            }
            temp[length] = '\0';
            field = temp;
            // exit if null or similar
            if (!field.length()) {
                if (numberGoodCommands == 1 && goodModel) {
                    // we just had file name - do branch and bound
                    field = "branch";
                } else if (!numberGoodCommands) {
                    // let's give the sucker a hint
                    std::cout
                        << "CoinSolver takes input from arguments ( - switches to stdin)"
                        << std::endl
                        << "Enter ? for list of commands or help" << std::endl;
                    field = "-";
                } else {
                    break;
                }
            }

            // see if ? at end
            size_t numberQuery = 0;
            if (field != "?" && field != "???") {
                size_t length = field.length();
                size_t i;
                for (i = length - 1; i > 0; i--) {
                    if (field[i] == '?')
                        numberQuery++;
                    else
                        break;
                }
                field = field.substr(0, length - numberQuery);
            }
            // find out if valid command
            int iParam;
            int numberMatches = 0;
            int firstMatch = -1;
            for ( iParam = 0; iParam < numberParameters_; iParam++ ) {
                int match = parameters_[iParam].matches(field);
                if (match == 1) {
                    numberMatches = 1;
                    firstMatch = iParam;
                    break;
                } else {
                    if (match && firstMatch < 0)
                        firstMatch = iParam;
                    numberMatches += match >> 1;
                }
            }
            if (iParam < numberParameters_ && !numberQuery) {
                // found
                CbcOrClpParam found = parameters_[iParam];
                CbcOrClpParameterType type = found.type();
                int valid;
                numberGoodCommands++;
                if (type == CBC_PARAM_ACTION_BAB && goodModel) {
#ifndef CBC_USE_INITIAL_TIME
		  if (model_.useElapsedTime())
		    model_.setDblParam(CbcModel::CbcStartSeconds, CoinGetTimeOfDay());
		  else
		    model_.setDblParam(CbcModel::CbcStartSeconds, CoinCpuTime());
#endif
		  biLinearProblem=false;
                    // check if any integers
#ifndef CBC_OTHER_SOLVER
#ifdef COIN_HAS_ASL
                    if (info.numberSos && doSOS && statusUserFunction_[0]) {
                        // SOS
                        numberSOS = info.numberSos;
                    }
#endif
                    lpSolver = clpSolver->getModelPtr();
                    if (!lpSolver->integerInformation() && !numberSOS &&
                            !clpSolver->numberSOS() && !model_.numberObjects() && !clpSolver->numberObjects())
                        type = CLP_PARAM_ACTION_DUALSIMPLEX;
#endif
                }
                if (type == CBC_PARAM_GENERALQUERY) {
                    bool evenHidden = false;
                    int printLevel =
                        parameters_[whichParam(CLP_PARAM_STR_ALLCOMMANDS,
                                               numberParameters_, parameters_)].currentOptionAsInteger();
                    int convertP[] = {2, 1, 0};
                    printLevel = convertP[printLevel];
                    if ((verbose&8) != 0) {
                        // even hidden
                        evenHidden = true;
                        verbose &= ~8;
                    }
#ifdef COIN_HAS_ASL
                    if (verbose < 4 && statusUserFunction_[0])
                        verbose += 4;
#endif
                    if (verbose < 4) {
                        std::cout << "In argument list keywords have leading - "
                                  ", -stdin or just - switches to stdin" << std::endl;
                        std::cout << "One command per line (and no -)" << std::endl;
                        std::cout << "abcd? gives list of possibilities, if only one + explanation" << std::endl;
                        std::cout << "abcd?? adds explanation, if only one fuller help" << std::endl;
                        std::cout << "abcd without value (where expected) gives current value" << std::endl;
                        std::cout << "abcd value sets value" << std::endl;
                        std::cout << "Commands are:" << std::endl;
                    } else {
                        std::cout << "Cbc options are set within AMPL with commands like:" << std::endl << std::endl;
                        std::cout << "         option cbc_options \"cuts=root log=2 feas=on slog=1\"" << std::endl << std::endl;
                        std::cout << "only maximize, dual, primal, help and quit are recognized without =" << std::endl;
                    }
                    int maxAcross = 10;
                    if ((verbose % 4) != 0)
                        maxAcross = 1;
                    int limits[] = {1, 51, 101, 151, 201, 251, 301, 351, 401};
                    std::vector<std::string> types;
                    types.push_back("Double parameters:");
                    types.push_back("Branch and Cut double parameters:");
                    types.push_back("Integer parameters:");
                    types.push_back("Branch and Cut integer parameters:");
                    types.push_back("Keyword parameters:");
                    types.push_back("Branch and Cut keyword parameters:");
                    types.push_back("Actions or string parameters:");
                    types.push_back("Branch and Cut actions:");
                    int iType;
                    for (iType = 0; iType < 8; iType++) {
                        int across = 0;
                        int lengthLine = 0;
                        if ((verbose % 4) != 0)
                            std::cout << std::endl;
                        std::cout << types[iType] << std::endl;
                        if ((verbose&2) != 0)
                            std::cout << std::endl;
                        for ( iParam = 0; iParam < numberParameters_; iParam++ ) {
                            int type = parameters_[iParam].type();
                            //printf("%d type %d limits %d %d display %d\n",iParam,
                            //     type,limits[iType],limits[iType+1],parameters_[iParam].displayThis());
                            if ((parameters_[iParam].displayThis() >= printLevel || evenHidden) &&
                                    type >= limits[iType]
                                    && type < limits[iType+1]) {
                                // but skip if not useful for ampl (and in ampl mode)
                                if (verbose >= 4 && (parameters_[iParam].whereUsed()&4) == 0)
                                    continue;
                                if (!across) {
                                    if ((verbose&2) != 0)
                                        std::cout << "Command ";
                                }
                                int length = parameters_[iParam].lengthMatchName() + 1;
                                if (lengthLine + length > 80) {
                                    std::cout << std::endl;
                                    across = 0;
                                    lengthLine = 0;
                                }
                                std::cout << " " << parameters_[iParam].matchName();
                                lengthLine += length;
                                across++;
                                if (across == maxAcross) {
                                    across = 0;
                                    if ((verbose % 4) != 0) {
                                        // put out description as well
                                        if ((verbose&1) != 0)
                                            std::cout << " " << parameters_[iParam].shortHelp();
                                        std::cout << std::endl;
                                        if ((verbose&2) != 0) {
                                            std::cout << "---- description" << std::endl;
                                            parameters_[iParam].printLongHelp();
                                            std::cout << "----" << std::endl << std::endl;
                                        }
                                    } else {
                                        std::cout << std::endl;
                                    }
                                }
                            }
                        }
                        if (across)
                            std::cout << std::endl;
                    }
                } else if (type == CBC_PARAM_FULLGENERALQUERY) {
                    std::cout << "Full list of commands is:" << std::endl;
                    int maxAcross = 5;
                    int limits[] = {1, 51, 101, 151, 201, 251, 301, 351, 401};
                    std::vector<std::string> types;
                    types.push_back("Double parameters:");
                    types.push_back("Branch and Cut double parameters:");
                    types.push_back("Integer parameters:");
                    types.push_back("Branch and Cut integer parameters:");
                    types.push_back("Keyword parameters:");
                    types.push_back("Branch and Cut keyword parameters:");
                    types.push_back("Actions or string parameters:");
                    types.push_back("Branch and Cut actions:");
                    int iType;
                    for (iType = 0; iType < 8; iType++) {
                        int across = 0;
                        std::cout << types[iType] << "  ";
                        for ( iParam = 0; iParam < numberParameters_; iParam++ ) {
                            int type = parameters_[iParam].type();
                            if (type >= limits[iType]
                                    && type < limits[iType+1]) {
                                if (!across)
                                    std::cout << "  ";
                                std::cout << parameters_[iParam].matchName() << "  ";
                                across++;
                                if (across == maxAcross) {
                                    std::cout << std::endl;
                                    across = 0;
                                }
                            }
                        }
                        if (across)
                            std::cout << std::endl;
                    }
                } else if (type < 101) {
                    // get next field as double
                    double value = CoinReadGetDoubleField(argc, argv, &valid);
                    if (!valid) {
                        if (type < 51) {
                            int returnCode;
                            const char * message =
                                parameters_[iParam].setDoubleParameterWithMessage(lpSolver, value, returnCode);
                            if (!noPrinting_ && strlen(message)) {
                                generalMessageHandler->message(CLP_GENERAL, generalMessages)
                                << message
                                << CoinMessageEol;
                            }
                        } else if (type < 81) {
                            int returnCode;
                            const char * message =
                                parameters_[iParam].setDoubleParameterWithMessage(model_, value, returnCode);
                            if (!noPrinting_ && strlen(message)) {
                                generalMessageHandler->message(CLP_GENERAL, generalMessages)
                                << message
                                << CoinMessageEol;
                            }
                        } else {
                            int returnCode;
                            const char * message =
                                parameters_[iParam].setDoubleParameterWithMessage(lpSolver, value, returnCode);
                            if (!noPrinting_ && strlen(message)) {
                                generalMessageHandler->message(CLP_GENERAL, generalMessages)
                                << message
                                << CoinMessageEol;
                            }
                            switch (type) {
                            case CBC_PARAM_DBL_DJFIX:
                                djFix = value;
#ifndef CBC_OTHER_SOLVER
                                if (goodModel && djFix < 1.0e20) {
                                    // do some fixing
                                    clpSolver = dynamic_cast< OsiClpSolverInterface*> (model_.solver());
                                    clpSolver->initialSolve();
                                    lpSolver = clpSolver->getModelPtr();
                                    int numberColumns = lpSolver->numberColumns();
                                    int i;
                                    const char * type = lpSolver->integerInformation();
                                    double * lower = lpSolver->columnLower();
                                    double * upper = lpSolver->columnUpper();
                                    double * solution = lpSolver->primalColumnSolution();
                                    double * dj = lpSolver->dualColumnSolution();
                                    int numberFixed = 0;
                                    double dextra4 = parameters_[whichParam(CBC_PARAM_DBL_DEXTRA4, numberParameters_, parameters_)].doubleValue();
                                    if (dextra4)
                                        printf("Multiple for continuous dj fixing is %g\n", dextra4);
                                    for (i = 0; i < numberColumns; i++) {
                                        double djValue = dj[i];
                                        if (!type[i])
                                            djValue *= dextra4;
                                        if (type[i] || dextra4) {
                                            double value = solution[i];
                                            if (value < lower[i] + 1.0e-5 && djValue > djFix) {
                                                solution[i] = lower[i];
                                                upper[i] = lower[i];
                                                numberFixed++;
                                            } else if (value > upper[i] - 1.0e-5 && djValue < -djFix) {
                                                solution[i] = upper[i];
                                                lower[i] = upper[i];
                                                numberFixed++;
                                            }
                                        }
                                    }
                                    sprintf(generalPrint, "%d columns fixed\n", numberFixed);
                                    generalMessageHandler->message(CLP_GENERAL, generalMessages)
                                    << generalPrint
                                    << CoinMessageEol;
                                }
#endif
                                break;
                            case CBC_PARAM_DBL_TIGHTENFACTOR:
                                tightenFactor = value;
                                if (!complicatedInteger)
                                    defaultSettings = false; // user knows what she is doing
                                break;
                            default:
                                break;
                            }
                        }
                    } else if (valid == 1) {
                        std::cout << " is illegal for double parameter " << parameters_[iParam].name() << " value remains " <<
                                  parameters_[iParam].doubleValue() << std::endl;
                    } else {
                        std::cout << parameters_[iParam].name() << " has value " <<
                                  parameters_[iParam].doubleValue() << std::endl;
                    }
                } else if (type < 201) {
                    // get next field as int
                    int value = CoinReadGetIntField(argc, argv, &valid);
                    if (!valid) {
                        if (type < 151) {
                            if (parameters_[iParam].type() == CLP_PARAM_INT_PRESOLVEPASS)
                                preSolve = value;
                            else if (parameters_[iParam].type() == CLP_PARAM_INT_IDIOT)
                                doIdiot = value;
                            else if (parameters_[iParam].type() == CLP_PARAM_INT_SPRINT)
                                doSprint = value;
                            else if (parameters_[iParam].type() == CLP_PARAM_INT_OUTPUTFORMAT)
                                outputFormat = value;
                            else if (parameters_[iParam].type() == CLP_PARAM_INT_SLPVALUE)
                                slpValue = value;
                            else if (parameters_[iParam].type() == CLP_PARAM_INT_CPP)
                                cppValue = value;
                            else if (parameters_[iParam].type() == CLP_PARAM_INT_PRESOLVEOPTIONS)
                                presolveOptions = value;
                            else if (parameters_[iParam].type() == CLP_PARAM_INT_PRINTOPTIONS)
                                printOptions = value;
                            else if (parameters_[iParam].type() == CLP_PARAM_INT_SUBSTITUTION)
                                substitution = value;
                            else if (parameters_[iParam].type() == CLP_PARAM_INT_DUALIZE)
                                dualize = value;
                            else if (parameters_[iParam].type() == CLP_PARAM_INT_PROCESSTUNE)
                                tunePreProcess = value;
                            else if (parameters_[iParam].type() == CLP_PARAM_INT_USESOLUTION)
                                useSolution = value;
                            else if (parameters_[iParam].type() == CLP_PARAM_INT_VERBOSE)
                                verbose = value;
                            int returnCode;
                            const char * message =
                                parameters_[iParam].setIntParameterWithMessage(lpSolver, value, returnCode);
                            if (!noPrinting_ && strlen(message)) {
                                generalMessageHandler->message(CLP_GENERAL, generalMessages)
                                << message
                                << CoinMessageEol;
                            }
                        } else {
                            if (parameters_[iParam].type() == CBC_PARAM_INT_CUTPASS)
                                cutPass = value;
                            else if (parameters_[iParam].type() == CBC_PARAM_INT_CUTPASSINTREE)
                                cutPassInTree = value;
                            else if (parameters_[iParam].type() == CBC_PARAM_INT_STRONGBRANCHING ||
                                     parameters_[iParam].type() == CBC_PARAM_INT_NUMBERBEFORE)
                                strongChanged = true;
                            else if (parameters_[iParam].type() == CBC_PARAM_INT_FPUMPTUNE ||
                                     parameters_[iParam].type() == CBC_PARAM_INT_FPUMPTUNE2 ||
                                     parameters_[iParam].type() == CBC_PARAM_INT_FPUMPITS)
                                pumpChanged = true;
                            else if (parameters_[iParam].type() == CBC_PARAM_INT_EXPERIMENT) {
  			        int addFlags=0;
				// switch on some later features if >999
				if (value>999) {
				  int switchValue=value/1000;
				  const char * message = NULL;
				  value -= 1000*switchValue;
				  parameters_[whichParam(CBC_PARAM_INT_EXPERIMENT, numberParameters_, parameters_)].setIntValue(0/*value*/);
				  switch (switchValue) {
				  default:
				  case 4:
				    // hotstart 500, -200 cut passes
				    message=parameters_[whichParam(CBC_PARAM_INT_MAXHOTITS, numberParameters_, parameters_)].setIntValueWithMessage(500);
                                    if (!noPrinting_&&message) 
                                        generalMessageHandler->message(CLP_GENERAL, generalMessages)
                                        << message << CoinMessageEol;
				    message=parameters_[whichParam(CBC_PARAM_INT_CUTPASS, numberParameters_, parameters_)].setIntValueWithMessage(-200);
                                    if (!noPrinting_&&message) 
                                        generalMessageHandler->message(CLP_GENERAL, generalMessages)
                                        << message << CoinMessageEol;
				  case 3:
				    // multiple 4
				    message=parameters_[whichParam(CBC_PARAM_INT_MULTIPLEROOTS, numberParameters_, parameters_)].setIntValueWithMessage(4);
                                    if (!noPrinting_&&message) 
                                        generalMessageHandler->message(CLP_GENERAL, generalMessages)
                                        << message << CoinMessageEol;
				  case 2:
				    // rens plus all diving at root
				    message=parameters_[whichParam(CBC_PARAM_INT_DIVEOPT, numberParameters_, parameters_)].setIntValueWithMessage(16);
                                    if (!noPrinting_&&message) 
                                        generalMessageHandler->message(CLP_GENERAL, generalMessages)
                                        << message << CoinMessageEol;
				    model_.setNumberAnalyzeIterations(-value);
				    // -tune 7 zero,lagomory,gmi at root - probing on 
				  case 1:
				    tunePreProcess=7;
				    message=parameters_[whichParam(CLP_PARAM_INT_PROCESSTUNE, numberParameters_, parameters_)].setIntValueWithMessage(7);
                                    if (!noPrinting_&&message) 
                                        generalMessageHandler->message(CLP_GENERAL, generalMessages)
                                        << message << CoinMessageEol;
				    //message = parameters_[whichParam(CBC_PARAM_INT_MIPOPTIONS, numberParameters_, parameters_)].setIntValueWithMessage(1025);
                                    //if (!noPrinting_&&message) 
                                    //    generalMessageHandler->message(CLP_GENERAL, generalMessages)
				    //  << message << CoinMessageEol;
				    message=parameters_[whichParam(CBC_PARAM_STR_PROBINGCUTS, numberParameters_, parameters_)].setCurrentOptionWithMessage("on");
				    probingAction = 1;
                                    if (!noPrinting_&&message) 
                                        generalMessageHandler->message(CLP_GENERAL, generalMessages)
                                        << message << CoinMessageEol;
				    message=parameters_[whichParam(CBC_PARAM_STR_ZEROHALFCUTS, numberParameters_, parameters_)].setCurrentOptionWithMessage("root");
                                    if (!noPrinting_&&message) 
                                        generalMessageHandler->message(CLP_GENERAL, generalMessages)
                                        << message << CoinMessageEol;
				    message=parameters_[whichParam(CBC_PARAM_STR_LAGOMORYCUTS, numberParameters_, parameters_)].setCurrentOptionWithMessage("root");
                                    if (!noPrinting_&&message) 
                                        generalMessageHandler->message(CLP_GENERAL, generalMessages)
                                        << message << CoinMessageEol;
#ifdef SWAP_GOMORY
				    GMIAction = 3;
				    message=parameters_[whichParam(CBC_PARAM_STR_GMICUTS, numberParameters_, parameters_)].setCurrentOptionWithMessage("ifmove");
#else
				    GMIAction = 2;
				    message=parameters_[whichParam(CBC_PARAM_STR_GMICUTS, numberParameters_, parameters_)].setCurrentOptionWithMessage("root");
#endif
                                    if (!noPrinting_&&message) 
                                        generalMessageHandler->message(CLP_GENERAL, generalMessages)
                                        << message << CoinMessageEol;
				  }
				  value = 0;
				}
				if (value>=10) {
				  addFlags = 1048576*(value/10);
				  value = value % 10;
				  parameters_[whichParam(CBC_PARAM_INT_EXPERIMENT, numberParameters_, parameters_)].setIntValue(value);
				}
                                if (value >= 1) {
				    int values[]={24003,280003,792003,24003,24003};
				    if (value>=2&&value<=3) {
				      // swap default diving
				      int iParam = whichParam(CBC_PARAM_STR_DIVINGC, numberParameters_, parameters_);
				      parameters_[iParam].setCurrentOption("off");
				      iParam = whichParam(CBC_PARAM_STR_DIVINGP, numberParameters_, parameters_);
				      parameters_[iParam].setCurrentOption("on");
				    }
				    int extra4 = values[value-1]+addFlags;
                                    parameters_[whichParam(CBC_PARAM_INT_EXTRA4, numberParameters_, parameters_)].setIntValue(extra4);
                                    if (!noPrinting_) {
                                        generalMessageHandler->message(CLP_GENERAL, generalMessages)
                                        << "switching on global root cuts for gomory and knapsack"
                                        << CoinMessageEol;
                                        generalMessageHandler->message(CLP_GENERAL, generalMessages)
                                        << "using OSL factorization"
                                        << CoinMessageEol;
                                        generalMessageHandler->message(CLP_GENERAL, generalMessages)
                                        << "extra options - -rens on -extra4 "
					<<extra4<<" -passc 1000!"
                                        << CoinMessageEol;
                                    }
                                    parameters_[whichParam(CBC_PARAM_STR_PROBINGCUTS, numberParameters_, parameters_)].setCurrentOption("forceOnStrong");
                                    probingAction = 8;
                                    parameters_[whichParam(CBC_PARAM_STR_GOMORYCUTS, numberParameters_, parameters_)].setCurrentOption("onGlobal");
                                    gomoryAction = 5;
                                    parameters_[whichParam(CBC_PARAM_STR_KNAPSACKCUTS, numberParameters_, parameters_)].setCurrentOption("onGlobal");
                                    knapsackAction = 5;
                                    parameters_[whichParam(CLP_PARAM_STR_FACTORIZATION, numberParameters_, parameters_)].setCurrentOption("osl");
                                    lpSolver->factorization()->forceOtherFactorization(3);
                                    parameters_[whichParam(CBC_PARAM_INT_MAXHOTITS, numberParameters_, parameters_)].setIntValue(100);
                                    parameters_[whichParam(CBC_PARAM_INT_CUTPASS, numberParameters_, parameters_)].setIntValue(1000);
                                    cutPass = 1000;
                                    parameters_[whichParam(CBC_PARAM_STR_RENS, numberParameters_, parameters_)].setCurrentOption("on");
                                }
                            } else if (parameters_[iParam].type() == CBC_PARAM_INT_STRATEGY) {
                                if (value == 0) {
                                    gomoryGen.setAwayAtRoot(0.05);
                                    int iParam;
                                    iParam = whichParam(CBC_PARAM_INT_DIVEOPT, numberParameters_, parameters_);
                                    parameters_[iParam].setIntValue(-1);
                                    iParam = whichParam(CBC_PARAM_INT_FPUMPITS, numberParameters_, parameters_);
                                    parameters_[iParam].setIntValue(20);
                                    iParam = whichParam(CBC_PARAM_INT_FPUMPTUNE, numberParameters_, parameters_);
                                    parameters_[iParam].setIntValue(1003);
                                    initialPumpTune = 1003;
                                    iParam = whichParam(CLP_PARAM_INT_PROCESSTUNE, numberParameters_, parameters_);
                                    parameters_[iParam].setIntValue(0);
                                    tunePreProcess = 0;
                                    iParam = whichParam(CBC_PARAM_STR_DIVINGC, numberParameters_, parameters_);
                                    parameters_[iParam].setCurrentOption("off");
                                    iParam = whichParam(CBC_PARAM_STR_RINS, numberParameters_, parameters_);
                                    parameters_[iParam].setCurrentOption("off");
                                    iParam = whichParam(CBC_PARAM_STR_PROBINGCUTS, numberParameters_, parameters_);
				    // but not if cuts off
                                    int jParam = whichParam(CBC_PARAM_STR_CUTSSTRATEGY, numberParameters_, parameters_);
				    
                                    jParam = parameters_[jParam].currentOptionAsInteger();
				    if (jParam) {
				      parameters_[iParam].setCurrentOption("on");
				      probingAction = 1;
				    } else {
				      parameters_[iParam].setCurrentOption("off");
				      probingAction = 0;
				    }
                                }
                            }
                            int returnCode;
                            const char * message =
                                parameters_[iParam].setIntParameterWithMessage(model_, value, returnCode);
                            if (!noPrinting_ && strlen(message)) {
                                generalMessageHandler->message(CLP_GENERAL, generalMessages)
                                << message
                                << CoinMessageEol;
                            }
                        }
                    } else if (valid == 1) {
                        std::cout << " is illegal for integer parameter " << parameters_[iParam].name() << " value remains " <<
                                  parameters_[iParam].intValue() << std::endl;
                    } else {
                        std::cout << parameters_[iParam].name() << " has value " <<
                                  parameters_[iParam].intValue() << std::endl;
                    }
                } else if (type < 301) {
                    // one of several strings
                    std::string value = CoinReadGetString(argc, argv);
                    int action = parameters_[iParam].parameterOption(value);
                    if (action < 0) {
                        if (value != "EOL") {
                            // no match
                            parameters_[iParam].printOptions();
                        } else {
                            // print current value
                            std::cout << parameters_[iParam].name() << " has value " <<
                                      parameters_[iParam].currentOption() << std::endl;
                        }
                    } else {
                        const char * message =
                            parameters_[iParam].setCurrentOptionWithMessage(action);
                        if (!noPrinting_ && strlen(message)) {
                            generalMessageHandler->message(CLP_GENERAL, generalMessages)
                            << message
                            << CoinMessageEol;
                        }
                        // for now hard wired
                        switch (type) {
                        case CLP_PARAM_STR_DIRECTION:
                            if (action == 0)
                                lpSolver->setOptimizationDirection(1);
                            else if (action == 1)
                                lpSolver->setOptimizationDirection(-1);
                            else
                                lpSolver->setOptimizationDirection(0);
                            break;
                        case CLP_PARAM_STR_DUALPIVOT:
                            if (action == 0) {
                                ClpDualRowSteepest steep(3);
                                lpSolver->setDualRowPivotAlgorithm(steep);
                            } else if (action == 1) {
                                ClpDualRowDantzig dantzig;
                                //ClpDualRowSteepest dantzig(5);
                                lpSolver->setDualRowPivotAlgorithm(dantzig);
                            } else if (action == 2) {
                                // partial steep
                                ClpDualRowSteepest steep(2);
                                lpSolver->setDualRowPivotAlgorithm(steep);
                            } else {
                                ClpDualRowSteepest steep;
                                lpSolver->setDualRowPivotAlgorithm(steep);
                            }
                            break;
                        case CLP_PARAM_STR_PRIMALPIVOT:
                            if (action == 0) {
                                ClpPrimalColumnSteepest steep(3);
                                lpSolver->setPrimalColumnPivotAlgorithm(steep);
                            } else if (action == 1) {
                                ClpPrimalColumnSteepest steep(0);
                                lpSolver->setPrimalColumnPivotAlgorithm(steep);
                            } else if (action == 2) {
                                ClpPrimalColumnDantzig dantzig;
                                lpSolver->setPrimalColumnPivotAlgorithm(dantzig);
                            } else if (action == 3) {
                                ClpPrimalColumnSteepest steep(4);
                                lpSolver->setPrimalColumnPivotAlgorithm(steep);
                            } else if (action == 4) {
                                ClpPrimalColumnSteepest steep(1);
                                lpSolver->setPrimalColumnPivotAlgorithm(steep);
                            } else if (action == 5) {
                                ClpPrimalColumnSteepest steep(2);
                                lpSolver->setPrimalColumnPivotAlgorithm(steep);
                            } else if (action == 6) {
                                ClpPrimalColumnSteepest steep(10);
                                lpSolver->setPrimalColumnPivotAlgorithm(steep);
                            }
                            break;
                        case CLP_PARAM_STR_SCALING:
                            lpSolver->scaling(action);
                            solver->setHintParam(OsiDoScale, action != 0, OsiHintTry);
                            doScaling = action;
                            break;
                        case CLP_PARAM_STR_AUTOSCALE:
                            lpSolver->setAutomaticScaling(action != 0);
                            break;
                        case CLP_PARAM_STR_SPARSEFACTOR:
                            lpSolver->setSparseFactorization((1 - action) != 0);
                            break;
                        case CLP_PARAM_STR_BIASLU:
                            lpSolver->factorization()->setBiasLU(action);
                            break;
                        case CLP_PARAM_STR_PERTURBATION:
                            if (action == 0)
                                lpSolver->setPerturbation(50);
                            else
                                lpSolver->setPerturbation(100);
                            break;
                        case CLP_PARAM_STR_ERRORSALLOWED:
                            allowImportErrors = action;
                            break;
                        case CLP_PARAM_STR_INTPRINT:
                            printMode = action;
                            break;
                            //case CLP_PARAM_NOTUSED_ALGORITHM:
                            //algorithm  = action;
                            //defaultSettings=false; // user knows what she is doing
                            //abort();
                            //break;
                        case CLP_PARAM_STR_KEEPNAMES:
                            keepImportNames = 1 - action;
                            break;
                        case CLP_PARAM_STR_PRESOLVE:
                            if (action == 0)
                                preSolve = 5;
                            else if (action == 1)
                                preSolve = 0;
                            else if (action == 2)
                                preSolve = 10;
                            else
                                preSolveFile = true;
                            break;
                        case CLP_PARAM_STR_PFI:
                            lpSolver->factorization()->setForrestTomlin(action == 0);
                            break;
                        case CLP_PARAM_STR_FACTORIZATION:
                            lpSolver->factorization()->forceOtherFactorization(action);
                            break;
                        case CLP_PARAM_STR_CRASH:
                            doCrash = action;
                            break;
                        case CLP_PARAM_STR_VECTOR:
                            doVector = action;
                            break;
                        case CLP_PARAM_STR_MESSAGES:
                            lpSolver->messageHandler()->setPrefix(action != 0);
                            break;
                        case CLP_PARAM_STR_CHOLESKY:
                            choleskyType = action;
                            break;
                        case CLP_PARAM_STR_GAMMA:
                            gamma = action;
                            break;
                        case CLP_PARAM_STR_BARRIERSCALE:
                            scaleBarrier = action;
                            break;
                        case CLP_PARAM_STR_KKT:
                            doKKT = action;
                            break;
                        case CLP_PARAM_STR_CROSSOVER:
                            crossover = action;
                            break;
                        case CLP_PARAM_STR_TIME_MODE:
			    model_.setUseElapsedTime(action!=0);
                            break;
                        case CBC_PARAM_STR_SOS:
                            doSOS = action;
                            break;
                        case CBC_PARAM_STR_GOMORYCUTS:
                            defaultSettings = false; // user knows what she is doing
                            gomoryAction = action;
                            break;
                        case CBC_PARAM_STR_PROBINGCUTS:
                            defaultSettings = false; // user knows what she is doing
                            probingAction = action;
                            break;
                        case CBC_PARAM_STR_KNAPSACKCUTS:
                            defaultSettings = false; // user knows what she is doing
                            knapsackAction = action;
                            break;
                        case CBC_PARAM_STR_REDSPLITCUTS:
                            defaultSettings = false; // user knows what she is doing
                            redsplitAction = action;
                            break;
                        case CBC_PARAM_STR_REDSPLIT2CUTS:
                            defaultSettings = false; // user knows what she is doing
                            redsplit2Action = action;
                            break;
                        case CBC_PARAM_STR_GMICUTS:
                            defaultSettings = false; // user knows what she is doing
                            GMIAction = action;
                            break;
                        case CBC_PARAM_STR_CLIQUECUTS:
                            defaultSettings = false; // user knows what she is doing
                            cliqueAction = action;
                            break;
                        case CBC_PARAM_STR_FLOWCUTS:
                            defaultSettings = false; // user knows what she is doing
                            flowAction = action;
                            break;
                        case CBC_PARAM_STR_MIXEDCUTS:
                            defaultSettings = false; // user knows what she is doing
                            mixedAction = action;
                            break;
                        case CBC_PARAM_STR_TWOMIRCUTS:
                            defaultSettings = false; // user knows what she is doing
                            twomirAction = action;
                            break;
                        case CBC_PARAM_STR_LANDPCUTS:
                            defaultSettings = false; // user knows what she is doing
                            landpAction = action;
                            break;
                        case CBC_PARAM_STR_RESIDCUTS:
                            defaultSettings = false; // user knows what she is doing
                            residualCapacityAction = action;
                            break;
                        case CBC_PARAM_STR_ZEROHALFCUTS:
                            defaultSettings = false; // user knows what she is doing
                            zerohalfAction = action;
                            break;
                        case CBC_PARAM_STR_ROUNDING:
                            defaultSettings = false; // user knows what she is doing
                            break;
                        case CBC_PARAM_STR_FPUMP:
                            defaultSettings = false; // user knows what she is doing
                            break;
                        case CBC_PARAM_STR_RINS:
                            break;
                        case CBC_PARAM_STR_DINS:
                            break;
                        case CBC_PARAM_STR_RENS:
                            break;
                        case CBC_PARAM_STR_CUTSSTRATEGY:
                            gomoryAction = action;
                            probingAction = action;
                            knapsackAction = action;
                            cliqueAction = action;
                            flowAction = action;
                            mixedAction = action;
                            twomirAction = action;
                            //landpAction = action;
                            parameters_[whichParam(CBC_PARAM_STR_GOMORYCUTS, numberParameters_, parameters_)].setCurrentOption(action);
                            parameters_[whichParam(CBC_PARAM_STR_PROBINGCUTS, numberParameters_, parameters_)].setCurrentOption(action);
                            parameters_[whichParam(CBC_PARAM_STR_KNAPSACKCUTS, numberParameters_, parameters_)].setCurrentOption(action);
                            parameters_[whichParam(CBC_PARAM_STR_CLIQUECUTS, numberParameters_, parameters_)].setCurrentOption(action);
                            parameters_[whichParam(CBC_PARAM_STR_FLOWCUTS, numberParameters_, parameters_)].setCurrentOption(action);
                            parameters_[whichParam(CBC_PARAM_STR_MIXEDCUTS, numberParameters_, parameters_)].setCurrentOption(action);
                            parameters_[whichParam(CBC_PARAM_STR_TWOMIRCUTS, numberParameters_, parameters_)].setCurrentOption(action);
                            if (!action) {
                                zerohalfAction = action;
				parameters_[whichParam(CBC_PARAM_STR_ZEROHALFCUTS, numberParameters_, parameters_)].setCurrentOption(action);
                                redsplitAction = action;
                                parameters_[whichParam(CBC_PARAM_STR_REDSPLITCUTS, numberParameters_, parameters_)].setCurrentOption(action);
                                redsplit2Action = action;
                                parameters_[whichParam(CBC_PARAM_STR_REDSPLIT2CUTS, numberParameters_, parameters_)].setCurrentOption(action);
                                GMIAction = action;
                                parameters_[whichParam(CBC_PARAM_STR_GMICUTS, numberParameters_, parameters_)].setCurrentOption(action);
                                landpAction = action;
                                parameters_[whichParam(CBC_PARAM_STR_LANDPCUTS, numberParameters_, parameters_)].setCurrentOption(action);
                                residualCapacityAction = action;
                                parameters_[whichParam(CBC_PARAM_STR_RESIDCUTS, numberParameters_, parameters_)].setCurrentOption(action);
                            }
                            break;
                        case CBC_PARAM_STR_HEURISTICSTRATEGY:
                            parameters_[whichParam(CBC_PARAM_STR_ROUNDING, numberParameters_, parameters_)].setCurrentOption(action);
                            parameters_[whichParam(CBC_PARAM_STR_GREEDY, numberParameters_, parameters_)].setCurrentOption(action);
                            parameters_[whichParam(CBC_PARAM_STR_COMBINE, numberParameters_, parameters_)].setCurrentOption(action);
                            //parameters_[whichParam(CBC_PARAM_STR_LOCALTREE,numberParameters_,parameters_)].setCurrentOption(action);
                            parameters_[whichParam(CBC_PARAM_STR_FPUMP, numberParameters_, parameters_)].setCurrentOption(action);
                            parameters_[whichParam(CBC_PARAM_STR_DIVINGC, numberParameters_, parameters_)].setCurrentOption(action);
                            parameters_[whichParam(CBC_PARAM_STR_RINS, numberParameters_, parameters_)].setCurrentOption(action);
                            break;
                        case CBC_PARAM_STR_GREEDY:
                        case CBC_PARAM_STR_DIVINGS:
                        case CBC_PARAM_STR_DIVINGC:
                        case CBC_PARAM_STR_DIVINGF:
                        case CBC_PARAM_STR_DIVINGG:
                        case CBC_PARAM_STR_DIVINGL:
                        case CBC_PARAM_STR_DIVINGP:
                        case CBC_PARAM_STR_DIVINGV:
                        case CBC_PARAM_STR_COMBINE:
                        case CBC_PARAM_STR_PIVOTANDCOMPLEMENT:
                        case CBC_PARAM_STR_PIVOTANDFIX:
                        case CBC_PARAM_STR_RANDROUND:
                        case CBC_PARAM_STR_LOCALTREE:
                        case CBC_PARAM_STR_NAIVE:
                        case CBC_PARAM_STR_CPX:
                            defaultSettings = false; // user knows what she is doing
                            break;
                        case CBC_PARAM_STR_COSTSTRATEGY:
                            useCosts = action;
                            break;
                        case CBC_PARAM_STR_NODESTRATEGY:
                            nodeStrategy = action;
                            break;
                        case CBC_PARAM_STR_PREPROCESS:
                            preProcess = action;
                            break;
                        default:
                            //abort();
                            break;
                        }
                    }
                } else {
                    // action
                    if (type == CLP_PARAM_ACTION_EXIT) {
#ifdef COIN_HAS_ASL
                        if (statusUserFunction_[0]) {
                            if (info.numberIntegers || info.numberBinary) {
                                // integer
                            } else {
                                // linear
                            }
                            writeAmpl(&info);
                            freeArrays2(&info);
                            freeArgs(&info);
                        }
#endif
                        break; // stop all
                    }
                    switch (type) {
                    case CLP_PARAM_ACTION_DUALSIMPLEX:
                    case CLP_PARAM_ACTION_PRIMALSIMPLEX:
                    case CLP_PARAM_ACTION_SOLVECONTINUOUS:
                    case CLP_PARAM_ACTION_BARRIER:
                        if (goodModel) {
                            // Say not in integer
                            integerStatus = -1;
                            double objScale =
                                parameters_[whichParam(CLP_PARAM_DBL_OBJSCALE2, numberParameters_, parameters_)].doubleValue();
                            if (objScale != 1.0) {
                                int iColumn;
                                int numberColumns = lpSolver->numberColumns();
                                double * dualColumnSolution =
                                    lpSolver->dualColumnSolution();
                                ClpObjective * obj = lpSolver->objectiveAsObject();
                                assert(dynamic_cast<ClpLinearObjective *> (obj));
                                double offset;
                                double * objective = obj->gradient(NULL, NULL, offset, true);
                                for (iColumn = 0; iColumn < numberColumns; iColumn++) {
                                    dualColumnSolution[iColumn] *= objScale;
                                    objective[iColumn] *= objScale;;
                                }
                                int iRow;
                                int numberRows = lpSolver->numberRows();
                                double * dualRowSolution =
                                    lpSolver->dualRowSolution();
                                for (iRow = 0; iRow < numberRows; iRow++)
                                    dualRowSolution[iRow] *= objScale;
                                lpSolver->setObjectiveOffset(objScale*lpSolver->objectiveOffset());
                            }
                            ClpSolve::SolveType method;
                            ClpSolve::PresolveType presolveType;
                            ClpSimplex * model2 = lpSolver;
                            if (dualize) {
                                bool tryIt = true;
                                double fractionColumn = 1.0;
                                double fractionRow = 1.0;
                                if (dualize == 3) {
                                    dualize = 1;
                                    int numberColumns = lpSolver->numberColumns();
                                    int numberRows = lpSolver->numberRows();
                                    if (numberRows < 50000 || 5*numberColumns > numberRows) {
                                        tryIt = false;
                                    } else {
                                        fractionColumn = 0.1;
                                        fractionRow = 0.1;
                                    }
                                }
                                if (tryIt) {
                                    model2 = static_cast<ClpSimplexOther *> (model2)->dualOfModel(fractionRow, fractionColumn);
                                    if (model2) {
                                        sprintf(generalPrint, "Dual of model has %d rows and %d columns",
                                                model2->numberRows(), model2->numberColumns());
                                        generalMessageHandler->message(CLP_GENERAL, generalMessages)
                                        << generalPrint
                                        << CoinMessageEol;
                                        model2->setOptimizationDirection(1.0);
                                    } else {
                                        model2 = lpSolver;
                                        dualize = 0;
                                    }
                                } else {
                                    dualize = 0;
                                }
                            }
                            if (noPrinting_)
                                lpSolver->setLogLevel(0);
                            ClpSolve solveOptions;
                            solveOptions.setPresolveActions(presolveOptions);
                            solveOptions.setSubstitution(substitution);
                            if (preSolve != 5 && preSolve) {
                                presolveType = ClpSolve::presolveNumber;
                                if (preSolve < 0) {
                                    preSolve = - preSolve;
                                    if (preSolve <= 100) {
                                        presolveType = ClpSolve::presolveNumber;
                                        sprintf(generalPrint, "Doing %d presolve passes - picking up non-costed slacks",
                                                preSolve);
                                        generalMessageHandler->message(CLP_GENERAL, generalMessages)
                                        << generalPrint
                                        << CoinMessageEol;
                                        solveOptions.setDoSingletonColumn(true);
                                    } else {
                                        preSolve -= 100;
                                        presolveType = ClpSolve::presolveNumberCost;
                                        sprintf(generalPrint, "Doing %d presolve passes - picking up costed slacks",
                                                preSolve);
                                        generalMessageHandler->message(CLP_GENERAL, generalMessages)
                                        << generalPrint
                                        << CoinMessageEol;
                                    }
                                }
                            } else if (preSolve) {
                                presolveType = ClpSolve::presolveOn;
                            } else {
                                presolveType = ClpSolve::presolveOff;
                            }
                            solveOptions.setPresolveType(presolveType, preSolve);
                            if (type == CLP_PARAM_ACTION_DUALSIMPLEX ||
                                    type == CLP_PARAM_ACTION_SOLVECONTINUOUS) {
                                method = ClpSolve::useDual;
                            } else if (type == CLP_PARAM_ACTION_PRIMALSIMPLEX) {
                                method = ClpSolve::usePrimalorSprint;
                            } else {
                                method = ClpSolve::useBarrier;
                                if (crossover == 1) {
                                    method = ClpSolve::useBarrierNoCross;
                                } else if (crossover == 2) {
                                    ClpObjective * obj = lpSolver->objectiveAsObject();
                                    if (obj->type() > 1) {
                                        method = ClpSolve::useBarrierNoCross;
                                        presolveType = ClpSolve::presolveOff;
                                        solveOptions.setPresolveType(presolveType, preSolve);
                                    }
                                }
                            }
                            solveOptions.setSolveType(method);
                            if (preSolveFile)
                                presolveOptions |= 0x40000000;
                            solveOptions.setSpecialOption(4, presolveOptions);
                            solveOptions.setSpecialOption(5, printOptions);
                            if (doVector) {
                                ClpMatrixBase * matrix = lpSolver->clpMatrix();
                                if (dynamic_cast< ClpPackedMatrix*>(matrix)) {
                                    ClpPackedMatrix * clpMatrix = dynamic_cast< ClpPackedMatrix*>(matrix);
                                    clpMatrix->makeSpecialColumnCopy();
                                }
                            }
                            if (method == ClpSolve::useDual) {
                                // dual
                                if (doCrash)
                                    solveOptions.setSpecialOption(0, 1, doCrash); // crash
                                else if (doIdiot)
                                    solveOptions.setSpecialOption(0, 2, doIdiot); // possible idiot
                            } else if (method == ClpSolve::usePrimalorSprint) {
                                // primal
                                // if slp turn everything off
                                if (slpValue > 0) {
                                    doCrash = false;
                                    doSprint = 0;
                                    doIdiot = -1;
                                    solveOptions.setSpecialOption(1, 10, slpValue); // slp
                                    method = ClpSolve::usePrimal;
                                }
                                if (doCrash) {
                                    solveOptions.setSpecialOption(1, 1, doCrash); // crash
                                } else if (doSprint > 0) {
                                    // sprint overrides idiot
                                    solveOptions.setSpecialOption(1, 3, doSprint); // sprint
                                } else if (doIdiot > 0) {
                                    solveOptions.setSpecialOption(1, 2, doIdiot); // idiot
                                } else if (slpValue <= 0) {
                                    if (doIdiot == 0) {
                                        if (doSprint == 0)
                                            solveOptions.setSpecialOption(1, 4); // all slack
                                        else
                                            solveOptions.setSpecialOption(1, 9); // all slack or sprint
                                    } else {
                                        if (doSprint == 0)
                                            solveOptions.setSpecialOption(1, 8); // all slack or idiot
                                        else
                                            solveOptions.setSpecialOption(1, 7); // initiative
                                    }
                                }
                                if (basisHasValues == -1)
                                    solveOptions.setSpecialOption(1, 11); // switch off values
                            } else if (method == ClpSolve::useBarrier || method == ClpSolve::useBarrierNoCross) {
                                int barrierOptions = choleskyType;
                                if (scaleBarrier)
                                    barrierOptions |= 8;
                                if (doKKT)
                                    barrierOptions |= 16;
                                if (gamma)
                                    barrierOptions |= 32 * gamma;
                                if (crossover == 3)
                                    barrierOptions |= 256; // try presolve in crossover
                                solveOptions.setSpecialOption(4, barrierOptions);
                            }
                            model2->setMaximumSeconds(model_.getMaximumSeconds());
#ifdef COIN_HAS_LINK
                            OsiSolverInterface * coinSolver = model_.solver();
                            OsiSolverLink * linkSolver = dynamic_cast< OsiSolverLink*> (coinSolver);
                            if (!linkSolver) {
                                model2->initialSolve(solveOptions);
                            } else {
                                // special solver
                                int testOsiOptions = parameters_[whichParam(CBC_PARAM_INT_TESTOSI, numberParameters_, parameters_)].intValue();
                                double * solution = NULL;
                                if (testOsiOptions < 10) {
                                    solution = linkSolver->nonlinearSLP(slpValue > 0 ? slpValue : 20 , 1.0e-5);
                                } else if (testOsiOptions >= 10) {
                                    CoinModel coinModel = *linkSolver->coinModel();
                                    ClpSimplex * tempModel = approximateSolution(coinModel, slpValue > 0 ? slpValue : 50 , 1.0e-5, 0);
                                    assert (tempModel);
                                    solution = CoinCopyOfArray(tempModel->primalColumnSolution(), coinModel.numberColumns());
                                    model2->setObjectiveValue(tempModel->objectiveValue());
                                    model2->setProblemStatus(tempModel->problemStatus());
                                    model2->setSecondaryStatus(tempModel->secondaryStatus());
                                    delete tempModel;
                                }
                                if (solution) {
                                    memcpy(model2->primalColumnSolution(), solution,
                                           CoinMin(model2->numberColumns(), linkSolver->coinModel()->numberColumns())*sizeof(double));
                                    delete [] solution;
                                } else {
                                    printf("No nonlinear solution\n");
                                }
                            }
#else
                            model2->initialSolve(solveOptions);
#endif
                            {
                                // map states
                                /* clp status
                                   -1 - unknown e.g. before solve or if postSolve says not optimal
                                   0 - optimal
                                   1 - primal infeasible
                                   2 - dual infeasible
                                   3 - stopped on iterations or time
                                   4 - stopped due to errors
                                   5 - stopped by event handler (virtual int ClpEventHandler::event()) */
                                /* cbc status
                                   -1 before branchAndBound
                                   0 finished - check isProvenOptimal or isProvenInfeasible to see if solution found
                                   (or check value of best solution)
                                   1 stopped - on maxnodes, maxsols, maxtime
                                   2 difficulties so run was abandoned
                                   (5 event user programmed event occurred) */
                                /* clp secondary status of problem - may get extended
                                   0 - none
                                   1 - primal infeasible because dual limit reached OR probably primal
                                   infeasible but can't prove it (main status 4)
                                   2 - scaled problem optimal - unscaled problem has primal infeasibilities
                                   3 - scaled problem optimal - unscaled problem has dual infeasibilities
                                   4 - scaled problem optimal - unscaled problem has primal and dual infeasibilities
                                   5 - giving up in primal with flagged variables
                                   6 - failed due to empty problem check
                                   7 - postSolve says not optimal
                                   8 - failed due to bad element check
                                   9 - status was 3 and stopped on time
                                   100 up - translation of enum from ClpEventHandler
                                */
                                /* cbc secondary status of problem
                                   -1 unset (status_ will also be -1)
                                   0 search completed with solution
                                   1 linear relaxation not feasible (or worse than cutoff)
                                   2 stopped on gap
                                   3 stopped on nodes
                                   4 stopped on time
                                   5 stopped on user event
                                   6 stopped on solutions
                                   7 linear relaxation unbounded
                                   8 stopped on iterations limit
                                */
                                int iStatus = model2->status();
                                int iStatus2 = model2->secondaryStatus();
                                if (iStatus == 0) {
                                    iStatus2 = 0;
                                    if (found.type() == CBC_PARAM_ACTION_BAB) {
                                        // set best solution in model as no integers
                                        model_.setBestSolution(model2->primalColumnSolution(),
                                                               model2->numberColumns(),
                                                               model2->getObjValue()*
                                                               model2->getObjSense());
                                    }
                                } else if (iStatus == 1) {
                                    iStatus = 0;
                                    iStatus2 = 1; // say infeasible
                                } else if (iStatus == 2) {
                                    iStatus = 0;
                                    iStatus2 = 7; // say unbounded
                                } else if (iStatus == 3) {
                                    iStatus = 1;
                                    if (iStatus2 == 9)  // what does 9 mean ?????????????
                                        iStatus2 = 4;
                                    else
                                        iStatus2 = 3; // Use nodes - as closer than solutions
                                } else if (iStatus == 4) {
                                    iStatus = 2; // difficulties
                                    iStatus2 = 0;
                                }
                                model_.setProblemStatus(iStatus);
                                model_.setSecondaryStatus(iStatus2);
				if ((iStatus == 2 || iStatus2 > 0) &&
				    !noPrinting_) {
				   std::string statusName[] = {"", "Stopped on ", "Run abandoned", "", "", "User ctrl-c"};
				   std::string minor[] = {"Optimal solution found", "Linear relaxation infeasible", "Optimal solution found (within gap tolerance)", "node limit", "time limit", "user ctrl-c", "solution limit", "Linear relaxation unbounded", "iterations limit", "Problem proven infeasible"};
				   sprintf(generalPrint, "\nResult - %s%s\n\n", 
					   statusName[iStatus].c_str(), 
					   minor[iStatus2].c_str());
				   sprintf(generalPrint + strlen(generalPrint),
					   "Enumerated nodes:           0\n");
				   sprintf(generalPrint + strlen(generalPrint), 
					   "Total iterations:           0\n");
#if CBC_QUIET == 0
				   sprintf(generalPrint + strlen(generalPrint),
					   "Time (CPU seconds):         %.2f\n", 
					   CoinCpuTime() - time0);
				   sprintf(generalPrint + strlen(generalPrint),
					   "Time (Wallclock Seconds):   %.2f\n", 
					   CoinGetTimeOfDay()-time0Elapsed);
#endif
				   generalMessageHandler->message(CLP_GENERAL, generalMessages)
				      << generalPrint
				      << CoinMessageEol;
				}
				//assert (lpSolver==clpSolver->getModelPtr());
                                assert (clpSolver == model_.solver());
                                clpSolver->setWarmStart(NULL);
                                // and in babModel if exists
                                if (babModel_) {
                                    babModel_->setProblemStatus(iStatus);
                                    babModel_->setSecondaryStatus(iStatus2);
                                }
                                int returnCode = callBack(&model, 1);
                                if (returnCode) {
                                    // exit if user wants
                                    delete babModel_;
                                    babModel_ = NULL;
                                    return returnCode;
                                }
                            }
                            basisHasValues = 1;
                            if (dualize) {
                                int returnCode = static_cast<ClpSimplexOther *> (lpSolver)->restoreFromDual(model2);
                                if (model2->status() == 3)
                                    returnCode = 0;
                                delete model2;
                                if (returnCode && dualize != 2)
                                    lpSolver->primal(1);
                                model2 = lpSolver;
                            }
#ifdef COIN_HAS_ASL
                            if (statusUserFunction_[0]) {
			        double value = model2->getObjValue();
                                char buf[300];
                                int pos = 0;
                                int iStat = model2->status();
                                if (iStat == 0) {
                                    pos += sprintf(buf + pos, "optimal," );
                                } else if (iStat == 1) {
                                    // infeasible
                                    pos += sprintf(buf + pos, "infeasible,");
                                } else if (iStat == 2) {
                                    // unbounded
                                    pos += sprintf(buf + pos, "unbounded,");
                                } else if (iStat == 3) {
                                    pos += sprintf(buf + pos, "stopped on iterations or time,");
                                } else if (iStat == 4) {
                                    iStat = 7;
                                    pos += sprintf(buf + pos, "stopped on difficulties,");
                                } else if (iStat == 5) {
                                    iStat = 3;
                                    pos += sprintf(buf + pos, "stopped on ctrl-c,");
                                } else if (iStat == 6) {
                                    // bab infeasible
                                    pos += sprintf(buf + pos, "integer infeasible,");
                                    iStat = 1;
                                } else {
                                    pos += sprintf(buf + pos, "status unknown,");
                                    iStat = 6;
                                }
                                info.problemStatus = iStat;
                                info.objValue = value;
                                pos += sprintf(buf + pos, " objective %.*g", ampl_obj_prec(),
                                               value);
                                sprintf(buf + pos, "\n%d iterations",
                                        model2->getIterationCount());
                                free(info.primalSolution);
                                int numberColumns = model2->numberColumns();
                                info.primalSolution = reinterpret_cast<double *> (malloc(numberColumns * sizeof(double)));
                                CoinCopyN(model2->primalColumnSolution(), numberColumns, info.primalSolution);
                                int numberRows = model2->numberRows();
                                free(info.dualSolution);
                                info.dualSolution = reinterpret_cast<double *> (malloc(numberRows * sizeof(double)));
                                CoinCopyN(model2->dualRowSolution(), numberRows, info.dualSolution);
                                CoinWarmStartBasis * basis = model2->getBasis();
                                free(info.rowStatus);
                                info.rowStatus = reinterpret_cast<int *> (malloc(numberRows * sizeof(int)));
                                free(info.columnStatus);
                                info.columnStatus = reinterpret_cast<int *> (malloc(numberColumns * sizeof(int)));
                                // Put basis in
                                int i;
                                // free,basic,ub,lb are 0,1,2,3
                                for (i = 0; i < numberRows; i++) {
                                    CoinWarmStartBasis::Status status = basis->getArtifStatus(i);
                                    info.rowStatus[i] = status;
                                }
                                for (i = 0; i < numberColumns; i++) {
                                    CoinWarmStartBasis::Status status = basis->getStructStatus(i);
                                    info.columnStatus[i] = status;
                                }
                                // put buffer into info
                                strcpy(info.buffer, buf);
                                delete basis;
                            }
#endif
                        } else {
			  sprintf(generalPrint, "** Current model not valid");
			  printGeneralMessage(model_,generalPrint);
                        }
                        break;
                    case CLP_PARAM_ACTION_STATISTICS:
                        if (goodModel) {
                            // If presolve on look at presolved
                            bool deleteModel2 = false;
                            ClpSimplex * model2 = lpSolver;
                            if (preSolve) {
                                ClpPresolve pinfo;
                                int presolveOptions2 = presolveOptions&~0x40000000;
                                if ((presolveOptions2&0xffff) != 0)
                                    pinfo.setPresolveActions(presolveOptions2);
                                pinfo.setSubstitution(substitution);
                                if ((printOptions&1) != 0)
                                    pinfo.statistics();
                                double presolveTolerance =
                                    parameters_[whichParam(CLP_PARAM_DBL_PRESOLVETOLERANCE, numberParameters_, parameters_)].doubleValue();
                                model2 =
                                    pinfo.presolvedModel(*lpSolver, presolveTolerance,
                                                         true, preSolve);
                                if (model2) {
                                    printf("Statistics for presolved model\n");
                                    deleteModel2 = true;
                                } else {
                                    printf("Presolved model looks infeasible - will use unpresolved\n");
                                    model2 = lpSolver;
                                }
                            } else {
                                printf("Statistics for unpresolved model\n");
                                model2 =  lpSolver;
                            }
                            statistics(lpSolver, model2);
                            if (deleteModel2)
                                delete model2;
                        } else {
			  sprintf(generalPrint, "** Current model not valid");
			  printGeneralMessage(model_,generalPrint);
                        }
                        break;
                    case CLP_PARAM_ACTION_TIGHTEN:
                        if (goodModel) {
                            int numberInfeasibilities = lpSolver->tightenPrimalBounds();
                            if (numberInfeasibilities) {
			      sprintf(generalPrint,"** Analysis indicates model infeasible");
			      printGeneralMessage(model_,generalPrint);
			    }
                        } else {
			  sprintf(generalPrint, "** Current model not valid");
			  printGeneralMessage(model_,generalPrint);
                        }
                        break;
                    case CLP_PARAM_ACTION_PLUSMINUS:
                        if (goodModel) {
                            ClpMatrixBase * saveMatrix = lpSolver->clpMatrix();
                            ClpPackedMatrix* clpMatrix =
                                dynamic_cast< ClpPackedMatrix*>(saveMatrix);
                            if (clpMatrix) {
                                ClpPlusMinusOneMatrix * newMatrix = new ClpPlusMinusOneMatrix(*(clpMatrix->matrix()));
                                if (newMatrix->getIndices()) {
                                    lpSolver->replaceMatrix(newMatrix);
                                    delete saveMatrix;
				    sprintf(generalPrint, "Matrix converted to +- one matrix");
				    printGeneralMessage(model_,generalPrint);
                                } else {
				  sprintf(generalPrint, "Matrix can not be converted to +- 1 matrix");
				  printGeneralMessage(model_,generalPrint);
                                }
                            } else {
			      sprintf(generalPrint, "Matrix not a ClpPackedMatrix");
			      printGeneralMessage(model_,generalPrint);
                            }
                        } else {
			  sprintf(generalPrint, "** Current model not valid");
			  printGeneralMessage(model_,generalPrint);
                        }
                        break;
                    case CLP_PARAM_ACTION_OUTDUPROWS:
                        dominatedCuts = true;
#ifdef JJF_ZERO
                        if (goodModel) {
                            int numberRows = clpSolver->getNumRows();
                            //int nOut = outDupRow(clpSolver);
                            CglDuplicateRow dupcuts(clpSolver);
                            storedCuts = dupcuts.outDuplicates(clpSolver) != 0;
                            int nOut = numberRows - clpSolver->getNumRows();
                            if (nOut && !noPrinting_)
                                sprintf(generalPrint, "%d rows eliminated", nOut);
                            generalMessageHandler->message(CLP_GENERAL, generalMessages)
                            << generalPrint
                            << CoinMessageEol;
                        } else {
			  sprintf(generalPrint, "** Current model not valid");
			  printGeneralMessage(model_,generalPrint);
                        }
#endif
                        break;
                    case CLP_PARAM_ACTION_NETWORK:
                        if (goodModel) {
                            ClpMatrixBase * saveMatrix = lpSolver->clpMatrix();
                            ClpPackedMatrix* clpMatrix =
                                dynamic_cast< ClpPackedMatrix*>(saveMatrix);
                            if (clpMatrix) {
                                ClpNetworkMatrix * newMatrix = new ClpNetworkMatrix(*(clpMatrix->matrix()));
                                if (newMatrix->getIndices()) {
                                    lpSolver->replaceMatrix(newMatrix);
                                    delete saveMatrix;
				    sprintf(generalPrint, "Matrix converted to network matrix");
				    printGeneralMessage(model_,generalPrint);
                                } else {
				  sprintf(generalPrint, "Matrix can not be converted to network matrix");
				  printGeneralMessage(model_,generalPrint);
                                }
                            } else {
			      sprintf(generalPrint, "Matrix not a ClpPackedMatrix");
			      printGeneralMessage(model_,generalPrint);
                            }
                        } else {
			  sprintf(generalPrint, "** Current model not valid");
			  printGeneralMessage(model_,generalPrint);
                        }
                        break;
                    case CBC_PARAM_ACTION_DOHEURISTIC:
                        if (goodModel) {
#ifndef CBC_USE_INITIAL_TIME
			  if (model_.useElapsedTime())
			    model_.setDblParam(CbcModel::CbcStartSeconds, CoinGetTimeOfDay());
			  else
			    model_.setDblParam(CbcModel::CbcStartSeconds, CoinCpuTime());
#endif
                            int vubAction = parameters_[whichParam(CBC_PARAM_INT_VUBTRY, numberParameters_, parameters_)].intValue();
                            if (vubAction != -1) {
                                // look at vubs
                                // extra1 is number of ints to leave free
                                // Just ones which affect >= extra3
                                int extra3 = parameters_[whichParam(CBC_PARAM_INT_EXTRA3, numberParameters_, parameters_)].intValue();
                                /* 2 is cost above which to fix if feasible
                                   3 is fraction of integer variables fixed if relaxing (0.97)
                                   4 is fraction of all variables fixed if relaxing (0.0)
                                */
                                double dextra[6];
                                int extra[5];
                                extra[1] = parameters_[whichParam(CBC_PARAM_INT_EXTRA1, numberParameters_, parameters_)].intValue();
                                int exp1 = parameters_[whichParam(CBC_PARAM_INT_EXPERIMENT, numberParameters_,
                                                                  parameters_)].intValue();
                                if (exp1 == 4 && extra[1] == -1)
                                    extra[1] = 999998;
                                dextra[1] = parameters_[whichParam(CBC_PARAM_DBL_FAKEINCREMENT, numberParameters_, parameters_)].doubleValue();
                                dextra[2] = parameters_[whichParam(CBC_PARAM_DBL_FAKECUTOFF, numberParameters_, parameters_)].doubleValue();
                                dextra[3] = parameters_[whichParam(CBC_PARAM_DBL_DEXTRA3, numberParameters_, parameters_)].doubleValue();
                                dextra[4] = parameters_[whichParam(CBC_PARAM_DBL_DEXTRA4, numberParameters_, parameters_)].doubleValue();
                                dextra[5] = parameters_[whichParam(CBC_PARAM_DBL_DEXTRA5, numberParameters_, parameters_)].doubleValue();
                                if (!dextra[3])
                                    dextra[3] = 0.97;
                                //OsiClpSolverInterface * newSolver =
                                fixVubs(model_, extra3, vubAction, generalMessageHandler,
                                        debugValues, dextra, extra);
                                //assert (!newSolver);
                            }
                            // Actually do heuristics
			    // may need to flip objective
			    bool needFlip = model_.solver()->getObjSense()<0.0;
			    if (needFlip)
			      model_.flipModel(); 
			    //if we do then - fix priorities in clonebutmodel_.convertToDynamic();
			    bool objectsExist = model_.objects() != NULL;
			    if (!objectsExist) {
			      model_.findIntegers(false);
			      model_.convertToDynamic();
			    }
			    // set priorities etc
			    if (priorities) {
			      OsiObject ** objects = model_.objects();
			      int numberObjects = model_.numberObjects();
			      for (int iObj = 0; iObj < numberObjects; iObj++) {
				CbcSimpleInteger * obj =
				  dynamic_cast <CbcSimpleInteger *>(objects[iObj]) ;
				if (!obj)
				  continue;
				int iColumn = obj->columnNumber();
				if (branchDirection) {
				  obj->setPreferredWay(branchDirection[iColumn]);
				}
				if (priorities) {
				  int iPriority = priorities[iColumn];
				  if (iPriority > 0)
				    obj->setPriority(iPriority);
				}
				if (pseudoUp && pseudoUp[iColumn]) {
				  CbcSimpleIntegerPseudoCost * obj1a =
				    dynamic_cast <CbcSimpleIntegerPseudoCost *>(objects[iObj]) ;
				  assert (obj1a);
				  if (pseudoDown[iColumn] > 0.0)
				    obj1a->setDownPseudoCost(pseudoDown[iColumn]);
				  if (pseudoUp[iColumn] > 0.0)
				    obj1a->setUpPseudoCost(pseudoUp[iColumn]);
				}
			      }
			    }
                            doHeuristics(&model_, 2, parameters_,
                                         numberParameters_, noPrinting_, initialPumpTune);
			    if (!objectsExist) {
			      model_.deleteObjects(false);
			    }
			    if (needFlip)
			      model_.flipModel();
                            if (model_.bestSolution()) {
                                model_.setProblemStatus(1);
                                model_.setSecondaryStatus(6);
#ifdef COIN_HAS_ASL
                                if (statusUserFunction_[0]) {
                                    double value = model_.getObjValue();
                                    char buf[300];
                                    int pos = 0;
                                    pos += sprintf(buf + pos, "feasible,");
                                    info.problemStatus = 0;
                                    info.objValue = value;
                                    pos += sprintf(buf + pos, " objective %.*g", ampl_obj_prec(),
                                                   value);
                                    sprintf(buf + pos, "\n0 iterations");
                                    free(info.primalSolution);
                                    int numberColumns = lpSolver->numberColumns();
                                    info.primalSolution = reinterpret_cast<double *> (malloc(numberColumns * sizeof(double)));
                                    CoinCopyN(model_.bestSolution(), numberColumns, info.primalSolution);
                                    int numberRows = lpSolver->numberRows();
                                    free(info.dualSolution);
                                    info.dualSolution = reinterpret_cast<double *> (malloc(numberRows * sizeof(double)));
                                    CoinZeroN(info.dualSolution, numberRows);
                                    CoinWarmStartBasis * basis = lpSolver->getBasis();
                                    free(info.rowStatus);
                                    info.rowStatus = reinterpret_cast<int *> (malloc(numberRows * sizeof(int)));
                                    free(info.columnStatus);
                                    info.columnStatus = reinterpret_cast<int *> (malloc(numberColumns * sizeof(int)));
                                    // Put basis in
                                    int i;
                                    // free,basic,ub,lb are 0,1,2,3
                                    for (i = 0; i < numberRows; i++) {
                                        CoinWarmStartBasis::Status status = basis->getArtifStatus(i);
                                        info.rowStatus[i] = status;
                                    }
                                    for (i = 0; i < numberColumns; i++) {
                                        CoinWarmStartBasis::Status status = basis->getStructStatus(i);
                                        info.columnStatus[i] = status;
                                    }
                                    // put buffer into info
                                    strcpy(info.buffer, buf);
                                    delete basis;
                                }
#endif
                            }
                            int returnCode = callBack(&model, 6);
                            if (returnCode) {
                                // exit if user wants
                                delete babModel_;
                                babModel_ = NULL;
                                return returnCode;
                            }
                        }
                        break;
                    case CBC_PARAM_ACTION_MIPLIB:
                        // User can set options - main difference is lack of model and CglPreProcess
                        goodModel = true;
			parameters_[whichParam(CBC_PARAM_INT_MULTIPLEROOTS, numberParameters_, parameters_)].setIntValue(0);
                        /*
                          Run branch-and-cut. First set a few options -- node comparison, scaling.
                          Print elapsed time at the end.
                        */
                    case CBC_PARAM_ACTION_BAB: // branchAndBound
                        // obsolete case STRENGTHEN:
                        if (goodModel) {
                            bool miplib = type == CBC_PARAM_ACTION_MIPLIB;
                            int logLevel = parameters_[slog].intValue();
			    int truncateColumns=COIN_INT_MAX;
			    int truncateRows=-1;
			    bool redoSOS=false;
			    double * truncatedRhsLower=NULL;
			    double * truncatedRhsUpper=NULL;
			    int * newPriorities=NULL;
                            // Reduce printout
                            if (logLevel <= 1) {
                                model_.solver()->setHintParam(OsiDoReducePrint, true, OsiHintTry);
                            } else {
                                model_.solver()->setHintParam(OsiDoReducePrint, false, OsiHintTry);
                            }
                            {
                                OsiSolverInterface * solver = model_.solver();
#ifndef CBC_OTHER_SOLVER
                                OsiClpSolverInterface * si =
                                    dynamic_cast<OsiClpSolverInterface *>(solver) ;
                                assert (si != NULL);
                                si->getModelPtr()->scaling(doScaling);
                                ClpSimplex * lpSolver = si->getModelPtr();
                                if (doVector) {
                                    ClpMatrixBase * matrix = lpSolver->clpMatrix();
                                    if (dynamic_cast< ClpPackedMatrix*>(matrix)) {
                                        ClpPackedMatrix * clpMatrix = dynamic_cast< ClpPackedMatrix*>(matrix);
                                        clpMatrix->makeSpecialColumnCopy();
                                    }
                                }
#elif CBC_OTHER_SOLVER==1
                                OsiCpxSolverInterface * si =
                                    dynamic_cast<OsiCpxSolverInterface *>(solver) ;
                                assert (si != NULL);
#endif
                                statistics_nrows = si->getNumRows();
                                statistics_ncols = si->getNumCols();
                                statistics_nprocessedrows = si->getNumRows();
                                statistics_nprocessedcols = si->getNumCols();
                                // See if quadratic
#ifndef CBC_OTHER_SOLVER
#ifdef COIN_HAS_LINK
                                if (!complicatedInteger) {
                                    ClpQuadraticObjective * obj = (dynamic_cast< ClpQuadraticObjective*>(lpSolver->objectiveAsObject()));
                                    if (obj) {
                                        preProcess = 0;
                                        int testOsiOptions = parameters_[whichParam(CBC_PARAM_INT_TESTOSI, numberParameters_, parameters_)].intValue();
                                        parameters_[whichParam(CBC_PARAM_INT_TESTOSI, numberParameters_, parameters_)].setIntValue(CoinMax(0, testOsiOptions));
                                        // create coin model
                                        coinModel = lpSolver->createCoinModel();
                                        assert (coinModel);
                                        // load from coin model
                                        OsiSolverLink solver1;
                                        OsiSolverInterface * solver2 = solver1.clone();
                                        model_.assignSolver(solver2, false);
                                        OsiSolverLink * si =
                                            dynamic_cast<OsiSolverLink *>(model_.solver()) ;
                                        assert (si != NULL);
                                        si->setDefaultMeshSize(0.001);
                                        // need some relative granularity
                                        si->setDefaultBound(100.0);
                                        double dextra3 = parameters_[whichParam(CBC_PARAM_DBL_DEXTRA3, numberParameters_, parameters_)].doubleValue();
                                        if (dextra3)
                                            si->setDefaultMeshSize(dextra3);
                                        si->setDefaultBound(1000.0);
                                        si->setIntegerPriority(1000);
                                        si->setBiLinearPriority(10000);
					biLinearProblem=true;
                                        si->setSpecialOptions2(2 + 4 + 8);
                                        CoinModel * model2 = coinModel;
                                        si->load(*model2, true, parameters_[log].intValue());
                                        // redo
                                        solver = model_.solver();
                                        clpSolver = dynamic_cast< OsiClpSolverInterface*> (solver);
                                        lpSolver = clpSolver->getModelPtr();
                                        clpSolver->messageHandler()->setLogLevel(0) ;
                                        testOsiParameters = 0;
                                        complicatedInteger = 2;  // allow cuts
                                        OsiSolverInterface * coinSolver = model_.solver();
                                        OsiSolverLink * linkSolver = dynamic_cast< OsiSolverLink*> (coinSolver);
                                        if (linkSolver->quadraticModel()) {
                                            ClpSimplex * qp = linkSolver->quadraticModel();
                                            //linkSolver->nonlinearSLP(CoinMax(slpValue,10),1.0e-5);
                                            qp->nonlinearSLP(CoinMax(slpValue, 40), 1.0e-5);
                                            qp->primal(1);
                                            OsiSolverLinearizedQuadratic solver2(qp);
                                            const double * solution = NULL;
                                            // Reduce printout
                                            solver2.setHintParam(OsiDoReducePrint, true, OsiHintTry);
                                            CbcModel model2(solver2);
                                            // Now do requested saves and modifications
                                            CbcModel * cbcModel = & model2;
                                            OsiSolverInterface * osiModel = model2.solver();
                                            OsiClpSolverInterface * osiclpModel = dynamic_cast< OsiClpSolverInterface*> (osiModel);
                                            ClpSimplex * clpModel = osiclpModel->getModelPtr();

                                            // Set changed values

                                            CglProbing probing;
                                            probing.setMaxProbe(10);
                                            probing.setMaxLook(10);
                                            probing.setMaxElements(200);
                                            probing.setMaxProbeRoot(50);
                                            probing.setMaxLookRoot(10);
                                            probing.setRowCuts(3);
                                            probing.setUsingObjective(true);
                                            cbcModel->addCutGenerator(&probing, -1, "Probing", true, false, false, -100, -1, -1);
                                            cbcModel->cutGenerator(0)->setTiming(true);

                                            CglGomory gomory;
                                            gomory.setLimitAtRoot(512);
                                            cbcModel->addCutGenerator(&gomory, -98, "Gomory", true, false, false, -100, -1, -1);
                                            cbcModel->cutGenerator(1)->setTiming(true);

                                            CglKnapsackCover knapsackCover;
                                            cbcModel->addCutGenerator(&knapsackCover, -98, "KnapsackCover", true, false, false, -100, -1, -1);
                                            cbcModel->cutGenerator(2)->setTiming(true);

                                            CglRedSplit redSplit;
                                            cbcModel->addCutGenerator(&redSplit, -99, "RedSplit", true, false, false, -100, -1, -1);
                                            cbcModel->cutGenerator(3)->setTiming(true);

                                            CglClique clique;
                                            clique.setStarCliqueReport(false);
                                            clique.setRowCliqueReport(false);
                                            clique.setMinViolation(0.1);
                                            cbcModel->addCutGenerator(&clique, -98, "Clique", true, false, false, -100, -1, -1);
                                            cbcModel->cutGenerator(4)->setTiming(true);

                                            CglMixedIntegerRounding2 mixedIntegerRounding2;
                                            cbcModel->addCutGenerator(&mixedIntegerRounding2, -98, "MixedIntegerRounding2", true, false, false, -100, -1, -1);
                                            cbcModel->cutGenerator(5)->setTiming(true);

                                            CglFlowCover flowCover;
                                            cbcModel->addCutGenerator(&flowCover, -98, "FlowCover", true, false, false, -100, -1, -1);
                                            cbcModel->cutGenerator(6)->setTiming(true);

                                            CglTwomir twomir;
                                            twomir.setMaxElements(250);
                                            cbcModel->addCutGenerator(&twomir, -99, "Twomir", true, false, false, -100, -1, -1);
                                            cbcModel->cutGenerator(7)->setTiming(true);

                                            CbcHeuristicFPump heuristicFPump(*cbcModel);
                                            heuristicFPump.setWhen(13);
                                            heuristicFPump.setMaximumPasses(20);
                                            heuristicFPump.setMaximumRetries(7);
                                            heuristicFPump.setHeuristicName("feasibility pump");
                                            heuristicFPump.setInitialWeight(1);
                                            heuristicFPump.setFractionSmall(0.6);
                                            cbcModel->addHeuristic(&heuristicFPump);

                                            CbcRounding rounding(*cbcModel);
                                            rounding.setHeuristicName("rounding");
                                            cbcModel->addHeuristic(&rounding);

                                            CbcHeuristicLocal heuristicLocal(*cbcModel);
                                            heuristicLocal.setHeuristicName("combine solutions");
                                            heuristicLocal.setSearchType(1);
                                            heuristicLocal.setFractionSmall(0.6);
                                            cbcModel->addHeuristic(&heuristicLocal);

                                            CbcHeuristicGreedyCover heuristicGreedyCover(*cbcModel);
                                            heuristicGreedyCover.setHeuristicName("greedy cover");
                                            cbcModel->addHeuristic(&heuristicGreedyCover);

                                            CbcHeuristicGreedyEquality heuristicGreedyEquality(*cbcModel);
                                            heuristicGreedyEquality.setHeuristicName("greedy equality");
                                            cbcModel->addHeuristic(&heuristicGreedyEquality);

                                            CbcCompareDefault compare;
                                            cbcModel->setNodeComparison(compare);
                                            cbcModel->setNumberBeforeTrust(5);
                                            cbcModel->setSpecialOptions(2);
                                            cbcModel->messageHandler()->setLogLevel(1);
                                            cbcModel->setMaximumCutPassesAtRoot(-100);
                                            cbcModel->setMaximumCutPasses(1);
                                            cbcModel->setMinimumDrop(0.05);
                                            // For branchAndBound this may help
                                            clpModel->defaultFactorizationFrequency();
                                            clpModel->setDualBound(1.0001e+08);
                                            clpModel->setPerturbation(50);
                                            osiclpModel->setSpecialOptions(193);
                                            osiclpModel->messageHandler()->setLogLevel(0);
                                            osiclpModel->setIntParam(OsiMaxNumIterationHotStart, 100);
                                            osiclpModel->setHintParam(OsiDoReducePrint, true, OsiHintTry);
                                            // You can save some time by switching off message building
                                            // clpModel->messagesPointer()->setDetailMessages(100,10000,(int *) NULL);

                                            // Solve

                                            cbcModel->initialSolve();
                                            if (clpModel->tightenPrimalBounds() != 0) {
					      sprintf(generalPrint, "Problem is infeasible - tightenPrimalBounds!");
					      printGeneralMessage(model_,generalPrint);
                                                break;
                                            }
                                            clpModel->dual();  // clean up
                                            cbcModel->initialSolve();
#ifdef CBC_THREAD
                                            int numberThreads = parameters_[whichParam(CBC_PARAM_INT_THREADS, numberParameters_, parameters_)].intValue();
                                            cbcModel->setNumberThreads(numberThreads % 100);
                                            cbcModel->setThreadMode(CoinMin(numberThreads / 100, 7));
#endif
                                            //setCutAndHeuristicOptions(*cbcModel);
                                            cbcModel->branchAndBound();
                                            OsiSolverLinearizedQuadratic * solver3 = dynamic_cast<OsiSolverLinearizedQuadratic *> (model2.solver());
                                            assert (solver3);
                                            solution = solver3->bestSolution();
					    double bestObjectiveValue = solver3->bestObjectiveValue();
					    linkSolver->setBestObjectiveValue(bestObjectiveValue);
					    if (solution) {
					      linkSolver->setBestSolution(solution, solver3->getNumCols());
					    }
                                            CbcHeuristicDynamic3 dynamic(model_);
                                            dynamic.setHeuristicName("dynamic pass thru");
                                            model_.addHeuristic(&dynamic);
                                            // if convex
                                            if ((linkSolver->specialOptions2()&4) != 0 && solution) {
                                                int numberColumns = coinModel->numberColumns();
                                                assert (linkSolver->objectiveVariable() == numberColumns);
                                                // add OA cut
                                                double offset;
                                                double * gradient = new double [numberColumns+1];
                                                memcpy(gradient, qp->objectiveAsObject()->gradient(qp, solution, offset, true, 2),
                                                       numberColumns*sizeof(double));
                                                double rhs = 0.0;
                                                int * column = new int[numberColumns+1];
                                                int n = 0;
                                                for (int i = 0; i < numberColumns; i++) {
                                                    double value = gradient[i];
                                                    if (fabs(value) > 1.0e-12) {
                                                        gradient[n] = value;
                                                        rhs += value * solution[i];
                                                        column[n++] = i;
                                                    }
                                                }
                                                gradient[n] = -1.0;
                                                column[n++] = numberColumns;
                                                storedAmpl.addCut(-COIN_DBL_MAX, offset + 1.0e-7, n, column, gradient);
                                                delete [] gradient;
                                                delete [] column;
                                            }
                                            // could do three way branching round a) continuous b) best solution
                                            printf("obj %g\n", bestObjectiveValue);
                                            linkSolver->initialSolve();
                                        }
                                    }
                                }
#endif
#endif
                                if (logLevel <= 1)
                                    si->setHintParam(OsiDoReducePrint, true, OsiHintTry);
#ifndef CBC_OTHER_SOLVER
                                si->setSpecialOptions(0x40000000);
#endif
                            }
                            if (!miplib) {
                                if (!preSolve) {
                                    model_.solver()->setHintParam(OsiDoPresolveInInitial, false, OsiHintTry);
                                    model_.solver()->setHintParam(OsiDoPresolveInResolve, false, OsiHintTry);
                                }
                                double time1a = CoinCpuTime();
                                OsiSolverInterface * solver = model_.solver();
#ifndef CBC_OTHER_SOLVER
                                OsiClpSolverInterface * si =
                                    dynamic_cast<OsiClpSolverInterface *>(solver) ;
                                if (si)
                                    si->setSpecialOptions(si->specialOptions() | 1024);
#endif
                                model_.initialSolve();
#ifndef CBC_OTHER_SOLVER
                                ClpSimplex * clpSolver = si->getModelPtr();
                                int iStatus = clpSolver->status();
                                int iStatus2 = clpSolver->secondaryStatus();
                                if (iStatus == 0) {
                                    iStatus2 = 0;
                                } else if (iStatus == 1) {
                                    iStatus = 0;
                                    iStatus2 = 1; // say infeasible
                                } else if (iStatus == 2) {
                                    iStatus = 0;
                                    iStatus2 = 7; // say unbounded
                                } else if (iStatus == 3) {
                                    iStatus = 1;
                                    if (iStatus2 == 9)
                                        iStatus2 = 4;
                                    else
                                        iStatus2 = 3; // Use nodes - as closer than solutions
                                } else if (iStatus == 4) {
                                    iStatus = 2; // difficulties
                                    iStatus2 = 0;
                                }
                                model_.setProblemStatus(iStatus);
                                model_.setSecondaryStatus(iStatus2);
                                si->setWarmStart(NULL);
                                int returnCode = callBack(&model_, 1);
                                if (returnCode) {
                                    // exit if user wants
                                    delete babModel_;
                                    babModel_ = NULL;
                                    return returnCode;
                                }
                                if (clpSolver->status() > 0) {
                                    // and in babModel if exists
                                    if (babModel_) {
                                        babModel_->setProblemStatus(iStatus);
                                        babModel_->setSecondaryStatus(iStatus2);
                                    }
                                    if (!noPrinting_) {
                                        iStatus = clpSolver->status();
                                        const char * msg[] = {"infeasible", "unbounded", "stopped",
                                                              "difficulties", "other"
                                                             };
                                        sprintf(generalPrint, "Problem is %s - %.2f seconds",
                                                msg[iStatus-1], CoinCpuTime() - time1a);
                                        generalMessageHandler->message(CLP_GENERAL, generalMessages)
                                        << generalPrint
                                        << CoinMessageEol;
                                    }
                                    break;
                                }
                                clpSolver->setSpecialOptions(clpSolver->specialOptions() | IN_BRANCH_AND_BOUND); // say is Cbc (and in branch and bound)
#elif CBC_OTHER_SOLVER==1
#endif
                                if (!noPrinting_) {
                                    sprintf(generalPrint, "Continuous objective value is %g - %.2f seconds",
                                            solver->getObjValue(), CoinCpuTime() - time1a);
                                    generalMessageHandler->message(CLP_GENERAL, generalMessages)
                                    << generalPrint
                                    << CoinMessageEol;
                                }
                                if (model_.getMaximumNodes() == -987654321) {
                                    // See if No objective!
                                    int numberColumns = clpSolver->getNumCols();
                                    const double * obj = clpSolver->getObjCoefficients();
                                    const double * lower = clpSolver->getColLower();
                                    const double * upper = clpSolver->getColUpper();
                                    int nObj = 0;
                                    for (int i = 0; i < numberColumns; i++) {
                                        if (upper[i] > lower[i] && obj[i])
                                            nObj++;
                                    }
                                    if (!nObj) {
                                        printf("************No objective!!\n");
                                        model_.setMaximumSolutions(1);
                                        // Column copy
                                        CoinPackedMatrix  matrixByCol(*model_.solver()->getMatrixByCol());
                                        //const double * element = matrixByCol.getElements();
                                        //const int * row = matrixByCol.getIndices();
                                        //const CoinBigIndex * columnStart = matrixByCol.getVectorStarts();
                                        const int * columnLength = matrixByCol.getVectorLengths();
                                        for (int i = 0; i < numberColumns; i++) {
                                            double value = (CoinDrand48() + 0.5) * 10000;
                                            value = 10;
                                            value *= columnLength[i];
                                            int iValue = static_cast<int> (value) / 10;
                                            //iValue=1;
                                            clpSolver->setObjCoeff(i, iValue);
                                        }
                                    }
                                }
#ifndef CBC_OTHER_SOLVER
                                if (!complicatedInteger && preProcess == 0 && clpSolver->tightenPrimalBounds(0.0, 0, true) != 0) {
				  sprintf(generalPrint, "Problem is infeasible - tightenPrimalBounds!");
				  printGeneralMessage(model_,generalPrint);
                                    model_.setProblemStatus(0);
                                    model_.setSecondaryStatus(1);
                                    // say infeasible for solution
                                    integerStatus = 6;
                                    // and in babModel if exists
                                    if (babModel_) {
                                        babModel_->setProblemStatus(0);
                                        babModel_->setSecondaryStatus(1);
                                    }
                                    break;
                                }
                                if (clpSolver->dualBound() == 1.0e10) {
                                    ClpSimplex temp = *clpSolver;
                                    temp.setLogLevel(0);
                                    temp.dual(0, 7);
                                    // user did not set - so modify
                                    // get largest scaled away from bound
                                    double largest = 1.0e-12;
                                    double largestScaled = 1.0e-12;
                                    int numberRows = temp.numberRows();
                                    const double * rowPrimal = temp.primalRowSolution();
                                    const double * rowLower = temp.rowLower();
                                    const double * rowUpper = temp.rowUpper();
                                    const double * rowScale = temp.rowScale();
                                    int iRow;
                                    for (iRow = 0; iRow < numberRows; iRow++) {
                                        double value = rowPrimal[iRow];
                                        double above = value - rowLower[iRow];
                                        double below = rowUpper[iRow] - value;
                                        if (above < 1.0e12) {
                                            largest = CoinMax(largest, above);
                                        }
                                        if (below < 1.0e12) {
                                            largest = CoinMax(largest, below);
                                        }
                                        if (rowScale) {
                                            double multiplier = rowScale[iRow];
                                            above *= multiplier;
                                            below *= multiplier;
                                        }
                                        if (above < 1.0e12) {
                                            largestScaled = CoinMax(largestScaled, above);
                                        }
                                        if (below < 1.0e12) {
                                            largestScaled = CoinMax(largestScaled, below);
                                        }
                                    }

                                    int numberColumns = temp.numberColumns();
                                    const double * columnPrimal = temp.primalColumnSolution();
                                    const double * columnLower = temp.columnLower();
                                    const double * columnUpper = temp.columnUpper();
                                    const double * columnScale = temp.columnScale();
                                    int iColumn;
                                    for (iColumn = 0; iColumn < numberColumns; iColumn++) {
                                        double value = columnPrimal[iColumn];
                                        double above = value - columnLower[iColumn];
                                        double below = columnUpper[iColumn] - value;
                                        if (above < 1.0e12) {
                                            largest = CoinMax(largest, above);
                                        }
                                        if (below < 1.0e12) {
                                            largest = CoinMax(largest, below);
                                        }
                                        if (columnScale) {
                                            double multiplier = 1.0 / columnScale[iColumn];
                                            above *= multiplier;
                                            below *= multiplier;
                                        }
                                        if (above < 1.0e12) {
                                            largestScaled = CoinMax(largestScaled, above);
                                        }
                                        if (below < 1.0e12) {
                                            largestScaled = CoinMax(largestScaled, below);
                                        }
                                    }
#ifdef COIN_DEVELOP
                                    if (!noPrinting_)
                                        std::cout << "Largest (scaled) away from bound " << largestScaled
                                                  << " unscaled " << largest << std::endl;
#endif
                                    clpSolver->setDualBound(CoinMax(1.0001e8, CoinMin(100.0*largest, 1.00001e10)));
                                }
                                si->resolve();  // clean up
#endif
                            }
                            // If user made settings then use them
                            if (!defaultSettings) {
                                OsiSolverInterface * solver = model_.solver();
                                if (!doScaling)
                                    solver->setHintParam(OsiDoScale, false, OsiHintTry);
#ifndef CBC_OTHER_SOLVER
                                OsiClpSolverInterface * si =
                                    dynamic_cast<OsiClpSolverInterface *>(solver) ;
                                assert (si != NULL);
                                // get clp itself
                                ClpSimplex * modelC = si->getModelPtr();
                                //if (modelC->tightenPrimalBounds()!=0) {
                                //std::cout<<"Problem is infeasible!"<<std::endl;
                                //break;
                                //}
                                // bounds based on continuous
                                if (tightenFactor && !complicatedInteger) {
                                    if (modelC->tightenPrimalBounds(tightenFactor) != 0) {
				      sprintf(generalPrint, "Problem is infeasible!");
				      printGeneralMessage(model_,generalPrint);
                                        model_.setProblemStatus(0);
                                        model_.setSecondaryStatus(1);
                                        // and in babModel if exists
                                        if (babModel_) {
                                            babModel_->setProblemStatus(0);
                                            babModel_->setSecondaryStatus(1);
                                        }
                                        break;
                                    }
                                }
#endif
                            }
                            // See if we want preprocessing
                            OsiSolverInterface * saveSolver = NULL;
                            CglPreProcess process;
                            // Say integers in sync
                            bool integersOK = true;
                            delete babModel_;
                            babModel_ = new CbcModel(model_);
#ifndef CBC_OTHER_SOLVER
                            int numberChanged = 0;
                            OsiSolverInterface * solver3 = clpSolver->clone();
                            babModel_->assignSolver(solver3);
                            OsiClpSolverInterface * clpSolver2 = dynamic_cast< OsiClpSolverInterface*> (babModel_->solver());
                            if (clpSolver2->messageHandler()->logLevel())
                                clpSolver2->messageHandler()->setLogLevel(1);
                            if (logLevel > -1)
                                clpSolver2->messageHandler()->setLogLevel(logLevel);
                            lpSolver = clpSolver2->getModelPtr();
                            if (lpSolver->factorizationFrequency() == 200 && !miplib) {
                                // User did not touch preset
                                int numberRows = lpSolver->numberRows();
                                const int cutoff1 = 10000;
                                const int cutoff2 = 100000;
                                const int base = 75;
                                const int freq0 = 50;
                                const int freq1 = 200;
                                const int freq2 = 400;
                                const int maximum = 1000;
                                int frequency;
                                if (numberRows < cutoff1)
                                    frequency = base + numberRows / freq0;
                                else if (numberRows < cutoff2)
                                    frequency = base + cutoff1 / freq0 + (numberRows - cutoff1) / freq1;
                                else
                                    frequency = base + cutoff1 / freq0 + (cutoff2 - cutoff1) / freq1 + (numberRows - cutoff2) / freq2;
                                lpSolver->setFactorizationFrequency(CoinMin(maximum, frequency));
                            }
#elif CBC_OTHER_SOLVER==1
                            OsiSolverInterface * solver3 = model_.solver()->clone();
                            babModel_->assignSolver(solver3);
#endif
                            time2 = CoinCpuTime();
                            totalTime += time2 - time1;
                            //time1 = time2;
                            double timeLeft = babModel_->getMaximumSeconds();
                            int numberOriginalColumns = babModel_->solver()->getNumCols();
                            if (preProcess == 7) {
                                // use strategy instead
                                preProcess = 0;
                                useStrategy = true;
#ifdef COIN_HAS_LINK
                                // empty out any cuts
                                if (storedAmpl.sizeRowCuts()) {
                                    printf("Emptying ampl stored cuts as internal preprocessing\n");
                                    CglStored temp;
                                    storedAmpl = temp;
                                }
#endif
                            }
                            if (preProcess && type == CBC_PARAM_ACTION_BAB) {
			      // see whether to switch off preprocessing
			      // only allow SOS and integer
			      OsiObject ** objects = babModel_->objects();
			      int numberObjects = babModel_->numberObjects();
			      for (int iObj = 0; iObj < numberObjects; iObj++) {
				CbcSOS * objSOS =
				  dynamic_cast <CbcSOS *>(objects[iObj]) ;
				CbcSimpleInteger * objSimpleInteger =
				  dynamic_cast <CbcSimpleInteger *>(objects[iObj]) ;
				if (!objSimpleInteger&&!objSOS) {
				  // find all integers anyway
				  babModel_->findIntegers(true);
				  preProcess=0;
				  break;
				}
			      }
			    }
                            if (type == CBC_PARAM_ACTION_BAB) {
                                double limit;
                                clpSolver->getDblParam(OsiDualObjectiveLimit, limit);
                                if (clpSolver->getObjValue()*clpSolver->getObjSense() >=
                                        limit*clpSolver->getObjSense())
                                    preProcess = 0;
                            }
			    if (mipStartBefore.size())
			      {
				CbcModel tempModel=*babModel_;
				assert (babModel_->getNumCols()==model_.getNumCols());
				std::vector< std::string > colNames;
				for ( int i=0 ; (i<model_.solver()->getNumCols()) ; ++i )
				  colNames.push_back( model_.solver()->getColName(i) );
				std::vector< double > x( model_.getNumCols(), 0.0 );
				double obj;
				int status = computeCompleteSolution( &tempModel, colNames, mipStartBefore, &x[0], obj );
				// set cutoff ( a trifle high) 
				if (!status) {
				  double newCutoff = CoinMin(babModel_->getCutoff(),obj+1.0e-4);
				  babModel_->setBestSolution( &x[0], static_cast<int>(x.size()), obj, false );
				  babModel_->setCutoff(newCutoff);
				  babModel_->setSolutionCount(1);
				  model_.setBestSolution( &x[0], static_cast<int>(x.size()), obj, false );
				  model_.setCutoff(newCutoff);
				  model_.setSolutionCount(1);
				}
			      }
                            if (preProcess && type == CBC_PARAM_ACTION_BAB) {
#ifndef CBC_OTHER_SOLVER
                                // See if sos from mps file
                                if (numberSOS == 0 && clpSolver->numberSOS() && doSOS) {
                                    // SOS
                                    numberSOS = clpSolver->numberSOS();
                                    const CoinSet * setInfo = clpSolver->setInfo();
                                    sosStart = new int [numberSOS+1];
                                    sosType = new char [numberSOS];
                                    int i;
                                    int nTotal = 0;
                                    sosStart[0] = 0;
                                    for ( i = 0; i < numberSOS; i++) {
                                        int type = setInfo[i].setType();
                                        int n = setInfo[i].numberEntries();
                                        sosType[i] = static_cast<char>(type);
                                        nTotal += n;
                                        sosStart[i+1] = nTotal;
                                    }
                                    sosIndices = new int[nTotal];
                                    sosReference = new double [nTotal];
                                    for (i = 0; i < numberSOS; i++) {
                                        int n = setInfo[i].numberEntries();
                                        const int * which = setInfo[i].which();
                                        const double * weights = setInfo[i].weights();
                                        int base = sosStart[i];
                                        for (int j = 0; j < n; j++) {
                                            int k = which[j];
                                            sosIndices[j+base] = k;
                                            sosReference[j+base] = weights ? weights[j] : static_cast<double> (j);
                                        }
                                    }
                                }
#endif
                                saveSolver = babModel_->solver()->clone();
                                /* Do not try and produce equality cliques and
                                   do up to 10 passes */
                                OsiSolverInterface * solver2;
                                {
                                    // Tell solver we are in Branch and Cut
                                    saveSolver->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo) ;
                                    // Default set of cut generators
                                    CglProbing generator1;
                                    generator1.setUsingObjective(1);
                                    generator1.setMaxPass(1);
                                    generator1.setMaxPassRoot(1);
                                    generator1.setMaxProbeRoot(CoinMin(3000, saveSolver->getNumCols()));
                                    generator1.setMaxElements(100);
                                    generator1.setMaxElementsRoot(200);
                                    generator1.setMaxLookRoot(50);
                                    if (saveSolver->getNumCols() > 3000)
                                        generator1.setMaxProbeRoot(123);
                                    generator1.setRowCuts(3);
                                    if ((tunePreProcess&1) != 0) {
                                        // heavy probing
                                        generator1.setMaxPassRoot(2);
                                        generator1.setMaxElements(1000);
                                        generator1.setMaxProbeRoot(saveSolver->getNumCols());
					generator1.setMaxLookRoot(saveSolver->getNumCols());
                                    }
                                    if ((babModel_->specialOptions()&65536) != 0)
                                        process.setOptions(1);
                                    // Add in generators
				    if ((model_.moreSpecialOptions()&65536)==0)
				      process.addCutGenerator(&generator1);
                                    int translate[] = {9999, 0, 0, -3, 2, 3, -2, 9999, 4, 5};
                                    process.passInMessageHandler(babModel_->messageHandler());
                                    //process.messageHandler()->setLogLevel(babModel_->logLevel());
#ifdef COIN_HAS_ASL
                                    if (info.numberSos && doSOS && statusUserFunction_[0]) {
                                        // SOS
                                        numberSOS = info.numberSos;
                                        sosStart = info.sosStart;
                                        sosIndices = info.sosIndices;
                                    }
#endif
                                    if (numberSOS && doSOS) {
                                        // SOS
                                        int numberColumns = saveSolver->getNumCols();
                                        char * prohibited = new char[numberColumns];
                                        memset(prohibited, 0, numberColumns);
                                        int n = sosStart[numberSOS];
                                        for (int i = 0; i < n; i++) {
                                            int iColumn = sosIndices[i];
                                            prohibited[iColumn] = 1;
                                        }
                                        process.passInProhibited(prohibited, numberColumns);
                                        delete [] prohibited;
                                    }
                                    if (0) {
				      
				      // Special integers
				      int numberColumns = saveSolver->getNumCols();
				      char * prohibited = new char[numberColumns];
				      memset(prohibited, 0, numberColumns);
				      const CoinPackedMatrix * matrix = saveSolver->getMatrixByCol();
				      const int * columnLength = matrix->getVectorLengths();
				      int numberProhibited=0;
				      for (int iColumn = numberColumns-1; iColumn >=0; iColumn--) {
					if (!saveSolver->isInteger(iColumn)||
					    columnLength[iColumn]>1)
					  break;
					numberProhibited++;
					prohibited[iColumn] = 1;
				      }
				      if (numberProhibited) {
					process.passInProhibited(prohibited, numberColumns);
					printf("**** Treating last %d integers as special - give high priority?\n",numberProhibited);
				      }
				      delete [] prohibited;
                                    }
                                    if (!model_.numberObjects() && true) {
                                        /* model may not have created objects
                                           If none then create
                                        */
                                        model_.findIntegers(true);
                                    }
                                    if (model_.numberObjects()) {
                                        OsiObject ** oldObjects = babModel_->objects();
                                        int numberOldObjects = babModel_->numberObjects();
					if (!numberOldObjects) {
					  oldObjects = model_.objects();
					  numberOldObjects = model_.numberObjects();
					}
                                        // SOS
                                        int numberColumns = saveSolver->getNumCols();
                                        char * prohibited = new char[numberColumns];
                                        memset(prohibited, 0, numberColumns);
                                        int numberProhibited = 0;
                                        for (int iObj = 0; iObj < numberOldObjects; iObj++) {
                                            CbcSOS * obj =
                                                dynamic_cast <CbcSOS *>(oldObjects[iObj]) ;
                                            if (obj) {
                                                int n = obj->numberMembers();
                                                const int * which = obj->members();
                                                for (int i = 0; i < n; i++) {
                                                    int iColumn = which[i];
                                                    prohibited[iColumn] = 1;
                                                    numberProhibited++;
                                                }
                                            }
                                            CbcLotsize * obj2 =
                                                dynamic_cast <CbcLotsize *>(oldObjects[iObj]) ;
                                            if (obj2) {
                                                int iColumn = obj2->columnNumber();
                                                prohibited[iColumn] = 1;
                                                numberProhibited++;
                                            }
                                        }
                                        if (numberProhibited)
                                            process.passInProhibited(prohibited, numberColumns);
                                        delete [] prohibited;
                                    }
                                    int numberPasses = 10;
#ifndef CBC_OTHER_SOLVER
                                    if (doSprint > 0) {
                                        // Sprint for primal solves
                                        ClpSolve::SolveType method = ClpSolve::usePrimalorSprint;
                                        ClpSolve::PresolveType presolveType = ClpSolve::presolveOff;
                                        int numberPasses = 5;
                                        int options[] = {0, 3, 0, 0, 0, 0};
                                        int extraInfo[] = { -1, 20, -1, -1, -1, -1};
                                        extraInfo[1] = doSprint;
                                        int independentOptions[] = {0, 0, 3};
                                        ClpSolve clpSolve(method, presolveType, numberPasses,
                                                          options, extraInfo, independentOptions);
                                        // say use in OsiClp
                                        clpSolve.setSpecialOption(6, 1);
                                        OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (saveSolver);
                                        osiclp->setSolveOptions(clpSolve);
                                        osiclp->setHintParam(OsiDoDualInResolve, false);
                                        // switch off row copy
                                        osiclp->getModelPtr()->setSpecialOptions(osiclp->getModelPtr()->specialOptions() | 256);
                                        osiclp->getModelPtr()->setInfeasibilityCost(1.0e11);
                                    }
#endif
#ifndef CBC_OTHER_SOLVER
                                    {
                                        OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (saveSolver);
                                        osiclp->setSpecialOptions(osiclp->specialOptions() | 1024);
                                        int savePerturbation = osiclp->getModelPtr()->perturbation();
                                        //#define CBC_TEMP1
#ifdef CBC_TEMP1
                                        if (savePerturbation == 50)
                                            osiclp->getModelPtr()->setPerturbation(52); // try less
#endif
					if ((model_.moreSpecialOptions()&65536)!=0)
					  process.setOptions(2+4+8); // no cuts
					cbcPreProcessPointer = & process;
					int saveOptions = osiclp->getModelPtr()->moreSpecialOptions();
					if ((model_.specialOptions()&16777216)!=0&&
					    model_.getCutoff()>1.0e30) {
					  osiclp->getModelPtr()->setMoreSpecialOptions(saveOptions|262144);
					}
					redoSOS=true;
					solver2 = process.preProcessNonDefault(*saveSolver, translate[preProcess], numberPasses,
                                                                               tunePreProcess);
					if (solver2) {
					  model_.setOriginalColumns( process.originalColumns(), solver2->getNumCols() );
					  osiclp->getModelPtr()->setPerturbation(savePerturbation);
					  osiclp->getModelPtr()->setMoreSpecialOptions(saveOptions);
					}
                                    }
#elif CBC_OTHER_SOLVER==1
				    cbcPreProcessPointer = & process;
				    redoSOS=true;
                                    solver2 = process.preProcessNonDefault(*saveSolver, translate[preProcess], numberPasses,
                                                                           tunePreProcess);
#endif
                                    integersOK = false; // We need to redo if CbcObjects exist
                                    // Tell solver we are not in Branch and Cut
                                    saveSolver->setHintParam(OsiDoInBranchAndCut, false, OsiHintDo) ;
                                    if (solver2)
                                        solver2->setHintParam(OsiDoInBranchAndCut, false, OsiHintDo) ;
                                }
#ifdef COIN_HAS_ASL
                                if (!solver2 && statusUserFunction_[0]) {
                                    // infeasible
                                    info.problemStatus = 1;
                                    info.objValue = 1.0e100;
                                    sprintf(info.buffer, "infeasible/unbounded by pre-processing");
                                    info.primalSolution = NULL;
                                    info.dualSolution = NULL;
                                    break;
                                }
#endif
                                if (!noPrinting_) {
                                    if (!solver2) {
                                        sprintf(generalPrint, "Pre-processing says infeasible or unbounded");
                                        generalMessageHandler->message(CLP_GENERAL, generalMessages)
                                        << generalPrint
                                        << CoinMessageEol;
                                    } else {
                                        //printf("processed model has %d rows, %d columns and %d elements\n",
                                        //     solver2->getNumRows(),solver2->getNumCols(),solver2->getNumElements());
                                    }
                                }
                                if (!solver2) {
                                    // say infeasible for solution
                                    integerStatus = 6;
				    delete saveSolver;
				    saveSolver=NULL;
                                    model_.setProblemStatus(0);
                                    model_.setSecondaryStatus(1);
                                    babModel_->setProblemStatus(0);
                                    babModel_->setSecondaryStatus(1);
                                } else {
                                    statistics_nprocessedrows = solver2->getNumRows();
                                    statistics_nprocessedcols = solver2->getNumCols();
                                    model_.setProblemStatus(-1);
                                    babModel_->setProblemStatus(-1);
                                }
                                int returnCode = callBack(babModel_, 2);
                                if (returnCode) {
                                    // exit if user wants
                                    delete babModel_;
                                    babModel_ = NULL;
                                    return returnCode;
                                }
                                if (!solver2)
                                    break;
                                if (model_.bestSolution()) {
                                    // need to redo - in case no better found in BAB
                                    // just get integer part right
                                    const int * originalColumns = process.originalColumns();
                                    int numberColumns = solver2->getNumCols();
                                    double * bestSolution = babModel_->bestSolution();
                                    const double * oldBestSolution = model_.bestSolution();
                                    for (int i = 0; i < numberColumns; i++) {
                                        int jColumn = originalColumns[i];
                                        bestSolution[i] = oldBestSolution[jColumn];
                                    }
                                }
                                //solver2->resolve();
                                if (preProcess == 2) {
				    // names are wrong - redo
				    const int * originalColumns = process.originalColumns();
				    int numberColumns = solver2->getNumCols();
				    OsiSolverInterface * originalSolver = model.solver();
				    for (int i=0;i<numberColumns;i++) {
				      int iColumn = originalColumns[i];
				      solver2->setColName(i,originalSolver->getColName(iColumn));
				    }
                                    OsiClpSolverInterface * clpSolver2 = dynamic_cast< OsiClpSolverInterface*> (solver2);
                                    ClpSimplex * lpSolver = clpSolver2->getModelPtr();
                                    lpSolver->writeMps("presolved.mps", 2, 1, lpSolver->optimizationDirection());
                                    printf("Preprocessed model (minimization) on presolved.mps\n");
                                }
                                {
                                    // look at new integers
                                    int numberOriginalColumns =
                                        process.originalModel()->getNumCols();
                                    const int * originalColumns = process.originalColumns();
                                    OsiClpSolverInterface * osiclp2 = dynamic_cast< OsiClpSolverInterface*> (solver2);
                                    int numberColumns = osiclp2->getNumCols();
                                    OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (saveSolver);
                                    for (int i = 0; i < numberColumns; i++) {
                                        int iColumn = originalColumns[i];
                                        if (iColumn < numberOriginalColumns) {
                                            if (osiclp2->isInteger(i) && !osiclp->isInteger(iColumn))
                                                osiclp2->setOptionalInteger(i); // say optional
                                        }
                                    }
				    // redo existing SOS
				    if (osiclp->numberSOS()) {
				      redoSOS=false;
				      int * back = new int[numberOriginalColumns];
				      for (int i = 0; i < numberOriginalColumns; i++)
					back[i]=-1;
				      for (int i = 0; i < numberColumns; i++) {
                                        int iColumn = originalColumns[i];
					back[iColumn]=i;
				      }
				      int numberSOSOld=osiclp->numberSOS();
				      int numberSOS=osiclp2->numberSOS();
				      assert (numberSOS==numberSOSOld);
				      CoinSet * setInfo = const_cast<CoinSet *>(osiclp2->setInfo());
				      for (int i = 0; i < numberSOS; i++) {
                                        //int type = setInfo[i].setType();
                                        int n = setInfo[i].numberEntries();
                                        int * which = const_cast<int *>(setInfo[i].which());
					for (int j=0;j<n;j++) {
					  int iColumn = which[j];
					  iColumn=back[iColumn];
					  assert(iColumn>=0);
					  which[j]=iColumn;
					}
				      }
				      delete [] back;
				    }
                                }
                                // we have to keep solver2 so pass clone
                                solver2 = solver2->clone();
				// see if extra variables wanted
				int threshold = 
				  parameters_[whichParam(CBC_PARAM_INT_EXTRA_VARIABLES, numberParameters_, parameters_)].intValue();
				int more2 = parameters_[whichParam(CBC_PARAM_INT_MOREMOREMIPOPTIONS, numberParameters_, parameters_)].intValue();
				if (threshold || (more2&(512|1024)) != 0) {
				  int numberColumns = solver2->getNumCols();
				  truncateRows = solver2->getNumRows();
				  bool modifiedModel=false;
				  int highPriority=0;
				  /*
				    normal - no priorities
				    >10000 equal high priority
				    >20000 higher priority for higher cost
				  */
				  if (threshold>10000) {
				    highPriority=threshold/10000;
				    threshold -= 10000*highPriority;
				  }
				  const double * columnLower = solver2->getColLower();
				  const double * columnUpper = solver2->getColUpper();
				  const double * objective = solver2->getObjCoefficients();
				  int numberIntegers = 0;
				  int numberBinary = 0;
				  int numberTotalIntegers=0;
				  double * obj = new double [numberColumns];
				  int * which = new int [numberColumns];
				  for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
				    if (solver2->isInteger(iColumn)) {
				      numberTotalIntegers++;
				      if (columnUpper[iColumn] > columnLower[iColumn]) {
					numberIntegers++;
					if (columnLower[iColumn] == 0.0 && columnUpper[iColumn] == 1)
					  numberBinary++;
				      }
				    }
				  }
				  int numberSort=0;
				  int numberZero=0;
				  int numberZeroContinuous=0;
				  int numberDifferentObj=0;
				  int numberContinuous=0;
				  for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
				    if (columnUpper[iColumn] > columnLower[iColumn]) {
				      if (solver2->isInteger(iColumn)) {
					if (!objective[iColumn]) {
					  numberZero++;
					} else {
					  obj[numberSort]= fabs(objective[iColumn]);
					  which[numberSort++]=iColumn;
					}
				      } else if (objective[iColumn]) {
					numberContinuous++;
				      } else {
					numberZeroContinuous++;
				      }
				    }
				  }
				  CoinSort_2(obj,obj+numberSort,which);
				  double last=obj[0];
				  for (int jColumn = 1; jColumn < numberSort; jColumn++) {
				    if (fabs(obj[jColumn]-last)>1.0e-12) {
				      numberDifferentObj++;
				      last=obj[jColumn];
				    }
				  }
				  numberDifferentObj++;
				  sprintf(generalPrint,"Problem has %d integers (%d of which binary) and %d continuous",
					 numberIntegers,numberBinary,numberColumns-numberIntegers);
				  generalMessageHandler->message(CLP_GENERAL, generalMessages)
                                    << generalPrint
                                    << CoinMessageEol;
				  if (numberColumns>numberIntegers) {
				    sprintf(generalPrint,"%d continuous have nonzero objective, %d have zero objective",
					    numberContinuous,numberZeroContinuous);
				    generalMessageHandler->message(CLP_GENERAL, generalMessages)
				      << generalPrint
				      << CoinMessageEol;
				  }
				  sprintf(generalPrint,"%d integer have nonzero objective, %d have zero objective, %d different nonzero (taking abs)",
					  numberSort,numberZero,numberDifferentObj);
				  generalMessageHandler->message(CLP_GENERAL, generalMessages)
                                    << generalPrint
                                    << CoinMessageEol;
				  if (numberDifferentObj<=threshold + (numberZero) ? 1 : 0 && numberDifferentObj) {
				    int * backward=NULL;
				    if (highPriority) {
				      newPriorities = new int [numberTotalIntegers+numberDifferentObj+numberColumns];
				      backward=newPriorities+numberTotalIntegers+numberDifferentObj;
				      numberTotalIntegers=0;
				      for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
					if (solver2->isInteger(iColumn)) {
					  backward[iColumn]=numberTotalIntegers;
					  newPriorities[numberTotalIntegers++]=10000;
					}
				      }
				    }
				    int iLast=0;
				    double last=obj[0];
				    for (int jColumn = 1; jColumn < numberSort; jColumn++) {
				      if (fabs(obj[jColumn]-last)>1.0e-12) {
					sprintf(generalPrint,"%d variables have objective of %g",
					       jColumn-iLast,last);
					generalMessageHandler->message(CLP_GENERAL, generalMessages)
					  << generalPrint
					  << CoinMessageEol;
					iLast=jColumn;
					last=obj[jColumn];
				      }
				    }
				    sprintf(generalPrint,"%d variables have objective of %g",
					   numberSort-iLast,last);
				    generalMessageHandler->message(CLP_GENERAL, generalMessages)
				      << generalPrint
				      << CoinMessageEol;
				    int spaceNeeded=numberSort+numberDifferentObj;
				    int * columnAdd = new int[spaceNeeded+numberDifferentObj+1];
				    double * elementAdd = new double[spaceNeeded];
				    int * rowAdd = new int[numberDifferentObj+1];
				    double * objectiveNew = new double[3*numberDifferentObj];
				    double * lowerNew = objectiveNew+numberDifferentObj;
				    double * upperNew = lowerNew+numberDifferentObj;
				    memset(columnAdd+spaceNeeded,0,
					   (numberDifferentObj+1)*sizeof(int));
				    iLast=0;
				    last=obj[0];
				    numberDifferentObj=0;
				    int priorityLevel=9999;
				    int numberElements=0;
				    rowAdd[0]=0;
				    for (int jColumn = 1; jColumn < numberSort+1; jColumn++) {
				      if (jColumn==numberSort||fabs(obj[jColumn]-last)>1.0e-12) {
					// not if just one
					if (jColumn-iLast>1) {
					  // do priority
					  if (highPriority==1) {
					    newPriorities[numberTotalIntegers+numberDifferentObj]
					      = 500;
					  } else if (highPriority==2) {
					    newPriorities[numberTotalIntegers+numberDifferentObj]
					      = priorityLevel;
					    priorityLevel--;
					  }
					  int iColumn=which[iLast];
					  objectiveNew[numberDifferentObj]=objective[iColumn];
					  double lower=0.0;
					  double upper=0.0;
					  for (int kColumn=iLast;kColumn<jColumn;kColumn++) {
					    iColumn=which[kColumn];
					    solver2->setObjCoeff(iColumn,0.0);
					    double lowerValue=columnLower[iColumn];
					    double upperValue=columnUpper[iColumn];
					    double elementValue=-1.0;
					    if (objectiveNew[numberDifferentObj]*objective[iColumn]<0.0) {
					      lowerValue=-columnUpper[iColumn];
					      upperValue=-columnLower[iColumn];
					      elementValue=1.0;
					    }
					    columnAdd[numberElements]=iColumn;
					    elementAdd[numberElements++]=elementValue;
					    if (lower!=-COIN_DBL_MAX) {
					      if (lowerValue!=-COIN_DBL_MAX)
						lower += lowerValue;
					      else
						lower=-COIN_DBL_MAX;
					    }
					    if (upper!=COIN_DBL_MAX) {
					      if (upperValue!=COIN_DBL_MAX)
						upper += upperValue;
					      else
						upper=COIN_DBL_MAX;
					    }
					  }
					  columnAdd[numberElements]=numberColumns+numberDifferentObj;
					  elementAdd[numberElements++]=1.0;
					  lowerNew[numberDifferentObj]=lower;
					  upperNew[numberDifferentObj]=upper;
					  numberDifferentObj++;
					  rowAdd[numberDifferentObj]=numberElements;
					} else if (highPriority) {
					  // just one
					  // do priority
					  int iColumn=which[iLast];
					  int iInt=backward[iColumn];
					  if (highPriority==1) {
					    newPriorities[iInt] = 500;
					  } else {
					    newPriorities[iInt] = priorityLevel;
					    priorityLevel--;
					  }
					}
					if (jColumn<numberSort) {
					  iLast=jColumn;
					  last=obj[jColumn];
					}
				      }
				    }
				    if (numberDifferentObj) {
				      // add columns
				      solver2->addCols(numberDifferentObj, 
						       columnAdd+spaceNeeded, NULL, NULL,
						       lowerNew, upperNew,objectiveNew);
				      // add constraints and make integer if all integer in group
				      for (int iObj=0; iObj < numberDifferentObj; iObj++) {
					lowerNew[iObj]=0.0;
					upperNew[iObj]=0.0;
					solver2->setInteger(numberColumns+iObj);
				      }
				      solver2->addRows(numberDifferentObj, 
						       rowAdd,columnAdd,elementAdd,
						       lowerNew, upperNew);
				      sprintf(generalPrint,"Replacing model - %d new variables",numberDifferentObj);
				      modifiedModel=true;
				    }
				    delete [] columnAdd;
				    delete [] elementAdd;
				    delete [] rowAdd;
				    delete [] objectiveNew;
				  }
				  delete [] which;
				  delete [] obj;
				  if ((more2&(512|1024)) != 0) {
				    // try for row slacks etc
				    // later do row branching
				    int iRow, iColumn;
				    int numberColumns = solver2->getNumCols();
				    int numberRows = solver2->getNumRows();
				    int fudgeObjective = more2&512;
				    int addSlacks = more2&1024;
				    if (fudgeObjective) {
				      bool moveObj = false;
				      fudgeObjective = 0;
				      const double * objective = solver2->getObjCoefficients();
				      const double * columnLower = solver2->getColLower();
				      const double * columnUpper = solver2->getColUpper();
				      double * newValues = new double [numberColumns+1];
				      int * newColumn = new int [numberColumns+1];
				      bool allInteger=true;
				      int n=0;
				      double newLower = 0.0;
				      double newUpper = 0.0;
				      for (iColumn=0;iColumn<numberColumns;iColumn++) {
					if (objective[iColumn]) {
					  if (!solver2->isInteger(iColumn)) {
					    allInteger=false;
					    break;
					  } else {
					    double value = objective[iColumn];
					    double nearest = floor(value+0.5);
					    if (fabs(value-nearest)>1.0e-8) {
					      allInteger=false;
					      break;
					    } else {
					      newValues[n]=nearest;
					      newColumn[n++]=iColumn;
					      if (nearest>0.0) {
						newLower += CoinMax(columnLower[iColumn],-1.0e20)*nearest;
						newUpper += CoinMin(columnUpper[iColumn],1.0e20)*nearest;
					      } else {
						newUpper += CoinMax(columnLower[iColumn],-1.0e20)*nearest;
						newLower += CoinMin(columnUpper[iColumn],1.0e20)*nearest;
					      }
					    }
					  }
					}
				      }
				      if (allInteger && n) {
					fudgeObjective = n;
					solver2->addCol(0,NULL,NULL,newLower,newUpper,0.0,"obj_col");
					solver2->setInteger(numberColumns);
					newValues[n]=-1.0;
					newColumn[n++]=numberColumns;
					solver2->addRow(n,newColumn,newValues,0.0,0.0);
					if (moveObj) {
					  memset(newValues,0,numberColumns*sizeof(double));
					  newValues[numberColumns]=1.0;
					  solver2->setObjective(newValues);
					}
					numberRows++;
					numberColumns++;
				      }
				      delete [] newValues;
				      delete [] newColumn;
				    }
				    if (addSlacks) {
				      bool moveObj = false;
				      addSlacks=0;
				      // get row copy
				      const CoinPackedMatrix * matrix = solver2->getMatrixByRow();
				      const double * element = matrix->getElements();
				      const int * column = matrix->getIndices();
				      const CoinBigIndex * rowStart = matrix->getVectorStarts();
				      const int * rowLength = matrix->getVectorLengths();
				      const double * rowLower = solver2->getRowLower();
				      const double * rowUpper = solver2->getRowUpper();
				      const double * columnLower = solver2->getColLower();
				      const double * columnUpper = solver2->getColUpper();
				      
				      // maximum space for additional columns
				      CoinBigIndex * newColumnStart = new CoinBigIndex[numberRows+1];
				      newColumnStart[0]=0;
				      int * newRow = new int [numberRows];
				      double * newElement = new double [numberRows]; 
				      double * newObjective = new double [numberRows]; 
				      double * newColumnLower = new double [numberRows]; 
				      double * newColumnUpper = new double [numberRows];
				      double * oldObjective = CoinCopyOfArray(solver2->getObjCoefficients(),
									      numberColumns);
				      for (iRow=0;iRow<numberRows;iRow++) {
					if (rowLower[iRow]!=rowUpper[iRow]) {
					  bool allInteger=true;
					  double newLower = 0.0;
					  double newUpper = 0.0;
					  double constantObjective=0.0;
					  for (int j=rowStart[iRow];j<rowStart[iRow]+rowLength[iRow];j++) {
					    int iColumn = column[j];
					    if (!solver2->isInteger(iColumn)) {
					      allInteger=false;
					      break;
					    } else {
					      double value = element[j];
					      double nearest = floor(value+0.5);
					      if (fabs(value-nearest)>1.0e-8) {
						allInteger=false;
						break;
					      } else {
						if (!oldObjective[iColumn])
						  constantObjective=COIN_DBL_MAX;
						if (!constantObjective) {
						  constantObjective=oldObjective[iColumn]/nearest;
						} else if (constantObjective!=COIN_DBL_MAX) {
						  double newConstant=oldObjective[iColumn]/nearest;
						  if (constantObjective>0.0) {
						    if (newConstant<=0.0)
						      constantObjective=COIN_DBL_MAX;
						    else
						      constantObjective=CoinMin(constantObjective,newConstant);
						  } else {
						    if (newConstant>=0.0)
						      constantObjective=COIN_DBL_MAX;
						    else
						      constantObjective=CoinMax(constantObjective,newConstant);
						  }
						}
						if (nearest>0.0) {
						  newLower += CoinMax(columnLower[iColumn],-1.0e20)*nearest;
						  newUpper += CoinMin(columnUpper[iColumn],1.0e20)*nearest;
						} else {
						  newUpper += CoinMax(columnLower[iColumn],-1.0e20)*nearest;
						  newLower += CoinMin(columnUpper[iColumn],1.0e20)*nearest;
						}
					      }
					    }
					  }
					  if (allInteger) {
					    newColumnStart[addSlacks+1]=addSlacks+1;
					    newRow[addSlacks]=iRow;
					    newElement[addSlacks]=-1.0;
					    newObjective[addSlacks] = 0.0;
					    if (moveObj && constantObjective != COIN_DBL_MAX) {
					      // move some of objective here if looks constant
					      newObjective[addSlacks]=constantObjective;
					      for (int j=rowStart[iRow];j<rowStart[iRow]+rowLength[iRow];j++) {
						int iColumn = column[j];
						double value = element[j];
						double nearest = floor(value+0.5);
						oldObjective[iColumn] -= nearest*constantObjective;
					      }
					    }
					    newColumnLower[addSlacks] = CoinMax(newLower,ceil(rowLower[iRow]));;
					    newColumnUpper[addSlacks] = CoinMin(newUpper,floor(rowUpper[iRow]));
					    addSlacks++;
					  }
					}
				      }
				      if (addSlacks) {
					solver2->setObjective(oldObjective);
					solver2->addCols(addSlacks,newColumnStart,newRow,newElement,
							 newColumnLower,newColumnUpper,newObjective);
					truncatedRhsLower = CoinCopyOfArray(solver2->getRowLower(),numberRows);
					truncatedRhsUpper = CoinCopyOfArray(solver2->getRowUpper(),numberRows);
					for (int j=0;j<addSlacks;j++) {
					  int iRow = newRow[j];
					  solver2->setRowLower(iRow,0.0);
					  solver2->setRowUpper(iRow,0.0);
					  int iColumn = j+numberColumns;
					  solver2->setInteger(iColumn);
					  std::string name = solver2->getRowName(iRow);
					  name += "_int";
					  solver2->setColName(iColumn,name);
					}
				      }
				    }
				    if (fudgeObjective||addSlacks) {
				      modifiedModel=true;
				      if (fudgeObjective && addSlacks) {
					sprintf(generalPrint,"Objective integer added with %d elements and %d Integer slacks added",
						fudgeObjective,addSlacks);
				      } else if (fudgeObjective) {
					// just objective
					sprintf(generalPrint,"Objective integer added with %d elements",
					       fudgeObjective);
					more2 &= ~1024;
				      } else {
					// just slacks
					sprintf(generalPrint,"%d Integer slacks added",addSlacks);
					more2 &= ~512;
				      }
				    } else {
				      more2 &= ~(512|1024);
				    }
				    parameters_[whichParam(CBC_PARAM_INT_MOREMOREMIPOPTIONS, numberParameters_, parameters_)].setIntValue(more2);
				  }
				  if (modifiedModel) {
				    generalMessageHandler->message(CLP_GENERAL, generalMessages)
				      << generalPrint
				      << CoinMessageEol;
				    truncateColumns=numberColumns;
				  }
				}
                                babModel_->assignSolver(solver2);
                                babModel_->setOriginalColumns(process.originalColumns(),
							      truncateColumns);
                                babModel_->initialSolve();
                                babModel_->setMaximumSeconds(timeLeft - (CoinCpuTime() - time2));
                            }
                            // now tighten bounds
                            if (!miplib) {
#ifndef CBC_OTHER_SOLVER
                                OsiClpSolverInterface * si =
                                    dynamic_cast<OsiClpSolverInterface *>(babModel_->solver()) ;
                                assert (si != NULL);
                                // get clp itself
                                ClpSimplex * modelC = si->getModelPtr();
                                //if (noPrinting_)
                                //modelC->setLogLevel(0);
                                if (!complicatedInteger && modelC->tightenPrimalBounds() != 0) {
				  sprintf(generalPrint, "Problem is infeasible!");
				  printGeneralMessage(model_,generalPrint);
                                    model_.setProblemStatus(0);
                                    model_.setSecondaryStatus(1);
                                    // say infeasible for solution
                                    integerStatus = 6;
				    delete saveSolver;
				    saveSolver=NULL;
                                    // and in babModel_ if exists
                                    if (babModel_) {
                                        babModel_->setProblemStatus(0);
                                        babModel_->setSecondaryStatus(1);
                                    }
                                    break;
                                }
                                si->resolve();
#elif CBC_OTHER_SOLVER==1
#endif
                            }
                            if (debugValues) {
                                // for debug
                                std::string problemName ;
                                babModel_->solver()->getStrParam(OsiProbName, problemName) ;
                                babModel_->solver()->activateRowCutDebugger(problemName.c_str()) ;
                                twomirGen.probname_ = CoinStrdup(problemName.c_str());
                                // checking seems odd
                                //redsplitGen.set_given_optsol(babModel_->solver()->getRowCutDebuggerAlways()->optimalSolution(),
                                //                         babModel_->getNumCols());
                            }
                            int testOsiOptions = parameters_[whichParam(CBC_PARAM_INT_TESTOSI, numberParameters_, parameters_)].intValue();
                            //#ifdef COIN_HAS_ASL
#ifndef JJF_ONE
                            // If linked then see if expansion wanted
                            {
                                OsiSolverLink * solver3 = dynamic_cast<OsiSolverLink *> (babModel_->solver());
                                int options = parameters_[whichParam(CBC_PARAM_INT_MIPOPTIONS, numberParameters_, parameters_)].intValue() / 10000;
                                if (solver3 || (options&16) != 0) {
                                    if (options) {
                                        /*
                                          1 - force mini branch and bound
                                          2 - set priorities high on continuous
                                          4 - try adding OA cuts
                                          8 - try doing quadratic linearization
                                          16 - try expanding knapsacks
                                        */
                                        if ((options&16)) {
                                            int numberColumns = saveCoinModel.numberColumns();
                                            int numberRows = saveCoinModel.numberRows();
                                            whichColumn = new int[numberColumns];
                                            knapsackStart = new int[numberRows+1];
                                            knapsackRow = new int[numberRows];
                                            numberKnapsack = 10000;
                                            int extra1 = parameters_[whichParam(CBC_PARAM_INT_EXTRA1, numberParameters_, parameters_)].intValue();
                                            int extra2 = parameters_[whichParam(CBC_PARAM_INT_EXTRA2, numberParameters_, parameters_)].intValue();
                                            int logLevel = parameters_[log].intValue();
                                            OsiSolverInterface * solver = expandKnapsack(saveCoinModel, whichColumn, knapsackStart,
                                                                          knapsackRow, numberKnapsack,
                                                                          storedAmpl, logLevel, extra1, extra2,
                                                                          saveTightenedModel);
                                            if (solver) {
#ifndef CBC_OTHER_SOLVER
                                                clpSolver = dynamic_cast< OsiClpSolverInterface*> (solver);
                                                assert (clpSolver);
                                                lpSolver = clpSolver->getModelPtr();
#endif
                                                babModel_->assignSolver(solver);
                                                testOsiOptions = 0;
                                                // allow gomory
                                                complicatedInteger = 0;
#ifdef COIN_HAS_ASL
                                                // Priorities already done
                                                free(info.priorities);
                                                info.priorities = NULL;
#endif
                                            } else {
                                                numberKnapsack = 0;
                                                delete [] whichColumn;
                                                delete [] knapsackStart;
                                                delete [] knapsackRow;
                                                whichColumn = NULL;
                                                knapsackStart = NULL;
                                                knapsackRow = NULL;
                                            }
                                        }
                                    }
                                }
                            }
#endif
                            if (useCosts && testOsiOptions < 0) {
                                int numberColumns = babModel_->getNumCols();
                                int * sort = new int[numberColumns];
                                double * dsort = new double[numberColumns];
                                int * priority = new int [numberColumns];
                                const double * objective = babModel_->getObjCoefficients();
                                const double * lower = babModel_->getColLower() ;
                                const double * upper = babModel_->getColUpper() ;
                                const CoinPackedMatrix * matrix = babModel_->solver()->getMatrixByCol();
                                const int * columnLength = matrix->getVectorLengths();
                                int iColumn;
                                int n = 0;
                                for (iColumn = 0; iColumn < numberColumns; iColumn++) {
                                    if (babModel_->isInteger(iColumn)) {
                                        sort[n] = n;
                                        if (useCosts == 1)
                                            dsort[n++] = -fabs(objective[iColumn]);
                                        else if (useCosts == 2)
                                            dsort[n++] = iColumn;
                                        else if (useCosts == 3)
                                            dsort[n++] = upper[iColumn] - lower[iColumn];
                                        else if (useCosts == 4)
                                            dsort[n++] = -(upper[iColumn] - lower[iColumn]);
                                        else if (useCosts == 5)
                                            dsort[n++] = -columnLength[iColumn];
                                        else if (useCosts == 6)
					    dsort[n++] = (columnLength[iColumn]==1) ? -1.0 : 0.0;
                                        else if (useCosts == 7)
					    dsort[n++] = (objective[iColumn]) ? -1.0 : 0.0;
                                    }
                                }
                                CoinSort_2(dsort, dsort + n, sort);
                                int level = 0;
                                double last = -1.0e100;
                                for (int i = 0; i < n; i++) {
                                    int iPut = sort[i];
                                    if (dsort[i] != last) {
                                        level++;
                                        last = dsort[i];
                                    }
                                    priority[iPut] = level;
                                }
				if(newPriorities ) {
				  // get rid of
				  delete [] newPriorities;
				  newPriorities = NULL;
				}
                                babModel_->passInPriorities( priority, false);
                                integersOK = true;
                                delete [] priority;
                                delete [] sort;
                                delete [] dsort;
                            }
                            // Set up heuristics
                            doHeuristics(babModel_, ((!miplib) ? 1 : 10), parameters_,
                                         numberParameters_, noPrinting_, initialPumpTune);
                            if (!miplib) {
                                if (parameters_[whichParam(CBC_PARAM_STR_LOCALTREE, numberParameters_, parameters_)].currentOptionAsInteger()) {
                                    CbcTreeLocal localTree(babModel_, NULL, 10, 0, 0, 10000, 2000);
                                    babModel_->passInTreeHandler(localTree);
                                }
                            }
                            if (type == CBC_PARAM_ACTION_MIPLIB) {
                                if (babModel_->numberStrong() == 5 && babModel_->numberBeforeTrust() == 5)
                                    babModel_->setNumberBeforeTrust(10);
                            }
                            int experimentFlag = parameters_[whichParam(CBC_PARAM_INT_EXPERIMENT, numberParameters_,
                                                             parameters_)].intValue();
                            int strategyFlag = parameters_[whichParam(CBC_PARAM_INT_STRATEGY, numberParameters_,
                                                           parameters_)].intValue();
                            int bothFlags = CoinMax(CoinMin(experimentFlag, 1), strategyFlag);
                            // add cut generators if wanted
                            int switches[30]={};
                            int accuracyFlag[30]={};
			    char doAtEnd[30]={};
                            int numberGenerators = 0;
                            int translate[] = { -100, -1, -99, -98, 1, -1098, -999, 1, 1, 1, -1};
			    int maximumSlowPasses = 
			      parameters_[whichParam(CBC_PARAM_INT_MAX_SLOW_CUTS, 
						     numberParameters_, parameters_)].intValue();
                            if (probingAction) {
                                int numberColumns = babModel_->solver()->getNumCols();
                                if (probingAction > 7) {
                                    probingGen.setMaxElements(numberColumns);
                                    probingGen.setMaxElementsRoot(numberColumns);
                                }
                                probingGen.setMaxProbeRoot(CoinMin(2000, numberColumns));
                                probingGen.setMaxProbeRoot(123);
                                probingGen.setMaxProbe(123);
                                probingGen.setMaxLookRoot(20);
                                if (probingAction == 7 || probingAction == 9)
                                    probingGen.setRowCuts(-3); // strengthening etc just at root
                                if (probingAction == 8 || probingAction == 9) {
                                    // Number of unsatisfied variables to look at
                                    probingGen.setMaxProbeRoot(numberColumns);
                                    probingGen.setMaxProbe(numberColumns);
                                    // How far to follow the consequences
                                    probingGen.setMaxLook(50);
                                    probingGen.setMaxLookRoot(50);
                                }
                                if (probingAction == 10) {
                                    probingGen.setMaxPassRoot(2);
                                    probingGen.setMaxProbeRoot(numberColumns);
                                    probingGen.setMaxLookRoot(numberColumns);
                                }
                                // If 5 then force on
                                int iAction = translate[probingAction];
                                if (probingAction == 5)
                                    iAction = 1;
                                babModel_->addCutGenerator(&probingGen, iAction, "Probing");
                                accuracyFlag[numberGenerators] = 5;
                                switches[numberGenerators++] = 0;
                            }
                            if (gomoryAction && (complicatedInteger != 1 ||
                                                 (gomoryAction == 1 || gomoryAction >= 4))) {
                                // try larger limit
                                int numberColumns = babModel_->getNumCols();
                                if (gomoryAction == 7) {
                                    gomoryAction = 4;
                                    gomoryGen.setLimitAtRoot(numberColumns);
                                    gomoryGen.setLimit(numberColumns);
                                } else if (gomoryAction == 8) {
                                    gomoryAction = 3;
                                    gomoryGen.setLimitAtRoot(numberColumns);
                                    gomoryGen.setLimit(200);
                                } else if (numberColumns > 5000) {
                                    //#define MORE_CUTS2
#ifdef MORE_CUTS2
                                    // try larger limit
                                    gomoryGen.setLimitAtRoot(numberColumns);
                                    gomoryGen.setLimit(200);
#else
                                    gomoryGen.setLimitAtRoot(2000);
                                    //gomoryGen.setLimit(200);
#endif
                                } else {
#ifdef MORE_CUTS2
                                    // try larger limit
                                    gomoryGen.setLimitAtRoot(numberColumns);
                                    gomoryGen.setLimit(200);
#endif
                                }
                                int cutLength =
                                    parameters_[whichParam(CBC_PARAM_INT_CUTLENGTH, numberParameters_, parameters_)].intValue();
                                if (cutLength != -1) {
                                    gomoryGen.setLimitAtRoot(cutLength);
                                    if (cutLength < 10000000) {
                                        gomoryGen.setLimit(cutLength);
                                    } else {
                                        gomoryGen.setLimit(cutLength % 10000000);
                                    }
                                }
                                int laGomory = parameters_[whichParam(CBC_PARAM_STR_LAGOMORYCUTS, numberParameters_, parameters_)].currentOptionAsInteger();
				int gType = translate[gomoryAction];
				if (!laGomory) {
				  // Normal
				  babModel_->addCutGenerator(&gomoryGen, translate[gomoryAction], "Gomory");
				  accuracyFlag[numberGenerators] = 3;
				  switches[numberGenerators++] = 0;
				} else {
				  laGomory--;
				  int type = (laGomory % 3)+1;
				  int when = laGomory/3;
				  char atEnd = (when<2) ? 1 : 0;
				  int gomoryTypeMajor = 10;
				  if (when<3) {
				    // normal as well
				    babModel_->addCutGenerator(&gomoryGen, gType, "Gomory");
				    accuracyFlag[numberGenerators] = 3;
				    switches[numberGenerators++] = 0;
				    if (when==2)
				      gomoryTypeMajor=20;
				  } else {
				    when--; // so on
				    gomoryTypeMajor=20;
				  }
				  if (!when)
				    gType=-99; // root
				  gomoryGen.passInOriginalSolver(babModel_->solver());
				  if ((type&1) !=0) {
				    // clean
				    gomoryGen.setGomoryType(gomoryTypeMajor+1);
				    babModel_->addCutGenerator(&gomoryGen, gType, "GomoryL1");
				    accuracyFlag[numberGenerators] = 3;
				    doAtEnd[numberGenerators]=atEnd;
				    if (atEnd) {
				      babModel_->cutGenerator(numberGenerators)->setMaximumTries(99999999);
				      babModel_->cutGenerator(numberGenerators)->setHowOften(1);
				    }
				    switches[numberGenerators++] = 0;
				  }
				  if ((type&2) !=0) {
				    // simple
				    gomoryGen.setGomoryType(gomoryTypeMajor+2);
				    babModel_->addCutGenerator(&gomoryGen, gType, "GomoryL2");
				    accuracyFlag[numberGenerators] = 3;
				    doAtEnd[numberGenerators]=atEnd;
				    if (atEnd) {
				      babModel_->cutGenerator(numberGenerators)->setMaximumTries(99999999);
				      babModel_->cutGenerator(numberGenerators)->setHowOften(1);
				    }
				    switches[numberGenerators++] = 0;
				  }
				}
                            }
#ifdef CLIQUE_ANALYSIS
                            if (miplib && !storedAmpl.sizeRowCuts()) {
                                printf("looking at probing\n");
                                babModel_->addCutGenerator(&storedAmpl, 1, "Stored");
                            }
#endif
                            if (knapsackAction) {
                                babModel_->addCutGenerator(&knapsackGen, translate[knapsackAction], "Knapsack");
                                accuracyFlag[numberGenerators] = 1;
                                switches[numberGenerators++] = -2;
                            }
                            if (redsplitAction && !complicatedInteger) {
                                babModel_->addCutGenerator(&redsplitGen, translate[redsplitAction], "Reduce-and-split");
                                accuracyFlag[numberGenerators] = 5;
				// slow ? - just do a few times
				if (redsplitAction!=1) {
				  babModel_->cutGenerator(numberGenerators)->setMaximumTries(maximumSlowPasses);
				  babModel_->cutGenerator(numberGenerators)->setHowOften(10);
				}
				switches[numberGenerators++] = 1;
                            }
                            if (redsplit2Action && !complicatedInteger) {
				int maxLength=256;
				if (redsplit2Action>2) {
				  redsplit2Action-=2;
				  maxLength=COIN_INT_MAX;
				}
				CglRedSplit2Param & parameters = redsplit2Gen.getParam();
				parameters.setMaxNonzeroesTab(maxLength);
                                babModel_->addCutGenerator(&redsplit2Gen, translate[redsplit2Action], "Reduce-and-split(2)");
                                accuracyFlag[numberGenerators] = 5;
				// slow ? - just do a few times
				if (redsplit2Action!=1) {
				  babModel_->cutGenerator(numberGenerators)->setHowOften(maximumSlowPasses);
				  babModel_->cutGenerator(numberGenerators)->setMaximumTries(maximumSlowPasses);
				  babModel_->cutGenerator(numberGenerators)->setHowOften(5);
				}
				
				switches[numberGenerators++] = 1;
                            }
                            if (GMIAction && !complicatedInteger) {
			        if (GMIAction>5) {
				  // long
				  GMIAction-=5;
				  CglGMIParam & parameters = GMIGen.getParam();
				  parameters.setMaxSupportRel(1.0);
				}
                                babModel_->addCutGenerator(&GMIGen, translate[GMIAction], "Gomory(2)");
			        if (GMIAction==5) {
				  // just at end and root
				  GMIAction=2;
				  doAtEnd[numberGenerators]=1;
				  babModel_->cutGenerator(numberGenerators)->setMaximumTries(99999999);
				  babModel_->cutGenerator(numberGenerators)->setHowOften(1);
				}
                                accuracyFlag[numberGenerators] = 5;
				switches[numberGenerators++] = 0;
                            }
                            if (cliqueAction) {
                                babModel_->addCutGenerator(&cliqueGen, translate[cliqueAction], "Clique");
                                accuracyFlag[numberGenerators] = 0;
                                switches[numberGenerators++] = 0;
                            }
                            if (mixedAction) {
                                babModel_->addCutGenerator(&mixedGen, translate[mixedAction], "MixedIntegerRounding2");
                                accuracyFlag[numberGenerators] = 2;
                                switches[numberGenerators++] = 0;
                            }
                            if (flowAction) {
                                babModel_->addCutGenerator(&flowGen, translate[flowAction], "FlowCover");
                                accuracyFlag[numberGenerators] = 2;
                                switches[numberGenerators++] = 0;
                            }
                            if (twomirAction && (complicatedInteger != 1 ||
                                                 (twomirAction == 1 || twomirAction >= 4))) {
                                // try larger limit
                                int numberColumns = babModel_->getNumCols();
                                if (twomirAction == 7) {
                                    twomirAction = 4;
                                    twomirGen.setMaxElements(numberColumns);
                                } else if (numberColumns > 5000 && twomirAction == 4) {
                                    twomirGen.setMaxElements(2000);
                                }
                                int laTwomir = parameters_[whichParam(CBC_PARAM_STR_LATWOMIRCUTS, numberParameters_, parameters_)].currentOptionAsInteger();
				int twomirType = translate[twomirAction];
				if (!laTwomir) {
				  // Normal
				  babModel_->addCutGenerator(&twomirGen, translate[twomirAction], "TwoMirCuts");
				  accuracyFlag[numberGenerators] = 4;
				  switches[numberGenerators++] = 1;
				} else {
				  laTwomir--;
				  int type = (laTwomir % 3)+1;
				  int when = laTwomir/3;
				  char atEnd = (when<2) ? 1 : 0;
				  int twomirTypeMajor = 10;
				  if (when<3) {
				    // normal as well
				    babModel_->addCutGenerator(&twomirGen, translate[twomirAction], "TwoMirCuts");
				    accuracyFlag[numberGenerators] = 4;
				    switches[numberGenerators++] = 1;
				    if (when==2)
				      twomirTypeMajor=10;
				  } else {
				    when--; // so on
				    twomirTypeMajor=20;
				  }
				  if (!when)
				    twomirType=-99; // root
				  twomirGen.passInOriginalSolver(babModel_->solver());
				  if ((type&1) !=0) {
				    // clean
				    twomirGen.setTwomirType(twomirTypeMajor+1);
				    babModel_->addCutGenerator(&twomirGen, twomirType, "TwoMirCutsL1");
				    accuracyFlag[numberGenerators] = 4;
				    doAtEnd[numberGenerators]=atEnd;
				    switches[numberGenerators++] = atEnd ? 0 : 1;
				  }
				  if ((type&2) !=0) {
				    // simple
				    twomirGen.setTwomirType(twomirTypeMajor+2);
				    babModel_->addCutGenerator(&twomirGen, twomirType, "TwoMirCutsL2");
				    accuracyFlag[numberGenerators] = 4;
				    doAtEnd[numberGenerators]=atEnd;
				    switches[numberGenerators++] = atEnd ? 0 : 1;
				  }
				}
                            }
#ifndef DEBUG_MALLOC
                            if (landpAction) {
                                babModel_->addCutGenerator(&landpGen, translate[landpAction], "LiftAndProject");
                                accuracyFlag[numberGenerators] = 5;
				// slow ? - just do a few times
				if (landpAction!=1) {
				  babModel_->cutGenerator(numberGenerators)->setMaximumTries(maximumSlowPasses);
				  babModel_->cutGenerator(numberGenerators)->setHowOften(10);
				}
                                switches[numberGenerators++] = 1;
                            }
#endif
                            if (residualCapacityAction) {
                                babModel_->addCutGenerator(&residualCapacityGen, translate[residualCapacityAction], "ResidualCapacity");
                                accuracyFlag[numberGenerators] = 5;
                                switches[numberGenerators++] = 1;
                            }
                            if (zerohalfAction) {
                                if (zerohalfAction > 4) {
                                    //zerohalfAction -=4;
                                    zerohalfGen.setFlags(1);
                                }
                                babModel_->addCutGenerator(&zerohalfGen, translate[zerohalfAction], "ZeroHalf");
                                accuracyFlag[numberGenerators] = 5;
                                babModel_->cutGenerator(numberGenerators)->
				  setNeedsRefresh(true);
                                switches[numberGenerators++] = 2;
                            }
                            if (dominatedCuts)
                                babModel_->setSpecialOptions(babModel_->specialOptions() | 64);
                            // Say we want timings
                            numberGenerators = babModel_->numberCutGenerators();
                            int iGenerator;
                            int cutDepth =
                                parameters_[whichParam(CBC_PARAM_INT_CUTDEPTH, numberParameters_, parameters_)].intValue();
                            for (iGenerator = 0; iGenerator < numberGenerators; iGenerator++) {
                                CbcCutGenerator * generator = babModel_->cutGenerator(iGenerator);
                                int howOften = generator->howOften();
                                if (howOften == -98 || howOften == -99 || generator->maximumTries()>0)
                                    generator->setSwitchOffIfLessThan(switches[iGenerator]);
                                // Use if any at root as more likely later and fairly cheap
                                //if (switches[iGenerator]==-2)
                                //generator->setWhetherToUse(true);
                                generator->setInaccuracy(accuracyFlag[iGenerator]);
                                if (doAtEnd[iGenerator]) {
                                    generator->setWhetherCallAtEnd(true);
                                    //generator->setMustCallAgain(true);
                                }
                                generator->setTiming(true);
                                if (cutDepth >= 0)
                                    generator->setWhatDepth(cutDepth) ;
                            }
                            // Could tune more
                            if (!miplib) {
                                double minimumDrop =
                                    fabs(babModel_->solver()->getObjValue()) * 1.0e-5 + 1.0e-5;
                                babModel_->setMinimumDrop(CoinMin(5.0e-2, minimumDrop));
                                if (cutPass == -1234567) {
                                    if (babModel_->getNumCols() < 500)
                                        babModel_->setMaximumCutPassesAtRoot(-100); // always do 100 if possible
                                    else if (babModel_->getNumCols() < 5000)
                                        babModel_->setMaximumCutPassesAtRoot(100); // use minimum drop
                                    else
                                        babModel_->setMaximumCutPassesAtRoot(20);
                                } else {
                                    babModel_->setMaximumCutPassesAtRoot(cutPass);
                                }
                                if (cutPassInTree == -1234567)
                                    babModel_->setMaximumCutPasses(4);
                                else
                                    babModel_->setMaximumCutPasses(cutPassInTree);
                            } else if (cutPass != -1234567) {
                                babModel_->setMaximumCutPassesAtRoot(cutPass);
                            }
                            // Do more strong branching if small
                            //if (babModel_->getNumCols()<5000)
                            //babModel_->setNumberStrong(20);
                            // Switch off strong branching if wanted
                            //if (babModel_->getNumCols()>10*babModel_->getNumRows())
                            //babModel_->setNumberStrong(0);
                            if (!noPrinting_) {
                                int iLevel = parameters_[log].intValue();
                                if (iLevel < 0) {
                                    if (iLevel > -10) {
                                        babModel_->setPrintingMode(1);
                                    } else {
                                        babModel_->setPrintingMode(2);
                                        iLevel += 10;
                                        parameters_[log].setIntValue(iLevel);
                                    }
                                    iLevel = -iLevel;
                                }
                                babModel_->messageHandler()->setLogLevel(iLevel);
                                if (babModel_->getNumCols() > 2000 || babModel_->getNumRows() > 1500 ||
                                        babModel_->messageHandler()->logLevel() > 1)
                                    babModel_->setPrintFrequency(100);
                            }

                            babModel_->solver()->setIntParam(OsiMaxNumIterationHotStart,
                                                             parameters_[whichParam(CBC_PARAM_INT_MAXHOTITS, numberParameters_, parameters_)].intValue());
#ifndef CBC_OTHER_SOLVER
                            OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (babModel_->solver());
                            // go faster stripes
                            if ((osiclp->getNumRows() < 300 && osiclp->getNumCols() < 500)) {
                                osiclp->setupForRepeatedUse(2, parameters_[slog].intValue());
                                if (bothFlags >= 1) {
                                    ClpSimplex * lp = osiclp->getModelPtr();
                                    int specialOptions = lp->specialOptions();
                                    lp->setSpecialOptions(specialOptions | (2048 + 4096));
                                }
                            } else {
                                osiclp->setupForRepeatedUse(0, parameters_[slog].intValue());
                            }
                            if (bothFlags >= 2) {
                                ClpSimplex * lp = osiclp->getModelPtr();
                                int specialOptions = lp->specialOptions();
                                lp->setSpecialOptions(specialOptions | (2048 + 4096));
                            }
                            double increment = babModel_->getCutoffIncrement();;
                            int * changed = NULL;
                            if (!miplib && increment == normalIncrement)
                                changed = analyze( osiclp, numberChanged, increment, false, generalMessageHandler, noPrinting);
#elif CBC_OTHER_SOLVER==1
                            double increment = babModel_->getCutoffIncrement();;
#endif
                            if (debugValues) {
                                int numberColumns = babModel_->solver()->getNumCols();
                                if (numberDebugValues == numberColumns) {
                                    // for debug
                                    babModel_->solver()->activateRowCutDebugger(debugValues) ;
                                } else {
                                    int numberOriginalColumns =
                                        process.originalModel()->getNumCols();
                                    if (numberDebugValues <= numberOriginalColumns) {
                                        const int * originalColumns = process.originalColumns();
                                        double * newValues = new double [numberColumns];
                                        // in case preprocess added columns!
                                        // need to find values
                                        OsiSolverInterface * siCopy =
                                            babModel_->solver()->clone();
                                        for (int i = 0; i < numberColumns; i++) {
                                            int jColumn = originalColumns[i];
                                            if (jColumn < numberDebugValues &&
                                                    siCopy->isInteger(i)) {
                                                // integer variable
                                                double soln = floor(debugValues[jColumn] + 0.5);
                                                // Set bounds to fix variable to its solution
                                                siCopy->setColUpper(i, soln);
                                                siCopy->setColLower(i, soln);
                                            }
                                        }
                                        // All integers have been fixed at optimal value.
                                        // Now solve to get continuous values
                                        siCopy->setHintParam(OsiDoScale, false);
                                        siCopy->initialSolve();
                                        if (siCopy->isProvenOptimal()) {
                                            memcpy(newValues, siCopy->getColSolution(),
                                                   numberColumns*sizeof(double));
                                        } else {
                                            printf("BAD debug file\n");
                                            siCopy->writeMps("Bad");
                                            exit(22);
                                        }
                                        delete siCopy;
                                        // for debug
                                        babModel_->solver()->activateRowCutDebugger(newValues) ;
                                        delete [] newValues;
                                    } else {
                                        printf("debug file has incorrect number of columns\n");
                                    }
                                }
                            }
                            babModel_->setCutoffIncrement(CoinMax(babModel_->getCutoffIncrement(), increment));
                            // Turn this off if you get problems
                            // Used to be automatically set
                            int mipOptions = parameters_[whichParam(CBC_PARAM_INT_MIPOPTIONS, numberParameters_, parameters_)].intValue() % 10000;
                            if (mipOptions != (1057) && mipOptions != 1025 ) {
                                sprintf(generalPrint, "mip options %d", mipOptions);
                                generalMessageHandler->message(CLP_GENERAL, generalMessages)
                                << generalPrint
                                << CoinMessageEol;
                            }
#ifndef CBC_OTHER_SOLVER
                            osiclp->setSpecialOptions(mipOptions);
#elif CBC_OTHER_SOLVER==1
#endif
                            // probably faster to use a basis to get integer solutions
                            babModel_->setSpecialOptions(babModel_->specialOptions() | 2);
                            currentBranchModel = babModel_;
                            //OsiSolverInterface * strengthenedModel=NULL;
                            if (type == CBC_PARAM_ACTION_BAB ||
                                    type == CBC_PARAM_ACTION_MIPLIB) {
                                if (strategyFlag == 1) {
                                    // try reduced model
                                    babModel_->setSpecialOptions(babModel_->specialOptions() | 512);
                                }
                                if (experimentFlag >= 5 || strategyFlag == 2) {
                                    // try reduced model at root
                                    babModel_->setSpecialOptions(babModel_->specialOptions() | 32768);
                                }
                                {
                                    int depthMiniBab = parameters_[whichParam(CBC_PARAM_INT_DEPTHMINIBAB, numberParameters_, parameters_)].intValue();
                                    if (depthMiniBab != -1)
                                        babModel_->setFastNodeDepth(depthMiniBab);
                                }
                                int extra4 = parameters_[whichParam(CBC_PARAM_INT_EXTRA4, numberParameters_, parameters_)].intValue();
                                if (extra4 >= 0) {
                                    int strategy = extra4 % 10;
                                    extra4 /= 10;
                                    int method = extra4 % 100;
                                    extra4 /= 100;
                                    extra4 = strategy + method * 8 + extra4 * 1024;
                                    babModel_->setMoreSpecialOptions(extra4);
                                }
                                int moreMipOptions = parameters_[whichParam(CBC_PARAM_INT_MOREMIPOPTIONS, numberParameters_, parameters_)].intValue();
                                if (moreMipOptions >= 0) {
                                    sprintf(generalPrint, "more mip options %d", moreMipOptions);
                                    generalMessageHandler->message(CLP_GENERAL, generalMessages)
                                    << generalPrint
                                    << CoinMessageEol;
#if 1
				    // some options may have been set already
				    // e.g. use elapsed time
                                    babModel_->setMoreSpecialOptions(moreMipOptions|babModel_->moreSpecialOptions());
#else
                                    OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (babModel_->solver());
                                    if (moreMipOptions == 10000) {
                                        // test memory saving
                                        moreMipOptions -= 10000;
                                        ClpSimplex * lpSolver = osiclp->getModelPtr();
                                        lpSolver->setPersistenceFlag(1);
                                        // switch off row copy if few rows
                                        if (lpSolver->numberRows() < 150)
                                            lpSolver->setSpecialOptions(lpSolver->specialOptions() | 256);
                                    }
                                    if (moreMipOptions < 10000 && moreMipOptions) {
                                        if (((moreMipOptions + 1) % 1000000) != 0)
                                            babModel_->setSearchStrategy(moreMipOptions % 1000000);
                                    } else if (moreMipOptions < 100000) {
                                        // try reduced model
                                        babModel_->setSpecialOptions(babModel_->specialOptions() | 512);
                                    }
                                    // go faster stripes
                                    if ( moreMipOptions >= 999999) {
                                        if (osiclp) {
                                            int save = osiclp->specialOptions();
                                            osiclp->setupForRepeatedUse(2, 0);
                                            osiclp->setSpecialOptions(save | osiclp->specialOptions());
                                        }
                                    }
#endif
                                }
                            }
                            {
                                int extra1 = parameters_[whichParam(CBC_PARAM_INT_EXTRA1, numberParameters_, parameters_)].intValue();
                                if (extra1 != -1) {
                                    if (extra1 < 0) {
                                        if (extra1 == -7777)
                                            extra1 = -1;
                                        else if (extra1 == -8888)
                                            extra1 = 1;
                                        babModel_->setWhenCuts(-extra1);
                                    } else if (extra1 < 19000) {
                                        babModel_->setSearchStrategy(extra1);
                                        printf("XXXXX searchStrategy %d\n", extra1);
                                    } else {
                                        int n = extra1 - 20000;
                                        if (!n)
                                            n--;
                                        babModel_->setNumberAnalyzeIterations(n);
                                        printf("XXXXX analyze %d\n", extra1);
                                    }
                                } else if (bothFlags >= 1) {
                                    babModel_->setWhenCuts(999998);
                                }
                            }
                            if (type == CBC_PARAM_ACTION_BAB) {
#ifdef COIN_HAS_ASL
                                if (statusUserFunction_[0]) {
                                    priorities = info.priorities;
                                    branchDirection = info.branchDirection;
                                    pseudoDown = info.pseudoDown;
                                    pseudoUp = info.pseudoUp;
                                    solutionIn = info.primalSolution;
                                    prioritiesIn = info.priorities;
                                    if (info.numberSos && doSOS) {
                                        // SOS
                                        numberSOS = info.numberSos;
                                        sosStart = info.sosStart;
                                        sosIndices = info.sosIndices;
                                        sosType = info.sosType;
                                        sosReference = info.sosReference;
                                        sosPriority = info.sosPriority;
                                    }
                                }
#endif
                                const int * originalColumns = preProcess ? process.originalColumns() : NULL;

                                if (model.getMIPStart().size())
				                    mipStart = model.getMIPStart();

                                if (mipStart.size() && !mipStartBefore.size() && babModel_->getNumCols())
                                {
                                    std::vector< std::string > colNames;
                                    if (preProcess)
                                    {
                                        /* translating mipstart solution */
                                        std::map< std::string, double > mipStartV;
                                        for ( size_t i=0 ; (i<mipStart.size()) ; ++i )
                                            mipStartV[mipStart[i].first] = mipStart[i].second;

                                        std::vector< std::pair< std::string, double > > mipStart2;
                                        for ( int i=0 ; (i<babModel_->solver()->getNumCols()) ; ++i ) {
                                            int iColumn = babModel_->originalColumns()[i];
                                            if (iColumn>=0) {
                                                std::string cname = model_.solver()->getColName( iColumn );
                                                colNames.push_back( cname );
                                                babModel_->solver()->setColName( i, cname );
                                                std::map< std::string, double >::const_iterator msIt = mipStartV.find( cname );
                                                if ( msIt != mipStartV.end() )
                                                    mipStart2.push_back( std::pair< std::string, double>( cname, msIt->second ) );
                                            } else {
                                                // created variable
                                                char newName[15];
                                                sprintf(newName,"C%7.7d",i);
                                                colNames.push_back( newName );
                                            }
                                        }
                                        mipStart = mipStart2;
                                    } else {
                                        for ( int i=0 ; (i<babModel_->solver()->getNumCols()) ; ++i )
                                            colNames.push_back( model_.solver()->getColName(i) );
                                    }
                                    //printf("--- %s %d\n", babModel_->solver()->getColName(0).c_str(), babModel_->solver()->getColNames().size() );
                                    //printf("-- SIZES of models %d %d %d\n", model_.getNumCols(),  babModel_->solver()->getNumCols(), babModel_->solver()->getColNames().size() );
                                    std::vector< double > x( babModel_->getNumCols(), 0.0 );
                                    double obj;
                                    int status = computeCompleteSolution( babModel_, colNames, mipStart, &x[0], obj );
                                    if (!status) {
                                        babModel_->setBestSolution( &x[0], static_cast<int>(x.size()), obj, false );
                                        babModel_->setSolutionCount(1);
                                    }
                               }


                                if (solutionIn && useSolution >= 0) {
                                    if (!prioritiesIn) {
                                        int n;
                                        if (preProcess) {
                                            int numberColumns = babModel_->getNumCols();
                                            // extend arrays in case SOS
                                            n = originalColumns[numberColumns-1] + 1;
                                        } else {
                                            n = babModel_->getNumCols();
                                        }
                                        prioritiesIn = reinterpret_cast<int *> (malloc(n * sizeof(int)));
                                        for (int i = 0; i < n; i++)
                                            prioritiesIn[i] = 100;
                                    }
                                    if (preProcess) {
                                        int numberColumns = babModel_->getNumCols();
                                        // extend arrays in case SOS
                                        int n = originalColumns[numberColumns-1] + 1;
                                        int nSmaller = CoinMin(n, numberOriginalColumns);
                                        double * solutionIn2 = new double [n];
                                        int * prioritiesIn2 = new int[n];
                                        int i;
                                        for (i = 0; i < nSmaller; i++) {
                                            solutionIn2[i] = solutionIn[i];
                                            prioritiesIn2[i] = prioritiesIn[i];
                                        }
                                        for (; i < n; i++) {
                                            solutionIn2[i] = 0.0;
                                            prioritiesIn2[i] = 1000000;
                                        }
#ifndef NDEBUG
                                        int iLast = -1;
#endif
                                        for (i = 0; i < numberColumns; i++) {
                                            int iColumn = originalColumns[i];
#ifndef NDEBUG
                                            assert (iColumn > iLast);
                                            iLast = iColumn;
#endif
                                            solutionIn2[i] = solutionIn2[iColumn];
                                            if (prioritiesIn)
                                                prioritiesIn2[i] = prioritiesIn2[iColumn];
                                        }
                                        if (useSolution)
                                            babModel_->setHotstartSolution(solutionIn2, prioritiesIn2);
                                        else
                                            babModel_->setBestSolution(solutionIn2, numberColumns,
                                                                       COIN_DBL_MAX, true);
                                        delete [] solutionIn2;
                                        delete [] prioritiesIn2;
                                    } else {
                                        if (useSolution)
                                            babModel_->setHotstartSolution(solutionIn, prioritiesIn);
                                        else
                                            babModel_->setBestSolution(solutionIn, babModel_->getNumCols(),
                                                                       COIN_DBL_MAX, true);
                                    }
                                }
                                OsiSolverInterface * testOsiSolver = (testOsiOptions >= 0) ? babModel_->solver() : NULL;
                                if (!testOsiSolver) {
                                    // *************************************************************
                                    // CbcObjects
                                    if (preProcess && (process.numberSOS() || babModel_->numberObjects())) {
                                        int numberSOS = process.numberSOS();
                                        int numberIntegers = babModel_->numberIntegers();
                                        /* model may not have created objects
                                           If none then create
                                        */
                                        if (!numberIntegers || !babModel_->numberObjects()) {
                                            int type = (pseudoUp) ? 1 : 0;
                                            babModel_->findIntegers(true, type);
                                            numberIntegers = babModel_->numberIntegers();
                                            integersOK = true;
                                        }
                                        OsiObject ** oldObjects = babModel_->objects();
                                        // Do sets and priorities
                                        OsiObject ** objects = new OsiObject * [numberSOS];
                                        // set old objects to have low priority
                                        int numberOldObjects = babModel_->numberObjects();
                                        int numberColumns = babModel_->getNumCols();
                                        // backward pointer to new variables
                                        // extend arrays in case SOS
                                        assert (originalColumns);
					int n = CoinMin(truncateColumns,numberColumns);
					// allow for empty problem
                                        n = (n) ? originalColumns[n-1] + 1 : 0;
                                        n = CoinMax(n, CoinMax(numberColumns, numberOriginalColumns));
                                        int * newColumn = new int[n];
                                        int i;
                                        for (i = 0; i < numberOriginalColumns; i++)
                                            newColumn[i] = -1;
                                        for (i = 0; i < CoinMin(truncateColumns,numberColumns); i++)
                                            newColumn[originalColumns[i]] = i;
                                        if (!integersOK) {
                                            // Change column numbers etc
                                            int n = 0;
                                            for (int iObj = 0; iObj < numberOldObjects; iObj++) {
                                                int iColumn = oldObjects[iObj]->columnNumber();
                                                if (iColumn < 0 || iColumn >= numberOriginalColumns) {
                                                    oldObjects[n++] = oldObjects[iObj];
                                                } else {
                                                    iColumn = newColumn[iColumn];
                                                    if (iColumn >= 0) {
                                                        CbcSimpleInteger * obj =
                                                            dynamic_cast <CbcSimpleInteger *>(oldObjects[iObj]) ;
                                                        if (obj) {
                                                            obj->setColumnNumber(iColumn);
                                                        } else {
                                                            // only other case allowed is lotsizing
                                                            CbcLotsize * obj2 =
                                                                dynamic_cast <CbcLotsize *>(oldObjects[iObj]) ;
                                                            assert (obj2);
                                                            obj2->setModelSequence(iColumn);
                                                        }
                                                        oldObjects[n++] = oldObjects[iObj];
                                                    } else {
                                                        delete oldObjects[iObj];
                                                    }
                                                }
                                            }
                                            babModel_->setNumberObjects(n);
                                            numberOldObjects = n;
                                            babModel_->zapIntegerInformation();
                                        }
                                        int nMissing = 0;
                                        for (int iObj = 0; iObj < numberOldObjects; iObj++) {
                                            if (process.numberSOS())
                                                oldObjects[iObj]->setPriority(numberColumns + 1);
                                            int iColumn = oldObjects[iObj]->columnNumber();
                                            if (iColumn < 0 || iColumn >= numberOriginalColumns) {
					      if (redoSOS) { // now done earlier??
                                                CbcSOS * obj =
                                                    dynamic_cast <CbcSOS *>(oldObjects[iObj]) ;
                                                if (obj) {
                                                    int n = obj->numberMembers();
                                                    int * which = obj->mutableMembers();
                                                    double * weights = obj->mutableWeights();
                                                    int nn = 0;
                                                    for (i = 0; i < n; i++) {
                                                        int iColumn = which[i];
                                                        int jColumn = newColumn[iColumn];
                                                        if (jColumn >= 0) {
                                                            which[nn] = jColumn;
                                                            weights[nn++] = weights[i];
                                                        } else {
                                                            nMissing++;
                                                        }
                                                    }
                                                    obj->setNumberMembers(nn);
                                                }
					      }
					      continue;
                                            }
                                            if (originalColumns)
                                                iColumn = originalColumns[iColumn];
                                            if (branchDirection) {
                                                CbcSimpleInteger * obj =
                                                    dynamic_cast <CbcSimpleInteger *>(oldObjects[iObj]) ;
                                                if (obj) {
                                                    obj->setPreferredWay(branchDirection[iColumn]);
                                                } else {
                                                    CbcObject * obj =
                                                        dynamic_cast <CbcObject *>(oldObjects[iObj]) ;
                                                    assert (obj);
                                                    obj->setPreferredWay(branchDirection[iColumn]);
                                                }
                                            }
                                            if (pseudoUp) {
                                                CbcSimpleIntegerPseudoCost * obj1a =
                                                    dynamic_cast <CbcSimpleIntegerPseudoCost *>(oldObjects[iObj]) ;
                                                assert (obj1a);
                                                if (pseudoDown[iColumn] > 0.0)
                                                    obj1a->setDownPseudoCost(pseudoDown[iColumn]);
                                                if (pseudoUp[iColumn] > 0.0)
                                                    obj1a->setUpPseudoCost(pseudoUp[iColumn]);
                                            }
                                        }
                                        if (nMissing) {
                                            sprintf(generalPrint, "%d SOS variables vanished due to pre processing? - check validity?", nMissing);
                                            generalMessageHandler->message(CLP_GENERAL, generalMessages)
                                            << generalPrint
                                            << CoinMessageEol;
                                        }
                                        delete [] newColumn;
                                        const int * starts = process.startSOS();
                                        const int * which = process.whichSOS();
                                        const int * type = process.typeSOS();
                                        const double * weight = process.weightSOS();
                                        int iSOS;
                                        for (iSOS = 0; iSOS < numberSOS; iSOS++) {
                                            int iStart = starts[iSOS];
                                            int n = starts[iSOS+1] - iStart;
					    //#define MAKE_SOS_CLIQUES
#ifndef MAKE_SOS_CLIQUES
                                            objects[iSOS] = new CbcSOS(babModel_, n, which + iStart, weight + iStart,
                                                                       iSOS, type[iSOS]);
#else
                                            objects[iSOS] = 
					      new CbcClique(babModel_, 1, n, which + iStart, 
							    NULL,-iSOS-1);
#endif
                                            // branch on long sets first
                                            objects[iSOS]->setPriority(numberColumns - n);
                                        }
                                        if (numberSOS)
                                            babModel_->addObjects(numberSOS, objects);
                                        for (iSOS = 0; iSOS < numberSOS; iSOS++)
                                            delete objects[iSOS];
                                        delete [] objects;
                                    } else if (priorities || branchDirection || pseudoDown || pseudoUp || numberSOS) {
                                        // do anyway for priorities etc
                                        int numberIntegers = babModel_->numberIntegers();
                                        /* model may not have created objects
                                           If none then create
                                        */
                                        if (!numberIntegers || !babModel_->numberObjects()) {
                                            int type = (pseudoUp) ? 1 : 0;
                                            babModel_->findIntegers(true, type);
                                        }
                                        if (numberSOS) {
                                            // Do sets and priorities
                                            OsiObject ** objects = new OsiObject * [numberSOS];
                                            int iSOS;
                                            if (originalColumns) {
                                                // redo sequence numbers
                                                int numberColumns = babModel_->getNumCols();
                                                int nOld = originalColumns[numberColumns-1] + 1;
                                                int * back = new int[nOld];
                                                int i;
                                                for (i = 0; i < nOld; i++)
                                                    back[i] = -1;
                                                for (i = 0; i < numberColumns; i++)
                                                    back[originalColumns[i]] = i;
                                                // Really need better checks
                                                int nMissing = 0;
                                                int n = sosStart[numberSOS];
                                                for (i = 0; i < n; i++) {
                                                    int iColumn = sosIndices[i];
                                                    int jColumn = back[iColumn];
                                                    if (jColumn >= 0)
                                                        sosIndices[i] = jColumn;
                                                    else
                                                        nMissing++;
                                                }
                                                delete [] back;
                                                if (nMissing) {
                                                    sprintf(generalPrint, "%d SOS variables vanished due to pre processing? - check validity?", nMissing);
                                                    generalMessageHandler->message(CLP_GENERAL, generalMessages)
                                                    << generalPrint
                                                    << CoinMessageEol;
                                                }
                                            }
                                            for (iSOS = 0; iSOS < numberSOS; iSOS++) {
                                                int iStart = sosStart[iSOS];
                                                int n = sosStart[iSOS+1] - iStart;
                                                objects[iSOS] = new CbcSOS(babModel_, n, sosIndices + iStart, sosReference + iStart,
                                                                           iSOS, sosType[iSOS]);
                                                if (sosPriority)
                                                    objects[iSOS]->setPriority(sosPriority[iSOS]);
                                                else if (!prioritiesIn)
                                                    objects[iSOS]->setPriority(10);  // rather than 1000
                                            }
                                            // delete any existing SOS objects
                                            int numberObjects = babModel_->numberObjects();
                                            OsiObject ** oldObjects = babModel_->objects();
                                            int nNew = 0;
                                            for (int i = 0; i < numberObjects; i++) {
                                                OsiObject * objThis = oldObjects[i];
                                                CbcSOS * obj1 =
                                                    dynamic_cast <CbcSOS *>(objThis) ;
                                                OsiSOS * obj2 =
                                                    dynamic_cast <OsiSOS *>(objThis) ;
                                                if (!obj1 && !obj2) {
                                                    oldObjects[nNew++] = objThis;
                                                } else {
                                                    delete objThis;
                                                }
                                            }
                                            babModel_->setNumberObjects(nNew);
                                            babModel_->addObjects(numberSOS, objects);
                                            for (iSOS = 0; iSOS < numberSOS; iSOS++)
                                                delete objects[iSOS];
                                            delete [] objects;
                                        }
                                    }
                                    OsiObject ** objects = babModel_->objects();
                                    int numberObjects = babModel_->numberObjects();
                                    for (int iObj = 0; iObj < numberObjects; iObj++) {
                                        // skip sos
                                        CbcSOS * objSOS =
                                            dynamic_cast <CbcSOS *>(objects[iObj]) ;
                                        if (objSOS)
                                            continue;
#ifdef MAKE_SOS_CLIQUES
                                        // skip cliques
                                        CbcClique * objClique =
                                            dynamic_cast <CbcClique *>(objects[iObj]) ;
                                        if (objClique)
                                            continue;
#endif
                                        int iColumn = objects[iObj]->columnNumber();
                                        assert (iColumn >= 0);
                                        if (originalColumns)
                                            iColumn = originalColumns[iColumn];
                                        if (branchDirection) {
                                            CbcSimpleInteger * obj =
                                                dynamic_cast <CbcSimpleInteger *>(objects[iObj]) ;
                                            if (obj) {
                                                obj->setPreferredWay(branchDirection[iColumn]);
                                            } else {
                                                CbcObject * obj =
                                                    dynamic_cast <CbcObject *>(objects[iObj]) ;
                                                assert (obj);
                                                obj->setPreferredWay(branchDirection[iColumn]);
                                            }
                                        }
                                        if (priorities) {
                                            int iPriority = priorities[iColumn];
                                            if (iPriority > 0)
                                                objects[iObj]->setPriority(iPriority);
                                        }
                                        if (pseudoUp && pseudoUp[iColumn]) {
                                            CbcSimpleIntegerPseudoCost * obj1a =
                                                dynamic_cast <CbcSimpleIntegerPseudoCost *>(objects[iObj]) ;
                                            assert (obj1a);
                                            if (pseudoDown[iColumn] > 0.0)
                                                obj1a->setDownPseudoCost(pseudoDown[iColumn]);
                                            if (pseudoUp[iColumn] > 0.0)
                                                obj1a->setUpPseudoCost(pseudoUp[iColumn]);
                                        }
                                    }
                                    // *************************************************************
                                } else {
                                    // *************************************************************
                                    // OsiObjects
                                    // Find if none
                                    int numberIntegers = testOsiSolver->getNumIntegers();
                                    /* model may not have created objects
                                       If none then create
                                    */
                                    if (!numberIntegers || !testOsiSolver->numberObjects()) {
                                        //int type = (pseudoUp) ? 1 : 0;
                                        testOsiSolver->findIntegers(false);
                                        numberIntegers = testOsiSolver->getNumIntegers();
                                    }
                                    if (preProcess && process.numberSOS()) {
                                        int numberSOS = process.numberSOS();
                                        OsiObject ** oldObjects = testOsiSolver->objects();
                                        // Do sets and priorities
                                        OsiObject ** objects = new OsiObject * [numberSOS];
                                        // set old objects to have low priority
                                        int numberOldObjects = testOsiSolver->numberObjects();
                                        int numberColumns = testOsiSolver->getNumCols();
                                        for (int iObj = 0; iObj < numberOldObjects; iObj++) {
                                            oldObjects[iObj]->setPriority(numberColumns + 1);
                                            int iColumn = oldObjects[iObj]->columnNumber();
                                            assert (iColumn >= 0);
                                            if (iColumn >= numberOriginalColumns)
                                                continue;
                                            if (originalColumns)
                                                iColumn = originalColumns[iColumn];
                                            if (branchDirection) {
                                                OsiSimpleInteger * obj =
                                                    dynamic_cast <OsiSimpleInteger *>(oldObjects[iObj]) ;
                                                if (obj) {
                                                    obj->setPreferredWay(branchDirection[iColumn]);
                                                } else {
                                                    OsiObject2 * obj =
                                                        dynamic_cast <OsiObject2 *>(oldObjects[iObj]) ;
                                                    if (obj)
                                                        obj->setPreferredWay(branchDirection[iColumn]);
                                                }
                                            }
                                            if (pseudoUp) {
                                                abort();
                                            }
                                        }
                                        const int * starts = process.startSOS();
                                        const int * which = process.whichSOS();
                                        const int * type = process.typeSOS();
                                        const double * weight = process.weightSOS();
                                        int iSOS;
                                        for (iSOS = 0; iSOS < numberSOS; iSOS++) {
                                            int iStart = starts[iSOS];
                                            int n = starts[iSOS+1] - iStart;
                                            objects[iSOS] = new OsiSOS(testOsiSolver, n, which + iStart, weight + iStart,
                                                                       type[iSOS]);
                                            // branch on long sets first
                                            objects[iSOS]->setPriority(numberColumns - n);
                                        }
                                        testOsiSolver->addObjects(numberSOS, objects);
                                        for (iSOS = 0; iSOS < numberSOS; iSOS++)
                                            delete objects[iSOS];
                                        delete [] objects;
                                    } else if (priorities || branchDirection || pseudoDown || pseudoUp || numberSOS) {
                                        if (numberSOS) {
                                            // Do sets and priorities
                                            OsiObject ** objects = new OsiObject * [numberSOS];
                                            int iSOS;
                                            if (originalColumns) {
                                                // redo sequence numbers
                                                int numberColumns = testOsiSolver->getNumCols();
                                                int nOld = originalColumns[numberColumns-1] + 1;
                                                int * back = new int[nOld];
                                                int i;
                                                for (i = 0; i < nOld; i++)
                                                    back[i] = -1;
                                                for (i = 0; i < numberColumns; i++)
                                                    back[originalColumns[i]] = i;
                                                // Really need better checks
                                                int nMissing = 0;
                                                int n = sosStart[numberSOS];
                                                for (i = 0; i < n; i++) {
                                                    int iColumn = sosIndices[i];
                                                    int jColumn = back[iColumn];
                                                    if (jColumn >= 0)
                                                        sosIndices[i] = jColumn;
                                                    else
                                                        nMissing++;
                                                }
                                                delete [] back;
                                                if (nMissing) {
                                                    sprintf(generalPrint, "%d SOS variables vanished due to pre processing? - check validity?", nMissing);
                                                    generalMessageHandler->message(CLP_GENERAL, generalMessages)
                                                    << generalPrint
                                                    << CoinMessageEol;
                                                }
                                            }
                                            for (iSOS = 0; iSOS < numberSOS; iSOS++) {
                                                int iStart = sosStart[iSOS];
                                                int n = sosStart[iSOS+1] - iStart;
                                                objects[iSOS] = new OsiSOS(testOsiSolver, n, sosIndices + iStart, sosReference + iStart,
                                                                           sosType[iSOS]);
                                                if (sosPriority)
                                                    objects[iSOS]->setPriority(sosPriority[iSOS]);
                                                else if (!prioritiesIn)
                                                    objects[iSOS]->setPriority(10);  // rather than 1000
                                            }
                                            // delete any existing SOS objects
                                            int numberObjects = testOsiSolver->numberObjects();
                                            OsiObject ** oldObjects = testOsiSolver->objects();
                                            int nNew = 0;
                                            for (int i = 0; i < numberObjects; i++) {
                                                OsiObject * objThis = oldObjects[i];
                                                OsiSOS * obj1 =
                                                    dynamic_cast <OsiSOS *>(objThis) ;
                                                OsiSOS * obj2 =
                                                    dynamic_cast <OsiSOS *>(objThis) ;
                                                if (!obj1 && !obj2) {
                                                    oldObjects[nNew++] = objThis;
                                                } else {
                                                    delete objThis;
                                                }
                                            }
                                            testOsiSolver->setNumberObjects(nNew);
                                            testOsiSolver->addObjects(numberSOS, objects);
                                            for (iSOS = 0; iSOS < numberSOS; iSOS++)
                                                delete objects[iSOS];
                                            delete [] objects;
                                        }
                                    }
                                    OsiObject ** objects = testOsiSolver->objects();
                                    int numberObjects = testOsiSolver->numberObjects();
                                    int logLevel = parameters_[log].intValue();
                                    for (int iObj = 0; iObj < numberObjects; iObj++) {
                                        // skip sos
                                        OsiSOS * objSOS =
                                            dynamic_cast <OsiSOS *>(objects[iObj]) ;
                                        if (objSOS) {
                                            if (logLevel > 2)
                                                printf("Set %d is SOS - priority %d\n", iObj, objSOS->priority());
                                            continue;
                                        }
                                        int iColumn = objects[iObj]->columnNumber();
                                        if (iColumn >= 0) {
                                            if (originalColumns)
                                                iColumn = originalColumns[iColumn];
                                            if (branchDirection) {
                                                OsiSimpleInteger * obj =
                                                    dynamic_cast <OsiSimpleInteger *>(objects[iObj]) ;
                                                if (obj) {
                                                    obj->setPreferredWay(branchDirection[iColumn]);
                                                } else {
                                                    OsiObject2 * obj =
                                                        dynamic_cast <OsiObject2 *>(objects[iObj]) ;
                                                    if (obj)
                                                        obj->setPreferredWay(branchDirection[iColumn]);
                                                }
                                            }
                                            if (priorities) {
                                                int iPriority = priorities[iColumn];
                                                if (iPriority > 0)
                                                    objects[iObj]->setPriority(iPriority);
                                            }
                                            if (logLevel > 2)
                                                printf("Obj %d is int? - priority %d\n", iObj, objects[iObj]->priority());
                                            if (pseudoUp && pseudoUp[iColumn]) {
                                                abort();
                                            }
                                        }
                                    }
                                    // *************************************************************
                                }
                                int statistics = (printOptions > 0) ? printOptions : 0;
#ifdef COIN_HAS_ASL
                                if (!statusUserFunction_[0]) {
#endif
                                    free(priorities);
                                    priorities = NULL;
                                    free(branchDirection);
                                    branchDirection = NULL;
                                    free(pseudoDown);
                                    pseudoDown = NULL;
                                    free(pseudoUp);
                                    pseudoUp = NULL;
                                    free(solutionIn);
                                    solutionIn = NULL;
                                    free(prioritiesIn);
                                    prioritiesIn = NULL;
                                    free(sosStart);
                                    sosStart = NULL;
                                    free(sosIndices);
                                    sosIndices = NULL;
                                    free(sosType);
                                    sosType = NULL;
                                    free(sosReference);
                                    sosReference = NULL;
                                    free(cut);
                                    cut = NULL;
                                    free(sosPriority);
                                    sosPriority = NULL;
#ifdef COIN_HAS_ASL
                                }
#endif
                                if (nodeStrategy) {
                                    // change default
                                    if (nodeStrategy > 2) {
                                        // up or down
                                        int way = (((nodeStrategy - 1) % 1) == 1) ? -1 : +1;
                                        babModel_->setPreferredWay(way);
#ifdef JJF_ZERO
                                        OsiObject ** objects = babModel_->objects();
                                        int numberObjects = babModel_->numberObjects();
                                        for (int iObj = 0; iObj < numberObjects; iObj++) {
                                            CbcObject * obj =
                                                dynamic_cast <CbcObject *>(objects[iObj]) ;
                                            assert (obj);
                                            obj->setPreferredWay(way);
                                        }
#endif
                                    }
                                    if (nodeStrategy == 2 || nodeStrategy > 4) {
                                        // depth
                                        CbcCompareDefault compare;
                                        compare.setWeight(-3.0);
                                        babModel_->setNodeComparison(compare);
                                    } else if (nodeStrategy == 0) {
                                        // hybrid was default i.e. mixture of low depth and infeasibility
                                    } else if (nodeStrategy == 1) {
                                        // real fewest
                                        CbcCompareDefault compare;
                                        compare.setWeight(-2.0);
                                        babModel_->setNodeComparison(compare);
                                    }
                                }
                                if (cppValue >= 0) {
                                    int prepro = useStrategy ? -1 : preProcess;
                                    // generate code
                                    FILE * fp = fopen("user_driver.cpp", "w");
                                    if (fp) {
                                        // generate enough to do BAB
                                        babModel_->generateCpp(fp, 1);
                                        OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (babModel_->solver());
                                        // Make general so do factorization
                                        int factor = osiclp->getModelPtr()->factorizationFrequency();
                                        osiclp->getModelPtr()->setFactorizationFrequency(200);
                                        osiclp->generateCpp(fp);
                                        osiclp->getModelPtr()->setFactorizationFrequency(factor);
                                        //solveOptions.generateCpp(fp);
                                        fclose(fp);
                                        // now call generate code
                                        generateCode(babModel_, "user_driver.cpp", cppValue, prepro);
                                    } else {
                                        std::cout << "Unable to open file user_driver.cpp" << std::endl;
                                    }
                                }
                                if (!babModel_->numberStrong() && babModel_->numberBeforeTrust() > 0)
                                    babModel_->setNumberBeforeTrust(0);
                                if (useStrategy) {
                                    CbcStrategyDefault strategy(1, babModel_->numberStrong(), babModel_->numberBeforeTrust());
                                    strategy.setupPreProcessing(1);
                                    babModel_->setStrategy(strategy);
                                }
                                if (testOsiOptions >= 0) {
                                    sprintf(generalPrint, "Testing OsiObject options %d", testOsiOptions);
                                    generalMessageHandler->message(CLP_GENERAL, generalMessages)
                                    << generalPrint
                                    << CoinMessageEol;
                                    if (!numberSOS) {
                                        babModel_->solver()->findIntegersAndSOS(false);
#ifdef COIN_HAS_LINK
                                        // If linked then pass in model
                                        OsiSolverLink * solver3 = dynamic_cast<OsiSolverLink *> (babModel_->solver());
                                        if (solver3) {
                                            CbcHeuristicDynamic3 serendipity(*babModel_);
                                            serendipity.setHeuristicName("linked");
                                            babModel_->addHeuristic(&serendipity);
                                            double dextra3 = parameters_[whichParam(CBC_PARAM_DBL_DEXTRA3, numberParameters_, parameters_)].doubleValue();
                                            if (dextra3)
                                                solver3->setMeshSizes(dextra3);
                                            int options = parameters_[whichParam(CBC_PARAM_INT_MIPOPTIONS, numberParameters_, parameters_)].intValue() / 10000;
                                            CglStored stored;
                                            if (options) {
                                                printf("nlp options %d\n", options);
                                                /*
                                                  1 - force mini branch and bound
                                                  2 - set priorities high on continuous
                                                  4 - try adding OA cuts
                                                  8 - try doing quadratic linearization
                                                  16 - try expanding knapsacks
                                                              32 - OA cuts strictly concave
                                                  64 - no branching at all on bilinear x-x!
                                                */
                                                if ((options&2)) {
                                                    solver3->setBiLinearPriorities(10, tightenFactor > 0.0 ? tightenFactor : 1.0);
                                                } else if (tightenFactor > 0.0) {
                                                    // set grid size for all continuous bi-linear
                                                    solver3->setMeshSizes(tightenFactor);
                                                }
                                                if ((options&4)) {
                                                    solver3->setSpecialOptions2(solver3->specialOptions2() | (8 + 4));
                                                    // say convex
                                                    solver3->sayConvex((options&32) == 0);
                                                }
                                                int extra1 = parameters_[whichParam(CBC_PARAM_INT_EXTRA1, numberParameters_, parameters_)].intValue();
                                                if ((options&1) != 0 && extra1 > 0)
                                                    solver3->setFixedPriority(extra1);
                                                double cutoff = COIN_DBL_MAX;
                                                if ((options&8))
                                                    cutoff = solver3->linearizedBAB(&stored);
                                                if (cutoff < babModel_->getCutoff()) {
                                                    babModel_->setCutoff(cutoff);
                                                    // and solution
                                                    //babModel_->setBestObjectiveValue(solver3->bestObjectiveValue());
                                                    babModel_->setBestSolution(solver3->bestSolution(), solver3->getNumCols(),
                                                                               solver3->bestObjectiveValue());
                                                }
                                                if ((options&64))
                                                    solver3->setBranchingStrategyOnVariables(16, -1, 4);
                                            }
                                            solver3->setCbcModel(babModel_);
                                            if (stored.sizeRowCuts())
                                                babModel_->addCutGenerator(&stored, 1, "Stored");
                                            CglTemporary temp;
                                            babModel_->addCutGenerator(&temp, 1, "OnceOnly");
                                            //choose.setNumberBeforeTrusted(2000);
                                            //choose.setNumberStrong(20);
                                        }
                                        // For temporary testing of heuristics
                                        //int testOsiOptions = parameters_[whichParam(CBC_PARAM_INT_TESTOSI,numberParameters_,parameters_)].intValue();
                                        if (testOsiOptions >= 10) {
                                            if (testOsiOptions >= 20)
                                                testOsiOptions -= 10;
                                            printf("*** Temp heuristic with mode %d\n", testOsiOptions - 10);
                                            OsiSolverLink * solver3 = dynamic_cast<OsiSolverLink *> (babModel_->solver());
                                            assert (solver3) ;
                                            int extra1 = parameters_[whichParam(CBC_PARAM_INT_EXTRA1, numberParameters_, parameters_)].intValue();
                                            solver3->setBiLinearPriority(extra1);
                                            printf("bilinear priority now %d\n", extra1);
                                            int extra2 = parameters_[whichParam(CBC_PARAM_INT_EXTRA2, numberParameters_, parameters_)].intValue();
                                            double saveDefault = solver3->defaultBound();
                                            solver3->setDefaultBound(static_cast<double> (extra2));
                                            double * solution = solver3->heuristicSolution(slpValue > 0 ? slpValue : 40 , 1.0e-5, testOsiOptions - 10);
                                            solver3->setDefaultBound(saveDefault);
                                            if (!solution)
                                                printf("Heuristic failed\n");
                                        }
#endif
                                    } else {
                                        // move across
                                        babModel_->deleteObjects(false);
                                        //babModel_->addObjects(babModel_->solver()->numberObjects(),babModel_->solver()->objects());
                                    }
                                    CbcBranchDefaultDecision decision;
                                    if (babModel_->numberStrong()) {
                                        OsiChooseStrong choose(babModel_->solver());
                                        choose.setNumberBeforeTrusted(babModel_->numberBeforeTrust());
                                        choose.setNumberStrong(babModel_->numberStrong());
                                        choose.setShadowPriceMode(testOsiOptions);
                                        decision.setChooseMethod(choose);
                                    } else {
                                        OsiChooseVariable choose(babModel_->solver());
                                        decision.setChooseMethod(choose);
                                    }
                                    babModel_->setBranchingMethod(decision);
                                    if (useCosts && testOsiOptions >= 0) {
				      if(newPriorities ) {
					// get rid of
					delete [] newPriorities;
					newPriorities = NULL;
				      }
                                        int numberColumns = babModel_->getNumCols();
                                        int * sort = new int[numberColumns];
                                        double * dsort = new double[numberColumns];
                                        int * priority = new int [numberColumns];
                                        const double * objective = babModel_->getObjCoefficients();
                                        const double * lower = babModel_->getColLower() ;
                                        const double * upper = babModel_->getColUpper() ;
                                        const CoinPackedMatrix * matrix = babModel_->solver()->getMatrixByCol();
                                        const int * columnLength = matrix->getVectorLengths();
                                        int iColumn;
                                        for (iColumn = 0; iColumn < numberColumns; iColumn++) {
                                            sort[iColumn] = iColumn;
                                            if (useCosts == 1)
                                                dsort[iColumn] = -fabs(objective[iColumn]);
                                            else if (useCosts == 2)
                                                dsort[iColumn] = iColumn;
                                            else if (useCosts == 3)
                                                dsort[iColumn] = upper[iColumn] - lower[iColumn];
                                            else if (useCosts == 4)
                                                dsort[iColumn] = -(upper[iColumn] - lower[iColumn]);
                                            else if (useCosts == 5)
                                                dsort[iColumn] = -columnLength[iColumn];
                                        }
                                        CoinSort_2(dsort, dsort + numberColumns, sort);
                                        int level = 0;
                                        double last = -1.0e100;
                                        for (int i = 0; i < numberColumns; i++) {
                                            int iPut = sort[i];
                                            if (dsort[i] != last) {
                                                level++;
                                                last = dsort[i];
                                            }
                                            priority[iPut] = level;
                                        }
                                        OsiObject ** objects = babModel_->objects();
                                        int numberObjects = babModel_->numberObjects();
                                        for (int iObj = 0; iObj < numberObjects; iObj++) {
                                            OsiObject * obj = objects[iObj] ;
                                            int iColumn = obj->columnNumber();
                                            if (iColumn >= 0)
                                                obj->setPriority(priority[iColumn]);
                                        }
                                        delete [] priority;
                                        delete [] sort;
                                        delete [] dsort;
                                    }
                                }
                                checkSOS(babModel_, babModel_->solver());
                                if (doSprint > 0) {
                                    // Sprint for primal solves
                                    ClpSolve::SolveType method = ClpSolve::usePrimalorSprint;
                                    ClpSolve::PresolveType presolveType = ClpSolve::presolveOff;
                                    int numberPasses = 5;
                                    int options[] = {0, 3, 0, 0, 0, 0};
                                    int extraInfo[] = { -1, 20, -1, -1, -1, -1};
                                    extraInfo[1] = doSprint;
                                    int independentOptions[] = {0, 0, 3};
                                    ClpSolve clpSolve(method, presolveType, numberPasses,
                                                      options, extraInfo, independentOptions);
                                    // say use in OsiClp
                                    clpSolve.setSpecialOption(6, 1);
                                    OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (babModel_->solver());
                                    osiclp->setSolveOptions(clpSolve);
                                    osiclp->setHintParam(OsiDoDualInResolve, false);
                                    // switch off row copy
                                    osiclp->getModelPtr()->setSpecialOptions(osiclp->getModelPtr()->specialOptions() | 256);
                                    osiclp->getModelPtr()->setInfeasibilityCost(1.0e11);
                                }
#ifdef COIN_HAS_LINK
                                if (storedAmpl.sizeRowCuts()) {
                                    if (preProcess) {
                                        const int * originalColumns = process.originalColumns();
                                        int numberColumns = babModel_->getNumCols();
                                        int * newColumn = new int[numberOriginalColumns];
                                        int i;
                                        for (i = 0; i < numberOriginalColumns; i++)
                                            newColumn[i] = -1;
                                        for (i = 0; i < numberColumns; i++) {
                                            int iColumn = originalColumns[i];
                                            newColumn[iColumn] = i;
                                        }
                                        int * buildColumn = new int[numberColumns];
                                        // Build up valid cuts
                                        int nBad = 0;
                                        int nCuts = storedAmpl.sizeRowCuts();
                                        CglStored newCuts;
                                        for (i = 0; i < nCuts; i++) {
                                            const OsiRowCut * cut = storedAmpl.rowCutPointer(i);
                                            double lb = cut->lb();
                                            double ub = cut->ub();
                                            int n = cut->row().getNumElements();
                                            const int * column = cut->row().getIndices();
                                            const double * element = cut->row().getElements();
                                            bool bad = false;
                                            for (int i = 0; i < n; i++) {
                                                int iColumn = column[i];
                                                iColumn = newColumn[iColumn];
                                                if (iColumn >= 0) {
                                                    buildColumn[i] = iColumn;
                                                } else {
                                                    bad = true;
                                                    break;
                                                }
                                            }
                                            if (!bad) {
                                                newCuts.addCut(lb, ub, n, buildColumn, element);
                                            } else {
                                                nBad++;
                                            }
                                        }
                                        storedAmpl = newCuts;
                                        if (nBad)
                                            printf("%d cuts dropped\n", nBad);
                                        delete [] newColumn;
                                        delete [] buildColumn;
                                    }
                                }
#endif
#ifdef CLP_MALLOC_STATISTICS
                                malloc_stats();
                                malloc_stats2();
#endif
#ifndef CBC_OTHER_SOLVER
                                if (outputFormat == 5) {
                                    osiclp = dynamic_cast< OsiClpSolverInterface*> (babModel_->solver());
                                    lpSolver = osiclp->getModelPtr();
                                    lpSolver->setPersistenceFlag(1);
                                }
#endif
#ifdef COIN_HAS_ASL
                                // add in lotsizing
                                if (statusUserFunction_[0] && info.special) {
                                    int numberColumns = babModel_->getNumCols();
                                    int i;
                                    int n = 0;
                                    if (preProcess) {
                                        const int * originalColumns = process.originalColumns();
                                        for (i = 0; i < numberColumns; i++) {
                                            int iColumn = originalColumns[i];
                                            assert (iColumn >= i);
                                            int iType = info.special[iColumn];
                                            if (iType) {
                                                assert (iType == 1);
                                                n++;
                                            }
                                            info.special[i] = iType;
                                        }
                                    }
                                    if (n) {
                                        int numberIntegers = 0;
                                        int numberOldObjects = 0;
                                        OsiObject ** oldObjects = NULL;
                                        const double * lower = babModel_->solver()->getColLower();
                                        const double * upper = babModel_->solver()->getColUpper();
                                        if (testOsiOptions < 0) {
                                            // *************************************************************
                                            // CbcObjects
                                            numberIntegers = babModel_->numberIntegers();
                                            /* model may not have created objects
                                            If none then create
                                            */
                                            if (!numberIntegers || !babModel_->numberObjects()) {
                                                int type = (pseudoUp) ? 1 : 0;
                                                babModel_->findIntegers(true, type);
                                                numberIntegers = babModel_->numberIntegers();
                                            }
                                            oldObjects = babModel_->objects();
                                            numberOldObjects = babModel_->numberObjects();
                                        } else {
                                            numberIntegers = testOsiSolver->getNumIntegers();
                                            if (!numberIntegers || !testOsiSolver->numberObjects()) {
                                                /* model may not have created objects
                                                   If none then create
                                                */
                                                testOsiSolver->findIntegers(false);
                                                numberIntegers = testOsiSolver->getNumIntegers();
                                            }
                                            oldObjects = testOsiSolver->objects();
                                            numberOldObjects = testOsiSolver->numberObjects();
                                        }
                                        OsiObject ** objects = new OsiObject * [n];
                                        n = 0;
                                        // set new objects to have one lower priority
                                        double ranges[] = { -COIN_DBL_MAX, -1.0, 1.0, COIN_DBL_MAX};
                                        for (int iObj = 0; iObj < numberOldObjects; iObj++) {
                                            int iColumn = oldObjects[iObj]->columnNumber();
                                            if (iColumn >= 0 && info.special[iColumn]) {
                                                if (lower[iColumn] <= -1.0 && upper[iColumn] >= 0.0) {
                                                    ranges[0] = lower[iColumn];
                                                    ranges[3] = upper[iColumn];
                                                    int priority = oldObjects[iObj]->priority();
                                                    if (testOsiOptions < 0) {
                                                        objects[n] = new CbcLotsize(babModel_, iColumn, 2, ranges, true);
                                                    } else {
                                                        objects[n] = new OsiLotsize(testOsiSolver, iColumn, 2, ranges, true);
                                                    }
                                                    objects[n++]->setPriority (priority - 1);
                                                }
                                            }
                                        }
                                        if (testOsiOptions < 0) {
                                            babModel_->addObjects(n, objects);
                                        } else {
                                            testOsiSolver->addObjects(n, objects);
                                        }
                                        for (i = 0; i < n; i++)
                                            delete objects[i];
                                        delete [] objects;
                                    }
                                }
#endif
                                if (storedAmpl.sizeRowCuts()) {
                                    //babModel_->addCutGenerator(&storedAmpl,1,"AmplStored");
                                    int numberRowCuts = storedAmpl.sizeRowCuts();
                                    for (int i = 0; i < numberRowCuts; i++) {
                                        const OsiRowCut * rowCutPointer = storedAmpl.rowCutPointer(i);
                                        babModel_->makeGlobalCut(rowCutPointer);
                                    }
                                }
                                // If defaults then increase trust for small models
                                if (!strongChanged) {
                                    int numberColumns = babModel_->getNumCols();
                                    if (numberColumns <= 50)
                                        babModel_->setNumberBeforeTrust(1000);
                                    else if (numberColumns <= 100)
                                        babModel_->setNumberBeforeTrust(100);
                                    else if (numberColumns <= 300)
                                        babModel_->setNumberBeforeTrust(50);
                                }
#ifdef CBC_THREAD
                                int numberThreads = parameters_[whichParam(CBC_PARAM_INT_THREADS, numberParameters_, parameters_)].intValue();
                                babModel_->setNumberThreads(numberThreads % 100);
                                babModel_->setThreadMode(numberThreads / 100);
#endif
                                int returnCode = callBack(babModel_, 3);
                                if (returnCode) {
                                    // exit if user wants
                                    delete babModel_;
                                    babModel_ = NULL;
                                    return returnCode;
                                }
#ifndef CBC_OTHER_SOLVER
                                osiclp = dynamic_cast< OsiClpSolverInterface*> (babModel_->solver());
                                lpSolver = osiclp->getModelPtr();
				int hotits = parameters_[whichParam(CBC_PARAM_INT_MAXHOTITS, numberParameters_, parameters_)].intValue();
				if (hotits>100) {
				  osiclp->setSpecialOptions(osiclp->specialOptions()&~32);
				  osiclp->setIntParam(OsiMaxNumIterationHotStart, hotits);
				} else {
				  osiclp->setIntParam(OsiMaxNumIterationHotStart, hotits);
				}
#elif CBC_OTHER_SOLVER==1
#endif
                                if ((experimentFlag >= 1 || strategyFlag >= 1) && babModel_->fastNodeDepth() == -1) {
                                    if (babModel_->solver()->getNumCols() +
                                            babModel_->solver()->getNumRows() < 500)
                                        babModel_->setFastNodeDepth(-12);
                                } else if (babModel_->fastNodeDepth() == -999) {
                                    babModel_->setFastNodeDepth(-1);
                                }
                                int heurOptions = parameters_[whichParam(CBC_PARAM_INT_HOPTIONS, numberParameters_, parameters_)].intValue();
                                if (heurOptions > 100)
                                    babModel_->setSpecialOptions(babModel_->specialOptions() | 8192);

#ifndef CBC_OTHER_SOLVER
#ifdef CLP_MULTIPLE_FACTORIZATIONS
                                int denseCode = parameters_[whichParam(CBC_PARAM_INT_DENSE, numberParameters_, parameters_)].intValue();
                                int smallCode = parameters_[whichParam(CBC_PARAM_INT_SMALLFACT, numberParameters_, parameters_)].intValue();
                                if (bothFlags >= 1) {
                                    if (denseCode < 0)
                                        denseCode = 40;
                                    if (smallCode < 0 && !lpSolver->factorization()->isDenseOrSmall())
                                        smallCode = 40;
                                }
                                if (denseCode > 0) {
                                    lpSolver->factorization()->setGoDenseThreshold(denseCode);
                                    assert (osiclp == babModel_->solver());
                                    osiclp->setSpecialOptions(osiclp->specialOptions() | 1024);
                                }
                                if (smallCode > 0 && smallCode > denseCode)
                                    lpSolver->factorization()->setGoSmallThreshold(smallCode);
                                //if (denseCode>=lpSolver->numberRows()) {
                                //lpSolver->factorization()->goDense();
                                //}
                                if (lpSolver->factorization()->goOslThreshold() > 1000) {
                                    // use osl in gomory (may not if CglGomory decides not to)
                                    int numberGenerators = babModel_->numberCutGenerators();
				    int nGomory=0;
                                    for (int iGenerator = 0; iGenerator < numberGenerators;
                                            iGenerator++) {
                                        CbcCutGenerator * generator = babModel_->cutGenerator(iGenerator);
                                        CglGomory * gomory = dynamic_cast<CglGomory *>
                                                             (generator->generator());
                                        if (gomory) {
					  if (nGomory<2) {
                                            gomory->useAlternativeFactorization();
					  } else if (gomory->originalSolver()) {
					    OsiClpSolverInterface * clpSolver = dynamic_cast<OsiClpSolverInterface *>(gomory->originalSolver());
					    if (clpSolver) {
					      ClpSimplex * simplex = clpSolver->getModelPtr();
					      simplex->factorization()->setGoOslThreshold(0);
					    }
					  }
					    nGomory++;
					}
                                    }
                                }
#endif
#endif
#ifdef CLIQUE_ANALYSIS
                                if (!storedAmpl.sizeRowCuts()) {
                                    printf("looking at probing\n");
                                    babModel_->addCutGenerator(&storedAmpl, 1, "Stored");
                                }
#endif
                                if (useSolution > 1) {
                                    // use hotstart to try and find solution
                                    CbcHeuristicPartial partial(*babModel_, 10000, useSolution);
                                    partial.setHeuristicName("Partial solution given");
                                    babModel_->addHeuristic(&partial);
                                }
                                if (logLevel <= 1)
                                    babModel_->solver()->setHintParam(OsiDoReducePrint, true, OsiHintTry);
#ifdef CBC_TEMP1
                                if (osiclp->getModelPtr()->perturbation() == 50)
                                    osiclp->getModelPtr()->setPerturbation(52); // try less
#endif
#ifdef JJF_ZERO
                                if (osiclp->getNumCols() == 29404) {
                                    void restoreSolution(ClpSimplex * lpSolver,
                                                         std::string fileName, int mode);
                                    restoreSolution(osiclp->getModelPtr(), "debug.file", 0);
                                    int numberColumns = osiclp->getNumCols();
                                    const double * solution = osiclp->getColSolution();
                                    const int * originalColumns = process.originalColumns();
                                    for (int i = 0; i < numberColumns; i++) {
                                        int iColumn = originalColumns[i];
                                        if (saveSolver->isInteger(iColumn)) {
                                            double value = solution[i];
                                            double value2 = floor(value + 0.5);
                                            assert (fabs(value - value2) < 1.0e-3);
                                            saveSolver->setColLower(iColumn, value2);
                                            saveSolver->setColUpper(iColumn, value2);
                                        }
                                    }
                                    saveSolver->writeMps("fixed");
                                    babModel_->setBestSolution(osiclp->getColSolution(),
                                                               osiclp->getNumCols(),
                                                               1.5325e10);
                                } else {
                                    babModel_->branchAndBound(statistics);
                                }
#else
#ifdef ORBITAL
                                CbcOrbital orbit(babModel_);
                                orbit.morph();
                                exit(1);
#endif
                                int hOp1 = parameters_[whichParam(CBC_PARAM_INT_HOPTIONS, numberParameters_, parameters_)].intValue() / 100000;
                                if (hOp1 % 10) {
                                    CbcCompareDefault compare;
                                    compare.setBreadthDepth(hOp1 % 10);
                                    babModel_->setNodeComparison(compare);
                                }
#if CBC_OTHER_SOLVER==1
                                if (dynamic_cast<OsiCpxSolverInterface *> (babModel_->solver()))
                                    babModel_->solver()->messageHandler()->setLogLevel(0);
#endif
                                if (parameters_[whichParam(CBC_PARAM_STR_CPX, numberParameters_, parameters_)].currentOptionAsInteger()) {
                                    babModel_->setSpecialOptions(babModel_->specialOptions() | 16384);
                                    //if (babModel_->fastNodeDepth()==-1)
                                    babModel_->setFastNodeDepth(-2); // Use Cplex at root
                                }
                                int hOp2 = parameters_[whichParam(CBC_PARAM_INT_HOPTIONS, numberParameters_, parameters_)].intValue() / 10000;
                                if (hOp2 % 10) {
                                    babModel_->setSpecialOptions(babModel_->specialOptions() | 16384);
                                    if (babModel_->fastNodeDepth() == -1)
                                        babModel_->setFastNodeDepth(-2); // Use Cplex at root
                                }
                                if (experimentFlag >= 5) {
                                    CbcModel donor(*babModel_);
                                    int options = babModel_->specialOptions();
                                    donor.setSpecialOptions(options | 262144);
                                    ClpSimplex * lpSolver2;
                                    OsiClpSolverInterface * clpSolver2;
                                    clpSolver2 =
                                        dynamic_cast<OsiClpSolverInterface *> (donor.solver());
                                    assert (clpSolver2);
                                    lpSolver2 = clpSolver2->getModelPtr();
                                    assert (lpSolver2);
                                    if (lpSolver->factorization()->isDenseOrSmall()) {
                                        lpSolver2->factorization()->forceOtherFactorization(0);
                                        lpSolver2->factorization()->setGoOslThreshold(0);
                                        lpSolver2->factorization()->setGoDenseThreshold(0);
                                        lpSolver2->factorization()->setGoSmallThreshold(0);
                                        lpSolver2->allSlackBasis();
                                        lpSolver2->initialSolve();
                                        int numberGenerators = donor.numberCutGenerators();
                                        for (int iGenerator = 0; iGenerator < numberGenerators;
                                                iGenerator++) {
                                            CbcCutGenerator * generator = donor.cutGenerator(iGenerator);
                                            CglGomory * gomory = dynamic_cast<CglGomory *>
                                                                 (generator->generator());
                                            if (gomory)
                                                gomory->useAlternativeFactorization(false);
                                        }
                                    } else {
                                        printf("code this\n");
                                        abort();
                                    }
                                    babModel_->setSpecialOptions(options | 524288);
                                    CglStored * stored = new CglStored(donor.getNumCols());
                                    donor.setStoredRowCuts(stored);
                                    donor.branchAndBound(0);
                                    babModel_->setStoredRowCuts(donor.storedRowCuts());
                                    donor.setStoredRowCuts(NULL);
                                }
				// We may have priorities from extra variables
				int more2 = parameters_[whichParam(CBC_PARAM_INT_MOREMOREMIPOPTIONS, numberParameters_, parameters_)].intValue();
				if(newPriorities ) {
				  if (truncateColumns<babModel_->getNumCols()) {
				    // set new ones as high prority
				    babModel_->passInPriorities(newPriorities,false);
				  }
				  delete [] newPriorities;
				} else if ((more2&(512|1024)) != 0) {
				  babModel_->findIntegers(true);
				  int numberIntegers = babModel_->numberIntegers();
				  int * newPriorities = new int [numberIntegers];
				  int n = numberIntegers - (babModel_->getNumCols()-truncateColumns);
				  for (int i=0;i<n;i++)
				    newPriorities[i]=babModel_->priority(i);
#if 1
				  int ixxxxxx = 
				    parameters_[whichParam(CBC_PARAM_INT_MAXNODES, numberParameters_, parameters_)].intValue();
				  int obj_priority=1000;
				  int slack_priority=1000;
				  if (ixxxxxx>=1000000&&ixxxxxx<1010000) {
				    ixxxxxx -= 1000000;
				    if (ixxxxxx == 0) {
				      obj_priority=1000;
				      slack_priority=1000;
				    } else if(ixxxxxx == 1) {
				      obj_priority=10000;
				      slack_priority=10000;
				    } else if(ixxxxxx == 2) {
				      obj_priority=100;
				      slack_priority=100;
				    } else if(ixxxxxx == 3) {
				      obj_priority=100;
				      slack_priority=10000;
				    } else if(ixxxxxx == 4) {
				      obj_priority=10000;
				      slack_priority=100;
				    } else if(ixxxxxx == 5) {
				      obj_priority=100;
				      slack_priority=200;
				    } else if(ixxxxxx == 6) {
				      obj_priority=200;
				      slack_priority=100;
				    } else {
				      abort();
				    }
				  }
				  if ((more2&512)!=0) {
				    newPriorities[n++]=obj_priority;
				  }
				  if ((more2&1024)!=0) {
				    for (int i=n;i<numberIntegers;i++)
				      newPriorities[i]=slack_priority;
				  }
#else
#define PRIORITY_TRY 0
#if PRIORITY_TRY == 0
#define OBJ_PRIORITY 1000
#define SLACK_PRIORITY 1000
#elif PRIORITY_TRY == 1
#define OBJ_PRIORITY 10000
#define SLACK_PRIORITY 10000
#elif PRIORITY_TRY == 2
#define OBJ_PRIORITY 100
#define SLACK_PRIORITY 100
#elif PRIORITY_TRY == 3
#define OBJ_PRIORITY 100
#define SLACK_PRIORITY 10000
#elif PRIORITY_TRY == 4
#define OBJ_PRIORITY 10000
#define SLACK_PRIORITY 100
#elif PRIORITY_TRY == 5
#define OBJ_PRIORITY 100
#define SLACK_PRIORITY 200
#elif PRIORITY_TRY == 6
#define OBJ_PRIORITY 200
#define SLACK_PRIORITY 100
#endif
				  if ((more2&512)!=0) {
				    newPriorities[n++]=OBJ_PRIORITY;
				  }
				  if ((more2&1024)!=0) {
				    for (int i=n;i<numberIntegers;i++)
				      newPriorities[i]=SLACK_PRIORITY;
				  }
#endif
				  babModel_->passInPriorities(newPriorities,false);
				  delete [] newPriorities;
				}
#ifdef JJF_ZERO
                                int extra5 = parameters_[whichParam(EXTRA5, numberParameters_, parameters_)].intValue();
                                if (extra5 > 0) {
                                    int numberGenerators = babModel_->numberCutGenerators();
                                    for (int iGenerator = 0; iGenerator < numberGenerators;
                                            iGenerator++) {
                                        CbcCutGenerator * generator = babModel_->cutGenerator(iGenerator);
                                        CglGomory * gomory = dynamic_cast<CglGomory *>
                                                             (generator->generator());
                                        if (gomory) {
                                            CglGomory gomory2(*gomory);
                                            gomory2.useAlternativeFactorization(!gomory->alternativeFactorization());
                                            babModel_->addCutGenerator(&gomory2, -99, "Gomory2");
                                        }
                                    }
                                }
#endif
                                int specialOptions = parameters_[whichParam(CBC_PARAM_INT_STRONG_STRATEGY, numberParameters_, parameters_)].intValue();
				if (specialOptions>=0)
				  babModel_->setStrongStrategy(specialOptions);
				int jParam = whichParam(CBC_PARAM_STR_CUTOFF_CONSTRAINT, 
							numberParameters_, parameters_);
				if(parameters_[jParam].currentOptionAsInteger()) {
				  babModel_->setCutoffAsConstraint(true);
				  int moreOptions=babModel_->moreSpecialOptions();
				  if(parameters_[jParam].currentOptionAsInteger()==4) 
				    babModel_->setMoreSpecialOptions(moreOptions|4194304);
				}
                                int multipleRoot = parameters_[whichParam(CBC_PARAM_INT_MULTIPLEROOTS, numberParameters_, parameters_)].intValue();
				if (multipleRoot<10000) {
				  babModel_->setMultipleRootTries(multipleRoot);
				} else {
				  // will be doing repeated solves and saves
				  int numberGoes=multipleRoot/10000;
				  multipleRoot-=10000*numberGoes;
				  int moreOptions=babModel_->moreSpecialOptions();
				  if (numberGoes<100) {
				    remove("global.cuts");
				    remove("global.fix");
				    moreOptions |= (67108864|134217728);
				  } else {
				    moreOptions |= 67108864*(numberGoes/100);
				    numberGoes=numberGoes%100;
				  }
				  babModel_->setMultipleRootTries(multipleRoot);
				  babModel_->setMoreSpecialOptions(moreOptions);
				  int numberColumns=babModel_->getNumCols();
				  double * bestValues=new double [numberGoes];
				  double ** bestSolutions=new double * [numberGoes];
				  int * which=new int[numberGoes];
				  int numberSolutions=0;
				  sprintf(generalPrint,"Starting %d passes each with %d solvers",
					  numberGoes, multipleRoot%10);
				  generalMessageHandler->message(CLP_GENERAL, generalMessages)
				    << generalPrint
				    << CoinMessageEol;
				  for (int iGo=0;iGo<numberGoes;iGo++) {
				    sprintf(generalPrint,"Starting pass %d",iGo+1);
				    generalMessageHandler->message(CLP_GENERAL, generalMessages)
				      << generalPrint
				      << CoinMessageEol;
				    CbcModel tempModel=*babModel_;
				    tempModel.setMaximumNodes(0);
				    // switch off cuts if none generated
				    int numberGenerators = tempModel.numberCutGenerators();
				    for (int iGenerator = 0; iGenerator < numberGenerators; iGenerator++) {
				      CbcCutGenerator * generator = tempModel.cutGenerator(iGenerator);
				      generator->setSwitchOffIfLessThan(1);
				    }
				    // random
				    tempModel.setRandomSeed(tempModel.getRandomSeed()+100000000*(iGo+1+5*numberGoes));
				    for (int i=0;i<tempModel.numberHeuristics();i++)
				      tempModel.heuristic(i)->setSeed(tempModel.heuristic(i)->getSeed()+100000000*iGo);
#ifndef CBC_OTHER_SOLVER
				    OsiClpSolverInterface * solver = dynamic_cast<OsiClpSolverInterface *> (tempModel.solver());
				    ClpSimplex * simplex = solver->getModelPtr();
				    int solverSeed=simplex->randomNumberGenerator()->getSeed();
				    simplex->setRandomSeed(solverSeed+100000000*(iGo+1));
#endif
				    tempModel.branchAndBound();
				    if (tempModel.bestSolution()) {
				      bestSolutions[numberSolutions]=
					CoinCopyOfArray(tempModel.bestSolution(),
							numberColumns);
				      bestValues[numberSolutions]=-tempModel.getMinimizationObjValue();
				      which[numberSolutions]=numberSolutions;
				      numberSolutions++;
				    }
				  }
				  // allow solutions
				  double sense = babModel_->solver()->getObjSense();;
				  CoinSort_2(bestValues,bestValues+numberSolutions,which);
				  babModel_->setMoreSpecialOptions(moreOptions&(~16777216));
				  for (int i=0;i<numberSolutions;i++) {
				    int k=which[i];
				    if (bestValues[i]<babModel_->getCutoff()) {
				      babModel_->setBestSolution(bestSolutions[k],numberColumns,
								 -bestValues[i]*sense,true);
				      babModel_->incrementUsed(bestSolutions[k]);
				    }
				    delete [] bestSolutions[k];
				  }
				  babModel_->setMoreSpecialOptions(moreOptions);
				  if (numberSolutions)
				    sprintf(generalPrint,"Ending major passes - best solution %g",-bestValues[numberSolutions-1]);
				  else
				    sprintf(generalPrint,"Ending major passes - no solution found");
				    generalMessageHandler->message(CLP_GENERAL, generalMessages)
				      << generalPrint
				      << CoinMessageEol;
				  delete [] which;
				  delete [] bestValues;
				  delete [] bestSolutions;
				}
				if (biLinearProblem)
				  babModel_->setSpecialOptions(babModel_->specialOptions() &(~(512|32768)));
                                babModel_->setMoreSpecialOptions2(parameters_[whichParam(CBC_PARAM_INT_MOREMOREMIPOPTIONS, numberParameters_, parameters_)].intValue());
#ifdef COIN_HAS_NTY
				{
				  int jParam = whichParam(CBC_PARAM_STR_ORBITAL, 
							numberParameters_, parameters_);
				  if(parameters_[jParam].currentOptionAsInteger()) {
				    int k = parameters_[jParam].currentOptionAsInteger();
				    babModel_->setMoreSpecialOptions2(babModel_->moreSpecialOptions2() | (k*128));
				  }
				}
#endif
                                babModel_->branchAndBound(statistics);
				if (truncateColumns<babModel_->solver()->getNumCols()) {
				  OsiSolverInterface * solverX = babModel_->solver();
				  int numberColumns=solverX->getNumCols();
				  int numberRows=solverX->getNumRows();
				  int numberDelete = numberColumns-truncateColumns;
				  int * delStuff=new int [numberDelete];
				  for (int i=0;i<numberDelete;i++)
				    delStuff[i]=i+truncateColumns;
				  solverX->deleteCols(numberDelete,delStuff);
				  numberDelete = numberRows-truncateRows;
				  for (int i=0;i<numberDelete;i++)
				    delStuff[i]=i+truncateRows;
				  solverX->deleteRows(numberDelete,delStuff);
				  delete [] delStuff;
				  if (truncatedRhsLower) {
				    numberRows=solverX->getNumRows();
				    for (int i=0;i<numberRows;i++) {
				      solverX->setRowLower(i,truncatedRhsLower[i]);
				      solverX->setRowUpper(i,truncatedRhsUpper[i]);
				    }
				    delete [] truncatedRhsLower;
				    delete [] truncatedRhsUpper;
				  }
				}
                                //#define CLP_FACTORIZATION_INSTRUMENT
#ifdef CLP_FACTORIZATION_INSTRUMENT
                                extern double factorization_instrument(int type);
                                double facTime = factorization_instrument(0);
                                printf("Factorization %g seconds\n",
                                       facTime);
#endif
#endif
#ifdef COIN_DEVELOP
#ifndef JJF_ONE
                                {
                                    int numberColumns = babModel_->getNumCols();
                                    const double * solution = babModel_->bestSolution();
                                    if (solution && numberColumns < 1000) {
                                        for (int i = 0; i < numberColumns; i++) {
                                            if (solution[i])
                                                printf("SOL %d %.18g\n", i, solution[i]);
                                        }
                                    }
                                }
#endif
                                void printHistory(const char * file/*,CbcModel * model*/);
                                printHistory("branch.log"/*,babModel_*/);
#endif
                                returnCode = callBack(babModel_, 4);
                                if (returnCode) {
                                    // exit if user wants
                                    model_.moveInfo(*babModel_);
                                    delete babModel_;
                                    babModel_ = NULL;
                                    return returnCode;
				} else {
				  int numberSolutions = babModel_->numberSavedSolutions();
				  if (numberSolutions>1) {
				    for (int iSolution=numberSolutions-1;iSolution>=0;iSolution--) {
				      const double * savedSolution =babModel_->savedSolution(iSolution);
				      int numberColumns=model_.solver()->getNumCols();
				      // only set if dimensions OK
				      int numberBabColumns=static_cast<int>
					(savedSolution[-2]);
				      if (numberBabColumns>=numberColumns)
					model_.setBestSolution(savedSolution,
							     numberColumns,
							     babModel_->savedSolutionObjective(iSolution));
				    }
				  }
                                }
#ifdef CLP_MALLOC_STATISTICS
                                malloc_stats();
                                malloc_stats2();
#endif
                                checkSOS(babModel_, babModel_->solver());
                            } else if (type == CBC_PARAM_ACTION_MIPLIB) {
                                int typeOfCuts = babModel_->numberCutGenerators() ? 1 : -1;
                                CbcStrategyDefault strategy(typeOfCuts,
                                                            babModel_->numberStrong(),
                                                            babModel_->numberBeforeTrust());
                                // Set up pre-processing
                                int translate2[] = {9999, 1, 1, 3, 2, 4, 5, 6, 6};
                                if (preProcess)
                                    strategy.setupPreProcessing(translate2[ preProcess ]);
                                babModel_->setStrategy(strategy);
#ifdef CBC_THREAD
                                int numberThreads = parameters_[whichParam(CBC_PARAM_INT_THREADS, numberParameters_, parameters_)].intValue();
                                babModel_->setNumberThreads(numberThreads % 100);
                                babModel_->setThreadMode(numberThreads / 100);
#endif
#ifndef CBC_OTHER_SOLVER
                                if (outputFormat == 5) {
                                    osiclp = dynamic_cast< OsiClpSolverInterface*> (babModel_->solver());
                                    lpSolver = osiclp->getModelPtr();
                                    lpSolver->setPersistenceFlag(1);
                                }
#endif
                                if (testOsiOptions >= 0) {
                                    printf("Testing OsiObject options %d\n", testOsiOptions);
                                    CbcBranchDefaultDecision decision;
                                    OsiChooseStrong choose(babModel_->solver());
                                    choose.setNumberBeforeTrusted(babModel_->numberBeforeTrust());
                                    choose.setNumberStrong(babModel_->numberStrong());
                                    choose.setShadowPriceMode(testOsiOptions);
                                    //babModel_->deleteObjects(false);
                                    decision.setChooseMethod(choose);
                                    babModel_->setBranchingMethod(decision);
                                }
                                model_ = *babModel_;
#ifndef CBC_OTHER_SOLVER
                                {
                                    osiclp = dynamic_cast< OsiClpSolverInterface*> (model_.solver());
                                    lpSolver = osiclp->getModelPtr();
                                    lpSolver->setSpecialOptions(lpSolver->specialOptions() | IN_BRANCH_AND_BOUND); // say is Cbc (and in branch and bound)
                                    if (lpSolver->factorization()->goOslThreshold() > 1000) {
                                        // use osl in gomory (may not if CglGomory decides not to)
                                        int numberGenerators = model_.numberCutGenerators();
                                        for (int iGenerator = 0; iGenerator < numberGenerators;
                                                iGenerator++) {
                                            CbcCutGenerator * generator = model_.cutGenerator(iGenerator);
                                            CglGomory * gomory = dynamic_cast<CglGomory *>
                                                                 (generator->generator());
                                            if (gomory)
                                                gomory->useAlternativeFactorization();
                                        }
                                    }
                                }
#endif
                                /* LL: this was done in CoinSolve.cpp: main(argc, argv).
                                   I have moved it here so that the miplib directory location
                                   could be passed to CbcClpUnitTest. */
                                /* JJF: No need to have 777 flag at all - user
                                   says -miplib
                                */
                                int extra2 = parameters_[whichParam(CBC_PARAM_INT_EXTRA2, numberParameters_, parameters_)].intValue();
                                double stuff[11];
                                stuff[0] = parameters_[whichParam(CBC_PARAM_DBL_FAKEINCREMENT, numberParameters_, parameters_)].doubleValue();
                                stuff[1] = parameters_[whichParam(CBC_PARAM_DBL_FAKECUTOFF, numberParameters_, parameters_)].doubleValue();
                                stuff[2] = parameters_[whichParam(CBC_PARAM_DBL_DEXTRA3, numberParameters_, parameters_)].doubleValue();
                                stuff[3] = parameters_[whichParam(CBC_PARAM_DBL_DEXTRA4, numberParameters_, parameters_)].doubleValue();
                                stuff[4] = parameters_[whichParam(CBC_PARAM_INT_DENSE, numberParameters_, parameters_)].intValue();
                                stuff[5] = parameters_[whichParam(CBC_PARAM_INT_EXTRA1, numberParameters_, parameters_)].intValue();
                                stuff[6] = parameters_[whichParam(CBC_PARAM_INT_EXTRA3, numberParameters_, parameters_)].intValue();
                                stuff[7] = parameters_[whichParam(CBC_PARAM_INT_DEPTHMINIBAB, numberParameters_, parameters_)].intValue();
                                stuff[8] = bothFlags;
                                stuff[9] = doVector;
                                stuff[10] = parameters_[whichParam(CBC_PARAM_INT_SMALLFACT, numberParameters_, parameters_)].intValue();
                                if ( dominatedCuts)
                                    model_.setSpecialOptions(model_.specialOptions() | 64);
                                if (parameters_[whichParam(CBC_PARAM_STR_CPX, numberParameters_, parameters_)].currentOptionAsInteger()) {
                                    model_.setSpecialOptions(model_.specialOptions() | 16384);
                                    //if (model_.fastNodeDepth()==-1)
                                    model_.setFastNodeDepth(-2); // Use Cplex at root
                                }
                                int hOp2 = parameters_[whichParam(CBC_PARAM_INT_HOPTIONS, numberParameters_, parameters_)].intValue() / 10000;
                                if (hOp2 % 10) {
                                    model_.setSpecialOptions(model_.specialOptions() | 16384);
                                    if (model_.fastNodeDepth() == -1)
                                        model_.setFastNodeDepth(-2); // Use Cplex at root
                                }
                                int multipleRoot = parameters_[whichParam(CBC_PARAM_INT_MULTIPLEROOTS, numberParameters_, parameters_)].intValue();
				model_.setMultipleRootTries(multipleRoot);
                                int specialOptions = parameters_[whichParam(CBC_PARAM_INT_STRONG_STRATEGY, numberParameters_, parameters_)].intValue();
				if (specialOptions>=0)
				  model_.setStrongStrategy(specialOptions);
                                if (!pumpChanged) {
                                    // Make more lightweight
                                    for (int iHeur = 0; iHeur < model_.numberHeuristics(); iHeur++) {
                                        CbcHeuristic * heuristic = model_.heuristic(iHeur);
                                        CbcHeuristicFPump* pump =
                                            dynamic_cast<CbcHeuristicFPump*>(heuristic);
                                        if (pump) {
                                            CbcHeuristicFPump heuristic4(model_);
                                            heuristic4.setFractionSmall(0.5);
                                            heuristic4.setMaximumPasses(5);
                                            heuristic4.setFeasibilityPumpOptions(30);
                                            heuristic4.setWhen(13);
                                            heuristic4.setHeuristicName("feasibility pump");
                                            //CbcHeuristicFPump & pump2 = pump;
                                            *pump = heuristic4;
                                        }
                                    }
                                }
                                int returnCode = CbcClpUnitTest(model_, dirMiplib, extra2, stuff);
                                babModel_ = NULL;
                                return returnCode;
                            } else {
                                abort(); // can't get here
                                //strengthenedModel = babModel_->strengthenedModel();
                            }
                            currentBranchModel = NULL;
#ifndef CBC_OTHER_SOLVER
                            osiclp = dynamic_cast< OsiClpSolverInterface*> (babModel_->solver());
                            if (debugFile == "createAfterPre" && babModel_->bestSolution()) {
                                lpSolver = osiclp->getModelPtr();
                                //move best solution (should be there -- but ..)
                                int n = lpSolver->getNumCols();
                                memcpy(lpSolver->primalColumnSolution(), babModel_->bestSolution(), n*sizeof(double));
                                saveSolution(osiclp->getModelPtr(), "debug.file");
                            }
#endif
                            statistics_cut_time = 0.0;
                            if (!noPrinting_) {
                                // Print more statistics
                                sprintf(generalPrint, "Cuts at root node changed objective from %g to %g",
                                        babModel_->getContinuousObjective(), babModel_->rootObjectiveAfterCuts());
                                generalMessageHandler->message(CLP_GENERAL, generalMessages)
                                << generalPrint
                                << CoinMessageEol;

                                numberGenerators = babModel_->numberCutGenerators();
                                if (statistics_number_cuts)
                                    delete[] statistics_number_cuts;
                                statistics_number_cuts = new int [numberGenerators];;
                                statistics_number_generators = numberGenerators;
                                statistics_name_generators = new const char *[numberGenerators];
                                char timing[30];
                                for (iGenerator = 0; iGenerator < numberGenerators; iGenerator++) {
                                    CbcCutGenerator * generator = babModel_->cutGenerator(iGenerator);
                                    statistics_name_generators[iGenerator] =
                                        generator->cutGeneratorName();
                                    statistics_number_cuts[iGenerator] = generator->numberCutsInTotal();
                                    sprintf(generalPrint, "%s was tried %d times and created %d cuts of which %d were active after adding rounds of cuts",
                                            generator->cutGeneratorName(),
                                            generator->numberTimesEntered(),
                                            generator->numberCutsInTotal() +
                                            generator->numberColumnCuts(),
                                            generator->numberCutsActive());
                                    if (generator->timing()) {
                                        sprintf(timing, " (%.3f seconds)", generator->timeInCutGenerator());
                                        strcat(generalPrint, timing);
                                        statistics_cut_time += generator->timeInCutGenerator();
                                    }
                                    CglStored * stored = dynamic_cast<CglStored*>(generator->generator());
                                    if (stored && !generator->numberCutsInTotal())
                                        continue;
#ifndef CLP_INVESTIGATE
                                    CglImplication * implication = dynamic_cast<CglImplication*>(generator->generator());
                                    if (implication && !generator->numberCutsInTotal())
                                        continue;
#endif
                                    generalMessageHandler->message(CLP_GENERAL, generalMessages)
                                    << generalPrint
                                    << CoinMessageEol;
                                }

#ifdef COIN_DEVELOP
                                printf("%d solutions found by heuristics\n",
                                       babModel_->getNumberHeuristicSolutions());
                                // Not really generator but I am feeling lazy
                                for (iGenerator = 0; iGenerator < babModel_->numberHeuristics(); iGenerator++) {
                                    CbcHeuristic * heuristic = babModel_->heuristic(iGenerator);
                                    if (heuristic->numRuns()) {
                                        // Need to bring others inline
                                        sprintf(generalPrint, "%s was tried %d times out of %d and created %d solutions\n",
                                                heuristic->heuristicName(),
                                                heuristic->numRuns(),
                                                heuristic->numCouldRun(),
                                                heuristic->numberSolutionsFound());
                                        generalMessageHandler->message(CLP_GENERAL, generalMessages)
                                        << generalPrint
                                        << CoinMessageEol;
                                    }
                                }
#endif
                            }
                            // adjust time to allow for children on some systems
                            time2 = CoinCpuTime() + CoinCpuTimeJustChildren();
                            totalTime += time2 - time1;
                            // For best solution
                            double * bestSolution = NULL;
                            // Say in integer
                            if (babModel_->status()) {
                                // treat as stopped
                                integerStatus = 3;
                            } else {
                                if (babModel_->isProvenOptimal()) {
                                    integerStatus = 0;
                                } else if (!babModel_->bestSolution()) {
                                    // infeasible
                                    integerStatus = 6;
				    delete saveSolver;
				    saveSolver=NULL;
                                }
                            }
                            if (babModel_->getMinimizationObjValue() < 1.0e50 && type == CBC_PARAM_ACTION_BAB) {
                                // post process
                                int n;
                                if (preProcess) {
                                    n = saveSolver->getNumCols();
                                    bestSolution = new double [n];
#ifndef CBC_OTHER_SOLVER
                                    OsiClpSolverInterface * clpSolver = dynamic_cast< OsiClpSolverInterface*> (babModel_->solver());
#else
                                    OsiCpxSolverInterface * clpSolver = dynamic_cast< OsiCpxSolverInterface*> (babModel_->solver());
#endif
                                    // Save bounds on processed model
                                    const int * originalColumns = process.originalColumns();
                                    int numberColumns2 = clpSolver->getNumCols();
                                    double * solution2 = new double[n];
                                    double * lower2 = new double [n];
                                    double * upper2 = new double [n];
                                    for (int i = 0; i < n; i++) {
                                        solution2[i] = COIN_DBL_MAX;
                                        lower2[i] = COIN_DBL_MAX;
                                        upper2[i] = -COIN_DBL_MAX;
                                    }
                                    const double *columnLower = clpSolver->getColLower() ;
                                    const double * columnUpper = clpSolver->getColUpper() ;
                                    const double * solution = babModel_->bestSolution();
                                    for (int i = 0; i < numberColumns2; i++) {
                                        int jColumn = originalColumns[i];
                                        if (jColumn < n) {
                                            solution2[jColumn] = solution[i];
                                            lower2[jColumn] = columnLower[i];
                                            upper2[jColumn] = columnUpper[i];
                                        }
                                    }
#ifndef CBC_OTHER_SOLVER
                                    ClpSimplex * lpSolver = clpSolver->getModelPtr();
                                    lpSolver->setSpecialOptions(lpSolver->specialOptions() | IN_BRANCH_AND_BOUND); // say is Cbc (and in branch and bound)
#endif
                                    // put back any saved solutions
                                    putBackOtherSolutions(babModel_,&model_,&process);
                                    process.postProcess(*babModel_->solver());
#ifdef COIN_DEVELOP
                                    if (model_.bestSolution() && fabs(model_.getMinimizationObjValue() -
                                                                      babModel_->getMinimizationObjValue()) < 1.0e-8) {
                                        const double * b1 = model_.bestSolution();
                                        const double * b2 = saveSolver->getColSolution();
                                        const double * columnLower = saveSolver->getColLower() ;
                                        const double * columnUpper = saveSolver->getColUpper() ;
                                        for (int i = 0; i < n; i++) {
                                            if (fabs(b1[i] - b2[i]) > 1.0e-7) {
                                                printf("%d %g %g %g %g\n", i, b1[i], b2[i],
                                                       columnLower[i], columnUpper[i]);
                                            }
                                        }
                                    }
#endif
                                    bool tightenB = false;
                                    {
                                        int n = babModel_->numberObjects();
                                        for (int i = 0; i < n; i++) {
                                            const OsiObject * obj = babModel_->object(i);
                                            if (!dynamic_cast<const CbcSimpleInteger *>(obj)) {
                                                tightenB = true;
                                                break;
                                            }
                                        }
                                    }
                                    // Solution now back in saveSolver
                                    // Double check bounds
                                    columnLower = saveSolver->getColLower() ;
                                    columnUpper = saveSolver->getColUpper() ;
                                    solution = saveSolver->getColSolution();
                                    int numberChanged = 0;
                                    for (int i = 0; i < n; i++) {
                                        if (!saveSolver->isInteger(i) && !tightenB)
                                            continue;
                                        if (lower2[i] != COIN_DBL_MAX) {
                                            if (lower2[i] != columnLower[i] ||
                                                    upper2[i] != columnUpper[i]) {
                                                if (lower2[i] < columnLower[i] ||
                                                        upper2[i] > columnUpper[i]) {
#ifdef COIN_DEVELOP
                                                    printf("odd bounds tighter");
                                                    printf("%d bab bounds %g %g now %g %g\n",
                                                           i, lower2[i], upper2[i], columnLower[i],
                                                           columnUpper[i]);
#endif
                                                } else {
#ifdef COIN_DEVELOP
                                                    printf("%d bab bounds %g %g now %g %g\n",
                                                           i, lower2[i], upper2[i], columnLower[i],
                                                           columnUpper[i]);
#endif
                                                    numberChanged++;
                                                    saveSolver->setColLower(i, lower2[i]);
                                                    saveSolver->setColUpper(i, upper2[i]);
                                                }
                                            }
                                        }
                                    }
#ifdef JJF_ZERO
                                    // See if sos so we can fix
                                    OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (saveSolver);
                                    if (osiclp && osiclp->numberSOS()) {
                                        // SOS
                                        numberSOS = osiclp->numberSOS();
                                        const CoinSet * setInfo = osiclp->setInfo();
                                        int i;
                                        for ( i = 0; i < numberSOS; i++) {
                                            int type = setInfo[i].setType();
                                            int n = setInfo[i].numberEntries();
                                            const int * which = setInfo[i].which();
                                            int first = -1;
                                            int last = -1;
                                            for (int j = 0; j < n; j++) {
                                                int iColumn = which[j];
                                                if (fabs(solution[iColumn]) > 1.0e-7) {
                                                    last = j;
                                                    if (first < 0)
                                                        first = j;
                                                }
                                            }
                                            assert (last - first < type);
                                            for (int j = 0; j < n; j++) {
                                                if (j < first || j > last) {
                                                    int iColumn = which[j];
                                                    saveSolver->setColLower(iColumn, 0.0);
                                                    saveSolver->setColUpper(iColumn, 0.0);
                                                }
                                            }
                                        }
                                    }
#endif
                                    delete [] solution2;
                                    delete [] lower2;
                                    delete [] upper2;
                                    if (numberChanged) {
                                        sprintf(generalPrint, "%d bounds tightened after postprocessing\n",
                                                numberChanged);
                                        generalMessageHandler->message(CLP_GENERAL, generalMessages)
                                        << generalPrint
                                        << CoinMessageEol;
                                    }
                                    saveSolver->resolve();
                                    if (!saveSolver->isProvenOptimal()) {
                                        // try all slack
                                        CoinWarmStartBasis * basis = dynamic_cast<CoinWarmStartBasis *> (babModel_->solver()->getEmptyWarmStart());
                                        saveSolver->setWarmStart(basis);
                                        delete basis;
                                        saveSolver->initialSolve();
#ifdef COIN_DEVELOP
                                        saveSolver->writeMps("inf2");
#endif
					OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (saveSolver);
					if (osiclp)
					  osiclp->getModelPtr()->checkUnscaledSolution();
                                    }

                                    if (!saveSolver->isProvenOptimal()) {
				      generalMessageHandler->message(CLP_GENERAL, generalMessages)
					<< "Accuracy problem on post-processing - maybe try without pre-processing"
					<< CoinMessageEol;
				    }
                                    //assert (saveSolver->isProvenOptimal());
#ifndef CBC_OTHER_SOLVER
                                    // and original solver
                                    originalSolver->setDblParam(OsiDualObjectiveLimit, COIN_DBL_MAX);
                                    assert (n >= originalSolver->getNumCols());
                                    n = originalSolver->getNumCols();
                                    originalSolver->setColLower(saveSolver->getColLower());
                                    originalSolver->setColUpper(saveSolver->getColUpper());
                                    // basis
                                    CoinWarmStartBasis * basis = dynamic_cast<CoinWarmStartBasis *> (babModel_->solver()->getWarmStart());
                                    originalSolver->setBasis(*basis);
                                    delete basis;
                                    originalSolver->resolve();
                                    if (!originalSolver->isProvenOptimal()) {
                                        // try all slack
                                        CoinWarmStartBasis * basis = dynamic_cast<CoinWarmStartBasis *> (babModel_->solver()->getEmptyWarmStart());
                                        originalSolver->setBasis(*basis);
                                        delete basis;
                                        originalSolver->initialSolve();
					OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (originalSolver);
					if (osiclp)
					  osiclp->getModelPtr()->checkUnscaledSolution();
                                    }
                                    assert (originalSolver->isProvenOptimal());
#endif
                                    babModel_->assignSolver(saveSolver);
                                    memcpy(bestSolution, babModel_->solver()->getColSolution(), n*sizeof(double));
                                } else {
                                    n = babModel_->solver()->getNumCols();
                                    bestSolution = new double [n];
                                    memcpy(bestSolution, babModel_->solver()->getColSolution(), n*sizeof(double));
                                }
                                if (returnMode == 1&&model_.numberSavedSolutions()<2) {
                                    model_.deleteSolutions();
                                    model_.setBestSolution(bestSolution, n, babModel_->getMinimizationObjValue());
                                }
                                babModel_->deleteSolutions();
                                babModel_->setBestSolution(bestSolution, n, babModel_->getMinimizationObjValue());
#ifndef CBC_OTHER_SOLVER
                                // and put back in very original solver
                                {
                                    ClpSimplex * original = originalSolver->getModelPtr();
                                    double * lower = original->columnLower();
                                    double * upper = original->columnUpper();
                                    double * solution = original->primalColumnSolution();
                                    int n = original->numberColumns();
                                    //assert (!n||n==babModel_->solver()->getNumCols());
                                    for (int i = 0; i < n; i++) {
                                        solution[i] = bestSolution[i];
                                        if (originalSolver->isInteger(i)) {
                                            lower[i] = solution[i];
                                            upper[i] = solution[i];
                                        }
                                    }
                                    // basis
                                    CoinWarmStartBasis * basis = dynamic_cast<CoinWarmStartBasis *> (babModel_->solver()->getWarmStart());
                                    originalSolver->setBasis(*basis);
                                    delete basis;
                                    originalSolver->setDblParam(OsiDualObjectiveLimit, COIN_DBL_MAX);
                                    originalSolver->resolve();
                                    if (!originalSolver->isProvenOptimal()) {
                                        // try all slack
                                        CoinWarmStartBasis * basis = dynamic_cast<CoinWarmStartBasis *> (babModel_->solver()->getEmptyWarmStart());
                                        originalSolver->setBasis(*basis);
                                        delete basis;
                                        originalSolver->initialSolve();
					OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (originalSolver);
					if (osiclp)
					  osiclp->getModelPtr()->checkUnscaledSolution();
#ifdef CLP_INVESTIGATE
                                        if (!originalSolver->isProvenOptimal()) {
                                            if (saveSolver) {
                                                printf("saveSolver and originalSolver matrices saved\n");
                                                saveSolver->writeMps("infA");
                                            } else {
                                                printf("originalSolver matrix saved\n");
                                                originalSolver->writeMps("infB");
                                            }
                                        }
#endif
                                    }
                                    assert (originalSolver->isProvenOptimal());
                                }
#endif
                                checkSOS(babModel_, babModel_->solver());
                            } else if (model_.bestSolution() && type == CBC_PARAM_ACTION_BAB && model_.getMinimizationObjValue() < 1.0e50 && preProcess) {
                                sprintf(generalPrint, "Restoring heuristic best solution of %g", model_.getMinimizationObjValue());
                                generalMessageHandler->message(CLP_GENERAL, generalMessages)
                                << generalPrint
                                << CoinMessageEol;
                                int n = saveSolver->getNumCols();
                                bestSolution = new double [n];
                                // Put solution now back in saveSolver
                                saveSolver->setColSolution(model_.bestSolution());
                                babModel_->assignSolver(saveSolver);
				saveSolver=NULL;
                                babModel_->setMinimizationObjValue(model_.getMinimizationObjValue());
                                memcpy(bestSolution, babModel_->solver()->getColSolution(), n*sizeof(double));
#ifndef CBC_OTHER_SOLVER
                                // and put back in very original solver
                                {
                                    ClpSimplex * original = originalSolver->getModelPtr();
                                    double * lower = original->columnLower();
                                    double * upper = original->columnUpper();
                                    double * solution = original->primalColumnSolution();
                                    int n = original->numberColumns();
                                    //assert (!n||n==babModel_->solver()->getNumCols());
                                    for (int i = 0; i < n; i++) {
                                        solution[i] = bestSolution[i];
                                        if (originalSolver->isInteger(i)) {
                                            lower[i] = solution[i];
                                            upper[i] = solution[i];
                                        }
                                    }
                                    // basis
                                    CoinWarmStartBasis * basis = dynamic_cast<CoinWarmStartBasis *> (babModel_->solver()->getWarmStart());
                                    originalSolver->setBasis(*basis);
                                    delete basis;
                                }
#endif
                            }
#ifndef CBC_OTHER_SOLVER
                            //if (type==CBC_PARAM_ACTION_STRENGTHEN&&strengthenedModel)
                            //clpSolver = dynamic_cast< OsiClpSolverInterface*> (strengthenedModel);
#ifdef COIN_HAS_ASL
                            else if (statusUserFunction_[0])
                                clpSolver = dynamic_cast< OsiClpSolverInterface*> (babModel_->solver());
#endif
                            lpSolver = clpSolver->getModelPtr();
                            if (numberChanged) {
                                for (int i = 0; i < numberChanged; i++) {
                                    int iColumn = changed[i];
                                    clpSolver->setContinuous(iColumn);
                                }
                                delete [] changed;
                            }
#endif
                            if (type == CBC_PARAM_ACTION_BAB) {
#ifndef CBC_OTHER_SOLVER
                                //move best solution (should be there -- but ..)
                                int n = lpSolver->getNumCols();
                                if (bestSolution) {
                                    memcpy(lpSolver->primalColumnSolution(), bestSolution, n*sizeof(double));
                                    // now see what that does to row solution
                                    int numberRows = lpSolver->numberRows();
                                    double * rowSolution = lpSolver->primalRowSolution();
                                    memset (rowSolution, 0, numberRows*sizeof(double));
                                    lpSolver->clpMatrix()->times(1.0, bestSolution, rowSolution);
                                    lpSolver->setObjectiveValue(babModel_->getObjValue());
                                }
                                if (debugFile == "create" && bestSolution) {
                                    saveSolution(lpSolver, "debug.file");
                                }
#else
                                if (bestSolution) {
                                    model_.solver()->setColSolution(bestSolution);
                                }
#endif
				delete saveSolver;
                                delete [] bestSolution;
				std::string statusName[] = {"", "Stopped on ", "Run abandoned", "", "", "User ctrl-c"};
				std::string minor[] = {"Optimal solution found", "Linear relaxation infeasible", "Optimal solution found (within gap tolerance)", "node limit", "time limit", "user ctrl-c", "solution limit", "Linear relaxation unbounded", "Problem proven infeasible"};
                                int iStat = babModel_->status();
                                int iStat2 = babModel_->secondaryStatus();
                                if (!iStat && !iStat2 && !bestSolution)
                                    iStat2 = 8;
                                if (!iStat && iStat2==1 && bestSolution)
				  iStat2 = 0; // solution and search completed
                                statistics_seconds = time2 - time1;
                                statistics_sys_seconds = CoinSysTime();
                                statistics_elapsed_seconds = CoinWallclockTime();
                                statistics_obj = babModel_->getObjValue();
                                statistics_continuous = babModel_->getContinuousObjective();
                                statistics_tighter = babModel_->rootObjectiveAfterCuts();
                                statistics_nodes = babModel_->getNodeCount();
                                statistics_iterations = babModel_->getIterationCount();;
                                statistics_result = statusName[iStat];;
                                if (!noPrinting_) {
				    sprintf(generalPrint, "\nResult - %s%s\n", 
					    statusName[iStat].c_str(), 
					    minor[iStat2].c_str());
				    generalMessageHandler->message(CLP_GENERAL, generalMessages)
				       << generalPrint
				       << CoinMessageEol;
				    if (babModel_->bestSolution()){
				      sprintf(generalPrint, 
					      "Objective value:                %.8f\n", 
					      babModel_->getObjValue());
				    }else{
				      sprintf(generalPrint,
					      "No feasible solution found\n");
				    }
				    if (iStat2 >= 2 && iStat2 <=6){
				      bool minimizing = babModel_->solver()->getObjSense()>0.0;
				       sprintf(generalPrint + strlen(generalPrint), 
					       "%s bound:                    %.3f\n", 
					       minimizing ? "Lower" : "Upper",
					       babModel_->getBestPossibleObjValue());
				       if (babModel_->bestSolution()){
					  sprintf(generalPrint + strlen(generalPrint), 
						  "Gap:                            %.2f\n", 
						  (babModel_->getObjValue()-babModel_->getBestPossibleObjValue())/
						  fabs(babModel_->getBestPossibleObjValue()));
				       }
				    }
				    sprintf(generalPrint + strlen(generalPrint), 
					    "Enumerated nodes:               %d\n", 
					    babModel_->getNodeCount());
				    sprintf(generalPrint + strlen(generalPrint), 
					    "Total iterations:               %d\n", 
					    babModel_->getIterationCount());
#if CBC_QUIET == 0
				    sprintf(generalPrint + strlen(generalPrint), 
					    "Time (CPU seconds):             %.2f\n",
					    CoinCpuTime() - time1);
				    sprintf(generalPrint + strlen(generalPrint),
					    "Time (Wallclock seconds):       %.2f\n", 
					    CoinGetTimeOfDay() - time1Elapsed);
#endif
				    generalMessageHandler->message(CLP_GENERAL, generalMessages)
				       << generalPrint
				       << CoinMessageEol;
                                }
                                int returnCode = callBack(babModel_, 5);
                                if (returnCode) {
                                    // exit if user wants
                                    model_.moveInfo(*babModel_);
                                    delete babModel_;
                                    babModel_ = NULL;
                                    return returnCode;
                                }
#ifdef COIN_HAS_ASL
				if (statusUserFunction_[0]) {
				   clpSolver = dynamic_cast< OsiClpSolverInterface*> (babModel_->solver());
				   lpSolver = clpSolver->getModelPtr();
				   double value = babModel_->getObjValue()*lpSolver->getObjSense();
				   char buf[300];
				   int pos=0;
				   if (iStat==0) {
				      if (babModel_->getObjValue()<1.0e40) {
					 pos += sprintf(buf+pos,"optimal," );
				      } else {
					 // infeasible
					 iStat=1;
					 pos += sprintf(buf+pos,"infeasible,");
				      }
				   } else if (iStat==1) {
				      if (iStat2!=6)
					 iStat=3;
				      else
					 iStat=4;
				      pos += sprintf(buf+pos,"stopped on %s,",minor[iStat2].c_str());
				   } else if (iStat==2) {
				      iStat = 7;
				      pos += sprintf(buf+pos,"stopped on difficulties,");
				   } else if (iStat==5) {
				      iStat = 3;
				      pos += sprintf(buf+pos,"stopped on ctrl-c,");
				   } else {
				      pos += sprintf(buf+pos,"status unknown,");
				      iStat=6;
				   }
				   info.problemStatus=iStat;
				   info.objValue = value;
				   if (babModel_->getObjValue()<1.0e40) {
				      int precision = ampl_obj_prec();
				      if (precision>0)
					 pos += sprintf(buf+pos," objective %.*g",precision,
							value);
				      else
					 pos += sprintf(buf+pos," objective %g",value);
				   }
				   sprintf(buf+pos,"\n%d nodes, %d iterations, %g seconds",
					   babModel_->getNodeCount(),
					   babModel_->getIterationCount(),
					   totalTime);
				   if (bestSolution) {
				      free(info.primalSolution);
				      if (!numberKnapsack) {
					 info.primalSolution = (double *) malloc(n*sizeof(double));
					 CoinCopyN(lpSolver->primalColumnSolution(),n,info.primalSolution);
					 int numberRows = lpSolver->numberRows();
					 free(info.dualSolution);
					 info.dualSolution = (double *) malloc(numberRows*sizeof(double));
					 CoinCopyN(lpSolver->dualRowSolution(),numberRows,info.dualSolution);
				      } else {
					 // expanded knapsack
					 info.dualSolution=NULL;
					 int numberColumns = saveCoinModel.numberColumns();
					 info.primalSolution = (double *) malloc(numberColumns*sizeof(double));
					 // Fills in original solution (coinModel length)
					 afterKnapsack(saveTightenedModel,  whichColumn,  knapsackStart,
					 	       knapsackRow,  numberKnapsack,
					 	       lpSolver->primalColumnSolution(), info.primalSolution,1);
				      }
				   } else {
				      info.primalSolution=NULL;
				      info.dualSolution=NULL;
				   }
				   // put buffer into info
				   strcpy(info.buffer,buf);
				}
#endif
                            } else {
			      sprintf(generalPrint, "Model strengthened - now has %d rows",
				      clpSolver->getNumRows());
			      printGeneralMessage(model_,generalPrint);
                            }
                            time1 = time2;
#ifdef COIN_HAS_ASL
                            if (statusUserFunction_[0]) {
                                // keep if going to be destroyed
                                OsiSolverInterface * solver = babModel_->solver();
                                OsiClpSolverInterface * clpSolver = dynamic_cast< OsiClpSolverInterface*> (solver);
                                ClpSimplex * lpSolver2 = clpSolver->getModelPtr();
                                if (lpSolver == lpSolver2)
                                    babModel_->setModelOwnsSolver(false);
                            }
#endif
                            //delete babModel_;
                            //babModel_=NULL;
                        } else {
			  sprintf(generalPrint, "** Current model not valid");
			  printGeneralMessage(model_,generalPrint);
                        }
                        break ;
                    case CLP_PARAM_ACTION_IMPORT: {
#ifdef COIN_HAS_ASL
                        if (!statusUserFunction_[0]) {
#endif
                            free(priorities);
                            priorities = NULL;
                            free(branchDirection);
                            branchDirection = NULL;
                            free(pseudoDown);
                            pseudoDown = NULL;
                            free(pseudoUp);
                            pseudoUp = NULL;
                            free(solutionIn);
                            solutionIn = NULL;
                            free(prioritiesIn);
                            prioritiesIn = NULL;
                            free(sosStart);
                            sosStart = NULL;
                            free(sosIndices);
                            sosIndices = NULL;
                            free(sosType);
                            sosType = NULL;
                            free(sosReference);
                            sosReference = NULL;
                            free(cut);
                            cut = NULL;
                            free(sosPriority);
                            sosPriority = NULL;
#ifdef COIN_HAS_ASL
                        }
#endif
                        //delete babModel_;
                        //babModel_=NULL;
                        // get next field
                        field = CoinReadGetString(argc, argv);
                        if (field == "$") {
                            field = parameters_[iParam].stringValue();
                        } else if (field == "EOL") {
                            parameters_[iParam].printString();
                            break;
                        } else {
                            parameters_[iParam].setStringValue(field);
                        }
                        std::string fileName;
                        bool canOpen = false;
                        // See if gmpl file
                        int gmpl = 0;
                        std::string gmplData;
                        if (field == "-" || field == "stdin") {
                            // stdin
                            canOpen = true;
                            fileName = "-";
                        } else if (field == "stdin_lp") {
                            // stdin
                            canOpen = true;
                            fileName = "-";
			    gmpl = -1; //.lp format
                        } else {
                            // See if .lp
                            {
                                const char * c_name = field.c_str();
                                size_t length = strlen(c_name);
                                if (length > 3 && !strncmp(c_name + length - 3, ".lp", 3))
                                    gmpl = -1; // .lp
                            }
                            bool absolutePath;
                            if (dirsep == '/') {
                                // non Windows (or cygwin)
                                absolutePath = (field[0] == '/');
                            } else {
                                //Windows (non cycgwin)
                                absolutePath = (field[0] == '\\');
                                // but allow for :
                                if (strchr(field.c_str(), ':'))
                                    absolutePath = true;
                            }
                            if (absolutePath) {
                                fileName = field;
				size_t length = field.size();
				size_t percent = field.find('%');
				if (percent < length && percent > 0) {
				  gmpl = 1;
				  fileName = field.substr(0, percent);
				  gmplData = field.substr(percent + 1);
				  if (percent < length - 1)
				    gmpl = 2; // two files
				  printf("GMPL model file %s and data file %s\n",
					 fileName.c_str(), gmplData.c_str());
				}
                            } else if (field[0] == '~') {
                                char * environVar = getenv("HOME");
                                if (environVar) {
                                    std::string home(environVar);
                                    field = field.erase(0, 1);
                                    fileName = home + field;
                                } else {
                                    fileName = field;
                                }
                            } else {
                                fileName = directory + field;
                                // See if gmpl (model & data) - or even lp file
                                size_t length = field.size();
                                size_t percent = field.find('%');
                                if (percent<length && percent>0) {
                                    gmpl = 1;
                                    fileName = directory + field.substr(0, percent);
                                    gmplData = directory + field.substr(percent + 1);
                                    if (percent < length - 1)
                                        gmpl = 2; // two files
                                    printf("GMPL model file %s and data file %s\n",
                                           fileName.c_str(), gmplData.c_str());
                                }
                            }
                            std::string name = fileName;
                            if (fileCoinReadable(name)) {
                                // can open - lets go for it
                                canOpen = true;
                                if (gmpl == 2) {
                                    FILE *fp;
                                    fp = fopen(gmplData.c_str(), "r");
                                    if (fp) {
                                        fclose(fp);
                                    } else {
                                        canOpen = false;
					sprintf(generalPrint, "Unable to open file %s",gmplData.c_str());
					printGeneralMessage(model_,generalPrint);
                                    }
                                }
                            } else {
			      sprintf(generalPrint, "Unable to open file %s",fileName.c_str());
			      printGeneralMessage(model_,generalPrint);
                            }
                        }
                        if (canOpen) {
                            int status;
#ifndef CBC_OTHER_SOLVER
                            ClpSimplex * lpSolver = clpSolver->getModelPtr();
                            if (!gmpl) {
                                status = clpSolver->readMps(fileName.c_str(),
                                                            keepImportNames != 0,
                                                            allowImportErrors != 0);
                            } else if (gmpl > 0) {
                                status = lpSolver->readGMPL(fileName.c_str(),
                                                            (gmpl == 2) ? gmplData.c_str() : NULL,
                                                            keepImportNames != 0);
                            } else {
#ifdef KILL_ZERO_READLP
                                status = clpSolver->readLp(fileName.c_str(), lpSolver->getSmallElementValue());
#else
                                status = clpSolver->readLp(fileName.c_str(), 1.0e-12);
#endif
                            }
#else
                            status = clpSolver->readMps(fileName.c_str(), "");
#endif
                            if (!status || (status > 0 && allowImportErrors)) {
#ifndef CBC_OTHER_SOLVER
                                if (keepImportNames) {
                                    lengthName = lpSolver->lengthNames();
                                    rowNames = *(lpSolver->rowNames());
                                    columnNames = *(lpSolver->columnNames());
                                } else {
                                    lengthName = 0;
                                }
                                goodModel = true;
                                // sets to all slack (not necessary?)
                                lpSolver->createStatus();
                                // make sure integer
                                int numberColumns = lpSolver->numberColumns();
                                for (int i = 0; i < numberColumns; i++) {
                                    if (lpSolver->isInteger(i))
                                        clpSolver->setInteger(i);
                                }
#else
                                lengthName = 0;
                                goodModel = true;
#endif
                                time2 = CoinCpuTime();
                                totalTime += time2 - time1;
                                time1 = time2;
                                // Go to canned file if just input file
                                if (CbcOrClpRead_mode == 2 && argc == 2) {
                                    // only if ends .mps
                                    char * find = const_cast<char *>(strstr(fileName.c_str(), ".mps"));
                                    if (find && find[4] == '\0') {
                                        find[1] = 'p';
                                        find[2] = 'a';
                                        find[3] = 'r';
                                        FILE *fp = fopen(fileName.c_str(), "r");
                                        if (fp) {
                                            CbcOrClpReadCommand = fp; // Read from that file
                                            CbcOrClpRead_mode = -1;
                                        }
                                    }
                                }
                            } else {
                                // errors
			      sprintf(generalPrint, "There were %d errors on input",status);
			      printGeneralMessage(model_,generalPrint);
                            }
                        }
                    }
                    break;
                    case CLP_PARAM_ACTION_MODELIN:
#ifndef CBC_OTHER_SOLVER
#ifdef COIN_HAS_LINK
                        {
                            // get next field
                            field = CoinReadGetString(argc, argv);
                            if (field == "$") {
                                field = parameters_[iParam].stringValue();
                            } else if (field == "EOL") {
                                parameters_[iParam].printString();
                                break;
                            } else {
                                parameters_[iParam].setStringValue(field);
                            }
                            std::string fileName;
                            bool canOpen = false;
                            if (field == "-") {
                                // stdin
                                canOpen = true;
                                fileName = "-";
                            } else {
                                bool absolutePath;
                                if (dirsep == '/') {
                                    // non Windows (or cygwin)
                                    absolutePath = (field[0] == '/');
                                } else {
                                    //Windows (non cycgwin)
                                    absolutePath = (field[0] == '\\');
                                    // but allow for :
                                    if (strchr(field.c_str(), ':'))
                                        absolutePath = true;
                                }
                                if (absolutePath) {
                                    fileName = field;
                                } else if (field[0] == '~') {
                                    char * environVar = getenv("HOME");
                                    if (environVar) {
                                        std::string home(environVar);
                                        field = field.erase(0, 1);
                                        fileName = home + field;
                                    } else {
                                        fileName = field;
                                    }
                                } else {
                                    fileName = directory + field;
                                }
                                FILE *fp = fopen(fileName.c_str(), "r");
                                if (fp) {
                                    // can open - lets go for it
                                    fclose(fp);
                                    canOpen = true;
                                } else {
				  sprintf(generalPrint, "Unable to open file %s",fileName.c_str());
				  printGeneralMessage(model_,generalPrint);
                                }
                            }
                            if (canOpen) {
                                CoinModel coinModel(fileName.c_str(), 2);
                                // load from coin model
                                OsiSolverLink solver1;
                                OsiSolverInterface * solver2 = solver1.clone();
                                model_.assignSolver(solver2, false);
                                OsiSolverLink * si =
                                    dynamic_cast<OsiSolverLink *>(model_.solver()) ;
                                assert (si != NULL);
                                si->setDefaultMeshSize(0.001);
                                // need some relative granularity
                                si->setDefaultBound(100.0);
                                double dextra3 = parameters_[whichParam(CBC_PARAM_DBL_DEXTRA3, numberParameters_, parameters_)].doubleValue();
                                if (dextra3)
                                    si->setDefaultMeshSize(dextra3);
                                si->setDefaultBound(100.0);
                                si->setIntegerPriority(1000);
                                si->setBiLinearPriority(10000);
                                CoinModel * model2 = &coinModel;
                                si->load(*model2);
                                // redo
                                solver = model_.solver();
                                clpSolver = dynamic_cast< OsiClpSolverInterface*> (solver);
                                lpSolver = clpSolver->getModelPtr();
                                clpSolver->messageHandler()->setLogLevel(0) ;
                                testOsiParameters = 0;
                                complicatedInteger = 2;
                            }
                        }
#endif
#endif
                        break;
                    case CLP_PARAM_ACTION_EXPORT:
                        if (goodModel) {
                            // get next field
                            field = CoinReadGetString(argc, argv);
                            if (field == "$") {
                                field = parameters_[iParam].stringValue();
                            } else if (field == "EOL") {
                                parameters_[iParam].printString();
                                break;
                            } else {
                                parameters_[iParam].setStringValue(field);
                            }
                            std::string fileName;
                            bool canOpen = false;
                            if (field[0] == '/' || field[0] == '\\') {
                                fileName = field;
                            } else if (field[0] == '~') {
                                char * environVar = getenv("HOME");
                                if (environVar) {
                                    std::string home(environVar);
                                    field = field.erase(0, 1);
                                    fileName = home + field;
                                } else {
                                    fileName = field;
                                }
                            } else {
                                fileName = directory + field;
                            }
                            FILE *fp = fopen(fileName.c_str(), "w");
                            if (fp) {
                                // can open - lets go for it
                                fclose(fp);
                                canOpen = true;
                            } else {
				  sprintf(generalPrint, "Unable to open file %s",fileName.c_str());
				  printGeneralMessage(model_,generalPrint);
                            }
                            if (canOpen) {
                                // If presolve on then save presolved
                                bool deleteModel2 = false;
                                ClpSimplex * model2 = lpSolver;
                                if (dualize && dualize < 3) {
                                    model2 = static_cast<ClpSimplexOther *> (model2)->dualOfModel();
                                    sprintf(generalPrint, "Dual of model has %d rows and %d columns",
                                            model2->numberRows(), model2->numberColumns());
                                    generalMessageHandler->message(CLP_GENERAL, generalMessages)
                                    << generalPrint
                                    << CoinMessageEol;
                                    model2->setOptimizationDirection(1.0);
                                }
#ifndef CBC_OTHER_SOLVER
#ifdef COIN_HAS_ASL
                                if (info.numberSos && doSOS && statusUserFunction_[0]) {
                                    // SOS
                                    numberSOS = info.numberSos;
                                    sosStart = info.sosStart;
                                    sosIndices = info.sosIndices;
                                    sosReference = info.sosReference;
                                    clpSolver->setSOSData(numberSOS, info.sosType, sosStart, sosIndices, sosReference);
                                }
#endif
				numberSOS = clpSolver->numberSOS();
				if (numberSOS)
				  preSolve = false;
#endif
                                if (preSolve) {
                                    ClpPresolve pinfo;
                                    int presolveOptions2 = presolveOptions&~0x40000000;
                                    if ((presolveOptions2&0xffff) != 0)
                                        pinfo.setPresolveActions(presolveOptions2);
                                    if ((printOptions&1) != 0)
                                        pinfo.statistics();
                                    double presolveTolerance =
                                        parameters_[whichParam(CLP_PARAM_DBL_PRESOLVETOLERANCE, numberParameters_, parameters_)].doubleValue();
                                    model2 =
                                        pinfo.presolvedModel(*lpSolver, presolveTolerance,
                                                             true, preSolve);
                                    if (model2) {
                                        printf("Saving presolved model on %s\n",
                                               fileName.c_str());
                                        deleteModel2 = true;
                                    } else {
                                        printf("Presolved model looks infeasible - saving original on %s\n",
                                               fileName.c_str());
                                        deleteModel2 = false;
                                        model2 = lpSolver;

                                    }
                                    model2->writeMps(fileName.c_str(), (outputFormat - 1) / 2, 1 + ((outputFormat - 1)&1));
                                    if (deleteModel2)
                                        delete model2;
                                } else {
                                    printf("Saving model on %s\n",
                                           fileName.c_str());
                                    if (numberSOS) {
                                        // Convert names
                                        int iRow;
                                        int numberRows = model2->numberRows();
                                        int iColumn;
                                        int numberColumns = model2->numberColumns();

                                        char ** rowNames = NULL;
                                        char ** columnNames = NULL;
                                        if (model2->lengthNames()) {
                                            rowNames = new char * [numberRows];
                                            for (iRow = 0; iRow < numberRows; iRow++) {
                                                rowNames[iRow] =
                                                    CoinStrdup(model2->rowName(iRow).c_str());
                                            }

                                            columnNames = new char * [numberColumns];
                                            for (iColumn = 0; iColumn < numberColumns; iColumn++) {
                                                columnNames[iColumn] =
                                                    CoinStrdup(model2->columnName(iColumn).c_str());
                                            }
                                        }
					// see if extension lp
					bool writeLp=false;
					{
					  int lengthName = strlen(fileName.c_str());
					  if (lengthName>3&&!strcmp(fileName.c_str()+lengthName-3,".lp"))
					    writeLp=true;
					}
					if (!writeLp) {
					  remove(fileName.c_str());
					  clpSolver->writeMpsNative(fileName.c_str(), const_cast<const char **> (rowNames), const_cast<const char **> (columnNames),
								    (outputFormat - 1) / 2, 1 + ((outputFormat - 1)&1)); 
					} else {
					  FILE *fp = fopen(fileName.c_str(), "w");
					  assert (fp);
					  clpSolver->writeLp(fp,1.0e-12);
					}
                                        if (rowNames) {
                                            for (iRow = 0; iRow < numberRows; iRow++) {
                                                free(rowNames[iRow]);
                                            }
                                            delete [] rowNames;
                                            for (iColumn = 0; iColumn < numberColumns; iColumn++) {
                                                free(columnNames[iColumn]);
                                            }
                                            delete [] columnNames;
                                        }
                                    } else {
#ifdef COIN_HAS_LINK
                                        OsiSolverLink * linkSolver = dynamic_cast< OsiSolverLink*> (clpSolver);
                                        if (!linkSolver || !linkSolver->quadraticModel())
                                            model2->writeMps(fileName.c_str(), (outputFormat - 1) / 2, 1 + ((outputFormat - 1)&1));
                                        else
                                            linkSolver->quadraticModel()->writeMps(fileName.c_str(), (outputFormat - 1) / 2, 1 + ((outputFormat - 1)&1));
#endif
                                    }
                                }
                                time2 = CoinCpuTime();
                                totalTime += time2 - time1;
                                time1 = time2;
                            }
                        } else {
			  sprintf(generalPrint, "** Current model not valid");
			  printGeneralMessage(model_,generalPrint);
                        }
                        break;
                    case CLP_PARAM_ACTION_BASISIN:
                        if (goodModel) {
                            // get next field
                            field = CoinReadGetString(argc, argv);
                            if (field == "$") {
                                field = parameters_[iParam].stringValue();
                            } else if (field == "EOL") {
                                parameters_[iParam].printString();
                                break;
                            } else {
                                parameters_[iParam].setStringValue(field);
                            }
                            std::string fileName;
                            bool canOpen = false;
                            if (field == "-") {
                                // stdin
                                canOpen = true;
                                fileName = "-";
                            } else {
                                if (field[0] == '/' || field[0] == '\\') {
                                    fileName = field;
                                } else if (field[0] == '~') {
                                    char * environVar = getenv("HOME");
                                    if (environVar) {
                                        std::string home(environVar);
                                        field = field.erase(0, 1);
                                        fileName = home + field;
                                    } else {
                                        fileName = field;
                                    }
                                } else {
                                    fileName = directory + field;
                                }
                                FILE *fp = fopen(fileName.c_str(), "r");
                                if (fp) {
                                    // can open - lets go for it
                                    fclose(fp);
                                    canOpen = true;
                                } else {
				  sprintf(generalPrint, "Unable to open file %s",fileName.c_str());
				  printGeneralMessage(model_,generalPrint);
                                }
                            }
                            if (canOpen) {
#ifndef CBC_OTHER_SOLVER
                                int values = lpSolver->readBasis(fileName.c_str());
                                if (values == 0)
                                    basisHasValues = -1;
                                else
                                    basisHasValues = 1;
                                assert (lpSolver == clpSolver->getModelPtr());
                                clpSolver->setWarmStart(NULL);
#endif
                            }
                        } else {
			  sprintf(generalPrint, "** Current model not valid");
			  printGeneralMessage(model_,generalPrint);
                        }
                        break;
                    case CBC_PARAM_ACTION_PRIORITYIN:
                        if (goodModel) {
                            // get next field
                            field = CoinReadGetString(argc, argv);
                            if (field == "$") {
                                field = parameters_[iParam].stringValue();
                            } else if (field == "EOL") {
                                parameters_[iParam].printString();
                                break;
                            } else {
                                parameters_[iParam].setStringValue(field);
                            }
                            std::string fileName;
                            if (field[0] == '/' || field[0] == '\\') {
                                fileName = field;
                            } else if (field[0] == '~') {
                                char * environVar = getenv("HOME");
                                if (environVar) {
                                    std::string home(environVar);
                                    field = field.erase(0, 1);
                                    fileName = home + field;
                                } else {
                                    fileName = field;
                                }
                            } else {
                                fileName = directory + field;
                            }
                            FILE *fp = fopen(fileName.c_str(), "r");
                            if (fp) {
                                // can open - lets go for it
                                std::string headings[] = {"name", "number", "direction", "priority", "up", "down",
                                                          "solution", "priin"
                                                         };
                                int got[] = { -1, -1, -1, -1, -1, -1, -1, -1};
                                int order[8];
				bool useMasks = false;
				if (strstr(fileName.c_str(),"mask_")) {
				  // look more closely
				  const char * name = fileName.c_str();
				  int length = strlen(name);
				  for (int i=length-1;i>=0;i--) {
				    if (name[i]==dirsep) {
				      name += i+1;
				      break;
				    }
				  }
				  useMasks = !strncmp(name,"mask_",5);
				} 
                                assert(sizeof(got) == sizeof(order));
                                int nAcross = 0;
                                char line[1000];
                                int numberColumns = lpSolver->numberColumns();
                                if (!fgets(line, 1000, fp)) {
                                    std::cout << "Odd file " << fileName << std::endl;
                                } else {
                                    char * pos = line;
                                    char * put = line;
                                    while (*pos >= ' ' && *pos != '\n') {
                                        if (*pos != ' ' && *pos != '\t') {
                                            *put = static_cast<char>(tolower(*pos));
                                            put++;
                                        }
                                        pos++;
                                    }
                                    *put = '\0';
                                    pos = line;
                                    int i;
                                    bool good = true;
                                    while (pos) {
                                        char * comma = strchr(pos, ',');
                                        if (comma)
                                            *comma = '\0';
                                        for (i = 0; i < static_cast<int> (sizeof(got) / sizeof(int)); i++) {
                                            if (headings[i] == pos) {
                                                if (got[i] < 0) {
                                                    order[nAcross] = i;
                                                    got[i] = nAcross++;
                                                } else {
                                                    // duplicate
                                                    good = false;
                                                }
                                                break;
                                            }
                                        }
                                        if (i == static_cast<int> (sizeof(got) / sizeof(int)))
                                            good = false;
                                        if (comma) {
                                            *comma = ',';
                                            pos = comma + 1;
                                        } else {
                                            break;
                                        }
                                    }
                                    if (got[0] < 0 && got[1] < 0)
                                        good = false;
                                    if (got[0] >= 0 && got[1] >= 0)
                                        good = false;
                                    if (got[0] >= 0 && !lpSolver->lengthNames())
                                        good = false;
                                    int numberFields = 99;
                                    if (good && (strstr(fileName.c_str(), ".mst") || strstr(fileName.c_str(), ".MST") || strstr(fileName.c_str(), ".csv"))) {
                                        numberFields = 0;
                                        for (i = 2; i < static_cast<int> (sizeof(got) / sizeof(int)); i++) {
                                            if (got[i] >= 0)
                                                numberFields++;
                                        }
                                        if (!numberFields) {
                                            // Like Cplex format
                                            order[nAcross] = 6;
                                            got[6] = nAcross++;
                                        }
                                    }
                                    if (good) {
                                        char ** columnNames = new char * [numberColumns];
                                        //pseudoDown = NULL;
                                        //pseudoUp = NULL;
                                        //branchDirection = NULL;
					//if (got[5]!=-1)
					  pseudoDown = reinterpret_cast<double *> (malloc(numberColumns * sizeof(double)));
					  //if (got[4]!=-1)
					  pseudoUp = reinterpret_cast<double *> (malloc(numberColumns * sizeof(double)));
					  //if (got[2]!=-1)
					  branchDirection = reinterpret_cast<int *> (malloc(numberColumns * sizeof(int)));
                                        priorities = reinterpret_cast<int *> (malloc(numberColumns * sizeof(int)));
                                        free(solutionIn);
                                        solutionIn = NULL;
                                        free(prioritiesIn);
                                        prioritiesIn = NULL;
                                        int iColumn;
                                        if (got[6] >= 0) {
                                            solutionIn = reinterpret_cast<double *> (malloc(numberColumns * sizeof(double)));
                                            for (iColumn = 0; iColumn < numberColumns; iColumn++)
                                                solutionIn[iColumn] = -COIN_DBL_MAX;
                                        }
                                        if (got[7] >= 0 || !numberFields) {
                                            prioritiesIn = reinterpret_cast<int *> (malloc(numberColumns * sizeof(int)));
                                            for (iColumn = 0; iColumn < numberColumns; iColumn++)
                                                prioritiesIn[iColumn] = 10000;
                                        }
                                        for (iColumn = 0; iColumn < numberColumns; iColumn++) {
                                            columnNames[iColumn] =
                                                CoinStrdup(lpSolver->columnName(iColumn).c_str());
					    //if (got[5]!=-1)
					      pseudoDown[iColumn] = 0.0;
					      //if (got[4]!=-1)
					      pseudoUp[iColumn] = 0.0;
					      //if (got[2]!=-1)
					      branchDirection[iColumn] = 0;
                                            priorities[iColumn] = useMasks ? -123456789 : 0;
                                        }
                                        int nBadPseudo = 0;
                                        int nBadDir = 0;
                                        int nBadPri = 0;
                                        int nBadName = 0;
                                        int nBadLine = 0;
                                        int nLine = 0;
					iColumn = -1;
					int lowestPriority=-COIN_INT_MAX;
					bool needCard = true;
                                        while (!needCard || fgets(line, 1000, fp)) {
                                            if (!strncmp(line, "ENDATA", 6)||
						!strncmp(line, "endata", 6))
                                                break;
                                            nLine++;
					    if (!useMasks) 
					      iColumn = -1;
					    else
					      needCard=false;
                                            double up = 0.0;
                                            double down = 0.0;
                                            int pri = 0;
                                            int dir = 0;
                                            double solValue = COIN_DBL_MAX;
                                            int priValue = 1000000;
                                            char * pos = line;
                                            char * put = line;
                                            if (!numberFields) {
                                                // put in ,
                                                for (i = 4; i < 100; i++) {
                                                    if (line[i] == ' ' || line[i] == '\t') {
                                                        line[i] = ',';
                                                        break;
                                                    }
                                                }
                                            }
                                            while (*pos >= ' ' && *pos != '\n') {
                                                if (*pos != ' ' && *pos != '\t') {
                                                    *put = *pos;
                                                    put++;
                                                }
                                                pos++;
                                            }
                                            *put = '\0';
                                            pos = line;
                                            for (int i = 0; i < nAcross; i++) {
                                                char * comma = strchr(pos, ',');
                                                if (comma) {
                                                    *comma = '\0';
                                                } else if (i < nAcross - 1) {
                                                    nBadLine++;
                                                    break;
                                                }
                                                switch (order[i]) {
                                                    // name
                                                case 0:
						  iColumn++;
						  for (; iColumn < numberColumns; iColumn++) {
						      if (priorities[iColumn]!=-123456789) {
                                                        if (!strcmp(columnNames[iColumn], pos))
                                                            break;
						      } else {
							// mask (at present ? and trailing *)
							const char * name = columnNames[iColumn];
							int length=strlen(name);
							int lengthMask=strlen(pos);
							bool asterisk = pos[lengthMask-1]=='*';
							if (asterisk) 
							  length=lengthMask-1;
							int i;
							for (i=0;i<length;i++) {
							  if (name[i]!=pos[i]) {
							    if (pos[i]!='?')
							      break;
							  }
							}
							if (i==length)
							  break;
						      }
                                                    }
						    if (iColumn == numberColumns) {
                                                        iColumn = -1;
							needCard = true;
						    }
                                                    break;
                                                    // number
                                                case 1:
                                                    iColumn = atoi(pos);
                                                    if (iColumn < 0 || iColumn >= numberColumns)
                                                        iColumn = -1;
                                                    break;
                                                    // direction
                                                case 2:
                                                    if (*pos == 'D')
                                                        dir = -1;
                                                    else if (*pos == 'U')
                                                        dir = 1;
                                                    else if (*pos == 'N')
                                                        dir = 0;
                                                    else if (*pos == '1' && *(pos + 1) == '\0')
                                                        dir = 1;
                                                    else if (*pos == '0' && *(pos + 1) == '\0')
                                                        dir = 0;
                                                    else if (*pos == '1' && *(pos + 1) == '1' && *(pos + 2) == '\0')
                                                        dir = -1;
                                                    else
                                                        dir = -2; // bad
                                                    break;
                                                    // priority
                                                case 3:
                                                    pri = atoi(pos);
						    lowestPriority=CoinMax(lowestPriority,pri);
                                                    break;
                                                    // up
                                                case 4:
                                                    up = atof(pos);
                                                    break;
                                                    // down
                                                case 5:
                                                    down = atof(pos);
                                                    break;
                                                    // sol value
                                                case 6:
                                                    solValue = atof(pos);
                                                    break;
                                                    // priority in value
                                                case 7:
                                                    priValue = atoi(pos);
                                                    break;
                                                }
                                                if (comma) {
                                                    *comma = ',';
                                                    pos = comma + 1;
                                                }
                                            }
                                            if (iColumn >= 0) {
                                                if (down < 0.0) {
                                                    nBadPseudo++;
                                                    down = 0.0;
                                                }
                                                if (up < 0.0) {
                                                    nBadPseudo++;
                                                    up = 0.0;
                                                }
                                                if (!up)
                                                    up = down;
                                                if (!down)
                                                    down = up;
                                                if (dir < -1 || dir > 1) {
                                                    nBadDir++;
                                                    dir = 0;
                                                }
                                                if (pri < 0) {
                                                    nBadPri++;
                                                    pri = 0;
                                                }
						//if (got[5]!=-1)
						  pseudoDown[iColumn] = down;
						  //if (got[4]!=-1)
						  pseudoUp[iColumn] = up;
						  //if (got[2]!=-1)
						  branchDirection[iColumn] = dir;
                                                priorities[iColumn] = pri;
                                                if (solValue != COIN_DBL_MAX) {
                                                    assert (solutionIn);
                                                    solutionIn[iColumn] = solValue;
                                                }
                                                if (priValue != 1000000) {
                                                    assert (prioritiesIn);
                                                    prioritiesIn[iColumn] = priValue;
                                                }
                                            } else if (!useMasks) {
                                                nBadName++;
                                            }
                                        }
                                        for (iColumn = 0; iColumn < numberColumns; iColumn++) {
					  if (priorities[iColumn] == -123456789)
                                            priorities[iColumn] = lowestPriority+1;
                                        }
                                        if (!noPrinting_) {
                                            printf("%d fields and %d records", nAcross, nLine);
                                            if (nBadPseudo)
                                                printf(" %d bad pseudo costs", nBadPseudo);
                                            if (nBadDir)
                                                printf(" %d bad directions", nBadDir);
                                            if (nBadPri)
                                                printf(" %d bad priorities", nBadPri);
                                            if (nBadName)
                                                printf(" ** %d records did not match on name/sequence", nBadName);
                                            printf("\n");
                                        }
                                        for (iColumn = 0; iColumn < numberColumns; iColumn++) {
                                            free(columnNames[iColumn]);
                                        }
                                        delete [] columnNames;
                                    } else {
                                        std::cout << "Duplicate or unknown keyword - or name/number fields wrong" << line << std::endl;
                                    }
                                }
                                fclose(fp);
                            } else {
			      sprintf(generalPrint, "Unable to open file %s",fileName.c_str());
			      printGeneralMessage(model_,generalPrint);
                            }
                        } else {
			  sprintf(generalPrint, "** Current model not valid");
			  printGeneralMessage(model_,generalPrint);
                        }
                        break;
                    case CBC_PARAM_ACTION_MIPSTART:
                        if (goodModel) {
                            // get next field
                            field = CoinReadGetString(argc, argv);
                            if (field == "$") {
                                field = parameters_[iParam].stringValue();
                            } else if (field == "EOL") {
                                parameters_[iParam].printString();
                                break;
                            } else {
                                parameters_[iParam].setStringValue(field);
                            }
                            std::string fileName;
                            if (field[0] == '/' || field[0] == '\\') {
                                fileName = field;
                            } else if (field[0] == '~') {
                                char * environVar = getenv("HOME");
                                if (environVar) {
                                    std::string home(environVar);
                                    field = field.erase(0, 1);
                                    fileName = home + field;
                                } else {
                                    fileName = field;
                                }
                            } else {
                                fileName = directory + field;
                            }
                            sprintf(generalPrint,"opening mipstart file %s.",fileName.c_str() );
                            generalMessageHandler->message(CLP_GENERAL, generalMessages) << generalPrint << CoinMessageEol;
                            double msObj;
                            readMIPStart( &model_, fileName.c_str(), mipStart, msObj );
                            // copy to before preprocess if has .before.
                            if (strstr(fileName.c_str(),".before.")) {
                                mipStartBefore = mipStart;
                                sprintf(generalPrint,"file %s will be used before preprocessing.",fileName.c_str() );
                                generalMessageHandler->message(CLP_GENERAL, generalMessages)
                                    << generalPrint
                                    << CoinMessageEol;
                            }
                        } else {
                            sprintf(generalPrint, "** Current model not valid");
                            printGeneralMessage(model_,generalPrint);
                        }
                        break;
                    case CLP_PARAM_ACTION_DEBUG:
                        if (goodModel) {
                            delete [] debugValues;
                            debugValues = NULL;
                            // get next field
                            field = CoinReadGetString(argc, argv);
                            if (field == "$") {
                                field = parameters_[iParam].stringValue();
                            } else if (field == "EOL") {
                                parameters_[iParam].printString();
                                break;
                            } else {
                                parameters_[iParam].setStringValue(field);
                                debugFile = field;
                                if (debugFile == "create" ||
                                        debugFile == "createAfterPre") {
                                    printf("Will create a debug file so this run should be a good one\n");
                                    break;
                                }
                            }
                            std::string fileName;
                            if (field[0] == '/' || field[0] == '\\') {
                                fileName = field;
                            } else if (field[0] == '~') {
                                char * environVar = getenv("HOME");
                                if (environVar) {
                                    std::string home(environVar);
                                    field = field.erase(0, 1);
                                    fileName = home + field;
                                } else {
                                    fileName = field;
                                }
                            } else {
                                fileName = directory + field;
                            }
                            FILE *fp = fopen(fileName.c_str(), "rb");
                            if (fp) {
                                // can open - lets go for it
                                int numRows;
                                double obj;
                                size_t nRead;
                                nRead = fread(&numRows, sizeof(int), 1, fp);
                                if (nRead != 1)
                                    throw("Error in fread");
                                nRead = fread(&numberDebugValues, sizeof(int), 1, fp);
                                if (nRead != 1)
                                    throw("Error in fread");
                                nRead = fread(&obj, sizeof(double), 1, fp);
                                if (nRead != 1)
                                    throw("Error in fread");
                                debugValues = new double[numberDebugValues+numRows];
                                nRead = fread(debugValues, sizeof(double), numRows, fp);
                                if (nRead != static_cast<size_t>(numRows))
                                    throw("Error in fread");
                                nRead = fread(debugValues, sizeof(double), numRows, fp);
                                if (nRead != static_cast<size_t>(numRows))
                                    throw("Error in fread");
                                nRead = fread(debugValues, sizeof(double), numberDebugValues, fp);
                                if (nRead != static_cast<size_t>(numberDebugValues))
                                    throw("Error in fread");
                                printf("%d doubles read into debugValues\n", numberDebugValues);
#ifdef CGL_WRITEMPS
				debugSolution = debugValues;
				debugNumberColumns = numberDebugValues;
#endif
                                if (numberDebugValues < 200) {
                                    for (int i = 0; i < numberDebugValues; i++) {
                                        if (clpSolver->isInteger(i) && debugValues[i])
                                            printf("%d %g\n", i, debugValues[i]);
                                    }
                                }
                                fclose(fp);
                            } else {
			      sprintf(generalPrint, "Unable to open file %s",fileName.c_str());
			      printGeneralMessage(model_,generalPrint);
                            }
                        } else {
			  sprintf(generalPrint, "** Current model not valid");
			  printGeneralMessage(model_,generalPrint);
                        }
                        break;
                    case CLP_PARAM_ACTION_PRINTMASK:
                        // get next field
                    {
                        std::string name = CoinReadGetString(argc, argv);
                        if (name != "EOL") {
                            parameters_[iParam].setStringValue(name);
                            printMask = name;
                        } else {
                            parameters_[iParam].printString();
                        }
                    }
                    break;
                    case CLP_PARAM_ACTION_BASISOUT:
                        if (goodModel) {
                            // get next field
                            field = CoinReadGetString(argc, argv);
                            if (field == "$") {
                                field = parameters_[iParam].stringValue();
                            } else if (field == "EOL") {
                                parameters_[iParam].printString();
                                break;
                            } else {
                                parameters_[iParam].setStringValue(field);
                            }
                            std::string fileName;
                            bool canOpen = false;
                            if (field[0] == '/' || field[0] == '\\') {
                                fileName = field;
                            } else if (field[0] == '~') {
                                char * environVar = getenv("HOME");
                                if (environVar) {
                                    std::string home(environVar);
                                    field = field.erase(0, 1);
                                    fileName = home + field;
                                } else {
                                    fileName = field;
                                }
                            } else {
                                fileName = directory + field;
                            }
                            FILE *fp = fopen(fileName.c_str(), "w");
                            if (fp) {
                                // can open - lets go for it
                                fclose(fp);
                                canOpen = true;
                            } else {
			      sprintf(generalPrint, "Unable to open file %s",fileName.c_str());
			      printGeneralMessage(model_,generalPrint);
                            }
                            if (canOpen) {
                                ClpSimplex * model2 = lpSolver;
                                model2->writeBasis(fileName.c_str(), outputFormat > 1, outputFormat - 2);
                                time2 = CoinCpuTime();
                                totalTime += time2 - time1;
                                time1 = time2;
                            }
                        } else {
			  sprintf(generalPrint, "** Current model not valid");
			  printGeneralMessage(model_,generalPrint);
                        }
                        break;
                    case CLP_PARAM_ACTION_SAVE: {
                        // get next field
                        field = CoinReadGetString(argc, argv);
                        if (field == "$") {
                            field = parameters_[iParam].stringValue();
                        } else if (field == "EOL") {
                            parameters_[iParam].printString();
                            break;
                        } else {
                            parameters_[iParam].setStringValue(field);
                        }
                        std::string fileName;
                        bool canOpen = false;
                        if (field[0] == '/' || field[0] == '\\') {
                            fileName = field;
                        } else if (field[0] == '~') {
                            char * environVar = getenv("HOME");
                            if (environVar) {
                                std::string home(environVar);
                                field = field.erase(0, 1);
                                fileName = home + field;
                            } else {
                                fileName = field;
                            }
                        } else {
                            fileName = directory + field;
                        }
                        FILE *fp = fopen(fileName.c_str(), "wb");
                        if (fp) {
                            // can open - lets go for it
                            fclose(fp);
                            canOpen = true;
                        } else {
			  sprintf(generalPrint, "Unable to open file %s",fileName.c_str());
			  printGeneralMessage(model_,generalPrint);
                        }
                        if (canOpen) {
                            int status;
                            // If presolve on then save presolved
                            bool deleteModel2 = false;
                            ClpSimplex * model2 = lpSolver;
                            if (preSolve) {
                                ClpPresolve pinfo;
                                double presolveTolerance =
                                    parameters_[whichParam(CLP_PARAM_DBL_PRESOLVETOLERANCE, numberParameters_, parameters_)].doubleValue();
                                model2 =
                                    pinfo.presolvedModel(*lpSolver, presolveTolerance,
                                                         false, preSolve);
                                if (model2) {
                                    printf("Saving presolved model on %s\n",
                                           fileName.c_str());
                                    deleteModel2 = true;
                                } else {
                                    printf("Presolved model looks infeasible - saving original on %s\n",
                                           fileName.c_str());
                                    deleteModel2 = false;
                                    model2 = lpSolver;

                                }
                            } else {
                                printf("Saving model on %s\n",
                                       fileName.c_str());
                            }
                            status = model2->saveModel(fileName.c_str());
                            if (deleteModel2)
                                delete model2;
                            if (!status) {
                                goodModel = true;
                                time2 = CoinCpuTime();
                                totalTime += time2 - time1;
                                time1 = time2;
                            } else {
                                // errors
			      sprintf(generalPrint, "There were errors on output");
			      printGeneralMessage(model_,generalPrint);
                            }
                        }
                    }
                    break;
                    case CLP_PARAM_ACTION_RESTORE: {
                        // get next field
                        field = CoinReadGetString(argc, argv);
                        if (field == "$") {
                            field = parameters_[iParam].stringValue();
                        } else if (field == "EOL") {
                            parameters_[iParam].printString();
                            break;
                        } else {
                            parameters_[iParam].setStringValue(field);
                        }
                        std::string fileName;
                        bool canOpen = false;
                        if (field[0] == '/' || field[0] == '\\') {
                            fileName = field;
                        } else if (field[0] == '~') {
                            char * environVar = getenv("HOME");
                            if (environVar) {
                                std::string home(environVar);
                                field = field.erase(0, 1);
                                fileName = home + field;
                            } else {
                                fileName = field;
                            }
                        } else {
                            fileName = directory + field;
                        }
                        FILE *fp = fopen(fileName.c_str(), "rb");
                        if (fp) {
                            // can open - lets go for it
                            fclose(fp);
                            canOpen = true;
                        } else {
			  sprintf(generalPrint, "Unable to open file %s",fileName.c_str());
			  printGeneralMessage(model_,generalPrint);
                        }
                        if (canOpen) {
                            int status = lpSolver->restoreModel(fileName.c_str());
                            if (!status) {
                                goodModel = true;
                                time2 = CoinCpuTime();
                                totalTime += time2 - time1;
                                time1 = time2;
                            } else {
                                // errors
			      sprintf(generalPrint, "There were errors on input");
			      printGeneralMessage(model_,generalPrint);
                            }
                        }
                    }
                    break;
                    case CLP_PARAM_ACTION_MAXIMIZE:
                        lpSolver->setOptimizationDirection(-1);
                        break;
                    case CLP_PARAM_ACTION_MINIMIZE:
                        lpSolver->setOptimizationDirection(1);
                        break;
                    case CLP_PARAM_ACTION_ALLSLACK:
                        lpSolver->allSlackBasis(true);
                        break;
                    case CLP_PARAM_ACTION_REVERSE:
                        if (goodModel) {
                            int iColumn;
                            int numberColumns = lpSolver->numberColumns();
                            double * dualColumnSolution =
                                lpSolver->dualColumnSolution();
                            ClpObjective * obj = lpSolver->objectiveAsObject();
                            assert(dynamic_cast<ClpLinearObjective *> (obj));
                            double offset;
                            double * objective = obj->gradient(NULL, NULL, offset, true);
                            for (iColumn = 0; iColumn < numberColumns; iColumn++) {
                                dualColumnSolution[iColumn] = dualColumnSolution[iColumn];
                                objective[iColumn] = -objective[iColumn];
                            }
                            int iRow;
                            int numberRows = lpSolver->numberRows();
                            double * dualRowSolution =
                                lpSolver->dualRowSolution();
                            for (iRow = 0; iRow < numberRows; iRow++)
                                dualRowSolution[iRow] = dualRowSolution[iRow];
                        }
                        break;
                    case CLP_PARAM_ACTION_DIRECTORY: {
                        std::string name = CoinReadGetString(argc, argv);
                        if (name != "EOL") {
                            size_t length = name.length();
                            if (length > 0 && name[length-1] == dirsep) {
                                directory = name;
                            } else {
                                directory = name + dirsep;
                            }
                            parameters_[iParam].setStringValue(directory);
                        } else {
                            parameters_[iParam].printString();
                        }
                    }
                    break;
                    case CLP_PARAM_ACTION_DIRSAMPLE: {
                        std::string name = CoinReadGetString(argc, argv);
                        if (name != "EOL") {
                            size_t length = name.length();
                            if (length > 0 && name[length-1] == dirsep) {
                                dirSample = name;
                            } else {
                                dirSample = name + dirsep;
                            }
                            parameters_[iParam].setStringValue(dirSample);
                        } else {
                            parameters_[iParam].printString();
                        }
                    }
                    break;
                    case CLP_PARAM_ACTION_DIRNETLIB: {
                        std::string name = CoinReadGetString(argc, argv);
                        if (name != "EOL") {
                            size_t length = name.length();
                            if (length > 0 && name[length-1] == dirsep) {
                                dirNetlib = name;
                            } else {
                                dirNetlib = name + dirsep;
                            }
                            parameters_[iParam].setStringValue(dirNetlib);
                        } else {
                            parameters_[iParam].printString();
                        }
                    }
                    break;
                    case CBC_PARAM_ACTION_DIRMIPLIB: {
                        std::string name = CoinReadGetString(argc, argv);
                        if (name != "EOL") {
                            size_t length = name.length();
                            if (length > 0 && name[length-1] == dirsep) {
                                dirMiplib = name;
                            } else {
                                dirMiplib = name + dirsep;
                            }
                            parameters_[iParam].setStringValue(dirMiplib);
                        } else {
                            parameters_[iParam].printString();
                        }
                    }
                    break;
                    case CLP_PARAM_ACTION_STDIN:
                        CbcOrClpRead_mode = -1;
                        break;
                    case CLP_PARAM_ACTION_NETLIB_DUAL:
                    case CLP_PARAM_ACTION_NETLIB_EITHER:
                    case CLP_PARAM_ACTION_NETLIB_BARRIER:
                    case CLP_PARAM_ACTION_NETLIB_PRIMAL:
                    case CLP_PARAM_ACTION_NETLIB_TUNE: {
                        printf("unit test is now only from clp - does same thing\n");
                        //return(22);
                    }
                    break;
                    case CLP_PARAM_ACTION_UNITTEST: {
                        CbcClpUnitTest(model_, dirSample, -2, NULL);
                    }
                    break;
                    case CLP_PARAM_ACTION_FAKEBOUND:
                        if (goodModel) {
                            // get bound
                            double value = CoinReadGetDoubleField(argc, argv, &valid);
                            if (!valid) {
			      sprintf(generalPrint, "Setting %s to DEBUG %g",parameters_[iParam].name().c_str(),value);
			      printGeneralMessage(model_,generalPrint);
                                int iRow;
                                int numberRows = lpSolver->numberRows();
                                double * rowLower = lpSolver->rowLower();
                                double * rowUpper = lpSolver->rowUpper();
                                for (iRow = 0; iRow < numberRows; iRow++) {
                                    // leave free ones for now
                                    if (rowLower[iRow] > -1.0e20 || rowUpper[iRow] < 1.0e20) {
                                        rowLower[iRow] = CoinMax(rowLower[iRow], -value);
                                        rowUpper[iRow] = CoinMin(rowUpper[iRow], value);
                                    }
                                }
                                int iColumn;
                                int numberColumns = lpSolver->numberColumns();
                                double * columnLower = lpSolver->columnLower();
                                double * columnUpper = lpSolver->columnUpper();
                                for (iColumn = 0; iColumn < numberColumns; iColumn++) {
                                    // leave free ones for now
                                    if (columnLower[iColumn] > -1.0e20 ||
                                            columnUpper[iColumn] < 1.0e20) {
                                        columnLower[iColumn] = CoinMax(columnLower[iColumn], -value);
                                        columnUpper[iColumn] = CoinMin(columnUpper[iColumn], value);
                                    }
                                }
                            } else if (valid == 1) {
                                abort();
                            } else {
                                std::cout << "enter value for " << parameters_[iParam].name() <<
                                          std::endl;
                            }
                        }
                        break;
                    case CLP_PARAM_ACTION_REALLY_SCALE:
                        if (goodModel) {
                            ClpSimplex newModel(*lpSolver,
                                                lpSolver->scalingFlag());
                            printf("model really really scaled\n");
                            *lpSolver = newModel;
                        }
                        break;
                    case CLP_PARAM_ACTION_USERCLP:
#ifdef USER_HAS_FAKE_CLP
                        // Replace the sample code by whatever you want
                        if (goodModel) {
                            // Way of using an existing piece of code
                            OsiClpSolverInterface * clpSolver = dynamic_cast< OsiClpSolverInterface*> (model_.solver());
                            ClpSimplex * lpSolver = clpSolver->getModelPtr();
                            // set time from integer model
                            double timeToGo = model_.getMaximumSeconds();
                            lpSolver->setMaximumSeconds(timeToGo);
                            int extra1 = parameters_[whichParam(CBC_PARAM_INT_EXTRA1, numberParameters_, parameters_)].intValue();
                            fakeMain2(*lpSolver, *clpSolver, extra1);
                            lpSolver = clpSolver->getModelPtr();
#ifdef COIN_HAS_ASL
                            // My actual usage has objective only in clpSolver
                            //double objectiveValue=clpSolver->getObjValue();
                            //int iStat = lpSolver->status();
                            //int iStat2 = lpSolver->secondaryStatus();
#endif
                        }
#endif
                        break;
                    case CBC_PARAM_ACTION_USERCBC:
#ifdef USER_HAS_FAKE_CBC
                        // Replace the sample code by whatever you want
                        if (goodModel) {
                            // Way of using an existing piece of code
                            OsiClpSolverInterface * clpSolver = dynamic_cast< OsiClpSolverInterface*> (model_.solver());
                            ClpSimplex * lpSolver = clpSolver->getModelPtr();
                            // set time from integer model
                            double timeToGo = model_.getMaximumSeconds();
                            lpSolver->setMaximumSeconds(timeToGo);
                            fakeMain(*lpSolver, *clpSolver, model);
#ifdef COIN_HAS_ASL
                            // My actual usage has objective only in clpSolver
                            double objectiveValue = clpSolver->getObjValue();
                            int iStat = lpSolver->status();
                            int iStat2 = lpSolver->secondaryStatus();
#endif
                            // make sure solution back in correct place
                            clpSolver = dynamic_cast< OsiClpSolverInterface*> (model_.solver());
                            lpSolver = clpSolver->getModelPtr();
#ifdef COIN_HAS_ASL
                            if (statusUserFunction_[0]) {
                                int n = clpSolver->getNumCols();
                                double value = objectiveValue * lpSolver->getObjSense();
                                char buf[300];
                                int pos = 0;
                                std::string minor[] = {"", "", "gap", "nodes", "time", "", "solutions", "user ctrl-c"};
                                if (iStat == 0) {
                                    if (objectiveValue < 1.0e40) {
                                        pos += sprintf(buf + pos, "optimal," );
                                    } else {
                                        // infeasible
                                        iStat = 1;
                                        pos += sprintf(buf + pos, "infeasible,");
                                    }
                                } else if (iStat == 1) {
                                    if (iStat2 != 6)
                                        iStat = 3;
                                    else
                                        iStat = 4;
                                    pos += sprintf(buf + pos, "stopped on %s,", minor[iStat2].c_str());
                                } else if (iStat == 2) {
                                    iStat = 7;
                                    pos += sprintf(buf + pos, "stopped on difficulties,");
                                } else if (iStat == 5) {
                                    iStat = 3;
                                    pos += sprintf(buf + pos, "stopped on ctrl-c,");
                                } else if (iStat == 6) {
                                    // bab infeasible
                                    pos += sprintf(buf + pos, "integer infeasible,");
                                    iStat = 1;
                                } else {
                                    pos += sprintf(buf + pos, "status unknown,");
                                    iStat = 6;
                                }
                                info.problemStatus = iStat;
                                info.objValue = value;
                                if (objectiveValue < 1.0e40)
                                    pos += sprintf(buf + pos, " objective %.*g", ampl_obj_prec(),
                                                   value);
                                sprintf(buf + pos, "\n%d nodes, %d iterations",
                                        model_.getNodeCount(),
                                        model_.getIterationCount());
                                if (objectiveValue < 1.0e50) {
                                    free(info.primalSolution);
                                    info.primalSolution = (double *) malloc(n * sizeof(double));
                                    CoinCopyN(lpSolver->primalColumnSolution(), n, info.primalSolution);
                                    int numberRows = lpSolver->numberRows();
                                    free(info.dualSolution);
                                    info.dualSolution = (double *) malloc(numberRows * sizeof(double));
                                    CoinCopyN(lpSolver->dualRowSolution(), numberRows, info.dualSolution);
                                } else {
                                    info.primalSolution = NULL;
                                    info.dualSolution = NULL;
                                }
                                // put buffer into info
                                strcpy(info.buffer, buf);
                            }
#endif
                        }
#endif
                        break;
                    case CLP_PARAM_ACTION_HELP:
                        std::cout << "Cbc version " << CBC_VERSION
                                  << ", build " << __DATE__ << std::endl;
                        std::cout << "Non default values:-" << std::endl;
                        std::cout << "Perturbation " << lpSolver->perturbation() << " (default 100)"
                                  << std::endl;
                        CoinReadPrintit(
                            "Presolve being done with 5 passes\n\
Dual steepest edge steep/partial on matrix shape and factorization density\n\
Clpnnnn taken out of messages\n\
If Factorization frequency default then done on size of matrix\n\n\
(-)unitTest, (-)netlib or (-)netlibp will do standard tests\n\n\
You can switch to interactive mode at any time so\n\
clp watson.mps -scaling off -primalsimplex\nis the same as\n\
clp watson.mps -\nscaling off\nprimalsimplex"
                        );
                        break;
                    case CLP_PARAM_ACTION_CSVSTATISTICS: {
                        // get next field
                        field = CoinReadGetString(argc, argv);
                        if (field == "$") {
                            field = parameters_[iParam].stringValue();
                        } else if (field == "EOL") {
                            parameters_[iParam].printString();
                            break;
                        } else {
                            parameters_[iParam].setStringValue(field);
                        }
                        std::string fileName;
                        if (field[0] == '/' || field[0] == '\\') {
                            fileName = field;
                        } else if (field[0] == '~') {
                            char * environVar = getenv("HOME");
                            if (environVar) {
                                std::string home(environVar);
                                field = field.erase(0, 1);
                                fileName = home + field;
                            } else {
                                fileName = field;
                            }
                        } else {
                            fileName = directory + field;
                        }
                        int state = 0;
                        char buffer[1000];
                        FILE *fp = fopen(fileName.c_str(), "r");
                        if (fp) {
                            // file already there
                            state = 1;
                            char * getBuffer = fgets(buffer, 1000, fp);
                            if (getBuffer) {
                                // assume header there
                                state = 2;
                            }
                            fclose(fp);
                        }
                        fp = fopen(fileName.c_str(), "a");
                        if (fp) {
                            // can open - lets go for it
                            // first header if needed
                            if (state != 2) {
                                fprintf(fp, "Name,result,time,sys,elapsed,objective,continuous,tightened,cut_time,nodes,iterations,rows,columns,processed_rows,processed_columns");
                                for (int i = 0; i < statistics_number_generators; i++)
                                    fprintf(fp, ",%s", statistics_name_generators[i]);
                                fprintf(fp, ",runtime_options");
                                fprintf(fp, "\n");
                            }
                            strcpy(buffer, argv[1]);
                            char * slash = buffer;
                            for (int i = 0; i < static_cast<int>(strlen(buffer)); i++) {
                                if (buffer[i] == '/' || buffer[i] == '\\')
                                    slash = buffer + i + 1;
                            }
                            fprintf(fp, "%s,%s,%.2f,%.2f,%.2f,%.16g,%g,%g,%.2f,%d,%d,%d,%d,%d,%d",
                                    slash, statistics_result.c_str(), statistics_seconds,
                                    statistics_sys_seconds, statistics_elapsed_seconds,
                                    statistics_obj,
                                    statistics_continuous, statistics_tighter, statistics_cut_time, statistics_nodes,
                                    statistics_iterations, statistics_nrows, statistics_ncols,
                                    statistics_nprocessedrows, statistics_nprocessedcols);
                            for (int i = 0; i < statistics_number_generators; i++)
                                fprintf(fp, ",%d", (statistics_number_cuts!=NULL) ? statistics_number_cuts[i] : 0 );
                            fprintf(fp, ",");
                            for (int i = 1; i < argc; i++) {
                                if (strstr(argv[i], ".gz") || strstr(argv[i], ".mps"))
                                    continue;
                                if (!argv[i] || !strncmp(argv[i], "-csv", 4))
                                    break;
                                fprintf(fp, "%s ", argv[i]);
                            }
                            fprintf(fp, "\n");
                            fclose(fp);
                        } else {
			  sprintf(generalPrint, "Unable to open file %s",fileName.c_str());
			  printGeneralMessage(model_,generalPrint);
                        }
                    }
                    break;
                    case CLP_PARAM_ACTION_SOLUTION:
                    case CLP_PARAM_ACTION_NEXTBESTSOLUTION:
                    case CLP_PARAM_ACTION_GMPL_SOLUTION:
                        if (goodModel) {
			  ClpSimplex * saveLpSolver = NULL;
                            // get next field
                            field = CoinReadGetString(argc, argv);
			    bool append = false;
			    if (field == "append$") {
			      field = "$";
			      append = true;
			    }
                            if (field == "$") {
                                field = parameters_[iParam].stringValue();
                            } else if (field == "EOL") {
                                parameters_[iParam].printString();
                                break;
                            } else {
                                parameters_[iParam].setStringValue(field);
                            }
                            std::string fileName;
                            FILE *fp = NULL;
                            if (field == "-" || field == "EOL" || field == "stdout") {
                                // stdout
                                fp = stdout;
                            } else if (field == "stderr") {
                                // stderr
                                fp = stderr;
                            } else {
                                bool absolutePath;
                                if (dirsep == '/') {
                                    // non Windows (or cygwin)
                                    absolutePath = (field[0] == '/');
                                } else {
                                    //Windows (non cycgwin)
                                    absolutePath = (field[0] == '\\');
                                    // but allow for :
                                    if (strchr(field.c_str(), ':'))
                                        absolutePath = true;
                                }
                                if (absolutePath) {
                                    fileName = field;
                                } else if (field[0] == '~') {
                                    char * environVar = getenv("HOME");
                                    if (environVar) {
                                        std::string home(environVar);
                                        field = field.erase(0, 1);
                                        fileName = home + field;
                                    } else {
                                        fileName = field;
                                    }
                                } else {
                                    fileName = directory + field;
                                }
				if (!append)
				  fp = fopen(fileName.c_str(), "w");
				else
				  fp = fopen(fileName.c_str(), "a");
                            }
                            if (fp) {
#ifndef CBC_OTHER_SOLVER
			      // See if Glpk 
			      if (type == CLP_PARAM_ACTION_GMPL_SOLUTION) {
				int numberRows = lpSolver->getNumRows();
				int numberColumns = lpSolver->getNumCols();
				int numberGlpkRows=numberRows+1;
#ifdef COIN_HAS_GLPK
				if (cbc_glp_prob) {
				  // from gmpl
				  numberGlpkRows=glp_get_num_rows(cbc_glp_prob);
				  if (numberGlpkRows!=numberRows)
				    printf("Mismatch - cbc %d rows, glpk %d\n",
					   numberRows,numberGlpkRows);
				}
#endif
				fprintf(fp,"%d %d\n",numberGlpkRows,
					numberColumns);
				int iStat = lpSolver->status();
				int iStat2 = GLP_UNDEF;
				bool integerProblem = false;
				if (integerStatus >= 0){
				  iStat = integerStatus;
				  integerProblem = true;
				}
				if (iStat == 0) {
				  // optimal
				  if (integerProblem)
				    iStat2 = GLP_OPT;
				  else
				    iStat2 = GLP_FEAS;
				} else if (iStat == 1) {
				  // infeasible
				  iStat2 = GLP_NOFEAS;
				} else if (iStat == 2) {
				  // unbounded
				  // leave as 1
				} else if (iStat >= 3 && iStat <= 5) {
				  if (babModel_ && !babModel_->bestSolution())
				    iStat2 = GLP_NOFEAS;
				  else
				    iStat2 = GLP_FEAS;
				} else if (iStat == 6) {
				  // bab infeasible
				  iStat2 = GLP_NOFEAS;
				}
				lpSolver->computeObjectiveValue(false);
				double objValue = clpSolver->getObjValue(); 
				if (integerProblem)
				  fprintf(fp,"%d %g\n",iStat2,objValue);
				else
				  fprintf(fp,"%d 2 %g\n",iStat2,objValue);
				if (numberGlpkRows > numberRows) {
				  // objective as row
				  if (integerProblem) {
				    fprintf(fp,"%g\n",objValue);
				  } else {
				    fprintf(fp,"4 %g 1.0\n",objValue);
				  }
				}
				int lookup[6]=
				  {4,1,3,2,4,5};
				const double * primalRowSolution =
				  lpSolver->primalRowSolution();
				const double * dualRowSolution =
				  lpSolver->dualRowSolution();
				for (int i=0;i<numberRows;i++) {
				  if (integerProblem) {
				    fprintf(fp,"%g\n",primalRowSolution[i]);
				  } else {
				    fprintf(fp,"%d %g %g\n",lookup[lpSolver->getRowStatus(i)],
								   primalRowSolution[i],dualRowSolution[i]);
				  }
				}
				const double * primalColumnSolution =
				  lpSolver->primalColumnSolution();
				const double * dualColumnSolution =
				  lpSolver->dualColumnSolution();
				for (int i=0;i<numberColumns;i++) {
				  if (integerProblem) {
				    fprintf(fp,"%g\n",primalColumnSolution[i]);
				  } else {
				    fprintf(fp,"%d %g %g\n",lookup[lpSolver->getColumnStatus(i)],
								   primalColumnSolution[i],dualColumnSolution[i]);
				  }
				}
				fclose(fp);
#ifdef COIN_HAS_GLPK
				if (cbc_glp_prob) {
				  if (integerProblem) {
				    glp_read_mip(cbc_glp_prob,fileName.c_str());
				    glp_mpl_postsolve(cbc_glp_tran,
						      cbc_glp_prob,
						      GLP_MIP);
				  } else {
				    glp_read_sol(cbc_glp_prob,fileName.c_str());
				    glp_mpl_postsolve(cbc_glp_tran,
						      cbc_glp_prob,
						      GLP_SOL);
				  }
				  // free up as much as possible
				  glp_free(cbc_glp_prob);
				  glp_mpl_free_wksp(cbc_glp_tran);
				  cbc_glp_prob = NULL;
				  cbc_glp_tran = NULL;
				  //gmp_free_mem();
				  /* check that no memory blocks are still allocated */
				  glp_free_env();
				}
#endif
				break;
			      }
			      if (printMode < 5) {
			        if (type == CLP_PARAM_ACTION_NEXTBESTSOLUTION) {
				  // save
				  const double * nextBestSolution = model_.savedSolution(1);
				  if (!nextBestSolution) {
				    sprintf(generalPrint, "All alternative solutions printed");
				    generalMessageHandler->message(CLP_GENERAL, generalMessages)
				      << generalPrint
				      << CoinMessageEol;
				    break;
				  } else {
				    sprintf(generalPrint, "Alternative solution - %d remaining",model_.numberSavedSolutions()-2);
				    generalMessageHandler->message(CLP_GENERAL, generalMessages)
				      << generalPrint
				      << CoinMessageEol;
				  }
				  saveLpSolver = lpSolver;
				  assert (clpSolver->getModelPtr()==saveLpSolver);
				  lpSolver = new ClpSimplex(*saveLpSolver);
#ifndef NDEBUG
				  ClpSimplex * oldSimplex = clpSolver->swapModelPtr(lpSolver);
				  assert (oldSimplex==saveLpSolver);
#else
              clpSolver->swapModelPtr(lpSolver);
#endif
				  double * solution = lpSolver->primalColumnSolution();
				  double * lower = lpSolver->columnLower();
				  double * upper = lpSolver->columnUpper();
				  int numberColumns=lpSolver->numberColumns();
				  memcpy(solution,nextBestSolution,numberColumns*sizeof(double));
				  model_.deleteSavedSolution(1);
				  for (int i = 0; i < numberColumns; i++) {
				    if (clpSolver->isInteger(i)) {
				      double value=floor(solution[i]+0.5);
				      lower[i]=value;
				      upper[i]=value;
				    }
				  }
				  lpSolver->allSlackBasis();
				  lpSolver->initialSolve();
				}
                                    // Write solution header (suggested by Luigi Poderico)
				    // Refresh solver
				    lpSolver = clpSolver->getModelPtr();
                                    lpSolver->computeObjectiveValue(false);
                                    double objValue = lpSolver->getObjValue();
                                    int iStat = lpSolver->status();
				    int iStat2 = -1;
                                    if (integerStatus >= 0){
                                        iStat = integerStatus;
					iStat2 = babModel_->secondaryStatus();
				    }
                                    if (iStat == 0) {
                                        fprintf(fp, "Optimal" );
					if (iStat2 == 2){
					   fprintf(fp, " (within gap tolerance)" );
					}
                                    } else if (iStat == 1) {
                                        // infeasible
                                        fprintf(fp, "Infeasible" );
                                    } else if (iStat == 2) {
                                        // unbounded
                                        fprintf(fp, "Unbounded" );
                                    } else if (iStat >= 3 && iStat <= 5) {
				        if (iStat == 3) {
					    if (iStat2 == 4){
					        fprintf(fp, "Stopped on time" );
					    }else{
					        fprintf(fp, "Stopped on iterations" );
					    }
					} else if (iStat == 4){
					    fprintf(fp, "Stopped on difficulties" );
					} else {
					    fprintf(fp, "Stopped on ctrl-c" );
					}
                                        if (babModel_ && !babModel_->bestSolution())
                                            fprintf(fp, " (no integer solution - continuous used)");
                                    } else if (iStat == 6) {
				         // bab infeasible
				         fprintf(fp, "Integer infeasible" );
                                    } else {
				         fprintf(fp, "Status unknown" );
                                    }
                                    fprintf(fp, " - objective value %.8f\n", objValue);
                                }
#endif
                                // make fancy later on
                                int iRow;
                                int numberRows = clpSolver->getNumRows();
                                const double * dualRowSolution = clpSolver->getRowPrice();
                                const double * primalRowSolution =
                                    clpSolver->getRowActivity();
                                const double * rowLower = clpSolver->getRowLower();
                                const double * rowUpper = clpSolver->getRowUpper();
                                double primalTolerance ;
                                clpSolver->getDblParam(OsiPrimalTolerance, primalTolerance);
                                size_t lengthPrint = static_cast<size_t>(CoinMax(lengthName, 8));
                                bool doMask = (printMask != "" && lengthName);
                                int * maskStarts = NULL;
                                int maxMasks = 0;
                                char ** masks = NULL;
                                if (doMask) {
                                    int nAst = 0;
                                    const char * pMask2 = printMask.c_str();
                                    char pMask[100];
                                    size_t iChar;
                                    size_t lengthMask = strlen(pMask2);
                                    assert (lengthMask < 100);
                                    if (*pMask2 == '"') {
                                        if (pMask2[lengthMask-1] != '"') {
                                            printf("mismatched \" in mask %s\n", pMask2);
                                            break;
                                        } else {
                                            strcpy(pMask, pMask2 + 1);
                                            *strchr(pMask, '"') = '\0';
                                        }
                                    } else if (*pMask2 == '\'') {
                                        if (pMask2[lengthMask-1] != '\'') {
                                            printf("mismatched ' in mask %s\n", pMask2);
                                            break;
                                        } else {
                                            strcpy(pMask, pMask2 + 1);
                                            *strchr(pMask, '\'') = '\0';
                                        }
                                    } else {
                                        strcpy(pMask, pMask2);
                                    }
                                    if (lengthMask > static_cast<size_t>(lengthName)) {
                                        printf("mask %s too long - skipping\n", pMask);
                                        break;
                                    }
                                    maxMasks = 1;
                                    for (iChar = 0; iChar < lengthMask; iChar++) {
                                        if (pMask[iChar] == '*') {
                                            nAst++;
                                            maxMasks *= (lengthName + 1);
                                        }
                                    }
                                    int nEntries = 1;
                                    maskStarts = new int[lengthName+2];
                                    masks = new char * [maxMasks];
                                    char ** newMasks = new char * [maxMasks];
                                    int i;
                                    for (i = 0; i < maxMasks; i++) {
                                        masks[i] = new char[lengthName+1];
                                        newMasks[i] = new char[lengthName+1];
                                    }
                                    strcpy(masks[0], pMask);
                                    for (int iAst = 0; iAst < nAst; iAst++) {
                                        int nOldEntries = nEntries;
                                        nEntries = 0;
                                        for (int iEntry = 0; iEntry < nOldEntries; iEntry++) {
                                            char * oldMask = masks[iEntry];
                                            char * ast = strchr(oldMask, '*');
                                            assert (ast);
                                            size_t length = strlen(oldMask) - 1;
                                            size_t nBefore = ast - oldMask;
                                            size_t nAfter = length - nBefore;
                                            // and add null
                                            nAfter++;
                                            for (int i = 0; i <= lengthName - static_cast<int>(length); i++) {
                                                char * maskOut = newMasks[nEntries];
                                                memcpy(maskOut, oldMask, nBefore);
                                                for (int k = 0; k < i; k++)
                                                    maskOut[k+nBefore] = '?';
                                                memcpy(maskOut + nBefore + i, ast + 1, nAfter);
                                                nEntries++;
                                                assert (nEntries <= maxMasks);
                                            }
                                        }
                                        char ** temp = masks;
                                        masks = newMasks;
                                        newMasks = temp;
                                    }
                                    // Now extend and sort
                                    int * sort = new int[nEntries];
                                    for (i = 0; i < nEntries; i++) {
                                        char * maskThis = masks[i];
                                        size_t length = strlen(maskThis);
                                        while (length > 0 && maskThis[length-1] == ' ')
                                            length--;
                                        maskThis[length] = '\0';
                                        sort[i] = static_cast<int>(length);
                                    }
                                    CoinSort_2(sort, sort + nEntries, masks);
                                    int lastLength = -1;
                                    for (i = 0; i < nEntries; i++) {
                                        int length = sort[i];
                                        while (length > lastLength)
                                            maskStarts[++lastLength] = i;
                                    }
                                    maskStarts[++lastLength] = nEntries;
                                    delete [] sort;
                                    for (i = 0; i < maxMasks; i++)
                                        delete [] newMasks[i];
                                    delete [] newMasks;
                                }
				if (printMode > 5) {
				  ClpSimplex * solver = clpSolver->getModelPtr();
				  int numberColumns = solver->numberColumns();
				  // column length unless rhs ranging
				  int number = numberColumns;
				  if (lpSolver->status()) {
				    fprintf(fp,"**** Results not valid when LP not optimal\n");
				    number=0;
				  }
				  switch (printMode) {
				    // bound ranging
				  case 6:
				    fprintf(fp,"Bound ranging");
				    break;
				    // rhs ranging
				  case 7:
				    fprintf(fp,"Rhs ranging");
				    if (!lpSolver->status()) 
				      number = numberRows;
				    break;
				    // objective ranging
				  case 8:
				    fprintf(fp,"Objective ranging");
				    break;
				  }
				  if (lengthName)
				    fprintf(fp,",name");
				  fprintf(fp,",increase,variable,decrease,variable\n");
				  int * which = new int [ number];
				  if (printMode != 7) {
				    if (!doMask) {
				      for (int i = 0; i < number;i ++)
					which[i]=i;
				    } else {
				      int n = 0;
				      for (int i = 0; i < number;i ++) {
					if (maskMatches(maskStarts,masks,columnNames[i]))
					  which[n++]=i;
				      }
				      if (n) {
					number=n;
				      } else {
					printf("No names match - doing all\n");
					for (int i = 0; i < number;i ++)
					  which[i]=i;
				      }
				    }
				  } else {
				    if (!doMask) {
				    for (int i = 0; i < number;i ++)
				      which[i]=i+numberColumns;
				    } else {
				      int n = 0;
				      for (int i = 0; i < number;i ++) {
					if (maskMatches(maskStarts,masks,rowNames[i]))
					  which[n++]=i+numberColumns;
				      }
				      if (n) {
					number=n;
				      } else {
					printf("No names match - doing all\n");
					for (int i = 0; i < number;i ++)
					  which[i]=i+numberColumns;
				      }
				    }
				  }
				  double * valueIncrease = new double [ number];
				  int * sequenceIncrease = new int [ number];
				  double * valueDecrease = new double [ number];
				  int * sequenceDecrease = new int [ number];
				  switch (printMode) {
				    // bound or rhs ranging
				  case 6:
				  case 7:
				    solver->primalRanging(numberRows,
								 which, valueIncrease, sequenceIncrease,
								 valueDecrease, sequenceDecrease);
				    break;
				    // objective ranging
				  case 8:
				    solver->dualRanging(number,
							       which, valueIncrease, sequenceIncrease,
							       valueDecrease, sequenceDecrease);
				    break;
				  }
				  for (int i = 0; i < number; i++) {
				    int iWhich = which[i];
				    fprintf(fp, "%d,", (iWhich<numberColumns) ? iWhich : iWhich-numberColumns);
				    if (lengthName) {
				      const char * name = (printMode==7) ? rowNames[iWhich-numberColumns].c_str() : columnNames[iWhich].c_str();
				      fprintf(fp,"%s,",name);
				    }
				    if (valueIncrease[i]<1.0e30) {
				      fprintf(fp, "%.10g,", valueIncrease[i]);
				      int outSequence = sequenceIncrease[i];
				      if (outSequence<numberColumns) {
					if (lengthName)
					  fprintf(fp,"%s,",columnNames[outSequence].c_str());
					else
					  fprintf(fp,"C%7.7d,",outSequence);
				      } else {
					outSequence -= numberColumns;
					if (lengthName)
					  fprintf(fp,"%s,",rowNames[outSequence].c_str());
					else
					  fprintf(fp,"R%7.7d,",outSequence);
				      }
				    } else {
				      fprintf(fp,"1.0e100,,");
				    }
				    if (valueDecrease[i]<1.0e30) {
				      fprintf(fp, "%.10g,", valueDecrease[i]);
				      int outSequence = sequenceDecrease[i];
				      if (outSequence<numberColumns) {
					if (lengthName)
					  fprintf(fp,"%s",columnNames[outSequence].c_str());
					else
					  fprintf(fp,"C%7.7d",outSequence);
				      } else {
					outSequence -= numberColumns;
					if (lengthName)
					  fprintf(fp,"%s",rowNames[outSequence].c_str());
					else
					  fprintf(fp,"R%7.7d",outSequence);
				      }
				    } else {
				      fprintf(fp,"1.0e100,");
				    }
				    fprintf(fp,"\n");
				  }
				  if (fp != stdout)
				    fclose(fp);
				  delete [] which;
				  delete [] valueIncrease;
				  delete [] sequenceIncrease;
				  delete [] valueDecrease;
				  delete [] sequenceDecrease;
				  if (masks) {
				    delete [] maskStarts;
				    for (int i = 0; i < maxMasks; i++)
				      delete [] masks[i];
				    delete [] masks;
				  }
				  break;
				}
				char printFormat[50];
				sprintf(printFormat," %s         %s\n",
					CLP_QUOTE(CLP_OUTPUT_FORMAT),
					CLP_QUOTE(CLP_OUTPUT_FORMAT));
                                if (printMode > 2 && printMode < 5) {
                                    for (iRow = 0; iRow < numberRows; iRow++) {
                                        int type = printMode - 3;
                                        if (primalRowSolution[iRow] > rowUpper[iRow] + primalTolerance ||
                                                primalRowSolution[iRow] < rowLower[iRow] - primalTolerance) {
                                            fprintf(fp, "** ");
                                            type = 2;
                                        } else if (fabs(primalRowSolution[iRow]) > 1.0e-8) {
                                            type = 1;
                                        } else if (numberRows < 50) {
                                            type = 3;
                                        }
                                        if (doMask && !maskMatches(maskStarts, masks, rowNames[iRow]))
                                            type = 0;
                                        if (type) {
                                            fprintf(fp, "%7d ", iRow);
                                            if (lengthName) {
                                                const char * name = rowNames[iRow].c_str();
                                                size_t n = strlen(name);
                                                size_t i;
                                                for (i = 0; i < n; i++)
                                                    fprintf(fp, "%c", name[i]);
                                                for (; i < lengthPrint; i++)
                                                    fprintf(fp, " ");
                                            }
                                            fprintf(fp, printFormat, primalRowSolution[iRow],
                                                    dualRowSolution[iRow]);
                                        }
                                    }
                                }
                                int iColumn;
                                int numberColumns = clpSolver->getNumCols();
                                const double * dualColumnSolution =
                                    clpSolver->getReducedCost();
                                const double * primalColumnSolution =
                                    clpSolver->getColSolution();
                                const double * columnLower = clpSolver->getColLower();
                                const double * columnUpper = clpSolver->getColUpper();
                                if (printMode != 2) {
                                    if (printMode == 5) {
                                        if (lengthName)
                                            fprintf(fp, "name");
                                        else
                                            fprintf(fp, "number");
                                        fprintf(fp, ",solution\n");
                                    }
                                    for (iColumn = 0; iColumn < numberColumns; iColumn++) {
                                        int type = (printMode > 3) ? 1 : 0;
                                        if (primalColumnSolution[iColumn] > columnUpper[iColumn] + primalTolerance ||
                                                primalColumnSolution[iColumn] < columnLower[iColumn] - primalTolerance) {
                                            fprintf(fp, "** ");
                                            type = 2;
                                        } else if (fabs(primalColumnSolution[iColumn]) > 1.0e-8) {
                                            type = 1;
                                        } else if (numberColumns < 50) {
                                            type = 3;
                                        }
                                        // see if integer
                                        if ((!clpSolver->isInteger(iColumn) || fabs(primalColumnSolution[iColumn]) < 1.0e-8)
                                                && printMode == 1)
                                            type = 0;
                                        if (doMask && !maskMatches(maskStarts, masks,
                                                                   columnNames[iColumn]))
                                            type = 0;
                                        if (type) {
                                            if (printMode != 5) {
                                                fprintf(fp, "%7d ", iColumn);
                                                if (lengthName) {
                                                    const char * name = columnNames[iColumn].c_str();
                                                    size_t n = strlen(name);
                                                    size_t i;
                                                    for (i = 0; i < n; i++)
                                                        fprintf(fp, "%c", name[i]);
                                                    for (; i < lengthPrint; i++)
                                                        fprintf(fp, " ");
                                                }
                                                fprintf(fp, printFormat,
                                                        primalColumnSolution[iColumn],
                                                        dualColumnSolution[iColumn]);
                                            } else {
                                                char temp[100];
                                                if (lengthName) {
                                                    const char * name = columnNames[iColumn].c_str();
                                                    for (int i = 0; i < lengthName; i++)
                                                        temp[i] = name[i];
                                                    temp[lengthName] = '\0';
                                                } else {
                                                    sprintf(temp, "%7d", iColumn);
                                                }
                                                sprintf(temp + strlen(temp), ", %15.8g",
                                                        primalColumnSolution[iColumn]);
                                                size_t n = strlen(temp);
                                                size_t k = 0;
                                                for (size_t i = 0; i < n + 1; i++) {
                                                    if (temp[i] != ' ')
                                                        temp[k++] = temp[i];
                                                }
                                                fprintf(fp, "%s\n", temp);
                                            }
                                        }
                                    }
				    if (type == CLP_PARAM_ACTION_NEXTBESTSOLUTION) {
				      if(saveLpSolver) {
					clpSolver->swapModelPtr(saveLpSolver);
					delete lpSolver;
					lpSolver=saveLpSolver;
					saveLpSolver=NULL;
				      }
				    }
                                } else {
                                    // special format suitable for OsiRowCutDebugger
                                    int n = 0;
                                    bool comma = false;
                                    bool newLine = false;
                                    fprintf(fp, "\tint intIndicesV[]={\n");
                                    for (iColumn = 0; iColumn < numberColumns; iColumn++) {
                                        if (primalColumnSolution[iColumn] > 0.5 && model_.solver()->isInteger(iColumn)) {
                                            if (comma)
                                                fprintf(fp, ",");
                                            if (newLine)
                                                fprintf(fp, "\n");
                                            fprintf(fp, "%d ", iColumn);
                                            comma = true;
                                            newLine = false;
                                            n++;
                                            if (n == 10) {
                                                n = 0;
                                                newLine = true;
                                            }
                                        }
                                    }
                                    fprintf(fp, "};\n");
                                    n = 0;
                                    comma = false;
                                    newLine = false;
                                    fprintf(fp, "\tdouble intSolnV[]={\n");
                                    for ( iColumn = 0; iColumn < numberColumns; iColumn++) {
                                        if (primalColumnSolution[iColumn] > 0.5 && model_.solver()->isInteger(iColumn)) {
                                            if (comma)
                                                fprintf(fp, ",");
                                            if (newLine)
                                                fprintf(fp, "\n");
                                            int value = static_cast<int> (primalColumnSolution[iColumn] + 0.5);
                                            fprintf(fp, "%d. ", value);
                                            comma = true;
                                            newLine = false;
                                            n++;
                                            if (n == 10) {
                                                n = 0;
                                                newLine = true;
                                            }
                                        }
                                    }
                                    fprintf(fp, "};\n");
                                }
                                if (fp != stdout)
                                    fclose(fp);
                                if (masks) {
                                    delete [] maskStarts;
                                    for (int i = 0; i < maxMasks; i++)
                                        delete [] masks[i];
                                    delete [] masks;
                                }
                            } else {
			      sprintf(generalPrint, "Unable to open file %s",fileName.c_str());
			      printGeneralMessage(model_,generalPrint);
                            }
                        } else {
			  sprintf(generalPrint, "** Current model not valid");
			  printGeneralMessage(model_,generalPrint);
                        }
                        break;
                    case CLP_PARAM_ACTION_SAVESOL:
                        if (goodModel) {
                            // get next field
                            field = CoinReadGetString(argc, argv);
                            if (field == "$") {
                                field = parameters_[iParam].stringValue();
                            } else if (field == "EOL") {
                                parameters_[iParam].printString();
                                break;
                            } else {
                                parameters_[iParam].setStringValue(field);
                            }
                            std::string fileName;
                            if (field[0] == '/' || field[0] == '\\') {
                                fileName = field;
                            } else if (field[0] == '~') {
                                char * environVar = getenv("HOME");
                                if (environVar) {
                                    std::string home(environVar);
                                    field = field.erase(0, 1);
                                    fileName = home + field;
                                } else {
                                    fileName = field;
                                }
                            } else {
                                fileName = directory + field;
                            }
                            saveSolution(lpSolver, fileName);
                        } else {
			  sprintf(generalPrint, "** Current model not valid");
			  printGeneralMessage(model_,generalPrint);
                        }
                        break;
                    case CLP_PARAM_ACTION_DUMMY:
                        break;
                    case CLP_PARAM_ACTION_ENVIRONMENT:
                        CbcOrClpEnvironmentIndex = 0;
                        break;
                    case CLP_PARAM_ACTION_PARAMETRICS:
                          if (goodModel) {
                               // get next field
                               field = CoinReadGetString(argc, argv);
                               if (field == "$") {
                                    field = parameters_[iParam].stringValue();
                               } else if (field == "EOL") {
                                    parameters_[iParam].printString();
                                    break;
                               } else {
                                    parameters_[iParam].setStringValue(field);
                               }
                               std::string fileName;
                               //bool canOpen = false;
                               if (field[0] == '/' || field[0] == '\\') {
                                    fileName = field;
                               } else if (field[0] == '~') {
                                    char * environVar = getenv("HOME");
                                    if (environVar) {
                                         std::string home(environVar);
                                         field = field.erase(0, 1);
                                         fileName = home + field;
                                    } else {
                                         fileName = field;
                                    }
                               } else {
                                    fileName = directory + field;
                               }
			       static_cast<ClpSimplexOther *> (lpSolver)->parametrics(fileName.c_str());
			       time2 = CoinCpuTime();
			       totalTime += time2 - time1;
			       time1 = time2;
                          } else {
			    sprintf(generalPrint, "** Current model not valid");
			    printGeneralMessage(model_,generalPrint);
                          }
                          break;
                    default:
                        abort();
                    }
                }
            } else if (!numberMatches) {
                std::cout << "No match for " << field << " - ? for list of commands"
                          << std::endl;
            } else if (numberMatches == 1) {
                if (!numberQuery) {
                    std::cout << "Short match for " << field << " - completion: ";
                    std::cout << parameters_[firstMatch].matchName() << std::endl;
                } else if (numberQuery) {
                    std::cout << parameters_[firstMatch].matchName() << " : ";
                    std::cout << parameters_[firstMatch].shortHelp() << std::endl;
                    if (numberQuery >= 2)
                        parameters_[firstMatch].printLongHelp();
                }
            } else {
                if (!numberQuery)
                    std::cout << "Multiple matches for " << field << " - possible completions:"
                              << std::endl;
                else
                    std::cout << "Completions of " << field << ":" << std::endl;
                for ( iParam = 0; iParam < numberParameters_; iParam++ ) {
                    int match = parameters_[iParam].matches(field);
                    if (match && parameters_[iParam].displayThis()) {
                        std::cout << parameters_[iParam].matchName();
                        if (numberQuery >= 2)
                            std::cout << " : " << parameters_[iParam].shortHelp();
                        std::cout << std::endl;
                    }
                }
            }
        }
    }
#if CBC_QUIET == 0
    sprintf(generalPrint ,
	    "Total time (CPU seconds):       %.2f   (Wallclock seconds):       %.2f\n", 
	    CoinCpuTime() - time0,
	    CoinGetTimeOfDay() - time0Elapsed);
    generalMessageHandler->message(CLP_GENERAL, generalMessages)
      << generalPrint
      << CoinMessageEol;
#endif
#ifdef COIN_HAS_GLPK
    if (cbc_glp_prob) {
      // free up as much as possible
      glp_free(cbc_glp_prob);
      glp_mpl_free_wksp(cbc_glp_tran);
      glp_free_env(); 
      cbc_glp_prob = NULL;
      cbc_glp_tran = NULL;
    }
#endif
    if (statistics_number_cuts != NULL)
        delete [] statistics_number_cuts;
    delete [] statistics_name_generators;
    // By now all memory should be freed
#ifdef DMALLOC
    //dmalloc_log_unfreed();
    //dmalloc_shutdown();
#endif
    if (babModel_) {
        model_.moveInfo(*babModel_);
#ifndef CBC_OTHER_SOLVER
        OsiClpSolverInterface * clpSolver0 = dynamic_cast< OsiClpSolverInterface*> (babModel_->solver());
        ClpSimplex * lpSolver0 = clpSolver0->getModelPtr();
        OsiClpSolverInterface * clpSolver = dynamic_cast< OsiClpSolverInterface*> (model_.solver());
        ClpSimplex * lpSolver = clpSolver->getModelPtr();
        if (lpSolver0 != lpSolver && lpSolver != originalSolver->getModelPtr())
            lpSolver->moveInfo(*lpSolver0);
        //babModel_->setModelOwnsSolver(false);
#endif
    }
#ifdef CBC_SIG_TRAP
    // On Sun sometimes seems to be error - try and get round it
    CoinSighandler_t saveSignal = SIG_DFL;
    // register signal handler
    saveSignal = signal(SIGSEGV, signal_handler_error);
    // to force failure!babModel_->setNumberObjects(20000);
    if (!sigsetjmp(cbc_seg_buffer, 1)) {
#endif
        delete babModel_;
#ifdef CBC_SIG_TRAP
    } else {
        std::cerr << "delete babModel_ failed" << std::endl;
    }
#endif
    babModel_ = NULL;
    model_.solver()->setWarmStart(NULL);
    //sprintf(generalPrint, "Total time %.2f", CoinCpuTime() - time0);
    //generalMessageHandler->message(CLP_GENERAL, generalMessages)
    //<< generalPrint
    //<< CoinMessageEol;
    return 0;
}



int CbcMain (int argc, const char *argv[],
             CbcModel  & model)
{
    CbcMain0(model);
    return CbcMain1(argc, argv, model);
}

void CbcMain0 (CbcModel  & model)
{
  CbcMain0(model,staticParameterData);
}
void CbcMain0 (CbcModel  & model,
	       CbcSolverUsefulData & parameterData)
{
    CbcOrClpParam * parameters = parameterData.parameters_;
    int numberParameters = parameterData.numberParameters_;
#ifndef CBC_OTHER_SOLVER
    OsiClpSolverInterface * originalSolver = dynamic_cast<OsiClpSolverInterface *> (model.solver());
#elif CBC_OTHER_SOLVER==1
    OsiCpxSolverInterface * originalSolver = dynamic_cast<OsiCpxSolverInterface *> (model.solver());
    // Dummy solvers
    OsiClpSolverInterface dummySolver;
    ClpSimplex * lpSolver = dummySolver.getModelPtr();
    OsiCpxSolverInterface * clpSolver = originalSolver;
#endif
    assert (originalSolver);
    CoinMessageHandler * generalMessageHandler = originalSolver->messageHandler();
    generalMessageHandler->setPrefix(true);
#ifndef CBC_OTHER_SOLVER
    OsiSolverInterface * solver = model.solver();
    OsiClpSolverInterface * clpSolver = dynamic_cast< OsiClpSolverInterface*> (solver);
    ClpSimplex * lpSolver = clpSolver->getModelPtr();
    lpSolver->setPerturbation(50);
    lpSolver->messageHandler()->setPrefix(false);
#endif
    //establishParams(numberParameters, parameters) ;
    const char dirsep =  CoinFindDirSeparator();
    std::string directory;
    std::string dirSample;
    std::string dirNetlib;
    std::string dirMiplib;
    if (dirsep == '/') {
        directory = "./";
        dirSample = "../../Data/Sample/";
        dirNetlib = "../../Data/Netlib/";
        dirMiplib = "../../Data/miplib3/";
    } else {
        directory = ".\\";
        dirSample = "..\\..\\..\\..\\Data\\Sample\\";
        dirNetlib = "..\\..\\..\\..\\Data\\Netlib\\";
        dirMiplib = "..\\..\\..\\..\\Data\\miplib3\\";
    }
    std::string defaultDirectory = directory;
    std::string importFile = "";
    std::string exportFile = "default.mps";
    std::string importBasisFile = "";
    std::string importPriorityFile = "";
    std::string debugFile = "";
    std::string printMask = "";
    std::string exportBasisFile = "default.bas";
    std::string saveFile = "default.prob";
    std::string restoreFile = "default.prob";
    std::string solutionFile = "stdout";
    std::string solutionSaveFile = "solution.file";
    int doIdiot = -1;
    int outputFormat = 2;
    int substitution = 3;
    int dualize = 3;
    int preSolve = 5;
    int doSprint = -1;
    int testOsiParameters = -1;
    parameters[whichParam(CLP_PARAM_ACTION_BASISIN, numberParameters, parameters)].setStringValue(importBasisFile);
    parameters[whichParam(CBC_PARAM_ACTION_PRIORITYIN, numberParameters, parameters)].setStringValue(importPriorityFile);
    parameters[whichParam(CLP_PARAM_ACTION_BASISOUT, numberParameters, parameters)].setStringValue(exportBasisFile);
    parameters[whichParam(CLP_PARAM_ACTION_DEBUG, numberParameters, parameters)].setStringValue(debugFile);
    parameters[whichParam(CLP_PARAM_ACTION_PRINTMASK, numberParameters, parameters)].setStringValue(printMask);
    parameters[whichParam(CLP_PARAM_ACTION_DIRECTORY, numberParameters, parameters)].setStringValue(directory);
    parameters[whichParam(CLP_PARAM_ACTION_DIRSAMPLE, numberParameters, parameters)].setStringValue(dirSample);
    parameters[whichParam(CLP_PARAM_ACTION_DIRNETLIB, numberParameters, parameters)].setStringValue(dirNetlib);
    parameters[whichParam(CBC_PARAM_ACTION_DIRMIPLIB, numberParameters, parameters)].setStringValue(dirMiplib);
    parameters[whichParam(CLP_PARAM_DBL_DUALBOUND, numberParameters, parameters)].setDoubleValue(lpSolver->dualBound());
    parameters[whichParam(CLP_PARAM_DBL_DUALTOLERANCE, numberParameters, parameters)].setDoubleValue(lpSolver->dualTolerance());
    parameters[whichParam(CLP_PARAM_ACTION_EXPORT, numberParameters, parameters)].setStringValue(exportFile);
    parameters[whichParam(CLP_PARAM_INT_IDIOT, numberParameters, parameters)].setIntValue(doIdiot);
    parameters[whichParam(CLP_PARAM_ACTION_IMPORT, numberParameters, parameters)].setStringValue(importFile);
    parameters[whichParam(CLP_PARAM_DBL_PRESOLVETOLERANCE, numberParameters, parameters)].setDoubleValue(1.0e-8);
    int slog = whichParam(CLP_PARAM_INT_SOLVERLOGLEVEL, numberParameters, parameters);
    int log = whichParam(CLP_PARAM_INT_LOGLEVEL, numberParameters, parameters);
    parameters[slog].setIntValue(1);
    clpSolver->messageHandler()->setLogLevel(1) ;
    model.messageHandler()->setLogLevel(1);
    lpSolver->setLogLevel(1);
    parameters[log].setIntValue(1);
    parameters[whichParam(CLP_PARAM_INT_MAXFACTOR, numberParameters, parameters)].setIntValue(lpSolver->factorizationFrequency());
    parameters[whichParam(CLP_PARAM_INT_MAXITERATION, numberParameters, parameters)].setIntValue(lpSolver->maximumIterations());
    parameters[whichParam(CLP_PARAM_INT_OUTPUTFORMAT, numberParameters, parameters)].setIntValue(outputFormat);
    parameters[whichParam(CLP_PARAM_INT_PRESOLVEPASS, numberParameters, parameters)].setIntValue(preSolve);
    parameters[whichParam(CLP_PARAM_INT_PERTVALUE, numberParameters, parameters)].setIntValue(lpSolver->perturbation());
    parameters[whichParam(CLP_PARAM_DBL_PRIMALTOLERANCE, numberParameters, parameters)].setDoubleValue(lpSolver->primalTolerance());
    parameters[whichParam(CLP_PARAM_DBL_PRIMALWEIGHT, numberParameters, parameters)].setDoubleValue(lpSolver->infeasibilityCost());
    parameters[whichParam(CLP_PARAM_ACTION_RESTORE, numberParameters, parameters)].setStringValue(restoreFile);
    parameters[whichParam(CLP_PARAM_ACTION_SAVE, numberParameters, parameters)].setStringValue(saveFile);
    //parameters[whichParam(CLP_PARAM_DBL_TIMELIMIT,numberParameters,parameters)].setDoubleValue(1.0e8);
    parameters[whichParam(CBC_PARAM_DBL_TIMELIMIT_BAB, numberParameters, parameters)].setDoubleValue(1.0e8);
    parameters[whichParam(CLP_PARAM_ACTION_SOLUTION, numberParameters, parameters)].setStringValue(solutionFile);
    parameters[whichParam(CLP_PARAM_ACTION_NEXTBESTSOLUTION, numberParameters, parameters)].setStringValue(solutionFile);
    parameters[whichParam(CLP_PARAM_ACTION_SAVESOL, numberParameters, parameters)].setStringValue(solutionSaveFile);
    parameters[whichParam(CLP_PARAM_INT_SPRINT, numberParameters, parameters)].setIntValue(doSprint);
    parameters[whichParam(CLP_PARAM_INT_SUBSTITUTION, numberParameters, parameters)].setIntValue(substitution);
    parameters[whichParam(CLP_PARAM_INT_DUALIZE, numberParameters, parameters)].setIntValue(dualize);
    model.setNumberBeforeTrust(10);
    parameters[whichParam(CBC_PARAM_INT_NUMBERBEFORE, numberParameters, parameters)].setIntValue(5);
    parameters[whichParam(CBC_PARAM_INT_MAXNODES, numberParameters, parameters)].setIntValue(model.getMaximumNodes());
    model.setNumberStrong(5);
    parameters[whichParam(CBC_PARAM_INT_STRONGBRANCHING, numberParameters, parameters)].setIntValue(model.numberStrong());
    parameters[whichParam(CBC_PARAM_DBL_INFEASIBILITYWEIGHT, numberParameters, parameters)].setDoubleValue(model.getDblParam(CbcModel::CbcInfeasibilityWeight));
    parameters[whichParam(CBC_PARAM_DBL_INTEGERTOLERANCE, numberParameters, parameters)].setDoubleValue(model.getDblParam(CbcModel::CbcIntegerTolerance));
    parameters[whichParam(CBC_PARAM_DBL_INCREMENT, numberParameters, parameters)].setDoubleValue(model.getDblParam(CbcModel::CbcCutoffIncrement));
    parameters[whichParam(CBC_PARAM_INT_TESTOSI, numberParameters, parameters)].setIntValue(testOsiParameters);
    parameters[whichParam(CBC_PARAM_INT_FPUMPTUNE, numberParameters, parameters)].setIntValue(1003);
    initialPumpTune = 1003;
#ifdef CBC_THREAD
    parameters[whichParam(CBC_PARAM_INT_THREADS, numberParameters, parameters)].setIntValue(0);
#endif
    // Set up likely cut generators and defaults
    parameters[whichParam(CBC_PARAM_STR_PREPROCESS, numberParameters, parameters)].setCurrentOption("sos");
    parameters[whichParam(CBC_PARAM_INT_MIPOPTIONS, numberParameters, parameters)].setIntValue(1057);
    parameters[whichParam(CBC_PARAM_INT_CUTPASSINTREE, numberParameters, parameters)].setIntValue(1);
    parameters[whichParam(CBC_PARAM_INT_MOREMIPOPTIONS, numberParameters, parameters)].setIntValue(-1);
    parameters[whichParam(CBC_PARAM_INT_MAXHOTITS, numberParameters, parameters)].setIntValue(100);
    parameters[whichParam(CBC_PARAM_STR_CUTSSTRATEGY, numberParameters, parameters)].setCurrentOption("on");
    parameters[whichParam(CBC_PARAM_STR_HEURISTICSTRATEGY, numberParameters, parameters)].setCurrentOption("on");
    parameters[whichParam(CBC_PARAM_STR_NODESTRATEGY, numberParameters, parameters)].setCurrentOption("fewest");
    parameters[whichParam(CBC_PARAM_STR_GOMORYCUTS, numberParameters, parameters)].setCurrentOption("ifmove");
    parameters[whichParam(CBC_PARAM_STR_PROBINGCUTS, numberParameters, parameters)].setCurrentOption("ifmove");
    parameters[whichParam(CBC_PARAM_STR_KNAPSACKCUTS, numberParameters, parameters)].setCurrentOption("ifmove");
    parameters[whichParam(CBC_PARAM_STR_ZEROHALFCUTS, numberParameters, parameters)].setCurrentOption("off");
    parameters[whichParam(CBC_PARAM_STR_REDSPLITCUTS, numberParameters, parameters)].setCurrentOption("off");
    parameters[whichParam(CBC_PARAM_STR_REDSPLIT2CUTS, numberParameters, parameters)].setCurrentOption("off");
    parameters[whichParam(CBC_PARAM_STR_GMICUTS, numberParameters, parameters)].setCurrentOption("off");
    parameters[whichParam(CBC_PARAM_STR_CLIQUECUTS, numberParameters, parameters)].setCurrentOption("ifmove");
    parameters[whichParam(CBC_PARAM_STR_MIXEDCUTS, numberParameters, parameters)].setCurrentOption("ifmove");
    parameters[whichParam(CBC_PARAM_STR_FLOWCUTS, numberParameters, parameters)].setCurrentOption("ifmove");
    parameters[whichParam(CBC_PARAM_STR_TWOMIRCUTS, numberParameters, parameters)].setCurrentOption("root");
    parameters[whichParam(CBC_PARAM_STR_LANDPCUTS, numberParameters, parameters)].setCurrentOption("off");
    parameters[whichParam(CBC_PARAM_STR_RESIDCUTS, numberParameters, parameters)].setCurrentOption("off");
    parameters[whichParam(CBC_PARAM_STR_ROUNDING, numberParameters, parameters)].setCurrentOption("on");
    parameters[whichParam(CBC_PARAM_STR_FPUMP, numberParameters, parameters)].setCurrentOption("on");
    parameters[whichParam(CBC_PARAM_STR_GREEDY, numberParameters, parameters)].setCurrentOption("on");
    parameters[whichParam(CBC_PARAM_STR_COMBINE, numberParameters, parameters)].setCurrentOption("off");
    parameters[whichParam(CBC_PARAM_STR_CROSSOVER2, numberParameters, parameters)].setCurrentOption("off");
    parameters[whichParam(CBC_PARAM_STR_PIVOTANDCOMPLEMENT, numberParameters, parameters)].setCurrentOption("off");
    parameters[whichParam(CBC_PARAM_STR_PIVOTANDFIX, numberParameters, parameters)].setCurrentOption("off");
    parameters[whichParam(CBC_PARAM_STR_RANDROUND, numberParameters, parameters)].setCurrentOption("off");
    parameters[whichParam(CBC_PARAM_STR_NAIVE, numberParameters, parameters)].setCurrentOption("off");
    parameters[whichParam(CBC_PARAM_STR_RINS, numberParameters, parameters)].setCurrentOption("off");
    parameters[whichParam(CBC_PARAM_STR_DINS, numberParameters, parameters)].setCurrentOption("off");
    parameters[whichParam(CBC_PARAM_STR_RENS, numberParameters, parameters)].setCurrentOption("off");
    parameters[whichParam(CBC_PARAM_STR_LOCALTREE, numberParameters, parameters)].setCurrentOption("off");
    parameters[whichParam(CBC_PARAM_STR_COSTSTRATEGY, numberParameters, parameters)].setCurrentOption("off");
}

/*
  Routines to print statistics.
*/
static void breakdown(const char * name, int numberLook, const double * region)
{
    double range[] = {
        -COIN_DBL_MAX,
        -1.0e15, -1.0e11, -1.0e8, -1.0e5, -1.0e4, -1.0e3, -1.0e2, -1.0e1,
        -1.0,
        -1.0e-1, -1.0e-2, -1.0e-3, -1.0e-4, -1.0e-5, -1.0e-8, -1.0e-11, -1.0e-15,
        0.0,
        1.0e-15, 1.0e-11, 1.0e-8, 1.0e-5, 1.0e-4, 1.0e-3, 1.0e-2, 1.0e-1,
        1.0,
        1.0e1, 1.0e2, 1.0e3, 1.0e4, 1.0e5, 1.0e8, 1.0e11, 1.0e15,
        COIN_DBL_MAX
    };
    int nRanges = static_cast<int> (sizeof(range) / sizeof(double));
    int * number = new int[nRanges];
    memset(number, 0, nRanges*sizeof(int));
    int * numberExact = new int[nRanges];
    memset(numberExact, 0, nRanges*sizeof(int));
    int i;
    for ( i = 0; i < numberLook; i++) {
        double value = region[i];
        for (int j = 0; j < nRanges; j++) {
            if (value == range[j]) {
                numberExact[j]++;
                break;
            } else if (value < range[j]) {
                number[j]++;
                break;
            }
        }
    }
    printf("\n%s has %d entries\n", name, numberLook);
    for (i = 0; i < nRanges; i++) {
        if (number[i])
            printf("%d between %g and %g", number[i], range[i-1], range[i]);
        if (numberExact[i]) {
            if (number[i])
                printf(", ");
            printf("%d exactly at %g", numberExact[i], range[i]);
        }
        if (number[i] + numberExact[i])
            printf("\n");
    }
    delete [] number;
    delete [] numberExact;
}
static void sortOnOther(int * column,
                 const CoinBigIndex * rowStart,
                 int * order,
                 int * other,
                 int nRow,
                 int nInRow,
                 int where)
{
     if (nRow < 2 || where >= nInRow)
          return;
     // do initial sort
     int kRow;
     int iRow;
     for ( kRow = 0; kRow < nRow; kRow++) {
          iRow = order[kRow];
          other[kRow] = column[rowStart[iRow] + where];
     }
     CoinSort_2(other, other + nRow, order);
     int first = 0;
     iRow = order[0];
     int firstC = column[rowStart[iRow] + where];
     kRow = 1;
     while (kRow < nRow) {
          int lastC = 9999999;;
          for (; kRow < nRow + 1; kRow++) {
               if (kRow < nRow) {
                    iRow = order[kRow];
                    lastC = column[rowStart[iRow] + where];
               } else {
                    lastC = 9999999;
               }
               if (lastC > firstC)
                    break;
          }
          // sort
          sortOnOther(column, rowStart, order + first, other, kRow - first,
                      nInRow, where + 1);
          firstC = lastC;
          first = kRow;
     }
}
static void statistics(ClpSimplex * originalModel, ClpSimplex * model)
{
     int numberColumns = originalModel->numberColumns();
     const char * integerInformation  = originalModel->integerInformation();
     const double * columnLower = originalModel->columnLower();
     const double * columnUpper = originalModel->columnUpper();
     int numberIntegers = 0;
     int numberBinary = 0;
     int iRow, iColumn;
     if (integerInformation) {
          for (iColumn = 0; iColumn < numberColumns; iColumn++) {
               if (integerInformation[iColumn]) {
                    if (columnUpper[iColumn] > columnLower[iColumn]) {
                         numberIntegers++;
                         if (columnLower[iColumn] == 0.0 && columnUpper[iColumn] == 1)
                              numberBinary++;
                    }
               }
          }
	  printf("Original problem has %d integers (%d of which binary)\n",
		 numberIntegers,numberBinary);
     }
     numberColumns = model->numberColumns();
     int numberRows = model->numberRows();
     columnLower = model->columnLower();
     columnUpper = model->columnUpper();
     const double * rowLower = model->rowLower();
     const double * rowUpper = model->rowUpper();
     const double * objective = model->objective();
     if (model->integerInformation()) {
       const char * integerInformation  = model->integerInformation();
       int numberIntegers = 0;
       int numberBinary = 0;
       double * obj = new double [numberColumns];
       int * which = new int [numberColumns];
       for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
	 if (columnUpper[iColumn] > columnLower[iColumn]) {
	   if (integerInformation[iColumn]) {
	     numberIntegers++;
	     if (columnLower[iColumn] == 0.0 && columnUpper[iColumn] == 1)
	       numberBinary++;
	   }
	 }
       }
       if(numberColumns != originalModel->numberColumns())
	 printf("Presolved problem has %d integers (%d of which binary)\n",
		numberIntegers,numberBinary);
       for (int ifInt=0;ifInt<2;ifInt++) {
	 for (int ifAbs=0;ifAbs<2;ifAbs++) {
	   int numberSort=0;
	   int numberZero=0;
	   int numberDifferentObj=0;
	   for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
	     if (columnUpper[iColumn] > columnLower[iColumn]) {
	       if (!ifInt||integerInformation[iColumn]) {
		 obj[numberSort]=(ifAbs) ? fabs(objective[iColumn]) :
		   objective[iColumn];
		 which[numberSort++]=iColumn;
		 if (!objective[iColumn])
		   numberZero++;
	       }
	     }
	   }
	   CoinSort_2(obj,obj+numberSort,which);
	   double last=obj[0];
	   for (int jColumn = 1; jColumn < numberSort; jColumn++) {
	     if (fabs(obj[jColumn]-last)>1.0e-12) {
	       numberDifferentObj++;
	       last=obj[jColumn];
	     }
	   }
	   numberDifferentObj++;
	   printf("==== ");
	   if (ifInt)
	     printf("for integers ");
	   if (!ifAbs)
	     printf("%d zero objective ",numberZero);
	   else
	     printf("absolute objective values ");
	   printf("%d different\n",numberDifferentObj);
	   bool saveModel=false;
	   int target=model->logLevel();
	   if (target>10000) {
	     if (ifInt&&!ifAbs)
	       saveModel=true;
	     target-=10000;
	   }

	   if (target<=100)
	     target=12;
	   else
	     target-=100;
	   if (numberDifferentObj<target) {
	     int iLast=0;
	     double last=obj[0];
	     for (int jColumn = 1; jColumn < numberSort; jColumn++) {
	       if (fabs(obj[jColumn]-last)>1.0e-12) {
		 printf("%d variables have objective of %g\n",
			jColumn-iLast,last);
		 iLast=jColumn;
		 last=obj[jColumn];
	       }
	     }
	     printf("%d variables have objective of %g\n",
		    numberSort-iLast,last);
	     if (saveModel) {
	       int spaceNeeded=numberSort+numberDifferentObj;
	       int * columnAdd = new int[spaceNeeded+numberDifferentObj+1];
	       double * elementAdd = new double[spaceNeeded];
	       int * rowAdd = new int[2*numberDifferentObj+1];
	       int * newIsInteger = rowAdd+numberDifferentObj+1;
	       double * objectiveNew = new double[3*numberDifferentObj];
	       double * lowerNew = objectiveNew+numberDifferentObj;
	       double * upperNew = lowerNew+numberDifferentObj;
	       memset(columnAdd+spaceNeeded,0,
		      (numberDifferentObj+1)*sizeof(int));
	       ClpSimplex tempModel=*model;
	       int iLast=0;
	       double last=obj[0];
	       numberDifferentObj=0;
	       int numberElements=0;
	       rowAdd[0]=0;
	       double * objective = tempModel.objective();
	       for (int jColumn = 1; jColumn < numberSort+1; jColumn++) {
		 if (jColumn==numberSort||fabs(obj[jColumn]-last)>1.0e-12) {
		   // not if just one
		   if (jColumn-iLast>1) {
		     bool allInteger=integerInformation!=NULL;
		     int iColumn=which[iLast];
		     objectiveNew[numberDifferentObj]=objective[iColumn];
		     double lower=0.0;
		     double upper=0.0;
		     for (int kColumn=iLast;kColumn<jColumn;kColumn++) {
		       iColumn=which[kColumn];
		       objective[iColumn]=0.0;
		       double lowerValue=columnLower[iColumn];
		       double upperValue=columnUpper[iColumn];
		       double elementValue=-1.0;
		       if (objectiveNew[numberDifferentObj]*objective[iColumn]<0.0) {
			 lowerValue=-columnUpper[iColumn];
			 upperValue=-columnLower[iColumn];
			 elementValue=1.0;
		       }
		       columnAdd[numberElements]=iColumn;
		       elementAdd[numberElements++]=elementValue;
		       if (integerInformation&&!integerInformation[iColumn])
			 allInteger=false;
		       if (lower!=-COIN_DBL_MAX) {
			 if (lowerValue!=-COIN_DBL_MAX)
			   lower += lowerValue;
			 else
			   lower=-COIN_DBL_MAX;
		       }
		       if (upper!=COIN_DBL_MAX) {
			 if (upperValue!=COIN_DBL_MAX)
			   upper += upperValue;
			 else
			   upper=COIN_DBL_MAX;
		       }
		     }
		     columnAdd[numberElements]=numberColumns+numberDifferentObj;
		     elementAdd[numberElements++]=1.0;
		     newIsInteger[numberDifferentObj]= (allInteger) ? 1 : 0;
		     lowerNew[numberDifferentObj]=lower;
		     upperNew[numberDifferentObj]=upper;
		     numberDifferentObj++;
		     rowAdd[numberDifferentObj]=numberElements;
		   }
		   iLast=jColumn;
		   last=obj[jColumn];
		 }
	       }
	       // add columns
	       tempModel.addColumns(numberDifferentObj, lowerNew, upperNew,
				    objectiveNew,
				    columnAdd+spaceNeeded, NULL, NULL);
	       // add constraints and make integer if all integer in group
	       for (int iObj=0; iObj < numberDifferentObj; iObj++) {
		 lowerNew[iObj]=0.0;
		 upperNew[iObj]=0.0;
		 if (newIsInteger[iObj])
		   tempModel.setInteger(numberColumns+iObj);
	       }
	       tempModel.addRows(numberDifferentObj, lowerNew, upperNew,
				 rowAdd,columnAdd,elementAdd);
	       delete [] columnAdd;
	       delete [] elementAdd;
	       delete [] rowAdd;
	       delete [] objectiveNew;
	       // save
	       std::string tempName = model->problemName();
	       if (ifInt)
		 tempName += "_int";
	       if (ifAbs)
		 tempName += "_abs";
	       tempName += ".mps";
	       tempModel.writeMps(tempName.c_str());
	     }
	   }
	 }
       }
       delete [] which;
       delete [] obj;
       printf("===== end objective counts\n");
     }
     CoinPackedMatrix * matrix = model->matrix();
     CoinBigIndex numberElements = matrix->getNumElements();
     const int * columnLength = matrix->getVectorLengths();
     //const CoinBigIndex * columnStart = matrix->getVectorStarts();
     const double * elementByColumn = matrix->getElements();
     int * number = new int[numberRows+1];
     memset(number, 0, (numberRows + 1)*sizeof(int));
     int numberObjSingletons = 0;
     /* cType
        0 0/inf, 1 0/up, 2 lo/inf, 3 lo/up, 4 free, 5 fix, 6 -inf/0, 7 -inf/up,
        8 0/1
     */
     int cType[9];
     std::string cName[] = {"0.0->inf,", "0.0->up,", "lo->inf,", "lo->up,", "free,", "fixed,", "-inf->0.0,",
                            "-inf->up,", "0.0->1.0"
                           };
     int nObjective = 0;
     memset(cType, 0, sizeof(cType));
     for (iColumn = 0; iColumn < numberColumns; iColumn++) {
          int length = columnLength[iColumn];
          if (length == 1 && objective[iColumn])
               numberObjSingletons++;
          number[length]++;
          if (objective[iColumn])
               nObjective++;
          if (columnLower[iColumn] > -1.0e20) {
               if (columnLower[iColumn] == 0.0) {
                    if (columnUpper[iColumn] > 1.0e20)
                         cType[0]++;
                    else if (columnUpper[iColumn] == 1.0)
                         cType[8]++;
                    else if (columnUpper[iColumn] == 0.0)
                         cType[5]++;
                    else
                         cType[1]++;
               } else {
                    if (columnUpper[iColumn] > 1.0e20)
                         cType[2]++;
                    else if (columnUpper[iColumn] == columnLower[iColumn])
                         cType[5]++;
                    else
                         cType[3]++;
               }
          } else {
               if (columnUpper[iColumn] > 1.0e20)
                    cType[4]++;
               else if (columnUpper[iColumn] == 0.0)
                    cType[6]++;
               else
                    cType[7]++;
          }
     }
     /* rType
        0 E 0, 1 E 1, 2 E -1, 3 E other, 4 G 0, 5 G 1, 6 G other,
        7 L 0,  8 L 1, 9 L other, 10 Range 0/1, 11 Range other, 12 free
     */
     int rType[13];
     std::string rName[] = {"E 0.0,", "E 1.0,", "E -1.0,", "E other,", "G 0.0,", "G 1.0,", "G other,",
                            "L 0.0,", "L 1.0,", "L other,", "Range 0.0->1.0,", "Range other,", "Free"
                           };
     memset(rType, 0, sizeof(rType));
     for (iRow = 0; iRow < numberRows; iRow++) {
          if (rowLower[iRow] > -1.0e20) {
               if (rowLower[iRow] == 0.0) {
                    if (rowUpper[iRow] > 1.0e20)
                         rType[4]++;
                    else if (rowUpper[iRow] == 1.0)
                         rType[10]++;
                    else if (rowUpper[iRow] == 0.0)
                         rType[0]++;
                    else
                         rType[11]++;
               } else if (rowLower[iRow] == 1.0) {
                    if (rowUpper[iRow] > 1.0e20)
                         rType[5]++;
                    else if (rowUpper[iRow] == rowLower[iRow])
                         rType[1]++;
                    else
                         rType[11]++;
               } else if (rowLower[iRow] == -1.0) {
                    if (rowUpper[iRow] > 1.0e20)
                         rType[6]++;
                    else if (rowUpper[iRow] == rowLower[iRow])
                         rType[2]++;
                    else
                         rType[11]++;
               } else {
                    if (rowUpper[iRow] > 1.0e20)
                         rType[6]++;
                    else if (rowUpper[iRow] == rowLower[iRow])
                         rType[3]++;
                    else
                         rType[11]++;
               }
          } else {
               if (rowUpper[iRow] > 1.0e20)
                    rType[12]++;
               else if (rowUpper[iRow] == 0.0)
                    rType[7]++;
               else if (rowUpper[iRow] == 1.0)
                    rType[8]++;
               else
                    rType[9]++;
          }
     }
     // Basic statistics
     printf("\n\nProblem has %d rows, %d columns (%d with objective) and %d elements\n",
            numberRows, numberColumns, nObjective, numberElements);
     if (number[0] + number[1]) {
          printf("There are ");
          if (numberObjSingletons)
               printf("%d singletons with objective ", numberObjSingletons);
          int numberNoObj = number[1] - numberObjSingletons;
          if (numberNoObj)
               printf("%d singletons with no objective ", numberNoObj);
          if (number[0])
               printf("** %d columns have no entries", number[0]);
          printf("\n");
     }
     printf("Column breakdown:\n");
     int k;
     for (k = 0; k < static_cast<int> (sizeof(cType) / sizeof(int)); k++) {
          printf("%d of type %s ", cType[k], cName[k].c_str());
          if (((k + 1) % 3) == 0)
               printf("\n");
     }
     if ((k % 3) != 0)
          printf("\n");
     printf("Row breakdown:\n");
     for (k = 0; k < static_cast<int> (sizeof(rType) / sizeof(int)); k++) {
          printf("%d of type %s ", rType[k], rName[k].c_str());
          if (((k + 1) % 3) == 0)
               printf("\n");
     }
     if ((k % 3) != 0)
          printf("\n");
     //#define SYM
#ifndef SYM
     if (model->logLevel() < 2)
          return ;
#endif
     int kMax = model->logLevel() > 3 ? 1000000 : 10;
     k = 0;
     for (iRow = 1; iRow <= numberRows; iRow++) {
          if (number[iRow]) {
               k++;
               printf("%d columns have %d entries\n", number[iRow], iRow);
               if (k == kMax)
                    break;
          }
     }
     if (k < numberRows) {
          int kk = k;
          k = 0;
          for (iRow = numberRows; iRow >= 1; iRow--) {
               if (number[iRow]) {
                    k++;
                    if (k == kMax)
                         break;
               }
          }
          if (k > kk) {
               printf("\n    .........\n\n");
               iRow = k;
               k = 0;
               for (; iRow < numberRows; iRow++) {
                    if (number[iRow]) {
                         k++;
                         printf("%d columns have %d entries\n", number[iRow], iRow);
                         if (k == kMax)
                              break;
                    }
               }
          }
     }
     delete [] number;
     printf("\n\n");
     if (model->logLevel() == 63
#ifdef SYM
               || true
#endif
        ) {
          // get column copy
          CoinPackedMatrix columnCopy = *matrix;
          const int * columnLength = columnCopy.getVectorLengths();
          number = new int[numberRows+1];
          memset(number, 0, (numberRows + 1)*sizeof(int));
          for (iColumn = 0; iColumn < numberColumns; iColumn++) {
               int length = columnLength[iColumn];
               number[length]++;
          }
          k = 0;
          for (iRow = 1; iRow <= numberRows; iRow++) {
               if (number[iRow]) {
                    k++;
               }
          }
          int * row = columnCopy.getMutableIndices();
          const CoinBigIndex * columnStart = columnCopy.getVectorStarts();
          double * element = columnCopy.getMutableElements();
          int * order = new int[numberColumns];
          int * other = new int[numberColumns];
          for (iColumn = 0; iColumn < numberColumns; iColumn++) {
               int length = columnLength[iColumn];
               order[iColumn] = iColumn;
               other[iColumn] = length;
               CoinBigIndex start = columnStart[iColumn];
               CoinSort_2(row + start, row + start + length, element + start);
          }
          CoinSort_2(other, other + numberColumns, order);
          int jColumn = number[0] + number[1];
          for (iRow = 2; iRow <= numberRows; iRow++) {
               if (number[iRow]) {
                    printf("XX %d columns have %d entries\n", number[iRow], iRow);
                    int kColumn = jColumn + number[iRow];
                    sortOnOther(row, columnStart,
                                order + jColumn, other, number[iRow], iRow, 0);
                    // Now print etc
                    if (iRow < 500000) {
                         for (int lColumn = jColumn; lColumn < kColumn; lColumn++) {
                              iColumn = order[lColumn];
                              CoinBigIndex start = columnStart[iColumn];
                              if (model->logLevel() == 63) {
                                   printf("column %d %g <= ", iColumn, columnLower[iColumn]);
                                   for (CoinBigIndex i = start; i < start + iRow; i++)
                                        printf("( %d, %g) ", row[i], element[i]);
                                   printf("<= %g\n", columnUpper[iColumn]);
                              }
                         }
                    }
                    jColumn = kColumn;
               }
          }
          delete [] order;
          delete [] other;
          delete [] number;
     }
     // get row copy
     CoinPackedMatrix rowCopy = *matrix;
     rowCopy.reverseOrdering();
     const int * rowLength = rowCopy.getVectorLengths();
     number = new int[numberColumns+1];
     memset(number, 0, (numberColumns + 1)*sizeof(int));
     if (model->logLevel() > 3) {
       // get column copy
       CoinPackedMatrix columnCopy = *matrix;
       const int * columnLength = columnCopy.getVectorLengths();
       const int * row = columnCopy.getIndices();
       const CoinBigIndex * columnStart = columnCopy.getVectorStarts();
       const double * element = columnCopy.getElements();
       const double * elementByRow = rowCopy.getElements();
       const int * rowStart = rowCopy.getVectorStarts();
       const int * column = rowCopy.getIndices();
       int nPossibleZeroCost=0;
       int nPossibleNonzeroCost=0;
       for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
	 int length = columnLength[iColumn];
	 if (columnLower[iColumn]<-1.0e30&&columnUpper[iColumn]>1.0e30) {
	   if (length==1) {
	     printf("Singleton free %d - cost %g\n",iColumn,objective[iColumn]);
	   } else if (length==2) {
	     int iRow0=row[columnStart[iColumn]];
	     int iRow1=row[columnStart[iColumn]+1];
	     double element0=element[columnStart[iColumn]];
	     double element1=element[columnStart[iColumn]+1];
	     int n0=rowLength[iRow0];
	     int n1=rowLength[iRow1];
	     printf("Doubleton free %d - cost %g - %g in %srow with %d entries and %g in %srow with %d entries\n",
		    iColumn,objective[iColumn],element0,(rowLower[iRow0]==rowUpper[iRow0]) ? "==" : "",n0,
		    element1,(rowLower[iRow1]==rowUpper[iRow1]) ? "==" : "",n1);

	   }
	 }
	 if (length==1) {
	   int iRow=row[columnStart[iColumn]];
	   double value=COIN_DBL_MAX;
	   for (int i=rowStart[iRow];i<rowStart[iRow]+rowLength[iRow];i++) {
	     int jColumn=column[i];
	     if (jColumn!=iColumn) {
	       if (value!=elementByRow[i]) {
		 if (value==COIN_DBL_MAX) {
		   value=elementByRow[i];
		 } else {
		   value = -COIN_DBL_MAX;
		   break;
		 }
	       }
	     }
	   }
	   if (!objective[iColumn]) {
	     if (model->logLevel() > 4) 
	     printf("Singleton %d with no objective in row with %d elements - rhs %g,%g\n",iColumn,rowLength[iRow],rowLower[iRow],rowUpper[iRow]);
	     nPossibleZeroCost++;
	   } else if (value!=-COIN_DBL_MAX) {
	     if (model->logLevel() > 4) 
	       printf("Singleton %d (%s) with objective in row %d (%s) with %d equal elements - rhs %g,%g\n",iColumn,model->getColumnName(iColumn).c_str(),
		      iRow,model->getRowName(iRow).c_str(),
		      rowLength[iRow],rowLower[iRow],rowUpper[iRow]);
	     nPossibleNonzeroCost++;
	   }
	 }
       }
       if (nPossibleZeroCost||nPossibleNonzeroCost)
	 printf("%d singletons with zero cost, %d with valid cost\n",
		nPossibleZeroCost,nPossibleNonzeroCost);
       // look for DW
       int * blockStart = new int [2*(numberRows+numberColumns)+1+numberRows];
       int * columnBlock = blockStart+numberRows;
       int * nextColumn = columnBlock+numberColumns;
       int * blockCount = nextColumn+numberColumns;
       int * blockEls = blockCount+numberRows+1;
       int direction[2]={-1,1};
       int bestBreak=-1;
       double bestValue=0.0;
       int iPass=0;
       int halfway=(numberRows+1)/2;
       int firstMaster=-1;
       int lastMaster=-2;
       while (iPass<2) {
	 int increment=direction[iPass];
	 int start= increment>0 ? 0 : numberRows-1;
	 int stop=increment>0 ? numberRows : -1;
	 int numberBlocks=0;
	 int thisBestBreak=-1;
	 double thisBestValue=COIN_DBL_MAX;
	 int numberRowsDone=0;
	 int numberMarkedColumns=0;
	 int maximumBlockSize=0;
	 for (int i=0;i<numberRows+2*numberColumns;i++) 
	   blockStart[i]=-1;
	 for (int i=0;i<numberRows+1;i++)
	   blockCount[i]=0;
	 for (int iRow=start;iRow!=stop;iRow+=increment) {
	   int iBlock = -1;
	   for (CoinBigIndex j=rowStart[iRow];j<rowStart[iRow]+rowLength[iRow];j++) {
	     int iColumn=column[j];
	     int whichColumnBlock=columnBlock[iColumn];
	     if (whichColumnBlock>=0) {
	       // column marked
	       if (iBlock<0) {
		 // put row in that block
		 iBlock=whichColumnBlock;
	       } else if (iBlock!=whichColumnBlock) {
		 // merge
		 blockCount[iBlock]+=blockCount[whichColumnBlock];
		 blockCount[whichColumnBlock]=0;
		 int jColumn=blockStart[whichColumnBlock];
		 while (jColumn>=0) {
		   columnBlock[jColumn]=iBlock;
		   iColumn=jColumn;
		   jColumn=nextColumn[jColumn];
		 }
		 nextColumn[iColumn]=blockStart[iBlock];
		 blockStart[iBlock]=blockStart[whichColumnBlock];
		 blockStart[whichColumnBlock]=-1;
	       }
	     }
	   }
	   int n=numberMarkedColumns;
	   if (iBlock<0) {
	     //new block
	     if (rowLength[iRow]) {
	       numberBlocks++;
	       iBlock=numberBlocks;
	       int jColumn=column[rowStart[iRow]];
	       columnBlock[jColumn]=iBlock;
	       blockStart[iBlock]=jColumn;
	       numberMarkedColumns++;
	       for (CoinBigIndex j=rowStart[iRow]+1;j<rowStart[iRow]+rowLength[iRow];j++) {
		 int iColumn=column[j];
		 columnBlock[iColumn]=iBlock;
		 numberMarkedColumns++;
		 nextColumn[jColumn]=iColumn;
		 jColumn=iColumn;
	       }
	       blockCount[iBlock]=numberMarkedColumns-n;
	     } else {
	       // empty
	       iBlock=numberRows;
	     }
	   } else {
	     // put in existing block
	     int jColumn=blockStart[iBlock];
	     for (CoinBigIndex j=rowStart[iRow];j<rowStart[iRow]+rowLength[iRow];j++) {
	       int iColumn=column[j];
	       assert (columnBlock[iColumn]<0||columnBlock[iColumn]==iBlock);
	       if (columnBlock[iColumn]<0) {
		 columnBlock[iColumn]=iBlock;
		 numberMarkedColumns++;
		 nextColumn[iColumn]=jColumn;
		 jColumn=iColumn;
	       }
	     }
	     blockStart[iBlock]=jColumn;
	     blockCount[iBlock]+=numberMarkedColumns-n;
	   }
	   maximumBlockSize=CoinMax(maximumBlockSize,blockCount[iBlock]);
	   numberRowsDone++;
	   if (thisBestValue*numberRowsDone > maximumBlockSize&&numberRowsDone>halfway) { 
	     thisBestBreak=iRow;
	     thisBestValue=static_cast<double>(maximumBlockSize)/
	       static_cast<double>(numberRowsDone);
	   }
	 }
	 if (thisBestBreak==stop)
	   thisBestValue=COIN_DBL_MAX;
	 iPass++;
	 if (iPass==1) {
	   bestBreak=thisBestBreak;
	   bestValue=thisBestValue;
	 } else {
	   if (bestValue<thisBestValue) {
	     firstMaster=0;
	     lastMaster=bestBreak;
	   } else {
	     firstMaster=thisBestBreak; // ? +1
	     lastMaster=numberRows;
	   }
	 }
       }
       if (firstMaster<lastMaster) {
	 printf("%d master rows %d <= < %d\n",lastMaster-firstMaster,
		firstMaster,lastMaster);
	 for (int i=0;i<numberRows+2*numberColumns;i++) 
	   blockStart[i]=-1;
	 for (int i=firstMaster;i<lastMaster;i++)
	   blockStart[i]=-2;
	 int firstRow=0;
	 int numberBlocks=-1;
	 while (true) {
	   for (;firstRow<numberRows;firstRow++) {
	     if (blockStart[firstRow]==-1)
	       break;
	   }
	   if (firstRow==numberRows)
	     break;
	   int nRows=0;
	   numberBlocks++;
	   int numberStack=1;
	   blockCount[0] = firstRow;
	   while (numberStack) {
	     int iRow=blockCount[--numberStack];
	     for (CoinBigIndex j=rowStart[iRow];j<rowStart[iRow]+rowLength[iRow];j++) {
	       int iColumn=column[j];
	       int iBlock=columnBlock[iColumn];
	       if (iBlock<0) {
		 columnBlock[iColumn]=numberBlocks;
		 for (CoinBigIndex k=columnStart[iColumn];
		      k<columnStart[iColumn]+columnLength[iColumn];k++) {
		   int jRow=row[k];
		   int rowBlock=blockStart[jRow];
		   if (rowBlock==-1) {
		     nRows++;
		     blockStart[jRow]=numberBlocks;
		     blockCount[numberStack++]=jRow;
		   }
		 }
	       }
	     }
	   }
	   if (!nRows) {
	     // empty!!
	     numberBlocks--;
	   }
	   firstRow++;
	 }
	 // adjust 
	 numberBlocks++;
	 for (int i=0;i<numberBlocks;i++) {
	   blockCount[i]=0;
	   nextColumn[i]=0;
	 }
	 int numberEmpty=0;
	 int numberMaster=0;
	 memset(blockEls,0,numberBlocks*sizeof(int));
	 for (int iRow = 0; iRow < numberRows; iRow++) {
	   int iBlock=blockStart[iRow];
	   if (iBlock>=0) {
	     blockCount[iBlock]++;
	     blockEls[iBlock]+=rowLength[iRow];
	   } else {
	     if (iBlock==-2)
	       numberMaster++;
	     else
	       numberEmpty++;
	   }
	 }
	 int numberEmptyColumns=0;
	 int numberMasterColumns=0;
	 for (int iColumn = 0; iColumn < numberColumns; iColumn++) {
	   int iBlock=columnBlock[iColumn];
	   if (iBlock>=0) {
	     nextColumn[iBlock]++;
	   } else {
	     if (columnLength[iColumn])
	       numberMasterColumns++;
	     else
	       numberEmptyColumns++;
	   }
	 }
	 int largestRows=0;
	 int largestColumns=0;
	 for (int i=0;i<numberBlocks;i++) {
	   if (blockCount[i]+nextColumn[i]>largestRows+largestColumns) {
	     largestRows=blockCount[i];
	     largestColumns=nextColumn[i];
	   }
	 }
	 bool useful=true;
	 if (numberMaster>halfway||largestRows*3>numberRows)
	   useful=false;
	 printf("%s %d blocks (largest %d,%d), %d master rows (%d empty) out of %d, %d master columns (%d empty) out of %d\n",
		useful ? "**Useful" : "NoGood",
		numberBlocks,largestRows,largestColumns,numberMaster,numberEmpty,numberRows,
		numberMasterColumns,numberEmptyColumns,numberColumns);
	 FILE * fp=NULL;
	 bool justIntegers=true;
	 bool oneFile=true;
	 int logLevel = model->logLevel();
	 if (logLevel>19) {
	   logLevel-=2;
	   oneFile=true;
	   fp = fopen("fake.bnd","w");
	 }
	 if (logLevel==19)
	   justIntegers=false;
	 for (int i=0;i<numberBlocks;i++) 
	   printf("Block %d has %d rows and %d columns (%d elements)\n",
		  i,blockCount[i],nextColumn[i],blockEls[i]);
	 if (logLevel >= 17 && logLevel <= 21) {
	   int * whichRows=new int[numberRows+numberColumns];
	   int * whichColumns=whichRows+numberRows;
	   char name[20];
	   for (int iBlock=0;iBlock<numberBlocks;iBlock++) {
	     sprintf(name,"block%d.mps",iBlock);
	     int nRows=0;
	     for (int iRow=0;iRow<numberRows;iRow++) {
	       if (blockStart[iRow]==iBlock)
		 whichRows[nRows++]=iRow;
	     }
	     int nColumns=0;
	     for (int iColumn=0;iColumn<numberColumns;iColumn++) {
	       if (columnBlock[iColumn]==iBlock)
		 whichColumns[nColumns++]=iColumn;
	     }
	     ClpSimplex subset(model,nRows,whichRows,nColumns,whichColumns);
	     for (int jRow=0;jRow<nRows;jRow++) {
	       int iRow = whichRows[jRow];
	       std::string name = model->getRowName(iRow);
	       subset.setRowName(jRow,name);
	     }
	     int nInteger=0;
	     for (int jColumn=0;jColumn<nColumns;jColumn++) {
	       int iColumn = whichColumns[jColumn];
	       if (model->isInteger(iColumn)) {
		 subset.setInteger(jColumn);
		 nInteger++;
	       }
	       std::string name = model->getColumnName(iColumn);
	       subset.setColumnName(jColumn,name);
	     }
	     if (logLevel == 17) {
	       subset.writeMps(name,0,1);
	     } else if (nInteger) {
	       OsiClpSolverInterface subset2(&subset);
	       CbcModel smallModel(subset2);
	       smallModel.branchAndBound();
	       const double * solution = smallModel.bestSolution();
	       if (solution) {
		 if (!oneFile) {
		   sprintf(name,"block%d.bnd",iBlock);
		   fp = fopen(name,"w");
		   assert (fp);
		 }
		 fprintf(fp,"BBB objective %g for block %d\n",
			 smallModel.getObjValue(),iBlock);
		 for (int jColumn=0;jColumn<nColumns;jColumn++) {
		   if (subset.isInteger(jColumn)||
		       !justIntegers) 
		     fprintf(fp," FX BOUND1    %.8s  %g\n",
			     subset.getColumnName(jColumn).c_str(),
			     solution[jColumn]);
		 }
		 if (!oneFile) 
		   fclose(fp);
	       } else {
		 printf("***** Problem is infeasible\n");
		 abort();
	       }
	     }
	   }
	   if (oneFile)
	     fclose(fp);
	   delete [] whichRows;
	 } 
       }
       delete [] blockStart;
     }
     for (iRow = 0; iRow < numberRows; iRow++) {
          int length = rowLength[iRow];
          number[length]++;
     }
     if (number[0])
          printf("** %d rows have no entries\n", number[0]);
     k = 0;
     for (iColumn = 1; iColumn <= numberColumns; iColumn++) {
          if (number[iColumn]) {
               k++;
               printf("%d rows have %d entries\n", number[iColumn], iColumn);
               if (k == kMax)
                    break;
          }
     }
     if (k < numberColumns) {
          int kk = k;
          k = 0;
          for (iColumn = numberColumns; iColumn >= 1; iColumn--) {
               if (number[iColumn]) {
                    k++;
                    if (k == kMax)
                         break;
               }
          }
          if (k > kk) {
               printf("\n    .........\n\n");
               iColumn = k;
               k = 0;
               for (; iColumn < numberColumns; iColumn++) {
                    if (number[iColumn]) {
                         k++;
                         printf("%d rows have %d entries\n", number[iColumn], iColumn);
                         if (k == kMax)
                              break;
                    }
               }
          }
     }
     if (model->logLevel() == 63
#ifdef SYM
               || true
#endif
        ) {
          int * column = rowCopy.getMutableIndices();
          const CoinBigIndex * rowStart = rowCopy.getVectorStarts();
          double * element = rowCopy.getMutableElements();
          int * order = new int[numberRows];
          int * other = new int[numberRows];
          for (iRow = 0; iRow < numberRows; iRow++) {
               int length = rowLength[iRow];
               order[iRow] = iRow;
               other[iRow] = length;
               CoinBigIndex start = rowStart[iRow];
               CoinSort_2(column + start, column + start + length, element + start);
          }
          CoinSort_2(other, other + numberRows, order);
          int jRow = number[0] + number[1];
          double * weight = new double[numberRows];
          double * randomColumn = new double[numberColumns+1];
          double * randomRow = new double [numberRows+1];
          int * sortRow = new int [numberRows];
          int * possibleRow = new int [numberRows];
          int * backRow = new int [numberRows];
          int * stackRow = new int [numberRows];
          int * sortColumn = new int [numberColumns];
          int * possibleColumn = new int [numberColumns];
          int * backColumn = new int [numberColumns];
          int * backColumn2 = new int [numberColumns];
          int * mapRow = new int [numberRows];
          int * mapColumn = new int [numberColumns];
          int * stackColumn = new int [numberColumns];
          double randomLower = CoinDrand48();
          double randomUpper = CoinDrand48();
          double randomInteger = CoinDrand48();
          int * startAdd = new int[numberRows+1];
          int * columnAdd = new int [2*numberElements];
          double * elementAdd = new double[2*numberElements];
          int nAddRows = 0;
          startAdd[0] = 0;
          for (iColumn = 0; iColumn < numberColumns; iColumn++) {
               randomColumn[iColumn] = CoinDrand48();
               backColumn2[iColumn] = -1;
          }
          for (iColumn = 2; iColumn <= numberColumns; iColumn++) {
               if (number[iColumn]) {
                    printf("XX %d rows have %d entries\n", number[iColumn], iColumn);
                    int kRow = jRow + number[iColumn];
                    sortOnOther(column, rowStart,
                                order + jRow, other, number[iColumn], iColumn, 0);
                    // Now print etc
                    if (iColumn < 500000) {
                         int nLook = 0;
                         for (int lRow = jRow; lRow < kRow; lRow++) {
                              iRow = order[lRow];
                              CoinBigIndex start = rowStart[iRow];
                              if (model->logLevel() == 63) {
                                   printf("row %d %g <= ", iRow, rowLower[iRow]);
                                   for (CoinBigIndex i = start; i < start + iColumn; i++)
                                        printf("( %d, %g) ", column[i], element[i]);
                                   printf("<= %g\n", rowUpper[iRow]);
                              }
                              int first = column[start];
                              double sum = 0.0;
                              for (CoinBigIndex i = start; i < start + iColumn; i++) {
                                   int jColumn = column[i];
                                   double value = element[i];
                                   jColumn -= first;
                                   assert (jColumn >= 0);
                                   sum += value * randomColumn[jColumn];
                              }
                              if (rowLower[iRow] > -1.0e30 && rowLower[iRow])
                                   sum += rowLower[iRow] * randomLower;
                              else if (!rowLower[iRow])
                                   sum += 1.234567e-7 * randomLower;
                              if (rowUpper[iRow] < 1.0e30 && rowUpper[iRow])
                                   sum += rowUpper[iRow] * randomUpper;
                              else if (!rowUpper[iRow])
                                   sum += 1.234567e-7 * randomUpper;
                              sortRow[nLook] = iRow;
                              randomRow[nLook++] = sum;
                              // best way is to number unique elements and bounds and use
                              if (fabs(sum) > 1.0e4)
                                   sum *= 1.0e-6;
                              weight[iRow] = sum;
                         }
                         assert (nLook <= numberRows);
                         CoinSort_2(randomRow, randomRow + nLook, sortRow);
                         randomRow[nLook] = COIN_DBL_MAX;
                         double last = -COIN_DBL_MAX;
                         int iLast = -1;
                         for (int iLook = 0; iLook < nLook + 1; iLook++) {
                              if (randomRow[iLook] > last) {
                                   if (iLast >= 0) {
                                        int n = iLook - iLast;
                                        if (n > 1) {
                                             //printf("%d rows possible?\n",n);
                                        }
                                   }
                                   iLast = iLook;
                                   last = randomRow[iLook];
                              }
                         }
                    }
                    jRow = kRow;
               }
          }
          CoinPackedMatrix columnCopy = *matrix;
          const int * columnLength = columnCopy.getVectorLengths();
          const int * row = columnCopy.getIndices();
          const CoinBigIndex * columnStart = columnCopy.getVectorStarts();
          const double * elementByColumn = columnCopy.getElements();
          for (iColumn = 0; iColumn < numberColumns; iColumn++) {
               int length = columnLength[iColumn];
               CoinBigIndex start = columnStart[iColumn];
               double sum = objective[iColumn];
               if (columnLower[iColumn] > -1.0e30 && columnLower[iColumn])
                    sum += columnLower[iColumn] * randomLower;
               else if (!columnLower[iColumn])
                    sum += 1.234567e-7 * randomLower;
               if (columnUpper[iColumn] < 1.0e30 && columnUpper[iColumn])
                    sum += columnUpper[iColumn] * randomUpper;
               else if (!columnUpper[iColumn])
                    sum += 1.234567e-7 * randomUpper;
               if (model->isInteger(iColumn))
                    sum += 9.87654321e-6 * randomInteger;
               for (CoinBigIndex i = start; i < start + length; i++) {
                    int iRow = row[i];
                    sum += elementByColumn[i] * weight[iRow];
               }
               sortColumn[iColumn] = iColumn;
               randomColumn[iColumn] = sum;
          }
          {
               CoinSort_2(randomColumn, randomColumn + numberColumns, sortColumn);
               for (iColumn = 0; iColumn < numberColumns; iColumn++) {
                    int i = sortColumn[iColumn];
                    backColumn[i] = iColumn;
               }
               randomColumn[numberColumns] = COIN_DBL_MAX;
               double last = -COIN_DBL_MAX;
               int iLast = -1;
               for (int iLook = 0; iLook < numberColumns + 1; iLook++) {
                    if (randomColumn[iLook] > last) {
                         if (iLast >= 0) {
                              int n = iLook - iLast;
                              if (n > 1) {
                                   //printf("%d columns possible?\n",n);
                              }
                              for (int i = iLast; i < iLook; i++) {
                                   possibleColumn[sortColumn[i]] = n;
                              }
                         }
                         iLast = iLook;
                         last = randomColumn[iLook];
                    }
               }
               for (iRow = 0; iRow < numberRows; iRow++) {
                    CoinBigIndex start = rowStart[iRow];
                    double sum = 0.0;
                    int length = rowLength[iRow];
                    for (CoinBigIndex i = start; i < start + length; i++) {
                         int jColumn = column[i];
                         double value = element[i];
                         jColumn = backColumn[jColumn];
                         sum += value * randomColumn[jColumn];
                         //if (iColumn==23089||iRow==23729)
                         //printf("row %d cola %d colb %d value %g rand %g sum %g\n",
                         //   iRow,jColumn,column[i],value,randomColumn[jColumn],sum);
                    }
                    sortRow[iRow] = iRow;
                    randomRow[iRow] = weight[iRow];
                    randomRow[iRow] = sum;
               }
               CoinSort_2(randomRow, randomRow + numberRows, sortRow);
               for (iRow = 0; iRow < numberRows; iRow++) {
                    int i = sortRow[iRow];
                    backRow[i] = iRow;
               }
               randomRow[numberRows] = COIN_DBL_MAX;
               last = -COIN_DBL_MAX;
               iLast = -1;
               // Do backward indices from order
               for (iRow = 0; iRow < numberRows; iRow++) {
                    other[order[iRow]] = iRow;
               }
               for (int iLook = 0; iLook < numberRows + 1; iLook++) {
                    if (randomRow[iLook] > last) {
                         if (iLast >= 0) {
                              int n = iLook - iLast;
                              if (n > 1) {
                                   //printf("%d rows possible?\n",n);
                                   // Within group sort as for original "order"
                                   for (int i = iLast; i < iLook; i++) {
                                        int jRow = sortRow[i];
                                        order[i] = other[jRow];
                                   }
                                   CoinSort_2(order + iLast, order + iLook, sortRow + iLast);
                              }
                              for (int i = iLast; i < iLook; i++) {
                                   possibleRow[sortRow[i]] = n;
                              }
                         }
                         iLast = iLook;
                         last = randomRow[iLook];
                    }
               }
               // Temp out
               for (int iLook = 0; iLook < numberRows - 1000000; iLook++) {
                    iRow = sortRow[iLook];
                    CoinBigIndex start = rowStart[iRow];
                    int length = rowLength[iRow];
                    int numberPossible = possibleRow[iRow];
                    for (CoinBigIndex i = start; i < start + length; i++) {
                         int jColumn = column[i];
                         if (possibleColumn[jColumn] != numberPossible)
                              numberPossible = -1;
                    }
                    int n = numberPossible;
                    if (numberPossible > 1) {
                         //printf("pppppossible %d\n",numberPossible);
                         for (int jLook = iLook + 1; jLook < iLook + numberPossible; jLook++) {
                              int jRow = sortRow[jLook];
                              CoinBigIndex start2 = rowStart[jRow];
                              assert (numberPossible == possibleRow[jRow]);
                              assert(length == rowLength[jRow]);
                              for (CoinBigIndex i = start2; i < start2 + length; i++) {
                                   int jColumn = column[i];
                                   if (possibleColumn[jColumn] != numberPossible)
                                        numberPossible = -1;
                              }
                         }
                         if (numberPossible < 2) {
                              // switch off
                              for (int jLook = iLook; jLook < iLook + n; jLook++)
                                   possibleRow[sortRow[jLook]] = -1;
                         }
                         // skip rest
                         iLook += n - 1;
                    } else {
                         possibleRow[iRow] = -1;
                    }
               }
               for (int iLook = 0; iLook < numberRows; iLook++) {
                    iRow = sortRow[iLook];
                    int numberPossible = possibleRow[iRow];
                    // Only if any integers
                    int numberIntegers = 0;
                    CoinBigIndex start = rowStart[iRow];
                    int length = rowLength[iRow];
                    for (CoinBigIndex i = start; i < start + length; i++) {
                         int jColumn = column[i];
                         if (model->isInteger(jColumn))
                              numberIntegers++;
                    }
                    if (numberPossible > 1 && !numberIntegers) {
                         //printf("possible %d - but no integers\n",numberPossible);
                    }
                    if (numberPossible > 1 && (numberIntegers || false)) {
                         //
                         printf("possible %d - %d integers\n", numberPossible, numberIntegers);
                         int lastLook = iLook;
                         int nMapRow = -1;
                         for (int jLook = iLook + 1; jLook < iLook + numberPossible; jLook++) {
                              // stop if too many failures
                              if (jLook > iLook + 10 && nMapRow < 0)
                                   break;
                              // Create identity mapping
                              int i;
                              for (i = 0; i < numberRows; i++)
                                   mapRow[i] = i;
                              for (i = 0; i < numberColumns; i++)
                                   mapColumn[i] = i;
                              int offset = jLook - iLook;
                              int nStackC = 0;
                              // build up row and column mapping
                              int nStackR = 1;
                              stackRow[0] = iLook;
                              bool good = true;
                              while (nStackR) {
                                   nStackR--;
                                   int look1 = stackRow[nStackR];
                                   int look2 = look1 + offset;
                                   assert (randomRow[look1] == randomRow[look2]);
                                   int row1 = sortRow[look1];
                                   int row2 = sortRow[look2];
                                   assert (mapRow[row1] == row1);
                                   assert (mapRow[row2] == row2);
                                   mapRow[row1] = row2;
                                   mapRow[row2] = row1;
                                   CoinBigIndex start1 = rowStart[row1];
                                   CoinBigIndex offset2 = rowStart[row2] - start1;
                                   int length = rowLength[row1];
                                   assert( length == rowLength[row2]);
                                   for (CoinBigIndex i = start1; i < start1 + length; i++) {
                                        int jColumn1 = column[i];
                                        int jColumn2 = column[i+offset2];
                                        if (randomColumn[backColumn[jColumn1]] !=
                                                  randomColumn[backColumn[jColumn2]]) {
                                             good = false;
                                             break;
                                        }
                                        if (mapColumn[jColumn1] == jColumn1) {
                                             // not touched
                                             assert (mapColumn[jColumn2] == jColumn2);
                                             if (jColumn1 != jColumn2) {
                                                  // Put on stack
                                                  mapColumn[jColumn1] = jColumn2;
                                                  mapColumn[jColumn2] = jColumn1;
                                                  stackColumn[nStackC++] = jColumn1;
                                             }
                                        } else {
                                             if (mapColumn[jColumn1] != jColumn2 ||
                                                       mapColumn[jColumn2] != jColumn1) {
                                                  // bad
                                                  good = false;
                                                  printf("bad col\n");
                                                  break;
                                             }
                                        }
                                   }
                                   if (!good)
                                        break;
                                   while (nStackC) {
                                        nStackC--;
                                        int iColumn = stackColumn[nStackC];
                                        int iColumn2 = mapColumn[iColumn];
                                        assert (iColumn != iColumn2);
                                        int length = columnLength[iColumn];
                                        assert (length == columnLength[iColumn2]);
                                        CoinBigIndex start = columnStart[iColumn];
                                        CoinBigIndex offset2 = columnStart[iColumn2] - start;
                                        for (CoinBigIndex i = start; i < start + length; i++) {
                                             int iRow = row[i];
                                             int iRow2 = row[i+offset2];
                                             if (mapRow[iRow] == iRow) {
                                                  // First (but be careful)
                                                  if (iRow != iRow2) {
                                                       //mapRow[iRow]=iRow2;
                                                       //mapRow[iRow2]=iRow;
                                                       int iBack = backRow[iRow];
                                                       int iBack2 = backRow[iRow2];
                                                       if (randomRow[iBack] == randomRow[iBack2] &&
                                                                 iBack2 - iBack == offset) {
                                                            stackRow[nStackR++] = iBack;
                                                       } else {
                                                            //printf("randomRow diff - weights %g %g\n",
                                                            //     weight[iRow],weight[iRow2]);
                                                            // bad
                                                            good = false;
                                                            break;
                                                       }
                                                  }
                                             } else {
                                                  if (mapRow[iRow] != iRow2 ||
                                                            mapRow[iRow2] != iRow) {
                                                       // bad
                                                       good = false;
                                                       printf("bad row\n");
                                                       break;
                                                  }
                                             }
                                        }
                                        if (!good)
                                             break;
                                   }
                              }
                              // then check OK
                              if (good) {
                                   for (iRow = 0; iRow < numberRows; iRow++) {
                                        CoinBigIndex start = rowStart[iRow];
                                        int length = rowLength[iRow];
                                        if (mapRow[iRow] == iRow) {
                                             for (CoinBigIndex i = start; i < start + length; i++) {
                                                  int jColumn = column[i];
                                                  backColumn2[jColumn] = i - start;
                                             }
                                             for (CoinBigIndex i = start; i < start + length; i++) {
                                                  int jColumn = column[i];
                                                  if (mapColumn[jColumn] != jColumn) {
                                                       int jColumn2 = mapColumn[jColumn];
                                                       CoinBigIndex i2 = backColumn2[jColumn2];
                                                       if (i2 < 0) {
                                                            good = false;
                                                       } else if (element[i] != element[i2+start]) {
                                                            good = false;
                                                       }
                                                  }
                                             }
                                             for (CoinBigIndex i = start; i < start + length; i++) {
                                                  int jColumn = column[i];
                                                  backColumn2[jColumn] = -1;
                                             }
                                        } else {
                                             int row2 = mapRow[iRow];
                                             assert (iRow = mapRow[row2]);
                                             if (rowLower[iRow] != rowLower[row2] ||
                                                       rowLower[row2] != rowLower[iRow])
                                                  good = false;
                                             CoinBigIndex offset2 = rowStart[row2] - start;
                                             for (CoinBigIndex i = start; i < start + length; i++) {
                                                  int jColumn = column[i];
                                                  double value = element[i];
                                                  int jColumn2 = column[i+offset2];
                                                  double value2 = element[i+offset2];
                                                  if (value != value2 || mapColumn[jColumn] != jColumn2 ||
                                                            mapColumn[jColumn2] != jColumn)
                                                       good = false;
                                             }
                                        }
                                   }
                                   if (good) {
                                        // check rim
                                        for (iColumn = 0; iColumn < numberColumns; iColumn++) {
                                             if (mapColumn[iColumn] != iColumn) {
                                                  int iColumn2 = mapColumn[iColumn];
                                                  if (objective[iColumn] != objective[iColumn2])
                                                       good = false;
                                                  if (columnLower[iColumn] != columnLower[iColumn2])
                                                       good = false;
                                                  if (columnUpper[iColumn] != columnUpper[iColumn2])
                                                       good = false;
                                                  if (model->isInteger(iColumn) != model->isInteger(iColumn2))
                                                       good = false;
                                             }
                                        }
                                   }
                                   if (good) {
                                        // temp
                                        if (nMapRow < 0) {
                                             //const double * solution = model->primalColumnSolution();
                                             // find mapped
                                             int nMapColumn = 0;
                                             for (int i = 0; i < numberColumns; i++) {
                                                  if (mapColumn[i] > i)
                                                       nMapColumn++;
                                             }
                                             nMapRow = 0;
                                             int kRow = -1;
                                             for (int i = 0; i < numberRows; i++) {
                                                  if (mapRow[i] > i) {
                                                       nMapRow++;
                                                       kRow = i;
                                                  }
                                             }
                                             printf("%d columns, %d rows\n", nMapColumn, nMapRow);
                                             if (nMapRow == 1) {
                                                  CoinBigIndex start = rowStart[kRow];
                                                  int length = rowLength[kRow];
                                                  printf("%g <= ", rowLower[kRow]);
                                                  for (CoinBigIndex i = start; i < start + length; i++) {
                                                       int jColumn = column[i];
                                                       if (mapColumn[jColumn] != jColumn)
                                                            printf("* ");
                                                       printf("%d,%g ", jColumn, element[i]);
                                                  }
                                                  printf("<= %g\n", rowUpper[kRow]);
                                             }
                                        }
                                        // temp
                                        int row1 = sortRow[lastLook];
                                        int row2 = sortRow[jLook];
                                        lastLook = jLook;
                                        CoinBigIndex start1 = rowStart[row1];
                                        CoinBigIndex offset2 = rowStart[row2] - start1;
                                        int length = rowLength[row1];
                                        assert( length == rowLength[row2]);
                                        CoinBigIndex put = startAdd[nAddRows];
                                        double multiplier = length < 11 ? 2.0 : 1.125;
                                        double value = 1.0;
                                        for (CoinBigIndex i = start1; i < start1 + length; i++) {
                                             int jColumn1 = column[i];
                                             int jColumn2 = column[i+offset2];
                                             columnAdd[put] = jColumn1;
                                             elementAdd[put++] = value;
                                             columnAdd[put] = jColumn2;
                                             elementAdd[put++] = -value;
                                             value *= multiplier;
                                        }
                                        nAddRows++;
                                        startAdd[nAddRows] = put;
                                   } else {
                                        printf("ouch - did not check out as good\n");
                                   }
                              }
                         }
                         // skip rest
                         iLook += numberPossible - 1;
                    }
               }
          }
          if (nAddRows) {
               double * lower = new double [nAddRows];
               double * upper = new double[nAddRows];
               int i;
               //const double * solution = model->primalColumnSolution();
               for (i = 0; i < nAddRows; i++) {
                    lower[i] = 0.0;
                    upper[i] = COIN_DBL_MAX;
               }
               printf("Adding %d rows with %d elements\n", nAddRows,
                      startAdd[nAddRows]);
               //ClpSimplex newModel(*model);
               //newModel.addRows(nAddRows,lower,upper,startAdd,columnAdd,elementAdd);
               //newModel.writeMps("modified.mps");
               delete [] lower;
               delete [] upper;
          }
          delete [] startAdd;
          delete [] columnAdd;
          delete [] elementAdd;
          delete [] order;
          delete [] other;
          delete [] randomColumn;
          delete [] weight;
          delete [] randomRow;
          delete [] sortRow;
          delete [] backRow;
          delete [] possibleRow;
          delete [] sortColumn;
          delete [] backColumn;
          delete [] backColumn2;
          delete [] possibleColumn;
          delete [] mapRow;
          delete [] mapColumn;
          delete [] stackRow;
          delete [] stackColumn;
     }
     delete [] number;
     // Now do breakdown of ranges
     breakdown("Elements", numberElements, elementByColumn);
     breakdown("RowLower", numberRows, rowLower);
     breakdown("RowUpper", numberRows, rowUpper);
     breakdown("ColumnLower", numberColumns, columnLower);
     breakdown("ColumnUpper", numberColumns, columnUpper);
     breakdown("Objective", numberColumns, objective);
}


static bool maskMatches(const int * starts, char ** masks,
                        std::string & check)
{
    // back to char as I am old fashioned
    const char * checkC = check.c_str();
    size_t length = strlen(checkC);
    while (length > 0 && checkC[length-1] == ' ')
        length--;
    for (int i = starts[length]; i < starts[length+1]; i++) {
        char * thisMask = masks[i];
        size_t k;
        for ( k = 0; k < length; k++) {
            if (thisMask[k] != '?' && thisMask[k] != checkC[k])
                break;
        }
        if (k == length)
            return true;
    }
    return false;
}

static void clean(char * temp)
{
    char * put = temp;
    while (*put >= ' ')
        put++;
    *put = '\0';
}

static void generateCode(CbcModel * /*model*/, const char * fileName, int type, int preProcess)
{
    // options on code generation
    bool sizecode = (type & 4) != 0;
    type &= 3;
    FILE * fp = fopen(fileName, "r");
    assert (fp);
    int numberLines = 0;
#define MAXLINES 5000
#define MAXONELINE 200
    char line[MAXLINES][MAXONELINE];
    strcpy(line[numberLines++], "0#if defined(_MSC_VER)");
    strcpy(line[numberLines++], "0// Turn off compiler warning about long names");
    strcpy(line[numberLines++], "0#  pragma warning(disable:4786)");
    strcpy(line[numberLines++], "0#endif\n");
    strcpy(line[numberLines++], "0#include <cassert>");
    strcpy(line[numberLines++], "0#include <iomanip>");
    strcpy(line[numberLines++], "0#include \"OsiClpSolverInterface.hpp\"");
    strcpy(line[numberLines++], "0#include \"CbcModel.hpp\"");
    strcpy(line[numberLines++], "0#include \"CbcCutGenerator.hpp\"");
    strcpy(line[numberLines++], "0#include \"CbcStrategy.hpp\"");
    strcpy(line[numberLines++], "0#include \"CglPreProcess.hpp\"");
    strcpy(line[numberLines++], "0#include \"CoinTime.hpp\"");
    if (preProcess > 0)
        strcpy(line[numberLines++], "0#include \"CglProbing.hpp\""); // possibly redundant
    // To allow generated 5's to be just before branchAndBound - do rest here
    strcpy(line[numberLines++], "5  cbcModel->initialSolve();");
    strcpy(line[numberLines++], "5  if (clpModel->tightenPrimalBounds()!=0) {");
    strcpy(line[numberLines++], "5    std::cout<<\"Problem is infeasible - tightenPrimalBounds!\"<<std::endl;");
    strcpy(line[numberLines++], "5    exit(1);");
    strcpy(line[numberLines++], "5  }");
    strcpy(line[numberLines++], "5  clpModel->dual();  // clean up");
    if (sizecode) {
        // override some settings
        strcpy(line[numberLines++], "5  // compute some things using problem size");
        strcpy(line[numberLines++], "5  cbcModel->setMinimumDrop(CoinMin(5.0e-2,");
        strcpy(line[numberLines++], "5       fabs(cbcModel->getMinimizationObjValue())*1.0e-3+1.0e-4));");
        strcpy(line[numberLines++], "5  if (cbcModel->getNumCols()<500)");
        strcpy(line[numberLines++], "5    cbcModel->setMaximumCutPassesAtRoot(-100); // always do 100 if possible");
        strcpy(line[numberLines++], "5  else if (cbcModel->getNumCols()<5000)");
        strcpy(line[numberLines++], "5    cbcModel->setMaximumCutPassesAtRoot(100); // use minimum drop");
        strcpy(line[numberLines++], "5  else");
        strcpy(line[numberLines++], "5    cbcModel->setMaximumCutPassesAtRoot(20);");
        strcpy(line[numberLines++], "5  cbcModel->setMaximumCutPasses(1);");
    }
    if (preProcess <= 0) {
        // no preprocessing or strategy
        if (preProcess) {
            strcpy(line[numberLines++], "5  // Preprocessing using CbcStrategy");
            strcpy(line[numberLines++], "5  CbcStrategyDefault strategy(1,5,5);");
            strcpy(line[numberLines++], "5  strategy.setupPreProcessing(1);");
            strcpy(line[numberLines++], "5  cbcModel->setStrategy(strategy);");
        }
    } else {
        int translate[] = {9999, 0, 0, -1, 2, 3, -2};
        strcpy(line[numberLines++], "5  // Hand coded preprocessing");
        strcpy(line[numberLines++], "5  CglPreProcess process;");
        strcpy(line[numberLines++], "5  OsiSolverInterface * saveSolver=cbcModel->solver()->clone();");
        strcpy(line[numberLines++], "5  // Tell solver we are in Branch and Cut");
        strcpy(line[numberLines++], "5  saveSolver->setHintParam(OsiDoInBranchAndCut,true,OsiHintDo) ;");
        strcpy(line[numberLines++], "5  // Default set of cut generators");
        strcpy(line[numberLines++], "5  CglProbing generator1;");
        strcpy(line[numberLines++], "5  generator1.setUsingObjective(1);");
        strcpy(line[numberLines++], "5  generator1.setMaxPass(3);");
        strcpy(line[numberLines++], "5  generator1.setMaxProbeRoot(saveSolver->getNumCols());");
        strcpy(line[numberLines++], "5  generator1.setMaxElements(100);");
        strcpy(line[numberLines++], "5  generator1.setMaxLookRoot(50);");
        strcpy(line[numberLines++], "5  generator1.setRowCuts(3);");
        strcpy(line[numberLines++], "5  // Add in generators");
        strcpy(line[numberLines++], "5  process.addCutGenerator(&generator1);");
        strcpy(line[numberLines++], "5  process.messageHandler()->setLogLevel(cbcModel->logLevel());");
        strcpy(line[numberLines++], "5  OsiSolverInterface * solver2 = ");
        sprintf(line[numberLines++], "5    process.preProcessNonDefault(*saveSolver,%d,10);", translate[preProcess]);
        strcpy(line[numberLines++], "5  // Tell solver we are not in Branch and Cut");
        strcpy(line[numberLines++], "5  saveSolver->setHintParam(OsiDoInBranchAndCut,false,OsiHintDo) ;");
        strcpy(line[numberLines++], "5  if (solver2)");
        strcpy(line[numberLines++], "5    solver2->setHintParam(OsiDoInBranchAndCut,false,OsiHintDo) ;");
        strcpy(line[numberLines++], "5  if (!solver2) {");
        strcpy(line[numberLines++], "5    std::cout<<\"Pre-processing says infeasible!\"<<std::endl;");
        strcpy(line[numberLines++], "5    exit(1);");
        strcpy(line[numberLines++], "5  } else {");
        strcpy(line[numberLines++], "5    std::cout<<\"processed model has \"<<solver2->getNumRows()");
        strcpy(line[numberLines++], "5	     <<\" rows, \"<<solver2->getNumCols()");
        strcpy(line[numberLines++], "5	     <<\" columns and \"<<solver2->getNumElements()");
        strcpy(line[numberLines++], "5	     <<\" elements\"<<solver2->getNumElements()<<std::endl;");
        strcpy(line[numberLines++], "5  }");
        strcpy(line[numberLines++], "5  // we have to keep solver2 so pass clone");
        strcpy(line[numberLines++], "5  solver2 = solver2->clone();");
        strcpy(line[numberLines++], "5  cbcModel->assignSolver(solver2);");
        strcpy(line[numberLines++], "5  cbcModel->initialSolve();");
    }
    while (fgets(line[numberLines], MAXONELINE, fp)) {
        assert (numberLines < MAXLINES);
        clean(line[numberLines]);
        numberLines++;
    }
    fclose(fp);
    strcpy(line[numberLines++], "0\nint main (int argc, const char *argv[])\n{");
    strcpy(line[numberLines++], "0  OsiClpSolverInterface solver1;");
    strcpy(line[numberLines++], "0  int status=1;");
    strcpy(line[numberLines++], "0  if (argc<2)");
    strcpy(line[numberLines++], "0    std::cout<<\"Please give file name\"<<std::endl;");
    strcpy(line[numberLines++], "0  else");
    strcpy(line[numberLines++], "0    status=solver1.readMps(argv[1],\"\");");
    strcpy(line[numberLines++], "0  if (status) {");
    strcpy(line[numberLines++], "0    std::cout<<\"Bad readMps \"<<argv[1]<<std::endl;");
    strcpy(line[numberLines++], "0    exit(1);");
    strcpy(line[numberLines++], "0  }\n");
    strcpy(line[numberLines++], "0  double time1 = CoinCpuTime();");
    strcpy(line[numberLines++], "0  CbcModel model(solver1);");
    strcpy(line[numberLines++], "0  // Now do requested saves and modifications");
    strcpy(line[numberLines++], "0  CbcModel * cbcModel = & model;");
    strcpy(line[numberLines++], "0  OsiSolverInterface * osiModel = model.solver();");
    strcpy(line[numberLines++], "0  OsiClpSolverInterface * osiclpModel = dynamic_cast< OsiClpSolverInterface*> (osiModel);");
    strcpy(line[numberLines++], "0  ClpSimplex * clpModel = osiclpModel->getModelPtr();");
    // add in comments about messages
    strcpy(line[numberLines++], "3  // You can save some time by switching off message building");
    strcpy(line[numberLines++], "3  // clpModel->messagesPointer()->setDetailMessages(100,10000,(int *) NULL);");
    // add in actual solve
    strcpy(line[numberLines++], "5  cbcModel->branchAndBound();");
    strcpy(line[numberLines++], "8  std::cout<<argv[1]<<\" took \"<<CoinCpuTime()-time1<<\" seconds, \"");
    strcpy(line[numberLines++], "8	   <<cbcModel->getNodeCount()<<\" nodes with objective \"");
    strcpy(line[numberLines++], "8	   <<cbcModel->getObjValue()");
    strcpy(line[numberLines++], "8	   <<(!cbcModel->status() ? \" Finished\" : \" Not finished\")");
    strcpy(line[numberLines++], "8	   <<std::endl;");
    strcpy(line[numberLines++], "5  // For best solution");
    strcpy(line[numberLines++], "5  int numberColumns = solver1.getNumCols();");
    strcpy(line[numberLines++], "5  if (cbcModel->getMinimizationObjValue()<1.0e50) {");
    if (preProcess > 0) {
        strcpy(line[numberLines++], "5    // post process");
        strcpy(line[numberLines++], "5    process.postProcess(*cbcModel->solver());");
        strcpy(line[numberLines++], "5    // Solution now back in saveSolver");
        strcpy(line[numberLines++], "5    cbcModel->assignSolver(saveSolver);");
        strcpy(line[numberLines++], "5    memcpy(cbcModel->bestSolution(),cbcModel->solver()->getColSolution(),");
        strcpy(line[numberLines++], "5	   numberColumns*sizeof(double));");
    }
    strcpy(line[numberLines++], "5    // put back in original solver");
    strcpy(line[numberLines++], "5    solver1.setColSolution(cbcModel->bestSolution());");
    strcpy(line[numberLines++], "5    const double * solution = solver1.getColSolution();");
    strcpy(line[numberLines++], "8  \n  // Now you would use solution etc etc\n");
    strcpy(line[numberLines++], "5");
    strcpy(line[numberLines++], "5    // Get names from solver1 (as OsiSolverInterface may lose)");
    strcpy(line[numberLines++], "5    std::vector<std::string> columnNames = *solver1.getModelPtr()->columnNames();");
    strcpy(line[numberLines++], "5    ");
    strcpy(line[numberLines++], "5    int iColumn;");
    strcpy(line[numberLines++], "5    std::cout<<std::setiosflags(std::ios::fixed|std::ios::showpoint)<<std::setw(14);");
    strcpy(line[numberLines++], "5    ");
    strcpy(line[numberLines++], "5    std::cout<<\"--------------------------------------\"<<std::endl;");
    strcpy(line[numberLines++], "5    for (iColumn=0;iColumn<numberColumns;iColumn++) {");
    strcpy(line[numberLines++], "5      double value=solution[iColumn];");
    strcpy(line[numberLines++], "5      if (fabs(value)>1.0e-7&&solver1.isInteger(iColumn)) ");
    strcpy(line[numberLines++], "5	std::cout<<std::setw(6)<<iColumn<<\" \"");
    strcpy(line[numberLines++], "5                 <<columnNames[iColumn]<<\" \"");
    strcpy(line[numberLines++], "5                 <<value<<std::endl;");
    strcpy(line[numberLines++], "5    }");
    strcpy(line[numberLines++], "5    std::cout<<\"--------------------------------------\"<<std::endl;");
    strcpy(line[numberLines++], "5  ");
    strcpy(line[numberLines++], "5    std::cout<<std::resetiosflags(std::ios::fixed|std::ios::showpoint|std::ios::scientific);");
    strcpy(line[numberLines++], "5  }");
    strcpy(line[numberLines++], "8  return 0;\n}");
    fp = fopen(fileName, "w");
    assert (fp);

    int wanted[9];
    memset(wanted, 0, sizeof(wanted));
    wanted[0] = wanted[3] = wanted[5] = wanted[8] = 1;
    if (type > 0)
        wanted[1] = wanted[6] = 1;
    if (type > 1)
        wanted[2] = wanted[4] = wanted[7] = 1;
    std::string header[9] = { "", "Save values", "Redundant save of default values", "Set changed values",
                              "Redundant set default values", "Solve", "Restore values", "Redundant restore values", "Finish up"
                            };
    for (int iType = 0; iType < 9; iType++) {
        if (!wanted[iType])
            continue;
        int n = 0;
        int iLine;
        for (iLine = 0; iLine < numberLines; iLine++) {
            if (line[iLine][0] == '0' + iType) {
                if (!n && header[iType] != "")
                    fprintf(fp, "\n  // %s\n\n", header[iType].c_str());
                n++;
                // skip save and clp as cloned
                if (!strstr(line[iLine], "save") || (!strstr(line[iLine], "clpMo") &&
                                                     !strstr(line[iLine], "_Osi")))
                    fprintf(fp, "%s\n", line[iLine] + 1);
            }
        }
    }
    fclose(fp);
    printf("C++ file written to %s\n", fileName);
}
// Print a general message
static void printGeneralMessage(CbcModel &model,const char * message)
{
#ifndef DISALLOW_PRINTING
  model.messageHandler()->message(CBC_FPUMP1, model.messages())
    << message
    << CoinMessageEol;
#endif
}
/*
  Version 1.00.00 November 16 2005.
  This is to stop me (JJF) messing about too much.
  Tuning changes should be noted here.
  The testing next version may be activated by CBC_NEXT_VERSION
  This applies to OsiClp, Clp etc
  Version 1.00.01 November 24 2005
  Added several classes for advanced users.  This can't affect code (if you don't use it)
  Made some tiny changes (for N way branching) which should not change anything.
  CbcNWay object class - for N way branching this also allows use of CbcConsequence class.
  CbcBranchAllDifferent object class - for branching on general integer variables
  to stop them having same value so branches are x >= y+1 and x <= y-1.
  Added two new Cgl classes - CglAllDifferent which does column fixing (too slowly)
  and CglStored which just has a list of cuts which can be activated.
  Modified preprocess option to SOS
  Version 1.00.02 December 9 2005
  Added use of CbcStrategy to do clean preprocessing
  Added use of referenceSolver for cleaner repetition of Cbc
  Version 1.01.00 February 2 2006
  Added first try at Ampl interface
  Version 1.04 June 2007
  Goes parallel
  Version 2.00 September 2007
  Improvements to feaspump
  Source code changes so up to 2.0
*/
                            
