Example #1
0
//===========================================================================//
void ATM_DecompApp::createModels(){

   //---
   //--- This function does the work to create the different models 
   //---  that will be used. This memory is owned by the user. It will
   //---  be passed to the application interface and used by the algorithms.
   //---
   UtilPrintFuncBegin(m_osLog, m_classTag,
		      "APPcreateModel()", m_appParam.LogLevel, 2);
   
   //---
   //--- The original problem is in the form of a MINLP:
   //---    min  sum{a in A, d in D} | f[a,d] | 
   //---    s.t.
   //---    for a in A, d in D:
   //---       f[a,d] =  
   //---         a[a,d] x1[a]       +
   //---         b[a,d] x2[a]       +     
   //---         c[a,d] x1[a] x2[a] + 
   //---         d[a,d] x3[a]       +
   //---         e[a,d]
   //---    for d in D:
   //---       sum{a in A} f[a,d]      <= B[d]
   //---    for a in A:
   //---      |{d in D : f[a,d] < 0} | <= K[a] (notice strict ineq)
   //---    for a in A, d in D:
   //---      f[a,d] free
   //---    for a in A:
   //---      x1[a], x2[a] in [0,1], x3[a] >= 0
   //---

   //---
   //--- Discretization of continuous variable.
   //---      n     = number of steps
   //---      T     = {1, ..., n}
   //---      sum{t in T} (t/n) * x1[a,t]  = x1[a], for a in A
   //---      sum{t in T}         x1[a,t] <= 1    , for a in A
   //---   so, if n=10, x1[a] in {0,0.1,0.2,...,1.0}.
   //---

   //---
   //--- Linearization of product of a binary and a continuous.
   //---  For a in A, t in T:
   //---     z[a,t] = x1[a,t] * x2[a] 
   //---         <==>
   //---     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.
   //---

   //---
   //--- Linearization of the absolute value.
   //---  For a in A, d in D: 
   //---     f+[a,d], f-[a,d] >= 0
   //---     f[a,d] = f+[a,d] - f-[a,d]
   //---    |f[a,d]|= f+[a,d] + f-[a,d]
   //--- 

   //---
   //--- To model the count constraints.
   //---  For a in A:
   //---    |{d in D : f[a,d]            < 0}| <= K[a]
   //---      <==>
   //---    |{d in D : f+[a,d] - f-[a,d] < 0}| <= K[a]
   //---
   //---  At optimality, if f[a,d] != 0, then either
   //---    f+[a,d] > 0 and f-[a,d] = 0, or
   //---    f+[a,d] = 0 and f-[a,d] > 0.
   //---  So, to count the cases when f[a,d] < 0, we can restrict
   //---  attention to the cases where f-[a,d] > 0.
   //---
   //---  With some application specific stuff, 
   //---      we know that f-[a,d] <= w[a,d].
   //---
   //---  So, to count the number of cases we can use the following:
   //---      f-[a,d] >  0 ==> v[a,d] = 1
   //---      f-[a,d] <= 0 <== v[a,d] = 0
   //---        <==>
   //---      f-[a,d] <= w[a,d] * v[a,d]
   //---
   //---  and, then
   //---    |{d in D : f+[a,d] - f-[a,d] <  0}| <= K[a]
   //---        <==>
   //---    sum{d in D} v[a,d]                  <= K[a]
   //---

   //---
   //--- (Approximate) MILP Reformulation
   //---
   //---    min  sum{a in A, d in D} f+[a,d] + f-[a,d] 
   //---    s.t.
   //---    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 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.
   //---    for d in D:
   //---       sum{a in A} (f+[a,d] - f-[a,d]) <= B[d]
   //---    for a in A:
   //---       sum{d in D} v[a,d]              <= K[a]
   //---    for a in A, d in D:
   //---       f+[a,d], f-[a,d] >= 0
   //---                f-[a,d] <= w[a,d]
   //---       v[a,d] in {0,1}
   //---    for a in A:
   //---       x2[a], x3[a] in [0,1]
   //---    for a in A, t in T
   //---       x1[a,t] in {0,1}, z[a,t] in [0,1]
   //---

   //---
   //--- UPDATE (April 2010). 
   //---
   //--- A tighter formulation of the 
   //---   linearization of product of a binary and a continuous 
   //---   is possible due to the constraint: sum{t in T}  x1[a,t] <= 1
   //---
   //---  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].
   //---


   //---
   //--- Columns
   //---   x1[a,t] (binary)
   //---   z [a,t]
   //---   f+[a,d] 
   //---   f-[a,d]
   //---   x2[a]
   //---   x3[a]
   //----  v[a,d] (binary)
   //---
   int i, a;
   int nAtms   = m_instance.getNAtms();
   int numCols = numCoreCols();

   //---
   //--- Construct the objective function.
   //---    Coefficients of f+ and f- are 1.0, the rest are 0.
   //---
   m_objective = new double[numCols];
   if(!m_objective)
      throw UtilExceptionMemory("createModels", "MMKP_DecompApp");
   UtilFillN(m_objective, numCols, 0.0);
   for(i = getColOffset_fp(); i < getColOffset_x2(); i++)
      m_objective[i] = 1.0;
   setModelObjective(m_objective, numCols);
   
   
   //---
   //--- A'' (core):
   //---    for d in D:
   //---       sum{a in A} (f+[a,d] - f-[a,d]) <= B[d]
   //---    for a in A: <--- option ( core or relax )
   //---       sum{d in D} v[a,d] <= K[a]
   //---
   //--- A'[a] for a in A (independent blocks)
   //---    for 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]
   //---    sum{t in T}  x1[a,t] <= 1
   //---    for t in T:
   //---       z[a,t] <= x1[a,t],            
   //---       z[a,t] <= x2[a],              
   //---       z[a,t] >= x1[a,t] + x2[a] - 1.
   //---    sum{d in D} v[a,d] <= K[a] <--- option ( core or relax )
   //---
   if(m_appParam.ModelNameCore == "BUDGET"){
      DecompConstraintSet * modelCore = createModelCore1(false);
      m_models.push_back(modelCore);
      setModelCore(modelCore, "BUDGET");
   }
   if(m_appParam.ModelNameCore == "BUDGET_COUNT"){
      DecompConstraintSet * modelCore = createModelCore1();
      m_models.push_back(modelCore);
      setModelCore(modelCore, "BUDGET_COUNT");
   }   
   if(m_appParam.ModelNameRelax == "CASH"){
      for(a = 0; a < nAtms; a++){
	 DecompConstraintSet * modelRelax = createModelRelax1(a, false);
         m_models.push_back(modelRelax);
         setModelRelax(modelRelax, "CASH" + UtilIntToStr(a), a);
      }
   }
   if(m_appParam.ModelNameRelax == "CASH_COUNT"){
      for(a = 0; a < nAtms; a++){
	 DecompConstraintSet * modelRelax = createModelRelax1(a);
         m_models.push_back(modelRelax);
         setModelRelax(modelRelax, "CASH_COUNT" + UtilIntToStr(a), a);
      }
   }
   if(m_appParam.ModelNameRelaxNest == "CASH_COUNT"){
      for(a = 0; a < nAtms; a++){
	 DecompConstraintSet * modelRelax = createModelRelax1(a);
         m_models.push_back(modelRelax);
         setModelRelaxNest(modelRelax, "CASH_COUNT" + UtilIntToStr(a), a);
      }
   }


   //TODO: solve this A' with gap as relaxNest - but
   //  we are doing blocks - so find a column then break it out
   //  tell framework to do that? or do as user? show how we can 
   //  get stuff back from framework to setup and solve... 
   /*{
      //---
      //--- Version MODEL_MASTER_COUNT
      //---    is relaxation too hard?
      //---
      //--- A'' (core):
      //---    for a in A:
      //---       sum{d in D} v[a,d] <= K[a]
      //---
      //--- A' (relax):
      //---    for d in D:
      //---       sum{a in A} (f+[a,d] - f-[a,d]) <= B[d]
      //---    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.      
      //---    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]
      //---
     vector< DecompConstraintSet* > modelRelaxV;   
     DecompConstraintSet * modelCoreCount  = createModelCoreCount();
     DecompConstraintSet * modelRelaxCount = createModelRelaxCount();
     modelRelaxV.push_back(modelRelaxCount);   
     modelCore.insert (make_pair(MODEL_COUNT, modelCoreCount));
     modelRelax.insert(make_pair(MODEL_COUNT, modelRelaxV));
     }*/
   
   UtilPrintFuncEnd(m_osLog, m_classTag,
		    "APPcreateModel()", m_appParam.LogLevel, 2);
}
Example #2
0
// --------------------------------------------------------------------- //
int GAP_DecompApp::createModels()
{
   //---
   //--- This function does the work to create the different models
   //---  that will be used. This memory is owned by the user. It will
   //---  be passed to the application interface and used by the algorithms.
   //---
   UtilPrintFuncBegin(m_osLog, m_classTag,
                      "createModels()", m_appParam.LogLevel, 2);
   //---
   //--- Generalized Assignment Problem (GAP)
   //---   m is number of machines (index i)
   //---   n is number of tasks    (index j)
   //---
   //--- min  sum{i in 1..m, j in 1..n} p[i,j] x[i,j]
   //--- s.t. sum{           j in 1..n} w[i,j] x[i,j] <= b[i], i in 1..m
   //---      sum{i in 1..m           }        x[i,j]  = 1   , j in 1..n
   //---      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]
   //---  x   x   x     = 1 [j=1]
   //---   x   x   x    = 1 [j=2]
   //---    x   x   x   = 1 [j=3]
   //---     x   x   x  = 1 [j=4]
   //---
   //---
   //--- Get information about this problem instance.
   //--
   int          i;
   string       modelName;
   int          status     = GAPStatusOk;
   int          nTasks     = m_instance.getNTasks();    //n
   int          nMachines  = m_instance.getNMachines(); //m
   const int*   profit     = m_instance.getProfit();
   int          nCols      = nTasks * nMachines;
   //---
   //--- Construct the objective function (the original problem is
   //---  a maximization, so we flip the sign to make it minimization).
   //---
   m_objective = new double[nCols];
   assert(m_objective);

   if (!m_objective) {
      return GAPStatusOutOfMemory;
   }

   for (i = 0; i < nCols; i++) {
      m_objective[i] = profit[i];
   }

   //---
   //--- A'[i] for i=1..m: m independent knapsacks
   //---  sum{j in 1..n}  w[i,j] x[i,j] <= b[i]
   //---  x[i,j] in {0,1}, i in 1..m, j in 1..n
   //---
   //--- A'':
   //---  sum{i in 1..m} x[i,j] = 1, j in 1..n
   //---
   //--- Example structure: m=3, n=4
   //--- A'[i=1]:
   //---  xxxx         <= b[i=1]
   //--- A'[i=2]:
   //---      xxxx     <= b[i=2]
   //--- A'[i=3]:
   //---          xxxx <= b[i=3]
   //---
   //--- A'':
   //---  x   x   x     = 1 [j=1]
   //---   x   x   x    = 1 [j=2]
   //---    x   x   x   = 1 [j=3]
   //---     x   x   x  = 1 [j=4]
   //---
   setModelObjective(m_objective, nCols);
   DecompConstraintSet* modelCore = new DecompConstraintSet();
   status = createModelPartAP(modelCore);

   if (status) {
      return status;
   }

   setModelCore(modelCore, "AP");
   m_models.push_back(modelCore);

   for (i = 0; i < nMachines; i++) {
      DecompConstraintSet* modelRelax = new DecompConstraintSet();
      status = createModelPartKP(modelRelax, i);
      modelName = "KP" + UtilIntToStr(i);
      setModelRelax(modelRelax, modelName, i);
      m_models.push_back(modelRelax);
   }

   UtilPrintFuncEnd(m_osLog, m_classTag,
                    "createModels()", m_appParam.LogLevel, 2);
   return status;
}
Example #3
0
//===========================================================================//
void OSDipApp::createModels() {

	UtilPrintFuncBegin(m_osLog, m_classTag, "createModels()",
			m_appParam.LogLevel, 2);
	int i;
	int j;
	const int nCols = m_osInterface.getVariableNumber();
	const int nRows = m_osInterface.getConstraintNumber();
	
	try{

		//First the define the objective function over the entire variable space
		//Create the memory for the objective  function
		m_objective = new double[nCols];
		for (i = 0; i < nCols; i++) {
			m_objective[i] = m_osInterface.getObjectiveFunctionCoeff()[i];
			//std::cout << "obj coeff = " << m_objective[i] << std::endl;
		}
		setModelObjective( m_objective);
	
		//---
		//--- Construct the core matrix.
		//---
		int nRowsRelax, nRowsCore;
		nRowsRelax = 0;
		nRowsCore = 0;
  
	

		std::vector<OtherConstraintOption*> otherConstraintOptions;
		std::vector<OtherConstraintOption*>::iterator vit;
		
		

		//
		// Now construct the block matrices
		//
		int *rowsRelax;
		int whichBlock;
		DecompConstraintSet *modelRelax = NULL;

		std::set<int> blockVars; //variables indexes in the specific block
		std::set<int> blockVarsAll; //all variable indexes that appear in a block
		std::set<int> blockConAll; //all constraint indexes that appear in a block
		std::set<int>::iterator sit;
		CoinPackedVector *row;
		int *rowVars;
		int rowSize;
		if (m_osInterface.m_osoption != NULL
				&& m_osInterface.m_osoption->getNumberOfOtherConstraintOptions()
						> 0) {
	
			otherConstraintOptions
					= m_osInterface.m_osoption->getOtherConstraintOptions("Dip");
			
			//iterate over the vector of contraint options
			for (vit = otherConstraintOptions.begin(); vit
					!= otherConstraintOptions.end(); vit++) {
	
				// see if we have a Core Constraint Set
	
				if( ( (*vit)->name.compare("constraintSet") == 0)
						&& ( (*vit)->type.compare("Block") == 0)) {
					
					
					//get the block number
	
					//ch = new char[(*vit)->value.size() + 1];
					//ch[(*vit)->value.size()] = 0;
					//memcpy(ch, (*vit)->value.c_str(), (*vit)->value.size());
					//whichBlock = atoi(ch);
					//delete ch;
					whichBlock = atoi( (*vit)->value.c_str() );
			
	
					
					// first get the number of constraints in this block
					nRowsRelax = (*vit)->numberOfCon;
					rowsRelax = new int[nRowsRelax];
	
					//now get the variable indexes for just this block
					//first clear indexes from a previous block
					blockVars.clear();
					for (i = 0; i < nRowsRelax; i++) {
						rowsRelax[i] = (*vit)->con[i]->idx;
						
						if( (*vit)->con[i]->idx >= nRows) throw ErrorClass( "found an invalid row index in OSoL file");
						
						m_blocks[ whichBlock].push_back( rowsRelax[i] );
						
						//also add to the set of all rows
						
						if (blockConAll.find(  (*vit)->con[i]->idx ) == blockConAll.end()) {
							blockConAll.insert(  (*vit)->con[i]->idx );	
						}					
						
						//add the variables for this row to the set blockVars
						row = m_osInterface.getRow(rowsRelax[i]);
						rowSize = row->getNumElements();
						rowVars = row->getIndices();
	
						for (j = 0; j < rowSize; j++) {
							
							if (blockVars.find(rowVars[j]) == blockVars.end()) {
								blockVars.insert(rowVars[j]);	
							}	
							
						}
						
						delete row;
	
					}//end for or rows in this block
	
					modelRelax = new DecompConstraintSet();
					CoinAssertHint(modelRelax, "Error: Out of Memory");
	
	
	
					//create the active columns in this block
					for (sit = blockVars.begin(); sit != blockVars.end(); sit++) {
	
						modelRelax->activeColumns.push_back( *sit);
						
						   
						//insert into the all variables set also, but throw an execption
						//if already there -- same variable cannot be in more than one block
						
						if (blockVarsAll.find( *sit) == blockVarsAll.end()) {
							blockVarsAll.insert (*sit);	
						}else{
							
							throw ErrorClass("Variable " + UtilIntToStr(*sit) + " appears in more than one block");
							
						}
	
					}
	
					//
					//
	
					if (m_appParam.LogLevel >= 3) {
						(*m_osLog) << "Active Columns : " << whichBlock << endl;
						UtilPrintVector(modelRelax->activeColumns, m_osLog);

					}
					createModelPartSparse(modelRelax, nRowsRelax, rowsRelax);  //does not work for cutting planes
					//createModelPart(modelRelax, nRowsRelax, rowsRelax);
					//modelRelax->fixNonActiveColumns();
					m_modelR.insert(make_pair(whichBlock + 1, modelRelax));
					setModelRelax(modelRelax, "relax" + UtilIntToStr(whichBlock),
							whichBlock);
					
					if (m_appParam.LogLevel >= 3) {
						(*m_osLog) <<  std::endl <<  std::endl;
						(*m_osLog) << "HERE COMES THE DUPLICATION (WHEN createModelPartSparse USED)" << std::endl;
					}

					UtilPrintVector( modelRelax->activeColumns, m_osLog); 
					
									
	 			//free local memory
	 			UTIL_DELARR( rowsRelax);
	
	
	
				}
			}//end for over constraint options
		}// if on ospton null
	
		//get the core constraints -- constraints NOT in a block
		int *rowsCore = NULL;
		
		int kount = 0;
		nRowsCore = nRows - blockConAll.size();
		
		if(nRowsCore <= 0) throw ErrorClass("We need at least one coupling constraint");
	
		rowsCore = new int[nRowsCore];
			
		for(i = 0; i < nRows; i++){
			
			if (blockConAll.find( i ) == blockConAll.end() ){
				
				
				rowsCore[ kount++] =  i;
				
				
				
			}
		}

		if( kount  !=  nRowsCore) throw ErrorClass("There was an error counting coupling constraints");
		
	
		DecompConstraintSet * modelCore = new DecompConstraintSet();
		createModelPart(modelCore, nRowsCore, rowsCore);
	
		setModelCore(modelCore, "core");
		//---
		//--- save a pointer so we can delete it later
		//---
		m_modelC = modelCore;
		

		//get the master only variables
		//modelCore->masterOnlyCols.push_back(i);
		for (i = 0; i < nCols; i++) {
			if (blockVarsAll.find(i) == blockVarsAll.end()) {
				modelCore->masterOnlyCols.push_back(i);
				std::cout << "MASTER ONLY VARIABLE " << i << std::endl;
			}
		}
	
		//---
		//--- create an extra "empty" block for the master-only vars
		//---   since I don't know what OSI will do with empty problem
		//---   we will make column bounds explicity rows
		//---
		int nMasterOnlyCols = static_cast<int> (modelCore->masterOnlyCols.size());
		if (nMasterOnlyCols) {
			if (m_appParam.LogLevel >= 1)
				(*m_osLog) << "Create model part Master-Only." << endl;
	
			createModelMasterOnlys2(modelCore->masterOnlyCols);
	
		}
		
		
		UtilPrintFuncBegin(m_osLog, m_classTag, "printCurrentProblem()",
				m_appParam.LogLevel, 2);
				
				
	 //free local memory
	 UTIL_DELARR( rowsCore);
	
	
	}//end try
	
	catch(const ErrorClass& eclass){
		
		throw ErrorClass( eclass.errormsg);
		
	} 

}// end createModels()
Example #4
0
//===========================================================================//
void MCF_DecompApp::createModels()
{
   //---
   //--- This function does the work to create the different models
   //---  that will be used. This memory is owned by the user. It will
   //---  be passed to the application interface and used by the algorithms.
   //---
   UtilPrintFuncBegin(m_osLog, m_classTag,
                      "createModels()", m_appParam.LogLevel, 2);
   //---
   //--- (Integer) Multi-Commodity Flow Problem (MCF).
   //---
   //--- We are given:
   //---    (1) a directed graph G=(N,A),
   //---    (2) a set of commodities K, where each commodity is
   //---         a source-sink pair.
   //---
   //--- min  sum{k in K} sum{(i,j) in A} w[i,j] x[k,i,j]
   //--- s.t. 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, k in K
   //---      sum{k in K} x[k,i,j] >= l[i,j],       for all (i,j) in A
   //---      sum{k in K} x[k,i,j] <= u[i,j],       for all (i,j) in A
   //---      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
   //---
   //--- NOTE: to make sure the problem is always feasible, dummy arcs
   //---   have been added between all source-sink commodity pairs and have
   //---   been given a 'big' weight.
   //---
   //---
   //--- The decomposition is formed as:
   //---
   //--- MASTER (A''):
   //---      sum{k in K} x[k,i,j] >= l[i,j],       for all (i,j) in A
   //---      sum{k in K} x[k,i,j] <= u[i,j],       for all (i,j) in A
   //---      x[k,i,j] integer >= l[i,j] <= u[i,j], for all (i,j) in A
   //---
   //--- 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
   //---
   //---
   //--- Get information about this problem instance.
   //---
   int   k, a, colIndex;
   int   numCommodities = m_instance.m_numCommodities;
   int   numArcs        = m_instance.m_numArcs;
   int   numCols        = numCommodities * numArcs;
   MCF_Instance::arc* arcs = m_instance.m_arcs;
   //---
   //--- Construct the objective function and set it
   //---    columns indexed as [k,a]= k*numArcs + a
   //---
   objective = new double[numCols];

   if (!objective) {
      throw UtilExceptionMemory("createModels", "MCF_DecompApp");
   }

   colIndex = 0;

   for (k = 0; k < numCommodities; k++)
      for (a = 0; a < numArcs; a++) {
         objective[colIndex++] = arcs[a].weight;
      }

   //---
   //--- set the objective
   //---
   setModelObjective(objective, numCols);
   //---
   //--- create the core/master model and set it
   //---
   modelCore = new DecompConstraintSet();
   createModelCore(modelCore);
   setModelCore(modelCore, "core");

   //---
   //--- create the relaxed/subproblem models and set them
   //---
   for (k = 0; k < numCommodities; k++) {
      modelRelax = new DecompConstraintSet();
      string                modelName  = "relax" + UtilIntToStr(k);

      if (m_appParam.UseSparse) {
         createModelRelaxSparse(modelRelax, k);
      } else {
         createModelRelax(modelRelax, k);
      }

      setModelRelax(modelRelax, modelName, k);
      m_models.push_back(modelRelax);
   }

   UtilPrintFuncEnd(m_osLog, m_classTag,
                    "createModels()", m_appParam.LogLevel, 2);
}
Example #5
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);
}
Example #6
0
//===========================================================================//
void SDPUC_DecompApp::createModels(){

   //---
   //--- This function does the work to create the different models 
   //---  that will be used. This memory is owned by the user. It will
   //---  be passed to the application interface and used by the algorithms.
   //---
   UtilPrintFuncBegin(m_osLog, m_classTag,
		      "createModels()", m_appParam.LogLevel, 2);

   //---
   //---  Switched Dispatch Problem with Unit Commitment (SDPUC).
   //---
   //--- We are given: 
   //---    (1) a directed graph G=(N,A),
   //---    (2) a set of time periods T, 
   //---
   //--- min  sum{(i,j) in A} f1[i,j] y1[i,j] 
   //---		  + sum{t in T} sum{(i,j) in A} f2[i,j] y2[i,j,t] + c[i,j,t] x[i,j,t]
   //--- s.t. sum{(j,i) in A} x[i,j,t] - 
   //---        sum{(i,j) in A} x[i,j,t] = d[i,t],  for all i in N, t in T
   //---      x[i,j,t] >= l[i,j,t] z[i,j,t],       for all (i,j) in A, t in T
   //---      x[i,j,t] <= u[i,j,t] z[i,j,t],       for all (i,j) in A, t in T
   //---	  r[i,j] x[i,j,t] - theta[j] + theta[i] <=  M (1 - z[i,j,t]) for all i,j,t
   //---	  r[i,j] x[i,j,t] - theta[j] + theta[i] >= -M (1 - z[i,j,t]) for all i,j,t
   //---	  z[i,j,t] <= y1[i,j]  for all (i,j) in A, t in T				  //arc-investment
   //---	  z[i,j,t] - z[i,j,t-1] <= y2[i,j,t]  for all (i,j) in A, t in T  //arc(unit) commitment
   //---	  y[i,j] binary for all (i,j) in A
   //---
   //--- NOTE: to make sure the problem is always feasible, 
   //----      demand may have to be modelled as arcs with large negative costs
   //---
   //---
   //--- The decomposition is formed as:
   //---
   //--- MASTER (A''):
   //---	  z[i,j,t] <= y1[i,j]  for all (i,j) in A, t in T				  //arc-investment
   //---	  z[i,j,t] - z[i,j,t-1] <= y2[i,j,t]  for all (i,j) in A, t in T  //arc(unit) commitment
   //---	  y[i,j] binary for all (i,j) in A
   //---
   //--- SUBPROBLEM (A'): (one block for each t in T)
   //---     sum{(j,i) in A} x[i,j,t] - 
   //---        sum{(i,j) in A} x[i,j,t] = d[i,t],  for all i in N
   //---      x[i,j,t] >= l[i,j,t] z[i,j,t],       for all (i,j) in A
   //---      x[i,j,t] <= u[i,j,t] z[i,j,t],       for all (i,j) in A
   //---	  r[i,j] x[i,j,t] - theta[j] + theta[i] <=  M (1 - z[i,j,t]) for all i,j
   //---	  r[i,j] x[i,j,t] - theta[j] + theta[i] >= -M (1 - z[i,j,t]) for all i,j

   //---

   //---
   //--- Get information about this problem instance.
   //---
   int   i, t, a, colIndex;
   int   numTimeperiods = m_instance.m_numTimeperiods;
   int   numArcs        = m_instance.m_numArcs;
   int	 numNodes		= m_instance.m_numNodes;
   int   numCols        = numArcs							//y1-vars
      + 3 * numTimeperiods * numArcs	//y2-, z-, and x-vars
      + numTimeperiods * numNodes;		//theta-vars
   SDPUC_Instance::arc * arcs = m_instance.m_arcs;
   SDPUC_Instance::timeseries * ts = m_instance.m_timeseries;
   cout << "\nnumCols=" << numCols << " numTimePeriods=" << numTimeperiods;
   cout << "numNodes=" << numNodes << " numArcs=" << numArcs << endl;

   //---
   //--- Construct the objective function and set it
   //---    y1-var columns indexed as [a]   = a  in [0 ; numArcs-1]
   //---	y2-var columns indexed as [a,t]  = a + numArcs in [numArcs ; numArcs * (1 + numTimeperiods) - 1]
   //---	z-var columns indexed as [a,t] = t*numArcs + a +  numArcs * (1 + numTimeperiods) 
   //---										in [numArcs*(1+numTimeperiods); numArcs*(1 + 2*numTimeperiods) - 1]
   //---	x-var columns indexed as [a,t] = t*numArcs + a + numArcs*(1 + 2*numTimeperiods) , 
   //---										in [numArcs*(1 + 2*numTimeperiods) ; numArcs*(1 + 3*numTimeperiods) - 1]
   //---	theta-var columns indexed as [i,t] = t*numNodes + i + numArcs*(1 + 3*numTimeperiods) , 
   //---										   in [numArcs*(1 + 3*numTimeperiods) ; numArcs*(1 + 3*numTimeperiods) + numNodes*numTimeperiods - 1]
   //--
   m_objective = new double[numCols];
   //initialise to 0
   for(i = 0; i < numCols; i++){
      m_objective[i] = 0;
   }
   if(!m_objective)
      throw UtilExceptionMemory("createModels", "MCF_DecompApp");
   colIndex = 0;
   for(a = 0; a < numArcs; a++) {
      m_objective[colIndex++] = arcs[a].fcost1;  //fixed arc investment cost 
   }
   for(t = 0; t < numTimeperiods; t++) {
      for(a = 0; a < numArcs; a++) {
	 m_objective[colIndex++] = arcs[a].fcost2;  //fixed arc "start-up" cost 
      }
   }
   colIndex = numArcs*(1 + 2*numTimeperiods);  //start-index for x-vars
   for(t = 0; t < numTimeperiods; t++) {
      for(a = 0; a < numArcs; a++) {
         m_objective[colIndex++] = arcs[a].mcost * ts[0].values[t] ;  //arc cost * probability (assume ts[0] indicate timeperiod probabilities)
      }
   }	 
   //---
   //--- set the objective 
   //---        
   setModelObjective(m_objective, numCols);
   /*cout << "obj = " ;
     for(i = 0; i < numCols; i++){
     cout << m_objective[i] << " ";
     }
     cout << endl;*/
   
   //---
   //--- create the core/master model and set it
   //---
   DecompConstraintSet * modelCore = new DecompConstraintSet();      
   createModelCore(modelCore);
   setModelCore(modelCore, "core");

   //---
   //--- create the relaxed/subproblem models and set them
   //---
   for(t = 0; t < numTimeperiods; t++){
      DecompConstraintSet * modelRelax = new DecompConstraintSet();
      string                modelName  = "relax" + UtilIntToStr(t);
      if(m_appParam.UseSparse)
         createModelRelaxSparse(modelRelax, t);
      else
         createModelRelax(modelRelax, t);
      
      setModelRelax(modelRelax, modelName, t);
   }

   //---
   //--- create an extra "empty" block for the master-only vars
   //---   since I don't know what OSI will do with empty problem
   //---   we will make column bounds explicity rows
   //---
   
   UtilPrintFuncEnd(m_osLog, m_classTag,
                    "createModels()", m_appParam.LogLevel, 2);
}