//===========================================================================// void GAP_DecompApp::initializeApp(UtilParameters& utilParam) { UtilPrintFuncBegin(m_osLog, m_classTag, "initializeApp()", m_appParam.LogLevel, 2); //--- //--- get application parameters //--- m_appParam.getSettings(utilParam); if (m_appParam.LogLevel >= 1) { m_appParam.dumpSettings(m_osLog); } //--- //--- read instance // string instanceFile = m_appParam.DataDir + UtilDirSlash() + m_appParam.Instance; m_instance.readInstance(instanceFile); //--- //--- read best known lb/ub (for debugging) //--- string bestKnownFile = m_appParam.DataDir + UtilDirSlash() + "gap.opt"; m_instance.readBestKnown(bestKnownFile, m_appParam.Instance); setBestKnownLB(m_instance.getBestKnownLB()); setBestKnownUB(m_instance.getBestKnownUB()); //--- //--- create models //--- createModels(); UtilPrintFuncEnd(m_osLog, m_classTag, "initializeApp()", m_appParam.LogLevel, 2); }
//===========================================================================// void ATM_DecompApp::initializeApp() { UtilPrintFuncBegin(m_osLog, m_classTag, "initializeApp()", m_appParam.LogLevel, 2); //--- //--- read instance // string fileNameA, fileNameD, fileNameAD; if (m_appParam.DataDir != "") { fileNameA = m_appParam.DataDir + UtilDirSlash() + m_appParam.DataAtm; fileNameD = m_appParam.DataDir + UtilDirSlash() + m_appParam.DataDate; fileNameAD = m_appParam.DataDir + UtilDirSlash() + m_appParam.DataAtmDate; } else { fileNameA = m_appParam.DataAtm; fileNameD = m_appParam.DataDate; fileNameAD = m_appParam.DataAtmDate; } m_instance.readInstance(fileNameA, fileNameD, fileNameAD); //--- //--- create models //--- createModels(); UtilPrintFuncEnd(m_osLog, m_classTag, "initializeApp()", m_appParam.LogLevel, 2); }
//===========================================================================// DecompConstraintSet * ATM_DecompApp::createModelCoreCount(){ UtilPrintFuncBegin(m_osLog, m_classTag, "createModelCoreCount()", m_appParam.LogLevel, 2); int a, nRows; const int nAtms = m_instance.getNAtms(); const int nAtmsSteps = getNAtmsSteps(); const int nCols = numCoreCols(); if(m_appParam.UseTightModel) nRows = 3*nAtms + nAtmsSteps; else nRows = 2*nAtms + 3*nAtmsSteps; int rowCnt = 0; //--- //--- A'' (core): //--- for a in A: //--- sum{d in D} v[a,d] <= K[a] //--- DecompConstraintSet * model = new DecompConstraintSet(); CoinAssertHint(model, "Error: Out of Memory"); //--- //--- create new matrix //--- model->M = new CoinPackedMatrix(false, 0.0, 0.0); CoinAssertHint(model->M, "Error: Out of Memory"); model->M->setDimensions(0, nCols); model->reserve(nRows, nCols); //--- //--- create model constraints //--- for(a = 0; a < nAtms; a++){ rowCnt += createConCount (model, a); rowCnt += createConZtoX (model, a);//OPT rowCnt += createConPickOne(model, a);//OPT } //THINK - add conZtoX to core and remove from relax? printf("nRows = %d, rowCnt = %d\n", nRows, rowCnt); assert(rowCnt == nRows); //--- //--- create model variables/columns //--- createModelColumns(model); UtilPrintFuncEnd(m_osLog, m_classTag, "createModelCoreCount()", m_appParam.LogLevel, 2); return model; }
//===========================================================================// DecompConstraintSet * ATM_DecompApp::createModelCore2(){ UtilPrintFuncBegin(m_osLog, m_classTag, "createModelCore2()", m_appParam.LogLevel, 2); int a; const int nAtms = m_instance.getNAtms(); const int nCols = numCoreCols(); const int nRows = (2*nAtms); int rowCnt = 0; //--- //--- A'' (core): //--- for a in A: //--- sum{t in T} x1[a,t] <= 1 //--- sum{d in D} v[a,d] <= K[a] //--- for a in A, t in T: //--- z[a,t] <= x1[a,t], //--- z[a,t] <= x2[a], //--- z[a,t] >= x1[a,t] + x2[a] - 1. //--- DecompConstraintSet * model = new DecompConstraintSet(); CoinAssertHint(model, "Error: Out of Memory"); //--- //--- create new matrix //--- model->M = new CoinPackedMatrix(false, 0.0, 0.0); CoinAssertHint(model->M, "Error: Out of Memory"); model->M->setDimensions(0, nCols); model->reserve(nRows, nCols); //--- //--- create model constraints //--- for(a = 0; a < nAtms; a++){ rowCnt += createConPickOne(model, a); rowCnt += createConCount (model, a); } printf("nRows = %d, rowCnt = %d\n", nRows, rowCnt); assert(rowCnt == nRows); //--- //--- create model variables/columns //--- createModelColumns(model); UtilPrintFuncEnd(m_osLog, m_classTag, "createModelCore2()", m_appParam.LogLevel, 2); return model; }
//===========================================================================// 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); }
//===========================================================================// 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); }
//===========================================================================// void ATM_DecompApp::initializeApp(UtilParameters & utilParam) { UtilPrintFuncBegin(m_osLog, m_classTag, "initializeApp()", m_appParam.LogLevel, 2); //--- //--- get application parameters //--- m_appParam.getSettings(utilParam); if(m_appParam.LogLevel >= 1) m_appParam.dumpSettings(m_osLog); //--- //--- read instance // string fileNameA, fileNameD, fileNameAD; if (m_appParam.DataDir != "") { fileNameA = m_appParam.DataDir + UtilDirSlash() + m_appParam.DataAtm; fileNameD = m_appParam.DataDir + UtilDirSlash() + m_appParam.DataDate; fileNameAD = m_appParam.DataDir + UtilDirSlash() + m_appParam.DataAtmDate; } else { fileNameA = m_appParam.DataAtm; fileNameD = m_appParam.DataDate; fileNameAD = m_appParam.DataAtmDate; } m_instance.readInstance(fileNameA, fileNameD, fileNameAD); //--- //--- create models //--- createModels(); UtilPrintFuncEnd(m_osLog, m_classTag, "initializeApp()", m_appParam.LogLevel, 2); }
//===========================================================================// 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; }
//===========================================================================// DecompConstraintSet * ATM_DecompApp::createModelCore1(bool includeCount){ UtilPrintFuncBegin(m_osLog, m_classTag, "createModelCore1()", m_appParam.LogLevel, 2); int a, d, pairIndex; pair<int,int> adP; vector<int>::const_iterator vi; const int nAtms = m_instance.getNAtms(); const int nDates = m_instance.getNDates(); const vector<int> & pairsAD = m_instance.getPairsAD(); const double * B_d = m_instance.get_B_d(); const int nCols = numCoreCols(); int nRows = nDates; if(includeCount) nRows += nAtms; DecompConstraintSet * model = new DecompConstraintSet(); CoinAssertHint(model, "Error: Out of Memory"); model->M = new CoinPackedMatrix(false, 0.0, 0.0); CoinAssertHint(model->M, "Error: Out of Memory"); model->M->setDimensions(0, nCols); model->reserve(nRows, nCols); //--- //--- for d in D: //--- sum{a in A} (f+[a,d] - f-[a,d]) <= B[d] //--- CoinPackedVector * rowsD = new CoinPackedVector[nDates]; pairIndex = 0; for(vi = pairsAD.begin(); vi != pairsAD.end(); vi++){ adP = m_instance.getIndexADInv(*vi); a = adP.first; d = adP.second; rowsD[d].insert(getColOffset_fp() + pairIndex, 1.0); rowsD[d].insert(getColOffset_fm() + pairIndex, -1.0); pairIndex++; } for(d = 0; d < nDates; d++){ string rowName = "budget(d_" + m_instance.getDateName(d) + ")"; model->appendRow(rowsD[d], -DecompInf, B_d[d], rowName); } UTIL_DELARR(rowsD); if(includeCount){ //--- for a in A: //--- sum{d in D} v[a,d] <= K[a] //--- for(a = 0; a < nAtms; a++){ createConCount(model, a); } } //--- //--- create model columns //--- createModelColumns(model); UtilPrintFuncEnd(m_osLog, m_classTag, "createModelCore1()", m_appParam.LogLevel, 2); return model; }
//===========================================================================// 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 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); }
//===========================================================================// 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); }
//===========================================================================// 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); }
// --------------------------------------------------------------------- // 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; }
//===========================================================================// 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); }
//===========================================================================// DecompConstraintSet * ATM_DecompApp::createModelRelax2(const int d){ UtilPrintFuncBegin(m_osLog, m_classTag, "createModelRelax2()", m_appParam.LogLevel, 2); int a, t, nRows, pairIndex, nRowsMax; double rhs, coefA, coefC; pair<int,int> adP; vector<int>::const_iterator vi; const int nSteps = m_appParam.NumSteps; const int nAtms = m_instance.getNAtms(); const vector<int> & pairsAD = m_instance.getPairsAD(); const double * a_ad = m_instance.get_a_ad(); //dense storage const double * b_ad = m_instance.get_b_ad(); //dense storage const double * c_ad = m_instance.get_c_ad(); //dense storage const double * d_ad = m_instance.get_d_ad(); //dense storage const double * e_ad = m_instance.get_e_ad(); //dense storage const double * w_ad = m_instance.get_w_ad(); //dense storage const double * B_d = m_instance.get_B_d(); const int nCols = numCoreCols(); if(m_appParam.UseTightModel) nRowsMax = 3*nAtms + 1 + getNAtmsSteps(); else nRowsMax = 2*nAtms + 1 + (3*getNAtmsSteps()); //--- //--- A'[d] for d in D (independent blocks) //--- for a in A //--- f+[a,d] - f-[a,d] = //--- a[a,d] sum{t in T} (t/n) x1[a,t] + //--- b[a,d] x2[a] + //--- c[a,d] sum{t in T} (t/n) z[a,t] + //--- d[a,d] x3[a] + //--- e[a,d] //--- f-[a,d] <= w[a,d] * v[a,d] //--- sum{a in A} (f+[a,d] - f-[a,d]) <= B[d] //--- for a in A, t in T: //--- z[a,t] <= x1[a,t], //--- z[a,t] <= x2[a], //--- z[a,t] >= x1[a,t] + x2[a] - 1. //--- DecompConstraintSet * model = new DecompConstraintSet(); CoinAssertHint(model, "Error: Out of Memory"); model->M = new CoinPackedMatrix(false, 0.0, 0.0); CoinAssertHint(model->M, "Error: Out of Memory"); model->M->setDimensions(0, nCols); model->reserve(nRowsMax, nCols); CoinPackedVector rowBudget; nRows = 0; pairIndex = 0; for(vi = pairsAD.begin(); vi != pairsAD.end(); vi++){ adP = m_instance.getIndexADInv(*vi); if(d != adP.second){ pairIndex++; continue; } a = adP.first; //--- //--- sum{a in A} (f+[a,d] - f-[a,d]) <= B[d] //--- rowBudget.insert(getColOffset_fp() + pairIndex, 1.0); rowBudget.insert(getColOffset_fm() + pairIndex, -1.0); //--- //--- f+[a,d] - f-[a,d] = //--- a[a,d] sum{t in T} (t/n) x1[a,t] + //--- b[a,d] x2[a] + //--- c[a,d] sum{t in T} (t/n) z[a,t] + //--- d[a,d] x3[a] + //--- e[a,d] //--- CoinPackedVector row; string rowName = "demand_def(a_" + m_instance.getAtmName(a) + ",d_" + m_instance.getDateName(d) + ")"; row.insert(colIndex_fp(pairIndex), 1.0); row.insert(colIndex_fm(pairIndex), -1.0); coefA = -a_ad[*vi] / nSteps; coefC = -c_ad[*vi] / nSteps; if(m_appParam.UseTightModel){ for(t = 0; t <= nSteps; t++){ row.insert(colIndex_x1(a,t), t * coefA); row.insert(colIndex_z (a,t), t * coefC); } } else{ for(t = 0; t < nSteps; t++){ row.insert(colIndex_x1(a,t), (t+1) * coefA); row.insert(colIndex_z (a,t), (t+1) * coefC); } } row.insert(colIndex_x2(a), -b_ad[*vi]); row.insert(colIndex_x3(a), -d_ad[*vi]); rhs = e_ad[*vi]; model->appendRow(row, rhs, rhs, rowName); nRows++; //--- //--- f-[a,d] <= w[a,d] * v[a,d] //--- CoinPackedVector rowLink; string rowNameLink = "linkv(a_" + m_instance.getAtmName(a) + ",d_" + m_instance.getDateName(d) + ")"; rowLink.insert(colIndex_fm(pairIndex), 1.0); rowLink.insert(colIndex_v (pairIndex), -w_ad[*vi]); model->appendRow(rowLink, -DecompInf, 0.0, rowNameLink); nRows++; pairIndex++; } string rowNameBudget = "budget(d_" + m_instance.getDateName(d) + ")"; model->appendRow(rowBudget, -DecompInf, B_d[d], rowNameBudget); nRows++; for(a = 0; a < nAtms; a++) nRows += createConZtoX(model, a); assert(nRows <= nRowsMax); //--- //--- create model columns //--- createModelColumns(model, -1, d); UtilPrintFuncEnd(m_osLog, m_classTag, "createModelRelax2()", m_appParam.LogLevel, 2); return model; }
int OSDipApp::generateInitVars(DecompVarList & initVars) { //--- //--- generateInitVars is a virtual method and can be overriden //--- if the user has some idea how to initialize the list of //--- initial variables (columns in the DW master) //--- std::cout << "GENERATE INIT VARS" << std::endl; UtilPrintFuncBegin(m_osLog, m_classTag, "generateInitVars()", m_appParam.LogLevel, 2); //--- //--- Get the initial solution from the OSOption object //--- we want the variable other option where name="initialCol" //--- //std::vector<OtherVariableOption*> getOtherVariableOptions(std::string solver_name); std::vector<OtherVariableOption*> otherVarOptions; std::vector<OtherVariableOption*>::iterator vit; int *index = NULL; double *value = NULL; int i; double objValue; int whichBlock; DecompVar *var; try{ if (m_osInterface.m_osoption != NULL && m_osInterface.m_osoption->getNumberOfOtherVariableOptions() > 0) { std::cout << "Number of other variable options = " << m_osInterface.m_osoption->getNumberOfOtherVariableOptions() << std::endl; otherVarOptions = m_osInterface.m_osoption->getOtherVariableOptions( "Dip"); //iterate over the vector for (vit = otherVarOptions.begin(); vit != otherVarOptions.end(); vit++) { // see if we have an initialCol option if ((*vit)->name.compare("initialCol") == 0) { index = new int[(*vit)->numberOfVar]; value = new double[(*vit)->numberOfVar]; objValue = 0.0; for (i = 0; i < (*vit)->numberOfVar; i++) { index[i] = (*vit)->var[i]->idx; //convert the string to integer value[ i] = atoi((*vit)->var[i]->value.c_str()); objValue += m_objective[index[i]]; } whichBlock = atoi( (*vit)->value.c_str() ); var = new DecompVar((*vit)->numberOfVar, index, value, objValue); var->setBlockId(whichBlock); initVars.push_back(var); //free local memory UTIL_DELARR( index); UTIL_DELARR( value); } } } }//end try catch(const ErrorClass& eclass){ throw ErrorClass( eclass.errormsg); } UtilPrintFuncEnd(m_osLog, m_classTag, "generateInitVars()", m_appParam.LogLevel, 2); return static_cast<int> (initVars.size()); }
void OSDipApp::initializeApp(UtilParameters & utilParam) { UtilPrintFuncBegin(m_osLog, m_classTag, "initializeApp()", m_appParam.LogLevel, 2); //--- //--- get application parameters //--- m_appParam.getSettings(utilParam); if (m_appParam.LogLevel >= 1) m_appParam.dumpSettings(m_osLog); try { //--- //--- read OSiL instance // if (m_appParam.OSiLFile.size() <= 1) throw ErrorClass("An OSiL file not specified in the paramater file"); std::string osilFile = m_appParam.DataDir + UtilDirSlash() + m_appParam.OSiLFile; m_osInterface.readOSiL( osilFile); //--- //--- read OSoL instance -- it is not necessary, if not there //-- all constraints become block constraints // //if(m_appParam.OSoLFile.size() <= 1) throw ErrorClass("An OSoL file not specified in the paramater file"); if (m_appParam.OSoLFile.size() > 0) { std::string osolFile = m_appParam.DataDir + UtilDirSlash() + m_appParam.OSoLFile; m_osInterface.readOSoL( osolFile); } //--- //--- create models //--- createModels(); //just temporary playing around /** std::cout << std::endl << std::endl << std::endl; std::cout << "VARIABLE INDEX TESTING " <<std::endl; std::vector<std::set<int> > blockVars; std::set<int>::iterator sit; blockVars = m_osInterface.getBlockVarIndexes(); for(int i = 0; i < blockVars.size(); i++){ std::cout << "INSIDE BLOCK " << i << std::endl; for (sit = blockVars[i].begin(); sit != blockVars[i].end(); sit++) { std::cout << "VARIABLE = " << *sit << std::endl; } } //now test core constraints std::cout << "CORE CONSTRAINT TESTING " <<std::endl; std::set<int> conIndexes; conIndexes = m_osInterface.getCoreConstraintIndexes(); for (sit = conIndexes.begin(); sit != conIndexes.end(); sit++) { std::cout << "CORE INDEX = " << *sit << std::endl; } std::cout << "BLOCK CONSTRAINT INDEX TESTING " <<std::endl; std::vector<std::map<int, int> > blockCons; std::map<int, int>::iterator mit; blockCons = m_osInterface.getBlockConstraintIndexes(); for(int i = 0; i < blockCons.size(); i++){ std::cout << "INSIDE BLOCK " << i << std::endl; for (mit = blockCons[i].begin(); mit != blockCons[i].end(); mit++) { std::cout << "CONSTRAINT INDEX = " << mit->first << std::endl; } } */ m_blockOSInstances = m_osInterface.getBlockOSInstances(); //loop over the instances and generate a solver std::vector<OSInstance* >::iterator vit1; OSDipBlockCoinSolver *coinSolver = NULL; for (vit1 = m_blockOSInstances.begin(); vit1 != m_blockOSInstances.end(); vit1++) { coinSolver = new OSDipBlockCoinSolver( *vit1) ; m_osDipBlockCoinSolver.push_back( coinSolver ) ; } std::vector<std::set<int> >::iterator vit2; std::set<int>::iterator sit; std::set<int> blockVar; std::vector<IndexValuePair*> solIndexValPair; std::vector<IndexValuePair*>::iterator vit3; double optVal; double *cost = NULL; int index; int whichBlock; m_blockVars = m_osInterface.getBlockVarIndexes(); whichBlock = 0; for (vit2 = m_blockVars.begin(); vit2 != m_blockVars.end(); vit2++) { blockVar = *vit2; cost = new double[ blockVar.size() ]; index = 0; for (sit = blockVar.begin(); sit != blockVar.end(); sit++) { cost[index] = m_objective[ *sit]; index++; } m_osDipBlockCoinSolver[whichBlock++]->solve( cost, &solIndexValPair, &optVal); std::cout << "OPTIMAL VALUE = " << optVal << std::endl; std::cout << "solIndexValPair SIZE 2 = " << solIndexValPair.size() << std::endl; for (vit3 = solIndexValPair.begin(); vit3 != solIndexValPair.end(); vit3++) { std::cout << "IDEX = " << (*vit3)->idx << std::endl; std::cout << "VALUE = " << (*vit3)->value << std::endl; } delete []cost; } } catch (const ErrorClass& eclass) { throw ErrorClass(eclass.errormsg); } UtilPrintFuncEnd(m_osLog, m_classTag, "initializeApp()", m_appParam.LogLevel, 2); }//end initializeApp
//===========================================================================// 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); }
//===========================================================================// void MCF_DecompApp::createModelRelaxSparse(DecompConstraintSet* model, int commId) { //--- //--- SUBPROBLEM (A'): (one block for each k in K) //--- sum{(j,i) in A} x[k,i,j] - //--- sum{(i,j) in A} x[k,i,j] = d[i,k], for all i in N //--- x[k,i,j] integer >= l[i,j] <= u[i,j], for all (i,j) in A //--- For k=(s,t) in K, //--- d[i,k] = -d[k] if i=s //--- = d[k] if i=t //--- = 0, otherwise //--- int a, i, head, tail, origColIndex, source, sink; int numArcs = m_instance.m_numArcs; int numNodes = m_instance.m_numNodes; int numCommodities = m_instance.m_numCommodities; int numCols = numArcs; int numRows = numNodes; int numColsOrig = numArcs * numCommodities; MCF_Instance::arc* arcs = m_instance.m_arcs; MCF_Instance::commodity* commodities = m_instance.m_commodities; UtilPrintFuncBegin(m_osLog, m_classTag, "createModelRelaxSparse()", m_appParam.LogLevel, 2); //--- //--- create space for the model matrix (row-majored) //--- model->M = new CoinPackedMatrix(false, 0.0, 0.0); if (!model->M) { throw UtilExceptionMemory("createModelCore", "MCF_DecompApp"); } model->M->setDimensions(0, numCols); model->reserve(numRows, numCols); model->setSparse(numColsOrig); //--- //--- get this commodity's source and sink node //--- source = commodities[commId].source; sink = commodities[commId].sink; //--- //--- create the rows //--- NOTE: this is somewhat inefficient (but simple) //--- for (i = 0; i < numNodes; i++) { CoinPackedVector row; for (a = 0; a < numArcs; a++) { tail = arcs[a].tail; head = arcs[a].head; if (head == i) { row.insert(a, 1.0); } else if (tail == i) { row.insert(a, -1.0); } } if (i == source) model->appendRow(row, -commodities[commId].demand, -commodities[commId].demand); else if (i == sink) model->appendRow(row, commodities[commId].demand, commodities[commId].demand); else { model->appendRow(row, 0.0, 0.0); } } //--- //--- set the colLB, colUB, integerVars and sparse mapping //--- origColIndex = commId * numArcs; for (a = 0; a < numArcs; a++) { double arcLB = arcs[a].lb; double arcUB = arcs[a].ub; model->pushCol(arcLB, arcUB, true, origColIndex); origColIndex++; } UtilPrintFuncEnd(m_osLog, m_classTag, "createModelRelaxSparse()", m_appParam.LogLevel, 2); }
//===========================================================================// void 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); }
//===========================================================================// DecompConstraintSet * ATM_DecompApp::createModelRelax1(const int a, bool includeCount){ UtilPrintFuncBegin(m_osLog, m_classTag, "createModelRelax1()", m_appParam.LogLevel, 2); int t, d, nRows, pairIndex; double rhs, coefA, coefC; pair<int,int> adP; vector<int>::const_iterator vi; const int nSteps = m_appParam.NumSteps; const int nDates = m_instance.getNDates(); const vector<int> & pairsAD = m_instance.getPairsAD(); const double * a_ad = m_instance.get_a_ad(); //dense storage const double * b_ad = m_instance.get_b_ad(); //dense storage const double * c_ad = m_instance.get_c_ad(); //dense storage const double * d_ad = m_instance.get_d_ad(); //dense storage const double * e_ad = m_instance.get_e_ad(); //dense storage const double * w_ad = m_instance.get_w_ad(); //dense storage const int nCols = numCoreCols(); int nRowsMax = nDates + 1 + (3*nSteps); if(includeCount) nRowsMax += nDates + 1; //--- //--- for a in A, d in D: //--- f+[a,d] - f-[a,d] = //--- a[a,d] sum{t in T} (t/n) x1[a,t] + //--- b[a,d] x2[a] + //--- c[a,d] sum{t in T} (t/n) z[a,t] + //--- d[a,d] x3[a] + //--- e[a,d] //--- f-[a,d] <= w[a,d] * v[a,d] (for count) //--- for a in A: //--- sum{t in T} x1[a,t] <= 1 //--- sum{d in D} v[a,d] <= K[a] (for count) [OPT] //Probably not... //THINK: can't we just post-process this? z=x1*x2 //--- for a in A, t in T: //--- z[a,t] <= x1[a,t], //--- z[a,t] <= x2[a], //--- z[a,t] >= x1[a,t] + x2[a] - 1. //--- DecompConstraintSet * model = new DecompConstraintSet(); CoinAssertHint(model, "Error: Out of Memory"); model->M = new CoinPackedMatrix(false, 0.0, 0.0); CoinAssertHint(model->M, "Error: Out of Memory"); model->M->setDimensions(0, nCols); model->M->reserve(nRowsMax, nCols); model->rowLB.reserve(nRowsMax); model->rowUB.reserve(nRowsMax); //--- //--- for a in A, d in D: //--- f+[a,d] - f-[a,d] = //--- a[a,d] sum{t in T} (t/n) x1[a,t] + //--- b[a,d] x2[a] + //--- c[a,d] sum{t in T} (t/n) z[a,t] + //--- d[a,d] x3[a] + //--- e[a,d] //--- f-[a,d] <= w[a,d] * v[a,d] (for count) //--- nRows = 0; pairIndex = 0; for(vi = pairsAD.begin(); vi != pairsAD.end(); vi++){ adP = m_instance.getIndexADInv(*vi); if(a != adP.first){ pairIndex++; continue; } d = adP.second; CoinPackedVector row; string rowName = "demand_def(a_" + m_instance.getAtmName(a) + ",d_" + m_instance.getDateName(d) + ")"; row.insert(colIndex_fp(pairIndex), 1.0); row.insert(colIndex_fm(pairIndex), -1.0); coefA = -a_ad[*vi] / nSteps; coefC = -c_ad[*vi] / nSteps; if(m_appParam.UseTightModel){ for(t = 0; t <= nSteps; t++){ row.insert(colIndex_x1(a,t), t * coefA); row.insert(colIndex_z (a,t), t * coefC); } } else{ for(t = 0; t < nSteps; t++){ row.insert(colIndex_x1(a,t), (t+1) * coefA); row.insert(colIndex_z (a,t), (t+1) * coefC); } } row.insert(colIndex_x2(a), -b_ad[*vi]); row.insert(colIndex_x3(a), -d_ad[*vi]); rhs = e_ad[*vi]; model->M->appendRow(row); model->rowLB.push_back(rhs); model->rowUB.push_back(rhs); model->rowNames.push_back(rowName); nRows++; CoinPackedVector rowLink; string rowNameLink = "linkv(a_" + m_instance.getAtmName(a) + ",d_" + m_instance.getDateName(d) + ")"; rowLink.insert(colIndex_fm(pairIndex), 1.0); rowLink.insert(colIndex_v (pairIndex), -w_ad[*vi]); model->M->appendRow(rowLink); model->rowLB.push_back(-DecompInf); model->rowUB.push_back(0.0); model->rowNames.push_back(rowNameLink); nRows++; pairIndex++; } //--- //--- for a in A: //--- sum{t in T} x1[a,t] <= 1 //--- sum{d in D} v[a,d] <= K[a] (for count) //--- nRows += createConPickOne(model, a); if(includeCount) nRows += createConCount(model, a); //--- //--- for a in A, t in T: //--- z[a,t] <= x1[a,t], //--- z[a,t] <= x2[a], //--- z[a,t] >= x1[a,t] + x2[a] - 1. //--- nRows += createConZtoX(model, a); //--- //--- create model columns //--- createModelColumns(model, a); UtilPrintFuncEnd(m_osLog, m_classTag, "createModelRelax1()", m_appParam.LogLevel, 2); return model; }
//===========================================================================// 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 ; // //} }
//===========================================================================// DecompConstraintSet * ATM_DecompApp::createModelRelaxCount(){ UtilPrintFuncBegin(m_osLog, m_classTag, "createModelRelaxCount()", m_appParam.LogLevel, 2); int a, d, t, nRows, pairIndex, nRowsMax; double rhs, coefA, coefC; pair<int,int> adP; vector<int>::const_iterator vi; const int nSteps = m_appParam.NumSteps; const int nAtms = m_instance.getNAtms(); const int nDates = m_instance.getNDates(); const int nPairs = m_instance.getNPairs(); const int nAtmsSteps = getNAtmsSteps(); const vector<int> & pairsAD = m_instance.getPairsAD(); const double * a_ad = m_instance.get_a_ad(); //dense storage const double * b_ad = m_instance.get_b_ad(); //dense storage const double * c_ad = m_instance.get_c_ad(); //dense storage const double * d_ad = m_instance.get_d_ad(); //dense storage const double * e_ad = m_instance.get_e_ad(); //dense storage const double * w_ad = m_instance.get_w_ad(); //dense storage const double * B_d = m_instance.get_B_d(); const int nCols = numCoreCols(); if(m_appParam.UseTightModel) nRowsMax = nDates + 2*nAtms + nAtmsSteps + 2*nPairs; else nRowsMax = nDates + nAtms + 3*nAtmsSteps + 2*nPairs; //TODO: // try the nested idea - so master has ConZtoX and we price without that // but we solve with gap the harder oracle with those constraints //--- //--- A' (relax): //--- for d in D: //--- sum{a in A} (f+[a,d] - f-[a,d]) <= B[d] <---- makes it hard //OPT //--- for a in A: //--- sum{t in T} x1[a,t] <= 1 //OPT //--- for a in A, t in T: //--- z[a,t] <= x1[a,t], //--- z[a,t] <= x2[a], //--- z[a,t] >= x1[a,t] + x2[a] - 1. //--- for a in A, d in D: //--- f+[a,d] - f-[a,d] = //--- a[a,d] sum{t in T} (t/n) x1[a,t] + //--- b[a,d] x2[a] + //--- c[a,d] sum{t in T} (t/n) z[a,t] + //--- d[a,d] x3[a] + //--- e[a,d] //--- f-[a,d] <= w[a,d] * v[a,d] //--- DecompConstraintSet * model = new DecompConstraintSet(); CoinAssertHint(model, "Error: Out of Memory"); model->M = new CoinPackedMatrix(false, 0.0, 0.0); CoinAssertHint(model->M, "Error: Out of Memory"); model->M->setDimensions(0, nCols); model->reserve(nRowsMax, nCols); //--- //--- create nDates empty rowBudget packed vectors //--- vector<CoinPackedVector> rowBudget; for(d = 0; d < nDates; d++){ CoinPackedVector row; rowBudget.push_back(row); } nRows = 0; pairIndex = 0; for(vi = pairsAD.begin(); vi != pairsAD.end(); vi++){ adP = m_instance.getIndexADInv(*vi); a = adP.first; d = adP.second; //--- //--- sum{a in A} (f+[a,d] - f-[a,d]) <= B[d] //--- rowBudget[d].insert(getColOffset_fp() + pairIndex, 1.0); rowBudget[d].insert(getColOffset_fm() + pairIndex, -1.0); //--- //--- f+[a,d] - f-[a,d] = //--- a[a,d] sum{t in T} (t/n) x1[a,t] + //--- b[a,d] x2[a] + //--- c[a,d] sum{t in T} (t/n) z[a,t] + //--- d[a,d] x3[a] + //--- e[a,d] //--- CoinPackedVector row; string rowName = "demand_def(a_" + m_instance.getAtmName(a) + ",d_" + m_instance.getDateName(d) + ")"; row.insert(colIndex_fp(pairIndex), 1.0); row.insert(colIndex_fm(pairIndex), -1.0); coefA = -a_ad[*vi] / nSteps; coefC = -c_ad[*vi] / nSteps; if(m_appParam.UseTightModel){ for(t = 0; t <= nSteps; t++){ row.insert(colIndex_x1(a,t), t * coefA); row.insert(colIndex_z (a,t), t * coefC); } } else{ for(t = 0; t < nSteps; t++){ row.insert(colIndex_x1(a,t), (t+1) * coefA); row.insert(colIndex_z (a,t), (t+1) * coefC); } } row.insert(colIndex_x2(a), -b_ad[*vi]); row.insert(colIndex_x3(a), -d_ad[*vi]); rhs = e_ad[*vi]; model->appendRow(row, rhs, rhs, rowName); nRows++; //--- //--- f-[a,d] <= w[a,d] * v[a,d] //--- CoinPackedVector rowLink; string rowNameLink = "linkv(a_" + m_instance.getAtmName(a) + ",d_" + m_instance.getDateName(d) + ")"; rowLink.insert(colIndex_fm(pairIndex), 1.0); rowLink.insert(colIndex_v (pairIndex), -w_ad[*vi]); model->appendRow(rowLink, -DecompInf, 0.0, rowNameLink); nRows++; pairIndex++; } for(d = 0; d < nDates; d++){ string rowNameBudget = "budget(d_" + m_instance.getDateName(d) + ")"; model->appendRow(rowBudget[d], -DecompInf, B_d[d], rowNameBudget); nRows++; } //--- //--- for a in A: //--- sum{t in T} x1[a,t] <= 1 //--- for a in A, t in T: //--- z[a,t] <= x1[a,t], //--- z[a,t] <= x2[a], //--- z[a,t] >= x1[a,t] + x2[a] - 1. //--- //THINK: if you use this, shouldn't we postprocess z=x1*x2? // putting those constaints in master are unneccessary... // in fact, why not just do that in block version too... //for(a = 0; a < nAtms; a++){ //nRows += createConZtoX(model, a); //nRows += createConPickOne(model, a); //} assert(nRows <= nRowsMax); //--- //--- create model columns //--- createModelColumns(model); UtilPrintFuncEnd(m_osLog, m_classTag, "createModelRelaxCount()", m_appParam.LogLevel, 2); return model; }
// --------------------------------------------------------------------- // 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; }