00001
00002
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
00015 #include "ClpPackedMatrix.hpp"
00016 #include "ClpMessage.hpp"
00017
00018
00019
00020
00021
00022
00023
00024
00025 ClpPackedMatrix::ClpPackedMatrix ()
00026 : ClpMatrixBase(),
00027 matrix_(NULL),
00028 zeroElements_(false)
00029 {
00030 setType(1);
00031 }
00032
00033
00034
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
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
00067
00068 ClpPackedMatrix::~ClpPackedMatrix ()
00069 {
00070 delete matrix_;
00071 }
00072
00073
00074
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
00089
00090 ClpMatrixBase * ClpPackedMatrix::clone() const
00091 {
00092 return new ClpPackedMatrix(*this);
00093 }
00094
00095
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
00105
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
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
00139 void
00140 ClpPackedMatrix::times(double scalar,
00141 const double * x, double * y) const
00142 {
00143 int iRow,iColumn;
00144
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
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
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
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
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
00201 for (iColumn=0;iColumn<numberColumns;iColumn++) {
00202 CoinBigIndex j;
00203 double value = x[iColumn];
00204 if (value) {
00205
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
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
00237 for (iColumn=0;iColumn<numberColumns;iColumn++) {
00238 CoinBigIndex j;
00239 double value=0.0;
00240
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
00253
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
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
00274 int numberColumns = model->numberColumns();
00275
00276
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
00285
00286 }
00287 if (numberInRowArray>factor*numberRows||!rowCopy) {
00288
00289 int iColumn;
00290
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
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
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
00326
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
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
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();
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
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
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
00518
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
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
00540
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
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
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();
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
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
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
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
00644 iRow0=iRow1;
00645 iRow1=whichRow[0];
00646 pi0=pi1;
00647 pi1=pi[0];
00648 }
00649
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
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
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
00713 if (array[iColumn])
00714 value2 += array[iColumn];
00715 else
00716 index[numberNonZero++]=iColumn;
00717 array[iColumn] = value2;
00718 }
00719
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
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
00762
00763
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
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
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
00814
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
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
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
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
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
00892 if (!rowScale) {
00893
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
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
00932
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
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
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
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
00984 if (!rowScale) {
00985
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
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
01023 for (i=0;i<numberColumnBasic;i++) {
01024 int iColumn = whichColumn[i];
01025 numberElements += columnLength[iColumn];
01026 }
01027 }
01028 return numberElements;
01029 }
01030
01031 int
01032 ClpPackedMatrix::scale(ClpSimplex * model) const
01033 {
01034 int numberRows = model->numberRows();
01035 int numberColumns = model->numberColumns();
01036
01037 if (!numberRows||!numberColumns)
01038 return 1;
01039 ClpMatrixBase * rowCopyBase=model->rowCopy();
01040 if (!rowCopyBase) {
01041
01042 rowCopyBase = reverseOrderedCopy();
01043 }
01044 ClpPackedMatrix* rowCopy =
01045 dynamic_cast< ClpPackedMatrix*>(rowCopyBase);
01046
01047
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
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
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
01070
01071 assert (model->scalingFlag()<4);
01072 double largest=0.0;
01073 double smallest=1.0e50;
01074
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
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
01110 int scalingMethod = model->scalingFlag();
01111 if (scalingMethod==3) {
01112
01113 if (smallest<1.0e-5||smallest*largest<1.0)
01114 scalingMethod=1;
01115 else
01116 scalingMethod=2;
01117 }
01118
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
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
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
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
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
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
01212 if (numberPass==1)
01213 break;
01214
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
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
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
01255 rowScale[iRow] *= 1.0e-4/scaledDifference;
01256
01257
01258 }
01259 }
01260 }
01261
01262
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
01285 for (iRow=0;iRow<numberRows;iRow++) {
01286 double value = 0.5-CoinDrand48();
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();
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
01318 columnScale[iColumn] *= 1.0e-4/scaledDifference;
01319
01320
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
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
01339 int numberQuadraticColumns=0;
01340 int i;
01341
01342
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
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
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
01396 double * newElement = new double[numberColumns];
01397
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
01414 delete rowCopyBase;
01415 }
01416 return 0;
01417 }
01418 }
01419
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
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
01447
01448
01449
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
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
01482
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
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
01510
01511
01512
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
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
01550 numberDuplicate++;
01551 }
01552
01553 if (!value)
01554 zeroElements_ = true;
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
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
01594 if (smallest>0.0)
01595 zeroElements_=false;
01596 return true;
01597 }
01598
01599
01600
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
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
01629
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
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
01660 bool
01661 ClpPackedMatrix::canDoPartialPricing() const
01662 {
01663 return true;
01664 }
01665
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
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
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
01713 value *= FREE_BIAS;
01714 if (value>bestDj) {
01715
01716 if (!model->flagged(iSequence)) {
01717 bestDj=value;
01718 bestSequence = iSequence;
01719 } else {
01720
01721 numberWanted++;
01722 }
01723 }
01724 }
01725 break;
01726 case ClpSimplex::atUpperBound:
01727 value=0.0;
01728
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
01739 if (!model->flagged(iSequence)) {
01740 bestDj=value;
01741 bestSequence = iSequence;
01742 } else {
01743
01744 numberWanted++;
01745 }
01746 }
01747 }
01748 break;
01749 case ClpSimplex::atLowerBound:
01750 value=0.0;
01751
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
01762 if (!model->flagged(iSequence)) {
01763 bestDj=value;
01764 bestSequence = iSequence;
01765 } else {
01766
01767 numberWanted++;
01768 }
01769 }
01770 }
01771 break;
01772 }
01773 }
01774 if (!numberWanted)
01775 break;
01776 }
01777 if (bestSequence!=saveSequence) {
01778
01779 double value=0.0;
01780
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
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
01812 value *= FREE_BIAS;
01813 if (value>bestDj) {
01814
01815 if (!model->flagged(iSequence)) {
01816 bestDj=value;
01817 bestSequence = iSequence;
01818 } else {
01819
01820 numberWanted++;
01821 }
01822 }
01823 }
01824 break;
01825 case ClpSimplex::atUpperBound:
01826 value=cost[iSequence];
01827
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
01837 if (!model->flagged(iSequence)) {
01838 bestDj=value;
01839 bestSequence = iSequence;
01840 } else {
01841
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
01859 if (!model->flagged(iSequence)) {
01860 bestDj=value;
01861 bestSequence = iSequence;
01862 } else {
01863
01864 numberWanted++;
01865 }
01866 }
01867 }
01868 break;
01869 }
01870 }
01871 if (!numberWanted)
01872 break;
01873 }
01874 if (bestSequence!=saveSequence) {
01875
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