Changeset 642 for branches/devel/Cbc


Ignore:
Timestamp:
Jun 26, 2007 5:59:58 AM (12 years ago)
Author:
forrest
Message:

update branches/devel for threads

Location:
branches/devel/Cbc/src
Files:
4 added
25 edited

Legend:

Unmodified
Added
Removed
  • branches/devel/Cbc/src/CbcBranchBase.hpp

    r463 r642  
    323323  {way_=way;};
    324324
     325   /// update model
     326  inline void setModel(CbcModel * model)
     327  { model_ = model;};
    325328  /// Return model
    326329  inline CbcModel * model() const
  • branches/devel/Cbc/src/CbcCompareBase.hpp

    r424 r642  
    1818*/
    1919#include "CbcNode.hpp"
     20#include "CbcConfig.h"
    2021
    2122class CbcModel;
     
    7677  {
    7778    assert (x);
     79    assert (y);
     80#ifndef CBC_THREAD
    7881    CbcNodeInfo * infoX = x->nodeInfo();
    7982    assert (infoX);
    8083    int nodeNumberX = infoX->nodeNumber();
    81     assert (y);
    8284    CbcNodeInfo * infoY = y->nodeInfo();
    8385    assert (infoY);
     
    8587    assert (nodeNumberX!=nodeNumberY);
    8688    return (nodeNumberX>nodeNumberY);
     89#else
     90    // doesn't work if threaded
     91    assert (x!=y);
     92    return (x>y);
     93#endif
    8794  };
    8895protected:
  • branches/devel/Cbc/src/CbcCountRowCut.cpp

    r310 r642  
    4141                                int whichGenerator)
    4242  : OsiRowCut(rhs),
    43   owner_(info),
    44   ownerCut_(whichOne),
     43    owner_(info),
     44    ownerCut_(whichOne),
    4545    numberPointingToThis_(0),
    46   whichCutGenerator_(whichGenerator)
     46    whichCutGenerator_(whichGenerator)
    4747{
    4848#ifdef CHECK_CUT_COUNTS
     
    5858  // Look at owner and delete
    5959  owner_->deleteCut(ownerCut_);
     60  ownerCut_=-1234567;
    6061}
    6162// Increment number of references
     
    6364CbcCountRowCut::increment(int change)
    6465{
     66  assert(ownerCut_!=-1234567);
    6567  numberPointingToThis_+=change;
    6668}
     
    7072CbcCountRowCut::decrement(int change)
    7173{
    72   assert(numberPointingToThis_>=change);
     74  assert(ownerCut_!=-1234567);
     75  //assert(numberPointingToThis_>=change);
     76  assert(numberPointingToThis_>=0);
     77  if(numberPointingToThis_<change) {
     78    assert(numberPointingToThis_>0);
     79    printf("negative cut count %d - %d\n",numberPointingToThis_, change);
     80    change = numberPointingToThis_;
     81  }
    7382  numberPointingToThis_-=change;
    7483  return numberPointingToThis_;
    7584}
     85
    7686// Set information
    7787void
  • branches/devel/Cbc/src/CbcCutGenerator.cpp

    r529 r642  
    8383  model_ = rhs.model_;
    8484  generator_=rhs.generator_->clone();
    85   generator_->refreshSolver(model_->solver());
     85  //generator_->refreshSolver(model_->solver());
    8686  whenCutGenerator_=rhs.whenCutGenerator_;
    8787  whenCutGeneratorInSub_ = rhs.whenCutGeneratorInSub_;
     
    160160*/
    161161bool
    162 CbcCutGenerator::generateCuts( OsiCuts & cs , bool fullScan, CbcNode * node)
     162CbcCutGenerator::generateCuts( OsiCuts & cs , bool fullScan, OsiSolverInterface * solver, CbcNode * node)
    163163{
    164164  int howOften = whenCutGenerator_;
     
    172172    howOften=1;
    173173  bool returnCode=false;
    174   OsiSolverInterface * solver = model_->solver();
     174  //OsiSolverInterface * solver = model_->solver();
    175175  int depth;
    176176  if (node)
     
    210210    if (!generator) {
    211211      // Pass across model information in case it could be useful
    212       //OsiSolverInterface * solver = model_->solver();
    213212      //void * saveData = solver->getApplicationData();
    214213      //solver->setApplicationData(model_);
     
    235234      int numberColumns = solver->getNumCols();
    236235      double primalTolerance = 1.0e-8;
    237 #if 0
    238       int numberChanged=0,ifCut=0;
    239       CoinPackedVector lbs;
    240       CoinPackedVector ubs;
    241       for (j=0;j<numberColumns;j++) {
    242         if (solver->isInteger(j)) {
    243           if (tightUpper[j]<upper[j]) {
    244             numberChanged++;
    245             assert (tightUpper[j]==floor(tightUpper[j]+0.5));
    246             ubs.insert(j,tightUpper[j]);
    247             if (tightUpper[j]<solution[j]-primalTolerance)
    248               ifCut=1;
    249           }
    250           if (tightLower[j]>lower[j]) {
    251             numberChanged++;
    252             assert (tightLower[j]==floor(tightLower[j]+0.5));
    253             lbs.insert(j,tightLower[j]);
    254             if (tightLower[j]>solution[j]+primalTolerance)
    255               ifCut=1;
    256           }
    257         } else {
    258           if (tightUpper[j]==tightLower[j]&&
    259               upper[j]>lower[j]) {
    260             // fix
    261             //solver->setColLower(j,tightLower[j]);
    262             //solver->setColUpper(j,tightUpper[j]);
    263             double value = tightUpper[j];
    264             numberChanged++;
    265             if (value<upper[j])
    266               ubs.insert(j,value);
    267             if (value>lower[j])
    268               lbs.insert(j,value);
    269           }
    270         }
    271       }
    272       if (numberChanged) {
    273         OsiColCut cc;
    274         cc.setUbs(ubs);
    275         cc.setLbs(lbs);
    276         if (ifCut) {
    277           cc.setEffectiveness(100.0);
    278         } else {
    279           cc.setEffectiveness(1.0e-5);
    280         }
    281         cs.insert(cc);
    282       }
    283       // need to resolve if some bounds changed
    284       returnCode = !solver->basisIsAvailable();
    285       assert (!returnCode);
    286 #else
    287236      const char * tightenBounds = generator->tightenBounds();
    288       for (j=0;j<numberColumns;j++) {
    289         if (solver->isInteger(j)) {
    290           if (tightUpper[j]<upper[j]) {
    291             double nearest = floor(tightUpper[j]+0.5);
    292             //assert (fabs(tightUpper[j]-nearest)<1.0e-5); may be infeasible
    293             solver->setColUpper(j,nearest);
    294             if (nearest<solution[j]-primalTolerance)
    295               returnCode=true;
    296           }
    297           if (tightLower[j]>lower[j]) {
    298             double nearest = floor(tightLower[j]+0.5);
    299             //assert (fabs(tightLower[j]-nearest)<1.0e-5); may be infeasible
    300             solver->setColLower(j,nearest);
    301             if (nearest>solution[j]+primalTolerance)
    302               returnCode=true;
    303           }
    304         } else {
    305           if (upper[j]>lower[j]) {
    306             if (tightUpper[j]==tightLower[j]) {
    307               // fix
    308               solver->setColLower(j,tightLower[j]);
    309               solver->setColUpper(j,tightUpper[j]);
    310               if (tightLower[j]>solution[j]+primalTolerance||
    311                   tightUpper[j]<solution[j]-primalTolerance)
    312                 returnCode=true;
    313             } else if (tightenBounds&&tightenBounds[j]) {
    314               solver->setColLower(j,CoinMax(tightLower[j],lower[j]));
    315               solver->setColUpper(j,CoinMin(tightUpper[j],upper[j]));
    316               if (tightLower[j]>solution[j]+primalTolerance||
    317                   tightUpper[j]<solution[j]-primalTolerance)
     237      if ((model_->getThreadMode()&2)==0) {
     238        for (j=0;j<numberColumns;j++) {
     239          if (solver->isInteger(j)) {
     240            if (tightUpper[j]<upper[j]) {
     241              double nearest = floor(tightUpper[j]+0.5);
     242              //assert (fabs(tightUpper[j]-nearest)<1.0e-5); may be infeasible
     243              solver->setColUpper(j,nearest);
     244              if (nearest<solution[j]-primalTolerance)
    318245                returnCode=true;
    319246            }
     247            if (tightLower[j]>lower[j]) {
     248              double nearest = floor(tightLower[j]+0.5);
     249              //assert (fabs(tightLower[j]-nearest)<1.0e-5); may be infeasible
     250              solver->setColLower(j,nearest);
     251              if (nearest>solution[j]+primalTolerance)
     252                returnCode=true;
     253            }
     254          } else {
     255            if (upper[j]>lower[j]) {
     256              if (tightUpper[j]==tightLower[j]) {
     257                // fix
     258                solver->setColLower(j,tightLower[j]);
     259                solver->setColUpper(j,tightUpper[j]);
     260                if (tightLower[j]>solution[j]+primalTolerance||
     261                    tightUpper[j]<solution[j]-primalTolerance)
     262                  returnCode=true;
     263              } else if (tightenBounds&&tightenBounds[j]) {
     264                solver->setColLower(j,CoinMax(tightLower[j],lower[j]));
     265                solver->setColUpper(j,CoinMin(tightUpper[j],upper[j]));
     266                if (tightLower[j]>solution[j]+primalTolerance||
     267                    tightUpper[j]<solution[j]-primalTolerance)
     268                  returnCode=true;
     269              }
     270            }
    320271          }
    321         }
     272        }
     273      } else {
     274        CoinPackedVector lbs;
     275        CoinPackedVector ubs;
     276        int numberChanged=0;
     277        bool ifCut=false;
     278        for (j=0;j<numberColumns;j++) {
     279          if (solver->isInteger(j)) {
     280            if (tightUpper[j]<upper[j]) {
     281              double nearest = floor(tightUpper[j]+0.5);
     282              //assert (fabs(tightUpper[j]-nearest)<1.0e-5); may be infeasible
     283              ubs.insert(j,nearest);
     284              numberChanged++;
     285              if (nearest<solution[j]-primalTolerance)
     286                ifCut=true;
     287            }
     288            if (tightLower[j]>lower[j]) {
     289              double nearest = floor(tightLower[j]+0.5);
     290              //assert (fabs(tightLower[j]-nearest)<1.0e-5); may be infeasible
     291              lbs.insert(j,nearest);
     292              numberChanged++;
     293              if (nearest>solution[j]+primalTolerance)
     294                ifCut=true;
     295            }
     296          } else {
     297            if (upper[j]>lower[j]) {
     298              if (tightUpper[j]==tightLower[j]) {
     299                // fix
     300                lbs.insert(j,tightLower[j]);
     301                ubs.insert(j,tightUpper[j]);
     302                if (tightLower[j]>solution[j]+primalTolerance||
     303                    tightUpper[j]<solution[j]-primalTolerance)
     304                  ifCut=true;
     305              } else if (tightenBounds&&tightenBounds[j]) {
     306                lbs.insert(j,CoinMax(tightLower[j],lower[j]));
     307                ubs.insert(j,CoinMin(tightUpper[j],upper[j]));
     308                if (tightLower[j]>solution[j]+primalTolerance||
     309                    tightUpper[j]<solution[j]-primalTolerance)
     310                  ifCut=true;
     311              }
     312            }
     313          }
     314        }
     315        if (numberChanged) {
     316          OsiColCut cc;
     317          cc.setUbs(ubs);
     318          cc.setLbs(lbs);
     319          if (ifCut) {
     320            cc.setEffectiveness(100.0);
     321          } else {
     322            cc.setEffectiveness(1.0e-5);
     323          }
     324          cs.insert(cc);
     325        }
    322326      }
    323327      //if (!solver->basisIsAvailable())
    324328      //returnCode=true;
    325 #endif
    326329#if 0
    327330      // Pass across info to pseudocosts
     
    352355      int k ;
    353356      int nOdd=0;
    354       const OsiSolverInterface * solver = model_->solver();
     357      //const OsiSolverInterface * solver = model_->solver();
    355358      for (k = numberRowCutsAfter-1;k>=numberRowCutsBefore;k--) {
    356359        OsiRowCut & thisCut = cs.rowCut(k) ;
  • branches/devel/Cbc/src/CbcCutGenerator.hpp

    r482 r642  
    6464    If node then can find out depth
    6565  */
    66   bool generateCuts( OsiCuts &cs, bool fullScan,CbcNode * node);
     66  bool generateCuts( OsiCuts &cs, bool fullScan,OsiSolverInterface * solver,CbcNode * node);
    6767  //@}
    6868
     
    177177  inline double timeInCutGenerator() const
    178178  { return timeInCutGenerator_;};
     179  inline void incrementTimeInCutGenerator(double value)
     180  { timeInCutGenerator_ += value;};
    179181  /// Get the \c CglCutGenerator corresponding to this \c CbcCutGenerator.
    180182  inline CglCutGenerator * generator() const
     
    237239  inline void setNumberActiveCutsAtRoot(int value)
    238240  { numberActiveCutsAtRoot_ = value;};
     241  /// Set model
     242  inline void setModel(CbcModel * model)
     243  { model_ = model;};
    239244  //@}
    240245 
  • branches/devel/Cbc/src/CbcFathom.cpp

    r310 r642  
    99#include <cfloat>
    1010
    11 #include "OsiSolverInterface.hpp"
     11#ifdef COIN_HAS_CLP
     12#include "OsiClpSolverInterface.hpp"
     13#endif
    1214#include "CbcModel.hpp"
    1315#include "CbcMessage.hpp"
     
    4547  model_ = model;
    4648}
     49#ifdef COIN_HAS_CLP
     50
     51//#############################################################################
     52// Constructors, destructors clone and assignment
     53//#############################################################################
     54
     55//-------------------------------------------------------------------
     56// Default Constructor
     57//-------------------------------------------------------------------
     58CbcOsiSolver::CbcOsiSolver ()
     59  : OsiClpSolverInterface()
     60{
     61  cbcModel_ = NULL;
     62}
     63//-------------------------------------------------------------------
     64// Clone
     65//-------------------------------------------------------------------
     66OsiSolverInterface *
     67CbcOsiSolver::clone(bool copyData) const
     68{
     69  assert (copyData);
     70  return new CbcOsiSolver(*this);
     71}
     72
     73
     74//-------------------------------------------------------------------
     75// Copy constructor
     76//-------------------------------------------------------------------
     77CbcOsiSolver::CbcOsiSolver (
     78                  const CbcOsiSolver & rhs)
     79  : OsiClpSolverInterface(rhs)
     80{
     81  cbcModel_ = rhs.cbcModel_;
     82}
     83
     84//-------------------------------------------------------------------
     85// Destructor
     86//-------------------------------------------------------------------
     87CbcOsiSolver::~CbcOsiSolver ()
     88{
     89}
     90
     91//-------------------------------------------------------------------
     92// Assignment operator
     93//-------------------------------------------------------------------
     94CbcOsiSolver &
     95CbcOsiSolver::operator=(const CbcOsiSolver& rhs)
     96{
     97  if (this != &rhs) {
     98    OsiClpSolverInterface::operator=(rhs);
     99    cbcModel_ = rhs.cbcModel_;
     100  }
     101  return *this;
     102}
     103#endif
  • branches/devel/Cbc/src/CbcFathom.hpp

    r36 r642  
    33#ifndef CbcFathom_H
    44#define CbcFathom_H
     5#include "CbcConfig.h"
    56
    67class CbcModel;
     
    6364 
    6465};
     66#ifdef COIN_HAS_CLP
     67#include "OsiClpSolverInterface.hpp"
    6568
     69//#############################################################################
     70
     71/**
     72   
     73This is for codes where solver needs to know about CbcModel
     74*/
     75
     76class CbcOsiSolver : public OsiClpSolverInterface {
     77 
     78public:
     79 
     80  /**@name Constructors and destructors */
     81  //@{
     82  /// Default Constructor
     83  CbcOsiSolver ();
     84 
     85  /// Clone
     86  virtual OsiSolverInterface * clone(bool copyData=true) const;
     87 
     88  /// Copy constructor
     89  CbcOsiSolver (const CbcOsiSolver &);
     90 
     91  /// Assignment operator
     92  CbcOsiSolver & operator=(const CbcOsiSolver& rhs);
     93 
     94  /// Destructor
     95  virtual ~CbcOsiSolver ();
     96 
     97  //@}
     98 
     99 
     100  /**@name Sets and Gets */
     101  //@{
     102  /// Set Cbc Model
     103  inline void setCbcModel(CbcModel * model)
     104  { cbcModel_=model;};
     105  /// Return Cbc Model
     106  inline CbcModel * cbcModel() const
     107  { return cbcModel_;};
     108  //@}
     109 
     110  //---------------------------------------------------------------------------
     111 
     112protected:
     113 
     114 
     115  /**@name Private member data */
     116  //@{
     117  /// Pointer back to CbcModel
     118  CbcModel * cbcModel_;
     119  //@}
     120};
    66121#endif
     122#endif
  • branches/devel/Cbc/src/CbcHeuristic.cpp

    r607 r642  
    178178      // probably faster to use a basis to get integer solutions
    179179      model.setSpecialOptions(2);
     180#ifdef CBC_THREAD
     181      if (model_->getNumberThreads()>0&&(model_->getThreadMode()&1)!=0) {
     182        // See if at root node
     183        bool atRoot = model_->getNodeCount()==0;
     184        int passNumber = model_->getCurrentPassNumber();
     185        if (atRoot&&passNumber==1)
     186          model.setNumberThreads(model_->getNumberThreads());
     187      }
     188#endif
    180189      model.branchAndBound();
    181190      if (logLevel>1)
     
    302311      (when()%10==2&&(model_->phase()!=2&&model_->phase()!=3)))
    303312    return 0; // switched off
    304 
    305313  OsiSolverInterface * solver = model_->solver();
    306314  const double * lower = solver->getColLower();
     
    315323
    316324  int numberRows = matrix_.getNumRows();
    317 
     325  assert (numberRows<=solver->getNumRows());
    318326  int numberIntegers = model_->numberIntegers();
    319327  const int * integerVariable = model_->integerVariable();
     
    322330  double newSolutionValue = direction*solver->getObjValue();
    323331  int returnCode = 0;
    324 
    325332  // Column copy
    326333  const double * element = matrix_.getElements();
     
    893900      }
    894901    }
     902    // Just in case of some stupidity
     903    double objOffset=0.0;
     904    solver->getDblParam(OsiObjOffset,objOffset);
     905    newSolutionValue = -objOffset;
     906    for ( i=0 ; i<numberColumns ; i++ )
     907      newSolutionValue += objective[i]*newSolution[i];
     908    newSolutionValue *= direction;
     909    //printf("new solution value %g %g\n",newSolutionValue,solutionValue);
    895910    if (newSolutionValue<solutionValue) {
    896911      // paranoid check
  • branches/devel/Cbc/src/CbcHeuristic.hpp

    r607 r642  
    7979  inline int numberNodes() const
    8080  { return numberNodes_;};
     81  /// Just set model - do not do anything else
     82  inline void setModelOnly(CbcModel * model)
     83  { model_ = model;};
     84 
    8185
    8286  /// Sets fraction of new(rows+columns)/old(rows+columns) before doing small branch and bound (default 1.0)
  • branches/devel/Cbc/src/CbcHeuristicFPump.cpp

    r625 r642  
    175175                         double * betterSolution)
    176176{
     177#define LEN_PRINT 132
     178  char pumpPrint[LEN_PRINT];
     179  pumpPrint[0]='\0';
    177180  if (!when()||(when()==1&&model_->phase()!=1))
    178181    return 0; // switched off
     
    364367      }
    365368      if (maximumTime_>0.0&&CoinCpuTime()>=startTime_+maximumTime_) break;
    366       numberPasses++;
    367369      memcpy(newSolution,solution,numberColumns*sizeof(double));
    368370      int flip;
    369       returnCode = rounds(solver,newSolution,saveObjective,numberIntegers,integerVariable,
    370                           roundExpensive_,defaultRounding_,&flip);
     371      returnCode = rounds(solver, newSolution,saveObjective,numberIntegers,integerVariable,
     372                          pumpPrint,numberPasses,roundExpensive_,defaultRounding_,&flip);
     373      numberPasses++;
    371374      if (returnCode) {
    372375        // SOLUTION IS INTEGER
     
    382385          newSolutionValue += saveObjective[i]*newSolution[i];
    383386        newSolutionValue *= direction;
    384         if (model_->logLevel())
    385           printf(" - solution found of %g",newSolutionValue);
     387        sprintf(pumpPrint+strlen(pumpPrint)," - solution found of %g",newSolutionValue);
    386388        newLineNeeded=false;
    387389        if (newSolutionValue<solutionValue) {
     
    416418            solutionFound=true;
    417419            if (general&&saveValue!=newSolutionValue)
    418               printf(" - cleaned solution of %g\n",solutionValue);
    419             else
    420               printf("\n");
     420              sprintf(pumpPrint+strlen(pumpPrint)," - cleaned solution of %g",solutionValue);
     421            if (pumpPrint[0]!='\0')
     422              model_->messageHandler()->message(CBC_FPUMP1,model_->messages())
     423                << pumpPrint
     424                <<CoinMessageEol;
     425            pumpPrint[0]='\0';
    421426          } else {
    422           if (model_->logLevel())
    423             printf(" - not good enough after small branch and bound\n");
     427            sprintf(pumpPrint+strlen(pumpPrint)," - not good enough after mini branch and bound");
     428            model_->messageHandler()->message(CBC_FPUMP1,model_->messages())
     429              << pumpPrint
     430              <<CoinMessageEol;
     431            pumpPrint[0]='\0';
    424432          }
    425433        } else {
    426           if (model_->logLevel())
    427             printf(" - not good enough\n");
     434          sprintf(pumpPrint+strlen(pumpPrint)," - not good enough");
     435          model_->messageHandler()->message(CBC_FPUMP1,model_->messages())
     436            << pumpPrint
     437            <<CoinMessageEol;
     438          pumpPrint[0]='\0';
    428439          newLineNeeded=false;
    429440          returnCode=0;
     
    448459        if (matched || numberPasses%100 == 0) {
    449460          // perturbation
    450           if (model_->logLevel())
    451             printf("Perturbation applied");
     461          sprintf(pumpPrint+strlen(pumpPrint)," perturbation applied");
    452462          newLineNeeded=true;
    453463          for (i=0;i<numberIntegers;i++) {
     
    531541          memcpy(newSolution,solution,numberColumns*sizeof(double));
    532542          int flip;
    533           returnCode = rounds(solver,newSolution,saveObjective,numberIntegers,integerVariable,
    534                               roundExpensive_,defaultRounding_,&flip);
     543          returnCode = rounds(solver, newSolution,saveObjective,numberIntegers,integerVariable,
     544                              pumpPrint,numberPasses,roundExpensive_,defaultRounding_,&flip);
     545          numberPasses++;
    535546          if (returnCode) {
    536547            // solution - but may not be better
     
    540551              newSolutionValue += saveObjective[i]*newSolution[i];
    541552            newSolutionValue *= direction;
    542             if (model_->logLevel())
    543               printf(" - intermediate solution found of %g",newSolutionValue);
     553            sprintf(pumpPrint+strlen(pumpPrint)," - intermediate solution found of %g",newSolutionValue);
    544554            if (newSolutionValue<solutionValue) {
    545555              memcpy(betterSolution,newSolution,numberColumns*sizeof(double));
     
    636646          }
    637647        }
    638         if (model_->logLevel())
    639           printf("\npass %3d: obj. %10.5f --> ", numberPasses+totalNumberPasses,solver->getObjValue());
     648        if (pumpPrint[0]!='\0')
     649          model_->messageHandler()->message(CBC_FPUMP1,model_->messages())
     650            << pumpPrint
     651            <<CoinMessageEol;
     652        pumpPrint[0]='\0';
     653        sprintf(pumpPrint+strlen(pumpPrint),"Pass %3d: obj. %10.5f --> ", numberPasses+totalNumberPasses,solver->getObjValue());
    640654        if (closestSolution&&solver->getObjValue()<closestObjectiveValue) {
    641655          int i;
     
    656670      scaleFactor *= weightFactor_;
    657671    } // END WHILE
    658     if (newLineNeeded&&model_->logLevel())
    659       printf(" - no solution found\n");
     672    if (!solutionFound) {
     673      sprintf(pumpPrint+strlen(pumpPrint),"No solution found this major pass");
     674      model_->messageHandler()->message(CBC_FPUMP1,model_->messages())
     675        << pumpPrint
     676        <<CoinMessageEol;
     677      pumpPrint[0]='\0';
     678    }
    660679    delete solver;
    661680    for ( j=0;j<NUMBER_OLD;j++)
     
    724743      newSolver->initialSolve();
    725744      if (!newSolver->isProvenOptimal()) {
    726         newSolver->writeMps("bad.mps");
     745        //newSolver->writeMps("bad.mps");
    727746        assert (newSolver->isProvenOptimal());
    728747        break;
    729748      }
    730       printf("%d integers at bound fixed and %d continuous",
     749      sprintf(pumpPrint+strlen(pumpPrint),"Before mini branch and bound, %d integers at bound fixed and %d continuous",
    731750             nFix,nFixC);
    732       if (nFixC2+nFixI==0)
    733         printf("\n");
    734       else
    735         printf(" of which %d were internal integer and %d internal continuous\n",
    736              nFixI,nFixC2);
     751      if (nFixC2+nFixI!=0)
     752        sprintf(pumpPrint+strlen(pumpPrint)," of which %d were internal integer and %d internal continuous",
     753                nFixI,nFixC2);
     754      model_->messageHandler()->message(CBC_FPUMP1,model_->messages())
     755        << pumpPrint
     756        <<CoinMessageEol;
     757      pumpPrint[0]='\0';
    737758      double saveValue = newSolutionValue;
    738759      returnCode = smallBranchAndBound(newSolver,numberNodes_,newSolution,newSolutionValue,
    739                                        newSolutionValue,"CbcHeuristicLocalAfterFPump");
     760                                       cutoff,"CbcHeuristicLocalAfterFPump");
    740761      if ((returnCode&2)!=0) {
    741762        // could add cut
     
    743764      }
    744765      if (returnCode) {
    745         printf("old sol of %g new of %g\n",saveValue,newSolutionValue);
     766        sprintf(pumpPrint+strlen(pumpPrint),"Mini branch and bound improved solution from %g to %g",saveValue,newSolutionValue);
     767        model_->messageHandler()->message(CBC_FPUMP1,model_->messages())
     768          << pumpPrint
     769          <<CoinMessageEol;
     770        pumpPrint[0]='\0';
    746771        memcpy(betterSolution,newSolution,numberColumns*sizeof(double));
    747772        if (fixContinuous) {
     
    763788            double value = newSolver->getObjValue()*newSolver->getObjSense();
    764789            if (value<newSolutionValue) {
    765               printf("freeing continuous gives a solution of %g\n", value);
     790              sprintf(pumpPrint+strlen(pumpPrint),"Freeing continuous variables gives a solution of %g", value);
     791              model_->messageHandler()->message(CBC_FPUMP1,model_->messages())
     792                << pumpPrint
     793                <<CoinMessageEol;
     794              pumpPrint[0]='\0';
    766795              newSolutionValue=value;
    767796              memcpy(betterSolution,newSolver->getColSolution(),numberColumns*sizeof(double));
    768797            }
    769798          } else {
    770             newSolver->writeMps("bad3.mps");
     799            //newSolver->writeMps("bad3.mps");
    771800          }
    772801        }
     
    786815      double gap = relativeIncrement_*fabs(solutionValue);
    787816      cutoff -= CoinMax(CoinMax(gap,absoluteIncrement_),model_->getCutoffIncrement());
    788       printf("round again with cutoff of %g\n",cutoff);
     817      sprintf(pumpPrint+strlen(pumpPrint),"Round again with cutoff of %g",cutoff);
     818      model_->messageHandler()->message(CBC_FPUMP1,model_->messages())
     819        << pumpPrint
     820        <<CoinMessageEol;
     821      pumpPrint[0]='\0';
    789822      if ((accumulate_&3)<2&&usedColumn)
    790823        memset(usedColumn,0,numberColumns);
    791       totalNumberPasses += numberPasses;
     824      totalNumberPasses += numberPasses-1;
    792825    } else {
    793826      break;
     
    817850    newSolver->addRow(numberIntegersOrig,closestSolution,
    818851                      lastSolution,-COIN_DBL_MAX,rhs+10.0);
    819     double saveValue = newSolutionValue;
     852    //double saveValue = newSolutionValue;
    820853    //newSolver->writeMps("sub");
    821854    int returnCode = smallBranchAndBound(newSolver,numberNodes_,newSolution,newSolutionValue,
     
    857890                          const double * objective,
    858891                          int numberIntegers, const int * integerVariable,
     892                          char * pumpPrint, int & iter,
    859893                          bool roundExpensive, double downValue, int *flip)
    860894{
     
    865899  int i;
    866900
    867   static int iter = 0;
    868901  int numberColumns = model_->getNumCols();
    869902  // tmp contains the current obj coefficients
     
    905938
    906939  if (nnv > nn) nnv = nn;
    907   if (iter != 0&&model_->logLevel())
    908     printf("up = %5d , down = %5d", flip_up, flip_down); fflush(stdout);
     940  if (iter != 0)
     941    sprintf(pumpPrint+strlen(pumpPrint),"up = %5d , down = %5d", flip_up, flip_down);
    909942  *flip = flip_up + flip_down;
    910943  delete [] tmp;
     
    913946  const double * columnUpper = solver->getColUpper();
    914947  if (*flip == 0 && iter != 0) {
    915     if(model_->logLevel())
    916       printf(" -- rand = %4d (%4d) ", nnv, nn);
     948    sprintf(pumpPrint+strlen(pumpPrint)," -- rand = %4d (%4d) ", nnv, nn);
    917949     for (i = 0; i < nnv; i++) {
    918950       // was solution[list[i]] = 1. - solution[list[i]]; but does that work for 7>=x>=6
     
    930962     }
    931963     *flip = nnv;
    932   } else if (model_->logLevel()) {
    933     printf(" ");
     964  } else {
     965    //sprintf(pumpPrint+strlen(pumpPrint)," ");
    934966  }
    935967  delete [] list; delete [] val;
    936   iter++;
     968  //iter++;
    937969   
    938970  const double * rowLower = solver->getRowLower();
  • branches/devel/Cbc/src/CbcHeuristicFPump.hpp

    r625 r642  
    165165  int rounds(OsiSolverInterface * solver,double * solution, const double * objective,
    166166             int numberIntegers, const int * integerVariable,
     167             char * pumpPrint,int & passNumber,
    167168             bool roundExpensive=false,
    168169             double downValue=0.5, int *flip=0);
  • branches/devel/Cbc/src/CbcHeuristicGreedy.cpp

    r502 r642  
    764764      memcpy(betterSolution,newSolution,numberColumns*sizeof(double));
    765765      solutionValue = newSolutionValue;
    766       model_->messageHandler()->message(CBC_HEURISTIC_SOLUTION,model_->messages())
    767         << newSolutionValue
    768         << "CbcHeuristicGreedy"<<model_->getCurrentSeconds()
    769         <<CoinMessageEol;
    770766      returnCode=1;
    771767    }
  • branches/devel/Cbc/src/CbcHeuristicLocal.cpp

    r502 r642  
    549549        returnCode=1;
    550550        solutionValue = newSolutionValue + bestChange;
    551         if (bestChange<-1.0e-1)
    552           model_->messageHandler()->message(CBC_HEURISTIC_SOLUTION,model_->messages())
    553             << solutionValue
    554             << "CbcHeuristicLocal"<<model_->getCurrentSeconds()
    555             <<CoinMessageEol;
    556551      } else {
    557552        // bad solution - should not happen so debug if see message
  • branches/devel/Cbc/src/CbcLinked.cpp

    r612 r642  
    1313#include "CoinModel.hpp"
    1414#include "ClpSimplex.hpp"
     15#include "ClpAmplObjective.hpp"
    1516// returns jColumn (-2 if linear term, -1 if unknown) and coefficient
    1617static
     
    185186  if (modelPtr_->status()==0&&(secondaryStatus==2||secondaryStatus==4))
    186187    modelPtr_->cleanup(1);
    187   if (!isProvenOptimal())
    188     writeMps("yy");
     188  //if (!isProvenOptimal())
     189  //writeMps("yy");
    189190  if (isProvenOptimal()&&quadraticModel_&&modelPtr_->numberColumns()==quadraticModel_->numberColumns()) {
    190191    // see if qp can get better solution
     
    233234          int numberGenerators = cbcModel_->numberCutGenerators();
    234235          int iGenerator;
     236          cbcModel_->lockThread();
    235237          for (iGenerator=0;iGenerator<numberGenerators;iGenerator++) {
    236238            CbcCutGenerator * generator = cbcModel_->cutGenerator(iGenerator);
     
    263265            }
    264266          }
     267          cbcModel_->unlockThread();
    265268        }
    266269      }
     
    461464          bestSolution_ = CoinCopyOfArray(modelPtr_->getColSolution(),modelPtr_->getNumCols());
    462465          bestObjectiveValue_ = value;
     466          if (maxIts<=10000&&cbcModel_) {
     467            OsiSolverLink * solver2 = dynamic_cast<OsiSolverLink *> (cbcModel_->solver());
     468            assert (solver2);
     469            if (solver2!=this) {
     470              // in strong branching - need to store in original solver
     471              if (value<solver2->bestObjectiveValue_-1.0e-3) {
     472                delete [] solver2->bestSolution_;
     473                solver2->bestSolution_ = CoinCopyOfArray(bestSolution_,modelPtr_->getNumCols());
     474                solver2->bestObjectiveValue_ = value;
     475              }
     476            }
     477          }
    463478          // If model has stored then add cut (if convex)
    464479          if (cbcModel_&&(specialOptions2_&4)!=0&&quadraticModel_) {
     
    470485              CglStored * gen2 = dynamic_cast<CglStored *> (gen);
    471486              if (gen2) {
     487                cbcModel_->lockThread();
    472488                // add OA cut
    473                 double offset;
     489                double offset=0.0;
    474490                int numberColumns = quadraticModel_->numberColumns();
    475491                double * gradient = new double [numberColumns+1];
     
    492508                    int yColumn = obj->yColumn();
    493509                    if (xColumn!=yColumn) {
    494                       double coefficient = 2.0*obj->coefficient();
     510                      double coefficient = /* 2.0* */obj->coefficient();
    495511                      gradient[xColumn] += coefficient*solution[yColumn];
    496512                      gradient[yColumn] += coefficient*solution[xColumn];
     
    520536                delete [] gradient;
    521537                delete [] column;
     538                cbcModel_->unlockThread();
    522539                break;
    523540              }
     
    634651          delete [] lower2;
    635652          delete [] upper2;
    636           if (isProvenOptimal())
    637             writeMps("zz");
     653          //if (isProvenOptimal())
     654          //writeMps("zz");
    638655        }
    639656      }
     
    652669            CglTemporary * gen2 = dynamic_cast<CglTemporary *> (gen);
    653670            if (gen2) {
     671              cbcModel_->lockThread();
    654672              const double * solution = getColSolution();
    655673              // add OA cut
    656               double offset;
     674              double offset=0.0;
    657675              int numberColumns = quadraticModel_->numberColumns();
    658676              double * gradient = new double [numberColumns+1];
     
    677695                  int yColumn = obj->yColumn();
    678696                  if (xColumn!=yColumn) {
    679                     double coefficient = 2.0*obj->coefficient();
     697                    double coefficient = /* 2.0* */obj->coefficient();
    680698                    gradient[xColumn] += coefficient*solution[yColumn];
    681699                    gradient[yColumn] += coefficient*solution[xColumn];
     
    710728              delete [] gradient;
    711729              delete [] column;
     730              cbcModel_->unlockThread();
    712731              break;
    713732            }
     
    735754            //const double * columnLower = modelPtr_->columnLower();
    736755            //const double * columnUpper = modelPtr_->columnUpper();
     756            cbcModel_->lockThread();
    737757            for (int iNon=0;iNon<numberNonLinearRows_;iNon++) {
    738758              int iRow = rowNonLinear_[iNon];
     
    754774                int yColumn = obj->yColumn();
    755775                if (xColumn!=yColumn) {
    756                   double coefficient = 2.0*obj->coefficient();
     776                  double coefficient = /* 2.0* */obj->coefficient();
    757777                  gradient[xColumn] += coefficient*solution[yColumn];
    758778                  gradient[yColumn] += coefficient*solution[xColumn];
     
    791811                gen2->addCut(offset-1.0e-7,COIN_DBL_MAX,n,column,gradient);
    792812            }
     813            cbcModel_->unlockThread();
    793814            delete [] gradient;
    794815            delete [] column;
     
    812833//-------------------------------------------------------------------
    813834OsiSolverLink::OsiSolverLink ()
    814   : OsiClpSolverInterface()
     835  : CbcOsiSolver()
    815836{
    816837  gutsOfDestructor(true);
     
    893914*/
    894915OsiSolverLink::OsiSolverLink ( CoinModel & coinModel)
    895   : OsiClpSolverInterface()
     916  : CbcOsiSolver()
    896917{
    897918  gutsOfDestructor(true);
     
    899920}
    900921// need bounds
    901 static void fakeBounds(OsiSolverInterface * solver,int column,double maximumValue)
     922static void fakeBounds(OsiSolverInterface * solver,int column,double maximumValue,
     923                       CoinModel * model1, CoinModel * model2)
    902924{
    903925  double lo = solver->getColLower()[column];
    904   if (lo<-maximumValue)
     926  if (lo<-maximumValue) {
    905927    solver->setColLower(column,-maximumValue);
     928    if (model1)
     929      model1->setColLower(column,-maximumValue);
     930    if (model2)
     931      model2->setColLower(column,-maximumValue);
     932  }
    906933  double up = solver->getColUpper()[column];
    907   if (up>maximumValue)
     934  if (up>maximumValue) {
    908935    solver->setColUpper(column,maximumValue);
    909 }
    910 void OsiSolverLink::load ( CoinModel & coinModel, bool tightenBounds,int logLevel)
     936    if (model1)
     937      model1->setColUpper(column,maximumValue);
     938    if (model2)
     939      model2->setColUpper(column,maximumValue);
     940  }
     941}
     942void OsiSolverLink::load ( CoinModel & coinModelOriginal, bool tightenBounds,int logLevel)
    911943{
    912944  // first check and set up arrays
    913   int numberColumns = coinModel.numberColumns();
    914   int numberRows = coinModel.numberRows();
     945  int numberColumns = coinModelOriginal.numberColumns();
     946  int numberRows = coinModelOriginal.numberRows();
    915947  // List of nonlinear entries
    916948  int * which = new int[numberColumns];
     
    920952  int numberErrors=0;
    921953  for (iColumn=0;iColumn<numberColumns;iColumn++) {
    922     CoinModelLink triple=coinModel.firstInColumn(iColumn);
     954    CoinModelLink triple=coinModelOriginal.firstInColumn(iColumn);
    923955    bool linear=true;
    924956    int n=0;
    925957    // See if quadratic objective
    926     const char * expr = coinModel.getColumnObjectiveAsString(iColumn);
     958    const char * expr = coinModelOriginal.getColumnObjectiveAsString(iColumn);
    927959    if (strcmp(expr,"Numeric")) {
    928960      linear=false;
     
    930962    while (triple.row()>=0) {
    931963      int iRow = triple.row();
    932       const char * expr = coinModel.getElementAsString(iRow,iColumn);
     964      const char * expr = coinModelOriginal.getElementAsString(iRow,iColumn);
    933965      if (strcmp(expr,"Numeric")) {
    934966        linear=false;
    935967      }
    936       triple=coinModel.next(triple);
     968      triple=coinModelOriginal.next(triple);
    937969      n++;
    938970    }
     
    944976  if (!numberVariables_) {
    945977    delete [] which;
    946     coinModel_ = coinModel;
     978    coinModel_ = coinModelOriginal;
    947979    int nInt=0;
    948980    for (iColumn=0;iColumn<numberColumns;iColumn++) {   
     
    951983    }
    952984    printf("There are %d integers\n",nInt);
    953     loadFromCoinModel(coinModel,true);
     985    loadFromCoinModel(coinModelOriginal,true);
    954986    OsiObject ** objects = new OsiObject * [nInt];
    955987    nInt=0;
     
    9681000    return;
    9691001  } else {
    970     coinModel_ = coinModel;
     1002    coinModel_ = coinModelOriginal;
    9711003    // arrays for tightening bounds
    9721004    int * freeRow = new int [numberRows];
     
    10041036          ifFirst=false;
    10051037        }
    1006         coinModel.setObjective(iColumn,linearTerm);
     1038        coinModelOriginal.setObjective(iColumn,linearTerm);
    10071039      }
    10081040    }
     
    10391071            ifFirst=false;
    10401072          }
    1041           coinModel.setElement(iRow,iColumn,linearTerm);
     1073          coinModelOriginal.setElement(iRow,iColumn,linearTerm);
    10421074        }
    10431075        triple=coinModel_.next(triple);
     
    10531085    }
    10541086    printf("There are %d bilinear and %d integers\n",nBi,nInt);
    1055     loadFromCoinModel(coinModel,true);
     1087    loadFromCoinModel(coinModelOriginal,true);
     1088    CoinModel coinModel = coinModelOriginal;
    10561089    if (tightenBounds&&numberColumns<100) {
    10571090      // first fake bounds
    10581091      for (iColumn=0;iColumn<numberColumns;iColumn++) {
    10591092        if (tryColumn[iColumn]) {
    1060           fakeBounds(this,iColumn,defaultBound_);
     1093          fakeBounds(this,iColumn,defaultBound_,&coinModel,&coinModel_);
    10611094        }
    10621095      }
     
    10911124            columnLower[iColumn]=value;
    10921125            coinModel_.setColumnLower(iColumn,value);
     1126            coinModel.setColumnLower(iColumn,value);
    10931127          }
    10941128          objective[iColumn]=-1.0;
     
    11021136            columnUpper[iColumn]=value;
    11031137            coinModel_.setColumnUpper(iColumn,value);
     1138            coinModel.setColumnUpper(iColumn,value);
    11041139          }
    11051140          objective[iColumn]=0.0;
     
    11271162      // add in objective as constraint
    11281163      objectiveVariable_= numberColumns;
    1129       objectiveRow_ = modelPtr_->numberRows();
    1130       addCol(0,NULL,NULL,-COIN_DBL_MAX,COIN_DBL_MAX,1.0);
     1164      objectiveRow_ = coinModel.numberRows();
     1165      coinModel.addColumn(0,NULL,NULL,-COIN_DBL_MAX,COIN_DBL_MAX,1.0);
    11311166      int * column = new int[numberColumns+1];
    11321167      double * element = new double[numberColumns+1];
    1133       double * objective = modelPtr_->objective();
     1168      double * objective = coinModel.objectiveArray();
    11341169      int n=0;
    1135       int starts[2]={0,0};
    11361170      for (int i=0;i<numberColumns;i++) {
    11371171        if (objective[i]) {
     
    11431177      column[n]=objectiveVariable_;
    11441178      element[n++]=-1.0;
    1145       starts[1]=n;
    1146       double offset = - modelPtr_->objectiveOffset();
     1179      double offset = - coinModel.objectiveOffset();
    11471180      assert (!offset); // get sign right if happens
    1148       modelPtr_->setObjectiveOffset(0.0);
     1181      coinModel.setObjectiveOffset(0.0);
    11491182      double lowerBound = -COIN_DBL_MAX;
    1150       addRows(1,starts,column,element,&lowerBound,&offset);
     1183      coinModel.addRow(n,column,element,lowerBound,offset);
    11511184      delete [] column;
    11521185      delete [] element;
     
    11661199      if (strcmp(expr,"Numeric")) {
    11671200        // need bounds
    1168         fakeBounds(this,iColumn,defaultBound_);
     1201        fakeBounds(this,iColumn,defaultBound_,&coinModel,&coinModel_);
    11691202        // value*x*y
    11701203        char temp[20000];
     
    11791212            if (quadraticObjective) {
    11801213              columnQuadratic[numberQuadratic]=jColumn;
    1181               elementQuadratic[numberQuadratic++]=2.0*value; // convention
     1214              if (jColumn==iColumn)
     1215                elementQuadratic[numberQuadratic++]=2.0*value; // convention
     1216              else
     1217                elementQuadratic[numberQuadratic++]=1.0*value; // convention
    11821218            }
    11831219            // need bounds
    1184             fakeBounds(this,jColumn,defaultBound_);
     1220            fakeBounds(this,jColumn,defaultBound_,&coinModel,&coinModel_);
    11851221            double meshI = coinModel_.isInteger(iColumn) ? 1.0 : 0.0;
    11861222            if (meshI)
     
    12091245              meshJ=0.0;
    12101246            }
    1211             OsiBiLinear * newObj = new OsiBiLinear(this,iColumn,jColumn,objectiveRow_,value,meshI,meshJ,
     1247            OsiBiLinear * newObj = new OsiBiLinear(&coinModel,iColumn,jColumn,objectiveRow_,value,meshI,meshJ,
    12121248                                                   nBi-nInt,(const OsiObject **) (objects+nInt));
    12131249            newObj->setPriority(biLinearPriority_);
     
    12401276        if (strcmp("Numeric",el)) {
    12411277          // need bounds
    1242           fakeBounds(this,iColumn,defaultBound_);
     1278          fakeBounds(this,iColumn,defaultBound_,&coinModel,&coinModel_);
    12431279          // value*x*y
    12441280          char temp[20000];
     
    12521288            if (jColumn>=0) {
    12531289              // need bounds
    1254               fakeBounds(this,jColumn,defaultBound_);
     1290              fakeBounds(this,jColumn,defaultBound_,&coinModel,&coinModel_);
    12551291              double meshI = coinModel_.isInteger(iColumn) ? 1.0 : 0.0;
    12561292              if (meshI)
     
    12791315                meshJ=0.0;
    12801316              }
    1281               OsiBiLinear * newObj = new OsiBiLinear(this,iColumn,jColumn,iRow,value,meshI,meshJ,
     1317              OsiBiLinear * newObj = new OsiBiLinear(&coinModel,iColumn,jColumn,iRow,value,meshI,meshJ,
    12821318                                                     nBi-nInt,(const OsiObject **) (objects+nInt));
    12831319              newObj->setPriority(biLinearPriority_);
     
    13081344             stats[0],stats[1],stats[2],nBi-nInt-nDiff);
    13091345    }
     1346    // reload with all bilinear stuff
     1347    loadFromCoinModel(coinModel,true);
     1348    //exit(77);
    13101349    nInt=0;
    13111350    for (iColumn=0;iColumn<numberColumns;iColumn++) {   
     
    15021541  delete [] newObject;
    15031542}
     1543/* Set options and priority on all or some biLinear variables
     1544   1 - on I-I
     1545   2 - on I-x
     1546   4 - on x-x
     1547      or combinations.
     1548      -1 means leave (for priority value and strategy value)
     1549*/
     1550void
     1551OsiSolverLink::setBranchingStrategyOnVariables(int strategyValue, int priorityValue,
     1552                                               int mode)
     1553{
     1554  int i;
     1555  for ( i =0;i<numberObjects_;i++) {
     1556    OsiBiLinear * obj = dynamic_cast<OsiBiLinear *> (object_[i]);
     1557    if (obj) {
     1558      bool change=false;
     1559      if (obj->xMeshSize()<1.0&&obj->yMeshSize()<1.0&&(mode&4)!=0)
     1560        change=true;
     1561      else if (((obj->xMeshSize()==1.0&&obj->yMeshSize()<1.0)||
     1562                (obj->xMeshSize()<1.0&&obj->yMeshSize()==1.0))&&(mode&2)!=0)
     1563        change=true;
     1564      else if (obj->xMeshSize()==1.0&&obj->yMeshSize()==1.0&&(mode&1)!=0)
     1565        change=true;
     1566      else if (obj->xMeshSize()>1.0||obj->yMeshSize()>1.0)
     1567        abort();
     1568      if (change) {
     1569        if (strategyValue>=0)
     1570          obj->setBranchingStrategy(strategyValue);
     1571        if (priorityValue>=0)
     1572          obj->setPriority(priorityValue);
     1573      }
     1574    }
     1575  }
     1576}
     1577
    15041578// Say convex (should work it out)
    15051579void
     
    17121786  }
    17131787  model.initialSolve();
    1714   model.writeMps("bad.mps");
     1788  //model.writeMps("bad.mps");
    17151789  // redo number of columns
    17161790  numberColumns = model.numberColumns();
     
    20792153      char temp[20];
    20802154      sprintf(temp,"pass%d.mps",iPass);
    2081       model.writeMps(temp);
     2155      //model.writeMps(temp);
    20822156#ifdef CLP_DEBUG
    20832157      if (model.status()) {
     
    21382212      }
    21392213      model.primal(1);
    2140       model.writeMps("xx.mps");
     2214      //model.writeMps("xx.mps");
    21412215      iPass--;
    21422216      goodMove=-1;
     
    22702344    cbcModel->cutGenerator(6)->setTiming(true);
    22712345    // For now - switch off most heuristics (because CglPreProcess is bad with QP)
    2272 #if 0   
     2346#if 1   
    22732347    CbcHeuristicFPump heuristicFPump(*cbcModel);
    22742348    heuristicFPump.setWhen(13);
     
    22912365   
    22922366    CbcRounding rounding(*cbcModel);
     2367    rounding.setHeuristicName("rounding");
    22932368    cbcModel->addHeuristic(&rounding);
    22942369   
     
    23292404    // if convex
    23302405    if ((specialOptions2()&4)!=0) {
     2406      if (cbcModel_)
     2407        cbcModel_->lockThread();
    23312408      // add OA cut
    23322409      double offset;
     
    23502427      delete [] gradient;
    23512428      delete [] column;
     2429      if (cbcModel_)
     2430        cbcModel_->unlockThread();
    23522431    }
    23532432    delete qp;
     
    23692448  double * solution = CoinCopyOfArray(temp->primalColumnSolution(),numberColumns);
    23702449  delete temp;
     2450  if (mode==0) {
     2451    return solution;
     2452  } else if (mode==2) {
     2453    const double * lower = getColLower();
     2454    const double * upper = getColUpper();
     2455    for (int iObject =0;iObject<numberObjects_;iObject++) {
     2456      OsiSimpleInteger * obj = dynamic_cast<OsiSimpleInteger *> (object_[iObject]);
     2457      if (obj&&(obj->priority()<biLinearPriority_||biLinearPriority_<=0)) {
     2458        int iColumn = obj->columnNumber();
     2459        double value = solution[iColumn];
     2460        value = floor(value+0.5);
     2461        if (fabs(value-solution[iColumn])>0.01) {
     2462          setColLower(iColumn,CoinMax(lower[iColumn],value-CoinMax(defaultBound_,0.0)));
     2463          setColUpper(iColumn,CoinMin(upper[iColumn],value+CoinMax(defaultBound_,1.0)));
     2464        } else {
     2465          // could fix to integer
     2466          setColLower(iColumn,CoinMax(lower[iColumn],value-CoinMax(defaultBound_,0.0)));
     2467          setColUpper(iColumn,CoinMin(upper[iColumn],value+CoinMax(defaultBound_,0.0)));
     2468        }
     2469      }
     2470    }
     2471    return solution;
     2472  }
    23712473  OsiClpSolverInterface newSolver;
    23722474  if (mode==1) {
     
    23762478    tempModel = coinModel_;
    23772479    // solve modified problem
     2480    char * mark = new char[numberColumns];
     2481    memset(mark,0,numberColumns);
    23782482    for (int iObject =0;iObject<numberObjects_;iObject++) {
    23792483      OsiSimpleInteger * obj = dynamic_cast<OsiSimpleInteger *> (object_[iObject]);
     
    23832487        value = ceil(value-1.0e-7);
    23842488        tempModel.associateElement(coinModel_.columnName(iColumn),value);
    2385       }
    2386     }
     2489        mark[iColumn]=1;
     2490      }
     2491      OsiBiLinear * objB = dynamic_cast<OsiBiLinear *> (object_[iObject]);
     2492      if (objB) {
     2493        // if one or both continuous then fix one
     2494        if (objB->xMeshSize()<1.0) {
     2495          int xColumn = objB->xColumn();
     2496          double value = solution[xColumn];
     2497          tempModel.associateElement(coinModel_.columnName(xColumn),value);
     2498          mark[xColumn]=1;
     2499        } else if (objB->yMeshSize()<1.0) {
     2500          int yColumn = objB->yColumn();
     2501          double value = solution[yColumn];
     2502          tempModel.associateElement(coinModel_.columnName(yColumn),value);
     2503          mark[yColumn]=1;
     2504        }
     2505      }
     2506    }
     2507    CoinModel * reOrdered = tempModel.reorder(mark);
     2508    assert (reOrdered);
     2509    tempModel=*reOrdered;
     2510    delete reOrdered;
     2511    delete [] mark;
    23872512    newSolver.loadFromCoinModel(tempModel,true);
    23882513    for (int iObject =0;iObject<numberObjects_;iObject++) {
     
    23942519        newSolver.setColLower(iColumn,value);
    23952520        newSolver.setColUpper(iColumn,value);
     2521      }
     2522      OsiBiLinear * objB = dynamic_cast<OsiBiLinear *> (object_[iObject]);
     2523      if (objB) {
     2524        // if one or both continuous then fix one
     2525        if (objB->xMeshSize()<1.0) {
     2526          int xColumn = objB->xColumn();
     2527          double value = solution[xColumn];
     2528          newSolver.setColLower(xColumn,value);
     2529          newSolver.setColUpper(xColumn,value);
     2530        } else if (objB->yMeshSize()<1.0) {
     2531          int yColumn = objB->yColumn();
     2532          double value = solution[yColumn];
     2533          newSolver.setColLower(yColumn,value);
     2534          newSolver.setColUpper(yColumn,value);
     2535        }
    23962536      }
    23972537    }
     
    24912631    clpModel->setLogLevel(saveLogLevel);
    24922632    returnCode=-1; // infeasible//std::cout<<"Problem is infeasible - tightenPrimalBounds!"<<std::endl;
    2493     clpModel->writeMps("infeas2.mps");
     2633    //clpModel->writeMps("infeas2.mps");
    24942634  } else {
    24952635    clpModel->setLogLevel(saveLogLevel);
     
    27102850{
    27112851  assert (copyData);
    2712   return new OsiSolverLink(*this);
     2852  OsiSolverLink * newModel = new OsiSolverLink(*this);
     2853  return newModel;
    27132854}
    27142855
     
    27192860OsiSolverLink::OsiSolverLink (
    27202861                  const OsiSolverLink & rhs)
    2721   : OsiClpSolverInterface(rhs)
     2862  : CbcOsiSolver(rhs)
    27222863{
    27232864  gutsOfDestructor(true);
     
    27432884  if (this != &rhs) {
    27442885    gutsOfDestructor();
    2745     OsiClpSolverInterface::operator=(rhs);
     2886    CbcOsiSolver::operator=(rhs);
    27462887    gutsOfCopy(rhs);
    27472888  }
     
    27712912  convex_ = NULL;
    27722913  whichNonLinear_ = NULL;
    2773   cbcModel_ = NULL;
    27742914  info_ = NULL;
    27752915  fixVariables_=NULL;
     
    28012941  biLinearPriority_ = rhs.biLinearPriority_;
    28022942  numberFix_ = rhs.numberFix_;
    2803   cbcModel_ = rhs.cbcModel_;
    28042943  if (numberVariables_) {
    28052944    if (rhs.matrix_)
     
    30943233      }
    30953234    }
    3096     newSolver.writeMps("xx");
     3235    //newSolver.writeMps("xx");
    30973236    CbcModel model(newSolver);
    30983237    // Now do requested saves and modifications
     
    33183457          setRowBounds(i,-COIN_DBL_MAX,COIN_DBL_MAX);
    33193458        initialSolve();
    3320         if (!isProvenOptimal())
    3321           getModelPtr()->writeMps("bad.mps");
     3459        //if (!isProvenOptimal())
     3460        //getModelPtr()->writeMps("bad.mps");
    33223461        if (isProvenOptimal()) {
    33233462          delete [] bestSolution_;
     
    45174656  }
    45184657}
     4658// Useful constructor
     4659OsiBiLinear::OsiBiLinear (CoinModel * coinModel, int xColumn,
     4660                          int yColumn, int xyRow, double coefficient,
     4661                          double xMesh, double yMesh,
     4662                          int numberExistingObjects,const OsiObject ** objects )
     4663  : OsiObject2(),
     4664    coefficient_(coefficient),
     4665    xMeshSize_(xMesh),
     4666    yMeshSize_(yMesh),
     4667    xSatisfied_(1.0e-6),
     4668    ySatisfied_(1.0e-6),
     4669    xOtherSatisfied_(0.0),
     4670    yOtherSatisfied_(0.0),
     4671    xySatisfied_(1.0e-6),
     4672    xyBranchValue_(0.0),
     4673    xColumn_(xColumn),
     4674    yColumn_(yColumn),
     4675    firstLambda_(-1),
     4676    branchingStrategy_(0),
     4677    boundType_(0),
     4678    xRow_(-1),
     4679    yRow_(-1),
     4680    xyRow_(xyRow),
     4681    convexity_(-1),
     4682    chosen_(-1)
     4683{
     4684  double columnLower[4];
     4685  double columnUpper[4];
     4686  double objective[4];
     4687  double rowLower[3];
     4688  double rowUpper[3];
     4689  CoinBigIndex starts[5];
     4690  int index[16];
     4691  double element[16];
     4692  int i;
     4693  starts[0]=0;
     4694  // rows
     4695  int numberRows = coinModel->numberRows();
     4696  // convexity
     4697  rowLower[0]=1.0;
     4698  rowUpper[0]=1.0;
     4699  convexity_ = numberRows;
     4700  starts[1]=0;
     4701  // x
     4702  rowLower[1]=0.0;
     4703  rowUpper[1]=0.0;
     4704  index[0]=xColumn_;
     4705  element[0]=-1.0;
     4706  xRow_ = numberRows+1;
     4707  starts[2]=1;
     4708  int nAdd=2;
     4709  if (xColumn_!=yColumn_) {
     4710    rowLower[2]=0.0;
     4711    rowUpper[2]=0.0;
     4712    index[1]=yColumn;
     4713    element[1]=-1.0;
     4714    nAdd=3;
     4715    yRow_ = numberRows+2;
     4716    starts[3]=2;
     4717  } else {
     4718    yRow_=-1;
     4719    branchingStrategy_=1;
     4720  }
     4721  // may be objective
     4722  assert (xyRow_>=-1);
     4723  for (i=0;i<nAdd;i++) {
     4724    CoinBigIndex iStart = starts[i];
     4725    coinModel->addRow(starts[i+1]-iStart,index+iStart,element+iStart,rowLower[i],rowUpper[i]);
     4726  }
     4727  int n=0;
     4728  // order is LxLy, LxUy, UxLy and UxUy
     4729  firstLambda_ = coinModel->numberColumns();
     4730  // bit sloppy as theoretically could be infeasible but otherwise need to do more work
     4731  double xB[2];
     4732  double yB[2];
     4733  const double * lower = coinModel->columnLowerArray();
     4734  const double * upper = coinModel->columnUpperArray();
     4735  xB[0]=lower[xColumn_];
     4736  xB[1]=upper[xColumn_];
     4737  yB[0]=lower[yColumn_];
     4738  yB[1]=upper[yColumn_];
     4739  if (xMeshSize_!=floor(xMeshSize_)) {
     4740    // not integral
     4741    xSatisfied_ = CoinMax(xSatisfied_,0.51*xMeshSize_);
     4742    if (!yMeshSize_) {
     4743      xySatisfied_ = CoinMax(xySatisfied_,xSatisfied_*CoinMax(fabs(yB[0]),fabs(yB[1])));
     4744    }
     4745  }
     4746  if (yMeshSize_!=floor(yMeshSize_)) {
     4747    // not integral
     4748    ySatisfied_ = CoinMax(ySatisfied_,0.51*yMeshSize_);
     4749    if (!xMeshSize_) {
     4750      xySatisfied_ = CoinMax(xySatisfied_,ySatisfied_*CoinMax(fabs(xB[0]),fabs(xB[1])));
     4751    }
     4752  }
     4753  // adjust
     4754  double distance;
     4755  double steps;
     4756  if (xMeshSize_) {
     4757    distance = xB[1]-xB[0];
     4758    steps = floor ((distance+0.5*xMeshSize_)/xMeshSize_);
     4759    distance = xB[0]+xMeshSize_*steps;
     4760    if (fabs(xB[1]-distance)>xSatisfied_) {
     4761      printf("bad x mesh %g %g %g -> %g\n",xB[0],xMeshSize_,xB[1],distance);
     4762      //double newValue = CoinMax(fabs(xB[1]-distance),xMeshSize_);
     4763      //printf("xSatisfied increased to %g\n",newValue);
     4764      //xSatisfied_ = newValue;
     4765      //xB[1]=distance;
     4766      //coinModel->setColUpper(xColumn_,distance);
     4767    }
     4768  }
     4769  if (yMeshSize_) {
     4770    distance = yB[1]-yB[0];
     4771    steps = floor ((distance+0.5*yMeshSize_)/yMeshSize_);
     4772    distance = yB[0]+yMeshSize_*steps;
     4773    if (fabs(yB[1]-distance)>ySatisfied_) {
     4774      printf("bad y mesh %g %g %g -> %g\n",yB[0],yMeshSize_,yB[1],distance);
     4775      //double newValue = CoinMax(fabs(yB[1]-distance),yMeshSize_);
     4776      //printf("ySatisfied increased to %g\n",newValue);
     4777      //ySatisfied_ = newValue;
     4778      //yB[1]=distance;
     4779      //coinModel->setColUpper(yColumn_,distance);
     4780    }
     4781  }
     4782  for (i=0;i<4;i++) {
     4783    double x = (i<2) ? xB[0] : xB[1];
     4784    double y = ((i&1)==0) ? yB[0] : yB[1];
     4785    columnLower[i]=0.0;
     4786    columnUpper[i]=2.0;
     4787    objective[i]=0.0;
     4788    double value;
     4789    // xy
     4790    value=coefficient_*x*y;
     4791    if (xyRow_>=0) {
     4792      if (fabs(value)<1.0e-19)
     4793        value = 1.0e-19;
     4794      element[n]=value;
     4795      index[n++]=xyRow_;
     4796    } else {
     4797      objective[i]=value;
     4798    }
     4799    // convexity
     4800    value=1.0;
     4801    element[n]=value;
     4802    index[n++]=0+numberRows;
     4803    // x
     4804    value=x;
     4805    if (fabs(value)<1.0e-19)
     4806      value = 1.0e-19;
     4807    element[n]=value;
     4808    index[n++]=1+numberRows;
     4809    if (xColumn_!=yColumn_) {
     4810      // y
     4811      value=y;
     4812      if (fabs(value)<1.0e-19)
     4813      value = 1.0e-19;
     4814      element[n]=value;
     4815      index[n++]=2+numberRows;
     4816    }
     4817    starts[i+1]=n;
     4818  }
     4819  for (i=0;i<4;i++) {
     4820    CoinBigIndex iStart = starts[i];
     4821    coinModel->addColumn(starts[i+1]-iStart,index+iStart,element+iStart,columnLower[i],
     4822                         columnUpper[i],objective[i]);
     4823  }
     4824  // At least one has to have a mesh
     4825  if (!xMeshSize_&&(!yMeshSize_||yRow_<0)) {
     4826    printf("one of x and y must have a mesh size\n");
     4827    abort();
     4828  } else if (yRow_>=0) {
     4829    if (!xMeshSize_)
     4830      branchingStrategy_ = 2;
     4831    else if (!yMeshSize_)
     4832      branchingStrategy_ = 1;
     4833  }
     4834  // Now add constraints to link in x and or y to existing ones.
     4835  bool xDone=false;
     4836  bool yDone=false;
     4837  // order is LxLy, LxUy, UxLy and UxUy
     4838  for (i=numberExistingObjects-1;i>=0;i--) {
     4839    const OsiObject * obj = objects[i];
     4840    const OsiBiLinear * obj2 =
     4841      dynamic_cast <const OsiBiLinear *>(obj) ;
     4842    if (obj2) {
     4843      if (xColumn_==obj2->xColumn_&&!xDone) {
     4844        // make sure y equal
     4845        double rhs=0.0;
     4846        CoinBigIndex starts[2];
     4847        int index[4];
     4848        double element[4]= {1.0,1.0,-1.0,-1.0};
     4849        starts[0]=0;
     4850        starts[1]=4;
     4851        index[0]=firstLambda_+0;
     4852        index[1]=firstLambda_+1;
     4853        index[2]=obj2->firstLambda_+0;
     4854        index[3]=obj2->firstLambda_+1;
     4855        coinModel->addRow(4,index,element,rhs,rhs);
     4856        xDone=true;
     4857      }
     4858      if (yColumn_==obj2->yColumn_&&yRow_>=0&&!yDone) {
     4859        // make sure x equal
     4860        double rhs=0.0;
     4861        CoinBigIndex starts[2];
     4862        int index[4];
     4863        double element[4]= {1.0,1.0,-1.0,-1.0};
     4864        starts[0]=0;
     4865        starts[1]=4;
     4866        index[0]=firstLambda_+0;
     4867        index[1]=firstLambda_+2;
     4868        index[2]=obj2->firstLambda_+0;
     4869        index[3]=obj2->firstLambda_+2;
     4870        coinModel->addRow(4,index,element,rhs,rhs);
     4871        yDone=true;
     4872      }
     4873    }
     4874  }
     4875}
    45194876
    45204877// Copy constructor
     
    45834940{
    45844941}
    4585 
     4942static bool testCoarse=true;
    45864943// Infeasibility - large is 0.5
    45874944double
     
    46575014  double steps;
    46585015  bool xSatisfied;
    4659   double xNew;
     5016  double xNew=xB[0];
    46605017  if (xMeshSize_) {
    46615018    if (x<0.5*(xB[0]+xB[1])) {
     
    46735030    }
    46745031    // but if first coarse grid then only if gap small
    4675     if (false&&(branchingStrategy_&8)!=0&&xSatisfied&&
     5032    if (testCoarse&&(branchingStrategy_&8)!=0&&xSatisfied&&
    46765033        xB[1]-xB[0]>=xMeshSize_) {
    46775034      // but allow if fine grid would allow
     
    46875044  }
    46885045  bool ySatisfied;
    4689   double yNew;
     5046  double yNew=yB[0];
    46905047  if (yMeshSize_) {
    46915048    if (y<0.5*(yB[0]+yB[1])) {
     
    47035060    }
    47045061    // but if first coarse grid then only if gap small
    4705     if (false&&(branchingStrategy_&8)!=0&&ySatisfied&&
     5062    if (testCoarse&&(branchingStrategy_&8)!=0&&ySatisfied&&
    47065063        yB[1]-yB[0]>=yMeshSize_) {
    47075064      // but allow if fine grid would allow
     
    47815138      // == row so move x and y not xy
    47825139    }
     5140  }
     5141  if ((branchingStrategy_&16)!=0) {
     5142    // always treat as satisfied!!
     5143    xSatisfied=true;
     5144    ySatisfied=true;
     5145    xyTrue=xyLambda;
    47835146  }
    47845147  if ( !xSatisfied) {
     
    49385301  }
    49395302  whichWay=whichWay_;
     5303  //if (infeasibility_&&priority_==10)
     5304  //printf("x %d %g %g %g, y %d %g %g %g\n",xColumn_,xB[0],x,xB[1],yColumn_,yB[0],y,yB[1]);
    49405305  return infeasibility_;
    49415306}
     
    67057070                    int mode)
    67067071{
     7072  // matrix etc will be changed
     7073  CoinModel coinModel2 = coinModel;
     7074  if (coinModel2.moreInfo()) {
     7075    // for now just ampl objective
     7076    ClpSimplex * model = new ClpSimplex();
     7077    model->loadProblem(coinModel2);
     7078    int numberConstraints;
     7079    ClpConstraint ** constraints=NULL;
     7080    int type = model->loadNonLinear(coinModel2.moreInfo(),
     7081                                    numberConstraints,constraints);
     7082    if (type==1||type==3) {
     7083      int returnCode = model->nonlinearSLP(numberPasses,deltaTolerance);
     7084      assert (!returnCode);
     7085    } else if (type==2||type==4) {
     7086      int returnCode = model->nonlinearSLP(numberConstraints,constraints,
     7087                                           numberPasses,deltaTolerance);
     7088      assert (!returnCode);
     7089    } else {
     7090      printf("error or linear - fix %d\n",type);
     7091    }
     7092    //exit(66);
     7093    return model;
     7094  }
    67077095  // first check and set up arrays
    67087096  int numberColumns = coinModel.numberColumns();
    67097097  int numberRows = coinModel.numberRows();
    67107098  // List of nonlinear rows
    6711   int * which = new int[numberRows+1];
     7099  int * which = new int[numberRows];
    67127100  bool testLinear=false;
    67137101  int numberConstraints=0;
    67147102  int iColumn;
    6715   // matrix etc will be changed
    6716   CoinModel coinModel2 = coinModel;
    67177103  bool linearObjective=true;
    67187104  int maximumQuadraticElements=0;
     
    67497135    for (iColumn=0;iColumn<numberColumns;iColumn++)
    67507136      coinModel2.setObjective(iColumn,0.0);
    6751     which[numberConstraints++]=-1;
    67527137  }
    67537138  int iRow;
     
    67987183  ClpSimplex * model = new ClpSimplex();
    67997184  // return if nothing
    6800   if (!numberConstraints) {
     7185  if (!numberConstraints&&linearObjective) {
    68017186    delete [] which;
    68027187    model->loadProblem(coinModel);
     
    68147199  int saveNumber=numberConstraints;
    68157200  numberConstraints=0;
     7201  ClpQuadraticObjective * quadObj = NULL;
    68167202  if (!linearObjective) {
    68177203    int numberQuadratic=0;
    6818     int largestColumn=-1;
    68197204    CoinZeroN(linearTerm,numberColumns);
    68207205    for (iColumn=0;iColumn<numberColumns;iColumn++) {
     
    68237208      const char * expr = coinModel.getColumnObjectiveAsString(iColumn);
    68247209      if (strcmp(expr,"Numeric")) {
    6825         largestColumn = CoinMax(largestColumn,iColumn);
    68267210        // value*x*y
    68277211        char temp[20000];
     
    68357219          if (jColumn>=0) {
    68367220            columnQuadratic[numberQuadratic]=jColumn;
    6837             elementQuadratic[numberQuadratic++]=2.0*value; // convention
    6838             largestColumn = CoinMax(largestColumn,jColumn);
     7221            if (jColumn!=iColumn)
     7222              elementQuadratic[numberQuadratic++]=1.0*value; // convention
     7223            else if (jColumn==iColumn)
     7224              elementQuadratic[numberQuadratic++]=2.0*value; // convention
    68397225          } else if (jColumn==-2) {
    68407226            linearTerm[iColumn] = value;
    6841             // and put in as row -1
    6842             columnQuadratic[numberQuadratic]=-1;
    6843             elementQuadratic[numberQuadratic++]=value;
    6844             largestColumn = CoinMax(largestColumn,iColumn);
    68457227          } else {
    68467228            printf("bad nonlinear term %s\n",temp);
     
    68527234        // linear part
    68537235        linearTerm[iColumn] = coinModel.getColumnObjective(iColumn);
    6854         // and put in as row -1
    6855         columnQuadratic[numberQuadratic]=-1;
    6856         elementQuadratic[numberQuadratic++]=linearTerm[iColumn];
    6857         if (linearTerm[iColumn])
    6858           largestColumn = CoinMax(largestColumn,iColumn);
    68597236      }
    68607237    }
    68617238    startQuadratic[numberColumns] = numberQuadratic;
    6862     // here we create ClpConstraint
    6863     constraints[numberConstraints++] = new ClpConstraintQuadratic(-1, largestColumn+1, numberColumns,
    6864                                                                   startQuadratic,columnQuadratic,elementQuadratic);
     7239    quadObj = new ClpQuadraticObjective(linearTerm, numberColumns,
     7240                                           startQuadratic,columnQuadratic,elementQuadratic);
    68657241  }
    68667242  int iConstraint;
     
    69497325  delete [] which;
    69507326  model->loadProblem(coinModel2);
    6951   int returnCode = model->nonlinearSLP(numberConstraints, constraints,
    6952                                        numberPasses,deltaTolerance);
    6953   // See if any integers
    6954   for (iConstraint=0;iConstraint<saveNumber;iConstraint++)
    6955     delete constraints[iConstraint];
    6956  
     7327  if (quadObj)
     7328    model->setObjective(quadObj);
     7329  delete quadObj;
     7330  int returnCode;
     7331  if (numberConstraints) {
     7332    returnCode = model->nonlinearSLP(numberConstraints, constraints,
     7333                                     numberPasses,deltaTolerance);
     7334    for (iConstraint=0;iConstraint<saveNumber;iConstraint++)
     7335      delete constraints[iConstraint];
     7336  } else {
     7337    returnCode = model->nonlinearSLP(numberPasses,deltaTolerance);
     7338  }
    69577339  delete [] constraints;
    69587340  assert (!returnCode);
  • branches/devel/Cbc/src/CbcLinked.hpp

    r604 r642  
    1616#ifdef COIN_HAS_LINK
    1717#include "OsiClpSolverInterface.hpp"
     18#include "CbcFathom.hpp"
    1819class CbcModel;
    1920class CoinPackedMatrix;
     
    2122class OsiObject;
    2223class CglStored;
    23 //#############################################################################
    24 
    2524/**
    2625   
     
    2928*/
    3029
    31 class OsiSolverLink : public OsiClpSolverInterface {
     30class OsiSolverLink : public CbcOsiSolver {
    3231 
    3332public:
     
    6362      heuristic solution
    6463      Returns solution array
     64      mode -
     65      0 just get continuous
     66      1 round and try normal bab
     67      2 use defaultBound_ to bound integer variables near current solution
    6568  */
    6669  double * heuristicSolution(int numberPasses,double deltaTolerance,int mode);
     
    163166  inline int integerPriority() const
    164167  { return integerPriority_;};
     168  /// Objective transfer variable if one
     169  inline int objectiveVariable() const
     170  { return objectiveVariable_;}
    165171  /// Set biLinear priority
    166172  inline void setBiLinearPriority(int value)
     
    169175  inline int biLinearPriority() const
    170176  { return biLinearPriority_;};
    171   /// Set Cbc Model
    172   inline void setCbcModel(CbcModel * model)
    173   { cbcModel_=model;};
    174177  /// Return CoinModel
    175178  inline const CoinModel * coinModel() const
     
    177180  /// Set all biLinear priorities on x-x variables
    178181  void setBiLinearPriorities(int value, double meshSize=1.0);
     182  /** Set options and priority on all or some biLinear variables
     183      1 - on I-I
     184      2 - on I-x
     185      4 - on x-x
     186      or combinations.
     187      -1 means leave (for priority value and strategy value)
     188  */
     189  void setBranchingStrategyOnVariables(int strategyValue, int priorityValue=-1,
     190                                       int mode=7);
    179191  /// Set all mesh sizes on x-x variables
    180192  void setMeshSizes(double value);
     
    212224  /// Copy of quadratic model if one
    213225  ClpSimplex * quadraticModel_;
    214   /// Pointer back to CbcModel
    215   CbcModel * cbcModel_;
    216226  /// Number of rows with nonLinearities
    217227  int numberNonLinearRows_;
     
    681691  */
    682692  OsiBiLinear (OsiSolverInterface * solver, int xColumn,
     693               int yColumn, int xyRow, double coefficient,
     694               double xMesh, double yMesh,
     695               int numberExistingObjects=0,const OsiObject ** objects=NULL );
     696 
     697  /** Useful constructor -
     698      This Adds in rows and variables to construct valid Linked Ordered Set
     699      Adds extra constraints to match other x/y
     700      So note not const model
     701  */
     702  OsiBiLinear (CoinModel * coinModel, int xColumn,
    683703               int yColumn, int xyRow, double coefficient,
    684704               double xMesh, double yMesh,
     
    793813      next bit
    794814      8 set to say don't use in feasible region
     815      next bit
     816      16 set to say - Always satisfied !!
    795817  */
    796818  inline int branchingStrategy() const
     
    857879      next bit
    858880      8 set to say don't use in feasible region
     881      next bit
     882      16 set to say - Always satisfied !!
    859883  */
    860884  int branchingStrategy_;
  • branches/devel/Cbc/src/CbcMessage.cpp

    r539 r642  
    3131  {CBC_STATUS,10,1,"After %d nodes, %d on tree, %g best solution, best possible %g (%.2f seconds)"},
    3232  {CBC_GAP,11,1,"Exiting as integer gap of %g less than %g or %g%%"},
    33   {CBC_ROUNDING,12,1,"Integer solution of %g found by heuristic after %d iterations and %d nodes (%.2f seconds)"},
     33  {CBC_ROUNDING,12,1,"Integer solution of %g found by %s after %d iterations and %d nodes (%.2f seconds)"},
    3434  {CBC_TREE_SOL,24,1,"Integer solution of %g found by subtree after %d iterations and %d nodes (%.2f seconds)"},
    3535  {CBC_ROOT,13,1,"At root node, %d cuts changed objective from %g to %g in %d passes"},
     
    4949  {CBC_START_SUB,28,1,"Starting sub-tree for %s - maximum nodes %d"},
    5050  {CBC_END_SUB,29,1,"Ending sub-tree for %s"},
    51   {CBC_HEURISTIC_SOLUTION,30,1,"solution of %g found by %s after %2.f seconds"},
     51  {CBC_THREAD_STATS,30,1,"%s%? %d used %d times,  waiting to start %g, %?%g cpu time,%? %g waiting for threads, %? %d locks, %g locked, %g waiting for locks"},
    5252  {CBC_CUTS_STATS,31,1,"%d added rows had average density of %g"},
    5353  {CBC_STRONG_STATS,32,1,"Strong branching done %d times (%d iterations), fathomed %d nodes and fixed %d variables"},
     
    5656  {CBC_HEURISTICS_OFF,36,1,"Heuristics switched off as %d branching objects are of wrong type"},
    5757  {CBC_STATUS2,37,1,"%d nodes, %d on tree, best %g - possible %g depth %d unsat %d its %d (%.2f seconds)"},
     58  {CBC_FPUMP1,38,1,"%s"},
     59  {CBC_FPUMP2,39,2,"%s"},
    5860  {CBC_DUMMY_END,999999,0,""}
    5961};
  • branches/devel/Cbc/src/CbcMessage.hpp

    r439 r642  
    5454  CBC_START_SUB,
    5555  CBC_END_SUB,
    56   CBC_HEURISTIC_SOLUTION,
     56  CBC_THREAD_STATS,
    5757  CBC_CUTS_STATS,
    5858  CBC_STRONG_STATS,
     
    6161  CBC_HEURISTICS_OFF,
    6262  CBC_STATUS2,
     63  CBC_FPUMP1,
     64  CBC_FPUMP2,
    6365  CBC_DUMMY_END
    6466};
  • branches/devel/Cbc/src/CbcModel.cpp

    r616 r642  
    3636#include "CbcBranchDynamic.hpp"
    3737#include "CbcHeuristic.hpp"
     38#include "CbcHeuristicFPump.hpp"
    3839#include "CbcModel.hpp"
    3940#include "CbcTreeLocal.hpp"
     
    4849#include "CbcCutGenerator.hpp"
    4950#include "CbcFeasibilityBase.hpp"
     51#include "CbcFathom.hpp"
    5052// include Probing
    5153#include "CglProbing.hpp"
     
    6062#include "CbcCompareActual.hpp"
    6163#include "CbcTree.hpp"
     64//#define CBC_THREAD
     65#ifdef CBC_THREAD
     66#include <pthread.h>
     67//#define CBC_THREAD_DEBUG 1
     68// To Pass across to doOneNode
     69typedef struct {
     70  CbcModel * baseModel;
     71  CbcModel * thisModel;
     72  CbcNode * node; // filled in every time
     73  CbcNode * createdNode; // filled in every time on return
     74  pthread_t threadIdOfBase;
     75  pthread_mutex_t * mutex; // for locking data
     76  pthread_mutex_t * mutex2; // for waking up threads
     77  pthread_cond_t * condition2; // for waking up thread
     78  int returnCode; // -1 available, 0 busy, 1 finished , 2??
     79  double timeLocked;
     80  double timeWaitingToLock;
     81  double timeWaitingToStart;
     82  double timeInThread;
     83  int numberTimesLocked;
     84  int numberTimesUnlocked;
     85  int numberTimesWaitingToStart;
     86  int saveStuff[2];
     87  struct timespec absTime;
     88  bool locked;
     89#if CBC_THREAD_DEBUG
     90  int threadNumber;
     91#endif
     92} threadStruct;
     93static void * doNodesThread(void * voidInfo);
     94static void * doCutsThread(void * voidInfo);
     95#endif
    6296/* Various functions local to CbcModel.cpp */
    6397
     
    449483  system held by the solver.
    450484*/
    451 
    452485void CbcModel::branchAndBound(int doStatistics)
    453486
     
    461494  strongInfo_[2]=0;
    462495  numberStrongIterations_ = 0;
     496#ifndef NDEBUG
     497  {
     498    int i;
     499    int n = solver_->getNumCols();
     500    const double *lower = solver_->getColLower() ;
     501    const double *upper = solver_->getColUpper() ;
     502    for (i=0;i<n;i++) {
     503      assert (lower[i]<1.0e10);
     504      assert (upper[i]>-1.0e10);
     505    }
     506    n = solver_->getNumRows();
     507    lower = solver_->getRowLower() ;
     508    upper = solver_->getRowUpper() ;
     509    for (i=0;i<n;i++) {
     510      assert (lower[i]<1.0e10);
     511      assert (upper[i]>-1.0e10);
     512    }
     513  }
     514#endif
    463515  // original solver (only set if pre-processing)
    464516  OsiSolverInterface * originalSolver=NULL;
     
    466518  OsiObject ** originalObject = NULL;
    467519  // Set up strategies
     520#if 0
     521  std::string problemName ;
     522  solver_->getStrParam(OsiProbName,problemName) ;
     523  if (!strcmp(problemName.c_str(),"P0282")) solver_->activateRowCutDebugger(problemName.c_str()) ;
     524#endif
    468525  if (strategy_) {
    469526    // May do preprocessing
     
    894951     = dynamic_cast<OsiClpSolverInterface *> (solver_);
    895952   if (clpSolver) {
    896 #define CLP_QUICK_OPTIONS
     953     //#define CLP_QUICK_OPTIONS
    897954#ifdef CLP_QUICK_OPTIONS
    898955     // Try and re-use regions   
     
    9431000  whichGenerator_ = new int[maximumWhich_] ;
    9441001  memset(whichGenerator_,0,maximumWhich_*sizeof(int));
    945   int currentNumberCuts = 0 ;
    9461002  maximumNumberCuts_ = 0 ;
    9471003  currentNumberCuts_ = 0 ;
     
    10051061  maximumDepthActual_=0;
    10061062  numberDJFixed_=0.0;
     1063  // Do heuristics
     1064  {
     1065    double * newSolution = new double [numberColumns] ;
     1066    double heuristicValue = getCutoff() ;
     1067    int found = -1; // no solution found
     1068
     1069    currentPassNumber_ = 1; // so root heuristics will run
     1070    int i;
     1071    for (i = 0;i<numberHeuristics_;i++) {
     1072      // see if heuristic will do anything
     1073      double saveValue = heuristicValue ;
     1074      int ifSol = heuristic_[i]->solution(heuristicValue,
     1075                                          newSolution);
     1076      if (ifSol>0) {
     1077        // better solution found
     1078        found = i ;
     1079        incrementUsed(newSolution);
     1080        // increment number of solutions so other heuristics can test
     1081        numberSolutions_++;
     1082        numberHeuristicSolutions_++;
     1083      } else {
     1084        heuristicValue = saveValue ;
     1085      }
     1086    }
     1087    currentPassNumber_ = 0;
     1088    /*
     1089      Did any of the heuristics turn up a new solution? Record it before we free
     1090      the vector.
     1091    */
     1092    if (found >= 0) {
     1093      lastHeuristic_ = heuristic_[found];
     1094      setBestSolution(CBC_ROUNDING,heuristicValue,newSolution) ;
     1095      CbcTreeLocal * tree
     1096          = dynamic_cast<CbcTreeLocal *> (tree_);
     1097      if (tree)
     1098        tree->passInSolution(bestSolution_,heuristicValue);
     1099    }
     1100    for (i = 0;i<numberHeuristics_;i++) {
     1101      // delete FPump
     1102      CbcHeuristicFPump * pump
     1103        = dynamic_cast<CbcHeuristicFPump *> (heuristic_[i]);
     1104      if (pump) {
     1105        delete pump;
     1106        numberHeuristics_ --;
     1107        for (int j=i;j<numberHeuristics_;j++)
     1108          heuristic_[j] = heuristic_[j+1];
     1109      }
     1110    }
     1111    delete [] newSolution ;
     1112  }
    10071113  statistics_ = NULL;
    10081114  // Do on switch
     
    10371143        feasible = solveWithCuts(cuts, 1,
    10381144                                 NULL);
    1039 #if 0
    1040         currentNumberCuts_ = cuts.sizeRowCuts();
    1041         if (currentNumberCuts_ >= maximumNumberCuts_) {
    1042           maximumNumberCuts_ = currentNumberCuts;
    1043           delete [] addedCuts_;
    1044           addedCuts_ = new CbcCountRowCut * [maximumNumberCuts_];
    1045         }
    1046 #endif
    10471145      }
    10481146    }
     
    10641162                           *dblParam_[CbcAllowableFractionGap]);
    10651163  if (bestObjective_-bestPossibleObjective_ < testGap && getCutoffIncrement()>=0.0) {
    1066     if (bestPossibleObjective_<getCutoff()) {
     1164    if (bestPossibleObjective_<getCutoff())
    10671165      stoppedOnGap_ = true ;
    1068       messageHandler()->message(CBC_GAP,messages())
    1069         << bestObjective_-bestPossibleObjective_
    1070         << dblParam_[CbcAllowableGap]
    1071         << dblParam_[CbcAllowableFractionGap]*100.0
    1072         << CoinMessageEol ;
    1073       secondaryStatus_ = 2;
    1074     }
    10751166    feasible = false;
    10761167  }
     
    11271218      }
    11281219    }
    1129 #if 0
    1130     while (anyAction == -1)
    1131     {
    1132       // Set objective value (not so obvious if NLP etc)
    1133       setObjectiveValue(newNode,NULL);
    1134       if (numberBeforeTrust_==0 ) {
    1135         anyAction = newNode->chooseBranch(this,NULL,numberPassesLeft) ;
    1136       } else {
    1137         OsiSolverBranch * branches=NULL;
    1138         anyAction = newNode->chooseDynamicBranch(this,NULL,branches,numberPassesLeft) ;
    1139         if (anyAction==-3)
    1140           anyAction = newNode->chooseBranch(this,NULL,numberPassesLeft) ; // dynamic did nothing
    1141       }
    1142       numberPassesLeft--;
    1143       if (anyAction == -1)
    1144       {
    1145         //if (solverCharacteristics_->solverType()!=4)
    1146           feasible = resolve(NULL,10) != 0 ;
    1147           //else
    1148           //feasible = solveWithCuts(cuts,maximumCutPassesAtRoot_,NULL);
    1149       if (problemFeasibility_->feasible(this,0)<0) {
    1150         feasible=false; // pretend infeasible
    1151       }
    1152       reducedCostFix() ;
    1153       resolved = true ;
    1154 #       ifdef CBC_DEBUG
    1155       printf("Resolve (root) as something fixed, Obj value %g %d rows\n",
    1156              solver_->getObjValue(),
    1157              solver_->getNumRows()) ;
    1158 #       endif
    1159       if (!feasible) anyAction = -2 ; }
    1160       if (anyAction == -2||newNode->objectiveValue() >= cutoff)
    1161       { delete newNode ;
    1162         newNode = NULL ;
    1163         feasible = false ; } }
    1164 #else
    1165   OsiSolverBranch * branches = NULL;
    1166   anyAction = chooseBranch(newNode, numberPassesLeft, NULL, cuts,resolved,
    1167                            NULL,NULL,NULL,branches);
    1168   if (anyAction == -2||newNode->objectiveValue() >= cutoff) {
    1169     if (anyAction != -2) {
    1170       // zap parent nodeInfo
     1220    OsiSolverBranch * branches = NULL;
     1221    anyAction = chooseBranch(newNode, numberPassesLeft, NULL, cuts,resolved,
     1222                             NULL,NULL,NULL,branches);
     1223    if (anyAction == -2||newNode->objectiveValue() >= cutoff) {
     1224      if (anyAction != -2) {
     1225        // zap parent nodeInfo
    11711226#ifdef COIN_DEVELOP
    1172       printf("zapping CbcNodeInfo %x\n",newNode->nodeInfo()->parent());
     1227        printf("zapping CbcNodeInfo %x\n",newNode->nodeInfo()->parent());
    11731228#endif
    1174       if (newNode->nodeInfo())
    1175         newNode->nodeInfo()->nullParent();
    1176     }
    1177     delete newNode ;
    1178     newNode = NULL ;
    1179     feasible = false ;
    1180   }
    1181 #endif
     1229        if (newNode->nodeInfo())
     1230          newNode->nodeInfo()->nullParent();
     1231      }
     1232      delete newNode ;
     1233      newNode = NULL ;
     1234      feasible = false ;
     1235    }
    11821236  }
    11831237/*
     
    11881242  assert (!newNode || newNode->objectiveValue() <= cutoff) ;
    11891243  // Save address of root node as we don't want to delete it
    1190   CbcNode * rootNode = newNode;
    11911244  // initialize for print out
    11921245  int lastDepth=0;
     
    12041257  a valid solution for use by setBestSolution().
    12051258*/
    1206   CoinWarmStartBasis *lastws = 0 ;
     1259  CoinWarmStartBasis *lastws = NULL ;
    12071260  if (feasible && newNode->branchingObject())
    12081261  { if (resolved)
     
    12911344  */
    12921345  numberLongStrong_=0;
     1346  double totalTime = 0.0;
     1347#ifdef CBC_THREAD
     1348  CbcNode * createdNode=NULL;
     1349  CbcModel ** threadModel = NULL;
     1350  pthread_t * threadId = NULL;
     1351  int * threadCount = NULL;
     1352  pthread_mutex_t mutex;
     1353  pthread_cond_t condition_main;
     1354  pthread_mutex_t condition_mutex;
     1355  pthread_mutex_t * mutex2 = NULL;
     1356  pthread_cond_t * condition2 = NULL;
     1357  threadStruct * threadInfo = NULL;
     1358  bool locked=false;
     1359  int threadStats[6];
     1360  memset(threadStats,0,sizeof(threadStats));
     1361  double timeWaiting=0.0;
     1362  // For now just one model
     1363  if (numberThreads_) {
     1364    threadId = new pthread_t [numberThreads_];
     1365    threadCount = new int [numberThreads_];
     1366    CoinZeroN(threadCount,numberThreads_);
     1367    pthread_mutex_init(&mutex,NULL);
     1368    pthread_cond_init(&condition_main,NULL);
     1369    pthread_mutex_init(&condition_mutex,NULL);
     1370    threadModel = new CbcModel * [numberThreads_+1];
     1371    threadInfo = new threadStruct [numberThreads_+1];
     1372    mutex2 = new pthread_mutex_t [numberThreads_];
     1373    condition2 = new pthread_cond_t [numberThreads_];
     1374    // we don't want a strategy object
     1375    CbcStrategy * saveStrategy = strategy_;
     1376    strategy_ = NULL;
     1377    for (int i=0;i<numberThreads_;i++) {
     1378      pthread_mutex_init(mutex2+i,NULL);
     1379      pthread_cond_init(condition2+i,NULL);
     1380      threadId[i]=0;
     1381      threadInfo[i].baseModel=this;
     1382      threadModel[i]=new CbcModel(*this);
     1383#ifdef COIN_HAS_CLP
     1384      // Solver may need to know about model
     1385      CbcModel * thisModel = threadModel[i];
     1386      CbcOsiSolver * solver =
     1387              dynamic_cast<CbcOsiSolver *>(thisModel->solver()) ;
     1388      if (solver)
     1389        solver->setCbcModel(thisModel);
     1390#endif
     1391      mutex_ = (void *) (threadInfo+i);
     1392      threadModel[i]->moveToModel(this,-1);
     1393      threadInfo[i].thisModel=threadModel[i];
     1394      threadInfo[i].node=NULL;
     1395      threadInfo[i].createdNode=NULL;
     1396      threadInfo[i].threadIdOfBase=pthread_self();
     1397      threadInfo[i].mutex=&mutex;
     1398      threadInfo[i].mutex2=mutex2+i;
     1399      threadInfo[i].condition2=condition2+i;
     1400      threadInfo[i].returnCode=-1;
     1401      threadInfo[i].timeLocked=0.0;
     1402      threadInfo[i].timeWaitingToLock=0.0;
     1403      threadInfo[i].timeWaitingToStart=0.0;
     1404      threadInfo[i].timeInThread=0.0;
     1405      threadInfo[i].numberTimesLocked=0;
     1406      threadInfo[i].numberTimesUnlocked=0;
     1407      threadInfo[i].numberTimesWaitingToStart=0;
     1408      threadInfo[i].locked=false;
     1409#if CBC_THREAD_DEBUG
     1410      threadInfo[i].threadNumber=i+2;
     1411#endif
     1412      pthread_create(threadId+i,NULL,doNodesThread,threadInfo+i);
     1413    }
     1414    strategy_ = saveStrategy;
     1415    // Do a partial one for base model
     1416    threadInfo[numberThreads_].baseModel=this;
     1417    threadModel[numberThreads_]=this;
     1418    mutex_ = (void *) (threadInfo+numberThreads_);
     1419    threadInfo[numberThreads_].node=NULL;
     1420    threadInfo[numberThreads_].mutex=&mutex;
     1421    threadInfo[numberThreads_].condition2=&condition_main;
     1422    threadInfo[numberThreads_].mutex2=&condition_mutex;
     1423    threadInfo[numberThreads_].timeLocked=0.0;
     1424    threadInfo[numberThreads_].timeWaitingToLock=0.0;
     1425    threadInfo[numberThreads_].numberTimesLocked=0;
     1426    threadInfo[numberThreads_].numberTimesUnlocked=0;
     1427    threadInfo[numberThreads_].locked=false;
     1428#if CBC_THREAD_DEBUG
     1429    threadInfo[numberThreads_].threadNumber=1;
     1430#endif
     1431  }
     1432#endif
    12931433/*
    12941434  At last, the actual branch-and-cut search loop, which will iterate until
     
    13011441  than the current objective cutoff.
    13021442*/
    1303   while (!tree_->empty()) {
     1443  while (true) {
     1444#ifdef CBC_THREAD
     1445    if (!locked) {
     1446      lockThread();
     1447      locked=true;
     1448    }
     1449#endif
     1450    if (tree_->empty()) {
     1451#ifdef CBC_THREAD
     1452      if (numberThreads_) {
     1453        // may still be outstanding nodes
     1454        int iThread;
     1455        for (iThread=0;iThread<numberThreads_;iThread++) {
     1456          if (threadId[iThread]) {
     1457            if (threadInfo[iThread].returnCode==0)
     1458              break;
     1459          }
     1460        }
     1461        if (iThread<numberThreads_) {
     1462          unlockThread();
     1463          locked = false;
     1464          pthread_cond_signal(threadInfo[iThread].condition2); // unlock in case
     1465#define CONDITION_WAIT
     1466#ifdef CONDITION_WAIT
     1467          while (true) {
     1468            pthread_mutex_lock(&condition_mutex);
     1469            struct timespec absTime;
     1470            clock_gettime(CLOCK_REALTIME,&absTime);
     1471            double time = absTime.tv_sec+1.0e-9*absTime.tv_nsec;
     1472            absTime.tv_nsec += 1000000; // millisecond
     1473            if (absTime.tv_nsec>=1000000000) {
     1474              absTime.tv_nsec -= 1000000000;
     1475              absTime.tv_sec++;
     1476            }
     1477            pthread_cond_timedwait(&condition_main,&condition_mutex,&absTime);
     1478            clock_gettime(CLOCK_REALTIME,&absTime);
     1479            double time2 = absTime.tv_sec+1.0e-9*absTime.tv_nsec;
     1480            timeWaiting += time2-time;
     1481            pthread_mutex_unlock(&condition_mutex);
     1482            if (threadInfo[iThread].returnCode!=0)
     1483              break;
     1484          }
     1485#else
     1486          while (threadInfo[iThread].returnCode==0) {
     1487            struct timespec moreTime;
     1488            moreTime.tv_nsec = 10000;
     1489            moreTime.tv_sec = 0;
     1490            nanosleep(&moreTime,NULL);
     1491          }
     1492#endif
     1493          threadModel[iThread]->moveToModel(this,1);
     1494          assert (threadInfo[iThread].returnCode==1);
     1495          // say available
     1496          threadInfo[iThread].returnCode=-1;
     1497          threadStats[4]++;
     1498          continue;
     1499        }
     1500      }
     1501      unlockThread();
     1502      locked=false; // not needed as break
     1503#endif
     1504      break;
     1505    }
     1506#ifdef CBC_THREAD
     1507    unlockThread();
     1508    locked = false;
     1509#endif
     1510/*
     1511  Check for abort on limits: node count, solution count, time, integrality gap.
     1512*/
     1513    totalTime = CoinCpuTime()-dblParam_[CbcStartSeconds] ;
     1514    if (!(numberNodes_ < intParam_[CbcMaxNumNode] &&
     1515          numberSolutions_ < intParam_[CbcMaxNumSol] &&
     1516          totalTime < dblParam_[CbcMaximumSeconds] &&
     1517          !stoppedOnGap_&&!eventHappened_)) {
     1518      // out of loop
     1519      break;
     1520    }
    13041521#ifdef BONMIN
    13051522    assert(!solverCharacteristics_->solutionAddsCuts() || solverCharacteristics_->mipFeasible());
     
    13081525      double newCutoff = getCutoff();
    13091526      if (analyzeResults_) {
    1310         // see if we could fix any (more)
    1311         int n=0;
    1312         double * newLower = analyzeResults_;
    1313         double * objLower = newLower+numberIntegers_;
    1314         double * newUpper = objLower+numberIntegers_;
    1315         double * objUpper = newUpper+numberIntegers_;
    1316         for (int i=0;i<numberIntegers_;i++) {
    1317           if (objLower[i]>newCutoff) {
    1318             n++;
    1319             if (objUpper[i]>newCutoff) {
    1320               newCutoff = -COIN_DBL_MAX;
    1321               break;
    1322             }
    1323           } else if (objUpper[i]>newCutoff) {
    1324             n++;
    1325           }
    1326         }
    1327         if (newCutoff==-COIN_DBL_MAX) {
    1328           printf("Root analysis says finished\n");
    1329         } else if (n>numberFixedNow_) {
    1330           printf("%d more fixed by analysis - now %d\n",n-numberFixedNow_,n);
    1331           numberFixedNow_=n;
    1332         }
     1527        // see if we could fix any (more)
     1528        int n=0;
     1529        double * newLower = analyzeResults_;
     1530        double * objLower = newLower+numberIntegers_;
     1531        double * newUpper = objLower+numberIntegers_;
     1532        double * objUpper = newUpper+numberIntegers_;
     1533        for (int i=0;i<numberIntegers_;i++) {
     1534          if (objLower[i]>newCutoff) {
     1535            n++;
     1536            if (objUpper[i]>newCutoff) {
     1537              newCutoff = -COIN_DBL_MAX;
     1538              break;
     1539            }
     1540          } else if (objUpper[i]>newCutoff) {
     1541            n++;
     1542          }
     1543        }
     1544        if (newCutoff==-COIN_DBL_MAX) {
     1545          printf("Root analysis says finished\n");
     1546        } else if (n>numberFixedNow_) {
     1547          printf("%d more fixed by analysis - now %d\n",n-numberFixedNow_,n);
     1548          numberFixedNow_=n;
     1549        }
    13331550      }
    13341551      if (eventHandler) {
    1335         if (!eventHandler->event(CbcEventHandler::solution)) {
    1336           eventHappened_=true; // exit
    1337         }
    1338       }
     1552        if (!eventHandler->event(CbcEventHandler::solution)) {
     1553          eventHappened_=true; // exit
     1554        }
     1555      }
     1556      lockThread();
    13391557      // Do from deepest
    13401558      tree_->cleanTree(this, newCutoff,bestPossibleObjective_) ;
    13411559      nodeCompare_->newSolution(this) ;
    13421560      nodeCompare_->newSolution(this,continuousObjective_,
    1343                                 continuousInfeasibilities_) ;
     1561                                continuousInfeasibilities_) ;
    13441562      tree_->setComparison(*nodeCompare_) ;
    1345       if (tree_->empty())
     1563      if (tree_->empty()) {
     1564        unlockThread();
    13461565        break; // finished
     1566      }
     1567      unlockThread();
    13471568    }
    13481569    cutoff = getCutoff() ;
    13491570/*
    1350   Periodic activities: Opportunities to
     1571    Periodic activities: Opportunities to
    13511572    + tweak the nodeCompare criteria,
    13521573    + check if we've closed the integrality gap enough to quit,
     
    13541575*/
    13551576    if ((numberNodes_%1000) == 0) {
     1577      lockThread();
    13561578      bool redoTree=nodeCompare_->every1000Nodes(this, numberNodes_) ;
    13571579#ifdef CHECK_CUT_SIZE
     
    13611583      if (redoTree)
    13621584        tree_->setComparison(*nodeCompare_) ;
     1585      unlockThread();
    13631586    }
    13641587    if (saveCompare&&!hotstartSolution_) {
     
    13681591      saveCompare=NULL;
    13691592      // redo tree
     1593      lockThread();
    13701594      tree_->setComparison(*nodeCompare_) ;
     1595      unlockThread();
    13711596    }
    13721597    if ((numberNodes_%printFrequency_) == 0) {
     1598      lockThread();
    13731599      int j ;
    13741600      int nNodes = tree_->size() ;
     
    13791605          bestPossibleObjective_ = node->objectiveValue() ;
    13801606      }
     1607      unlockThread();
    13811608      if (!intParam_[CbcPrinting]) {
    13821609        messageHandler()->message(CBC_STATUS,messages())
     
    14051632      stoppedOnGap_ = true ;
    14061633    }
    1407 
     1634   
    14081635#   ifdef CHECK_NODE_FULL
    14091636    verifyTreeNodes(tree_,*this) ;
     
    14121639    verifyCutCounts(tree_,*this) ;
    14131640#   endif
    1414 
    14151641/*
    14161642  Now we come to the meat of the loop. To create the active subproblem, we'll
     
    14231649    if (!node)
    14241650      continue;
     1651#ifndef CBC_THREAD
     1652    int currentNumberCuts = 0 ;
    14251653    currentNode_=node; // so can be accessed elsewhere
    14261654#ifdef CBC_DEBUG
     
    14321660    if(branchingMethod_)
    14331661      branchingMethod_->saveBranchingObject(node->modifiableBranchingObject());
    1434     bool nodeOnTree=false; // Node has been popped
    14351662    // Say not on optimal path
    14361663    bool onOptimalPath=false;
     
    14601687    CbcNodeInfo * nodeInfo = node->nodeInfo() ;
    14611688    newNode = NULL ;
     1689    int branchesLeft=0;
    14621690    if (!addCuts(node,lastws,numberFixedNow_>numberFixedAtRoot_))
    14631691    { int i ;
     
    14711699        solverCharacteristics_->setBeforeUpper(upperBefore);
    14721700      }
    1473       bool deleteNode ;
    14741701      if (messageHandler()->logLevel()>2)
    14751702        node->modifiableBranchingObject()->print();
    1476       int retCode;
    14771703      if (!useOsiBranching)
    1478         retCode = node->branch(NULL); // old way
     1704        branchesLeft = node->branch(NULL); // old way
    14791705      else
    1480         retCode = node->branch(solver_); // new way
    1481       if (retCode)
    1482       {
     1706        branchesLeft = node->branch(solver_); // new way
     1707      if (branchesLeft) {
    14831708        // set nodenumber correctly
    14841709        node->nodeInfo()->setNodeNumber(numberNodes2_);
     
    14971722        }
    14981723        numberNodes2_++;
    1499         nodeOnTree=true; // back on tree
    1500         deleteNode = false ;
     1724        //nodeOnTree=true; // back on tree
     1725        //deleteNode = false ;
    15011726#       ifdef CHECK_NODE
    15021727        printf("Node %x pushed back on tree - %d left, %d count\n",node,
     
    15041729               nodeInfo->numberPointingToThis()) ;
    15051730#       endif
    1506       }
    1507       else
    1508       { deleteNode = true ;
    1509       if (!nodeInfo->numberBranchesLeft())
    1510         nodeInfo->allBranchesGone(); // can clean up
    1511       }
    1512 
     1731      } else {
     1732        //deleteNode = true ;
     1733        if (!nodeInfo->numberBranchesLeft())
     1734          nodeInfo->allBranchesGone(); // can clean up
     1735      }
    15131736      if ((specialOptions_&1)!=0) {
    15141737        /*
     
    15241747        }
    15251748      }
     1749     
    15261750/*
    15271751  Reoptimize, possibly generating cuts and/or using heuristics to find
     
    15971821      }
    15981822/*
    1599   Check for abort on limits: node count, solution count, time, integrality gap.
    1600 */
    1601       double totalTime = CoinCpuTime()-dblParam_[CbcStartSeconds] ;
    1602       if (numberNodes_ < intParam_[CbcMaxNumNode] &&
    1603           numberSolutions_ < intParam_[CbcMaxNumSol] &&
    1604           totalTime < dblParam_[CbcMaximumSeconds] &&
    1605           !stoppedOnGap_&&!eventHappened_)
    1606       {
    1607 /*
    16081823  Are we still feasible? If so, create a node and do the work to attach a
    16091824  branching object, reoptimising as needed if chooseBranch() identifies
     
    16451860          int numberPassesLeft=5;
    16461861          checkingNode=true;
    1647 #if 0
    1648           while (anyAction == -1)
    1649           {
    1650             // Set objective value (not so obvious if NLP etc)
    1651             setObjectiveValue(newNode,node);
    1652             if (numberBeforeTrust_==0 ) {
    1653               anyAction = newNode->chooseBranch(this,node,numberPassesLeft) ;
    1654             } else {
    1655               OsiSolverBranch * branches=NULL;
    1656               anyAction = newNode->chooseDynamicBranch(this,node,branches,numberPassesLeft) ;
    1657               if (anyAction==-3)
    1658                 anyAction = newNode->chooseBranch(this,node,numberPassesLeft) ; // dynamic did nothing
    1659             }
    1660             if (solverCharacteristics_ &&
    1661                 solverCharacteristics_->solutionAddsCuts() && // we are in some OA based bab
    1662                 feasible && (newNode->numberUnsatisfied()==0) //solution has become integer feasible during strong branching
    1663                 )
    1664               {
    1665                 //in the present case we need to check here integer infeasibility if the node is not fathomed we will have to do the loop
    1666                 // again
    1667                 std::cout<<solver_<<std::endl;
    1668                 resolve(solver_);
    1669                 double objval = solver_->getObjValue();
    1670                 setBestSolution(CBC_SOLUTION, objval,
    1671                                 solver_->getColSolution()) ;
    1672                 lastHeuristic_ = NULL;
    1673                 int easy=2;
    1674                 if (!solverCharacteristics_->mipFeasible())//did we prove that the node could be pruned?
    1675                   feasible = false;
    1676                 // Reset the bound now
    1677                 solverCharacteristics_->setMipBound(-COIN_DBL_MAX);
    1678                
    1679                
    1680                 //numberPassesLeft++;
    1681                 solver_->setHintParam(OsiDoInBranchAndCut,true,OsiHintDo,&easy) ;
    1682                 feasible &= resolve(node ? node->nodeInfo() : NULL,11) != 0 ;
    1683                 solver_->setHintParam(OsiDoInBranchAndCut,true,OsiHintDo,NULL) ;
    1684                 resolved = true ;
    1685                 if (problemFeasibility_->feasible(this,0)<0) {
    1686                   feasible=false; // pretend infeasible
    1687                 }
    1688                 if(feasible)
    1689                   anyAction = -1;
    1690                 else
    1691                   anyAction = -2;
    1692               }
    1693 /*
    1694   Yep, false positives for sure. And no easy way to distinguish honest
    1695   infeasibility from `found a solution and tightened objective target.'
    1696 
    1697             if (onOptimalPath)
    1698               assert (anyAction!=-2); // can be useful but gives false positives on strong
    1699 */
    1700             numberPassesLeft--;
    1701             if (numberPassesLeft<=-1) {
    1702               if (!numberLongStrong_)
    1703                 messageHandler()->message(CBC_WARNING_STRONG,
    1704                                           messages()) << CoinMessageEol ;
    1705               numberLongStrong_++;
    1706             }
    1707             if (anyAction == -1)
    1708             {
    1709               // can do quick optimality check
    1710               int easy=2;
    1711               solver_->setHintParam(OsiDoInBranchAndCut,true,OsiHintDo,&easy) ;
    1712               //if (solverCharacteristics_->solverType()!=4)
    1713                 feasible = resolve(node ? node->nodeInfo() : NULL,11) != 0 ;
    1714                 //else
    1715                 //feasible = solveWithCuts(cuts,maximumCutPasses_,node);
    1716               solver_->setHintParam(OsiDoInBranchAndCut,true,OsiHintDo,NULL) ;
    1717               resolved = true ;
    1718               if (problemFeasibility_->feasible(this,0)<0) {
    1719                 feasible=false; // pretend infeasible
    1720               }
    1721               if (feasible)
    1722               {
    1723                 // Set objective value (not so obvious if NLP etc)
    1724                 setObjectiveValue(newNode,node);
    1725                 reducedCostFix() ;
    1726                 if (newNode->objectiveValue() >= getCutoff())
    1727                   anyAction=-2;
    1728               }
    1729               else
    1730               { anyAction = -2 ; } } }
    1731           if (anyAction >= 0)
    1732           { if (resolved)
    1733             { bool needValidSolution = (newNode->branchingObject() == NULL) ;
    1734               takeOffCuts(cuts,needValidSolution,NULL) ;
    1735 #             ifdef CHECK_CUT_COUNTS
    1736               { printf("Number of rows after chooseBranch fix (node)"
    1737                        "(active only) %d\n",
    1738                         numberRowsAtContinuous_+numberNewCuts_+
    1739                         numberOldActiveCuts_) ;
    1740                 const CoinWarmStartBasis* debugws =
    1741                   dynamic_cast<const CoinWarmStartBasis*>
    1742                     (solver_->getWarmStart()) ;
    1743                 debugws->print() ;
    1744                 delete debugws ; }
    1745 #             endif
    1746             }
    1747             newNode->createInfo(this,node,lastws,lowerBefore,upperBefore,
    1748                                 numberOldActiveCuts_,numberNewCuts_) ;
    1749             if (newNode->numberUnsatisfied()) {
    1750               maximumDepthActual_ = CoinMax(maximumDepthActual_,newNode->depth());
    1751               newNode->initializeInfo() ;
    1752               newNode->nodeInfo()->addCuts(cuts,newNode->numberBranches(),
    1753                                            whichGenerator_) ; } } }
    1754         else {
    1755           anyAction = -2 ;
    1756           // Reset bound anyway (no harm if not odd)
    1757           solverCharacteristics_->setMipBound(-COIN_DBL_MAX);
    1758           node->nodeInfo()->decrement();
    1759         }
    1760         // May have slipped through i.e. anyAction == 0 and objective above cutoff
    1761         // I think this will screw up cut reference counts if executed.
    1762         // We executed addCuts just above. (lh)
    1763         if ( anyAction >=0 ) {
    1764           assert (newNode);
    1765           if (newNode->objectiveValue() >= getCutoff()) {
    1766             anyAction = -2; // say bad after all
    1767 #ifdef COIN_DEVELOP
    1768             printf("zapping2 CbcNodeInfo %x\n",newNode->nodeInfo()->parent());
    1769 #endif
    1770             // zap parent nodeInfo
    1771             if (newNode->nodeInfo())
    1772               newNode->nodeInfo()->nullParent();
    1773           }
    1774         }
    1775 /*
    1776   If we end up infeasible, we can delete the new node immediately. Since this
    1777   node won't be needing the cuts we collected, decrement the reference counts.
    1778   If we are feasible, then we'll be placing this node into the live set, so
    1779   increment the reference count in the current (parent) nodeInfo.
    1780 */
    1781         if (anyAction == -2)
    1782         { delete newNode ;
    1783           newNode = NULL ;
    1784           // say strong doing well
    1785           if (checkingNode)
    1786             setSpecialOptions(specialOptions_|8);
    1787           for (i = 0 ; i < currentNumberCuts_ ; i++)
    1788           { if (addedCuts_[i])
    1789             { if (!addedCuts_[i]->decrement(1))
    1790                 delete addedCuts_[i] ; } } }
    1791         else
    1792         { nodeInfo->increment() ;
    1793         if ((numberNodes_%20)==0) {
    1794           // say strong not doing as well
    1795           setSpecialOptions(specialOptions_&~8);
    1796         }
    1797 #else
    17981862        OsiSolverBranch * branches=NULL;
    17991863        // point to useful information
     
    18231887          }
    18241888        }
    1825 #endif
    18261889        }
    18271890/*
     
    18661929                generate=false; // only special cuts
    18671930              if (generate) {
    1868                 generator_[i]->generateCuts(theseCuts,true,NULL) ;
     1931                generator_[i]->generateCuts(theseCuts,true,solver_,NULL) ;
    18691932                int numberRowCutsAfter = theseCuts.sizeRowCuts() ;
    18701933                if (numberRowCutsAfter) {
     
    19131976                heurValue = saveValue ; } }
    19141977            if (found >= 0) {
     1978              lastHeuristic_ = heuristic_[found];
    19151979              setBestSolution(CBC_ROUNDING,heurValue,newSolution) ;
    1916               lastHeuristic_ = heuristic_[found];
    19171980            }
    19181981            delete [] newSolution ;
     
    19642027  set.
    19652028*/
    1966         if (deleteNode)
    1967           delete node ; }
    1968 /*
    1969   End of the non-abort actions. The next block of code is executed if we've
    1970   aborted because we hit one of the limits. Clean up by deleting the live set
    1971   and break out of the node processing loop. Note that on an abort, node may
    1972   have been pushed back onto the tree for further processing, in which case
    1973   it'll be deleted in cleanTree. We need to check.
    1974 */
     2029      if (branchesLeft)
     2030      {
     2031      }
    19752032      else
    19762033      {
    1977         if (tree_->size())
    1978           tree_->cleanTree(this,-COIN_DBL_MAX,bestPossibleObjective_) ;
    1979         delete nextRowCut_;
    1980         // We need to get rid of node if is has already been popped from tree
    1981         if (!nodeOnTree&&!stoppedOnGap_&&node!=rootNode)
    1982           delete node;
    1983         if (stoppedOnGap_)
    1984         { messageHandler()->message(CBC_GAP,messages())
    1985             << bestObjective_-bestPossibleObjective_
    1986             << dblParam_[CbcAllowableGap]
    1987             << dblParam_[CbcAllowableFractionGap]*100.0
    1988             << CoinMessageEol ;
    1989         secondaryStatus_ = 2;
    1990           status_ = 0 ; }
    1991         else
    1992         if (isNodeLimitReached())
    1993         { handler_->message(CBC_MAXNODES,messages_) << CoinMessageEol ;
    1994         secondaryStatus_ = 3;
    1995           status_ = 1 ; }
    1996         else
    1997         if (totalTime >= dblParam_[CbcMaximumSeconds])
    1998         { handler_->message(CBC_MAXTIME,messages_) << CoinMessageEol ;
    1999         secondaryStatus_ = 4;
    2000           status_ = 1 ; }
    2001         else
    2002         if (eventHappened_)
    2003         { handler_->message(CBC_EVENT,messages_) << CoinMessageEol ;
    2004         secondaryStatus_ = 5;
    2005           status_ = 5 ; }
    2006         else
    2007         { handler_->message(CBC_MAXSOLS,messages_) << CoinMessageEol ;
    2008         secondaryStatus_ = 6;
    2009           status_ = 1 ; }
    2010         break ; }
     2034        if (!nodeInfo->numberBranchesLeft())
     2035          nodeInfo->allBranchesGone(); // can clean up
     2036        delete node ; }
     2037    } else {
     2038      // add cuts found to be infeasible (on bound)!
     2039      abort();
     2040      delete node;
     2041    }
    20112042/*
    20122043  Delete cuts to get back to the original system.
     
    20222053        { delRows[i] = i+numberRowsAtContinuous_ ; }
    20232054        solver_->deleteRows(numberToDelete,delRows) ;
    2024         delete [] delRows ; } }
    2025 /*
    2026   This node fathomed when addCuts atttempted to revive it. Toss it.
    2027 */
    2028     else
    2029       { delete node ; } }
     2055        delete [] delRows ; }
     2056#else // end of not CBC_THREAD
     2057      if (!numberThreads_) {
     2058        doOneNode(this,node,createdNode);
     2059      } else {
     2060        threadStats[0]++;
     2061        //need to think
     2062        int iThread;
     2063        // Start one off if any available
     2064        for (iThread=0;iThread<numberThreads_;iThread++) {
     2065          if (threadInfo[iThread].returnCode==-1)
     2066            break;
     2067        }
     2068        if (iThread<numberThreads_) {
     2069          threadInfo[iThread].node=node;
     2070          assert (threadInfo[iThread].returnCode==-1);
     2071          // say in use
     2072          threadInfo[iThread].returnCode=0;
     2073          threadModel[iThread]->moveToModel(this,0);
     2074          pthread_cond_signal(threadInfo[iThread].condition2); // unlock
     2075          threadCount[iThread]++;
     2076        }
     2077        lockThread();
     2078        locked=true;
     2079        // see if any finished
     2080        for (iThread=0;iThread<numberThreads_;iThread++) {
     2081          if (threadInfo[iThread].returnCode>0)
     2082            break;
     2083        }
     2084        unlockThread();
     2085        locked=false;
     2086        if (iThread<numberThreads_) {
     2087          threadModel[iThread]->moveToModel(this,1);
     2088          assert (threadInfo[iThread].returnCode==1);
     2089          // say available
     2090          threadInfo[iThread].returnCode=-1;
     2091          // carry on
     2092          threadStats[3]++;
     2093        } else {
     2094          // Start one off if any available
     2095          for (iThread=0;iThread<numberThreads_;iThread++) {
     2096            if (threadInfo[iThread].returnCode==-1)
     2097              break;
     2098          }
     2099          if (iThread<numberThreads_) {
     2100            lockThread();
     2101            locked=true;
     2102            // If any on tree get
     2103            if (!tree_->empty()) {
     2104              //node = tree_->bestNode(cutoff) ;
     2105              //assert (node);
     2106              threadStats[1]++;
     2107              continue; // ** get another node
     2108            }
     2109            unlockThread();
     2110            locked=false;
     2111          }
     2112          // wait (for debug could sleep and use test)
     2113          bool finished=false;
     2114          while (!finished) {
     2115#ifdef CONDITION_WAIT
     2116            pthread_mutex_lock(&condition_mutex);
     2117            struct timespec absTime;
     2118            clock_gettime(CLOCK_REALTIME,&absTime);
     2119            double time = absTime.tv_sec+1.0e-9*absTime.tv_nsec;
     2120            absTime.tv_nsec += 1000000; // millisecond
     2121            if (absTime.tv_nsec>=1000000000) {
     2122              absTime.tv_nsec -= 1000000000;
     2123              absTime.tv_sec++;
     2124            }
     2125            pthread_cond_timedwait(&condition_main,&condition_mutex,&absTime);
     2126            clock_gettime(CLOCK_REALTIME,&absTime);
     2127            double time2 = absTime.tv_sec+1.0e-9*absTime.tv_nsec;
     2128            timeWaiting += time2-time;
     2129            pthread_mutex_unlock(&condition_mutex);
     2130#else
     2131            struct timespec moreTime;
     2132            moreTime.tv_nsec = 100;
     2133            moreTime.tv_sec = 0;
     2134            nanosleep(&moreTime,NULL);
     2135#endif
     2136            for (iThread=0;iThread<numberThreads_;iThread++) {
     2137              if (threadInfo[iThread].returnCode>0) {
     2138                finished=true;
     2139                break;
     2140              } else if (threadInfo[iThread].returnCode==0) {
     2141                pthread_cond_signal(threadInfo[iThread].condition2); // unlock
     2142              }
     2143            }
     2144          }
     2145          assert (iThread<numberThreads_);
     2146          threadModel[iThread]->moveToModel(this,1);
     2147          node = threadInfo[iThread].node;
     2148          threadInfo[iThread].node=NULL;
     2149          assert (threadInfo[iThread].returnCode==1);
     2150          // say available
     2151          threadInfo[iThread].returnCode=-1;
     2152          // carry on
     2153          threadStats[2]++;
     2154        }
     2155      }
     2156      //lastDepth=node->depth();
     2157      //lastUnsatisfied=node->numberUnsatisfied();
     2158#endif // end of CBC_THREAD
     2159  }
     2160#ifdef CBC_THREAD
     2161  if (numberThreads_) {
     2162    //printf("stats ");
     2163    //for (unsigned int j=0;j<sizeof(threadStats)/sizeof(int);j++)
     2164    //printf("%d ",threadStats[j]);
     2165    //printf("\n");
     2166    int i;
     2167    // Seems to be bug in CoinCpu on Linux - does threads as well despite documentation
     2168    double time=0.0;
     2169    for (i=0;i<numberThreads_;i++)
     2170      time += threadInfo[i].timeInThread;
     2171    bool goodTimer = time<(CoinCpuTime() - dblParam_[CbcStartSeconds]);
     2172    for (i=0;i<numberThreads_;i++) {
     2173      pthread_cond_signal(threadInfo[i].condition2); // unlock
     2174      while (threadInfo[i].returnCode==0) {
     2175        struct timespec moreTime;
     2176        moreTime.tv_nsec = 10000;
     2177        moreTime.tv_sec = 0;
     2178        nanosleep(&moreTime,NULL);
     2179      }
     2180      threadModel[i]->numberThreads_=0; // say exit
     2181      threadInfo[i].returnCode=0;
     2182      pthread_cond_signal(threadInfo[i].condition2); // unlock
     2183      pthread_join(threadId[i],NULL);
     2184      threadModel[i]->moveToModel(this,2);
     2185      pthread_mutex_destroy (threadInfo[i].mutex2);
     2186      pthread_cond_destroy (threadInfo[i].condition2);
     2187      assert (threadInfo[i].numberTimesLocked==threadInfo[i].numberTimesUnlocked);
     2188      handler_->message(CBC_THREAD_STATS,messages_)
     2189        <<"Thread";
     2190      handler_->printing(true)
     2191        <<i<<threadCount[i]<<threadInfo[i].timeWaitingToStart;
     2192      handler_->printing(goodTimer)<<threadInfo[i].timeInThread;
     2193      handler_->printing(false)<<0.0;
     2194      handler_->printing(true)<<threadInfo[i].numberTimesLocked
     2195        <<threadInfo[i].timeLocked<<threadInfo[i].timeWaitingToLock
     2196        <<CoinMessageEol;
     2197    }
     2198    assert (threadInfo[numberThreads_].numberTimesLocked==threadInfo[numberThreads_].numberTimesUnlocked);
     2199    handler_->message(CBC_THREAD_STATS,messages_)
     2200      <<"Main thread";
     2201    handler_->printing(false)<<0<<0<<0.0;
     2202    handler_->printing(false)<<0.0;
     2203    handler_->printing(true)<<timeWaiting;
     2204    handler_->printing(true)<<threadInfo[numberThreads_].numberTimesLocked
     2205      <<threadInfo[numberThreads_].timeLocked<<threadInfo[numberThreads_].timeWaitingToLock
     2206      <<CoinMessageEol;
     2207    pthread_mutex_destroy (&mutex);
     2208    pthread_cond_destroy (&condition_main);
     2209    pthread_mutex_destroy (&condition_mutex);
     2210    // delete models (here in case some point to others)
     2211    for (i=0;i<numberThreads_;i++) {
     2212      delete threadModel[i];
     2213    }
     2214    delete [] mutex2;
     2215    delete [] condition2;
     2216    delete [] threadId;
     2217    delete [] threadInfo;
     2218    delete [] threadModel;
     2219    delete [] threadCount;
     2220    mutex_=NULL;
     2221  }
     2222#endif
     2223/*
     2224  End of the non-abort actions. The next block of code is executed if we've
     2225  aborted because we hit one of the limits. Clean up by deleting the live set
     2226  and break out of the node processing loop. Note that on an abort, node may
     2227  have been pushed back onto the tree for further processing, in which case
     2228  it'll be deleted in cleanTree. We need to check.
     2229*/
     2230    if (!(numberNodes_ < intParam_[CbcMaxNumNode] &&
     2231        numberSolutions_ < intParam_[CbcMaxNumSol] &&
     2232        totalTime < dblParam_[CbcMaximumSeconds] &&
     2233        !stoppedOnGap_&&!eventHappened_)) {
     2234      if (tree_->size())
     2235        tree_->cleanTree(this,-COIN_DBL_MAX,bestPossibleObjective_) ;
     2236      delete nextRowCut_;
     2237      if (stoppedOnGap_)
     2238        { messageHandler()->message(CBC_GAP,messages())
     2239          << bestObjective_-bestPossibleObjective_
     2240          << dblParam_[CbcAllowableGap]
     2241          << dblParam_[CbcAllowableFractionGap]*100.0
     2242          << CoinMessageEol ;
     2243        secondaryStatus_ = 2;
     2244        status_ = 0 ; }
     2245        else
     2246          if (isNodeLimitReached())
     2247            { handler_->message(CBC_MAXNODES,messages_) << CoinMessageEol ;
     2248            secondaryStatus_ = 3;
     2249            status_ = 1 ; }
     2250          else
     2251        if (totalTime >= dblParam_[CbcMaximumSeconds])
     2252          { handler_->message(CBC_MAXTIME,messages_) << CoinMessageEol ;
     2253          secondaryStatus_ = 4;
     2254          status_ = 1 ; }
     2255        else
     2256          if (eventHappened_)
     2257            { handler_->message(CBC_EVENT,messages_) << CoinMessageEol ;
     2258            secondaryStatus_ = 5;
     2259            status_ = 5 ; }
     2260          else
     2261            { handler_->message(CBC_MAXSOLS,messages_) << CoinMessageEol ;
     2262            secondaryStatus_ = 6;
     2263            status_ = 1 ; }
     2264    }
    20302265/*
    20312266  That's it, we've exhausted the search tree, or broken out of the loop because
     
    24642699  subTreeModel_(NULL),
    24652700  numberStoppedSubTrees_(0),
     2701  mutex_(NULL),
    24662702  presolve_(0),
    24672703  numberStrong_(5),
     
    25112747  searchStrategy_(-1),
    25122748  numberStrongIterations_(0),
    2513   resolveAfterTakeOffCuts_(true)
     2749  resolveAfterTakeOffCuts_(true),
     2750  numberThreads_(0),
     2751  threadMode_(0)
    25142752{
    25152753  memset(intParam_,0,sizeof(intParam_));
     
    25942832  subTreeModel_(NULL),
    25952833  numberStoppedSubTrees_(0),
     2834  mutex_(NULL),
    25962835  presolve_(0),
    25972836  numberStrong_(5),
     
    26412880  searchStrategy_(-1),
    26422881  numberStrongIterations_(0),
    2643   resolveAfterTakeOffCuts_(true)
     2882  resolveAfterTakeOffCuts_(true),
     2883  numberThreads_(0),
     2884  threadMode_(0)
    26442885{
    26452886  memset(intParam_,0,sizeof(intParam_));
     
    28193060  subTreeModel_(rhs.subTreeModel_),
    28203061  numberStoppedSubTrees_(rhs.numberStoppedSubTrees_),
     3062  mutex_(NULL),
    28213063  presolve_(rhs.presolve_),
    28223064  numberStrong_(rhs.numberStrong_),
     
    28553097  searchStrategy_(rhs.searchStrategy_),
    28563098  numberStrongIterations_(rhs.numberStrongIterations_),
    2857   resolveAfterTakeOffCuts_(rhs.resolveAfterTakeOffCuts_)
     3099  resolveAfterTakeOffCuts_(rhs.resolveAfterTakeOffCuts_),
     3100  numberThreads_(rhs.numberThreads_),
     3101  threadMode_(rhs.threadMode_)
    28583102{
    28593103  memcpy(intParam_,rhs.intParam_,sizeof(intParam_));
     
    29073151      object_ = new OsiObject * [numberObjects_];
    29083152      int i;
    2909       for (i=0;i<numberObjects_;i++)
     3153      for (i=0;i<numberObjects_;i++) {
    29103154        object_[i]=(rhs.object_[i])->clone();
     3155        CbcObject * obj = dynamic_cast <CbcObject *>(object_[i]) ;
     3156        assert (obj);
     3157        obj->setModel(this);
     3158      }
    29113159    } else {
    29123160      object_=NULL;
     
    31053353    subTreeModel_ = rhs.subTreeModel_;
    31063354    numberStoppedSubTrees_ = rhs.numberStoppedSubTrees_;
     3355    mutex_ = NULL;
    31073356    presolve_ = rhs.presolve_;
    31083357    numberStrong_ = rhs.numberStrong_;
     
    31563405    numberNewCuts_ = rhs.numberNewCuts_;
    31573406    resolveAfterTakeOffCuts_=rhs.resolveAfterTakeOffCuts_;
     3407    numberThreads_ = rhs.numberThreads_;
     3408    threadMode_ = rhs.threadMode_;
    31583409    sizeMiniTree_ = rhs.sizeMiniTree_;
    31593410    searchStrategy_ = rhs.searchStrategy_;
     
    36863937*/
    36873938  currentNumberCuts_=currentNumberCuts;
    3688   if (currentNumberCuts >= maximumNumberCuts_) {
     3939  if (currentNumberCuts > maximumNumberCuts_) {
    36893940    maximumNumberCuts_ = currentNumberCuts;
    36903941    delete [] addedCuts_;
     
    37844035  reconstructed basis in the solver.
    37854036*/
    3786   if (node->objectiveValue() < cutoff)
     4037  if (node->objectiveValue() < cutoff||numberThreads_)
    37874038  {
    37884039#   ifdef CBC_CHECK_BASIS
     
    38644115  set. Adjust the cut reference counts to reflect that we no longer need to
    38654116  explore the remaining branch arms, hence they will no longer reference any
    3866   cuts. Cuts whose reference count falls to zero are deleted.
     4117  cuts. Cuts whose reference count falls to zero are deleted. 
    38674118*/
    38684119  else
    38694120  { int i;
    3870     int numberLeft = nodeInfo->numberBranchesLeft();
    3871     for (i = 0 ; i < currentNumberCuts ; i++)
    3872     { if (addedCuts_[i])
    3873       { if (!addedCuts_[i]->decrement(numberLeft))
    3874         { delete addedCuts_[i];
    3875           addedCuts_[i] = NULL; } } }
     4121    if (currentNumberCuts) {
     4122      lockThread();
     4123      int numberLeft = nodeInfo->numberBranchesLeft();
     4124      for (i = 0 ; i < currentNumberCuts ; i++)
     4125        { if (addedCuts_[i])
     4126          { if (!addedCuts_[i]->decrement(numberLeft))
     4127            { delete addedCuts_[i];
     4128            addedCuts_[i] = NULL; } } }
     4129      unlockThread();
     4130    }
    38764131    return 1 ; }
    38774132}
     
    39884243    saveClpOptions = clpSolver->specialOptions();
    39894244# endif
     4245#ifdef CBC_THREAD
     4246  CbcModel ** threadModel = NULL;
     4247  pthread_t * threadId = NULL;
     4248  pthread_cond_t condition_main;
     4249  pthread_mutex_t condition_mutex;
     4250  pthread_mutex_t * mutex2 = NULL;
     4251  pthread_cond_t * condition2 = NULL;
     4252  threadStruct * threadInfo = NULL;
     4253  void * saveMutex = NULL;
     4254  if (numberThreads_&&(threadMode_&2)!=0&&!numberNodes_) {
     4255    threadId = new pthread_t [numberThreads_];
     4256    pthread_cond_init(&condition_main,NULL);
     4257    pthread_mutex_init(&condition_mutex,NULL);
     4258    threadModel = new CbcModel * [numberThreads_];
     4259    threadInfo = new threadStruct [numberThreads_+1];
     4260    mutex2 = new pthread_mutex_t [numberThreads_];
     4261    condition2 = new pthread_cond_t [numberThreads_];
     4262    saveMutex = mutex_;
     4263    for (int i=0;i<numberThreads_;i++) {
     4264      pthread_mutex_init(mutex2+i,NULL);
     4265      pthread_cond_init(condition2+i,NULL);
     4266      threadId[i]=0;
     4267      threadModel[i]=new CbcModel;
     4268      threadModel[i]->generator_ = new CbcCutGenerator * [1];
     4269      delete threadModel[i]->solver_;
     4270      threadModel[i]->solver_=NULL;
     4271      threadModel[i]->numberThreads_=numberThreads_;
     4272      mutex_ = (void *) (threadInfo+i);
     4273      threadInfo[i].thisModel=(CbcModel *) threadModel[i];
     4274      threadInfo[i].baseModel=this;
     4275      threadInfo[i].threadIdOfBase=pthread_self();
     4276      threadInfo[i].mutex2=mutex2+i;
     4277      threadInfo[i].condition2=condition2+i;
     4278      threadInfo[i].returnCode=-1;
     4279      pthread_create(threadId+i,NULL,doCutsThread,threadInfo+i);
     4280    }
     4281    // Do a partial one for base model
     4282    threadInfo[numberThreads_].baseModel=this;
     4283    mutex_ = (void *) (threadInfo+numberThreads_);
     4284    threadInfo[numberThreads_].condition2=&condition_main;
     4285    threadInfo[numberThreads_].mutex2=&condition_mutex;
     4286  }
     4287#endif
    39904288  bool feasible = true ;
    39914289  int lastNumberCuts = 0 ;
     
    40264324  //printf("zero iterations on first solve of branch\n");
    40274325#endif
    4028   if (node&&!node->nodeInfo()->numberBranchesLeft())
     4326  if (node&&node->nodeInfo()&&!node->nodeInfo()->numberBranchesLeft())
    40294327    node->nodeInfo()->allBranchesGone(); // can clean up
    40304328  feasible = returnCode  != 0 ;
     
    42444542      whichGenerator_[numberViolated++]=-2;
    42454543    }
    4246     double * newSolution = new double [numberColumns] ;
    4247     double heuristicValue = getCutoff() ;
    4248     int found = -1; // no solution found
    42494544
    42504545    // reset probing info
    42514546    if (probingInfo_)
    42524547      probingInfo_->initializeFixing();
    4253     for (int i = 0;i<numberCutGenerators_+numberHeuristics_;i++) {
    4254       int numberRowCutsBefore = theseCuts.sizeRowCuts() ;
    4255       int numberColumnCutsBefore = theseCuts.sizeColCuts() ;
    4256       if (i<numberCutGenerators_) {
    4257         bool generate = generator_[i]->normal();
    4258         // skip if not optimal and should be (maybe a cut generator has fixed variables)
    4259         if (generator_[i]->needsOptimalBasis()&&!solver_->basisIsAvailable())
    4260           generate=false;
    4261         if (generator_[i]->switchedOff())
    4262           generate=false;;
     4548    int i;
     4549    if ((threadMode_&2)==0||numberNodes_) {
     4550      for (i = 0;i<numberCutGenerators_;i++) {
     4551        int numberRowCutsBefore = theseCuts.sizeRowCuts() ;
     4552        int numberColumnCutsBefore = theseCuts.sizeColCuts() ;
     4553        bool generate = generator_[i]->normal();
     4554        // skip if not optimal and should be (maybe a cut generator has fixed variables)
     4555        if (generator_[i]->needsOptimalBasis()&&!solver_->basisIsAvailable())
     4556          generate=false;
     4557        if (generator_[i]->switchedOff())
     4558          generate=false;;
    42634559        if (generate) {
    42644560          bool mustResolve =
    4265             generator_[i]->generateCuts(theseCuts,fullScan,node) ;
     4561            generator_[i]->generateCuts(theseCuts,fullScan,solver_,node) ;
    42664562          int numberRowCutsAfter = theseCuts.sizeRowCuts() ;
    4267           if(numberRowCutsBefore < numberRowCutsAfter &&
    4268              generator_[i]->mustCallAgain())
    4269             keepGoing=true; // say must go round
     4563          if(numberRowCutsBefore < numberRowCutsAfter &&
     4564             generator_[i]->mustCallAgain())
     4565            keepGoing=true; // say must go round
    42704566          // Check last cut to see if infeasible
    4271           if(numberRowCutsBefore < numberRowCutsAfter) {
     4567          if(numberRowCutsBefore < numberRowCutsAfter) {
    42724568            const OsiRowCut * thisCut = theseCuts.rowCutPtr(numberRowCutsAfter-1) ;
    42734569            if (thisCut->lb()>thisCut->ub()) {
     
    42774573          }
    42784574#ifdef CBC_DEBUG
    4279           {
    4280             int numberRowCutsAfter = theseCuts.sizeRowCuts() ;
    4281             int k ;
    4282             for (k = numberRowCutsBefore;k<numberRowCutsAfter;k++) {
    4283               OsiRowCut thisCut = theseCuts.rowCut(k) ;
    4284               /* check size of elements.
    4285                  We can allow smaller but this helps debug generators as it
    4286                  is unsafe to have small elements */
    4287               int n=thisCut.row().getNumElements();
    4288               const int * column = thisCut.row().getIndices();
    4289               const double * element = thisCut.row().getElements();
    4290               //assert (n);
    4291               for (int i=0;i<n;i++) {
    4292                 double value = element[i];
    4293                 assert(fabs(value)>1.0e-12&&fabs(value)<1.0e20);
    4294               }
    4295             }
    4296           }
     4575          {
     4576            int k ;
     4577            for (k = numberRowCutsBefore;k<numberRowCutsAfter;k++) {
     4578              OsiRowCut thisCut = theseCuts.rowCut(k) ;
     4579              /* check size of elements.
     4580                 We can allow smaller but this helps debug generators as it
     4581                 is unsafe to have small elements */
     4582              int n=thisCut.row().getNumElements();
     4583              const int * column = thisCut.row().getIndices();
     4584              const double * element = thisCut.row().getElements();
     4585              //assert (n);
     4586              for (int i=0;i<n;i++) {
     4587                double value = element[i];
     4588                assert(fabs(value)>1.0e-12&&fabs(value)<1.0e20);
     4589              }
     4590            }
     4591          }
    42974592#endif
    42984593          if (mustResolve) {
    4299             int returncode = resolve(node ? node->nodeInfo() : NULL,2);
    4300             feasible = returnCode  != 0 ;
    4301             if (returncode<0)
    4302               numberTries=0;
    4303             if ((specialOptions_&1)!=0) {
    4304               debugger = solver_->getRowCutDebugger() ;
    4305               if (debugger)
    4306                 onOptimalPath = (debugger->onOptimalPath(*solver_)) ;
    4307               else
    4308                 onOptimalPath=false;
    4309               if (onOptimalPath && !solver_->isDualObjectiveLimitReached())
    4310                 assert(feasible) ;
    4311             }
     4594            int returncode = resolve(node ? node->nodeInfo() : NULL,2);
     4595            feasible = returnCode  != 0 ;
     4596            if (returncode<0)
     4597              numberTries=0;
     4598            if ((specialOptions_&1)!=0) {
     4599              debugger = solver_->getRowCutDebugger() ;
     4600              if (debugger)
     4601                onOptimalPath = (debugger->onOptimalPath(*solver_)) ;
     4602              else
     4603                onOptimalPath=false;
     4604              if (onOptimalPath && !solver_->isDualObjectiveLimitReached())
     4605                assert(feasible) ;
     4606            }
    43124607            if (!feasible)
    43134608              break ;
    43144609          }
    43154610        }
     4611        int numberRowCutsAfter = theseCuts.sizeRowCuts() ;
     4612        int numberColumnCutsAfter = theseCuts.sizeColCuts() ;
     4613       
     4614        if ((specialOptions_&1)!=0) {
     4615          if (onOptimalPath) {
     4616            int k ;
     4617            for (k = numberRowCutsBefore;k<numberRowCutsAfter;k++) {
     4618              OsiRowCut thisCut = theseCuts.rowCut(k) ;
     4619              if(debugger->invalidCut(thisCut)) {
     4620                solver_->writeMps("badCut");
     4621#ifdef NDEBUG
     4622                printf("Cut generator %d (%s) produced invalid cut (%dth in this go)\n",
     4623                       i,generator_[i]->cutGeneratorName(),k-numberRowCutsBefore);
     4624                abort();
     4625#endif
     4626              }
     4627              assert(!debugger->invalidCut(thisCut)) ;
     4628            }
     4629          }
     4630        }
     4631/*
     4632  The cut generator has done its thing, and maybe it generated some
     4633  cuts.  Do a bit of bookkeeping: load
     4634  whichGenerator[i] with the index of the generator responsible for a cut,
     4635  and place cuts flagged as global in the global cut pool for the model.
     4636
     4637  lastNumberCuts is the sum of cuts added in previous iterations; it's the
     4638  offset to the proper starting position in whichGenerator.
     4639*/
     4640        int numberBefore =
     4641          numberRowCutsBefore+numberColumnCutsBefore+lastNumberCuts ;
     4642        int numberAfter =
     4643          numberRowCutsAfter+numberColumnCutsAfter+lastNumberCuts ;
     4644        // possibly extend whichGenerator
     4645        resizeWhichGenerator(numberBefore, numberAfter);
     4646        int j ;
     4647        if (fullScan) {
     4648          // counts
     4649          countColumnCuts[i] += numberColumnCutsAfter-numberColumnCutsBefore ;
     4650        }
     4651        countRowCuts[i] += numberRowCutsAfter-numberRowCutsBefore ;
     4652       
     4653        for (j = numberRowCutsBefore;j<numberRowCutsAfter;j++) {
     4654          whichGenerator_[numberBefore++] = i ;
     4655          const OsiRowCut * thisCut = theseCuts.rowCutPtr(j) ;
     4656          if (thisCut->lb()>thisCut->ub())
     4657            violated=-2; // sub-problem is infeasible
     4658          if (thisCut->globallyValid()) {
     4659            // add to global list
     4660            OsiRowCut newCut(*thisCut);
     4661            newCut.setGloballyValid(2);
     4662            newCut.mutableRow().setTestForDuplicateIndex(false);
     4663            globalCuts_.insert(newCut) ;
     4664          }
     4665        }
     4666        for (j = numberColumnCutsBefore;j<numberColumnCutsAfter;j++) {
     4667          whichGenerator_[numberBefore++] = i ;
     4668          const OsiColCut * thisCut = theseCuts.colCutPtr(j) ;
     4669          if (thisCut->globallyValid()) {
     4670            // add to global list
     4671            OsiColCut newCut(*thisCut);
     4672            newCut.setGloballyValid(2);
     4673            globalCuts_.insert(newCut) ;
     4674          }
     4675        }
     4676      }
     4677      // Add in any violated saved cuts
     4678      if (!theseCuts.sizeRowCuts()&&!theseCuts.sizeColCuts()) {
     4679        int numberOld = theseCuts.sizeRowCuts();
     4680        int numberCuts = slackCuts.sizeRowCuts() ;
     4681        int i;
     4682        // possibly extend whichGenerator
     4683        resizeWhichGenerator(numberOld, numberOld+numberCuts);
     4684        for ( i = 0;i<numberCuts;i++) {
     4685          const OsiRowCut * thisCut = slackCuts.rowCutPtr(i) ;
     4686          if (thisCut->violated(cbcColSolution_)>100.0*primalTolerance) {
     4687            if (messageHandler()->logLevel()>2)
     4688              printf("Old cut added - violation %g\n",
     4689                     thisCut->violated(cbcColSolution_)) ;
     4690            whichGenerator_[numberOld++]=-1;
     4691            theseCuts.insert(*thisCut) ;
     4692          }
     4693        }
     4694      }
     4695    } else {
     4696      // do cuts independently
     4697      OsiCuts * eachCuts = new OsiCuts [numberCutGenerators_];;
     4698#ifdef CBC_THREAD
     4699      if (!threadModel) {
     4700#endif
     4701        // generate cuts
     4702        for (i = 0;i<numberCutGenerators_;i++) {
     4703          bool generate = generator_[i]->normal();
     4704          // skip if not optimal and should be (maybe a cut generator has fixed variables)
     4705          if (generator_[i]->needsOptimalBasis()&&!solver_->basisIsAvailable())
     4706            generate=false;
     4707          if (generator_[i]->switchedOff())
     4708            generate=false;;
     4709          if (generate)
     4710            generator_[i]->generateCuts(eachCuts[i],fullScan,solver_,node) ;
     4711        }
     4712#ifdef CBC_THREAD
    43164713      } else {
     4714        for (i=0;i<numberThreads_;i++) {
     4715          // set solver here after cloning
     4716          threadModel[i]->solver_=solver_->clone();
     4717          threadModel[i]->numberNodes_ = (fullScan) ? 1 : 0;
     4718        }
     4719        // generate cuts
     4720        for (i = 0;i<numberCutGenerators_;i++) {
     4721          bool generate = generator_[i]->normal();
     4722          // skip if not optimal and should be (maybe a cut generator has fixed variables)
     4723          if (generator_[i]->needsOptimalBasis()&&!solver_->basisIsAvailable())
     4724            generate=false;
     4725          if (generator_[i]->switchedOff())
     4726            generate=false;;
     4727          if (generate) {
     4728            bool finished=false;
     4729            int iThread=-1;
     4730            // see if any available
     4731            for (iThread=0;iThread<numberThreads_;iThread++) {
     4732              if (threadInfo[iThread].returnCode) {
     4733                finished=true;
     4734                break;
     4735              } else if (threadInfo[iThread].returnCode==0) {
     4736#ifdef CONDITION_WAIT
     4737                pthread_cond_signal(threadInfo[iThread].condition2); // unlock
     4738#endif
     4739              }
     4740            }
     4741            while (!finished) {
     4742#ifdef CONDITION_WAIT
     4743              pthread_mutex_lock(&condition_mutex);
     4744              struct timespec absTime;
     4745              clock_gettime(CLOCK_REALTIME,&absTime);
     4746              absTime.tv_nsec += 1000000; // millisecond
     4747              if (absTime.tv_nsec>=1000000000) {
     4748                absTime.tv_nsec -= 1000000000;
     4749                absTime.tv_sec++;
     4750              }
     4751              pthread_cond_timedwait(&condition_main,&condition_mutex,&absTime);
     4752              pthread_mutex_unlock(&condition_mutex);
     4753#else
     4754              struct timespec moreTime;
     4755              moreTime.tv_nsec = 100;
     4756              moreTime.tv_sec = 0 ;
     4757              nanosleep(&moreTime,NULL);
     4758#endif
     4759              for (iThread=0;iThread<numberThreads_;iThread++) {
     4760                if (threadInfo[iThread].returnCode>0) {
     4761                  finished=true;
     4762                  break;
     4763                } else if (threadInfo[iThread].returnCode==0) {
     4764#ifdef CONDITION_WAIT
     4765                  pthread_cond_signal(threadInfo[iThread].condition2); // unlock
     4766#endif
     4767                }
     4768              }
     4769            }
     4770            assert (iThread<numberThreads_);
     4771            assert (threadInfo[iThread].returnCode);
     4772            threadModel[iThread]->generator_[0]=generator_[i];
     4773            threadModel[iThread]->object_ = (OsiObject **) (eachCuts+i);
     4774            // allow to start
     4775            threadInfo[iThread].returnCode=0;
     4776#ifdef CONDITION_WAIT
     4777            pthread_cond_signal(threadInfo[iThread].condition2); // unlock
     4778#endif
     4779          }
     4780        }
     4781        // wait
     4782        for (int iThread=0;iThread<numberThreads_;iThread++) {
     4783          if (threadInfo[iThread].returnCode==0) {
     4784            bool finished=false;
     4785#ifdef CONDITION_WAIT
     4786            pthread_cond_signal(threadInfo[iThread].condition2); // unlock
     4787#endif
     4788            while (!finished) {
     4789#ifdef CONDITION_WAIT
     4790              pthread_mutex_lock(&condition_mutex);
     4791              struct timespec absTime;
     4792              clock_gettime(CLOCK_REALTIME,&absTime);
     4793              absTime.tv_nsec += 1000000; // millisecond
     4794              if (absTime.tv_nsec>=1000000000) {
     4795                absTime.tv_nsec -= 1000000000;
     4796                absTime.tv_sec++;
     4797              }
     4798              pthread_cond_timedwait(&condition_main,&condition_mutex,&absTime);
     4799              pthread_mutex_unlock(&condition_mutex);
     4800#else
     4801              struct timespec moreTime;
     4802              moreTime.tv_nsec = 100;
     4803              moreTime.tv_sec = 0;
     4804              nanosleep(&moreTime,NULL);
     4805#endif
     4806              if (threadInfo[iThread].returnCode>0) {
     4807                finished=true;
     4808                break;
     4809              } else if (threadInfo[iThread].returnCode==0) {
     4810#ifdef CONDITION_WAIT
     4811                pthread_cond_signal(threadInfo[iThread].condition2); // unlock
     4812#endif
     4813              }
     4814            }
     4815          }
     4816          assert (threadInfo[iThread].returnCode);
     4817          // say available
     4818          threadInfo[iThread].returnCode=-1;
     4819          delete threadModel[iThread]->solver_;
     4820          threadModel[iThread]->solver_=NULL;
     4821        }
     4822      }
     4823#endif
     4824      // Now put together
     4825      for (i = 0;i<numberCutGenerators_;i++) {
     4826        // add column cuts
     4827        int numberColumnCutsBefore = theseCuts.sizeColCuts() ;
     4828        int numberColumnCuts = eachCuts[i].sizeColCuts();
     4829        int numberColumnCutsAfter = numberColumnCutsBefore
     4830          + numberColumnCuts;
     4831        int j;
     4832        for (j=0;j<numberColumnCuts;j++) {
     4833          theseCuts.insert(eachCuts[i].colCut(j));
     4834        }
     4835        int numberRowCutsBefore = theseCuts.sizeRowCuts() ;
     4836        int numberRowCuts = eachCuts[i].sizeRowCuts();
     4837        int numberRowCutsAfter = numberRowCutsBefore
     4838          + numberRowCuts;
     4839        if (numberRowCuts) {
     4840          for (j=0;j<numberRowCuts;j++) {
     4841            theseCuts.insert(eachCuts[i].rowCut(j));
     4842          }
     4843          if (generator_[i]->mustCallAgain())
     4844            keepGoing=true; // say must go round
     4845          // Check last cut to see if infeasible
     4846          const OsiRowCut * thisCut = theseCuts.rowCutPtr(numberRowCutsAfter-1) ;
     4847          if (thisCut->lb()>thisCut->ub()) {
     4848            feasible = false; // sub-problem is infeasible
     4849            break;
     4850          }
     4851        }
     4852#ifdef CBC_DEBUG
     4853        {
     4854          int k ;
     4855          for (k = numberRowCutsBefore;k<numberRowCutsAfter;k++) {
     4856            OsiRowCut thisCut = theseCuts.rowCut(k) ;
     4857            /* check size of elements.
     4858               We can allow smaller but this helps debug generators as it
     4859               is unsafe to have small elements */
     4860            int n=thisCut.row().getNumElements();
     4861            const int * column = thisCut.row().getIndices();
     4862            const double * element = thisCut.row().getElements();
     4863            //assert (n);
     4864            for (int i=0;i<n;i++) {
     4865              double value = element[i];
     4866              assert(fabs(value)>1.0e-12&&fabs(value)<1.0e20);
     4867            }
     4868          }
     4869        }
     4870#endif
     4871        if ((specialOptions_&1)!=0) {
     4872          if (onOptimalPath) {
     4873            int k ;
     4874            for (k = numberRowCutsBefore;k<numberRowCutsAfter;k++) {
     4875              OsiRowCut thisCut = theseCuts.rowCut(k) ;
     4876              if(debugger->invalidCut(thisCut)) {
     4877                solver_->writeMps("badCut");
     4878#ifdef NDEBUG
     4879                printf("Cut generator %d (%s) produced invalid cut (%dth in this go)\n",
     4880                       i,generator_[i]->cutGeneratorName(),k-numberRowCutsBefore);
     4881                abort();
     4882#endif
     4883              }
     4884              assert(!debugger->invalidCut(thisCut)) ;
     4885            }
     4886          }
     4887        }
     4888/*
     4889  The cut generator has done its thing, and maybe it generated some
     4890  cuts.  Do a bit of bookkeeping: load
     4891  whichGenerator[i] with the index of the generator responsible for a cut,
     4892  and place cuts flagged as global in the global cut pool for the model.
     4893
     4894  lastNumberCuts is the sum of cuts added in previous iterations; it's the
     4895  offset to the proper starting position in whichGenerator.
     4896*/
     4897        int numberBefore =
     4898          numberRowCutsBefore+numberColumnCutsBefore+lastNumberCuts ;
     4899        int numberAfter =
     4900          numberRowCutsAfter+numberColumnCutsAfter+lastNumberCuts ;
     4901        // possibly extend whichGenerator
     4902        resizeWhichGenerator(numberBefore, numberAfter);
     4903        if (fullScan) {
     4904          // counts
     4905          countColumnCuts[i] += numberColumnCutsAfter-numberColumnCutsBefore ;
     4906        }
     4907        countRowCuts[i] += numberRowCutsAfter-numberRowCutsBefore ;
     4908       
     4909        for (j = numberRowCutsBefore;j<numberRowCutsAfter;j++) {
     4910          whichGenerator_[numberBefore++] = i ;
     4911          const OsiRowCut * thisCut = theseCuts.rowCutPtr(j) ;
     4912          if (thisCut->lb()>thisCut->ub())
     4913            violated=-2; // sub-problem is infeasible
     4914          if (thisCut->globallyValid()) {
     4915            // add to global list
     4916            OsiRowCut newCut(*thisCut);
     4917            newCut.setGloballyValid(2);
     4918            newCut.mutableRow().setTestForDuplicateIndex(false);
     4919            globalCuts_.insert(newCut) ;
     4920          }
     4921        }
     4922        for (j = numberColumnCutsBefore;j<numberColumnCutsAfter;j++) {
     4923          whichGenerator_[numberBefore++] = i ;
     4924          const OsiColCut * thisCut = theseCuts.colCutPtr(j) ;
     4925          if (thisCut->globallyValid()) {
     4926            // add to global list
     4927            OsiColCut newCut(*thisCut);
     4928            newCut.setGloballyValid(2);
     4929            globalCuts_.insert(newCut) ;
     4930          }
     4931        }
     4932      }
     4933      // Add in any violated saved cuts
     4934      if (!theseCuts.sizeRowCuts()&&!theseCuts.sizeColCuts()) {
     4935        int numberOld = theseCuts.sizeRowCuts();
     4936        int numberCuts = slackCuts.sizeRowCuts() ;
     4937        int i;
     4938        // possibly extend whichGenerator
     4939        resizeWhichGenerator(numberOld, numberOld+numberCuts);
     4940        for ( i = 0;i<numberCuts;i++) {
     4941          const OsiRowCut * thisCut = slackCuts.rowCutPtr(i) ;
     4942          if (thisCut->violated(cbcColSolution_)>100.0*primalTolerance) {
     4943            if (messageHandler()->logLevel()>2)
     4944              printf("Old cut added - violation %g\n",
     4945                     thisCut->violated(cbcColSolution_)) ;
     4946            whichGenerator_[numberOld++]=-1;
     4947            theseCuts.insert(*thisCut) ;
     4948          }
     4949        }
     4950      }
     4951      delete [] eachCuts;
     4952    }
     4953    //if (!feasible)
     4954    //break;
     4955/*
     4956  End of the loop to exercise each generator - try heuristics
     4957  - unless at root node and first pass
     4958*/
     4959    if (numberNodes_||currentPassNumber_!=1) {
     4960      double * newSolution = new double [numberColumns] ;
     4961      double heuristicValue = getCutoff() ;
     4962      int found = -1; // no solution found
     4963      for (i = 0;i<numberHeuristics_;i++) {
    43174964        // see if heuristic will do anything
    43184965        double saveValue = heuristicValue ;
    43194966        int ifSol =
    4320           heuristic_[i-numberCutGenerators_]->solution(heuristicValue,
    4321                                                        newSolution,
    4322                                                        theseCuts) ;
     4967          heuristic_[i]->solution(heuristicValue,
     4968                                  newSolution,
     4969                                  theseCuts) ;
    43234970        if (ifSol>0) {
    43244971          // better solution found
    4325           found = i-numberCutGenerators_ ;
     4972          found = i ;
    43264973          incrementUsed(newSolution);
    43274974        } else if (ifSol<0) {
     
    43294976        }
    43304977      }
    4331       int numberRowCutsAfter = theseCuts.sizeRowCuts() ;
    4332       int numberColumnCutsAfter = theseCuts.sizeColCuts() ;
    4333 
    4334       if ((specialOptions_&1)!=0) {
    4335         if (onOptimalPath) {
    4336           int k ;
    4337           for (k = numberRowCutsBefore;k<numberRowCutsAfter;k++) {
    4338             OsiRowCut thisCut = theseCuts.rowCut(k) ;
    4339             if(debugger->invalidCut(thisCut)) {
    4340               solver_->writeMps("badCut");
    4341             }
    4342             assert(!debugger->invalidCut(thisCut)) ;
    4343           }
    4344         }
    4345       }
    4346 /*
    4347   The cut generator/heuristic has done its thing, and maybe it generated some
    4348   cuts and/or a new solution.  Do a bit of bookkeeping: load
    4349   whichGenerator[i] with the index of the generator responsible for a cut,
    4350   and place cuts flagged as global in the global cut pool for the model.
    4351 
    4352   lastNumberCuts is the sum of cuts added in previous iterations; it's the
    4353   offset to the proper starting position in whichGenerator.
    4354 */
    4355       int numberBefore =
    4356             numberRowCutsBefore+numberColumnCutsBefore+lastNumberCuts ;
    4357       int numberAfter =
    4358             numberRowCutsAfter+numberColumnCutsAfter+lastNumberCuts ;
    4359       // possibly extend whichGenerator
    4360       resizeWhichGenerator(numberBefore, numberAfter);
    4361       int j ;
    4362       if (fullScan) {
    4363         // counts
    4364         countColumnCuts[i] += numberColumnCutsAfter-numberColumnCutsBefore ;
    4365       }
    4366       countRowCuts[i] += numberRowCutsAfter-numberRowCutsBefore ;
    4367      
    4368       for (j = numberRowCutsBefore;j<numberRowCutsAfter;j++) {
    4369         whichGenerator_[numberBefore++] = i ;
    4370         const OsiRowCut * thisCut = theseCuts.rowCutPtr(j) ;
    4371         if (thisCut->lb()>thisCut->ub())
    4372           violated=-2; // sub-problem is infeasible
    4373         if (thisCut->globallyValid()) {
    4374           // add to global list
    4375           OsiRowCut newCut(*thisCut);
    4376           newCut.setGloballyValid(2);
    4377           newCut.mutableRow().setTestForDuplicateIndex(false);
    4378           globalCuts_.insert(newCut) ;
    4379         }
    4380       }
    4381       for (j = numberColumnCutsBefore;j<numberColumnCutsAfter;j++) {
    4382         whichGenerator_[numberBefore++] = i ;
    4383         const OsiColCut * thisCut = theseCuts.colCutPtr(j) ;
    4384         if (thisCut->globallyValid()) {
    4385           // add to global list
    4386           OsiColCut newCut(*thisCut);
    4387           newCut.setGloballyValid(2);
    4388           globalCuts_.insert(newCut) ;
    4389         }
    4390       }
    4391     }
    4392     // If at root node and first pass do heuristics without cuts
    4393     if (!numberNodes_&&currentPassNumber_==1) {
    4394       // Save number solutions
    4395       int saveNumberSolutions = numberSolutions_;
    4396       int saveNumberHeuristicSolutions = numberHeuristicSolutions_;
    4397       // make sure bounds tight
    4398       {
    4399         for (int i = 0;i < numberObjects_;i++)
    4400           object_[i]->resetBounds(solver_) ;
    4401       }
    4402       for (int i = 0;i<numberHeuristics_;i++) {
    4403         // see if heuristic will do anything
    4404         double saveValue = heuristicValue ;
    4405         int ifSol = heuristic_[i]->solution(heuristicValue,
    4406                                             newSolution);
    4407         if (ifSol>0) {
    4408           // better solution found
    4409           found = i ;
    4410           incrementUsed(newSolution);
    4411           // increment number of solutions so other heuristics can test
    4412           numberSolutions_++;
    4413           numberHeuristicSolutions_++;
    4414         } else {
    4415           heuristicValue = saveValue ;
    4416         }
    4417       }
    4418       // Restore number solutions
    4419       numberSolutions_ = saveNumberSolutions;
    4420       numberHeuristicSolutions_ = saveNumberHeuristicSolutions;
    4421     }
    4422     // Add in any violated saved cuts
    4423     if (!theseCuts.sizeRowCuts()&&!theseCuts.sizeColCuts()) {
    4424       int numberOld = theseCuts.sizeRowCuts();
    4425       int numberCuts = slackCuts.sizeRowCuts() ;
    4426       int i;
    4427       // possibly extend whichGenerator
    4428       resizeWhichGenerator(numberOld, numberOld+numberCuts);
    4429       for ( i = 0;i<numberCuts;i++) {
    4430         const OsiRowCut * thisCut = slackCuts.rowCutPtr(i) ;
    4431         if (thisCut->violated(cbcColSolution_)>100.0*primalTolerance) {
    4432           if (messageHandler()->logLevel()>2)
    4433             printf("Old cut added - violation %g\n",
    4434                    thisCut->violated(cbcColSolution_)) ;
    4435           whichGenerator_[numberOld++]=-1;
    4436           theseCuts.insert(*thisCut) ;
    4437         }
    4438       }
    4439     }
    4440 /*
    4441   End of the loop to exercise each generator/heuristic.
    4442 
     4978/*
    44434979  Did any of the heuristics turn up a new solution? Record it before we free
    44444980  the vector.
    44454981*/
    4446     if (found >= 0) {
    4447       phase_=4;
    4448       incrementUsed(newSolution);
    4449       setBestSolution(CBC_ROUNDING,heuristicValue,newSolution) ;
    4450       lastHeuristic_ = heuristic_[found];
    4451       CbcTreeLocal * tree
     4982      if (found >= 0) {
     4983        phase_=4;
     4984        incrementUsed(newSolution);
     4985        lastHeuristic_ = heuristic_[found];
     4986        setBestSolution(CBC_ROUNDING,heuristicValue,newSolution) ;
     4987        CbcTreeLocal * tree
    44524988          = dynamic_cast<CbcTreeLocal *> (tree_);
    4453       if (tree)
    4454         tree->passInSolution(bestSolution_,heuristicValue);
    4455     }
    4456     delete [] newSolution ;
     4989        if (tree)
     4990          tree->passInSolution(bestSolution_,heuristicValue);
     4991      }
     4992      delete [] newSolution ;
     4993    }
    44574994
    44584995#if 0
     
    46895226    if (!feasible)
    46905227    { int i ;
    4691       for (i = 0;i<currentNumberCuts_;i++) {
    4692         // take off node
    4693         if (addedCuts_[i]) {
    4694           if (!addedCuts_[i]->decrement())
    4695             delete addedCuts_[i] ;
    4696           addedCuts_[i] = NULL ;
     5228      if (currentNumberCuts_) {
     5229        lockThread();
     5230        for (i = 0;i<currentNumberCuts_;i++) {
     5231          // take off node
     5232          if (addedCuts_[i]) {
     5233            if (!addedCuts_[i]->decrement())
     5234              delete addedCuts_[i] ;
     5235            addedCuts_[i] = NULL ;
     5236          }
    46975237        }
    46985238      }
     
    48305370      phase_=4;
    48315371      incrementUsed(newSolution);
     5372      lastHeuristic_ = heuristic_[found];
    48325373      setBestSolution(CBC_ROUNDING,heuristicValue,newSolution) ;
    4833       lastHeuristic_ = heuristic_[found];
    48345374    }
    48355375    delete [] newSolution ;
     
    51655705    clpSolver->setSpecialOptions(saveClpOptions);
    51665706# endif
     5707#ifdef CBC_THREAD
     5708  if (threadModel) {
     5709    // stop threads
     5710    int i;
     5711    for (i=0;i<numberThreads_;i++) {
     5712      pthread_cond_signal(threadInfo[i].condition2); // unlock
     5713      while (threadInfo[i].returnCode==0) {
     5714        struct timespec moreTime;
     5715        moreTime.tv_nsec = 10000;
     5716        moreTime.tv_sec = 0;
     5717        nanosleep(&moreTime,NULL);
     5718      }
     5719      threadModel[i]->numberThreads_=0; // say exit
     5720      threadInfo[i].returnCode=0;
     5721      pthread_cond_signal(threadInfo[i].condition2); // unlock
     5722      pthread_join(threadId[i],NULL);
     5723      pthread_mutex_destroy (threadInfo[i].mutex2);
     5724      pthread_cond_destroy (threadInfo[i].condition2);
     5725      threadModel[i]->generator_[0]=NULL;
     5726      delete [] threadModel[i]->generator_;
     5727      threadModel[i]->generator_=NULL;
     5728      threadModel[i]->object_=NULL;
     5729    }
     5730    pthread_cond_destroy (&condition_main);
     5731    pthread_mutex_destroy (&condition_mutex);
     5732    // delete models and solvers
     5733    for (i=0;i<numberThreads_;i++) {
     5734      delete threadModel[i];
     5735    }
     5736    delete [] mutex2;
     5737    delete [] condition2;
     5738    delete [] threadId;
     5739    delete [] threadInfo;
     5740    delete [] threadModel;
     5741    mutex_ = saveMutex;
     5742  }
     5743#endif
    51675744
    51685745  return feasible ; }
     
    52425819*/
    52435820    int oldCutIndex = 0 ;
    5244     for (i = 0 ; i < numberOldActiveCuts_ ; i++)
    5245     { status = ws->getArtifStatus(i+firstOldCut) ;
    5246       while (!addedCuts_[oldCutIndex]) oldCutIndex++ ;
    5247       assert(oldCutIndex < currentNumberCuts_) ;
    5248       // always leave if from nextRowCut_
    5249       if (status == CoinWarmStartBasis::basic&&
    5250           addedCuts_[oldCutIndex]->effectiveness()!=COIN_DBL_MAX)
    5251       { solverCutIndices[numberOldToDelete++] = i+firstOldCut ;
    5252         if (saveCuts) {
    5253           // send to cut pool
    5254           OsiRowCut * slackCut = addedCuts_[oldCutIndex];
    5255           if (slackCut->effectiveness()!=-1.234) {
    5256             slackCut->setEffectiveness(-1.234);
    5257             saveCuts->insert(*slackCut);
    5258           }
    5259         }
    5260         if (addedCuts_[oldCutIndex]->decrement() == 0)
    5261           delete addedCuts_[oldCutIndex] ;
    5262         addedCuts_[oldCutIndex] = NULL ;
    5263         oldCutIndex++ ; }
    5264       else
    5265       { oldCutIndex++ ; } }
     5821    if (numberOldActiveCuts_) {
     5822      lockThread();
     5823      for (i = 0 ; i < numberOldActiveCuts_ ; i++)
     5824        { status = ws->getArtifStatus(i+firstOldCut) ;
     5825        while (!addedCuts_[oldCutIndex]) oldCutIndex++ ;
     5826        assert(oldCutIndex < currentNumberCuts_) ;
     5827        // always leave if from nextRowCut_
     5828        if (status == CoinWarmStartBasis::basic&&
     5829            addedCuts_[oldCutIndex]->effectiveness()!=COIN_DBL_MAX)
     5830          { solverCutIndices[numberOldToDelete++] = i+firstOldCut ;
     5831          if (saveCuts) {
     5832            // send to cut pool
     5833            OsiRowCut * slackCut = addedCuts_[oldCutIndex];
     5834            if (slackCut->effectiveness()!=-1.234) {
     5835              slackCut->setEffectiveness(-1.234);
     5836              saveCuts->insert(*slackCut);
     5837            }
     5838          }
     5839          if (addedCuts_[oldCutIndex]->decrement() == 0)
     5840            delete addedCuts_[oldCutIndex] ;
     5841          addedCuts_[oldCutIndex] = NULL ;
     5842          oldCutIndex++ ; }
     5843        else
     5844          { oldCutIndex++ ; } }
     5845      unlockThread();
     5846    }
    52665847/*
    52675848  Scan the basis entries of the new cuts generated with this round of cut
     
    66337214            if (generator_[i]->atSolution())
    66347215              {
    6635                 generator_[i]->generateCuts(theseCuts,true,NULL);
     7216                generator_[i]->generateCuts(theseCuts,true,solver_,NULL);
    66367217                int numberCuts = theseCuts.sizeRowCuts();
    66377218                for (int j=lastNumberCuts;j<numberCuts;j++)
     
    67597340      cutoff = bestObjective_-dblParam_[CbcCutoffIncrement];
    67607341      // But allow for rounding errors
    6761       if (dblParam_[CbcCutoffIncrement] == 1e-5)
     7342      if (dblParam_[CbcCutoffIncrement] == 1e-5) {
     7343#ifdef COIN_DEVELOP
     7344        if (saveObjectiveValue+1.0e-7<bestObjective_)
     7345          printf("First try at solution had objective %.16g, rechecked as %.16g\n",
     7346                 saveObjectiveValue,bestObjective_);
     7347#endif
     7348        saveObjectiveValue = CoinMax(saveObjectiveValue,bestObjective_-0.0000001*fabs(bestObjective_));
    67627349        cutoff = CoinMin(bestObjective_,saveObjectiveValue)-1.0e-5;
     7350      }
    67637351      // This is not correct - that way cutoff can go up if maximization
    67647352      //double direction = solver_->getObjSense();
     
    67737361      else
    67747362        stateOfSearch_ = 2;
    6775      
    6776       handler_->message(how,messages_)
    6777         <<bestObjective_<<numberIterations_
    6778         <<numberNodes_<<getCurrentSeconds()
    6779         <<CoinMessageEol;
     7363
     7364      if (how!=CBC_ROUNDING) {
     7365        handler_->message(how,messages_)
     7366          <<bestObjective_<<numberIterations_
     7367          <<numberNodes_<<getCurrentSeconds()
     7368          <<CoinMessageEol;
     7369      } else {
     7370        assert (lastHeuristic_);
     7371        const char * name = lastHeuristic_->heuristicName();
     7372        handler_->message(CBC_ROUNDING,messages_)
     7373          <<bestObjective_
     7374          <<name
     7375          <<numberIterations_
     7376          <<numberNodes_<<getCurrentSeconds()
     7377          <<CoinMessageEol;
     7378      }
    67807379      /*
    67817380        Now step through the cut generators and see if any of them are flagged to
     
    67967395          generate=false;
    67977396        if (generate) {
    6798           generator_[i]->generateCuts(theseCuts,true,NULL);
     7397          generator_[i]->generateCuts(theseCuts,true,solver_,NULL);
    67997398          int numberCuts = theseCuts.sizeRowCuts();
    68007399          for (int j=lastNumberCuts;j<numberCuts;j++) {
     
    76368235          testSolution_=currentSolution_;
    76378236          // better solution save
     8237          lastHeuristic_ = heuristic_[found];
    76388238          setBestSolution(CBC_ROUNDING,heuristicValue,
    76398239                          newSolution);
    7640           lastHeuristic_ = heuristic_[found];
    76418240          // update cutoff
    76428241          cutoff = getCutoff();
     
    86249223      resolve(solver_);
    86259224      double objval = solver_->getObjValue();
     9225      lastHeuristic_ = NULL;
    86269226      setBestSolution(CBC_SOLUTION, objval,
    86279227                      solver_->getColSolution()) ;
    8628       lastHeuristic_ = NULL;
    86299228      int easy=2;
    86309229      if (!solverCharacteristics_->mipFeasible())//did we prove that the node could be pruned?
     
    86559254    numberPassesLeft--;
    86569255    if (numberPassesLeft<=-1) {
    8657       if (!numberLongStrong_)
     9256      if (!numberLongStrong_&&!numberThreads_)
    86589257        messageHandler()->message(CBC_WARNING_STRONG,
    86599258                                  messages()) << CoinMessageEol ;
     
    87109309      maximumDepthActual_ = CoinMax(maximumDepthActual_,newNode->depth());
    87119310      newNode->initializeInfo() ;
    8712       newNode->nodeInfo()->addCuts(cuts,newNode->numberBranches(),
    8713                                    whichGenerator_) ;
     9311      if (cuts.sizeRowCuts()) {
     9312        lockThread();
     9313        newNode->nodeInfo()->addCuts(cuts,newNode->numberBranches(),
     9314                                     whichGenerator_) ;
     9315        unlockThread();
     9316      }
    87149317    }
    87159318  } else {
     
    89679570  delete solver_;
    89689571  solver_ = process->originalModel();
     9572}
     9573void
     9574CbcModel::setBestSolution(const double * solution,int numberColumns,double objectiveValue)
     9575{
     9576  bestObjective_ = objectiveValue;
     9577  int n = CoinMax(numberColumns,solver_->getNumCols());
     9578  delete [] bestSolution_;
     9579  bestSolution_ = new double [n];
     9580  memset(bestSolution_,0,n*sizeof(double));
     9581  memcpy(bestSolution_,solution,numberColumns*sizeof(double));
    89699582}
    89709583// Create C++ lines to get to current state
     
    91509763  cutModifier_ = modifier.clone();
    91519764}
     9765#ifdef CBC_THREAD
     9766/* Do one node - broken out for clarity?
     9767   also for parallel (when baseModel!=this)
     9768   Returns 1 if solution found
     9769   node NULL on return if no branches left
     9770   newNode NULL if no new node created
     9771*/
     9772int
     9773CbcModel::doOneNode(CbcModel * baseModel, CbcNode * & node, CbcNode * & newNode)
     9774{
     9775  int foundSolution=0;
     9776  int currentNumberCuts = 0 ;
     9777  currentNode_=node; // so can be accessed elsewhere
     9778  double bestObjective = bestObjective_;
     9779#ifdef CBC_DEBUG
     9780  printf("%d unsat, way %d, obj %g est %g\n",
     9781         node->numberUnsatisfied(),node->way(),node->objectiveValue(),
     9782         node->guessedObjectiveValue());
     9783#endif
     9784#if 0
     9785  if (node->objectiveValue()>getCutoff()) {
     9786    printf("cutoff\n");
     9787    assert (node->nodeInfo());
     9788    node->nodeInfo()->decrement(node->nodeInfo()->numberBranchesLeft()) ;
     9789    delete node;
     9790    node=NULL;
     9791    newNode=NULL;
     9792    return 0;
     9793  }
     9794#endif
     9795  // Save clone in branching decision
     9796  if(branchingMethod_)
     9797    branchingMethod_->saveBranchingObject(node->modifiableBranchingObject());
     9798  // Say not on optimal path
     9799  bool onOptimalPath=false;
     9800#   ifdef CHECK_NODE
     9801  printf("Node %x popped from tree - %d left, %d count\n",node,
     9802         node->nodeInfo()->numberBranchesLeft(),
     9803         node->nodeInfo()->numberPointingToThis()) ;
     9804  printf("\tdepth = %d, z =  %g, unsat = %d, var = %d.\n",
     9805         node->depth(),node->objectiveValue(),
     9806         node->numberUnsatisfied(),
     9807         node->columnNumber()) ;
     9808#   endif
     9809 
     9810  /*
     9811    Rebuild the subproblem for this node:        Call addCuts() to adjust the model
     9812    to recreate the subproblem for this node (set proper variable bounds, add
     9813    cuts, create a basis).  This may result in the problem being fathomed by
     9814    bound or infeasibility. Returns 1 if node is fathomed.
     9815    Execute the current arm of the branch: If the problem survives, save the
     9816    resulting variable bounds and call branch() to modify variable bounds
     9817    according to the current arm of the branching object. If we're processing
     9818    the final arm of the branching object, flag the node for removal from the
     9819    live set.
     9820  */
     9821  /*
     9822    Used to generate bound edits for CbcPartialNodeInfo.
     9823  */
     9824  int numberColumns = getNumCols() ;
     9825  double * lowerBefore = new double [numberColumns] ;
     9826  double * upperBefore = new double [numberColumns] ;
     9827  newNode = NULL ;
     9828  bool feasible=true;
     9829  CoinWarmStartBasis *lastws = new CoinWarmStartBasis();
     9830  lockThread();
     9831  // point to genuine ones
     9832  //int save1 = maximumNumberCuts_;
     9833  int save2 = maximumDepth_;
     9834  //maximumNumberCuts_ = baseModel->maximumNumberCuts_;
     9835  //addedCuts_ = baseModel->addedCuts_;
     9836  maximumDepth_ = baseModel->maximumDepth_;
     9837  walkback_ = baseModel->walkback_;
     9838  int retCode =addCuts(node,lastws,numberFixedNow_>numberFixedAtRoot_);
     9839  //if (save1<maximumNumberCuts_) {
     9840    // increased
     9841    //baseModel->maximumNumberCuts_ = maximumNumberCuts_;
     9842    //baseModel->addedCuts_ = addedCuts_;
     9843  //}
     9844  if (save2<maximumDepth_) {
     9845    // increased
     9846    baseModel->maximumDepth_ = maximumDepth_;
     9847    baseModel->walkback_ = walkback_;
     9848  }
     9849  unlockThread();
     9850  int branchesLeft=0;
     9851  if (!retCode) {
     9852    int i ;
     9853    const double * lower = getColLower() ;
     9854    const double * upper = getColUpper() ;
     9855    for (i = 0 ; i < numberColumns ; i++) {
     9856      lowerBefore[i]= lower[i] ;
     9857      upperBefore[i]= upper[i] ;
     9858    }
     9859    if ((solverCharacteristics_->extraCharacteristics()&2)!=0) {
     9860      solverCharacteristics_->setBeforeLower(lowerBefore);
     9861      solverCharacteristics_->setBeforeUpper(upperBefore);
     9862    }
     9863    lockThread();
     9864    if (messageHandler()->logLevel()>2)
     9865      node->modifiableBranchingObject()->print();
     9866    if (branchingMethod_&&branchingMethod_->chooseMethod()) {
     9867      branchesLeft = node->branch(solver_); // new way
     9868    } else {
     9869      // old way so need to cheat
     9870      OsiBranchingObject * branch2 = node->modifiableBranchingObject();
     9871      CbcBranchingObject * branch = dynamic_cast <CbcBranchingObject *>(branch2) ;
     9872      assert (branch);
     9873      branch->setModel(this);
     9874      branchesLeft = node->branch(NULL); // old way
     9875      branch->setModel(baseModel);
     9876    }
     9877    if (mutex_) {
     9878      assert (node->nodeInfo());
     9879      node->nodeInfo()->increment() ;
     9880    }
     9881    unlockThread();
     9882    if ((specialOptions_&1)!=0) {
     9883      /*
     9884        This doesn't work as intended --- getRowCutDebugger will return null
     9885        unless the current feasible solution region includes the optimal solution
     9886        that RowCutDebugger knows. There's no way to tell inactive from off the
     9887        optimal path.
     9888      */
     9889      const OsiRowCutDebugger *debugger = solver_->getRowCutDebugger() ;
     9890      if (debugger) {
     9891        onOptimalPath=true;
     9892        printf("On optimal path\n") ;
     9893      }
     9894    }
     9895     
     9896    /*
     9897      Reoptimize, possibly generating cuts and/or using heuristics to find
     9898      solutions.  Cut reference counts are unaffected unless we lose feasibility,
     9899      in which case solveWithCuts() will make the adjustment.
     9900    */
     9901    phase_=2;
     9902    OsiCuts cuts ;
     9903    currentNumberCuts = solver_->getNumRows()-numberRowsAtContinuous_ ;
     9904    int saveNumber = numberIterations_;
     9905    if(solverCharacteristics_->solutionAddsCuts()) {
     9906      int returnCode=resolve(node ? node->nodeInfo() : NULL,1);
     9907      feasible = returnCode != 0;
     9908      if (feasible) {
     9909        int iObject ;
     9910        int preferredWay ;
     9911        int numberUnsatisfied = 0 ;
     9912        memcpy(currentSolution_,solver_->getColSolution(),
     9913               numberColumns*sizeof(double)) ;
     9914        // point to useful information
     9915        OsiBranchingInformation usefulInfo=usefulInformation();
     9916       
     9917        for (iObject = 0 ; iObject < numberObjects_ ; iObject++) {
     9918          double infeasibility =
     9919            object_[iObject]->infeasibility(&usefulInfo,preferredWay) ;
     9920          if (infeasibility ) numberUnsatisfied++ ;
     9921        }
     9922        if (returnCode>0) {
     9923          if (numberUnsatisfied)   {
     9924            feasible = solveWithCuts(cuts,maximumCutPasses_,node);
     9925          } else {
     9926            // may generate cuts and turn the solution
     9927            //to an infeasible one
     9928            feasible = solveWithCuts(cuts, 1,
     9929                                     node);
     9930          }
     9931        }
     9932        // check extra info on feasibility
     9933        if (!solverCharacteristics_->mipFeasible()) {
     9934          feasible = false;
     9935          solverCharacteristics_->setMipBound(-COIN_DBL_MAX);
     9936        }
     9937      }
     9938    } else {
     9939      // normal
     9940      feasible = solveWithCuts(cuts,maximumCutPasses_,node);
     9941    }
     9942    if ((specialOptions_&1)!=0&&onOptimalPath) {
     9943      if (!solver_->getRowCutDebugger()) {
     9944        // dj fix did something???
     9945        solver_->writeMps("infeas2");
     9946        assert (solver_->getRowCutDebugger()) ;
     9947      }
     9948    }
     9949    if (statistics_) {
     9950      assert (numberNodes2_);
     9951      assert (statistics_[numberNodes2_-1]);
     9952      assert (statistics_[numberNodes2_-1]->node()==numberNodes2_-1);
     9953      statistics_[numberNodes2_-1]->endOfBranch(numberIterations_-saveNumber,
     9954                                                feasible ? solver_->getObjValue()
     9955                                                : COIN_DBL_MAX);
     9956    }
     9957    /*
     9958      Are we still feasible? If so, create a node and do the work to attach a
     9959      branching object, reoptimising as needed if chooseBranch() identifies
     9960      monotone objects.
     9961     
     9962      Finally, attach a partial nodeInfo object and store away any cuts that we
     9963      created back in solveWithCuts. addCuts() will initialise the reference
     9964      counts for these new cuts.
     9965     
     9966      This next test can be problematic if we've discovered an
     9967      alternate equivalent answer and subsequently fathom the solution
     9968      known to the row cut debugger due to bounds.
     9969    */
     9970    if (onOptimalPath) {
     9971      bool objLim = solver_->isDualObjectiveLimitReached() ;
     9972      if (!feasible && !objLim) {
     9973        printf("infeas2\n");
     9974        solver_->writeMps("infeas");
     9975        CoinWarmStartBasis *slack =
     9976          dynamic_cast<CoinWarmStartBasis *>(solver_->getEmptyWarmStart()) ;
     9977        solver_->setWarmStart(slack);
     9978        delete slack ;
     9979        solver_->setHintParam(OsiDoReducePrint,false,OsiHintDo,0) ;
     9980        solver_->initialSolve();
     9981        assert (!solver_->isProvenOptimal());
     9982      }
     9983      assert (feasible || objLim);
     9984    }
     9985    bool checkingNode=false;
     9986    if (feasible) {
     9987      newNode = new CbcNode ;
     9988      // Set objective value (not so obvious if NLP etc)
     9989      setObjectiveValue(newNode,node);
     9990      int anyAction =-1 ;
     9991      bool resolved = false ;
     9992      if (newNode->objectiveValue() >= getCutoff())
     9993        anyAction=-2;
     9994      // only allow at most a few passes
     9995      int numberPassesLeft=5;
     9996      checkingNode=true;
     9997      OsiSolverBranch * branches=NULL;
     9998      // point to useful information
     9999      anyAction = chooseBranch(newNode, numberPassesLeft,node, cuts,resolved,
     10000                               lastws, lowerBefore, upperBefore, branches);
     10001      /*
     10002        If we end up infeasible, we can delete the new node immediately. Since this
     10003        node won't be needing the cuts we collected, decrement the reference counts.
     10004        If we are feasible, then we'll be placing this node into the live set, so
     10005        increment the reference count in the current (parent) nodeInfo.
     10006      */
     10007      lockThread();
     10008      if (anyAction == -2) {
     10009        if (mutex_) {
     10010          assert (node->nodeInfo());
     10011          node->nodeInfo()->decrement() ;
     10012        }
     10013        delete newNode ;
     10014        if (mutex_) {
     10015          assert (node->nodeInfo());
     10016          node->nodeInfo()->increment() ;
     10017        }
     10018        newNode = NULL ;
     10019        // say strong doing well
     10020        if (checkingNode)
     10021          setSpecialOptions(specialOptions_|8);
     10022        for (i = 0 ; i < currentNumberCuts_ ; i++) {
     10023          if (addedCuts_[i]) {
     10024            if (!addedCuts_[i]->decrement(1)) {
     10025              delete addedCuts_[i] ;
     10026            }
     10027              addedCuts_[i]=NULL;
     10028              //}
     10029          }
     10030        }
     10031      } else {
     10032        assert (node->nodeInfo());
     10033        node->nodeInfo()->increment() ;
     10034        if ((numberNodes_%20)==0) {
     10035          // say strong not doing as well
     10036          setSpecialOptions(specialOptions_&~8);
     10037        }
     10038      }
     10039      unlockThread();
     10040    }
     10041    /*
     10042      At this point, there are three possibilities:
     10043      * newNode is live and will require further branching to resolve
     10044      (variable() >= 0). Increment the cut reference counts by
     10045      numberBranches() to allow for use by children of this node, and
     10046      decrement by 1 because we've executed one arm of the branch of our
     10047      parent (consuming one reference). Before we push newNode onto the
     10048      search tree, try for a heuristic solution.
     10049      * We have a solution, in which case newNode is non-null but we have no
     10050      branching variable. Decrement the cut counts and save the solution.
     10051      * The node was found to be infeasible, in which case it's already been
     10052      deleted, and newNode is null.
     10053    */
     10054    if (!getEventHandler()->event(CbcEventHandler::node)) {
     10055      eventHappened_=true; // exit
     10056    }
     10057    assert (!newNode || newNode->objectiveValue() <= getCutoff()) ;
     10058    if (statistics_) {
     10059      assert (numberNodes2_);
     10060      assert (statistics_[numberNodes2_-1]);
     10061      assert (statistics_[numberNodes2_-1]->node()==numberNodes2_-1);
     10062      if (newNode)
     10063        statistics_[numberNodes2_-1]->updateInfeasibility(newNode->numberUnsatisfied());
     10064      else
     10065        statistics_[numberNodes2_-1]->sayInfeasible();
     10066    }
     10067    lockThread();
     10068    if (newNode) {
     10069      if (newNode->branchingObject() == NULL&&solverCharacteristics_->solverType()==4) {
     10070        // need to check if any cuts would do anything
     10071        OsiCuts theseCuts;
     10072        // reset probing info
     10073        if (probingInfo_)
     10074          probingInfo_->initializeFixing();
     10075        for (int i = 0;i<numberCutGenerators_;i++) {
     10076          bool generate = generator_[i]->normal();
     10077          // skip if not optimal and should be (maybe a cut generator has fixed variables)
     10078          if (generator_[i]->needsOptimalBasis()&&!solver_->basisIsAvailable())
     10079            generate=false;
     10080          if (!generator_[i]->mustCallAgain())
     10081            generate=false; // only special cuts
     10082          if (generate) {
     10083            generator_[i]->generateCuts(theseCuts,true,solver_,NULL) ;
     10084            int numberRowCutsAfter = theseCuts.sizeRowCuts() ;
     10085            if (numberRowCutsAfter) {
     10086              // need dummy branch
     10087              newNode->setBranchingObject(new CbcDummyBranchingObject(this));
     10088              newNode->nodeInfo()->initializeInfo(1);
     10089              break;
     10090            }
     10091          }
     10092        }
     10093      }
     10094      if (newNode->branchingObject()) {
     10095        handler_->message(CBC_BRANCH,messages_)
     10096          << numberNodes_<< newNode->objectiveValue()
     10097          << newNode->numberUnsatisfied()<< newNode->depth()
     10098          << CoinMessageEol ;
     10099        // Increment cut counts (taking off current)
     10100        int numberLeft = newNode->numberBranches() ;
     10101        for (i = 0;i < currentNumberCuts_;i++) {
     10102          if (addedCuts_[i]) {
     10103#               ifdef CHECK_CUT_COUNTS
     10104            printf("Count on cut %x increased by %d\n",addedCuts_[i],
     10105                   numberLeft-1) ;
     10106#               endif
     10107            addedCuts_[i]->increment(numberLeft-1) ;
     10108          }
     10109        }
     10110        unlockThread();
     10111
     10112        double estValue = newNode->guessedObjectiveValue() ;
     10113        int found = -1 ;
     10114        double * newSolution = new double [numberColumns] ;
     10115        double heurValue = getCutoff() ;
     10116        int iHeur ;
     10117        for (iHeur = 0 ; iHeur < numberHeuristics_ ; iHeur++) {
     10118          double saveValue = heurValue ;
     10119          int ifSol = heuristic_[iHeur]->solution(heurValue,newSolution) ;
     10120          if (ifSol > 0) {
     10121            // new solution found
     10122            found = iHeur ;
     10123            lockThread();
     10124            baseModel->incrementUsed(newSolution);
     10125            unlockThread();
     10126          } else if (ifSol < 0) { // just returning an estimate
     10127            estValue = CoinMin(heurValue,estValue) ;
     10128            heurValue = saveValue ;
     10129          }
     10130        }
     10131        if (found >= 0) {
     10132          lastHeuristic_ = heuristic_[found];
     10133          setBestSolution(CBC_ROUNDING,heurValue,newSolution) ;
     10134          foundSolution=1;
     10135        }
     10136        delete [] newSolution ;
     10137        newNode->setGuessedObjectiveValue(estValue) ;
     10138        lockThread();
     10139#define PUSH_LATER
     10140#ifdef PUSH_LATER
     10141        if (!mutex_) // only if serial
     10142#endif
     10143        tree_->push(newNode) ;
     10144        if (statistics_) {
     10145          if (numberNodes2_==maximumStatistics_) {
     10146            maximumStatistics_ = 2*maximumStatistics_;
     10147            CbcStatistics ** temp = new CbcStatistics * [maximumStatistics_];
     10148            memset(temp,0,maximumStatistics_*sizeof(CbcStatistics *));
     10149            memcpy(temp,statistics_,numberNodes2_*sizeof(CbcStatistics *));
     10150            delete [] statistics_;
     10151            statistics_=temp;
     10152          }
     10153          assert (!statistics_[numberNodes2_]);
     10154          statistics_[numberNodes2_]=new CbcStatistics(newNode);
     10155        }
     10156        numberNodes2_++;
     10157#           ifdef CHECK_NODE
     10158        printf("Node %x pushed on tree c\n",newNode) ;
     10159#           endif
     10160      } else {
     10161        if(solverCharacteristics_ && //we may be in a non standard bab
     10162           solverCharacteristics_->solutionAddsCuts()// we are in some kind of OA based bab.
     10163           ) {
     10164         
     10165          std::cerr<<"You should never get here"<<std::endl;
     10166          throw CoinError("Nodes should not be fathomed on integer infeasibility in this setting",
     10167                          "branchAndBound","CbcModel") ;
     10168        }
     10169        for (i = 0 ; i < currentNumberCuts_ ; i++) {
     10170          if (addedCuts_[i]) {
     10171            if (!addedCuts_[i]->decrement(1)) {
     10172              delete addedCuts_[i] ;
     10173              addedCuts_[i]=NULL;
     10174            }
     10175          }
     10176        }
     10177        double objectiveValue = newNode->objectiveValue();
     10178        lastHeuristic_ = NULL;
     10179        // Just possible solver did not know about a solution from another thread!
     10180        if (objectiveValue<getCutoff()) {
     10181          incrementUsed(solver_->getColSolution());
     10182          setBestSolution(CBC_SOLUTION,objectiveValue,
     10183                          solver_->getColSolution()) ;
     10184          foundSolution=1;
     10185        }
     10186        //assert(nodeInfo->numberPointingToThis() <= 2) ;
     10187        // avoid accidental pruning, if newNode was final branch arm
     10188        node->nodeInfo()->increment();
     10189        delete newNode ;
     10190        newNode=NULL;
     10191        node->nodeInfo()->decrement() ;
     10192      }
     10193    }
     10194    if (branchesLeft) {
     10195      // set nodenumber correctly
     10196      if (node->nodeInfo())
     10197        node->nodeInfo()->setNodeNumber(numberNodes2_);
     10198#ifdef PUSH_LATER
     10199        if (!mutex_) // only if serial
     10200#endif
     10201      tree_->push(node) ;
     10202      if (statistics_) {
     10203        if (numberNodes2_==maximumStatistics_) {
     10204          maximumStatistics_ = 2*maximumStatistics_;
     10205          CbcStatistics ** temp = new CbcStatistics * [maximumStatistics_];
     10206          memset(temp,0,maximumStatistics_*sizeof(CbcStatistics *));
     10207          memcpy(temp,statistics_,numberNodes2_*sizeof(CbcStatistics *));
     10208          delete [] statistics_;
     10209          statistics_=temp;
     10210        }
     10211        assert (!statistics_[numberNodes2_]);
     10212        statistics_[numberNodes2_]=new CbcStatistics(node);
     10213      }
     10214      numberNodes2_++;
     10215      //nodeOnTree=true; // back on tree
     10216      //deleteNode = false ;
     10217#       ifdef CHECK_NODE
     10218      printf("Node %x pushed back on tree - %d left, %d count\n",node,
     10219             node->nodeInfo()->numberBranchesLeft(),
     10220             node->nodeInfo()->numberPointingToThis()) ;
     10221#       endif
     10222      if (mutex_) {
     10223        assert (node->nodeInfo());
     10224        node->nodeInfo()->decrement() ;
     10225      }
     10226    } else {
     10227    /*
     10228      This node has been completely expanded and can be removed from the live
     10229      set.
     10230    */
     10231      if (mutex_) {
     10232        assert (node->nodeInfo());
     10233        node->nodeInfo()->decrement() ;
     10234      }
     10235      assert (node->nodeInfo());
     10236      if (!node->nodeInfo()->numberBranchesLeft())
     10237        node->nodeInfo()->allBranchesGone(); // can clean up
     10238      delete node ;
     10239      node=NULL;
     10240    }
     10241    unlockThread();
     10242  } else {
     10243    // add cuts found to be infeasible (on bound)!
     10244    printf("found to be infeas! - branches left %d\n",node->nodeInfo()->numberBranchesLeft());
     10245    //abort();
     10246    assert (node->nodeInfo());
     10247    if (!node->nodeInfo()->numberBranchesLeft())
     10248      node->nodeInfo()->allBranchesGone(); // can clean up
     10249    delete node;
     10250    node=NULL;
     10251  }
     10252  /*
     10253    Delete cuts to get back to the original system.
     10254   
     10255    I'm thinking this is redundant --- the call to addCuts that conditions entry
     10256    to this code block also performs this action.
     10257  */
     10258  int numberToDelete = getNumRows()-numberRowsAtContinuous_ ;
     10259  if (numberToDelete) {
     10260    int * delRows = new int[numberToDelete] ;
     10261    int i ;
     10262    for (i = 0 ; i < numberToDelete ; i++)
     10263      delRows[i] = i+numberRowsAtContinuous_ ;
     10264    solver_->deleteRows(numberToDelete,delRows) ;
     10265    delete [] delRows ;
     10266  }
     10267  delete lastws ;
     10268  delete [] lowerBefore ;
     10269  delete [] upperBefore ;
     10270  if (bestObjective > bestObjective_)
     10271    foundSolution=2;
     10272  if (foundSolution) {
     10273    lockThread();
     10274    // might as well mark all including continuous
     10275    int numberColumns = solver_->getNumCols();
     10276    for (int i=0;i<numberColumns;i++) {
     10277      baseModel->usedInSolution_[i] += usedInSolution_[i];
     10278      usedInSolution_[i]=0;
     10279    }
     10280    baseModel->numberSolutions_ = numberSolutions_;
     10281    if (bestObjective_ < baseModel->bestObjective_&&bestObjective_<baseModel->getCutoff()) {
     10282      baseModel->bestObjective_ = bestObjective_ ;
     10283      int numberColumns = solver_->getNumCols();
     10284      if (!baseModel->bestSolution_)
     10285        baseModel->bestSolution_ = new double[numberColumns];
     10286      CoinCopyN(bestSolution_,numberColumns,baseModel->bestSolution_);
     10287      baseModel->setCutoff(getCutoff());
     10288    }
     10289    unlockThread();
     10290  }
     10291  return foundSolution;
     10292}
     10293/* Move/copy information from one model to another
     10294   -1 - initial setup
     10295   0 - from base model
     10296   1 - to base model (and reset)
     10297   2 - add in final statistics etc (and reset so can do clean destruction)
     10298*/
     10299void
     10300CbcModel::moveToModel(CbcModel * baseModel,int mode)
     10301{
     10302  if (mode==0) {
     10303    setCutoff(baseModel->getCutoff());
     10304    bestObjective_ = baseModel->bestObjective_;
     10305    assert (!baseModel->globalCuts_.sizeRowCuts());
     10306    numberSolutions_ = baseModel->numberSolutions_;
     10307    stateOfSearch_ = baseModel->stateOfSearch_;
     10308    numberNodes_ = baseModel->numberNodes_;
     10309    numberIterations_ = baseModel->numberIterations_;
     10310    numberFixedAtRoot_ = numberIterations_; // for statistics
     10311    phase_ = baseModel->phase_;
     10312    assert (!nextRowCut_);
     10313    nodeCompare_ = baseModel->nodeCompare_;
     10314    tree_ = baseModel->tree_;
     10315    assert (!subTreeModel_);
     10316    //branchingMethod_ = NULL; // need something but what
     10317    numberOldActiveCuts_ = baseModel->numberOldActiveCuts_;
     10318    cutModifier_ = NULL;
     10319    assert (!analyzeResults_);
     10320    threadStruct * stuff = (threadStruct *) mutex_;
     10321    assert (stuff);
     10322    //if (stuff)
     10323    stuff->createdNode=NULL;
     10324    // ?? searchStrategy_;
     10325    searchStrategy_=baseModel->searchStrategy_;
     10326    stuff->saveStuff[0]=searchStrategy_;
     10327    stateOfSearch_=baseModel->stateOfSearch_;
     10328    stuff->saveStuff[1]=stateOfSearch_;
     10329 } else if (mode==1) {
     10330    lockThread();
     10331    threadStruct * stuff = (threadStruct *) mutex_;
     10332    assert (stuff);
     10333    //stateOfSearch_
     10334#if 1
     10335    if(stuff->saveStuff[0]!=searchStrategy_) {
     10336      printf("changing searchStrategy from %d to %d\n",
     10337             baseModel->searchStrategy_,searchStrategy_);
     10338      baseModel->searchStrategy_=searchStrategy_;
     10339    }
     10340    if(stuff->saveStuff[1]!=stateOfSearch_) {
     10341      printf("changing stateOfSearch from %d to %d\n",
     10342             baseModel->stateOfSearch_,stateOfSearch_);
     10343      baseModel->stateOfSearch_=stateOfSearch_;
     10344    }
     10345#endif
     10346    if (eventHappened_)
     10347      baseModel->eventHappened_=true;
     10348    baseModel->numberNodes_++;
     10349    baseModel->numberIterations_ +=
     10350      numberIterations_ - numberFixedAtRoot_;
     10351#ifdef PUSH_LATER
     10352    if (stuff->node)
     10353      baseModel->tree_->push(stuff->node);
     10354    if (stuff->createdNode)
     10355      baseModel->tree_->push(stuff->createdNode);
     10356#endif
     10357    unlockThread();
     10358  } else if (mode==2) {
     10359    baseModel->sumChangeObjective1_ += sumChangeObjective1_;
     10360    baseModel->sumChangeObjective2_ += sumChangeObjective2_;
     10361    //baseModel->numberIterations_ += numberIterations_;
     10362    for (int iGenerator=0;iGenerator<numberCutGenerators_;iGenerator++) {
     10363      CbcCutGenerator * generator = baseModel->generator_[iGenerator];
     10364      CbcCutGenerator * generator2 = generator_[iGenerator];
     10365      generator->incrementNumberTimesEntered(generator2->numberTimesEntered());
     10366      generator->incrementNumberCutsInTotal(generator2->numberCutsInTotal());
     10367      generator->incrementNumberCutsActive(generator2->numberCutsActive());
     10368      generator->incrementTimeInCutGenerator(generator2->timeInCutGenerator());
     10369    }
     10370    nodeCompare_ = NULL;
     10371    baseModel->maximumDepthActual_ = CoinMax(baseModel->maximumDepthActual_,maximumDepthActual_);
     10372    baseModel->numberDJFixed_ += numberDJFixed_;
     10373    baseModel->numberStrongIterations_ += numberStrongIterations_;
     10374    int i;
     10375    for (i=0;i<3;i++)
     10376      baseModel->strongInfo_[i] += strongInfo_[i];
     10377    walkback_ = NULL;
     10378    //addedCuts_ = NULL;
     10379    tree_ = NULL;
     10380    eventHandler_=NULL;
     10381    delete solverCharacteristics_;
     10382    solverCharacteristics_ = NULL;
     10383    if (baseModel->branchingMethod_&&baseModel->branchingMethod_->chooseMethod()) {
     10384      // new method - we were using base models
     10385      numberObjects_=0;
     10386      object_=NULL;
     10387    }
     10388  } else {
     10389    delete eventHandler_;
     10390    eventHandler_ = baseModel->eventHandler_;
     10391    assert (!statistics_);
     10392    delete [] walkback_;
     10393    //delete [] addedCuts_;
     10394    walkback_ = NULL;
     10395    //addedCuts_ = NULL;
     10396    assert(baseModel->solverCharacteristics_);
     10397    solverCharacteristics_ = new OsiBabSolver (*baseModel->solverCharacteristics_);
     10398    solverCharacteristics_->setSolver(solver_);
     10399    delete tree_;
     10400    tree_ = NULL;
     10401    delete nodeCompare_;
     10402    nodeCompare_ = NULL;
     10403    continuousSolver_ = baseModel->continuousSolver_->clone();
     10404    if (baseModel->branchingMethod_&&baseModel->branchingMethod_->chooseMethod()) {
     10405      // new method uses solver - but point to base model
     10406      numberObjects_=baseModel->numberObjects_;
     10407      object_=baseModel->object_;
     10408    }
     10409    mutex_ = baseModel->mutex_;
     10410    int i;
     10411    for (i=0;i<numberHeuristics_;i++) {
     10412      delete heuristic_[i];
     10413      heuristic_[i] = baseModel->heuristic_[i]->clone();
     10414      heuristic_[i]->setModelOnly(this);
     10415    }
     10416    for (i=0;i<numberCutGenerators_;i++) {
     10417      delete generator_[i];
     10418      generator_[i] = new CbcCutGenerator(*baseModel->generator_[i]);
     10419      // refreshModel was overkill as thought too many rows
     10420      generator_[i]->setModel(this);
     10421    }
     10422  }
     10423}
     10424#ifdef CBC_THREAD
     10425static void * doNodesThread(void * voidInfo)
     10426{
     10427  threadStruct * stuff = (threadStruct *) voidInfo;
     10428  pthread_mutex_t * mutex = stuff->mutex2;
     10429  pthread_cond_t * condition = stuff->condition2;
     10430  CbcModel * thisModel = stuff->thisModel;
     10431  CbcModel * baseModel = stuff->baseModel;
     10432  while (true) {
     10433    pthread_mutex_lock (mutex);
     10434    while (stuff->returnCode) {
     10435      struct timespec absTime2;
     10436      clock_gettime(CLOCK_REALTIME,&absTime2);
     10437      double time2 = absTime2.tv_sec+1.0e-9*absTime2.tv_nsec;
     10438      pthread_cond_wait(condition,mutex);
     10439      clock_gettime(CLOCK_REALTIME,&stuff->absTime);
     10440      double time = stuff->absTime.tv_sec+1.0e-9*stuff->absTime.tv_nsec;
     10441      stuff->timeWaitingToStart+=time-time2;;
     10442      stuff->numberTimesWaitingToStart++;
     10443    }
     10444    //printf("start node %x\n",stuff->node);
     10445    int mode = thisModel->getNumberThreads();
     10446    if (mode) {
     10447      // normal
     10448      double time2 = CoinCpuTime();
     10449      assert (stuff->returnCode==0);
     10450      assert (stuff->node->nodeInfo());
     10451      thisModel->doOneNode(baseModel,stuff->node,stuff->createdNode);
     10452      stuff->returnCode=1;
     10453      //printf("end node %x\n",stuff->node);
     10454#ifdef CONDITION_WAIT
     10455      threadStruct * stuffMain = (threadStruct *) baseModel->mutex();
     10456      //pthread_mutex_t * condition_mutex = stuffMain->mutex2;
     10457      pthread_cond_t * condition_main = stuffMain->condition2;
     10458      pthread_cond_signal(condition_main); // unlock
     10459#endif
     10460      pthread_mutex_unlock(mutex);
     10461      stuff->timeInThread += CoinCpuTime()-time2;
     10462    } else {
     10463      // exit
     10464      break;
     10465    }
     10466  }
     10467  pthread_mutex_unlock(mutex);
     10468  pthread_exit(NULL);
     10469}
     10470static void * doCutsThread(void * voidInfo)
     10471{
     10472  threadStruct * stuff = (threadStruct *) voidInfo;
     10473  pthread_mutex_t * mutex = stuff->mutex2;
     10474  pthread_cond_t * condition = stuff->condition2;
     10475  CbcModel * thisModel =  stuff->thisModel;
     10476  CbcModel * baseModel = stuff->baseModel;
     10477  while (true) {
     10478    pthread_mutex_lock(mutex);
     10479    while (stuff->returnCode) {
     10480      pthread_cond_wait(condition,mutex);
     10481    }
     10482    //printf("start node %x\n",stuff->node);
     10483    int mode = thisModel->getNumberThreads();
     10484    if (mode) {
     10485      // normal
     10486      assert (stuff->returnCode==0);
     10487      bool fullScan = thisModel->getNodeCount()>0;
     10488      CbcCutGenerator * generator = thisModel->cutGenerator(0);
     10489      OsiCuts * cuts = (OsiCuts *) thisModel->objects();
     10490      OsiSolverInterface * thisSolver = thisModel->solver();
     10491      generator->generateCuts(*cuts,fullScan,thisSolver,NULL);
     10492      stuff->returnCode=1;
     10493      //printf("end node %x\n",stuff->node);
     10494#ifdef CONDITION_WAIT
     10495      threadStruct * stuffMain = (threadStruct *) baseModel->mutex();
     10496      //pthread_mutex_t * condition_mutex = stuffMain->mutex2;
     10497      pthread_cond_t * condition_main = stuffMain->condition2;
     10498      pthread_cond_signal(condition_main); // unlock
     10499#endif
     10500      pthread_mutex_unlock(mutex);
     10501    } else {
     10502      // exit
     10503      break;
     10504    }
     10505  }
     10506  pthread_mutex_unlock(mutex);
     10507  pthread_exit(NULL);
     10508}
     10509#endif
     10510#endif
     10511#if CBC_THREAD_DEBUG
     10512static int threadFlag=0;
     10513/*
     10514  -100 all quiet
     10515  k locked
     10516  k+n*100 locked for n'th time
     10517  -k unlocked when already unlocked
     10518*/
     10519static int lastAction=-100;
     10520#if CBC_THREAD_DEBUG>1
     10521#define MAX_DEBUG 10000000
     10522static int numberActions=0;
     10523static int action[MAX_DEBUG];
     10524#endif
     10525#endif
     10526#ifdef CBC_THREAD
     10527/*
     10528  Locks a thread if parallel so that stuff like cut pool
     10529  can be updated and/or used.y
     10530*/
     10531void
     10532CbcModel::lockThread()
     10533{
     10534  threadStruct * stuff = (threadStruct *) mutex_;
     10535  if (stuff) {
     10536    if(!stuff->locked) {
     10537      struct timespec absTime2;
     10538      clock_gettime(CLOCK_REALTIME,&absTime2);
     10539      double time2 = absTime2.tv_sec+1.0e-9*absTime2.tv_nsec;
     10540      pthread_mutex_lock (stuff->mutex);
     10541      stuff->locked=true;
     10542      clock_gettime(CLOCK_REALTIME,&stuff->absTime);
     10543      double time = stuff->absTime.tv_sec+1.0e-9*stuff->absTime.tv_nsec;
     10544      stuff->timeWaitingToLock+=time-time2;;
     10545      stuff->numberTimesLocked++;
     10546#if CBC_THREAD_DEBUG
     10547      if (lastAction==-100) {
     10548        lastAction = stuff->threadNumber;
     10549      } else if (lastAction<=0) {
     10550        printf ("thread %d was over unlocked - now locked by %d\n",
     10551                lastAction,stuff->threadNumber);
     10552        lastAction = stuff->threadNumber;
     10553      } else if ((lastAction%100)==stuff->threadNumber) {
     10554        printf ("thread %d was already locked at level %d\n",
     10555                stuff->threadNumber,lastAction);
     10556        lastAction += 100;
     10557      } else {
     10558        printf ("thread %d was locked - now lock wanted by %d\n",
     10559                lastAction,stuff->threadNumber);
     10560        abort();
     10561      }
     10562#if CBC_THREAD_DEBUG>1
     10563      assert (numberActions<MAX_DEBUG);
     10564      action[numberActions++] = lastAction;
     10565#endif
     10566      assert (threadFlag==0);
     10567      threadFlag=1;
     10568    } else {
     10569      if (lastAction>0&&(lastAction%100)==stuff->threadNumber) {
     10570        //printf ("OKish - thread %d was already locked at level %d\n",
     10571        //stuff->threadNumber,lastAction);
     10572        lastAction += 100;
     10573      } else {
     10574        printf ("lastAction %d - now second lock wanted by %d\n",
     10575                lastAction,stuff->threadNumber);
     10576        abort();
     10577      }
     10578#if CBC_THREAD_DEBUG>1
     10579      assert (numberActions<MAX_DEBUG);
     10580      action[numberActions++] = lastAction;
     10581#endif
     10582      assert (threadFlag==1);
     10583#endif
     10584    }
     10585  }
     10586}
     10587/*
     10588  Unlocks a thread if parallel
     10589*/
     10590void
     10591CbcModel::unlockThread()
     10592{
     10593  threadStruct * stuff = (threadStruct *) mutex_;
     10594  if (stuff) {
     10595    if(stuff->locked) {
     10596#if CBC_THREAD_DEBUG
     10597      if (lastAction>0&&(lastAction%100)==stuff->threadNumber) {
     10598        lastAction = -100;
     10599      } else {
     10600        printf ("lastAction %d - %d trying to unlock\n",
     10601                lastAction,stuff->threadNumber);
     10602        abort();
     10603      }
     10604#if CBC_THREAD_DEBUG>1
     10605      assert (numberActions<MAX_DEBUG);
     10606      action[numberActions++] = lastAction;
     10607#endif
     10608      assert (threadFlag==1);
     10609      threadFlag=0;
     10610#endif
     10611      stuff->locked=false;
     10612      pthread_mutex_unlock (stuff->mutex);
     10613      struct timespec absTime2;
     10614      clock_gettime(CLOCK_REALTIME,&absTime2);
     10615      double time2 = absTime2.tv_sec+1.0e-9*absTime2.tv_nsec;
     10616      double time = stuff->absTime.tv_sec+1.0e-9*stuff->absTime.tv_nsec;
     10617      stuff->timeLocked+=time2-time;
     10618      stuff->numberTimesUnlocked++;
     10619#if CBC_THREAD_DEBUG
     10620    } else {
     10621      printf ("lastAction %d - %d trying to unlock when flag says unlocked!\n",
     10622              lastAction,stuff->threadNumber);
     10623      lastAction = -100;
     10624#if CBC_THREAD_DEBUG>1
     10625      assert (numberActions<MAX_DEBUG);
     10626      action[numberActions++] = lastAction;
     10627#endif
     10628      assert (threadFlag==0);
     10629#endif
     10630    }
     10631  }
     10632}
     10633#endif
     10634// Returns true if locked
     10635bool
     10636CbcModel::isLocked() const
     10637{
     10638#ifdef CBC_THREAD
     10639  threadStruct * stuff = (threadStruct *) mutex_;
     10640  if (stuff) {
     10641    return (stuff->locked);
     10642  } else {
     10643    return true;
     10644  }
     10645#else
     10646  return true;
     10647#endif
     10648}
  • branches/devel/Cbc/src/CbcModel.hpp

    r607 r642  
    262262  /// Update size of whichGenerator
    263263  void resizeWhichGenerator(int numberNow, int numberAfter);
     264public:
     265  /** Do one node - broken out for clarity?
     266      also for parallel (when baseModel!=this)
     267      Returns 1 if solution found
     268      node NULL on return if no branches left
     269      newNode NULL if no new node created
     270  */
     271  int doOneNode(CbcModel * baseModel, CbcNode * & node, CbcNode * & newNode);
     272
     273  /// Returns true if locked
     274  bool isLocked() const;
     275#ifdef CBC_THREAD
     276  /**
     277     Locks a thread if parallel so that stuff like cut pool
     278     can be updated and/or used.
     279  */
     280  void lockThread();
     281  /**
     282     Unlocks a thread if parallel to say cut pool stuff not needed
     283  */
     284  void unlockThread();
     285#else
     286  inline void lockThread() {};
     287  inline void unlockThread() {};
     288#endif
     289private:
     290  /** Move/copy information from one model to another
     291      -1 - initialization
     292      0 - from base model
     293      1 - to base model (and reset)
     294      2 - add in final statistics etc (and reset so can do clean destruction)
     295  */
     296  void moveToModel(CbcModel * baseModel,int mode);
    264297public:
    265298    /** \brief Reoptimise an LP relaxation
     
    10401073  inline double * bestSolution() const
    10411074  { return bestSolution_;};
     1075  void setBestSolution(const double * solution,int numberColumns,double objectiveValue);
    10421076 
    10431077  /// Get number of solutions
     
    10931127  inline void setResolveAfterTakeOffCuts(bool yesNo)
    10941128  { resolveAfterTakeOffCuts_=yesNo;};
     1129  /// Get number of threads
     1130  inline int getNumberThreads() const
     1131  { return numberThreads_;};
     1132  /// Set number of threads
     1133  inline void setNumberThreads(int value)
     1134  { numberThreads_=value;};
     1135  /// Get thread mode
     1136  inline int getThreadMode() const
     1137  { return threadMode_;};
     1138  /** Set thread mode
     1139      always use numberThreads for branching
     1140      1 set then use numberThreads in root mini branch and bound
     1141      2 set then use numberThreads for root cuts
     1142      default is 0
     1143  */
     1144  inline void setThreadMode(int value)
     1145  { threadMode_=value;};
    10951146  //@}
    10961147
     
    11441195  inline void setTypePresolve(int value)
    11451196  { presolve_=value;};
     1197 
    11461198  //@}
    11471199
     
    13801432  inline bool ownObjects() const
    13811433  { return ownObjects_;};
     1434  /// Pointer to a mutex
     1435  inline void * mutex()
     1436  { return mutex_;};
    13821437  //@}
    13831438  //---------------------------------------------------------------------------
     
    18101865  /// Pointer to user-defined data structure
    18111866  void * appData_;
    1812   /// Pointer to
     1867  /// Pointer to a mutex
     1868  void * mutex_;
     1869  /// Presolve for CbcTreeLocal
    18131870  int presolve_;
    18141871  /** Maximum number of candidates to consider for strong branching.
     
    19492006  /// Whether to force a resolve after takeOffCuts
    19502007  bool resolveAfterTakeOffCuts_;
     2008  /**
     2009     Parallel
     2010     0 - off
     2011     1 - testing
     2012     2-99 threads
     2013     other special meanings
     2014  */
     2015  int numberThreads_;
     2016  /** thread mode
     2017      always use numberThreads for branching
     2018      1 set then use numberThreads in root mini branch and bound
     2019      2 set then use numberThreads for root cuts
     2020      default is 0
     2021  */
     2022  int threadMode_;
    19512023 //@}
    19522024};
  • branches/devel/Cbc/src/CbcNode.cpp

    r587 r642  
    1212//#define CHECK_CUT_COUNTS
    1313//#define CHECK_NODE
     14//#define CBC_CHECK_BASIS
    1415#define CBC_WEAK_STRONG
    1516#include <cassert>
     
    644645
    645646{ OsiSolverInterface *solver = model->solver();
    646 
    647647  basis->applyDiff(basisDiff_) ;
    648648
     
    41014101        delete ws;
    41024102        ws=NULL;
    4103         solver->writeMps("bad");
     4103        //solver->writeMps("bad");
    41044104        numberToFix=-1;
    41054105        delete choice.possibleBranch;
     
    41864186  return *this;
    41874187}
    4188 
    4189 
    41904188CbcNode::~CbcNode ()
    41914189{
     
    42064204      delete nodeInfo_;
    42074205    } else {
    4208       //printf("node %x nodeinfo %x parent %x\n",this,nodeInfo_,parent);
     4206      //printf("node %x nodeinfo %x parent %x\n",this,nodeInfo_,nodeInfo_->parent());
    42094207      // anyway decrement parent
    42104208      //if (parent)
  • branches/devel/Cbc/src/CbcSolver.cpp

    r621 r642  
    1515#include "CoinPragma.hpp"
    1616#include "CoinHelperFunctions.hpp"
    17 // Same version as CBC
    18 #define CBCVERSION "1.03.00"
     17// Version
     18#define CBCVERSION "1.04.00"
    1919
    2020#include "CoinMpsIO.hpp"
     
    2727#include "ClpSimplexOther.hpp"
    2828#include "ClpSolve.hpp"
     29#include "ClpMessage.hpp"
    2930#include "ClpPackedMatrix.hpp"
    3031#include "ClpPlusMinusOneMatrix.hpp"
     
    118119#include "CglStored.hpp"
    119120#include "CglLandP.hpp"
     121#include "CglResidualCapacity.hpp"
    120122
    121123#include "CbcModel.hpp"
     
    143145                        std::string & check);
    144146static void generateCode(CbcModel * model, const char * fileName,int type,int preProcess);
    145 #ifdef NDEBUG
    146 #undef NDEBUG
    147 #endif
     147//#ifdef NDEBUG
     148//#undef NDEBUG
     149//#endif
    148150//#############################################################################
    149151// To use USERCBC or USERCLP uncomment the following define and add in your fake main program in CoinSolve.cpp
     
    498500      int iColumn = objects[iObj]->columnNumber();
    499501      if (iColumn>=0&&iColumn<numberColumns) {
     502#ifndef NDEBUG
    500503        OsiSimpleInteger * obj =
    501504          dynamic_cast <OsiSimpleInteger *>(objects[iObj]) ;
     505#endif
    502506        assert (obj);
    503507        int iPriority = priorities[iColumn];
     
    816820          int iColumn = objects[iObj]->columnNumber();
    817821          if (iColumn>=0&&iColumn<nCol) {
     822#ifndef NDEBUG
    818823            OsiSimpleInteger * obj =
    819824              dynamic_cast <OsiSimpleInteger *>(objects[iObj]) ;
     825#endif
    820826            assert (obj);
    821827            int iPriority = priorities[whichColumn[iColumn]];
     
    10251031}
    10261032#endif
     1033#if 0
    10271034static int outDupRow(OsiSolverInterface * solver)
    10281035{
     
    10811088  return numberDrop;
    10821089}
     1090#endif
    10831091void checkSOS(CbcModel * babModel, const OsiSolverInterface * solver)
    10841092{
     
    12541262     It should only have one solver known to it.
    12551263  */
     1264  CoinMessageHandler * generalMessageHandler = originalSolver.messageHandler();
     1265  generalMessageHandler->setPrefix(true);
     1266  CoinMessages generalMessages = originalSolver.getModelPtr()->messages();
     1267  char generalPrint[10000];
     1268  if (originalSolver.getModelPtr()->logLevel()==0)
     1269    noPrinting=true;
    12561270  {
    12571271    double time1 = CoinCpuTime(),time2;
     
    12771291    model.setNumberBeforeTrust(21);
    12781292    int cutPass=-1234567;
     1293    int cutPassInTree=-1234567;
    12791294    int tunePreProcess=5;
    12801295    int testOsiParameters=-1;
     
    15611576    parameters[whichParam(TESTOSI,numberParameters,parameters)].setIntValue(testOsiParameters);
    15621577    parameters[whichParam(FPUMPTUNE,numberParameters,parameters)].setIntValue(1003);
     1578#ifdef CBC_THREAD
     1579    parameters[whichParam(THREADS,numberParameters,parameters)].setIntValue(0);
     1580#endif
    15631581    if (testOsiParameters>=0) {
    15641582      // trying nonlinear - switch off some stuff
     
    15691587    parameters[whichParam(MIPOPTIONS,numberParameters,parameters)].setIntValue(128|64|1);
    15701588    parameters[whichParam(MIPOPTIONS,numberParameters,parameters)].setIntValue(1);
     1589    parameters[whichParam(CUTPASSINTREE,numberParameters,parameters)].setIntValue(1);
    15711590    parameters[whichParam(MOREMIPOPTIONS,numberParameters,parameters)].setIntValue(-1);
    15721591    parameters[whichParam(MAXHOTITS,numberParameters,parameters)].setIntValue(100);
     
    16431662    int landpAction=0;
    16441663    parameters[whichParam(LANDPCUTS,numberParameters,parameters)].setCurrentOption("off");
     1664    CglResidualCapacity residualCapacityGen;
     1665    // set default action (0=off,1=on,2=root)
     1666    int residualCapacityAction=0;
     1667    parameters[whichParam(RESIDCUTS,numberParameters,parameters)].setCurrentOption("off");
    16451668    // Stored cuts
    16461669    bool storedCuts = false;
     
    16801703    std::string field;
    16811704    if (!noPrinting) {
    1682       std::cout<<"Coin Cbc and Clp Solver version "<<CBCVERSION
    1683                <<", build "<<__DATE__<<std::endl;
     1705      sprintf(generalPrint,"Coin Cbc and Clp Solver version %s, build %s",
     1706              CBCVERSION,__DATE__);
     1707      generalMessageHandler->message(CLP_GENERAL,generalMessages)
     1708        << generalPrint
     1709        <<CoinMessageEol;
    16841710      // Print command line
    16851711      if (argc>1) {
    1686         printf("command line - ");
     1712        sprintf(generalPrint,"command line - ");
    16871713        for (int i=0;i<argc;i++)
    1688           printf("%s ",argv[i]);
    1689         printf("\n");
     1714          sprintf(generalPrint+strlen(generalPrint),"%s ",argv[i]);
     1715        generalMessageHandler->message(CLP_GENERAL,generalMessages)
     1716          << generalPrint
     1717          <<CoinMessageEol;
    16901718      }
    16911719    }
     
    19451973              else if (parameters[iParam].type()==DUALIZE)
    19461974                dualize = value;
    1947               else if (parameters[iParam].type()==CUTPASS)
    1948                 cutPass = value;
    19491975              else if (parameters[iParam].type()==PROCESSTUNE)
    19501976                tunePreProcess = value;
    19511977              else if (parameters[iParam].type()==VERBOSE)
    19521978                verbose = value;
     1979              parameters[iParam].setIntParameter(lpSolver,value);
     1980            } else {
     1981              if (parameters[iParam].type()==CUTPASS)
     1982                cutPass = value;
     1983              else if (parameters[iParam].type()==CUTPASSINTREE)
     1984                cutPassInTree = value;
    19531985              else if (parameters[iParam].type()==FPUMPITS)
    19541986                { useFpump = true;parameters[iParam].setIntValue(value);}
    1955               parameters[iParam].setIntParameter(lpSolver,value);
    1956             } else {
    19571987              parameters[iParam].setIntParameter(model,value);
    19581988            }
     
    21392169              landpAction = action;
    21402170              break;
     2171            case RESIDCUTS:
     2172              defaultSettings=false; // user knows what she is doing
     2173              residualCapacityAction = action;
     2174              break;
    21412175            case ROUNDING:
    21422176              defaultSettings=false; // user knows what she is doing
     
    21622196              parameters[whichParam(PROBINGCUTS,numberParameters,parameters)].setCurrentOption(action);
    21632197              parameters[whichParam(KNAPSACKCUTS,numberParameters,parameters)].setCurrentOption(action);
    2164               if (!action) {
    2165                 redsplitAction = action;
    2166                 parameters[whichParam(REDSPLITCUTS,numberParameters,parameters)].setCurrentOption(action);
    2167               }
    21682198              parameters[whichParam(CLIQUECUTS,numberParameters,parameters)].setCurrentOption(action);
    21692199              parameters[whichParam(FLOWCUTS,numberParameters,parameters)].setCurrentOption(action);
     
    21712201              parameters[whichParam(TWOMIRCUTS,numberParameters,parameters)].setCurrentOption(action);
    21722202              if (!action) {
     2203                redsplitAction = action;
     2204                parameters[whichParam(REDSPLITCUTS,numberParameters,parameters)].setCurrentOption(action);
    21732205                landpAction = action;
    21742206                parameters[whichParam(LANDPCUTS,numberParameters,parameters)].setCurrentOption(action);
     2207                residualCapacityAction = action;
     2208                parameters[whichParam(RESIDCUTS,numberParameters,parameters)].setCurrentOption(action);
    21752209              }
    21762210              break;
     
    22672301                //printf("dualize %d\n",dualize);
    22682302                model2 = ((ClpSimplexOther *) model2)->dualOfModel();
    2269                 printf("Dual of model has %d rows and %d columns\n",
     2303                sprintf(generalPrint,"Dual of model has %d rows and %d columns\n",
    22702304                       model2->numberRows(),model2->numberColumns());
     2305                generalMessageHandler->message(CLP_GENERAL,generalMessages)
     2306                  << generalPrint
     2307                  <<CoinMessageEol;
    22712308                model2->setOptimizationDirection(1.0);
    22722309              }
     
    22822319                  if (preSolve<=100) {
    22832320                    presolveType=ClpSolve::presolveNumber;
    2284                     printf("Doing %d presolve passes - picking up non-costed slacks\n",
     2321                    sprintf(generalPrint,"Doing %d presolve passes - picking up non-costed slacks\n",
    22852322                           preSolve);
     2323                    generalMessageHandler->message(CLP_GENERAL,generalMessages)
     2324                      << generalPrint
     2325                      <<CoinMessageEol;
    22862326                    solveOptions.setDoSingletonColumn(true);
    22872327                  } else {
    22882328                    preSolve -=100;
    22892329                    presolveType=ClpSolve::presolveNumberCost;
    2290                     printf("Doing %d presolve passes - picking up costed slacks\n",
     2330                    sprintf(generalPrint,"Doing %d presolve passes - picking up costed slacks\n",
    22912331                           preSolve);
     2332                    generalMessageHandler->message(CLP_GENERAL,generalMessages)
     2333                      << generalPrint
     2334                      <<CoinMessageEol;
    22922335                  }
    22932336                }
     
    23882431                if (testOsiOptions<10) {
    23892432                  solution = linkSolver->nonlinearSLP(slpValue>0 ? slpValue : 20 ,1.0e-5);
    2390                 } else if (testOsiOptions==10) {
     2433                } else if (testOsiOptions>=10) {
    23912434                  CoinModel coinModel = *linkSolver->coinModel();
    2392                   ClpSimplex * tempModel = approximateSolution(coinModel,slpValue>0 ? slpValue : 20 ,1.0e-5,0);
     2435                  ClpSimplex * tempModel = approximateSolution(coinModel,slpValue>0 ? slpValue : 50 ,1.0e-5,0);
    23932436                  assert (tempModel);
    23942437                  solution = CoinCopyOfArray(tempModel->primalColumnSolution(),coinModel.numberColumns());
     
    25532596              int nOut = numberRows-clpSolver->getNumRows();
    25542597              if (nOut&&!noPrinting)
    2555                 printf("%d rows eliminated\n",nOut);
     2598                sprintf(generalPrint,"%d rows eliminated\n",nOut);
     2599              generalMessageHandler->message(CLP_GENERAL,generalMessages)
     2600                << generalPrint
     2601                <<CoinMessageEol;
    25562602            } else {
    25572603              std::cout<<"** Current model not valid"<<std::endl;
     
    26422688                      ClpSimplex * qp = linkSolver->quadraticModel();
    26432689                      //linkSolver->nonlinearSLP(CoinMax(slpValue,10),1.0e-5);
    2644                       qp->nonlinearSLP(CoinMax(slpValue,20),1.0e-5);
     2690                      qp->nonlinearSLP(CoinMax(slpValue,40),1.0e-5);
    26452691                      qp->primal(1);
    26462692                      OsiSolverLinearizedQuadratic solver2(qp);
     
    27142760                     
    27152761                      CbcHeuristicLocal heuristicLocal(*cbcModel);
    2716                       heuristicLocal.setHeuristicName("join solutions");
     2762                      heuristicLocal.setHeuristicName("combine solutions");
    27172763                      heuristicLocal.setSearchType(1);
    27182764                      cbcModel->addHeuristic(&heuristicLocal);
     
    27672813                      if ((linkSolver->specialOptions2()&4)!=0) {
    27682814                        int numberColumns = coinModel->numberColumns();
     2815                        assert (linkSolver->objectiveVariable()==numberColumns);
    27692816                        // add OA cut
    27702817                        double offset;
     
    29092956                    }
    29102957                  }
    2911                   printf("%d columns fixed\n",numberFixed);
     2958                  sprintf(generalPrint,"%d columns fixed\n",numberFixed);
     2959                  generalMessageHandler->message(CLP_GENERAL,generalMessages)
     2960                    << generalPrint
     2961                    <<CoinMessageEol;
    29122962                }
    29132963              }
     
    30833133                if (!noPrinting) {
    30843134                  if (!solver2) {
    3085                     printf("Pre-processing says infeasible or unbounded\n");
     3135                    sprintf(generalPrint,"Pre-processing says infeasible or unbounded\n");
     3136                    generalMessageHandler->message(CLP_GENERAL,generalMessages)
     3137                      << generalPrint
     3138                      <<CoinMessageEol;
    30863139                    break;
    30873140                  } else {
    3088                     printf("processed model has %d rows, %d columns and %d elements\n",
    3089                            solver2->getNumRows(),solver2->getNumCols(),solver2->getNumElements());
     3141                    //printf("processed model has %d rows, %d columns and %d elements\n",
     3142                    //     solver2->getNumRows(),solver2->getNumCols(),solver2->getNumElements());
    30903143                  }
    30913144                }
     
    33123365                  babModel->addHeuristic(&heuristic1) ;
    33133366                CbcHeuristicLocal heuristic2(*babModel);
    3314                 heuristic2.setHeuristicName("join solutions");
     3367                heuristic2.setHeuristicName("combine solutions");
    33153368                heuristic2.setSearchType(1);
    33163369                if (useCombine)
     
    33553408                switches[numberGenerators++]=0;
    33563409              }
    3357               if (gomoryAction&&(complicatedInteger!=1||gomoryAction==1)) {
     3410              if (gomoryAction&&(complicatedInteger!=1||
     3411                                 (gomoryAction==1||gomoryAction==4))) {
    33583412                babModel->addCutGenerator(&gomoryGen,translate[gomoryAction],"Gomory");
    33593413                switches[numberGenerators++]=-1;
     
    33853439              if (landpAction) {
    33863440                babModel->addCutGenerator(&landpGen,translate[landpAction],"LiftAndProject");
     3441                switches[numberGenerators++]=1;
     3442              }
     3443              if (residualCapacityAction) {
     3444                babModel->addCutGenerator(&residualCapacityGen,translate[residualCapacityAction],"ResidualCapacity");
    33873445                switches[numberGenerators++]=1;
    33883446              }
     
    34173475                  babModel->setMaximumCutPassesAtRoot(cutPass);
    34183476                }
    3419                 babModel->setMaximumCutPasses(1);
     3477                if (cutPassInTree==-1234567)
     3478                  babModel->setMaximumCutPasses(1);
     3479                else
     3480                  babModel->setMaximumCutPasses(cutPassInTree);
    34203481              }
    34213482              // Do more strong branching if small
     
    34623523              // Used to be automatically set
    34633524              int mipOptions = parameters[whichParam(MIPOPTIONS,numberParameters,parameters)].intValue()%10000;
    3464               if (mipOptions!=(1))
    3465                 printf("mip options %d\n",mipOptions);
     3525              if (mipOptions!=(1)) {
     3526                sprintf(generalPrint,"mip options %d\n",mipOptions);
     3527                generalMessageHandler->message(CLP_GENERAL,generalMessages)
     3528                  << generalPrint
     3529                  <<CoinMessageEol;
     3530              }
    34663531              osiclp->setSpecialOptions(mipOptions);
    34673532              if (gapRatio < 1.0e100) {
     
    34803545                int moreMipOptions = parameters[whichParam(MOREMIPOPTIONS,numberParameters,parameters)].intValue();
    34813546                if (moreMipOptions>=0) {
    3482                   printf("more mip options %d\n",moreMipOptions);
     3547                  sprintf(generalPrint,"more mip options %d\n",moreMipOptions);
     3548                  generalMessageHandler->message(CLP_GENERAL,generalMessages)
     3549                    << generalPrint
     3550                    <<CoinMessageEol;
    34833551                  OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (babModel->solver());
    34843552                  if (moreMipOptions==10000) {
     
    36613729                        }
    36623730                        delete [] back;
    3663                         if (nMissing)
    3664                           printf("%d SOS variables vanished due to pre processing? - check validity?\n",nMissing);
     3731                        if (nMissing) {
     3732                          sprintf(generalPrint,"%d SOS variables vanished due to pre processing? - check validity?\n",nMissing);
     3733                          generalMessageHandler->message(CLP_GENERAL,generalMessages)
     3734                            << generalPrint
     3735                            <<CoinMessageEol;
     3736                        }
    36653737                      }
    36663738                      for (iSOS =0;iSOS<numberSOS;iSOS++) {
     
    38263898                        }
    38273899                        delete [] back;
    3828                         if (nMissing)
    3829                           printf("%d SOS variables vanished due to pre processing? - check validity?\n",nMissing);
     3900                        if (nMissing) {
     3901                          sprintf(generalPrint,"%d SOS variables vanished due to pre processing? - check validity?\n",nMissing);
     3902                          generalMessageHandler->message(CLP_GENERAL,generalMessages)
     3903                            << generalPrint
     3904                            <<CoinMessageEol;
     3905                        }
    38303906                      }
    38313907                      for (iSOS =0;iSOS<numberSOS;iSOS++) {
     
    39884064                }
    39894065                if (testOsiOptions>=0) {
    3990                   printf("Testing OsiObject options %d\n",testOsiOptions);
     4066                  sprintf(generalPrint,"Testing OsiObject options %d\n",testOsiOptions);
     4067                  generalMessageHandler->message(CLP_GENERAL,generalMessages)
     4068                    << generalPrint
     4069                    <<CoinMessageEol;
    39914070                  if (!numberSOS) {
    39924071                    babModel->solver()->findIntegersAndSOS(false);
     
    39954074                    OsiSolverLink * solver3 = dynamic_ca