/home/coin/SVN-release/OS-2.4.1/examples/osDip/OSDipApp.cpp

Go to the documentation of this file.
00001 //===========================================================================//
00002 // This file is part of the Decomp Solver Framework.                         //
00003 //                                                                           //
00004 // Decomp is distributed under the Common Public License as part of the      //
00005 // COIN-OR repository (http://www.coin-or.org).                              //
00006 //                                                                           //
00007 // Author: Matthew Galati, Lehigh University  
00008 // Heavily edited by Kipp Martin, University of Chicago
00009 //                                                                           //
00010 // Copyright (C) 2002-2009, Lehigh University, Matthew Galati, and Ted Ralphs//
00011 // All Rights Reserved.                                                      //
00012 //===========================================================================//
00013 
00014 //===========================================================================//
00015 #include "OSDipApp.h"
00016 //===========================================================================//
00017 #include "DecompVar.h"
00018 #include  "OSDipBlockSolver.h"
00019 #include  "OSDipBlockCoinSolver.h"
00020 
00021 
00022 
00023 void OSDipApp::initializeApp(UtilParameters & utilParam) {
00024 
00025         UtilPrintFuncBegin(m_osLog, m_classTag, "initializeApp()",
00026                         m_appParam.LogLevel, 2);
00027 
00028         //---
00029         //--- get application parameters
00030         //---
00031         m_appParam.getSettings(utilParam);
00032         if (m_appParam.LogLevel >= 1)
00033                 m_appParam.dumpSettings(m_osLog);
00034 
00035         try {
00036 
00037                 //---
00038                 //--- read OSiL instance
00039                 //
00040                 if (m_appParam.OSiLFile.size() <= 1)
00041                         throw ErrorClass("An OSiL file not specified in the parameter file");
00042                 std::string osilFile = m_appParam.DataDir + UtilDirSlash()
00043                                 + m_appParam.OSiLFile;
00044                 m_osInterface.readOSiL( osilFile);
00045 
00046                 //---
00047                 //--- read OSoL instance --  it is not necessary, if not there
00048                 //--  all constraints become block constraints
00049                 //
00050                 //if(m_appParam.OSoLFile.size() <=  1) throw ErrorClass("An OSoL file not specified in the parameter file");
00051                 if (m_appParam.OSoLFile.size() > 0) {
00052                         std::string osolFile = m_appParam.DataDir + UtilDirSlash()
00053                                         + m_appParam.OSoLFile;
00054                         m_osInterface.readOSoL( osolFile);
00055                 }
00056 
00057                 //get relevant sets and vectors
00058                 //first get a set of core constraint indexes 
00059                 m_coreConstraintIndexes = m_osInterface.getCoreConstraintIndexes();
00060 
00061                 // next get a vector of sets, where each set is the
00062                 // variable indexes for a block
00063                 m_blockVars = m_osInterface.getBlockVarIndexes();
00064                 
00065                 //get the solver factory for each block
00066                  m_blockFactories = m_osInterface.getBlockFactories();
00067 
00068                 //finally get an osinstance for each block
00069                 m_blockOSInstances = m_osInterface.getBlockOSInstances();
00070                 
00071                 
00072 
00073                 //loop over the instances and generate a solver for each block
00074                 std::vector<OSInstance*>::iterator vit1;
00075                 
00076                 std::string solverFactory;
00077                 int whichBlock = 0;
00078 
00079                 OSDipBlockSolver *solver = NULL;
00080                 factoryInit  = new OSDipFactoryInitializer();
00081                 
00082                 for (vit1 = m_blockOSInstances.begin(); vit1
00083                                 != m_blockOSInstances.end(); vit1++) {
00084                         
00085                         //kipp check for a valid name here -- 
00086                         if( m_blockFactories[ whichBlock].size()  > 0){
00087                                 
00088                                 solverFactory =  m_blockFactories[ whichBlock];
00089                                 
00090                         }else{
00091                                 //give it the default factory in the parameter file
00092                                 solverFactory =  m_appParam.solverFactory;
00093                                 
00094                         }
00095                         
00096                         
00097                         
00098                         
00099                         OSDipBlockSolverFactory::factories[ solverFactory]->osinstance = *vit1;
00100                         OSDipBlockSolverFactory::factories[ solverFactory]->osoption = m_osInterface.m_osoption;
00101                         solver = OSDipBlockSolverFactory::factories[ solverFactory]->create();
00102                         solver->m_whichBlock  = whichBlock;
00103                         m_osDipBlockSolver.push_back( solver);
00104                         
00105                         whichBlock++;
00106 
00107                 }
00108 
00109                 //get a list of all variables in block
00110                 std::vector<std::set<int> >::iterator vit;
00111                 std::set<int>::iterator sit;
00112                 std::set<int> blockVar;
00113 
00114                 for (vit = m_blockVars.begin(); vit != m_blockVars.end(); vit++) {
00115 
00116                         blockVar = *vit;
00117 
00118                         for (sit = blockVar.begin(); sit != blockVar.end(); sit++) {
00119 
00120                                 if (m_blockVarsAll.find(*sit) == m_blockVarsAll.end()) {
00121                                         m_blockVarsAll.insert(*sit);
00122                                 }
00123 
00124                         }
00125 
00126                 }
00127 
00128                 blockVar.clear();
00129 
00130                 //---
00131                 //--- create models
00132                 //---
00133                 createModels();
00134 
00135                 //some testing
00185         } catch (const ErrorClass& eclass) {
00186 
00187                 throw ErrorClass(eclass.errormsg);
00188 
00189         }
00190 
00191         UtilPrintFuncEnd(m_osLog, m_classTag, "initializeApp()",
00192                         m_appParam.LogLevel, 2);
00193 
00194 }//end initializeApp
00195 
00196 //===========================================================================//
00197 void OSDipApp::createModelPart(DecompConstraintSet * model,
00198                 const int nRowsPart, const int * rowsPart) {
00199 
00200         const int nCols = m_osInterface.getVariableNumber();
00201         const double * rowLB = m_osInterface.getRowLower();
00202         const double * rowUB = m_osInterface.getRowUpper();
00203         const double * colLB = m_osInterface.getColLower();
00204         const double * colUB = m_osInterface.getColUpper();
00205         const char * integerVars = m_osInterface.getIntegerColumns();
00206 
00207         std::cout << "STARTING createModelPart" << std::endl;
00208 
00209         model->M = new CoinPackedMatrix(false, 0.0, 0.0);
00210 
00211         if (!model->M)
00212                 throw UtilExceptionMemory("createModels", "OSDipApp");
00213         model->reserve(nRowsPart, nCols);
00214         model->M->submatrixOf(*m_osInterface.m_coinpm, nRowsPart, rowsPart);
00215 
00216         //---
00217         //--- set the row upper and lower bounds
00218         //--- set the col upper and lower bounds
00219         //---
00220         m_appParam.UseNames = true;
00221         int i, r;
00222         for (i = 0; i < nRowsPart; i++) {
00223                 r = rowsPart[i];
00224                 if (m_appParam.UseNames) {
00225                         const char * rowName =
00226                                         m_osInterface.getConstraintNames()[r].c_str();
00227                         //              std::cout << "Row Name = " << m_osInterface.getConstraintNames()[r] << std::endl;
00228                         if (rowName)
00229                                 model->rowNames.push_back(rowName);
00230 
00231                         //std::cout << "Row Name = " << m_osInterface.getConstraintNames()[r] << std::endl;
00232                 }
00233                 model->rowLB.push_back(rowLB[r]);
00234                 model->rowUB.push_back(rowUB[r]);
00235         }
00236         copy(colLB, colLB + nCols, back_inserter(model->colLB));
00237         copy(colUB, colUB + nCols, back_inserter(model->colUB));
00238 
00239         //---
00240         //--- big fat hack... we don't deal with dual rays yet,
00241         //---  so, we assume subproblems are bounded
00242         //---
00243         //--- NOTE: might also need to tighten LBs
00244         //---
00245         //--- Too small - ATM infeasible!
00246         //--- Too big   - round off issues with big coeffs in 
00247         //---             master-only vars
00248         //---
00249         //--- TODO: need extreme rays or bounded subproblems from user
00250         //---
00251 
00252 
00253         if (m_appParam.ColumnUB < 1.0e15) {
00254                 for (i = 0; i < nCols; i++) {
00255                         if (colUB[i] > 1.0e15) {
00256                                 model->colUB[i] = m_appParam.ColumnUB;
00257                         }
00258                 }
00259         }
00260         if (m_appParam.ColumnLB > -1.0e15) {
00261                 for (i = 0; i < nCols; i++) {
00262                         if (colLB[i] < -1.0e15) {
00263                                 model->colLB[i] = m_appParam.ColumnLB;
00264                         }
00265                 }
00266         }
00267 
00268         //---
00269         //--- set the indices of the integer variables of modelRelax
00270         //---  also set the column names, if they exist
00271         //---
00272         for (i = 0; i < nCols; i++) {
00273                 if (m_appParam.UseNames) {
00274                         //const char * colName =  m_osInterface.columnName(i);
00275                         const char * colName = m_osInterface.getVariableNames()[i].c_str();
00276 
00277                         if (colName)
00278                                 model->colNames.push_back(colName);
00279                 }
00280 
00281                 if ((integerVars != NULL) && integerVars[i] == '1') {
00282                         //std::cout  << "WE HAVE AN INTEGER VARIABLE " << std::endl;
00283                         model->integerVars.push_back(i);
00284                 }
00285         }
00286 
00287         //free local memory
00288         UTIL_DELARR(integerVars);
00289 
00290 }
00291 
00292 //===========================================================================//
00293 void OSDipApp::createModels() {
00294 
00295         UtilPrintFuncBegin(m_osLog, m_classTag, "createModels()",
00296                         m_appParam.LogLevel, 2);
00297 
00298         const int nCols = m_osInterface.getVariableNumber();
00299         int nRowsCore;
00300         int *rowsCore = NULL;
00301         int coreRowIndex;
00302         int i;
00303         int numBlocks;
00304         std::set<int>::iterator sit;
00305         std::string modelName;
00306 
00307         try {
00308 
00309                 //First the define the objective function over the entire variable space
00310                 //Create the memory for the objective  function
00311                 m_objective = new double[nCols];
00312                 for (i = 0; i < nCols; i++) {
00313                         m_objective[i] = m_osInterface.getObjectiveFunctionCoeff()[i];
00314                         //std::cout << "obj coeff = " << m_objective[i] << std::endl;
00315                 }
00316                 setModelObjective( m_objective);
00317 
00318                 //define the blocks
00319                 numBlocks = static_cast<int> (m_blockVars.size());
00320                 for (i = 0; i < numBlocks; i++) {
00321 
00322                         modelName = "Block" + UtilIntToStr(i);
00323                         setModelRelax(NULL, modelName, i);
00324                 }
00325 
00326                 //define the core constraints -- constraints NOT in a block
00327 
00328                 nRowsCore = m_coreConstraintIndexes.size();
00329                 if (nRowsCore <= 0)
00330                         throw ErrorClass("We need at least one coupling constraint");
00331 
00332                 rowsCore = new int[nRowsCore];
00333 
00334                 //std::set<int>::iterator sit;  
00335                 coreRowIndex = 0;
00336                 for (sit = m_coreConstraintIndexes.begin(); sit
00337                                 != m_coreConstraintIndexes.end(); sit++) {
00338 
00339                         rowsCore[coreRowIndex++] = *sit;
00340 
00341                 }
00342 
00343                 if (coreRowIndex != nRowsCore)
00344                         throw ErrorClass("There was an error counting coupling constraints");
00345 
00346                 DecompConstraintSet * modelCore = new DecompConstraintSet();
00347                 createModelPart(modelCore, nRowsCore, rowsCore);
00348 
00349                 setModelCore(modelCore, "core");
00350                 //---
00351                 //--- save a pointer so we can delete it later
00352                 //---
00353                 m_modelC = modelCore;
00354 
00355                 // done generating the core
00356 
00357                 //get the master only variables
00358                 //modelCore->masterOnlyCols.push_back(i);
00359 
00360 
00361                 for (i = 0; i < nCols; i++) {
00362 
00363                         if (m_blockVarsAll.find(i) == m_blockVarsAll.end()) {
00364                                 modelCore->masterOnlyCols.push_back(i);
00365                                 //std::cout << "MASTER ONLY VARIABLE " << i << std::endl;
00366                         }
00367                 }
00368 
00369                 //---
00370                 //--- create an extra "empty" block for the master-only vars
00371                 //---   since I don't know what OSI will do with empty problem
00372                 //---   we will make column bounds explicity rows
00373                 //---
00374                 int nMasterOnlyCols =
00375                                 static_cast<int> (modelCore->masterOnlyCols.size());
00376                 if (nMasterOnlyCols) {
00377                         if (m_appParam.LogLevel >= 1)
00378                                 (*m_osLog) << "Create model part Master-Only." << std::endl;
00379 
00380                         createModelMasterOnlys2(modelCore->masterOnlyCols);
00381 
00382                 }
00383 
00384                 UtilPrintFuncBegin(m_osLog, m_classTag, "printCurrentProblem()",
00385                                 m_appParam.LogLevel, 2);
00386 
00387                 //free local memory
00388 
00389                 UTIL_DELARR(rowsCore);
00390 
00391         }//end try
00392 
00393         catch (const ErrorClass& eclass) {
00394 
00395                 throw ErrorClass(eclass.errormsg);
00396 
00397         }
00398 
00399 }// end createModels()
00400 
00401 
00402 //===========================================================================//
00403 
00404 void OSDipApp::createModelMasterOnlys2(std::vector<int> & masterOnlyCols) {
00405 
00406         int nBlocks = static_cast<int> (m_blockVars.size());
00407         const int nCols = m_osInterface.getVariableNumber();
00408         const double * colLB = m_osInterface.getColLower();
00409         const double * colUB = m_osInterface.getColUpper();
00410         const char * integerVars = m_osInterface.getIntegerColumns();
00411         int nMasterOnlyCols = static_cast<int> (masterOnlyCols.size());
00412 
00413         if (m_appParam.LogLevel >= 1) {
00414                 (*m_osLog) << "nCols = " << nCols << std::endl;
00415                 (*m_osLog) << "nMasterOnlyCols = " << nMasterOnlyCols << std::endl;
00416         }
00417 
00418         if (nMasterOnlyCols == 0)
00419                 return;
00420 
00421         int i;
00422         std::vector<int>::iterator vit;
00423         for (vit = masterOnlyCols.begin(); vit != masterOnlyCols.end(); vit++) {
00424                 i = *vit;
00425 
00426                 //THINK:
00427                 //  what-if master-only var is integer and bound is not at integer?
00428 
00429                 DecompConstraintSet * model = new DecompConstraintSet();
00430                 model->m_masterOnly = true;
00431                 model->m_masterOnlyIndex = i;
00432                 model->m_masterOnlyLB = colLB[i];
00433                 //std::cout << "MASTER ONLY LB =  " << model->m_masterOnlyLB << std::endl;
00434                 model->m_masterOnlyUB = colUB[i];
00435                 //std::cout << "MASTER ONLY UB =  " << model->m_masterOnlyUB << std::endl;
00436                 //0=cont, 1=integer
00437                 if (integerVars[i] == '1')
00438                         model->m_masterOnlyIsInt = true;
00439                 //model->m_masterOnlyIsInt = integerVars[i] ? true : false;
00440                 if (m_appParam.ColumnUB < 1.0e15)
00441                         if (colUB[i] > 1.0e15)
00442                                 model->m_masterOnlyUB = m_appParam.ColumnUB;
00443                 if (m_appParam.ColumnLB > -1.0e15)
00444                         if (colLB[i] < -1.0e15)
00445                                 model->m_masterOnlyLB = m_appParam.ColumnLB;
00446 
00447                 m_modelMasterOnly.insert(std::make_pair(i, model)); //keep track for garbage collection
00448                 setModelRelax(model, "master_only" + UtilIntToStr(i), nBlocks);
00449                 nBlocks++;
00450         }
00451         //free local memory
00452         UTIL_DELARR(integerVars);
00453         return;
00454 }//end createModelMasterOnlys2
00455 
00456 
00457 int OSDipApp::generateInitVars(DecompVarList & initVars) {
00458 
00459         //---
00460         //--- generateInitVars is a virtual method and can be overriden
00461         //---   if the user has some idea how to initialize the list of 
00462         //---   initial variables (columns in the DW master)
00463         //---
00464         std::cout << "GENERATE INIT VARS" << std::endl;
00465         UtilPrintFuncBegin(m_osLog, m_classTag, "generateInitVars()",
00466                         m_appParam.LogLevel, 2);
00467 
00468         //---
00469         //--- Get the initial solution from the OSOption object
00470         //--- we want the variable other option where name="initialCol"
00471         //---
00472 
00473         //std::vector<OtherVariableOption*> getOtherVariableOptions(std::string solver_name); 
00474         std::vector<OtherVariableOption*> otherVarOptions;
00475         std::vector<OtherVariableOption*>::iterator vit;
00476         int *index = NULL;
00477         double *value = NULL;
00478         int i;
00479         double objValue;
00480         int whichBlock;
00481         DecompVar *var;
00482 
00483         try {
00484                 if (m_osInterface.m_osoption != NULL
00485                                 && m_osInterface.m_osoption->getNumberOfOtherVariableOptions()
00486                                                 > 0) {
00487                         std::cout << "Number of other variable options = "
00488                                         << m_osInterface.m_osoption->getNumberOfOtherVariableOptions()
00489                                         << std::endl;
00490                         otherVarOptions
00491                                         = m_osInterface.m_osoption->getOtherVariableOptions("Dip");
00492                         //iterate over the vector
00493 
00494                         for (vit = otherVarOptions.begin(); vit != otherVarOptions.end(); vit++) {
00495 
00496                                 // see if we have an initialCol option
00497 
00498                                 if ((*vit)->name.compare("initialCol") == 0) {
00499 
00500                                         index = new int[(*vit)->numberOfVar];
00501                                         value = new double[(*vit)->numberOfVar];
00502 
00503                                         objValue = 0.0;
00504 
00505                                         for (i = 0; i < (*vit)->numberOfVar; i++) {
00506 
00507                                                 index[i] = (*vit)->var[i]->idx;
00508 
00509                                                 //convert the string to integer
00510                                                 value[i] = atoi((*vit)->var[i]->value.c_str());
00511                                                 objValue += m_objective[index[i]];
00512 
00513                                         }
00514 
00515                                         whichBlock = atoi((*vit)->value.c_str());
00516                                         var = new DecompVar((*vit)->numberOfVar, index, value,
00517                                                         objValue);
00518                                         var->setBlockId(whichBlock);
00519                                         initVars.push_back(var);
00520 
00521                                         //free local memory
00522                                         UTIL_DELARR(index);
00523                                         UTIL_DELARR(value);
00524 
00525                                 }
00526 
00527                         }
00528 
00529                 }
00530                 
00531                 //for bearcat
00578         }//end try
00579         catch (const ErrorClass& eclass) {
00580 
00581                 throw ErrorClass(eclass.errormsg);
00582 
00583         }
00584 
00585         UtilPrintFuncEnd(m_osLog, m_classTag, "generateInitVars()",
00586                         m_appParam.LogLevel, 2);
00587         return static_cast<int> (initVars.size());
00588 }
00589 
00590 DecompSolverStatus OSDipApp::solveRelaxed(const int whichBlock,
00591                 const double * redCostX, const double convexDual,
00592                 std::list<DecompVar*> & vars) {
00593         
00594         UtilPrintFuncBegin(m_osLog, m_classTag, "solveRelaxed()",
00595                         m_appParam.LogLevel, 2);
00596 
00597         std::vector<int> solInd;
00598         std::vector<double> solEls;
00599         double varRedCost = 0.0;
00600         double varOrigCost = 0.0;
00601         int kount;
00602         
00603         std::set<int> blockVar;
00604         
00605         
00606         blockVar = m_blockVars[ whichBlock];
00607         
00608         
00609         std::set<int>::iterator sit;
00610         std::vector<IndexValuePair*> solIndexValPair;
00611         std::vector<IndexValuePair*>::iterator vit;
00612 
00613 
00614 
00615         double *cost = NULL;
00616         int index;
00617 
00618         cost = new double[ blockVar.size()];
00619 
00620         index = 0;
00621         int* reverseMap;
00622         int reverseMapSize = blockVar.size();
00623         reverseMap = new int[ reverseMapSize];
00624         
00625         for (sit = blockVar.begin(); sit != blockVar.end(); sit++) {
00626 
00627                 cost[index] = redCostX[*sit];
00628                 reverseMap[ index] = *sit;
00629                 //std::cout  << "cost[index] =  " << cost[index] << std::endl;
00630                 index++;
00631 
00632         }
00633         
00634         try{
00635                 
00636                 
00637                 m_osDipBlockSolver[whichBlock]->m_whichBlock;
00638                 
00639         
00640                 m_osDipBlockSolver[whichBlock]->solve(cost, &solIndexValPair, &varRedCost);
00641                 kount = 0;      
00642                 
00643                 //std::cout << "NUMBER OF VARIABLES = " <<  solIndexValPair.size() << std::endl;
00644                 //kipp -- change this!!! Pushing back even the zero variables -- crazy!!!
00645                 /*
00646                 for (sit = blockVar.begin(); sit != blockVar.end(); sit++) {
00647                         //kipp be careful here -- the the dimension of the cost vector
00648                         //is the same as the number of variable in the block -- NOT in the model
00649                         if(solIndexValPair.size() != blockVar.size() ) throw ErrorClass("an inconsistent number of block variables"); 
00650                   solInd.push_back(  *sit ) ; //  again -- subproblem only sees variable in blockVar
00651                   //std::cout << "SOLUTION INDEX: = " << *sit << std::endl;
00652                   //std::cout << "  SOLUTION INDEX SUBPROBLEM = " << kount ;
00653                   //std::cout << "  VARIABLE VALUE  = " << solIndexValPair[ kount]->value << std::endl;         
00654                   solEls.push_back(  solIndexValPair[ kount]->value ) ;
00655                   varOrigCost +=  m_objective[ *sit]*solIndexValPair[ kount]->value;
00656                   kount++;
00657                  
00658                 }
00659                 */
00660 
00661                 for (vit = solIndexValPair.begin(); vit != solIndexValPair.end(); vit++) {
00662                         
00663                         //kipp -- check to make sure the variable indexed by (*vit)->idx is in the set blockVar
00664                         solInd.push_back( reverseMap[ (*vit)->idx] ) ;
00665                         solEls.push_back(  (*vit)->value ) ;
00666                         
00667                          varOrigCost +=  m_objective[ reverseMap[ (*vit)->idx]]*(*vit)->value;
00668                         
00669                 }
00670 
00671                 
00672                 delete[] reverseMap;
00673         
00674         } catch (const ErrorClass& eclass) {
00675 
00676                 throw ErrorClass(eclass.errormsg);
00677 
00678         }
00679 
00680         
00681 
00682 
00683         UTIL_DEBUG(m_appParam.LogLevel, 2,
00684                         std::cout << "WHICH BLOCK " << whichBlock << std::endl;
00685                         std::cout << "Convex Dual = " << convexDual << std::endl;
00686                         std::cout << "ORIGINAL COST =  = " <<  varOrigCost << std::endl;
00687                         std::cout << "SUPROBLEM OPT VAL  = " <<  varRedCost << std::endl;
00688                         printf("PUSH var with RC = %g\n", varRedCost - convexDual);
00689         );
00690 
00691         //exit( 1);
00692         DecompVar * var = new DecompVar(solInd, solEls, varRedCost - convexDual,
00693                         varOrigCost);
00694         
00695         var->setBlockId( whichBlock);
00696         vars.push_back(var);
00697 
00698         UtilPrintFuncEnd(m_osLog, m_classTag, "APPsolveRelaxed()",
00699                         m_appParam.LogLevel, 2);
00700                         
00701         
00702         
00703         delete[] cost;  
00704 
00705         return DecompSolStatOptimal;
00706 }//end solveRelaxed
00707 
00708 
00709 int OSDipApp::generateCuts(const double  * x, 
00710                             DecompCutList & newCuts){
00711         
00712         std::cout  << "I AM INSIDE GENERATE CUTS, IT WAS CALLED" << std::endl;
00713 
00714         //exit( 1);
00715         return 0;
00716 }//end generateCuts
00717 
00718 
00719 
00720 bool OSDipApp::APPisUserFeasible(const double * x, 
00721                                       const int      n_cols,
00722                                       const double   tolZero){
00723         
00724         std::cout  << "I AM INSIDE APPIS USER FEASIBLE, IT WAS CALLED" << std::endl;
00725         //exit( 1);
00726 
00727         return true;    
00728 }
00729 
00730 
00731 
00732 

Generated on Thu Nov 10 03:05:46 2011 by  doxygen 1.4.7