- Timestamp:
- Mar 14, 2006 10:39:00 AM (14 years ago)
- Location:
- trunk
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/CbcModel.cpp
r269 r271 354 354 return ; 355 355 } 356 #ifndef CBC_NEXT_VERSION357 356 358 357 … … 529 528 // If NLP then we assume already solved outside branchAndbound 530 529 if (!solverCharacteristics_->solverType()) { 531 feasible=resolve( );530 feasible=resolve(NULL,0) != 0 ; 532 531 } else { 533 532 // pick up given status … … 810 809 numberPassesLeft--; 811 810 if (anyAction == -1) 812 { feasible = resolve( );811 { feasible = resolve(NULL,10) != 0 ; 813 812 if (problemFeasibility_->feasible(this,0)<0) { 814 813 feasible=false; // pretend infeasible … … 1156 1155 int saveNumber = numberIterations_; 1157 1156 if(solverCharacteristics_->solutionAddsCuts()) { 1158 feasible=resolve(); 1157 int returnCode=resolve(node ? node->nodeInfo() : NULL,1); 1158 feasible = returnCode != 0; 1159 1159 if (feasible) { 1160 1160 int iObject ; … … 1169 1169 if (infeasibility ) numberUnsatisfied++ ; 1170 1170 } 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); 1178 1179 #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 1184 1187 } 1185 #endif1186 1188 } 1187 1189 // check extra info on feasibility … … 1280 1282 int easy=2; 1281 1283 solver_->setHintParam(OsiDoInBranchAndCut,true,OsiHintDo,&easy) ; 1282 feasible = resolve( );1284 feasible = resolve(node ? node->nodeInfo() : NULL,11) != 0 ; 1283 1285 solver_->setHintParam(OsiDoInBranchAndCut,true,OsiHintDo,NULL) ; 1284 1286 resolved = true ; … … 1782 1784 } 1783 1785 return ; } 1784 #else1785 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 strategies1799 if (strategy_) {1800 // May do preprocessing1801 originalSolver = solver_;1802 strategy_->setupOther(*this);1803 if (strategy_->preProcessState()) {1804 // pre-processing done1805 if (strategy_->preProcessState()<0) {1806 // infeasible1807 handler_->message(CBC_INFEAS,messages_)<< CoinMessageEol ;1808 status_ = 0 ;1809 secondaryStatus_ = 1;1810 originalContinuousObjective_ = COIN_DBL_MAX;1811 return ;1812 }1813 } else {1814 //no preprocessing1815 originalSolver=NULL;1816 }1817 strategy_->setupCutGenerators(*this);1818 strategy_->setupHeuristics(*this);1819 // Set strategy print level to models1820 strategy_->setupPrinting(*this,handler_->logLevel());1821 }1822 eventHappened_=false;1823 #ifdef COIN_USE_CLP1824 ClpEventHandler * eventHandler=NULL;1825 {1826 OsiClpSolverInterface * clpSolver1827 = dynamic_cast<OsiClpSolverInterface *> (solver_);1828 if (clpSolver) {1829 ClpSimplex * clpSimplex = clpSolver->getModelPtr();1830 eventHandler = clpSimplex->eventHandler();1831 }1832 }1833 #endif1834 if (!nodeCompare_)1835 nodeCompare_=new CbcCompareDefault();;1836 if (!problemFeasibility_)1837 problemFeasibility_=new CbcFeasibilityBase();1838 # ifdef CBC_DEBUG1839 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 # endif1844 /*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 an1852 CbcSimpleInteger object for each integer variable.1853 */1854 findIntegers(false) ;1855 // If dynamic pseudo costs then do1856 if (numberBeforeTrust_)1857 convertToDynamic();1858 // Set up char array to say if integer1859 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 else1867 integerInfo_[i]=0;1868 }1869 }1870 1871 /*1872 Ensure that objects on the lists of CbcObjects, heuristics, and cut1873 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 solver1882 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 resolve1888 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 the1894 continuous relaxation.1895 */1896 bool feasible = resolve() ;1897 if (problemFeasibility_->feasible(this,0)<0) {1898 feasible=false; // pretend infeasible1899 }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 to1918 see if it cuts off the optimal answer.1919 */1920 // If debugger exists set specialOptions_ bit1921 if (solver_->getRowCutDebuggerAlways())1922 specialOptions_ |= 1;1923 1924 # ifdef CBC_DEBUG1925 if ((specialOptions_&1)==0)1926 solver_->activateRowCutDebugger(problemName.c_str()) ;1927 if (solver_->getRowCutDebuggerAlways())1928 specialOptions_ |= 1;1929 # endif1930 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 minimization1939 {1940 // needed to sync cutoffs1941 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 Cut1963 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_CLP1971 OsiClpSolverInterface * clpSolver1972 = dynamic_cast<OsiClpSolverInterface *> (solver_);1973 if (clpSolver) {1974 ClpSimplex * clpSimplex = clpSolver->getModelPtr();1975 // take off names1976 clpSimplex->dropNames();1977 }1978 #endif1979 1980 numberRowsAtContinuous_ = getNumRows() ;1981 /*1982 Check the objective to see if we can deduce a nontrivial increment. If1983 it's better than the current value for CbcCutoffIncrement, it'll be1984 installed.1985 */1986 if(solverCharacteristics_->reducedCostsAccurate())1987 analyzeObjective() ;1988 /*1989 Set up for cut generation. addedCuts_ holds the cuts which are relevant for1990 the active subproblem. whichGenerator will be used to record the generator1991 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 set2003 (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 that2008 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 heavy2021 lifting. It will iterate a generate/reoptimise loop (including reduced cost2022 fixing) until no cuts are generated, the change in objective falls off, or2023 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 also2026 installed in the solver's constraint system. We'll have reoptimised, and2027 removed any slack cuts (numberOldActiveCuts_ and numberNewCuts_ have been2028 adjusted accordingly).2029 2030 Tell cut generators they can be a bit more aggressive at root node2031 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 solution2046 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 switch2058 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 aggressive2079 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. chooseBranch2087 currently uses strong branching to evaluate branch object candidates,2088 unless forced back to simple branching. If chooseBranch concludes that a2089 branching candidate is monotone (anyAction == -1) or infeasible (anyAction2090 == -2) when forced to integer values, it returns here immediately.2091 2092 Monotone variables trigger a call to resolve(). If the problem remains2093 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 node2110 CbcNode fakeNode;2111 if (!currentNode_) {2112 // Not true if sub trees assert (!numberNodes_);2113 currentNode_=&fakeNode;2114 }2115 phase_=3;2116 // only allow 1000 passes2117 int numberPassesLeft=1000;2118 // This is first crude step2119 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 nothing2146 }2147 numberPassesLeft--;2148 if (anyAction == -1)2149 { feasible = resolve() ;2150 if (problemFeasibility_->feasible(this,0)<0) {2151 feasible=false; // pretend infeasible2152 }2153 reducedCostFix() ;2154 resolved = true ;2155 # ifdef CBC_DEBUG2156 printf("Resolve (root) as something fixed, Obj value %g %d rows\n",2157 solver_->getObjValue(),2158 solver_->getNumRows()) ;2159 # endif2160 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 bound2167 (newNode == NULL), or we're live with an objective value that satisfies the2168 current objective cutoff.2169 */2170 assert (!newNode || newNode->objectiveValue() <= cutoff) ;2171 // Save address of root node as we don't want to delete it2172 //CbcNode * rootNode = newNode;2173 /*2174 The common case is that the lp relaxation is feasible but doesn't satisfy2175 integrality (i.e., newNode->variable() >= 0, indicating we've been able to2176 select a branching variable). Remove any cuts that have gone slack due to2177 forcing monotone variables. Then tack on an CbcFullNodeInfo object and full2178 basis (via createInfo()) and stash the new cuts in the nodeInfo (via2179 addCuts()). If, by some miracle, we have an integral solution at the root2180 (newNode->variable() < 0), takeOffCuts() will ensure that the solver holds2181 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_COUNTS2188 { 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 # endif2196 }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 later2203 */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 objects2214 */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 future2221 expansion (indicated by variable() >= 0), or (miracle of miracles) an2222 integral solution at the root node.2223 2224 initializeInfo sets the reference counts in the nodeInfo object. Since2225 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_NODE2247 printf("Node %x on tree\n",newNode) ;2248 # endif2249 } else {2250 // continuous is integer2251 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 round2266 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 until2271 the live set is empty or we hit some limit (integrality gap, time, node2272 count, etc.). The overall flow is to rebuild a subproblem, reoptimise using2273 solveWithCuts(), choose a branching pattern with chooseBranch(), and finally2274 add the node to the live set.2275 2276 The first action is to winnow the live set to remove nodes which are worse2277 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_CLP2308 if (eventHandler) {2309 if (!eventHandler->event(ClpEventHandler::solution)) {2310 eventHappened_=true; // exit2311 }2312 }2313 #endif2314 // Do from deepest2315 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; // finished2322 }2323 cutoff = getCutoff() ;2324 /*2325 Periodic activities: Opportunities to2326 + 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 working2329 */2330 if ((numberNodes_%1000) == 0) {2331 bool redoTree=nodeCompare_->every1000Nodes(this, numberNodes_) ;2332 // redo tree if wanted2333 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_CLP2349 if (eventHandler) {2350 if (!eventHandler->event(ClpEventHandler::treeStatus)) {2351 eventHappened_=true; // exit2352 }2353 }2354 #endif2355 }2356 // If no solution but many nodes - signal change in strategy2357 if (numberNodes_>2*numberObjects_+1000&&stateOfSearch_!=2)2358 stateOfSearch_=3;2359 // See if can stop on gap2360 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_FULL2368 verifyTreeNodes(tree_,*this) ;2369 # endif2370 # ifdef CHECK_CUT_COUNTS2371 verifyCutCounts(tree_,*this) ;2372 # endif2373 2374 /*2375 Now we come to the meat of the loop. To create the active subproblem, we'll2376 pop the most promising node in the live set, rebuild the subproblem it2377 represents, and then execute the current arm of the branch to create the2378 active subproblem.2379 */2380 CbcNode *node = tree_->bestNode(cutoff) ;2381 // Possible one on tree worse than cutoff2382 if (!node)2383 continue;2384 // Solve node2385 int status;2386 int numberNewNodes;2387 CbcNode ** newNodes = solveOneNode(-1,node,numberNewNodes,status);2388 // put nodes back on tree2389 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've2396 aborted because we hit one of the limits. Clean up by deleting the live set2397 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 tree2402 //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.02410 << 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 entry2436 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 because2451 we hit some limit on evaluation.2452 2453 We may have got an intelligent tree so give it one more chance2454 */2455 // Tell solver we are not in Branch and Cut2456 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 way2478 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 solution2512 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 summary2533 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 completed2561 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 print2599 if (numberSolutions)2600 averageSolutionDepth /= (double) numberSolutions;2601 int numberSolved = numberNodes2_-numberCutoff;2602 double averageNumberIterations2=numberIterations_-averageNumberIterations12603 -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 to2645 setBestSolution(). We need to reset the cutoff value so as not to fathom2646 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 already2650 reoptimised using the continuousSolver_. If for some reason we fail to2651 prove optimality, run the problem again after instructing the solver to2652 tell us more.2653 2654 If all looks good, replace solver_ with continuousSolver_, so that the2655 outside world will be able to obtain information about the solution using2656 public methods.2657 */2658 if (bestSolution_) {2659 setCutoff(1.0e50) ; // As best solution should be worse than cutoff2660 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 characteristics2684 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 preprocessing2695 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 originalSolver2705 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 update2713 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 more2715 status is 0 for normal, 1 if solution, 2 if should stop2716 Calling code should always push nodes back on tree2717 */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 known2725 // 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 elsewhere2730 #ifdef CBC_DEBUG2731 printf("%d unsat, way %d, obj %g est %g\n",2732 node->numberUnsatisfied(),node->way(),node->objectiveValue(),2733 node->guessedObjectiveValue());2734 #endif2735 // Save clone in branching decision2736 if(branchingMethod_)2737 branchingMethod_->saveBranchingObject(node->modifiableBranchingObject());2738 // Say not on optimal path2739 bool onOptimalPath=false;2740 # ifdef CHECK_NODE2741 /*2742 WARNING: The use of integerVariable_[*] here will break as soon as the2743 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 # endif2754 2755 /*2756 Rebuild the subproblem for this node: Call addCuts() to adjust the model2757 to recreate the subproblem for this node (set proper variable bounds, add2758 cuts, create a basis). This may result in the problem being fathomed by2759 bound or infeasibility. Returns 1 if node is fathomed.2760 Execute the current arm of the branch: If the problem survives, save the2761 resulting variable bounds and call branch() to modify variable bounds2762 according to the current arm of the branching object. If we're processing2763 the final arm of the branching object, flag the node for removal from the2764 live set.2765 */2766 CbcNodeInfo * nodeInfo = node->nodeInfo() ;2767 // empty basis2768 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 correctly2783 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_NODE2800 printf("Node %x pushed back on tree - %d left, %d count\n",node,2801 nodeInfo->numberBranchesLeft(),2802 nodeInfo->numberPointingToThis()) ;2803 # endif2804 } else {2805 deleteNode = true ;2806 }2807 2808 if ((specialOptions_&1)!=0) {2809 /*2810 This doesn't work as intended --- getRowCutDebugger will return null2811 unless the current feasible solution region includes the optimal solution2812 that RowCutDebugger knows. There's no way to tell inactive from off the2813 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 find2823 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 solution2848 //to an infeasible one2849 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 feasibility2859 if (!solverCharacteristics_->mipFeasible())2860 feasible = false;2861 }2862 } else {2863 // normal2864 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 a2884 branching object, reoptimising as needed if chooseBranch() identifies2885 monotone objects.2886 2887 Finally, attach a partial nodeInfo object and store away any cuts that we2888 created back in solveWithCuts. addCuts() will also deal with the cut2889 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 passes2907 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 nothing2919 }2920 if (onOptimalPath)2921 assert (anyAction!=-2); // can be useful but gives false positives on strong2922 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 check2931 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 infeasible2938 }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_COUNTS2955 { 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 # endif2965 }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 tree2977 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 leaves2995 numberNodes_ += (numberSolves-numberGood);2996 int numberCutsAdd=-1; // We will be taking off one anyway2997 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 etc3003 solver_->setColLower(lowerBefore2);3004 solver_->setColUpper(upperBefore2);3005 result[iResult].restoreResult(*solver_);3006 numberNodes_++;3007 #if 03008 // need to tell solver that current factorization is no good3009 // should be better way3010 #ifdef COIN_USE_CLP3011 OsiClpSolverInterface * clpSolver3012 = dynamic_cast<OsiClpSolverInterface *> (solver_);3013 if (clpSolver)3014 clpSolver->getModelPtr()->setWhatsChanged(clpSolver->getModelPtr()->whatsChanged()&(~512));3015 #endif3016 solver_->resolve();3017 assert (!solver_->getIterationCount());3018 printf("res obj %g was %g\n",solver_->getObjValue(),3019 result[iResult].objectiveValue());3020 #endif3021 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 passes3028 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 nothing3038 }3039 numberPassesLeft--;3040 if (anyAction == -1) {3041 // can do quick optimality check3042 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 infeasible3048 }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 cutoff3061 if ( anyAction ==0 ) {3062 assert (newNode2);3063 if (newNode2->objectiveValue() >= getCutoff())3064 anyAction = -2; // say bad after all3065 }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 this3079 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, so3081 increment the reference count in the current (parent) nodeInfo.3082 */3083 if (anyAction == -2) {3084 delete newNode2 ;3085 newNode2 = NULL ;3086 #if 03087 // say strong doing well3088 if (checkingNode)3089 setSpecialOptions(specialOptions_|8);3090 #endif3091 #if 03092 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 #endif3101 } else {3102 nodeInfo->increment() ;3103 #if 03104 if ((numberNodes_%20)==0) {3105 // say strong not doing as well3106 setSpecialOptions(specialOptions_&~8);3107 }3108 #endif3109 }3110 /*3111 At this point, there are three possibilities:3112 * We have a live node (variable() >= 0) which will require further3113 branching to resolve. Before we push it onto the search tree, try for3114 a heuristic solution.3115 * We have a solution, in which case newNode is non-null but we have no3116 branching variable. Decrement the cut counts and save the solution.3117 * The node was found to be infeasible, in which case it's already been3118 deleted, and newNode is null.3119 3120 */3121 #ifdef COIN_USE_CLP3122 if (eventHandler()) {3123 if (!eventHandler()->event(ClpEventHandler::node)) {3124 eventHappened_=true; // exit3125 }3126 }3127 #endif3128 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 else3136 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 counts3145 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 found3156 found = iHeur ;3157 incrementUsed(newSolution);3158 } else if (ifSol < 0) { // just returning an estimate3159 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_NODE3186 printf("Node %x pushed on tree c\n",newNode2) ;3187 # endif3188 } else {3189 #if 03190 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 #endif3199 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 arm3206 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_COUNTS3218 printf("Count on cut %x increased by %d\n",addedCuts_[i],3219 numberCutsAdd) ;3220 # endif3221 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 else3235 anyAction=-2;3236 }3237 }3238 } else {3239 anyAction = -2 ;3240 }3241 #if 03242 if (numberNodesOutput) {3243 if (!sizeMiniTree_)3244 assert(newNode== newNodes[numberNodesOutput-1]);3245 newNode= newNodes[numberNodesOutput-1];3246 } else {3247 assert (!newNode);3248 }3249 #endif3250 // May have slipped through i.e. anyAction == 0 and objective above cutoff3251 if ( anyAction >=0 ) {3252 assert (newNode);3253 if (newNode->objectiveValue() >= getCutoff())3254 anyAction = -2; // say bad after all3255 }3256 /*3257 If we end up infeasible, we can delete the new node immediately. Since this3258 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, so3260 increment the reference count in the current (parent) nodeInfo.3261 */3262 if (anyAction == -2) {3263 delete newNode ;3264 newNode = NULL ;3265 // say strong doing well3266 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 well3280 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 further3286 branching to resolve. Before we push it onto the search tree, try for3287 a heuristic solution.3288 * We have a solution, in which case newNode is non-null but we have no3289 branching variable. Decrement the cut counts and save the solution.3290 * The node was found to be infeasible, in which case it's already been3291 deleted, and newNode is null.3292 3293 */3294 #ifdef COIN_USE_CLP3295 if (eventHandler()) {3296 if (!eventHandler()->event(ClpEventHandler::node)) {3297 eventHappened_=true; // exit3298 }3299 }3300 #endif3301 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 else3309 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_COUNTS3322 printf("Count on cut %x increased by %d\n",addedCuts_[i],3323 numberLeft-1) ;3324 # endif3325 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 found3339 found = iHeur ;3340 incrementUsed(newSolution);3341 } else if (ifSol < 0) { // just returning an estimate3342 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_NODE3368 printf("Node %x pushed on tree c\n",newNode) ;3369 # endif3370 } 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 arm3386 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 live3394 set.3395 */3396 if (deleteNode)3397 delete node ;3398 } else {3399 // max time etc3400 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 #endif3414 1786 3415 1787 … … 4990 3362 if (node) 4991 3363 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; 4993 3368 if (problemFeasibility_->feasible(this,0)<0) { 4994 3369 feasible=false; // pretend infeasible … … 5150 3525 !solver_->optimalBasisIsAvailable()) { 5151 3526 //printf("XXXXYY no opt basis\n"); 5152 resolve( );3527 resolve(node ? node->nodeInfo() : NULL,3); 5153 3528 } 5154 3529 if (nextRowCut_) { … … 5217 3592 #endif 5218 3593 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; 5220 3598 if ((specialOptions_&1)!=0) { 5221 3599 debugger = solver_->getRowCutDebugger() ; … … 5523 3901 delete basis; 5524 3902 } 5525 feasible = resolve( ) ;3903 feasible = resolve(node ? node->nodeInfo() : NULL,2) ; 5526 3904 if ( CoinCpuTime()-dblParam_[CbcStartSeconds] > dblParam_[CbcMaximumSeconds] ) 5527 3905 numberTries=0; // exit … … 6157 4535 6158 4536 6159 bool 6160 CbcModel::resolve( )4537 int 4538 CbcModel::resolve(CbcNodeInfo * parent, int whereFrom) 6161 4539 { 6162 4540 // We may have deliberately added in violated cuts - check to avoid message … … 6213 4591 */ 6214 4592 if (feasible) 6215 {6216 solver_->resolve() ;6217 numberIterations_ += solver_->getIterationCount() ;6218 feasible = (solver_->isProvenOptimal() &&6219 6220 }4593 { 4594 solver_->resolve() ; 4595 numberIterations_ += solver_->getIterationCount() ; 4596 feasible = (solver_->isProvenOptimal() && 4597 !solver_->isDualObjectiveLimitReached()) ; 4598 } 6221 4599 if (0&&feasible) { 6222 4600 const double * lb = solver_->getColLower(); … … 6246 4624 } 6247 4625 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 } 6249 4641 6250 4642 … … 7867 6259 // solve LP 7868 6260 //solver_->writeMps("bad"); 7869 bool feasible = resolve( );6261 bool feasible = resolve(NULL,3); 7870 6262 7871 6263 CbcModel * newModel = NULL; … … 7899 6291 status_ = 0; 7900 6292 // solve LP 7901 bool feasible = resolve( );6293 bool feasible = resolve(NULL,3); 7902 6294 7903 6295 bestObjective_=1.0e50; … … 8082 6474 // just point to solver_ 8083 6475 continuousSolver_ = solver_; 8084 feasible=resolve( );6476 feasible=resolve(NULL,3); 8085 6477 if (!feasible||!doIntegerPresolve||weak) break; 8086 6478 // see if we can get solution by heuristics … … 8253 6645 if (bestSolution_) { 8254 6646 // solve problem 8255 resolve( );6647 resolve(NULL,3); 8256 6648 // should be feasible 8257 6649 if (!currentSolution_) … … 8612 7004 continuous relaxation. 8613 7005 */ 8614 bool feasible = resolve( );7006 bool feasible = resolve(NULL,0) != 0 ; 8615 7007 /* 8616 7008 If the linear relaxation of the root is infeasible, bail out now. Otherwise, -
trunk/CbcNode.cpp
r268 r271 21 21 #include "CbcNode.hpp" 22 22 #include "CbcStatistics.hpp" 23 #include "CbcStrategy.hpp" 23 24 #include "CbcBranchActual.hpp" 24 25 #include "CbcBranchDynamic.hpp" … … 684 685 int numberOldActiveCuts,int numberNewCuts) 685 686 { OsiSolverInterface * solver = model->solver(); 687 CbcStrategy * strategy = model->strategy(); 686 688 /* 687 689 The root --- no parent. Create full basis and bounds information. 688 690 */ 689 691 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 } 691 698 /* 692 699 Not the root. Create an edit from the parent's basis & bound information. … … 826 833 return. 827 834 */ 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) ; 831 842 delete basisDiff ; 832 843 delete [] boundChanges; -
trunk/CbcStrategy.cpp
r251 r271 18 18 #include "CbcCutGenerator.hpp" 19 19 #include "CbcBranchActual.hpp" 20 #include "CbcNode.hpp" 21 #include "CoinWarmStart.hpp" 20 22 #include "CglPreProcess.hpp" 21 23 // Cuts … … 52 54 delete process_; 53 55 process_=NULL; 56 } 57 // Return a new Full node information pointer (descendant of CbcFullNodeInfo) 58 CbcNodeInfo * 59 CbcStrategy::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) 64 CbcNodeInfo * 65 CbcStrategy::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 */ 79 int 80 CbcStrategy::status(CbcModel * model, CbcNodeInfo * parent,int whereFrom) 81 { 82 return -1; 54 83 } 55 84 -
trunk/include/CbcModel.hpp
r268 r271 244 244 245 245 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 246 255 */ 247 bool resolve();256 int resolve(CbcNodeInfo * parent, int whereFrom); 248 257 /// Make given rows (L or G) into global cuts and remove from lp 249 258 void makeGlobalCuts(int numberRows,const int * which); -
trunk/include/CbcStrategy.hpp
r222 r271 6 6 #include "CbcModel.hpp" 7 7 class CglPreProcess; 8 class CbcNodeInfo; 9 class CbcNode; 10 class CoinWarmStartDiff; 8 11 9 12 //############################################################################# … … 45 48 /// Delete pre-processing object to save memory 46 49 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); 47 64 private: 48 65
Note: See TracChangeset
for help on using the changeset viewer.