void OsiVolSolverInterface::initFromRlbRub(const int rownum, const double* rowlb, const double* rowub) { if (maxNumrows_ > 0) { rowRimAllocator_(); if (rowub) { CoinDisjointCopyN(rowub, rownum, rowupper_); } else { CoinFillN(rowupper_, rownum, OsiVolInfinity); } if (rowlb) { CoinDisjointCopyN(rowlb, rownum, rowlower_); } else { CoinFillN(rowlower_, rownum, -OsiVolInfinity); } // Set the initial dual solution CoinFillN(rowprice_, rownum, 0.0); convertBoundsToSenses_(); } }
void OsiVolSolverInterface::addRows(const int numrows, const CoinPackedVectorBase * const * rows, const double* rowlb, const double* rowub) { if (numrows > 0) { const int rownum = getNumRows(); rowRimResize_(rownum + numrows); CoinDisjointCopyN(rowlb, numrows, rowlower_ + rownum); CoinDisjointCopyN(rowub, numrows, rowupper_ + rownum); for (int i = rownum + numrows - 1; i >= rownum; --i) { convertBoundToSense(rowlower_[i], rowupper_[i], rowsense_[i], rhs_[i], rowrange_[i]); } CoinFillN(rowprice_ + rownum, numrows, 0.0); CoinFillN(lhs_ + rownum, numrows, 0.0); updateRowMatrix_(); rowMatrix_.appendRows(numrows, rows); colMatrixCurrent_ = false; } }
void CoinPackedVector::gutsOfSetVector(int size, const int * inds, const double * elems, bool testForDuplicateIndex, const char * method) { if ( size != 0 ) { reserve(size); nElements_ = size; CoinDisjointCopyN(inds, size, indices_); CoinDisjointCopyN(elems, size, elements_); CoinIotaN(origIndices_, size, 0); } if (testForDuplicateIndex) { try { CoinPackedVectorBase::setTestForDuplicateIndex(testForDuplicateIndex); } catch (CoinError e) { throw CoinError("duplicate index", method, "CoinPackedVector"); } } else { setTestsOff(); } }
bool OsiTestSolverInterface::setWarmStart(const CoinWarmStart* warmstart) { const CoinWarmStartDual* ws = dynamic_cast<const CoinWarmStartDual*>(warmstart); if (! ws) return false; const int ws_size = ws->size(); if (ws_size != getNumRows() && ws_size != 0) { throw CoinError("wrong dual warmstart size", "setWarmStart", "OsiTestSolverInterface"); } CoinDisjointCopyN(ws->dual(), ws_size, rowprice_); return true; }
void CoinPackedVector::setFull(int size, const double * elems, bool testForDuplicateIndex) { // Clear out any values presently stored clear(); // Allocate storage if ( size!=0 ) { reserve(size); nElements_ = size; CoinIotaN(origIndices_, size, 0); CoinIotaN(indices_, size, 0); CoinDisjointCopyN(elems, size, elements_); } // Full array can not have duplicates CoinPackedVectorBase::setTestForDuplicateIndexWhenTrue(testForDuplicateIndex); }
void CoinPackedVector::gutsOfSetConstant(int size, const int * inds, double value, bool testForDuplicateIndex, const char * method) { if ( size != 0 ) { reserve(size); nElements_ = size; CoinDisjointCopyN(inds, size, indices_); CoinFillN(elements_, size, value); CoinIotaN(origIndices_, size, 0); } try { CoinPackedVectorBase::setTestForDuplicateIndex(testForDuplicateIndex); } catch (CoinError& e) { throw CoinError("duplicate index", method, "CoinPackedVector"); } }
void OsiTestSolverInterface::setRowPrice(const double *rowprice) { CoinDisjointCopyN(rowprice, getNumRows(), rowprice_); compute_rc_(rowprice_, rc_); }
void OsiTestSolverInterface::resolve() { int i; checkData_(); // Only one of these can do any work updateRowMatrix_(); updateColMatrix_(); const int dsize = getNumRows(); const int psize = getNumCols(); // Negate the objective coefficients if necessary if (objsense_ < 0) { std::transform(objcoeffs_, objcoeffs_+psize, objcoeffs_, std::negate<double>()); } // Set the lb/ub on the duals volprob_.dual_lb.allocate(dsize); volprob_.dual_ub.allocate(dsize); double * dlb = volprob_.dual_lb.v; double * dub = volprob_.dual_ub.v; for (i = 0; i < dsize; ++i) { dlb[i] = rowupper_[i] < getInfinity() ? -1.0e31 : 0.0; dub[i] = rowlower_[i] > -getInfinity() ? 1.0e31 : 0.0; } volprob_.dsize = dsize; volprob_.psize = psize; // Set the dual starting point VOL_dvector& dsol = volprob_.dsol; dsol.allocate(dsize); std::transform(rowprice_, rowprice_+dsize, dsol.v, std::bind2nd(std::multiplies<double>(), objsense_)); // adjust the dual vector (if necessary) to be sure it's feasible double * dv = dsol.v; for (i = 0; i < dsize; ++i) { if (dv[i] < dlb[i]) { dv[i] = dlb[i]; } else if (dv[i] > dub[i]) { dv[i] = dub[i]; } } // If requested, check whether the matrix contains anything but 0/1/-1 #if 0 isZeroOneMinusOne_ = false; #else isZeroOneMinusOne_ = test_zero_one_minusone_(colMatrix_); if (isZeroOneMinusOne_) { colMatrixOneMinusOne_ = new OsiVolMatrixOneMinusOne_(colMatrix_); rowMatrixOneMinusOne_ = new OsiVolMatrixOneMinusOne_(rowMatrix_); } #endif volprob_.solve(*this, true); // extract the solution // the lower bound on the objective value lagrangeanCost_ = objsense_ * volprob_.value; // the primal solution CoinDisjointCopyN(volprob_.psol.v, psize, colsol_); // Reset the objective coefficients if necessary if (objsense_ < 0) { std::transform(objcoeffs_, objcoeffs_ + psize, objcoeffs_, std::negate<double>()); // also, multiply the dual solution by -1 std::transform(volprob_.dsol.v, volprob_.dsol.v+dsize, rowprice_, std::negate<double>()); } else { // now we just have to copy the dual CoinDisjointCopyN(volprob_.dsol.v, dsize, rowprice_); } // Compute the reduced costs compute_rc_(rowprice_, rc_); // Compute the left hand side (row activity levels) if (isZeroOneMinusOne_) { colMatrixOneMinusOne_->timesMajor(colsol_, lhs_); } else { colMatrix_.times(colsol_, lhs_); } if (isZeroOneMinusOne_) { delete colMatrixOneMinusOne_; colMatrixOneMinusOne_ = NULL; delete rowMatrixOneMinusOne_; rowMatrixOneMinusOne_ = NULL; } }
OsiTestSolverInterface& OsiTestSolverInterface::operator=(const OsiTestSolverInterface& rhs) { if (&rhs == this) return *this; OsiSolverInterface::operator=(rhs); gutsOfDestructor_(); rowMatrixCurrent_ = rhs.rowMatrixCurrent_; if (rowMatrixCurrent_) rowMatrix_ = rhs.rowMatrix_; colMatrixCurrent_ = rhs.colMatrixCurrent_; if (colMatrixCurrent_) colMatrix_ = rhs.colMatrix_; if (rhs.maxNumrows_) { maxNumrows_ = rhs.maxNumrows_; rowRimAllocator_(); const int rownum = getNumRows(); CoinDisjointCopyN(rhs.rowupper_, rownum, rowupper_); CoinDisjointCopyN(rhs.rowlower_, rownum, rowlower_); CoinDisjointCopyN(rhs.rowsense_, rownum, rowsense_); CoinDisjointCopyN(rhs.rhs_, rownum, rhs_); CoinDisjointCopyN(rhs.rowrange_, rownum, rowrange_); CoinDisjointCopyN(rhs.rowprice_, rownum, rowprice_); CoinDisjointCopyN(rhs.lhs_, rownum, lhs_); } if (rhs.maxNumcols_) { maxNumcols_ = rhs.maxNumcols_; colRimAllocator_(); const int colnum = getNumCols(); CoinDisjointCopyN(rhs.colupper_, colnum, colupper_); CoinDisjointCopyN(rhs.collower_, colnum, collower_); CoinDisjointCopyN(rhs.continuous_, colnum, continuous_); CoinDisjointCopyN(rhs.objcoeffs_, colnum, objcoeffs_); CoinDisjointCopyN(rhs.colsol_, colnum, colsol_); CoinDisjointCopyN(rhs.rc_, colnum, rc_); } volprob_.parm.granularity = 0.0; return *this; }
CoinTreeSiblings(const int n, CoinTreeNode** nodes) : current_(0), numSiblings_(n), siblings_(new CoinTreeNode*[n]) { CoinDisjointCopyN(nodes, n, siblings_); }
/** This helper function copies an array to another location. The two arrays must not overlap (otherwise an exception is thrown). For speed 8 entries are copied at a time. The source array is given by its first and "after last" entry; the target array is given by its first entry. */ template <class T> inline void CoinDisjointCopy(register const T* first, register const T* last, register T* to) { CoinDisjointCopyN(first, static_cast<int>(last - first), to); }
//----------------------------------------------------------------------------- // Generate Lift-and-Project cuts //------------------------------------------------------------------- void CglLiftAndProject::generateCuts(const OsiSolverInterface& si, OsiCuts& cs, const CglTreeInfo /*info*/) { // Assumes the mixed 0-1 problem // // min {cx: <Atilde,x> >= btilde} // // is in canonical form with all bounds, // including x_t>=0, -x_t>=-1 for x_t binary, // explicitly stated in the constraint matrix. // See ~/COIN/Examples/Cgl2/cgl2.cpp // for a general purpose "convert" function. // Reference [BCC]: Balas, Ceria, and Corneujols, // "A lift-and-project cutting plane algorithm // for mixed 0-1 program", Math Prog 58, (1993) // 295-324. // This implementation uses Normalization 1. // Given canonical problem and // the lp-relaxation solution, x, // the LAP cut generator attempts to construct // a cut for every x_j such that 0<x_j<1 // [BCC:307] // x_j is the strictly fractional binary variable // the cut is generated from int j = 0; // Get basic problem information // let Atilde be an m by n matrix const int m = si.getNumRows(); const int n = si.getNumCols(); const double * x = si.getColSolution(); // Remember - Atildes may have gaps.. const CoinPackedMatrix * Atilde = si.getMatrixByRow(); const double * AtildeElements = Atilde->getElements(); const int * AtildeIndices = Atilde->getIndices(); const CoinBigIndex * AtildeStarts = Atilde->getVectorStarts(); const int * AtildeLengths = Atilde->getVectorLengths(); const int AtildeFullSize = AtildeStarts[m]; const double * btilde = si.getRowLower(); // Set up memory for system (10) [BCC:307] // (the problem over the norm intersected // with the polar cone) // // min <<x^T,Atilde^T>,u> + x_ju_0 // s.t. // <B,w> = (0,...,0,beta_,beta)^T // w is nonneg for all but the // last two entries, which are free. // where // w = (u,v,v_0,u_0)in BCC notation // u and v are m-vectors; u,v >=0 // v_0 and u_0 are free-scalars, and // // B = Atilde^T -Atilde^T -e_j e_j // btilde^T e_0^T 0 0 // e_0^T btilde^T 1 0 // ^T indicates Transpose // e_0 is a (AtildeNCols x 1) vector of all zeros // e_j is e_0 with a 1 in the jth position // Storing B in column order. B is a (n+2 x 2m+2) matrix // But need to allow for possible gaps in Atilde. // At each iteration, only need to change 2 cols and objfunc // Sane design of OsiSolverInterface does not permit mucking // with matrix. // Because we must delete and add cols to alter matrix, // and we can only add columns on the end of the matrix // put the v_0 and u_0 columns on the end. // rather than as described in [BCC] // Initially allocating B with space for v_0 and u_O cols // but not populating, for efficiency. // B without u_0 and v_0 is a (n+2 x 2m) size matrix. int twoM = 2*m; int BNumRows = n+2; int BNumCols = twoM+2; int BFullSize = 2*AtildeFullSize+twoM+3; double * BElements = new double[BFullSize]; int * BIndices = new int[BFullSize]; CoinBigIndex * BStarts = new CoinBigIndex [BNumCols+1]; int * BLengths = new int[BNumCols]; int i, ij, k=0; int nPlus1=n+1; int offset = AtildeStarts[m]+m; for (i=0; i<m; i++){ for (ij=AtildeStarts[i];ij<AtildeStarts[i]+AtildeLengths[i];ij++){ BElements[k]=AtildeElements[ij]; BElements[k+offset]=-AtildeElements[ij]; BIndices[k]= AtildeIndices[ij]; BIndices[k+offset]= AtildeIndices[ij]; k++; } BElements[k]=btilde[i]; BElements[k+offset]=btilde[i]; BIndices[k]=n; BIndices[k+offset]=nPlus1; BStarts[i]= AtildeStarts[i]+i; BStarts[i+m]=offset+BStarts[i];// = AtildeStarts[m]+m+AtildeStarts[i]+i BLengths[i]= AtildeLengths[i]+1; BLengths[i+m]= AtildeLengths[i]+1; k++; } BStarts[twoM]=BStarts[twoM-1]+BLengths[twoM-1]; // Cols that will be deleted each iteration int BNumColsLessOne=BNumCols-1; int BNumColsLessTwo=BNumCols-2; const int delCols[2] = {BNumColsLessOne, BNumColsLessTwo}; // Set lower bound on u and v // u_0, v_0 will be reset as free const double solverINFINITY = si.getInfinity(); double * BColLowers = new double[BNumCols]; double * BColUppers = new double[BNumCols]; CoinFillN(BColLowers,BNumCols,0.0); CoinFillN(BColUppers,BNumCols,solverINFINITY); // Set row lowers and uppers. // The rhs is zero, for but the last two rows. // For these the rhs is beta_ double * BRowLowers = new double[BNumRows]; double * BRowUppers = new double[BNumRows]; CoinFillN(BRowLowers,BNumRows,0.0); CoinFillN(BRowUppers,BNumRows,0.0); BRowLowers[BNumRows-2]=beta_; BRowUppers[BNumRows-2]=beta_; BRowLowers[BNumRows-1]=beta_; BRowUppers[BNumRows-1]=beta_; // Calculate base objective <<x^T,Atilde^T>,u> // Note: at each iteration coefficient u_0 // changes to <x^T,e_j> // w=(u,v,beta,v_0,u_0) size 2m+3 // So, BOjective[2m+2]=x[j] double * BObjective= new double[BNumCols]; double * Atildex = new double[m]; CoinFillN(BObjective,BNumCols,0.0); Atilde->times(x,Atildex); // Atildex is size m, x is size n CoinDisjointCopyN(Atildex,m,BObjective); // Number of cols and size of Elements vector // in B without the v_0 and u_0 cols int BFullSizeLessThree = BFullSize-3; // Load B matrix into a column orders CoinPackedMatrix CoinPackedMatrix * BMatrix = new CoinPackedMatrix(true, BNumRows, BNumColsLessTwo, BFullSizeLessThree, BElements,BIndices, BStarts,BLengths); // Assign problem into a solver interface // Note: coneSi will cleanup the memory itself OsiSolverInterface * coneSi = si.clone(false); coneSi->assignProblem (BMatrix, BColLowers, BColUppers, BObjective, BRowLowers, BRowUppers); // Problem sense should default to "min" by default, // but just to be virtuous... coneSi->setObjSense(1.0); // The plot outline from here on down: // coneSi has been assigned B without the u_0 and v_0 columns // Calculate base objective <<x^T,Atilde^T>,u> // bool haveWarmStart = false; // For (j=0; j<n, j++) // if (!isBinary(x_j) || x_j<=0 || x_j>=1) continue; // // IMPROVEME: if(haveWarmStart) check if j attractive // add {-e_j,0,-1} matrix column for v_0 // add {e_j,0,0} matrix column for u_0 // objective coefficient for u_0 is x_j // if (haveWarmStart) // set warmstart info // solve min{objw:Bw=0; w>=0,except v_0, u_0 free} // if (bounded) // get warmstart info // haveWarmStart=true; // ustar = optimal u solution // ustar_0 = optimal u_0 solution // alpha^T= <ustar^T,Atilde> -ustar_0e_j^T // (double check <alpha^T,x> >= beta_ should be violated) // add <alpha^T,x> >= beta_ to cutset // endif // delete column for u_0 // this deletes all column info. // delete column for v_0 // endFor // clean up memory // return 0; int * nVectorIndices = new int[n]; CoinIotaN(nVectorIndices, n, 0); bool haveWarmStart = false; bool equalObj1, equalObj2; CoinRelFltEq eq; double v_0Elements[2] = {-1,1}; double u_0Elements[1] = {1}; CoinWarmStart * warmStart = 0; double * ustar = new double[m]; CoinFillN(ustar, m, 0.0); double* alpha = new double[n]; CoinFillN(alpha, n, 0.0); for (j=0;j<n;j++){ if (!si.isBinary(j)) continue; // Better to ask coneSi? No! // coneSi has no binInfo. equalObj1=eq(x[j],0); equalObj2=eq(x[j],1); if (equalObj1 || equalObj2) continue; // IMPROVEME: if (haveWarmStart) check if j attractive; // AskLL:wanted to declare u_0 and v_0 packedVec outside loop // and setIndices, but didn't see a method to do that(?) // (Could "insert". Seems inefficient) int v_0Indices[2]={j,nPlus1}; int u_0Indices[1]={j}; // CoinPackedVector v_0(2,v_0Indices,v_0Elements,false); CoinPackedVector u_0(1,u_0Indices,u_0Elements,false); #if CGL_DEBUG const CoinPackedMatrix *see1 = coneSi->getMatrixByRow(); #endif coneSi->addCol(v_0,-solverINFINITY,solverINFINITY,0); coneSi->addCol(u_0,-solverINFINITY,solverINFINITY,x[j]); if(haveWarmStart) { coneSi->setWarmStart(warmStart); coneSi->resolve(); } else { #if CGL_DEBUG const CoinPackedMatrix *see2 = coneSi->getMatrixByRow(); #endif coneSi->initialSolve(); } if(coneSi->isProvenOptimal()){ warmStart = coneSi->getWarmStart(); haveWarmStart=true; const double * wstar = coneSi->getColSolution(); CoinDisjointCopyN(wstar, m, ustar); Atilde->transposeTimes(ustar,alpha); alpha[j]+=wstar[BNumCols-1]; #if debug int p; double sum; for(p=0;p<n;p++)sum+=alpha[p]*x[p]; if (sum<=beta_){ throw CoinError("Cut not violated", "cutGeneration", "CglLiftAndProject"); } #endif // add <alpha^T,x> >= beta_ to cutset OsiRowCut rc; rc.setRow(n,nVectorIndices,alpha); rc.setLb(beta_); rc.setUb(solverINFINITY); cs.insert(rc); } // delete col for u_o and v_0 coneSi->deleteCols(2,delCols); // clean up memory } // clean up delete [] alpha; delete [] ustar; delete [] nVectorIndices; // BMatrix, BColLowers,BColUppers, BObjective, BRowLowers, BRowUppers // are all freed by OsiSolverInterface destructor (?) delete [] BLengths; delete [] BStarts; delete [] BIndices; delete [] BElements; }
//------------------------------------------------------------------- // Determine row types. Find the VUBS and VLBS. //------------------------------------------------------------------- void CglFlowCover::flowPreprocess(const OsiSolverInterface& si) const { CoinPackedMatrix matrixByRow(*si.getMatrixByRow()); int numRows = si.getNumRows(); int numCols = si.getNumCols(); const char* sense = si.getRowSense(); const double* RHS = si.getRightHandSide(); const double* coefByRow = matrixByRow.getElements(); const int* colInds = matrixByRow.getIndices(); const int* rowStarts = matrixByRow.getVectorStarts(); const int* rowLengths = matrixByRow.getVectorLengths(); int iRow = -1; int iCol = -1; numCols_ = numCols; // Record col and row numbers for copy constructor numRows_ = numRows; if (rowTypes_ != 0) { delete [] rowTypes_; rowTypes_ = 0; } rowTypes_ = new CglFlowRowType [numRows];// Destructor will free memory // Get integer types const char * columnType = si.getColType (true); // Summarize the row type infomation. int numUNDEFINED = 0; int numVARUB = 0; int numVARLB = 0; int numVAREQ = 0; int numMIXUB = 0; int numMIXEQ = 0; int numNOBINUB = 0; int numNOBINEQ = 0; int numSUMVARUB = 0; int numSUMVAREQ = 0; int numUNINTERSTED = 0; int* ind = new int [numCols]; double* coef = new double [numCols]; for (iRow = 0; iRow < numRows; ++iRow) { int rowLen = rowLengths[iRow]; char sen = sense[iRow]; double rhs = RHS[iRow]; CoinDisjointCopyN(colInds + rowStarts[iRow], rowLen, ind); CoinDisjointCopyN(coefByRow + rowStarts[iRow], rowLen, coef); CglFlowRowType rowType = determineOneRowType(si, rowLen, ind, coef, sen, rhs); rowTypes_[iRow] = rowType; switch(rowType) { case CGLFLOW_ROW_UNDEFINED: ++numUNDEFINED; break; case CGLFLOW_ROW_VARUB: ++numVARUB; break; case CGLFLOW_ROW_VARLB: ++numVARLB; break; case CGLFLOW_ROW_VAREQ: ++numVAREQ; break; case CGLFLOW_ROW_MIXUB: ++numMIXUB; break; case CGLFLOW_ROW_MIXEQ: ++numMIXEQ; break; case CGLFLOW_ROW_NOBINUB: ++numNOBINUB; break; case CGLFLOW_ROW_NOBINEQ: ++numNOBINEQ; break; case CGLFLOW_ROW_SUMVARUB: ++numSUMVARUB; break; case CGLFLOW_ROW_SUMVAREQ: ++numSUMVAREQ; break; case CGLFLOW_ROW_UNINTERSTED: ++numUNINTERSTED; break; default: throw CoinError("Unknown row type", "flowPreprocess", "CglFlowCover"); } } delete [] ind; ind = NULL; delete [] coef; coef = NULL; if(CGLFLOW_DEBUG) { std::cout << "The num of rows = " << numRows << std::endl; std::cout << "Summary of Row Type" << std::endl; std::cout << "numUNDEFINED = " << numUNDEFINED << std::endl; std::cout << "numVARUB = " << numVARUB << std::endl; std::cout << "numVARLB = " << numVARLB << std::endl; std::cout << "numVAREQ = " << numVAREQ << std::endl; std::cout << "numMIXUB = " << numMIXUB << std::endl; std::cout << "numMIXEQ = " << numMIXEQ << std::endl; std::cout << "numNOBINUB = " << numNOBINUB << std::endl; std::cout << "numNOBINEQ = " << numNOBINEQ << std::endl; std::cout << "numSUMVARUB = " << numSUMVARUB << std::endl; std::cout << "numSUMVAREQ = " << numSUMVAREQ << std::endl; std::cout << "numUNINTERSTED = " << numUNINTERSTED << std::endl; } //--------------------------------------------------------------------------- // Setup vubs_ and vlbs_ if (vubs_ != 0) { delete [] vubs_; vubs_ = 0; } vubs_ = new CglFlowVUB [numCols]; // Destructor will free memory if (vlbs_ != 0) { delete [] vlbs_; vlbs_ = 0; } vlbs_ = new CglFlowVLB [numCols]; // Destructor will free memory for (iCol = 0; iCol < numCols; ++iCol) { // Initilized in constructor vubs_[iCol].setVar(UNDEFINED_); // but, need redo since may call vlbs_[iCol].setVar(UNDEFINED_); // preprocess(...) more than once } for (iRow = 0; iRow < numRows; ++iRow) { CglFlowRowType rowType2 = rowTypes_[iRow]; if ( (rowType2 == CGLFLOW_ROW_VARUB) || (rowType2 == CGLFLOW_ROW_VARLB) || (rowType2 == CGLFLOW_ROW_VAREQ) ) { int startPos = rowStarts[iRow]; int index0 = colInds[startPos]; int index1 = colInds[startPos + 1]; double coef0 = coefByRow[startPos]; double coef1 = coefByRow[startPos + 1]; int xInd, yInd; // x is binary double xCoef, yCoef; if ( columnType[index0]==1 ) { xInd = index0; yInd = index1; xCoef = coef0; yCoef = coef1; } else { xInd = index1; yInd = index0; xCoef = coef1; yCoef = coef0; } switch (rowType2) { case CGLFLOW_ROW_VARUB: // Inequality: y <= ? * x vubs_[yInd].setVar(xInd); vubs_[yInd].setVal(-xCoef / yCoef); break; case CGLFLOW_ROW_VARLB: // Inequality: y >= ? * x vlbs_[yInd].setVar(xInd); vlbs_[yInd].setVal(-xCoef / yCoef); break; case CGLFLOW_ROW_VAREQ: // Inequality: y >= AND <= ? * x vubs_[yInd].setVar(xInd); vubs_[yInd].setVal(-xCoef / yCoef); vlbs_[yInd].setVar(xInd); vlbs_[yInd].setVal(-xCoef / yCoef); break; default: throw CoinError("Unknown row type: impossible", "flowPreprocess", "CglFlowCover"); } } } if(CGLFLOW_DEBUG) { printVubs(std::cout); } }
//############################################################################# OsiSolverInterface * MibSBilevel::setUpModel(OsiSolverInterface * oSolver, bool newOsi, const double *lpSol) { /** Create lower-level model with fixed upper-level vars **/ int probType = model_->MibSPar_->entry(MibSParams::bilevelProblemType); bool warmStartLL = model_->MibSPar_->entry(MibSParams::warmStartLL); bool doDualFixing = model_->MibSPar_->entry(MibSParams::doDualFixing); std::string feasCheckSolver = model_->MibSPar_->entry(MibSParams::feasCheckSolver); OsiSolverInterface * nSolver; double etol(model_->etol_); int i(0), j(0), index1(0), index2(0); int uCols(model_->getUpperDim()); int lRows(model_->getLowerRowNum()); int lCols(model_->getLowerDim()); int * uColIndices = model_->getUpperColInd(); int * lColIndices = model_->getLowerColInd(); int * lRowIndices = model_->getLowerRowInd(); double objSense(model_->getLowerObjSense()); double * lObjCoeffs = model_->getLowerObjCoeffs(); const CoinPackedMatrix * matrix = oSolver->getMatrixByRow(); double coeff(0.0); if (!lpSol){ lpSol = oSolver->getColSolution(); } const double * origRowLb = model_->getOrigRowLb(); const double * origRowUb = model_->getOrigRowUb(); const double * origColLb = model_->getOrigColLb(); const double * origColUb = model_->getOrigColUb(); double * rowUb = new double[lRows]; double * rowLb = new double[lRows]; double * colUb = new double[lCols]; double * colLb = new double[lCols]; //CoinZeroN(rowUb, lRows); //CoinZeroN(rowLb, lRows); //CoinZeroN(colUb, lCols); //CoinZeroN(colLb, lCols); /** Set the row bounds **/ for(i = 0; i < lRows; i++){ rowLb[i] = origRowLb[lRowIndices[i]]; rowUb[i] = origRowUb[lRowIndices[i]]; } for(i = 0; i < lCols; i++){ colLb[i] = origColLb[lColIndices[i]]; colUb[i] = origColUb[lColIndices[i]]; } if (newOsi){ if (feasCheckSolver == "Cbc"){ nSolver = new OsiCbcSolverInterface(); }else if (feasCheckSolver == "SYMPHONY"){ nSolver = new OsiSymSolverInterface(); }else if (feasCheckSolver == "CPLEX"){ #ifdef USE_CPLEX nSolver = new OsiCpxSolverInterface(); #else throw CoinError("CPLEX chosen as solver, but it has not been enabled", "setUpModel", "MibsBilevel"); #endif }else{ throw CoinError("Unknown solver chosen", "setUpModel", "MibsBilevel"); } int * integerVars = new int[lCols]; double * objCoeffs = new double[lCols]; CoinFillN(integerVars, lCols, 0); //CoinZeroN(objCoeffs, lCols); int intCnt(0); /** Fill in array of lower-level integer variables **/ for(i = 0; i < lCols; i++){ index1 = lColIndices[i]; if(oSolver->isInteger(index1)){ integerVars[intCnt] = i; intCnt++; } } CoinDisjointCopyN(lObjCoeffs, lCols, objCoeffs); CoinPackedMatrix * newMat = new CoinPackedMatrix(false, 0, 0); newMat->setDimensions(0, lCols); double tmp(0.0); /* for(i = 0; i < lRows; i++){ CoinPackedVector row; index1 = lRowIndices[i]; start = matStarts[index1]; end = start + matrix->getVectorSize(index1); for(j = start; j < end; j++){ index2 = matIndices[j]; //tmp = findIndex(index, lCols, lColIndices); tmp = binarySearch(0, lCols - 1, index2, lColIndices); if(tmp > -1) row.insert(tmp, matElements[j]); } newMat->appendRow(row); } */ for(i = 0; i < lRows; i++){ CoinPackedVector row; index1 = lRowIndices[i]; for(j = 0; j < lCols; j++){ index2 = lColIndices[j]; tmp = matrix->getCoefficient(index1, index2); row.insert(j, tmp); } newMat->appendRow(row); } /* nSolver->assignProblem(newMat, colLb, colUb, objCoeffs, rowLb, rowUb); */ nSolver->loadProblem(*newMat, colLb, colUb, objCoeffs, rowLb, rowUb); for(i = 0; i < intCnt; i++){ nSolver->setInteger(integerVars[i]); } //nSolver->setInteger(integerVars, intCnt); nSolver->setObjSense(objSense); //1 min; -1 max nSolver->setHintParam(OsiDoReducePrint, true, OsiHintDo); #if 0 if(0){ 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 delete [] integerVars; }else{ nSolver = solver_; } #define SYM_VERSION_IS_WS strcmp(SYMPHONY_VERSION, "WS") #if SYMPHONY_VERSION_IS_WS if (feasCheckSolver == "SYMPHONY" && probType == 1 && warmStartLL && !newOsi && doDualFixing){ //Interdiction /** Get upper bound from best known (feasible) lower level solution and try to fix additional variables by sensitivity analysis **/ std::vector<std::pair<AlpsKnowledge*, double> > solutionPool; model_->getKnowledgeBroker()-> getAllKnowledges(AlpsKnowledgeTypeSolution, solutionPool); const double * sol; double objval, Ub(objSense*nSolver->getInfinity()); BlisSolution* blisSol; std::vector<std::pair<AlpsKnowledge*, double> >::const_iterator si; for (si = solutionPool.begin(); si != solutionPool.end(); ++si){ blisSol = dynamic_cast<BlisSolution*>(si->first); sol = blisSol->getValues(); for (i = 0; i < uCols; i++){ if (lpSol[uColIndices[i]] > 1 - etol && sol[lColIndices[i]] > 1-etol){ break; } } if (i == uCols && -objSense*blisSol->getQuality() < Ub){ Ub = -objSense*blisSol->getQuality(); } } /** Figure out which variables get fixed by the upper level solution **/ int *newUbInd = new int[uCols]; int *newLbInd = new int[uCols]; double *newUbVal = new double[uCols]; double *newLbVal = new double[uCols]; double newLb; for (i = 0; i < uCols; i++){ newUbInd[i] = uColIndices[i]; newLbInd[i] = uColIndices[i]; newLbVal[i] = 0; if (lpSol[uColIndices[i]] > 1 - etol){ newUbVal[i] = 0; }else{ newUbVal[i] = 1; } } /** If we found an upper bound, then do the dual fixing **/ if (Ub < objSense*nSolver->getInfinity()){ sym_environment *env = dynamic_cast<OsiSymSolverInterface *>(nSolver)->getSymphonyEnvironment(); for (i = 0; i < uCols; i++){ if (newUbVal[i] == 1){ // Try fixing it to zero newUbVal[i] = 0; sym_get_lb_for_new_rhs(env, 0, NULL, NULL, uCols, newLbInd, newLbVal, uCols, newUbInd, newUbVal, &newLb); if (objSense*newLb > Ub + etol){ //Victory! This variable can be fixed to 1 permanently newLbVal[i] = 1; } //Set upper bound back to 1 newUbVal[i] = 1; if (newLbVal[i] == 0){ // Try fixing it to one newLbVal[i] = 1; sym_get_lb_for_new_rhs(env, 0, NULL, NULL, uCols, newLbInd, newLbVal, uCols, newUbInd, newUbVal, &newLb); if (objSense*newLb > Ub + etol){ //Victory! This variable can be fixed to 0 permanently newUbVal[i] = 0; } newLbVal[i] = 0; } } } } /** Now set the row bounds to account for fixings **/ /** This is probably very frgaile. Assuming interdiction rows come last. It would be better to set variable bounds directly, but this doesn't seem to work right now. **/ int iRowStart = lRows-uCols; #if 1 for(i = iRowStart; i < lRows; i++){ nSolver->setRowLower(i, newLbVal[i-iRowStart]); nSolver->setRowUpper(i, newUbVal[i-iRowStart]); } #else for(i = 0; i < uCols; i++){ nSolver->setColLower(i, newLbVal[i]); nSolver->setColUpper(i, newUbVal[i]); } #endif delete[] newUbInd; delete[] newLbInd; delete[] newUbVal; delete[] newLbVal; }else{ #endif //FIXME: NEED TO GET ROW SENSE HERE /** Get contribution of upper-level columns **/ double * upComp = new double[lRows]; CoinFillN(upComp, lRows, 0.0); for(i = 0; i < lRows; i++){ index1 = lRowIndices[i]; for(j = 0; j < uCols; j++){ index2 = uColIndices[j]; coeff = matrix->getCoefficient(index1, index2); if (coeff != 0){ upComp[i] += coeff * lpSol[index2]; } } } /** Correct the row bounds to account for fixed upper-level vars **/ for(i = 0; i < lRows; i++){ nSolver->setRowLower(i, rowLb[i] - upComp[i]); nSolver->setRowUpper(i, rowUb[i] - upComp[i]); } delete [] upComp; #if SYMPHONY_VERSION_IS_WS } #endif //I don't think this is needed //if(!getWarmStart()) // setWarmStart(nSolver->getWarmStart()); return nSolver; }
void BM_tm::initialize_core(BCP_vec<BCP_var_core*>& vars, BCP_vec<BCP_cut_core*>& cuts, BCP_lp_relax*& matrix) { char* argv_[3]; char** argv = argv_; argv[0] = NULL; argv[1] = strdup(par.entry(BM_par::NL_filename).c_str()); argv[2] = NULL; /* Get the basic options. */ Bonmin::BonminAmplSetup bonmin; bonmin.readOptionsFile(par.entry(BM_par::IpoptParamfile).c_str()); bonmin.initialize(argv); free(argv[1]); Bonmin::OsiTMINLPInterface& nlp = *bonmin.nonlinearSolver(); #if defined(BM_DISREGARD_SOS) const Bonmin::TMINLP::SosInfo * sos = nlp.model()->sosConstraints(); if (sos->num > 0) { printf("There are SOS constraints... disregarding them...\n"); } #endif OsiSolverInterface& clp = *bonmin.continuousSolver(); const int numCols = clp.getNumCols(); const int numRows = clp.getNumRows(); const double* clb = clp.getColLower(); const double* cub = clp.getColUpper(); double* obj = new double[numCols]; if (bonmin.getAlgorithm() == Bonmin::B_BB /* pure B&B */) { std::cout<<"Doing branch and bound"<<std::endl; CoinFillN(obj, numCols, 0.0); matrix = NULL; } else { std::cout<<"Doing hybrid"<<std::endl; CoinDisjointCopyN(clp.getObjCoefficients(), numCols, obj); cuts.reserve(numRows); const double* rlb = clp.getRowLower(); const double* rub = clp.getRowUpper(); for (int i = 0; i < numRows; ++i) { cuts.push_back(new BCP_cut_core(rlb[i], rub[i])); } matrix = new BCP_lp_relax(true /*column major ordered*/); matrix->copyOf(*clp.getMatrixByCol(), obj, clb, cub, rlb, rub); } vars.reserve(numCols); for (int i = 0; i < numCols; ++i) { BCP_var_t type = BCP_ContinuousVar; if (clp.isBinary(i)) type = BCP_BinaryVar; if (clp.isInteger(i)) type = BCP_IntegerVar; vars.push_back(new BCP_var_core(type, obj[i], clb[i], cub[i])); } delete[] obj; /* Initialize pseudocosts */ int nObj = 0; for (int i = 0; i < numCols; ++i) { if (nlp.isInteger(i)) { ++nObj; } } #if ! defined(BM_DISREGARD_SOS) const Bonmin::TMINLP::SosInfo * sos = nlp.model()->sosConstraints(); nObj += sos->num; #endif pseudoCosts_.initialize(nObj); }