/*------------------------------------------------------------------------*/ CoinPackedVector * DecompCutPool::createRowReform(const int n_corecols, const CoinPackedVector* row, const DecompVarList& vars) { double coeff; //--- //--- Create a dense row from the original sparse row (in terms of x). //--- double* rowDense = row->denseVector(n_corecols); //--- //--- In order to expand to the reformulated row (in terms of lambda), //--- we need to substitute x = sum{s in F'} s lambda[s] //--- //--- Example - Given a cut: //--- a[1]x[1] + a[2]x[2] >= b //--- a[1]x[1] = a[1] (s1[1] lam[1] + s2[1] lam[2]) //--- a[2]x[2] = a[2] (s1[2] lam[1] + s2[2] lam[2]) //--- So, lam[1]'s coeff = a[1] s1[1] + a[2] s1[2] //--- lam[2]'s coeff = a[1] s2[1] + a[2] s2[2] //--- int col_index = 0; CoinPackedVector* rowReform = new CoinPackedVector(); DecompVarList::const_iterator vli; for (vli = vars.begin(); vli != vars.end(); vli++) { coeff = (*vli)->m_s.dotProduct(rowDense); if (fabs(coeff) > 1.0e-12) { //m_app->m_param.tolerance) rowReform->insert(col_index, coeff); } col_index++; } if (rowReform->getNumElements() == 0) { cerr << "row size 0, don't add it" << endl; UTIL_DELPTR(rowReform); rowReform = 0; } UTIL_DELARR(rowDense); //--- //--- delete the temporary memory //--- UTIL_DELARR(rowDense); return rowReform; }
/*==========================================================================*/ int UtilScaleDblToIntArr(const int arrLen, const double* arrDbl, int* arrInt, const double epstol) { //--- //--- A very simple function to scale an array of doubles to integers. //--- Note: epstol denotes the preferred accuracy, //--- so, we will scale by 1.0/epstol, unless something smaller works. //--- It constructs the scaled array and returns the scale factor. //--- //--- It can also scale oneDbl to oneInt wrt to the array (e.g.., //--- the rhs of row). If oneInt == NULL, then this part is skipped. //--- int i, scaleFactor = 1, n_aFrac = 0, factorToBig = 0; double* arrFrac = NULL; double fractionalPart; double oneOverEps = 1.0 / epstol; //TODO: pass in arrFrac? arrFrac = new double[arrLen]; CoinAssertHint(arrFrac, "Error: Out of Memory"); for (i = 0; i < arrLen; i++) { fractionalPart = UtilFracPart(arrDbl[i]); if (!UtilIsZero(fractionalPart)) { fractionalPart *= oneOverEps; arrFrac[n_aFrac++] = (int)fractionalPart * (double)epstol; } } for (i = 0; i < n_aFrac; i++) { CoinAssertDebug(arrFrac[i] < (INT_MAX / scaleFactor)); arrFrac[i] *= scaleFactor; while (!UtilIsZero(UtilFracPart(arrFrac[i]))) { scaleFactor *= 10; if (scaleFactor >= oneOverEps) { factorToBig = 1; break; } CoinAssertDebug(arrFrac[i] < (INT_MAX / 10)); arrFrac[i] *= 10; CoinAssertDebug(arrFrac[i] >= 0); } if (factorToBig) { break; } } for (i = 0; i < arrLen; i++) { arrInt[i] = (int)(arrDbl[i] * scaleFactor); } UTIL_DELARR(arrFrac); return scaleFactor; }
// --------------------------------------------------------------------- // //THINK: this is specific to PC and DC?? void DecompVarPool::reExpand(const DecompConstraintSet& modelCore, const double tolZero) { //THIS IS WRONG... //in masterSI, we have //A'', convexity, cuts //in modelCore.M we have A'', cuts //the sparseCol that you come out with the end here has things in the wrong //order: //A'', cuts, convexity double* denseCol = new double[modelCore.getNumRows() + 1]; vector<DecompWaitingCol>::iterator vi; for (vi = begin(); vi != end(); vi++) { // --- // --- get dense column = A''s, append convexity constraint on end // --- modelCore.M->times((*vi).getVarPtr()->m_s, denseCol); denseCol[modelCore.getNumRows()] = 1.0; // --- // --- create a sparse column from the dense column // --- CoinPackedVector* sparseCol = UtilPackedVectorFromDense(modelCore.getNumRows() + 1, denseCol, tolZero); (*vi).deleteCol(); (*vi).setCol(sparseCol); } setColsAreValid(true); UTIL_DELARR(denseCol); }
void OSDipApp::createModelMasterOnlys2(vector<int> & masterOnlyCols) { int nBlocks = static_cast<int>(m_blocks.size()); const int nCols = m_osInterface.getVariableNumber(); const double * colLB = m_osInterface.getColLower(); const double * colUB = m_osInterface.getColUpper(); const char * integerVars = m_osInterface.getIntegerColumns(); int nMasterOnlyCols = static_cast<int> (masterOnlyCols.size()); if (m_appParam.LogLevel >= 1) { (*m_osLog) << "nCols = " << nCols << endl; (*m_osLog) << "nMasterOnlyCols = " << nMasterOnlyCols << endl; } if (nMasterOnlyCols == 0) return; int i; vector<int>::iterator vit; for (vit = masterOnlyCols.begin(); vit != masterOnlyCols.end(); vit++) { i = *vit; //THINK: // what-if master-only var is integer and bound is not at integer? DecompConstraintSet * model = new DecompConstraintSet(); model->m_masterOnly = true; model->m_masterOnlyIndex = i; model->m_masterOnlyLB = colLB[i]; //std::cout << "MASTER ONLY LB = " << model->m_masterOnlyLB << std::endl; model->m_masterOnlyUB = colUB[i]; //std::cout << "MASTER ONLY UB = " << model->m_masterOnlyUB << std::endl; //0=cont, 1=integer if(integerVars[i] == '1') model->m_masterOnlyIsInt = true; //model->m_masterOnlyIsInt = integerVars[i] ? true : false; if (m_appParam.ColumnUB < 1.0e15) if (colUB[i] > 1.0e15) model->m_masterOnlyUB = m_appParam.ColumnUB; if (m_appParam.ColumnLB > -1.0e15) if (colLB[i] < -1.0e15) model->m_masterOnlyLB = m_appParam.ColumnLB; m_modelMasterOnly.insert(make_pair(i, model)); //keep track for garbage collection setModelRelax(model, "master_only" + UtilIntToStr(i), nBlocks); nBlocks++; } //free local memory UTIL_DELARR( integerVars); return; }//end createModelMasterOnlys2
//===========================================================================// 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; }
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::createModels() { UtilPrintFuncBegin(m_osLog, m_classTag, "createModels()", m_appParam.LogLevel, 2); int i; int j; const int nCols = m_osInterface.getVariableNumber(); const int nRows = m_osInterface.getConstraintNumber(); try{ //First the define the objective function over the entire variable space //Create the memory for the objective function m_objective = new double[nCols]; for (i = 0; i < nCols; i++) { m_objective[i] = m_osInterface.getObjectiveFunctionCoeff()[i]; //std::cout << "obj coeff = " << m_objective[i] << std::endl; } setModelObjective( m_objective); //--- //--- Construct the core matrix. //--- int nRowsRelax, nRowsCore; nRowsRelax = 0; nRowsCore = 0; std::vector<OtherConstraintOption*> otherConstraintOptions; std::vector<OtherConstraintOption*>::iterator vit; // // Now construct the block matrices // int *rowsRelax; int whichBlock; DecompConstraintSet *modelRelax = NULL; std::set<int> blockVars; //variables indexes in the specific block std::set<int> blockVarsAll; //all variable indexes that appear in a block std::set<int> blockConAll; //all constraint indexes that appear in a block std::set<int>::iterator sit; CoinPackedVector *row; int *rowVars; int rowSize; if (m_osInterface.m_osoption != NULL && m_osInterface.m_osoption->getNumberOfOtherConstraintOptions() > 0) { otherConstraintOptions = m_osInterface.m_osoption->getOtherConstraintOptions("Dip"); //iterate over the vector of contraint options for (vit = otherConstraintOptions.begin(); vit != otherConstraintOptions.end(); vit++) { // see if we have a Core Constraint Set if( ( (*vit)->name.compare("constraintSet") == 0) && ( (*vit)->type.compare("Block") == 0)) { //get the block number //ch = new char[(*vit)->value.size() + 1]; //ch[(*vit)->value.size()] = 0; //memcpy(ch, (*vit)->value.c_str(), (*vit)->value.size()); //whichBlock = atoi(ch); //delete ch; whichBlock = atoi( (*vit)->value.c_str() ); // first get the number of constraints in this block nRowsRelax = (*vit)->numberOfCon; rowsRelax = new int[nRowsRelax]; //now get the variable indexes for just this block //first clear indexes from a previous block blockVars.clear(); for (i = 0; i < nRowsRelax; i++) { rowsRelax[i] = (*vit)->con[i]->idx; if( (*vit)->con[i]->idx >= nRows) throw ErrorClass( "found an invalid row index in OSoL file"); m_blocks[ whichBlock].push_back( rowsRelax[i] ); //also add to the set of all rows if (blockConAll.find( (*vit)->con[i]->idx ) == blockConAll.end()) { blockConAll.insert( (*vit)->con[i]->idx ); } //add the variables for this row to the set blockVars row = m_osInterface.getRow(rowsRelax[i]); rowSize = row->getNumElements(); rowVars = row->getIndices(); for (j = 0; j < rowSize; j++) { if (blockVars.find(rowVars[j]) == blockVars.end()) { blockVars.insert(rowVars[j]); } } delete row; }//end for or rows in this block modelRelax = new DecompConstraintSet(); CoinAssertHint(modelRelax, "Error: Out of Memory"); //create the active columns in this block for (sit = blockVars.begin(); sit != blockVars.end(); sit++) { modelRelax->activeColumns.push_back( *sit); //insert into the all variables set also, but throw an execption //if already there -- same variable cannot be in more than one block if (blockVarsAll.find( *sit) == blockVarsAll.end()) { blockVarsAll.insert (*sit); }else{ throw ErrorClass("Variable " + UtilIntToStr(*sit) + " appears in more than one block"); } } // // if (m_appParam.LogLevel >= 3) { (*m_osLog) << "Active Columns : " << whichBlock << endl; UtilPrintVector(modelRelax->activeColumns, m_osLog); } createModelPartSparse(modelRelax, nRowsRelax, rowsRelax); //does not work for cutting planes //createModelPart(modelRelax, nRowsRelax, rowsRelax); //modelRelax->fixNonActiveColumns(); m_modelR.insert(make_pair(whichBlock + 1, modelRelax)); setModelRelax(modelRelax, "relax" + UtilIntToStr(whichBlock), whichBlock); if (m_appParam.LogLevel >= 3) { (*m_osLog) << std::endl << std::endl; (*m_osLog) << "HERE COMES THE DUPLICATION (WHEN createModelPartSparse USED)" << std::endl; } UtilPrintVector( modelRelax->activeColumns, m_osLog); //free local memory UTIL_DELARR( rowsRelax); } }//end for over constraint options }// if on ospton null //get the core constraints -- constraints NOT in a block int *rowsCore = NULL; int kount = 0; nRowsCore = nRows - blockConAll.size(); if(nRowsCore <= 0) throw ErrorClass("We need at least one coupling constraint"); rowsCore = new int[nRowsCore]; for(i = 0; i < nRows; i++){ if (blockConAll.find( i ) == blockConAll.end() ){ rowsCore[ kount++] = i; } } if( kount != nRowsCore) throw ErrorClass("There was an error counting coupling constraints"); DecompConstraintSet * modelCore = new DecompConstraintSet(); createModelPart(modelCore, nRowsCore, rowsCore); setModelCore(modelCore, "core"); //--- //--- save a pointer so we can delete it later //--- m_modelC = modelCore; //get the master only variables //modelCore->masterOnlyCols.push_back(i); for (i = 0; i < nCols; i++) { if (blockVarsAll.find(i) == blockVarsAll.end()) { modelCore->masterOnlyCols.push_back(i); std::cout << "MASTER ONLY VARIABLE " << i << std::endl; } } //--- //--- create an extra "empty" block for the master-only vars //--- since I don't know what OSI will do with empty problem //--- we will make column bounds explicity rows //--- int nMasterOnlyCols = static_cast<int> (modelCore->masterOnlyCols.size()); if (nMasterOnlyCols) { if (m_appParam.LogLevel >= 1) (*m_osLog) << "Create model part Master-Only." << endl; createModelMasterOnlys2(modelCore->masterOnlyCols); } UtilPrintFuncBegin(m_osLog, m_classTag, "printCurrentProblem()", m_appParam.LogLevel, 2); //free local memory UTIL_DELARR( rowsCore); }//end try catch(const ErrorClass& eclass){ throw ErrorClass( eclass.errormsg); } }// end createModels()
//===========================================================================// void OSDipApp::createModelPartSparse(DecompConstraintSet * model, const int nRowsPart, const int * rowsPart) { const int nColsOrig = m_osInterface.getVariableNumber(); const double * rowLB = m_osInterface.getRowLower(); const double * rowUB = m_osInterface.getRowUpper(); const double * colLB = m_osInterface.getColLower(); const double * colUB = m_osInterface.getColUpper(); const char * integerVars = m_osInterface.getIntegerColumns(); //--- //--- set model as sparse //--- model->setSparse(nColsOrig); int nCols, origIndex, newIndex; vector<int>::iterator vit; newIndex = 0; for (vit = model->activeColumns.begin(); vit != model->activeColumns.end(); vit++) { origIndex = *vit; //std::cout << "lower bound = " << colLB[origIndex] << std::endl; //std::cout << "upper bound = " << colUB[origIndex] << std::endl; model->pushCol(colLB[origIndex], colUB[origIndex], integerVars[origIndex] == '0' ? false : true, origIndex); if(integerVars[origIndex] == 0) std::cout << "HERE I AM" << std::endl; //--- //--- big fat hack... we don't deal with dual rays yet, //--- so, we assume subproblems are bounded //--- if (m_appParam.ColumnUB < 1.0e15) { if (colUB[origIndex] > 1.0e15) { model->colUB[newIndex] = m_appParam.ColumnUB; } } if (m_appParam.ColumnLB > -1.0e15) { if (colLB[origIndex] < -1.0e15) { model->colLB[newIndex] = m_appParam.ColumnLB; } } if (m_appParam.UseNames) { //const char * colName = m_osInterface.columnName(origIndex); const char * colName = m_osInterface.getConstraintNames()[origIndex].c_str(); if (colName) model->colNames.push_back(colName); } newIndex++; } nCols = static_cast<int> (model->activeColumns.size()); assert(static_cast<int> (model->colLB.size()) == nCols); assert(static_cast<int> (model->colUB.size()) == nCols); model->M = new CoinPackedMatrix(false, 0.0, 0.0); if (!model->M) throw UtilExceptionMemory("createModels", "OSDipApp"); model->M->setDimensions(0, nCols); model->reserve(nRowsPart, nCols); //--- //--- for each row in rowsPart, create the row using sparse mapping //--- int i, k, r, begInd; const map<int, int> & origToSparse = model->getMapOrigToSparse(); const CoinPackedMatrix * M = m_osInterface.getCoinPackedMatrix(); const int * matInd = M->getIndices(); const CoinBigIndex * matBeg = M->getVectorStarts(); const int * matLen = M->getVectorLengths(); const double * matVal = M->getElements(); const int * matIndI = NULL; const double * matValI = NULL; vector<CoinBigIndex> & rowBeg = model->m_rowBeg;//used as temp vector<int> & rowInd = model->m_rowInd;//used as temp vector<double> & rowVal = model->m_rowVal;//used as temp map<int, int>::const_iterator mit; begInd = 0; rowBeg.push_back(0); for (i = 0; i < nRowsPart; i++) { r = rowsPart[i]; if (m_appParam.UseNames) { const char * rowName = m_osInterface.getConstraintNames()[r].c_str(); if (rowName) model->rowNames.push_back(rowName); } model->rowLB.push_back(rowLB[r]); model->rowUB.push_back(rowUB[r]); matIndI = matInd + matBeg[r]; matValI = matVal + matBeg[r]; for (k = 0; k < matLen[r]; k++) { origIndex = matIndI[k]; mit = origToSparse.find(origIndex); assert(mit != origToSparse.end()); rowInd.push_back(mit->second); rowVal.push_back(matValI[k]); } begInd += matLen[r]; rowBeg.push_back(begInd); } model->M->appendRows(nRowsPart, &rowBeg[0], &rowInd[0], &rowVal[0]); //free local memory rowBeg.clear(); rowInd.clear(); rowVal.clear(); UTIL_DELARR( integerVars); }
//===========================================================================// void OSDipApp::createModelPart(DecompConstraintSet * model, const int nRowsPart, const int * rowsPart) { const int nCols = m_osInterface.getVariableNumber(); const double * rowLB = m_osInterface.getRowLower(); const double * rowUB = m_osInterface.getRowUpper(); const double * colLB = m_osInterface.getColLower(); const double * colUB = m_osInterface.getColUpper(); const char * integerVars = m_osInterface.getIntegerColumns(); std::cout << "STARTING createModelPart" << std::endl; model->M = new CoinPackedMatrix(false, 0.0, 0.0); if (!model->M) throw UtilExceptionMemory("createModels", "OSDipApp"); model->reserve(nRowsPart, nCols); model->M->submatrixOf(*m_osInterface.m_coinpm, nRowsPart, rowsPart); //--- //--- set the row upper and lower bounds //--- set the col upper and lower bounds //--- m_appParam.UseNames = true; int i, r; for (i = 0; i < nRowsPart; i++) { r = rowsPart[i]; if (m_appParam.UseNames == true) { const char * rowName = m_osInterface.getConstraintNames()[r].c_str(); // std::cout << "Row Name = " << m_osInterface.getConstraintNames()[r] << std::endl; if (rowName) model->rowNames.push_back(rowName); //std::cout << "Row Name = " << m_osInterface.getConstraintNames()[r] << std::endl; } model->rowLB.push_back(rowLB[r]); model->rowUB.push_back(rowUB[r]); } copy(colLB, colLB + nCols, back_inserter(model->colLB)); copy(colUB, colUB + nCols, back_inserter(model->colUB)); //--- //--- big fat hack... we don't deal with dual rays yet, //--- so, we assume subproblems are bounded //--- //--- NOTE: might also need to tighten LBs //--- //--- Too small - ATM infeasible! //--- Too big - round off issues with big coeffs in //--- master-only vars //--- //--- TODO: need extreme rays or bounded subproblems from user //--- if (m_appParam.ColumnUB < 1.0e15) { for (i = 0; i < nCols; i++) { if (colUB[i] > 1.0e15) { model->colUB[i] = m_appParam.ColumnUB; } } } if (m_appParam.ColumnLB > -1.0e15) { for (i = 0; i < nCols; i++) { if (colLB[i] < -1.0e15) { model->colLB[i] = m_appParam.ColumnLB; } } } //--- //--- set the indices of the integer variables of modelRelax //--- also set the column names, if they exist //--- for (i = 0; i < nCols; i++) { if (m_appParam.UseNames == true) { //const char * colName = m_osInterface.columnName(i); const char * colName = m_osInterface.getVariableNames()[i].c_str(); if (colName) model->colNames.push_back(colName); } if ( (integerVars != NULL) && integerVars[i] == '1' ) { //std::cout << "WE HAVE AN INTEGER VARIABLE " << std::endl; model->integerVars.push_back(i); } } //free local memory UTIL_DELARR( integerVars); }
// --------------------------------------------------------------------- // void MMKP_MCKnap::solveMCKnap(const double * redCost, const double * origCost, vector<int> & solInd, vector<double> & solEls, double & varRedCost, double & varOrigCost){ int i, j, colIndex; //--- //--- Pisinger's code (mcknap) solves a max problem. And, it assumes //--- all positive costs/profits and weights. //--- memcpy(m_costDbl, redCost, m_nCols * sizeof(double)); #ifdef MMKP_MCKNAP_DEBUG for(i = 0; i < m_nCols; i++){ pair<int,int> ij = getIndexInv(i); printf("\ncostDbl[%d: %d, %d]: %g", i, ij.first, ij.second, m_costDbl[i]); } #endif //--- //--- flip reduced costs (max c == min -c) //--- UtilNegateArr(m_nCols, m_costDbl); //--- //--- add a constant so that all vertex weights are positive, inc alpha //--- double offset = 0.0; double minrc = *min_element(m_costDbl, m_costDbl + m_nCols); #ifdef MMKP_MCKNAP_DEBUG printf("\nminrc = %g", minrc); #endif if(minrc <= 0){ offset = -minrc + 1; UtilAddOffsetArr(m_nCols, offset, m_costDbl); } //--- //--- now scale the double array to an integer array //--- //TODO: magic number - have to be careful of overflow... m_cscale = UtilScaleDblToIntArr(m_nCols, m_costDbl, m_cost, MCKP_EPSILON); #ifdef MMKP_MCKNAP_DEBUG double diff; printf("\noffset = %g", offset); printf("\nm_cscale = %d", m_cscale); printf("\nm_wscale = %d", m_wscale); printf("\ncapacity = %d", m_capacity); for(i = 0; i < m_nCols; i++){ pair<int,int> ij = getIndexInv(i); diff = fabs((m_costDbl[i]*m_cscale) - m_cost[i]); printf("\n[%d: %d, %d]: dbl-> %12.5f int-> %8d diff-> %12.5f", i, ij.first, ij.second, m_costDbl[i], m_cost[i], diff); assert( diff < 0.99 ); } #endif //--- //--- sanity check //--- if any cost value becomes negative that //--- denotes an overflow happened //--- TODO: not sure how to do this scaling safely and //--- accurately //--- for(i = 0; i < m_nCols; i++){ if(m_cost[i] < 0){ throw UtilException("negative cost value", "solveMCKnap", "MMKP_MCKnap"); } } //--- //--- setup the data structures for mcknap //--- itemset * setPtr = m_setset->fset; itemrec * recPtr = NULL; itemrec * recSolPtr = NULL; //THINK: reset - assume memory is still there m_setset->size = m_nGroupRows; setPtr = m_setset->fset; for(i = 0; i < m_setset->size; i++){ setPtr->size = m_nGroupCols; recPtr = setPtr->fset; setPtr->lset = setPtr->fset + setPtr->size - 1; setPtr++; } m_setset->lset = m_setset->fset + m_setset->size - 1; colIndex = 0; setPtr = m_setset->fset; for(i = 0; i < m_setset->size; i++){ recPtr = setPtr->fset; for(j = 0; j < setPtr->size; j++){ recPtr->i = i; recPtr->j = j; recPtr->psum = m_cost[colIndex]; recPtr->wsum = m_weight[colIndex]; #ifdef MMKP_MCKNAP_DEBUG printf("\ncolIndex: %d i: %d, j: %d, p: %d, w: %d", colIndex, i, j, recPtr->psum, recPtr->wsum); #endif recPtr++; colIndex++; } setPtr++; } itemrec * solRec = new itemrec[m_setset->size]; double minObj = 99999; // long minObj = 99999; int status = minmcknapSolve(m_capacity, m_setset, solRec, &minObj); solInd.reserve(m_nGroupRows); solEls.reserve(m_nGroupRows); UtilFillN<double>(solEls, m_nGroupRows, 1.0); varRedCost = 0.0; varOrigCost = 0.0; //--- //--- TODO: //--- this is painful to get optimal assignments //--- wrote Dr. Pisinger for help (7/4/07) //--- NOTE: optsol is NOT reentrant //--- //CoinAssert(optsol.size == 1); //TODO #ifdef MMKP_MCKNAP_DEBUG printf("\nstatus=%d minObj=%g\n", status, minObj); #endif switch(status){ case MCKNAP_RC_INF: assert(status != MCKNAP_RC_INF); break; case MCKNAP_RC_OK: { //--- //--- need to unravel: //--- s * ((-x) + offset) //--- double solObj = minObj / static_cast<double>(m_cscale); solObj -= (offset * m_setset->size); solObj = -solObj; #ifdef MMKP_MCKNAP_DEBUG printf("\nminObj = %g, solObj = %g", minObj, solObj); #endif int c, i, j, g; for(g = 0; g < m_setset->size; g++){ recSolPtr = &solRec[g]; i = recSolPtr->i;//was missing - STOP j = recSolPtr->j;//was missing c = getIndexIJ(i, j); solInd.push_back(c); varRedCost += redCost[c]; varOrigCost += origCost[c]; #ifdef MMKP_MCKNAP_DEBUG printf("\nc: %d = (%d,%d) redCost: %g cost: %d wt: %d", c, i, j, redCost[c], m_cost[c], m_weight[c]); #endif /*for(c = 0; c < m_nCols; c++){ //but could have more than one equal in p and w! //this is NOT the right way to get back optimal if((m_cost[c] == recSolPtr->psum) && (m_weight[c] == recSolPtr->wsum)){ //TODO: why should the user have to calc origCost? //framework should probably do that solInd.push_back(c); varRedCost += redCost[c]; varOrigCost += origCost[c]; #ifdef MMKP_MCKNAP_DEBUG pair<int,int> ij = getIndexInv(c); printf("\nc: %d = (%d,%d) redCost: %g cost: %d wt: %d", c, ij.first, ij.second, redCost[c], m_cost[c], m_weight[c]); #endif break; } }*/ } //UtilPrintVector<int>(solInd); break; } case MCKNAP_RC_TRIVIAL_MAXSUM: fflush(stdout); //maxwsum <= c, so just pick the max elements from each group solveTrivialMaxSum(redCost, origCost, solInd, varRedCost, varOrigCost); #ifdef MMKP_MCKNAP_DEBUG printf("trivial sum varRedCost=%g varOrigCost=%g\n", varRedCost, varOrigCost); #endif break; default: assert(0); } UTIL_DELARR(solRec); }
/** * 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 ATM_Instance::generateRandom(const int nAtms, const int nDates, const int seed){ /* Data from original: \\ordsrv3\ormp\sas\ATM_Badshah\atm_20ATMS_3\atm_doc nDates=272, nAtms=20, nPairs=4730 (max=5440) proc means data=FTPLIB.amul_atms_dates; var withdrawal allocation NET_IMPACT_AVG NET_IMPACT_STD NORMAL_AVG NORMAL_STD TS1 TS2; run; The MEANS Procedure Variable Label Std Dev Mean ................................................................ WITHDRAWAL WITHDRAWAL 1456368.37 1457077.41 ALLOCATION ALLOCATION 1752334.72 2068196.66 NET_IMPACT_AVG NET_IMPACT_AVG 0.8990607 1.1961954 NET_IMPACT_STD NET_IMPACT_STD 1.8979644 1.4240460 NORMAL_AVG NORMAL_AVG 1352731.38 1440849.71 NORMAL_STD NORMAL_STD 352658.50 364123.38 TS1 TS1 1267244.80 1371637.24 S2 TS2 1246864.33 1361954.95 ................................................................ Variable Label Minimum Maximum ................................................................ WITHDRAWAL WITHDRAWAL 8000.00 7080400.00 ALLOCATION ALLOCATION 100000.00 7020000.00 NET_IMPACT_AVG NET_IMPACT_AVG 0.0053384 18.7119586 NET_IMPACT_STD NET_IMPACT_STD 0.0046809 54.0086478 NORMAL_AVG NORMAL_AVG 38864.52 4375539.71 NORMAL_STD NORMAL_STD 26833.85 1141006.06 TS1 TS1 25245.45 5250885.71 TS2 TS2 700.0000000 4182207.14 ................................................................ for{<a,d> in ATMS_DATES_THIS} do; CA[a,d] = (normal_avg[a,d] * net_impact_avg[a,d] - ts_period_2[a,d]); CB[a,d] = (ts_period_1[a,d] - ts_period_2[a,d]); CC[a,d] = (ts_period_2[a,d] - ts_period_1[a,d]); CD[a,d] = (normal_std[a,d] * net_impact_std[a,d]); CE[a,d] = (-actual_withdrawal[a,d] + ts_period_2[a,d]); end; These numbers are annoying big and causing lots of numerical round-off issues. So, Let's scale by 1000. */ #define STDD 0 #define MEAN 1 #define MIN 2 #define MAX 3 double s_withdrawal[4] = {1456368, 1457077, 8000, 7080400}; double s_allocation[4] = {1752334, 2068196, 100000, 7020000}; double s_netimpactAve[4] = {0.8990607, 1.1961954, 0.0053384, 18.7119586}; double s_netimpactStd[4] = {1.8979644, 1.4240460, 0.0046809, 54.0086478}; double s_normalAve[4] = {13527318, 1440849, 38864, 4375539.71}; double s_normalStd[4] = {352658, 364123, 26833, 1141006}; double s_ts1[4] = {1267244, 1371637, 25245, 5250885}; double s_ts2[4] = {1246864, 1361954, 700, 4182207}; double scale = 1000; int i; for(i = 0; i < 4; i++){ s_withdrawal[i] /= scale; s_allocation[i] /= scale; s_normalAve[i] /= scale; s_normalStd[i] /= scale; s_ts1[i] /= scale; s_ts2[i] /= scale; } int nAD = nAtms * nDates; double * withdrawal = new double[nAD]; double * allocation = new double[nAD]; double * netimpactAve = new double[nAD]; double * netimpactStd = new double[nAD]; double * normalAve = new double[nAD]; double * normalStd = new double[nAD]; double * ts1 = new double[nAD]; double * ts2 = new double[nAD]; assert(withdrawal && allocation && netimpactAve && netimpactStd && normalAve && normalStd && ts1 && ts2); string fileNameAD = "atm_randAD_"; fileNameAD += UtilIntToStr(nAtms) + "_"; fileNameAD += UtilIntToStr(nDates) + "_"; fileNameAD += UtilIntToStr(seed) + ".txt"; string fileNameA = "atm_randA_"; fileNameA += UtilIntToStr(nAtms) + "_"; fileNameA += UtilIntToStr(nDates) + "_"; fileNameA += UtilIntToStr(seed) + ".txt"; string fileNameD = "atm_randD_"; fileNameD += UtilIntToStr(nAtms) + "_"; fileNameD += UtilIntToStr(nDates) + "_"; fileNameD += UtilIntToStr(seed) + ".txt"; ofstream osAD, osA, osD; UtilOpenFile(osAD, fileNameAD.c_str()); UtilOpenFile(osA, fileNameA.c_str()); UtilOpenFile(osD, fileNameD.c_str()); int a, d; srand(seed); //--- //--- generate 'raw data' in N[mean,std-dev] //--- int index = 0;//a * nDates + d for(a = 0; a < nAtms; a++){ for(d = 0; d < nDates; d++){ do{ withdrawal[index] = UtilNormRand(s_withdrawal[MEAN] , s_withdrawal[STDD]); }while( withdrawal[index] < s_withdrawal[MIN] || withdrawal[index] > s_withdrawal[MAX]); do{ allocation[index] = UtilNormRand(s_allocation[MEAN] , s_allocation[STDD]); }while( allocation[index] < s_allocation[MIN] || allocation[index] > s_allocation[MAX]); do{ netimpactAve[index] = UtilNormRand(s_netimpactAve[MEAN], s_netimpactAve[STDD]); }while( netimpactAve[index] < s_netimpactAve[MIN] || netimpactAve[index] > s_netimpactAve[MAX]); do{ netimpactStd[index] = UtilNormRand(s_netimpactStd[MEAN], s_netimpactStd[STDD]); }while( netimpactStd[index] < s_netimpactStd[MIN] || netimpactStd[index] > s_netimpactStd[MAX]); do{ normalAve[index] = UtilNormRand(s_normalAve[MEAN] , s_normalAve[STDD]); }while( normalAve[index] < s_normalAve[MIN] || normalAve[index] > s_normalAve[MAX]); do{ normalStd[index] = UtilNormRand(s_normalStd[MEAN] , s_normalStd[STDD]); }while( normalStd[index] < s_normalStd[MIN] || normalStd[index] > s_normalStd[MAX]); do{ ts1[index] = UtilNormRand(s_ts1[MEAN] , s_ts1[STDD]); }while( ts1[index] < s_ts1[MIN] || ts1[index] > s_ts1[MAX]); do{ ts2[index] = UtilNormRand(s_ts2[MEAN] , s_ts2[STDD]); }while ( ts2[index] < s_ts2[MIN] || ts2[index] > s_ts2[MAX]); index++; } } //--- //--- generate coefficients //--- //CA[a,d] = (normal_avg[a,d] * net_impact_avg[a,d] - ts_period_2[a,d]); //CB[a,d] = (ts_period_1[a,d] - ts_period_2[a,d]); //CC[a,d] = (ts_period_2[a,d] - ts_period_1[a,d]); //CD[a,d] = (normal_std[a,d] * net_impact_std[a,d]); //CE[a,d] = (-actual_withdrawal[a,d] + ts_period_2[a,d]); double * ca = new double[nAD]; double * cb = new double[nAD]; double * cc = new double[nAD]; double * cd = new double[nAD]; double * ce = new double[nAD]; assert(ca && cb && cc && cd && ce); index = 0; osAD << "a\td\tCA\tCB\tCC\tCD\tCD\tCE\tCW\n"; for(a = 0; a < nAtms; a++){ for(d = 0; d < nDates; d++){ ca[index] = normalAve[index] * netimpactAve[index] - ts2[index]; cb[index] = ts1[index] - ts2[index]; cc[index] = -cb[index]; cd[index] = normalStd[index] * netimpactStd[index]; ce[index] = -withdrawal[index] + ts2[index]; osAD << "ATM" << UtilIntToStr(a) << "\t" << "DATE" << UtilIntToStr(d) << "\t" << setw(10) << UtilDblToStr(ca[index],0) << setw(10) << UtilDblToStr(cb[index],0) << setw(10) << UtilDblToStr(cc[index],0) << setw(10) << UtilDblToStr(cd[index],0) << setw(10) << UtilDblToStr(ce[index],0) << setw(10) << UtilDblToStr(withdrawal[index],0) << "\n"; index++; } } //--- //--- generate B and K //--- //--- f(a,d) = ca*x1[a] + cb*x2[a] + cc*x1[a]*x2[a] + cd*x3[a] + ce //--- x1,x2 in {0,1}, x3 >= 0 //--- //--- sum{a} f(a,d) <= B[d], for d //--- |{d in D | f(a,d) <= 0} <= K[a], for a //--- double x01, x1, x2, x3; double * f = new double[nAD]; assert(f); index = 0; for(a = 0; a < nAtms; a++){ x01 = UtilURand(0.0,1.0); x1 = x01 >= 0.5 ? 1 : 0; x01 = UtilURand(0.0,1.0); x2 = x01 >= 0.5 ? 1 : 0; x3 = UtilURand(0.0,1.0); printf("x1=%g x2=%g x3=%g\n", x1, x2, x3); for(d = 0; d < nDates; d++){ f[index] = ca[index] * x1; f[index] += cb[index] * x2; f[index] += cc[index] * x1 * x2; f[index] += cd[index] * x3; f[index] += ce[index]; index++; } } double * B = new double[nDates]; double maxB = -1e20; for(d = 0; d < nDates; d++){ B[d] = 0; for(a = 0; a < nAtms; a++){ B[d] += f[a * nDates + d]; } if(B[d] > maxB) maxB=B[d]; } //--- //--- B=budget for cash flow //--- if negative does not make sense //--- protect against this //--- osD << "d\tB\n"; for(d = 0; d < nDates; d++){ if(B[d] < 0) B[d] = maxB / 2.0; osD << "DATE" << UtilIntToStr(d) << "\t" << setw(10) << UtilDblToStr(B[d],0) << endl; } int * K = new int[nAtms]; int maxK = 0; index = 0; for(a = 0; a < nAtms; a++){ K[a] = 0; for(d = 0; d < nDates; d++){ K[a] += f[index] <= 0 ? 1 : 0; index++; } if(K[a] > maxK) maxK=K[a]; } //--- //--- randomize it (and tighten constraint) //--- osA << "a\tK\n"; for(a = 0; a < nAtms; a++){ //K[a] -= UtilURand(1, maxK/4); osA << "ATM" << UtilIntToStr(a) << "\t" << setw(10) << K[a] << endl; } osAD.close(); osA.close(); osD.close(); UTIL_DELARR(withdrawal); UTIL_DELARR(allocation); UTIL_DELARR(netimpactAve); UTIL_DELARR(netimpactStd); UTIL_DELARR(normalAve); UTIL_DELARR(normalStd); UTIL_DELARR(ts1); UTIL_DELARR(ts2); UTIL_DELARR(ca); UTIL_DELARR(cb); UTIL_DELARR(cc); UTIL_DELARR(cd); UTIL_DELARR(ce); UTIL_DELARR(f); UTIL_DELARR(B); UTIL_DELARR(K); }