/** * 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; }
//===========================================================================// bool ATM_DecompApp::APPisUserFeasible(const double * x, const int nCols, const double tolZero){ //--- //--- sanity check - is this solution feasible? //--- since we provide a full matrix, DECOMP will also check //--- that the algebra gives a feasible point //--- UtilPrintFuncBegin(m_osLog, m_classTag, "APPisUserFeasible()", m_appParam.LogLevel, 2); double lhs, rhs, coeff; int a, d, t; int pairIndex = 0; bool isFeas = true; const int nSteps = m_appParam.NumSteps; const int nAtms = m_instance.getNAtms(); const vector<int> & pairsAD = m_instance.getPairsAD(); const double * K_a = m_instance.get_K_a(); const double * a_ad = m_instance.get_a_ad(); //dense storage const double * b_ad = m_instance.get_b_ad(); //dense storage const double * c_ad = m_instance.get_c_ad(); //dense storage const double * d_ad = m_instance.get_d_ad(); //dense storage const double * e_ad = m_instance.get_e_ad(); //dense storage double * count = new double[nAtms]; //--- //--- is the flow variable matching x,z variables //--- 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] //--- pair<int,int> adP; vector<int>::const_iterator vi; double actViol = 0.0; double relViol = 0.0; for(vi = pairsAD.begin(); vi != pairsAD.end(); vi++){ adP = m_instance.getIndexADInv(*vi); a = adP.first; lhs = x[getColOffset_fp() + pairIndex]; lhs -= x[getColOffset_fm() + pairIndex]; rhs = e_ad[*vi] + b_ad[*vi] * x[colIndex_x2(a)] + d_ad[*vi] * x[colIndex_x3(a)]; if(m_appParam.UseTightModel){ for(t = 0; t <= nSteps; t++){ coeff = (double)(t) / (double)nSteps; rhs += a_ad[*vi] * coeff * x[colIndex_x1(a,t)]; rhs += c_ad[*vi] * coeff * x[colIndex_z (a,t)]; } } else{ for(t = 0; t < nSteps; t++){ coeff = (double)(t+1) / (double)nSteps; rhs += a_ad[*vi] * coeff * x[colIndex_x1(a,t)]; rhs += c_ad[*vi] * coeff * x[colIndex_z (a,t)]; } } actViol = fabs(lhs-rhs); if(UtilIsZero(lhs,1.0e-3)) relViol = actViol; else relViol = actViol / std::fabs(lhs); if(relViol > 0.05){ printf("NOT FEASIBLE lhs=%12.10f, rhs=%12.10f\n", lhs, rhs); isFeas = false; } pairIndex++; } //--- //--- did the indicators work correctly? //--- f+[a,d] - f-[a,d] < 0 ==> v[a,d] = 1 //--- pairIndex = 0; for(vi = pairsAD.begin(); vi != pairsAD.end(); vi++){ adP = m_instance.getIndexADInv(*vi); a = adP.first; lhs = x[getColOffset_fp() + pairIndex]; lhs -= x[getColOffset_fm() + pairIndex]; //if(lhs < -DecompEpsilon){ if(lhs < -0.01){ if(fabs(x[getColOffset_v() + pairIndex] - 1.0) > tolZero){ printf("NOT FEASIBLE fp=%10.5f fm=%10.5f f=%10.5f < 0, but v=%g not 1\n", x[getColOffset_fp() + pairIndex], x[getColOffset_fm() + pairIndex], lhs, x[getColOffset_v() + pairIndex]); isFeas = false; } } pairIndex++; } //--- //--- did the surrogate z work correctly? //--- z[a,t] = sum{t in T} x1[a,t] * x2[a] //--- //--- //--- is budget satisfied? //--- for d in D: //--- sum{a in A} (f+[a,d] - f-[a,d]) <= B[d] //--- //--- //--- is the count constraint satisifed //--- for a in A: //--- sum{d in D} v[a,d] <= K[a] //--- pairIndex = 0; UtilFillN(count, nAtms, 0.0); for(vi = pairsAD.begin(); vi != pairsAD.end(); vi++){ adP = m_instance.getIndexADInv(*vi); a = adP.first; d = adP.second; count[a] += x[getColOffset_v() + pairIndex]; pairIndex++; } for(a = 0; a < nAtms; a++){ #if 0 printf("COUNT[a=%3d->%10s]: %5g <= K=%5g\n", a, m_instance.getAtmName(a).c_str(), count[a], K_a[a]); #endif if(count[a] > (K_a[a] + 0.01)){ #if 0 printf("NOT FEASIBLE a:%d count=%g K=%g\n", a, count[a], K_a[a]); #endif isFeas = false; } } #if 0 printf("IsUserFeas = %d\n", isFeas); #endif //--- //--- free local memory //--- UTIL_DELARR(count); UtilPrintFuncEnd(m_osLog, m_classTag, "APPisUserFeasible()", m_appParam.LogLevel, 2); return isFeas; }
//===========================================================================// void ATM_DecompApp::createModelColumns(DecompConstraintSet * model, const int atmIndex, const int dateIndex){ //--- //--- Column bounds: //--- 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] in [0,1], x3[a] >= 0 //--- NOTE: x3 no UB causing unbounded subproblems? try <= 1000 //--- for a in A, t in T //--- x1[a,t] in {0,1}, z[a,t] in [0,1] //--- //--- If this is for block atmIndex(>=0), //--- fix all a!=atmIndex in A columns to 0. //--- //--- If this is for block dateIndex(>=0), //--- fix all d!=dateIndex in D columns to 0. //--- string colName; const int nPairs = m_instance.getNPairs(); const int nAtms = m_instance.getNAtms(); const int nSteps = m_appParam.NumSteps; const int nAtmsSteps = getNAtmsSteps(); const int nCols = numCoreCols(); const double * w_ad = m_instance.get_w_ad(); //dense storage const vector<int> & pairsAD = m_instance.getPairsAD(); vector<int>::const_iterator vi; //--- //--- set the col upper and lower bounds //--- UtilFillN(model->colLB, nCols, 0.0); UtilFillN(model->colUB, nCols, 1.0); int index; index = getColOffset_fm(); for(vi = pairsAD.begin(); vi != pairsAD.end(); vi++){ model->colUB[index] = w_ad[*vi]; index++; } UtilFillN(&model->colUB[0] + getColOffset_fp(), nPairs, DecompInf); //Another case of needing extreme rays?? //UtilFillN(&model->colUB[0] + getColOffset_x3(), nAtms, DecompInf); UtilFillN(&model->colUB[0] + getColOffset_x3(), nAtms, 1000.0); //--- //--- if this is for block a, fix all others to 0. //--- if(atmIndex >= 0){ int a, t; int index_x1 = getColOffset_x1(); int index_z = getColOffset_z(); int index_x2 = getColOffset_x2(); int index_x3 = getColOffset_x3(); int end = nSteps; if(m_appParam.UseTightModel) end++; for(a = 0; a < nAtms; a++){ if(a != atmIndex){ model->colUB[index_x2] = 0.0; model->colUB[index_x3] = 0.0; for(t = 0; t < end; t++){ model->colUB[index_x1++] = 0.0; model->colUB[index_z ++] = 0.0; } } else{ for(t = 0; t < end; t++){ model->activeColumns.push_back(index_x1++); model->activeColumns.push_back(index_z++); } model->activeColumns.push_back(index_x2); model->activeColumns.push_back(index_x3); } index_x2++; index_x3++; } int index_fp = getColOffset_fp(); int index_fm = getColOffset_fm(); int index_v = getColOffset_v(); for(vi = pairsAD.begin(); vi != pairsAD.end(); vi++){ a = m_instance.getIndexADInv(*vi).first; if(a != atmIndex){ model->colUB[index_fp] = 0.0; model->colUB[index_fm] = 0.0; model->colUB[index_v] = 0.0; } else{ model->activeColumns.push_back(index_fp); model->activeColumns.push_back(index_fm); model->activeColumns.push_back(index_v); } index_fp++; index_fm++; index_v++; } } if(dateIndex >= 0){ int d; int index_fp = getColOffset_fm(); int index_fm = getColOffset_fm(); int index_v = getColOffset_v(); for(vi = pairsAD.begin(); vi != pairsAD.end(); vi++){ d = m_instance.getIndexADInv(*vi).second; if(d != dateIndex){ model->colUB[index_fp] = 0.0; model->colUB[index_fm] = 0.0; model->colUB[index_v] = 0.0; } else{ model->activeColumns.push_back(index_fp); model->activeColumns.push_back(index_fm); model->activeColumns.push_back(index_v); } index_fp++; index_fm++; index_v++; } } //--- //--- set the indices of the integer variables of model: x1, v //--- UtilIotaN(model->integerVars, nAtmsSteps, getColOffset_x1()); UtilIotaN(model->integerVars, nPairs, getColOffset_v()); //--- //--- set column names for debugging //--- addColumnNamesAT(model, "x1", getColOffset_x1()); addColumnNamesAT(model, "z", getColOffset_z()); addColumnNamesAD(model, "fp", getColOffset_fp()); addColumnNamesAD(model, "fm", getColOffset_fm()); addColumnNamesA (model, "x2", getColOffset_x2()); addColumnNamesA (model, "x3", getColOffset_x3()); addColumnNamesAD(model, "v", getColOffset_v()); #if 0 { int i; for(i = 0; i < static_cast<int>(model->colNames.size()); i++){ printf("COL[%4d] = %20s LB:%g UB:%g\n", i, model->colNames[i].c_str(), model->colLB[i], model->colUB[i]); } } #endif }
//===========================================================================// 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); }
// --------------------------------------------------------------------- // int GAP_DecompApp::createModelPartAP(DecompConstraintSet* model) { int i, j, colIndex; int status = GAPStatusOk; int nTasks = m_instance.getNTasks(); //n int nMachines = m_instance.getNMachines(); //m int nCols = nTasks * nMachines; int nRows = nTasks; UtilPrintFuncBegin(m_osLog, m_classTag, "createModelPartAP()", m_appParam.LogLevel, 2); //--- //--- Build the core model constraints (AP = assignment problem). //--- //--- m is number of machines (index i) //--- n is number of tasks (index j) //--- //--- sum{i in 1..m} x[i,j] = 1, j in 1..n //--- //--- Example structure: m=3, n=4 //--- x x x = 1 [j=1] //--- x x x = 1 [j=2] //--- x x x = 1 [j=3] //--- x x x = 1 [j=4] //--- //--- //--- Allocate an empty row-ordered CoinPackedMatrix. Since we plan //--- to add rows, set the column dimension and let the row dimension //--- be set dynamically. //--- model->M = new CoinPackedMatrix(false, 0.0, 0.0); CoinAssertHint(model->M, "Error: Out of Memory"); model->M->setDimensions(0, nCols); //--- //--- we know the sizes needed, so reserve space for them (for efficiency) //--- model->reserve(nRows, nCols); //--- //--- create one row per task //--- rowNames are not needed, they are used for debugging //--- for (j = 0; j < nTasks; j++) { CoinPackedVector row; string rowName = "a(j_" + UtilIntToStr(j) + ")"; for (i = 0; i < nMachines; i++) { colIndex = getIndexIJ(i, j); row.insert(colIndex, 1.0); } model->appendRow(row, 1.0, 1.0, rowName); } //--- //--- set the col upper and lower bounds (all in [0,1]) //--- UtilFillN(model->colLB, nCols, 0.0); UtilFillN(model->colUB, nCols, 1.0); //--- //--- set the indices of the integer variables of model //--- (all vars are binary) //--- UtilIotaN(model->integerVars, nCols, 0); //--- //--- set column names for debugging //--- colIndex = 0; for (i = 0; i < nMachines; i++) { for (j = 0; j < nTasks; j++) { string colName = "x(" + UtilIntToStr(colIndex) + "_" + UtilIntToStr(i) + "," + UtilIntToStr(j) + ")"; model->colNames.push_back(colName); colIndex++; } } UtilPrintFuncEnd(m_osLog, m_classTag, "createModelPartAP()", m_appParam.LogLevel, 2); return status; }
//===========================================================================// int GAP_DecompApp::createModelPartKP(DecompConstraintSet* model, vector<int>& whichKnaps) { int i, j, b, colIndex; int status = GAPStatusOk; int nTasks = m_instance.getNTasks(); //n int nMachines = m_instance.getNMachines(); //m int nKnaps = static_cast<int>(whichKnaps.size()); const int* weight = m_instance.getWeight(); const int* capacity = m_instance.getCapacity(); int nCols = nTasks * nMachines; int nRows = nKnaps; UtilPrintFuncBegin(m_osLog, m_classTag, "createModelPartKP()", m_appParam.LogLevel, 2); //--- //--- Build the relax model constraints (KP = assignment problem). //--- //--- m is number of machines (index i) //--- n is number of tasks (index j) //--- //--- sum{j in 1..n} w[i,j] x[i,j] <= b[i], i in 1..m //--- x[i,j] in {0,1}, i in 1..m, j in 1..n //--- //--- Example structure: m=3, n=4 //--- xxxx <= b[i=1] //--- xxxx <= b[i=2] //--- xxxx <= b[i=3] //--- //--- //--- Allocate an empty row-ordered CoinPackedMatrix. Since we plan //--- to add rows, set the column dimension and let the row dimension //--- be set dynamically. //--- model->M = new CoinPackedMatrix(false, 0.0, 0.0); CoinAssertHint(model->M, "Error: Out of Memory"); model->M->setDimensions(0, nCols); //--- //--- we know the sizes needed, so reserve space for them (for efficiency) //--- model->reserve(nRows, nCols); //--- //--- create one row per knapsack //--- rowNames are not needed, they are used for debugging //--- vector<int>::iterator it; for (it = whichKnaps.begin(); it != whichKnaps.end(); ++it) { i = *it; CoinPackedVector row; string rowName = "k(i_" + UtilIntToStr(i) + ")"; for (j = 0; j < nTasks; j++) { colIndex = getIndexIJ(i, j); row.insert(colIndex, weight[colIndex]); } model->appendRow(row, -m_infinity, capacity[i], rowName); } //--- //--- set the col upper and lower bounds (all in [0,1]) //--- UtilFillN(model->colLB, nCols, 0.0); UtilFillN(model->colUB, nCols, 1.0); //--- //--- set the indices of the integer variables of model //--- UtilIotaN(model->integerVars, nCols, 0); //--- //--- tell the solver which columns are active (in this block) //--- for (it = whichKnaps.begin(); it != whichKnaps.end(); ++it) { b = *it; for (i = 0; i < nMachines; i++) { for (j = 0; j < nTasks; j++) { colIndex = getIndexIJ(i, j); if (i == b) { model->activeColumns.push_back(colIndex); } } } } //--- //--- set column names for debugging //--- colIndex = 0; for (i = 0; i < nMachines; i++) { for (j = 0; j < nTasks; j++) { string colName = "x(" + UtilIntToStr(colIndex) + "_" + UtilIntToStr(i) + "," + UtilIntToStr(j) + ")"; model->colNames.push_back(colName); colIndex++; } } UtilPrintFuncEnd(m_osLog, m_classTag, "createModelPartKP()", m_appParam.LogLevel, 2); return status; }
//===========================================================================// void MCF_DecompApp::createModelRelax(DecompConstraintSet* model, int commId) { //--- //--- SUBPROBLEM (A'): (one block for each k in K) //--- sum{(j,i) in A} x[k,i,j] - //--- sum{(i,j) in A} x[k,i,j] = d[i,k], for all i in N //--- x[k,i,j] integer >= l[i,j] <= u[i,j], for all (i,j) in A //--- For k=(s,t) in K, //--- d[i,k] = -d[k] if i=s //--- = d[k] if i=t //--- = 0, otherwise //--- int a, i, head, tail, colIndex, source, sink; int numCommodities = m_instance.m_numCommodities; int numArcs = m_instance.m_numArcs; int numNodes = m_instance.m_numNodes; int numCols = numCommodities * numArcs; int numRows = numNodes; MCF_Instance::arc* arcs = m_instance.m_arcs; MCF_Instance::commodity* commodities = m_instance.m_commodities; UtilPrintFuncBegin(m_osLog, m_classTag, "createModelRelax()", m_appParam.LogLevel, 2); //--- //--- create space for the model matrix (row-majored) //--- model->M = new CoinPackedMatrix(false, 0.0, 0.0); if (!model->M) { throw UtilExceptionMemory("createModelCore", "MCF_DecompApp"); } model->M->setDimensions(0, numCols); model->reserve(numRows, numCols); //--- //--- get this commodity's source and sink node //--- source = commodities[commId].source; sink = commodities[commId].sink; //--- //--- create the rows //--- NOTE: this is somewhat inefficient (but simple) //--- for (i = 0; i < numNodes; i++) { CoinPackedVector row; for (a = 0; a < numArcs; a++) { tail = arcs[a].tail; head = arcs[a].head; if (head == i) { colIndex = commId * numArcs + a; row.insert(colIndex, 1.0); } else if (tail == i) { colIndex = commId * numArcs + a; row.insert(colIndex, -1.0); } } if (i == source) model->appendRow(row, -commodities[commId].demand, -commodities[commId].demand); else if (i == sink) model->appendRow(row, commodities[commId].demand, commodities[commId].demand); else { model->appendRow(row, 0.0, 0.0); } string rowName = "flow(" + UtilIntToStr(commId) + "_" + UtilIntToStr(i) + "_" + UtilIntToStr(source) + "," + UtilIntToStr(sink) + ")"; model->rowNames.push_back(rowName); } //--- //--- create a list of the "active" columns (those related //--- to this commmodity) all other columns are fixed to 0 //--- UtilFillN(model->colLB, numCols, 0.0); UtilFillN(model->colUB, numCols, 0.0); colIndex = commId * numArcs; for (a = 0; a < numArcs; a++) { double arcLB = arcs[a].lb; double arcUB = arcs[a].ub; model->colLB[colIndex] = arcLB; model->colUB[colIndex] = arcUB; model->activeColumns.push_back(colIndex); colIndex++; } //--- //--- set the indices of the integer variables of model //--- UtilIotaN(model->integerVars, numCols, 0); UtilPrintFuncEnd(m_osLog, m_classTag, "createModelRelax()", m_appParam.LogLevel, 2); }
//===========================================================================// void MCF_DecompApp::createModelCore(DecompConstraintSet* model) { //--- //--- 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 //--- int k, a, colIndex; int numCommodities = m_instance.m_numCommodities; int numArcs = m_instance.m_numArcs; int numCols = numCommodities * numArcs; int numRows = 2 * numArcs; MCF_Instance::arc* arcs = m_instance.m_arcs; UtilPrintFuncBegin(m_osLog, m_classTag, "createModelCore()", m_appParam.LogLevel, 2); //--- //--- create space for the model matrix (row-majored) //--- model->M = new CoinPackedMatrix(false, 0.0, 0.0); if (!model->M) { throw UtilExceptionMemory("createModelCore", "MCF_DecompApp"); } model->M->setDimensions(0, numCols); model->reserve(numRows, numCols); //--- //--- create the rows and set the col/row bounds //--- UtilFillN(model->colLB, numCols, 0.0); UtilFillN(model->colUB, numCols, m_infinity); for (a = 0; a < numArcs; a++) { CoinPackedVector row; double arcLB = arcs[a].lb; double arcUB = arcs[a].ub; for (k = 0; k < numCommodities; k++) { colIndex = k * numArcs + a; model->colLB[colIndex] = arcLB; model->colUB[colIndex] = arcUB; row.insert(colIndex, 1.0); } //TODO: any issue with range constraints? model->appendRow(row, -m_infinity, arcUB); string rowNameUB = "capUB(" + UtilIntToStr(a) + "_" + UtilIntToStr(arcs[a].tail) + "," + UtilIntToStr(arcs[a].head) + ")"; model->rowNames.push_back(rowNameUB); model->appendRow(row, arcLB, m_infinity); string rowNameLB = "capLB(" + UtilIntToStr(a) + "_" + UtilIntToStr(arcs[a].tail) + "," + UtilIntToStr(arcs[a].head) + ")"; model->rowNames.push_back(rowNameLB); } //--- //--- create column names (helps with debugging) //--- for (k = 0; k < numCommodities; k++) { for (a = 0; a < numArcs; a++) { string colName = "x(comm_" + UtilIntToStr(k) + "," + UtilIntToStr(a) + "_" + UtilIntToStr(arcs[a].tail) + "," + UtilIntToStr(arcs[a].head) + ")"; model->colNames.push_back(colName); } } //--- //--- set the indices of the integer variables of model //--- UtilIotaN(model->integerVars, numCols, 0); UtilPrintFuncEnd(m_osLog, m_classTag, "createModelCore()", m_appParam.LogLevel, 2); }
/** * 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); }
//===========================================================================// void SDPUC_DecompApp::createModelRelax(DecompConstraintSet * model, int tpId){ //--- //--- SUBPROBLEM (A'): (one block for each k in K) //--- sum{(j,i) in A} x[k,i,j] - //--- sum{(i,j) in A} x[k,i,j] = d[i,k], for all i in N //--- x[k,i,j] integer >= l[i,j] <= u[i,j], for all (i,j) in A //--- For k=(s,t) in K, //--- d[i,k] = -d[k] if i=s //--- = d[k] if i=t //--- = 0, otherwise //--- 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\{s}, where s is the super source //--- 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 in A //--- r[i,j] x[i,j,t] - theta[j] + theta[i] >= -M (1 - z[i,j,t]) for all i,j in A //--- int a, i, j, head, tail, colIndex, source; int numTimeperiods = m_instance.m_numTimeperiods; int numArcs = m_instance.m_numArcs; int numSwitchings = m_instance.m_numSwitchings; 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::node * nodes = m_instance.m_nodes; SDPUC_Instance::timeseries * ts = m_instance.m_timeseries; int numACArcs = 0; for(a = 0; a < numArcs; a++){ if(arcs[a].acline == 1) { numACArcs++; } } int numRows = numNodes - 1 // balance + 2 * numArcs // capacity + 2 * numACArcs // and kirchoffs constraints + 1; // max. allowed no. of switches employed sum{z} <= k int col_yStartIndex = 0; int col_zStartIndex = numArcs*(1+numTimeperiods); int col_xStartIndex = numArcs * (1 + 2*numTimeperiods); int col_thetaStartIndex = numArcs*(1 + 3*numTimeperiods) ; double bigM = 100; UtilPrintFuncBegin(m_osLog, m_classTag, "createModelRelax()", m_appParam.LogLevel, 2); //--- //--- create space for the model matrix (row-majored) //--- model->M = new CoinPackedMatrix(false, 0.0, 0.0); if(!model->M) throw UtilExceptionMemory("createModelCore", "MCF_DecompApp"); model->M->setDimensions(0, numCols); model->reserve(numRows, numCols); //--- //--- set super source node //--- source = 0; //--- //--- create the rows //--- NOTE: this is somewhat inefficient (but simple) //--- int hej = 0; cout << "Generating sub-problem " << tpId << endl; hej++; //cout << "y_index = " << col_yStartIndex << endl; //cout << "z_index = " << col_zStartIndex << endl; //cout << "x_index = " << col_xStartIndex << endl; //cout << "theta_index = " << col_thetaStartIndex << endl; //--- create balance constraints for(i = 0; i < numNodes; i++){ CoinPackedVector row; for(a = 0; a < numArcs; a++){ tail = arcs[a].tail; head = arcs[a].head; if(head == i){ colIndex = col_xStartIndex + tpId * numArcs + a; row.insert(colIndex, 1.0); } else if(tail == i){ colIndex = col_xStartIndex + tpId * numArcs + a; row.insert(colIndex, -1.0); } } //set demand d double d = nodes[i].demand * ts[nodes[i].tsdemand].values[tpId]; std::string rowName = "balance_" + UtilIntToStr(i) + "_" + UtilIntToStr(tpId); if(i == source) { model->appendRow(row, -m_infinity, 0.0, rowName); } else { model->appendRow(row, d, d, rowName); } } //--- create capacity constraints and kirchoffs constraints for(a = 0; a < numArcs; a++){ CoinPackedVector rowLB, rowUB; //lower-, and upperbound //for(a = 0; a < numArcs; a++){ tail = arcs[a].tail; head = arcs[a].head; double lb = arcs[a].lb * ts[arcs[a].tscap].values[tpId]; double ub = arcs[a].ub * ts[arcs[a].tscap].values[tpId]; double reactance = arcs[a].weight; colIndex = col_zStartIndex + tpId * numArcs + a; rowLB.insert(colIndex, -lb); rowUB.insert(colIndex, -ub); colIndex = col_xStartIndex + tpId * numArcs + a; rowLB.insert(colIndex, 1.0); rowUB.insert(colIndex, 1.0); //set flow lower and upperbound std::string rowNameLB = "lb_" + UtilIntToStr(a) + "_" + UtilIntToStr(tpId); std::string rowNameUB = "ub_" + UtilIntToStr(a) + "_" + UtilIntToStr(tpId); model->appendRow(rowLB, 0.0, m_infinity, rowNameLB); model->appendRow(rowUB, -m_infinity, 0.0, rowNameUB); //set kirchoffs voltage constraints for ac-arcs if(arcs[a].acline == 1) { CoinPackedVector rowK1, rowK2; //Kirchoff1, and Kirchoff2 colIndex = col_zStartIndex + tpId * numArcs + a; rowK1.insert(colIndex, bigM); rowK2.insert(colIndex, -bigM); colIndex = col_xStartIndex + tpId * numArcs + a; rowK1.insert(colIndex, reactance); rowK2.insert(colIndex, reactance); for(i = 0; i < numNodes; i++){ if(head == i){ colIndex = col_thetaStartIndex + tpId * numNodes + i; rowK1.insert(colIndex, -1.0); rowK2.insert(colIndex, -1.0); } else if(tail == i){ colIndex = col_thetaStartIndex + tpId * numNodes + i; rowK1.insert(colIndex, 1.0); rowK2.insert(colIndex, 1.0); } } std::string rowNameK1 = "k1_" + UtilIntToStr(a) + "_" + UtilIntToStr(tpId); std::string rowNameK2 = "k2_" + UtilIntToStr(a) + "_" + UtilIntToStr(tpId); model->appendRow(rowK1, -m_infinity, bigM, rowNameK1); model->appendRow(rowK2, -bigM, m_infinity, rowNameK2); } } //--- create max. no. of switchings-constraint CoinPackedVector row; for(a = 0; a < numArcs; a++){ colIndex = col_zStartIndex + tpId * numArcs + a; if(arcs[a].acline == 1) { //only for arcs with voltage constraints row.insert(colIndex, 1.0); } } //model->appendRow(row, numACArcs-numSwitchings, numACArcs, std::string("sum{1-z}<=k")); std::string rowNameSumK = "sumk_" + UtilIntToStr(tpId); model->appendRow(row, numACArcs-numSwitchings, numACArcs, rowNameSumK); //--- //--- create a list of the "active" columns (those related //--- to this commmodity) all other columns are fixed to 0 //--- UtilFillN(model->colLB, numCols, 0.0); UtilFillN(model->colUB, numCols, 0.0); colIndex = 0; for(a = 0; a < numArcs; a++){ //set y-columns active //if(tpId == 0) { //colIndex = col_yStartIndex + a; // model->colLB[colIndex] = 0; // model->colUB[colIndex] = 1; // model->activeColumns.push_back(colIndex); //cout << "" << colIndex << ", " ; //} //set z-columns active colIndex = col_zStartIndex + tpId * numArcs + a; model->colLB[colIndex] = 0; //1 - arcs[a].switchable; //if arc not switchable then fix z=1 model->colUB[colIndex] = 1; model->activeColumns.push_back(colIndex); //set x-columns active colIndex = col_xStartIndex + tpId * numArcs + a; double arcLB = min(0.0, arcs[a].lb * ts[arcs[a].tscap].values[tpId]); //!!**** double arcUB = arcs[a].ub * ts[arcs[a].tscap].values[tpId]; model->colLB[colIndex] = arcLB; model->colUB[colIndex] = arcUB; model->activeColumns.push_back(colIndex); } //set theta-columns active for(i = 0; i < numNodes; i++){ colIndex = col_thetaStartIndex + tpId * numNodes + i; model->colLB[colIndex] = -m_infinity; model->colUB[colIndex] = m_infinity; model->activeColumns.push_back(colIndex); } //--- //--- set the indices of the integer variables of model //--- UtilIotaN(model->integerVars, col_xStartIndex, col_yStartIndex); ////Display problem //cout << "find: \nActive cols: "; //std::vector<int>::const_iterator it; //for(it = model->getActiveColumns().begin(); it < model->getActiveColumns().end(); it++){ //cout << *it << " "; //} //cout << "\ns.t.\n"; //for(j = 0; j < model->getNumRows(); j++){ //cout << model->rowNames[j] << " : \t\t"; //cout << model->rowLB[j] << " \t <= \t" ; //for (i = 0; i < model->getNumCols(); i++){ ////cout << "numCols=" << model->getNumCols() << endl; //if(model->getMatrix()->getCoefficient(j,i) != 0) { ////cout << "i" << i << " "; //cout << " " << model->M->getCoefficient(j,i) << " (" << i << ") + "; ////cout << model->getColNames()[i] ; //} //else {cout << "" ;} //} //cout << " \t <= \t " << model->rowUB[j] << endl ; // //} UtilPrintFuncEnd(m_osLog, m_classTag, "createModelRelax()", m_appParam.LogLevel, 2); }
//===========================================================================// void SDPUC_DecompApp::createModelCore(DecompConstraintSet * model){ //--- //--- 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 //--- 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 int numRows = numArcs * numTimeperiods; int col_yStartIndex = 0; int col_zStartIndex = numArcs*(1+numTimeperiods); int col_xStartIndex = numArcs * (1 + 2*numTimeperiods); int col_thetaStartIndex = numArcs*(1 + 3*numTimeperiods) ; SDPUC_Instance::arc * arcs = m_instance.m_arcs; UtilPrintFuncBegin(m_osLog, m_classTag, "createModelCore()", m_appParam.LogLevel, 2); //--- //--- create space for the model matrix (row-majored) //--- model->M = new CoinPackedMatrix(false, 0.0, 0.0); if(!model->M) throw UtilExceptionMemory("createModelCore", "SDPUC_DecompApp"); model->M->setDimensions(0, numCols); model->reserve(numRows, numCols); //--- //--- create the rows and set the col/row bounds //--- UtilFillN(model->colLB, numCols, -m_infinity); UtilFillN(model->colUB, numCols, m_infinity); for(a = 0; a < numArcs; a++){ colIndex = a; //add y1-vars model->colLB[colIndex] = 0; model->colUB[colIndex] = 1; for(t = 0; t < numTimeperiods; t++){ int t_prev = 0; if(t == 0) { t_prev = numTimeperiods - 1; } else { t_prev = t - 1; } colIndex = a + t * numArcs + numArcs; //add y2-vars model->colLB[colIndex] = 0; model->colUB[colIndex] = 1; CoinPackedVector row1; // 0 <= y1[i,j] - z[i,j,t] for all (i,j) in A, t in T CoinPackedVector row2; // 0 <= y2[i,j,t] - z[i,j,t] + z[i,j,t-1] for all (i,j) in A, t in T CoinPackedVector rowFix_y1; //fix y1=1 CoinPackedVector y2upper1; // y2(t) <= z(t) : if off in t then we dont start-up CoinPackedVector y2upper2; // y2(t) <= 1-z(t-1) : if on in t-1 then dont start up in t //insert y1-var coefficient row1.insert(a, 1.0); rowFix_y1.insert(a, 1.0); //insert y2-var coefficient colIndex = t * numArcs + a + numArcs; row2.insert(colIndex, 1.0); y2upper1.insert(colIndex, -1.0); y2upper2.insert(colIndex, -1.0); //add z-vars colIndex = t * numArcs + a + col_zStartIndex; model->colLB[colIndex] = 0; model->colUB[colIndex] = 1; //insert z-var coefficient row1.insert(colIndex, -1.0); row2.insert(colIndex, -1.0); y2upper1.insert(colIndex, 1.0); colIndex = t_prev * numArcs + a + col_zStartIndex; row2.insert(colIndex, 1.0); y2upper2.insert(colIndex, -1.0); std::string rowName1_1 = "MP1_1_" + UtilIntToStr(a) + "_" + UtilIntToStr(t); std::string rowName1_2 = "MP1_2_" + UtilIntToStr(a) + "_" + UtilIntToStr(t); std::string rowName2_1 = "MP2_1_" + UtilIntToStr(a) + "_" + UtilIntToStr(t); std::string rowName2_2 = "MP2_2_" + UtilIntToStr(a) + "_" + UtilIntToStr(t); std::string rowNameFix = "fix_y1_" + UtilIntToStr(a) + "_" + UtilIntToStr(t); //TODO: any issue with range constraint model->appendRow(row1, 0.0, m_infinity, rowName1_1); //add MP1_constraints (arc investments) model->appendRow(row1, -m_infinity, 1.0, rowName1_2); //add MP1_constraints (arc investments) if(arcs[a].tail == 0) { //ONLY for supply arcs (!!) model->appendRow(row2, 0.0, m_infinity, rowName2_1); //add MP2_constraints (arc commitment) model->appendRow(row2, -m_infinity, 1.0, rowName2_2); //add MP2_constraints (arc commitment) } model->appendRow(rowFix_y1, 1.0, m_infinity, rowNameFix); //add fix y1 vars //model->appendRow(y2upper1, 0.0, m_infinity, std::string("y2-upperbound-1")); //add upperbounds on y2 //model->appendRow(y2upper2, -1.0, m_infinity, std::string("y2-upperbound-2")); //..to strengthen formulation } } //--- //--- create column names (helps with debugging) //--- //y-vars for(a = 0; a < numArcs; a++){ std::string colName = "y1(a" + UtilIntToStr(a) + "(" + UtilIntToStr(arcs[a].tail) + "," + UtilIntToStr(arcs[a].head) + "))"; model->colNames.push_back(colName); } for(t = 0; t < numTimeperiods; t++){ for(a = 0; a < numArcs; a++){ std::string colName = "y2(t" + UtilIntToStr(t) + ",a" + UtilIntToStr(a) + "(" + UtilIntToStr(arcs[a].tail) + "," + UtilIntToStr(arcs[a].head) + "))"; model->colNames.push_back(colName); } } //z-vars for(t = 0; t < numTimeperiods; t++){ for(a = 0; a < numArcs; a++){ std::string colName = "z(t" + UtilIntToStr(t) + ",a" + UtilIntToStr(a) + "(" + UtilIntToStr(arcs[a].tail) + "," + UtilIntToStr(arcs[a].head) + "))"; model->colNames.push_back(colName); } } //x-vars for(t = 0; t < numTimeperiods; t++){ for(a = 0; a < numArcs; a++){ std::string colName = "x(t" + UtilIntToStr(t) + ",a" + UtilIntToStr(a) + "(" + UtilIntToStr(arcs[a].tail) + "," + UtilIntToStr(arcs[a].head) + "))"; model->colNames.push_back(colName); } } //theta-vars for(t = 0; t < numTimeperiods; t++){ for(i = 0; i < numNodes; i++){ std::string colName = "theta(t" + UtilIntToStr(t) + ",n" + UtilIntToStr(i) + ")"; model->colNames.push_back(colName); } } //--- //--- create a list of the "active" columns (those related //--- to this commmodity) all other columns are fixed to 0 //--- UtilFillN(model->colLB, numCols, 0.0); UtilFillN(model->colUB, numCols, 0.0); colIndex = 0; for(a = 0; a < numArcs; a++){ //set y-columns active //model->colLB[colIndex] = 0; //model->colUB[colIndex] = 1; //model->activeColumns.push_back(colIndex); //set y-columns as master-only columns colIndex = col_yStartIndex + a; model->masterOnlyCols.push_back(colIndex); //y1-vars for(t = 0; t < numTimeperiods; t++){ colIndex = col_yStartIndex + t * numArcs + a + numArcs; model->masterOnlyCols.push_back(colIndex); //y2-vars } } if(m_appParam.LogLevel >= 3){ (*m_osLog) << "Master only columns:" << endl; UtilPrintVector(model->masterOnlyCols, m_osLog); if(model->getColNames().size() > 0) UtilPrintVector(model->masterOnlyCols, model->getColNames(), m_osLog); } //--- //--- set the indices of the integer variables of model //--- UtilIotaN(model->integerVars, col_xStartIndex, col_yStartIndex); UtilPrintFuncEnd(m_osLog, m_classTag, "createModelCore()", m_appParam.LogLevel, 2); //--- //--- display problem //--- //int j = 0; //cout << "find: \nActive cols: "; //std::vector<int>::const_iterator it; //for(it = model->getActiveColumns().begin(); it != model->getActiveColumns().end(); it++){ //cout << *it << " "; //} // //cout << "\ns.t.\n"; //for(j = 0; j < model->getNumRows(); j++){ //cout << model->rowNames[j] << " : \t\t"; //cout << model->rowLB[j] << " \t <= \t" ; //for (i = 0; i < model->getNumCols(); i++){ ////cout << "numCols=" << model->getNumCols() << endl; //if(model->getMatrix()->getCoefficient(j,i) != 0) { ////cout << "i" << i << " "; //cout << " " << model->M->getCoefficient(j,i) << " " ; //cout << model->getColNames()[i] ; //} //else {cout << "" ;} //} //cout << " \t <= \t " << model->rowUB[j] << endl ; // //} }