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

ClpPackedMatrix.cpp

00001 // Copyright (C) 2002, 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 #include "ClpQuadraticObjective.hpp"
00014 // at end to get min/max!
00015 #include "ClpPackedMatrix.hpp"
00016 #include "ClpMessage.hpp"
00017 
00018 //#############################################################################
00019 // Constructors / Destructor / Assignment
00020 //#############################################################################
00021 
00022 //-------------------------------------------------------------------
00023 // Default Constructor 
00024 //-------------------------------------------------------------------
00025 ClpPackedMatrix::ClpPackedMatrix () 
00026   : ClpMatrixBase(),
00027     matrix_(NULL),
00028     zeroElements_(false)
00029 {
00030   setType(1);
00031 }
00032 
00033 //-------------------------------------------------------------------
00034 // Copy constructor 
00035 //-------------------------------------------------------------------
00036 ClpPackedMatrix::ClpPackedMatrix (const ClpPackedMatrix & rhs) 
00037 : ClpMatrixBase(rhs)
00038 {  
00039   matrix_ = new CoinPackedMatrix(*(rhs.matrix_));
00040   zeroElements_ = rhs.zeroElements_;
00041   
00042 }
00043 
00044 //-------------------------------------------------------------------
00045 // assign matrix (for space reasons)
00046 //-------------------------------------------------------------------
00047 ClpPackedMatrix::ClpPackedMatrix (CoinPackedMatrix * rhs) 
00048 : ClpMatrixBase()
00049 {  
00050   matrix_ = rhs;
00051   zeroElements_ = false;
00052   setType(1);
00053   
00054 }
00055 
00056 ClpPackedMatrix::ClpPackedMatrix (const CoinPackedMatrix & rhs) 
00057 : ClpMatrixBase()
00058 {  
00059   matrix_ = new CoinPackedMatrix(rhs);
00060   zeroElements_ = false;
00061   setType(1);
00062   
00063 }
00064 
00065 //-------------------------------------------------------------------
00066 // Destructor 
00067 //-------------------------------------------------------------------
00068 ClpPackedMatrix::~ClpPackedMatrix ()
00069 {
00070   delete matrix_;
00071 }
00072 
00073 //----------------------------------------------------------------
00074 // Assignment operator 
00075 //-------------------------------------------------------------------
00076 ClpPackedMatrix &
00077 ClpPackedMatrix::operator=(const ClpPackedMatrix& rhs)
00078 {
00079   if (this != &rhs) {
00080     ClpMatrixBase::operator=(rhs);
00081     delete matrix_;
00082     matrix_ = new CoinPackedMatrix(*(rhs.matrix_));
00083     zeroElements_ = rhs.zeroElements_;
00084   }
00085   return *this;
00086 }
00087 //-------------------------------------------------------------------
00088 // Clone
00089 //-------------------------------------------------------------------
00090 ClpMatrixBase * ClpPackedMatrix::clone() const
00091 {
00092   return new ClpPackedMatrix(*this);
00093 }
00094 /* Subset clone (without gaps).  Duplicates are allowed
00095    and order is as given */
00096 ClpMatrixBase * 
00097 ClpPackedMatrix::subsetClone (int numberRows, const int * whichRows,
00098                               int numberColumns, 
00099                               const int * whichColumns) const 
00100 {
00101   return new ClpPackedMatrix(*this, numberRows, whichRows,
00102                                    numberColumns, whichColumns);
00103 }
00104 /* Subset constructor (without gaps).  Duplicates are allowed
00105    and order is as given */
00106 ClpPackedMatrix::ClpPackedMatrix (
00107                        const ClpPackedMatrix & rhs,
00108                        int numberRows, const int * whichRows,
00109                        int numberColumns, const int * whichColumns)
00110 : ClpMatrixBase(rhs)
00111 {
00112   matrix_ = new CoinPackedMatrix(*(rhs.matrix_),numberRows,whichRows,
00113                                  numberColumns,whichColumns);
00114   zeroElements_ = rhs.zeroElements_;
00115 }
00116 ClpPackedMatrix::ClpPackedMatrix (
00117                        const CoinPackedMatrix & rhs,
00118                        int numberRows, const int * whichRows,
00119                        int numberColumns, const int * whichColumns)
00120 : ClpMatrixBase()
00121 {
00122   matrix_ = new CoinPackedMatrix(rhs,numberRows,whichRows,
00123                                  numberColumns,whichColumns);
00124   zeroElements_ = false;
00125   setType(1);
00126 }
00127 
00128 /* Returns a new matrix in reverse order without gaps */
00129 ClpMatrixBase * 
00130 ClpPackedMatrix::reverseOrderedCopy() const
00131 {
00132   ClpPackedMatrix * copy = new ClpPackedMatrix();
00133   copy->matrix_= new CoinPackedMatrix();
00134   copy->matrix_->reverseOrderedCopyOf(*matrix_);
00135   copy->matrix_->removeGaps();
00136   return copy;
00137 }
00138 //unscaled versions
00139 void 
00140 ClpPackedMatrix::times(double scalar,
00141                    const double * x, double * y) const
00142 {
00143   int iRow,iColumn;
00144   // get matrix data pointers
00145   const int * row = matrix_->getIndices();
00146   const CoinBigIndex * columnStart = matrix_->getVectorStarts();
00147   const int * columnLength = matrix_->getVectorLengths(); 
00148   const double * elementByColumn = matrix_->getElements();
00149   int numberColumns = matrix_->getNumCols();
00150   //memset(y,0,matrix_->getNumRows()*sizeof(double));
00151   for (iColumn=0;iColumn<numberColumns;iColumn++) {
00152     CoinBigIndex j;
00153     double value = scalar*x[iColumn];
00154     if (value) {
00155       for (j=columnStart[iColumn];
00156            j<columnStart[iColumn]+columnLength[iColumn];j++) {
00157         iRow=row[j];
00158         y[iRow] += value*elementByColumn[j];
00159       }
00160     }
00161   }
00162 }
00163 void 
00164 ClpPackedMatrix::transposeTimes(double scalar,
00165                                 const double * x, double * y) const
00166 {
00167   int iColumn;
00168   // get matrix data pointers
00169   const int * row = matrix_->getIndices();
00170   const CoinBigIndex * columnStart = matrix_->getVectorStarts();
00171   const int * columnLength = matrix_->getVectorLengths(); 
00172   const double * elementByColumn = matrix_->getElements();
00173   int numberColumns = matrix_->getNumCols();
00174   //memset(y,0,numberColumns*sizeof(double));
00175   for (iColumn=0;iColumn<numberColumns;iColumn++) {
00176     CoinBigIndex j;
00177     double value=0.0;
00178     for (j=columnStart[iColumn];
00179          j<columnStart[iColumn]+columnLength[iColumn];j++) {
00180       int jRow=row[j];
00181       value += x[jRow]*elementByColumn[j];
00182     }
00183     y[iColumn] += value*scalar;
00184   }
00185 }
00186 void 
00187 ClpPackedMatrix::times(double scalar,
00188                        const double * x, double * y,
00189                        const double * rowScale, 
00190                        const double * columnScale) const
00191 {
00192   if (rowScale) {
00193     int iRow,iColumn;
00194     // get matrix data pointers
00195     const int * row = matrix_->getIndices();
00196     const CoinBigIndex * columnStart = matrix_->getVectorStarts();
00197     const int * columnLength = matrix_->getVectorLengths(); 
00198     const double * elementByColumn = matrix_->getElements();
00199     int numberColumns = matrix_->getNumCols();
00200     //memset(y,0,matrix_->getNumRows()*sizeof(double));
00201     for (iColumn=0;iColumn<numberColumns;iColumn++) {
00202       CoinBigIndex j;
00203       double value = x[iColumn];
00204       if (value) {
00205         // scaled
00206         value *= scalar*columnScale[iColumn];
00207         for (j=columnStart[iColumn];
00208              j<columnStart[iColumn]+columnLength[iColumn];j++) {
00209           iRow=row[j];
00210           y[iRow] += value*elementByColumn[j];
00211         }
00212       }
00213     }
00214     int numberRows = getNumRows();
00215     for (iRow=0;iRow<numberRows;iRow++) {
00216       y[iRow] *= rowScale[iRow];
00217     }
00218   } else {
00219     times(scalar,x,y);
00220   }
00221 }
00222 void 
00223 ClpPackedMatrix::transposeTimes( double scalar,
00224                                  const double * x, double * y,
00225                                  const double * rowScale, 
00226                                  const double * columnScale) const
00227 {
00228   if (rowScale) {
00229     int iColumn;
00230     // get matrix data pointers
00231     const int * row = matrix_->getIndices();
00232     const CoinBigIndex * columnStart = matrix_->getVectorStarts();
00233     const int * columnLength = matrix_->getVectorLengths(); 
00234     const double * elementByColumn = matrix_->getElements();
00235     int numberColumns = matrix_->getNumCols();
00236     //memset(y,0,numberColumns*sizeof(double));
00237     for (iColumn=0;iColumn<numberColumns;iColumn++) {
00238       CoinBigIndex j;
00239       double value=0.0;
00240       // scaled
00241       for (j=columnStart[iColumn];
00242            j<columnStart[iColumn]+columnLength[iColumn];j++) {
00243         int jRow=row[j];
00244       value += x[jRow]*elementByColumn[j]*rowScale[jRow];
00245       }
00246       y[iColumn] += value*scalar*columnScale[iColumn];
00247     }
00248   } else {
00249     transposeTimes(scalar,x,y);
00250   }
00251 }
00252 /* Return <code>x * A + y</code> in <code>z</code>. 
00253         Squashes small elements and knows about ClpSimplex */
00254 void 
00255 ClpPackedMatrix::transposeTimes(const ClpSimplex * model, double scalar,
00256                               const CoinIndexedVector * rowArray,
00257                               CoinIndexedVector * y,
00258                               CoinIndexedVector * columnArray) const
00259 {
00260   columnArray->clear();
00261   double * pi = rowArray->denseVector();
00262   int numberNonZero=0;
00263   int * index = columnArray->getIndices();
00264   double * array = columnArray->denseVector();
00265   int numberInRowArray = rowArray->getNumElements();
00266   // maybe I need one in OsiSimplex
00267   double zeroTolerance = model->factorization()->zeroTolerance();
00268   int numberRows = model->numberRows();
00269   ClpPackedMatrix* rowCopy =
00270     dynamic_cast< ClpPackedMatrix*>(model->rowCopy());
00271   bool packed = rowArray->packedMode();
00272   double factor = 0.3;
00273   // We may not want to do by row if there may be cache problems
00274   int numberColumns = model->numberColumns();
00275   // It would be nice to find L2 cache size - for moment 512K
00276   // Be slightly optimistic
00277   if (numberColumns*sizeof(double)>1000000) {
00278     if (numberRows*10<numberColumns)
00279       factor=0.1;
00280     else if (numberRows*4<numberColumns)
00281       factor=0.15;
00282     else if (numberRows*2<numberColumns)
00283       factor=0.2;
00284     //if (model->numberIterations()%50==0)
00285     //printf("%d nonzero\n",numberInRowArray);
00286   }
00287   if (numberInRowArray>factor*numberRows||!rowCopy) {
00288     // do by column
00289     int iColumn;
00290     // get matrix data pointers
00291     const int * row = matrix_->getIndices();
00292     const CoinBigIndex * columnStart = matrix_->getVectorStarts();
00293     const int * columnLength = matrix_->getVectorLengths(); 
00294     const double * elementByColumn = matrix_->getElements();
00295     const double * rowScale = model->rowScale();
00296     int numberColumns = model->numberColumns();
00297     if (!y->getNumElements()) {
00298       if (packed) {
00299         // need to expand pi into y
00300         assert(y->capacity()>=numberRows);
00301         double * piOld = pi;
00302         pi = y->denseVector();
00303         const int * whichRow = rowArray->getIndices();
00304         int i;
00305         if (!rowScale) {
00306           // modify pi so can collapse to one loop
00307           for (i=0;i<numberInRowArray;i++) {
00308             int iRow = whichRow[i];
00309             pi[iRow]=scalar*piOld[i];
00310           }
00311           for (iColumn=0;iColumn<numberColumns;iColumn++) {
00312             double value = 0.0;
00313             CoinBigIndex j;
00314             for (j=columnStart[iColumn];
00315                  j<columnStart[iColumn]+columnLength[iColumn];j++) {
00316               int iRow = row[j];
00317               value += pi[iRow]*elementByColumn[j];
00318             }
00319             if (fabs(value)>zeroTolerance) {
00320               array[numberNonZero]=value;
00321               index[numberNonZero++]=iColumn;
00322             }
00323           }
00324         } else {
00325           // scaled
00326           // modify pi so can collapse to one loop
00327           for (i=0;i<numberInRowArray;i++) {
00328             int iRow = whichRow[i];
00329             pi[iRow]=scalar*piOld[i]*rowScale[iRow];
00330           }
00331           for (iColumn=0;iColumn<numberColumns;iColumn++) {
00332             double value = 0.0;
00333             CoinBigIndex j;
00334             const double * columnScale = model->columnScale();
00335             for (j=columnStart[iColumn];
00336                  j<columnStart[iColumn]+columnLength[iColumn];j++) {
00337               int iRow = row[j];
00338               value += pi[iRow]*elementByColumn[j];
00339             }
00340             value *= columnScale[iColumn];
00341             if (fabs(value)>zeroTolerance) {
00342               array[numberNonZero]=value;
00343               index[numberNonZero++]=iColumn;
00344             }
00345           }
00346         }
00347         // zero out
00348         for (i=0;i<numberInRowArray;i++) {
00349           int iRow = whichRow[i];
00350           pi[iRow]=0.0;
00351         }
00352       } else {
00353         if (!rowScale) {
00354           if (scalar==-1.0) {
00355             for (iColumn=0;iColumn<numberColumns;iColumn++) {
00356               double value = 0.0;
00357               CoinBigIndex j;
00358               for (j=columnStart[iColumn];
00359                    j<columnStart[iColumn]+columnLength[iColumn];j++) {
00360                 int iRow = row[j];
00361                 value += pi[iRow]*elementByColumn[j];
00362               }
00363               if (fabs(value)>zeroTolerance) {
00364                 index[numberNonZero++]=iColumn;
00365                 array[iColumn]=-value;
00366               }
00367             }
00368           } else if (scalar==1.0) {
00369             for (iColumn=0;iColumn<numberColumns;iColumn++) {
00370               double value = 0.0;
00371               CoinBigIndex j;
00372               for (j=columnStart[iColumn];
00373                    j<columnStart[iColumn]+columnLength[iColumn];j++) {
00374                 int iRow = row[j];
00375                 value += pi[iRow]*elementByColumn[j];
00376               }
00377               if (fabs(value)>zeroTolerance) {
00378                 index[numberNonZero++]=iColumn;
00379                 array[iColumn]=value;
00380               }
00381             }
00382           } else {
00383             for (iColumn=0;iColumn<numberColumns;iColumn++) {
00384               double value = 0.0;
00385               CoinBigIndex j;
00386               for (j=columnStart[iColumn];
00387                    j<columnStart[iColumn]+columnLength[iColumn];j++) {
00388                 int iRow = row[j];
00389                 value += pi[iRow]*elementByColumn[j];
00390               }
00391               value *= scalar;
00392               if (fabs(value)>zeroTolerance) {
00393                 index[numberNonZero++]=iColumn;
00394                 array[iColumn]=value;
00395               }
00396             }
00397           }
00398         } else {
00399           // scaled
00400           if (scalar==-1.0) {
00401             for (iColumn=0;iColumn<numberColumns;iColumn++) {
00402               double value = 0.0;
00403               CoinBigIndex j;
00404               const double * columnScale = model->columnScale();
00405               for (j=columnStart[iColumn];
00406                    j<columnStart[iColumn]+columnLength[iColumn];j++) {
00407                 int iRow = row[j];
00408                 value += pi[iRow]*elementByColumn[j]*rowScale[iRow];
00409               }
00410               value *= columnScale[iColumn];
00411               if (fabs(value)>zeroTolerance) {
00412                 index[numberNonZero++]=iColumn;
00413                 array[iColumn]=-value;
00414               }
00415             }
00416           } else if (scalar==1.0) {
00417             for (iColumn=0;iColumn<numberColumns;iColumn++) {
00418               double value = 0.0;
00419               CoinBigIndex j;
00420               const double * columnScale = model->columnScale();
00421               for (j=columnStart[iColumn];
00422                    j<columnStart[iColumn]+columnLength[iColumn];j++) {
00423                 int iRow = row[j];
00424                 value += pi[iRow]*elementByColumn[j]*rowScale[iRow];
00425               }
00426               value *= columnScale[iColumn];
00427               if (fabs(value)>zeroTolerance) {
00428                 index[numberNonZero++]=iColumn;
00429                 array[iColumn]=value;
00430               }
00431             }
00432           } else {
00433             for (iColumn=0;iColumn<numberColumns;iColumn++) {
00434               double value = 0.0;
00435               CoinBigIndex j;
00436               const double * columnScale = model->columnScale();
00437               for (j=columnStart[iColumn];
00438                    j<columnStart[iColumn]+columnLength[iColumn];j++) {
00439                 int iRow = row[j];
00440                 value += pi[iRow]*elementByColumn[j]*rowScale[iRow];
00441               }
00442               value *= scalar*columnScale[iColumn];
00443               if (fabs(value)>zeroTolerance) {
00444                 index[numberNonZero++]=iColumn;
00445                 array[iColumn]=value;
00446               }
00447             }
00448           }
00449         }
00450       }
00451     } else {
00452       assert(!packed);
00453       double * markVector = y->denseVector(); // not empty
00454       if (!rowScale) {
00455         for (iColumn=0;iColumn<numberColumns;iColumn++) {
00456           double value = markVector[iColumn];
00457           markVector[iColumn]=0.0;
00458           double value2 = 0.0;
00459           CoinBigIndex j;
00460           for (j=columnStart[iColumn];
00461                j<columnStart[iColumn]+columnLength[iColumn];j++) {
00462             int iRow = row[j];
00463             value2 += pi[iRow]*elementByColumn[j];
00464           }
00465           value += value2*scalar;
00466           if (fabs(value)>zeroTolerance) {
00467             index[numberNonZero++]=iColumn;
00468             array[iColumn]=value;
00469           }
00470         }
00471       } else {
00472         // scaled
00473         for (iColumn=0;iColumn<numberColumns;iColumn++) {
00474           double value = markVector[iColumn];
00475           markVector[iColumn]=0.0;
00476           CoinBigIndex j;
00477           const double * columnScale = model->columnScale();
00478           double value2 = 0.0;
00479           for (j=columnStart[iColumn];
00480                j<columnStart[iColumn]+columnLength[iColumn];j++) {
00481             int iRow = row[j];
00482             value2 += pi[iRow]*elementByColumn[j]*rowScale[iRow];
00483           }
00484           value += value2*scalar*columnScale[iColumn];
00485           if (fabs(value)>zeroTolerance) {
00486             index[numberNonZero++]=iColumn;
00487             array[iColumn]=value;
00488           }
00489         }
00490       }
00491     }
00492     columnArray->setNumElements(numberNonZero);
00493     y->setNumElements(0);
00494   } else {
00495     // do by row
00496     rowCopy->transposeTimesByRow(model, scalar, rowArray, y, columnArray);
00497   }
00498   if (packed)
00499     columnArray->setPackedMode(true);
00500   if (0) {
00501     columnArray->checkClean();
00502     int numberNonZero=columnArray->getNumElements();;
00503     int * index = columnArray->getIndices();
00504     double * array = columnArray->denseVector();
00505     int i;
00506     for (i=0;i<numberNonZero;i++) {
00507       int j=index[i];
00508       double value;
00509       if (packed)
00510         value=array[i];
00511       else
00512         value=array[j];
00513       printf("Ti %d %d %g\n",i,j,value);
00514     }
00515   }
00516 }
00517 /* Return <code>x * A + y</code> in <code>z</code>. 
00518         Squashes small elements and knows about ClpSimplex */
00519 void 
00520 ClpPackedMatrix::transposeTimesByRow(const ClpSimplex * model, double scalar,
00521                               const CoinIndexedVector * rowArray,
00522                               CoinIndexedVector * y,
00523                               CoinIndexedVector * columnArray) const
00524 {
00525   columnArray->clear();
00526   double * pi = rowArray->denseVector();
00527   int numberNonZero=0;
00528   int * index = columnArray->getIndices();
00529   double * array = columnArray->denseVector();
00530   int numberInRowArray = rowArray->getNumElements();
00531   // maybe I need one in OsiSimplex
00532   double zeroTolerance = model->factorization()->zeroTolerance();
00533   const int * column = getIndices();
00534   const CoinBigIndex * rowStart = getVectorStarts();
00535   const double * element = getElements();
00536   const int * whichRow = rowArray->getIndices();
00537   bool packed = rowArray->packedMode();
00538   if (numberInRowArray>2||y->getNumElements()) {
00539     // do by rows
00540     // ** Row copy is already scaled
00541     int iRow;
00542     int * mark = y->getIndices();
00543     int numberOriginal=y->getNumElements();
00544     int i;
00545     if (packed) {
00546       assert(!numberOriginal);
00547       numberNonZero=0;
00548       // and set up mark as char array
00549       char * marked = (char *) (index+columnArray->capacity());
00550       double * array2 = y->denseVector();
00551 #ifdef CLP_DEBUG
00552       int numberColumns = model->numberColumns();
00553       for (i=0;i<numberColumns;i++) {
00554         assert(!marked[i]);
00555         assert(!array2[i]);
00556       }
00557 #endif      
00558       for (i=0;i<numberInRowArray;i++) {
00559         iRow = whichRow[i]; 
00560         double value = pi[i]*scalar;
00561         CoinBigIndex j;
00562         for (j=rowStart[iRow];j<rowStart[iRow+1];j++) {
00563           int iColumn = column[j];
00564           if (!marked[iColumn]) {
00565             marked[iColumn]=1;
00566             index[numberNonZero++]=iColumn;
00567           }
00568           array2[iColumn] += value*element[j];
00569         }
00570       }
00571       // get rid of tiny values and zero out marked
00572       numberOriginal=numberNonZero;
00573       numberNonZero=0;
00574       for (i=0;i<numberOriginal;i++) {
00575         int iColumn = index[i];
00576         if (marked[iColumn]) {
00577           double value = array2[iColumn];
00578           array2[iColumn]=0.0;
00579           marked[iColumn]=0;
00580           if (fabs(value)>zeroTolerance) {
00581             array[numberNonZero]=value;
00582             index[numberNonZero++]=iColumn;
00583           }
00584         }
00585       }
00586     } else {
00587       double * markVector = y->denseVector(); // probably empty .. but
00588       for (i=0;i<numberOriginal;i++) {
00589         int iColumn = mark[i];
00590         index[i]=iColumn;
00591         array[iColumn]=markVector[iColumn];
00592         markVector[iColumn]=0.0;
00593       }
00594       numberNonZero=numberOriginal;
00595       // and set up mark as char array
00596       char * marked = (char *) markVector;
00597       for (i=0;i<numberOriginal;i++) {
00598         int iColumn = index[i];
00599         marked[iColumn]=0;
00600       }
00601       
00602       for (i=0;i<numberInRowArray;i++) {
00603         iRow = whichRow[i]; 
00604         double value = pi[iRow]*scalar;
00605         CoinBigIndex j;
00606         for (j=rowStart[iRow];j<rowStart[iRow+1];j++) {
00607           int iColumn = column[j];
00608           if (!marked[iColumn]) {
00609             marked[iColumn]=1;
00610             index[numberNonZero++]=iColumn;
00611           }
00612           array[iColumn] += value*element[j];
00613         }
00614       }
00615       // get rid of tiny values and zero out marked
00616       numberOriginal=numberNonZero;
00617       numberNonZero=0;
00618       for (i=0;i<numberOriginal;i++) {
00619         int iColumn = index[i];
00620         marked[iColumn]=0;
00621         if (fabs(array[iColumn])>zeroTolerance) {
00622           index[numberNonZero++]=iColumn;
00623         } else {
00624           array[iColumn]=0.0;
00625         }
00626       }
00627     }
00628   } else if (numberInRowArray==2) {
00629     // do by rows when two rows
00630     int numberOriginal;
00631     int i;
00632     CoinBigIndex j;
00633     numberNonZero=0;
00634 
00635     double value;
00636     if (packed) {
00637       int iRow0 = whichRow[0]; 
00638       int iRow1 = whichRow[1]; 
00639       double pi0 = pi[0];
00640       double pi1 = pi[1];
00641       if (rowStart[iRow0+1]-rowStart[iRow0]>
00642           rowStart[iRow1+1]-rowStart[iRow1]) {
00643         // do one with fewer first
00644         iRow0=iRow1;
00645         iRow1=whichRow[0];
00646         pi0=pi1;
00647         pi1=pi[0];
00648       }
00649       // and set up mark as char array
00650       char * marked = (char *) (index+columnArray->capacity());
00651       int * lookup = y->getIndices();
00652       value = pi0*scalar;
00653       for (j=rowStart[iRow0];j<rowStart[iRow0+1];j++) {
00654         int iColumn = column[j];
00655         double value2 = value*element[j];
00656         array[numberNonZero] = value2;
00657         marked[iColumn]=1;
00658         lookup[iColumn]=numberNonZero;
00659         index[numberNonZero++]=iColumn;
00660       }
00661       numberOriginal = numberNonZero;
00662       value = pi1*scalar;
00663       for (j=rowStart[iRow1];j<rowStart[iRow1+1];j++) {
00664         int iColumn = column[j];
00665         double value2 = value*element[j];
00666         // I am assuming no zeros in matrix
00667         if (marked[iColumn]) {
00668           int iLookup = lookup[iColumn];
00669           array[iLookup] += value2;
00670         } else {
00671           if (fabs(value2)>zeroTolerance) {
00672             array[numberNonZero] = value2;
00673             index[numberNonZero++]=iColumn;
00674           }
00675         }
00676       }
00677       // get rid of tiny values and zero out marked
00678       int nDelete=0;
00679       for (i=0;i<numberOriginal;i++) {
00680         int iColumn = index[i];
00681         marked[iColumn]=0;
00682         if (fabs(array[i])<=zeroTolerance) 
00683           nDelete++;
00684       }
00685       if (nDelete) {
00686         numberOriginal=numberNonZero;
00687         numberNonZero=0;
00688         for (i=0;i<numberOriginal;i++) {
00689           int iColumn = index[i];
00690           double value = array[i];
00691           array[i]=0.0;
00692           if (fabs(value)>zeroTolerance) {
00693             array[numberNonZero]=value;
00694             index[numberNonZero++]=iColumn;
00695           }
00696         }
00697       }
00698     } else {
00699       int iRow = whichRow[0]; 
00700       value = pi[iRow]*scalar;
00701       for (j=rowStart[iRow];j<rowStart[iRow+1];j++) {
00702         int iColumn = column[j];
00703         double value2 = value*element[j];
00704         index[numberNonZero++]=iColumn;
00705         array[iColumn] = value2;
00706       }
00707       iRow = whichRow[1]; 
00708       value = pi[iRow]*scalar;
00709       for (j=rowStart[iRow];j<rowStart[iRow+1];j++) {
00710         int iColumn = column[j];
00711         double value2 = value*element[j];
00712         // I am assuming no zeros in matrix
00713         if (array[iColumn])
00714           value2 += array[iColumn];
00715         else
00716           index[numberNonZero++]=iColumn;
00717         array[iColumn] = value2;
00718       }
00719       // get rid of tiny values and zero out marked
00720       numberOriginal=numberNonZero;
00721       numberNonZero=0;
00722       for (i=0;i<numberOriginal;i++) {
00723         int iColumn = index[i];
00724         if (fabs(array[iColumn])>zeroTolerance) {
00725           index[numberNonZero++]=iColumn;
00726         } else {
00727           array[iColumn]=0.0;
00728         }
00729       }
00730     }
00731   } else if (numberInRowArray==1) {
00732     // Just one row
00733     int iRow=rowArray->getIndices()[0];
00734     numberNonZero=0;
00735     CoinBigIndex j;
00736     if (packed) {
00737       double value = pi[0]*scalar;
00738       for (j=rowStart[iRow];j<rowStart[iRow+1];j++) {
00739         int iColumn = column[j];
00740         double value2 = value*element[j];
00741         if (fabs(value2)>zeroTolerance) {
00742           array[numberNonZero] = value2;
00743           index[numberNonZero++]=iColumn;
00744         }
00745       }
00746     } else {
00747       double value = pi[iRow]*scalar;
00748       for (j=rowStart[iRow];j<rowStart[iRow+1];j++) {
00749         int iColumn = column[j];
00750         double value2 = value*element[j];
00751         if (fabs(value2)>zeroTolerance) {
00752           index[numberNonZero++]=iColumn;
00753           array[iColumn] = value2;
00754         }
00755       }
00756     }
00757   }
00758   columnArray->setNumElements(numberNonZero);
00759   y->setNumElements(0);
00760 }
00761 /* Return <code>x *A in <code>z</code> but
00762    just for indices in y.
00763    Squashes small elements and knows about ClpSimplex */
00764 void 
00765 ClpPackedMatrix::subsetTransposeTimes(const ClpSimplex * model,
00766                               const CoinIndexedVector * rowArray,
00767                               const CoinIndexedVector * y,
00768                               CoinIndexedVector * columnArray) const
00769 {
00770   columnArray->clear();
00771   double * pi = rowArray->denseVector();
00772   double * array = columnArray->denseVector();
00773   int jColumn;
00774   // get matrix data pointers
00775   const int * row = matrix_->getIndices();
00776   const CoinBigIndex * columnStart = matrix_->getVectorStarts();
00777   const int * columnLength = matrix_->getVectorLengths(); 
00778   const double * elementByColumn = matrix_->getElements();
00779   const double * rowScale = model->rowScale();
00780   int numberToDo = y->getNumElements();
00781   const int * which = y->getIndices();
00782   assert (!rowArray->packedMode());
00783   columnArray->setPacked();
00784   if (!rowScale) {
00785     for (jColumn=0;jColumn<numberToDo;jColumn++) {
00786       int iColumn = which[jColumn];
00787       double value = 0.0;
00788       CoinBigIndex j;
00789       for (j=columnStart[iColumn];
00790            j<columnStart[iColumn]+columnLength[iColumn];j++) {
00791         int iRow = row[j];
00792         value += pi[iRow]*elementByColumn[j];
00793       }
00794       array[jColumn]=value;
00795     }
00796   } else {
00797     // scaled
00798     for (jColumn=0;jColumn<numberToDo;jColumn++) {
00799       int iColumn = which[jColumn];
00800       double value = 0.0;
00801       CoinBigIndex j;
00802       const double * columnScale = model->columnScale();
00803       for (j=columnStart[iColumn];
00804            j<columnStart[iColumn]+columnLength[iColumn];j++) {
00805         int iRow = row[j];
00806         value += pi[iRow]*elementByColumn[j]*rowScale[iRow];
00807       }
00808       value *= columnScale[iColumn];
00809       array[jColumn]=value;
00810     }
00811   }
00812 }
00813 /* Returns number of elements in basis
00814    column is basic if entry >=0 */
00815 CoinBigIndex 
00816 ClpPackedMatrix::numberInBasis(const int * columnIsBasic) const 
00817 {
00818   int i;
00819   int numberColumns = getNumCols();
00820   const int * columnLength = matrix_->getVectorLengths(); 
00821   CoinBigIndex numberElements=0;
00822   if (!zeroElements_) {
00823     for (i=0;i<numberColumns;i++) {
00824       if (columnIsBasic[i]>=0) {
00825         numberElements += columnLength[i];
00826       }
00827     }
00828   } else {
00829     // there are zero elements so need to look more closely
00830     const CoinBigIndex * columnStart = matrix_->getVectorStarts();
00831     const double * elementByColumn = matrix_->getElements();
00832     for (i=0;i<numberColumns;i++) {
00833       if (columnIsBasic[i]>=0) {
00834         CoinBigIndex j;
00835         for (j=columnStart[i];j<columnStart[i]+columnLength[i];j++) {
00836           if (elementByColumn[j])
00837             numberElements++;
00838         }
00839       }
00840     }
00841   }
00842   return numberElements;
00843 }
00844 // Fills in basis (Returns number of elements and updates numberBasic)
00845 CoinBigIndex 
00846 ClpPackedMatrix::fillBasis(const ClpSimplex * model,
00847                                 const int * columnIsBasic, int & numberBasic,
00848                                 int * indexRowU, int * indexColumnU,
00849                                 double * elementU) const 
00850 {
00851   const double * rowScale = model->rowScale();
00852   const int * row = matrix_->getIndices();
00853   const CoinBigIndex * columnStart = matrix_->getVectorStarts();
00854   const int * columnLength = matrix_->getVectorLengths(); 
00855   const double * elementByColumn = matrix_->getElements();
00856   int i;
00857   int numberColumns = getNumCols();
00858   CoinBigIndex numberElements=0;
00859   if (!zeroElements_) {
00860     if (!rowScale) {
00861       // no scaling
00862       for (i=0;i<numberColumns;i++) {
00863         if (columnIsBasic[i]>=0) {
00864           CoinBigIndex j;
00865           for (j=columnStart[i];j<columnStart[i]+columnLength[i];j++) {
00866             indexRowU[numberElements]=row[j];
00867             indexColumnU[numberElements]=numberBasic;
00868             elementU[numberElements++]=elementByColumn[j];
00869           }
00870           numberBasic++;
00871         }
00872       }
00873     } else {
00874       // scaling
00875       const double * columnScale = model->columnScale();
00876       for (i=0;i<numberColumns;i++) {
00877         if (columnIsBasic[i]>=0) {
00878           CoinBigIndex j;
00879           double scale = columnScale[i];
00880           for (j=columnStart[i];j<columnStart[i]+columnLength[i];j++) {
00881             int iRow = row[j];
00882             indexRowU[numberElements]=iRow;
00883             indexColumnU[numberElements]=numberBasic;
00884             elementU[numberElements++]=elementByColumn[j]*scale*rowScale[iRow];
00885           }
00886           numberBasic++;
00887         }
00888       }
00889     }
00890   } else {
00891     // there are zero elements so need to look more closely
00892     if (!rowScale) {
00893       // no scaling
00894       for (i=0;i<numberColumns;i++) {
00895         if (columnIsBasic[i]>=0) {
00896           CoinBigIndex j;
00897           for (j=columnStart[i];j<columnStart[i]+columnLength[i];j++) {
00898             double value = elementByColumn[j];
00899             if (value) {
00900               indexRowU[numberElements]=row[j];
00901               indexColumnU[numberElements]=numberBasic;
00902               elementU[numberElements++]=value;
00903             }
00904           }
00905           numberBasic++;
00906         }
00907       }
00908     } else {
00909       // scaling
00910       const double * columnScale = model->columnScale();
00911       for (i=0;i<numberColumns;i++) {
00912         if (columnIsBasic[i]>=0) {
00913           CoinBigIndex j;
00914           double scale = columnScale[i];
00915           for (j=columnStart[i];j<columnStart[i]+columnLength[i];j++) {
00916             double value = elementByColumn[j];
00917             if (value) {
00918               int iRow = row[j];
00919               indexRowU[numberElements]=iRow;
00920               indexColumnU[numberElements]=numberBasic;
00921               elementU[numberElements++]=value*scale*rowScale[iRow];
00922             }
00923           }
00924           numberBasic++;
00925         }
00926       }
00927     }
00928   }
00929   return numberElements;
00930 }
00931 /* If element NULL returns number of elements in column part of basis,
00932    If not NULL fills in as well */
00933 CoinBigIndex 
00934 ClpPackedMatrix::fillBasis(const ClpSimplex * model,
00935                            const int * whichColumn, 
00936                            int numberBasic,
00937                            int numberColumnBasic,
00938                            int * indexRowU, int * indexColumnU,
00939                            double * elementU) const 
00940 {
00941   const int * columnLength = matrix_->getVectorLengths(); 
00942   int i;
00943   CoinBigIndex numberElements=0;
00944   if (elementU!=NULL) {
00945     // fill
00946     const CoinBigIndex * columnStart = matrix_->getVectorStarts();
00947     const double * rowScale = model->rowScale();
00948     const int * row = matrix_->getIndices();
00949     const double * elementByColumn = matrix_->getElements();
00950     if (!zeroElements_) {
00951       if (!rowScale) {
00952         // no scaling
00953         for (i=0;i<numberColumnBasic;i++) {
00954           int iColumn = whichColumn[i];
00955           CoinBigIndex j;
00956           for (j=columnStart[iColumn];
00957                j<columnStart[iColumn]+columnLength[iColumn];j++) {
00958             indexRowU[numberElements]=row[j];
00959             indexColumnU[numberElements]=numberBasic;
00960             elementU[numberElements++]=elementByColumn[j];
00961           }
00962           numberBasic++;
00963         }
00964       } else {
00965         // scaling
00966         const double * columnScale = model->columnScale();
00967         for (i=0;i<numberColumnBasic;i++) {
00968           int iColumn = whichColumn[i];
00969           CoinBigIndex j;
00970           double scale = columnScale[iColumn];
00971           for (j=columnStart[iColumn];
00972                j<columnStart[iColumn]+columnLength[iColumn];j++) {
00973             int iRow = row[j];
00974             indexRowU[numberElements]=iRow;
00975             indexColumnU[numberElements]=numberBasic;
00976             elementU[numberElements++]=
00977               elementByColumn[j]*scale*rowScale[iRow];
00978           }
00979           numberBasic++;
00980         }
00981       }
00982     } else {
00983       // there are zero elements so need to look more closely
00984       if (!rowScale) {
00985         // no scaling
00986         for (i=0;i<numberColumnBasic;i++) {
00987           int iColumn = whichColumn[i];
00988           CoinBigIndex j;
00989           for (j=columnStart[iColumn];
00990                j<columnStart[iColumn]+columnLength[iColumn];j++) {
00991             double value = elementByColumn[j];
00992             if (value) {
00993               indexRowU[numberElements]=row[j];
00994               indexColumnU[numberElements]=numberBasic;
00995               elementU[numberElements++]=value;
00996             }
00997           }
00998           numberBasic++;
00999         }
01000       } else {
01001         // scaling
01002         const double * columnScale = model->columnScale();
01003         for (i=0;i<numberColumnBasic;i++) {
01004           int iColumn = whichColumn[i];
01005           CoinBigIndex j;
01006           double scale = columnScale[iColumn];
01007           for (j=columnStart[iColumn];
01008                j<columnStart[iColumn]+columnLength[i];j++) {
01009             double value = elementByColumn[j];
01010             if (value) {
01011               int iRow = row[j];
01012               indexRowU[numberElements]=iRow;
01013               indexColumnU[numberElements]=numberBasic;
01014               elementU[numberElements++]=value*scale*rowScale[iRow];
01015             }
01016           }
01017           numberBasic++;
01018         }
01019       }
01020     }
01021   } else {
01022     // just count - can be over so ignore zero problem
01023     for (i=0;i<numberColumnBasic;i++) {
01024       int iColumn = whichColumn[i];
01025       numberElements += columnLength[iColumn];
01026     }
01027   }
01028   return numberElements;
01029 }
01030 // Creates scales for column copy (rowCopy in model may be modified)
01031 int 
01032 ClpPackedMatrix::scale(ClpSimplex * model) const 
01033 {
01034   int numberRows = model->numberRows();
01035   int numberColumns = model->numberColumns();
01036   // If empty - return as sanityCheck will trap
01037   if (!numberRows||!numberColumns)
01038     return 1;
01039   ClpMatrixBase * rowCopyBase=model->rowCopy();
01040   if (!rowCopyBase) {
01041     // temporary copy
01042     rowCopyBase = reverseOrderedCopy();
01043   }
01044   ClpPackedMatrix* rowCopy =
01045     dynamic_cast< ClpPackedMatrix*>(rowCopyBase);
01046 
01047   // Make sure it is really a ClpPackedMatrix
01048   assert (rowCopy!=NULL);
01049   const int * column = rowCopy->getIndices();
01050   const CoinBigIndex * rowStart = rowCopy->getVectorStarts();
01051   const double * element = rowCopy->getElements();
01052   double * rowScale = new double [numberRows];
01053   double * columnScale = new double [numberColumns];
01054   // we are going to mark bits we are interested in
01055   char * usefulRow = new char [numberRows];
01056   char * usefulColumn = new char [numberColumns];
01057   double * rowLower = model->rowLower();
01058   double * rowUpper = model->rowUpper();
01059   double * columnLower = model->columnLower();
01060   double * columnUpper = model->columnUpper();
01061   int iColumn, iRow;
01062   // mark free rows
01063   for (iRow=0;iRow<numberRows;iRow++) {
01064     usefulRow[iRow]=0;
01065     if (rowUpper[iRow]<1.0e20||
01066         rowLower[iRow]>-1.0e20)
01067       usefulRow[iRow]=1;
01068   }
01069   // mark empty and fixed columns
01070   // also see if worth scaling
01071   assert (model->scalingFlag()<4); // dynamic not implemented
01072   double largest=0.0;
01073   double smallest=1.0e50;
01074   // get matrix data pointers
01075   const int * row = matrix_->getIndices();
01076   const CoinBigIndex * columnStart = matrix_->getVectorStarts();
01077   const int * columnLength = matrix_->getVectorLengths(); 
01078   const double * elementByColumn = matrix_->getElements();
01079   for (iColumn=0;iColumn<numberColumns;iColumn++) {
01080     CoinBigIndex j;
01081     char useful=0;
01082     if (columnUpper[iColumn]>
01083         columnLower[iColumn]+1.0e-9) {
01084       for (j=columnStart[iColumn];
01085            j<columnStart[iColumn]+columnLength[iColumn];j++) {
01086         iRow=row[j];
01087         if(elementByColumn[j]&&usefulRow[iRow]) {
01088           useful=1;
01089           largest = max(largest,fabs(elementByColumn[j]));
01090           smallest = min(smallest,fabs(elementByColumn[j]));
01091         }
01092       }
01093     }
01094     usefulColumn[iColumn]=useful;
01095   }
01096   model->messageHandler()->message(CLP_PACKEDSCALE_INITIAL,*model->messagesPointer())
01097     <<smallest<<largest
01098     <<CoinMessageEol;
01099   if (smallest>=0.5&&largest<=2.0) {
01100     // don't bother scaling
01101     model->messageHandler()->message(CLP_PACKEDSCALE_FORGET,*model->messagesPointer())
01102       <<CoinMessageEol;
01103     delete [] rowScale;
01104     delete [] usefulRow;
01105     delete [] columnScale;
01106     delete [] usefulColumn;
01107     return 1;
01108   } else {
01109       // need to scale 
01110     int scalingMethod = model->scalingFlag();
01111     if (scalingMethod==3) {
01112       // Choose between 1 and 2
01113       if (smallest<1.0e-5||smallest*largest<1.0)
01114         scalingMethod=1;
01115       else
01116         scalingMethod=2;
01117     }
01118     // and see if there any empty rows
01119     for (iRow=0;iRow<numberRows;iRow++) {
01120       if (usefulRow[iRow]) {
01121         CoinBigIndex j;
01122         int useful=0;
01123         for (j=rowStart[iRow];j<rowStart[iRow+1];j++) {
01124           int iColumn = column[j];
01125           if (usefulColumn[iColumn]) {
01126             useful=1;
01127             break;
01128           }
01129         }
01130         usefulRow[iRow]=useful;
01131       }
01132     }
01133     ClpFillN ( rowScale, numberRows,1.0);
01134     ClpFillN ( columnScale, numberColumns,1.0);
01135     double overallLargest=-1.0e-30;
01136     double overallSmallest=1.0e30;
01137     if (scalingMethod==1) {
01138       // Maximum in each row
01139       for (iRow=0;iRow<numberRows;iRow++) {
01140         if (usefulRow[iRow]) {
01141           CoinBigIndex j;
01142           largest=1.0e-20;
01143           for (j=rowStart[iRow];j<rowStart[iRow+1];j++) {
01144             int iColumn = column[j];
01145             if (usefulColumn[iColumn]) {
01146               double value = fabs(element[j]);
01147               largest = max(largest,value);
01148             }
01149           }
01150           rowScale[iRow]=1.0/largest;
01151           overallLargest = max(overallLargest,largest);
01152           overallSmallest = min(overallSmallest,largest);
01153         }
01154       }
01155     } else {
01156       assert(scalingMethod==2);
01157       int numberPass=3;
01158 #ifdef USE_OBJECTIVE
01159       // This will be used to help get scale factors
01160       double * objective = new double[numberColumns];
01161       memcpy(objective,model->costRegion(1),numberColumns*sizeof(double));
01162       double objScale=1.0;
01163 #endif
01164       while (numberPass) {
01165         overallLargest=0.0;
01166         overallSmallest=1.0e50;
01167         numberPass--;
01168         // Geometric mean on row scales
01169         for (iRow=0;iRow<numberRows;iRow++) {
01170           if (usefulRow[iRow]) {
01171             CoinBigIndex j;
01172             largest=1.0e-20;
01173             smallest=1.0e50;
01174             for (j=rowStart[iRow];j<rowStart[iRow+1];j++) {
01175               int iColumn = column[j];
01176               if (usefulColumn[iColumn]) {
01177                 double value = fabs(element[j]);
01178                 // Don't bother with tiny elements
01179                 if (value>1.0e-30) {
01180                   value *= columnScale[iColumn];
01181                   largest = max(largest,value);
01182                   smallest = min(smallest,value);
01183                 }
01184               }
01185             }
01186             rowScale[iRow]=1.0/sqrt(smallest*largest);
01187             overallLargest = max(largest*rowScale[iRow],overallLargest);
01188             overallSmallest = min(smallest*rowScale[iRow],overallSmallest);
01189           }
01190         }
01191 #ifdef USE_OBJECTIVE
01192         largest=1.0e-20;
01193         smallest=1.0e50;
01194         for (iColumn=0;iColumn<numberColumns;iColumn++) {
01195           if (usefulColumn[iColumn]) {
01196             double value = fabs(objective[iColumn]);
01197             // Don't bother with tiny elements
01198             if (value>1.0e-30) {
01199               value *= columnScale[iColumn];
01200               largest = max(largest,value);
01201               smallest = min(smallest,value);
01202             }
01203           }
01204         }
01205         objScale=1.0/sqrt(smallest*largest);
01206 #endif
01207         model->messageHandler()->message(CLP_PACKEDSCALE_WHILE,*model->messagesPointer())
01208           <<overallSmallest
01209           <<overallLargest
01210           <<CoinMessageEol;
01211         // skip last column round
01212         if (numberPass==1)
01213           break;
01214         // Geometric mean on column scales
01215         for (iColumn=0;iColumn<numberColumns;iColumn++) {
01216           if (usefulColumn[iColumn]) {
01217             CoinBigIndex j;
01218             largest=1.0e-20;
01219             smallest=1.0e50;
01220             for (j=columnStart[iColumn];
01221                  j<columnStart[iColumn]+columnLength[iColumn];j++) {
01222               iRow=row[j];
01223               double value = fabs(elementByColumn[j]);
01224               // Don't bother with tiny elements
01225               if (value>1.0e-30&&usefulRow[iRow]) {
01226                 value *= rowScale[iRow];
01227                 largest = max(largest,value);
01228                 smallest = min(smallest,value);
01229               }
01230             }
01231 #ifdef USE_OBJECTIVE
01232             if (fabs(objective[iColumn])>1.0e-30) {
01233               double value = fabs(objective[iColumn])*objScale;
01234               largest = max(largest,value);
01235               smallest = min(smallest,value);
01236             }
01237 #endif
01238             columnScale[iColumn]=1.0/sqrt(smallest*largest);
01239           }
01240         }
01241       }
01242 #ifdef USE_OBJECTIVE
01243       delete [] objective;
01244       printf("obj scale %g - use it if you want\n",objScale);
01245 #endif
01246     }
01247     // If ranges will make horrid then scale
01248     double tolerance = 5.0*model->primalTolerance();
01249     for (iRow=0;iRow<numberRows;iRow++) {
01250       if (usefulRow[iRow]) {
01251         double difference = rowUpper[iRow]-rowLower[iRow];
01252         double scaledDifference = difference*rowScale[iRow];
01253         if (scaledDifference>tolerance&&scaledDifference<1.0e-4) {
01254           // make gap larger
01255           rowScale[iRow] *= 1.0e-4/scaledDifference;
01256           //printf("Row %d difference %g scaled diff %g => %g\n",iRow,difference,
01257           // scaledDifference,difference*rowScale[iRow]);
01258         }
01259       }
01260     }
01261     // final pass to scale columns so largest is reasonable
01262     // See what smallest will be if largest is 1.0
01263     overallSmallest=1.0e50;
01264     for (iColumn=0;iColumn<numberColumns;iColumn++) {
01265       if (usefulColumn[iColumn]) {
01266         CoinBigIndex j;
01267         largest=1.0e-20;
01268         smallest=1.0e50;
01269         for (j=columnStart[iColumn];
01270              j<columnStart[iColumn]+columnLength[iColumn];j++) {
01271           iRow=row[j];
01272           if(elementByColumn[j]&&usefulRow[iRow]) {
01273             double value = fabs(elementByColumn[j]*rowScale[iRow]);
01274             largest = max(largest,value);
01275             smallest = min(smallest,value);
01276           }
01277         }
01278         if (overallSmallest*largest>smallest)
01279           overallSmallest = smallest/largest;
01280       }
01281     }
01282 #define RANDOMIZE
01283 #ifdef RANDOMIZE
01284     // randomize by up to 10%
01285     for (iRow=0;iRow<numberRows;iRow++) {
01286       double value = 0.5-CoinDrand48();//between -0.5 to + 0.5
01287       rowScale[iRow] *= (1.0+0.1*value);
01288     }
01289 #endif
01290     overallLargest=1.0;
01291     if (overallSmallest<1.0e-1)
01292       overallLargest = 1.0/sqrt(overallSmallest);
01293     overallLargest = min(1000.0,overallLargest);
01294     overallSmallest=1.0e50;
01295     for (iColumn=0;iColumn<numberColumns;iColumn++) {
01296       if (usefulColumn[iColumn]) {
01297         CoinBigIndex j;
01298         largest=1.0e-20;
01299         smallest=1.0e50;
01300         for (j=columnStart[iColumn];
01301              j<columnStart[iColumn]+columnLength[iColumn];j++) {
01302           iRow=row[j];
01303           if(elementByColumn[j]&&usefulRow[iRow]) {
01304             double value = fabs(elementByColumn[j]*rowScale[iRow]);
01305             largest = max(largest,value);
01306             smallest = min(smallest,value);
01307           }
01308         }
01309         columnScale[iColumn]=overallLargest/largest;
01310 #ifdef RANDOMIZE
01311         double value = 0.5-CoinDrand48();//between -0.5 to + 0.5
01312         columnScale[iColumn] *= (1.0+0.1*value);
01313 #endif
01314         double difference = columnUpper[iColumn]-columnLower[iColumn];
01315         double scaledDifference = difference*columnScale[iColumn];
01316         if (scaledDifference>tolerance&&scaledDifference<1.0e-4) {
01317           // make gap larger
01318           columnScale[iColumn] *= 1.0e-4/scaledDifference;
01319           //printf("Column %d difference %g scaled diff %g => %g\n",iColumn,difference,
01320           // scaledDifference,difference*columnScale[iColumn]);
01321         }
01322         overallSmallest = min(overallSmallest,smallest*columnScale[iColumn]);
01323       }
01324     }
01325     model->messageHandler()->message(CLP_PACKEDSCALE_FINAL,*model->messagesPointer())
01326       <<overallSmallest
01327       <<overallLargest
01328       <<CoinMessageEol;
01329     delete [] usefulRow;
01330     delete [] usefulColumn;
01331     // If quadratic then make symmetric
01332     ClpObjective * obj = model->objectiveAsObject();
01333     ClpQuadraticObjective * quadraticObj = (dynamic_cast< ClpQuadraticObjective*>(obj));
01334     if (quadraticObj) {
01335       CoinPackedMatrix * quadratic = quadraticObj->quadraticObjective();
01336       int numberXColumns = quadratic->getNumCols();
01337       if (numberXColumns<numberColumns) {
01338         // we assume symmetric
01339         int numberQuadraticColumns=0;
01340         int i;
01341         //const int * columnQuadratic = quadratic->getIndices();
01342         //const int * columnQuadraticStart = quadratic->getVectorStarts();
01343         const int * columnQuadraticLength = quadratic->getVectorLengths();
01344         for (i=0;i<numberXColumns;i++) {
01345           int length=columnQuadraticLength[i];
01346 #ifndef CORRECT_COLUMN_COUNTS
01347           length=1;
01348 #endif
01349           if (length)
01350             numberQuadraticColumns++;
01351         }
01352         int numberXRows = numberRows-numberQuadraticColumns;
01353         numberQuadraticColumns=0;
01354         for (i=0;i<numberXColumns;i++) { 
01355           int length=columnQuadraticLength[i];
01356 #ifndef CORRECT_COLUMN_COUNTS
01357           length=1;
01358 #endif
01359           if (length) {
01360             rowScale[numberQuadraticColumns+numberXRows] = columnScale[i];
01361             numberQuadraticColumns++;
01362           }
01363         }    
01364         int numberQuadraticRows=0;
01365         for (i=0;i<numberXRows;i++) {
01366           // See if any in row quadratic
01367           int j;
01368           int numberQ=0;
01369           for (j=rowStart[i];j<rowStart[i+1];j++) {
01370             int iColumn = column[j];
01371             if (columnQuadraticLength[iColumn])
01372               numberQ++;
01373           }
01374 #ifndef CORRECT_ROW_COUNTS
01375           numberQ=1;
01376 #endif
01377           if (numberQ) {
01378             columnScale[numberQuadraticRows+numberXColumns] = rowScale[i];
01379             numberQuadraticRows++;
01380           }
01381         }
01382         // and make sure Sj okay
01383         for (iColumn=numberQuadraticRows+numberXColumns;iColumn<numberColumns;iColumn++) {
01384           CoinBigIndex j=columnStart[iColumn];
01385           assert(columnLength[iColumn]==1);
01386           int iRow=row[j];
01387           double value = fabs(elementByColumn[j]*rowScale[iRow]);
01388           columnScale[iColumn]=1.0/value;
01389         }
01390       }
01391     }
01392     model->setRowScale(rowScale);
01393     model->setColumnScale(columnScale);
01394     if (model->rowCopy()) {
01395       // need to replace row by row
01396       double * newElement = new double[numberColumns];
01397       // scale row copy
01398       for (iRow=0;iRow<numberRows;iRow++) {
01399         int j;
01400         double scale = rowScale[iRow];
01401         const double * elementsInThisRow = element + rowStart[iRow];
01402         const int * columnsInThisRow = column + rowStart[iRow];
01403         int number = rowStart[iRow+1]-rowStart[iRow];
01404         assert (number<=numberColumns);
01405         for (j=0;j<number;j++) {
01406           int iColumn = columnsInThisRow[j];
01407           newElement[j] = elementsInThisRow[j]*scale*columnScale[iColumn];
01408         }
01409         rowCopy->replaceVector(iRow,number,newElement);
01410       }
01411       delete [] newElement;
01412     } else {
01413       // no row copy
01414       delete rowCopyBase;
01415     }
01416     return 0;
01417   }
01418 }
01419 /* Unpacks a column into an CoinIndexedvector
01420  */
01421 void 
01422 ClpPackedMatrix::unpack(const ClpSimplex * model,CoinIndexedVector * rowArray,
01423                    int iColumn) const 
01424 {
01425   const double * rowScale = model->rowScale();
01426   const int * row = matrix_->getIndices();
01427   const CoinBigIndex * columnStart = matrix_->getVectorStarts();
01428   const int * columnLength = matrix_->getVectorLengths(); 
01429   const double * elementByColumn = matrix_->getElements();
01430   CoinBigIndex i;
01431   if (!rowScale) {
01432     for (i=columnStart[iColumn];
01433          i<columnStart[iColumn]+columnLength[iColumn];i++) {
01434       rowArray->add(row[i],elementByColumn[i]);
01435     }
01436   } else {
01437     // apply scaling
01438     double scale = model->columnScale()[iColumn];
01439     for (i=columnStart[iColumn];
01440          i<columnStart[iColumn]+columnLength[iColumn];i++) {
01441       int iRow = row[i];
01442       rowArray->add(iRow,elementByColumn[i]*scale*rowScale[iRow]);
01443     }
01444   }
01445 }
01446 /* Unpacks a column into a CoinIndexedVector
01447 ** in packed format
01448 Note that model is NOT const.  Bounds and objective could
01449 be modified if doing column generation (just for this variable) */
01450 void 
01451 ClpPackedMatrix::unpackPacked(ClpSimplex * model,
01452                             CoinIndexedVector * rowArray,
01453                             int iColumn) const
01454 {
01455   const double * rowScale = model->rowScale();
01456   const int * row = matrix_->getIndices();
01457   const CoinBigIndex * columnStart = matrix_->getVectorStarts();
01458   const int * columnLength = matrix_->getVectorLengths(); 
01459   const double * elementByColumn = matrix_->getElements();
01460   CoinBigIndex i;
01461   if (!rowScale) {
01462     int j=columnStart[iColumn];
01463     rowArray->createPacked(columnLength[iColumn],
01464                            row+j,elementByColumn+j);
01465   } else {
01466     // apply scaling
01467     double scale = model->columnScale()[iColumn];
01468     int * index = rowArray->getIndices();
01469     double * array = rowArray->denseVector();
01470     int number = 0;
01471     for (i=columnStart[iColumn];
01472          i<columnStart[iColumn]+columnLength[iColumn];i++) {
01473       int iRow = row[i];
01474       array[number]=elementByColumn[i]*scale*rowScale[iRow];
01475       index[number++]=iRow;
01476     }
01477     rowArray->setNumElements(number);
01478     rowArray->setPackedMode(true);
01479   }
01480 }
01481 /* Adds multiple of a column into an CoinIndexedvector
01482       You can use quickAdd to add to vector */
01483 void 
01484 ClpPackedMatrix::add(const ClpSimplex * model,CoinIndexedVector * rowArray,
01485                    int iColumn, double multiplier) const 
01486 {
01487   const double * rowScale = model->rowScale();
01488   const int * row = matrix_->getIndices();
01489   const CoinBigIndex * columnStart = matrix_->getVectorStarts();
01490   const int * columnLength = matrix_->getVectorLengths(); 
01491   const double * elementByColumn = matrix_->getElements();
01492   CoinBigIndex i;
01493   if (!rowScale) {
01494     for (i=columnStart[iColumn];
01495          i<columnStart[iColumn]+columnLength[iColumn];i++) {
01496       int iRow = row[i];
01497       rowArray->quickAdd(iRow,multiplier*elementByColumn[i]);
01498     }
01499   } else {
01500     // apply scaling
01501     double scale = model->columnScale()[iColumn]*multiplier;
01502     for (i=columnStart[iColumn];
01503          i<columnStart[iColumn]+columnLength[iColumn];i++) {
01504       int iRow = row[i];
01505       rowArray->quickAdd(iRow,elementByColumn[i]*scale*rowScale[iRow]);
01506     }
01507   }
01508 }
01509 /* Checks if all elements are in valid range.  Can just
01510    return true if you are not paranoid.  For Clp I will
01511    probably expect no zeros.  Code can modify matrix to get rid of
01512    small elements.
01513 */
01514 bool 
01515 ClpPackedMatrix::allElementsInRange(ClpModel * model,
01516                                     double smallest, double largest)
01517 {
01518   int iColumn;
01519   CoinBigIndex numberLarge=0;;
01520   CoinBigIndex numberSmall=0;;
01521   CoinBigIndex numberDuplicate=0;;
01522   int firstBadColumn=-1;
01523   int firstBadRow=-1;
01524   double firstBadElement=0.0;
01525   // get matrix data pointers
01526   const int * row = matrix_->getIndices();
01527   const CoinBigIndex * columnStart = matrix_->getVectorStarts();
01528   const int * columnLength = matrix_->getVectorLengths(); 
01529   const double * elementByColumn = matrix_->getElements();
01530   int numberColumns = matrix_->getNumCols();
01531   int numberRows = matrix_->getNumRows();
01532   int * mark = new int [numberRows];
01533   int i;
01534   for (i=0;i<numberRows;i++)
01535     mark[i]=-1;
01536   for (iColumn=0;iColumn<numberColumns;iColumn++) {
01537     CoinBigIndex j;
01538     for (j=columnStart[iColumn];
01539          j<columnStart[iColumn]+columnLength[iColumn];j++) {
01540       double value = fabs(elementByColumn[j]);
01541       int iRow = row[j];
01542       if (iRow<0||iRow>=numberRows) {
01543         printf("Out of range %d %d %d %g\n",iColumn,j,row[j],elementByColumn[j]);
01544         return false;
01545       }
01546       if (mark[iRow]==-1) {
01547         mark[iRow]=j;
01548       } else {
01549         // duplicate
01550         numberDuplicate++;
01551       }
01552       //printf("%d %d %d %g\n",iColumn,j,row[j],elementByColumn[j]);
01553       if (!value)
01554         zeroElements_ = true; // there are zero elements
01555       if (value<smallest) {
01556         numberSmall++;
01557       } else if (value>largest) {
01558         numberLarge++;
01559         if (firstBadColumn<0) {
01560           firstBadColumn=iColumn;
01561           firstBadRow=row[j];
01562           firstBadElement=elementByColumn[j];
01563         }
01564       }
01565     }
01566     //clear mark
01567     for (j=columnStart[iColumn];
01568          j<columnStart[iColumn]+columnLength[iColumn];j++) {
01569       int iRow = row[j];
01570       mark[iRow]=-1;
01571     }
01572   }
01573   delete [] mark;
01574   if (numberLarge) {
01575     model->messageHandler()->message(CLP_BAD_MATRIX,model->messages())
01576       <<numberLarge
01577       <<firstBadColumn<<firstBadRow<<firstBadElement
01578       <<CoinMessageEol;
01579     return false;
01580   }
01581   if (numberSmall) 
01582     model->messageHandler()->message(CLP_SMALLELEMENTS,model->messages())
01583       <<numberSmall
01584       <<CoinMessageEol;
01585   if (numberDuplicate) 
01586     model->messageHandler()->message(CLP_DUPLICATEELEMENTS,model->messages())
01587       <<numberDuplicate
01588       <<CoinMessageEol;
01589   if (numberDuplicate) 
01590     matrix_->eliminateDuplicates(smallest);
01591   else if (numberSmall) 
01592     matrix_->compress(smallest);
01593   // If smallest >0.0 then there can't be zero elements
01594   if (smallest>0.0)
01595     zeroElements_=false;
01596   return true;
01597 }
01598 /* Given positive integer weights for each row fills in sum of weights
01599    for each column (and slack).
01600    Returns weights vector
01601 */
01602 CoinBigIndex * 
01603 ClpPackedMatrix::dubiousWeights(const ClpSimplex * model,int * inputWeights) const
01604 {
01605   int numberRows = model->numberRows();
01606   int numberColumns =model->numberColumns();
01607   int number = numberRows+numberColumns;
01608   CoinBigIndex * weights = new CoinBigIndex[number];
01609   // get matrix data pointers
01610   const int * row = matrix_->getIndices();
01611   const CoinBigIndex * columnStart = matrix_->getVectorStarts();
01612   const int * columnLength = matrix_->getVectorLengths(); 
01613   int i;
01614   for (i=0;i<numberColumns;i++) {
01615     CoinBigIndex j;
01616     CoinBigIndex count=0;
01617     for (j=columnStart[i];j<columnStart[i]+columnLength[i];j++) {
01618       int iRow=row[j];
01619       count += inputWeights[iRow];
01620     }
01621     weights[i]=count;
01622   }
01623   for (i=0;i<numberRows;i++) {
01624     weights[i+numberColumns]=inputWeights[i];
01625   }
01626   return weights;
01627 }
01628 /* Returns largest and smallest elements of both signs.
01629    Largest refers to largest absolute value.
01630 */
01631 void 
01632 ClpPackedMatrix::rangeOfElements(double & smallestNegative, double & largestNegative,
01633                        double & smallestPositive, double & largestPositive)
01634 {
01635   smallestNegative=-COIN_DBL_MAX;
01636   largestNegative=0.0;
01637   smallestPositive=COIN_DBL_MAX;
01638   largestPositive=0.0;
01639   int numberColumns = matrix_->getNumCols();
01640   // get matrix data pointers
01641   const double * elementByColumn = matrix_->getElements();
01642   const CoinBigIndex * columnStart = matrix_->getVectorStarts();
01643   const int * columnLength = matrix_->getVectorLengths(); 
01644   int i;
01645   for (i=0;i<numberColumns;i++) {
01646     CoinBigIndex j;
01647     for (j=columnStart[i];j<columnStart[i]+columnLength[i];j++) {
01648       double value = elementByColumn[j];
01649       if (value>0.0) {
01650         smallestPositive = min(smallestPositive,value);
01651         largestPositive = max(largestPositive,value);
01652       } else if (value<0.0) {
01653         smallestNegative = max(smallestNegative,value);
01654         largestNegative = min(largestNegative,value);
01655       }
01656     }
01657   }
01658 }
01659 // Says whether it can do partial pricing
01660 bool 
01661 ClpPackedMatrix::canDoPartialPricing() const
01662 {
01663   return true;
01664 }
01665 // Partial pricing 
01666 void 
01667 ClpPackedMatrix::partialPricing(ClpSimplex * model, int start, int end,
01668                               int & bestSequence, int & numberWanted)
01669 {
01670   const double * element =matrix_->getElements();
01671   const int * row = matrix_->getIndices();
01672   const int * startColumn = matrix_->getVectorStarts();
01673   const int * length = matrix_->getVectorLengths();
01674   const double * rowScale = model->rowScale();
01675   const double * columnScale = model->columnScale();
01676   int iSequence,j;
01677   double tolerance=model->currentDualTolerance();
01678   double * reducedCost = model->djRegion();
01679   const double * duals = model->dualRowSolution();
01680   const double * cost = model->costRegion();
01681   double bestDj;
01682   if (bestSequence>=0)
01683     bestDj = fabs(reducedCost[bestSequence]);
01684   else
01685     bestDj=tolerance;
01686   int sequenceOut = model->sequenceOut();
01687   int saveSequence = bestSequence;
01688   if (rowScale) {
01689     // scaled
01690     for (iSequence=start;iSequence<end;iSequence++) {
01691       if (iSequence!=sequenceOut) {
01692         double value;
01693         ClpSimplex::Status status = model->getStatus(iSequence);
01694         
01695         switch(status) {
01696           
01697         case ClpSimplex::basic:
01698         case ClpSimplex::isFixed:
01699           break;
01700         case ClpSimplex::isFree:
01701         case ClpSimplex::superBasic:
01702           value=0.0;
01703           // scaled
01704           for (j=startColumn[iSequence];
01705                j<startColumn[iSequence]+length[iSequence];j++) {
01706             int jRow=row[j];
01707             value -= duals[jRow]*element[j]*rowScale[jRow];
01708           }
01709           value = fabs(cost[iSequence] +value*columnScale[iSequence]);
01710           if (value>FREE_ACCEPT*tolerance) {
01711             numberWanted--;
01712             // we are going to bias towards free (but only if reasonable)
01713             value *= FREE_BIAS;
01714             if (value>bestDj) {
01715               // check flagged variable and correct dj
01716               if (!model->flagged(iSequence)) {
01717                 bestDj=value;
01718                 bestSequence = iSequence;
01719               } else {
01720                 // just to make sure we don't exit before got something
01721                 numberWanted++;
01722               }
01723             }
01724           }
01725           break;
01726         case ClpSimplex::atUpperBound:
01727           value=0.0;
01728           // scaled
01729           for (j=startColumn[iSequence];
01730                j<startColumn[iSequence]+length[iSequence];j++) {
01731             int jRow=row[j];
01732             value -= duals[jRow]*element[j]*rowScale[jRow];
01733           }
01734           value = cost[iSequence] +value*columnScale[iSequence];
01735           if (value>tolerance) {
01736             numberWanted--;
01737             if (value>bestDj) {
01738               // check flagged variable and correct dj
01739               if (!model->flagged(iSequence)) {
01740                 bestDj=value;
01741                 bestSequence = iSequence;
01742               } else {
01743                 // just to make sure we don't exit before got something
01744                 numberWanted++;
01745               }
01746             }
01747           }
01748           break;
01749         case ClpSimplex::atLowerBound:
01750           value=0.0;
01751           // scaled
01752           for (j=startColumn[iSequence];
01753                j<startColumn[iSequence]+length[iSequence];j++) {
01754             int jRow=row[j];
01755             value -= duals[jRow]*element[j]*rowScale[jRow];
01756           }
01757           value = -(cost[iSequence] +value*columnScale[iSequence]);
01758           if (value>tolerance) {
01759             numberWanted--;
01760             if (value>bestDj) {
01761               // check flagged variable and correct dj
01762               if (!model->flagged(iSequence)) {
01763                 bestDj=value;
01764                 bestSequence = iSequence;
01765               } else {
01766                 // just to make sure we don't exit before got something
01767                 numberWanted++;
01768               }
01769             }
01770           }
01771           break;
01772         }
01773       }
01774       if (!numberWanted)
01775         break;
01776     }
01777     if (bestSequence!=saveSequence) {
01778       // recompute dj
01779       double value=0.0;
01780       // scaled
01781       for (j=startColumn[bestSequence];
01782            j<startColumn[bestSequence]+length[bestSequence];j++) {
01783         int jRow=row[j];
01784         value -= duals[jRow]*element[j]*rowScale[jRow];
01785       }
01786       reducedCost[bestSequence] = cost[bestSequence] +value*columnScale[bestSequence];
01787     }
01788   } else {
01789     // not scaled
01790     for (iSequence=start;iSequence<end;iSequence++) {
01791       if (iSequence!=sequenceOut) {
01792         double value;
01793         ClpSimplex::Status status = model->getStatus(iSequence);
01794         
01795         switch(status) {
01796           
01797         case ClpSimplex::basic:
01798         case ClpSimplex::isFixed:
01799           break;
01800         case ClpSimplex::isFree:
01801         case ClpSimplex::superBasic:
01802           value=cost[iSequence];
01803           for (j=startColumn[iSequence];
01804                j<startColumn[iSequence]+length[iSequence];j++) {
01805             int jRow=row[j];
01806             value -= duals[jRow]*element[j];
01807           }
01808           value = fabs(value);
01809           if (value>FREE_ACCEPT*tolerance) {
01810             numberWanted--;
01811             // we are going to bias towards free (but only if reasonable)
01812             value *= FREE_BIAS;
01813             if (value>bestDj) {
01814               // check flagged variable and correct dj
01815               if (!model->flagged(iSequence)) {
01816                 bestDj=value;
01817                 bestSequence = iSequence;
01818               } else {
01819                 // just to make sure we don't exit before got something
01820                 numberWanted++;
01821               }
01822             }
01823           }
01824           break;
01825         case ClpSimplex::atUpperBound:
01826           value=cost[iSequence];
01827           // scaled
01828           for (j=startColumn[iSequence];
01829                j<startColumn[iSequence]+length[iSequence];j++) {
01830             int jRow=row[j];
01831             value -= duals[jRow]*element[j];
01832           }
01833           if (value>tolerance) {
01834             numberWanted--;
01835             if (value>bestDj) {
01836               // check flagged variable and correct dj
01837               if (!model->flagged(iSequence)) {
01838                 bestDj=value;
01839                 bestSequence = iSequence;
01840               } else {
01841                 // just to make sure we don't exit before got something
01842                 numberWanted++;
01843               }
01844             }
01845           }
01846           break;
01847         case ClpSimplex::atLowerBound:
01848           value=cost[iSequence];
01849           for (j=startColumn[iSequence];
01850                j<startColumn[iSequence]+length[iSequence];j++) {
01851             int jRow=row[j];
01852             value -= duals[jRow]*element[j];
01853           }
01854           value = -value;
01855           if (value>tolerance) {
01856             numberWanted--;
01857             if (value>bestDj) {
01858               // check flagged variable and correct dj
01859               if (!model->flagged(iSequence)) {
01860                 bestDj=value;
01861                 bestSequence = iSequence;
01862               } else {
01863                 // just to make sure we don't exit before got something
01864                 numberWanted++;
01865               }
01866             }
01867           }
01868           break;
01869         }
01870       }
01871       if (!numberWanted)
01872         break;
01873     }
01874     if (bestSequence!=saveSequence) {
01875       // recompute dj
01876       double value=cost[bestSequence];
01877       for (j=startColumn[bestSequence];
01878            j<startColumn[bestSequence]+length[bestSequence];j++) {
01879         int jRow=row[j];
01880         value -= duals[jRow]*element[j];
01881       }
01882       reducedCost[bestSequence] = value;
01883     }
01884   }
01885 }
01886 
01887 

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