Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members

OsiOslSolverInterface.cpp

00001 // Copyright (C) 2000, International Business Machines
00002 // Corporation and others.  All Rights Reserved.
00003 
00004 #if defined(_MSC_VER)
00005 // Turn off compiler warning about long names
00006 #  pragma warning(disable:4786)
00007 #endif
00008 
00009 #include <cassert>
00010 
00011 #include "CoinPackedMatrix.hpp"
00012 #include "OsiOslSolverInterface.hpp"
00013 #include "OsiCuts.hpp"
00014 #include "OsiRowCut.hpp"
00015 #include "OsiColCut.hpp"
00016 
00017 //#############################################################################
00018 // A helper function that converts a packed matrix into a columnordered
00019 // gap-free matrix.
00020 //#############################################################################
00021 
00022 static const CoinPackedMatrix *
00023 toColumnOrderedGapFree(const CoinPackedMatrix& matrix)
00024 {
00025    CoinPackedMatrix * m = 0;
00026    if (matrix.isColOrdered()) {
00027       const int * start = matrix.getVectorStarts();
00028       const int * length = matrix.getVectorLengths();
00029       int i;
00030       for (i = matrix.getNumCols() - 1; i >= 0; --i)
00031          if (start[i+1] - start[i] != length[i])
00032             break;
00033       if (i >= 0) {
00034          // got to get rid of the gaps
00035          m = new CoinPackedMatrix();
00036          m->setExtraGap(0.0);
00037          m->setExtraMajor(0.0);
00038          m->operator=(matrix);
00039       }
00040    } else {
00041       // must create a column ordered copy without gaps
00042       m = new CoinPackedMatrix();
00043       m->setExtraGap(0.0);
00044       m->setExtraMajor(0.0);
00045       m->reverseOrderedCopyOf(matrix);
00046    }
00047    return m ? m : &matrix;
00048 }
00049 
00050 //#############################################################################
00051 // Solve methods
00052 //#############################################################################
00053 void OsiOslSolverInterface::initialSolve()
00054 {
00055   EKKModel* model = getMutableModelPtr();
00056   int rtcod;
00057   // Switch off printing if asked to
00058   bool takeHint;
00059   OsiHintStrength strength;
00060   bool gotHint = getHintParam(OsiDoReducePrint,takeHint,strength);
00061   assert(gotHint);
00062   if (strength!=OsiHintIgnore&&takeHint) {
00063     if (!messageHandler()->logLevel())
00064       ekk_messagesPrintOff(model,1,5999);
00065     else if (messageHandler()->logLevel()==1)
00066       ekk_messagePrintOff(model,317);
00067   }
00068 #if 0
00069   ekk_crash(model,1); 
00070   rtcod=ekk_primalSimplex(model,1);
00071 #elif 0
00072   ekk_setIiternum(model, 0);
00073   rtcod=ekk_simplex(model, 2); // *FIXME* : why not 0 (eitherSimplex)
00074 #else
00075   ekk_setIiternum(model, 0);
00076   rtcod=ekk_simplex(model, 0);
00077 #endif
00078   // If abandoned use B&B status which says abandoned
00079   if (rtcod>200)
00080     ekk_setIprobstat(model,6);
00081 }
00082 //-----------------------------------------------------------------------------
00083 void OsiOslSolverInterface::resolve()
00084 {
00085   EKKModel* model = getMutableModelPtr();
00086   int rtcod;
00087 
00088   ekk_mergeBlocks(model, 1);
00089   ekk_setIiternum(model, 0);
00090   // Switch off printing if asked to
00091   bool takeHint;
00092   OsiHintStrength strength;
00093   bool gotHint = getHintParam(OsiDoReducePrint,takeHint,strength);
00094   assert(gotHint);
00095   if (strength!=OsiHintIgnore&&takeHint) {
00096     if (!messageHandler()->logLevel())
00097       ekk_messagesPrintOff(model,1,5999);
00098     else if (messageHandler()->logLevel()==1)
00099       ekk_messagePrintOff(model,317);
00100   }
00101 #if 0
00102   rtcod=ekk_dualSimplex(model); // *FIXME* : why not 0 (eitherSimplex)
00103 #else
00104   rtcod=ekk_simplex(model, 256 + 32); // no presolve and no scaling
00105 #endif
00106   // If abandoned use B&B status which says abandoned
00107   if (rtcod>200)
00108     ekk_setIprobstat(model,6);
00109 }
00110 //-----------------------------------------------------------------------------
00111 void OsiOslSolverInterface::branchAndBound()
00112 {
00113   EKKModel* model = getMutableModelPtr();
00114 
00115   ekk_primalSimplex(model,1);
00116 #if 0
00117   EKKCuts cuts;
00118   cuts.numberCuts = 0;
00119   cuts.maxCuts = 0;
00120   cuts.cut = NULL;
00121   
00122   EKKIntegerPresolve info;
00123   info.number01 = 0;
00124   info.sequence = NULL;
00125   info.numberClique = 0;
00126   info.cliqueType = NULL;
00127   info.cliqueMember = NULL;
00128   info.cliqueStart = NULL;
00129   info.implicationStart = NULL;
00130   info.implication = NULL;
00131   info.numberChains = 0;
00132   info.chainInformation = NULL;
00133   
00134   ekk_integerPresolve(model, &info, &cuts, 0);
00135   // OSL computes a threshold to stop adding cuts if change in objective
00136   // is less than this, but it may be too small.
00137   ekk_setRthreshold(model, CoinMax(1.0e-3, ekk_getRthreshold(model)));
00138   ekk_branchAndCut(model, NULL, NULL, &info, &cuts, 0, 0);
00139   ekk_deleteCuts(&cuts);
00140   ekk_deleteIntegerPresolve(&info);
00141 #else
00142   //strong branching
00143   //  const int old_strategy = ekk_getIstrategy(model);
00144   //  ekk_setIstrategy(model, old_strategy|1024);
00145   ekk_branchAndBound(model, NULL, NULL);
00146   //  ekk_setIstrategy(model, old_strategy);
00147 #endif
00148 }
00149 
00150 //#############################################################################
00151 // Parameter related methods
00152 //#############################################################################
00153 
00154 bool
00155 OsiOslSolverInterface::setIntParam(OsiIntParam key, int value)
00156 {
00157   switch (key) {
00158   case OsiMaxNumIteration:
00159     if (value < 0)
00160       return false;
00161     // should use getModelPtr(), but setting max iterations does not
00162     // invalidate anything that's cached.
00163     ekk_setImaxiter(getMutableModelPtr(), value);
00164     break;
00165   case OsiMaxNumIterationHotStart:
00166     if (value < 0)
00167       return false;
00168     OsiSolverInterface::setIntParam(key, value);
00169     break;
00170   case OsiLastIntParam:
00171     return false;
00172   }
00173   return true;
00174 }
00175 
00176 //-----------------------------------------------------------------------------
00177 
00178 bool
00179 OsiOslSolverInterface::setDblParam(OsiDblParam key, double value)
00180 {
00181   int retval;
00182   // *THINK* : how to set opt limits for OSL?
00183   switch (key) {
00184   case OsiDualObjectiveLimit:
00185     retval = ekk_setRbbcutoff(getMutableModelPtr(), value);
00186     // OsiSolverInterface::setDblParam(key, value);
00187     return retval == 0;
00188 
00189   case OsiPrimalObjectiveLimit:
00190     return OsiSolverInterface::setDblParam(key, value);
00191 
00192   case OsiDualTolerance: // return false if not succeeded (out of range)
00193     retval = ekk_setRtoldinf(getMutableModelPtr(), value);
00194     return retval == 0;
00195 
00196   case OsiPrimalTolerance: // return false if not succeeded (out of range)
00197     retval = ekk_setRtolpinf(getMutableModelPtr(), value);
00198     return retval == 0;
00199 
00200   case OsiObjOffset: 
00201     retval = ekk_setRobjectiveOffset(getMutableModelPtr(), value);
00202     return retval == 0;
00203 
00204   case OsiLastDblParam:
00205     return false;
00206   }
00207   return true;
00208 }
00209 
00210 //-----------------------------------------------------------------------------
00211 
00212 bool
00213 OsiOslSolverInterface::setStrParam(OsiStrParam key, const std::string & value)
00214 {
00215   int retval;
00216   switch (key) {
00217   case OsiProbName:
00218     retval = ekk_setCname(getMutableModelPtr(), value.c_str());
00219     return retval == 0;
00220 
00221   case OsiSolverName:
00222     return false;
00223   case OsiLastStrParam:
00224     return false;
00225   }
00226   return false;
00227 }
00228 
00229 
00230 //-----------------------------------------------------------------------------
00231 
00232 bool
00233 OsiOslSolverInterface::getIntParam(OsiIntParam key, int& value) const 
00234 {
00235   switch (key) {
00236   case OsiMaxNumIteration:
00237     value = ekk_getImaxiter(getMutableModelPtr());
00238     break;
00239   case OsiMaxNumIterationHotStart:
00240     OsiSolverInterface::getIntParam(key, value);
00241     break;
00242   case OsiLastIntParam:
00243     return false;
00244   }
00245   return true;
00246 }
00247 
00248 //-----------------------------------------------------------------------------
00249 
00250 bool
00251 OsiOslSolverInterface::getDblParam(OsiDblParam key, double& value) const
00252 {
00253   // *THINK* : how to set opt limits for OSL?
00254   switch (key) {
00255   case OsiDualObjectiveLimit:
00256     value = ekk_getRbbcutoff(getMutableModelPtr());
00257     //OsiSolverInterface::getDblParam(key, value);
00258     break;
00259   case OsiPrimalObjectiveLimit:
00260     OsiSolverInterface::getDblParam(key, value);
00261     break;
00262   case OsiDualTolerance:
00263     value = ekk_getRtoldinf(getMutableModelPtr());
00264     break;
00265   case OsiPrimalTolerance:
00266     value = ekk_getRtolpinf(getMutableModelPtr());
00267     break;
00268   case OsiObjOffset:
00269     value = ekk_getRobjectiveOffset(getMutableModelPtr());
00270     break;
00271   case OsiLastDblParam:
00272     return false;
00273   }
00274   return true;
00275 }
00276 
00277 //-----------------------------------------------------------------------------
00278 
00279 bool
00280 OsiOslSolverInterface::getStrParam(OsiStrParam key, std::string & value) const
00281 {
00282   switch (key) {
00283   case OsiProbName:
00284     value = ekk_getCname(getMutableModelPtr());
00285     break;
00286   case OsiSolverName:
00287     value = "osl";
00288     break;
00289   case OsiLastStrParam:
00290     return false;
00291   }
00292   return true;
00293 }
00294 
00295 
00296 //#############################################################################
00297 // Methods returning info on how the solution process terminated
00298 //#############################################################################
00299 
00300 bool OsiOslSolverInterface::isAbandoned() const
00301 {
00302   EKKModel* model = getMutableModelPtr();
00303   return (ekk_getIprobstat(model)==6);
00304 }
00305 
00306 bool OsiOslSolverInterface::isProvenOptimal() const
00307 {
00308   EKKModel* model = getMutableModelPtr();
00309   const int stat = ekk_getIprobstat(model);
00310   return (stat == 0);
00311 }
00312 
00313 bool OsiOslSolverInterface::isProvenPrimalInfeasible() const
00314 {
00315   // *TEST*
00316   EKKModel* model = getMutableModelPtr();
00317   const int stat = ekk_getIprobstat(model);
00318   if (stat != 1)
00319      return false;
00320   if (ekk_lastAlgorithm(model) == 2) { // dual
00321      const int stat2 = ekk_getIprobstat2(model);
00322      if (stat2 == 11) // over dual limit
00323         return false;
00324   }
00325   return true;
00326 }
00327 
00328 bool OsiOslSolverInterface::isProvenDualInfeasible() const
00329 {
00330   EKKModel* model = getMutableModelPtr();
00331   const int stat = ekk_getIprobstat(model);
00332   return stat == 2;
00333 }
00334 
00335 bool OsiOslSolverInterface::isPrimalObjectiveLimitReached() const
00336 {
00337   // *TEST*
00338   double limit = 0.0;
00339   getDblParam(OsiPrimalObjectiveLimit, limit);
00340   if (limit > 1e30) {
00341     // was not ever set
00342     return false;
00343   }
00344    
00345   EKKModel* model = getMutableModelPtr();
00346   if (ekk_getIprobstat(model)==6)
00347     return false;
00348   const int lastalgo = ekk_lastAlgorithm(model);
00349   const double obj = ekk_getRobjvalue(model);
00350   const double maxmin = ekk_getRmaxmin(model);
00351 
00352   switch (lastalgo) {
00353    case 0: // no simplex was needed
00354      return maxmin > 0 ? (obj < limit) /*minim*/ : (obj > limit) /*maxim*/;
00355    case 2: // dual simplex
00356      if (ekk_getIprobstat(model) == 0) // optimal
00357         return maxmin > 0 ? (obj < limit) /*minim*/ : (obj > limit) /*maxim*/;
00358      return false;
00359    case 1: // primal simplex
00360      return maxmin > 0 ? (obj < limit) /*minim*/ : (obj > limit) /*maxim*/;
00361   }
00362   return false; // fake return
00363 }
00364 
00365 bool OsiOslSolverInterface::isDualObjectiveLimitReached() const
00366 {
00367   // *TEST*
00368   double limit = 0.0;
00369   getDblParam(OsiDualObjectiveLimit, limit);
00370   if (limit > 1e30) {
00371     // was not ever set
00372     return false;
00373   }
00374    
00375   EKKModel* model = getMutableModelPtr();
00376   if (ekk_getIprobstat(model)==6)
00377     return false;
00378   const int lastalgo = ekk_lastAlgorithm(model);
00379   const double obj = ekk_getRobjvalue(model);
00380   const double maxmin = ekk_getRmaxmin(model);
00381 
00382   switch (lastalgo) {
00383    case 0: // no simplex was needed
00384      return maxmin > 0 ? (obj > limit) /*minim*/ : (obj < limit) /*maxim*/;
00385    case 1: // primal simplex
00386      if (ekk_getIprobstat(model) == 0) // optimal
00387         return maxmin > 0 ? (obj > limit) /*minim*/ : (obj < limit) /*maxim*/;
00388      return false;
00389    case 2: // dual simplex
00390      if (ekk_getIprobstat(model) != 0 && ekk_getIprobstat2(model) == 11)
00391         // over dual limit
00392         return true;
00393      return maxmin > 0 ? (obj > limit) /*minim*/ : (obj < limit) /*maxim*/;
00394   }
00395   return false; // fake return
00396 }
00397 
00398 bool OsiOslSolverInterface::isIterationLimitReached() const
00399 {
00400   // *TEST*
00401   EKKModel* model = getMutableModelPtr();
00402   if (ekk_getIprobstat(model)==6)
00403     return false;
00404   const int stat = ekk_getIprobstat(model);
00405   return (stat == 3);
00406 }
00407 
00408 //#############################################################################
00409 // WarmStart related methods
00410 //#############################################################################
00411 
00412 CoinWarmStart* OsiOslSolverInterface::getWarmStart() const
00413 {
00414   // *TEST*
00415   EKKModel* model = getMutableModelPtr();
00416   const int numcols = getNumCols();
00417   const int numrows = getNumRows();
00418 
00419   CoinWarmStartBasis* ws = new CoinWarmStartBasis;
00420   ws->setSize(numcols, numrows);
00421 
00422   int i;
00423 
00424   for (i = 0; i < numrows; ++i) {
00425     switch (ekk_rowStatus(model, i)) {
00426     case -2:
00427     case -1:
00428       ws->setArtifStatus(i, CoinWarmStartBasis::atLowerBound);
00429       break;
00430     case  0:
00431       ws->setArtifStatus(i, CoinWarmStartBasis::basic);
00432       break;
00433     case  1:
00434     case  2:
00435       ws->setArtifStatus(i, CoinWarmStartBasis::atUpperBound);
00436       break;
00437     }
00438   }
00439 
00440   for (i = 0; i < numcols; ++i) {
00441     switch (ekk_columnStatus(model, i)) {
00442     case -2:
00443     case -1:
00444       ws->setStructStatus(i, CoinWarmStartBasis::atLowerBound);
00445       break;
00446     case  0:
00447       ws->setStructStatus(i, CoinWarmStartBasis::basic);
00448       break;
00449     case  1: 
00450     case  2:
00451       ws->setStructStatus(i, CoinWarmStartBasis::atUpperBound);
00452       break;
00453     }
00454   }
00455   
00456   return ws;
00457 }
00458 
00459 //-----------------------------------------------------------------------------
00460 
00461 bool OsiOslSolverInterface::setWarmStart(const CoinWarmStart* warmstart)
00462 {
00463   // *TEST*
00464   const CoinWarmStartBasis* ws =
00465     dynamic_cast<const CoinWarmStartBasis*>(warmstart);
00466 
00467   if (! ws)
00468     return false;
00469 
00470   const int numcols = ws->getNumStructural();
00471   const int numrows = ws->getNumArtificial();
00472 
00473   EKKModel* model = getMutableModelPtr();
00474 
00475   const int maxdim = CoinMax(numcols, numrows);
00476   int * atLower = new int[maxdim];
00477   int * atUpper = new int[maxdim];
00478   int * basic = new int[maxdim];
00479   int numLower = 0;
00480   int numUpper = 0;
00481   int numBasic = 0;
00482   int i;
00483 
00484   for (i = 0; i < numrows; ++i) {
00485     switch (ws->getArtifStatus(i)) {
00486     case CoinWarmStartBasis::atUpperBound:
00487       atUpper[numUpper++] = i;
00488       break;
00489     case CoinWarmStartBasis::atLowerBound:
00490       atLower[numLower++] = i;
00491       break;
00492     case CoinWarmStartBasis::basic:
00493       basic[numBasic++] = i;
00494       break;
00495     case CoinWarmStartBasis::isFree: // superbasic
00496       basic[numBasic++] = i;
00497       break;
00498     }
00499   }
00500   if (ekk_setRowsNonBasicAtLower(model, numLower, atLower) != 0)
00501     goto setWarmStart_Error;
00502   if (ekk_setRowsNonBasicAtUpper(model, numUpper, atUpper) != 0)
00503     goto setWarmStart_Error;
00504   if (ekk_markRowsAsBasic(model, numBasic, basic) != 0)
00505     goto setWarmStart_Error;
00506 
00507   numLower = 0;
00508   numUpper = 0;
00509   numBasic = 0;
00510   for (i = 0; i < numcols; ++i) {
00511     switch (ws->getStructStatus(i)) {
00512     case CoinWarmStartBasis::atUpperBound:
00513       atUpper[numUpper++] = i;
00514       break;
00515     case CoinWarmStartBasis::atLowerBound:
00516       atLower[numLower++] = i;
00517       break;
00518     case CoinWarmStartBasis::basic:
00519       basic[numBasic++] = i;
00520       break;
00521     case CoinWarmStartBasis::isFree: // superbasic
00522       basic[numBasic++] = i;
00523       break;
00524     }
00525   }
00526   if (ekk_setColumnsNonBasicAtLower(model, numLower, atLower) != 0)
00527     goto setWarmStart_Error;
00528   if (ekk_setColumnsNonBasicAtUpper(model, numUpper, atUpper) != 0)
00529     goto setWarmStart_Error;
00530   if (ekk_markColumnsAsBasic(model, numBasic, basic) != 0)
00531     goto setWarmStart_Error;
00532 
00533   delete[] basic;
00534   delete[] atUpper;
00535   delete[] atLower;
00536   return true;
00537 
00538   setWarmStart_Error:
00539   delete[] basic;
00540   delete[] atUpper;
00541   delete[] atLower;
00542   return false;
00543 }
00544 
00545 //#############################################################################
00546 // Hotstart related methods (primarily used in strong branching)
00547 //#############################################################################
00548 
00549 void OsiOslSolverInterface::markHotStart()
00550 {
00551   // *TEST*
00552   //EKKModel* model = getMutableModelPtr();
00553   delete ws_;
00554   ws_ = dynamic_cast<CoinWarmStartBasis*>(getWarmStart());
00555   //  ekk_startFastDualSimplex(model, itlim);
00556 }
00557 
00558 void OsiOslSolverInterface::solveFromHotStart()
00559 {
00560   EKKModel* model = getMutableModelPtr();
00561   // *TEST*
00562   ekk_setIiternum(model, 0);
00563   setWarmStart(ws_);
00564   //  ekk_fastDualSimplex(model);
00565   itlimOrig_ = ekk_getImaxiter(model);
00566   int itlim;
00567   OsiSolverInterface::getIntParam(OsiMaxNumIterationHotStart, itlim);
00568   ekk_setImaxiter(model, itlim);
00569   resolve();
00570   ekk_setImaxiter(model, itlimOrig_);
00571 }
00572 
00573 void OsiOslSolverInterface::unmarkHotStart()
00574 {
00575   // *TEST*
00576   EKKModel* model = getMutableModelPtr();
00577   //  ekk_stopFastDualSimplex(model);
00578   ekk_setImaxiter(model, itlimOrig_);
00579   delete ws_;
00580   ws_ = NULL;
00581 }
00582 
00583 //#############################################################################
00584 // Problem information methods (original data)
00585 //#############################################################################
00586 
00587 //------------------------------------------------------------------
00588 // Get number of rows, columns and elements
00589 //------------------------------------------------------------------
00590 int OsiOslSolverInterface::getNumCols() const
00591 {
00592   return ekk_getInumcols(getMutableModelPtr());
00593 }
00594 int OsiOslSolverInterface::getNumRows() const
00595 {
00596   return ekk_getInumrows(getMutableModelPtr());
00597 }
00598 int OsiOslSolverInterface::getNumElements() const
00599 {
00600   return ekk_getInumels(getMutableModelPtr());
00601 }
00602 
00603 //------------------------------------------------------------------
00604 // Get pointer to rim vectors
00605 //------------------------------------------------------------------  
00606 const double * OsiOslSolverInterface::getColLower() const
00607 {
00608   return ekk_collower(getMutableModelPtr());
00609 }
00610 //------------------------------------------------------------------
00611 const double * OsiOslSolverInterface::getColUpper() const
00612 {
00613   return ekk_colupper(getMutableModelPtr());
00614 }
00615 //------------------------------------------------------------------
00616 const char * OsiOslSolverInterface::getRowSense() const
00617 {
00618   extractSenseRhsRange();
00619   return rowsense_;
00620 }
00621 //------------------------------------------------------------------
00622 const double * OsiOslSolverInterface::getRightHandSide() const
00623 {
00624   extractSenseRhsRange();
00625   return rhs_;
00626 }
00627 //------------------------------------------------------------------
00628 const double * OsiOslSolverInterface::getRowRange() const
00629 {
00630   extractSenseRhsRange();
00631   return rowrange_;
00632 }
00633 //------------------------------------------------------------------
00634 const double * OsiOslSolverInterface::getRowLower() const
00635 {
00636   return ekk_rowlower(getMutableModelPtr());
00637 }
00638 //------------------------------------------------------------------
00639 const double * OsiOslSolverInterface::getRowUpper() const
00640 {
00641   return ekk_rowupper(getMutableModelPtr());
00642 }
00643 //------------------------------------------------------------------
00644 const double * OsiOslSolverInterface::getObjCoefficients() const
00645 {
00646   return ekk_objective(getMutableModelPtr());
00647 }
00648 //------------------------------------------------------------------
00649 double OsiOslSolverInterface::getObjSense() const
00650 {
00651   return ekk_getRmaxmin(getMutableModelPtr());
00652 }
00653 
00654 //------------------------------------------------------------------
00655 // Return information on integrality
00656 //------------------------------------------------------------------
00657 bool OsiOslSolverInterface::isContinuous(int colNumber) const
00658 {
00659   const char * intType = ekk_integerType(getMutableModelPtr());
00660   if ( intType==NULL ) return true;
00661   if ( intType[colNumber]==0 ) return true;
00662   return false;
00663 }
00664 //------------------------------------------------------------------
00665 #if 0
00666 bool OsiOslSolverInterface::isInteger(
00667       int columnNumber ) const
00668 {
00669   return !(isContinuous(columnNumber));
00670 }
00671 //------------------------------------------------------------------
00672 bool OsiOslSolverInterface::isBinary(
00673   int columnNumber ) const
00674 {
00675   if ( isContinuous(columnNumber) ) return false;  
00676   EKKModel * m=getMutableModelPtr();
00677   const double * upper = ekk_colupper(m);
00678   const double * lower = ekk_collower(m);
00679   if (
00680     (upper[columnNumber]== 1 || upper[columnNumber]== 0) && 
00681     (lower[columnNumber]== 0 || lower[columnNumber]==1)
00682     ) return true;
00683   else return false;
00684 }
00685 //------------------------------------------------------------------
00686 bool OsiOslSolverInterface::isIntegerNonBinary(
00687   int columnNumber ) const
00688 {
00689   if ( isInteger(columnNumber) && !isBinary(columnNumber) )
00690     return true; 
00691   else return false;
00692 }
00693 //------------------------------------------------------------------
00694 bool OsiOslSolverInterface::isFreeBinary(
00695   int columnNumber ) const
00696 {
00697   if ( isContinuous(columnNumber) ) return false;
00698   EKKModel * m=getMutableModelPtr();
00699   const double * upper = ekk_colupper(m);
00700   const double * lower = ekk_collower(m);
00701   if (
00702     (upper[columnNumber]== 1) &&
00703     (lower[columnNumber]== 0)
00704     ) return true;
00705   else return false;
00706 }
00707 #endif
00708 
00709 //------------------------------------------------------------------
00710 // Row and column copies of the matrix ...
00711 //------------------------------------------------------------------
00712 const CoinPackedMatrix * OsiOslSolverInterface::getMatrixByRow() const
00713 {
00714   if ( matrixByRow_ == NULL ) {
00715     EKKMatrixCopy rowCopy;
00716     ekk_createRowCopy(getMutableModelPtr(), &rowCopy);
00717     matrixByRow_ = new CoinPackedMatrix();
00718     matrixByRow_->copyOf(false /* not column ordered */,
00719                          getNumCols(), getNumRows(), getNumElements(),
00720                          rowCopy.element, rowCopy.index, rowCopy.start,
00721                          NULL /* compute lengths */);
00722     ekk_free(rowCopy.element);
00723     ekk_free(rowCopy.index);
00724     ekk_free(rowCopy.start);
00725   }
00726   return matrixByRow_;
00727 }
00728 //------------------------------------------------------------------
00729 const CoinPackedMatrix * OsiOslSolverInterface::getMatrixByCol() const
00730 {
00731   if ( matrixByColumn_ == NULL ) {
00732     EKKMatrixCopy colCopy;
00733     ekk_createColumnCopy(getMutableModelPtr(), &colCopy);
00734     matrixByColumn_ = new CoinPackedMatrix();
00735     matrixByColumn_->copyOf(true /* column ordered */,
00736                             getNumRows(), getNumCols(), getNumElements(),
00737                             colCopy.element, colCopy.index, colCopy.start,
00738                             NULL /* compute lengths */);
00739     ekk_free(colCopy.element);
00740     ekk_free(colCopy.index);
00741     ekk_free(colCopy.start);
00742   }
00743   return matrixByColumn_;
00744 }
00745 //------------------------------------------------------------------
00746 // Get solver's value for infinity
00747 //------------------------------------------------------------------
00748 double OsiOslSolverInterface::getInfinity() const
00749 {
00750   return OSL_INFINITY;
00751 }
00752 
00753 //#############################################################################
00754 // Problem information methods (results)
00755 //#############################################################################
00756 
00757 const double * OsiOslSolverInterface::getColSolution() const
00758 {
00759   return ekk_colsol(getMutableModelPtr());
00760 }
00761 //------------------------------------------------------------------
00762 
00763 const double * OsiOslSolverInterface::getRowPrice() const
00764 {
00765   return ekk_rowduals(getMutableModelPtr());
00766 }
00767 //------------------------------------------------------------------
00768 const double * OsiOslSolverInterface::getReducedCost() const
00769 {
00770   // *TEST*
00771   return ekk_colrcosts(getMutableModelPtr());
00772 }
00773 //------------------------------------------------------------------
00774 const double * OsiOslSolverInterface::getRowActivity() const
00775 {
00776   // *TEST*
00777   return ekk_rowacts(getMutableModelPtr());
00778 }
00779 //------------------------------------------------------------------
00780 double OsiOslSolverInterface::getObjValue() const
00781 {
00782 #if 0
00783   // This does not pass unitTest if getObjValue is called
00784   // before solving.
00785   return ekk_getRobjvalue(getMutableModelPtr());
00786 #else
00787   return OsiSolverInterface::getObjValue();
00788 #endif
00789 }
00790 //------------------------------------------------------------------
00791 int OsiOslSolverInterface::getIterationCount() const
00792 {
00793   return ekk_getIiternum(getMutableModelPtr());
00794 }
00795 //------------------------------------------------------------------
00796 std::vector<double*> OsiOslSolverInterface::getDualRays(int maxNumRays) const
00797 {
00798   const int m = getNumRows();
00799   double* ray = new double[m];
00800   const double* negray = ekk_rowaux(getMutableModelPtr());
00801   for (int i = 0; i < m; ++i) {
00802      ray[i] = -negray[i];
00803   }
00804   return std::vector<double*>(1, ray);
00805 }
00806 //------------------------------------------------------------------
00807 std::vector<double*> OsiOslSolverInterface::getPrimalRays(int maxNumRays) const
00808 {
00809   const int n = getNumCols();
00810   double* ray = new double[n];
00811   CoinDisjointCopyN(ekk_colaux(getMutableModelPtr()), n, ray);
00812   return std::vector<double*>(1, ray);
00813 }
00814 //------------------------------------------------------------------
00815 #if 0
00816 OsiVectorInt
00817 OsiOslSolverInterface::getFractionalIndices(const double etol) const
00818 {
00819   OsiVectorInt retVal;
00820   EKKModel * m = getMutableModelPtr();
00821   int numInts = ekk_getInumints(m);
00822   int * intInx = ekk_listOfIntegers(m);
00823   const double * colSolVec = ekk_colsol(m); 
00824   OsiAbsFltEq eq(etol);
00825   for ( int i=0; i<numInts; i++ ) {
00826     const double colSolElem = colSolVec[intInx[i]];
00827     const double distanceFromInteger = colSolElem - floor(colSolElem + 0.5);
00828     if ( !eq( distanceFromInteger, 0.0 ) ) {
00829       retVal.push_back(intInx[i]);
00830     }
00831   }
00832   ekk_free( intInx );
00833   return retVal;
00834 }
00835 #endif
00836 
00837 //#############################################################################
00838 // Problem modifying methods (rim vectors)
00839 //#############################################################################
00840 void
00841 OsiOslSolverInterface::setObjCoeff( int elementIndex, double elementValue )
00842 {
00843   // *TEST*
00844   EKKModel* model = getMutableModelPtr();
00845   ekk_copyObjective(model, &elementValue, elementIndex, elementIndex+1 );
00846 }
00847 //-----------------------------------------------------------------------------
00848 void
00849 OsiOslSolverInterface::setColLower( int elementIndex, double elementValue )
00850 {
00851   // *TEST*
00852   EKKModel* model = getMutableModelPtr();
00853   const double newVal =
00854     forceIntoRange(elementValue, -OSL_INFINITY, OSL_INFINITY);
00855   ekk_copyCollower(model, &newVal, elementIndex, elementIndex+1 );
00856 }
00857 //-----------------------------------------------------------------------------
00858 void
00859 OsiOslSolverInterface::setColUpper( int elementIndex, double elementValue )
00860 {
00861   // *TEST*
00862   EKKModel* model = getMutableModelPtr();
00863   const double newVal =
00864     forceIntoRange(elementValue, -OSL_INFINITY, OSL_INFINITY);
00865   ekk_copyColupper(model, &newVal, elementIndex, elementIndex+1 );
00866 }
00867 //-----------------------------------------------------------------------------
00868 void OsiOslSolverInterface::setColSetBounds(const int* indexFirst,
00869                                             const int* indexLast,
00870                                             const double* boundList)
00871 {
00872   // *TEST*
00873   const int numcols = getNumCols();
00874   if (indexLast - indexFirst < numcols/8) {
00875     // It's probably more effective to invoke setColBounds() iteratively
00876     while (indexFirst != indexLast) {
00877       setColBounds(*indexFirst, boundList[0], boundList[1]);
00878       ++indexFirst;
00879       boundList += 2;
00880     }
00881   } else {
00882     // probably faster to set everything at once
00883     EKKModel* model = getMutableModelPtr();
00884     double * lower = ekk_getCollower(model);
00885     double * upper = ekk_getColupper(model);
00886     while (indexFirst != indexLast) {
00887       const int iCol=*indexFirst++;
00888       lower[iCol]= forceIntoRange(*boundList++, -OSL_INFINITY, OSL_INFINITY);
00889       upper[iCol]= forceIntoRange(*boundList++, -OSL_INFINITY, OSL_INFINITY);
00890     }
00891     ekk_setCollower(model, lower);
00892     ekk_setColupper(model, upper);
00893     ekk_free(lower);
00894     ekk_free(upper);
00895   }
00896 }
00897 //-----------------------------------------------------------------------------
00898 void
00899 OsiOslSolverInterface::setRowLower( int i, double elementValue )
00900 {
00901   // *TEST*
00902   EKKModel* model = getMutableModelPtr();
00903   const double newVal =
00904     forceIntoRange(elementValue, -OSL_INFINITY, OSL_INFINITY);
00905   ekk_copyRowlower(model, &newVal, i, i+1 );
00906   if (rowsense_ != NULL) {
00907     assert ((rhs_ != NULL) && (rowrange_ != NULL));
00908     convertBoundToSense(newVal, getRowUpper()[i],
00909                         rowsense_[i], rhs_[i], rowrange_[i]);
00910   }
00911 }
00912 //-----------------------------------------------------------------------------
00913 void
00914 OsiOslSolverInterface::setRowUpper( int i, double elementValue )
00915 {
00916   // *TEST*
00917   const double newVal =
00918     forceIntoRange(elementValue, -OSL_INFINITY, OSL_INFINITY);
00919   ekk_copyRowupper(getMutableModelPtr(), &newVal, i, i+1 );
00920   if (rowsense_ != NULL) {
00921     assert ((rhs_ != NULL) && (rowrange_ != NULL));
00922     convertBoundToSense(getRowLower()[i], newVal,
00923                         rowsense_[i], rhs_[i], rowrange_[i]);
00924   }
00925 }
00926 //-----------------------------------------------------------------------------
00927 void
00928 OsiOslSolverInterface::setRowBounds( int i,
00929                                      double lower, double upper )
00930 {
00931   // *TEST*
00932   const double newLower = forceIntoRange(lower, -OSL_INFINITY, OSL_INFINITY);
00933   const double newUpper = forceIntoRange(upper, -OSL_INFINITY, OSL_INFINITY);
00934   EKKModel* model = getMutableModelPtr();
00935   ekk_copyRowlower(model, &newLower, i, i+1 );
00936   ekk_copyRowupper(model, &newUpper, i, i+1 );
00937   if (rowsense_ != NULL) {
00938     assert ((rhs_ != NULL) && (rowrange_ != NULL));
00939     convertBoundToSense(newLower, newUpper,
00940                         rowsense_[i], rhs_[i], rowrange_[i]);
00941   }
00942 }
00943 //-----------------------------------------------------------------------------
00944 void
00945 OsiOslSolverInterface::setRowType(int i, char sense, double rightHandSide,
00946                                   double range)
00947 {
00948   // *TEST*
00949   double lower, upper;
00950   convertSenseToBound(sense, rightHandSide, range, lower, upper);
00951   setRowBounds(i, lower, upper);
00952 }
00953 //-----------------------------------------------------------------------------
00954 void OsiOslSolverInterface::setRowSetBounds(const int* indexFirst,
00955                                             const int* indexLast,
00956                                             const double* boundList)
00957 {
00958   // *TEST*
00959   const int numrows = getNumRows();
00960   if (indexLast - indexFirst < numrows / 16) {
00961     // It's probably more effective to invoke setRowBounds() iteratively
00962     while (indexFirst != indexLast) {
00963       setRowBounds(*indexFirst, boundList[0], boundList[1]);
00964       ++indexFirst;
00965       boundList += 2;
00966     }
00967   } else {
00968     // probably faster to set everything at once
00969     EKKModel* model = getMutableModelPtr();
00970     double * lower = ekk_getRowlower(model);
00971     double * upper = ekk_getRowupper(model);
00972     const int len = indexLast - indexFirst;
00973     while (indexFirst != indexLast) {
00974       const int iRow=*indexFirst++;
00975       lower[iRow]= forceIntoRange(*boundList++, -OSL_INFINITY, OSL_INFINITY);
00976       upper[iRow]= forceIntoRange(*boundList++, -OSL_INFINITY, OSL_INFINITY);
00977     }
00978     if (rowsense_ != NULL) {
00979       assert ((rhs_ != NULL) && (rowrange_ != NULL));
00980       indexFirst -= len;
00981       while (indexFirst != indexLast) {
00982         const int iRow=*indexFirst++;
00983         convertBoundToSense(lower[iRow], upper[iRow],
00984                             rowsense_[iRow], rhs_[iRow], rowrange_[iRow]);
00985       }
00986     }
00987     ekk_setRowlower(model, lower);
00988     ekk_setRowupper(model, upper);
00989     ekk_free(lower);
00990     ekk_free(upper);
00991   }
00992 }
00993 //-----------------------------------------------------------------------------
00994 void
00995 OsiOslSolverInterface::setRowSetTypes(const int* indexFirst,
00996                                       const int* indexLast,
00997                                       const char* senseList,
00998                                       const double* rhsList,
00999                                       const double* rangeList)
01000 {
01001   // *TEST*
01002   const int numrows = getNumRows();
01003   if (indexLast - indexFirst < numrows / 16) {
01004     // It's probably more effective to invoke setRowType() iteratively
01005     while (indexFirst != indexLast) {
01006       if (rangeList){
01007         setRowType(*indexFirst++, *senseList++, *rhsList++, *rangeList++);
01008       } else {
01009         setRowType(*indexFirst++, *senseList++, *rhsList++, 0);
01010       } 
01011     }
01012   } else {
01013     // probably faster to set everything at once
01014     EKKModel* model = getMutableModelPtr();
01015     double * lower = ekk_getRowlower(model);
01016     double * upper = ekk_getRowupper(model);
01017     const int len = indexLast - indexFirst;
01018     while (indexFirst != indexLast) {
01019       const int iRow= *indexFirst++;
01020       if (rangeList){
01021         convertSenseToBound(*senseList++, *rhsList++, *rangeList++,
01022                             lower[iRow], upper[iRow]);
01023       } else {
01024         convertSenseToBound(*senseList++, *rhsList++, 0,
01025                             lower[iRow], upper[iRow]);
01026       }
01027     }
01028     if (rowsense_ != NULL) {
01029       assert ((rhs_ != NULL) && (rowrange_ != NULL));
01030       indexFirst -= len;
01031       senseList -= len;
01032       rhsList -= len;
01033       if (rangeList)
01034         rangeList -= len;
01035       while (indexFirst != indexLast) {
01036         const int iRow=*indexFirst++;
01037         rowsense_[iRow] = *senseList++;
01038         rhs_[iRow] = *rhsList++;
01039         if (rangeList)
01040           rowrange_[iRow] = *rangeList++;
01041       }
01042     }
01043     ekk_setRowlower(model, lower);
01044     ekk_setRowupper(model, upper);
01045     ekk_free(lower);
01046     ekk_free(upper);
01047   }
01048 }
01049 //#############################################################################
01050 void
01051 OsiOslSolverInterface::setContinuous(int index)
01052 {
01053   // *FIXME*: This is really painful, but this is the only way...
01054   EKKModel* model = getMutableModelPtr();
01055   int intnum = ekk_getInumints(model);
01056   if (intnum > 0) {
01057     int * intlist = ekk_listOfIntegers(model);
01058     int * inspoint = std::lower_bound(intlist, intlist + intnum, index);
01059     if (*inspoint == index) {
01060       ekk_deleteIntegerInformation(model);
01061       if (intnum > 1) {
01062         // *inspoint = intlist[intnum - 1];
01063         CoinCopy(inspoint + 1, intlist + intnum, inspoint);
01064         ekk_addIntegerSet(model, 100, intnum - 1, intlist, NULL, NULL);
01065       }
01066     }
01067     ekk_free(intlist);
01068   }
01069 }
01070 //-----------------------------------------------------------------------------
01071 void
01072 OsiOslSolverInterface::setInteger(int index)
01073 {
01074   ekk_markAsInteger(getMutableModelPtr(), index);
01075 }
01076 //-----------------------------------------------------------------------------
01077 void
01078 OsiOslSolverInterface::setContinuous(const int* indices, int len)
01079 {
01080   // *FIXME*: This is really painful, but this is the only way...
01081   EKKModel* model = getMutableModelPtr();
01082   int intnum = ekk_getInumints(model);
01083   if (intnum > 0 && len > 0) {
01084     int * intlist = ekk_listOfIntegers(model);
01085     int * sorted = new int[len];
01086     CoinDisjointCopyN(indices, len, sorted);
01087     std::sort(sorted, sorted+len);
01088     int * diff = new int[intnum];
01089     int numdiff = std::set_difference(intlist, intlist+intnum,
01090                                       indices, indices+len, diff) - diff;
01091     if (numdiff < intnum) {
01092       ekk_deleteIntegerInformation(model);
01093       if (numdiff > 0) {
01094         ekk_addIntegerSet(model, 100, numdiff, diff, NULL, NULL);
01095       }
01096     }
01097     delete[] diff;
01098     delete[] sorted;
01099     ekk_free(intlist);
01100   }
01101 }
01102 //-----------------------------------------------------------------------------
01103 void
01104 OsiOslSolverInterface::setInteger(const int* indices, int len)
01105 {
01106   ekk_addIntegerSet(getMutableModelPtr(), 100, len, indices, NULL, NULL);
01107 }
01108 //#############################################################################
01109 void OsiOslSolverInterface::setObjSense(double s) 
01110 {
01111   ekk_setRmaxmin(getMutableModelPtr(),s);
01112 }
01113 //-----------------------------------------------------------------------------
01114 void OsiOslSolverInterface::setColSolution(const double * cs) 
01115 {
01116   EKKModel * m = getMutableModelPtr();
01117   ekk_copyColsol(m,cs,0,ekk_getInumcols(m));
01118 }
01119 //-----------------------------------------------------------------------------
01120 void OsiOslSolverInterface::setRowPrice(const double * rs) 
01121 {
01122   EKKModel * m = getMutableModelPtr();
01123   ekk_copyRowduals(m,rs,0,ekk_getInumrows(m));
01124 }
01125 
01126 //#############################################################################
01127 // Problem modifying methods (matrix)
01128 //#############################################################################
01129 void 
01130 OsiOslSolverInterface::addCol(const CoinPackedVectorBase& vec,
01131                               const double collb, const double colub,   
01132                               const double obj)
01133 {
01134   // *TEST*
01135   ekk_addOneColumn(getModelPtr(), obj, collb, colub,
01136                    vec.getNumElements(), vec.getIndices(), vec.getElements());
01137 }
01138 //-----------------------------------------------------------------------------
01139 void 
01140 OsiOslSolverInterface::addCols(const int numcols,
01141                                const CoinPackedVectorBase * const * cols,
01142                                const double* collb, const double* colub,   
01143                                const double* obj)
01144 {
01145   // *TEST*
01146   int i;
01147   int nz = 0;
01148   for (i = 0; i < numcols; ++i)
01149     nz += cols[i]->getNumElements();
01150 
01151   int* index = new int[nz];
01152   double* elem = new double[nz];
01153   int* start = new int[numcols+1];
01154 
01155   nz = 0;
01156   start[0] = 0;
01157   for (i = 0; i < numcols; ++i) {
01158     const CoinPackedVectorBase* col = cols[i];
01159     const int len = col->getNumElements();
01160     CoinDisjointCopyN(col->getIndices(), len, index+nz);
01161     CoinDisjointCopyN(col->getElements(), len, elem+nz);
01162     nz += len;
01163     start[i+1] = nz;
01164   }
01165   ekk_addColumns(getModelPtr(), numcols, obj, collb, colub,
01166                  start, index, elem);
01167   delete[] start;
01168   delete[] elem;
01169   delete[] index;
01170 }
01171 //-----------------------------------------------------------------------------
01172 void 
01173 OsiOslSolverInterface::deleteCols(const int num, const int * columnIndices)
01174 {
01175   // *TEST*
01176   ekk_deleteColumns(getModelPtr(), num, columnIndices);
01177 }
01178 //-----------------------------------------------------------------------------
01179 void 
01180 OsiOslSolverInterface::addRow(const CoinPackedVectorBase& vec,
01181                               const double rowlb, const double rowub)
01182 {
01183   // *TEST*
01184   ekk_addOneRow(getModelPtr(), rowlb, rowub,
01185                 vec.getNumElements(), vec.getIndices(), vec.getElements());
01186 }
01187 //-----------------------------------------------------------------------------
01188 void 
01189 OsiOslSolverInterface::addRow(const CoinPackedVectorBase& vec,
01190                               const char rowsen, const double rowrhs,   
01191                               const double rowrng)
01192 {
01193   // *TEST*
01194   double rowlb, rowub;
01195   convertSenseToBound(rowsen, rowrhs, rowrng, rowlb, rowub);
01196   ekk_addOneRow(getModelPtr(), rowlb, rowub,
01197                 vec.getNumElements(), vec.getIndices(), vec.getElements());
01198 }
01199 //-----------------------------------------------------------------------------
01200 void 
01201 OsiOslSolverInterface::addRows(const int numrows,
01202                                const CoinPackedVectorBase * const * rows,
01203                                const double* rowlb, const double* rowub)
01204 {
01205   // *TEST*
01206   int i;
01207   int nz = 0;
01208   for (i = 0; i < numrows; ++i)
01209     nz += rows[i]->getNumElements();
01210 
01211   int* index = new int[nz];
01212   double* elem = new double[nz];
01213   int* start = new int[numrows+1];
01214 
01215   nz = 0;
01216   start[0] = 0;
01217   for (i = 0; i < numrows; ++i) {
01218     const CoinPackedVectorBase* row = rows[i];
01219     const int len = row->getNumElements();
01220     CoinDisjointCopyN(row->getIndices(), len, index+nz);
01221     CoinDisjointCopyN(row->getElements(), len, elem+nz);
01222     nz += len;
01223     start[i+1] = nz;
01224   }
01225   ekk_addRows(getModelPtr(), numrows, rowlb, rowub, start, index, elem);
01226   delete[] start;
01227   delete[] elem;
01228   delete[] index;
01229 }
01230 //-----------------------------------------------------------------------------
01231 void 
01232 OsiOslSolverInterface::addRows(const int numrows,
01233                                const CoinPackedVectorBase * const * rows,
01234                                const char* rowsen, const double* rowrhs,   
01235                                const double* rowrng)
01236 {
01237   // *TEST*
01238   int i;
01239   int nz = 0;
01240   for (i = 0; i < numrows; ++i)
01241     nz += rows[i]->getNumElements();
01242 
01243   int* index = new int[nz];
01244   double* elem = new double[nz];
01245   int* start = new int[numrows+1];
01246   double* rowlb = new double[numrows];
01247   double* rowub = new double[numrows];
01248 
01249   nz = 0;
01250   start[0] = 0;
01251   for (i = 0; i < numrows; ++i) {
01252     convertSenseToBound(rowsen[i], rowrhs[i], rowrng[i], rowlb[i], rowub[i]);
01253     const CoinPackedVectorBase* row = rows[i];
01254     const int len = row->getNumElements();
01255     CoinDisjointCopyN(row->getIndices(), len, index+nz);
01256     CoinDisjointCopyN(row->getElements(), len, elem+nz);
01257     nz += len;
01258     start[i+1] = nz;
01259   }
01260   ekk_addRows(getModelPtr(), numrows, rowlb, rowub, start, index, elem);
01261   delete[] rowub;
01262   delete[] rowlb;
01263   delete[] start;
01264   delete[] elem;
01265   delete[] index;
01266 }
01267 //-----------------------------------------------------------------------------
01268 void 
01269 OsiOslSolverInterface::deleteRows(const int num, const int * rowIndices)
01270 {
01271   // *TEST*
01272   ekk_deleteRows(getModelPtr(), num, rowIndices);
01273 }
01274 
01275 //#############################################################################
01276 // Methods to input a problem
01277 //#############################################################################
01278 
01279 void
01280 OsiOslSolverInterface::loadProblem(const CoinPackedMatrix& matrix,
01281                                    const double* collb, const double* colub,   
01282                                    const double* obj,
01283                                    const double* rowlb, const double* rowub)
01284 {
01285    const CoinPackedMatrix * m = toColumnOrderedGapFree(matrix);
01286    loadProblem(m->getNumCols(), m->getNumRows(),
01287                m->getVectorStarts(), m->getIndices(), m->getElements(),
01288                collb, colub, obj, rowlb, rowub);
01289    if (m != &matrix)
01290       delete m;
01291 }
01292 
01293 //-----------------------------------------------------------------------------
01294 
01295 void
01296 OsiOslSolverInterface::assignProblem(CoinPackedMatrix*& matrix,
01297                                      double*& collb, double*& colub,
01298                                      double*& obj,
01299                                      double*& rowlb, double*& rowub)
01300 {
01301    loadProblem(*matrix, collb, colub, obj, rowlb, rowub);
01302    delete matrix;   matrix = 0;
01303    delete[] collb;  collb = 0;
01304    delete[] colub;  colub = 0;
01305    delete[] obj;    obj = 0;
01306    delete[] rowlb;  rowlb = 0;
01307    delete[] rowub;  rowub = 0;
01308 }
01309 
01310 //-----------------------------------------------------------------------------
01311 
01312 void
01313 OsiOslSolverInterface::loadProblem(const CoinPackedMatrix& matrix,
01314                                    const double* collb, const double* colub,
01315                                    const double* obj,
01316                                    const char* rowsen, const double* rowrhs,   
01317                                    const double* rowrng)
01318 {
01319    const CoinPackedMatrix * m = toColumnOrderedGapFree(matrix);
01320    loadProblem(m->getNumCols(), m->getNumRows(),
01321                m->getVectorStarts(), m->getIndices(), m->getElements(),
01322                collb, colub, obj, rowsen, rowrhs, rowrng);
01323    if (m != &matrix)
01324       delete m;
01325 }
01326 
01327 //-----------------------------------------------------------------------------
01328 
01329 void
01330 OsiOslSolverInterface::assignProblem(CoinPackedMatrix*& matrix,
01331                                      double*& collb, double*& colub,
01332                                      double*& obj,
01333                                      char*& rowsen, double*& rowrhs,
01334                                      double*& rowrng)
01335 {
01336    loadProblem(*matrix, collb, colub, obj, rowsen, rowrhs, rowrng);
01337    delete matrix;   matrix = 0;
01338    delete[] collb;  collb = 0;
01339    delete[] colub;  colub = 0;
01340    delete[] obj;    obj = 0;
01341    delete[] rowsen; rowsen = 0;
01342    delete[] rowrhs; rowrhs = 0;
01343    delete[] rowrng; rowrng = 0;
01344 }
01345 
01346 //-----------------------------------------------------------------------------
01347 
01348 void
01349 OsiOslSolverInterface::loadProblem(const int numcols, const int numrows,
01350                                    const int* start, const int* index,
01351                                    const double* value,
01352                                    const double* collb, const double* colub,
01353                                    const double* obj,
01354                                    const double* rowlb, const double* rowub)
01355 {
01356    // Use getMutableModelPtr(), so that the cached stuff is not immediately
01357    // deleted.
01358    ekk_loadRimModel(getMutableModelPtr(),
01359                     numrows, rowlb, rowub, numcols, obj, collb, colub);
01360    ekk_addColumnElementBlock(getMutableModelPtr(),
01361                              numcols, index, start, value);
01362    // Now we can free the cached results
01363    freeCachedResults();
01364 }
01365 //-----------------------------------------------------------------------------
01366 
01367 void
01368 OsiOslSolverInterface::loadProblem(const int numcols, const int numrows,
01369                                    const int* start, const int* index,
01370                                    const double* value,
01371                                    const double* collb, const double* colub,
01372                                    const double* obj,
01373                                    const char* rowsen, const double* rowrhs,   
01374                                    const double* rowrng)
01375 {
01376    assert( rowsen != NULL );
01377    assert( rowrhs != NULL );
01378    double * rowlb = new double[numrows];
01379    double * rowub = new double[numrows];
01380    for (int i = numrows-1; i >= 0; --i) {   
01381       convertSenseToBound(rowsen[i],rowrhs[i],rowrng[i],rowlb[i],rowub[i]);
01382    }
01383    // Use getMutableModelPtr(), so that the cached stuff is not immediately
01384    // deleted.
01385    ekk_loadRimModel(getMutableModelPtr(),
01386                     numrows, rowlb, rowub, numcols, obj, collb, colub);
01387    ekk_addColumnElementBlock(getMutableModelPtr(),
01388                              numcols, index, start, value);
01389    // Now we can free the cached results
01390    freeCachedResults();
01391    delete[] rowlb;
01392    delete[] rowub;
01393 }
01394 
01395 //-----------------------------------------------------------------------------
01396 // Read mps files
01397 //-----------------------------------------------------------------------------
01398 
01399 int OsiOslSolverInterface::readMps(const char *filename,
01400                                    const char *extension)
01401 {
01402    return OsiSolverInterface::readMps(filename, extension);
01403 }
01404 
01405 //-----------------------------------------------------------------------------
01406 // Write mps files
01407 //-----------------------------------------------------------------------------
01408 
01409 void OsiOslSolverInterface::writeMps(const char * filename,
01410                                      const char * extension,
01411                                      double objSense) const
01412 {
01413   std::string f(filename);
01414   std::string e(extension);
01415   std::string fullname;
01416   if (e!="") {
01417     fullname = f + "." + e;
01418   } else {
01419     // no extension so no trailing period
01420     fullname = f;
01421   }
01422   ekk_exportModel(getMutableModelPtr(), fullname.c_str(), 1, 2);
01423 }
01424 
01425 //#############################################################################
01426 // OSL specific public interfaces
01427 //#############################################################################
01428 
01429 EKKModel * OsiOslSolverInterface::getModelPtr()
01430 {
01431   freeCachedResults();
01432   return getMutableModelPtr();
01433 }
01434 
01435 //------------------------------------------------------------------- 
01436 
01437 void OsiOslSolverInterface::incrementInstanceCounter()
01438 {
01439   if ( numInstances_ == 0 ) {
01440     contextPtr_ = ekk_initializeContext();
01441     assert( contextPtr_ != NULL );    
01442     ekk_messagesPrintOff(ekk_baseModel(contextPtr_), 1, 5999);
01443     //FILE *oslMesgFILE = fopen("osl.log","a+");    
01444     //ekk_setLogfileFilePointer(ekk_baseModel(contextPtr_),stderr );    
01445     //ekk_messagesPrintOn(NULL ,1,2999);
01446   }
01447   numInstances_++;
01448 }
01449 
01450 //------------------------------------------------------------------- 
01451 
01452 void OsiOslSolverInterface::decrementInstanceCounter()
01453 {
01454   assert( getNumInstances() != 0 );
01455   numInstances_--;
01456   if ( numInstances_ == 0 ) {
01457     //FILE * oslMesgFile =
01458     //   ekk_getLogfileFilePointer(ekk_baseModel(contextPtr_));
01459     //fclose(oslMesgFile);
01460     ekk_endContext(contextPtr_);
01461     contextPtr_ = NULL;
01462   }
01463 }
01464 
01465 //------------------------------------------------------------------- 
01466 
01467 unsigned int OsiOslSolverInterface::getNumInstances()
01468 {
01469   return numInstances_;
01470 }
01471 
01472 //#############################################################################
01473 // Constructors, destructors clone and assignment
01474 //#############################################################################
01475 
01476 //-------------------------------------------------------------------
01477 // Default Constructor 
01478 //-------------------------------------------------------------------
01479 OsiOslSolverInterface::OsiOslSolverInterface ()
01480   :
01481 OsiSolverInterface(),
01482 modelPtr_(NULL),
01483 rowsense_(NULL),
01484 rhs_(NULL),
01485 rowrange_(NULL),
01486 ws_(NULL),
01487 matrixByRow_(NULL),
01488 matrixByColumn_(NULL)
01489 {
01490   incrementInstanceCounter();
01491 }
01492 
01493 //-------------------------------------------------------------------
01494 // Clone
01495 //-------------------------------------------------------------------
01496 OsiSolverInterface * OsiOslSolverInterface::clone(bool CopyData) const
01497 {
01498    if (CopyData) {
01499       return new OsiOslSolverInterface(*this);
01500    } else {
01501       return new OsiOslSolverInterface();
01502    }
01503 }
01504 
01505 #if 0
01506 //-------------------------------------------------------------------
01507 // Alternate Constructor 
01508 //-------------------------------------------------------------------
01509 OsiOslSolverInterface::OsiOslSolverInterface (EKKModel * m)
01510 :
01511 OsiSolverInterface(),
01512 modelPtr_(m)
01513 {
01514   // nothing to do here
01515 }
01516 #endif
01517 
01518 //-------------------------------------------------------------------
01519 // Copy constructor 
01520 //-------------------------------------------------------------------
01521 OsiOslSolverInterface::OsiOslSolverInterface (
01522                   const OsiOslSolverInterface & source)
01523 :
01524 OsiSolverInterface(source),
01525 modelPtr_(NULL),
01526 rowsense_(NULL),
01527 rhs_(NULL),
01528 rowrange_(NULL),
01529 ws_(NULL),
01530 matrixByRow_(NULL),
01531 matrixByColumn_(NULL)
01532 {
01533   incrementInstanceCounter();  
01534   if ( source.modelPtr_ !=NULL ) {
01535     ekk_copyModel(getModelPtr(),source.modelPtr_);
01536     // OK and proper to leave rowsense_, rhs_, and
01537     // rowrange_ to NULL.  They will be constructed
01538     // if they are required.
01539   }
01540 }
01541 
01542 
01543 //-------------------------------------------------------------------
01544 // Destructor 
01545 //-------------------------------------------------------------------
01546 OsiOslSolverInterface::~OsiOslSolverInterface ()
01547 {
01548   gutsOfDestructor();
01549   decrementInstanceCounter();
01550 }
01551 
01552 //-------------------------------------------------------------------
01553 // Assignment operator 
01554 //-------------------------------------------------------------------
01555 OsiOslSolverInterface &
01556 OsiOslSolverInterface::operator=(const OsiOslSolverInterface& rhs)
01557 {
01558   if (this != &rhs) {    
01559     OsiSolverInterface::operator=(rhs);
01560     gutsOfDestructor();
01561     if ( rhs.modelPtr_ !=NULL ) {
01562       ekk_copyModel(getModelPtr(),rhs.modelPtr_);
01563     }
01564     delete ws_;
01565     ws_ = NULL;
01566   }
01567   return *this;
01568 }
01569 
01570 //#############################################################################
01571 // Applying cuts
01572 //#############################################################################
01573 
01574 void OsiOslSolverInterface::applyRowCut( const OsiRowCut & rowCut )
01575 {
01576   EKKModel * m = getModelPtr();
01577   const CoinPackedVector & row=rowCut.row();
01578   ekk_addOneRow(m, rowCut.lb(),rowCut.ub(),
01579                 row.getNumElements(),row.getIndices(),row.getElements() ); 
01580 }
01581 
01582 //-----------------------------------------------------------------------------
01583 
01584 void OsiOslSolverInterface::applyColCut( const OsiColCut & cc )
01585 {
01586   EKKModel * m = getModelPtr();
01587   const double * oslColLB = ekk_collower(m);
01588   const double * oslColUB = ekk_colupper(m);
01589   const CoinPackedVector & lbs = cc.lbs();
01590   const CoinPackedVector & ubs = cc.ubs();
01591   int i;
01592 
01593   for ( i=0; i<lbs.getNumElements(); i++ ) {
01594     if ( lbs.getElements()[i] > oslColLB[lbs.getIndices()[i]] )
01595        //oslColLB[lbs.getIndices()[i]] = lbs.getElements()[i];
01596        ekk_copyCollower(m, &(lbs.getElements()[i]),
01597                         lbs.getIndices()[i],lbs.getIndices()[i]+1);
01598   }
01599   for ( i=0; i<ubs.getNumElements(); i++ ) {
01600     if ( ubs.getElements()[i] < oslColUB[ubs.getIndices()[i]] )
01601       // oslColUB[ubs.getIndices()[i]] = ubs.getElements()[i];
01602       ekk_copyColupper(m, &(ubs.getElements()[i]),
01603                        ubs.getIndices()[i],ubs.getIndices()[i]+1);
01604   }
01605 }
01606 
01607 //#############################################################################
01608 // Static methods and data
01609 //#############################################################################
01610 
01611 EKKContext * OsiOslSolverInterface::getContextPtr()
01612 {
01613   assert( contextPtr_ != NULL );
01614   return contextPtr_;
01615 }
01616 
01617 //------------------------------------------------------------------- 
01618 
01619 EKKContext * OsiOslSolverInterface::contextPtr_  = NULL;
01620 
01621 //-------------------------------------------------------------------
01622 
01623 unsigned int OsiOslSolverInterface::numInstances_ = 0;
01624  
01625 //#############################################################################
01626 // Private methods
01627 //#############################################################################
01628 
01629 //-------------------------------------------------------------------
01630 // Get pointer to EKKModel.
01631 // const methods should use getMutableModelPtr().
01632 // non-const methods should use getModelPtr().
01633 //------------------------------------------------------------------- 
01634 EKKModel * OsiOslSolverInterface::getMutableModelPtr() const
01635 {
01636   if ( modelPtr_ == NULL ) {
01637     modelPtr_ = ekk_newModel(getContextPtr(),NULL);
01638   }
01639   return modelPtr_;
01640 }
01641 
01642 //-------------------------------------------------------------------
01643 
01644 #if 0
01645 void OsiOslSolverInterface::gutsOfCopy( const OsiOslSolverInterface & source )
01646 {
01647   modelPtr_ = source.modelPtr_;
01648 }
01649 #endif
01650 
01651 //-------------------------------------------------------------------
01652 
01653 void OsiOslSolverInterface::gutsOfDestructor()
01654 {  
01655   if ( modelPtr_ != NULL ) {
01656     ekk_deleteModel(modelPtr_);
01657     modelPtr_=NULL;
01658     freeCachedResults();
01659   }
01660   assert( modelPtr_==NULL );
01661   assert( rowsense_==NULL );
01662   assert( rhs_==NULL );
01663   assert( rowrange_==NULL );
01664   assert( ws_==NULL );
01665   assert( matrixByRow_==NULL );
01666   assert( matrixByColumn_==NULL );
01667 }
01668 
01669 //------------------------------------------------------------------- 
01670 
01671 void OsiOslSolverInterface::freeCachedResults()
01672 {  
01673   delete [] rowsense_;
01674   delete [] rhs_;
01675   delete [] rowrange_;
01676   delete matrixByRow_;
01677   delete matrixByColumn_;
01678   delete ws_;
01679   rowsense_=NULL;
01680   rhs_=NULL;
01681   rowrange_=NULL;
01682   matrixByRow_=NULL;
01683   matrixByColumn_=NULL;
01684   ws_ = NULL;
01685 }
01686 
01687 //------------------------------------------------------------------
01688 void OsiOslSolverInterface::extractSenseRhsRange() const
01689 {
01690   if (rowsense_ == NULL) {
01691     // all three must be NULL
01692     assert ((rhs_ == NULL) && (rowrange_ == NULL));
01693     
01694     EKKModel * m = getMutableModelPtr();
01695     
01696     int nr=ekk_getInumrows(m);
01697     if ( nr != 0 ) {
01698       rowsense_ = new char[nr];
01699       rhs_ = new double[nr];
01700       rowrange_ = new double[nr];
01701       std::fill(rowrange_,rowrange_+nr,0.0);
01702       
01703       const double * lb = ekk_rowlower(m);
01704       const double * ub = ekk_rowupper(m);
01705       
01706       int i;
01707       for ( i=0; i<nr; i++ ) {
01708         convertBoundToSense(lb[i], ub[i], rowsense_[i], rhs_[i], rowrange_[i]);
01709       }
01710     }
01711   }
01712 }
01713 
01714 //#############################################################################
01715 // Resets as if default constructor
01716 void 
01717 OsiOslSolverInterface::reset()
01718 {
01719   setInitialData(); // clear base class
01720   gutsOfDestructor();
01721   itlimOrig_=9999999;
01722 }

Generated on Wed Dec 3 14:35:32 2003 for Osi by doxygen 1.3.5