Exemple #1
0
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;
}
Exemple #2
0
//===========================================================================//
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;
      }
   }
}
Exemple #3
0
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;
}
Exemple #4
0
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);
}
Exemple #6
0
/**
 * 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;
}
Exemple #7
0
/**
 * 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;
}
Exemple #8
0
//===========================================================================//
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);
}
Exemple #9
0
/**
 * 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);
}
Exemple #10
0
// --------------------------------------------------------------------- //
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);
}
Exemple #11
0
/**
 * 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;
}
Exemple #12
0
/**
 * 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);
}
Exemple #13
0
//===========================================================================//
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;
}
Exemple #14
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;
   }
}