/** construct master problem */ STO_RTN_CODE TssBd::constructMasterProblem(TssBdSub * tssbdsub, double lowerbound) { #define FREE_MEMORY \ FREE_PTR(mat) \ FREE_ARRAY_PTR(clbd) \ FREE_ARRAY_PTR(cubd) \ FREE_ARRAY_PTR(ctype) \ FREE_ARRAY_PTR(obj) \ FREE_ARRAY_PTR(rlbd) \ FREE_ARRAY_PTR(rubd) \ FREE_ARRAY_PTR(auxind) \ FREE_ARRAY_PTR(auxcoef) assert(model_); if (naux_ <= 0 || !obj_aux_ || !clbd_aux_ || !cubd_aux_) { printf("Warning: Auxiliary column information is required.\n"); return 1; } /** master problem */ CoinPackedMatrix * mat = NULL; double * clbd = NULL; double * cubd = NULL; double * obj = NULL; char * ctype = NULL; double * rlbd = NULL; double * rubd = NULL; /** for recourse lower bound */ int * auxind = NULL; double * auxcoef = NULL; BGN_TRY_CATCH int ncols = model_->getNumCols(0) + naugs_ * model_->getNumCols(1) + naux_; /** number of integer variables in the core */ int nIntegers = model_->getNumCoreIntegers(); /** allocate memory */ auxind = new int [ncols]; auxcoef = new double [ncols]; /** decompose model */ STO_RTN_CHECK_THROW(model_->decompose( naugs_, augs_, naux_, clbd_aux_, cubd_aux_, obj_aux_, mat, clbd, cubd, ctype, obj, rlbd, rubd), "decompose", "TssModel"); /** convert column types */ if (par_->relaxIntegrality_[0]) { for (int j = 0; j < model_->getNumCols(0); ++j) { if (ctype[j] != 'C') nIntegers--; ctype[j] = 'C'; } } if (par_->relaxIntegrality_[1] && naugs_ > 0) { for (int j = 0; j < model_->getNumCols(1); ++j) { if (ctype[model_->getNumCols(0) + j] != 'C') nIntegers--; } CoinFillN(ctype + model_->getNumCols(0), naugs_ * model_->getNumCols(1), 'C'); } if (nIntegers > 0) { si_ = new SolverInterfaceScip(par_); si_->setPrintLevel(CoinMin(par_->logLevel_ + 1, 5)); } else { si_ = new SolverInterfaceSpx(par_); si_->setPrintLevel(CoinMax(par_->logLevel_ - 1, 0)); } /** load problem data */ si_->loadProblem(mat, clbd, cubd, obj, ctype, rlbd, rubd, "BdMaster"); /** add row for lower bound */ for (int j = 0; j < ncols; ++j) auxind[j] = j; CoinCopyN(obj, ncols, auxcoef); si_->addRow(ncols, auxind, auxcoef, lowerbound, COIN_DBL_MAX); /** save memory */ FREE_MEMORY END_TRY_CATCH_RTN(FREE_MEMORY,STO_RTN_ERR) return STO_RTN_OK; #undef FREE_MEMORY }
template <class T> inline void CoinMemcpyN(register const T* from, const int size, register T* to) { #ifndef _MSC_VER #ifdef USE_MEMCPY // Use memcpy - seems a lot faster on Intel with gcc #ifndef NDEBUG // Some debug so check if (size < 0) throw CoinError("trying to copy negative number of entries", "CoinMemcpyN", ""); #if 0 /* There is no point to do this test. If to and from are from different blocks then dist is undefined, so this can crash correct code. It's better to trust the user that the arrays are really disjoint. */ const long dist = to - from; if (-size < dist && dist < size) throw CoinError("overlapping arrays", "CoinMemcpyN", ""); #endif #endif std::memcpy(to,from,size*sizeof(T)); #else if (size == 0 || from == to) return; #ifndef NDEBUG if (size < 0) throw CoinError("trying to copy negative number of entries", "CoinMemcpyN", ""); #endif #if 0 /* There is no point to do this test. If to and from are from different blocks then dist is undefined, so this can crash correct code. It's better to trust the user that the arrays are really disjoint. */ const long dist = to - from; if (-size < dist && dist < size) throw CoinError("overlapping arrays", "CoinMemcpyN", ""); #endif for (register int n = size / 8; n > 0; --n, from += 8, to += 8) { to[0] = from[0]; to[1] = from[1]; to[2] = from[2]; to[3] = from[3]; to[4] = from[4]; to[5] = from[5]; to[6] = from[6]; to[7] = from[7]; } switch (size % 8) { case 7: to[6] = from[6]; case 6: to[5] = from[5]; case 5: to[4] = from[4]; case 4: to[3] = from[3]; case 3: to[2] = from[2]; case 2: to[1] = from[1]; case 1: to[0] = from[0]; case 0: break; } #endif #else CoinCopyN(from, size, to); #endif }
/** This helper function copies an array to another location using Duff's device (for a speedup of ~2). The source array is given by its first and "after last" entry; the target array is given by its first entry. Overlapping arrays are handled correctly. All of the various CoinCopyN variants use an int for size. On 64-bit architectures, the address diff last-first will be a 64-bit quantity. Given that everything else uses an int, I'm going to choose to kick the difference down to int. -- lh, 100823 -- */ template <class T> inline void CoinCopy(register const T* first, register const T* last, register T* to) { CoinCopyN(first, static_cast<int>(last-first), to); }
//############################################################################# void MibSHeuristic::greedyHeuristic() { MibSModel * model = MibSModel_; //OsiSolverInterface * oSolver = model->getSolver(); OsiSolverInterface * oSolver = model->solver(); double uObjSense(oSolver->getObjSense()); double lObjSense(model->getLowerObjSense()); int lCols(model->getLowerDim()); int uCols(model->getUpperDim()); int * uColIndices = model->getUpperColInd(); int * lColIndices = model->getLowerColInd(); double * lObjCoeffs = model->getLowerObjCoeffs(); double * intCost = model->getInterdictCost(); double intBudget = model->getInterdictBudget(); int tCols(uCols + lCols); assert(tCols == oSolver->getNumCols()); int i(0), ind_min_wt(0); double usedBudget(0.0); double * fixedVars = new double[lCols]; double * testsol = new double[tCols]; CoinZeroN(fixedVars, lCols); CoinZeroN(testsol, tCols); std::multimap<double, int> lObjCoeffsOrd; for(i = 0; i < lCols; i++) lObjCoeffsOrd.insert(std::pair<double, int>(lObjCoeffs[i] * lObjSense, i)); if(!bestSol_) bestSol_ = new double[tCols]; //initialize the best solution information //bestObjVal_ = model->getSolver()->getInfinity() * uObjSense; //CoinZeroN(bestSol_, tCols); std::multimap<double, int>::iterator iter; //std::multimap<double, int>::iterator first; //std::multimap<double, int>::iterator last; //int dist = std::distance(first, last); SRANDOM((unsigned) time(NULL)); int randchoice(0); if(0) std::cout << "randchoice " << randchoice << std::endl; double cost(0.0); //starting from the largest, fix corr upper-level variables //then, with these fixed, solve the lower-level problem //this yields a feasible solution iter = lObjCoeffsOrd.begin(); while((usedBudget < intBudget) && (iter != lObjCoeffsOrd.end())){ ind_min_wt = iter->second; cost = intCost[ind_min_wt]; testsol[uColIndices[ind_min_wt]] = 1.0; double min_wt = iter->first; if(0){ std::cout << "upper: " << ind_min_wt << " " << uColIndices[ind_min_wt] << " " << oSolver->getColUpper()[uColIndices[ind_min_wt]] << " " << oSolver->getColLower()[uColIndices[ind_min_wt]] << std::endl; std::cout << "lower: " << ind_min_wt << " " << lColIndices[ind_min_wt] << " " << oSolver->getColUpper()[lColIndices[ind_min_wt]] << std::endl; } //if((oSolver->getColUpper()[uColIndices[ind_min_wt]] == 1.0) //&& (oSolver->getColUpper()[lColIndices[ind_min_wt]] > 0)){ if(oSolver->getColUpper()[uColIndices[ind_min_wt]] > etol_){ //if(((usedBudget + cost) <= intBudget) // && checkLowerFeasibility(oSolver, testsol)){ if((usedBudget + cost) <= intBudget){ //FIXME: SHOULD BE CHECKING FOR CURRENT BOUNDS HERE //fix the corresponding upper-level variable to 1 randchoice = RANDOM() % 2; if(0) std::cout << "randchoice " << randchoice << std::endl; if(randchoice){ fixedVars[ind_min_wt] = 1.0; usedBudget += intCost[ind_min_wt]; } } } else{ testsol[uColIndices[ind_min_wt]] = 0; //break; } iter++; } /* now we find a feasible solution by fixing upper-level vars and solving the lower-level problem */ double * incumbentSol = new double[tCols]; double * colsol = new double[tCols]; CoinZeroN(colsol, tCols); for(i = 0; i < uCols; i++){ colsol[uColIndices[i]] = fixedVars[i]; if(fixedVars[i] == 1.0) if(0) std::cout << "fixed " << i << std::endl; } bfSol * sol = getBilevelSolution(colsol, lObjSense * oSolver->getInfinity()); if(sol){ double incumbentObjVal = sol->getObjVal(); CoinCopyN(sol->getColumnSol(), tCols, incumbentSol); MibSSolution * mibSol = new MibSSolution(tCols, incumbentSol, incumbentObjVal, model); model->storeSolution(BlisSolutionTypeHeuristic, mibSol); } //bestObjVal_ = incumbentObjVal; //CoinCopyN(incumbentSol, tCols, bestSol_); delete [] incumbentSol; delete [] testsol; //delete [] colsol; //delete [] fixedVars; //delete sol; }
//############################################################################# void MibSHeuristic::createBilevelSolutions(std::map<double, mcSol> mcSolutions) { MibSModel * model = MibSModel_; double uObjSense(model->getSolver()->getObjSense()); int lCols(model->getLowerDim()); int uCols(model->getUpperDim()); int tCols(uCols + lCols); double incumbentObjVal(model->getSolver()->getInfinity() * uObjSense); double * incumbentSol = new double[tCols]; int i(0); if(!bestSol_) bestSol_ = new double[tCols]; //initialize the best solution information //bestObjVal_ = model->getSolver()->getInfinity() * uObjSense; //CoinZeroN(bestSol_, tCols); std::map<double, mcSol >::iterator iter = mcSolutions.begin(); for(iter = mcSolutions.begin(); iter != mcSolutions.end(); iter++){ mcSol tmpsol = iter->second; const double * colsol = tmpsol.getColumnSol(); double origLower = tmpsol.getObjPair().second; if(0){ std::cout << "Candidate solution value: " << origLower << std::endl; for(i = 0; i < tCols; i++){ std::cout << "colsol[" << i << "] :" << colsol[i] << std::endl; } } bfSol * sol = getBilevelSolution(colsol, origLower); if(sol){ if(0){ std::cout << "Returned solution: " << std::endl; for(i = 0; i < tCols; i++){ std::cout << "sol->getColumnSol[" << i << "]" << sol->getColumnSol()[i] << std::endl; } std::cout << "sol->getObjVal: " << sol->getObjVal() << std::endl; } if(sol->getObjVal() < incumbentObjVal){ incumbentObjVal = sol->getObjVal(); CoinCopyN(sol->getColumnSol(), tCols, incumbentSol); if(0){ std::cout << "New incumbent found." << std::endl; for(i = 0; i < tCols; i++){ std::cout << "incumbentSol[" << i << "]: " << incumbentSol[i] << std::endl; } std::cout << "incumbentObjVal: " << incumbentObjVal << std::endl; } } } } if(0){ std::cout << "This solution comes from MibSHeuristic.cpp:742" << std::endl; } MibSSolution * mibSol = new MibSSolution(tCols, incumbentSol, incumbentObjVal, model); model->storeSolution(BlisSolutionTypeHeuristic, mibSol); //need to add this solution to mibssolutions instead //bestObjVal_ = incumbentObjVal; //CoinCopyN(incumbentSol, tCols, bestSol_); //delete bfSol; delete [] incumbentSol; }
//############################################################################# mcSol MibSHeuristic::solveSubproblem(double beta) { /* optimize wrt to weighted upper-level objective over current feasible lp feasible region */ MibSModel * model = MibSModel_; OsiSolverInterface * oSolver = model->getSolver(); #ifndef COIN_HAS_SYMPHONY OsiSolverInterface * sSolver = new OsiCbcSolverInterface(); #else OsiSolverInterface* sSolver = new OsiSymSolverInterface(); //sSolver = oSolver->clone(); //OsiSolverInterface * sSolver = tmpSolver; //OsiSolverInterface * tmpSolver = new OsiSolverInterface(oSolver); #endif double uObjSense(oSolver->getObjSense()); double lObjSense(model->getLowerObjSense()); int lCols(model->getLowerDim()); int uCols(model->getUpperDim()); int * lColIndices = model->getLowerColInd(); int * uColIndices = model->getUpperColInd(); double * lObjCoeffs = model->getLowerObjCoeffs(); const double * uObjCoeffs = oSolver->getObjCoefficients(); double etol(etol_); int tCols(uCols + lCols); assert(tCols == oSolver->getNumCols()); sSolver->loadProblem(*oSolver->getMatrixByCol(), oSolver->getColLower(), oSolver->getColUpper(), oSolver->getObjCoefficients(), oSolver->getRowLower(), oSolver->getRowUpper()); int j(0); for(j = 0; j < tCols; j++){ if(oSolver->isInteger(j)) sSolver->setInteger(j); } double * nObjCoeffs = new double[tCols]; int i(0), index(0); CoinZeroN(nObjCoeffs, tCols); /* Multiply the UL columns of the UL objective by beta */ for(i = 0; i < uCols; i++){ index = uColIndices[i]; if(fabs(uObjCoeffs[index]) > etol) nObjCoeffs[index] = beta * uObjCoeffs[index] * uObjSense; else nObjCoeffs[index] = 0.0; } /* Multiply the LL columns of the UL objective by beta */ for(i = 0; i < lCols; i++){ index = lColIndices[i]; if(fabs(uObjCoeffs[index]) > etol) nObjCoeffs[index] = beta* uObjCoeffs[index] * uObjSense; else nObjCoeffs[index] = 0.0; } /* Add the LL columns of the LL objective multiplied by (1 - beta) */ for(i = 0; i < lCols; i++){ index = lColIndices[i]; if(fabs(lObjCoeffs[i]) > etol) nObjCoeffs[index] += (1 - beta) * lObjCoeffs[i] * lObjSense; } sSolver->setObjective(nObjCoeffs); //int i(0); if(0){ for(i = 0; i < sSolver->getNumCols(); i++){ std::cout << "betaobj " << sSolver->getObjCoefficients()[i] << std::endl; } } if(0){ sSolver->writeLp("afterbeta"); //sSolver->writeMps("afterbeta"); } if(0){ for(i = 0; i < sSolver->getNumCols(); i++){ std::cout << "obj " << sSolver->getObjCoefficients()[i] << std::endl; std::cout << "upper " << sSolver->getColUpper()[i] << std::endl; std::cout << "lower " << sSolver->getColLower()[i] << std::endl; } } #ifndef COIN_HAS_SYMPHONY dynamic_cast<OsiCbcSolverInterface *> (sSolver)->getModelPtr()->messageHandler()->setLogLevel(0); #else dynamic_cast<OsiSymSolverInterface *> (sSolver)->setSymParam("prep_level", -1); dynamic_cast<OsiSymSolverInterface *> (sSolver)->setSymParam("verbosity", -2); dynamic_cast<OsiSymSolverInterface *> (sSolver)->setSymParam("max_active_nodes", 1); #endif //dynamic_cast<OsiSymSolverInterface *> (sSolver)->branchAndBound(); sSolver->branchAndBound(); if(sSolver->isProvenOptimal()){ if(0){ std::cout << "writing lp file." << std::endl; sSolver->writeLp("afterbeta"); //sSolver->writeMps("afterbeta"); } double upperObjVal(0.0); double lowerObjVal(0.0); for(i = 0; i < tCols; i++){ upperObjVal += sSolver->getColSolution()[i] * oSolver->getObjCoefficients()[i]; if(0){ std::cout << "sSolver->getColSolution()[" << i << "] :" << sSolver->getColSolution()[i] << std::endl; } } lowerObjVal = getLowerObj(sSolver->getColSolution(), lObjSense); if(beta == 1.0){ /* fix upper-level objective to current value and reoptimize wrt to lower-level objective */ #ifndef COIN_HAS_SYMPHONY OsiSolverInterface * nSolver = new OsiCbcSolverInterface(); #else OsiSolverInterface * nSolver = new OsiSymSolverInterface(); #endif nSolver->loadProblem(*oSolver->getMatrixByCol(), oSolver->getColLower(), oSolver->getColUpper(), oSolver->getObjCoefficients(), oSolver->getRowLower(), oSolver->getRowUpper()); for(j = 0; j < tCols; j++){ if(oSolver->isInteger(j)) nSolver->setInteger(j); } CoinZeroN(nObjCoeffs, tCols); for(i = 0; i < lCols; i++){ index = lColIndices[i]; nObjCoeffs[index] = lObjCoeffs[i] * lObjSense; } nSolver->setObjective(nObjCoeffs); CoinPackedVector objCon; for(i = 0; i < tCols; i++){ objCon.insert(i, uObjCoeffs[i] * uObjSense); } nSolver->addRow(objCon, upperObjVal, upperObjVal); nSolver->writeLp("beta1"); #ifndef COIN_HAS_SYMPHONY dynamic_cast<OsiCbcSolverInterface *> (nSolver)->getModelPtr()->messageHandler()->setLogLevel(0); #else dynamic_cast<OsiSymSolverInterface *> (nSolver)->setSymParam("prep_level", -1); dynamic_cast<OsiSymSolverInterface *> (nSolver)->setSymParam("verbosity", -2); dynamic_cast<OsiSymSolverInterface *> (nSolver)->setSymParam("max_active_nodes", 1); #endif nSolver->branchAndBound(); double * colsol = new double[tCols]; if(nSolver->isProvenOptimal()){ lowerObjVal = nSolver->getObjValue(); CoinCopyN(nSolver->getColSolution(), tCols, colsol); } else{ //just take the current solution lowerObjVal = sSolver->getObjValue(); CoinCopyN(sSolver->getColSolution(), tCols, colsol); } delete[] nObjCoeffs; nObjCoeffs = 0; delete sSolver; delete nSolver; return mcSol(std::make_pair(upperObjVal, lowerObjVal), colsol); } else if(beta == 0.0){ /* fix lower-level objective to current value and reoptimize wrt to upper-level objective */ #ifndef COIN_HAS_SYMPHONY OsiSolverInterface * nSolver = new OsiCbcSolverInterface(); #else OsiSolverInterface * nSolver = new OsiSymSolverInterface(); #endif nSolver->loadProblem(*oSolver->getMatrixByCol(), oSolver->getColLower(), oSolver->getColUpper(), oSolver->getObjCoefficients(), oSolver->getRowLower(), oSolver->getRowUpper()); for(j = 0; j < tCols; j++){ if(oSolver->isInteger(j)) nSolver->setInteger(j); } CoinZeroN(nObjCoeffs, tCols); for(i = 0; i < tCols; i++) nObjCoeffs[i] = uObjCoeffs[i] * uObjSense; nSolver->setObjective(nObjCoeffs); CoinPackedVector objCon; for(i = 0; i < lCols; i++){ index = lColIndices[i]; objCon.insert(index, lObjCoeffs[i] * lObjSense); } nSolver->addRow(objCon, lowerObjVal, lowerObjVal); #ifndef COIN_HAS_SYMPHONY dynamic_cast<OsiCbcSolverInterface *> (nSolver)->getModelPtr()->messageHandler()->setLogLevel(0); #else dynamic_cast<OsiSymSolverInterface *> (nSolver)->setSymParam("prep_level", -1); dynamic_cast<OsiSymSolverInterface *> (nSolver)->setSymParam("verbosity", -2); dynamic_cast<OsiSymSolverInterface *> (nSolver)->setSymParam("max_active_nodes", 1); #endif if(0) nSolver->writeLp("nSolver"); nSolver->branchAndBound(); double * colsol = new double[tCols]; if(nSolver->isProvenOptimal()){ upperObjVal = nSolver->getObjValue(); CoinCopyN(nSolver->getColSolution(), tCols, colsol); } else{ upperObjVal = nSolver->getObjValue(); CoinCopyN(nSolver->getColSolution(), tCols, colsol); } delete[] nObjCoeffs; nObjCoeffs = 0; delete sSolver; delete nSolver; return mcSol(std::make_pair(upperObjVal, lowerObjVal), colsol); } else{ //no optimality cut needed here. all solutions are supported. double * colsol = new double[tCols]; CoinCopyN(sSolver->getColSolution(), tCols, colsol); delete[] nObjCoeffs; nObjCoeffs = 0; delete sSolver; return mcSol(std::make_pair(upperObjVal, lowerObjVal), colsol); } } else{ //FIXME:SHOULD JUST TAKE THIS OUT. DELETE sSolver and remove it from above nObjCoeffs = 0; delete[] nObjCoeffs; delete sSolver; std::cout << "Subproblem is not proven optimal." << std::endl; //return NULL; //abort(); } }
//############################################################################# bfSol* MibSHeuristic::getBilevelSolution1(const double * sol) { /* Find a bilevel feasible solution by solving the LL problem for a fixed UL solution, given by the UL portion of sol */ MibSModel * model = MibSModel_; OsiSolverInterface * oSolver = model->getSolver(); OsiSolverInterface * lSolver = new OsiCbcSolverInterface(oSolver); //double uObjSense(model->getSolver()->getObjSense()); double lObjSense(model->getLowerObjSense()); int lCols(model->getLowerDim()); int uCols(model->getUpperDim()); int * lColIndices = model->getLowerColInd(); int uRowNum = model->getUpperRowNum(); int lRowNum = model->getLowerRowNum(); int * uRowIndices = model->getUpperRowInd(); int * lRowIndices = model->getLowerRowInd(); int * uColIndices = model->getUpperColInd(); double * lObjCoeffs = model->getLowerObjCoeffs(); int tCols(uCols + lCols); int i(0), index(0); /* delete the UL rows */ lSolver->deleteRows(uRowNum, uRowIndices); /* Fix the UL variables to their current value in sol */ for(i = 0; i < uCols; i++){ index = uColIndices[i]; lSolver->setColLower(index, sol[index]); lSolver->setColUpper(index, sol[index]); } /* Set the objective to the LL objective coefficients */ double * nObjCoeffs = new double[tCols]; CoinZeroN(nObjCoeffs, tCols); for(i = 0; i < lCols; i++){ index = lColIndices[i]; nObjCoeffs[index] = lObjCoeffs[i] * lObjSense; } lSolver->setObjective(nObjCoeffs); #ifndef COIN_HAS_SYMPHONY dynamic_cast<OsiCbcSolverInterface *> (lSolver)->getModelPtr()->messageHandler()->setLogLevel(0); #else dynamic_cast<OsiSymSolverInterface *> (lSolver)->setSymParam("prep_level", -1); dynamic_cast<OsiSymSolverInterface *> (lSolver)->setSymParam("verbosity", -2); dynamic_cast<OsiSymSolverInterface *> (lSolver)->setSymParam("max_active_nodes", 1); #endif lSolver->branchAndBound(); if(lSolver->isProvenOptimal()){ double objVal(0.0); for(i = 0; i < tCols; i++) objVal += lSolver->getColSolution()[i] * oSolver->getObjCoefficients()[i]; double * colsol = new double[tCols]; CoinCopyN(lSolver->getColSolution(), tCols, colsol); bfSol * bfsol = new bfSol(objVal, colsol); delete lSolver; return bfsol; } else{ delete lSolver; return NULL; } }
void CouenneCutGenerator::generateCuts (const OsiSolverInterface &si, OsiCuts &cs, const CglTreeInfo info) #if CGL_VERSION_MAJOR == 0 && CGL_VERSION_MINOR <= 57 const #endif { // check if out of time or if an infeasibility cut (iis of type 0) // was added as a result of, e.g., pruning on BT. If so, no need to // run this. if (isWiped (cs) || (CoinCpuTime () > problem_ -> getMaxCpuTime ())) return; #ifdef FM_TRACE_OPTSOL double currCutOff = problem_->getCutOff(); double bestVal = 1e50; CouenneRecordBestSol *rs = problem_->getRecordBestSol(); if(rs->getHasSol()) { bestVal = rs->getVal(); } if(currCutOff > bestVal) { //problem_ -> setCutOff (bestVal - 1e-6); // FIXME: don't add numerical constants problem_ -> setCutOff (bestVal); int indObj = problem_->Obj(0)->Body()->Index(); if (indObj >= 0) { OsiColCut *objCut = new OsiColCut; objCut->setUbs(1, &indObj, &bestVal); cs.insert(objCut); delete objCut; } } #endif #ifdef FM_PRINT_INFO if((BabPtr_ != NULL) && (info.level >= 0) && (info.pass == 0) && (BabPtr_->model().getNodeCount() > lastPrintLine)) { printLineInfo(); lastPrintLine += 1; } #endif const int infeasible = 1; int nInitCuts = cs.sizeRowCuts (); CouNumber *&realOpt = problem_ -> bestSol (), *saveOptimum = realOpt; if (!firstcall_ && realOpt) { // have a debug optimal solution. Check if current bounds // contain it, otherwise pretend it does not exist CouNumber *opt = realOpt; const CouNumber *sol = si.getColSolution (), *lb = si.getColLower (), *ub = si.getColUpper (); int objind = problem_ -> Obj (0) -> Body () -> Index (); for (int j=0, i=problem_ -> nVars (); i--; j++, opt++, lb++, ub++) if ((j != objind) && ((*opt < *lb - COUENNE_EPS * (1 + CoinMin (fabs (*opt), fabs (*lb)))) || (*opt > *ub + COUENNE_EPS * (1 + CoinMin (fabs (*opt), fabs (*ub)))))) { jnlst_ -> Printf (J_VECTOR, J_CONVEXIFYING, "out of bounds, ignore x%d = %g [%g,%g] opt = %g\n", problem_ -> nVars () - i - 1, *sol, *lb, *ub, *opt); // optimal point is not in current bounding box, // pretend realOpt is NULL until we return from this procedure realOpt = NULL; break; } } /*static int count = 0; char fname [20]; sprintf (fname, "relax_%d", count++); si.writeLp (fname); printf ("writing %s\n", fname);*/ jnlst_ -> Printf (J_DETAILED, J_CONVEXIFYING, "generateCuts: level = %d, pass = %d, intree = %d\n", info.level, info.pass, info.inTree); Bonmin::BabInfo * babInfo = dynamic_cast <Bonmin::BabInfo *> (si.getAuxiliaryInfo ()); if (babInfo) babInfo -> setFeasibleNode (); double now = CoinCpuTime (); int ncols = problem_ -> nVars (); // This vector contains variables whose bounds have changed due to // branching, reduced cost fixing, or bound tightening below. To be // used with malloc/realloc/free t_chg_bounds *chg_bds = new t_chg_bounds [ncols]; /*for (int i=0; i < ncols; i++) if (problem_ -> Var (i) -> Multiplicity () <= 0) { chg_bds [i].setLower (t_chg_bounds::UNCHANGED); chg_bds [i].setUpper (t_chg_bounds::UNCHANGED); }*/ problem_ -> installCutOff (); // install upper bound if (firstcall_) { // First convexification ////////////////////////////////////// // OsiSolverInterface is empty yet, no information can be obtained // on variables or bounds -- and none is needed since our // constructor populated *problem_ with variables and bounds. We // only need to update the auxiliary variables and bounds with // their current value. for (int i=0; i < ncols; i++) if (problem_ -> Var (i) -> Multiplicity () > 0) { chg_bds [i].setLower (t_chg_bounds::CHANGED); chg_bds [i].setUpper (t_chg_bounds::CHANGED); } // start with FBBT, should take advantage of cutoff found by NLP // run AFTER initial FBBT... if (problem_ -> doFBBT () && (! (problem_ -> boundTightening (chg_bds, babInfo)))) jnlst_ -> Printf (J_STRONGWARNING, J_CONVEXIFYING, "Couenne: WARNING, first convexification is infeasible\n"); // For each auxiliary variable replacing the original (nonlinear) // constraints, check if corresponding bounds are violated, and // add cut to cs int nnlc = problem_ -> nCons (); for (int i=0; i<nnlc; i++) { if (CoinCpuTime () > problem_ -> getMaxCpuTime ()) break; // for each constraint CouenneConstraint *con = problem_ -> Con (i); // (which has an aux as its body) int objindex = con -> Body () -> Index (); if ((objindex >= 0) && ((con -> Body () -> Type () == AUX) || (con -> Body () -> Type () == VAR))) { // get the auxiliary that is at the lhs exprVar *conaux = problem_ -> Var (objindex); if (conaux && (conaux -> Type () == AUX) && (conaux -> Image ()) && (conaux -> Image () -> Linearity () <= LINEAR)) { // reduce density of problem by adding w >= l rather than // ax + b >= l for any linear auxiliary defined as w := ax+b double lb = (*(con -> Lb ())) (), ub = (*(con -> Ub ())) (); OsiColCut newBound; if (lb > -COUENNE_INFINITY) newBound.setLbs (1, &objindex, &lb); if (ub < COUENNE_INFINITY) newBound.setUbs (1, &objindex, &ub); cs.insert (newBound); // the auxiliary w of constraint w <= b is associated with a // linear expression w = ax: add constraint ax <= b /*conaux -> Image () -> generateCuts (conaux, si, cs, this, chg_bds, conaux -> Index (), (*(con -> Lb ())) (), (*(con -> Ub ())) ());*/ // take it from the list of the variables to be linearized // // DO NOT decrease multiplicity. Even if it is a linear // term, its bounds can still be used in implied bounds // // Are we sure? That will happen only if its multiplicity is // nonzero, for otherwise this aux is only used here, and is // useless elsewhere // //conaux -> decreaseMult (); // !!! } // also, add constraint w <= b // not now, do it later // // if there exists violation, add constraint // CouNumber l = con -> Lb () -> Value (), // u = con -> Ub () -> Value (); // // tighten bounds in Couenne's problem representation // problem_ -> Lb (index) = CoinMax (l, problem_ -> Lb (index)); // problem_ -> Ub (index) = CoinMin (u, problem_ -> Ub (index)); } else { // body is more than just a variable, but it should be // linear. If so, generate equivalent linear cut assert (false); // TODO } } if (jnlst_ -> ProduceOutput (J_ITERSUMMARY, J_CONVEXIFYING)) { if (cs.sizeRowCuts ()) { jnlst_ -> Printf (J_ITERSUMMARY, J_CONVEXIFYING,"Couenne: %d constraint row cuts\n", cs.sizeRowCuts ()); for (int i=0; i<cs.sizeRowCuts (); i++) cs.rowCutPtr (i) -> print (); } if (cs.sizeColCuts ()) { jnlst_ -> Printf (J_ITERSUMMARY, J_CONVEXIFYING,"Couenne: %d constraint col cuts\n", cs.sizeColCuts ()); for (int i=0; i<cs.sizeColCuts (); i++) cs.colCutPtr (i) -> print (); } } } else { // use new optimum as lower bound for variable associated w/objective int indobj = problem_ -> Obj (0) -> Body () -> Index (); // transmit solution from OsiSolverInterface to problem problem_ -> domain () -> push (&si, &cs); if (indobj >= 0) { // Use current value of objvalue's x as a lower bound for bound // tightening double lp_bound = problem_ -> domain () -> x (indobj); //if (problem_ -> Obj (0) -> Sense () == MINIMIZE) {if (lp_bound > problem_ -> Lb (indobj)) problem_ -> Lb (indobj) = lp_bound;} //else {if (lp_bound < problem_ -> Ub (indobj)) problem_ -> Ub (indobj) = lp_bound;} } updateBranchInfo (si, problem_, chg_bds, info); // info.depth >= 0 || info.pass >= 0 } // restore constraint bounds before tightening and cut generation for (int i = problem_ -> nCons (); i--;) { // for each constraint CouenneConstraint *con = problem_ -> Con (i); // (which has an aux as its body) int objindex = con -> Body () -> Index (); if ((objindex >= 0) && ((con -> Body () -> Type () == AUX) || (con -> Body () -> Type () == VAR))) { // if there exists violation, add constraint CouNumber l = con -> Lb () -> Value (), u = con -> Ub () -> Value (); // tighten bounds in Couenne's problem representation problem_ -> Lb (objindex) = CoinMax (l, problem_ -> Lb (objindex)); problem_ -> Ub (objindex) = CoinMin (u, problem_ -> Ub (objindex)); } } problem_ -> installCutOff (); // install upper bound fictitiousBound (cs, problem_, false); // install finite lower bound, if currently -inf int *changed = NULL, nchanged; // Bound tightening /////////////////////////////////////////// // do bound tightening only at first pass of cutting plane in a node // of BB tree (info.pass == 0) or if first call (creation of RLT, // info.pass == -1) try { // Before bound tightening, compute symmetry group. After bound // tightening is done, we can apply further tightening using orbit // information. #ifdef COIN_HAS_NTY // ChangeBounds (psi -> getColLower (), // psi -> getColUpper (), // psi -> getNumCols ()); if (problem_ -> orbitalBranching ()) problem_ -> Compute_Symmetry (); #endif // Bound tightening //////////////////////////////////// /*printf ("== BT ================\n"); for (int i = 0; i < problem_ -> nVars (); i++) if (problem_ -> Var (i) -> Multiplicity () > 0) printf ("%4d %+20.8g [%+20.8g,%+20.8g]\n", i, problem_ -> X (i), problem_ -> Lb (i), problem_ -> Ub (i)); printf("=============================\n");*/ // Reduced Cost BT -- to be done first to use rcost correctly if (!firstcall_ && // have a linearization already problem_ -> doRCBT () && // authorized to do reduced cost tightening problem_ -> redCostBT (&si, chg_bds) && // some variables were tightened with reduced cost !(problem_ -> btCore (chg_bds))) // in this case, do another round of FBBT throw infeasible; // FBBT if (problem_ -> doFBBT () && //(info.pass <= 0) && // do it in subsequent rounds too (! (problem_ -> boundTightening (chg_bds, babInfo)))) throw infeasible; // OBBT if (!firstcall_ && // no obbt if first call (there is no LP to work with) problem_ -> obbt (this, si, cs, info, babInfo, chg_bds) < 0) throw infeasible; // Bound tightening done ///////////////////////////// if ((problem_ -> doFBBT () || problem_ -> doOBBT () || problem_ -> doABT ()) && (jnlst_ -> ProduceOutput (J_VECTOR, J_CONVEXIFYING))) { jnlst_ -> Printf(J_VECTOR, J_CONVEXIFYING,"== after bt =============\n"); for (int i = 0; i < problem_ -> nVars (); i++) if (problem_ -> Var (i) -> Multiplicity () > 0) jnlst_->Printf(J_VECTOR, J_CONVEXIFYING,"%4d %+20.8g [%+20.8g,%+20.8g]\n", i, problem_ -> X (i), problem_ -> Lb (i), problem_ -> Ub (i)); jnlst_->Printf(J_VECTOR, J_CONVEXIFYING,"=============================\n"); } // Use orbit info to tighten bounds #ifdef COIN_HAS_NTY // TODO: when independent bound tightener, can get original bounds // through si.getCol{Low,Upp}er() if (problem_ -> orbitalBranching () && !firstcall_) { CouNumber *lb = problem_ -> Lb (), *ub = problem_ -> Ub (); std::vector<std::vector<int> > *new_orbits = problem_ -> getNtyInfo () -> getOrbits(); for (int i=0, ii = problem_ -> getNtyInfo () -> getNumOrbits (); ii--; i++){ CouNumber ll = -COUENNE_INFINITY, uu = COUENNE_INFINITY; std::vector <int> orbit = (*new_orbits)[i]; if (orbit.size () <= 1) continue; // not much to do when only one variable in this orbit if (jnlst_ -> ProduceOutput (J_VECTOR, J_BOUNDTIGHTENING)) { printf ("orbit bounds: "); fflush (stdout); for(int j = 0; j < orbit.size (); j++) { printf ("x_%d [%g,%g] ", orbit[j], lb [orbit [j]], ub [orbit [j]]); fflush (stdout); } printf ("\n"); } for (int j = 0; j < orbit.size (); j++) { int indOrb = orbit [j]; if (indOrb < problem_ -> nVars ()) { if (lb [indOrb] > ll) ll = lb [indOrb]; if (ub [indOrb] < uu) uu = ub [indOrb]; } } jnlst_ -> Printf (J_VECTOR, J_BOUNDTIGHTENING, " --> new common lower bounds: [%g,--]\n", ll); for(int j = 0; j < orbit.size (); j++) { int indOrb = orbit [j]; if (indOrb < problem_ -> nVars ()){ lb [indOrb] = ll; ub [indOrb] = uu; } } } delete new_orbits; } #endif // Generate convexification cuts ////////////////////////////// sparse2dense (ncols, chg_bds, changed, nchanged); double *nlpSol = NULL; //-------------------------------------------- if (true) { if (babInfo) nlpSol = const_cast <double *> (babInfo -> nlpSolution ()); // Aggressive Bound Tightening //////////////////////////////// int logAbtLev = problem_ -> logAbtLev (); if (problem_ -> doABT () && // flag is checked, AND ((logAbtLev != 0) || // (parameter is nonzero OR (info.level == 0)) && // we are at root node), AND (info.pass == 0) && // at first round of cuts, AND ((logAbtLev < 0) || // (logAbtLev = -1, OR (info.level <= logAbtLev) || // depth is lower than COU_OBBT_CUTOFF_LEVEL, OR (CoinDrand48 () < // probability inversely proportional to the level) pow (2., (double) logAbtLev - (info.level + 1))))) { jnlst_ -> Printf(J_VECTOR, J_BOUNDTIGHTENING," performing ABT\n"); if (! (problem_ -> aggressiveBT (nlp_, chg_bds, info, babInfo))) throw infeasible; sparse2dense (ncols, chg_bds, changed, nchanged); } // obtain solution just found by nlp solver // Auxiliaries should be correct. solution should be the one found // at the node even if not as good as the best known. // save violation flag and disregard it while adding cut at NLP // point (which are not violated by the current, NLP, solution) bool save_av = addviolated_; addviolated_ = false; // save values problem_ -> domain () -> push (problem_ -> nVars (), problem_ -> domain () -> x (), problem_ -> domain () -> lb (), problem_ -> domain () -> ub (), false); // fill originals with nlp values if (nlpSol) { CoinCopyN (nlpSol, problem_ -> nOrigVars (), problem_ -> domain () -> x ()); //problem_ -> initAuxs (); problem_ -> getAuxs (problem_ -> domain () -> x ()); } if (jnlst_ -> ProduceOutput (J_VECTOR, J_CONVEXIFYING)) { jnlst_ -> Printf(J_VECTOR, J_CONVEXIFYING,"== genrowcuts on NLP =============\n"); for (int i = 0; i < problem_ -> nVars (); i++) if (problem_ -> Var (i) -> Multiplicity () > 0) jnlst_->Printf(J_VECTOR, J_CONVEXIFYING,"%4d %+20.8g [%+20.8g,%+20.8g]\n", i, problem_ -> X (i), problem_ -> Lb (i), problem_ -> Ub (i)); jnlst_->Printf(J_VECTOR, J_CONVEXIFYING,"=============================\n"); } problem_ -> domain () -> current () -> isNlp () = true; genRowCuts (si, cs, nchanged, changed, chg_bds); // add cuts problem_ -> domain () -> pop (); // restore point addviolated_ = save_av; // restore previous value // if (!firstcall_) // keep solution if called from extractLinearRelaxation() if (babInfo) babInfo -> setHasNlpSolution (false); // reset it after use //AW HERE } else { if (jnlst_ -> ProduceOutput (J_VECTOR, J_CONVEXIFYING)) { jnlst_ -> Printf(J_VECTOR, J_CONVEXIFYING,"== genrowcuts on LP =============\n"); for (int i = 0; i < problem_ -> nVars (); i++) if (problem_ -> Var (i) -> Multiplicity () > 0) jnlst_->Printf(J_VECTOR, J_CONVEXIFYING,"%4d %+20.8g [%+20.8g,%+20.8g]\n", i, problem_ -> X (i), problem_ -> Lb (i), problem_ -> Ub (i)); jnlst_->Printf(J_VECTOR, J_CONVEXIFYING,"=============================\n"); } genRowCuts (si, cs, nchanged, changed, chg_bds); } // change tightened bounds through OsiCuts if (nchanged) genColCuts (si, cs, nchanged, changed); if (firstcall_ && (cs.sizeRowCuts () >= 1)) jnlst_->Printf(J_ITERSUMMARY, J_CONVEXIFYING, "Couenne: %d initial row cuts\n", cs.sizeRowCuts ()); if (realOpt && // this is a good time to check if we have cut the optimal solution isOptimumCut (realOpt, cs, problem_)) jnlst_->Printf(J_ITERSUMMARY, J_CONVEXIFYING, "Warning: Optimal solution was cut\n"); } catch (int exception) { if ((exception == infeasible) && (!firstcall_)) { jnlst_ -> Printf (J_ITERSUMMARY, J_CONVEXIFYING, "Couenne: Infeasible node\n"); WipeMakeInfeas (cs); } if (babInfo) // set infeasibility to true in order to skip NLP heuristic babInfo -> setInfeasibleNode (); } delete [] chg_bds; if (changed) free (changed); if (firstcall_) { jnlst_ -> Printf (J_SUMMARY, J_CONVEXIFYING, "Couenne: %d cuts (%d row, %d col) for linearization\n", cs.sizeRowCuts () + cs.sizeColCuts (), cs.sizeRowCuts (), cs.sizeColCuts ()); fictitiousBound (cs, problem_, true); firstcall_ = false; ntotalcuts_ = nrootcuts_ = cs.sizeRowCuts (); } else { problem_ -> domain () -> pop (); ntotalcuts_ += (cs.sizeRowCuts () - nInitCuts); if (saveOptimum) realOpt = saveOptimum; // restore debug optimum } septime_ += CoinCpuTime () - now; if (jnlst_ -> ProduceOutput (J_ITERSUMMARY, J_CONVEXIFYING)) { if (cs.sizeColCuts ()) { jnlst_ -> Printf (J_ITERSUMMARY, J_CONVEXIFYING,"Couenne col cuts:\n"); for (int i=0; i<cs.sizeColCuts (); i++) cs.colCutPtr (i) -> print (); } } if (!(info.inTree)) rootTime_ = CoinCpuTime (); }
bool calModel::search (CalCubeHeur &calCube, FILE *f, int repl) { int N = instance_ -> N (), n = instance_ -> n (), n_iter = (calInstance::GLOBAL == instance_ -> algType ()) ? 1 : instance_ -> nSolves (); double *bestSol = new double [1 + 2*N], bestObj = COIN_DBL_MAX; double *s0 = NULL; for (int nRetries = 0; !GLOBAL_interrupt && (nRetries < n_iter) && (square (bestObj) > instance_ -> eps ()); ++nRetries) { setMaximumSeconds (CoinMin (instance_ -> maxTime () < 0. ? COIN_DBL_MAX : instance_ -> maxTime (), instance_ -> maxTotalTime () < 0. ? COIN_DBL_MAX : (instance_ -> maxTotalTime () - CoinCpuTime ()) / (instance_ -> nReplications () - repl))); calModel *b = clone (); OsiSolverInterface *si = b -> solver (); for (int i=0; i<N; ++i) { si -> setColLower (1 + N + i, 0.); si -> setColUpper (1 + N + i, 1.); } if (calInstance::GLOBAL == instance_ -> algType ()) { // do nothing: just run the BB } else if (0 == nRetries) { // // First step: generate initial solution, either from input // vector or through the Cube variant // // Generate initial point ON SUBSPACE. Does nothing if algtype // in {RANDOM, GLOBAL} // s0 = calCube. generateInitS (*si); calCube. standalone (s0); // call Cube method b -> changeLU (*si, s0); // fixes some of the s variables after // cube's flight phase } else { // change LU bounds based on current solution #ifdef DEBUG printVec (s0, N, "s0"); #endif const double // reduce changes when random and solution available fraction = FRACTION * (((calInstance::RANDOM == instance_ -> algType ()) && (instance_ -> d () [0] >= 0.)) ? RANDOM_MOBILITY : 1.), multiplier = fraction * (double) (N_RESTART - (nRetries % N_RESTART)) / N_RESTART, threshold_0 = multiplier * (double) (N-n) / N, // free half 0-fixed at beginning threshold_1 = multiplier * (double) n / N; // free half 1-fixed //threshold_0 = CoinMax (1. / CoinMax (1., (double) (N-n)), multiplier * (double) (N-n) / N), // free half 0-fixed at beginning //threshold_1 = CoinMax (1. / CoinMax (1., (double) n), multiplier * (double) n / N); // free half 1-fixed bool one_changed = false; for (int nAttempts = 0; nAttempts < 20 && !one_changed; ++nAttempts) for (int i=0; i<N; ++i) if (s0 [i] < 1e-5) {if (drand48 () > threshold_0) si -> setColUpper (1 + N + i, 0.); else one_changed = true;} else if (s0 [i] > 1 - 1e-5) {if (drand48 () > threshold_1) si -> setColLower (1 + N + i, 1.); else one_changed = true;} #ifdef DEBUG char filename [40]; sprintf (filename, "lp_%d_%d", repl, nRetries); si -> writeLp (filename); #endif // int nChanges = CoinMax (1, n / nRetries); // <------------------ Number of changed variables // for (int i=0; i<nChanges;) { // int indChange = floor ((N - 1e-4) * drand48 ()); // printf ("trying %d [%g,%g], i=%d\n", indChange, lb [1 + N + indChange], ub [1 + N + indChange], i); // if (ub [1 + N + indChange] < 1e-5) {si -> setColUpper (1 + N + indChange, 1.); ++i;} // if (lb [1 + N + indChange] > 1 - 1e-5) {si -> setColLower (1 + N + indChange, 0.); ++i;} // } } GLOBAL_curBB = b; // /| // / |--------+ b -> branchAndBound (); // < | | // \ |--------+ // \| //assert (fabs (b -> bestObj () - val [0]) < 1e-5); printf ("BB iteration %4d done (%10.2fs). ", 1+nRetries, CoinCpuTime ()); //optimal = b -> isProvenOptimal(); //const double *val = b -> getColSolution(); //int numberColumns = model.getNumCols(); if (b -> bestObj () < 1e20) printf ("Best solution: value %10.4f\n", square (b -> bestObj ())); else printf ("No solution found :-(\n"); if (b -> bestSol ()) { if (b -> bestObj () < bestObj) { bestObj = b -> bestObj (); CoinCopyN (b -> bestSol (), 2*N+1, bestSol); } if (!s0) s0 = new double [N]; CoinCopyN (b -> bestSol () + 1 + N, N, s0); } delete b; } bool retval = true, row_format = (calInstance::ROW_BASED == instance_ -> outFormat ()); delete [] s0; double w0 = (double) N / instance_ -> n (); if (bestObj < 1e20) { const double *val = bestSol; if (row_format) fprintf (f, "%lf,", square (bestObj)); //double *d = instance_ -> d (); printf ("sample:\n"); for (int j=N+1, np=0; j<=2*N; ++j) { char strNum [5]; sprintf (strNum, "%d", j-N); if (!row_format) fprintf (f, "%d,%g,%s,%d,%g,\n", 1+repl, square (bestObj), instance_ -> id (j-N-1) ? instance_ -> id (j-N-1) : strNum, (fabs (val [j]) > 1e-6) ? 1 : 0, w0 + val [j-N]); if (fabs (val [j]) > 1e-6) { if (row_format) fprintf (f, "1,"); printf ("%d ", j-N); if (!(++np % 10)) printf ("\n"); } else if (row_format) fprintf (f, "0,"); } printf ("\nweights:\n"); for (int j=1, np=0; j<=N; ++j) { if (row_format) fprintf (f, "%g,", w0 + val [j]); if (fabs (val [j]) > 1e-6) { printf ("[%d,%g] ", j, w0 + val [j]); if (!(++np % 10)) printf ("\n"); } } if (square (bestObj) > instance_ -> eps ()) { printf ("(warning: solution has large objective at replication %d)", 1 + repl); //retval = false; } printf ("\n"); if (row_format) fprintf (f, "\n"); fflush (f); } delete [] bestSol; return retval; }
// Returns type int CbcFathomDynamicProgramming::checkPossible(int allowableSize) { algorithm_ = -1; assert(model_->solver()); OsiSolverInterface * solver = model_->solver(); const CoinPackedMatrix * matrix = solver->getMatrixByCol(); int numberIntegers = model_->numberIntegers(); int numberColumns = solver->getNumCols(); size_ = 0; if (numberIntegers != numberColumns) return -1; // can't do dynamic programming const double * lower = solver->getColLower(); const double * upper = solver->getColUpper(); const double * rowUpper = solver->getRowUpper(); int numberRows = model_->getNumRows(); int i; // First check columns to see if possible double * rhs = new double [numberRows]; CoinCopyN(rowUpper, numberRows, rhs); // Column copy const double * element = matrix->getElements(); const int * row = matrix->getIndices(); const CoinBigIndex * columnStart = matrix->getVectorStarts(); const int * columnLength = matrix->getVectorLengths(); bool bad = false; /* It is just possible that we could say okay as variables may get fixed but seems unlikely */ for (i = 0; i < numberColumns; i++) { int j; double lowerValue = lower[i]; assert (lowerValue == floor(lowerValue)); for (j = columnStart[i]; j < columnStart[i] + columnLength[i]; j++) { int iRow = row[j]; double value = element[j]; if (upper[i] > lowerValue && (value <= 0.0 || value != floor(value))) bad = true; if (lowerValue) rhs[iRow] -= lowerValue * value; } } // check possible (at present do not allow covering) int numberActive = 0; bool infeasible = false; bool saveBad = bad; for (i = 0; i < numberRows; i++) { if (rhs[i] < 0) infeasible = true; else if (rhs[i] > 1.0e5 || fabs(rhs[i] - floor(rhs[i] + 0.5)) > 1.0e-7) bad = true; else if (rhs[i] > 0.0) numberActive++; } if (bad || infeasible) { delete [] rhs; if (!saveBad && infeasible) return -2; else return -1; } // check size of array needed double size = 1.0; double check = COIN_INT_MAX; for (i = 0; i < numberRows; i++) { int n = static_cast<int> (floor(rhs[i] + 0.5)); if (n) { n++; // allow for 0,1... n if (numberActive != 1) { // power of 2 int iBit = 0; int k = n; k &= ~1; while (k) { iBit++; k &= ~(1 << iBit); } // See if exact power if (n != (1 << iBit)) { // round up to next power of 2 n = 1 << (iBit + 1); } size *= n; if (size >= check) break; } else { size = n; // just one constraint } } } // set size needed if (size >= check) size_ = COIN_INT_MAX; else size_ = static_cast<int> (size); int n01 = 0; int nbadcoeff = 0; // See if we can tighten bounds for (i = 0; i < numberColumns; i++) { int j; double lowerValue = lower[i]; double gap = upper[i] - lowerValue; for (j = columnStart[i]; j < columnStart[i] + columnLength[i]; j++) { int iRow = row[j]; double value = element[j]; if (value != 1.0) nbadcoeff++; if (gap*value > rhs[iRow] + 1.0e-8) gap = rhs[iRow] / value; } gap = lowerValue + floor(gap + 1.0e-7); if (gap < upper[i]) solver->setColUpper(i, gap); if (gap <= 1.0) n01++; } if (allowableSize && size_ <= allowableSize) { if (n01 == numberColumns && !nbadcoeff) algorithm_ = 0; // easiest else algorithm_ = 1; } if (allowableSize && size_ <= allowableSize) { numberActive_ = numberActive; indices_ = new int [numberActive_]; cost_ = new double [size_]; CoinFillN(cost_, size_, COIN_DBL_MAX); // but do nothing is okay cost_[0] = 0.0; back_ = new int[size_]; CoinFillN(back_, size_, -1); startBit_ = new int[numberActive_]; numberBits_ = new int[numberActive_]; lookup_ = new int [numberRows]; rhs_ = new int [numberActive_]; numberActive = 0; int kBit = 0; for (i = 0; i < numberRows; i++) { int n = static_cast<int> (floor(rhs[i] + 0.5)); if (n) { lookup_[i] = numberActive; rhs_[numberActive] = n; startBit_[numberActive] = kBit; n++; // allow for 0,1... n int iBit = 0; // power of 2 int k = n; k &= ~1; while (k) { iBit++; k &= ~(1 << iBit); } // See if exact power if (n != (1 << iBit)) { // round up to next power of 2 iBit++; } if (numberActive != 1) { n = 1 << iBit; size *= n; if (size >= check) break; } else { size = n; // just one constraint } numberBits_[numberActive++] = iBit; kBit += iBit; } else { lookup_[i] = -1; } } const double * rowLower = solver->getRowLower(); if (algorithm_ == 0) { // rhs 1 and coefficients 1 // Get first possible solution for printing target_ = -1; int needed = 0; int numberActive = 0; for (i = 0; i < numberRows; i++) { int newRow = lookup_[i]; if (newRow >= 0) { if (rowLower[i] == rowUpper[i]) { needed += 1 << numberActive; numberActive++; } } } for (i = 0; i < size_; i++) { if ((i&needed) == needed) { break; } } target_ = i; } else { coefficients_ = new int[numberActive_]; // If not too many general rhs then we can be more efficient numberNonOne_ = 0; for (i = 0; i < numberActive_; i++) { if (rhs_[i] != 1) numberNonOne_++; } if (numberNonOne_*2 < numberActive_) { // put rhs >1 every second int * permute = new int[numberActive_]; int * temp = new int[numberActive_]; // try different ways int k = 0; for (i = 0; i < numberRows; i++) { int newRow = lookup_[i]; if (newRow >= 0 && rhs_[newRow] > 1) { permute[newRow] = k; k += 2; } } // adjust so k points to last k -= 2; // and now rest int k1 = 1; for (i = 0; i < numberRows; i++) { int newRow = lookup_[i]; if (newRow >= 0 && rhs_[newRow] == 1) { permute[newRow] = k1; k1++; if (k1 <= k) k1++; } } for (i = 0; i < numberActive_; i++) { int put = permute[i]; temp[put] = rhs_[i]; } memcpy(rhs_, temp, numberActive_*sizeof(int)); for (i = 0; i < numberActive_; i++) { int put = permute[i]; temp[put] = numberBits_[i]; } memcpy(numberBits_, temp, numberActive_*sizeof(int)); k = 0; for (i = 0; i < numberActive_; i++) { startBit_[i] = k; k += numberBits_[i]; } for (i = 0; i < numberRows; i++) { int newRow = lookup_[i]; if (newRow >= 0) lookup_[i] = permute[newRow]; } delete [] permute; delete [] temp; // mark new method algorithm_ = 2; } // Get first possible solution for printing target_ = -1; int needed = 0; int * lower2 = new int[numberActive_]; for (i = 0; i < numberRows; i++) { int newRow = lookup_[i]; if (newRow >= 0) { int gap = static_cast<int> (rowUpper[i] - CoinMax(0.0, rowLower[i])); lower2[newRow] = rhs_[newRow] - gap; int numberBits = numberBits_[newRow]; int startBit = startBit_[newRow]; if (numberBits == 1 && !gap) { needed |= 1 << startBit; } } } for (i = 0; i < size_; i++) { if ((i&needed) == needed) { // this one may do bool good = true; for (int kk = 0; kk < numberActive_; kk++) { int numberBits = numberBits_[kk]; int startBit = startBit_[kk]; int size = 1 << numberBits; int start = 1 << startBit; int mask = start * (size - 1); int level = (i & mask) >> startBit; if (level < lower2[kk]) { good = false; break; } } if (good) { break; } } } delete [] lower2; target_ = i; }