void OsiIF::loadDummyRow(OsiSolverInterface* s2, const double* lbounds, const double* ubounds, const double* objectives) { CoinPackedVector *coinrow = new CoinPackedVector(); CoinPackedMatrix *matrix = new CoinPackedMatrix(false,0,0); matrix->setDimensions(0, numCols_); ArrayBuffer<int> dummy(1,false); dummy.push(0); char *senses = new char[1]; double *rhs = new double[1]; double *ranges = new double[1]; coinrow->insert(0, 1.); matrix->appendRow(*coinrow); senses[0] = 'E'; rhs[0] = 1.; ranges[0] = 0.; lpSolverTime_.start(); s2->loadProblem(*matrix, lbounds, ubounds, objectives, senses, rhs, ranges); lpSolverTime_.stop(); _remRows(dummy); delete coinrow; delete matrix; freeChar(senses); freeDouble(rhs); freeDouble(ranges); return; }
//===========================================================================// int ATM_DecompApp::createConCount(DecompConstraintSet * model, const int atmIndex){ //--- //--- sum{d in D} v[a,d] <= K[a] (for count) //--- CoinPackedVector row; string rowName = "count(a_" + m_instance.getAtmName(atmIndex) + ")"; pair<int,int> adP; int pairIndex = 0; const vector<int> & pairsAD = m_instance.getPairsAD(); const double * K_a = m_instance.get_K_a(); vector<int>::const_iterator vi; //TODO: this can be faster by storing the incident d's for each a for(vi = pairsAD.begin(); vi != pairsAD.end(); vi++){ adP = m_instance.getIndexADInv(*vi); if(atmIndex != adP.first){ pairIndex++; continue; } row.insert(colIndex_v(pairIndex), 1.0); pairIndex++; } model->appendRow(row, -DecompInf, K_a[atmIndex], rowName); return 1; }
template <class BinaryFunction> void binaryOp(CoinPackedVector& retVal, const CoinPackedVectorBase& op1, const CoinPackedVectorBase& op2, BinaryFunction bf) { retVal.clear(); const int s1 = op1.getNumElements(); const int s2 = op2.getNumElements(); /* Replaced || with &&, in response to complaint from Sven deVries, who rightly points out || is not appropriate for additive operations. && should be ok as long as binaryOp is understood not to create something from nothing. -- lh, 04.06.11 */ if (s1 == 0 && s2 == 0) return; retVal.reserve(s1+s2); const int * inds1 = op1.getIndices(); const double * elems1 = op1.getElements(); const int * inds2 = op2.getIndices(); const double * elems2 = op2.getElements(); int i; // loop once for each element in op1 for ( i=0; i<s1; ++i ) { const int index = inds1[i]; const int pos2 = op2.findIndex(index); const double val = bf(elems1[i], pos2 == -1 ? 0.0 : elems2[pos2]); // if (val != 0.0) // *THINK* : should we put in only nonzeros? retVal.insert(index, val); } // loop once for each element in operand2 for ( i=0; i<s2; ++i ) { const int index = inds2[i]; // if index exists in op1, then element was processed in prior loop if ( op1.isExistingIndex(index) ) continue; // Index does not exist in op1, so the element value must be zero const double val = bf(0.0, elems2[i]); // if (val != 0.0) // *THINK* : should we put in only nonzeros? retVal.insert(index, val); } }
//===========================================================================// int ATM_DecompApp::createConPickOne(DecompConstraintSet * model, const int atmIndex){ //--- //--- sum{t in T} x1[a,t] <= 1 //--- int t; CoinPackedVector row; string rowName = "pickone_x1(a_" + m_instance.getAtmName(atmIndex) + ")"; if(m_appParam.UseTightModel){ for(t = 0; t <= m_appParam.NumSteps; t++) row.insert(colIndex_x1(atmIndex,t), 1.0); model->appendRow(row, 1.0, 1.0, rowName); } else{ for(t = 0; t < m_appParam.NumSteps; t++) row.insert(colIndex_x1(atmIndex,t), 1.0); model->appendRow(row, -DecompInf, 1.0, rowName); } return 1; }
/** scale the cut passed as argument*/ void scale(OsiRowCut &cut) { double rhs = fabs(cut.lb()); CoinPackedVector row; row.reserve(cut.row().getNumElements()); for (int i = 0 ; i < cut.row().getNumElements() ; i++) { row.insert(cut.row().getIndices()[i], cut.row().getElements()[i]/rhs); } cut.setLb(cut.lb()/rhs); cut.setRow(row); }
/** scale the cut passed as argument using provided normalization factor*/ void scale(OsiRowCut &cut, double norma) { assert(norma >0.); CoinPackedVector row; row.reserve(cut.row().getNumElements()); for (int i = 0 ; i < cut.row().getNumElements() ; i++) { row.insert(cut.row().getIndices()[i], cut.row().getElements()[i]/norma); } cut.setLb(cut.lb()/norma); cut.setRow(row); }
// ------------------------------------------------------------------------- // void UtilPackedVectorFromDense(const int len, const double* dense, const double etol, CoinPackedVector& v) { //TODO: test for dup? - efficiency vs debug //TODO: insert is slow - better to use setVector? int i; for (i = 0; i < len; i++) { if (fabs(dense[i]) > etol) { v.insert(i, dense[i]); } } }
/*------------------------------------------------------------------------*/ CoinPackedVector * DecompCutPool::createRowReform(const int n_corecols, const CoinPackedVector* row, const DecompVarList& vars) { double coeff; //--- //--- Create a dense row from the original sparse row (in terms of x). //--- double* rowDense = row->denseVector(n_corecols); //--- //--- In order to expand to the reformulated row (in terms of lambda), //--- we need to substitute x = sum{s in F'} s lambda[s] //--- //--- Example - Given a cut: //--- a[1]x[1] + a[2]x[2] >= b //--- a[1]x[1] = a[1] (s1[1] lam[1] + s2[1] lam[2]) //--- a[2]x[2] = a[2] (s1[2] lam[1] + s2[2] lam[2]) //--- So, lam[1]'s coeff = a[1] s1[1] + a[2] s1[2] //--- lam[2]'s coeff = a[1] s2[1] + a[2] s2[2] //--- int col_index = 0; CoinPackedVector* rowReform = new CoinPackedVector(); DecompVarList::const_iterator vli; for (vli = vars.begin(); vli != vars.end(); vli++) { coeff = (*vli)->m_s.dotProduct(rowDense); if (fabs(coeff) > 1.0e-12) { //m_app->m_param.tolerance) rowReform->insert(col_index, coeff); } col_index++; } if (rowReform->getNumElements() == 0) { cerr << "row size 0, don't add it" << endl; UTIL_DELPTR(rowReform); rowReform = 0; } UTIL_DELARR(rowDense); //--- //--- delete the temporary memory //--- UTIL_DELARR(rowDense); return rowReform; }
//@{ template <class BinaryFunction> void binaryOp(CoinPackedVector& retVal, const CoinPackedVectorBase& op1, double value, BinaryFunction bf) { retVal.clear(); const int s = op1.getNumElements(); if (s > 0) { retVal.reserve(s); const int * inds = op1.getIndices(); const double * elems = op1.getElements(); for (int i=0; i<s; ++i ) { retVal.insert(inds[i], bf(value, elems[i])); } } }
// ========================================================================= // COIN Macros // ========================================================================= // ------------------------------------------------------------------------- // CoinPackedVector* UtilPackedVectorFromDense(const int len, const double* dense, const double etol) { //TODO: test for dup? - efficiency vs debug //TODO: insert is slow - better to use setVector? int i; CoinPackedVector* v = new CoinPackedVector(); for (i = 0; i < len; i++) { if (fabs(dense[i]) > etol) { v->insert(i, dense[i]); } } return v; }
/* Extract a column from a CoinPostsolveMatrix. At least here we only need to walk one threaded column. */ CoinPackedVector *CoinPresolveMonitor::extractCol (int j, const CoinPostsolveMatrix *mtx) const { const CoinBigIndex *colStarts = mtx->getColStarts() ; const int *colLens = mtx->getColLengths() ; const double *coeffs = mtx->getElementsByCol() ; const int *rowIndices = mtx->getRowIndicesByCol() ; const CoinBigIndex *colLinks = mtx->link_ ; CoinPackedVector *pkvec = new CoinPackedVector() ; CoinBigIndex jj = colStarts[j] ; const int &lenj = colLens[j] ; for (int k = 0 ; k < lenj ; k++) { pkvec->insert(rowIndices[jj],coeffs[jj]) ; jj = colLinks[jj] ; } return (pkvec) ; }
/* Extract a row from a CoinPostsolveMatrix. This is very painful, because the matrix is threaded column-ordered only. We have to scan every entry in the matrix, looking for entries that match the requested row index. */ CoinPackedVector *CoinPresolveMonitor::extractRow (int i, const CoinPostsolveMatrix *mtx) const { const CoinBigIndex *colStarts = mtx->getColStarts() ; const int *colLens = mtx->getColLengths() ; const double *coeffs = mtx->getElementsByCol() ; const int *rowIndices = mtx->getRowIndicesByCol() ; const CoinBigIndex *colLinks = mtx->link_ ; int n = mtx->getNumCols() ; CoinPackedVector *pkvec = new CoinPackedVector() ; for (int j = 0 ; j < n ; j++) { const CoinBigIndex ii = presolve_find_row3(i,colStarts[j],colLens[j],rowIndices,colLinks) ; if (ii >= 0) pkvec->insert(j,coeffs[ii]) ; } return (pkvec) ; }
void OsiSolver::add_in_constraint(LinearConstraint *con, double coef) { CoinPackedVector row; for (unsigned int i = 0; i < con->_variables.size(); ++i) { int *index = new int; MipWrapper_Expression *var = con->_variables[i]; if (var->_var == NULL) { *index = n_cols++; var->_var = index; if (!var->_continuous) { hasIntegers = true; integer_vars.push_back(*index); } } else { index = (int*) var->_var; } col_lb[*index] = manageInfinity(var->_lower); col_ub[*index] = manageInfinity(var->_upper); row.insert(*index, con->_coefficients[i]); } row_lb[n_rows] = manageInfinity(con->_lhs); row_ub[n_rows] = manageInfinity(con->_rhs); n_rows++; matrix->appendRow(row); }
void OsiIF::_addRows(ArrayBuffer<Row*> &rows) { CoinPackedVector *coinrow = new CoinPackedVector(); for (int i = 0; i < rows.size(); i++) { coinrow->clear(); for (int j = 0; j < rows[i]->nnz(); j++){ coinrow->insert(rows[i]->support(j), rows[i]->coeff(j)); } lpSolverTime_.start(); osiLP_->addRow(*coinrow, csense2osi(rows[i]->sense()), rows[i]->rhs(), 0.0); lpSolverTime_.stop(); } delete coinrow; lpSolverTime_.start(); numRows_ = osiLP_->getNumRows(); rhs_ = osiLP_->getRightHandSide(); numCols_ = osiLP_->getNumCols(); collower_ = osiLP_->getColLower(); colupper_ = osiLP_->getColUpper(); lpSolverTime_.stop(); }
//############################################################################# 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(); //OsiSolverInterface * sSolver = new OsiCbcSolverInterface(); OsiSolverInterface* sSolver = new OsiSymSolverInterface(); //sSolver = oSolver->clone(); //OsiSolverInterface * sSolver = tmpSolver; //OsiSolverInterface * tmpSolver = new OsiSolverInterface(oSolver); 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; } } if(0){ 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); } //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 */ //OsiSolverInterface * nSolver = new OsiCbcSolverInterface(); OsiSolverInterface * nSolver = new OsiSymSolverInterface(); 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"); 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); } 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 */ //OsiSolverInterface * nSolver = new OsiCbcSolverInterface(); OsiSolverInterface * nSolver = new OsiSymSolverInterface(); 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); 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); } 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(); } }
bool OSI_X_SolverWrapper<SOLVERINTERFACE>::setup(const LP_Constraints & cstraints) //cstraints <-> constraints { bool bOk = true; if ( si == NULL ) { return false; } assert(nbParams_ == cstraints.nbParams_); const unsigned int NUMVAR = cstraints.constraint_mat_.cols(); std::vector<double> col_lb(NUMVAR);//the column lower bounds std::vector<double> col_ub(NUMVAR);//the column upper bounds this->nbParams_ = NUMVAR; si->setObjSense( ((cstraints.bminimize_) ? 1 : -1) ); const Mat & A = cstraints.constraint_mat_; //Equality constraint will be done by two constraints due to the API limitation ( >= & <=). const size_t nbLine = A.rows() + std::count(cstraints.vec_sign_.begin(), cstraints.vec_sign_.end(), LP_Constraints::LP_EQUAL); std::vector<double> row_lb(nbLine);//the row lower bounds std::vector<double> row_ub(nbLine);//the row upper bounds CoinPackedMatrix * matrix = new CoinPackedMatrix(false,0,0); matrix->setDimensions(0, NUMVAR); //-- Add row-wise constraint size_t indexRow = 0; for (int i=0; i < A.rows(); ++i) { Vec temp = A.row(i); CoinPackedVector row; if ( cstraints.vec_sign_[i] == LP_Constraints::LP_EQUAL || cstraints.vec_sign_[i] == LP_Constraints::LP_LESS_OR_EQUAL ) { int coef = 1; for ( int j = 0; j < A.cols() ; j++ ) { row.insert(j, coef * temp.data()[j]); } row_lb[indexRow] = -1.0 * si->getInfinity(); row_ub[indexRow] = coef * cstraints.constraint_objective_(i); matrix->appendRow(row); indexRow++; } if ( cstraints.vec_sign_[i] == LP_Constraints::LP_EQUAL || cstraints.vec_sign_[i] == LP_Constraints::LP_GREATER_OR_EQUAL ) { int coef = -1; for ( int j = 0; j < A.cols() ; j++ ) { row.insert(j, coef * temp.data()[j]); } row_lb[indexRow] = -1.0 * si->getInfinity(); row_ub[indexRow] = coef * cstraints.constraint_objective_(i); matrix->appendRow(row); indexRow++; } } //-- Setup bounds for all the parameters if (cstraints.vec_bounds_.size() == 1) { // Setup the same bound for all the parameters for (int i=0; i < this->nbParams_; ++i) { col_lb[i] = cstraints.vec_bounds_[0].first; col_ub[i] = cstraints.vec_bounds_[0].second; } } else // each parameter have it's own bounds { for (int i=0; i < this->nbParams_; ++i) { col_lb[i] = cstraints.vec_bounds_[i].first; col_ub[i] = cstraints.vec_bounds_[i].second; } } si->loadProblem(*matrix, &col_lb[0], &col_ub[0], cstraints.vec_cost_.empty() ? NULL : &cstraints.vec_cost_[0], &row_lb[0], &row_ub[0] ); delete matrix; return bOk; }
//===========================================================================// DecompConstraintSet * ATM_DecompApp::createModelRelaxCount(){ UtilPrintFuncBegin(m_osLog, m_classTag, "createModelRelaxCount()", m_appParam.LogLevel, 2); int a, d, t, nRows, pairIndex, nRowsMax; double rhs, coefA, coefC; pair<int,int> adP; vector<int>::const_iterator vi; const int nSteps = m_appParam.NumSteps; const int nAtms = m_instance.getNAtms(); const int nDates = m_instance.getNDates(); const int nPairs = m_instance.getNPairs(); const int nAtmsSteps = getNAtmsSteps(); const vector<int> & pairsAD = m_instance.getPairsAD(); const double * a_ad = m_instance.get_a_ad(); //dense storage const double * b_ad = m_instance.get_b_ad(); //dense storage const double * c_ad = m_instance.get_c_ad(); //dense storage const double * d_ad = m_instance.get_d_ad(); //dense storage const double * e_ad = m_instance.get_e_ad(); //dense storage const double * w_ad = m_instance.get_w_ad(); //dense storage const double * B_d = m_instance.get_B_d(); const int nCols = numCoreCols(); if(m_appParam.UseTightModel) nRowsMax = nDates + 2*nAtms + nAtmsSteps + 2*nPairs; else nRowsMax = nDates + nAtms + 3*nAtmsSteps + 2*nPairs; //TODO: // try the nested idea - so master has ConZtoX and we price without that // but we solve with gap the harder oracle with those constraints //--- //--- A' (relax): //--- for d in D: //--- sum{a in A} (f+[a,d] - f-[a,d]) <= B[d] <---- makes it hard //OPT //--- for a in A: //--- sum{t in T} x1[a,t] <= 1 //OPT //--- for a in A, t in T: //--- z[a,t] <= x1[a,t], //--- z[a,t] <= x2[a], //--- z[a,t] >= x1[a,t] + x2[a] - 1. //--- for a in A, d in D: //--- f+[a,d] - f-[a,d] = //--- a[a,d] sum{t in T} (t/n) x1[a,t] + //--- b[a,d] x2[a] + //--- c[a,d] sum{t in T} (t/n) z[a,t] + //--- d[a,d] x3[a] + //--- e[a,d] //--- f-[a,d] <= w[a,d] * v[a,d] //--- DecompConstraintSet * model = new DecompConstraintSet(); CoinAssertHint(model, "Error: Out of Memory"); model->M = new CoinPackedMatrix(false, 0.0, 0.0); CoinAssertHint(model->M, "Error: Out of Memory"); model->M->setDimensions(0, nCols); model->reserve(nRowsMax, nCols); //--- //--- create nDates empty rowBudget packed vectors //--- vector<CoinPackedVector> rowBudget; for(d = 0; d < nDates; d++){ CoinPackedVector row; rowBudget.push_back(row); } nRows = 0; pairIndex = 0; for(vi = pairsAD.begin(); vi != pairsAD.end(); vi++){ adP = m_instance.getIndexADInv(*vi); a = adP.first; d = adP.second; //--- //--- sum{a in A} (f+[a,d] - f-[a,d]) <= B[d] //--- rowBudget[d].insert(getColOffset_fp() + pairIndex, 1.0); rowBudget[d].insert(getColOffset_fm() + pairIndex, -1.0); //--- //--- f+[a,d] - f-[a,d] = //--- a[a,d] sum{t in T} (t/n) x1[a,t] + //--- b[a,d] x2[a] + //--- c[a,d] sum{t in T} (t/n) z[a,t] + //--- d[a,d] x3[a] + //--- e[a,d] //--- CoinPackedVector row; string rowName = "demand_def(a_" + m_instance.getAtmName(a) + ",d_" + m_instance.getDateName(d) + ")"; row.insert(colIndex_fp(pairIndex), 1.0); row.insert(colIndex_fm(pairIndex), -1.0); coefA = -a_ad[*vi] / nSteps; coefC = -c_ad[*vi] / nSteps; if(m_appParam.UseTightModel){ for(t = 0; t <= nSteps; t++){ row.insert(colIndex_x1(a,t), t * coefA); row.insert(colIndex_z (a,t), t * coefC); } } else{ for(t = 0; t < nSteps; t++){ row.insert(colIndex_x1(a,t), (t+1) * coefA); row.insert(colIndex_z (a,t), (t+1) * coefC); } } row.insert(colIndex_x2(a), -b_ad[*vi]); row.insert(colIndex_x3(a), -d_ad[*vi]); rhs = e_ad[*vi]; model->appendRow(row, rhs, rhs, rowName); nRows++; //--- //--- f-[a,d] <= w[a,d] * v[a,d] //--- CoinPackedVector rowLink; string rowNameLink = "linkv(a_" + m_instance.getAtmName(a) + ",d_" + m_instance.getDateName(d) + ")"; rowLink.insert(colIndex_fm(pairIndex), 1.0); rowLink.insert(colIndex_v (pairIndex), -w_ad[*vi]); model->appendRow(rowLink, -DecompInf, 0.0, rowNameLink); nRows++; pairIndex++; } for(d = 0; d < nDates; d++){ string rowNameBudget = "budget(d_" + m_instance.getDateName(d) + ")"; model->appendRow(rowBudget[d], -DecompInf, B_d[d], rowNameBudget); nRows++; } //--- //--- for a in A: //--- sum{t in T} x1[a,t] <= 1 //--- for a in A, t in T: //--- z[a,t] <= x1[a,t], //--- z[a,t] <= x2[a], //--- z[a,t] >= x1[a,t] + x2[a] - 1. //--- //THINK: if you use this, shouldn't we postprocess z=x1*x2? // putting those constaints in master are unneccessary... // in fact, why not just do that in block version too... //for(a = 0; a < nAtms; a++){ //nRows += createConZtoX(model, a); //nRows += createConPickOne(model, a); //} assert(nRows <= nRowsMax); //--- //--- create model columns //--- createModelColumns(model); UtilPrintFuncEnd(m_osLog, m_classTag, "createModelRelaxCount()", m_appParam.LogLevel, 2); return model; }
//===========================================================================// DecompConstraintSet * ATM_DecompApp::createModelRelax2(const int d){ UtilPrintFuncBegin(m_osLog, m_classTag, "createModelRelax2()", m_appParam.LogLevel, 2); int a, t, nRows, pairIndex, nRowsMax; double rhs, coefA, coefC; pair<int,int> adP; vector<int>::const_iterator vi; const int nSteps = m_appParam.NumSteps; const int nAtms = m_instance.getNAtms(); const vector<int> & pairsAD = m_instance.getPairsAD(); const double * a_ad = m_instance.get_a_ad(); //dense storage const double * b_ad = m_instance.get_b_ad(); //dense storage const double * c_ad = m_instance.get_c_ad(); //dense storage const double * d_ad = m_instance.get_d_ad(); //dense storage const double * e_ad = m_instance.get_e_ad(); //dense storage const double * w_ad = m_instance.get_w_ad(); //dense storage const double * B_d = m_instance.get_B_d(); const int nCols = numCoreCols(); if(m_appParam.UseTightModel) nRowsMax = 3*nAtms + 1 + getNAtmsSteps(); else nRowsMax = 2*nAtms + 1 + (3*getNAtmsSteps()); //--- //--- A'[d] for d in D (independent blocks) //--- for a in A //--- f+[a,d] - f-[a,d] = //--- a[a,d] sum{t in T} (t/n) x1[a,t] + //--- b[a,d] x2[a] + //--- c[a,d] sum{t in T} (t/n) z[a,t] + //--- d[a,d] x3[a] + //--- e[a,d] //--- f-[a,d] <= w[a,d] * v[a,d] //--- sum{a in A} (f+[a,d] - f-[a,d]) <= B[d] //--- for a in A, t in T: //--- z[a,t] <= x1[a,t], //--- z[a,t] <= x2[a], //--- z[a,t] >= x1[a,t] + x2[a] - 1. //--- DecompConstraintSet * model = new DecompConstraintSet(); CoinAssertHint(model, "Error: Out of Memory"); model->M = new CoinPackedMatrix(false, 0.0, 0.0); CoinAssertHint(model->M, "Error: Out of Memory"); model->M->setDimensions(0, nCols); model->reserve(nRowsMax, nCols); CoinPackedVector rowBudget; nRows = 0; pairIndex = 0; for(vi = pairsAD.begin(); vi != pairsAD.end(); vi++){ adP = m_instance.getIndexADInv(*vi); if(d != adP.second){ pairIndex++; continue; } a = adP.first; //--- //--- sum{a in A} (f+[a,d] - f-[a,d]) <= B[d] //--- rowBudget.insert(getColOffset_fp() + pairIndex, 1.0); rowBudget.insert(getColOffset_fm() + pairIndex, -1.0); //--- //--- f+[a,d] - f-[a,d] = //--- a[a,d] sum{t in T} (t/n) x1[a,t] + //--- b[a,d] x2[a] + //--- c[a,d] sum{t in T} (t/n) z[a,t] + //--- d[a,d] x3[a] + //--- e[a,d] //--- CoinPackedVector row; string rowName = "demand_def(a_" + m_instance.getAtmName(a) + ",d_" + m_instance.getDateName(d) + ")"; row.insert(colIndex_fp(pairIndex), 1.0); row.insert(colIndex_fm(pairIndex), -1.0); coefA = -a_ad[*vi] / nSteps; coefC = -c_ad[*vi] / nSteps; if(m_appParam.UseTightModel){ for(t = 0; t <= nSteps; t++){ row.insert(colIndex_x1(a,t), t * coefA); row.insert(colIndex_z (a,t), t * coefC); } } else{ for(t = 0; t < nSteps; t++){ row.insert(colIndex_x1(a,t), (t+1) * coefA); row.insert(colIndex_z (a,t), (t+1) * coefC); } } row.insert(colIndex_x2(a), -b_ad[*vi]); row.insert(colIndex_x3(a), -d_ad[*vi]); rhs = e_ad[*vi]; model->appendRow(row, rhs, rhs, rowName); nRows++; //--- //--- f-[a,d] <= w[a,d] * v[a,d] //--- CoinPackedVector rowLink; string rowNameLink = "linkv(a_" + m_instance.getAtmName(a) + ",d_" + m_instance.getDateName(d) + ")"; rowLink.insert(colIndex_fm(pairIndex), 1.0); rowLink.insert(colIndex_v (pairIndex), -w_ad[*vi]); model->appendRow(rowLink, -DecompInf, 0.0, rowNameLink); nRows++; pairIndex++; } string rowNameBudget = "budget(d_" + m_instance.getDateName(d) + ")"; model->appendRow(rowBudget, -DecompInf, B_d[d], rowNameBudget); nRows++; for(a = 0; a < nAtms; a++) nRows += createConZtoX(model, a); assert(nRows <= nRowsMax); //--- //--- create model columns //--- createModelColumns(model, -1, d); UtilPrintFuncEnd(m_osLog, m_classTag, "createModelRelax2()", m_appParam.LogLevel, 2); return model; }
//===========================================================================// DecompConstraintSet * ATM_DecompApp::createModelRelax1(const int a, bool includeCount){ UtilPrintFuncBegin(m_osLog, m_classTag, "createModelRelax1()", m_appParam.LogLevel, 2); int t, d, nRows, pairIndex; double rhs, coefA, coefC; pair<int,int> adP; vector<int>::const_iterator vi; const int nSteps = m_appParam.NumSteps; const int nDates = m_instance.getNDates(); const vector<int> & pairsAD = m_instance.getPairsAD(); const double * a_ad = m_instance.get_a_ad(); //dense storage const double * b_ad = m_instance.get_b_ad(); //dense storage const double * c_ad = m_instance.get_c_ad(); //dense storage const double * d_ad = m_instance.get_d_ad(); //dense storage const double * e_ad = m_instance.get_e_ad(); //dense storage const double * w_ad = m_instance.get_w_ad(); //dense storage const int nCols = numCoreCols(); int nRowsMax = nDates + 1 + (3*nSteps); if(includeCount) nRowsMax += nDates + 1; //--- //--- for a in A, d in D: //--- f+[a,d] - f-[a,d] = //--- a[a,d] sum{t in T} (t/n) x1[a,t] + //--- b[a,d] x2[a] + //--- c[a,d] sum{t in T} (t/n) z[a,t] + //--- d[a,d] x3[a] + //--- e[a,d] //--- f-[a,d] <= w[a,d] * v[a,d] (for count) //--- for a in A: //--- sum{t in T} x1[a,t] <= 1 //--- sum{d in D} v[a,d] <= K[a] (for count) [OPT] //Probably not... //THINK: can't we just post-process this? z=x1*x2 //--- for a in A, t in T: //--- z[a,t] <= x1[a,t], //--- z[a,t] <= x2[a], //--- z[a,t] >= x1[a,t] + x2[a] - 1. //--- DecompConstraintSet * model = new DecompConstraintSet(); CoinAssertHint(model, "Error: Out of Memory"); model->M = new CoinPackedMatrix(false, 0.0, 0.0); CoinAssertHint(model->M, "Error: Out of Memory"); model->M->setDimensions(0, nCols); model->M->reserve(nRowsMax, nCols); model->rowLB.reserve(nRowsMax); model->rowUB.reserve(nRowsMax); //--- //--- for a in A, d in D: //--- f+[a,d] - f-[a,d] = //--- a[a,d] sum{t in T} (t/n) x1[a,t] + //--- b[a,d] x2[a] + //--- c[a,d] sum{t in T} (t/n) z[a,t] + //--- d[a,d] x3[a] + //--- e[a,d] //--- f-[a,d] <= w[a,d] * v[a,d] (for count) //--- nRows = 0; pairIndex = 0; for(vi = pairsAD.begin(); vi != pairsAD.end(); vi++){ adP = m_instance.getIndexADInv(*vi); if(a != adP.first){ pairIndex++; continue; } d = adP.second; CoinPackedVector row; string rowName = "demand_def(a_" + m_instance.getAtmName(a) + ",d_" + m_instance.getDateName(d) + ")"; row.insert(colIndex_fp(pairIndex), 1.0); row.insert(colIndex_fm(pairIndex), -1.0); coefA = -a_ad[*vi] / nSteps; coefC = -c_ad[*vi] / nSteps; if(m_appParam.UseTightModel){ for(t = 0; t <= nSteps; t++){ row.insert(colIndex_x1(a,t), t * coefA); row.insert(colIndex_z (a,t), t * coefC); } } else{ for(t = 0; t < nSteps; t++){ row.insert(colIndex_x1(a,t), (t+1) * coefA); row.insert(colIndex_z (a,t), (t+1) * coefC); } } row.insert(colIndex_x2(a), -b_ad[*vi]); row.insert(colIndex_x3(a), -d_ad[*vi]); rhs = e_ad[*vi]; model->M->appendRow(row); model->rowLB.push_back(rhs); model->rowUB.push_back(rhs); model->rowNames.push_back(rowName); nRows++; CoinPackedVector rowLink; string rowNameLink = "linkv(a_" + m_instance.getAtmName(a) + ",d_" + m_instance.getDateName(d) + ")"; rowLink.insert(colIndex_fm(pairIndex), 1.0); rowLink.insert(colIndex_v (pairIndex), -w_ad[*vi]); model->M->appendRow(rowLink); model->rowLB.push_back(-DecompInf); model->rowUB.push_back(0.0); model->rowNames.push_back(rowNameLink); nRows++; pairIndex++; } //--- //--- for a in A: //--- sum{t in T} x1[a,t] <= 1 //--- sum{d in D} v[a,d] <= K[a] (for count) //--- nRows += createConPickOne(model, a); if(includeCount) nRows += createConCount(model, a); //--- //--- for a in A, t in T: //--- z[a,t] <= x1[a,t], //--- z[a,t] <= x2[a], //--- z[a,t] >= x1[a,t] + x2[a] - 1. //--- nRows += createConZtoX(model, a); //--- //--- create model columns //--- createModelColumns(model, a); UtilPrintFuncEnd(m_osLog, m_classTag, "createModelRelax1()", m_appParam.LogLevel, 2); return model; }
bool OSI_X_SolverWrapper<SOLVERINTERFACE>::setup(const LP_Constraints & cstraints) //cstraints <-> constraints { bool bOk = true; if ( si == NULL ) { return false; } assert(_nbParams == cstraints._nbParams); int NUMVAR = cstraints._constraintMat.cols(); int NUMCON = cstraints._constraintMat.rows(); int NUMANZ = cstraints._constraintMat.cols() * cstraints._constraintMat.rows(); //DENSE MATRIX std::vector<double> col_lb(NUMVAR);//the column lower bounds std::vector<double> col_ub(NUMVAR);//the column upper bounds this->_nbParams = NUMVAR; if (cstraints._bminimize) { si->setObjSense( 1 ); } else { si->setObjSense( -1 ); } const Mat & A = cstraints._constraintMat; //Equality constraint will be handked by two constraintsdue to the API limitation. size_t nbLine = A.rows() + std::count(cstraints._vec_sign.begin(), cstraints._vec_sign.end(), EQ); std::vector<double> row_lb(nbLine);//the row lower bounds std::vector<double> row_ub(nbLine);//the row upper bounds CoinPackedMatrix * matrix = new CoinPackedMatrix(false,0,0); matrix->setDimensions(0, NUMVAR); //-- Add row-wise constraint size_t indexRow = 0; for (int i=0; i < A.rows(); ++i) { Vec temp = A.row(i); CoinPackedVector row; if ( cstraints._vec_sign[i] == EQ || cstraints._vec_sign[i] == LE ) { int coef = 1; for ( int j = 0; j < A.cols() ; j++ ) { row.insert(j, coef * temp.data()[j]); } row_lb[indexRow] = -1.0 * si->getInfinity(); row_ub[indexRow] = coef * cstraints._Cst_objective(i); matrix->appendRow(row); indexRow++; } if ( cstraints._vec_sign[i] == EQ || cstraints._vec_sign[i] == GE ) { int coef = -1; for ( int j = 0; j < A.cols() ; j++ ) { row.insert(j, coef * temp.data()[j]); } row_lb[indexRow] = -1.0 * si->getInfinity(); row_ub[indexRow] = coef * cstraints._Cst_objective(i); matrix->appendRow(row); indexRow++; } } //-- Setup bounds if (cstraints._vec_bounds.size() == 1) { // Setup the same bound for all the parameter for (int i=0; i < this->_nbParams; ++i) { col_lb[i] = cstraints._vec_bounds[0].first; col_ub[i] = cstraints._vec_bounds[0].second; } } else { for (int i=0; i < this->_nbParams; ++i) { col_lb[i] = cstraints._vec_bounds[i].first; col_ub[i] = cstraints._vec_bounds[i].second; } } si->loadProblem(*matrix, &col_lb[0], &col_ub[0], cstraints._vec_cost.empty() ? NULL : &cstraints._vec_cost[0], &row_lb[0], &row_ub[0] ); delete matrix; return bOk; }
//===========================================================================// void MCF_DecompApp::createModelRelaxSparse(DecompConstraintSet* model, int commId) { //--- //--- SUBPROBLEM (A'): (one block for each k in K) //--- sum{(j,i) in A} x[k,i,j] - //--- sum{(i,j) in A} x[k,i,j] = d[i,k], for all i in N //--- x[k,i,j] integer >= l[i,j] <= u[i,j], for all (i,j) in A //--- For k=(s,t) in K, //--- d[i,k] = -d[k] if i=s //--- = d[k] if i=t //--- = 0, otherwise //--- int a, i, head, tail, origColIndex, source, sink; int numArcs = m_instance.m_numArcs; int numNodes = m_instance.m_numNodes; int numCommodities = m_instance.m_numCommodities; int numCols = numArcs; int numRows = numNodes; int numColsOrig = numArcs * numCommodities; MCF_Instance::arc* arcs = m_instance.m_arcs; MCF_Instance::commodity* commodities = m_instance.m_commodities; UtilPrintFuncBegin(m_osLog, m_classTag, "createModelRelaxSparse()", m_appParam.LogLevel, 2); //--- //--- create space for the model matrix (row-majored) //--- model->M = new CoinPackedMatrix(false, 0.0, 0.0); if (!model->M) { throw UtilExceptionMemory("createModelCore", "MCF_DecompApp"); } model->M->setDimensions(0, numCols); model->reserve(numRows, numCols); model->setSparse(numColsOrig); //--- //--- get this commodity's source and sink node //--- source = commodities[commId].source; sink = commodities[commId].sink; //--- //--- create the rows //--- NOTE: this is somewhat inefficient (but simple) //--- for (i = 0; i < numNodes; i++) { CoinPackedVector row; for (a = 0; a < numArcs; a++) { tail = arcs[a].tail; head = arcs[a].head; if (head == i) { row.insert(a, 1.0); } else if (tail == i) { row.insert(a, -1.0); } } if (i == source) model->appendRow(row, -commodities[commId].demand, -commodities[commId].demand); else if (i == sink) model->appendRow(row, commodities[commId].demand, commodities[commId].demand); else { model->appendRow(row, 0.0, 0.0); } } //--- //--- set the colLB, colUB, integerVars and sparse mapping //--- origColIndex = commId * numArcs; for (a = 0; a < numArcs; a++) { double arcLB = arcs[a].lb; double arcUB = arcs[a].ub; model->pushCol(arcLB, arcUB, true, origColIndex); origColIndex++; } UtilPrintFuncEnd(m_osLog, m_classTag, "createModelRelaxSparse()", m_appParam.LogLevel, 2); }
//############################################################################# void MibSHeuristic::objCutHeuristic() { /* Solve the LP relaxation with the new constraint d^2 y <= d^y* */ MibSModel * model = MibSModel_; //OsiSolverInterface * oSolver = model->origLpSolver_; OsiSolverInterface * oSolver = model->getSolver(); //OsiSolverInterface * hSolver = new OsiCbcSolverInterface(); OsiSolverInterface * hSolver = new OsiSymSolverInterface(); double objSense(model->getLowerObjSense()); int lCols(model->getLowerDim()); int uCols(model->getUpperDim()); int tCols(lCols + uCols); int * lColIndices = model->getLowerColInd(); int * uColIndices = model->getUpperColInd(); double * lObjCoeffs = model->getLowerObjCoeffs(); hSolver->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)) hSolver->setInteger(j); } double * optLowerSolutionOrd = model->bS_->optLowerSolutionOrd_; CoinPackedVector objCon; int i(0), index(0); double rhs(0.0); for(i = 0; i < lCols; i++){ index = lColIndices[i]; objCon.insert(index, lObjCoeffs[i] * objSense); //should this be ordered? and should lObjCoeffs by at index? //rhs += optLowerSolutionOrd_[i] * lObjCoeffs[i] * objSense; rhs += optLowerSolutionOrd[i] * lObjCoeffs[i] * objSense; } //Hmm, I think this was wrong before...? // hSolver->addRow(objCon, - hSolver->getInfinity(), rhs); hSolver->addRow(objCon, rhs, hSolver->getInfinity()); /* optimize w.r.t. to the UL objective with the new row */ if(0){ dynamic_cast<OsiCbcSolverInterface *> (hSolver)->getModelPtr()->messageHandler()->setLogLevel(0); } else{ dynamic_cast<OsiSymSolverInterface *> (hSolver)->setSymParam("prep_level", -1); dynamic_cast<OsiSymSolverInterface *> (hSolver)->setSymParam("verbosity", -2); dynamic_cast<OsiSymSolverInterface *> (hSolver)->setSymParam("max_active_nodes", 1); } hSolver->branchAndBound(); if(0) hSolver->writeLp("objcutheuristic"); if(hSolver->isProvenOptimal()){ MibSSolution *mibSol = NULL; OsiSolverInterface * lSolver = model->bS_->setUpModel(hSolver, true); if(0){ 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); } lSolver->branchAndBound(); const double * sol = hSolver->getColSolution(); double objVal(lSolver->getObjValue() * objSense); double etol(etol_); double lowerObj = getLowerObj(sol, objSense); double * optUpperSolutionOrd = new double[uCols]; double * optLowerSolutionOrd = new double[lCols]; CoinZeroN(optUpperSolutionOrd, uCols); CoinZeroN(optLowerSolutionOrd, lCols); if(fabs(objVal - lowerObj) < etol){ /** Current solution is bilevel feasible **/ mibSol = new MibSSolution(hSolver->getNumCols(), hSolver->getColSolution(), hSolver->getObjValue(), model); model->storeSolution(BlisSolutionTypeHeuristic, mibSol); mibSol = NULL; } else{ /* solution is not bilevel feasible, create one that is */ const double * uSol = hSolver->getColSolution(); const double * lSol = lSolver->getColSolution(); //int numElements(lSolver->getNumCols()); int numElements(hSolver->getNumCols()); int i(0), pos(0), index(0); double * lpSolution = new double[numElements]; double upperObj(0.0); //FIXME: problem is still here. indices may be wrong. //also is all this necessary, or can we just paste together uSol and lSol? for(i = 0; i < numElements; i++){ //index = indices[i]; pos = model->bS_->binarySearch(0, lCols - 1, i, lColIndices); if(pos < 0){ pos = model->bS_->binarySearch(0, uCols - 1, i, uColIndices); //optUpperSolutionOrd[pos] = values[i]; //optUpperSolutionOrd[pos] = uSol[pos]; if (pos >= 0){ optUpperSolutionOrd[pos] = uSol[i]; } } else{ //optLowerSolutionOrd[pos] = lSol[i]; optLowerSolutionOrd[pos] = lSol[pos]; } } for(i = 0; i < uCols; i++){ index = uColIndices[i]; lpSolution[index] = optUpperSolutionOrd[i]; upperObj += optUpperSolutionOrd[i] * hSolver->getObjCoefficients()[index]; } for(i = 0; i < lCols; i++){ index = lColIndices[i]; lpSolution[index] = optLowerSolutionOrd[i]; upperObj += optLowerSolutionOrd[i] * hSolver->getObjCoefficients()[index]; } if(model->checkUpperFeasibility(lpSolution)){ mibSol = new MibSSolution(hSolver->getNumCols(), lpSolution, upperObj * hSolver->getObjSense(), model); model->storeSolution(BlisSolutionTypeHeuristic, mibSol); mibSol = NULL; } delete [] lpSolution; } delete lSolver; } delete hSolver; }
/** Get an inner-approximation constraint obtained by drawing a chord linking the two given points x and x2. * This only applies to nonlinear constraints featuring univariate functions (f(x) <= y).**/ bool HeuristicInnerApproximation::getMyInnerApproximation(Bonmin::OsiTMINLPInterface &si, OsiCuts &cs, int ind, const double * x, const double * x2) { int n, m, nnz_jac_g, nnz_h_lag; Ipopt::TNLP::IndexStyleEnum index_style; Bonmin::TMINLP2TNLP * problem = si.problem(); problem->get_nlp_info(n, m, nnz_jac_g, nnz_h_lag, index_style); double infty = si.getInfinity(); CoinPackedVector cut; double lb = -infty; double ub = 0; double g = 0; double g2 = 0; double diff = 0; double a = 0; problem->eval_gi(n, x, 1, ind, g); problem->eval_gi(n, x2, 1, ind, g2); Bonmin::vector<int> jCol(n); int nnz; problem->eval_grad_gi(n, x2, 0, ind, nnz, jCol(), NULL); Bonmin::vector<double> jValues(nnz); problem->eval_grad_gi(n, x2, 0, ind, nnz, NULL, jValues()); bool add = false; //printf("const %i nnz %i\n", ind, nnz); for (int i = 0; i < nnz; i++) { const int &colIdx = jCol[i]; if(index_style == Ipopt::TNLP::FORTRAN_STYLE) jCol[i]--; diff = x[colIdx] - x2[colIdx]; if (fabs(diff) >= 1e-8) { a = (g - g2) / diff; cut.insert(colIdx, a); ub = (a * x[colIdx] - g) - fabs(a * x[colIdx] - g)*1e-6; //printf("const %i col %i p[col] %g pp[col] %g g %g g2 %g diff %g\n",ind, colIdx, x[colIdx], x2[colIdx], g, g2, diff); add = true; } else { cut.insert(colIdx, jValues[i]); //printf("const %i col %i val %g\n",ind, colIdx, jValues[i]); } } if (add) { OsiRowCut newCut; newCut.setGloballyValidAsInteger(1); newCut.setLb(lb); //********* Perspective Extension ********// int binary_id = 0; // index corresponding to the binary variable activating the corresponding constraint const int* ids = problem->get_const_xtra_id(); // vector of indices corresponding to the binary variable activating the corresponding constraint // Get the index of the corresponding indicator binary variable binary_id = (ids == NULL) ? -1 : ids[ind]; if(binary_id>0) {// If this hyperplane is a linearization of a disjunctive constraint, we link its righthand side to the corresponding indicator binary variable cut.insert(binary_id, -ub); // ∂x ≤ ub => ∂x - ub*z ≤ 0 newCut.setUb(0); } else newCut.setUb(ub); //********* Perspective Extension ********// newCut.setRow(cut); cs.insert(newCut); //newCut.print(); return true; } return false; }
bool OSI_X_SolverWrapper::setup(const LP_Constraints & cstraints) //cstraints <-> constraints { if ( si == nullptr ) { return false; } assert(nbParams_ == cstraints.nbParams_); const unsigned int NUMVAR = cstraints.constraint_mat_.cols(); std::vector<double> col_lb(NUMVAR), // the column lower bounds col_ub(NUMVAR); // the column upper bounds this->nbParams_ = NUMVAR; si->setObjSense( ((cstraints.bminimize_) ? 1 : -1) ); const Mat & A = cstraints.constraint_mat_; //Equality constraint will be done by two constraints due to the API limitation ( >= & <=). const size_t nbLine = A.rows() + std::count(cstraints.vec_sign_.begin(), cstraints.vec_sign_.end(), LP_Constraints::LP_EQUAL); // Define default lower and upper bound to [-inf, inf] std::vector<double> row_lb(nbLine, -si->getInfinity()), // the row lower bounds row_ub(nbLine, si->getInfinity()); // the row upper bounds std::unique_ptr<CoinPackedMatrix> matrix(new CoinPackedMatrix(false,0,0)); matrix->setDimensions(0, NUMVAR); //-- Add row-wise constraint size_t indexRow = 0; for (int i=0; i < A.rows(); ++i) { const Vec temp = A.row(i); CoinPackedVector row; if (cstraints.vec_sign_[i] == LP_Constraints::LP_EQUAL || cstraints.vec_sign_[i] == LP_Constraints::LP_LESS_OR_EQUAL) { const int coef = 1; for ( int j = 0; j < A.cols(); ++j ) { row.insert(j, coef * temp.data()[j]); } row_ub[indexRow] = coef * cstraints.constraint_objective_(i); matrix->appendRow(row); ++indexRow; } if (cstraints.vec_sign_[i] == LP_Constraints::LP_EQUAL || cstraints.vec_sign_[i] == LP_Constraints::LP_GREATER_OR_EQUAL) { const int coef = -1; for ( int j = 0; j < A.cols(); ++j ) { row.insert(j, coef * temp.data()[j]); } row_ub[indexRow] = coef * cstraints.constraint_objective_(i); matrix->appendRow(row); ++indexRow; } } //-- Setup bounds for all the parameters if (cstraints.vec_bounds_.size() == 1) { // Setup the same bound for all the parameters std::fill(col_lb.begin(), col_lb.end(), cstraints.vec_bounds_[0].first); std::fill(col_ub.begin(), col_ub.end(), cstraints.vec_bounds_[0].second); } else // each parameter have its own bounds { for (int i=0; i < this->nbParams_; ++i) { col_lb[i] = cstraints.vec_bounds_[i].first; col_ub[i] = cstraints.vec_bounds_[i].second; } } si->loadProblem(*matrix, &col_lb[0], &col_ub[0], cstraints.vec_cost_.empty() ? nullptr : &cstraints.vec_cost_[0], &row_lb[0], &row_ub[0] ); return true; }
// --------------------------------------------------------------------- // int GAP_DecompApp::createModelPartAP(DecompConstraintSet* model) { int i, j, colIndex; int status = GAPStatusOk; int nTasks = m_instance.getNTasks(); //n int nMachines = m_instance.getNMachines(); //m int nCols = nTasks * nMachines; int nRows = nTasks; UtilPrintFuncBegin(m_osLog, m_classTag, "createModelPartAP()", m_appParam.LogLevel, 2); //--- //--- Build the core model constraints (AP = assignment problem). //--- //--- m is number of machines (index i) //--- n is number of tasks (index j) //--- //--- sum{i in 1..m} x[i,j] = 1, j in 1..n //--- //--- Example structure: m=3, n=4 //--- x x x = 1 [j=1] //--- x x x = 1 [j=2] //--- x x x = 1 [j=3] //--- x x x = 1 [j=4] //--- //--- //--- Allocate an empty row-ordered CoinPackedMatrix. Since we plan //--- to add rows, set the column dimension and let the row dimension //--- be set dynamically. //--- model->M = new CoinPackedMatrix(false, 0.0, 0.0); CoinAssertHint(model->M, "Error: Out of Memory"); model->M->setDimensions(0, nCols); //--- //--- we know the sizes needed, so reserve space for them (for efficiency) //--- model->reserve(nRows, nCols); //--- //--- create one row per task //--- rowNames are not needed, they are used for debugging //--- for (j = 0; j < nTasks; j++) { CoinPackedVector row; string rowName = "a(j_" + UtilIntToStr(j) + ")"; for (i = 0; i < nMachines; i++) { colIndex = getIndexIJ(i, j); row.insert(colIndex, 1.0); } model->appendRow(row, 1.0, 1.0, rowName); } //--- //--- set the col upper and lower bounds (all in [0,1]) //--- UtilFillN(model->colLB, nCols, 0.0); UtilFillN(model->colUB, nCols, 1.0); //--- //--- set the indices of the integer variables of model //--- (all vars are binary) //--- UtilIotaN(model->integerVars, nCols, 0); //--- //--- set column names for debugging //--- colIndex = 0; for (i = 0; i < nMachines; i++) { for (j = 0; j < nTasks; j++) { string colName = "x(" + UtilIntToStr(colIndex) + "_" + UtilIntToStr(i) + "," + UtilIntToStr(j) + ")"; model->colNames.push_back(colName); colIndex++; } } UtilPrintFuncEnd(m_osLog, m_classTag, "createModelPartAP()", m_appParam.LogLevel, 2); return status; }
//===========================================================================// int GAP_DecompApp::createModelPartKP(DecompConstraintSet* model, vector<int>& whichKnaps) { int i, j, b, colIndex; int status = GAPStatusOk; int nTasks = m_instance.getNTasks(); //n int nMachines = m_instance.getNMachines(); //m int nKnaps = static_cast<int>(whichKnaps.size()); const int* weight = m_instance.getWeight(); const int* capacity = m_instance.getCapacity(); int nCols = nTasks * nMachines; int nRows = nKnaps; UtilPrintFuncBegin(m_osLog, m_classTag, "createModelPartKP()", m_appParam.LogLevel, 2); //--- //--- Build the relax model constraints (KP = assignment problem). //--- //--- m is number of machines (index i) //--- n is number of tasks (index j) //--- //--- sum{j in 1..n} w[i,j] x[i,j] <= b[i], i in 1..m //--- x[i,j] in {0,1}, i in 1..m, j in 1..n //--- //--- Example structure: m=3, n=4 //--- xxxx <= b[i=1] //--- xxxx <= b[i=2] //--- xxxx <= b[i=3] //--- //--- //--- Allocate an empty row-ordered CoinPackedMatrix. Since we plan //--- to add rows, set the column dimension and let the row dimension //--- be set dynamically. //--- model->M = new CoinPackedMatrix(false, 0.0, 0.0); CoinAssertHint(model->M, "Error: Out of Memory"); model->M->setDimensions(0, nCols); //--- //--- we know the sizes needed, so reserve space for them (for efficiency) //--- model->reserve(nRows, nCols); //--- //--- create one row per knapsack //--- rowNames are not needed, they are used for debugging //--- vector<int>::iterator it; for (it = whichKnaps.begin(); it != whichKnaps.end(); ++it) { i = *it; CoinPackedVector row; string rowName = "k(i_" + UtilIntToStr(i) + ")"; for (j = 0; j < nTasks; j++) { colIndex = getIndexIJ(i, j); row.insert(colIndex, weight[colIndex]); } model->appendRow(row, -m_infinity, capacity[i], rowName); } //--- //--- set the col upper and lower bounds (all in [0,1]) //--- UtilFillN(model->colLB, nCols, 0.0); UtilFillN(model->colUB, nCols, 1.0); //--- //--- set the indices of the integer variables of model //--- UtilIotaN(model->integerVars, nCols, 0); //--- //--- tell the solver which columns are active (in this block) //--- for (it = whichKnaps.begin(); it != whichKnaps.end(); ++it) { b = *it; for (i = 0; i < nMachines; i++) { for (j = 0; j < nTasks; j++) { colIndex = getIndexIJ(i, j); if (i == b) { model->activeColumns.push_back(colIndex); } } } } //--- //--- set column names for debugging //--- colIndex = 0; for (i = 0; i < nMachines; i++) { for (j = 0; j < nTasks; j++) { string colName = "x(" + UtilIntToStr(colIndex) + "_" + UtilIntToStr(i) + "," + UtilIntToStr(j) + ")"; model->colNames.push_back(colName); colIndex++; } } UtilPrintFuncEnd(m_osLog, m_classTag, "createModelPartKP()", m_appParam.LogLevel, 2); return status; }
//############################################################################# void MibSHeuristic::lowerObjHeuristic() { /* optimize wrt to lower-level objective over current feasible lp feasible region */ MibSModel * model = MibSModel_; OsiSolverInterface * oSolver = model->getSolver(); //OsiSolverInterface * hSolver = new OsiCbcSolverInterface(); OsiSolverInterface* hSolver = new OsiSymSolverInterface(); double objSense(model->getLowerObjSense()); int lCols(model->getLowerDim()); int uCols(model->getUpperDim()); int * lColIndices = model->getLowerColInd(); int * uColIndices = model->getUpperColInd(); double * lObjCoeffs = model->getLowerObjCoeffs(); //int tCols(lCols + uCols); int tCols(oSolver->getNumCols()); //assert(tCols == oSolver->getNumCols()); hSolver->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)) hSolver->setInteger(j); } double * nObjCoeffs = new double[tCols]; int i(0), index(0); CoinZeroN(nObjCoeffs, tCols); for(i = 0; i < lCols; i++){ index = lColIndices[i]; nObjCoeffs[index] = lObjCoeffs[i]; } //MibS objective sense is the opposite of OSI's! hSolver->setObjSense(objSense); hSolver->setObjective(nObjCoeffs); //double cutoff(model->getCutoff()); double cutoff(model->getKnowledgeBroker()->getIncumbentValue()); if(model->getNumSolutions()){ CoinPackedVector objCon; //double rhs(cutoff * objSense); //double smlTol(1.0); double rhs(cutoff); for(i = 0; i < tCols; i++){ objCon.insert(i, oSolver->getObjCoefficients()[i] * oSolver->getObjSense()); } hSolver->addRow(objCon, - hSolver->getInfinity(), rhs); } if(0) hSolver->writeLp("lobjheurstic"); if(0){ dynamic_cast<OsiCbcSolverInterface *> (hSolver)->getModelPtr()->messageHandler()->setLogLevel(0); } else{ dynamic_cast<OsiSymSolverInterface *> (hSolver)->setSymParam("prep_level", -1); dynamic_cast<OsiSymSolverInterface *> (hSolver)->setSymParam("verbosity", -2); dynamic_cast<OsiSymSolverInterface *> (hSolver)->setSymParam("max_active_nodes", 1); } hSolver->branchAndBound(); if(hSolver->isProvenOptimal()){ double upperObjVal(0.0); /*****************NEW ******************/ MibSSolution *mibSol = NULL; OsiSolverInterface * lSolver = model->bS_->setUpModel(hSolver, true); if(0){ lSolver->writeLp("tmp"); } if(0){ 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); } lSolver->branchAndBound(); if (lSolver->isProvenOptimal()){ const double * sol = hSolver->getColSolution(); double objVal(lSolver->getObjValue() * objSense); double etol(etol_); double lowerObj = getLowerObj(sol, objSense); double * optUpperSolutionOrd = new double[uCols]; double * optLowerSolutionOrd = new double[lCols]; CoinZeroN(optUpperSolutionOrd, uCols); CoinZeroN(optLowerSolutionOrd, lCols); if(fabs(objVal - lowerObj) < etol){ /** Current solution is bilevel feasible **/ for(i = 0; i < tCols; i++) upperObjVal += hSolver->getColSolution()[i] * oSolver->getObjCoefficients()[i]; mibSol = new MibSSolution(hSolver->getNumCols(), hSolver->getColSolution(), upperObjVal, model); model->storeSolution(BlisSolutionTypeHeuristic, mibSol); mibSol = NULL; } else{ /* solution is not bilevel feasible, create one that is */ const double * uSol = hSolver->getColSolution(); const double * lSol = lSolver->getColSolution(); int numElements(hSolver->getNumCols()); int i(0), pos(0), index(0); double * lpSolution = new double[numElements]; double upperObj(0.0); //FIXME: problem is still here. indices may be wrong. //also is all this necessary, or can we just paste together uSol and lSol? //this may be an old comment for(i = 0; i < numElements; i++){ pos = model->bS_->binarySearch(0, lCols - 1, i, lColIndices); if(pos < 0){ pos = model->bS_->binarySearch(0, uCols - 1, i, uColIndices); if (pos >= 0){ optUpperSolutionOrd[pos] = uSol[i]; } } else{ optLowerSolutionOrd[pos] = lSol[pos]; } } for(i = 0; i < uCols; i++){ index = uColIndices[i]; lpSolution[index] = optUpperSolutionOrd[i]; upperObj += optUpperSolutionOrd[i] * oSolver->getObjCoefficients()[index]; } for(i = 0; i < lCols; i++){ index = lColIndices[i]; lpSolution[index] = optLowerSolutionOrd[i]; upperObj += optLowerSolutionOrd[i] * oSolver->getObjCoefficients()[index]; } if(model->checkUpperFeasibility(lpSolution)){ mibSol = new MibSSolution(hSolver->getNumCols(), lpSolution, upperObj * oSolver->getObjSense(), model); model->storeSolution(BlisSolutionTypeHeuristic, mibSol); mibSol = NULL; } delete [] lpSolution; } } delete lSolver; } delete hSolver; }
LPSolver::Status LPSolver::optimize( OptimizationGoal goal, // goal of optimization (minimize or maximize) Array<double> &obj, // objective function vector Array<int> &matrixBegin, // matrixBegin[i] = begin of column i Array<int> &matrixCount, // matrixCount[i] = number of nonzeroes in column i Array<int> &matrixIndex, // matrixIndex[n] = index of matrixValue[n] in its column Array<double> &matrixValue, // matrixValue[n] = non-zero value in matrix Array<double> &rightHandSide, // right-hand side of LP constraints Array<char> &equationSense, // 'E' == 'G' >= 'L' <= Array<double> &lowerBound, // lower bound of x[i] Array<double> &upperBound, // upper bound of x[i] double &optimum, // optimum value of objective function (if result is lpOptimal) Array<double> &x // x-vector of optimal solution (if result is lpOptimal) ) { if(osi->getNumCols()>0) { // get a fresh one if necessary delete osi; osi = CoinManager::createCorrectOsiSolverInterface(); } const int numRows = rightHandSide.size(); const int numCols = obj.size(); #ifdef OGDF_DEBUG const int numNonzeroes = matrixIndex.size(); #endif // assert correctness of array boundaries OGDF_ASSERT(obj .low() == 0 && obj .size() == numCols); OGDF_ASSERT(matrixBegin .low() == 0 && matrixBegin .size() == numCols); OGDF_ASSERT(matrixCount .low() == 0 && matrixCount .size() == numCols); OGDF_ASSERT(matrixIndex .low() == 0 && matrixIndex .size() == numNonzeroes); OGDF_ASSERT(matrixValue .low() == 0 && matrixValue .size() == numNonzeroes); OGDF_ASSERT(rightHandSide.low() == 0 && rightHandSide.size() == numRows); OGDF_ASSERT(equationSense.low() == 0 && equationSense.size() == numRows); OGDF_ASSERT(lowerBound .low() == 0 && lowerBound .size() == numCols); OGDF_ASSERT(upperBound .low() == 0 && upperBound .size() == numCols); OGDF_ASSERT(x .low() == 0 && x .size() == numCols); osi->setObjSense(goal==lpMinimize ? 1 : -1); int i; CoinPackedVector zero; for(i = 0; i < numRows; ++i) { osi->addRow(zero,equationSense[i],rightHandSide[i],0); } for(int colNo = 0; colNo < numCols; ++colNo) { CoinPackedVector cpv; for(i = matrixBegin[colNo]; i<matrixBegin[colNo]+matrixCount[colNo]; ++i) { cpv.insert(matrixIndex[i],matrixValue[i]); } osi->addCol(cpv,lowerBound[colNo],upperBound[colNo],obj[colNo]); } osi->initialSolve(); Status status; if(osi->isProvenOptimal()) { optimum = osi->getObjValue(); const double* sol = osi->getColSolution(); for(i = numCols; i-->0;) x[i]=sol[i]; status = lpOptimal; OGDF_ASSERT_IF(dlExtendedChecking, checkFeasibility(matrixBegin,matrixCount,matrixIndex,matrixValue, rightHandSide,equationSense,lowerBound,upperBound,x)); } else if(osi->isProvenPrimalInfeasible()) status = lpInfeasible; else if(osi->isProvenDualInfeasible()) status = lpUnbounded; else OGDF_THROW_PARAM(AlgorithmFailureException,afcNoSolutionFound); return status; }
//===========================================================================// int ATM_DecompApp::createConZtoX(DecompConstraintSet * model, const int atmIndex){ //--- //--- for a in A, t in T: //--- z[a,t] = x1[a,t] * x2[a] //--- <==> //--- OLD: //--- for a in A: //--- sum{t in T} x1[a,t] <= 1 (where, T = 1..n) //--- for a in A, t in T: //--- z[a,t] >= 0 <= 1, //--- z[a,t] <= x1[a,t], //--- z[a,t] <= x2[a], //--- z[a,t] >= x1[a,t] + x2[a] - 1. //--- NEW: //--- for a in A: //--- sum{t in T} x1[a,t] = 1 (where, T = 0..n) //--- sum{t in T} z[a,t] = x2[a] //--- for a in A, t in T: //--- z[a,t] >= 0 <= 1, //--- z[a,t] <= x1[a,t]. //--- int t; int nRows = 0; const int nSteps = m_appParam.NumSteps; if(m_appParam.UseTightModel){ for(t = 0; t <= nSteps; t++){ CoinPackedVector row; string strAT = "(a_" + m_instance.getAtmName(atmIndex) + ",t_" + UtilIntToStr(t) + ")"; string rowName = "ztox1" + strAT; row.insert(colIndex_z (atmIndex,t), 1.0); row.insert(colIndex_x1(atmIndex,t), -1.0); model->appendRow(row, -DecompInf, 0.0, rowName); nRows++; } CoinPackedVector row2; string rowName2 = "ztox2(a_" + m_instance.getAtmName(atmIndex) + ")"; row2.insert(colIndex_x2(atmIndex), -1.0); for(t = 0; t <= nSteps; t++){ row2.insert(colIndex_z (atmIndex,t), 1.0); } model->appendRow(row2, 0.0, 0.0, rowName2); nRows++; } else{ for(t = 0; t < nSteps; t++){ CoinPackedVector row1, row2, row3; string strAT = "(a_" + m_instance.getAtmName(atmIndex) + ",t_" + UtilIntToStr(t+1) + ")"; string rowName1 = "ztox1" + strAT; string rowName2 = "ztox2" + strAT; string rowName3 = "ztox3" + strAT; row1.insert(colIndex_z (atmIndex,t), 1.0); row1.insert(colIndex_x1(atmIndex,t), -1.0); model->appendRow(row1, -DecompInf, 0.0, rowName1); row2.insert(colIndex_z (atmIndex,t), 1.0); row2.insert(colIndex_x2(atmIndex) , -1.0); model->appendRow(row2, -DecompInf, 0.0, rowName2); row3.insert(colIndex_z (atmIndex,t), 1.0); row3.insert(colIndex_x1(atmIndex,t), -1.0); row3.insert(colIndex_x2(atmIndex) , -1.0); model->appendRow(row3, -1.0, DecompInf, rowName3); nRows+=3; } } return nRows; }
//===========================================================================// void MCF_DecompApp::createModelRelax(DecompConstraintSet* model, int commId) { //--- //--- SUBPROBLEM (A'): (one block for each k in K) //--- sum{(j,i) in A} x[k,i,j] - //--- sum{(i,j) in A} x[k,i,j] = d[i,k], for all i in N //--- x[k,i,j] integer >= l[i,j] <= u[i,j], for all (i,j) in A //--- For k=(s,t) in K, //--- d[i,k] = -d[k] if i=s //--- = d[k] if i=t //--- = 0, otherwise //--- int a, i, head, tail, colIndex, source, sink; int numCommodities = m_instance.m_numCommodities; int numArcs = m_instance.m_numArcs; int numNodes = m_instance.m_numNodes; int numCols = numCommodities * numArcs; int numRows = numNodes; MCF_Instance::arc* arcs = m_instance.m_arcs; MCF_Instance::commodity* commodities = m_instance.m_commodities; UtilPrintFuncBegin(m_osLog, m_classTag, "createModelRelax()", m_appParam.LogLevel, 2); //--- //--- create space for the model matrix (row-majored) //--- model->M = new CoinPackedMatrix(false, 0.0, 0.0); if (!model->M) { throw UtilExceptionMemory("createModelCore", "MCF_DecompApp"); } model->M->setDimensions(0, numCols); model->reserve(numRows, numCols); //--- //--- get this commodity's source and sink node //--- source = commodities[commId].source; sink = commodities[commId].sink; //--- //--- create the rows //--- NOTE: this is somewhat inefficient (but simple) //--- for (i = 0; i < numNodes; i++) { CoinPackedVector row; for (a = 0; a < numArcs; a++) { tail = arcs[a].tail; head = arcs[a].head; if (head == i) { colIndex = commId * numArcs + a; row.insert(colIndex, 1.0); } else if (tail == i) { colIndex = commId * numArcs + a; row.insert(colIndex, -1.0); } } if (i == source) model->appendRow(row, -commodities[commId].demand, -commodities[commId].demand); else if (i == sink) model->appendRow(row, commodities[commId].demand, commodities[commId].demand); else { model->appendRow(row, 0.0, 0.0); } string rowName = "flow(" + UtilIntToStr(commId) + "_" + UtilIntToStr(i) + "_" + UtilIntToStr(source) + "," + UtilIntToStr(sink) + ")"; model->rowNames.push_back(rowName); } //--- //--- create a list of the "active" columns (those related //--- to this commmodity) all other columns are fixed to 0 //--- UtilFillN(model->colLB, numCols, 0.0); UtilFillN(model->colUB, numCols, 0.0); colIndex = commId * numArcs; for (a = 0; a < numArcs; a++) { double arcLB = arcs[a].lb; double arcUB = arcs[a].ub; model->colLB[colIndex] = arcLB; model->colUB[colIndex] = arcUB; model->activeColumns.push_back(colIndex); colIndex++; } //--- //--- set the indices of the integer variables of model //--- UtilIotaN(model->integerVars, numCols, 0); UtilPrintFuncEnd(m_osLog, m_classTag, "createModelRelax()", m_appParam.LogLevel, 2); }