Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Cbc/src/CbcNode.cpp

    r2098 r2103  
    77// Turn off compiler warning about long names
    88#  pragma warning(disable:4786)
     9#include <windows.h> // for Sleep()
     10#ifdef small
     11#undef small
     12#endif
     13#else
     14#include <unistd.h> // for usleep()
    915#endif
    1016
    1117#include "CbcConfig.h"
     18#ifdef COIN_HAS_NTY
     19#include "CbcSymmetry.hpp"
     20#endif
    1221//#define DEBUG_SOLUTION
    1322#ifdef DEBUG_SOLUTION
     
    4352#include "OsiClpSolverInterface.hpp"
    4453#include "ClpSimplexOther.hpp"
     54#include "ClpSolve.hpp"
     55#include "ClpDualRowSteepest.hpp"
     56#include "ClpPrimalColumnPivot.hpp"
    4557#endif
    4658using namespace std;
     
    6072{
    6173#ifdef CHECK_NODE
    62     printf("CbcNode %x Constructor\n", this);
     74    printf("CbcNode %p Constructor\n", this);
    6375#endif
    6476}
     
    8395{
    8496#ifdef CHECK_NODE
    85     printf("CbcNode %x Constructor from model\n", this);
     97    printf("CbcNode %p Constructor from model\n", this);
    8698#endif
    8799    model->setObjectiveValue(this, lastNode);
     
    882894            }
    883895        }
     896        //if (!model->parentModel())
     897        //solver->writeMps("query");
    884898        // If we have hit max time don't do strong branching
    885899        bool hitMaxTime = (model->getCurrentSeconds() >
     
    15401554    // Set guessed solution value
    15411555    guessedObjectiveValue_ = objectiveValue_ + estimatedDegradation;
     1556    //printf ("Node %d depth %d unsatisfied %d sum %g obj %g guess %g\n",
     1557    //      model->getNodeCount(),depth_,numberUnsatisfied_,
     1558    //      sumInfeasibilities_,objectiveValue_,guessedObjectiveValue_);
    15421559    /*
    15431560      Cleanup, then we're outta here.
     
    16111628    branch_ = NULL;
    16121629    OsiSolverInterface * solver = model->solver();
     1630    //#define CHECK_DEBUGGER_PATH
     1631#ifdef CHECK_DEBUGGER_PATH
     1632    bool onOptimalPath=false;
     1633    if ((model->specialOptions()&1) != 0) {
     1634      const OsiRowCutDebugger *debugger = solver->getRowCutDebugger() ;
     1635      if (debugger) {
     1636        onOptimalPath = true;
     1637      }
     1638    }
     1639#endif
    16131640    // get information on solver type
    16141641    const OsiAuxInfo * auxInfo = solver->getAuxiliaryInfo();
     
    19541981    choice.possibleBranch = choiceObject;
    19551982    numberPassesLeft = CoinMax(numberPassesLeft, 2);
     1983    /* How dogged to be in strong branching
     1984       0 - default
     1985       1 - go to end on first time
     1986       2 - always go to end
     1987     */
     1988    int goToEndInStrongBranching = (model->moreSpecialOptions2()&(3*8192))>>13;
     1989#ifdef COIN_HAS_NTY
     1990    // 1 after, 2 strong, 3 until depth 5
     1991    int orbitOption = (model->moreSpecialOptions2()&(128|256))>>7;
     1992#endif
    19561993    //#define DEBUG_SOLUTION
    19571994#ifdef DEBUG_SOLUTION
     
    26202657                        solver->unmarkHotStart();
    26212658                        model->resolve(NULL, 11, saveSolution, saveLower, saveUpper);
     2659#ifdef CHECK_DEBUGGER_PATH
     2660                        if ((model->specialOptions()&1) != 0 && onOptimalPath) {
     2661                          const OsiRowCutDebugger *debugger = solver->getRowCutDebugger() ;
     2662                          if (!debugger) {
     2663                            printf("Strong branching down on %d went off optimal path\n",iObject);
     2664                            abort();
     2665                          }
     2666                        }
     2667#endif
    26222668                        double newObjValue = solver->getObjSense()*solver->getObjValue();
    26232669                        objectiveValue_ = CoinMax(objectiveValue_,newObjValue);
     
    28022848            }
    28032849#endif
     2850#ifdef COIN_HAS_NTY
     2851            const int * orbits = NULL;
     2852#endif
     2853#ifdef COIN_HAS_NTY
     2854            if (orbitOption==2 /* was >1*/) {
     2855              CbcSymmetry * symmetryInfo = model->symmetryInfo();
     2856              CbcNodeInfo * infoX = lastNode ? lastNode->nodeInfo() : NULL;
     2857              bool worthTrying = false;
     2858              if (infoX) {
     2859                CbcNodeInfo * info = infoX;
     2860                for (int i=0;i<NTY_BAD_DEPTH;i++) {
     2861                  if (!info->parent()) {
     2862                    worthTrying = true;
     2863                    break;
     2864                  }
     2865                  info = info->parent();
     2866                  if (info->symmetryWorked()) {
     2867                    worthTrying = true;
     2868                    break;
     2869                  }
     2870                }
     2871              } else {
     2872                worthTrying=true;
     2873              }
     2874              if (symmetryInfo && worthTrying) {
     2875                symmetryInfo->ChangeBounds(solver->getColLower(),
     2876                                            solver->getColUpper(),
     2877                                            solver->getNumCols(),false);
     2878                symmetryInfo->Compute_Symmetry();
     2879                symmetryInfo->fillOrbits();
     2880                orbits = symmetryInfo->whichOrbit();
     2881                int iColumn=-1;
     2882                if (orbits && symmetryInfo->numberUsefulOrbits()) {
     2883                  bool doBranch=true;
     2884                  int numberUsefulOrbits = symmetryInfo->numberUsefulOrbits();
     2885                  if (numberUsefulOrbits<2) {
     2886                    assert (numberUsefulOrbits);
     2887                    double largest=-1.0;
     2888                    for (int i=0;i<numberColumns;i++) {
     2889                      if (orbits[i]>=0) {
     2890                        if (saveSolution[i]>largest) {
     2891                          largest=saveSolution[i];
     2892                          iColumn=i;
     2893                        }
     2894                      }
     2895                    }
     2896                  } else {
     2897#if COIN_HAS_NTY2 == 1
     2898                    // take largest
     2899                    int iOrbit=symmetryInfo->largestOrbit(solver->getColLower(),
     2900                                                          solver->getColUpper());
     2901                    double largest=-1.0;
     2902                    for (int i=0;i<numberColumns;i++) {
     2903                      if (orbits[i]==iOrbit) {
     2904                        if (saveSolution[i]>largest) {
     2905                          largest=saveSolution[i];
     2906                          iColumn=i;
     2907                        }
     2908                      }
     2909                    }
     2910#endif
     2911                    if (orbitOption==2) {
     2912                      // strong
     2913                      int nDo=0;
     2914                      const double * lower = solver->getColLower();
     2915                      const double * upper = solver->getColUpper();
     2916                      const int * integerVariable = model->integerVariable();
     2917                      for (int iOrbit = 0; iOrbit < numberUsefulOrbits; iOrbit++) {
     2918                        double distance=1.0;
     2919                        int iColumn = -1;
     2920                        int numberIntegers = model->numberIntegers();
     2921                        for (int j=0;j<numberIntegers;j++) {
     2922                          int i=integerVariable[j];
     2923                          if (orbits[i]==iOrbit &&lower[i]==0.0&&upper[i]==1.0) {
     2924                            double away = fabs(saveSolution[i]-0.5);
     2925                            if (away<distance&&away<0.4999) {
     2926                              distance=away;
     2927                              iColumn=j;
     2928                            }
     2929                          }
     2930                        }
     2931                        if (iColumn>=0)
     2932                          whichObject[nDo++]=iColumn;
     2933                      }
     2934                      if (nDo)
     2935                        numberToDo=nDo;
     2936                      doBranch=false;
     2937                    } else if (orbitOption==3) {
     2938                      // subset
     2939                      int nDo=0;
     2940                      for (int iDo = 0; iDo < numberToDo; iDo++) {
     2941                        int iObject = whichObject[iDo];
     2942                        OsiObject * object = model->modifiableObject(iObject);
     2943                        CbcSimpleIntegerDynamicPseudoCost * dynamicObject =
     2944                          dynamic_cast <CbcSimpleIntegerDynamicPseudoCost *>(object) ;
     2945                        int iColumn = dynamicObject ? dynamicObject->columnNumber() : -1;
     2946                        if (iColumn<0||orbits[iColumn]>=0)
     2947                          whichObject[nDo++]=whichObject[iDo];
     2948                      }
     2949                      assert(nDo);
     2950                      //printf("nDo %d\n",nDo);
     2951                      numberToDo=nDo;
     2952                      doBranch=false;
     2953                      /* need NULL as if two in same orbit and strong branching fixes
     2954                         then we may be in trouble.
     2955                         Strong option should be OK as only one in set done.
     2956                       */
     2957                      orbits=NULL;
     2958                    }
     2959                  }
     2960                  if(doBranch) {
     2961                    orbitOption=0;
     2962                    branch_ = new CbcOrbitalBranchingObject(model,iColumn,1,0,NULL);
     2963                    if (infoX)
     2964                      infoX->setSymmetryWorked();
     2965                    numberToDo=0;
     2966                  }
     2967                }
     2968              }
     2969            }
     2970#endif
    28042971            for ( iDo = 0; iDo < numberToDo; iDo++) {
    28052972                int iObject = whichObject[iDo];
     
    28102977                int preferredWay;
    28112978                double infeasibility = object->infeasibility(&usefulInfo, preferredWay);
     2979                bool feasibleSolution=false;
    28122980                double predictedChange=0.0;
    28132981                // may have become feasible
     
    28483016                  choice.downMovement = 0.1;
    28493017                }
    2850                   assert (choice.upMovement >= 0.0);
    2851                   assert (choice.downMovement >= 0.0);
     3018                assert (choice.upMovement >= 0.0);
     3019                assert (choice.downMovement >= 0.0);
    28523020                choice.fix = 0; // say not fixed
    28533021                // see if can skip strong branching
     
    28923060                    double newObjectiveValue = 1.0e100;
    28933061                    int j;
     3062#ifdef COIN_HAS_CLP
     3063                    int saveMaxHotIts=0;
     3064                    int saveOsiClpOptions=0;
     3065                    if (osiclp && goToEndInStrongBranching) {
     3066                      /* How dogged to be in strong branching
     3067                         0 - default
     3068                         1 - go to end on first time
     3069                         2 - always go to end
     3070                      */
     3071                      osiclp->getIntParam(OsiMaxNumIterationHotStart, saveMaxHotIts);
     3072                      saveOsiClpOptions=osiclp->specialOptions();
     3073                      if (goToEndInStrongBranching==2 ||
     3074                          dynamicObject->numberTimesBranched()==0) {
     3075                        osiclp->setIntParam(OsiMaxNumIterationHotStart,
     3076                                            10*(osiclp->getNumRows()+numberColumns));
     3077                        osiclp->setSpecialOptions(saveOsiClpOptions & (~32));
     3078                      }
     3079                    }
     3080#endif
    28943081                    // status is 0 finished, 1 infeasible and other
    28953082                    int iStatus;
     
    29023089                    choice.possibleBranch->way(-1) ;
    29033090                    predictedChange = choice.possibleBranch->branch() ;
     3091#ifdef COIN_HAS_NTY
     3092                    if (orbits) {
     3093                      // can fix all in orbit
     3094                      int fixOrbit = orbits[iObject];
     3095                      if (fixOrbit>=0) {
     3096                        //printf("fixing all in orbit %d for column %d\n",fixOrbit,iObject);
     3097                        for (int i=0;i<numberColumns;i++) {
     3098                          if (orbits[i]==fixOrbit)
     3099                            solver->setColUpper(i,0.0);
     3100                        }
     3101                      }
     3102                    }
     3103#endif
    29043104                    solver->solveFromHotStart() ;
    29053105                    bool needHotStartUpdate = false;
     
    29213121                        iStatus = 1; // infeasible
    29223122#ifdef CONFLICT_CUTS
     3123#undef CONFLICT_CUTS
     3124                        //#define CONFLICT_CUTS 2
     3125#endif
     3126#ifdef CONFLICT_CUTS
    29233127# ifdef COIN_HAS_CLP
    29243128                        if (osiclp&&(model->moreSpecialOptions()&4194304)!=0) {
     
    29263130                            model->topOfTree();
    29273131                          if (topOfTree) {
     3132#if CONFLICT_CUTS==2
    29283133                            OsiRowCut * cut = osiclp->smallModelCut(topOfTree->lower(),
    29293134                                                                    topOfTree->upper(),
    29303135                                                                    model->numberRowsAtContinuous(),
    29313136                                                                    model->whichGenerator());
     3137#else
     3138                            OsiRowCut * cut = osiclp->modelCut(topOfTree->lower(),
     3139                                                               topOfTree->upper(),
     3140                                                               model->numberRowsAtContinuous(),
     3141                                                               model->whichGenerator(),0);
     3142#endif
    29323143                            if (cut) {
    2933                               printf("XXXXXX found conflict cut in strong branching\n");
     3144                              if (model->messageHandler()->logLevel() > 1)
     3145                                printf("Conflict cut found in strong branching (%d elements)\n",
     3146                                       cut->row().getNumElements());
    29343147                              //cut->print();
    29353148                              if ((model->specialOptions()&1) != 0) {
     
    29983211#endif
    29993212                            // See if integer solution
    3000                             if (model->feasibleSolution(choice.numIntInfeasDown,
    3001                                                         choice.numObjInfeasDown)
     3213                            feasibleSolution =
     3214                              model->feasibleSolution(choice.numIntInfeasDown,
     3215                                                      choice.numObjInfeasDown);
     3216                            if (feasibleSolution
    30023217                                    && model->problemFeasibility()->feasible(model, -1) >= 0) {
    30033218                                if (auxiliaryInfo->solutionAddsCuts()) {
     
    30463261                        needHotStartUpdate = false;
    30473262                        model->resolve(NULL, 11, saveSolution, saveLower, saveUpper);
     3263#ifdef CHECK_DEBUGGER_PATH
     3264                        if ((model->specialOptions()&1) != 0 && onOptimalPath) {
     3265                          const OsiRowCutDebugger *debugger = solver->getRowCutDebugger() ;
     3266                          if (!debugger) {
     3267                            printf("Strong branching down on %d went off optimal path\n",iObject);
     3268                            model->solver()->writeMps("query");
     3269                            abort();
     3270                          }
     3271                        }
     3272#endif
    30483273                        double newObjValue = solver->getObjSense()*solver->getObjValue();
    30493274                        objectiveValue_ = CoinMax(objectiveValue_,newObjValue);
     
    30923317                    predictedChange=choice.possibleBranch->branch();
    30933318                    solver->solveFromHotStart() ;
     3319#ifdef COIN_HAS_CLP
     3320                    if (osiclp && goToEndInStrongBranching) {
     3321                      osiclp->setIntParam(OsiMaxNumIterationHotStart, saveMaxHotIts);
     3322                      osiclp->setSpecialOptions(saveOsiClpOptions);
     3323                    }
     3324#endif
    30943325                    numberStrongDone++;
    30953326                    numberStrongIterations += solver->getIterationCount();
     
    31143345                            model->topOfTree();
    31153346                          if (topOfTree) {
     3347#if CONFLICT_CUTS==2
    31163348                            OsiRowCut * cut = osiclp->smallModelCut(topOfTree->lower(),
    31173349                                                                    topOfTree->upper(),
    31183350                                                                    model->numberRowsAtContinuous(),
    31193351                                                                    model->whichGenerator());
     3352#else
     3353                            OsiRowCut * cut = osiclp->modelCut(topOfTree->lower(),
     3354                                                               topOfTree->upper(),
     3355                                                               model->numberRowsAtContinuous(),
     3356                                                               model->whichGenerator(),0);
     3357#endif
    31203358                            if (cut) {
    3121                               printf("XXXXXX found conflict cut in strong branching\n");
     3359                              //printf("XXXXXX found conflict cut in strong branching\n");
    31223360                              //cut->print();
    31233361                              if ((model->specialOptions()&1) != 0) {
     
    31853423#endif
    31863424                            // See if integer solution
    3187                             if (model->feasibleSolution(choice.numIntInfeasUp,
    3188                                                         choice.numObjInfeasUp)
     3425                            feasibleSolution =
     3426                              model->feasibleSolution(choice.numIntInfeasUp,
     3427                                                      choice.numObjInfeasUp);
     3428                            if (feasibleSolution
    31893429                                    && model->problemFeasibility()->feasible(model, -1) >= 0) {
    31903430#ifdef BONMIN
     
    32133453                                if (needHotStartUpdate) {
    32143454                                    model->resolve(NULL, 11, saveSolution, saveLower, saveUpper);
     3455#ifdef CHECK_DEBUGGER_PATH
     3456                                    if ((model->specialOptions()&1) != 0 && onOptimalPath) {
     3457                                      const OsiRowCutDebugger *debugger = solver->getRowCutDebugger() ;
     3458                                      if (!debugger) {
     3459                                        printf("Strong branching up on %d went off optimal path\n",iObject);
     3460                                        abort();
     3461                                      }
     3462                                    }
     3463#endif
    32153464                                    newObjectiveValue = solver->getObjSense() * solver->getObjValue();
    32163465                                    objectiveValue_ = CoinMax(objectiveValue_,newObjectiveValue);
     
    32483497                        needHotStartUpdate = false;
    32493498                        model->resolve(NULL, 11, saveSolution, saveLower, saveUpper);
     3499#ifdef CHECK_DEBUGGER_PATH
     3500                        if ((model->specialOptions()&1) != 0 && onOptimalPath) {
     3501                          const OsiRowCutDebugger *debugger = solver->getRowCutDebugger() ;
     3502                          if (!debugger) {
     3503                            printf("Strong branching up on %d went off optimal path\n",iObject);
     3504                            abort();
     3505                          }
     3506                        }
     3507#endif
    32503508                        double newObjValue = solver->getObjSense()*solver->getObjValue();
    32513509                        objectiveValue_ = CoinMax(objectiveValue_,newObjValue);
     
    32623520                                                   solver->getColSolution()) ;
    32633521                            model->resolve(NULL, 11, saveSolution, saveLower, saveUpper);
     3522#ifdef CHECK_DEBUGGER_PATH
     3523                            if ((model->specialOptions()&1) != 0 && onOptimalPath) {
     3524                              const OsiRowCutDebugger *debugger = solver->getRowCutDebugger() ;
     3525                              if (!debugger) {
     3526                                printf("Strong branching up on %d went off optimal path\n",iObject);
     3527                                abort();
     3528                              }
     3529                            }
     3530#endif
    32643531                            double newObjValue = solver->getObjSense()*solver->getObjValue();
    32653532                            objectiveValue_ = CoinMax(objectiveValue_,newObjValue);
     
    34173684                        solver->unmarkHotStart();
    34183685                        model->resolve(NULL, 11, saveSolution, saveLower, saveUpper);
     3686#ifdef CHECK_DEBUGGER_PATH
     3687                        if ((model->specialOptions()&1) != 0 && onOptimalPath) {
     3688                          const OsiRowCutDebugger *debugger = solver->getRowCutDebugger() ;
     3689                          if (!debugger) {
     3690                            printf("Strong branching down on %d went off optimal path\n",iObject);
     3691                            abort();
     3692                          }
     3693                        }
     3694#endif
    34193695                        double newObjValue = solver->getObjSense()*solver->getObjValue();
    34203696                        objectiveValue_ = CoinMax(objectiveValue_,newObjValue);
     
    34693745                        solver->unmarkHotStart();
    34703746                        model->resolve(NULL, 11, saveSolution, saveLower, saveUpper);
     3747#ifdef CHECK_DEBUGGER_PATH
     3748                        if ((model->specialOptions()&1) != 0 && onOptimalPath) {
     3749                          const OsiRowCutDebugger *debugger = solver->getRowCutDebugger() ;
     3750                          if (!debugger) {
     3751                            printf("Strong branching down on %d went off optimal path\n",iObject);
     3752                            solver->writeMps("query");
     3753                            abort();
     3754                          }
     3755                        }
     3756#endif
    34713757                        double newObjValue = solver->getObjSense()*solver->getObjValue();
    34723758                        objectiveValue_ = CoinMax(objectiveValue_,newObjValue);
     
    35623848                    solver->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo, &easy) ;
    35633849                    model->resolve(NULL, 11, saveSolution, saveLower, saveUpper) ;
     3850#ifdef CHECK_DEBUGGER_PATH
     3851                    if ((model->specialOptions()&1) != 0 && onOptimalPath) {
     3852                      const OsiRowCutDebugger *debugger = solver->getRowCutDebugger() ;
     3853                      if (!debugger) {
     3854                        printf("Strong branching went off optimal path\n");
     3855                        abort();
     3856                      }
     3857                    }
     3858#endif
    35643859                    double newObjValue = solver->getObjSense()*solver->getObjValue();
    35653860                    objectiveValue_ = CoinMax(objectiveValue_,newObjValue);
     
    36683963    // Set guessed solution value
    36693964    guessedObjectiveValue_ = objectiveValue_ + estimatedDegradation;
     3965    int kColumn=-1;
     3966    if (branch_) {
     3967      CbcObject * obj = (dynamic_cast<CbcBranchingObject *>(branch_))->object();
     3968      CbcSimpleInteger * branchObj =
     3969        dynamic_cast <CbcSimpleInteger *>(obj) ;
     3970      if (branchObj) {
     3971        kColumn=branchObj->columnNumber();
     3972      }
     3973    }
     3974#ifdef COIN_HAS_NTY
     3975    if (orbitOption&&kColumn>=0) {
     3976      CbcSymmetry * symmetryInfo = model->symmetryInfo();
     3977      CbcNodeInfo * infoX = lastNode ? lastNode->nodeInfo() : NULL;
     3978      bool worthTrying = false;
     3979      if (infoX) {
     3980        CbcNodeInfo * info = infoX;
     3981        for (int i=0;i<NTY_BAD_DEPTH;i++) {
     3982          if (!info->parent()) {
     3983            worthTrying = true;
     3984            break;
     3985          }
     3986          info = info->parent();
     3987          if (info->symmetryWorked()) {
     3988            worthTrying = true;
     3989            break;
     3990          }
     3991        }
     3992      } else {
     3993        worthTrying=true;
     3994      }
     3995      if (orbitOption==3&&depth_>5)
     3996        worthTrying=false;
     3997      if (symmetryInfo && worthTrying) {
     3998        if ((orbitOption&1)==1) {
     3999          symmetryInfo->ChangeBounds(solver->getColLower(),
     4000                                     solver->getColUpper(),
     4001                                     solver->getNumCols(),false);
     4002          symmetryInfo->Compute_Symmetry();
     4003          symmetryInfo->fillOrbits();
     4004        }
     4005        const int * orbits = symmetryInfo->whichOrbit();
     4006        if (orbits && orbits[kColumn]>=0) {
     4007          int numberUsefulOrbits = symmetryInfo->numberUsefulOrbits();
     4008          if (solver->messageHandler()->logLevel() > 1)
     4009            printf("Orbital Branching on %d - way %d n %d\n",kColumn,way(),numberUsefulOrbits);
     4010          if (numberUsefulOrbits<1000||orbitOption==3) {
     4011            delete branch_;
     4012            branch_ = new CbcOrbitalBranchingObject(model,kColumn,1,0,NULL);
     4013            if (infoX)
     4014              infoX->setSymmetryWorked();
     4015          }
     4016        }
     4017      }
     4018    }
     4019#endif
     4020    if (model->logLevel()>1)
     4021    printf ("Node %d depth %d unsatisfied %d sum %g obj %g guess %g branching on %d\n",
     4022            model->getNodeCount(),depth_,numberUnsatisfied_,
     4023            sumInfeasibilities_,objectiveValue_,guessedObjectiveValue_,
     4024            kColumn);
    36704025#ifdef DO_ALL_AT_ROOT
    36714026    if (strongType) {
     
    37324087    return anyAction;
    37334088}
     4089// 0 is down, 1 is up
     4090typedef struct {
     4091  double initialValue; // initial value
     4092  double upLowerBound; // Lower bound when going up
     4093  double downUpperBound; // Upper bound when going down
     4094  double movement[2]; // cost  (and initial away from feasible)
     4095  double sumModified[2]; // Sum of integer changes
     4096  int modified[2]; // Number integers changed
     4097  int numIntInfeas[2]; // without odd ones
     4098  int numObjInfeas[2]; // just odd ones
     4099  bool finished[2]; // true if solver finished
     4100  int numIters[2]; // number of iterations in solver (-1 if never solved)
     4101  double * integerSolution; // output if thinks integer solution
     4102# ifdef COIN_HAS_CLP
     4103  ClpDualRowSteepest * steepest;
     4104#endif
     4105  int columnNumber; // Which column it is
     4106} StrongInfo;
     4107typedef struct {
     4108  double integerTolerance;
     4109  double * originalSolution;
     4110  CoinWarmStart * ws;
     4111  double * newObjective;
     4112# ifdef COIN_HAS_CLP
     4113  ClpDualRowSteepest * dualRowPivot;
     4114  ClpPrimalColumnPivot * primalColumnPivot;
     4115# endif
     4116  int * back;
     4117  int solveType;
     4118} StrongStaticInfo;
     4119typedef struct {
     4120  StrongStaticInfo *staticInfo;
     4121  StrongInfo * choice;
     4122  OsiSolverInterface * solver;
     4123  double * tempSolution;
     4124  CoinWarmStart * tempBasis;
     4125  int whichChoice;
     4126} StrongBundle;
     4127/* return 1 if possible solution (for solveType 100 if infeasible)
     4128   2 set if down was infeasible
     4129   4 set if up was infeasible
     4130 */
     4131int solveAnalyze(void * info) {
     4132  StrongBundle * bundle = reinterpret_cast<StrongBundle *>(info);
     4133  StrongInfo * choice = bundle->choice;
     4134  StrongStaticInfo * staticInfo = bundle->staticInfo;
     4135  OsiSolverInterface * solver = bundle->solver;
     4136  int solveType = staticInfo->solveType;
     4137  if (solveType==77) {
     4138    return 0;
     4139  }
     4140  const double * saveSolution = staticInfo->originalSolution;
     4141  int iColumn = choice->columnNumber;
     4142  const int * back = staticInfo->back;
     4143  double newObjectiveValue = 1.0e100;
     4144  double integerTolerance = staticInfo->integerTolerance;
     4145  double bestSolutionValue=COIN_DBL_MAX;
     4146  int returnStatus=0;
     4147  // status is 0 finished, 1 infeasible and other
     4148  int iStatus;
     4149  /*
     4150    Try the down direction first. (Specify the initial branching alternative as
     4151    down with a call to way(-1). Each subsequent call to branch() performs the
     4152    specified branch and advances the branch object state to the next branch
     4153    alternative.)
     4154  */
     4155  for (int iWay=0;iWay<2;iWay++) {
     4156    if (choice->numIters[iWay]==0) {
     4157      int numberColumns=solver->getNumCols();
     4158      if (solveType!=100) {
     4159        double saveBound;
     4160        if (iWay==0) {
     4161          saveBound = solver->getColUpper()[iColumn];
     4162          solver->setColUpper(iColumn,choice->downUpperBound);
     4163        } else {
     4164          saveBound = solver->getColLower()[iColumn];
     4165          solver->setColLower(iColumn,choice->upLowerBound);
     4166        }
     4167        if ((solveType&2)==0) {
     4168          solver->solveFromHotStart() ;
     4169        } else {
     4170          // restore basis
     4171          solver->setWarmStart(staticInfo->ws);
     4172# ifdef COIN_HAS_CLP
     4173          if (staticInfo->dualRowPivot) {
     4174            OsiClpSolverInterface * osiclp = dynamic_cast<OsiClpSolverInterface *>(solver);
     4175            ClpSimplex * simplex = osiclp->getModelPtr();
     4176            simplex->setDualRowPivotAlgorithm(*staticInfo->dualRowPivot);
     4177            //simplex->dualRowPivot()->saveWeights(simplex,4);
     4178            simplex->setWhatsChanged(ALL_SAME_EXCEPT_COLUMN_BOUNDS);
     4179            simplex->dual(0,5);
     4180          } else {
     4181#endif
     4182          solver->resolve();
     4183# ifdef COIN_HAS_CLP
     4184          }
     4185#endif
     4186        }
     4187        if (iWay==0)
     4188          solver->setColUpper(iColumn,saveBound);
     4189        else
     4190          solver->setColLower(iColumn,saveBound);
     4191        /*
     4192          We now have an estimate of objective degradation that we can use for strong
     4193          branching. If we're over the cutoff, the variable is monotone up.
     4194          If we actually made it to optimality, check for a solution, and if we have
     4195          a good one, call setBestSolution to process it. Note that this may reduce the
     4196          cutoff, so we check again to see if we can declare this variable monotone.
     4197        */
     4198        if (solver->isProvenOptimal()) {
     4199          iStatus = 0; // optimal
     4200        } else if (solver->isIterationLimitReached()
     4201                   && !solver->isDualObjectiveLimitReached()) {
     4202          iStatus = 2; // unknown
     4203        } else {
     4204          iStatus = 1; // infeasible
     4205        }
     4206        newObjectiveValue = solver->getObjSense() * solver->getObjValue();
     4207        choice->numIters[iWay] = solver->getIterationCount();
     4208        // Look at interaction
     4209        const double * thisSolution = solver->getColSolution();
     4210        int numberModified=0;
     4211        double sumModified=0.0;
     4212        int numberInfeas=0;
     4213        for (int i=0;i<numberColumns;i++) {
     4214          if (back[i]>=0) {
     4215            double value = thisSolution[i];
     4216            if (iColumn!=i) {
     4217              double difference = fabs(saveSolution[i]-value);
     4218              if (difference>integerTolerance) {
     4219                numberModified++;
     4220                sumModified += difference;
     4221              }
     4222            }
     4223            if (fabs(value-floor(value+0.5))>integerTolerance)
     4224              numberInfeas++;;
     4225          }
     4226        }
     4227        choice->numIntInfeas[iWay]=numberInfeas;
     4228        choice->sumModified[iWay] = sumModified;
     4229        choice->modified[iWay] = numberModified;
     4230        if (!iStatus) {
     4231          choice->finished[iWay] = true ;
     4232          if (!numberInfeas) {
     4233            returnStatus=1;
     4234            if (!choice->integerSolution) {
     4235              bestSolutionValue=newObjectiveValue;
     4236              choice->integerSolution=CoinCopyOfArray(thisSolution,numberColumns);;
     4237            } else if (bestSolutionValue>newObjectiveValue) {
     4238              memcpy(choice->integerSolution,thisSolution,numberColumns*sizeof(double));
     4239            }
     4240          }
     4241        } else if (iStatus == 1) {
     4242          newObjectiveValue = 1.0e100 ;
     4243        } else {
     4244          // Can't say much as we did not finish
     4245          choice->finished[iWay] = false ;
     4246        }
     4247        choice->movement[iWay] = newObjectiveValue ;
     4248      } else {
     4249# ifdef COIN_HAS_CLP
     4250        OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (solver);
     4251        ClpSimplex * simplex = osiclp ? osiclp->getModelPtr() : NULL;
     4252#endif
     4253        // doing continuous and general integer
     4254        solver->setColSolution(staticInfo->originalSolution);
     4255        solver->setWarmStart(staticInfo->ws);
     4256        double saveBound;
     4257        double newBound;
     4258        if (iWay==0) {
     4259          saveBound=solver->getColUpper()[iColumn];
     4260          solver->setColUpper(iColumn,choice->downUpperBound);
     4261          newBound=choice->downUpperBound;
     4262        } else {
     4263          saveBound=solver->getColLower()[iColumn];
     4264          solver->setColLower(iColumn,choice->upLowerBound);
     4265          newBound=choice->upLowerBound;
     4266        }
     4267# if 0 //def COIN_HAS_CLP
     4268        if (simplex) {
     4269          // set solution to new bound (if basic will be recomputed)
     4270          simplex->primalColumnSolution()[iColumn]=newBound;
     4271        }
     4272#endif
     4273        solver->setHintParam(OsiDoDualInResolve, true, OsiHintDo) ;
     4274#define PRINT_ANALYZE  0
     4275#if PRINT_ANALYZE>0
     4276        osiclp->getModelPtr()->setLogLevel(1);
     4277        solver->setHintParam(OsiDoReducePrint, false, OsiHintTry);
     4278#endif
     4279        solver->resolve();
     4280        if (iWay==0) {
     4281#if PRINT_ANALYZE>0
     4282          printf("column %d down original %g <= %g <= %g upper now %g - result %s\n",
     4283                 iColumn,solver->getColLower()[iColumn],
     4284                 staticInfo->originalSolution[iColumn],saveBound,
     4285                 newBound,solver->isProvenOptimal() ? "ok" : "infeas");
     4286#endif
     4287          solver->setColUpper(iColumn,saveBound);
     4288        } else {
     4289#if PRINT_ANALYZE>0
     4290          printf("column %d up original %g <= %g <= %g lower now %g - result %s\n",
     4291                 iColumn,saveBound,staticInfo->originalSolution[iColumn],
     4292                 solver->getColUpper()[iColumn],
     4293                 newBound,solver->isProvenOptimal() ? "ok" : "infeas");
     4294#endif
     4295          solver->setColLower(iColumn,saveBound);
     4296        }
     4297        choice->numIters[iWay] = solver->getIterationCount();
     4298        if (solver->isProvenOptimal()) {
     4299          //printf("Way %d - all way %d iterations - column %d\n",
     4300          //     iWay,solver->getIterationCount(),iColumn);
     4301          // can go all way
     4302          choice->movement[iWay] = newBound;
     4303        } else {
     4304          // zero objective
     4305          double offset;
     4306          solver->getDblParam(OsiObjOffset,offset);
     4307          solver->setDblParam(OsiObjOffset, 0.0);
     4308          solver->setObjective(staticInfo->newObjective+numberColumns);
     4309          if (iWay==0) {
     4310            solver->setObjCoeff(iColumn,1.0);
     4311          } else {
     4312            solver->setObjCoeff(iColumn,-1.0);
     4313          }
     4314          solver->setColSolution(staticInfo->originalSolution);
     4315          solver->setWarmStart(staticInfo->ws);
     4316          solver->setHintParam(OsiDoDualInResolve, false, OsiHintDo) ;
     4317          solver->resolve();
     4318          //printf("Way %d - first solve %d iterations, second %d - column %d\n",
     4319          //     iWay,choice->numIters[iWay],solver->getIterationCount(),iColumn);
     4320          choice->movement[iWay] = solver->getColSolution()[iColumn];
     4321          choice->numIters[iWay] += solver->getIterationCount();
     4322#if PRINT_ANALYZE>0
     4323          if (iWay==0) {
     4324            printf("column %d down can get to %g - result %s\n",
     4325                 iColumn,solver->getColSolution()[iColumn],solver->isProvenOptimal() ? "ok" : "infeas");
     4326          } else {
     4327            printf("column %d up can get to %g - result %s\n",
     4328                 iColumn,solver->getColSolution()[iColumn],solver->isProvenOptimal() ? "ok" : "infeas");
     4329          }
     4330#endif
     4331          // reset objective
     4332          solver->setDblParam(OsiObjOffset, offset);
     4333          solver->setObjective(staticInfo->newObjective);
     4334          if (!solver->isProvenOptimal()) {
     4335# ifdef COIN_HAS_CLP
     4336            OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (solver);
     4337            ClpSimplex * simplex = osiclp->getModelPtr();
     4338            double sum = simplex->sumPrimalInfeasibilities();
     4339            sum /= static_cast<double>(simplex->numberPrimalInfeasibilities());
     4340            if (sum>1.0e-3) {
     4341#endif
     4342            choice->modified[0]=1;
     4343            returnStatus=1;
     4344            solver->writeMps("bad","mps");
     4345            abort();
     4346# ifdef COIN_HAS_CLP
     4347            }
     4348#endif
     4349          }
     4350        }
     4351        //solver->setObjCoeff(iColumn,0.0);
     4352      }
     4353    }
     4354  }
     4355  return returnStatus;
     4356}
     4357#ifdef THREADS_IN_ANALYZE
     4358void * cbc_parallelManager(void * stuff)
     4359{
     4360  CoinPthreadStuff * driver = reinterpret_cast<CoinPthreadStuff *>(stuff);
     4361  int whichThread=driver->whichThread();
     4362  CoinThreadInfo * threadInfo = driver->threadInfoPointer(whichThread);
     4363  threadInfo->status=-1;
     4364  int * which = threadInfo->stuff;
     4365  pthread_barrier_wait(driver->barrierPointer());
     4366#if 0
     4367  int status=-1;
     4368  while (status!=100)
     4369    status=timedWait(driver,1000,2);
     4370  pthread_cond_signal(driver->conditionPointer(1));
     4371  pthread_mutex_unlock(driver->mutexPointer(1,whichThread));
     4372#endif
     4373  // so now mutex_ is locked
     4374  int whichLocked=0;
     4375  while (true) {
     4376    pthread_mutex_t * mutexPointer = driver->mutexPointer(whichLocked,whichThread);
     4377    // wait
     4378    //printf("Child waiting for %d - status %d %d %d\n",
     4379    //     whichLocked,lockedX[0],lockedX[1],lockedX[2]);
     4380#ifdef DETAIL_THREAD
     4381    printf("thread %d about to lock mutex %d\n",whichThread,whichLocked);
     4382#endif
     4383    pthread_mutex_lock (mutexPointer);
     4384    whichLocked++;
     4385    if (whichLocked==3)
     4386      whichLocked=0;
     4387    int unLock=whichLocked+1;
     4388    if (unLock==3)
     4389      unLock=0;
     4390    //printf("child pointer %p status %d\n",threadInfo,threadInfo->status);
     4391    assert(threadInfo->status>=0);
     4392    if (threadInfo->status==1000)
     4393      pthread_exit(NULL);
     4394    int type=threadInfo->status;
     4395    int & returnCode=which[0];
     4396    int iPass=which[1];
     4397    //CoinIndexedVector * array;
     4398    //double dummy;
     4399    switch(type) {
     4400      // dummy
     4401    case 0:
     4402      break;
     4403    case 1:
     4404      returnCode=solveAnalyze(threadInfo->extraInfo);
     4405      threadInfo->stuff[3]=0;
     4406      break;
     4407    case 100:
     4408      // initialization
     4409      break;
     4410    }
     4411    threadInfo->status= (type!=1) ? -1 : -2;
     4412#ifdef DETAIL_THREAD
     4413    printf("thread %d about to unlock mutex %d\n",whichThread,unLock);
     4414#endif
     4415    pthread_mutex_unlock (driver->mutexPointer(unLock,whichThread));
     4416  }
     4417}
     4418#endif
    37344419int CbcNode::analyze (CbcModel *model, double * results)
    37354420{
    3736     int i;
    3737     int numberIterationsAllowed = model->numberAnalyzeIterations();
    3738     OsiSolverInterface * solver = model->solver();
    3739     objectiveValue_ = solver->getObjSense() * solver->getObjValue();
    3740     double cutoff = model->getCutoff();
     4421#define COIN_DETAIL
     4422  int i;
     4423  int numberIterationsAllowed = model->numberAnalyzeIterations();
     4424  int numberColumns = model->getNumCols();
     4425  int numberRows = model->getNumRows();
     4426  int numberObjects = model->numberObjects();
     4427  int numberIntegers = model->numberIntegers();
     4428  int numberLookIntegers=0;
     4429  int highestPriority=COIN_INT_MAX;
     4430  int * back = new int[numberColumns];
     4431  const int * integerVariable = model->integerVariable();
     4432  for (i = 0; i < numberIntegers; i++) {
     4433    highestPriority = CoinMin(highestPriority,model->modifiableObject(i)->priority());
     4434  }
     4435  for (i = 0; i < numberColumns; i++)
     4436    back[i] = -1;
     4437  for (i = 0; i < numberIntegers; i++) {
     4438    int iColumn = integerVariable[i];
     4439    back[iColumn] = i;
     4440    if (model->modifiableObject(i)->priority()==highestPriority) {
     4441      numberLookIntegers++;
     4442    } else {
     4443      back[iColumn] = i+numberColumns;
     4444    }
     4445  }
     4446  /*
     4447    0 - just look
     4448    0 (1) bit - use to set priorities
     4449    1 (2) bit - look at bounds on all variables and more iterations
     4450    2 (4) bit - do threaded (if parallelMode()==1 then not repeatable if any fixed)
     4451    3 (8) bit -
     4452    4 (16) bit - do even if m*n>1,000,000
     4453    5 (32) bit - printing time
     4454    6 (64) bit - save mps file
     4455  */
     4456  int solveType;
     4457  char general[200];
     4458  if (numberIterationsAllowed>0) {
     4459    solveType = 0;
     4460  } else {
     4461    solveType = - numberIterationsAllowed;
     4462    if ((solveType&16)==0) {
     4463      double size=numberRows;
     4464      size*=numberLookIntegers;
     4465      if (size>1000000) {
     4466        if ((solveType&32)!=0)
     4467          model->messageHandler()->message(CBC_GENERAL, *model->messagesPointer())
     4468            << "Skipping analyze as problem too large"
     4469            << CoinMessageEol;
     4470        return 0;
     4471      }
     4472    }
     4473    sprintf(general,"Analyze options %d",solveType);
     4474    model->messageHandler()->message(CBC_GENERAL, *model->messagesPointer())
     4475      << general
     4476      << CoinMessageEol;
     4477    if ((solveType&1)!=0)
     4478      model->messageHandler()->message(CBC_GENERAL, *model->messagesPointer())
     4479        << "Using to set priorities (probably bad idea)"
     4480        << CoinMessageEol;
     4481    if ((solveType&2)!=0)
     4482      model->messageHandler()->message(CBC_GENERAL, *model->messagesPointer())
     4483        << "Use more iterations and look at continuous/general integer variables"
     4484        << CoinMessageEol;
     4485    if ((solveType&4)!=0)
     4486      model->messageHandler()->message(CBC_GENERAL, *model->messagesPointer())
     4487        << "Use threads"
     4488        << CoinMessageEol;
     4489    if ((solveType&32)!=0)
     4490      model->messageHandler()->message(CBC_GENERAL, *model->messagesPointer())
     4491        << "32 switches on more printing, (16 bit allows large problems)"
     4492        << CoinMessageEol;
     4493  }
     4494  OsiSolverInterface * solver = model->solver();
     4495  objectiveValue_ = solver->getObjSense() * solver->getObjValue();
     4496  const double * lower = solver->getColLower();
     4497  const double * upper = solver->getColUpper();
     4498  const double * dj = solver->getReducedCost();
     4499  // What results is
     4500  double * newLower = results;
     4501  double * objLower = newLower + numberIntegers;
     4502  double * newUpper = objLower + numberIntegers;
     4503  double * objUpper = newUpper + numberIntegers;
     4504  double * interAction = objUpper + numberIntegers;
     4505  for (i = 0; i < numberIntegers; i++) {
     4506    int iColumn = integerVariable[i];
     4507    newLower[i] = lower[iColumn];
     4508    objLower[i] = -COIN_DBL_MAX;
     4509    newUpper[i] = upper[iColumn];
     4510    objUpper[i] = -COIN_DBL_MAX;
     4511    interAction[i] = 0.0;
     4512  }
     4513  double * objMovement=new double[2*numberIntegers];
     4514  memset(objMovement,0,2*numberIntegers*sizeof(double));
     4515  double * saveUpper = new double[numberColumns];
     4516  double * saveLower = new double[numberColumns];
     4517  // Save solution in case heuristics need good solution later
     4518 
     4519  double * saveSolution = new double[numberColumns];
     4520  memcpy(saveSolution, solver->getColSolution(), numberColumns*sizeof(double));
     4521  model->reserveCurrentSolution(saveSolution);
     4522  for (i = 0; i < numberColumns; i++) {
     4523    saveLower[i] = lower[i];
     4524    saveUpper[i] = upper[i];
     4525  }
     4526  // Get arrays to sort
     4527  double * sort = new double[numberObjects];
     4528  int * whichObject = new int[numberObjects];
     4529  int numberToFix = 0;
     4530  int numberToDo = 0;
     4531  double integerTolerance =
     4532    model->getDblParam(CbcModel::CbcIntegerTolerance);
     4533  // point to useful information
     4534  OsiBranchingInformation usefulInfo = model->usefulInformation();
     4535  // and modify
     4536  usefulInfo.depth_ = depth_;
     4537 
     4538  // compute current state
     4539  int numberObjectInfeasibilities; // just odd ones
     4540  int numberIntegerInfeasibilities;
     4541  model->feasibleSolution(
     4542                          numberIntegerInfeasibilities,
     4543                          numberObjectInfeasibilities);
     4544  if (solveType) {
     4545    if ((solveType&2)==0)
     4546      numberIterationsAllowed=200*numberIntegerInfeasibilities;
     4547    else
     4548      numberIterationsAllowed=COIN_INT_MAX;
     4549  }
     4550  int saveAllowed=numberIterationsAllowed;
     4551# ifdef COIN_HAS_CLP
     4552  OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (solver);
     4553  int saveClpOptions = 0;
     4554  bool fastIterations = (model->specialOptions() & 8) != 0;
     4555  if (osiclp) {
     4556    saveClpOptions = osiclp->specialOptions();
     4557    // for faster hot start
     4558    if (fastIterations)
     4559      osiclp->setSpecialOptions(saveClpOptions | 8192);
     4560    else
     4561      osiclp->setSpecialOptions(saveClpOptions | 2048); // switch off crunch
     4562  }
     4563# else
     4564  bool fastIterations = false ;
     4565# endif
     4566  /*
     4567    Scan for branching objects that indicate infeasibility.
     4568   
     4569    The algorithm is to fill the array with a set of good candidates (by
     4570    infeasibility).
     4571   
     4572  */
     4573  numberToDo = 0;
     4574  for (i = 0; i < numberObjects; i++) {
     4575    OsiObject * object = model->modifiableObject(i);
     4576    CbcSimpleIntegerDynamicPseudoCost * dynamicObject =
     4577      dynamic_cast <CbcSimpleIntegerDynamicPseudoCost *>(object) ;
     4578    if (!dynamicObject)
     4579      continue;
     4580    if (dynamicObject->priority()!=highestPriority)
     4581      continue;
     4582    double infeasibility = object->checkInfeasibility(&usefulInfo);
     4583    int iColumn = dynamicObject->columnNumber();
     4584    if (saveUpper[iColumn] == saveLower[iColumn])
     4585      continue;
     4586    if (infeasibility)
     4587      sort[numberToDo] = -1.0e10 - infeasibility;
     4588    else
     4589      sort[numberToDo] = -fabs(dj[iColumn]);
     4590    whichObject[numberToDo++] = i;
     4591  }
     4592  // Save basis
     4593  CoinWarmStart * ws = solver->getWarmStart();
     4594  int saveLimit;
     4595  solver->getIntParam(OsiMaxNumIterationHotStart, saveLimit);
     4596  int targetIterations = CoinMax(500, numberIterationsAllowed / numberObjects);
     4597  if (saveLimit < targetIterations)
     4598    solver->setIntParam(OsiMaxNumIterationHotStart, targetIterations);
     4599  if ((solveType&2)==0) {
     4600    // Mark hot start
     4601    solver->markHotStart();
     4602  }
     4603  solver->setHintParam(OsiDoDualInResolve, true, OsiHintDo) ;
     4604  // Sort
     4605  CoinSort_2(sort, sort + numberToDo, whichObject);
     4606  double * currentSolution = model->currentSolution();
     4607  double objMin = 1.0e50;
     4608  double objMax = -1.0e50;
     4609  bool needResolve = false;
     4610  int maxChoices=1;
     4611  int currentChoice=0;
     4612  int numberThreads=0;
     4613  bool doAtEnd=false;
     4614  if (model->parallelMode() && (solveType&4)!=0) {
     4615    numberThreads=model->getNumberThreads();
     4616    sprintf(general,"Using %d threads in analysis\n",numberThreads);
     4617    model->messageHandler()->message(CBC_GENERAL, *model->messagesPointer())
     4618      << general
     4619      << CoinMessageEol;
     4620    if (model->parallelMode()==1) {
     4621      maxChoices=numberThreads;
     4622    } else {
     4623      maxChoices = numberToDo;
     4624      if ((solveType&2)!=0)
     4625        maxChoices = numberColumns;
     4626      doAtEnd=true;
     4627    }
     4628  }
     4629  StrongInfo * choices = new StrongInfo[maxChoices];
     4630  StrongStaticInfo staticInfo;
     4631  int numberBundles = CoinMax(1,numberThreads);
     4632  StrongBundle * bundles = new StrongBundle[numberBundles];
     4633  /*
     4634    0 - available - no need to look at results
     4635    1 - not available
     4636    2 - available - need to look at results
     4637  */
     4638#ifndef NUMBER_THREADS
     4639#define NUMBER_THREADS 4
     4640#endif
     4641  int status[NUMBER_THREADS];
     4642  memset(status,0,sizeof(status));
     4643  memset(&staticInfo,0,sizeof(staticInfo));
     4644  staticInfo.solveType = solveType;
     4645  staticInfo.originalSolution=saveSolution;
     4646  staticInfo.back=back;
     4647  staticInfo.ws=ws;
     4648  staticInfo.integerTolerance=integerTolerance;
     4649  double time1 = model->getCurrentSeconds();
     4650#define DO_STEEPEST_SERIAL 1
     4651# ifdef COIN_HAS_CLP
     4652  if (osiclp&&(solveType&2)!=0&&(!numberThreads||DO_STEEPEST_SERIAL)) {
     4653    ClpSimplex * simplex = osiclp->getModelPtr();
     4654    simplex->setLogLevel(0);
     4655    simplex->dual(0,1);
     4656    ClpDualRowPivot * dualRowPivot=simplex->dualRowPivot();
     4657    ClpDualRowSteepest * steep = dynamic_cast<ClpDualRowSteepest *>(dualRowPivot);
     4658    if (steep) {
     4659      staticInfo.dualRowPivot=new ClpDualRowSteepest (*steep);
     4660      staticInfo.dualRowPivot->setMode(1); // full steepest edge
     4661      simplex->spareIntArray_[0]=0;
     4662      simplex->spareIntArray_[1]=numberRows;
     4663      staticInfo.dualRowPivot->saveWeights(simplex,7);
     4664    }
     4665  }
     4666#endif
     4667  for (int i=0;i<numberBundles;i++) {
     4668    memset(bundles+i,0,sizeof(StrongBundle));
     4669    bundles[i].staticInfo=&staticInfo;
     4670  }
     4671#if defined (THREADS_IN_ANALYZE) && defined (COIN_HAS_CLP)
     4672#define USE_STRONG_THREADS
     4673  CoinPthreadStuff threadInfo(numberThreads,cbc_parallelManager);
     4674  int threadNeedsRefreshing[NUMBER_THREADS];
     4675  for (int i=0;i<numberThreads;i++) {
     4676    threadInfo.threadInfo_[i].extraInfo2 = solver->clone();
     4677    threadNeedsRefreshing[i]=0;
     4678  }
     4679# ifdef COIN_HAS_CLP
     4680  int numberSteepThreads=0;
     4681  int step=numberThreads ? (numberRows+numberThreads-1)/numberThreads : 0;
     4682  int first=0;
     4683  for (int i=0;i<numberThreads;i++) {
     4684    if (osiclp&&(solveType&2)!=0&&!DO_STEEPEST_SERIAL) {
     4685      OsiSolverInterface * solver=
     4686        reinterpret_cast<OsiSolverInterface *>(threadInfo.threadInfo_[i].extraInfo2);
     4687      OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (solver);
     4688      ClpSimplex * simplex = osiclp->getModelPtr();
     4689      simplex->setLogLevel(0);
     4690      simplex->dual(0,1);
     4691      ClpDualRowPivot * dualRowPivot=simplex->dualRowPivot();
     4692      ClpDualRowSteepest * steep = dynamic_cast<ClpDualRowSteepest *>(dualRowPivot);
     4693      if (steep) {
     4694        numberSteepThreads=numberThreads;
     4695        ClpDualRowSteepest * dualRowPivot=new ClpDualRowSteepest (*steep);
     4696        dualRowPivot->setMode(1); // full steepest edge
     4697        simplex->spareIntArray_[0]=0;
     4698        simplex->spareIntArray_[1]=numberRows;
     4699        simplex->spareIntArray_[0]=first;
     4700        simplex->spareIntArray_[1]=CoinMin(first+step,numberRows);
     4701        first += step;
     4702        if (i==0)
     4703          staticInfo.dualRowPivot=dualRowPivot;
     4704        choices[i].steepest=dualRowPivot;
     4705        dualRowPivot->saveWeights(simplex,7);
     4706      }
     4707    }
     4708  }
     4709  if (numberSteepThreads&&false) {
     4710    int numberDone=0;
     4711    int iDo=0;
     4712    staticInfo.solveType = 200;
     4713    while (numberDone<numberSteepThreads) {
     4714      int iThread;
     4715      threadInfo.waitParallelTask(1,iThread,iDo<numberToDo);
     4716      int threadStatus = 1+threadInfo.threadInfo_[iThread].status;
     4717      iThread=iThread;
     4718      if (threadStatus==0&&iDo<numberSteepThreads) {
     4719        StrongInfo & choice = choices[iThread];
     4720        StrongBundle & bundle = bundles[iThread];
     4721        bundle.whichChoice=iThread;
     4722        memset(&choice,0,sizeof(StrongInfo));
     4723        iDo++; //started this one
     4724        bundle.choice=&choice;
     4725        bundle.solver = solver;
     4726        bundle.solver=reinterpret_cast<OsiSolverInterface *>(threadInfo.threadInfo_[iThread].extraInfo2);
     4727        threadStatus=0;
     4728#ifdef DETAIL_THREAD
     4729        printf("Starting steep task on thread %d\n",
     4730               choice.iThread);
     4731#endif
     4732        threadInfo.startParallelTask(1,iThread,&bundle);
     4733      }
     4734      if (!threadStatus) {
     4735#ifdef _MSC_VER
     4736        Sleep(1);
     4737#else
     4738        usleep(1000);
     4739#endif
     4740        continue;
     4741      }
     4742      if (threadStatus) {
     4743        numberDone++;
     4744        // say available
     4745        threadInfo.sayIdle(iThread);
     4746      }
     4747      staticInfo.solveType = solveType;
     4748    }
     4749    OsiSolverInterface * solver0=
     4750      reinterpret_cast<OsiSolverInterface *>(threadInfo.threadInfo_[0].extraInfo2);
     4751    CoinIndexedVector * savedWeights0 = staticInfo.dualRowPivot->savedWeights();
     4752    int * index0 = savedWeights0->getIndices();
     4753    double * weight0 = savedWeights0->denseVector();
     4754    int step=(numberRows+numberSteepThreads-1)/numberSteepThreads;
     4755    int first=step;
     4756    //memset(weight0+first,0,(numberRows-first)*sizeof(double));
     4757    for (int i=1;i<numberSteepThreads;i++) {
     4758      int n=CoinMin(step,numberRows-first);
     4759      CoinIndexedVector * savedWeights = choices[i].steepest->savedWeights();
     4760      int * index = savedWeights->getIndices();
     4761      double * weight = savedWeights->denseVector();
     4762      memcpy(index0+first,index+first,n*sizeof(int));
     4763      memcpy(weight0+first,weight+first,n*sizeof(double));
     4764      first += step;
     4765      delete choices[i].steepest;
     4766      choices[i].steepest=NULL;
     4767    }
     4768    //for (int j=0;j<numberRows;j++)
     4769    //weight0[j]=1.0;
     4770  }
     4771#endif
     4772#endif
     4773  double bestSolutionValue = model->getMinimizationObjValue();
     4774  double * bestSolution = NULL;
     4775  double cutoff;
     4776  solver->getDblParam(OsiDualObjectiveLimit,cutoff);
     4777  double maxMovement = 2.0*(cutoff-objectiveValue_)+1.0e-6;
     4778  /*
     4779    Now calculate the cost forcing the variable up and down.
     4780  */
     4781  int iDo=0;
     4782  int iDone=-1;
     4783  int numberDone=0;
     4784  int iThread=0;
     4785  int threadStatus=0;
     4786  int whenPrint = (numberToDo+9)/10;
     4787  while (numberDone<numberToDo) {
     4788    if ((solveType&32)!=0&&numberDone==whenPrint) {
     4789      whenPrint += (numberToDo+9)/10;
     4790      sprintf(general,"%d variables looked at - %d changed by initial strong branching (%.2f seconds - %d iterations)",numberDone,numberToFix,model->getCurrentSeconds()-time1,saveAllowed-numberIterationsAllowed);
     4791      model->messageHandler()->message(CBC_GENERAL, *model->messagesPointer())
     4792        << general
     4793        << CoinMessageEol;
     4794    }
     4795#ifdef USE_STRONG_THREADS
     4796    if (numberThreads) {
     4797      threadInfo.waitParallelTask(1,iThread,iDo<numberToDo);
     4798      threadStatus = 1+threadInfo.threadInfo_[iThread].status;
     4799      if (!doAtEnd)
     4800        currentChoice=iThread;
     4801      if (threadNeedsRefreshing[iThread]) {
     4802        OsiSolverInterface * solver=
     4803          reinterpret_cast<OsiSolverInterface *>(threadInfo.threadInfo_[iThread].extraInfo2);
     4804        if ((threadNeedsRefreshing[iThread]&1)!=0)
     4805          solver->setColLower(saveLower);
     4806        if ((threadNeedsRefreshing[iThread]&2)!=0)
     4807          solver->setColUpper(saveUpper);
     4808        threadNeedsRefreshing[iThread]=0;
     4809      }
     4810    }
     4811#endif
     4812    if (threadStatus==0&&iDo<numberToDo) {
     4813      StrongInfo & choice = choices[currentChoice];
     4814      StrongBundle & bundle = bundles[iThread];
     4815      bundle.whichChoice=currentChoice;
     4816      memset(&choice,0,sizeof(StrongInfo));
     4817      int iObject = whichObject[iDo];
     4818      iDo++; //started this one
     4819      OsiObject * object = model->modifiableObject(iObject);
     4820      CbcSimpleIntegerDynamicPseudoCost * dynamicObject =
     4821        dynamic_cast <CbcSimpleIntegerDynamicPseudoCost *>(object) ;
     4822      int iColumn = dynamicObject->columnNumber();
     4823      double value = currentSolution[iColumn];
     4824      double nearest = floor(value + 0.5);
     4825      double lowerValue = floor(value);
     4826      bool satisfied = false;
     4827      if (fabs(value - nearest) <= integerTolerance ||
     4828          value < saveLower[iColumn] || value > saveUpper[iColumn]) {
     4829        satisfied = true;
     4830        if (nearest < saveUpper[iColumn]) {
     4831          lowerValue = nearest;
     4832        } else {
     4833          lowerValue = nearest - 1;
     4834        }
     4835      }
     4836      double upperValue = lowerValue + 1.0;
     4837      // Save which object it was
     4838      choice.columnNumber = iColumn;
     4839      choice.initialValue=value;
     4840      choice.upLowerBound=upperValue;
     4841      choice.downUpperBound=lowerValue;
     4842      choice.numIntInfeas[1] = numberUnsatisfied_;
     4843      choice.numIntInfeas[0] = numberUnsatisfied_;
     4844      choice.movement[0] = 0.0;
     4845      choice.movement[1] = 0.0;
     4846      choice.numIters[0] = 0;
     4847      choice.numIters[1] = 0;
     4848      if (fabs(value - lowerValue) <= integerTolerance)
     4849        choice.numIters[0]=-1; // mark as not done
     4850      if (fabs(value - upperValue) <= integerTolerance)
     4851        choice.numIters[1]=-1; // mark as not done
     4852      bundle.choice=&choice;
     4853      bundle.solver = solver;
     4854#ifdef USE_STRONG_THREADS
     4855      if (numberThreads) {
     4856        bundle.solver=reinterpret_cast<OsiSolverInterface *>(threadInfo.threadInfo_[iThread].extraInfo2);
     4857        threadStatus=0;
     4858#ifdef DETAIL_THREAD
     4859        printf("Starting task for column %d on thread %d\n",
     4860               choice.columnNumber,iThread);
     4861#endif
     4862        threadInfo.startParallelTask(1,iThread,&bundle);
     4863      } else {
     4864#endif
     4865        threadStatus=2;
     4866        solveAnalyze(&bundle);
     4867#ifdef USE_STRONG_THREADS
     4868      }
     4869#endif
     4870    }
     4871    if (!threadStatus) {
     4872#ifdef _MSC_VER
     4873        Sleep(1);
     4874#else
     4875        usleep(1000);
     4876#endif
     4877      continue;
     4878    }
     4879    if (threadStatus) {
     4880      int whichChoice = bundles[iThread].whichChoice; 
     4881      StrongInfo & choice = choices[whichChoice];
     4882      int iColumn=choice.columnNumber;
     4883      if (choice.integerSolution) {
     4884        double * foundSolution = choice.integerSolution;
     4885        solver->setColSolution(foundSolution);
     4886        // See if integer solution
     4887        int numberInfeas=0;
     4888        int numberOddInfeas=0;
     4889        if (model->feasibleSolution(numberInfeas,numberOddInfeas)
     4890            && model->problemFeasibility()->feasible(model, -1) >= 0) {
     4891          double newObjectiveValue;
     4892          solver->getDblParam(OsiObjOffset,newObjectiveValue);
     4893          newObjectiveValue=-newObjectiveValue;
     4894          const double * cost = solver->getObjCoefficients();
     4895          for ( int i = 0 ; i < numberColumns ; i++ )
     4896            newObjectiveValue += cost[i] * foundSolution[i];
     4897          if (newObjectiveValue<bestSolutionValue) {
     4898            if (doAtEnd) {
     4899              if (!bestSolution)
     4900                bestSolution = CoinCopyOfArray(foundSolution,numberColumns);
     4901              else
     4902                memcpy(bestSolution,foundSolution,numberColumns*sizeof(double));
     4903              bestSolutionValue=newObjectiveValue;
     4904            } else {
     4905              model->setBestSolution(CBC_STRONGSOL,
     4906                                     newObjectiveValue,
     4907                                     foundSolution) ;
     4908              model->setLastHeuristic(NULL);
     4909              model->incrementUsed(solver->getColSolution());
     4910              bestSolutionValue = model->getMinimizationObjValue();
     4911            }
     4912          }
     4913        }
     4914        delete [] foundSolution;
     4915      }
     4916      for (int iWay=0;iWay<2;iWay++) {
     4917        numberIterationsAllowed -= choice.numIters[iWay];
     4918        choice.movement[iWay] -= objectiveValue_;
     4919      }
     4920      // If objective goes above certain amount we can set bound
     4921      int jInt = back[iColumn];
     4922      OsiObject * object = model->modifiableObject(jInt);
     4923      CbcSimpleIntegerDynamicPseudoCost * dynamicObject =
     4924        dynamic_cast <CbcSimpleIntegerDynamicPseudoCost *>(object) ;
     4925      if (dynamicObject) {
     4926        if (choice.numIters[0]>=0) {
     4927          dynamicObject->addToSumDownCost(CoinMin(choice.movement[0],maxMovement));
     4928          dynamicObject->addToSumDownChange(choice.initialValue-choice.downUpperBound);
     4929        }
     4930        if (choice.numIters[1]>=0) {
     4931          dynamicObject->addToSumUpCost(CoinMin(choice.movement[1],maxMovement));
     4932          dynamicObject->addToSumUpChange(choice.upLowerBound-choice.initialValue);
     4933        }
     4934      }
     4935      newLower[jInt] = choice.upLowerBound;
     4936      if (choice.finished[0])
     4937        objLower[jInt] = choice.movement[0] + objectiveValue_;
     4938      else
     4939        objLower[jInt] = objectiveValue_;
     4940      newUpper[jInt] = choice.downUpperBound;
     4941      if (choice.finished[1])
     4942        objUpper[jInt] = choice.movement[1] + objectiveValue_;
     4943      else
     4944        objUpper[jInt] = objectiveValue_;
     4945      objMin = CoinMin(CoinMin(objLower[jInt], objUpper[jInt]), objMin);
     4946      objMovement[2*jInt]=choice.movement[0];
     4947      objMovement[2*jInt+1]=choice.movement[1];
     4948      double sumModified = choice.modified[0] + choice.modified[1] +
     4949        1.0e-15*(choice.sumModified[0]+choice.sumModified[1]);
     4950      if (choice.numIters[0]>=0&&choice.numIters[1]>=0)
     4951        sumModified *= 0.6;
     4952      interAction[jInt] = sumModified;
     4953      /*
     4954        End of evaluation for this candidate variable. Possibilities are:
     4955        * Both sides below cutoff; this variable is a candidate for branching.
     4956        * Both sides infeasible or above the objective cutoff: no further action
     4957        here. Break from the evaluation loop and assume the node will be purged
     4958        by the caller.
     4959        * One side below cutoff: Install the branch (i.e., fix the variable). Break
     4960        from the evaluation loop and assume the node will be reoptimised by the
     4961        caller.
     4962      */
     4963      threadStatus=0;
     4964      currentChoice++;
     4965      numberDone++;
     4966#ifdef USE_STRONG_THREADS
     4967      // say available
     4968      if (numberThreads) {
     4969        threadInfo.sayIdle(iThread);
     4970      }
     4971#endif
     4972      if (doAtEnd)
     4973        continue;
     4974      if (choice.movement[1] < 1.0e100) {
     4975        if (choice.movement[0] < 1.0e100) {
     4976          objMax = CoinMax(CoinMax(objLower[jInt], objUpper[jInt]), objMax);
     4977          // In case solution coming in was odd
     4978          choice.movement[1] = CoinMax(0.0, choice.movement[1]);
     4979          choice.movement[0] = CoinMax(0.0, choice.movement[0]);
     4980          // feasible -
     4981          model->messageHandler()->message(CBC_STRONG, *model->messagesPointer())
     4982            << iColumn << iColumn
     4983            << choice.movement[0] << choice.numIntInfeas[0]
     4984            << choice.movement[1] << choice.numIntInfeas[1]
     4985            << choice.initialValue
     4986            << CoinMessageEol;
     4987        } else {
     4988          // up feasible, down infeasible
     4989          needResolve = true;
     4990          numberToFix++;
     4991          saveLower[iColumn] = choice.upLowerBound;
     4992          solver->setColLower(iColumn, choice.upLowerBound);
     4993#ifdef USE_STRONG_THREADS
     4994          for (int i=0;i<numberThreads;i++) {
     4995            threadNeedsRefreshing[i] |= 1;
     4996          }
     4997#endif
     4998        }
     4999      } else {
     5000        if (choice.movement[0] < 1.0e100) {
     5001          // down feasible, up infeasible
     5002          needResolve = true;
     5003          numberToFix++;
     5004          saveUpper[iColumn] = choice.downUpperBound;
     5005          solver->setColUpper(iColumn, choice.downUpperBound);
     5006#ifdef USE_STRONG_THREADS
     5007          for (int i=0;i<numberThreads;i++) {
     5008            threadNeedsRefreshing[i] |= 2;
     5009          }
     5010#endif
     5011        } else {
     5012          // neither side feasible
     5013          COIN_DETAIL_PRINT(printf("Both infeasible for choice %d sequence %d\n", i,
     5014                                   model->object(choice.objectNumber)->columnNumber()));
     5015          //solver->writeMps("bad");
     5016          numberToFix = -1;
     5017          break;
     5018        }
     5019      }
     5020      if (numberIterationsAllowed <= 0)
     5021        break;
     5022      if (currentChoice==maxChoices)
     5023        currentChoice=0;
     5024    }
     5025    //printf("obj %d, col %d, down %g up %g value %g\n",iObject,iColumn,
     5026    //     choice.downMovement,choice.upMovement,value);
     5027  }
     5028  // Do at end if deterministic
     5029  if (doAtEnd) {
     5030    if (bestSolution) {
     5031      model->setBestSolution(CBC_STRONGSOL,
     5032                             bestSolutionValue,
     5033                             bestSolution) ;
     5034      model->setLastHeuristic(NULL);
     5035      model->incrementUsed(solver->getColSolution());
     5036      delete [] bestSolution;
     5037    }
     5038    for (int iDo = 0; iDo < numberLookIntegers; iDo++) {
     5039      StrongInfo & choice = choices[iDo];
     5040      int iColumn = choice.columnNumber;
     5041      int iObject = iColumn;
     5042      int jInt = back[iColumn];
     5043      double value = choice.initialValue;
     5044      double lowerValue = choice.downUpperBound;
     5045      double upperValue = choice.upLowerBound;
     5046      if (choice.movement[1] < 1.0e100) {
     5047        if (choice.movement[0] < 1.0e100) {
     5048          objMax = CoinMax(CoinMax(objLower[jInt], objUpper[jInt]), objMax);
     5049          // In case solution coming in was odd
     5050          choice.movement[1] = CoinMax(0.0, choice.movement[1]);
     5051          choice.movement[0] = CoinMax(0.0, choice.movement[0]);
     5052          // feasible -
     5053          model->messageHandler()->message(CBC_STRONG, *model->messagesPointer())
     5054            << iObject << iColumn
     5055            << choice.movement[0] << choice.numIntInfeas[0]
     5056            << choice.movement[1] << choice.numIntInfeas[1]
     5057            << value
     5058            << CoinMessageEol;
     5059        } else {
     5060          // up feasible, down infeasible
     5061          numberToFix++;
     5062          saveLower[iColumn] = upperValue;
     5063          solver->setColLower(iColumn, upperValue);
     5064        }
     5065      } else {
     5066        if (choice.movement[0] < 1.0e100) {
     5067          // down feasible, up infeasible
     5068          needResolve = true;
     5069          numberToFix++;
     5070          saveUpper[iColumn] = lowerValue;
     5071          solver->setColUpper(iColumn, lowerValue);
     5072        } else {
     5073          // neither side feasible
     5074          COIN_DETAIL_PRINT(printf("Both infeasible for choice %d sequence %d\n", i,
     5075                                   model->object(choice.objectNumber)->columnNumber()));
     5076          //solver->writeMps("bad");
     5077          numberToFix = -1;
     5078          break;
     5079        }
     5080      }
     5081    }
     5082  }
     5083  if (false) {
    37415084    const double * lower = solver->getColLower();
    37425085    const double * upper = solver->getColUpper();
    3743     const double * dj = solver->getReducedCost();
    3744     int numberObjects = model->numberObjects();
    3745     int numberColumns = model->getNumCols();
    3746     // Initialize arrays
    3747     int numberIntegers = model->numberIntegers();
    3748     int * back = new int[numberColumns];
    3749     const int * integerVariable = model->integerVariable();
    3750     for (i = 0; i < numberColumns; i++)
    3751         back[i] = -1;
    3752     // What results is
    3753     double * newLower = results;
    3754     double * objLower = newLower + numberIntegers;
    3755     double * newUpper = objLower + numberIntegers;
    3756     double * objUpper = newUpper + numberIntegers;
    3757     for (i = 0; i < numberIntegers; i++) {
    3758         int iColumn = integerVariable[i];
    3759         back[iColumn] = i;
    3760         newLower[i] = 0.0;
    3761         objLower[i] = -COIN_DBL_MAX;
    3762         newUpper[i] = 0.0;
    3763         objUpper[i] = -COIN_DBL_MAX;
    3764     }
    3765     double * saveUpper = new double[numberColumns];
    3766     double * saveLower = new double[numberColumns];
    3767     // Save solution in case heuristics need good solution later
    3768 
    3769     double * saveSolution = new double[numberColumns];
    3770     memcpy(saveSolution, solver->getColSolution(), numberColumns*sizeof(double));
    3771     model->reserveCurrentSolution(saveSolution);
    3772     for (i = 0; i < numberColumns; i++) {
    3773         saveLower[i] = lower[i];
    3774         saveUpper[i] = upper[i];
    3775     }
    3776     // Get arrays to sort
    3777     double * sort = new double[numberObjects];
    3778     int * whichObject = new int[numberObjects];
    3779     int numberToFix = 0;
    3780     int numberToDo = 0;
    3781     double integerTolerance =
    3782         model->getDblParam(CbcModel::CbcIntegerTolerance);
    3783     // point to useful information
    3784     OsiBranchingInformation usefulInfo = model->usefulInformation();
    3785     // and modify
    3786     usefulInfo.depth_ = depth_;
    3787 
    3788     // compute current state
    3789     int numberObjectInfeasibilities; // just odd ones
    3790     int numberIntegerInfeasibilities;
    3791     model->feasibleSolution(
    3792         numberIntegerInfeasibilities,
    3793         numberObjectInfeasibilities);
    3794 # ifdef COIN_HAS_CLP
    3795     OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (solver);
    3796     int saveClpOptions = 0;
    3797     bool fastIterations = (model->specialOptions() & 8) != 0;
    3798     if (osiclp && fastIterations) {
    3799         // for faster hot start
    3800         saveClpOptions = osiclp->specialOptions();
    3801         osiclp->setSpecialOptions(saveClpOptions | 8192);
    3802     }
    3803 # else
    3804     bool fastIterations = false ;
    3805 # endif
    3806     /*
    3807       Scan for branching objects that indicate infeasibility. Choose candidates
    3808       using priority as the first criteria, then integer infeasibility.
    3809 
    3810       The algorithm is to fill the array with a set of good candidates (by
    3811       infeasibility) with priority bestPriority.  Finding a candidate with
    3812       priority better (less) than bestPriority flushes the choice array. (This
    3813       serves as initialization when the first candidate is found.)
    3814 
    3815     */
    3816     numberToDo = 0;
    3817     for (i = 0; i < numberObjects; i++) {
    3818         OsiObject * object = model->modifiableObject(i);
    3819         CbcSimpleIntegerDynamicPseudoCost * dynamicObject =
    3820             dynamic_cast <CbcSimpleIntegerDynamicPseudoCost *>(object) ;
    3821         if (!dynamicObject)
    3822             continue;
    3823         double infeasibility = object->checkInfeasibility(&usefulInfo);
    3824         int iColumn = dynamicObject->columnNumber();
    3825         if (saveUpper[iColumn] == saveLower[iColumn])
    3826             continue;
    3827         if (infeasibility)
    3828             sort[numberToDo] = -1.0e10 - infeasibility;
    3829         else
    3830             sort[numberToDo] = -fabs(dj[iColumn]);
    3831         whichObject[numberToDo++] = i;
    3832     }
    3833     // Save basis
    3834     CoinWarmStart * ws = solver->getWarmStart();
    3835     int saveLimit;
    3836     solver->getIntParam(OsiMaxNumIterationHotStart, saveLimit);
    3837     int targetIterations = CoinMax(500, numberIterationsAllowed / numberObjects);
    3838     if (saveLimit < targetIterations)
    3839         solver->setIntParam(OsiMaxNumIterationHotStart, targetIterations);
    3840     // Mark hot start
    3841     solver->markHotStart();
    3842     // Sort
    3843     CoinSort_2(sort, sort + numberToDo, whichObject);
    3844     double * currentSolution = model->currentSolution();
    3845     double objMin = 1.0e50;
    3846     double objMax = -1.0e50;
    3847     bool needResolve = false;
    3848     /*
    3849       Now calculate the cost forcing the variable up and down.
    3850     */
    3851     int iDo;
    3852     for (iDo = 0; iDo < numberToDo; iDo++) {
    3853         CbcStrongInfo choice;
    3854         int iObject = whichObject[iDo];
    3855         OsiObject * object = model->modifiableObject(iObject);
    3856         CbcSimpleIntegerDynamicPseudoCost * dynamicObject =
    3857             dynamic_cast <CbcSimpleIntegerDynamicPseudoCost *>(object) ;
    3858         if (!dynamicObject)
    3859             continue;
    3860         int iColumn = dynamicObject->columnNumber();
    3861         int preferredWay;
    3862         /*
    3863           Update the information held in the object.
    3864         */
    3865         object->infeasibility(&usefulInfo, preferredWay);
    3866         double value = currentSolution[iColumn];
    3867         double nearest = floor(value + 0.5);
    3868         double lowerValue = floor(value);
    3869         bool satisfied = false;
    3870         if (fabs(value - nearest) <= integerTolerance || value < saveLower[iColumn] || value > saveUpper[iColumn]) {
    3871             satisfied = true;
    3872             double newValue;
    3873             if (nearest < saveUpper[iColumn]) {
    3874                 newValue = nearest + 1.0001 * integerTolerance;
    3875                 lowerValue = nearest;
    3876             } else {
    3877                 newValue = nearest - 1.0001 * integerTolerance;
    3878                 lowerValue = nearest - 1;
    3879             }
    3880             currentSolution[iColumn] = newValue;
    3881         }
    3882         double upperValue = lowerValue + 1.0;
    3883         //CbcSimpleInteger * obj =
    3884         //dynamic_cast <CbcSimpleInteger *>(object) ;
    3885         //if (obj) {
    3886         //choice.possibleBranch=obj->createCbcBranch(solver,&usefulInfo,preferredWay);
    3887         //} else {
    3888         CbcObject * obj =
    3889             dynamic_cast <CbcObject *>(object) ;
    3890         assert (obj);
    3891         choice.possibleBranch = obj->createCbcBranch(solver, &usefulInfo, preferredWay);
    3892         //}
    3893         currentSolution[iColumn] = value;
    3894         // Save which object it was
    3895         choice.objectNumber = iObject;
    3896         choice.numIntInfeasUp = numberUnsatisfied_;
    3897         choice.numIntInfeasDown = numberUnsatisfied_;
    3898         choice.downMovement = 0.0;
    3899         choice.upMovement = 0.0;
    3900         choice.numItersDown = 0;
    3901         choice.numItersUp = 0;
    3902         choice.fix = 0; // say not fixed
    3903         double objectiveChange ;
    3904         double newObjectiveValue = 1.0e100;
    3905         int j;
    3906         // status is 0 finished, 1 infeasible and other
    3907         int iStatus;
    3908         /*
    3909           Try the down direction first. (Specify the initial branching alternative as
    3910           down with a call to way(-1). Each subsequent call to branch() performs the
    3911           specified branch and advances the branch object state to the next branch
    3912           alternative.)
    3913         */
    3914         choice.possibleBranch->way(-1) ;
    3915         choice.possibleBranch->branch() ;
    3916         if (fabs(value - lowerValue) > integerTolerance) {
    3917             solver->solveFromHotStart() ;
    3918             /*
    3919               We now have an estimate of objective degradation that we can use for strong
    3920               branching. If we're over the cutoff, the variable is monotone up.
    3921               If we actually made it to optimality, check for a solution, and if we have
    3922               a good one, call setBestSolution to process it. Note that this may reduce the
    3923               cutoff, so we check again to see if we can declare this variable monotone.
    3924             */
    3925             if (solver->isProvenOptimal())
    3926                 iStatus = 0; // optimal
    3927             else if (solver->isIterationLimitReached()
    3928                      && !solver->isDualObjectiveLimitReached())
    3929                 iStatus = 2; // unknown
    3930             else
    3931                 iStatus = 1; // infeasible
    3932             newObjectiveValue = solver->getObjSense() * solver->getObjValue();
    3933             choice.numItersDown = solver->getIterationCount();
    3934             numberIterationsAllowed -= choice.numItersDown;
    3935             objectiveChange = newObjectiveValue  - objectiveValue_;
    3936             if (!iStatus) {
    3937                 choice.finishedDown = true ;
    3938                 if (newObjectiveValue >= cutoff) {
    3939                     objectiveChange = 1.0e100; // say infeasible
    3940                 } else {
    3941                     // See if integer solution
    3942                     if (model->feasibleSolution(choice.numIntInfeasDown,
    3943                                                 choice.numObjInfeasDown)
    3944                             && model->problemFeasibility()->feasible(model, -1) >= 0) {
    3945                         model->setBestSolution(CBC_STRONGSOL,
    3946                                                newObjectiveValue,
    3947                                                solver->getColSolution()) ;
    3948                         model->setLastHeuristic(NULL);
    3949                         model->incrementUsed(solver->getColSolution());
    3950                         cutoff = model->getCutoff();
    3951                         if (newObjectiveValue >= cutoff)        //  *new* cutoff
    3952                             objectiveChange = 1.0e100 ;
    3953                     }
    3954                 }
    3955             } else if (iStatus == 1) {
    3956                 objectiveChange = 1.0e100 ;
    3957             } else {
    3958                 // Can't say much as we did not finish
    3959                 choice.finishedDown = false ;
    3960             }
    3961             choice.downMovement = objectiveChange ;
    3962         }
    3963         // restore bounds
    3964         for ( j = 0; j < numberColumns; j++) {
    3965             if (saveLower[j] != lower[j])
    3966                 solver->setColLower(j, saveLower[j]);
    3967             if (saveUpper[j] != upper[j])
    3968                 solver->setColUpper(j, saveUpper[j]);
    3969         }
    3970         // repeat the whole exercise, forcing the variable up
    3971         choice.possibleBranch->branch();
    3972         if (fabs(value - upperValue) > integerTolerance) {
    3973             solver->solveFromHotStart() ;
    3974             /*
    3975               We now have an estimate of objective degradation that we can use for strong
    3976               branching. If we're over the cutoff, the variable is monotone up.
    3977               If we actually made it to optimality, check for a solution, and if we have
    3978               a good one, call setBestSolution to process it. Note that this may reduce the
    3979               cutoff, so we check again to see if we can declare this variable monotone.
    3980             */
    3981             if (solver->isProvenOptimal())
    3982                 iStatus = 0; // optimal
    3983             else if (solver->isIterationLimitReached()
    3984                      && !solver->isDualObjectiveLimitReached())
    3985                 iStatus = 2; // unknown
    3986             else
    3987                 iStatus = 1; // infeasible
    3988             newObjectiveValue = solver->getObjSense() * solver->getObjValue();
    3989             choice.numItersUp = solver->getIterationCount();
    3990             numberIterationsAllowed -= choice.numItersUp;
    3991             objectiveChange = newObjectiveValue  - objectiveValue_;
    3992             if (!iStatus) {
    3993                 choice.finishedUp = true ;
    3994                 if (newObjectiveValue >= cutoff) {
    3995                     objectiveChange = 1.0e100; // say infeasible
    3996                 } else {
    3997                     // See if integer solution
    3998                     if (model->feasibleSolution(choice.numIntInfeasUp,
    3999                                                 choice.numObjInfeasUp)
    4000                             && model->problemFeasibility()->feasible(model, -1) >= 0) {
    4001                         model->setBestSolution(CBC_STRONGSOL,
    4002                                                newObjectiveValue,
    4003                                                solver->getColSolution()) ;
    4004                         model->setLastHeuristic(NULL);
    4005                         model->incrementUsed(solver->getColSolution());
    4006                         cutoff = model->getCutoff();
    4007                         if (newObjectiveValue >= cutoff)        //  *new* cutoff
    4008                             objectiveChange = 1.0e100 ;
    4009                     }
    4010                 }
    4011             } else if (iStatus == 1) {
    4012                 objectiveChange = 1.0e100 ;
    4013             } else {
    4014                 // Can't say much as we did not finish
    4015                 choice.finishedUp = false ;
    4016             }
    4017             choice.upMovement = objectiveChange ;
    4018 
    4019             // restore bounds
    4020             for ( j = 0; j < numberColumns; j++) {
    4021                 if (saveLower[j] != lower[j])
    4022                     solver->setColLower(j, saveLower[j]);
    4023                 if (saveUpper[j] != upper[j])
    4024                     solver->setColUpper(j, saveUpper[j]);
    4025             }
    4026         }
    4027         // If objective goes above certain amount we can set bound
    4028         int jInt = back[iColumn];
    4029         newLower[jInt] = upperValue;
    4030         if (choice.finishedDown)
    4031             objLower[jInt] = choice.downMovement + objectiveValue_;
    4032         else
    4033             objLower[jInt] = objectiveValue_;
    4034         newUpper[jInt] = lowerValue;
    4035         if (choice.finishedUp)
    4036             objUpper[jInt] = choice.upMovement + objectiveValue_;
    4037         else
    4038             objUpper[jInt] = objectiveValue_;
    4039         objMin = CoinMin(CoinMin(objLower[jInt], objUpper[jInt]), objMin);
    4040         /*
    4041           End of evaluation for this candidate variable. Possibilities are:
    4042           * Both sides below cutoff; this variable is a candidate for branching.
    4043           * Both sides infeasible or above the objective cutoff: no further action
    4044           here. Break from the evaluation loop and assume the node will be purged
    4045           by the caller.
    4046           * One side below cutoff: Install the branch (i.e., fix the variable). Break
    4047           from the evaluation loop and assume the node will be reoptimised by the
    4048           caller.
    4049         */
    4050         if (choice.upMovement < 1.0e100) {
    4051             if (choice.downMovement < 1.0e100) {
    4052                 objMax = CoinMax(CoinMax(objLower[jInt], objUpper[jInt]), objMax);
    4053                 // In case solution coming in was odd
    4054                 choice.upMovement = CoinMax(0.0, choice.upMovement);
    4055                 choice.downMovement = CoinMax(0.0, choice.downMovement);
    4056                 // feasible -
    4057                 model->messageHandler()->message(CBC_STRONG, *model->messagesPointer())
    4058                 << iObject << iColumn
    4059                 << choice.downMovement << choice.numIntInfeasDown
    4060                 << choice.upMovement << choice.numIntInfeasUp
    4061                 << value
    4062                 << CoinMessageEol;
    4063             } else {
    4064                 // up feasible, down infeasible
    4065                 if (!satisfied)
    4066                     needResolve = true;
    4067                 choice.fix = 1;
    4068                 numberToFix++;
    4069                 saveLower[iColumn] = upperValue;
    4070                 solver->setColLower(iColumn, upperValue);
    4071             }
    4072         } else {
    4073             if (choice.downMovement < 1.0e100) {
    4074                 // down feasible, up infeasible
    4075                 if (!satisfied)
    4076                     needResolve = true;
    4077                 choice.fix = -1;
    4078                 numberToFix++;
    4079                 saveUpper[iColumn] = lowerValue;
    4080                 solver->setColUpper(iColumn, lowerValue);
    4081             } else {
    4082                 // neither side feasible
    4083                 COIN_DETAIL_PRINT(printf("Both infeasible for choice %d sequence %d\n", i,
    4084                                          model->object(choice.objectNumber)->columnNumber()));
    4085                 delete ws;
    4086                 ws = NULL;
    4087                 //solver->writeMps("bad");
    4088                 numberToFix = -1;
    4089                 delete choice.possibleBranch;
    4090                 choice.possibleBranch = NULL;
    4091                 break;
    4092             }
    4093         }
    4094         delete choice.possibleBranch;
    4095         if (numberIterationsAllowed <= 0)
    4096             break;
    4097         //printf("obj %d, col %d, down %g up %g value %g\n",iObject,iColumn,
    4098         //     choice.downMovement,choice.upMovement,value);
    4099     }
    4100     COIN_DETAIL_PRINT(printf("Best possible solution %g, can fix more if solution of %g found - looked at %d variables in %d iterations\n",
    4101                              objMin, objMax, iDo, model->numberAnalyzeIterations() - numberIterationsAllowed));
    4102     model->setNumberAnalyzeIterations(numberIterationsAllowed);
     5086    for (int i=0;i<numberColumns;i++) {
     5087      if (lower[i]!=saveLower[i]||upper[i]!=saveUpper[i]) {
     5088        printf("%d changed- saved %g,%g now %g,%g\n",i,saveLower[i],saveUpper[i],
     5089               lower[i],upper[i]);
     5090      }
     5091    }
     5092  }
     5093  COIN_DETAIL_PRINT(printf("Best possible solution %g, can fix more if solution of %g found - looked at %d variables in %d iterations\n",
     5094                           objMin, objMax, iDo, model->numberAnalyzeIterations() - numberIterationsAllowed));
     5095  model->setNumberAnalyzeIterations(numberIterationsAllowed);
     5096  if (numberToFix>0) {
     5097    sprintf(general,"%d variable bounds modified by initial strong branching (%.2f seconds - %d iterations)",numberToFix,model->getCurrentSeconds()-time1,saveAllowed-numberIterationsAllowed);
     5098  } else if (numberToFix<0) {
     5099    sprintf(general,"initial strong branching found to be infeasible (%.2f seconds - %d iterations)",model->getCurrentSeconds()-time1,saveAllowed-numberIterationsAllowed);
     5100  } else if ((solveType&32)!=0) {
     5101    sprintf(general,"No variables fixed by initial strong branching (%.2f seconds - %d iterations)",model->getCurrentSeconds()-time1,saveAllowed-numberIterationsAllowed);
     5102  } else {
     5103    general[0]='\0';
     5104  }
     5105  if (general[0]!='\0')
     5106    model->messageHandler()->message(CBC_GENERAL, *model->messagesPointer())
     5107      << general
     5108      << CoinMessageEol;
     5109  double smallestEffect=COIN_DBL_MAX;
     5110  double largestEffect=0.0;
     5111  for (i = 0; i < numberIntegers; i++) {
     5112    int iColumn=integerVariable[i];
     5113    if (back[iColumn]>=numberColumns)
     5114      continue;
     5115    smallestEffect = CoinMin(smallestEffect,interAction[i]);
     5116    largestEffect = CoinMax(largestEffect,interAction[i]);
     5117  }
     5118  double groupValue[11];
     5119  int groupCounts[11]={0,0,0,0,0,0,0,0,0,0,0};
     5120  groupValue[10]=largestEffect;
     5121  for (int i=0;i<10;i++)
     5122    groupValue[i]=smallestEffect+i*0.1*(largestEffect-smallestEffect);
     5123  sprintf(general,"Looked at %d integer variables - smallest interaction %g",
     5124          numberLookIntegers,smallestEffect);
     5125  model->messageHandler()->message((solveType&32)==0 ? CBC_FPUMP2 : CBC_FPUMP1,
     5126                                    *model->messagesPointer())
     5127    << general
     5128    << CoinMessageEol;
     5129  for (int i = 0; i < numberIntegers; i++) {
     5130    int iColumn=integerVariable[i];
     5131    if (back[iColumn]>=numberColumns)
     5132      continue;
     5133    double value = interAction[i];
     5134    int j;
     5135    for (j=0;j<11;j++) {
     5136      if (value<=groupValue[j]||j==10)
     5137        break;
     5138    }
     5139    groupCounts[j]++;
     5140  }
     5141  general[0]='\0';
     5142  for (int i=0;i<11;i++)
     5143    sprintf(general+strlen(general),"%d <= %g ",groupCounts[i],groupValue[i]);
     5144  model->messageHandler()->message((solveType&32)==0 ? CBC_FPUMP2 : CBC_FPUMP1,
     5145                                    *model->messagesPointer())
     5146    << general
     5147    << CoinMessageEol;
     5148  smallestEffect=COIN_DBL_MAX;
     5149  largestEffect=0.0;
     5150  int numberChanged=0;
     5151  int numberZeroMoved=0;
     5152  for (i = 0; i < numberIntegers; i++) {
     5153    int iColumn=integerVariable[i];
     5154    if (back[iColumn]>=numberColumns)
     5155      continue;
     5156    for (int iWay=0;iWay<2;iWay++) {
     5157      double value=objMovement[2*i+iWay];
     5158      if (value<1.0e-7) {
     5159        numberZeroMoved++;
     5160      } else if (value<1.0e50) {
     5161        smallestEffect = CoinMin(smallestEffect,value);
     5162        largestEffect = CoinMax(largestEffect,value);
     5163      } else {
     5164        numberChanged++;
     5165      }
     5166    }
     5167  }
     5168  memset(groupCounts,0,sizeof(groupCounts));
     5169  groupValue[10]=largestEffect;
     5170  for (int i=0;i<10;i++)
     5171    groupValue[i]=smallestEffect+i*0.1*(largestEffect-smallestEffect);
     5172  sprintf(general,"Strong branching - %d bounds changed, %d zero objective changes and %d nonzero (smallest %g)",
     5173          numberChanged,numberZeroMoved,
     5174          2*numberLookIntegers-numberChanged-numberZeroMoved,smallestEffect);
     5175  model->messageHandler()->message((solveType&32)==0 ? CBC_FPUMP2 : CBC_FPUMP1,
     5176                                    *model->messagesPointer())
     5177    << general
     5178    << CoinMessageEol;
     5179  sprintf(general,"Breakdown ");
     5180  for (i = 0; i < numberIntegers; i++) {
     5181    int iColumn=integerVariable[i];
     5182    if (back[iColumn]>=numberColumns)
     5183      continue;
     5184    for (int iWay=0;iWay<2;iWay++) {
     5185      double value = objMovement[2*i+iWay];
     5186      int j;
     5187      for (j=0;j<11;j++) {
     5188        if (value<=groupValue[j]||j==10)
     5189          break;
     5190      }
     5191      groupCounts[j]++;
     5192    }
     5193  }
     5194  for (int i=0;i<11;i++)
     5195    sprintf(general+strlen(general),"%d <= %g ",groupCounts[i],groupValue[i]);
     5196  model->messageHandler()->message((solveType&32)==0 ? CBC_FPUMP2 : CBC_FPUMP1,
     5197                                    *model->messagesPointer())
     5198    << general
     5199    << CoinMessageEol;
     5200  delete [] objMovement;
     5201  if ((solveType&2)==0) {
    41035202    // Delete the snapshot
    41045203    solver->unmarkHotStart();
    4105     // back to normal
    4106     solver->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo, NULL) ;
    4107     solver->setIntParam(OsiMaxNumIterationHotStart, saveLimit);
    4108     // restore basis
    4109     solver->setWarmStart(ws);
     5204  }
     5205  // back to normal
     5206  solver->setHintParam(OsiDoInBranchAndCut, true, OsiHintDo, NULL) ;
     5207  solver->setIntParam(OsiMaxNumIterationHotStart, saveLimit);
     5208  // restore basis
     5209  solver->setWarmStart(ws);
     5210  // skip if infeasible
     5211  if (numberToFix<0)
     5212    solveType=0;
     5213  int numberBoundsChanged=0;
     5214  if ((solveType&16)==0) {
     5215    double size=numberRows;
     5216    size*=numberColumns;
     5217    if (size>1000000) {
     5218      if ((solveType&32)!=0)
     5219        model->messageHandler()->message(CBC_GENERAL, *model->messagesPointer())
     5220          << "Skipping analyze on other columns as problem too large"
     5221          << CoinMessageEol;
     5222      solveType &= ~2;
     5223    }
     5224  }
     5225  if ((solveType&2)!=0) {
     5226# ifdef COIN_HAS_CLP
     5227    int saveOptions = osiclp ? osiclp->specialOptions() : 0;
     5228    if (osiclp) {
     5229      //ClpPrimalColumnPivot * primalColumnPivot=NULL;
     5230      osiclp->setSpecialOptions(saveOptions|2048); // off crunch
     5231    }
     5232#endif
     5233    double * newLower = new double [2*numberColumns];
     5234    double * newUpper = newLower + numberColumns;
     5235    // look at ints/all - should be parametrics - for now primal
     5236    OsiSolverInterface * temp = solver->clone();
     5237    // add constraint
     5238    int * indices = reinterpret_cast<int *>(newUpper);
     5239    double * obj = newLower;
     5240    memcpy(obj,solver->getObjCoefficients(),numberColumns*sizeof(double));
     5241    int n=0;
     5242    for (int i=0;i<numberColumns;i++) {
     5243      if (obj[i]) {
     5244        indices[n]=i;
     5245        obj[n++]=obj[i];
     5246      }
     5247    }
     5248    if (n) {
     5249      double cutoff=model->getCutoff();
     5250      // relax a little bit
     5251      cutoff += 1.0e-4;
     5252      double offset;
     5253      temp->getDblParam(OsiObjOffset, offset);
     5254      temp->addRow(n,indices,obj,-COIN_DBL_MAX,CoinMin(cutoff,1.0e25)+offset);
     5255      temp->setDblParam(OsiObjOffset, 0.0);
     5256#if defined (THREADS_IN_ANALYZE) && defined (COIN_HAS_CLP)
     5257      for (int iThread=0;iThread<numberThreads;iThread++) {
     5258        OsiSolverInterface * solver=
     5259          reinterpret_cast<OsiSolverInterface *>(threadInfo.threadInfo_[iThread].extraInfo2);
     5260        solver->addRow(n,indices,obj,-COIN_DBL_MAX,CoinMin(cutoff,1.0e25)+offset);
     5261      }
     5262#endif
     5263    }
     5264    //temp->setHintParam(OsiDoDualInResolve, false, OsiHintDo) ;
     5265    temp->setHintParam(OsiDoReducePrint, true, OsiHintTry);
     5266    temp->setDblParam(OsiDualObjectiveLimit, COIN_DBL_MAX);
     5267    temp->resolve();
     5268    {
     5269      const double * lower =temp->getColLower();
     5270      const double * upper =temp->getColUpper();
     5271      for (int i=0;i<numberColumns;i++) {
     5272        assert (lower[i]==saveLower[i]);
     5273        assert (upper[i]==saveUpper[i]);
     5274      }
     5275    }
    41105276    delete ws;
    4111 
    4112     delete [] sort;
    4113     delete [] whichObject;
    4114     delete [] saveLower;
    4115     delete [] saveUpper;
    4116     delete [] back;
    4117     // restore solution
    4118     solver->setColSolution(saveSolution);
     5277    ws = temp->getWarmStart();
     5278    staticInfo.ws=ws;
     5279    staticInfo.newObjective = new double[2*numberColumns];
     5280    memcpy(staticInfo.newObjective,solver->getObjCoefficients(),numberColumns*sizeof(double));
     5281    memset(staticInfo.newObjective+numberColumns,0,numberColumns*sizeof(double));
     5282#if defined (THREADS_IN_ANALYZE) && defined (COIN_HAS_CLP)
     5283    for (int iThread=0;iThread<numberThreads;iThread++) {
     5284      OsiSolverInterface * solver=
     5285        reinterpret_cast<OsiSolverInterface *>(threadInfo.threadInfo_[iThread].extraInfo2);
     5286      solver->setObjective(newLower);
     5287      solver->setDblParam(OsiDualObjectiveLimit, COIN_DBL_MAX);
     5288      threadNeedsRefreshing[iThread]=3;
     5289    }
     5290#endif
     5291    for (int i = 0; i < numberColumns; i++) {
     5292      newLower[i]=lower[i];
     5293      newUpper[i]=upper[i];
     5294    }
     5295    double * thisSolution = CoinCopyOfArray(temp->getColSolution(),numberColumns);
     5296    double primalTolerance;
     5297    solver->getDblParam(OsiPrimalTolerance,primalTolerance);
     5298    iDo=0;
     5299    iDone=-1;
     5300    numberDone=0;
     5301    int iThread=0;
     5302    threadStatus=0;
     5303    currentChoice=0;
     5304    staticInfo.solveType=100; //mark for analyze
     5305    staticInfo.originalSolution=thisSolution;
     5306    whenPrint=(numberColumns+9)/10;
     5307    while (numberDone<numberColumns) {
     5308      if ((solveType&32)!=0&&numberDone==whenPrint) {
     5309        whenPrint += (numberColumns+9)/10;
     5310        sprintf(general,"%d variables looked at - %d bounds changed by secondary solves (%.2f seconds - %d iterations)",numberDone,numberBoundsChanged,model->getCurrentSeconds()-time1,saveAllowed-numberIterationsAllowed);
     5311        model->messageHandler()->message(CBC_GENERAL, *model->messagesPointer())
     5312          << general
     5313          << CoinMessageEol;
     5314      }
     5315#ifdef USE_STRONG_THREADS
     5316      if (numberThreads) {
     5317        threadInfo.waitParallelTask(1,iThread,iDo<numberColumns);
     5318        threadStatus = 1+threadInfo.threadInfo_[iThread].status;
     5319        currentChoice=iThread;
     5320        if (threadNeedsRefreshing[iThread]) {
     5321          OsiSolverInterface * solver=
     5322            reinterpret_cast<OsiSolverInterface *>(threadInfo.threadInfo_[iThread].extraInfo2);
     5323          if ((threadNeedsRefreshing[iThread]&1)!=0)
     5324            solver->setColLower(saveLower);
     5325          if ((threadNeedsRefreshing[iThread]&2)!=0)
     5326            solver->setColUpper(saveUpper);
     5327          threadNeedsRefreshing[iThread]=0;
     5328        }
     5329      }
     5330#endif
     5331      if (threadStatus==0&&iDo<numberColumns) {
     5332        StrongInfo & choice = choices[currentChoice];
     5333        StrongBundle & bundle = bundles[currentChoice];
     5334        bundle.whichChoice=currentChoice;
     5335        memset(&choice,0,sizeof(StrongInfo));
     5336        int iColumn = iDo;
     5337        iDo++; //started this one
     5338        int typeSolve=0;
     5339        if (thisSolution[iColumn]>newLower[iColumn]+integerTolerance)
     5340          typeSolve=1;
     5341        if (thisSolution[iColumn]<newUpper[iColumn]-integerTolerance)
     5342          typeSolve += 2;
     5343        if (typeSolve&&back[iColumn]>=0) {
     5344          if (thisSolution[iColumn]<newLower[iColumn]+0.9999)
     5345            typeSolve &= ~1;
     5346          if (thisSolution[iColumn]>newUpper[iColumn]-0.9999)
     5347            typeSolve &= ~2;
     5348          if (temp->isBinary(iColumn))
     5349            typeSolve=0; // already done
     5350        }
     5351        if (typeSolve==0 || newUpper[iColumn]==newLower[iColumn]) {
     5352#ifdef USE_STRONG_THREADS
     5353          // say available
     5354          if (numberThreads) {
     5355            threadInfo.sayIdle(iThread);
     5356          }
     5357#endif
     5358          numberDone++;
     5359          continue;
     5360        }
     5361        // Save which object it was
     5362        choice.columnNumber = iColumn;
     5363        choice.initialValue=thisSolution[iColumn];
     5364        choice.movement[0]=COIN_DBL_MAX;
     5365        choice.movement[1]=-COIN_DBL_MAX;
     5366        choice.upLowerBound=newUpper[iColumn];
     5367        choice.downUpperBound=newLower[iColumn];
     5368        if ((typeSolve&1)==0)
     5369          choice.numIters[0]=-1; // mark as not done
     5370        if ((typeSolve&2)==0)
     5371          choice.numIters[1]=-1; // mark as not done
     5372        bundle.choice=&choice;
     5373        bundle.solver = temp;
     5374#ifdef USE_STRONG_THREADS
     5375        if (numberThreads) {
     5376          bundle.solver=reinterpret_cast<OsiSolverInterface *>(threadInfo.threadInfo_[iThread].extraInfo2);
     5377          threadStatus=0;
     5378#ifdef DETAIL_THREAD
     5379          printf("Starting task for column %d on thread %d\n",
     5380                 choice.columnNumber,iThread);
     5381#endif
     5382          threadInfo.startParallelTask(1,iThread,&bundle);
     5383        } else {
     5384#endif
     5385          threadStatus=2;
     5386          solveAnalyze(&bundle);
     5387#ifdef USE_STRONG_THREADS
     5388        }
     5389#endif
     5390      }
     5391      if (threadStatus) {
     5392        int whichChoice = bundles[iThread].whichChoice; 
     5393        StrongInfo & choice = choices[whichChoice];
     5394        int iColumn=choice.columnNumber;
     5395        if(choice.modified[0]) {
     5396          numberToFix = -numberColumns-1;
     5397        }
     5398        double gotLower=COIN_DBL_MAX;
     5399        double gotUpper=-COIN_DBL_MAX;
     5400        if (choice.numIters[0]>=0) {
     5401          // go down
     5402          double value = choice.movement[0];
     5403          if (value>newLower[iColumn]+100.0*integerTolerance) {
     5404            if (back[iColumn]>=0)
     5405              value = ceil(value-integerTolerance);
     5406            else
     5407              value = CoinMax(newLower[iColumn],value-1.0e-5-1.0e-8*fabs(value));
     5408            if (value>newLower[iColumn]+1.0e-8*(1.0+fabs(value))) {
     5409              sprintf(general,"Secondary analysis solve increases lower bound on %d from %g to %g%s",
     5410                      iColumn,newUpper[iColumn],value,(back[iColumn]>=0) ? "(integer)" : "");
     5411              model->messageHandler()->message(CBC_FPUMP2, *model->messagesPointer())
     5412                << general
     5413                << CoinMessageEol;
     5414              numberBoundsChanged++;
     5415              if (value>newUpper[iColumn]-primalTolerance) {
     5416                value=newUpper[iColumn];
     5417                if (value>newUpper[iColumn]+10.0*primalTolerance) {
     5418                  // infeasible
     5419                  numberToFix=-numberColumns-1;
     5420                }
     5421              }
     5422              gotLower = value;
     5423            }
     5424          }
     5425        }
     5426        if (choice.numIters[1]>=0) {
     5427          // go up
     5428          double value=choice.movement[1];
     5429          if (value<newUpper[iColumn]-100.0*integerTolerance) {
     5430            if (back[iColumn]>=0)
     5431              value = floor(value+integerTolerance);
     5432            else
     5433              value = CoinMin(newUpper[iColumn],value+1.0e-5+1.0e-8*fabs(value));
     5434            if (value<newUpper[iColumn]-1.0e-8*(1.0+fabs(value))) {
     5435              sprintf(general,"Secondary analysis solve decreases upper bound on %d from %g to %g%s",
     5436                      iColumn,newUpper[iColumn],value,(back[iColumn]>=0) ? "(integer)" : "");
     5437              model->messageHandler()->message(CBC_FPUMP2, *model->messagesPointer())
     5438                << general
     5439                << CoinMessageEol;
     5440              numberBoundsChanged++;
     5441              if (value<newLower[iColumn]+primalTolerance) {
     5442                value=newLower[iColumn];
     5443                if (value<newLower[iColumn]-10.0*primalTolerance) {
     5444                  // infeasible
     5445                  numberToFix=-numberColumns-1;
     5446                }
     5447              }
     5448              gotUpper=value;
     5449            }
     5450          }
     5451        }
     5452        if (gotLower!=COIN_DBL_MAX) {
     5453          newLower[iColumn]=gotLower;
     5454          temp->setColLower(iColumn,gotLower);
     5455          if (!doAtEnd)
     5456            solver->setColLower(iColumn,gotLower);
     5457        }
     5458        if (gotUpper!=-COIN_DBL_MAX) {
     5459          gotUpper=CoinMax(gotUpper,newLower[iColumn]);
     5460          newUpper[iColumn]=gotUpper;
     5461          temp->setColUpper(iColumn,gotUpper);
     5462          if (!doAtEnd)
     5463            solver->setColUpper(iColumn,gotUpper);
     5464        }
     5465#if 0
     5466        if ((model->specialOptions()&1) != 0) {
     5467          const OsiRowCutDebugger *debugger = solver->getRowCutDebugger() ;
     5468          if (!debugger) {
     5469            abort();
     5470          } else {
     5471            printf("still ok\n");
     5472          }
     5473        }
     5474#endif
     5475        threadStatus=0;
     5476        currentChoice++;
     5477        numberDone++;
     5478        for (int iWay=0;iWay<2;iWay++) {
     5479          if (choice.numIters[iWay]>0)
     5480            numberIterationsAllowed -= choice.numIters[iWay];
     5481        }
     5482        if (currentChoice==maxChoices)
     5483          currentChoice=0;
     5484#ifdef USE_STRONG_THREADS
     5485        // say available
     5486        if (numberThreads) {
     5487          threadInfo.sayIdle(iThread);
     5488        }
     5489#endif
     5490      }
     5491    }
     5492    delete [] thisSolution;
     5493    delete temp;
     5494    delete [] newLower;
    41195495# ifdef COIN_HAS_CLP
    4120     if (osiclp)
    4121         osiclp->setSpecialOptions(saveClpOptions);
     5496    if (osiclp) {
     5497      //ClpPrimalColumnPivot * primalColumnPivot=NULL;
     5498      osiclp->setSpecialOptions(saveOptions);
     5499    }
     5500#endif
     5501  }
     5502  delete [] staticInfo.newObjective;
     5503# ifdef COIN_HAS_CLP
     5504  if (osiclp) {
     5505    delete staticInfo.dualRowPivot;
     5506    delete staticInfo.primalColumnPivot;
     5507    ClpSimplex * simplex = osiclp->getModelPtr();
     5508    ClpDualRowPivot * dualRowPivot=simplex->dualRowPivot();
     5509    ClpDualRowSteepest * steep = dynamic_cast<ClpDualRowSteepest *>(dualRowPivot);
     5510    if (steep)
     5511      steep->setMode(3);
     5512  }
     5513#endif
     5514  if ((solveType&64)!=0) {
     5515    OsiSolverInterface * temp = solver->clone();
     5516    int numberRows=solver->getNumRows();
     5517    int numberContinuousRows=model->numberRowsAtContinuous();
     5518    int * del = new int[numberRows-numberContinuousRows];
     5519    for (int i=numberContinuousRows;i<numberRows;i++)
     5520      del[i-numberContinuousRows]=i;
     5521    temp->deleteRows(numberRows-numberContinuousRows,del);
     5522    delete [] del;
     5523# ifdef COIN_HAS_CLP
     5524    if (!osiclp) {
     5525#endif
     5526      solver->writeMps("analyzed");
     5527      temp->writeMps("analyzed2");
     5528# ifdef COIN_HAS_CLP
     5529    } else {
     5530      OsiClpSolverInterface * osiclp2 = dynamic_cast< OsiClpSolverInterface*> (temp);
     5531      osiclp->getModelPtr()->writeMps("analyzed.mps",2,1);
     5532      osiclp2->getModelPtr()->writeMps("analyzed2.mps",2,1);
     5533    }
     5534#endif
     5535    delete temp;
     5536    model->messageHandler()->message(CBC_GENERAL, *model->messagesPointer())
     5537      << "Models saved on 'analyzed' and 'analyzed2'"
     5538      << CoinMessageEol;
     5539  }
     5540  delete [] choices;
     5541  for (int i=0;i<numberBundles;i++) {
     5542    delete [] bundles[i].tempSolution;
     5543    delete bundles[i].tempBasis;
     5544  }
     5545  delete [] bundles;
     5546#ifdef USE_STRONG_THREADS
     5547  if (numberThreads) {
     5548    threadInfo.waitAllTasks();
     5549    for (int i=0;i<numberThreads;i++) {
     5550      delete reinterpret_cast<OsiSolverInterface *>(threadInfo.threadInfo_[i].extraInfo2);
     5551    }
     5552  }
     5553#endif
     5554  delete ws;
     5555 
     5556  delete [] sort;
     5557  delete [] whichObject;
     5558  delete [] saveLower;
     5559  delete [] saveUpper;
     5560  delete [] back;
     5561  // restore solution
     5562  solver->setColSolution(saveSolution);
     5563# ifdef COIN_HAS_CLP
     5564  if (osiclp)
     5565    osiclp->setSpecialOptions(saveClpOptions);
    41225566# endif
    4123     model->reserveCurrentSolution(saveSolution);
    4124     delete [] saveSolution;
    4125     if (needResolve)
    4126         solver->resolve();
     5567  delete [] saveSolution;
     5568  solver->resolve();
     5569  if (numberToFix<0&&!solver->isProvenOptimal()) {
     5570    // infeasible
     5571    model->messageHandler()->message(CBC_GENERAL, *model->messagesPointer())
     5572      << "Analysis shows problem to be infeasible"
     5573      << CoinMessageEol;
    41275574    return numberToFix;
     5575  }
     5576  if (numberBoundsChanged) {
     5577    sprintf(general,"%d bounds changed by secondary solves (%.2f seconds - %d iterations)",
     5578            numberBoundsChanged,model->getCurrentSeconds()-time1,saveAllowed-numberIterationsAllowed);
     5579    model->messageHandler()->message(CBC_GENERAL, *model->messagesPointer())
     5580      << general
     5581      << CoinMessageEol;
     5582  } else if ((solveType&32)!=0) {
     5583    sprintf(general,"No bounds changed by secondary solves (%.2f seconds - %d iterations)",
     5584            model->getCurrentSeconds()-time1,saveAllowed-numberIterationsAllowed);
     5585    model->messageHandler()->message(CBC_GENERAL, *model->messagesPointer())
     5586      << general
     5587      << CoinMessageEol;
     5588  }
     5589  model->reserveCurrentSolution(solver->getColSolution());
     5590  if ((solveType&1)!=0) {
     5591    if (groupCounts[0]*4>numberIntegers) {
     5592      // change priority on this group
     5593      int generalPriority=-10000000;
     5594      for (int i = 0; i < numberIntegers; i++) {
     5595        OsiObject * object = model->modifiableObject(i);
     5596        CbcSimpleInteger * integerObject =
     5597          dynamic_cast <CbcSimpleInteger *>(object) ;
     5598        if (!integerObject)
     5599          continue;
     5600        generalPriority = CoinMax(generalPriority,integerObject->priority());
     5601      }
     5602      for (int i = 0; i < numberIntegers; i++) {
     5603        OsiObject * object = model->modifiableObject(i);
     5604        CbcSimpleInteger * integerObject =
     5605          dynamic_cast <CbcSimpleInteger *>(object) ;
     5606        if (!integerObject)
     5607          continue;
     5608        if (!interAction[i]&&integerObject->priority()==generalPriority)
     5609          integerObject->setPriority(generalPriority+1);
     5610      }
     5611    }
     5612  }
     5613  return numberToFix;
    41285614}
    41295615
     
    41335619{
    41345620#ifdef CHECK_NODE
    4135     printf("CbcNode %x Constructor from rhs %x\n", this, &rhs);
     5621    printf("CbcNode %p Constructor from rhs %p\n", this, &rhs);
    41365622#endif
    41375623    if (rhs.nodeInfo_)
     
    41875673#ifdef CHECK_NODE
    41885674    if (nodeInfo_) {
    4189         printf("CbcNode %x Destructor nodeInfo %x (%d)\n",
     5675        printf("CbcNode %p Destructor nodeInfo %p (%d)\n",
    41905676               this, nodeInfo_, nodeInfo_->numberPointingToThis());
    41915677        //assert(nodeInfo_->numberPointingToThis()>=0);
    41925678    } else {
    4193         printf("CbcNode %x Destructor nodeInfo %x (?)\n",
     5679        printf("CbcNode %p Destructor nodeInfo %p (?)\n",
    41945680               this, nodeInfo_);
    41955681    }
     
    42065692            delete nodeInfo_;
    42075693        } else {
    4208             //printf("node %x nodeinfo %x parent %x\n",this,nodeInfo_,nodeInfo_->parent());
     5694            //printf("node %p nodeinfo %p parent %p\n",this,nodeInfo_,nodeInfo_->parent());
    42095695            // anyway decrement parent
    42105696            //if (parent)
Note: See TracChangeset for help on using the changeset viewer.