Changeset 271 for trunk


Ignore:
Timestamp:
Mar 14, 2006 10:39:00 AM (14 years ago)
Author:
forrest
Message:

for Pierre (and to annoy Lou:-)

Location:
trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/CbcModel.cpp

    r269 r271  
    354354  return ;
    355355}
    356 #ifndef CBC_NEXT_VERSION
    357356
    358357
     
    529528  // If NLP then we assume already solved outside branchAndbound
    530529  if (!solverCharacteristics_->solverType()) {
    531     feasible=resolve() ;
     530    feasible=resolve(NULL,0) != 0 ;
    532531  } else {
    533532    // pick up given status
     
    810809      numberPassesLeft--;
    811810      if (anyAction == -1)
    812       { feasible = resolve() ;
     811      { feasible = resolve(NULL,10) != 0 ;
    813812      if (problemFeasibility_->feasible(this,0)<0) {
    814813        feasible=false; // pretend infeasible
     
    11561155      int saveNumber = numberIterations_;
    11571156      if(solverCharacteristics_->solutionAddsCuts()) {
    1158         feasible=resolve();
     1157        int returnCode=resolve(node ? node->nodeInfo() : NULL,1);
     1158        feasible = returnCode != 0;
    11591159        if (feasible) {
    11601160          int iObject ;
     
    11691169            if (infeasibility ) numberUnsatisfied++ ;
    11701170          }
    1171           if (numberUnsatisfied)   {
    1172             feasible = solveWithCuts(cuts,maximumCutPasses_,node);
    1173           } else {
    1174             // may generate cuts and turn the solution
    1175             //to an infeasible one
    1176             feasible = solveWithCuts(cuts, 1,
    1177                                      node);
     1171          if (returnCode>0) {
     1172            if (numberUnsatisfied)   {
     1173              feasible = solveWithCuts(cuts,maximumCutPasses_,node);
     1174            } else {
     1175              // may generate cuts and turn the solution
     1176              //to an infeasible one
     1177              feasible = solveWithCuts(cuts, 1,
     1178                                       node);
    11781179#if 0
    1179             currentNumberCuts_ = cuts.sizeRowCuts();
    1180             if (currentNumberCuts_ >= maximumNumberCuts_) {
    1181               maximumNumberCuts_ = currentNumberCuts;
    1182               delete [] addedCuts_;
    1183               addedCuts_ = new CbcCountRowCut * [maximumNumberCuts_];
     1180              currentNumberCuts_ = cuts.sizeRowCuts();
     1181              if (currentNumberCuts_ >= maximumNumberCuts_) {
     1182                maximumNumberCuts_ = currentNumberCuts;
     1183                delete [] addedCuts_;
     1184                addedCuts_ = new CbcCountRowCut * [maximumNumberCuts_];
     1185              }
     1186#endif
    11841187            }
    1185 #endif
    11861188          }
    11871189          // check extra info on feasibility
     
    12801282              int easy=2;
    12811283              solver_->setHintParam(OsiDoInBranchAndCut,true,OsiHintDo,&easy) ;
    1282               feasible = resolve() ;
     1284              feasible = resolve(node ? node->nodeInfo() : NULL,11) != 0 ;
    12831285              solver_->setHintParam(OsiDoInBranchAndCut,true,OsiHintDo,NULL) ;
    12841286              resolved = true ;
     
    17821784  }
    17831785  return ; }
    1784 #else
    1785 void CbcModel::branchAndBound(int doStatistics)
    1786 
    1787 {
    1788 /*
    1789   Capture a time stamp before we start.
    1790 */
    1791   dblParam_[CbcStartSeconds] = CoinCpuTime();
    1792   strongInfo_[0]=0;
    1793   strongInfo_[1]=0;
    1794   strongInfo_[2]=0;
    1795   numberStrongIterations_ = 0;
    1796   // original solver (only set if pre-processing)
    1797   OsiSolverInterface * originalSolver=NULL;
    1798   // Set up strategies
    1799   if (strategy_) {
    1800     // May do preprocessing
    1801     originalSolver = solver_;
    1802     strategy_->setupOther(*this);
    1803     if (strategy_->preProcessState()) {
    1804       // pre-processing done
    1805       if (strategy_->preProcessState()<0) {
    1806         // infeasible
    1807         handler_->message(CBC_INFEAS,messages_)<< CoinMessageEol ;
    1808         status_ = 0 ;
    1809         secondaryStatus_ = 1;
    1810         originalContinuousObjective_ = COIN_DBL_MAX;
    1811         return ;
    1812       }
    1813     } else {
    1814       //no preprocessing
    1815       originalSolver=NULL;
    1816     }
    1817     strategy_->setupCutGenerators(*this);
    1818     strategy_->setupHeuristics(*this);
    1819     // Set strategy print level to models
    1820     strategy_->setupPrinting(*this,handler_->logLevel());
    1821   }
    1822   eventHappened_=false;
    1823 #ifdef COIN_USE_CLP
    1824   ClpEventHandler * eventHandler=NULL;
    1825  {
    1826    OsiClpSolverInterface * clpSolver
    1827      = dynamic_cast<OsiClpSolverInterface *> (solver_);
    1828    if (clpSolver) {
    1829      ClpSimplex * clpSimplex = clpSolver->getModelPtr();
    1830      eventHandler = clpSimplex->eventHandler();
    1831    }
    1832  }
    1833 #endif
    1834   if (!nodeCompare_)
    1835     nodeCompare_=new CbcCompareDefault();;
    1836   if (!problemFeasibility_)
    1837     problemFeasibility_=new CbcFeasibilityBase();
    1838 # ifdef CBC_DEBUG
    1839   std::string problemName ;
    1840   solver_->getStrParam(OsiProbName,problemName) ;
    1841   printf("Problem name - %s\n",problemName.c_str()) ;
    1842   solver_->setHintParam(OsiDoReducePrint,false,OsiHintDo,0) ;
    1843 # endif
    1844 /*
    1845   Assume we're done, and see if we're proven wrong.
    1846 */
    1847   status_ = 0 ;
    1848   secondaryStatus_ = 0;
    1849   phase_=0;
    1850 /*
    1851   Scan the variables, noting the integer variables. Create an
    1852   CbcSimpleInteger object for each integer variable.
    1853 */
    1854   findIntegers(false) ;
    1855   // If dynamic pseudo costs then do
    1856   if (numberBeforeTrust_)
    1857     convertToDynamic();
    1858   // Set up char array to say if integer
    1859   delete [] integerInfo_;
    1860   {
    1861     int n = solver_->getNumCols();
    1862     integerInfo_ = new char [n];
    1863     for (int i=0;i<n;i++) {
    1864       if (solver_->isInteger(i))
    1865         integerInfo_[i]=1;
    1866       else
    1867         integerInfo_[i]=0;
    1868     }
    1869   }
    1870    
    1871 /*
    1872   Ensure that objects on the lists of CbcObjects, heuristics, and cut
    1873   generators attached to this model all refer to this model.
    1874 */
    1875   synchronizeModel() ;
    1876   assert (!solverCharacteristics_);
    1877   OsiBabSolver * solverCharacteristics = dynamic_cast<OsiBabSolver *> (solver_->getAuxiliaryInfo());
    1878   if (solverCharacteristics) {
    1879     solverCharacteristics_ = solverCharacteristics;
    1880   } else {
    1881     // replace in solver
    1882     OsiBabSolver defaultC;
    1883     solver_->setAuxiliaryInfo(&defaultC);
    1884     solverCharacteristics_ = dynamic_cast<OsiBabSolver *> (solver_->getAuxiliaryInfo());
    1885   }
    1886   solverCharacteristics_->setSolver(solver_);
    1887   // Set so we can tell we are in initial phase in resolve
    1888   continuousObjective_ = -COIN_DBL_MAX ;
    1889 /*
    1890   Solve the relaxation.
    1891 
    1892   Apparently there are circumstances where this will be non-trivial --- i.e.,
    1893   we've done something since initialSolve that's trashed the solution to the
    1894   continuous relaxation.
    1895 */
    1896   bool feasible = resolve() ;
    1897   if (problemFeasibility_->feasible(this,0)<0) {
    1898     feasible=false; // pretend infeasible
    1899   }
    1900 /*
    1901   If the linear relaxation of the root is infeasible, bail out now. Otherwise,
    1902   continue with processing the root node.
    1903 */
    1904   if (!feasible)
    1905   { handler_->message(CBC_INFEAS,messages_)<< CoinMessageEol ;
    1906     status_ = 0 ;
    1907     secondaryStatus_ = 1;
    1908     originalContinuousObjective_ = COIN_DBL_MAX;
    1909     return ; }
    1910   // Save objective (just so user can access it)
    1911   originalContinuousObjective_ = solver_->getObjValue();
    1912   bestPossibleObjective_=originalContinuousObjective_;
    1913   sumChangeObjective1_=0.0;
    1914   sumChangeObjective2_=0.0;
    1915 /*
    1916   OsiRowCutDebugger knows an optimal answer for a subset of MIP problems.
    1917   Assuming it recognises the problem, when called upon it will check a cut to
    1918   see if it cuts off the optimal answer.
    1919 */
    1920   // If debugger exists set specialOptions_ bit
    1921   if (solver_->getRowCutDebuggerAlways())
    1922     specialOptions_ |= 1;
    1923 
    1924 # ifdef CBC_DEBUG
    1925   if ((specialOptions_&1)==0)
    1926     solver_->activateRowCutDebugger(problemName.c_str()) ;
    1927   if (solver_->getRowCutDebuggerAlways())
    1928     specialOptions_ |= 1;
    1929 # endif
    1930 
    1931 /*
    1932   Begin setup to process a feasible root node.
    1933 */
    1934   bestObjective_ = CoinMin(bestObjective_,1.0e50) ;
    1935   numberSolutions_ = 0 ;
    1936   stateOfSearch_=0;
    1937   numberHeuristicSolutions_ = 0 ;
    1938   // Everything is minimization
    1939   {
    1940     // needed to sync cutoffs
    1941     double value ;
    1942     solver_->getDblParam(OsiDualObjectiveLimit,value) ;
    1943     dblParam_[CbcCurrentCutoff]= value * solver_->getObjSense();
    1944   }
    1945   double cutoff=getCutoff() ;
    1946   double direction = solver_->getObjSense() ;
    1947   dblParam_[CbcOptimizationDirection]=direction;
    1948   if (cutoff < 1.0e20&&direction<0.0)
    1949     messageHandler()->message(CBC_CUTOFF_WARNING1,
    1950                                     messages())
    1951                                       << cutoff << -cutoff << CoinMessageEol ;
    1952   if (cutoff > bestObjective_)
    1953     cutoff = bestObjective_ ;
    1954   setCutoff(cutoff) ;
    1955 /*
    1956   We probably already have a current solution, but just in case ...
    1957 */
    1958   int numberColumns = getNumCols() ;
    1959   if (!currentSolution_)
    1960     currentSolution_ = new double[numberColumns] ;
    1961   testSolution_ = currentSolution_;
    1962   /* Tell solver we are in Branch and Cut
    1963      Could use last parameter for subtle differences */
    1964   solver_->setHintParam(OsiDoInBranchAndCut,true,OsiHintDo,NULL) ;
    1965 /*
    1966   Create a copy of the solver, thus capturing the original (root node)
    1967   constraint system (aka the continuous system).
    1968 */
    1969   continuousSolver_ = solver_->clone() ;
    1970 #ifdef COIN_USE_CLP
    1971   OsiClpSolverInterface * clpSolver
    1972     = dynamic_cast<OsiClpSolverInterface *> (solver_);
    1973   if (clpSolver) {
    1974     ClpSimplex * clpSimplex = clpSolver->getModelPtr();
    1975     // take off names
    1976     clpSimplex->dropNames();
    1977   }
    1978 #endif
    1979 
    1980   numberRowsAtContinuous_ = getNumRows() ;
    1981 /*
    1982   Check the objective to see if we can deduce a nontrivial increment. If
    1983   it's better than the current value for CbcCutoffIncrement, it'll be
    1984   installed.
    1985 */
    1986   if(solverCharacteristics_->reducedCostsAccurate())
    1987     analyzeObjective() ;
    1988 /*
    1989   Set up for cut generation. addedCuts_ holds the cuts which are relevant for
    1990   the active subproblem. whichGenerator will be used to record the generator
    1991   that produced a given cut.
    1992 */
    1993   maximumWhich_ = 1000 ;
    1994   delete [] whichGenerator_;
    1995   whichGenerator_ = new int[maximumWhich_] ;
    1996   memset(whichGenerator_,0,maximumWhich_*sizeof(int));
    1997   maximumNumberCuts_ = 0 ;
    1998   currentNumberCuts_ = 0 ;
    1999   delete [] addedCuts_ ;
    2000   addedCuts_ = NULL ;
    2001 /*
    2002   Set up an empty heap and associated data structures to hold the live set
    2003   (problems which require further exploration).
    2004 */
    2005   tree_->setComparison(*nodeCompare_) ;
    2006 /*
    2007   Used to record the path from a node to the root of the search tree, so that
    2008   we can then traverse from the root to the node when restoring a subproblem.
    2009 */
    2010   maximumDepth_ = 10 ;
    2011   delete [] walkback_ ;
    2012   walkback_ = new CbcNodeInfo * [maximumDepth_] ;
    2013 /*
    2014   Used to generate bound edits for CbcPartialNodeInfo.
    2015 */
    2016   double * lowerBefore = new double [numberColumns] ;
    2017   double * upperBefore = new double [numberColumns] ;
    2018 /*
    2019  
    2020   Generate cuts at the root node and reoptimise. solveWithCuts does the heavy
    2021   lifting. It will iterate a generate/reoptimise loop (including reduced cost
    2022   fixing) until no cuts are generated, the change in objective falls off,  or
    2023   the limit on the number of rounds of cut generation is exceeded.
    2024 
    2025   At the end of all this, any cuts will be recorded in cuts and also
    2026   installed in the solver's constraint system. We'll have reoptimised, and
    2027   removed any slack cuts (numberOldActiveCuts_ and numberNewCuts_ have been
    2028   adjusted accordingly).
    2029 
    2030   Tell cut generators they can be a bit more aggressive at root node
    2031 
    2032   TODO: Why don't we make a copy of the solution after solveWithCuts?
    2033   TODO: If numberUnsatisfied == 0, don't we have a solution?
    2034 */
    2035   phase_=1;
    2036   int iCutGenerator;
    2037   for (iCutGenerator = 0;iCutGenerator<numberCutGenerators_;iCutGenerator++) {
    2038     CglCutGenerator * generator = generator_[iCutGenerator]->generator();
    2039     generator->setAggressiveness(generator->getAggressiveness()+100);
    2040   }
    2041   OsiCuts cuts ;
    2042   int anyAction = -1 ;
    2043   numberOldActiveCuts_ = 0 ;
    2044   numberNewCuts_ = 0 ;
    2045   // Array to mark solution
    2046   delete [] usedInSolution_;
    2047   usedInSolution_ = new int[numberColumns];
    2048   CoinZeroN(usedInSolution_,numberColumns);
    2049 /*
    2050   For printing totals and for CbcNode (numberNodes_)
    2051 */
    2052   numberIterations_ = 0 ;
    2053   numberNodes_ = 0 ;
    2054   numberNodes2_ = 0 ;
    2055   maximumStatistics_=0;
    2056   statistics_ = NULL;
    2057   // Do on switch
    2058   if (doStatistics) {
    2059     maximumStatistics_=10000;
    2060     statistics_ = new CbcStatistics * [maximumStatistics_];
    2061     memset(statistics_,0,maximumStatistics_*sizeof(CbcStatistics *));
    2062   }
    2063 
    2064   { int iObject ;
    2065     int preferredWay ;
    2066     int numberUnsatisfied = 0 ;
    2067     memcpy(currentSolution_,solver_->getColSolution(),
    2068            numberColumns*sizeof(double)) ;
    2069 
    2070     for (iObject = 0 ; iObject < numberObjects_ ; iObject++)
    2071     { double infeasibility =
    2072           object_[iObject]->infeasibility(preferredWay) ;
    2073       if (infeasibility ) numberUnsatisfied++ ; }
    2074     if (numberUnsatisfied) {
    2075       feasible = solveWithCuts(cuts,maximumCutPassesAtRoot_,NULL);
    2076     }
    2077   }
    2078   // make cut generators less aggressive
    2079   for (iCutGenerator = 0;iCutGenerator<numberCutGenerators_;iCutGenerator++) {
    2080     CglCutGenerator * generator = generator_[iCutGenerator]->generator();
    2081     generator->setAggressiveness(generator->getAggressiveness()-100);
    2082   }
    2083   currentNumberCuts_ = numberNewCuts_ ;
    2084 /*
    2085   We've taken the continuous relaxation as far as we can. Time to branch.
    2086   The first order of business is to actually create a node. chooseBranch
    2087   currently uses strong branching to evaluate branch object candidates,
    2088   unless forced back to simple branching. If chooseBranch concludes that a
    2089   branching candidate is monotone (anyAction == -1) or infeasible (anyAction
    2090   == -2) when forced to integer values, it returns here immediately.
    2091 
    2092   Monotone variables trigger a call to resolve(). If the problem remains
    2093   feasible, try again to choose a branching variable. At the end of the loop,
    2094   resolved == true indicates that some variables were fixed.
    2095 
    2096   Loss of feasibility will result in the deletion of newNode.
    2097 */
    2098 
    2099   bool resolved = false ;
    2100   CbcNode *newNode = NULL ;
    2101   numberFixedAtRoot_=0;
    2102   numberFixedNow_=0;
    2103   int numberIterationsAtContinuous = numberIterations_;
    2104   if (feasible) {
    2105     newNode = new CbcNode ;
    2106     // Set objective value (not so obvious if NLP etc)
    2107     setObjectiveValue(newNode,NULL);
    2108     anyAction = -1 ;
    2109     // To make depth available we may need a fake node
    2110     CbcNode fakeNode;
    2111     if (!currentNode_) {
    2112       // Not true if sub trees assert (!numberNodes_);
    2113       currentNode_=&fakeNode;
    2114     }
    2115     phase_=3;
    2116     // only allow 1000 passes
    2117     int numberPassesLeft=1000;
    2118     // This is first crude step
    2119     if (numberAnalyzeIterations_) {
    2120       delete [] analyzeResults_;
    2121       analyzeResults_ = new double [4*numberIntegers_];
    2122       numberFixedAtRoot_=newNode->analyze(this,analyzeResults_);
    2123       if (numberFixedAtRoot_>0) {
    2124         printf("%d fixed by analysis\n",numberFixedAtRoot_);
    2125         setPointers(solver_);
    2126         numberFixedNow_ = numberFixedAtRoot_;
    2127       } else if (numberFixedAtRoot_<0) {
    2128         printf("analysis found to be infeasible\n");
    2129         anyAction=-2;
    2130         delete newNode ;
    2131         newNode = NULL ;
    2132         feasible = false ;
    2133       }
    2134     }
    2135     while (anyAction == -1)
    2136     {
    2137       // Set objective value (not so obvious if NLP etc)
    2138       setObjectiveValue(newNode,NULL);
    2139       if (numberBeforeTrust_==0 ) {
    2140         anyAction = newNode->chooseBranch(this,NULL,numberPassesLeft) ;
    2141       } else {
    2142         OsiSolverBranch * branches=NULL;
    2143         anyAction = newNode->chooseDynamicBranch(this,NULL,branches,numberPassesLeft) ;
    2144         if (anyAction==-3)
    2145           anyAction = newNode->chooseBranch(this,NULL,numberPassesLeft) ; // dynamic did nothing
    2146       }
    2147       numberPassesLeft--;
    2148       if (anyAction == -1)
    2149       { feasible = resolve() ;
    2150       if (problemFeasibility_->feasible(this,0)<0) {
    2151         feasible=false; // pretend infeasible
    2152       }
    2153       reducedCostFix() ;
    2154       resolved = true ;
    2155 #       ifdef CBC_DEBUG
    2156       printf("Resolve (root) as something fixed, Obj value %g %d rows\n",
    2157              solver_->getObjValue(),
    2158              solver_->getNumRows()) ;
    2159 #       endif
    2160       if (!feasible) anyAction = -2 ; }
    2161       if (anyAction == -2||newNode->objectiveValue() >= cutoff)
    2162       { delete newNode ;
    2163         newNode = NULL ;
    2164         feasible = false ; } } }
    2165 /*
    2166   At this point, the root subproblem is infeasible or fathomed by bound
    2167   (newNode == NULL), or we're live with an objective value that satisfies the
    2168   current objective cutoff.
    2169 */
    2170   assert (!newNode || newNode->objectiveValue() <= cutoff) ;
    2171   // Save address of root node as we don't want to delete it
    2172   //CbcNode * rootNode = newNode;
    2173 /*
    2174   The common case is that the lp relaxation is feasible but doesn't satisfy
    2175   integrality (i.e., newNode->variable() >= 0, indicating we've been able to
    2176   select a branching variable). Remove any cuts that have gone slack due to
    2177   forcing monotone variables. Then tack on an CbcFullNodeInfo object and full
    2178   basis (via createInfo()) and stash the new cuts in the nodeInfo (via
    2179   addCuts()). If, by some miracle, we have an integral solution at the root
    2180   (newNode->variable() < 0), takeOffCuts() will ensure that the solver holds
    2181   a valid solution for use by setBestSolution().
    2182 */
    2183   if (feasible && newNode->variable() >= 0)
    2184   { if (resolved)
    2185     { bool needValidSolution = (newNode->variable() < 0) ;
    2186       takeOffCuts(cuts,needValidSolution,NULL) ;
    2187 #     ifdef CHECK_CUT_COUNTS
    2188       { printf("Number of rows after chooseBranch fix (root)"
    2189                "(active only) %d\n",
    2190                 numberRowsAtContinuous_+numberNewCuts_+numberOldActiveCuts_) ;
    2191         const CoinWarmStartBasis* debugws =
    2192           dynamic_cast <const CoinWarmStartBasis*>(solver_->getWarmStart()) ;
    2193         debugws->print() ;
    2194         delete debugws ; }
    2195 #     endif
    2196     }
    2197     newNode->createInfo(this,NULL,NULL,NULL,NULL,0,0) ;
    2198     newNode->nodeInfo()->addCuts(cuts,
    2199                                  newNode->numberBranches(),whichGenerator_) ;
    2200   }
    2201 /*
    2202   Continuous data to be used later
    2203 */
    2204   continuousObjective_ = solver_->getObjValue()*solver_->getObjSense();
    2205   continuousInfeasibilities_ = 0 ;
    2206   if (newNode)
    2207   { continuousObjective_ = newNode->objectiveValue() ;
    2208     delete [] continuousSolution_;
    2209     continuousSolution_ = CoinCopyOfArray(solver_->getColSolution(),
    2210                                              numberColumns);
    2211     continuousInfeasibilities_ = newNode->numberUnsatisfied() ; }
    2212 /*
    2213   Bound may have changed so reset in objects
    2214 */
    2215   { int i ;
    2216     for (i = 0;i < numberObjects_;i++)
    2217       object_[i]->resetBounds() ; }
    2218   stoppedOnGap_ = false ;
    2219 /*
    2220   Feasible? Then we should have either a live node prepped for future
    2221   expansion (indicated by variable() >= 0), or (miracle of miracles) an
    2222   integral solution at the root node.
    2223 
    2224   initializeInfo sets the reference counts in the nodeInfo object.  Since
    2225   this node is still live, push it onto the heap that holds the live set.
    2226 */
    2227   double bestValue = 0.0 ;
    2228   if (newNode) {
    2229     bestValue = newNode->objectiveValue();
    2230     if (newNode->variable() >= 0) {
    2231       newNode->initializeInfo() ;
    2232       tree_->push(newNode) ;
    2233       if (statistics_) {
    2234         if (numberNodes2_==maximumStatistics_) {
    2235           maximumStatistics_ = 2*maximumStatistics_;
    2236           CbcStatistics ** temp = new CbcStatistics * [maximumStatistics_];
    2237           memset(temp,0,maximumStatistics_*sizeof(CbcStatistics *));
    2238           memcpy(temp,statistics_,numberNodes2_*sizeof(CbcStatistics *));
    2239           delete [] statistics_;
    2240           statistics_=temp;
    2241         }
    2242         assert (!statistics_[numberNodes2_]);
    2243         statistics_[numberNodes2_]=new CbcStatistics(newNode);
    2244       }
    2245       numberNodes2_++;
    2246 #     ifdef CHECK_NODE
    2247       printf("Node %x on tree\n",newNode) ;
    2248 #     endif
    2249     } else {
    2250       // continuous is integer
    2251       double objectiveValue = newNode->objectiveValue();
    2252       setBestSolution(CBC_SOLUTION,objectiveValue,
    2253                       solver_->getColSolution()) ;
    2254       delete newNode ;
    2255       newNode = NULL ;
    2256     }
    2257   }
    2258 
    2259   if (printFrequency_ <= 0) {
    2260     printFrequency_ = 1000 ;
    2261     if (getNumCols() > 2000)
    2262       printFrequency_ = 100 ;
    2263   }
    2264   /*
    2265     It is possible that strong branching fixes one variable and then the code goes round
    2266     again and again.  This can take too long.  So we need to warn user - just once.
    2267   */
    2268   numberLongStrong_=0;
    2269 /*
    2270   At last, the actual branch-and-cut search loop, which will iterate until
    2271   the live set is empty or we hit some limit (integrality gap, time, node
    2272   count, etc.). The overall flow is to rebuild a subproblem, reoptimise using
    2273   solveWithCuts(), choose a branching pattern with chooseBranch(), and finally
    2274   add the node to the live set.
    2275 
    2276   The first action is to winnow the live set to remove nodes which are worse
    2277   than the current objective cutoff.
    2278 */
    2279   while (!tree_->empty()) {
    2280     if (cutoff > getCutoff()) {
    2281       double newCutoff = getCutoff();
    2282       if (analyzeResults_) {
    2283         // see if we could fix any (more)
    2284         int n=0;
    2285         double * newLower = analyzeResults_;
    2286         double * objLower = newLower+numberIntegers_;
    2287         double * newUpper = objLower+numberIntegers_;
    2288         double * objUpper = newUpper+numberIntegers_;
    2289         for (int i=0;i<numberIntegers_;i++) {
    2290           if (objLower[i]>newCutoff) {
    2291             n++;
    2292             if (objUpper[i]>newCutoff) {
    2293               newCutoff = -COIN_DBL_MAX;
    2294               break;
    2295             }
    2296           } else if (objUpper[i]>newCutoff) {
    2297             n++;
    2298           }
    2299         }
    2300         if (newCutoff==-COIN_DBL_MAX) {
    2301           printf("Root analysis says finished\n");
    2302         } else if (n>numberFixedNow_) {
    2303           printf("%d more fixed by analysis - now %d\n",n-numberFixedNow_,n);
    2304           numberFixedNow_=n;
    2305         }
    2306       }
    2307 #ifdef COIN_USE_CLP
    2308       if (eventHandler) {
    2309         if (!eventHandler->event(ClpEventHandler::solution)) {
    2310           eventHappened_=true; // exit
    2311         }
    2312       }
    2313 #endif
    2314       // Do from deepest
    2315       tree_->cleanTree(this, newCutoff,bestPossibleObjective_) ;
    2316       nodeCompare_->newSolution(this) ;
    2317       nodeCompare_->newSolution(this,continuousObjective_,
    2318                                 continuousInfeasibilities_) ;
    2319       tree_->setComparison(*nodeCompare_) ;
    2320       if (tree_->empty())
    2321         break; // finished
    2322     }
    2323     cutoff = getCutoff() ;
    2324     /*
    2325       Periodic activities: Opportunities to
    2326       + tweak the nodeCompare criteria,
    2327       + check if we've closed the integrality gap enough to quit,
    2328       + print a summary line to let the user know we're working
    2329     */
    2330     if ((numberNodes_%1000) == 0) {
    2331       bool redoTree=nodeCompare_->every1000Nodes(this, numberNodes_) ;
    2332       // redo tree if wanted
    2333       if (redoTree)
    2334         tree_->setComparison(*nodeCompare_) ;
    2335     }
    2336     if ((numberNodes_%printFrequency_) == 0) {
    2337       int j ;
    2338       int nNodes = tree_->size() ;
    2339       bestPossibleObjective_ = 1.0e100 ;
    2340       for (j = 0;j < nNodes;j++) {
    2341         CbcNode * node = tree_->nodePointer(j) ;
    2342         if (node&&node->objectiveValue() < bestPossibleObjective_)
    2343           bestPossibleObjective_ = node->objectiveValue() ;
    2344       }
    2345       messageHandler()->message(CBC_STATUS,messages())
    2346         << numberNodes_<< nNodes<< bestObjective_<< bestPossibleObjective_
    2347         << CoinMessageEol ;
    2348 #ifdef COIN_USE_CLP
    2349       if (eventHandler) {
    2350         if (!eventHandler->event(ClpEventHandler::treeStatus)) {
    2351           eventHappened_=true; // exit
    2352         }
    2353       }
    2354 #endif
    2355     }
    2356     // If no solution but many nodes - signal change in strategy
    2357     if (numberNodes_>2*numberObjects_+1000&&stateOfSearch_!=2)
    2358       stateOfSearch_=3;
    2359     // See if can stop on gap
    2360     double testGap = CoinMax(dblParam_[CbcAllowableGap],
    2361                              CoinMax(fabs(bestObjective_),fabs(bestPossibleObjective_))
    2362                              *dblParam_[CbcAllowableFractionGap]);
    2363     if (bestObjective_-bestPossibleObjective_ < testGap && getCutoffIncrement()>=0.0) {
    2364       stoppedOnGap_ = true ;
    2365     }
    2366 
    2367 #   ifdef CHECK_NODE_FULL
    2368     verifyTreeNodes(tree_,*this) ;
    2369 #   endif
    2370 #   ifdef CHECK_CUT_COUNTS
    2371     verifyCutCounts(tree_,*this) ;
    2372 #   endif
    2373    
    2374     /*
    2375       Now we come to the meat of the loop. To create the active subproblem, we'll
    2376       pop the most promising node in the live set, rebuild the subproblem it
    2377       represents, and then execute the current arm of the branch to create the
    2378       active subproblem.
    2379     */
    2380     CbcNode *node = tree_->bestNode(cutoff) ;
    2381     // Possible one on tree worse than cutoff
    2382     if (!node)
    2383       continue;
    2384     // Solve node
    2385     int status;
    2386     int numberNewNodes;
    2387     CbcNode ** newNodes = solveOneNode(-1,node,numberNewNodes,status);
    2388     // put nodes back on tree
    2389     for (int iPush = 0; iPush<numberNewNodes;iPush++) {
    2390       tree_->push(newNodes[iPush]) ;
    2391     }     
    2392     delete [] newNodes;
    2393     if (status==2) {
    2394       /*
    2395         The next block of code is executed if we've
    2396         aborted because we hit one of the limits. Clean up by deleting the live set
    2397         and break out of the node processing loop.
    2398       */
    2399       tree_->cleanTree(this,-COIN_DBL_MAX,bestPossibleObjective_) ;
    2400       delete nextRowCut_;
    2401       // We need to get rid of node if is has already been popped from tree
    2402       //if (!nodeOnTree&&!stoppedOnGap_&&node!=rootNode)
    2403       //delete node;
    2404       double totalTime = CoinCpuTime()-dblParam_[CbcStartSeconds] ;
    2405       if (stoppedOnGap_) {
    2406         messageHandler()->message(CBC_GAP,messages())
    2407           << bestObjective_-bestPossibleObjective_
    2408           << dblParam_[CbcAllowableGap]
    2409           << dblParam_[CbcAllowableFractionGap]*100.0
    2410           << CoinMessageEol ;
    2411         secondaryStatus_ = 2;
    2412         status_ = 0 ;
    2413       } else if (isNodeLimitReached()) {
    2414         handler_->message(CBC_MAXNODES,messages_) << CoinMessageEol ;
    2415         secondaryStatus_ = 3;
    2416         status_ = 1 ;
    2417       } else if (totalTime >= dblParam_[CbcMaximumSeconds]) {
    2418         handler_->message(CBC_MAXTIME,messages_) << CoinMessageEol ;
    2419         secondaryStatus_ = 4;
    2420         status_ = 1 ;
    2421       } else if (eventHappened_) {
    2422         handler_->message(CBC_EVENT,messages_) << CoinMessageEol ;
    2423         secondaryStatus_ = 5;
    2424         status_ = 5 ;
    2425       } else {
    2426         handler_->message(CBC_MAXSOLS,messages_) << CoinMessageEol ;
    2427         secondaryStatus_ = 6;
    2428         status_ = 1 ;
    2429       }
    2430       break ;
    2431     } else {
    2432       /*
    2433         Delete cuts to get back to the original system.
    2434        
    2435         I'm thinking this is redundant --- the call to addCuts that conditions entry
    2436         to this code block also performs this action.
    2437       */
    2438       int numberToDelete = getNumRows()-numberRowsAtContinuous_ ;
    2439       if (numberToDelete) {
    2440         int * delRows = new int[numberToDelete] ;
    2441         int i ;
    2442         for (i = 0 ; i < numberToDelete ; i++)
    2443           delRows[i] = i+numberRowsAtContinuous_ ;
    2444         solver_->deleteRows(numberToDelete,delRows) ;
    2445         delete [] delRows ;
    2446       }
    2447     }
    2448   }
    2449   /*
    2450     That's it, we've exhausted the search tree, or broken out of the loop because
    2451     we hit some limit on evaluation.
    2452    
    2453     We may have got an intelligent tree so give it one more chance
    2454   */
    2455   // Tell solver we are not in Branch and Cut
    2456   solver_->setHintParam(OsiDoInBranchAndCut,false,OsiHintDo,NULL) ;
    2457   tree_->endSearch();
    2458   //  If we did any sub trees - did we give up on any?
    2459   if ( numberStoppedSubTrees_)
    2460     status_=1;
    2461   if (!status_) {
    2462     bestPossibleObjective_=bestObjective_;
    2463     handler_->message(CBC_END_GOOD,messages_)
    2464       << bestObjective_ << numberIterations_ << numberNodes_
    2465       << CoinMessageEol ;
    2466   } else {
    2467     handler_->message(CBC_END,messages_)
    2468       << bestObjective_ <<bestPossibleObjective_
    2469       << numberIterations_ << numberNodes_
    2470       << CoinMessageEol ;
    2471   }
    2472   if (numberStrongIterations_)
    2473     handler_->message(CBC_STRONG_STATS,messages_)
    2474       << strongInfo_[0] << numberStrongIterations_ << strongInfo_[2]
    2475       << strongInfo_[1] << CoinMessageEol ;
    2476   if (statistics_) {
    2477     // report in some way
    2478     int * lookup = new int[numberObjects_];
    2479     int i;
    2480     for (i=0;i<numberObjects_;i++)
    2481       lookup[i]=-1;
    2482     bool goodIds=true;
    2483     for (i=0;i<numberObjects_;i++) {
    2484       int id = object_[i]->id();
    2485       int iColumn = object_[i]->columnNumber();
    2486       if (iColumn<0)
    2487         iColumn = id+numberColumns;
    2488       if(id>=0&&id<numberObjects_) {
    2489         if (lookup[id]==-1) {
    2490           lookup[id]=iColumn;
    2491         } else {
    2492           goodIds=false;
    2493           break;
    2494         }
    2495       } else {
    2496         goodIds=false;
    2497         break;
    2498       }
    2499     }
    2500     if (!goodIds) {
    2501       delete [] lookup;
    2502       lookup=NULL;
    2503     }
    2504     if (doStatistics==3) {
    2505       printf("  node parent depth column   value                    obj      inf\n");
    2506       for ( i=0;i<numberNodes2_;i++) {
    2507         statistics_[i]->print(lookup);
    2508       }
    2509     }
    2510     if (doStatistics>1) {
    2511       // Find last solution
    2512       int k;
    2513       for (k=numberNodes2_-1;k>=0;k--) {
    2514         if (statistics_[k]->endingObjective()!=COIN_DBL_MAX&&
    2515             !statistics_[k]->endingInfeasibility())
    2516           break;
    2517       }
    2518       if (k>=0) {
    2519         int depth=statistics_[k]->depth();
    2520         int * which = new int[depth+1];
    2521         for (i=depth;i>=0;i--) {
    2522           which[i]=k;
    2523           k=statistics_[k]->parentNode();
    2524         }
    2525         printf("  node parent depth column   value                    obj      inf\n");
    2526         for (i=0;i<=depth;i++) {
    2527           statistics_[which[i]]->print(lookup);
    2528         }
    2529         delete [] which;
    2530       }
    2531     }
    2532     // now summary
    2533     int maxDepth=0;
    2534     double averageSolutionDepth=0.0;
    2535     int numberSolutions=0;
    2536     double averageCutoffDepth=0.0;
    2537     double averageSolvedDepth=0.0;
    2538     int numberCutoff=0;
    2539     int numberDown=0;
    2540     int numberFirstDown=0;
    2541     double averageInfDown=0.0;
    2542     double averageObjDown=0.0;
    2543     int numberCutoffDown=0;
    2544     int numberUp=0;
    2545     int numberFirstUp=0;
    2546     double averageInfUp=0.0;
    2547     double averageObjUp=0.0;
    2548     int numberCutoffUp=0;
    2549     double averageNumberIterations1=0.0;
    2550     double averageValue=0.0;
    2551     for ( i=0;i<numberNodes2_;i++) {
    2552       int depth =  statistics_[i]->depth();
    2553       int way =  statistics_[i]->way();
    2554       double value = statistics_[i]->value();
    2555       double startingObjective =  statistics_[i]->startingObjective();
    2556       int startingInfeasibility = statistics_[i]->startingInfeasibility();
    2557       double endingObjective = statistics_[i]->endingObjective();
    2558       int endingInfeasibility = statistics_[i]->endingInfeasibility();
    2559       maxDepth = CoinMax(depth,maxDepth);
    2560       // Only for completed
    2561       averageNumberIterations1 += statistics_[i]->numberIterations();
    2562       averageValue += value;
    2563       if (endingObjective!=COIN_DBL_MAX&&!endingInfeasibility) {
    2564         numberSolutions++;
    2565         averageSolutionDepth += depth;
    2566       }
    2567       if (endingObjective==COIN_DBL_MAX) {
    2568         numberCutoff++;
    2569         averageCutoffDepth += depth;
    2570         if (way<0) {
    2571           numberDown++;
    2572           numberCutoffDown++;
    2573           if (way==-1)
    2574             numberFirstDown++;
    2575         } else {
    2576           numberUp++;
    2577           numberCutoffUp++;
    2578           if (way==1)
    2579             numberFirstUp++;
    2580         }
    2581       } else {
    2582         averageSolvedDepth += depth;
    2583         if (way<0) {
    2584           numberDown++;
    2585           averageInfDown += startingInfeasibility-endingInfeasibility;
    2586           averageObjDown += endingObjective-startingObjective;
    2587           if (way==-1)
    2588             numberFirstDown++;
    2589         } else {
    2590           numberUp++;
    2591           averageInfUp += startingInfeasibility-endingInfeasibility;
    2592           averageObjUp += endingObjective-startingObjective;
    2593           if (way==1)
    2594             numberFirstUp++;
    2595         }
    2596       }
    2597     }
    2598     // Now print
    2599     if (numberSolutions)
    2600       averageSolutionDepth /= (double) numberSolutions;
    2601     int numberSolved = numberNodes2_-numberCutoff;
    2602     double averageNumberIterations2=numberIterations_-averageNumberIterations1
    2603       -numberIterationsAtContinuous;
    2604     if(numberCutoff) {
    2605       averageCutoffDepth /= (double) numberCutoff;
    2606       averageNumberIterations2 /= (double) numberCutoff;
    2607     }
    2608     if (numberNodes2_)
    2609       averageValue /= (double) numberNodes2_;
    2610     if (numberSolved) {
    2611       averageNumberIterations1 /= (double) numberSolved;
    2612       averageSolvedDepth /= (double) numberSolved;
    2613     }
    2614     printf("%d solution(s) were found (by branching) at an average depth of %g\n",
    2615            numberSolutions,averageSolutionDepth);
    2616     printf("average value of variable being branched on was %g\n",
    2617            averageValue);
    2618     printf("%d nodes were cutoff at an average depth of %g with iteration count of %g\n",
    2619            numberCutoff,averageCutoffDepth,averageNumberIterations2);
    2620     printf("%d nodes were solved at an average depth of %g with iteration count of %g\n",
    2621            numberSolved,averageSolvedDepth,averageNumberIterations1);
    2622     if (numberDown) {
    2623       averageInfDown /= (double) numberDown;
    2624       averageObjDown /= (double) numberDown;
    2625     }
    2626     printf("Down %d nodes (%d first, %d second) - %d cutoff, rest decrease numinf %g increase obj %g\n",
    2627            numberDown,numberFirstDown,numberDown-numberFirstDown,numberCutoffDown,
    2628            averageInfDown,averageObjDown);
    2629     if (numberUp) {
    2630       averageInfUp /= (double) numberUp;
    2631       averageObjUp /= (double) numberUp;
    2632     }
    2633     printf("Up %d nodes (%d first, %d second) - %d cutoff, rest decrease numinf %g increase obj %g\n",
    2634            numberUp,numberFirstUp,numberUp-numberFirstUp,numberCutoffUp,
    2635            averageInfUp,averageObjUp);
    2636     for ( i=0;i<numberNodes2_;i++)
    2637       delete statistics_[i];
    2638     delete [] statistics_;
    2639     statistics_=NULL;
    2640     maximumStatistics_=0;
    2641     delete [] lookup;
    2642   }
    2643 /*
    2644   If we think we have a solution, restore and confirm it with a call to
    2645   setBestSolution().  We need to reset the cutoff value so as not to fathom
    2646   the solution on bounds.  Note that calling setBestSolution( ..., true)
    2647   leaves the continuousSolver_ bounds vectors fixed at the solution value.
    2648 
    2649   Running resolve() here is a failsafe --- setBestSolution has already
    2650   reoptimised using the continuousSolver_. If for some reason we fail to
    2651   prove optimality, run the problem again after instructing the solver to
    2652   tell us more.
    2653 
    2654   If all looks good, replace solver_ with continuousSolver_, so that the
    2655   outside world will be able to obtain information about the solution using
    2656   public methods.
    2657 */
    2658   if (bestSolution_) {
    2659     setCutoff(1.0e50) ; // As best solution should be worse than cutoff
    2660     phase_=5;
    2661     setBestSolution(CBC_SOLUTION,bestObjective_,bestSolution_,true) ;
    2662     continuousSolver_->resolve() ;
    2663     if (!continuousSolver_->isProvenOptimal()) {
    2664       continuousSolver_->messageHandler()->setLogLevel(2) ;
    2665       continuousSolver_->initialSolve() ;
    2666     }
    2667     delete solver_ ;
    2668     solver_ = continuousSolver_ ;
    2669     setPointers(solver_);
    2670     continuousSolver_ = NULL ;
    2671   }
    2672   /*
    2673     Clean up dangling objects. continuousSolver_ may already be toast.
    2674   */
    2675   delete [] whichGenerator_ ;
    2676   whichGenerator_=NULL;
    2677   delete [] lowerBefore ;
    2678   delete [] upperBefore ;
    2679   delete [] walkback_ ;
    2680   walkback_ = NULL ;
    2681   delete [] addedCuts_ ;
    2682   addedCuts_ = NULL ;
    2683   // Get rid of characteristics
    2684   solverCharacteristics_=NULL;
    2685   if (continuousSolver_) {
    2686     delete continuousSolver_ ;
    2687     continuousSolver_ = NULL ;
    2688   }
    2689   /*
    2690     Destroy global cuts by replacing with an empty OsiCuts object.
    2691   */
    2692   globalCuts_= OsiCuts() ;
    2693   if (strategy_&&strategy_->preProcessState()>0) {
    2694     // undo preprocessing
    2695     CglPreProcess * process = strategy_->process();
    2696     assert (process);
    2697     int n = originalSolver->getNumCols();
    2698     if (bestSolution_) {
    2699       delete [] bestSolution_;
    2700       bestSolution_ = new double [n];
    2701       process->postProcess(*solver_);
    2702     }
    2703     strategy_->deletePreProcess();
    2704     // Solution now back in originalSolver
    2705     delete solver_;
    2706     solver_=originalSolver;
    2707     if (bestSolution_)
    2708       memcpy(bestSolution_,solver_->getColSolution(),n*sizeof(double));
    2709   }
    2710   return ;
    2711 }
    2712 /* Input one node output N nodes to put on tree and optional solution update
    2713    This should be able to operate in parallel so is given a solver and is const(ish)
    2714    However we will need to keep an array of solver_ and bases and more
    2715    status is 0 for normal, 1 if solution, 2 if should stop
    2716    Calling code should always push nodes back on tree
    2717  */
    2718 CbcNode **
    2719 CbcModel::solveOneNode(int whichSolver,CbcNode * node,
    2720                     int & numberNodesOutput, int & status)
    2721 {
    2722   numberNodesOutput=0;
    2723   status=0;
    2724   // Maximum number of new nodes will be known
    2725   // For normal case can be 2 (old + new)
    2726   int maximumNewNodes=2+(1<<sizeMiniTree_);
    2727   CbcNode ** newNodes = new CbcNode * [maximumNewNodes];
    2728  
    2729   currentNode_=node; // so can be accessed elsewhere
    2730 #ifdef CBC_DEBUG
    2731   printf("%d unsat, way %d, obj %g est %g\n",
    2732          node->numberUnsatisfied(),node->way(),node->objectiveValue(),
    2733          node->guessedObjectiveValue());
    2734 #endif
    2735   // Save clone in branching decision
    2736   if(branchingMethod_)
    2737     branchingMethod_->saveBranchingObject(node->modifiableBranchingObject());
    2738   // Say not on optimal path
    2739   bool onOptimalPath=false;
    2740 #   ifdef CHECK_NODE
    2741   /*
    2742     WARNING: The use of integerVariable_[*] here will break as soon as the
    2743     branching object is something other than an integer variable.
    2744     This needs some thought.
    2745   */
    2746   printf("Node %x popped from tree - %d left, %d count\n",node,
    2747          node->nodeInfo()->numberBranchesLeft(),
    2748          node->nodeInfo()->numberPointingToThis()) ;
    2749   printf("\tdepth = %d, z =  %g, unsat = %d, var = %d.\n",
    2750          node->depth(),node->objectiveValue(),
    2751          node->numberUnsatisfied(),
    2752          integerVariable_[node->variable()]) ;
    2753 #   endif
    2754  
    2755   /*
    2756     Rebuild the subproblem for this node:        Call addCuts() to adjust the model
    2757     to recreate the subproblem for this node (set proper variable bounds, add
    2758     cuts, create a basis).  This may result in the problem being fathomed by
    2759     bound or infeasibility. Returns 1 if node is fathomed.
    2760     Execute the current arm of the branch: If the problem survives, save the
    2761     resulting variable bounds and call branch() to modify variable bounds
    2762     according to the current arm of the branching object. If we're processing
    2763     the final arm of the branching object, flag the node for removal from the
    2764     live set.
    2765   */
    2766   CbcNodeInfo * nodeInfo = node->nodeInfo() ;
    2767   // empty basis
    2768   CoinWarmStartBasis * lastws = new CoinWarmStartBasis();
    2769   int numberColumns = getNumCols() ;
    2770   double * lowerBefore = new double[numberColumns];
    2771   double * upperBefore = new double[numberColumns];
    2772   if (!addCuts(node,lastws,numberFixedNow_>numberFixedAtRoot_)) {
    2773     int i ;
    2774     const double * lower = getColLower() ;
    2775     const double * upper = getColUpper() ;
    2776     for (i = 0 ; i < numberColumns ; i++) {
    2777       lowerBefore[i]= lower[i] ;
    2778       upperBefore[i]= upper[i] ;
    2779     }
    2780     bool deleteNode ;
    2781     if (node->branch()) {
    2782       // set nodenumber correctly
    2783       node->nodeInfo()->setNodeNumber(numberNodes2_);
    2784       if (statistics_) {
    2785         if (numberNodes2_==maximumStatistics_) {
    2786           maximumStatistics_ = 2*maximumStatistics_;
    2787           CbcStatistics ** temp = new CbcStatistics * [maximumStatistics_];
    2788           memset(temp,0,maximumStatistics_*sizeof(CbcStatistics *));
    2789           memcpy(temp,statistics_,numberNodes2_*sizeof(CbcStatistics *));
    2790           delete [] statistics_;
    2791           statistics_=temp;
    2792         }
    2793         assert (!statistics_[numberNodes2_]);
    2794         statistics_[numberNodes2_]=new CbcStatistics(node);
    2795       }
    2796       numberNodes2_++;
    2797       newNodes[numberNodesOutput++]=node;
    2798       deleteNode = false ;
    2799 #       ifdef CHECK_NODE
    2800       printf("Node %x pushed back on tree - %d left, %d count\n",node,
    2801              nodeInfo->numberBranchesLeft(),
    2802              nodeInfo->numberPointingToThis()) ;
    2803 #       endif
    2804     } else {
    2805       deleteNode = true ;
    2806     }
    2807    
    2808     if ((specialOptions_&1)!=0) {
    2809       /*
    2810         This doesn't work as intended --- getRowCutDebugger will return null
    2811         unless the current feasible solution region includes the optimal solution
    2812         that RowCutDebugger knows. There's no way to tell inactive from off the
    2813         optimal path.
    2814       */
    2815       const OsiRowCutDebugger *debugger = solver_->getRowCutDebugger() ;
    2816       if (debugger) {
    2817         onOptimalPath=true;
    2818         printf("On optimal path\n") ;
    2819       }
    2820     }
    2821     /*
    2822       Reoptimize, possibly generating cuts and/or using heuristics to find
    2823       solutions.  Cut reference counts are unaffected unless we lose feasibility,
    2824       in which case solveWithCuts() will make the adjustment.
    2825     */
    2826     phase_=2;
    2827     OsiCuts cuts = OsiCuts() ;
    2828     int saveNumber = numberIterations_;
    2829     if(solverCharacteristics_->solutionAddsCuts()) {
    2830       feasible=resolve();
    2831       if (feasible) {
    2832         int iObject ;
    2833         int preferredWay ;
    2834         int numberUnsatisfied = 0 ;
    2835         memcpy(currentSolution_,solver_->getColSolution(),
    2836                numberColumns*sizeof(double)) ;
    2837        
    2838         for (iObject = 0 ; iObject < numberObjects_ ; iObject++) {
    2839           double infeasibility =
    2840             object_[iObject]->infeasibility(preferredWay) ;
    2841           if (infeasibility ) numberUnsatisfied++ ;
    2842         }
    2843         if (numberUnsatisfied)   {
    2844           feasible = solveWithCuts(cuts,maximumCutPassesAtRoot_,
    2845                                    NULL);
    2846         } else {
    2847           // may generate cuts and turn the solution
    2848           //to an infeasible one
    2849           feasible = solveWithCuts(cuts, 1,
    2850                                    NULL);
    2851           currentNumberCuts_ = cuts.sizeRowCuts();
    2852             if (currentNumberCuts_ >= maximumNumberCuts_) {
    2853               maximumNumberCuts_ = currentNumberCuts;
    2854               delete [] addedCuts_;
    2855               addedCuts_ = new CbcCountRowCut * [maximumNumberCuts_];
    2856             }
    2857         }
    2858         // check extra info on feasibility
    2859         if (!solverCharacteristics_->mipFeasible())
    2860           feasible = false;
    2861       }
    2862     } else {
    2863       // normal
    2864       feasible = solveWithCuts(cuts,maximumCutPasses_,node);
    2865     }
    2866     if (statistics_) {
    2867       assert (numberNodes2_);
    2868       assert (statistics_[numberNodes2_-1]);
    2869       assert (statistics_[numberNodes2_-1]->node()==numberNodes2_-1);
    2870       statistics_[numberNodes2_-1]->endOfBranch(numberIterations_-saveNumber,
    2871                                                feasible ? solver_->getObjValue()
    2872                                                : COIN_DBL_MAX);
    2873     }
    2874     /*
    2875       Check for abort on limits: node count, solution count, time, integrality gap.
    2876     */
    2877     double totalTime = CoinCpuTime()-dblParam_[CbcStartSeconds] ;
    2878     if (numberNodes_ < intParam_[CbcMaxNumNode] &&
    2879         numberSolutions_ < intParam_[CbcMaxNumSol] &&
    2880         totalTime < dblParam_[CbcMaximumSeconds] &&
    2881         !stoppedOnGap_&&!eventHappened_) {
    2882       /*
    2883         Are we still feasible? If so, create a node and do the work to attach a
    2884         branching object, reoptimising as needed if chooseBranch() identifies
    2885         monotone objects.
    2886        
    2887         Finally, attach a partial nodeInfo object and store away any cuts that we
    2888         created back in solveWithCuts. addCuts() will also deal with the cut
    2889         reference counts.
    2890       */
    2891       if (onOptimalPath)
    2892         assert (feasible);
    2893       bool checkingNode=false;
    2894       int anyAction;
    2895       double direction =  dblParam_[CbcOptimizationDirection];
    2896       bool resolved = false;
    2897       CbcNode * newNode=NULL;
    2898       if (feasible) {
    2899         newNode = new CbcNode ;
    2900         // Set objective value (not so obvious if NLP etc)
    2901         setObjectiveValue(newNode,node);
    2902         anyAction =-1 ;
    2903         resolved = false ;
    2904         if (newNode->objectiveValue() >= getCutoff())
    2905           anyAction=-2;
    2906         // only allow twenty passes
    2907         int numberPassesLeft=20;
    2908         checkingNode=true;
    2909         OsiSolverBranch * branches=NULL;
    2910         while (anyAction == -1) {
    2911           // Set objective value (not so obvious if NLP etc)
    2912           setObjectiveValue(newNode,node);
    2913           if (numberBeforeTrust_==0 ) {
    2914             anyAction = newNode->chooseBranch(this,node,numberPassesLeft) ;
    2915           } else {
    2916             anyAction = newNode->chooseDynamicBranch(this,node,branches,numberPassesLeft) ;
    2917             if (anyAction==-3)
    2918               anyAction = newNode->chooseBranch(this,node,numberPassesLeft) ; // dynamic did nothing
    2919           }
    2920           if (onOptimalPath)
    2921             assert (anyAction!=-2); // can be useful but gives false positives on strong
    2922           numberPassesLeft--;
    2923           if (numberPassesLeft<=-1) {
    2924             if (!numberLongStrong_)
    2925               messageHandler()->message(CBC_WARNING_STRONG,
    2926                                         messages()) << CoinMessageEol ;
    2927             numberLongStrong_++;
    2928           }
    2929           if (anyAction == -1) {
    2930             // can do quick optimality check
    2931             int easy=2;
    2932             solver_->setHintParam(OsiDoInBranchAndCut,true,OsiHintDo,&easy) ;
    2933             feasible = resolve() ;
    2934             solver_->setHintParam(OsiDoInBranchAndCut,true,OsiHintDo,NULL) ;
    2935             resolved = true ;
    2936             if (problemFeasibility_->feasible(this,0)<0) {
    2937               feasible=false; // pretend infeasible
    2938             }
    2939             if (feasible) {
    2940               // Set objective value (not so obvious if NLP etc)
    2941               setObjectiveValue(newNode,node);
    2942               reducedCostFix() ;
    2943               if (newNode->objectiveValue() >= getCutoff())
    2944                 anyAction=-2;
    2945             } else {
    2946               anyAction = -2 ;
    2947             }
    2948           }
    2949         }
    2950         if (anyAction >= 0) {
    2951           if (resolved) {
    2952             bool needValidSolution = (newNode->variable() < 0) ;
    2953             takeOffCuts(cuts,needValidSolution,NULL) ;
    2954 #             ifdef CHECK_CUT_COUNTS
    2955             { printf("Number of rows after chooseBranch fix (node)"
    2956                      "(active only) %d\n",
    2957                      numberRowsAtContinuous_+numberNewCuts_+
    2958                      numberOldActiveCuts_) ;
    2959             const CoinWarmStartBasis* debugws =
    2960               dynamic_cast<const CoinWarmStartBasis*>
    2961               (solver_->getWarmStart()) ;
    2962             debugws->print() ;
    2963             delete debugws ; }
    2964 #             endif
    2965           }
    2966           if (anyAction==0||!newNode->numberUnsatisfied()) {
    2967             delete [] branches;
    2968             newNode->createInfo(this,node,lastws,lowerBefore,upperBefore,
    2969                                 numberOldActiveCuts_,numberNewCuts_) ;
    2970             if (newNode->numberUnsatisfied()) {
    2971               newNode->initializeInfo() ;
    2972               newNode->nodeInfo()->addCuts(cuts,newNode->numberBranches(),
    2973                                            whichGenerator_) ;
    2974             }
    2975           } else {
    2976             // mini tree
    2977             int numberBranches=anyAction;
    2978             int numberResults=1<<numberBranches;
    2979             OsiSolverResult * result = new OsiSolverResult[numberResults];
    2980             double * lowerBefore2 = new double[numberColumns];
    2981             double * upperBefore2 = new double[numberColumns];
    2982             int i ;
    2983             const double * lower = solver_->getColLower() ;
    2984             const double * upper = solver_->getColUpper() ;
    2985             for (i = 0 ; i < numberColumns ; i++) {
    2986               lowerBefore2[i]= lower[i] ;
    2987               upperBefore2[i]= upper[i] ;
    2988             }
    2989             int numberIterations;
    2990             int numberSolves;
    2991             int numberGood = solver_->solveBranches(numberBranches,branches,result,
    2992                                                     numberSolves,numberIterations);
    2993             numberIterations_ += numberIterations;
    2994             // Add in solves needed to get to leaves
    2995             numberNodes_ += (numberSolves-numberGood);
    2996             int numberCutsAdd=-1; // We will be taking off one anyway
    2997             int saveMini = sizeMiniTree_;
    2998             sizeMiniTree_=0;
    2999             int saveNumber = numberNodesOutput;
    3000             for (int iResult=0;iResult<numberGood;iResult++) {
    3001               if (result[iResult].objectiveValue()<1.0e50) {
    3002                 // put in correct bounds etc
    3003                 solver_->setColLower(lowerBefore2);
    3004                 solver_->setColUpper(upperBefore2);
    3005                 result[iResult].restoreResult(*solver_);
    3006                 numberNodes_++;
    3007 #if 0
    3008                 // need to tell solver that current factorization is no good
    3009                 // should be better way
    3010 #ifdef COIN_USE_CLP
    3011                 OsiClpSolverInterface * clpSolver
    3012                   = dynamic_cast<OsiClpSolverInterface *> (solver_);
    3013                 if (clpSolver)
    3014                   clpSolver->getModelPtr()->setWhatsChanged(clpSolver->getModelPtr()->whatsChanged()&(~512));
    3015 #endif
    3016                 solver_->resolve();
    3017                 assert (!solver_->getIterationCount());
    3018                 printf("res obj %g was %g\n",solver_->getObjValue(),
    3019                        result[iResult].objectiveValue());
    3020 #endif
    3021                 bool checkingNode=false;
    3022                 bool feasible = true;
    3023                 int anyAction;
    3024                 CbcNode * newNode2= new CbcNode ;
    3025                 newNode2->setObjectiveValue(result[iResult].objectiveValue()) ;
    3026                 anyAction =-1 ;
    3027                 // only allow twenty passes
    3028                 int numberPassesLeft=20;
    3029                 checkingNode=true;
    3030                 OsiSolverBranch * branches=NULL;
    3031                 while (anyAction == -1) {
    3032                   if (numberBeforeTrust_==0 ) {
    3033                     anyAction = newNode2->chooseBranch(this,node,numberPassesLeft) ;
    3034                   } else {
    3035                     anyAction = newNode2->chooseDynamicBranch(this,node,branches,numberPassesLeft) ;
    3036                     if (anyAction==-3)
    3037                       anyAction = newNode2->chooseBranch(this,node,numberPassesLeft) ; // dynamic did nothing
    3038                   }
    3039                   numberPassesLeft--;
    3040                   if (anyAction == -1) {
    3041                     // can do quick optimality check
    3042                     int easy=2;
    3043                     solver_->setHintParam(OsiDoInBranchAndCut,true,OsiHintDo,&easy) ;
    3044                     feasible = resolve() ;
    3045                     solver_->setHintParam(OsiDoInBranchAndCut,true,OsiHintDo,NULL) ;
    3046                     if (problemFeasibility_->feasible(this,0)<0) {
    3047                       feasible=false; // pretend infeasible
    3048                     }
    3049                     if (feasible) {
    3050                       // Set objective value (not so obvious if NLP etc)
    3051                       setObjectiveValue(newNode2,node);
    3052                       reducedCostFix() ;
    3053                       if (newNode2->objectiveValue() >= getCutoff())
    3054                         anyAction=-2;
    3055                     } else {
    3056                       anyAction = -2 ;
    3057                     }
    3058                   }
    3059                 }
    3060                 // May have slipped through i.e. anyAction == 0 and objective above cutoff
    3061                 if ( anyAction ==0 ) {
    3062                   assert (newNode2);
    3063                   if (newNode2->objectiveValue() >= getCutoff())
    3064                     anyAction = -2; // say bad after all
    3065                 }
    3066                 if (anyAction >= 0) {
    3067                   if (anyAction==0||!newNode2->numberUnsatisfied()) {
    3068                     newNode2->createInfo(this,node,lastws,lowerBefore,upperBefore,
    3069                                         numberOldActiveCuts_,numberNewCuts_) ;
    3070                     if (newNode2->numberUnsatisfied()) {
    3071                       newNode2->initializeInfo() ;
    3072                       newNode2->nodeInfo()->addCuts(cuts,newNode2->numberBranches(),
    3073                                                    whichGenerator_) ;
    3074                     }
    3075                   }
    3076                 }
    3077                 /*
    3078                   If we end up infeasible, we can delete the new node immediately. Since this
    3079                   node won't be needing the cuts we collected, decrement the reference counts.
    3080                   If we are feasible, then we'll be placing this node into the live set, so
    3081                   increment the reference count in the current (parent) nodeInfo.
    3082                 */
    3083                 if (anyAction == -2) {
    3084                   delete newNode2 ;
    3085                   newNode2 = NULL ;
    3086 #if 0
    3087                   // say strong doing well
    3088                   if (checkingNode)
    3089                     setSpecialOptions(specialOptions_|8);
    3090 #endif
    3091 #if 0
    3092                   for (i = 0 ; i < currentNumberCuts_ ; i++) {
    3093                     if (addedCuts_[i]) {
    3094                       if (!addedCuts_[i]->decrement(1)) {
    3095                         delete addedCuts_[i] ;
    3096                         addedCuts_[i]=NULL;
    3097                       }
    3098                     }
    3099                   }
    3100 #endif
    3101                 } else {
    3102                   nodeInfo->increment() ;
    3103 #if 0
    3104                   if ((numberNodes_%20)==0) {
    3105                     // say strong not doing as well
    3106                     setSpecialOptions(specialOptions_&~8);
    3107                   }
    3108 #endif
    3109                 }
    3110                 /*
    3111                   At this point, there are three possibilities:
    3112                   * We have a live node (variable() >= 0) which will require further
    3113                   branching to resolve. Before we push it onto the search tree, try for
    3114                   a heuristic solution.
    3115                   * We have a solution, in which case newNode is non-null but we have no
    3116                   branching variable. Decrement the cut counts and save the solution.
    3117                   * The node was found to be infeasible, in which case it's already been
    3118                   deleted, and newNode is null.
    3119                  
    3120                 */
    3121 #ifdef COIN_USE_CLP
    3122                 if (eventHandler()) {
    3123                   if (!eventHandler()->event(ClpEventHandler::node)) {
    3124                     eventHappened_=true; // exit
    3125                   }
    3126                 }
    3127 #endif
    3128                 assert (!newNode2 || newNode2->objectiveValue() <= getCutoff()) ;
    3129                 if (statistics_) {
    3130                   assert (numberNodes2_);
    3131                   assert (statistics_[numberNodes2_-1]);
    3132                   assert (statistics_[numberNodes2_-1]->node()==numberNodes2_-1);
    3133                   if (newNode2)
    3134                     statistics_[numberNodes2_-1]->updateInfeasibility(newNode2->numberUnsatisfied());
    3135                   else
    3136                     statistics_[numberNodes2_-1]->sayInfeasible();
    3137                 }
    3138                 if (newNode2) {
    3139                   if (newNode2->variable() >= 0) {
    3140                     handler_->message(CBC_BRANCH,messages_)
    3141                       << numberNodes_<< newNode2->objectiveValue()
    3142                       << newNode2->numberUnsatisfied()<< newNode2->depth()
    3143                       << CoinMessageEol ;
    3144                     // Increment cut counts
    3145                     numberCutsAdd += newNode2->numberBranches();
    3146                     double estValue = newNode2->guessedObjectiveValue() ;
    3147                     int found = -1 ;
    3148                     double * newSolution = new double [numberColumns] ;
    3149                     double heurValue = getCutoff() ;
    3150                     int iHeur ;
    3151                     for (iHeur = 0 ; iHeur < numberHeuristics_ ; iHeur++) {
    3152                       double saveValue = heurValue ;
    3153                       int ifSol = heuristic_[iHeur]->solution(heurValue,newSolution) ;
    3154                       if (ifSol > 0) {
    3155                         // new solution found
    3156                         found = iHeur ;
    3157                         incrementUsed(newSolution);
    3158                       } else if (ifSol < 0) {   // just returning an estimate
    3159                         estValue = CoinMin(heurValue,estValue) ;
    3160                         heurValue = saveValue ;
    3161                       }
    3162                     }
    3163                     if (found >= 0) {
    3164                       setBestSolution(CBC_ROUNDING,heurValue,newSolution) ;
    3165                       lastHeuristic_ = heuristic_[found];
    3166                       status=1;
    3167                     }
    3168                     delete [] newSolution ;
    3169                     newNode2->setGuessedObjectiveValue(estValue) ;
    3170                     newNodes[numberNodesOutput++] = newNode2 ;
    3171                     nodeInfo->increment();
    3172                     if (statistics_) {
    3173                       if (numberNodes2_==maximumStatistics_) {
    3174                         maximumStatistics_ = 2*maximumStatistics_;
    3175                         CbcStatistics ** temp = new CbcStatistics * [maximumStatistics_];
    3176                         memset(temp,0,maximumStatistics_*sizeof(CbcStatistics *));
    3177                         memcpy(temp,statistics_,numberNodes2_*sizeof(CbcStatistics *));
    3178                         delete [] statistics_;
    3179                         statistics_=temp;
    3180                       }
    3181                       assert (!statistics_[numberNodes2_]);
    3182                       statistics_[numberNodes2_]=new CbcStatistics(newNode2);
    3183                     }
    3184                     numberNodes2_++;
    3185 #           ifdef CHECK_NODE
    3186                     printf("Node %x pushed on tree c\n",newNode2) ;
    3187 #           endif
    3188                   } else {
    3189 #if 0
    3190                     for (i = 0 ; i < currentNumberCuts_ ; i++) {
    3191                       if (addedCuts_[i]) {
    3192                         if (!addedCuts_[i]->decrement(1)) {
    3193                           delete addedCuts_[i] ;
    3194                           addedCuts_[i]=NULL;
    3195                         }
    3196                       }
    3197                     }
    3198 #endif
    3199                     double objectiveValue = newNode2->objectiveValue();
    3200                     setBestSolution(CBC_SOLUTION,objectiveValue,
    3201                                     solver_->getColSolution()) ;
    3202                     lastHeuristic_ = NULL;
    3203                     incrementUsed(solver_->getColSolution());
    3204                     //assert(nodeInfo->numberPointingToThis() <= 2) ;
    3205                     // avoid accidental pruning, if newNode was final branch arm
    3206                     nodeInfo->increment();
    3207                     delete newNode2 ;
    3208                     nodeInfo->decrement() ;
    3209                     status=1;
    3210                   }
    3211                 }
    3212               }
    3213             }
    3214             if (numberCutsAdd>0) {
    3215               for (i = 0;i < currentNumberCuts_;i++) {
    3216                 if (addedCuts_[i]) {
    3217 #               ifdef CHECK_CUT_COUNTS
    3218                   printf("Count on cut %x increased by %d\n",addedCuts_[i],
    3219                          numberCutsAdd) ;
    3220 #               endif
    3221                   addedCuts_[i]->increment(numberCutsAdd) ;
    3222                 }
    3223               }
    3224             }     
    3225             sizeMiniTree_=saveMini;
    3226             delete [] result;
    3227             delete [] branches;
    3228             delete newNode ;
    3229             newNode = NULL ;
    3230             delete [] lowerBefore2;
    3231             delete [] upperBefore2;
    3232             if (saveNumber < numberNodesOutput)
    3233               anyAction = -4;
    3234             else
    3235               anyAction=-2;
    3236           }
    3237         }
    3238       } else {
    3239         anyAction = -2 ;
    3240       }
    3241 #if 0
    3242       if (numberNodesOutput) {
    3243         if (!sizeMiniTree_)
    3244           assert(newNode== newNodes[numberNodesOutput-1]);
    3245         newNode= newNodes[numberNodesOutput-1];
    3246       } else {
    3247         assert (!newNode);
    3248       }
    3249 #endif
    3250       // May have slipped through i.e. anyAction == 0 and objective above cutoff
    3251       if ( anyAction >=0 ) {
    3252         assert (newNode);
    3253         if (newNode->objectiveValue() >= getCutoff())
    3254           anyAction = -2; // say bad after all
    3255       }
    3256       /*
    3257         If we end up infeasible, we can delete the new node immediately. Since this
    3258         node won't be needing the cuts we collected, decrement the reference counts.
    3259         If we are feasible, then we'll be placing this node into the live set, so
    3260         increment the reference count in the current (parent) nodeInfo.
    3261       */
    3262       if (anyAction == -2) {
    3263         delete newNode ;
    3264         newNode = NULL ;
    3265         // say strong doing well
    3266         if (checkingNode)
    3267           setSpecialOptions(specialOptions_|8);
    3268         for (i = 0 ; i < currentNumberCuts_ ; i++) {
    3269           if (addedCuts_[i]) {
    3270             if (!addedCuts_[i]->decrement(1)) {
    3271               delete addedCuts_[i] ;
    3272               addedCuts_[i]=NULL;
    3273             }
    3274           }
    3275         }
    3276       } else if (anyAction>=0) {
    3277         nodeInfo->increment() ;
    3278         if ((numberNodes_%20)==0) {
    3279           // say strong not doing as well
    3280           setSpecialOptions(specialOptions_&~8);
    3281         }
    3282       }
    3283       /*
    3284         At this point, there are three possibilities:
    3285         * We have a live node (variable() >= 0) which will require further
    3286         branching to resolve. Before we push it onto the search tree, try for
    3287         a heuristic solution.
    3288         * We have a solution, in which case newNode is non-null but we have no
    3289         branching variable. Decrement the cut counts and save the solution.
    3290         * The node was found to be infeasible, in which case it's already been
    3291         deleted, and newNode is null.
    3292        
    3293       */
    3294 #ifdef COIN_USE_CLP
    3295       if (eventHandler()) {
    3296         if (!eventHandler()->event(ClpEventHandler::node)) {
    3297           eventHappened_=true; // exit
    3298         }
    3299       }
    3300 #endif
    3301       assert (!newNode || newNode->objectiveValue() <= getCutoff()) ;
    3302       if (statistics_) {
    3303         assert (numberNodes2_);
    3304         assert (statistics_[numberNodes2_-1]);
    3305         assert (statistics_[numberNodes2_-1]->node()==numberNodes2_-1);
    3306         if (newNode)
    3307           statistics_[numberNodes2_-1]->updateInfeasibility(newNode->numberUnsatisfied());
    3308         else
    3309           statistics_[numberNodes2_-1]->sayInfeasible();
    3310       }
    3311       if (newNode) {
    3312         if (newNode->variable() >= 0) {
    3313           handler_->message(CBC_BRANCH,messages_)
    3314             << numberNodes_<< newNode->objectiveValue()
    3315             << newNode->numberUnsatisfied()<< newNode->depth()
    3316             << CoinMessageEol ;
    3317           // Increment cut counts (taking off current)
    3318           int numberLeft = newNode->numberBranches() ;
    3319           for (i = 0;i < currentNumberCuts_;i++) {
    3320             if (addedCuts_[i]) {
    3321 #               ifdef CHECK_CUT_COUNTS
    3322               printf("Count on cut %x increased by %d\n",addedCuts_[i],
    3323                      numberLeft-1) ;
    3324 #               endif
    3325               addedCuts_[i]->increment(numberLeft-1) ;
    3326             }
    3327           }
    3328          
    3329           double estValue = newNode->guessedObjectiveValue() ;
    3330           int found = -1 ;
    3331           double * newSolution = new double [numberColumns] ;
    3332           double heurValue = getCutoff() ;
    3333           int iHeur ;
    3334           for (iHeur = 0 ; iHeur < numberHeuristics_ ; iHeur++) {
    3335             double saveValue = heurValue ;
    3336             int ifSol = heuristic_[iHeur]->solution(heurValue,newSolution) ;
    3337             if (ifSol > 0) {
    3338               // new solution found
    3339               found = iHeur ;
    3340               incrementUsed(newSolution);
    3341             } else if (ifSol < 0) {     // just returning an estimate
    3342               estValue = CoinMin(heurValue,estValue) ;
    3343               heurValue = saveValue ;
    3344             }
    3345           }
    3346           if (found >= 0) {
    3347             setBestSolution(CBC_ROUNDING,heurValue,newSolution) ;
    3348             lastHeuristic_ = heuristic_[found];
    3349             status=1;
    3350           }
    3351           delete [] newSolution ;
    3352           newNode->setGuessedObjectiveValue(estValue) ;
    3353           newNodes[numberNodesOutput++] = newNode ;
    3354           if (statistics_) {
    3355             if (numberNodes2_==maximumStatistics_) {
    3356               maximumStatistics_ = 2*maximumStatistics_;
    3357               CbcStatistics ** temp = new CbcStatistics * [maximumStatistics_];
    3358               memset(temp,0,maximumStatistics_*sizeof(CbcStatistics *));
    3359               memcpy(temp,statistics_,numberNodes2_*sizeof(CbcStatistics *));
    3360               delete [] statistics_;
    3361               statistics_=temp;
    3362             }
    3363             assert (!statistics_[numberNodes2_]);
    3364             statistics_[numberNodes2_]=new CbcStatistics(newNode);
    3365           }
    3366           numberNodes2_++;
    3367 #           ifdef CHECK_NODE
    3368           printf("Node %x pushed on tree c\n",newNode) ;
    3369 #           endif
    3370         } else {
    3371           for (i = 0 ; i < currentNumberCuts_ ; i++) {
    3372             if (addedCuts_[i]) {
    3373               if (!addedCuts_[i]->decrement(1)) {
    3374                 delete addedCuts_[i] ;
    3375                 addedCuts_[i]=NULL;
    3376               }
    3377             }
    3378           }
    3379           double objectiveValue = newNode->objectiveValue();
    3380           setBestSolution(CBC_SOLUTION,objectiveValue,
    3381                           solver_->getColSolution()) ;
    3382           lastHeuristic_ = NULL;
    3383           incrementUsed(solver_->getColSolution());
    3384           //assert(nodeInfo->numberPointingToThis() <= 2) ;
    3385           // avoid accidental pruning, if newNode was final branch arm
    3386           nodeInfo->increment();
    3387           delete newNode ;
    3388           nodeInfo->decrement() ;
    3389           status=1;
    3390         }
    3391       }
    3392       /*
    3393         This node has been completely expanded and can be removed from the live
    3394         set.
    3395       */
    3396       if (deleteNode) 
    3397         delete node ;
    3398     } else {
    3399       // max time etc
    3400       status=2;
    3401       if (deleteNode) 
    3402         delete node ;
    3403     }
    3404   } else {
    3405     // node before branching is infeasible (so no nodes output)
    3406     delete node;
    3407   }
    3408   delete lastws;
    3409   delete [] lowerBefore;
    3410   delete [] upperBefore;
    3411   return newNodes;
    3412 }
    3413 #endif
    34141786
    34151787
     
    49903362  if (node)
    49913363    objectiveValue= node->objectiveValue();
    4992   feasible = resolve() ;
     3364  int returnCode = resolve(node ? node->nodeInfo() : NULL,1);
     3365  feasible = returnCode  != 0 ;
     3366  if (returnCode<0)
     3367    numberTries=0;
    49933368  if (problemFeasibility_->feasible(this,0)<0) {
    49943369    feasible=false; // pretend infeasible
     
    51503525        !solver_->optimalBasisIsAvailable()) {
    51513526      //printf("XXXXYY no opt basis\n");
    5152       resolve();
     3527      resolve(node ? node->nodeInfo() : NULL,3);
    51533528    }
    51543529    if (nextRowCut_) {
     
    52173592#endif
    52183593          if (mustResolve) {
    5219             feasible = resolve() ;
     3594            int returncode = resolve(node ? node->nodeInfo() : NULL,2);
     3595            feasible = returnCode  != 0 ;
     3596            if (returncode<0)
     3597              numberTries=0;
    52203598            if ((specialOptions_&1)!=0) {
    52213599              debugger = solver_->getRowCutDebugger() ;
     
    55233901        delete basis;
    55243902      }
    5525       feasible = resolve() ;
     3903      feasible = resolve(node ? node->nodeInfo() : NULL,2) ;
    55263904      if ( CoinCpuTime()-dblParam_[CbcStartSeconds] > dblParam_[CbcMaximumSeconds] )
    55273905        numberTries=0; // exit
     
    61574535
    61584536
    6159 bool
    6160 CbcModel::resolve()
     4537int
     4538CbcModel::resolve(CbcNodeInfo * parent, int whereFrom)
    61614539{
    61624540  // We may have deliberately added in violated cuts - check to avoid message
     
    62134591*/
    62144592  if (feasible)
    6215   {
    6216     solver_->resolve() ;
    6217     numberIterations_ += solver_->getIterationCount() ;
    6218     feasible = (solver_->isProvenOptimal() &&
    6219                 !solver_->isDualObjectiveLimitReached()) ;
    6220   }
     4593    {
     4594      solver_->resolve() ;
     4595      numberIterations_ += solver_->getIterationCount() ;
     4596      feasible = (solver_->isProvenOptimal() &&
     4597                  !solver_->isDualObjectiveLimitReached()) ;
     4598    }
    62214599  if (0&&feasible) {
    62224600    const double * lb = solver_->getColLower();
     
    62464624  }
    62474625  setPointers(solver_);
    6248   return feasible ; }
     4626  int returnStatus = feasible ? 1 : 0;
     4627  if (strategy_) {
     4628    // user can play clever tricks here
     4629    int status = strategy_->status(this,parent,whereFrom);
     4630    if (status>=0) {
     4631      if (status==0)
     4632        returnStatus = 1;
     4633      else if(status==1)
     4634        returnStatus=-1;
     4635      else
     4636        returnStatus=0;
     4637    }
     4638  }
     4639  return returnStatus ;
     4640}
    62494641
    62504642
     
    78676259  // solve LP
    78686260  //solver_->writeMps("bad");
    7869   bool feasible = resolve();
     6261  bool feasible = resolve(NULL,3);
    78706262
    78716263  CbcModel * newModel = NULL;
     
    78996291  status_ = 0;
    79006292  // solve LP
    7901   bool feasible = resolve();
     6293  bool feasible = resolve(NULL,3);
    79026294
    79036295  bestObjective_=1.0e50;
     
    80826474        // just point to solver_
    80836475        continuousSolver_ = solver_;
    8084         feasible=resolve();
     6476        feasible=resolve(NULL,3);
    80856477        if (!feasible||!doIntegerPresolve||weak) break;
    80866478        // see if we can get solution by heuristics
     
    82536645    if (bestSolution_) {
    82546646      // solve problem
    8255       resolve();
     6647      resolve(NULL,3);
    82566648      // should be feasible
    82576649      if (!currentSolution_)
     
    86127004  continuous relaxation.
    86137005*/
    8614   bool feasible = resolve() ;
     7006  bool feasible = resolve(NULL,0) != 0 ;
    86157007/*
    86167008  If the linear relaxation of the root is infeasible, bail out now. Otherwise,
  • trunk/CbcNode.cpp

    r268 r271  
    2121#include "CbcNode.hpp"
    2222#include "CbcStatistics.hpp"
     23#include "CbcStrategy.hpp"
    2324#include "CbcBranchActual.hpp"
    2425#include "CbcBranchDynamic.hpp"
     
    684685                     int numberOldActiveCuts,int numberNewCuts)
    685686{ OsiSolverInterface * solver = model->solver();
     687 CbcStrategy * strategy = model->strategy();
    686688/*
    687689  The root --- no parent. Create full basis and bounds information.
    688690*/
    689691  if (!lastNode)
    690   { nodeInfo_=new CbcFullNodeInfo(model,solver->getNumRows()); }
     692  {
     693    if (!strategy)
     694      nodeInfo_=new CbcFullNodeInfo(model,solver->getNumRows());
     695    else
     696      nodeInfo_ = strategy->fullNodeInfo(model,solver->getNumRows());
     697  }
    691698/*
    692699  Not the root. Create an edit from the parent's basis & bound information.
     
    826833  return.
    827834*/
    828     nodeInfo_ =
    829       new CbcPartialNodeInfo(lastNode->nodeInfo_,this,numberChangedBounds,
    830                              variables,boundChanges,basisDiff) ;
     835    if (!strategy)
     836      nodeInfo_ =
     837        new CbcPartialNodeInfo(lastNode->nodeInfo_,this,numberChangedBounds,
     838                               variables,boundChanges,basisDiff) ;
     839    else
     840      nodeInfo_ = strategy->partialNodeInfo(model, lastNode->nodeInfo_,this,numberChangedBounds,
     841                               variables,boundChanges,basisDiff) ;
    831842    delete basisDiff ;
    832843    delete [] boundChanges;
  • trunk/CbcStrategy.cpp

    r251 r271  
    1818#include "CbcCutGenerator.hpp"
    1919#include "CbcBranchActual.hpp"
     20#include "CbcNode.hpp"
     21#include "CoinWarmStart.hpp"
    2022#include "CglPreProcess.hpp"
    2123// Cuts
     
    5254  delete process_;
    5355  process_=NULL;
     56}
     57// Return a new Full node information pointer (descendant of CbcFullNodeInfo)
     58CbcNodeInfo *
     59CbcStrategy::fullNodeInfo(CbcModel * model,int numberRowsAtContinuous) const
     60{
     61  return new CbcFullNodeInfo(model,numberRowsAtContinuous);
     62}
     63// Return a new Partial node information pointer (descendant of CbcPartialNodeInfo)
     64CbcNodeInfo *
     65CbcStrategy::partialNodeInfo(CbcModel * model, CbcNodeInfo * parent, CbcNode * owner,
     66                             int numberChangedBounds,const int * variables,
     67                             const double * boundChanges,
     68                             const CoinWarmStartDiff *basisDiff) const
     69{
     70  return new CbcPartialNodeInfo(parent, owner, numberChangedBounds, variables,
     71                            boundChanges,basisDiff);
     72}
     73/* After a CbcModel::resolve this can return a status
     74   -1 no effect
     75   0 treat as optimal
     76   1 as 0 but do not do any more resolves (i.e. no more cuts)
     77   2 treat as infeasible
     78*/
     79int
     80CbcStrategy::status(CbcModel * model, CbcNodeInfo * parent,int whereFrom)
     81{
     82  return -1;
    5483}
    5584
  • trunk/include/CbcModel.hpp

    r268 r271  
    244244   
    245245      Invoke the solver's %resolve() method.
     246      whereFrom -
     247      0 - initial continuous
     248      1 - resolve on branch (before new cuts)
     249      2 - after new cuts
     250      3  - obsolete code or something modified problem in unexpected way
     251      10 - after strong branching has fixed variables at root
     252      11 - after strong branching has fixed variables in tree
     253
     254      returns 1 feasible, 0 infeasible, -1 feasible but skip cuts
    246255    */
    247     bool resolve();
     256    int resolve(CbcNodeInfo * parent, int whereFrom);
    248257    /// Make given rows (L or G) into global cuts and remove from lp
    249258    void makeGlobalCuts(int numberRows,const int * which);
  • trunk/include/CbcStrategy.hpp

    r222 r271  
    66#include "CbcModel.hpp"
    77class CglPreProcess;
     8class CbcNodeInfo;
     9class CbcNode;
     10class CoinWarmStartDiff;
    811
    912//#############################################################################
     
    4548  /// Delete pre-processing object to save memory
    4649  void deletePreProcess();
     50  /// Return a new Full node information pointer (descendant of CbcFullNodeInfo)
     51  virtual CbcNodeInfo * fullNodeInfo(CbcModel * model,int numberRowsAtContinuous) const;
     52  /// Return a new Partial node information pointer (descendant of CbcPartialNodeInfo)
     53  virtual CbcNodeInfo * partialNodeInfo(CbcModel * model, CbcNodeInfo * parent, CbcNode * owner,
     54                                        int numberChangedBounds,const int * variables,
     55                                        const double * boundChanges,
     56                                        const CoinWarmStartDiff *basisDiff) const;
     57  /** After a CbcModel::resolve this can return a status
     58      -1 no effect
     59      0 treat as optimal
     60      1 as 0 but do not do any more resolves (i.e. no more cuts)
     61      2 treat as infeasible
     62  */
     63  virtual int status(CbcModel * model, CbcNodeInfo * parent, int whereFrom);
    4764private:
    4865 
Note: See TracChangeset for help on using the changeset viewer.