int DippyDecompApp::generateCuts(const double* x, DecompCutList& cutList) { if (!m_pyGenerateCuts) { return 0; } // PyObject *pSolutionList = pyTupleList_FromDoubleArray(x, m_colList); // MO (28/2/2012) - Don't need this anymore as solution is contained within node PyObject* pPackagedNode = pyTupleList_FromNode(getDecompAlgo(), STAT_FEASIBLE); PyObject* pCutList = PyObject_CallMethod(m_pProb, "generateCuts", "O", pPackagedNode); if (pCutList == NULL) { throw UtilException("Error calling method prob.generateCuts()", "generateCuts", "DippyDecompApp"); } // This should never happen, pyGenerateCuts should be set to false in dippy.py if (pCutList == Py_None) // method exists, but is not implemented, return 0 { return 0; } // generateCuts returns constraints, i.e., dictionary of (variable, value) pairs also with name, lb, ub const int len = PyObject_Length(pCutList); // loop through each cut // We can use these to construct a C++ DecompVar objects double lb, ub; PyObject *pLb, *pUb; string name; double value; for (int i = 0; i < len; i++) { PyObject* pRow = PySequence_GetItem(pCutList, i); pLb = PyObject_CallMethod(pRow, "getLb", NULL); if (pLb == NULL) { throw UtilException("Error calling method row.getLb()", "generateCuts", "DippyDecompApp"); } pUb = PyObject_CallMethod(pRow, "getUb", NULL); if (pUb == NULL) { throw UtilException("Error calling method row.getUb()", "generateCuts", "DippyDecompApp"); } lb = (pLb == Py_None) ? -m_infinity : PyFloat_AsDouble(pLb); ub = (pUb == Py_None) ? m_infinity : PyFloat_AsDouble(pUb); int* varInds = NULL; double* varVals = NULL; int numPairs = pyColDict_AsPackedArrays(pRow, m_colIndices, &varInds, &varVals); assert(numPairs == PyObject_Length(pRow)); // arrays are now owned by the Cut object DippyDecompCut* cut = new DippyDecompCut(lb, ub, numPairs, varInds, varVals); cutList.push_back(cut); } return len; }
//===========================================================================// void GAP_Instance::readBestKnown(string& fileName, string& instanceName) { ifstream is; string instance; double bestUpperBound; bool isProvenOptimal; int status = 0; status = UtilOpenFile(is, fileName); if (status) throw UtilException("Failed to best-known file", "readBestKnown", "GAP_Instance"); while (!is.eof()) { is >> instance >> bestUpperBound >> isProvenOptimal; instance = UtilStrTrim(instance); if (instance == instanceName) { if (isProvenOptimal) { m_bestKnownLB = bestUpperBound; } else { m_bestKnownLB = -COIN_DBL_MAX; } m_bestKnownUB = bestUpperBound; m_isProvenOptimal = isProvenOptimal; break; } } }
size_t toSize_t(const std::string& value) throw(UtilException) { size_t result; std::stringstream ss(value, std::ios_base::in); ss >> result; if (ss.fail()) { throw UtilException(); } return result; }
void Thread::start() { if(this->threadImpllData){ return; } this->threadImpllData = new ThreadImplData; this->running = true; if(pthread_create(&this->threadImpllData->thread, NULL, Thread::_threadSystem, this) != 0){ throw UtilException("Error creating thread!"); } }
//===========================================================================// void MILPBlock_DecompApp::initializeApp() { UtilPrintFuncBegin(m_osLog, m_classTag, "initializeApp()", m_appParam.LogLevel, 2); //--- //--- read MILPBlock instance (mps format) //--- string fileName; if (m_appParam.DataDir != "") { fileName = m_appParam.DataDir + UtilDirSlash() + m_param.Instance; } else { fileName = m_appParam.Instance; } m_mpsIO.messageHandler()->setLogLevel(m_param.LogLpLevel); int rstatus = m_mpsIO.readMps(fileName.c_str()); if(rstatus < 0){ cerr << "Error: Filename = " << fileName << " failed to open." << endl; throw UtilException("I/O Error.", "initalizeApp", "MILPBlock_DecompApp"); } if(m_appParam.LogLevel >= 2) (*m_osLog) << "Objective Offset = " << UtilDblToStr(m_mpsIO.objectiveOffset()) << endl; //--- //--- set best known lb/ub //--- double offset = m_mpsIO.objectiveOffset(); setBestKnownLB(m_appParam.BestKnownLB + offset); setBestKnownUB(m_appParam.BestKnownUB + offset); //--- //--- read block file //--- readBlockFile(); //--- //--- create models //--- createModels(); UtilPrintFuncEnd(m_osLog, m_classTag, "initializeApp()", m_appParam.LogLevel, 2); }
/** * APPheuristics callback * * Called by DIP, we interface with Python */ int DippyDecompApp::APPheuristics(const double* xhat, const double* origCost, vector<DecompSolution*>& xhatIPFeas) { if (!m_pyHeuristics) { return 0; } PyObject* pSolution = pyTupleList_FromDoubleArray(xhat, m_colList); PyObject* pObjective = pyTupleList_FromDoubleArray(origCost, m_colList); PyObject* pSolList = PyObject_CallMethod(m_pProb, "solveHeuristics", "OO", pSolution, pObjective); if (pSolList == NULL) { throw UtilException("Error calling method prob.solveHeuristics()", "APPheuristics", "DippyDecompApp"); } // This should never happen, pyHeuristics should be set to false in dippy.py if (pSolList == Py_None) // method exists, but is not implemented, return 0 { return 0; } // APPheuristics returns dictionary of (variable, value) pairs const int len = PyObject_Length(pSolList); // loop through each solution for (int i = 0; i < len; i++) { pSolution = PyList_GetItem(pSolList, i); int* varInds = NULL; double* varVals = NULL; int numPairs = pyColDict_AsPackedArrays(pSolution, m_colIndices, &varInds, &varVals); assert(numPairs == PyObject_Length(pSolution)); double* sol = new double[m_numCols]; UtilFillN(sol, m_numCols, 0.0); for (int j = 0; j < numPairs; j++) { sol[varInds[j]] = varVals[j]; } xhatIPFeas.push_back(new DecompSolution(m_numCols, sol, origCost)); delete [] sol; delete [] varInds; delete [] varVals; } return len; }
/** * generateInitVars callback * * Called by DIP, we interface with Python */ int DippyDecompApp::generateInitVars(DecompVarList& initVars) { if (!m_pyInitVars) { return 0; } PyObject* pVarList = PyObject_CallMethod(m_pProb, "generateInitVars", NULL); if (pVarList == NULL) { throw UtilException("Error calling method prob.generateInitVars()", "generateInitVars", "DippyDecompApp"); } if (pVarList == Py_None) // method exists, but is not implemented, return 0 { return 0; } int nVars = PyObject_Length(pVarList); // generateInitVars returns 2-tuples (index, (cost, dictionary of (variable, value) pairs)) // We can use these to construct a C++ DecompVar objects for (int i = 0; i < nVars; i++) { PyObject* pTuple = PyList_GetItem(pVarList, i); int whichBlock = m_relaxIndices[PyTuple_GetItem(pTuple, 0)]; PyObject* pVarTuple = PyTuple_GetItem(pTuple, 1); double cost = PyFloat_AsDouble(PyTuple_GetItem(pVarTuple, 0)); PyObject* pColDict = PyTuple_GetItem(pVarTuple, 1); int* varInds = NULL; double* varVals = NULL; DecompVarType varType; int numPairs = pyColDict_AsPackedArrays(pColDict, m_colIndices, &varInds, &varVals, varType); assert(numPairs == PyObject_Length(pColDict)); DecompVar* var = new DecompVar(numPairs, varInds, varVals, cost, varType); var->setBlockId(whichBlock); initVars.push_back(var); } return nVars; }
//===========================================================================// void SDPUC_DecompApp::initializeApp() { UtilPrintFuncBegin(m_osLog, m_classTag, "initializeApp()", m_appParam.LogLevel, 2); //--- //--- read problem instance //--- string instanceFile = m_appParam.DataDir + UtilDirSlash() + m_appParam.Instance; int rc = m_instance.readInstance(instanceFile, false); if(rc) throw UtilException("Error in readInstance", "initializeApp", "MCF_DecompApp"); //--- //--- create models //--- createModels(); UtilPrintFuncEnd(m_osLog, m_classTag, "initializeApp()", m_appParam.LogLevel, 2); }
/** * APPisUserFeasible callback * * Called by DIP, we interface with Python */ bool DippyDecompApp::APPisUserFeasible(const double* x, const int n_cols, const double tolZero) { assert(n_cols == m_modelCore.getModel()->getColNames().size()); PyObject* pSolutionList = pyTupleList_FromDoubleArray(x, m_colList); PyObject* pTolZero = PyFloat_FromDouble(tolZero); if (!m_pyIsUserFeasible) { return true; } PyObject* pResult = PyObject_CallMethod(m_pProb, "isUserFeasible", "Od", pSolutionList, pTolZero); if (pResult == NULL) { throw UtilException("Error calling method prob.isUserFeasible()", "APPisUserFeasible", "DippyDecompApp"); } // This should not happen as having isUserFeasible present but not returning a boolean is not good if (pResult == Py_None) { // method exists, but not implemented, return true return true; } return (bool)PyObject_IsTrue(pResult); }
// --------------------------------------------------------------------- // void MMKP_MCKnap::solveMCKnap(const double * redCost, const double * origCost, vector<int> & solInd, vector<double> & solEls, double & varRedCost, double & varOrigCost){ int i, j, colIndex; //--- //--- Pisinger's code (mcknap) solves a max problem. And, it assumes //--- all positive costs/profits and weights. //--- memcpy(m_costDbl, redCost, m_nCols * sizeof(double)); #ifdef MMKP_MCKNAP_DEBUG for(i = 0; i < m_nCols; i++){ pair<int,int> ij = getIndexInv(i); printf("\ncostDbl[%d: %d, %d]: %g", i, ij.first, ij.second, m_costDbl[i]); } #endif //--- //--- flip reduced costs (max c == min -c) //--- UtilNegateArr(m_nCols, m_costDbl); //--- //--- add a constant so that all vertex weights are positive, inc alpha //--- double offset = 0.0; double minrc = *min_element(m_costDbl, m_costDbl + m_nCols); #ifdef MMKP_MCKNAP_DEBUG printf("\nminrc = %g", minrc); #endif if(minrc <= 0){ offset = -minrc + 1; UtilAddOffsetArr(m_nCols, offset, m_costDbl); } //--- //--- now scale the double array to an integer array //--- //TODO: magic number - have to be careful of overflow... m_cscale = UtilScaleDblToIntArr(m_nCols, m_costDbl, m_cost, MCKP_EPSILON); #ifdef MMKP_MCKNAP_DEBUG double diff; printf("\noffset = %g", offset); printf("\nm_cscale = %d", m_cscale); printf("\nm_wscale = %d", m_wscale); printf("\ncapacity = %d", m_capacity); for(i = 0; i < m_nCols; i++){ pair<int,int> ij = getIndexInv(i); diff = fabs((m_costDbl[i]*m_cscale) - m_cost[i]); printf("\n[%d: %d, %d]: dbl-> %12.5f int-> %8d diff-> %12.5f", i, ij.first, ij.second, m_costDbl[i], m_cost[i], diff); assert( diff < 0.99 ); } #endif //--- //--- sanity check //--- if any cost value becomes negative that //--- denotes an overflow happened //--- TODO: not sure how to do this scaling safely and //--- accurately //--- for(i = 0; i < m_nCols; i++){ if(m_cost[i] < 0){ throw UtilException("negative cost value", "solveMCKnap", "MMKP_MCKnap"); } } //--- //--- setup the data structures for mcknap //--- itemset * setPtr = m_setset->fset; itemrec * recPtr = NULL; itemrec * recSolPtr = NULL; //THINK: reset - assume memory is still there m_setset->size = m_nGroupRows; setPtr = m_setset->fset; for(i = 0; i < m_setset->size; i++){ setPtr->size = m_nGroupCols; recPtr = setPtr->fset; setPtr->lset = setPtr->fset + setPtr->size - 1; setPtr++; } m_setset->lset = m_setset->fset + m_setset->size - 1; colIndex = 0; setPtr = m_setset->fset; for(i = 0; i < m_setset->size; i++){ recPtr = setPtr->fset; for(j = 0; j < setPtr->size; j++){ recPtr->i = i; recPtr->j = j; recPtr->psum = m_cost[colIndex]; recPtr->wsum = m_weight[colIndex]; #ifdef MMKP_MCKNAP_DEBUG printf("\ncolIndex: %d i: %d, j: %d, p: %d, w: %d", colIndex, i, j, recPtr->psum, recPtr->wsum); #endif recPtr++; colIndex++; } setPtr++; } itemrec * solRec = new itemrec[m_setset->size]; double minObj = 99999; // long minObj = 99999; int status = minmcknapSolve(m_capacity, m_setset, solRec, &minObj); solInd.reserve(m_nGroupRows); solEls.reserve(m_nGroupRows); UtilFillN<double>(solEls, m_nGroupRows, 1.0); varRedCost = 0.0; varOrigCost = 0.0; //--- //--- TODO: //--- this is painful to get optimal assignments //--- wrote Dr. Pisinger for help (7/4/07) //--- NOTE: optsol is NOT reentrant //--- //CoinAssert(optsol.size == 1); //TODO #ifdef MMKP_MCKNAP_DEBUG printf("\nstatus=%d minObj=%g\n", status, minObj); #endif switch(status){ case MCKNAP_RC_INF: assert(status != MCKNAP_RC_INF); break; case MCKNAP_RC_OK: { //--- //--- need to unravel: //--- s * ((-x) + offset) //--- double solObj = minObj / static_cast<double>(m_cscale); solObj -= (offset * m_setset->size); solObj = -solObj; #ifdef MMKP_MCKNAP_DEBUG printf("\nminObj = %g, solObj = %g", minObj, solObj); #endif int c, i, j, g; for(g = 0; g < m_setset->size; g++){ recSolPtr = &solRec[g]; i = recSolPtr->i;//was missing - STOP j = recSolPtr->j;//was missing c = getIndexIJ(i, j); solInd.push_back(c); varRedCost += redCost[c]; varOrigCost += origCost[c]; #ifdef MMKP_MCKNAP_DEBUG printf("\nc: %d = (%d,%d) redCost: %g cost: %d wt: %d", c, i, j, redCost[c], m_cost[c], m_weight[c]); #endif /*for(c = 0; c < m_nCols; c++){ //but could have more than one equal in p and w! //this is NOT the right way to get back optimal if((m_cost[c] == recSolPtr->psum) && (m_weight[c] == recSolPtr->wsum)){ //TODO: why should the user have to calc origCost? //framework should probably do that solInd.push_back(c); varRedCost += redCost[c]; varOrigCost += origCost[c]; #ifdef MMKP_MCKNAP_DEBUG pair<int,int> ij = getIndexInv(c); printf("\nc: %d = (%d,%d) redCost: %g cost: %d wt: %d", c, ij.first, ij.second, redCost[c], m_cost[c], m_weight[c]); #endif break; } }*/ } //UtilPrintVector<int>(solInd); break; } case MCKNAP_RC_TRIVIAL_MAXSUM: fflush(stdout); //maxwsum <= c, so just pick the max elements from each group solveTrivialMaxSum(redCost, origCost, solInd, varRedCost, varOrigCost); #ifdef MMKP_MCKNAP_DEBUG printf("trivial sum varRedCost=%g varOrigCost=%g\n", varRedCost, varOrigCost); #endif break; default: assert(0); } UTIL_DELARR(solRec); }
/** * solveRelaxed callback * * This is called by DIP. This function interfaces with Python to * call the user defined function if it's present * * We're expected to populate varList (basically a vector) and * return the status of the subproblem solver. */ DecompSolverStatus DippyDecompApp::solveRelaxed(const int whichBlock, const double* redCostX, const double convexDual, DecompVarList& varList) { if (!m_pySolveRelaxed) { return DecompSolStatNoSolution; } PyObject* pRelaxKey = PyList_GetItem(m_relaxedKeys, whichBlock); PyObject* pRedCostList = pyTupleList_FromDoubleArray(redCostX, m_colList); PyObject* pConvexDual = PyFloat_FromDouble(convexDual); // call solveRelaxed on DipProblem PyObject* pStatandVarList = PyObject_CallMethod(m_pProb, "solveRelaxed", "OOd", pRelaxKey, pRedCostList, pConvexDual); Py_DECREF(pRedCostList); Py_DECREF(pConvexDual); if ( (pStatandVarList == NULL) || (pStatandVarList == Py_None) ){ throw UtilException("Error calling method prob.solveRelaxed()", "solveRelaxed", "DippyDecompApp"); } // [status, varList] = relaxed_solver(...) PyObject * pStatus = PyTuple_GetItem(pStatandVarList, 0); int cStatus = PyInt_AsLong(pStatus); DecompSolverStatus status = (DecompSolverStatus)cStatus; PyObject * pVarList = PyTuple_GetItem(pStatandVarList, 1); int nVars = PyObject_Length(pVarList); // In the new design, we need to allow the possibility that the user will solve // the problem exactly, but not find any solutions with reduced costs zero // The below is is commented out and left in the source for posterity // tkr 11/11/15 //if (nVars == 0) { // throw UtilException("Empty variable list", "solveRelaxed", "DippyDecompApp"); //} // solveRelaxed returns 3-tuples (cost, reduced cost, dictionary of (variable, value) pairs) // We can use these to construct a C++ DecompVar objects double cost, rc; PyObject *pDict, *pKeys, *pCol; string name; double value; for (int j = 0; j < nVars; j++) { PyObject* pTuple = PySequence_GetItem(pVarList, j); cost = PyFloat_AsDouble(PyTuple_GetItem(pTuple, 0)); rc = PyFloat_AsDouble(PyTuple_GetItem(pTuple, 1)); pDict = PyTuple_GetItem(pTuple, 2); pKeys = PyDict_Keys(pDict); vector<int> varInds; vector<double> varVals; for (int n = 0; n < PyObject_Length(pDict); n++) { pCol = PyList_GetItem(pKeys, n); value = PyFloat_AsDouble(PyDict_GetItem(pDict, pCol)); varInds.push_back(m_colIndices[pCol]); varVals.push_back(value); } Py_DECREF(pKeys); Py_DECREF(pTuple); DecompVar* var = new DecompVar(varInds, varVals, rc, cost); var->setBlockId(whichBlock); varList.push_back(var); } Py_DECREF(pStatandVarList); return status; }
/** * Called to create the core and relaxation models */ void DippyDecompApp::createModels() { int i, len; string name; // create the core model DecompConstraintSet* modelCore = new DecompConstraintSet(); // gets the master problem model PyObject* pMasterAsTuple = PyObject_CallMethod(m_pProb, "getMasterAsTuple", NULL); if (pMasterAsTuple == NULL) { throw UtilException("Error calling method prob.getMasterAsTuple()", "createModels", "DippyDecompApp"); } PyObject* pObjective = PyTuple_GetItem(pMasterAsTuple, 0); PyObject* pRowList = PyTuple_GetItem(pMasterAsTuple, 1); PyObject* pColList = PyTuple_GetItem(pMasterAsTuple, 2); m_rowList = pRowList; Py_XINCREF(m_rowList); m_numCols = PyObject_Length(pColList); m_colList = pColList; Py_XINCREF(m_colList); int numRows = PyObject_Length(pRowList); PyObject* pRow, *pRowName, *pRowLb, *pRowUb; double lb, ub; for (int i = 0; i < numRows; i++) { pRow = PyList_GetItem(pRowList, i); pRowName = PyObject_CallMethod(pRow, "getName", NULL); if (pRowName == NULL) { throw UtilException("Error calling method row.getName()", "createModels", "DippyDecompApp"); } pRowLb = PyObject_CallMethod(pRow, "getLb", NULL); if (pRowLb == NULL) { throw UtilException("Error calling method row.getLb()", "createModels", "DippyDecompApp"); } pRowUb = PyObject_CallMethod(pRow, "getUb", NULL); if (pRowUb == NULL) { throw UtilException("Error calling method row.getUb()", "createModels", "DippyDecompApp"); } name = PyString_AsString(pRowName); if (pRowLb == Py_None) { lb = -m_infinity; } else { lb = PyFloat_AsDouble(pRowLb); } if (pRowUb == Py_None) { ub = m_infinity; } else { ub = PyFloat_AsDouble(pRowUb); } modelCore->rowNames.push_back(name); modelCore->rowLB.push_back(lb); modelCore->rowUB.push_back(ub); m_rowIndices[pRow] = i; // Don't need to increase reference count here as m_rowList // references pRow } PyObject* pCol, *pColLb, *pColUb, *pIsInt; for (int j = 0; j < m_numCols; j++) { pCol = PyList_GetItem(pColList, j); PyObject* pColName = PyObject_CallMethod(pCol, "getName", NULL); if (pColName == NULL) { throw UtilException("Error calling method col.getName()", "createModels", "DippyDecompApp"); } pColLb = PyObject_CallMethod(pCol, "getLb", NULL); if (pColLb == NULL) { throw UtilException("Error calling method col.getLb()", "createModels", "DippyDecompApp"); } pColUb = PyObject_CallMethod(pCol, "getUb", NULL); if (pColUb == NULL) { throw UtilException("Error calling method col.getUb()", "createModels", "DippyDecompApp"); } pIsInt = PyObject_CallMethod(pCol, "isInteger", NULL); if (pIsInt == NULL) { throw UtilException("Error calling method col.isInteger()", "createModels", "DippyDecompApp"); } name = PyString_AsString(pColName); if (pColLb == Py_None) { lb = -m_infinity; } else { lb = PyFloat_AsDouble(pColLb); } if (pColUb == Py_None) { ub = m_infinity; } else { ub = PyFloat_AsDouble(pColUb); } modelCore->colNames.push_back(name); modelCore->colLB.push_back(lb); modelCore->colUB.push_back(ub); if (PyObject_IsTrue(pIsInt)) { modelCore->integerVars.push_back(j); } m_colIndices[pCol] = j; // Don't need to increase reference count here // as m_rowList references pCol } // set objective coefficients double* obj = new double[m_numCols]; UtilFillN(obj, m_numCols, 0.0); PyObject* pObjKeys = PyDict_Keys(pObjective); PyObject* pCoeff; for (int j = 0; j < PyObject_Length(pObjKeys); j++) { pCol = PyList_GetItem(pObjKeys, j); pCoeff = PyDict_GetItem(pObjective, pCol); obj[m_colIndices[pCol]] = PyFloat_AsDouble(pCoeff); } setModelObjective(obj, m_numCols); // set constraint matrix modelCore->M = pyConstraints_AsPackedMatrix(pRowList, m_rowIndices, m_colIndices); modelCore->M->setDimensions(modelCore->rowLB.size(), modelCore->colLB.size()); // subproblems PyObject* pRelaxedDict = PyObject_CallMethod(m_pProb, "getRelaxsAsDict", NULL); if (pRelaxedDict == NULL) { throw UtilException("Error calling method prob.getRelaxsAsDict()", "createModels", "DippyDecompApp"); } int* masterOnly = new int[m_numCols]; if (!masterOnly) { throw UtilExceptionMemory("createModels", "DecompApp"); } UtilFillN(masterOnly, m_numCols, 1); int nRelaxed = 0; if (pRelaxedDict != Py_None) { nRelaxed = PyObject_Length(pRelaxedDict); } // we have a list of relaxations m_relaxedKeys = PyDict_Keys(pRelaxedDict); Py_XINCREF(m_relaxedKeys); PyObject* pKey, *pRelax; for (int p = 0; p < nRelaxed; p++) { DecompConstraintSet* modelRelax = new DecompConstraintSet(); // each relaxation is a LpProblem pKey = PyList_GetItem(m_relaxedKeys, p); pRelax = PyDict_GetItem(pRelaxedDict, pKey); m_relaxIndices[pKey] = p; // Don't need to increase reference count here //as m_relaxedKey references pKey PyObject* pRelaxAsTuple = PyObject_CallMethod(m_pProb, "getRelaxAsTuple", "O", pRelax); if (pRelaxAsTuple == NULL) { throw UtilException("Error calling method prob.getRelaxAsTuple()", "createModels", "DippyDecompApp"); } // row names pRowList = PyTuple_GetItem(pRelaxAsTuple, 0); pColList = PyTuple_GetItem(pRelaxAsTuple, 1); numRows = PyObject_Length(pRowList); map<PyObject*, int> relaxRowIndices; for (int i = 0; i < numRows; i++) { pRow = PyList_GetItem(pRowList, i); pRowName = PyObject_CallMethod(pRow, "getName", NULL); if (pRowName == NULL) { throw UtilException("Error calling method row.getName()", "createModels", "DippyDecompApp"); } pRowLb = PyObject_CallMethod(pRow, "getLb", NULL); if (pRowLb == NULL) { throw UtilException("Error calling method row.getLb()", "createModels", "DippyDecompApp"); } pRowUb = PyObject_CallMethod(pRow, "getUb", NULL); if (pRowUb == NULL) { throw UtilException("Error calling method row.getUb()", "createModels", "DippyDecompApp"); } name = PyString_AsString(pRowName); if (pRowLb == Py_None) { lb = -m_infinity; } else { lb = PyFloat_AsDouble(pRowLb); } if (pRowUb == Py_None) { ub = m_infinity; } else { ub = PyFloat_AsDouble(pRowUb); } modelRelax->rowNames.push_back(name); modelRelax->rowLB.push_back(lb); modelRelax->rowUB.push_back(ub); relaxRowIndices[pRow] = i; } // get the constraint matrix for this relaxation modelRelax->M = pyConstraints_AsPackedMatrix(pRowList, relaxRowIndices, m_colIndices); // set all cols at their lower bounds for (int j = 0; j < modelCore->colLB.size(); j++) { modelRelax->colLB.push_back(modelCore->colLB[j]); modelRelax->colUB.push_back(modelCore->colLB[j]); } // get active cols int cols = PyObject_Length(pColList); int index; for (int j = 0; j < cols; j++) { pCol = PyList_GetItem(pColList, j); index = m_colIndices[pCol]; if ( (index < 0) || (index >= m_colIndices.size()) ) { throw UtilException("Bad index for " + name, "createModels", "DippyDecompApp"); } modelRelax->colUB[index] = modelCore->colUB[index]; modelRelax->activeColumns.push_back(index); masterOnly[index] = 0; } modelRelax->M->setDimensions(modelRelax->rowLB.size(), modelRelax->colLB.size()); // copy integer vars (from master prob) for (int j = 0; j < modelCore->integerVars.size(); j++) { modelRelax->integerVars.push_back(modelCore->integerVars[j]); } setModelRelax(modelRelax, "BLOCK", p); } for (i = 0; i < m_numCols; i++) { if (masterOnly[i]){ modelCore->masterOnlyCols.push_back(i); } } printf("Num master-only cols: %d\n", modelCore->masterOnlyCols.size()); // set the core problem setModelCore(modelCore, "CORE"); UTIL_DELARR(masterOnly); }
//===========================================================================// int SDPUC_Instance::readInstance(string & fileName, bool addDummyArcs){ ifstream is; int status = UtilOpenFile(is, fileName.c_str()); if(status) throw UtilException("Failed to read instance", "readInstance", "MCF_Instance"); double sumweight = 0; bool size_read = true; int arcs_read = 0; int nodes_read = 0; int ts_read = 0; int nt = 0; char line[1000]; char name[1000]; while(is.good()) { is.getline(line, 1000); if (is.gcount() >= 999) { cerr << "ERROR: Input file is incorrect. " << "A line more than 1000 characters is found." << endl; return 1; } switch (line[0]) { case 'p': if (sscanf(line, "p%s%i%i%i%i%i", name, &m_numNodes, &m_numArcs, &m_numSwitchings, &m_numTimeseries, &m_numTimeperiods) != 6) { cerr << "ERROR: Input file is incorrect. (p line)" << endl; return 1; } m_problemName = name; m_arcs = new arc[m_numArcs + (addDummyArcs ? 0 : 0)]; if(!m_arcs) throw UtilExceptionMemory("readInstance", "MCF_DecompApp"); m_nodes = new node[m_numNodes]; if(!m_nodes) throw UtilExceptionMemory("readInstance", "MCF_DecompApp"); m_timeseries = new timeseries[m_numTimeseries]; if(!m_timeseries) throw UtilExceptionMemory("readInstance", "MCF_DecompApp"); break; case 'c': break; case '#': break; case 'n': if (sscanf(line, "n%i%lf%i", &m_nodes[nodes_read].id, &m_nodes[nodes_read].demand, &m_nodes[nodes_read].tsdemand) != 3) { cerr << "ERROR: Input file is incorrect. (n line)" << endl; return 1; } ++nodes_read; break; case 'a': if (sscanf(line, "a%i%i%lf%lf%lf%lf%lf%lf%i%i%i%i", &m_arcs[arcs_read].tail, &m_arcs[arcs_read].head, &m_arcs[arcs_read].lb, &m_arcs[arcs_read].ub, &m_arcs[arcs_read].weight, &m_arcs[arcs_read].mcost, &m_arcs[arcs_read].fcost1, &m_arcs[arcs_read].fcost2, &m_arcs[arcs_read].tscap, &m_arcs[arcs_read].tscost, &m_arcs[arcs_read].acline, &m_arcs[arcs_read].switchable ) != 12) { cerr << "Input file is incorrect. (a line)" << endl; return 1; } sumweight += fabs(m_arcs[arcs_read].mcost); ++arcs_read; break; case 't': //cout << "ts_read=" << ts_read ; //cout << " numTimeperiods=" << m_numTimeperiods << endl; m_timeseries[ts_read].values = new double[m_numTimeperiods]; /* if (sscanf(line, "t%i%lf%lf%lf%lf", &m_timeseries[ts_read].id, &m_timeseries[ts_read].values[0], &m_timeseries[ts_read].values[1], &m_timeseries[ts_read].values[2], &m_timeseries[ts_read].values[3] ) != 5) { cerr << "ERROR: Input file is incorrect. (t line) << " << line << endl; return 1; }*/ nt = 0; char * pch; //printf ("Splitting string \"%s\" into tokens:\n",line); pch = strtok (line,"\t"); //stripping the initial 't' //printf ("%s ",pch); pch = strtok (NULL, "\t"); //timeseries id m_timeseries[ts_read].id = atoi(pch); //printf ("%s\n",pch); while (pch != NULL && nt < m_numTimeperiods) { pch = strtok (NULL, "\t"); m_timeseries[ts_read].values[nt] = atof(pch); //printf ("%s\n",pch); nt++; } ++ts_read; break; default: if (sscanf(line+1, "%s", name) <= 0) { cerr << "Input file is incorrect. (non-recognizable line)" << endl; return 1; } break; } } if (!size_read || arcs_read != m_numArcs || nodes_read != m_numNodes || ts_read != m_numTimeseries ) { cerr << "Input file is incorrect." << " size_read=" << size_read << " arcs_read=" << arcs_read << " nodes_read=" << nodes_read << " ts_read=" << ts_read << endl; return 1; } /*if (addDummyArcs) { for (int i = 0; i < m_numCommodities; ++i) { m_arcs[m_numArcs].tail = m_commodities[i].source; m_arcs[m_numArcs].head = m_commodities[i].sink; m_arcs[m_numArcs].lb = 0; m_arcs[m_numArcs].ub = m_commodities[i].demand; m_arcs[m_numArcs].weight = sumweight+1; ++m_numArcs; } }*/ is.close(); return 0; }
/** * Perform branching * * This function should populate the (down|up)Branch(LB|UB) vectors with (indices, bound-value) pairs * which define the branch. */ bool DippyAlgoMixin::chooseBranchSet(DecompAlgo* algo, std::vector< std::pair<int, double> >& downBranchLB, std::vector< std::pair<int, double> >& downBranchUB, std::vector< std::pair<int, double> >& upBranchLB, std::vector< std::pair<int, double> >& upBranchUB) { bool ret_val; if (!m_utilParam->GetSetting("pyBranchMethod", true)) { return algo->DecompAlgo::chooseBranchSet(downBranchLB, downBranchUB, upBranchLB, upBranchUB); } DippyDecompApp* app = (DippyDecompApp*)algo->getDecompApp(); // copy the current solution into a Python list const double* xhat = algo->getXhat(); PyObject* pSolutionList = pyTupleList_FromDoubleArray(xhat, app->m_colList); // try to call chooseBranchSet on the DipProblem python object PyObject* pResult = PyObject_CallMethod(m_pProb, "chooseBranchSet", "O", pSolutionList); if (pResult == NULL) { //something's gone wrong with the function call, a Python exception has //been set throw UtilException("Error calling method prob.chooseBranchSet()", "chooseBranchSet", "DippyDecompAlgo"); } // need more error checking/assertion setting here if (pResult == Py_None) { // if chooseBranchSet returns None, do default branching for this algo ret_val = algo->DecompAlgo::chooseBranchSet(downBranchLB, downBranchUB, upBranchLB, upBranchUB); // Original comment: No branching set was returned. This shouldn't happen // tkr 11/11/15: Actually, it can happen if the solution is integral, but not feasible. // This happens sometimes when column generation is halted because of tailoff and // the solution to the relaxation is feasible. I'm leaving the commented code here for // posterity //assert(ret_val == true); //if (!ret_val){ // throw UtilException("No branch set found in prob.chooseBranchSet()", // "chooseBranchSet", "DippyDecompAlgo"); //} if (downBranchUB.size() > 0) { PyObject* downBranchVar, * upBranchVar; pDownLB = PyDict_New(); // Down branch LBs is an empty dictionary pDownUB = PyDict_New(); downBranchVar = PyList_GetItem(app->m_colList, downBranchUB[0].first); PyDict_SetItem(pDownUB, downBranchVar, PyInt_FromLong(static_cast<int>(round(downBranchUB[0].second)))); pUpLB = PyDict_New(); upBranchVar = PyList_GetItem(app->m_colList, upBranchLB[0].first); PyDict_SetItem(pUpLB, upBranchVar, PyInt_FromLong(static_cast<int>(round(upBranchLB[0].second)))); pUpUB = PyDict_New(); // Up branch UBs is an empty dictionary assert(downBranchVar == upBranchVar); }else{ //No branching set was returned. Zero out pointers to old branching //sets assert(ret_val == false); pDownLB = NULL; pDownUB = NULL; pUpLB = NULL; pUpUB = NULL; } return ret_val; } else { // or else, the function should have returned 4 lists of (name, value) tuples pDownLB = PyTuple_GetItem(pResult, 0); pDownUB = PyTuple_GetItem(pResult, 1); pUpLB = PyTuple_GetItem(pResult, 2); pUpUB = PyTuple_GetItem(pResult, 3); // copy the python dictionaries into the result vectors pyColDict_AsPairedVector(pDownLB, downBranchLB, app->m_colIndices); pyColDict_AsPairedVector(pDownUB, downBranchUB, app->m_colIndices); pyColDict_AsPairedVector(pUpLB, upBranchLB, app->m_colIndices); pyColDict_AsPairedVector(pUpUB, upBranchUB, app->m_colIndices); return true; } }