// Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. #include "CoinPragma.hpp" #include #include "CoinIndexedVector.hpp" #include "CoinHelperFunctions.hpp" #include "ClpMatrixBase.hpp" #include "ClpSimplex.hpp" //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- ClpMatrixBase::ClpMatrixBase () : rhsOffset_(NULL), startFraction_(0.0), endFraction_(1.0), savedBestDj_(0.0), originalWanted_(0), currentWanted_(0), savedBestSequence_(-1), type_(-1), lastRefresh_(-1), refreshFrequency_(0), minimumObjectsScan_(-1), minimumGoodReducedCosts_(-1), trueSequenceIn_(-1), trueSequenceOut_(-1), skipDualCheck_(false) { } //------------------------------------------------------------------- // Copy constructor //------------------------------------------------------------------- ClpMatrixBase::ClpMatrixBase (const ClpMatrixBase & rhs) : type_(rhs.type_), skipDualCheck_(rhs.skipDualCheck_) { startFraction_ = rhs.startFraction_; endFraction_ = rhs.endFraction_; savedBestDj_ = rhs.savedBestDj_; originalWanted_ = rhs.originalWanted_; currentWanted_ = rhs.currentWanted_; savedBestSequence_ = rhs.savedBestSequence_; lastRefresh_ = rhs.lastRefresh_; refreshFrequency_ = rhs.refreshFrequency_; minimumObjectsScan_ = rhs.minimumObjectsScan_; minimumGoodReducedCosts_ = rhs.minimumGoodReducedCosts_; trueSequenceIn_ = rhs.trueSequenceIn_; trueSequenceOut_ = rhs.trueSequenceOut_; skipDualCheck_ = rhs.skipDualCheck_; int numberRows = rhs.getNumRows(); if (rhs.rhsOffset_&&numberRows) { rhsOffset_ = ClpCopyOfArray(rhs.rhsOffset_,numberRows); } else { rhsOffset_=NULL; } } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- ClpMatrixBase::~ClpMatrixBase () { delete [] rhsOffset_; } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- ClpMatrixBase & ClpMatrixBase::operator=(const ClpMatrixBase& rhs) { if (this != &rhs) { type_ = rhs.type_; delete [] rhsOffset_; int numberRows = rhs.getNumRows(); if (rhs.rhsOffset_&&numberRows) { rhsOffset_ = ClpCopyOfArray(rhs.rhsOffset_,numberRows); } else { rhsOffset_=NULL; } startFraction_ = rhs.startFraction_; endFraction_ = rhs.endFraction_; savedBestDj_ = rhs.savedBestDj_; originalWanted_ = rhs.originalWanted_; currentWanted_ = rhs.currentWanted_; savedBestSequence_ = rhs.savedBestSequence_; lastRefresh_ = rhs.lastRefresh_; refreshFrequency_ = rhs.refreshFrequency_; minimumObjectsScan_ = rhs.minimumObjectsScan_; minimumGoodReducedCosts_ = rhs.minimumGoodReducedCosts_; trueSequenceIn_ = rhs.trueSequenceIn_; trueSequenceOut_ = rhs.trueSequenceOut_; skipDualCheck_ = rhs.skipDualCheck_; } return *this; } // And for scaling - default aborts for when scaling not supported void ClpMatrixBase::times(double scalar, const double * x, double * y, const double * rowScale, const double * columnScale) const { if (rowScale) { std::cerr<<"Scaling not supported - ClpMatrixBase"<numberRows()+model->numberColumns(); CoinBigIndex * weights = new CoinBigIndex[number]; int i; for (i=0;ix *A in z but just for number indices in y. Default cheats with fake CoinIndexedVector and then calls subsetTransposeTimes */ void ClpMatrixBase::listTransposeTimes(const ClpSimplex * model, double * x, int * y, int number, double * z) const { CoinIndexedVector pi; CoinIndexedVector list; CoinIndexedVector output; int * saveIndices = list.getIndices(); list.setNumElements(number); list.setIndexVector(y); double * savePi = pi.denseVector(); pi.setDenseVector(x); double * saveOutput = output.denseVector(); output.setDenseVector(z); output.setPacked(); subsetTransposeTimes(model,&pi,&list,&output); // restore settings list.setIndexVector(saveIndices); pi.setDenseVector(savePi); output.setDenseVector(saveOutput); } // Partial pricing void ClpMatrixBase::partialPricing(ClpSimplex * model, double start, double end, int & bestSequence, int & numberWanted) { std::cerr<<"partialPricing not supported - ClpMatrixBase"<numberColumns(); // Use different array so can build from true pivotVariable_ //int * pivotVariable = model->pivotVariable(); int * pivotVariable = model->rowArray(0)->getIndices(); for (i=0;igetColumnStatus(i) == ClpSimplex::basic) pivotVariable[numberBasic++]=i; } number = numberBasic; } break; // Do initial extra rows + maximum basic case 2: { number = model->numberRows(); } break; // To see if can dual or primal case 4: { returnCode= 3; } break; default: break; } return returnCode; } // Sets up an effective RHS void ClpMatrixBase::useEffectiveRhs(ClpSimplex * model) { std::cerr<<"useEffectiveRhs not supported - ClpMatrixBase"<numberRows(); int numberColumns = model->numberColumns(); double * solution = new double [numberColumns]; double * rhs = new double[numberRows]; const double * solutionSlack = model->solutionRegion(0); CoinMemcpyN(model->solutionRegion(),numberColumns,solution); int iRow; for (iRow=0;iRowgetRowStatus(iRow)!=ClpSimplex::basic) rhs[iRow]=solutionSlack[iRow]; else rhs[iRow]=0.0; } for (int iColumn=0;iColumngetColumnStatus(iColumn)==ClpSimplex::basic) solution[iColumn]=0.0; } times(-1.0,solution,rhs); delete [] solution; for (iRow=0;iRow1.0e-3) printf("** bad effective %d - true %g old %g\n",iRow,rhs[iRow],rhsOffset_[iRow]); } } #endif if (forceRefresh||(refreshFrequency_&&model->numberIterations()>= lastRefresh_+refreshFrequency_)) { // zero out basic int numberRows = model->numberRows(); int numberColumns = model->numberColumns(); double * solution = new double [numberColumns]; const double * solutionSlack = model->solutionRegion(0); CoinMemcpyN(model->solutionRegion(),numberColumns,solution); for (int iRow=0;iRowgetRowStatus(iRow)!=ClpSimplex::basic) rhsOffset_[iRow]=solutionSlack[iRow]; else rhsOffset_[iRow]=0.0; } for (int iColumn=0;iColumngetColumnStatus(iColumn)==ClpSimplex::basic) solution[iColumn]=0.0; } times(-1.0,solution,rhsOffset_); delete [] solution; lastRefresh_ = model->numberIterations(); } } return rhsOffset_; } /* update information for a pivot (and effective rhs) */ int ClpMatrixBase::updatePivot(ClpSimplex * model,double oldInValue, double oldOutValue) { if (rhsOffset_) { // update effective rhs int sequenceIn = model->sequenceIn(); int sequenceOut = model->sequenceOut(); double * solution = model->solutionRegion(); int numberColumns = model->numberColumns(); if (sequenceIn==sequenceOut) { if (sequenceInnumberRows(); int numberColumns = model->numberColumns(); if (sequencedjRegion()[sequence]; else return savedBestDj_; } /* Just for debug if odd type matrix. Returns number and sum of primal infeasibilities. */ int ClpMatrixBase::checkFeasible(ClpSimplex * model, double & sum) const { int numberRows = model->numberRows(); double * rhs = new double[numberRows]; int numberColumns = model->numberColumns(); int iRow; CoinZeroN(rhs,numberRows); times(1.0,model->solutionRegion(),rhs,model->rowScale(),model->columnScale()); int iColumn; int logLevel = model->messageHandler()->logLevel(); int numberInfeasible=0; const double * rowLower = model->lowerRegion(0); const double * rowUpper = model->upperRegion(0); const double * solution; solution = model->solutionRegion(0); double tolerance = model->primalTolerance()*1.01; sum=0.0; for (iRow=0;iRow3) { if (fabs(value-value2)>1.0e-8) printf("Row %d stored %g, computed %g\n",iRow,value2,value); } if (valuerowUpper[iRow]+tolerance) { numberInfeasible++; sum += CoinMax(rowLower[iRow]-value,value-rowUpper[iRow]); } if (value2>rowLower[iRow]+tolerance&& value2getRowStatus(iRow)!=ClpSimplex::basic) { assert (model->getRowStatus(iRow)==ClpSimplex::superBasic); } } const double * columnLower = model->lowerRegion(1); const double * columnUpper = model->upperRegion(1); solution = model->solutionRegion(1); for (iColumn=0;iColumncolumnUpper[iColumn]+tolerance) { numberInfeasible++; sum += CoinMax(columnLower[iColumn]-value,value-columnUpper[iColumn]); } if (value>columnLower[iColumn]+tolerance&& valuegetColumnStatus(iColumn)!=ClpSimplex::basic) { assert (model->getColumnStatus(iColumn)==ClpSimplex::superBasic); } } delete [] rhs; return numberInfeasible; } // These have to match ClpPrimalColumnSteepest version #define reference(i) (((reference[i>>5]>>(i&31))&1)!=0) // Updates second array for steepest and does devex weights (need not be coded) void ClpMatrixBase::subsetTimes2(const ClpSimplex * model, CoinIndexedVector * dj1, const CoinIndexedVector * pi2, CoinIndexedVector * dj2, double referenceIn, double devex, // Array for exact devex to say what is in reference framework unsigned int * reference, double * weights, double scaleFactor) { // get subset which have nonzero tableau elements subsetTransposeTimes(model,pi2,dj1,dj2); bool killDjs = (scaleFactor==0.0); if (!scaleFactor) scaleFactor=1.0; // columns int number = dj1->getNumElements(); const int * index = dj1->getIndices(); double * updateBy = dj1->denseVector(); double * updateBy2 = dj2->denseVector(); for (int j=0;jgetStatus(iSequence); if (status!=ClpSimplex::basic&&status!=ClpSimplex::isFixed) { thisWeight = weights[iSequence]; pivot = value2*scaleFactor; pivotSquared = pivot * pivot; thisWeight += pivotSquared * devex + pivot * modification; if (thisWeightsetNumElements(0); } // Correct sequence in and out to give true value void ClpMatrixBase::correctSequence(const ClpSimplex * model,int & sequenceIn, int & sequenceOut) { } // Really scale matrix void ClpMatrixBase::reallyScale(const double * rowScale, const double * columnScale) { std::cerr<<"reallyScale not supported - ClpMatrixBase"<0) or duplicates If 0 then rows, 1 if columns */ int ClpMatrixBase::appendMatrix(int number, int type, const CoinBigIndex * starts, const int * index, const double * element, int numberOther) { std::cerr<<"appendMatrix not supported - ClpMatrixBase"<