//----------------------------------------------------------------------------- void CbcSolverLongThin::resolve() { int * whichRow = NULL; int * whichColumn = NULL; // problem may be small enough to do nested search const double * colLower = modelPtr_->columnLower(); const double * colUpper = modelPtr_->columnUpper(); int numberIntegers = model_->numberIntegers(); const int * integerVariable = model_->integerVariable(); int numberRows=modelPtr_->numberRows(); int numberColumns = modelPtr_->numberColumns(); int i; int nFix=0; int nNewRow=0; int nNewCol=0; int sizeDynamic = COIN_INT_MAX; int smallOriginalNumberRows=0; if (algorithm_==0) { for (i=0;i<numberIntegers;i++) { int iColumn=integerVariable[i]; if (colLower[iColumn]==colUpper[iColumn]) nFix++; } } else { whichRow = new int[numberRows]; whichColumn = new int [numberColumns]; // more sophisticated OsiCuts cs; tryCut->generateCuts(*this,cs); int numberCuts = cs.sizeColCuts(); if (numberCuts) { for ( i = 0 ; i < numberCuts ; i++) { const OsiColCut *thisCut = cs.colCutPtr(i) ; const CoinPackedVector & ubs = thisCut->ubs() ; int n = ubs.getNumElements() ; const int * which = ubs.getIndices() ; const double * values = ubs.getElements() ; for (int j = 0;j<n;j++) { int iColumn = which[j] ; this->setColUpper(iColumn,values[j]) ; } } } #if 1 const int * duplicate = tryCut->duplicate(); sizeDynamic = tryCut->sizeDynamic(); int nOrig = tryCut->numberOriginalRows(); for (i=0;i<nOrig;i++) { if (duplicate[i]==-1) whichRow[nNewRow++]=i; else modelPtr_->setRowStatus(i,ClpSimplex::basic); } smallOriginalNumberRows=nNewRow; for (;i<numberRows;i++) { whichRow[nNewRow++]=i; } #else for (i=0;i<numberRows;i++) whichRow[i]=i; nNewRow=numberRows; #endif for (i=0;i<numberIntegers;i++) { int iColumn=integerVariable[i]; if (colLower[iColumn]==colUpper[iColumn]) nFix++; bool choose; if (algorithm_==1) choose = true; else choose = (node_[i]>count_-memory_&&node_[i]>0); if ((choose&&colUpper[i]) ||(modelPtr_->getStatus(i)!=ClpSimplex::atLowerBound&& modelPtr_->getStatus(i)!=ClpSimplex::isFixed) ||colLower[i]>0.0) whichColumn[nNewCol++]=i; } } if (nestedSearch_<1.0&&model_&&model_->phase()==2) { if (((double) sizeDynamic)*((double) nNewCol)<1000000000&&sizeDynamic<10000000) { // could do Dynamic Programming // back to original number of rows nNewRow = smallOriginalNumberRows; // and get rid of any basics int nNewCol=0; for (i=0;i<numberColumns;i++) { if (colUpper[i]||colLower[i]>0.0) whichColumn[nNewCol++]=i; } ClpSimplex temp(modelPtr_,nNewRow,whichRow,nNewCol,whichColumn); int returnCode; double * rowLower2 = temp.rowLower(); double * rowUpper2 = temp.rowUpper(); int numberColumns2 = temp.numberColumns(); double * colLower2 = temp.columnLower(); double * colUpper2 = temp.columnUpper(); const CoinPackedMatrix * matrix = temp.matrix(); const double * element = matrix->getElements(); const int * row = matrix->getIndices(); const CoinBigIndex * columnStart = matrix->getVectorStarts(); const int * columnLength = matrix->getVectorLengths(); double offset=0.0; const double * objective = temp.objective(); bool feasible=true; for (i=0;i<numberColumns2;i++) { double value = colLower2[i]; if (value) { offset += value*objective[i]; colLower2[i]=0.0; colUpper2[i] -= value; for (int j=columnStart[i]; j<columnStart[i]+columnLength[i];j++) { int iRow=row[j]; rowLower2[iRow] -= value*element[j]; rowUpper2[iRow] -= value*element[j]; if (rowUpper2[iRow]<-1.0e-8) { feasible=false; printf("odd - problem is infeasible\n"); } } } } temp.setObjectiveOffset(-offset); OsiClpSolverInterface temp2(&temp); double * solutionDP = NULL; if (feasible) { for (i=0;i<numberColumns2;i++) temp2.setInteger(i); CbcModel modelSmall(temp2); modelSmall.messageHandler()->setLogLevel(0); CbcFathomDynamicProgramming fathom1(modelSmall); // Set maximum space allowed fathom1.setMaximumSize(100000000); temp2.writeMps("small"); returnCode=fathom1.fathom(solutionDP); if (returnCode!=1) { printf("probably not enough memory\n"); abort(); } } if (solutionDP) { double objValue = 0.0; double * solution = modelPtr_->primalColumnSolution(); const double * objective = modelPtr_->objective(); for (i=0;i<numberColumns;i++) solution[i]=colLower[i]; for (i=0;i<nNewCol;i++) { int iColumn = whichColumn[i]; solution[iColumn]+=solutionDP[i]; } for (i=0;i<numberColumns;i++) objValue += solution[i]*objective[i]; if (objValue<model_->getCutoff()) { printf("good solution %g by dynamic programming\n",objValue); returnCode = 0; // paranoid check double * rowLower = modelPtr_->rowLower(); double * rowUpper = modelPtr_->rowUpper(); // Column copy const CoinPackedMatrix * matrix2 = modelPtr_->matrix(); element = matrix2->getElements(); row = matrix2->getIndices(); columnStart = matrix2->getVectorStarts(); columnLength = matrix2->getVectorLengths(); double * rowActivity = new double [numberRows]; memset(rowActivity,0,numberRows*sizeof(double)); for (i=0;i<numberColumns;i++) { int j; double value = solution[i]; assert (value>=colLower[i]&&value<=colUpper[i]); if (value) { printf("%d has value %g\n",i,value); for (j=columnStart[i]; j<columnStart[i]+columnLength[i];j++) { int iRow=row[j]; rowActivity[iRow] += value*element[j]; } } } // check was feasible bool feasible=true; for (i=0;i<numberRows;i++) { if(rowActivity[i]<rowLower[i]) { if (rowActivity[i]<rowLower[i]-1.0e-8) feasible = false; } else if(rowActivity[i]>rowUpper[i]) { if (rowActivity[i]>rowUpper[i]+1.0e-8) feasible = false; } } if (!feasible) { printf("** Bad solution by dynamic programming\n"); abort(); } delete [] rowActivity; model_->setBestSolution(CBC_TREE_SOL,objValue,solution); } else { returnCode=2; } } else { returnCode=2; } temp2.releaseClp(); modelPtr_->setProblemStatus(1); delete [] whichRow; delete [] whichColumn; return; } if (nFix>nestedSearch_*numberIntegers) { // Do nested search // back to original number of rows nNewRow = smallOriginalNumberRows; // and get rid of any basics int nNewCol=0; for (i=0;i<numberColumns;i++) { if (colUpper[i]||colLower[i]>0.0) whichColumn[nNewCol++]=i; } #if 0 // We clone from continuous solver so set some stuff OsiSolverInterface * solver = model_->continuousSolver(); CbcSolverLongThin * osiclp = dynamic_cast< CbcSolverLongThin*> (solver); assert (osiclp); // up special options if (osiclp->specialOptions()==3) osiclp->setSpecialOptions(7); double saveNested = osiclp->getNested(); int saveAlgorithm = osiclp->getAlgorithm(); osiclp->setNested(1.0); osiclp->setAlgorithm(0); int numberObjects = model_->numberObjects(); if (numberObjects>model_->numberIntegers()) { // for now only integers //assert (numberObjects == model_->numberIntegers()+1); model_->setNumberObjects(model_->numberIntegers()); // try follow on //model_->setNumberObjects(model_->numberIntegers()+1); } double saveMaxTime = model_->getDblParam(CbcModel::CbcMaximumSeconds); model_->setDblParam(CbcModel::CbcMaximumSeconds,1.0e5); // up special options #if 1 int returnCode= model_->subBranchAndBound(colLower,colUpper,2000); #else CbcModel * model3 = model_->cleanModel(colLower,colUpper); // integer presolve int returnCode=0; CbcModel * model2 = model3->integerPresolve(false); if (!model2||!model2->getNumRows()) { delete model2; delete model3; returnCode= 2; } else { if (handler_->logLevel()>1) printf("Reduced model has %d rows and %d columns\n", model2->getNumRows(),model2->getNumCols()); if (true) { OsiSolverInterface * solver = model2->solver(); OsiSolverInterface * osiclp = dynamic_cast< OsiSolverInterface*> (solver); assert (osiclp); int * priority = new int [numberColumns+1]; int n=0; int iColumn; for ( iColumn=0;iColumn<numberColumns;iColumn++) { if (solver->isInteger(iColumn)) { priority[n++]=10000; } } priority[n]=1; CbcObject * newObject =new CbcFollowOn2(model2); model2->addObjects(1,&newObject); delete newObject; model2->passInPriorities(priority,false); delete [] priority; } returnCode= model_->subBranchAndBound(model3,model2,4000); } #endif model_->setDblParam(CbcModel::CbcMaximumSeconds,saveMaxTime); model_->setNumberObjects(numberObjects); osiclp->setNested(saveNested); osiclp->setAlgorithm(saveAlgorithm); #else // start again very simply ClpSimplex temp(modelPtr_,nNewRow,whichRow,nNewCol,whichColumn); int returnCode; OsiClpSolverInterface temp2(&temp); temp2.setupForRepeatedUse(2); int numberColumns2 = temp.numberColumns(); const double * colUpper2 = temp2.getColUpper(); const double * colLower2 = temp2.getColLower(); const double * solution2 = temp.getColSolution(); double * cleanSolution2 = new double [numberColumns2]; for (i=0;i<numberColumns2;i++) { temp2.setInteger(i); double value = solution2[i]; value = CoinMin(CoinMax(value,colLower2[i]),colUpper2[i]); cleanSolution2[i] = value; } temp2.setColSolution(cleanSolution2); delete [] cleanSolution2; CbcModel modelSmall(temp2); modelSmall.setNumberStrong(0); CglProbing generator1; generator1.setUsingObjective(true); generator1.setMaxPass(3); generator1.setMaxProbe(100); generator1.setMaxLook(50); generator1.setRowCuts(3); CglGomory generator2; // try larger limit generator2.setLimit(300); CglKnapsackCover generator3; CglOddHole generator4; generator4.setMinimumViolation(0.005); generator4.setMinimumViolationPer(0.00002); // try larger limit generator4.setMaximumEntries(200); CglClique generator5; generator5.setStarCliqueReport(false); generator5.setRowCliqueReport(false); CglMixedIntegerRounding mixedGen; CglFlowCover flowGen; // Add in generators modelSmall.addCutGenerator(&generator1,-1,"Probing",true,false,false,-1); modelSmall.addCutGenerator(&generator2,-99,"Gomory",true,false,false,-99); modelSmall.addCutGenerator(&generator3,-99,"Knapsack",true,false,false,-99); modelSmall.addCutGenerator(&generator4,-99,"OddHole",true,false,false,-99); modelSmall.addCutGenerator(&generator5,-99,"Clique",true,false,false,-99); modelSmall.addCutGenerator(&flowGen,-99,"FlowCover",true,false,false,-99); modelSmall.addCutGenerator(&mixedGen,-99,"MixedIntegerRounding",true,false,false,-100); #if 1 const CoinPackedMatrix * matrix = temp2.getMatrixByCol(); const int * columnLength = matrix->getVectorLengths(); int * priority = new int [numberColumns2+1]; // do pseudo costs and priorities - take a reasonable guess CbcObject ** objects = new CbcObject * [numberColumns2+1]; int n=0; const double * objective = modelSmall.getObjCoefficients(); for (i=0;i<numberColumns2;i++) { CbcSimpleIntegerPseudoCost * newObject = new CbcSimpleIntegerPseudoCost(&modelSmall,n,i,objective[i],0.5*objective[i]); newObject->setMethod(3); objects[n]= newObject; priority[n++]=10000-columnLength[i]; } priority[n]=1; objects[n++]=new CbcFollowOn2(&modelSmall); modelSmall.addObjects(n,objects); for (i=0;i<n;i++) delete objects[i]; delete [] objects; modelSmall.passInPriorities(priority,false); delete [] priority; #endif modelSmall.setCutoff(model_->getCutoff()); //if (!onPathX&&modelSmall.getCutoff()>480.5) //modelSmall.setCutoff(480.5); //printf("cutoff %g\n",model_->getCutoff()); modelSmall.messageHandler()->setLogLevel(1); modelSmall.solver()->messageHandler()->setLogLevel(0); modelSmall.messagesPointer()->setDetailMessage(3,9); modelSmall.messagesPointer()->setDetailMessage(3,6); modelSmall.messagesPointer()->setDetailMessage(3,4); modelSmall.messagesPointer()->setDetailMessage(3,13); modelSmall.messagesPointer()->setDetailMessage(3,14); modelSmall.messagesPointer()->setDetailMessage(3,1); modelSmall.messagesPointer()->setDetailMessage(3,3007); modelSmall.branchAndBound(); temp2.releaseClp(); if (modelSmall.bestSolution()) { double objValue = 0.0; const double * solution2 = modelSmall.bestSolution(); double * solution = modelPtr_->primalColumnSolution(); const double * objective = modelPtr_->objective(); for (i=0;i<numberColumns;i++) solution[i]=colLower[i]; for (i=0;i<nNewCol;i++) { int iColumn = whichColumn[i]; solution[iColumn]=solution2[i]; } for (i=0;i<numberColumns;i++) objValue += solution[i]*objective[i]; assert (objValue<model_->getCutoff()); if (objValue<model_->getCutoff()) { //printf("good solution \n"); model_->setBestSolution(CBC_TREE_SOL,objValue,solution); returnCode = 0; } else { returnCode=2; } } else { returnCode=2; } #endif if (returnCode!=0&&returnCode!=2) { printf("pretending entire search done\n"); returnCode=0; } if (returnCode==0||returnCode==2) { modelPtr_->setProblemStatus(1); delete [] whichRow; delete [] whichColumn; return; } } } if ((count_<100&&algorithm_==2)||!algorithm_) { delete [] whichRow; delete [] whichColumn; assert(!modelPtr_->specialOptions()); int saveOptions = modelPtr_->specialOptions(); int startFinishOptions; bool takeHint; OsiHintStrength strength; bool gotHint = (getHintParam(OsiDoInBranchAndCut,takeHint,strength)); assert (gotHint); if (strength!=OsiHintIgnore&&takeHint) { // could do something - think about it //printf("thin hint %d %c\n",strength,takeHint ? 'T' :'F'); } if((specialOptions_&1)==0) { startFinishOptions=0; modelPtr_->setSpecialOptions(saveOptions|(64|1024)); } else { startFinishOptions=1+2+4; if((specialOptions_&4)==0) modelPtr_->setSpecialOptions(saveOptions|(64|128|512|1024|4096)); else modelPtr_->setSpecialOptions(saveOptions|(64|128|512|1024|2048|4096)); } //printf("thin options %d size %d\n",modelPtr_->specialOptions(),modelPtr_->numberColumns()); setBasis(basis_,modelPtr_); //modelPtr_->setLogLevel(1); modelPtr_->dual(0,0); basis_ = getBasis(modelPtr_); modelPtr_->setSpecialOptions(saveOptions); if (modelPtr_->status()==0) { count_++; double * solution = modelPtr_->primalColumnSolution(); int i; for (i=0;i<numberColumns;i++) { if (solution[i]>1.0e-6||modelPtr_->getStatus(i)==ClpSimplex::basic) { node_[i]=CoinMax(count_,node_[i]); howMany_[i]++; } } } else { if (!algorithm_==2) printf("infeasible early on\n"); } } else { // use counts int i; const double * lower = modelPtr_->columnLower(); const double * upper = modelPtr_->columnUpper(); setBasis(basis_,modelPtr_); ClpSimplex * temp = new ClpSimplex(modelPtr_,nNewRow,whichRow,nNewCol,whichColumn); //temp->setLogLevel(2); //printf("small has %d rows and %d columns\n",nNewRow,nNewCol); temp->setSpecialOptions(128+512); temp->setDualObjectiveLimit(1.0e50); temp->dual(); if (temp->status()) { // In some cases we know that it must be infeasible if (believeInfeasible_||algorithm_==1) { modelPtr_->setProblemStatus(1); printf("assuming infeasible!\n"); //modelPtr_->writeMps("infeas.mps"); //temp->writeMps("infeas2.mps"); //abort(); delete temp; delete [] whichRow; delete [] whichColumn; return; } } double * solution = modelPtr_->primalColumnSolution(); if (!temp->status()) { const double * solution2 = temp->primalColumnSolution(); memset(solution,0,numberColumns*sizeof(double)); for (i=0;i<nNewCol;i++) { int iColumn = whichColumn[i]; solution[iColumn]=solution2[i]; modelPtr_->setStatus(iColumn,temp->getStatus(i)); } double * rowSolution = modelPtr_->primalRowSolution(); const double * rowSolution2 = temp->primalRowSolution(); double * dual = modelPtr_->dualRowSolution(); const double * dual2 = temp->dualRowSolution(); memset(dual,0,numberRows*sizeof(double)); for (i=0;i<nNewRow;i++) { int iRow=whichRow[i]; modelPtr_->setRowStatus(iRow,temp->getRowStatus(i)); rowSolution[iRow]=rowSolution2[i]; dual[iRow]=dual2[i]; } // See if optimal double * dj = modelPtr_->dualColumnSolution(); // get reduced cost for large problem // this assumes minimization memcpy(dj,modelPtr_->objective(),numberColumns*sizeof(double)); modelPtr_->transposeTimes(-1.0,dual,dj); modelPtr_->setObjectiveValue(temp->objectiveValue()); modelPtr_->setProblemStatus(0); int nBad=0; for (i=0;i<numberColumns;i++) { if (modelPtr_->getStatus(i)==ClpSimplex::atLowerBound &&upper[i]>lower[i]&&dj[i]<-1.0e-5) nBad++; } //modelPtr_->writeMps("bada.mps"); //temp->writeMps("badb.mps"); if (nBad) { assert (algorithm_==2); //printf("%d bad\n",nBad); timesBad_++; modelPtr_->primal(); } } else { // infeasible - do all modelPtr_->setSpecialOptions(64+128+512); setBasis(basis_,modelPtr_); //modelPtr_->setLogLevel(1); modelPtr_->dual(0,0); basis_ = getBasis(modelPtr_); modelPtr_->setSpecialOptions(0); if (modelPtr_->status()) { printf("really infeasible!\n"); delete temp; delete [] whichRow; delete [] whichColumn; return; } else { printf("initially infeasible\n"); } } delete temp; delete [] whichRow; delete [] whichColumn; basis_ = getBasis(modelPtr_); modelPtr_->setSpecialOptions(0); count_++; if ((count_%100)==0&&algorithm_==2) printf("count %d, bad %d\n",count_,timesBad_); for (i=0;i<numberColumns;i++) { if (solution[i]>1.0e-6||modelPtr_->getStatus(i)==ClpSimplex::basic) { node_[i]=CoinMax(count_,node_[i]); howMany_[i]++; } } if (modelPtr_->objectiveValue()>=modelPtr_->dualObjectiveLimit()) modelPtr_->setProblemStatus(1); } }
/** Perform a branch-and-bound on given setup.*/ void CouenneBab::branchAndBound (Bonmin::BabSetupBase & s) { double remaining_time = s.getDoubleParameter(Bonmin::BabSetupBase::MaxTime) + CoinCpuTime(); /* Put a link to this into solver.*/ OsiBabSolver * babInfo = dynamic_cast<OsiBabSolver *>(s.continuousSolver()->getAuxiliaryInfo()); assert(babInfo); Bonmin::BabInfo * bonBabInfoPtr = dynamic_cast<Bonmin::BabInfo*>(babInfo); if (bonBabInfoPtr == NULL) { //Replace with a Bonmin::babInfo bonBabInfoPtr = new Bonmin::BabInfo(*babInfo); s.continuousSolver()->setAuxiliaryInfo(bonBabInfoPtr); delete bonBabInfoPtr; bonBabInfoPtr = dynamic_cast<Bonmin::BabInfo*>(s.continuousSolver()->getAuxiliaryInfo()); } bonBabInfoPtr->setBabPtr(this); s.nonlinearSolver()->solver()->setup_global_time_limit(s.getDoubleParameter(Bonmin::BabSetupBase::MaxTime)); OsiSolverInterface * solver = s.continuousSolver()->clone(); delete modelHandler_; modelHandler_ = s.continuousSolver()->messageHandler()->clone(); model_.passInMessageHandler(modelHandler_); model_.assignSolver(solver, true); // s.continuousSolver() = model_.solver(); // if(s.continuousSolver()->objects()!=NULL){ // model_.addObjects(s.continuousSolver()->numberObjects(),s.continuousSolver()->objects()); // } int specOpt = s.getIntParameter(Bonmin::BabSetupBase::SpecialOption); if (specOpt) { model_.setSpecialOptions(specOpt); if (specOpt==16) { Bonmin::CbcNlpStrategy strat(s.getIntParameter(Bonmin::BabSetupBase::MaxFailures), s.getIntParameter(Bonmin::BabSetupBase::MaxInfeasible), s.getIntParameter(Bonmin::BabSetupBase::FailureBehavior)); model_.setStrategy(strat); } } model_.setMaximumCutPasses(s.getIntParameter(Bonmin::BabSetupBase::NumCutPasses)); model_.setMaximumCutPassesAtRoot(s.getIntParameter(Bonmin::BabSetupBase::NumCutPassesAtRoot)); //Setup cutting plane methods for (Bonmin::BabSetupBase::CuttingMethods::iterator i = s.cutGenerators().begin() ; i != s.cutGenerators().end() ; i++) { Bonmin::OaDecompositionBase * oa = dynamic_cast<Bonmin::OaDecompositionBase *>(i->cgl); if (oa && oa->reassignLpsolver()) oa->assignLpInterface(model_.solver()); model_.addCutGenerator(i->cgl,i->frequency,i->id.c_str(), i->normal, i->atSolution); if(i->always){ model_.cutGenerators()[model_.numberCutGenerators()-1] ->setMustCallAgain(true); } } for (Bonmin::BabSetupBase::HeuristicMethods::iterator i = s.heuristics().begin() ; i != s.heuristics().end() ; i++) { CbcHeuristic * heu = i->heuristic; heu->setModel(&model_); model_.addHeuristic(heu, i->id.c_str()); } //need to record solver logLevel here int logLevel = s.continuousSolver()->messageHandler()->logLevel(); //Set true branch-and-bound parameters model_.setLogLevel(s.getIntParameter(Bonmin::BabSetupBase::BabLogLevel)); // Put back solver logLevel model_.solver()->messageHandler()->setLogLevel(logLevel); model_.setPrintFrequency(s.getIntParameter(Bonmin::BabSetupBase::BabLogInterval)); bool ChangedObject = false; //Pass over user set branching priorities to Cbc if (s.continuousSolver()->objects()==NULL) { //assert (s.branchingMethod() == NULL); const OsiTMINLPInterface * nlpSolver = s.nonlinearSolver(); //set priorities, prefered directions... const int * priorities = nlpSolver->getPriorities(); const double * upPsCosts = nlpSolver->getUpPsCosts(); const double * downPsCosts = nlpSolver->getDownPsCosts(); const int * directions = nlpSolver->getBranchingDirections(); bool hasPseudo = (upPsCosts!=NULL); model_.findIntegers(true,hasPseudo); OsiObject ** simpleIntegerObjects = model_.objects(); int numberObjects = model_.numberObjects(); if (priorities != NULL || directions != NULL || hasPseudo) { ChangedObject = true; for (int i = 0 ; i < numberObjects ; i++) { CbcObject * object = dynamic_cast<CbcObject *> (simpleIntegerObjects[i]); int iCol = object->columnNumber(); if (priorities) object->setPriority(priorities[iCol]); if (directions) object->setPreferredWay(directions[iCol]); if (upPsCosts) { CbcSimpleIntegerPseudoCost * pscObject = dynamic_cast<CbcSimpleIntegerPseudoCost*> (object); pscObject->setUpPseudoCost(upPsCosts[iCol]); pscObject->setDownPseudoCost(downPsCosts[iCol]); } } } #if 1 // Now pass user set Sos constraints (code inspired from CoinSolve.cpp) const TMINLP::SosInfo * sos = s.nonlinearSolver()->model()->sosConstraints(); if (!s.getIntParameter(Bonmin::BabSetupBase::DisableSos) && sos && sos->num > 0) { // we have some sos constraints const OsiTMINLPInterface * nlpSolver = s.nonlinearSolver(); const int & numSos = sos->num; (*nlpSolver->messageHandler())<<"Adding "<<sos->num<<" sos constraints." <<CoinMessageEol; CbcObject ** objects = new CbcObject*[numSos]; const int * starts = sos->starts; const int * indices = sos->indices; const char * types = sos->types; const double * weights = sos->weights; //verify if model has user set priorities bool hasPriorities = false; const int * varPriorities = nlpSolver->getPriorities(); int numberObjects = model_.numberObjects(); if (varPriorities) { for (int i = 0 ; i < numberObjects ; i++) { if (varPriorities[i]) { hasPriorities = true; break; } } } const int * sosPriorities = sos->priorities; if (sosPriorities) { for (int i = 0 ; i < numSos ; i++) { if (sosPriorities[i]) { hasPriorities = true; break; } } } for (int i = 0 ; i < numSos ; i++) { int start = starts[i]; int length = starts[i + 1] - start; #ifdef DO_IT_NWAY printf("setting nway object\n"), objects[i] = new CbcNWay(&model_, length, &indices[start], i); objects[i]->setPriority(1); #else objects[i] = new CbcSOS(&model_, length, &indices[start], &weights[start], i, types[i]); objects[i]->setPriority(10); #endif if (hasPriorities && sosPriorities && sosPriorities[i]) { objects[i]->setPriority(sosPriorities[i]); } } model_.addObjects (numSos, objects); for (int i = 0 ; i < numSos ; i++) delete objects[i]; delete [] objects; } #endif //If Setup contains more objects add them to Cbc if (s.objects().size()) { CbcObject ** objects = new CbcObject *[s.objects().size()]; for (unsigned int i = 0 ; i < s.objects().size() ; i++) { objects[i] = dynamic_cast<CbcObject *> (s.objects()[i]); assert(objects[i]); objects[i]->setModel(&model_); } model_.addObjects ((int) s.objects().size(), objects); delete [] objects; } replaceIntegers(model_.objects(), model_.numberObjects()); } else { // Pass in objects to Cbc // Redundant definition of default branching (as Default == User) assert (s.branchingMethod() != NULL); // Add nonlinear and integer objects (need to add OsiSOS) model_.addObjects (s.continuousSolver () -> numberObjects (), s.continuousSolver () -> objects ()); // Now model_ has only CouenneObjects and SOS objects // for (int i=0; i<nco; i++) // if (!(dynamic_cast <CbcSimpleInteger *> (s.continuousSolver () -> objects () [i]))) // model_ . objects () [nRealObj++] = s.continuousSolver () -> objects () [i] -> clone (); CbcBranchDefaultDecision branch; s.branchingMethod()->setSolver(model_.solver()); BonChooseVariable * strong2 = dynamic_cast<BonChooseVariable *>(s.branchingMethod()); if (strong2) strong2->setCbcModel(&model_); branch.setChooseMethod(*s.branchingMethod()); model_.setBranchingMethod(&branch); // prevent duplicating object when copying in CbcModel.cpp model_.solver()->deleteObjects(); } model_.setDblParam(CbcModel::CbcCutoffIncrement, s.getDoubleParameter(Bonmin::BabSetupBase::CutoffDecr)); model_.setCutoff(s.getDoubleParameter(Bonmin::BabSetupBase::Cutoff) + CUTOFF_TOL); model_.setDblParam(CbcModel::CbcAllowableGap, s.getDoubleParameter(Bonmin::BabSetupBase::AllowableGap)); model_.setDblParam(CbcModel::CbcAllowableFractionGap, s.getDoubleParameter(Bonmin::BabSetupBase::AllowableFractionGap)); // Definition of node selection strategy if (s.nodeComparisonMethod()==Bonmin::BabSetupBase::bestBound) { CbcCompareObjective compare; model_.setNodeComparison(compare); } else if (s.nodeComparisonMethod()==Bonmin::BabSetupBase::DFS) { CbcCompareDepth compare; model_.setNodeComparison(compare); } else if (s.nodeComparisonMethod()==Bonmin::BabSetupBase::BFS) { CbcCompareDefault compare; compare.setWeight(0.0); model_.setNodeComparison(compare); } else if (s.nodeComparisonMethod()==Bonmin::BabSetupBase::dynamic) { CbcCompareDefault compare; model_.setNodeComparison(compare); } else if (s.nodeComparisonMethod()==Bonmin::BabSetupBase::bestGuess) { // Right now, this is a mess. We need a separation of the // pseudo costs from the ChooseVariable method CbcCompareEstimate compare; model_.setNodeComparison(compare); GuessHeuristic * guessHeu = new GuessHeuristic(model_); model_.addHeuristic(guessHeu); delete guessHeu; } if (s.treeTraversalMethod() == Bonmin::BabSetupBase::HeapOnly) { //Do nothing this is the default of Cbc. } else if (s.treeTraversalMethod() == Bonmin::BabSetupBase::DiveFromBest) { CbcDiver treeTraversal; treeTraversal.initialize(s); model_.passInTreeHandler(treeTraversal); } else if (s.treeTraversalMethod() == Bonmin::BabSetupBase::ProbedDive) { CbcProbedDiver treeTraversal; treeTraversal.initialize(s); model_.passInTreeHandler(treeTraversal); } else if (s.treeTraversalMethod() == Bonmin::BabSetupBase::DfsDiveFromBest) { CbcDfsDiver treeTraversal; treeTraversal.initialize(s); model_.passInTreeHandler(treeTraversal); } else if (s.treeTraversalMethod() == Bonmin::BabSetupBase::DfsDiveDynamic) { CbcDfsDiver treeTraversal; treeTraversal.initialize(s); model_.passInTreeHandler(treeTraversal); DiverCompare compare; compare.setComparisonDive(*model_.nodeComparison()); compare.setComparisonBound(CbcCompareObjective()); CbcDfsDiver * dfs = dynamic_cast<CbcDfsDiver *> (model_.tree()); assert(dfs); compare.setDiver(dfs); model_.setNodeComparison(compare); } model_.setNumberStrong(s.getIntParameter(Bonmin::BabSetupBase::NumberStrong)); model_.setNumberBeforeTrust(s.getIntParameter(Bonmin::BabSetupBase::MinReliability)); model_.setNumberPenalties(8); model_.setDblParam(CbcModel::CbcMaximumSeconds, s.getDoubleParameter(Bonmin::BabSetupBase::MaxTime)); model_.setMaximumNodes(s.getIntParameter(Bonmin::BabSetupBase::MaxNodes)); model_.setMaximumNumberIterations(s.getIntParameter(Bonmin::BabSetupBase::MaxIterations)); model_.setMaximumSolutions(s.getIntParameter(Bonmin::BabSetupBase::MaxSolutions)); model_.setIntegerTolerance(s.getDoubleParameter(Bonmin::BabSetupBase::IntTol)); //Get objects from model_ if it is not null means there are some sos constraints or non-integer branching object // pass them to cut generators. OsiObject ** objects = model_.objects(); if (specOpt!=16 && objects) { int numberObjects = model_.numberObjects(); if (objects_ != NULL) { for (int i = 0 ; i < nObjects_; i++) delete objects_[i]; } delete [] objects_; objects_ = new OsiObject*[numberObjects]; nObjects_ = numberObjects; for (int i = 0 ; i < numberObjects; i++) { OsiObject * obj = objects[i]; CbcSimpleInteger * intObj = dynamic_cast<CbcSimpleInteger *> (obj); if (intObj) { objects_[i] = intObj->osiObject(); } else { CbcSOS * sosObj = dynamic_cast<CbcSOS *>(obj); if (sosObj) objects_[i] = sosObj->osiObject(model_.solver()); else {//Maybe an unsupported CbcObject CbcObject * cbcObj = dynamic_cast<CbcObject *>(obj); if (cbcObj) { std::cerr<<"Unsupported CbcObject appears in the code"<<std::endl; throw UNSUPPORTED_CBC_OBJECT; } else {//It has to be an OsiObject. objects_[i]=obj->clone(); } } } } CbcCutGenerator ** gen = model_.cutGenerators(); int numGen = model_.numberCutGenerators(); for (int i = 0 ; i < numGen ; i++) { Bonmin::OaDecompositionBase * oa = dynamic_cast<Bonmin::OaDecompositionBase * >(gen[i]->generator()); // if (oa) // printf ("\n\n\nat least one OADecompBase\n\n\n"); if (oa) // pass objects oa->setObjects(objects_,nObjects_); } } // if (objects_) { // for (int i = 0 ; i < nObjects_; i++) // delete objects_ [i]; // delete [] objects_; // } // OsiObject ** objects = model_.objects(); // int numObjects = model_.numberObjects(); // nObjects_ = 0; // objects_ = new OsiObject* [numObjects]; // for (int i=0; i < numObjects; ++i) // if (objects [i]) // objects_ [nObjects_++] = objects [i] -> clone (); try { //Get the time and start. { OsiTMINLPInterface * tmpOsi = NULL; if(s.nonlinearSolver() == s.continuousSolver()){ tmpOsi = dynamic_cast<OsiTMINLPInterface *> (model_.solver()); tmpOsi->forceSolverOutput(s.getIntParameter(Bonmin::BabSetupBase::RootLogLevel)); } model_.initialSolve(); if(tmpOsi != NULL){ tmpOsi->setSolverOutputToDefault(); } } int ival; s.options()->GetEnumValue("enable_dynamic_nlp", ival, "bonmin."); if(s.nonlinearSolver() == s.continuousSolver() && ival) { if(!model_.solver()->isProvenOptimal() ){//Something went wrong check if objective is linear and alternate model // can be solved OsiTMINLPInterface * tmpOsi = dynamic_cast<OsiTMINLPInterface *> (model_.solver()); TMINLPLinObj * tmp_tminlp = dynamic_cast<TMINLPLinObj *> (tmpOsi->model()); tmpOsi->setModel(tmp_tminlp->tminlp()); model_.initialSolve(); } else { LinearCutsGenerator cgl; cgl.initialize(s); OsiCuts cuts; cgl.generateCuts(*model_.solver(), cuts); std::vector<const OsiRowCut *> mycuts(cuts.sizeRowCuts()); for(int i = 0 ; i < cuts.sizeRowCuts() ; i++){ mycuts[i] = cuts.rowCutPtr(i); } model_. solver () -> applyRowCuts ((int) mycuts.size(), (const OsiRowCut **) &mycuts[0]); } //Added by Claudia OsiTMINLPInterface * nlpSolver = dynamic_cast<OsiTMINLPInterface *>(model_.solver()); if(nlpSolver && nlpSolver->getNewCutoffDecr()!=COIN_DBL_MAX) model_.setDblParam(CbcModel::CbcCutoffIncrement, nlpSolver->getNewCutoffDecr()); model_.solver()->resolve(); } // for Couenne model_.passInSolverCharacteristics (bonBabInfoPtr); continuousRelaxation_ =model_.solver()->getObjValue(); if (specOpt==16)//Set warm start point for Ipopt { #if 1 const double * colsol = model_.solver()->getColSolution(); const double * duals = model_.solver()->getRowPrice(); OsiTMINLPInterface * tnlpSolver = dynamic_cast<OsiTMINLPInterface *>(model_.solver()); // Primal dual point is not copied if one (supposedly a better one) has already been put into the solver. if(tnlpSolver->problem()->has_x_init() != 2){ model_.solver()->setColSolution(colsol); model_.solver()->setRowPrice(duals); } #else OsiTMINLPInterface * tnlpSolver = dynamic_cast<OsiTMINLPInterface *>(model_.solver()); CoinWarmStart * warm = tnlpSolver->solver()->getWarmStart(tnlpSolver->problem()); tnlpSolver->solver()->setWarmStart(warm, tnlpSolver->problem()); delete warm; #endif #if 0 // Sometimes primal dual point is problematic in the context of Cut-and-branch model_.solver()->resolve(); if(!model_.solver()->isProvenOptimal()) model_.solver()->setColSolution(NULL); #endif } #ifdef SIGNAL CoinSighandler_t saveSignal = SIG_DFL; // register signal handler saveSignal = signal (SIGINT,couenne_signal_handler); currentBranchModel = &model_; #endif // to get node parent info in Cbc, pass parameter 3. //model_.branchAndBound(3); remaining_time -= CoinCpuTime(); model_.setDblParam(CbcModel::CbcMaximumSeconds, remaining_time); if(remaining_time > 0.) model_.branchAndBound(); } catch(TNLPSolver::UnsolvedError *E){ s.nonlinearSolver()->model()->finalize_solution (TMINLP::MINLP_ERROR, 0, NULL, DBL_MAX); throw E; } numNodes_ = model_.getNodeCount(); bestObj_ = model_.getObjValue(); bestBound_ = model_.getBestPossibleObjValue(); mipIterationCount_ = model_.getIterationCount(); bool hasFailed = false; if (specOpt==16)//Did we continue branching on a failure { CbcNlpStrategy * nlpStrategy = dynamic_cast<CbcNlpStrategy *>(model_.strategy()); if (nlpStrategy) hasFailed = nlpStrategy->hasFailed(); else throw -1; } else hasFailed = s.nonlinearSolver()->hasContinuedOnAFailure(); // Output summarizing cut generators (taken from CbcSolver.cpp) // ToDo put into proper print level int numberGenerators = model_.numberCutGenerators(); for (int iGenerator=0;iGenerator<numberGenerators;iGenerator++) { CbcCutGenerator * generator = model_.cutGenerator(iGenerator); //CglStored * stored = dynamic_cast<CglStored*>(generator->generator()); if (true&&!(generator->numberCutsInTotal() || generator->numberColumnCuts())) continue; if(modelHandler_->logLevel() >= 1) { *modelHandler_ << generator->cutGeneratorName() << "was tried" << generator->numberTimesEntered() << "times and created" << generator->numberCutsInTotal()+generator->numberColumnCuts() << "cuts of which" << generator->numberCutsActive() << "were active after adding rounds of cuts"; // if (generator->timing()) { // char timebuf[20]; // sprintf(timebuf, "(%.3fs)", generator->timeInCutGenerator()); // *modelHandler_ << timebuf << CoinMessageEol; // } // else { // *modelHandler_ << CoinMessageEol; // } } } TMINLP::SolverReturn status = TMINLP::MINLP_ERROR; if (model_.numberObjects()==0) { if (bestSolution_) delete [] bestSolution_; OsiSolverInterface * solver = (s.nonlinearSolver() == s.continuousSolver())? model_.solver() : s.nonlinearSolver(); bestSolution_ = new double[solver->getNumCols()]; CoinCopyN(solver->getColSolution(), solver->getNumCols(), bestSolution_); bestObj_ = bestBound_ = solver->getObjValue(); } if (bonBabInfoPtr->bestSolution2().size() > 0) { assert((int) bonBabInfoPtr->bestSolution2().size() == s.nonlinearSolver()->getNumCols()); if (bestSolution_) delete [] bestSolution_; bestSolution_ = new double[s.nonlinearSolver()->getNumCols()]; std::copy(bonBabInfoPtr->bestSolution2().begin(), bonBabInfoPtr->bestSolution2().end(), bestSolution_); bestObj_ = (bonBabInfoPtr->bestObj2()); (*s.nonlinearSolver()->messageHandler())<<"\nReal objective function: " <<bestObj_<<CoinMessageEol; } else if (model_.bestSolution()) { if (bestSolution_) delete [] bestSolution_; bestSolution_ = new double[s.nonlinearSolver()->getNumCols()]; CoinCopyN(model_.bestSolution(), s.nonlinearSolver()->getNumCols(), bestSolution_); } if(remaining_time <= 0.){ status = TMINLP::LIMIT_EXCEEDED; if (bestSolution_) { mipStatus_ = Feasible; } else { mipStatus_ = NoSolutionKnown; } } else if (model_.status() == 0) { if(model_.isContinuousUnbounded()){ status = TMINLP::CONTINUOUS_UNBOUNDED; mipStatus_ = UnboundedOrInfeasible; } else if (bestSolution_) { status = TMINLP::SUCCESS; mipStatus_ = FeasibleOptimal; } else { status = TMINLP::INFEASIBLE; mipStatus_ = ProvenInfeasible; } } else if (model_.status() == 1 || model_.status() == 5) { #if (BONMIN_VERSION_MAJOR > 1) || (BONMIN_VERSION_MINOR > 6) status = model_.status() == 1 ? TMINLP::LIMIT_EXCEEDED : TMINLP::USER_INTERRUPT; #else status = TMINLP::LIMIT_EXCEEDED; #endif if (bestSolution_) { mipStatus_ = Feasible; } else { mipStatus_ = NoSolutionKnown; } } else if (model_.status()==2) { status = TMINLP::MINLP_ERROR; } // Which solution should we use? false if RBS's, true if Cbc's bool use_RBS_Cbc = !problem_ || !(problem_ -> getRecordBestSol ()) || !(problem_ -> getRecordBestSol () -> getHasSol()) || (((fabs (bestObj_) < COUENNE_INFINITY / 1e4) && (problem_ -> getRecordBestSol () -> getVal () > bestObj_))); /* if we do not pass the cbc solution and problem_ -> getRecordBestSol () -> getHasSol() is true, then there should be a solution vector in problem_ -> getRecordBestSol () */ assert(use_RBS_Cbc || problem_ -> getRecordBestSol () -> getSol() != NULL); s.nonlinearSolver () -> model () -> finalize_solution (status, s.nonlinearSolver () -> getNumCols (), use_RBS_Cbc ? bestSolution_ : problem_ -> getRecordBestSol () -> getSol (), use_RBS_Cbc ? bestObj_ : problem_ -> getRecordBestSol () -> getVal ()); }
int main (int argc, const char *argv[]) { CbcSolver3 solver1; // Read in model using argv[1] // and assert that it is a clean model std::string mpsFileName; if (argc>=2) mpsFileName = argv[1]; int numMpsReadErrors = solver1.readMps(mpsFileName.c_str(),""); assert(numMpsReadErrors==0); double time1 = CoinCpuTime(); /* Options are: preprocess to do preprocessing time in minutes if 2 parameters and numeric taken as time */ bool preProcess=false; double minutes=-1.0; int nGoodParam=0; for (int iParam=2; iParam<argc;iParam++) { if (!strcmp(argv[iParam],"preprocess")) { preProcess=true; nGoodParam++; } else if (!strcmp(argv[iParam],"time")) { if (iParam+1<argc&&isdigit(argv[iParam+1][0])) { minutes=atof(argv[iParam+1]); if (minutes>=0.0) { nGoodParam+=2; iParam++; // skip time } } } } if (nGoodParam==0&&argc==3&&isdigit(argv[2][0])) { // If time is given then stop after that number of minutes minutes = atof(argv[2]); if (minutes>=0.0) nGoodParam=1; } if (nGoodParam!=argc-2) { printf("Usage <file> [preprocess] [time <minutes>] or <file> <minutes>\n"); exit(1); } solver1.initialSolve(); // Reduce printout solver1.setHintParam(OsiDoReducePrint,true,OsiHintTry); // Say we want scaling //solver1.setHintParam(OsiDoScale,true,OsiHintTry); //solver1.setCleanupScaling(1); // See if we want preprocessing OsiSolverInterface * solver2=&solver1; CglPreProcess process; if (preProcess) { /* Do not try and produce equality cliques and do up to 5 passes */ solver2 = process.preProcess(solver1,false,5); if (!solver2) { printf("Pre-processing says infeasible\n"); exit(2); } solver2->resolve(); } CbcModel model(*solver2); // Point to solver OsiSolverInterface * solver3 = model.solver(); CbcSolver3 * osiclp = dynamic_cast< CbcSolver3*> (solver3); assert (osiclp); const double fractionFix=0.985; osiclp->initialize(&model,NULL); osiclp->setAlgorithm(2); osiclp->setMemory(1000); osiclp->setNested(fractionFix); //osiclp->setNested(1.0); //off // Set up some cut generators and defaults // Probing first as gets tight bounds on continuous CglProbing generator1; generator1.setUsingObjective(true); generator1.setMaxPass(3); // Number of unsatisfied variables to look at generator1.setMaxProbe(10); // How far to follow the consequences generator1.setMaxLook(50); // Only look at rows with fewer than this number of elements generator1.setMaxElements(200); generator1.setRowCuts(3); CglGomory generator2; // try larger limit generator2.setLimit(300); CglKnapsackCover generator3; CglOddHole generator4; generator4.setMinimumViolation(0.005); generator4.setMinimumViolationPer(0.00002); // try larger limit generator4.setMaximumEntries(200); CglClique generator5; generator5.setStarCliqueReport(false); generator5.setRowCliqueReport(false); CglMixedIntegerRounding mixedGen; /* This is same as default constructor - (1,true,1) I presume if maxAggregate larger then slower but maybe better criterion can be 1 through 3 Reference: Hugues Marchand and Laurence A. Wolsey Aggregation and Mixed Integer Rounding to Solve MIPs Operations Research, 49(3), May-June 2001. */ int maxAggregate=1; bool multiply=true; int criterion=1; CglMixedIntegerRounding2 mixedGen2(maxAggregate,multiply,criterion); CglFlowCover flowGen; // Add in generators // Experiment with -1 and -99 etc model.addCutGenerator(&generator1,-99,"Probing"); //model.addCutGenerator(&generator2,-1,"Gomory"); //model.addCutGenerator(&generator3,-1,"Knapsack"); //model.addCutGenerator(&generator4,-1,"OddHole"); //model.addCutGenerator(&generator5,-1,"Clique"); //model.addCutGenerator(&flowGen,-1,"FlowCover"); //model.addCutGenerator(&mixedGen,-1,"MixedIntegerRounding"); //model.addCutGenerator(&mixedGen2,-1,"MixedIntegerRounding2"); // Say we want timings int numberGenerators = model.numberCutGenerators(); int iGenerator; for (iGenerator=0;iGenerator<numberGenerators;iGenerator++) { CbcCutGenerator * generator = model.cutGenerator(iGenerator); generator->setTiming(true); } // Allow rounding heuristic CbcRounding heuristic1(model); model.addHeuristic(&heuristic1); // And Greedy heuristic CbcHeuristicGreedyCover heuristic2(model); // Use original upper and perturb more heuristic2.setAlgorithm(11); model.addHeuristic(&heuristic2); // Redundant definition of default branching (as Default == User) CbcBranchUserDecision branch; model.setBranchingMethod(&branch); // Definition of node choice CbcCompareUser compare; model.setNodeComparison(compare); int iColumn; int numberColumns = solver3->getNumCols(); // do pseudo costs CbcObject ** objects = new CbcObject * [numberColumns+1]; const CoinPackedMatrix * matrix = solver3->getMatrixByCol(); // Column copy const int * columnLength = matrix->getVectorLengths(); const double * objective = model.getObjCoefficients(); int n=0; for (iColumn=0;iColumn<numberColumns;iColumn++) { if (solver3->isInteger(iColumn)) { double costPer = objective[iColumn]/ ((double) columnLength[iColumn]); CbcSimpleIntegerPseudoCost * newObject = new CbcSimpleIntegerPseudoCost(&model,n,iColumn, costPer,costPer); newObject->setMethod(3); objects[n++]= newObject; } } // and special fix lots branch objects[n++]=new CbcBranchToFixLots(&model,-1.0e-6,fractionFix+0.01,1,0,NULL); model.addObjects(n,objects); for (iColumn=0;iColumn<n;iColumn++) delete objects[iColumn]; delete [] objects; // High priority for odd object int followPriority=1; model.passInPriorities(&followPriority,true); // Do initial solve to continuous model.initialSolve(); // Could tune more model.setMinimumDrop(CoinMin(1.0, fabs(model.getMinimizationObjValue())*1.0e-3+1.0e-4)); if (model.getNumCols()<500) model.setMaximumCutPassesAtRoot(-100); // always do 100 if possible else if (model.getNumCols()<5000) model.setMaximumCutPassesAtRoot(100); // use minimum drop else model.setMaximumCutPassesAtRoot(20); //model.setMaximumCutPasses(1); // Do more strong branching if small //if (model.getNumCols()<5000) //model.setNumberStrong(10); // Switch off strong branching if wanted model.setNumberStrong(0); model.solver()->setIntParam(OsiMaxNumIterationHotStart,100); // If time is given then stop after that number of minutes if (minutes>=0.0) { std::cout<<"Stopping after "<<minutes<<" minutes"<<std::endl; model.setDblParam(CbcModel::CbcMaximumSeconds,60.0*minutes); } // Switch off most output if (model.getNumCols()<300000) { model.messageHandler()->setLogLevel(1); //model.solver()->messageHandler()->setLogLevel(0); } else { model.messageHandler()->setLogLevel(2); model.solver()->messageHandler()->setLogLevel(1); } //model.messageHandler()->setLogLevel(2); //model.solver()->messageHandler()->setLogLevel(2); //model.setPrintFrequency(50); #define DEBUG_CUTS #ifdef DEBUG_CUTS // Set up debugger by name (only if no preprocesing) if (!preProcess) { std::string problemName ; //model.solver()->getStrParam(OsiProbName,problemName) ; //model.solver()->activateRowCutDebugger(problemName.c_str()) ; model.solver()->activateRowCutDebugger("cap6000a") ; } #endif // Do complete search try { model.branchAndBound(); } catch (CoinError e) { e.print(); if (e.lineNumber()>=0) std::cout<<"This was from a CoinAssert"<<std::endl; exit(0); } //void printHowMany(); //printHowMany(); std::cout<<mpsFileName<<" took "<<CoinCpuTime()-time1<<" seconds, " <<model.getNodeCount()<<" nodes with objective " <<model.getObjValue() <<(!model.status() ? " Finished" : " Not finished") <<std::endl; // Print more statistics std::cout<<"Cuts at root node changed objective from "<<model.getContinuousObjective() <<" to "<<model.rootObjectiveAfterCuts()<<std::endl; for (iGenerator=0;iGenerator<numberGenerators;iGenerator++) { CbcCutGenerator * generator = model.cutGenerator(iGenerator); std::cout<<generator->cutGeneratorName()<<" was tried " <<generator->numberTimesEntered()<<" times and created " <<generator->numberCutsInTotal()<<" cuts of which " <<generator->numberCutsActive()<<" were active after adding rounds of cuts"; if (generator->timing()) std::cout<<" ( "<<generator->timeInCutGenerator()<<" seconds)"<<std::endl; else std::cout<<std::endl; } // Print solution if finished - we can't get names from Osi! if (model.getMinimizationObjValue()<1.0e50) { // post process if (preProcess) process.postProcess(*model.solver()); int numberColumns = model.solver()->getNumCols(); const double * solution = model.solver()->getColSolution(); int iColumn; std::cout<<std::setiosflags(std::ios::fixed|std::ios::showpoint)<<std::setw(14); std::cout<<"--------------------------------------"<<std::endl; for (iColumn=0;iColumn<numberColumns;iColumn++) { double value=solution[iColumn]; if (fabs(value)>1.0e-7&&model.solver()->isInteger(iColumn)) std::cout<<std::setw(6)<<iColumn<<" "<<value<<std::endl; } std::cout<<"--------------------------------------"<<std::endl; std::cout<<std::resetiosflags(std::ios::fixed|std::ios::showpoint|std::ios::scientific); } return 0; }