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

ClpNetworkMatrix.cpp

00001 // Copyright (C) 2003, International Business Machines
00002 // Corporation and others.  All Rights Reserved.
00003 
00004 
00005 #include <cstdio>
00006 
00007 #include "CoinPragma.hpp"
00008 #include "CoinIndexedVector.hpp"
00009 #include "CoinHelperFunctions.hpp"
00010 
00011 #include "ClpSimplex.hpp"
00012 #include "ClpFactorization.hpp"
00013 // at end to get min/max!
00014 #include "ClpNetworkMatrix.hpp"
00015 #include "ClpPlusMinusOneMatrix.hpp"
00016 #include "ClpMessage.hpp"
00017 #include <iostream>
00018 
00019 //#############################################################################
00020 // Constructors / Destructor / Assignment
00021 //#############################################################################
00022 
00023 //-------------------------------------------------------------------
00024 // Default Constructor 
00025 //-------------------------------------------------------------------
00026 ClpNetworkMatrix::ClpNetworkMatrix () 
00027   : ClpMatrixBase()
00028 {
00029   setType(11);
00030   elements_ = NULL;
00031   starts_ = NULL;
00032   lengths_=NULL;
00033   indices_=NULL;
00034   numberRows_=0;
00035   numberColumns_=0;
00036   trueNetwork_=false;
00037 }
00038 
00039 /* Constructor from two arrays */
00040 ClpNetworkMatrix::ClpNetworkMatrix(int numberColumns, const int * head,
00041                                    const int * tail)
00042   : ClpMatrixBase()
00043 {
00044   setType(11);
00045   elements_ = NULL;
00046   starts_ = NULL;
00047   lengths_=NULL;
00048   indices_=new int[2*numberColumns];;
00049   numberRows_=-1;
00050   numberColumns_=numberColumns;
00051   trueNetwork_=true;
00052   int iColumn;
00053   CoinBigIndex j=0;
00054   for (iColumn=0;iColumn<numberColumns_;iColumn++, j+=2) {
00055     int iRow = head[iColumn];
00056     numberRows_ = max(numberRows_,iRow);
00057     indices_[j]=iRow;
00058     iRow = tail[iColumn];
00059     numberRows_ = max(numberRows_,iRow);
00060     indices_[j+1]=iRow;
00061   }
00062   numberRows_++;
00063 }
00064 //-------------------------------------------------------------------
00065 // Copy constructor 
00066 //-------------------------------------------------------------------
00067 ClpNetworkMatrix::ClpNetworkMatrix (const ClpNetworkMatrix & rhs) 
00068 : ClpMatrixBase(rhs)
00069 {  
00070   elements_ = NULL;
00071   starts_ = NULL;
00072   lengths_=NULL;
00073   indices_=NULL;
00074   numberRows_=rhs.numberRows_;
00075   numberColumns_=rhs.numberColumns_;
00076   trueNetwork_=rhs.trueNetwork_;
00077   if (numberColumns_) {
00078     indices_ = new int [ 2*numberColumns_];
00079     memcpy(indices_,rhs.indices_,2*numberColumns_*sizeof(int));
00080   }
00081 }
00082 
00083 ClpNetworkMatrix::ClpNetworkMatrix (const CoinPackedMatrix & rhs) 
00084   : ClpMatrixBase()
00085 {  
00086   setType(11);
00087   elements_ = NULL;
00088   starts_ = NULL;
00089   lengths_=NULL;
00090   indices_=NULL;
00091   int iColumn;
00092   assert (rhs.isColOrdered());
00093   // get matrix data pointers
00094   const int * row = rhs.getIndices();
00095   const CoinBigIndex * columnStart = rhs.getVectorStarts();
00096   const int * columnLength = rhs.getVectorLengths(); 
00097   const double * elementByColumn = rhs.getElements();
00098   numberColumns_ = rhs.getNumCols();
00099   int goodNetwork=1;
00100   numberRows_=-1;
00101   indices_ = new int[2*numberColumns_];
00102   CoinBigIndex j=0;
00103   for (iColumn=0;iColumn<numberColumns_;iColumn++, j+=2) {
00104     CoinBigIndex k=columnStart[iColumn];
00105     int iRow;
00106     switch (columnLength[iColumn]) {
00107     case 0:
00108       goodNetwork=-1; // not classic network
00109       indices_[j]=-1;
00110       indices_[j+1]=-1;
00111       break;
00112       
00113     case 1:
00114       goodNetwork=-1; // not classic network
00115       if (fabs(elementByColumn[k]-1.0)<1.0e-10) {
00116         indices_[j] = -1;
00117         iRow = row[k];
00118         numberRows_ = max(numberRows_,iRow);
00119         indices_[j+1]=iRow;
00120       } else if (fabs(elementByColumn[k]+1.0)<1.0e-10) {
00121         indices_[j+1] = -1;
00122         iRow = row[k];
00123         numberRows_ = max(numberRows_,iRow);
00124         indices_[j]=iRow;
00125       } else {
00126         goodNetwork = 0; // not a network
00127       }
00128       break;
00129       
00130     case 2:
00131       if (fabs(elementByColumn[k]-1.0)<1.0e-10) {
00132         if (fabs(elementByColumn[k+1]+1.0)<1.0e-10) {
00133           iRow = row[k];
00134           numberRows_ = max(numberRows_,iRow);
00135           indices_[j+1]=iRow;
00136           iRow = row[k+1];
00137           numberRows_ = max(numberRows_,iRow);
00138           indices_[j] = iRow;
00139         } else {
00140           goodNetwork = 0; // not a network
00141         }
00142       } else if (fabs(elementByColumn[k]+1.0)<1.0e-10) {
00143         if (fabs(elementByColumn[k+1]-1.0)<1.0e-10) {
00144           iRow = row[k];
00145           numberRows_ = max(numberRows_,iRow);
00146           indices_[j]=iRow;
00147           iRow = row[k+1];
00148           numberRows_ = max(numberRows_,iRow);
00149           indices_[j+1] = iRow;
00150         } else {
00151           goodNetwork = 0; // not a network
00152         }
00153       } else {
00154         goodNetwork = 0; // not a network
00155       }
00156       break;
00157 
00158     default:
00159       goodNetwork = 0; // not a network
00160       break;
00161     }
00162     if (!goodNetwork)
00163       break;
00164   }
00165   if (!goodNetwork) {
00166     delete [] indices_;
00167     // put in message
00168     printf("Not a network - can test if indices_ null\n");
00169     indices_=NULL;
00170     numberRows_=0;
00171     numberColumns_=0;
00172   } else {
00173     numberRows_ ++; //  correct
00174     trueNetwork_ = goodNetwork>0;
00175   }
00176 }
00177 
00178 //-------------------------------------------------------------------
00179 // Destructor 
00180 //-------------------------------------------------------------------
00181 ClpNetworkMatrix::~ClpNetworkMatrix ()
00182 {
00183   delete [] elements_;
00184   delete [] starts_;
00185   delete [] lengths_;
00186   delete [] indices_;
00187 }
00188 
00189 //----------------------------------------------------------------
00190 // Assignment operator 
00191 //-------------------------------------------------------------------
00192 ClpNetworkMatrix &
00193 ClpNetworkMatrix::operator=(const ClpNetworkMatrix& rhs)
00194 {
00195   if (this != &rhs) {
00196     ClpMatrixBase::operator=(rhs);
00197     delete [] elements_;
00198     delete [] starts_;
00199     delete [] lengths_;
00200     delete [] indices_;
00201     elements_ = NULL;
00202     starts_ = NULL;
00203     lengths_=NULL;
00204     indices_=NULL;
00205     numberRows_=rhs.numberRows_;
00206     numberColumns_=rhs.numberColumns_;
00207     trueNetwork_=rhs.trueNetwork_;
00208     if (numberColumns_) {
00209       indices_ = new int [ 2*numberColumns_];
00210       memcpy(indices_,rhs.indices_,2*numberColumns_*sizeof(int));
00211     }
00212   }
00213   return *this;
00214 }
00215 //-------------------------------------------------------------------
00216 // Clone
00217 //-------------------------------------------------------------------
00218 ClpMatrixBase * ClpNetworkMatrix::clone() const
00219 {
00220   return new ClpNetworkMatrix(*this);
00221 }
00222 
00223 /* Returns a new matrix in reverse order without gaps */
00224 ClpMatrixBase * 
00225 ClpNetworkMatrix::reverseOrderedCopy() const
00226 {
00227   // count number in each row
00228   int * tempP = new int [numberRows_];
00229   int * tempN = new int [numberRows_];
00230   memset(tempP,0,numberRows_*sizeof(int));
00231   memset(tempN,0,numberRows_*sizeof(int));
00232   CoinBigIndex j=0;
00233   int i;
00234   for (i=0;i<numberColumns_;i++,j+=2) {
00235     int iRow = indices_[j];
00236     tempN[iRow]++;
00237     iRow = indices_[j+1];
00238     tempP[iRow]++;
00239   }
00240   int * newIndices = new int [2*numberColumns_];
00241   int * newP = new int [numberRows_+1];
00242   int * newN = new int[numberRows_];
00243   int iRow;
00244   j=0;
00245   // do starts
00246   for (iRow=0;iRow<numberRows_;iRow++) {
00247     newP[iRow]=j;
00248     j += tempP[iRow];
00249     tempP[iRow]=newP[iRow];
00250     newN[iRow] = j;
00251     j += tempN[iRow];
00252     tempN[iRow]=newN[iRow];
00253   }
00254   newP[numberRows_]=j;
00255   j=0;
00256   for (i=0;i<numberColumns_;i++,j+=2) {
00257     int iRow = indices_[j];
00258     int put = tempN[iRow];
00259     newIndices[put++] = i;
00260     tempN[iRow] = put;
00261     iRow = indices_[j+1];
00262     put = tempP[iRow];
00263     newIndices[put++] = i;
00264     tempP[iRow] = put;
00265   }
00266   delete [] tempP;
00267   delete [] tempN;
00268   ClpPlusMinusOneMatrix * newCopy = new ClpPlusMinusOneMatrix();
00269   newCopy->passInCopy(numberRows_, numberColumns_,
00270                       false,  newIndices, newP, newN);
00271   return newCopy;
00272 }
00273 //unscaled versions
00274 void 
00275 ClpNetworkMatrix::times(double scalar,
00276                    const double * x, double * y) const
00277 {
00278   int iColumn;
00279   CoinBigIndex j=0;
00280   if (trueNetwork_) {
00281     for (iColumn=0;iColumn<numberColumns_;iColumn++,j+=2) {
00282       double value = scalar*x[iColumn];
00283       if (value) {
00284         int iRowM = indices_[j];
00285         int iRowP = indices_[j+1];
00286         y[iRowM] -= value;
00287         y[iRowP] += value;
00288       }
00289     }
00290   } else {
00291     // skip negative rows
00292     for (iColumn=0;iColumn<numberColumns_;iColumn++,j+=2) {
00293       double value = scalar*x[iColumn];
00294       if (value) {
00295         int iRowM = indices_[j];
00296         int iRowP = indices_[j+1];
00297         if (iRowM>=0)
00298           y[iRowM] -= value;
00299         if (iRowP>=0)
00300           y[iRowP] += value;
00301       }
00302     }
00303   }
00304 }
00305 void 
00306 ClpNetworkMatrix::transposeTimes(double scalar,
00307                                 const double * x, double * y) const
00308 {
00309   int iColumn;
00310   CoinBigIndex j=0;
00311   if (trueNetwork_) {
00312     for (iColumn=0;iColumn<numberColumns_;iColumn++,j+=2) {
00313       double value = y[iColumn];
00314       int iRowM = indices_[j];
00315       int iRowP = indices_[j+1];
00316       value -= scalar*x[iRowM];
00317       value += scalar*x[iRowP];
00318       y[iColumn] = value;
00319     }
00320   } else {
00321     // skip negative rows
00322     for (iColumn=0;iColumn<numberColumns_;iColumn++,j+=2) {
00323       double value = y[iColumn];
00324       int iRowM = indices_[j];
00325       int iRowP = indices_[j+1];
00326       if (iRowM>=0)
00327         value -= scalar*x[iRowM];
00328       if (iRowP>=0)
00329         value += scalar*x[iRowP];
00330       y[iColumn] = value;
00331     }
00332   }
00333 }
00334 void 
00335 ClpNetworkMatrix::times(double scalar,
00336                        const double * x, double * y,
00337                        const double * rowScale, 
00338                        const double * columnScale) const
00339 {
00340   // we know it is not scaled 
00341   times(scalar, x, y);
00342 }
00343 void 
00344 ClpNetworkMatrix::transposeTimes( double scalar,
00345                                  const double * x, double * y,
00346                                  const double * rowScale, 
00347                                  const double * columnScale) const
00348 {
00349   // we know it is not scaled 
00350   transposeTimes(scalar, x, y);
00351 }
00352 /* Return <code>x * A + y</code> in <code>z</code>. 
00353         Squashes small elements and knows about ClpSimplex */
00354 void 
00355 ClpNetworkMatrix::transposeTimes(const ClpSimplex * model, double scalar,
00356                               const CoinIndexedVector * rowArray,
00357                               CoinIndexedVector * y,
00358                               CoinIndexedVector * columnArray) const
00359 {
00360   // we know it is not scaled 
00361   columnArray->clear();
00362   double * pi = rowArray->denseVector();
00363   int numberNonZero=0;
00364   int * index = columnArray->getIndices();
00365   double * array = columnArray->denseVector();
00366   int numberInRowArray = rowArray->getNumElements();
00367   // maybe I need one in OsiSimplex
00368   double zeroTolerance = model->factorization()->zeroTolerance();
00369   int numberRows = model->numberRows();
00370   ClpPlusMinusOneMatrix* rowCopy =
00371     dynamic_cast< ClpPlusMinusOneMatrix*>(model->rowCopy());
00372   bool packed = rowArray->packedMode();
00373   double factor = 0.3;
00374   // We may not want to do by row if there may be cache problems
00375   int numberColumns = model->numberColumns();
00376   // It would be nice to find L2 cache size - for moment 512K
00377   // Be slightly optimistic
00378   if (numberColumns*sizeof(double)>1000000) {
00379     if (numberRows*10<numberColumns)
00380       factor=0.1;
00381     else if (numberRows*4<numberColumns)
00382       factor=0.15;
00383     else if (numberRows*2<numberColumns)
00384       factor=0.2;
00385     //if (model->numberIterations()%50==0)
00386     //printf("%d nonzero\n",numberInRowArray);
00387   }
00388   if (numberInRowArray>factor*numberRows||!rowCopy) {
00389     // do by column
00390     int iColumn;
00391     assert (!y->getNumElements());
00392     CoinBigIndex j=0;
00393     if (packed) {
00394       // need to expand pi into y
00395       assert(y->capacity()>=numberRows);
00396       double * piOld = pi;
00397       pi = y->denseVector();
00398       const int * whichRow = rowArray->getIndices();
00399       int i;
00400       // modify pi so can collapse to one loop
00401       for (i=0;i<numberInRowArray;i++) {
00402         int iRow = whichRow[i];
00403         pi[iRow]=scalar*piOld[i];
00404       }
00405       if (trueNetwork_) {
00406         for (iColumn=0;iColumn<numberColumns_;iColumn++,j+=2) {
00407           double value = 0.0;
00408           int iRowM = indices_[j];
00409           int iRowP = indices_[j+1];
00410           value -= pi[iRowM];
00411           value += pi[iRowP];
00412           if (fabs(value)>zeroTolerance) {
00413             array[numberNonZero]=value;
00414             index[numberNonZero++]=iColumn;
00415           }
00416         }
00417       } else {
00418         // skip negative rows
00419         for (iColumn=0;iColumn<numberColumns_;iColumn++,j+=2) {
00420           double value = 0.0;
00421           int iRowM = indices_[j];
00422           int iRowP = indices_[j+1];
00423           if (iRowM>=0)
00424             value -= pi[iRowM];
00425           if (iRowP>=0)
00426             value += pi[iRowP];
00427           if (fabs(value)>zeroTolerance) {
00428             array[numberNonZero]=value;
00429             index[numberNonZero++]=iColumn;
00430           }
00431         }
00432       }
00433       for (i=0;i<numberInRowArray;i++) {
00434         int iRow = whichRow[i];
00435         pi[iRow]=0.0;
00436       }
00437     } else {
00438       if (trueNetwork_) {
00439         for (iColumn=0;iColumn<numberColumns_;iColumn++,j+=2) {
00440           double value = 0.0;
00441           int iRowM = indices_[j];
00442           int iRowP = indices_[j+1];
00443           value -= scalar*pi[iRowM];
00444           value += scalar*pi[iRowP];
00445           if (fabs(value)>zeroTolerance) {
00446             index[numberNonZero++]=iColumn;
00447             array[iColumn]=value;
00448           }
00449         }
00450       } else {
00451         // skip negative rows
00452         for (iColumn=0;iColumn<numberColumns_;iColumn++,j+=2) {
00453           double value = 0.0;
00454           int iRowM = indices_[j];
00455           int iRowP = indices_[j+1];
00456           if (iRowM>=0)
00457             value -= scalar*pi[iRowM];
00458           if (iRowP>=0)
00459             value += scalar*pi[iRowP];
00460           if (fabs(value)>zeroTolerance) {
00461             index[numberNonZero++]=iColumn;
00462             array[iColumn]=value;
00463           }
00464         }
00465       }
00466     }
00467     columnArray->setNumElements(numberNonZero);
00468   } else {
00469     // do by row
00470     rowCopy->transposeTimesByRow(model, scalar, rowArray, y, columnArray);
00471   }
00472 }
00473 /* Return <code>x *A in <code>z</code> but
00474    just for indices in y.
00475    Squashes small elements and knows about ClpSimplex */
00476 void 
00477 ClpNetworkMatrix::subsetTransposeTimes(const ClpSimplex * model,
00478                               const CoinIndexedVector * rowArray,
00479                               const CoinIndexedVector * y,
00480                               CoinIndexedVector * columnArray) const
00481 {
00482   columnArray->clear();
00483   double * pi = rowArray->denseVector();
00484   double * array = columnArray->denseVector();
00485   int jColumn;
00486   int numberToDo = y->getNumElements();
00487   const int * which = y->getIndices();
00488   assert (!rowArray->packedMode());
00489   columnArray->setPacked();
00490   if (trueNetwork_) {
00491     for (jColumn=0;jColumn<numberToDo;jColumn++) {
00492       int iColumn = which[jColumn];
00493       double value = 0.0;
00494       CoinBigIndex j=iColumn<<1;
00495       int iRowM = indices_[j];
00496       int iRowP = indices_[j+1];
00497       value -= pi[iRowM];
00498       value += pi[iRowP];
00499       array[jColumn]=value;
00500     }
00501   } else {
00502     // skip negative rows
00503     for (jColumn=0;jColumn<numberToDo;jColumn++) {
00504       int iColumn = which[jColumn];
00505       double value = 0.0;
00506       CoinBigIndex j=iColumn<<1;
00507       int iRowM = indices_[j];
00508       int iRowP = indices_[j+1];
00509       if (iRowM>=0)
00510         value -= pi[iRowM];
00511       if (iRowP>=0)
00512         value += pi[iRowP];
00513       array[jColumn]=value;
00514     }
00515   }
00516 }
00517 /* Returns number of elements in basis
00518    column is basic if entry >=0 */
00519 CoinBigIndex 
00520 ClpNetworkMatrix::numberInBasis(const int * columnIsBasic) const 
00521 {
00522   int i;
00523   CoinBigIndex numberElements=0;
00524   if (trueNetwork_) {
00525     for (i=0;i<numberColumns_;i++) {
00526       if (columnIsBasic[i]>=0) 
00527         numberElements ++;
00528     }
00529     numberElements *= 2;
00530   } else {
00531     for (i=0;i<numberColumns_;i++) {
00532       if (columnIsBasic[i]>=0) {
00533         CoinBigIndex j=i<<1;
00534         int iRowM = indices_[j];
00535         int iRowP = indices_[j+1];
00536         if (iRowM>=0)
00537           numberElements ++;
00538         if (iRowP>=0)
00539           numberElements ++;
00540       }
00541     }
00542   }
00543   return numberElements;
00544 }
00545 // Fills in basis (Returns number of elements and updates numberBasic)
00546 CoinBigIndex 
00547 ClpNetworkMatrix::fillBasis(const ClpSimplex * model,
00548                                 const int * columnIsBasic, int & numberBasic,
00549                                 int * indexRowU, int * indexColumnU,
00550                                 double * elementU) const 
00551 {
00552 #ifdef CLPDEBUG
00553   const double * rowScale = model->rowScale();
00554   assert (!rowScale);
00555 #endif
00556   int i;
00557   CoinBigIndex numberElements=0;
00558   if (trueNetwork_) {
00559     for (i=0;i<numberColumns_;i++) {
00560       if (columnIsBasic[i]>=0) {
00561         CoinBigIndex j=i<<1;
00562         int iRowM = indices_[j];
00563         int iRowP = indices_[j+1];
00564         indexRowU[numberElements]=iRowM;
00565         indexColumnU[numberElements]=numberBasic;
00566         elementU[numberElements]=-1.0;
00567         indexRowU[numberElements+1]=iRowP;
00568         indexColumnU[numberElements+1]=numberBasic;
00569         elementU[numberElements+1]=1.0;
00570         numberElements+=2;
00571         numberBasic++;
00572       }
00573     }
00574   } else {
00575     for (i=0;i<numberColumns_;i++) {
00576       if (columnIsBasic[i]>=0) {
00577         CoinBigIndex j=i<<1;
00578         int iRowM = indices_[j];
00579         int iRowP = indices_[j+1];
00580         if (iRowM>=0) {
00581           indexRowU[numberElements]=iRowM;
00582           indexColumnU[numberElements]=numberBasic;
00583           elementU[numberElements++]=-1.0;
00584         }
00585         if (iRowP>=0) {
00586           indexRowU[numberElements]=iRowP;
00587           indexColumnU[numberElements]=numberBasic;
00588           elementU[numberElements++]=1.0;
00589         }
00590         numberBasic++;
00591       }
00592     }
00593   }
00594   return numberElements;
00595 }
00596 /* If element NULL returns number of elements in column part of basis,
00597    If not NULL fills in as well */
00598 CoinBigIndex 
00599 ClpNetworkMatrix::fillBasis(const ClpSimplex * model,
00600                                  const int * whichColumn, 
00601                                  int numberBasic,
00602                                  int numberColumnBasic,
00603                                  int * indexRowU, int * indexColumnU,
00604                                  double * elementU) const 
00605 {
00606   int i;
00607   CoinBigIndex numberElements=0;
00608   if (elementU!=NULL) {
00609     if (trueNetwork_) {
00610       for (i=0;i<numberColumnBasic;i++) {
00611         int iColumn = whichColumn[i];
00612         CoinBigIndex j=iColumn<<1;
00613         int iRowM = indices_[j];
00614         int iRowP = indices_[j+1];
00615         indexRowU[numberElements]=iRowM;
00616         indexColumnU[numberElements]=numberBasic;
00617         elementU[numberElements]=-1.0;
00618         indexRowU[numberElements+1]=iRowP;
00619         indexColumnU[numberElements+1]=numberBasic;
00620         elementU[numberElements+1]=1.0;
00621         numberElements+=2;
00622         numberBasic++;
00623       }
00624     } else {
00625       for (i=0;i<numberColumnBasic;i++) {
00626         int iColumn = whichColumn[i];
00627         CoinBigIndex j=iColumn<<1;
00628         int iRowM = indices_[j];
00629         int iRowP = indices_[j+1];
00630         if (iRowM>=0) {
00631           indexRowU[numberElements]=iRowM;
00632           indexColumnU[numberElements]=numberBasic;
00633           elementU[numberElements++]=-1.0;
00634         }
00635         if (iRowP>=0) {
00636           indexRowU[numberElements]=iRowP;
00637           indexColumnU[numberElements]=numberBasic;
00638           elementU[numberElements++]=1.0;
00639         }
00640         numberBasic++;
00641       }
00642     }
00643   } else {
00644     if (trueNetwork_) {
00645       numberElements = 2*numberColumnBasic;
00646     } else {
00647       for (i=0;i<numberColumnBasic;i++) {
00648         int iColumn = whichColumn[i];
00649         CoinBigIndex j=iColumn<<1;
00650         int iRowM = indices_[j];
00651         int iRowP = indices_[j+1];
00652         if (iRowM>=0)
00653           numberElements ++;
00654         if (iRowP>=0)
00655           numberElements ++;
00656       }
00657     }
00658   }
00659   return numberElements;
00660 }
00661 /* Unpacks a column into an CoinIndexedvector
00662  */
00663 void 
00664 ClpNetworkMatrix::unpack(const ClpSimplex * model,CoinIndexedVector * rowArray,
00665                    int iColumn) const 
00666 {
00667   CoinBigIndex j=iColumn<<1;
00668   int iRowM = indices_[j];
00669   int iRowP = indices_[j+1];
00670   if (iRowM>=0) 
00671     rowArray->add(iRowM,-1.0);
00672   if (iRowP>=0) 
00673     rowArray->add(iRowP,1.0);
00674 }
00675 /* Unpacks a column into an CoinIndexedvector
00676 ** in packed foramt
00677 Note that model is NOT const.  Bounds and objective could
00678 be modified if doing column generation (just for this variable) */
00679 void 
00680 ClpNetworkMatrix::unpackPacked(ClpSimplex * model,
00681                             CoinIndexedVector * rowArray,
00682                             int iColumn) const
00683 {
00684   int * index = rowArray->getIndices();
00685   double * array = rowArray->denseVector();
00686   int number = 0;
00687   CoinBigIndex j=iColumn<<1;
00688   int iRowM = indices_[j];
00689   int iRowP = indices_[j+1];
00690   if (iRowM>=0) {
00691     array[number]=-1.0;
00692     index[number++]=iRowM;
00693   }
00694   if (iRowP>=0) {
00695     array[number]=1.0;
00696     index[number++]=iRowP;
00697   }
00698   rowArray->setNumElements(number);
00699   rowArray->setPackedMode(true);
00700 }
00701 /* Adds multiple of a column into an CoinIndexedvector
00702       You can use quickAdd to add to vector */
00703 void 
00704 ClpNetworkMatrix::add(const ClpSimplex * model,CoinIndexedVector * rowArray,
00705                    int iColumn, double multiplier) const 
00706 {
00707   CoinBigIndex j=iColumn<<1;
00708   int iRowM = indices_[j];
00709   int iRowP = indices_[j+1];
00710   if (iRowM>=0) 
00711     rowArray->quickAdd(iRowM,-multiplier);
00712   if (iRowP>=0) 
00713     rowArray->quickAdd(iRowP,multiplier);
00714 }
00715 
00716 // Return a complete CoinPackedMatrix
00717 CoinPackedMatrix * 
00718 ClpNetworkMatrix::getPackedMatrix() const 
00719 {
00720   return new CoinPackedMatrix(true,numberRows_,numberColumns_,
00721                               2*numberColumns_,
00722                               getElements(),indices_,
00723                               getVectorStarts(),getVectorLengths());
00724 
00725 }
00726 /* A vector containing the elements in the packed matrix. Note that there
00727    might be gaps in this list, entries that do not belong to any
00728    major-dimension vector. To get the actual elements one should look at
00729    this vector together with vectorStarts and vectorLengths. */
00730 const double * 
00731 ClpNetworkMatrix::getElements() const 
00732 {
00733   assert (trueNetwork_); // fix later
00734   if (!elements_) {
00735     elements_ = new double [2*numberColumns_];
00736     int i;
00737     for (i=0;i<2*numberColumns_;i+=2) {
00738       elements_[i]=-1.0;
00739       elements_[i+1]=1.0;
00740     }
00741   }
00742   return elements_;
00743 }
00744 
00745 const CoinBigIndex * 
00746 ClpNetworkMatrix::getVectorStarts() const 
00747 {
00748   assert (trueNetwork_); // fix later
00749   if (!starts_) {
00750     starts_ = new int [numberColumns_+1];
00751     int i;
00752     for (i=0;i<numberColumns_+1;i++) {
00753       starts_[i]=i;
00754     }
00755   }
00756   return starts_;
00757 }
00758 /* The lengths of the major-dimension vectors. */
00759 const int * 
00760 ClpNetworkMatrix::getVectorLengths() const
00761 {
00762   assert (trueNetwork_); // fix later
00763   if (!lengths_) {
00764     lengths_ = new int [numberColumns_];
00765     int i;
00766     for (i=0;i<numberColumns_;i++) {
00767       lengths_[i]=2;
00768     }
00769   }
00770   return lengths_;
00771 }
00772 /* Delete the columns whose indices are listed in <code>indDel</code>. */
00773 void ClpNetworkMatrix::deleteCols(const int numDel, const int * indDel) 
00774 {
00775   std::cerr<<"deleteCols not implemented in ClpNetworkMatrix"<<std::endl;
00776   abort();
00777 }
00778 /* Delete the rows whose indices are listed in <code>indDel</code>. */
00779 void ClpNetworkMatrix::deleteRows(const int numDel, const int * indDel) 
00780 {
00781   std::cerr<<"deleteRows not implemented in ClpNetworkMatrix"<<std::endl;
00782   abort();
00783 }
00784 /* Given positive integer weights for each row fills in sum of weights
00785    for each column (and slack).
00786    Returns weights vector
00787 */
00788 CoinBigIndex * 
00789 ClpNetworkMatrix::dubiousWeights(const ClpSimplex * model,int * inputWeights) const
00790 {
00791   int numberRows = model->numberRows();
00792   int numberColumns =model->numberColumns();
00793   int number = numberRows+numberColumns;
00794   CoinBigIndex * weights = new CoinBigIndex[number];
00795   int i;
00796   for (i=0;i<numberColumns;i++) {
00797     CoinBigIndex j=i<<1;
00798     CoinBigIndex count=0;
00799     int iRowM = indices_[j];
00800     int iRowP = indices_[j+1];
00801     if (iRowM>=0) {
00802       count += inputWeights[iRowM];
00803     }
00804     if (iRowP>=0) {
00805       count += inputWeights[iRowP];
00806     }
00807     weights[i]=count;
00808   }
00809   for (i=0;i<numberRows;i++) {
00810     weights[i+numberColumns]=inputWeights[i];
00811   }
00812   return weights;
00813 }
00814 /* Returns largest and smallest elements of both signs.
00815    Largest refers to largest absolute value.
00816 */
00817 void 
00818 ClpNetworkMatrix::rangeOfElements(double & smallestNegative, double & largestNegative,
00819                        double & smallestPositive, double & largestPositive)
00820 {
00821   smallestNegative=-1.0;
00822   largestNegative=-1.0;
00823   smallestPositive=1.0;
00824   largestPositive=1.0;
00825 }
00826 // Says whether it can do partial pricing
00827 bool 
00828 ClpNetworkMatrix::canDoPartialPricing() const
00829 {
00830   return true; 
00831 }
00832 // Partial pricing 
00833 void 
00834 ClpNetworkMatrix::partialPricing(ClpSimplex * model, int start, int end,
00835                               int & bestSequence, int & numberWanted)
00836 {
00837   int j;
00838   double tolerance=model->currentDualTolerance();
00839   double * reducedCost = model->djRegion();
00840   const double * duals = model->dualRowSolution();
00841   const double * cost = model->costRegion();
00842   double bestDj;
00843   if (bestSequence>=0)
00844     bestDj = fabs(reducedCost[bestSequence]);
00845   else
00846     bestDj=tolerance;
00847   int sequenceOut = model->sequenceOut();
00848   int saveSequence = bestSequence;
00849   if (!trueNetwork_) {
00850     // Not true network
00851     int iSequence;
00852     for (iSequence=start;iSequence<end;iSequence++) {
00853       if (iSequence!=sequenceOut) {
00854         double value;
00855         int iRowM,iRowP;
00856         ClpSimplex::Status status = model->getStatus(iSequence);
00857         
00858         switch(status) {
00859           
00860         case ClpSimplex::basic:
00861         case ClpSimplex::isFixed:
00862           break;
00863         case ClpSimplex::isFree:
00864         case ClpSimplex::superBasic:
00865           value=cost[iSequence];
00866           j = iSequence<<1;
00867           // skip negative rows
00868           iRowM = indices_[j];
00869           iRowP = indices_[j+1];
00870           if (iRowM>=0)
00871             value += duals[iRowM];
00872           if (iRowP>=0)
00873             value -= duals[iRowP];
00874           value = fabs(value);
00875           if (value>FREE_ACCEPT*tolerance) {
00876             numberWanted--;
00877             // we are going to bias towards free (but only if reasonable)
00878             value *= FREE_BIAS;
00879             if (value>bestDj) {
00880               // check flagged variable and correct dj
00881               if (!model->flagged(iSequence)) {
00882                 bestDj=value;
00883                 bestSequence = iSequence;
00884               } else {
00885                 // just to make sure we don't exit before got something
00886                 numberWanted++;
00887               }
00888             }
00889           }
00890           break;
00891         case ClpSimplex::atUpperBound:
00892           value=cost[iSequence];
00893           j = iSequence<<1;
00894           // skip negative rows
00895           iRowM = indices_[j];
00896           iRowP = indices_[j+1];
00897           if (iRowM>=0)
00898             value += duals[iRowM];
00899           if (iRowP>=0)
00900             value -= duals[iRowP];
00901           if (value>tolerance) {
00902             numberWanted--;
00903             if (value>bestDj) {
00904               // check flagged variable and correct dj
00905               if (!model->flagged(iSequence)) {
00906                 bestDj=value;
00907                 bestSequence = iSequence;
00908               } else {
00909                 // just to make sure we don't exit before got something
00910                 numberWanted++;
00911               }
00912             }
00913           }
00914           break;
00915         case ClpSimplex::atLowerBound:
00916           value=cost[iSequence];
00917           j = iSequence<<1;
00918           // skip negative rows
00919           iRowM = indices_[j];
00920           iRowP = indices_[j+1];
00921           if (iRowM>=0)
00922             value += duals[iRowM];
00923           if (iRowP>=0)
00924             value -= duals[iRowP];
00925           value = -value;
00926           if (value>tolerance) {
00927             numberWanted--;
00928             if (value>bestDj) {
00929               // check flagged variable and correct dj
00930               if (!model->flagged(iSequence)) {
00931                 bestDj=value;
00932                 bestSequence = iSequence;
00933               } else {
00934                 // just to make sure we don't exit before got something
00935                 numberWanted++;
00936               }
00937             }
00938           }
00939           break;
00940         }
00941       }
00942       if (!numberWanted)
00943         break;
00944     }
00945     if (bestSequence!=saveSequence) {
00946       // recompute dj
00947       double value=cost[bestSequence];
00948       j = bestSequence<<1;
00949       // skip negative rows
00950       int iRowM = indices_[j];
00951       int iRowP = indices_[j+1];
00952       if (iRowM>=0)
00953         value += duals[iRowM];
00954       if (iRowP>=0)
00955         value -= duals[iRowP];
00956       reducedCost[bestSequence] = value;
00957     }
00958   } else {
00959     // true network
00960     int iSequence;
00961     for (iSequence=start;iSequence<end;iSequence++) {
00962       if (iSequence!=sequenceOut) {
00963         double value;
00964         int iRowM,iRowP;
00965         ClpSimplex::Status status = model->getStatus(iSequence);
00966         
00967         switch(status) {
00968           
00969         case ClpSimplex::basic:
00970         case ClpSimplex::isFixed:
00971           break;
00972         case ClpSimplex::isFree:
00973         case ClpSimplex::superBasic:
00974           value=cost[iSequence];
00975           j = iSequence<<1;
00976           iRowM = indices_[j];
00977           iRowP = indices_[j+1];
00978           value += duals[iRowM];
00979           value -= duals[iRowP];
00980           value = fabs(value);
00981           if (value>FREE_ACCEPT*tolerance) {
00982             numberWanted--;
00983             // we are going to bias towards free (but only if reasonable)
00984             value *= FREE_BIAS;
00985             if (value>bestDj) {
00986               // check flagged variable and correct dj
00987               if (!model->flagged(iSequence)) {
00988                 bestDj=value;
00989                 bestSequence = iSequence;
00990               } else {
00991                 // just to make sure we don't exit before got something
00992                 numberWanted++;
00993               }
00994             }
00995           }
00996           break;
00997         case ClpSimplex::atUpperBound:
00998           value=cost[iSequence];
00999           j = iSequence<<1;
01000           iRowM = indices_[j];
01001           iRowP = indices_[j+1];
01002           value += duals[iRowM];
01003           value -= duals[iRowP];
01004           if (value>tolerance) {
01005             numberWanted--;
01006             if (value>bestDj) {
01007               // check flagged variable and correct dj
01008               if (!model->flagged(iSequence)) {
01009                 bestDj=value;
01010                 bestSequence = iSequence;
01011               } else {
01012                 // just to make sure we don't exit before got something
01013                 numberWanted++;
01014               }
01015             }
01016           }
01017           break;
01018         case ClpSimplex::atLowerBound:
01019           value=cost[iSequence];
01020           j = iSequence<<1;
01021           iRowM = indices_[j];
01022           iRowP = indices_[j+1];
01023           value += duals[iRowM];
01024           value -= duals[iRowP];
01025           value = -value;
01026           if (value>tolerance) {
01027             numberWanted--;
01028             if (value>bestDj) {
01029               // check flagged variable and correct dj
01030               if (!model->flagged(iSequence)) {
01031                 bestDj=value;
01032                 bestSequence = iSequence;
01033               } else {
01034                 // just to make sure we don't exit before got something
01035                 numberWanted++;
01036               }
01037             }
01038           }
01039           break;
01040         }
01041       }
01042       if (!numberWanted)
01043         break;
01044     }
01045     if (bestSequence!=saveSequence) {
01046       // recompute dj
01047       double value=cost[bestSequence];
01048       j = bestSequence<<1;
01049       int iRowM = indices_[j];
01050       int iRowP = indices_[j+1];
01051       value += duals[iRowM];
01052       value -= duals[iRowP];
01053       reducedCost[bestSequence] = value;
01054     }
01055   }
01056 }

Generated on Wed Dec 3 14:37:27 2003 for CLP by doxygen 1.3.5