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

OsiVolSolverInterface.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 <numeric>
00010 #include <cassert>
00011 #include <cmath>
00012 
00013 #include "CoinHelperFunctions.hpp"
00014 #include "CoinWarmStartDual.hpp"
00015 
00016 #include "OsiVolSolverInterface.hpp"
00017 #include "OsiRowCut.hpp"
00018 #include "OsiColCut.hpp"
00019 
00020 //#######################################################################
00021 //  Private helper methods
00022 //#######################################################################
00023 
00024 void
00025 OsiVolSolverInterface::updateRowMatrix_() const 
00026 {
00027    if (! rowMatrixCurrent_) {
00028       rowMatrix_.reverseOrderedCopyOf(colMatrix_);
00029       rowMatrixCurrent_ = true;
00030    }
00031 }
00032 
00033 void
00034 OsiVolSolverInterface::updateColMatrix_() const
00035 {
00036    if (! colMatrixCurrent_) {
00037       colMatrix_.reverseOrderedCopyOf(rowMatrix_);
00038       colMatrixCurrent_ = true;
00039    }
00040 }
00041 
00042 //-----------------------------------------------------------------------------
00043 
00044 void
00045 OsiVolSolverInterface::checkData_() const throw(CoinError)
00046 {
00047    int i;
00048    for (i = getNumRows() - 1; i >= 0; --i) {
00049       if (rowlower_[i] > -1.0e20 &&
00050           rowupper_[i] < 1.0e20 &&
00051           rowlower_[i] != rowupper_[i])
00052          throw CoinError("Volume algorithm is unable to handle ranged rows",
00053                         "checkData_", "OsiVolSolverInterface");
00054    }
00055 
00056    for (i = getNumCols() - 1; i >= 0; --i)  {
00057       if (collower_[i] < -1.0e20 || colupper_[i] > 1.0e20)
00058          throw CoinError("Volume algorithm is unable to handle infinite bounds",
00059                         "checkData_", "OsiVolSolverInterface");
00060    }
00061 }
00062 
00063 //-----------------------------------------------------------------------------
00064 
00065 void
00066 OsiVolSolverInterface::compute_rc_(const double* u, double* rc) const 
00067 {
00068   if (isZeroOneMinusOne_) {
00069     rowMatrixOneMinusOne_->timesMajor(u, rc);
00070   } else {
00071     rowMatrix_.transposeTimes(u, rc);
00072   }
00073 
00074   const int psize = getNumCols();
00075   std::transform(rc, rc+psize, objcoeffs_, rc, std::minus<double>());
00076   std::transform(rc, rc+psize, rc, std::negate<double>());
00077 }
00078 
00079 //#############################################################################
00080 
00081 bool
00082 OsiVolSolverInterface::test_zero_one_minusone_(const CoinPackedMatrix& m) const
00083 {
00084   const int vecnum = m.getMajorDim();
00085   const double* elem = m.getElements();
00086   const int* start = m.getVectorStarts();
00087   const int* length = m.getVectorLengths();
00088   int i, j;
00089   for (i = 0; i < vecnum; ++i) {
00090     for (j = start[i] + length[i] - 1; j >= start[i]; --j) {
00091       const double val = elem[j];
00092       if (val != 1.0 && val != 0.0 && val != -1.0) {
00093         return false;
00094       }
00095     }
00096   }
00097   return true;
00098 }
00099 
00100 //-----------------------------------------------------------------------------
00101 
00102 OsiVolSolverInterface::OsiVolMatrixOneMinusOne_::
00103 OsiVolMatrixOneMinusOne_(const CoinPackedMatrix& m) {
00104   const int major = m.getMajorDim();
00105   const double* elem = m.getElements();
00106   const int* ind = m.getIndices();
00107   const int* start = m.getVectorStarts();
00108   const int* length = m.getVectorLengths();
00109 
00110   majorDim_ = major;
00111   minorDim_ = m.getMinorDim();
00112 
00113   plusSize_ = 0;
00114   minusSize_ = 0;
00115   int i, j;
00116   for (i = 0; i < major; ++i) {
00117     for (j = start[i] + length[i] - 1; j >= start[i]; --j) {
00118       const double val = elem[j];
00119       if (val == 1.0) {
00120         ++plusSize_;
00121       } else if (val == -1.0) {
00122         ++minusSize_;
00123       }
00124     }
00125   }
00126   if (plusSize_ > 0) {
00127     plusInd_ = new int[plusSize_];
00128   }
00129   if (minusSize_ > 0) {
00130     minusInd_ = new int[minusSize_];
00131   }
00132   plusStart_ = new int[major];
00133   plusLength_ = new int[major];
00134   minusStart_ = new int[major];
00135   minusLength_ = new int[major];
00136 
00137   plusSize_ = 0;
00138   minusSize_ = 0;
00139   for (i = 0; i < major; ++i) {
00140     plusStart_[i] = plusSize_;
00141     minusStart_[i] = minusSize_;
00142     const int last = start[i] + length[i];
00143     for (j = start[i]; j < last; ++j) {
00144       const double val = elem[j];
00145       if (val == 1.0) {
00146         plusInd_[plusSize_++] = ind[j];
00147       } else if (val == -1.0) {
00148         minusInd_[minusSize_++] = ind[j];
00149       }
00150     }
00151     plusLength_[i] = plusSize_ - plusStart_[i];
00152     minusLength_[i] = minusSize_ - minusStart_[i];
00153   }
00154   if (plusSize_ == 0) {
00155     delete[] plusStart_;    plusStart_  = NULL;
00156     delete[] plusLength_;   plusLength_ = NULL;
00157   }
00158   if (minusSize_ == 0) {
00159     delete[] minusStart_;    minusStart_  = NULL;
00160     delete[] minusLength_;   minusLength_ = NULL;
00161   }
00162 }
00163 
00164 //-----------------------------------------------------------------------------
00165 
00166 OsiVolSolverInterface::OsiVolMatrixOneMinusOne_::
00167 ~OsiVolMatrixOneMinusOne_() {
00168   if (plusSize_ > 0) {
00169     delete[] plusInd_;      plusInd_    = NULL;
00170     delete[] plusStart_;    plusStart_  = NULL;
00171     delete[] plusLength_;   plusLength_ = NULL;
00172   }
00173   if (minusSize_ > 0) {
00174     delete[] minusInd_;      minusInd_    = NULL;
00175     delete[] minusStart_;    minusStart_  = NULL;
00176     delete[] minusLength_;   minusLength_ = NULL;
00177   }
00178 }
00179 
00180 //-----------------------------------------------------------------------------
00181 
00182 void OsiVolSolverInterface::OsiVolMatrixOneMinusOne_::
00183 timesMajor(const double* x, double* y) const
00184 {
00185   memset(y, 0, minorDim_ * sizeof(double));
00186   int i;
00187 
00188   if (plusSize_ > 0 && minusSize_ > 0) {
00189     for (i = majorDim_ - 1; i >= 0; --i) {
00190       const double x_i = x[i];
00191       if (x_i != 0.0) {
00192         const int* vecInd = plusInd_ + plusStart_[i];
00193         int j;
00194         for ( j = plusLength_[i] - 1; j >= 0; --j)
00195           y[vecInd[j]] += x_i;
00196         vecInd = minusInd_ + minusStart_[i];
00197         for ( j = minusLength_[i] - 1; j >= 0; --j)
00198           y[vecInd[j]] -= x_i;
00199       }
00200     }
00201     return;
00202   }
00203   if (plusSize_ > 0) {
00204     for (i = majorDim_ - 1; i >= 0; --i) {
00205       const double x_i = x[i];
00206       if (x_i != 0.0) {
00207         const int* vecInd = plusInd_ + plusStart_[i];
00208         for (int j = plusLength_[i] - 1; j >= 0; --j)
00209           y[vecInd[j]] += x_i;
00210       }
00211     }
00212     return;
00213   }
00214   if (minusSize_ > 0) {
00215     for (i = majorDim_ - 1; i >= 0; --i) {
00216       const double x_i = x[i];
00217       if (x_i != 0.0) {
00218         const int* vecInd = minusInd_ + minusStart_[i];
00219         for (int j = minusLength_[i] - 1; j >= 0; --j)
00220           y[vecInd[j]] -= x_i;
00221       }
00222     }
00223     return;
00224   }
00225 }
00226 
00227 //#############################################################################
00228 
00229 void
00230 OsiVolSolverInterface::gutsOfDestructor_()
00231 {
00232   rowMatrix_.clear();
00233   colMatrix_.clear();
00234   rowMatrixCurrent_ = true;
00235   colMatrixCurrent_ = true;
00236 
00237   delete[] colupper_;   colupper_ = 0;  
00238   delete[] collower_;   collower_ = 0;  
00239   delete[] continuous_; continuous_ = 0;
00240   delete[] rowupper_;   rowupper_ = 0; 
00241   delete[] rowlower_;   rowlower_ = 0; 
00242   delete[] rowsense_;   rowsense_ = 0; 
00243   delete[] rhs_;        rhs_ = 0;      
00244   delete[] rowrange_;   rowrange_ = 0; 
00245   delete[] objcoeffs_;  objcoeffs_ = 0;
00246 
00247   delete[] colsol_;             colsol_ = 0;   
00248   delete[] rowprice_;           rowprice_ = 0;
00249   delete[] rowpriceHotStart_;   rowpriceHotStart_ = 0;
00250   delete[] rc_;                 rc_ = 0;
00251   delete[] lhs_;                lhs_ = 0;
00252 
00253   lagrangeanCost_ = 0.0;
00254 
00255   maxNumrows_ = 0;
00256   maxNumcols_ = 0;
00257 }
00258 
00259 //#############################################################################
00260 
00261 void
00262 OsiVolSolverInterface::rowRimAllocator_()
00263 {
00264    rowupper_ = new double[maxNumrows_];
00265    rowlower_ = new double[maxNumrows_];
00266    rowsense_ = new char[maxNumrows_];
00267    rhs_      = new double[maxNumrows_];
00268    rowrange_ = new double[maxNumrows_];
00269    rowprice_ = new double[maxNumrows_];
00270    lhs_      = new double[maxNumrows_];
00271 }
00272 
00273 //-----------------------------------------------------------------------------
00274 
00275 void
00276 OsiVolSolverInterface::colRimAllocator_()
00277 {
00278    colupper_  = new double[maxNumcols_];
00279    collower_  = new double[maxNumcols_];
00280    continuous_ = new bool[maxNumcols_];
00281    objcoeffs_ = new double[maxNumcols_];
00282    colsol_    = new double[maxNumcols_];
00283    rc_        = new double[maxNumcols_];
00284 }
00285 
00286 //-----------------------------------------------------------------------------
00287 
00288 void
00289 OsiVolSolverInterface::rowRimResize_(const int newSize)
00290 {
00291    if (newSize > maxNumrows_) {
00292       double* rub   = rowupper_;
00293       double* rlb   = rowlower_;
00294       char*   sense = rowsense_;
00295       double* right = rhs_;
00296       double* range = rowrange_;
00297       double* dual  = rowprice_;
00298       double* left  = lhs_;
00299       maxNumrows_ = CoinMax(1000, (newSize * 5) / 4);
00300       rowRimAllocator_();
00301       const int rownum = getNumRows();
00302       CoinDisjointCopyN(rub  , rownum, rowupper_);
00303       CoinDisjointCopyN(rlb  , rownum, rowlower_);
00304       CoinDisjointCopyN(sense, rownum, rowsense_);
00305       CoinDisjointCopyN(right, rownum, rhs_);
00306       CoinDisjointCopyN(range, rownum, rowrange_);
00307       CoinDisjointCopyN(dual , rownum, rowprice_);
00308       CoinDisjointCopyN(left , rownum, lhs_);
00309       delete[] rub;
00310       delete[] rlb;
00311       delete[] sense;
00312       delete[] right;
00313       delete[] range;
00314       delete[] dual;
00315       delete[] left;
00316    }
00317 }
00318 
00319 //-----------------------------------------------------------------------------
00320 
00321 void
00322 OsiVolSolverInterface::colRimResize_(const int newSize)
00323 {
00324    if (newSize > maxNumcols_) {
00325       double* cub = colupper_;
00326       double* clb = collower_;
00327       bool* cont  = continuous_;
00328       double* obj = objcoeffs_;
00329       double* sol = colsol_;
00330       double* rc  = rc_;
00331       maxNumcols_ = CoinMax(1000, (maxNumcols_ * 5) / 4);
00332       colRimAllocator_();
00333       const int colnum = getNumCols();
00334       CoinDisjointCopyN(cub , colnum, colupper_);
00335       CoinDisjointCopyN(clb , colnum, collower_);
00336       CoinDisjointCopyN(cont, colnum, continuous_);
00337       CoinDisjointCopyN(obj , colnum, objcoeffs_);
00338       CoinDisjointCopyN(sol , colnum, colsol_);
00339       CoinDisjointCopyN(rc  , colnum, rc_);
00340       delete[] cub;
00341       delete[] clb;
00342       delete[] cont;
00343       delete[] obj;
00344       delete[] sol;
00345       delete[] rc;
00346    }
00347 }
00348 
00349 //#############################################################################
00350 
00351 void
00352 OsiVolSolverInterface::convertBoundsToSenses_()
00353 {
00354    for (int i = getNumRows() - 1; i >= 0; --i ) {
00355       convertBoundToSense(rowlower_[i], rowupper_[i],
00356                           rowsense_[i], rhs_[i], rowrange_[i]);
00357    }
00358 }
00359 
00360 //-----------------------------------------------------------------------------
00361 
00362 void
00363 OsiVolSolverInterface::convertSensesToBounds_()
00364 {
00365    for (int i = getNumRows() - 1; i >= 0; --i) {
00366       convertSenseToBound(rowsense_[i], rhs_[i], rowrange_[i],
00367                           rowlower_[i], rowupper_[i]);
00368    }
00369 }
00370 
00371 //#############################################################################
00372 //  Here are the routines implementing the virtual methods inherited from
00373 //  VOL_user_hooks.
00374 //#############################################################################
00375 
00376 int
00377 OsiVolSolverInterface::compute_rc(const VOL_dvector& u, VOL_dvector& rc)
00378 {
00379    compute_rc_(u.v, rc.v);
00380    return 0;
00381 }
00382 
00383 //-----------------------------------------------------------------------
00384 
00385 int
00386 OsiVolSolverInterface::solve_subproblem(const VOL_dvector& dual,
00387                                         const VOL_dvector& rc,
00388                                         double& lcost,
00389                                         VOL_dvector& x, VOL_dvector& v,
00390                                         double& pcost)
00391 {
00392   int i;
00393 
00394   const int psize = x.size();
00395   for (i = 0; i < psize; ++i) {
00396     x[i] = (rc[i] >= 0.0) ? collower_[i] : colupper_[i];
00397   }
00398    
00399   const int dsize = v.size();
00400   lcost = (std::inner_product(rhs_, rhs_ + dsize, dual.v, 0.0) +
00401            std::inner_product(x.v, x.v + psize, rc.v, 0.0) );
00402 
00403   if (isZeroOneMinusOne_) {
00404     colMatrixOneMinusOne_->timesMajor(x.v, v.v);
00405   } else {
00406     colMatrix_.times(x.v, v.v);
00407   }
00408 
00409   std::transform(v.v, v.v+dsize, rhs_, v.v, std::minus<double>());
00410   std::transform(v.v, v.v+dsize, v.v, std::negate<double>());
00411 
00412   pcost = std::inner_product(x.v, x.v + psize, objcoeffs_, 0.0);
00413 
00414   return 0;
00415 }
00416 
00417 //#############################################################################
00418 // Solve methods
00419 //#############################################################################
00420 
00421 void 
00422 OsiVolSolverInterface::initialSolve()
00423 {
00424    // set every entry to 0.0 in the dual solution
00425    CoinFillN(rowprice_, getNumRows(), 0.0);
00426    resolve();
00427 }
00428 
00429 //-----------------------------------------------------------------------------
00430 
00431 void 
00432 OsiVolSolverInterface::resolve()
00433 {
00434   int i;
00435   
00436   checkData_();
00437 
00438   // Only one of these can do any work
00439   updateRowMatrix_();
00440   updateColMatrix_();
00441 
00442   const int dsize = getNumRows();
00443   const int psize = getNumCols();
00444 
00445   // Negate the objective coefficients if necessary
00446   if (objsense_ < 0) {
00447     std::transform(objcoeffs_, objcoeffs_+psize, objcoeffs_,
00448                    std::negate<double>());
00449   }
00450 
00451   // Set the lb/ub on the duals
00452   volprob_.dual_lb.allocate(dsize);
00453   volprob_.dual_ub.allocate(dsize);
00454   double * dlb = volprob_.dual_lb.v;
00455   double * dub = volprob_.dual_ub.v;
00456   for (i = 0; i < dsize; ++i) {
00457     dlb[i] = rowupper_[i] <  OsiVolInfinity ? -1.0e31 : 0.0;
00458     dub[i] = rowlower_[i] > -OsiVolInfinity ?  1.0e31 : 0.0;
00459   }
00460   volprob_.dsize = dsize;
00461   volprob_.psize = psize;
00462   
00463   // Set the dual starting point
00464   VOL_dvector& dsol = volprob_.dsol;
00465   dsol.allocate(dsize);
00466   std::transform(rowprice_, rowprice_+dsize, dsol.v,
00467                  std::bind2nd(std::multiplies<double>(), objsense_));
00468 
00469   // adjust the dual vector (if necessary) to be sure it's feasible
00470   double * dv = dsol.v;
00471   for (i = 0; i < dsize; ++i) {
00472     if (dv[i] < dlb[i]) {
00473       dv[i] = dlb[i];
00474     } else if (dv[i] > dub[i]) {
00475       dv[i] = dub[i];
00476     }
00477   }
00478 
00479   // If requested, check whether the matrix contains anything but 0/1/-1
00480 #if 0
00481   isZeroOneMinusOne_ = false;
00482 #else
00483   isZeroOneMinusOne_ = test_zero_one_minusone_(colMatrix_);
00484   if (isZeroOneMinusOne_) {
00485     colMatrixOneMinusOne_ = new OsiVolMatrixOneMinusOne_(colMatrix_);
00486     rowMatrixOneMinusOne_ = new OsiVolMatrixOneMinusOne_(rowMatrix_);
00487   }
00488 #endif
00489 
00490   volprob_.solve(*this, true);
00491 
00492   // extract the solution
00493 
00494   // the lower bound on the objective value
00495   lagrangeanCost_ = objsense_ * volprob_.value;
00496   // the primal solution
00497   CoinDisjointCopyN(volprob_.psol.v, psize, colsol_);
00498 
00499   // Reset the objective coefficients if necessary
00500   if (objsense_ < 0) {
00501     std::transform(objcoeffs_, objcoeffs_ + psize, objcoeffs_,
00502                    std::negate<double>());
00503     // also, multiply the dual solution by -1
00504     std::transform(volprob_.dsol.v, volprob_.dsol.v+dsize, rowprice_,
00505                    std::negate<double>());
00506   } else {
00507     // now we just have to copy the dual
00508     CoinDisjointCopyN(volprob_.dsol.v, dsize, rowprice_);
00509   }
00510 
00511   // Compute the reduced costs
00512   compute_rc_(rowprice_, rc_);
00513 
00514   // Compute the left hand side (row activity levels)
00515   if (isZeroOneMinusOne_) {
00516     colMatrixOneMinusOne_->timesMajor(colsol_, lhs_);
00517   } else {
00518     colMatrix_.times(colsol_, lhs_);
00519   }
00520 
00521   if (isZeroOneMinusOne_) {
00522     delete colMatrixOneMinusOne_;
00523     colMatrixOneMinusOne_ = NULL;
00524     delete rowMatrixOneMinusOne_;
00525     rowMatrixOneMinusOne_ = NULL;
00526   }
00527 }
00528 
00529 //#############################################################################
00530 // Parameter related methods
00531 //#############################################################################
00532 
00533 bool
00534 OsiVolSolverInterface::setIntParam(OsiIntParam key, int value)
00535 {
00536   switch (key) {
00537   case OsiMaxNumIteration:
00538     if (value < 0)
00539       return false;
00540     volprob_.parm.maxsgriters = value;
00541     break;
00542   case OsiMaxNumIterationHotStart:
00543     if (value < 0)
00544       return false;
00545     OsiSolverInterface::setIntParam(key, value);
00546     break;
00547   case OsiLastIntParam:
00548     return false;
00549   }
00550   return true;
00551 }
00552 
00553 //-----------------------------------------------------------------------------
00554 
00555 bool
00556 OsiVolSolverInterface::setDblParam(OsiDblParam key, double value)
00557 {
00558   switch (key) {
00559   case OsiDualObjectiveLimit:
00560     volprob_.parm.ubinit = value;
00561     break;
00562   case OsiPrimalObjectiveLimit: // not applicable
00563     return false;
00564   case OsiDualTolerance: // only ~0 is applicable, so accept only 1e-50 ...
00565     return (value == 1e-50);
00566   case OsiPrimalTolerance:
00567     if (value < 1e-04 || value > 1e-1)
00568       return false;
00569     volprob_.parm.primal_abs_precision = value;
00570     break;
00571   case OsiObjOffset: 
00572     return OsiSolverInterface::setDblParam(key, value);
00573   case OsiLastDblParam:
00574     return false;
00575   }
00576   return true;
00577 }
00578 
00579 
00580 //-----------------------------------------------------------------------------
00581 
00582 bool
00583 OsiVolSolverInterface::setStrParam(OsiStrParam key, const std::string & value)
00584 {
00585   bool retval=false;
00586   switch (key) {
00587   case OsiSolverName:
00588     return false;
00589 
00590   case OsiProbName:
00591     OsiSolverInterface::setStrParam(key,value);
00592     return retval = true;
00593 
00594   case OsiLastStrParam:
00595     return false;
00596   }
00597   return false;
00598 }
00599 
00600 //-----------------------------------------------------------------------------
00601 
00602 bool
00603 OsiVolSolverInterface::getIntParam(OsiIntParam key, int& value) const
00604 {
00605   switch (key) {
00606   case OsiMaxNumIteration:
00607     value = volprob_.parm.maxsgriters;
00608     break;
00609   case OsiMaxNumIterationHotStart:
00610     OsiSolverInterface::getIntParam(key, value);
00611     break;
00612   case OsiLastIntParam:
00613     return false;
00614   }
00615   return true;
00616 }
00617 
00618 //-----------------------------------------------------------------------------
00619 
00620 bool
00621 OsiVolSolverInterface::getDblParam(OsiDblParam key, double& value) const
00622 {
00623   switch (key) {
00624   case OsiDualObjectiveLimit:
00625     value = volprob_.parm.ubinit;
00626     break;
00627   case OsiPrimalObjectiveLimit: // not applicable
00628     return false;
00629   case OsiDualTolerance: // not applicable, but must return almost 0
00630     value = 1e-50;
00631     break;
00632   case OsiPrimalTolerance:
00633     value = volprob_.parm.primal_abs_precision; 
00634     break;
00635   case OsiObjOffset:
00636     OsiSolverInterface::getDblParam(key, value);
00637     break;
00638   case OsiLastDblParam:
00639     return false;
00640   }
00641   return true;
00642 }
00643 
00644 
00645 //-----------------------------------------------------------------------------
00646 
00647 bool
00648 OsiVolSolverInterface::getStrParam(OsiStrParam key, std::string & value) const
00649 {
00650   switch (key) {
00651   case OsiProbName:
00652     OsiSolverInterface::getStrParam(key, value);
00653     return true;
00654   case OsiSolverName:
00655     value = "vol";
00656     return true;
00657   case OsiLastStrParam:
00658     return false;
00659   }
00660   return false;
00661 }
00662 //#############################################################################
00663 // Methods returning info on how the solution process terminated
00664 //#############################################################################
00665 
00666 bool
00667 OsiVolSolverInterface::isAbandoned() const
00668 {
00669   // *THINK*: see the *THINK* in isProvenOptimal()
00670   return false;
00671 }
00672 
00673 bool
00674 OsiVolSolverInterface::isProvenOptimal() const
00675 {
00676   // if exited before reaching the iteration limit it is declared optimal
00677   // *THINK*: Granted, it can exit because the dual value is not improving.
00678   // *THINK*: Should that be "abandoned"? But then it'll be abandoned way too
00679   // *THINK*: frequently... 
00680   return (! isDualObjectiveLimitReached() &&
00681           volprob_.iter() < volprob_.parm.maxsgriters);
00682 }
00683 
00684 bool
00685 OsiVolSolverInterface::isProvenPrimalInfeasible() const
00686 {
00687   // LL: *FIXME* : at the moment the volume can't detect primal infeasibility.
00688   // LL: *FIXME* : The dual will go to infinity.
00689   return false;
00690 }
00691 
00692 bool
00693 OsiVolSolverInterface::isProvenDualInfeasible() const
00694 {
00695   // LL: *FIXME* : at the moment the volume assumes dual feasibility...
00696   return false;
00697 }
00698 
00699 bool
00700 OsiVolSolverInterface::isPrimalObjectiveLimitReached() const
00701 {
00702   // The volume algorithm doesn't know anything about the primal; only the
00703   // dual is monotone
00704   return false;
00705 }
00706 
00707 bool
00708 OsiVolSolverInterface::isDualObjectiveLimitReached() const
00709 {
00710   return volprob_.parm.ubinit - volprob_.value < volprob_.parm.granularity;
00711 }
00712 
00713 bool
00714 OsiVolSolverInterface::isIterationLimitReached() const
00715 {
00716   return volprob_.iter() >= volprob_.parm.maxsgriters;
00717 }
00718 
00719 //#############################################################################
00720 // WarmStart related methods
00721 //#############################################################################
00722 
00723 CoinWarmStart*
00724 OsiVolSolverInterface::getEmptyWarmStart () const
00725 { return (dynamic_cast<CoinWarmStart *>(new CoinWarmStartDual())) ; }
00726 
00727 CoinWarmStart*
00728 OsiVolSolverInterface::getWarmStart() const
00729 {
00730   return new CoinWarmStartDual(getNumRows(), rowprice_);
00731 }
00732 
00733 //-----------------------------------------------------------------------------
00734 
00735 bool
00736 OsiVolSolverInterface::setWarmStart(const CoinWarmStart* warmstart)
00737 {
00738   const CoinWarmStartDual* ws =
00739     dynamic_cast<const CoinWarmStartDual*>(warmstart);
00740 
00741   if (! ws)
00742     return false;
00743 
00744   const int ws_size = ws->size();
00745   if (ws_size != getNumRows() && ws_size != 0) {
00746     throw CoinError("wrong dual warmstart size", "setWarmStart",
00747                    "OsiVolSolverInterface");
00748   }
00749 
00750   CoinDisjointCopyN(ws->dual(), ws_size, rowprice_);
00751   return true;
00752 }
00753 
00754 //#############################################################################
00755 // HotStart related methods
00756 //#############################################################################
00757 
00758 void
00759 OsiVolSolverInterface::markHotStart()
00760 {
00761   delete[] rowpriceHotStart_;
00762   rowpriceHotStart_ = new double[getNumRows()];
00763   CoinDisjointCopyN(rowprice_, getNumRows(), rowpriceHotStart_);
00764 }
00765 
00766 void
00767 OsiVolSolverInterface::solveFromHotStart()
00768 {
00769    int itlimOrig = volprob_.parm.maxsgriters;
00770    getIntParam(OsiMaxNumIterationHotStart, volprob_.parm.maxsgriters);
00771    CoinDisjointCopyN(rowpriceHotStart_, getNumRows(), rowprice_);
00772    resolve();
00773    volprob_.parm.maxsgriters = itlimOrig;
00774 }
00775 
00776 void
00777 OsiVolSolverInterface::unmarkHotStart()
00778 {
00779   delete[] rowpriceHotStart_;
00780   rowpriceHotStart_ = NULL;
00781 }
00782 
00783 //#############################################################################
00784 // Problem information methods (original data)
00785 //#############################################################################
00786 
00787 bool 
00788 OsiVolSolverInterface::isContinuous(int colNumber) const
00789 {
00790   assert( continuous_!=NULL );
00791   if ( continuous_[colNumber] ) return true;
00792   return false;
00793 }
00794 
00795 //-----------------------------------------------------------------------------
00796 
00797 const CoinPackedMatrix *
00798 OsiVolSolverInterface::getMatrixByRow() const {
00799    updateRowMatrix_();
00800    return &rowMatrix_;
00801 }
00802 
00803 //-----------------------------------------------------------------------
00804 
00805 const CoinPackedMatrix *
00806 OsiVolSolverInterface::getMatrixByCol() const {
00807    updateColMatrix_();
00808    return &colMatrix_;
00809 }
00810 
00811 //#############################################################################
00812 // Problem information methods (results)
00813 //#############################################################################
00814 
00815 std::vector<double*> OsiVolSolverInterface::getDualRays(int maxNumRays) const
00816 {
00817   // *FIXME* : must write the method -LL
00818   throw CoinError("method is not yet written", "getDualRays",
00819                  "OsiVolSolverInterface");
00820   return std::vector<double*>();
00821 }
00822 //------------------------------------------------------------------
00823 std::vector<double*> OsiVolSolverInterface::getPrimalRays(int maxNumRays) const
00824 {
00825   // *FIXME* : must write the method -LL
00826   throw CoinError("method is not yet written", "getPrimalRays",
00827                  "OsiVolSolverInterface");
00828   return std::vector<double*>();
00829 }
00830 
00831 //#############################################################################
00832 // Problem modifying methods (rim vectors)
00833 //#############################################################################
00834 
00835 //-----------------------------------------------------------------------------
00836 void OsiVolSolverInterface::setColSetBounds(const int* indexFirst,
00837                                             const int* indexLast,
00838                                             const double* boundList)
00839 {
00840   while (indexFirst < indexLast) {
00841     const int ind = *indexFirst;
00842     collower_[ind] = boundList[0];
00843     colupper_[ind] = boundList[1];
00844     ++indexFirst;
00845     boundList += 2;
00846   }
00847 }
00848 
00849 //-----------------------------------------------------------------------------
00850 void OsiVolSolverInterface::setRowSetBounds(const int* indexFirst,
00851                                             const int* indexLast,
00852                                             const double* boundList)
00853 {
00854   if (indexLast - indexFirst < getNumRows() / 3) {
00855     while (indexFirst < indexLast) {
00856       setRowBounds(*indexFirst, boundList[0], boundList[1]);
00857       ++indexFirst;
00858       boundList += 2;
00859     }
00860   } else {
00861     // it's better to convert everything at once
00862     while (indexFirst < indexLast) {
00863       const int ind = *indexFirst;
00864       rowlower_[ind] = boundList[0];
00865       rowupper_[ind] = boundList[1];
00866       ++indexFirst;
00867       boundList += 2;
00868     }
00869     convertBoundsToSenses_();
00870   }
00871 }
00872 
00873 //-----------------------------------------------------------------------------
00874 void OsiVolSolverInterface::setRowSetTypes(const int* indexFirst,
00875                                            const int* indexLast,
00876                                            const char* senseList,
00877                                            const double* rhsList,
00878                                            const double* rangeList)
00879 {
00880   if (indexLast - indexFirst < getNumRows() / 3) {
00881     while (indexFirst < indexLast) {
00882       setRowType(*indexFirst++, *senseList++, *rhsList++, *rangeList++);
00883     }
00884   } else {
00885     // it's better to convert everything at once
00886     while (indexFirst < indexLast) {
00887       const int ind = *indexFirst++;
00888       rowsense_[ind] = *senseList++;
00889       rhs_[ind] = *rhsList++;
00890       rowrange_[ind] = *rangeList++;
00891     }
00892     convertSensesToBounds_();
00893   }
00894 }
00895 
00896 //#############################################################################
00897 
00898 void
00899 OsiVolSolverInterface::setContinuous(int index)
00900 {
00901   assert(continuous_ != NULL);
00902   if (index < 0 || index > getNumCols()) {
00903     throw CoinError("Index out of bound.", "setContinuous",
00904                    "OsiVolSolverInterface");
00905   }
00906   continuous_[index] = true;
00907 }
00908 
00909 //-----------------------------------------------------------------------
00910 
00911 void
00912 OsiVolSolverInterface::setInteger(int index)
00913 {
00914   assert(continuous_ != NULL);
00915   if (index < 0 || index > getNumCols()) {
00916     throw CoinError("Index out of bound.", "setContinuous",
00917                    "OsiVolSolverInterface");
00918   }
00919   continuous_[index] = false;
00920 }
00921 
00922 //-----------------------------------------------------------------------
00923 
00924 void
00925 OsiVolSolverInterface::setContinuous(const int* indices, int len)
00926 {
00927   assert(continuous_ != NULL);
00928   const int colnum = getNumCols();
00929   int i;
00930 
00931   for (i = len - 1; i >= 0; --i) {
00932     if (indices[i] < 0 || indices[i] > colnum) {
00933       throw CoinError("Index out of bound.", "setContinuous",
00934                      "OsiVolSolverInterface");
00935     }
00936   }
00937   
00938   for (i = len - 1; i >= 0; --i) {
00939     continuous_[indices[i]] = true;
00940   }
00941 }
00942 
00943 //-----------------------------------------------------------------------
00944 
00945 void
00946 OsiVolSolverInterface::setInteger(const int* indices, int len)
00947 {
00948   assert(continuous_ != NULL);
00949   const int colnum = getNumCols();
00950   int i;
00951 
00952   for (i = len - 1; i >= 0; --i) {
00953     if (indices[i] < 0 || indices[i] > colnum) {
00954       throw CoinError("Index out of bound.", "setContinuous",
00955                      "OsiVolSolverInterface");
00956     }
00957   }
00958   
00959   for (i = len - 1; i >= 0; --i) {
00960     continuous_[indices[i]] = false;
00961   }
00962 }
00963 
00964 //#############################################################################
00965 
00966 void
00967 OsiVolSolverInterface::setColSolution(const double *colsol)
00968 {
00969    CoinDisjointCopyN(colsol, getNumCols(), colsol_);
00970 }
00971 
00972 //-----------------------------------------------------------------------
00973 
00974 void
00975 OsiVolSolverInterface::setRowPrice(const double *rowprice)
00976 {
00977    CoinDisjointCopyN(rowprice, getNumRows(), rowprice_);
00978 }
00979 
00980 //#############################################################################
00981 // Problem modifying methods (matrix)
00982 //#############################################################################
00983 
00984 void 
00985 OsiVolSolverInterface::addCol(const CoinPackedVectorBase& vec,
00986                               const double collb, const double colub,   
00987                               const double obj)
00988 {
00989   const int colnum = getNumCols();
00990   colRimResize_(colnum + 1);
00991   collower_[colnum]   = collb;
00992   colupper_[colnum]   = colub;
00993   objcoeffs_[colnum]  = obj;
00994   continuous_[colnum] = true;
00995   colsol_[colnum]     = fabs(collb)<fabs(colub) ? collb : colub;
00996   rc_[colnum]         = 0.0;
00997 
00998   updateColMatrix_();
00999   colMatrix_.appendCol(vec);
01000   rowMatrixCurrent_ = false;
01001 }
01002 
01003 //-----------------------------------------------------------------------------
01004 
01005 void 
01006 OsiVolSolverInterface::addCols(const int numcols,
01007                                const CoinPackedVectorBase * const * cols,
01008                                const double* collb, const double* colub,   
01009                                const double* obj)
01010 {
01011   if (numcols > 0) {
01012     const int colnum = getNumCols();
01013     colRimResize_(colnum + numcols);
01014     CoinDisjointCopyN(collb, numcols, collower_ + colnum);
01015     CoinDisjointCopyN(colub, numcols, colupper_ + colnum);
01016     CoinDisjointCopyN(obj, numcols, objcoeffs_ + colnum);
01017     CoinFillN(continuous_ + colnum, numcols, true);
01018     int c;
01019     for ( c=0; c<numcols; c++ ) {
01020       if ( fabs(collb[c]) < fabs(colub[c]) ) {
01021         colsol_[colnum+c] = collb[c];
01022       }
01023       else {
01024         colsol_[colnum+c] = colub[c];
01025       }
01026     }
01027     //CoinFillN(colsol_     + colnum, numcols, 0.0);
01028     CoinFillN(rc_         + colnum, numcols, 0.0);
01029 
01030     updateColMatrix_();
01031     colMatrix_.appendCols(numcols, cols);
01032     rowMatrixCurrent_ = false;
01033   }
01034 }
01035 
01036 //-----------------------------------------------------------------------------
01037 
01038 void 
01039 OsiVolSolverInterface::deleteCols(const int num, const int * columnIndices)
01040 {
01041   if (num > 0) {
01042     int * delPos = new int[num];
01043     CoinDisjointCopyN(columnIndices, num, delPos);
01044     std::sort(delPos, delPos + num);
01045     const int delNum = std::unique(delPos, delPos + num) - delPos;
01046 
01047     const int colnum = getNumCols();
01048     CoinDeleteEntriesFromArray(collower_, collower_ + colnum,
01049                                delPos, delPos + delNum);
01050     CoinDeleteEntriesFromArray(colupper_, colupper_ + colnum,
01051                                delPos, delPos + delNum);
01052     CoinDeleteEntriesFromArray(objcoeffs_, objcoeffs_ + colnum,
01053                                delPos, delPos + delNum);
01054     CoinDeleteEntriesFromArray(continuous_, continuous_ + colnum,
01055                                delPos, delPos + delNum);
01056     CoinDeleteEntriesFromArray(colsol_, colsol_ + colnum,
01057                                delPos, delPos + delNum);
01058     CoinDeleteEntriesFromArray(rc_, rc_ + colnum,
01059                                delPos, delPos + delNum);
01060 
01061     updateColMatrix_();
01062     colMatrix_.deleteCols(delNum, delPos);
01063     rowMatrixCurrent_ = false;
01064   }
01065 }
01066 
01067 
01068 //-----------------------------------------------------------------------------
01069 
01070 void 
01071 OsiVolSolverInterface::addRow(const CoinPackedVectorBase& vec,
01072                               const double rowlb, const double rowub)
01073 {
01074   const int rownum = getNumRows();
01075   rowRimResize_(rownum + 1);
01076   rowlower_[rownum] = rowlb;
01077   rowupper_[rownum] = rowub;
01078   convertBoundToSense(rowlb, rowub,
01079                       rowsense_[rownum], rhs_[rownum], rowrange_[rownum]);
01080   rowprice_[rownum] = 0.0;
01081   lhs_[rownum] = 0.0;
01082 
01083   updateRowMatrix_();
01084   rowMatrix_.appendRow(vec);
01085   colMatrixCurrent_ = false;
01086 }
01087 
01088 //-----------------------------------------------------------------------------
01089 
01090 void 
01091 OsiVolSolverInterface::addRow(const CoinPackedVectorBase& vec,
01092                               const char rowsen, const double rowrhs,   
01093                               const double rowrng)
01094 {
01095   const int rownum = getNumRows();
01096   rowRimResize_(rownum + 1);
01097   rowsense_[rownum] = rowsen;
01098   rhs_[rownum] = rowrhs;
01099   rowrange_[rownum] = rowrng;
01100   convertSenseToBound(rowsen, rowrhs, rowrng,
01101                       rowlower_[rownum], rowupper_[rownum]);
01102   rowprice_[rownum] = 0.0;
01103   lhs_[rownum] = 0.0;
01104 
01105   updateRowMatrix_();
01106   rowMatrix_.appendRow(vec);
01107   colMatrixCurrent_ = false;
01108 }
01109 
01110 //-----------------------------------------------------------------------------
01111 
01112 void 
01113 OsiVolSolverInterface::addRows(const int numrows,
01114                                const CoinPackedVectorBase * const * rows,
01115                                const double* rowlb, const double* rowub)
01116 {
01117   if (numrows > 0) {
01118     const int rownum = getNumRows();
01119     rowRimResize_(rownum + numrows);
01120     CoinDisjointCopyN(rowlb, numrows, rowlower_ + rownum);
01121     CoinDisjointCopyN(rowub, numrows, rowupper_ + rownum);
01122     for (int i = rownum + numrows - 1; i >= rownum; --i) {
01123       convertBoundToSense(rowlower_[i], rowupper_[i],
01124                           rowsense_[i], rhs_[i], rowrange_[i]);
01125     }
01126     CoinFillN(rowprice_ + rownum, numrows, 0.0);
01127     CoinFillN(lhs_      + rownum, numrows, 0.0);
01128 
01129     updateRowMatrix_();
01130     rowMatrix_.appendRows(numrows, rows);
01131     colMatrixCurrent_ = false;
01132   }
01133 }
01134 
01135 //-----------------------------------------------------------------------------
01136 
01137 void 
01138 OsiVolSolverInterface::addRows(const int numrows,
01139                                const CoinPackedVectorBase * const * rows,
01140                                const char* rowsen, const double* rowrhs,   
01141                                const double* rowrng)
01142 {
01143   if (numrows > 0) {
01144     const int rownum = getNumRows();
01145     rowRimResize_(rownum + numrows);
01146     CoinDisjointCopyN(rowsen, numrows, rowsense_ + rownum);
01147     CoinDisjointCopyN(rowrhs, numrows, rhs_ + rownum);
01148     CoinDisjointCopyN(rowrng, numrows, rowrange_ + rownum);
01149     for (int i = rownum + numrows - 1; i >= rownum; --i) {
01150       convertSenseToBound(rowsense_[i], rhs_[i], rowrange_[i],
01151                           rowlower_[i], rowupper_[i]);
01152     }
01153     CoinFillN(rowprice_ + rownum, numrows, 0.0);
01154     CoinFillN(lhs_      + rownum, numrows, 0.0);
01155 
01156     updateRowMatrix_();
01157     rowMatrix_.appendRows(numrows, rows);
01158     colMatrixCurrent_ = false;
01159   }
01160 }
01161 
01162 //-----------------------------------------------------------------------------
01163 
01164 void 
01165 OsiVolSolverInterface::deleteRows(const int num, const int * rowIndices)
01166 {
01167   if (num > 0) {
01168     int * delPos = new int[num];
01169     CoinDisjointCopyN(rowIndices, num, delPos);
01170     std::sort(delPos, delPos + num);
01171     const int delNum = std::unique(delPos, delPos + num) - delPos;
01172 
01173     const int rownum = getNumRows();
01174     CoinDeleteEntriesFromArray(rowlower_, rowlower_ + rownum,
01175                                delPos, delPos + delNum);
01176     CoinDeleteEntriesFromArray(rowupper_, rowupper_ + rownum,
01177                                delPos, delPos + delNum);
01178     CoinDeleteEntriesFromArray(rowsense_, rowsense_ + rownum,
01179                                delPos, delPos + delNum);
01180     CoinDeleteEntriesFromArray(rowrange_, rowrange_ + rownum,
01181                                delPos, delPos + delNum);
01182     CoinDeleteEntriesFromArray(rhs_, rhs_ + rownum,
01183                                delPos, delPos + delNum);
01184     CoinDeleteEntriesFromArray(rowprice_, rowprice_ + rownum,
01185                                delPos, delPos + delNum);
01186     CoinDeleteEntriesFromArray(lhs_, lhs_ + rownum,
01187                                delPos, delPos + delNum);
01188 
01189     updateRowMatrix_();
01190     rowMatrix_.deleteRows(delNum, delPos);
01191     colMatrixCurrent_ = false;
01192 
01193     delete[] delPos;
01194   }
01195 }
01196    
01197 //#############################################################################
01198 // Constructors, destructors clone and assignment
01199 //#############################################################################
01200 
01201 OsiVolSolverInterface::OsiVolSolverInterface () :
01202    rowMatrixCurrent_(true),
01203    rowMatrix_(),
01204    colMatrixCurrent_(true),
01205    colMatrix_(),
01206 
01207    colupper_(0),
01208    collower_(0),
01209    continuous_(0),
01210    rowupper_(0),
01211    rowlower_(0),
01212    rowsense_(0),
01213    rhs_(0),
01214    rowrange_(0),
01215 
01216    objcoeffs_(0),
01217    objsense_(1.0),
01218    
01219    colsol_(0),
01220    rowprice_(0),
01221    rc_(0),
01222    lhs_(0),
01223    lagrangeanCost_(0.0),
01224 
01225    rowpriceHotStart_(0),
01226 
01227    maxNumrows_(0),
01228    maxNumcols_(0),
01229 
01230    volprob_()
01231 {
01232    volprob_.parm.granularity = 0.0;
01233 }
01234 
01235 //-----------------------------------------------------------------------
01236 
01237 OsiSolverInterface *
01238 OsiVolSolverInterface::clone(bool copyData) const {
01239   return copyData ?
01240     new OsiVolSolverInterface(*this) :
01241     new OsiVolSolverInterface();
01242 }
01243 
01244 //-----------------------------------------------------------------------
01245 
01246 OsiVolSolverInterface::OsiVolSolverInterface(const OsiVolSolverInterface& x) :
01247    rowMatrixCurrent_(true),
01248    rowMatrix_(),
01249    colMatrixCurrent_(true),
01250    colMatrix_(),
01251 
01252    colupper_(0),
01253    collower_(0),
01254    continuous_(0),
01255    rowupper_(0),
01256    rowlower_(0),
01257    rowsense_(0),
01258    rhs_(0),
01259    rowrange_(0),
01260 
01261    objcoeffs_(0),
01262    objsense_(1.0),
01263    
01264    colsol_(0),
01265    rowprice_(0),
01266    rc_(0),
01267    lhs_(0),
01268    lagrangeanCost_(0.0),
01269 
01270    rowpriceHotStart_(0),
01271 
01272    maxNumrows_(0),
01273    maxNumcols_(0),
01274 
01275    volprob_()
01276 {
01277    operator=(x);
01278    volprob_.parm.granularity = 0.0;
01279 }
01280 
01281 //-----------------------------------------------------------------------
01282 
01283 OsiVolSolverInterface&
01284 OsiVolSolverInterface::operator=(const OsiVolSolverInterface& rhs)
01285 {
01286    if (&rhs == this)
01287       return *this;
01288 
01289    OsiSolverInterface::operator=(rhs);
01290    gutsOfDestructor_();
01291 
01292    rowMatrixCurrent_ = rhs.rowMatrixCurrent_;
01293    if (rowMatrixCurrent_)
01294       rowMatrix_ = rhs.rowMatrix_;
01295    colMatrixCurrent_ = rhs.colMatrixCurrent_;
01296    if (colMatrixCurrent_)
01297       colMatrix_ = rhs.colMatrix_;
01298 
01299    if (rhs.maxNumrows_) {
01300       maxNumrows_ = rhs.maxNumrows_;
01301       rowRimAllocator_();
01302       const int rownum = getNumRows();
01303       CoinDisjointCopyN(rhs.rowupper_, rownum, rowupper_);
01304       CoinDisjointCopyN(rhs.rowlower_, rownum, rowlower_);
01305       CoinDisjointCopyN(rhs.rowsense_, rownum, rowsense_);
01306       CoinDisjointCopyN(rhs.rhs_, rownum, rhs_);
01307       CoinDisjointCopyN(rhs.rowrange_, rownum, rowrange_);
01308       CoinDisjointCopyN(rhs.rowprice_, rownum, rowprice_);
01309       CoinDisjointCopyN(rhs.lhs_, rownum, lhs_);
01310    }
01311    if (rhs.maxNumcols_) {
01312       maxNumcols_ = rhs.maxNumcols_;
01313       colRimAllocator_();
01314       const int colnum = getNumCols();
01315       CoinDisjointCopyN(rhs.colupper_, colnum, colupper_);
01316       CoinDisjointCopyN(rhs.collower_, colnum, collower_);
01317       CoinDisjointCopyN(rhs.continuous_, colnum, continuous_);
01318       CoinDisjointCopyN(rhs.objcoeffs_, colnum, objcoeffs_);
01319       CoinDisjointCopyN(rhs.colsol_, colnum, colsol_);
01320       CoinDisjointCopyN(rhs.rc_, colnum, rc_);
01321    }
01322    volprob_.parm.granularity = 0.0;
01323    return *this;
01324 }
01325 
01326 //-----------------------------------------------------------------------
01327 
01328 OsiVolSolverInterface::~OsiVolSolverInterface ()
01329 {
01330    gutsOfDestructor_();
01331 }
01332 
01333 //#############################################################################
01334 // Applying cuts
01335 //#############################################################################
01336 
01337 void
01338 OsiVolSolverInterface::applyRowCut(const OsiRowCut& rc)
01339 {
01340    const int rownum = getNumRows();
01341    const double lb = rc.lb();
01342    const double ub = rc.ub();
01343    rowRimResize_(rownum + 1);
01344    rowprice_[rownum] = 0.0;
01345    rowlower_[rownum] = lb;
01346    rowupper_[rownum] = ub;
01347    convertBoundToSense(lb, ub,
01348                        rowsense_[rownum], rhs_[rownum], rowrange_[rownum]);
01349 
01350    updateRowMatrix_();
01351    rowMatrix_.appendRow(rc.row());
01352    colMatrixCurrent_ = false;
01353 }
01354 
01355 //-----------------------------------------------------------------------
01356 
01357 void
01358 OsiVolSolverInterface::applyColCut(const OsiColCut& cc)
01359 {
01360    int i;
01361 
01362    const double* lb_elem = cc.lbs().getElements();
01363    const int* lb_ind = cc.lbs().getIndices();
01364    for (i = cc.lbs().getNumElements() - 1; i >= 0; --i) {
01365       collower_[lb_ind[i]] = CoinMax(collower_[lb_ind[i]], lb_elem[i]);
01366    }
01367    
01368    const double* ub_elem = cc.ubs().getElements();
01369    const int* ub_ind = cc.ubs().getIndices();
01370    for (i = cc.ubs().getNumElements() - 1; i >= 0; --i) {
01371       colupper_[ub_ind[i]] = CoinMin(colupper_[ub_ind[i]], ub_elem[i]);
01372    }
01373 }
01374 
01375 //#############################################################################

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