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

ClpSimplexPrimal Class Reference

#include <ClpSimplexPrimal.hpp>

Inheritance diagram for ClpSimplexPrimal:

ClpSimplex ClpModel ClpSimplexPrimalQuadratic List of all members.

Public Member Functions

Description of algorithm
int primal (int ifValuesPass=0)
For advanced users
void alwaysOptimal (bool onOff)
 Do not change infeasibility cost and always say optimal.

bool alwaysOptimal () const
void exactOutgoing (bool onOff)
bool exactOutgoing () const
Functions used in primal
int whileIterating (int valuesOption)
int pivotResult (int ifValuesPass=0)
int updatePrimalsInPrimal (CoinIndexedVector *rowArray, double theta, double &objectiveChange, int valuesPass)
void primalRow (CoinIndexedVector *rowArray, CoinIndexedVector *rhsArray, CoinIndexedVector *spareArray, CoinIndexedVector *spareArray2, int valuesPass)
void primalColumn (CoinIndexedVector *updateArray, CoinIndexedVector *spareRow1, CoinIndexedVector *spareRow2, CoinIndexedVector *spareColumn1, CoinIndexedVector *spareColumn2)
int checkUnbounded (CoinIndexedVector *ray, CoinIndexedVector *spare, double changeCost)
void statusOfProblemInPrimal (int &lastCleaned, int type, ClpSimplexProgress *progress, bool doFactorization, ClpSimplex *saveModel=NULL)
void perturb (int type)
 Perturbs problem (method depends on perturbation()).

bool unPerturb ()
 Take off effect of perturbation and say whether to try dual.

int unflag ()
 Unflag all variables and return number unflagged.

int nextSuperBasic (int superBasicType, CoinIndexedVector *columnArray)
void primalRay (CoinIndexedVector *rowArray)
 Create primal ray.

void clearAll ()
 Clears all bits and clears rowArray[1] etc.


Detailed Description

This solves LPs using the primal simplex method

It inherits from ClpSimplex. It has no data of its own and is never created - only cast from a ClpSimplex object at algorithm time.

Definition at line 22 of file ClpSimplexPrimal.hpp.


Member Function Documentation

int ClpSimplexPrimal::checkUnbounded CoinIndexedVector ray,
CoinIndexedVector spare,
double  changeCost
 

Checks if tentative optimal actually means unbounded in primal Returns -3 if not, 2 if is unbounded

void ClpSimplexPrimal::exactOutgoing bool  onOff  ) 
 

Normally outgoing variables can go out to slightly negative values (but within tolerance) - this is to help stability and and degeneracy. This can be switched off

Definition at line 1907 of file ClpSimplexPrimal.cpp.

01908 {
01909   if (onOff)
01910     specialOptions_ |= 4;
01911   else
01912     specialOptions_ &= ~4;
01913 }

int ClpSimplexPrimal::nextSuperBasic int  superBasicType,
CoinIndexedVector columnArray
 

Get next superbasic -1 if none, Normal type is 1 If type is 3 then initializes sorted list if 2 uses list.

Definition at line 2333 of file ClpSimplexPrimal.cpp.

References CoinIndexedVector::denseVector(), CoinIndexedVector::getIndices(), CoinIndexedVector::getNumElements(), and CoinIndexedVector::setNumElements().

Referenced by whileIterating().

02334 {
02335   if (firstFree_>=0&&superBasicType) {
02336     int returnValue=firstFree_;
02337     int iColumn=firstFree_+1;
02338     if (superBasicType>1) {
02339       if (superBasicType>2) {
02340         // Initialize list
02341         // Wild guess that lower bound more natural than upper
02342         int number=0;
02343         double * work=columnArray->denseVector();
02344         int * which=columnArray->getIndices();
02345         for (iColumn=0;iColumn<numberRows_+numberColumns_;iColumn++) {
02346           if (getStatus(iColumn)==superBasic) {
02347             if (fabs(solution_[iColumn]-lower_[iColumn])<=primalTolerance_) {
02348               solution_[iColumn]=lower_[iColumn];
02349               setStatus(iColumn,atLowerBound);
02350             } else if (fabs(solution_[iColumn]-upper_[iColumn])
02351                        <=primalTolerance_) {
02352               solution_[iColumn]=upper_[iColumn];
02353               setStatus(iColumn,atUpperBound);
02354             } else if (lower_[iColumn]<-1.0e20&&upper_[iColumn]>1.0e20) {
02355               setStatus(iColumn,isFree);
02356               break;
02357             } else if (!flagged(iColumn)) {
02358               // put ones near bounds at end after sorting
02359               work[number]= - min(0.1*(solution_[iColumn]-lower_[iColumn]),
02360                                   upper_[iColumn]-solution_[iColumn]);
02361               which[number++] = iColumn;
02362             }
02363           }
02364         }
02365         CoinSort_2(work,work+number,which);
02366         columnArray->setNumElements(number);
02367         memset(work,0,number*sizeof(double));
02368       }
02369       int * which=columnArray->getIndices();
02370       int number = columnArray->getNumElements();
02371       if (!number) {
02372         // finished
02373         iColumn = numberRows_+numberColumns_;
02374         returnValue=-1;
02375       } else {
02376         number--;
02377         returnValue=which[number];
02378         iColumn=returnValue;
02379         columnArray->setNumElements(number);
02380       }      
02381     } else {
02382       for (;iColumn<numberRows_+numberColumns_;iColumn++) {
02383         if (getStatus(iColumn)==superBasic) {
02384           if (fabs(solution_[iColumn]-lower_[iColumn])<=primalTolerance_) {
02385             solution_[iColumn]=lower_[iColumn];
02386             setStatus(iColumn,atLowerBound);
02387           } else if (fabs(solution_[iColumn]-upper_[iColumn])
02388                      <=primalTolerance_) {
02389             solution_[iColumn]=upper_[iColumn];
02390             setStatus(iColumn,atUpperBound);
02391           } else if (lower_[iColumn]<-1.0e20&&upper_[iColumn]>1.0e20) {
02392             setStatus(iColumn,isFree);
02393             break;
02394           } else {
02395             break;
02396           }
02397         }
02398       }
02399     }
02400     firstFree_ = iColumn;
02401     if (firstFree_==numberRows_+numberColumns_)
02402       firstFree_=-1;
02403     return returnValue;
02404   } else {
02405     return -1;
02406   }
02407 }

int ClpSimplexPrimal::pivotResult int  ifValuesPass = 0  ) 
 

Do last half of an iteration. This is split out so people can force incoming variable. If solveType_ is 2 then this may re-factorize while normally it would exit to re-factorize. Return codes Reasons to come out (normal mode/user mode): -1 normal -2 factorize now - good iteration/ NA -3 slight inaccuracy - refactorize - iteration done/ same but factor done -4 inaccuracy - refactorize - no iteration/ NA -5 something flagged - go round again/ pivot not possible +2 looks unbounded +3 max iterations (iteration done)

With solveType_ ==2 this should Pivot in a variable and choose an outgoing one. Assumes primal feasible - will not go through a bound. Returns step length in theta Returns ray in ray_

Definition at line 1930 of file ClpSimplexPrimal.cpp.

References CoinIndexedVector::checkClear(), ClpNonLinearCost::checkInfeasibilities(), CoinIndexedVector::clear(), clearAll(), ClpSimplexProgress::clearBadTimes(), CoinIndexedVector::denseVector(), CoinIndexedVector::getIndices(), ClpSimplex::housekeeping(), CoinIndexedVector::insert(), ClpSimplex::isColumn(), CoinMessageHandler::message(), primalRay(), primalRow(), ClpSimplex::sequenceWithin(), ClpSimplex::setFlagged(), ClpNonLinearCost::setOne(), ClpNonLinearCost::setOneOutgoing(), statusOfProblemInPrimal(), ClpMatrixBase::transposeTimes(), ClpSimplex::unpack(), ClpSimplex::unpackPacked(), updatePrimalsInPrimal(), and ClpPrimalColumnPivot::updateWeights().

Referenced by whileIterating().

01931 {
01932 
01933   bool roundAgain=true;
01934   int returnCode=-1;
01935 
01936   // loop round if user setting and doing refactorization
01937   while (roundAgain) {
01938     roundAgain=false;
01939     returnCode=-1;
01940     pivotRow_=-1;
01941     sequenceOut_=-1;
01942     rowArray_[1]->clear();
01943 #if 0
01944     {
01945       int seq[]={612,643};
01946       int k;
01947       for (k=0;k<sizeof(seq)/sizeof(int);k++) {
01948         int iSeq=seq[k];
01949         if (getColumnStatus(iSeq)!=basic) {
01950           double djval;
01951           double * work;
01952           int number;
01953           int * which;
01954           
01955           int iIndex;
01956           unpack(rowArray_[1],iSeq);
01957           factorization_->updateColumn(rowArray_[2],rowArray_[1]);
01958           djval = cost_[iSeq];
01959           work=rowArray_[1]->denseVector();
01960           number=rowArray_[1]->getNumElements();
01961           which=rowArray_[1]->getIndices();
01962           
01963           for (iIndex=0;iIndex<number;iIndex++) {
01964             
01965             int iRow = which[iIndex];
01966             double alpha = work[iRow];
01967             int iPivot=pivotVariable_[iRow];
01968             djval -= alpha*cost_[iPivot];
01969           }
01970           double comp = 1.0e-8 + 1.0e-7*(max(fabs(dj_[iSeq]),fabs(djval)));
01971           if (fabs(djval-dj_[iSeq])>comp)
01972             printf("Bad dj %g for %d - true is %g\n",
01973                    dj_[iSeq],iSeq,djval);
01974           assert (fabs(djval)<1.0e-3||djval*dj_[iSeq]>0.0);
01975           rowArray_[1]->clear();
01976         }
01977       }
01978     }
01979 #endif
01980         
01981     // we found a pivot column
01982     // update the incoming column
01983     unpackPacked(rowArray_[1]);
01984     // save reduced cost
01985     double saveDj = dualIn_;
01986     factorization_->updateColumnFT(rowArray_[2],rowArray_[1]);
01987     // do ratio test and re-compute dj
01988     primalRow(rowArray_[1],rowArray_[3],rowArray_[2],rowArray_[0],
01989               ifValuesPass);
01990     if (ifValuesPass) {
01991       saveDj=dualIn_;
01992       if (pivotRow_==-1||(pivotRow_>=0&&fabs(alpha_)<1.0e-5)) {
01993         if(fabs(dualIn_)<1.0e2*dualTolerance_) {
01994           // try other way
01995           directionIn_=-directionIn_;
01996           primalRow(rowArray_[1],rowArray_[3],rowArray_[2],rowArray_[0],
01997                     0);
01998         }
01999         if (pivotRow_==-1||(pivotRow_>=0&&fabs(alpha_)<1.0e-5)) {
02000           if (solveType_==1) {
02001             // reject it
02002             char x = isColumn(sequenceIn_) ? 'C' :'R';
02003             handler_->message(CLP_SIMPLEX_FLAG,messages_)
02004               <<x<<sequenceWithin(sequenceIn_)
02005               <<CoinMessageEol;
02006             setFlagged(sequenceIn_);
02007             progress_->clearBadTimes();
02008             lastBadIteration_ = numberIterations_; // say be more cautious
02009             clearAll();
02010             pivotRow_=-1;
02011           }
02012           returnCode=-5;
02013           break;
02014         }
02015       }
02016     }
02017     double checkValue=1.0e-2;
02018     if (largestDualError_>1.0e-5)
02019       checkValue=1.0e-1;
02020     if (solveType_==1&&((saveDj*dualIn_<1.0e-20&&!ifValuesPass)||
02021         fabs(saveDj-dualIn_)>checkValue*(1.0+fabs(saveDj)))) {
02022       handler_->message(CLP_PRIMAL_DJ,messages_)
02023         <<saveDj<<dualIn_
02024         <<CoinMessageEol;
02025       if(lastGoodIteration_ != numberIterations_) {
02026         clearAll();
02027         pivotRow_=-1; // say no weights update
02028         returnCode=-4;
02029         if(lastGoodIteration_+1 == numberIterations_) {
02030           // not looking wonderful - try cleaning bounds
02031           // put non-basics to bounds in case tolerance moved
02032           nonLinearCost_->checkInfeasibilities(0.0);
02033         }
02034         sequenceOut_=-1;
02035         break;
02036       } else {
02037         // take on more relaxed criterion
02038         if (saveDj*dualIn_<1.0e-20||
02039             fabs(saveDj-dualIn_)>2.0e-1*(1.0+fabs(dualIn_))) {
02040           // need to reject something
02041           char x = isColumn(sequenceIn_) ? 'C' :'R';
02042           handler_->message(CLP_SIMPLEX_FLAG,messages_)
02043             <<x<<sequenceWithin(sequenceIn_)
02044             <<CoinMessageEol;
02045           setFlagged(sequenceIn_);
02046           progress_->clearBadTimes();
02047           lastBadIteration_ = numberIterations_; // say be more cautious
02048           clearAll();
02049           pivotRow_=-1;
02050           returnCode=-5;
02051           sequenceOut_=-1;
02052           break;
02053         }
02054       }
02055     }
02056     if (pivotRow_>=0) {
02057       if (solveType_==2) {
02058         // **** Coding for user interface
02059         // do ray
02060         primalRay(rowArray_[1]);
02061         // update duals
02062         if (pivotRow_>=0) {
02063           // as packed need to find pivot row
02064           //assert (rowArray_[1]->packedMode());
02065           //int i;
02066           
02067           //alpha_ = rowArray_[1]->denseVector()[pivotRow_];
02068           assert (fabs(alpha_)>1.0e-8);
02069           double multiplier = dualIn_/alpha_;
02070           rowArray_[0]->insert(pivotRow_,multiplier);
02071           factorization_->updateColumnTranspose(rowArray_[2],rowArray_[0]);
02072           // put row of tableau in rowArray[0] and columnArray[0]
02073           matrix_->transposeTimes(this,-1.0,
02074                                   rowArray_[0],columnArray_[1],columnArray_[0]);
02075           // update column djs
02076           int i;
02077           int * index = columnArray_[0]->getIndices();
02078           int number = columnArray_[0]->getNumElements();
02079           double * element = columnArray_[0]->denseVector();
02080           for (i=0;i<number;i++) {
02081             int ii = index[i];
02082             dj_[ii] += element[ii];
02083             element[ii]=0.0;
02084           }
02085           columnArray_[0]->setNumElements(0);
02086           // and row djs
02087           index = rowArray_[0]->getIndices();
02088           number = rowArray_[0]->getNumElements();
02089           element = rowArray_[0]->denseVector();
02090           for (i=0;i<number;i++) {
02091             int ii = index[i];
02092             dj_[ii+numberColumns_] += element[ii];
02093             dual_[ii] = dj_[ii+numberColumns_];
02094             element[ii]=0.0;
02095           }
02096           rowArray_[0]->setNumElements(0);
02097           // check incoming
02098           assert (fabs(dj_[sequenceIn_])<1.0e-6);
02099         }
02100       }
02101       // if stable replace in basis
02102       int updateStatus = factorization_->replaceColumn(rowArray_[2],
02103                                                        pivotRow_,
02104                                                        alpha_);
02105       // if no pivots, bad update but reasonable alpha - take and invert
02106       if (updateStatus==2&&
02107           lastGoodIteration_==numberIterations_&&fabs(alpha_)>1.0e-5)
02108         updateStatus=4;
02109       if (updateStatus==1||updateStatus==4) {
02110         // slight error
02111         if (factorization_->pivots()>5||updateStatus==4) {
02112           returnCode=-3;
02113         }
02114       } else if (updateStatus==2) {
02115         // major error
02116         // better to have small tolerance even if slower
02117         factorization_->zeroTolerance(1.0e-15);
02118         int maxFactor = factorization_->maximumPivots();
02119         if (maxFactor>10) {
02120           if (forceFactorization_<0)
02121             forceFactorization_= maxFactor;
02122           forceFactorization_ = max (1,(forceFactorization_>>1));
02123         } 
02124         // later we may need to unwind more e.g. fake bounds
02125         if(lastGoodIteration_ != numberIterations_) {
02126           clearAll();
02127           pivotRow_=-1;
02128           if (solveType_==1) {
02129             returnCode=-4;
02130             break;
02131           } else {
02132             // user in charge - re-factorize
02133             int lastCleaned;
02134             ClpSimplexProgress dummyProgress;
02135             if (saveStatus_)
02136               statusOfProblemInPrimal(lastCleaned,1,&dummyProgress,true);
02137             else
02138               statusOfProblemInPrimal(lastCleaned,0,&dummyProgress,true);
02139             roundAgain=true;
02140             continue;
02141           }
02142         } else {
02143           // need to reject something
02144           if (solveType_==1) {
02145             char x = isColumn(sequenceIn_) ? 'C' :'R';
02146             handler_->message(CLP_SIMPLEX_FLAG,messages_)
02147               <<x<<sequenceWithin(sequenceIn_)
02148               <<CoinMessageEol;
02149             setFlagged(sequenceIn_);
02150             progress_->clearBadTimes();
02151           }
02152           lastBadIteration_ = numberIterations_; // say be more cautious
02153           clearAll();
02154           pivotRow_=-1;
02155           sequenceOut_=-1;
02156           returnCode = -5;
02157           break;
02158 
02159         }
02160       } else if (updateStatus==3) {
02161         // out of memory
02162         // increase space if not many iterations
02163         if (factorization_->pivots()<
02164             0.5*factorization_->maximumPivots()&&
02165             factorization_->pivots()<200)
02166           factorization_->areaFactor(
02167                                      factorization_->areaFactor() * 1.1);
02168         returnCode =-2; // factorize now
02169       } else if (updateStatus==5) {
02170         problemStatus_=-2; // factorize now
02171       }
02172       // here do part of steepest - ready for next iteration
02173       if (!ifValuesPass)
02174         primalColumnPivot_->updateWeights(rowArray_[1]);
02175     } else {
02176       if (pivotRow_==-1) {
02177         // no outgoing row is valid
02178         rowArray_[0]->clear();
02179         if (!factorization_->pivots()) {
02180           returnCode = 2; //say looks unbounded
02181           // do ray
02182           primalRay(rowArray_[1]);
02183         } else if (solveType_==2) {
02184           // refactorize
02185           int lastCleaned;
02186           ClpSimplexProgress dummyProgress;
02187           if (saveStatus_)
02188             statusOfProblemInPrimal(lastCleaned,1,&dummyProgress,true);
02189           else
02190             statusOfProblemInPrimal(lastCleaned,0,&dummyProgress,true);
02191           roundAgain=true;
02192           continue;
02193         } else {
02194           returnCode = 4; //say looks unbounded but has iterated
02195         }
02196         break;
02197       } else {
02198         // flipping from bound to bound
02199       }
02200     }
02201 
02202     
02203     // update primal solution
02204     
02205     double objectiveChange=0.0;
02206     // after this rowArray_[1] is not empty - used to update djs
02207     updatePrimalsInPrimal(rowArray_[1],theta_, objectiveChange,ifValuesPass);
02208     
02209     double oldValue = valueIn_;
02210     if (directionIn_==-1) {
02211       // as if from upper bound
02212       if (sequenceIn_!=sequenceOut_) {
02213         // variable becoming basic
02214         valueIn_ -= fabs(theta_);
02215       } else {
02216         valueIn_=lowerIn_;
02217       }
02218     } else {
02219       // as if from lower bound
02220       if (sequenceIn_!=sequenceOut_) {
02221         // variable becoming basic
02222         valueIn_ += fabs(theta_);
02223       } else {
02224         valueIn_=upperIn_;
02225       }
02226     }
02227     objectiveChange += dualIn_*(valueIn_-oldValue);
02228     // outgoing
02229     if (sequenceIn_!=sequenceOut_) {
02230       if (directionOut_>0) {
02231         valueOut_ = lowerOut_;
02232       } else {
02233         valueOut_ = upperOut_;
02234       }
02235       if(valueOut_<lower_[sequenceOut_]-primalTolerance_)
02236         valueOut_=lower_[sequenceOut_]-0.9*primalTolerance_;
02237       else if (valueOut_>upper_[sequenceOut_]+primalTolerance_)
02238         valueOut_=upper_[sequenceOut_]+0.9*primalTolerance_;
02239       // may not be exactly at bound and bounds may have changed
02240       // Make sure outgoing looks feasible
02241       directionOut_=nonLinearCost_->setOneOutgoing(sequenceOut_,valueOut_);
02242       solution_[sequenceOut_]=valueOut_;
02243     }
02244     // change cost and bounds on incoming if primal
02245     nonLinearCost_->setOne(sequenceIn_,valueIn_); 
02246     int whatNext=housekeeping(objectiveChange);
02247 
02248 #if 0
02249     if (numberIterations_==1148)
02250       whatNext=1;
02251     if (numberIterations_>1200)
02252     exit(0);
02253 #endif
02254     if (whatNext==1) {
02255         returnCode =-2; // refactorize
02256     } else if (whatNext==2) {
02257       // maximum iterations or equivalent
02258       returnCode=3;
02259     } else if(numberIterations_ == lastGoodIteration_
02260               + 2 * factorization_->maximumPivots()) {
02261       // done a lot of flips - be safe
02262       returnCode =-2; // refactorize
02263     }
02264   }
02265   if (solveType_==2&&(returnCode == -2||returnCode==-3)) {
02266     // refactorize here
02267     int lastCleaned;
02268     ClpSimplexProgress dummyProgress;
02269     if (saveStatus_)
02270       statusOfProblemInPrimal(lastCleaned,1,&dummyProgress,true);
02271     else
02272       statusOfProblemInPrimal(lastCleaned,0,&dummyProgress,true);
02273     if (problemStatus_==5) {
02274       printf("Singular basis\n");
02275       problemStatus_=-1;
02276       returnCode=5;
02277     }
02278   }
02279 #ifdef CLP_DEBUG
02280   {
02281     int i;
02282     // not [1] as may have information
02283     for (i=0;i<4;i++) {
02284       if (i!=1)
02285         rowArray_[i]->checkClear();
02286     }    
02287     for (i=0;i<2;i++) {
02288       columnArray_[i]->checkClear();
02289     }    
02290   }      
02291 #endif
02292   return returnCode;
02293 }

int ClpSimplexPrimal::primal int  ifValuesPass = 0  ) 
 

Primal algorithm

Method

It tries to be a single phase approach with a weight of 1.0 being given to getting optimal and a weight of infeasibilityCost_ being given to getting primal feasible. In this version I have tried to be clever in a stupid way. The idea of fake bounds in dual seems to work so the primal analogue would be that of getting bounds on reduced costs (by a presolve approach) and using these for being above or below feasible region. I decided to waste memory and keep these explicitly. This allows for non-linear costs! I have not tested non-linear costs but will be glad to do something if a reasonable example is provided.

The code is designed to take advantage of sparsity so arrays are seldom zeroed out from scratch or gone over in their entirety. The only exception is a full scan to find incoming variable for Dantzig row choice. For steepest edge we keep an updated list of dual infeasibilities (actually squares). On easy problems we don't need full scan - just pick first reasonable. This method has not been coded.

One problem is how to tackle degeneracy and accuracy. At present I am using the modification of costs which I put in OSL and which was extended by Gill et al. I am still not sure whether we will also need explicit perturbation.

The flow of primal is three while loops as follows:

while (not finished) {

while (not clean solution) {

Factorize and/or clean up solution by changing bounds so primal feasible. If looks finished check fake primal bounds. Repeat until status is iterating (-1) or finished (0,1,2)

}

while (status==-1) {

Iterate until no pivot in or out or time to re-factorize.

Flow is:

choose pivot column (incoming variable). if none then we are primal feasible so looks as if done but we need to break and check bounds etc.

Get pivot column in tableau

Choose outgoing row. If we don't find one then we look primal unbounded so break and check bounds etc. (Also the pivot tolerance is larger after any iterations so that may be reason)

If we do find outgoing row, we may have to adjust costs to keep going forwards (anti-degeneracy). Check pivot will be stable and if unstable throw away iteration and break to re-factorize. If minor error re-factorize after iteration.

Update everything (this may involve changing bounds on variables to stay primal feasible.

}

}

TODO's (or maybe not)

At present we never check we are going forwards. I overdid that in OSL so will try and make a last resort.

Needs partial scan pivot in option.

May need other anti-degeneracy measures, especially if we try and use loose tolerances as a way to solve in fewer iterations.

I like idea of dynamic scaling. This gives opportunity to decouple different implications of scaling for accuracy, iteration count and feasibility tolerance.

Reimplemented from ClpSimplex.

Definition at line 99 of file ClpSimplexPrimal.cpp.

References ClpNonLinearCost::checkInfeasibilities(), CoinIndexedVector::clear(), ClpSimplex::ClpSimplex(), ClpSimplex::computeDuals(), ClpSimplex::createRim(), ClpSimplex::gutsOfSolution(), CoinMessageHandler::logLevel(), CoinMessageHandler::message(), ClpNonLinearCost::numberInfeasibilities(), ClpPrimalColumnPivot::numberSprintColumns(), ClpModel::objectiveValue(), ClpSimplex::originalModel(), perturb(), CoinMessageHandler::printing(), ClpMatrixBase::refresh(), ClpSimplex::restoreData(), ClpSimplex::saveData(), ClpNonLinearCost::setAverageTheta(), ClpSimplexProgress::startCheck(), ClpSimplex::startup(), statusOfProblemInPrimal(), ClpNonLinearCost::sumInfeasibilities(), ClpPrimalColumnPivot::switchOffSprint(), unflag(), and whileIterating().

Referenced by ClpSimplexPrimalQuadratic::makeQuadratic(), ClpSimplexPrimalQuadratic::primalQuadratic(), and ClpSimplexPrimalQuadratic::primalSLP().

00100 {
00101 
00102   /*
00103       Method
00104 
00105      It tries to be a single phase approach with a weight of 1.0 being
00106      given to getting optimal and a weight of infeasibilityCost_ being
00107      given to getting primal feasible.  In this version I have tried to
00108      be clever in a stupid way.  The idea of fake bounds in dual
00109      seems to work so the primal analogue would be that of getting
00110      bounds on reduced costs (by a presolve approach) and using
00111      these for being above or below feasible region.  I decided to waste
00112      memory and keep these explicitly.  This allows for non-linear
00113      costs!
00114 
00115      The code is designed to take advantage of sparsity so arrays are
00116      seldom zeroed out from scratch or gone over in their entirety.
00117      The only exception is a full scan to find incoming variable for 
00118      Dantzig row choice.  For steepest edge we keep an updated list 
00119      of dual infeasibilities (actually squares).  
00120      On easy problems we don't need full scan - just
00121      pick first reasonable.
00122 
00123      One problem is how to tackle degeneracy and accuracy.  At present
00124      I am using the modification of costs which I put in OSL and which was
00125      extended by Gill et al.  I am still not sure of the exact details.
00126 
00127      The flow of primal is three while loops as follows:
00128 
00129      while (not finished) {
00130 
00131        while (not clean solution) {
00132 
00133           Factorize and/or clean up solution by changing bounds so
00134           primal feasible.  If looks finished check fake primal bounds.
00135           Repeat until status is iterating (-1) or finished (0,1,2)
00136 
00137        }
00138 
00139        while (status==-1) {
00140 
00141          Iterate until no pivot in or out or time to re-factorize.
00142 
00143          Flow is:
00144 
00145          choose pivot column (incoming variable).  if none then
00146          we are primal feasible so looks as if done but we need to
00147          break and check bounds etc.
00148 
00149          Get pivot column in tableau
00150 
00151          Choose outgoing row.  If we don't find one then we look
00152          primal unbounded so break and check bounds etc.  (Also the
00153          pivot tolerance is larger after any iterations so that may be
00154          reason)
00155 
00156          If we do find outgoing row, we may have to adjust costs to
00157          keep going forwards (anti-degeneracy).  Check pivot will be stable
00158          and if unstable throw away iteration and break to re-factorize.
00159          If minor error re-factorize after iteration.
00160 
00161          Update everything (this may involve changing bounds on 
00162          variables to stay primal feasible.
00163 
00164        }
00165 
00166      }
00167 
00168      At present we never check we are going forwards.  I overdid that in
00169      OSL so will try and make a last resort.
00170 
00171      Needs partial scan pivot in option.
00172 
00173      May need other anti-degeneracy measures, especially if we try and use
00174      loose tolerances as a way to solve in fewer iterations.
00175 
00176      I like idea of dynamic scaling.  This gives opportunity to decouple
00177      different implications of scaling for accuracy, iteration count and
00178      feasibility tolerance.
00179 
00180   */
00181 
00182   algorithm_ = +1;
00183   //specialOptions_ |= 4;
00184 
00185   // save data
00186   ClpDataSave data = saveData();
00187   
00188   // Save so can see if doing after dual
00189   int initialStatus=problemStatus_;
00190   // initialize - maybe values pass and algorithm_ is +1
00191   if (!startup(ifValuesPass)) {
00192     
00193     // Set average theta
00194     nonLinearCost_->setAverageTheta(1.0e3);
00195     int lastCleaned=0; // last time objective or bounds cleaned up
00196     
00197     // Say no pivot has occurred (for steepest edge and updates)
00198     pivotRow_=-2;
00199     
00200     // This says whether to restore things etc
00201     int factorType=0;
00202     if (problemStatus_<0&&perturbation_<100) {
00203       perturb(0);
00204       // Can't get here if values pass
00205       assert (!ifValuesPass);
00206       gutsOfSolution(NULL,NULL);
00207       if (handler_->logLevel()>2) {
00208         handler_->message(CLP_SIMPLEX_STATUS,messages_)
00209           <<numberIterations_<<objectiveValue();
00210         handler_->printing(sumPrimalInfeasibilities_>0.0)
00211           <<sumPrimalInfeasibilities_<<numberPrimalInfeasibilities_;
00212         handler_->printing(sumDualInfeasibilities_>0.0)
00213           <<sumDualInfeasibilities_<<numberDualInfeasibilities_;
00214         handler_->printing(numberDualInfeasibilitiesWithoutFree_
00215                            <numberDualInfeasibilities_)
00216                              <<numberDualInfeasibilitiesWithoutFree_;
00217         handler_->message()<<CoinMessageEol;
00218       }
00219     }
00220     ClpSimplex * saveModel=NULL;
00221     int stopSprint=-1;
00222     int sprintPass=0;
00223     int reasonableSprintIteration=0;
00224     int lastSprintIteration=0;
00225     double lastObjectiveValue=COIN_DBL_MAX;
00226     // Start check for cycles
00227     progress_->startCheck();
00228     /*
00229       Status of problem:
00230       0 - optimal
00231       1 - infeasible
00232       2 - unbounded
00233       -1 - iterating
00234       -2 - factorization wanted
00235       -3 - redo checking without factorization
00236       -4 - looks infeasible
00237       -5 - looks unbounded
00238     */
00239     while (problemStatus_<0) {
00240       int iRow,iColumn;
00241       // clear
00242       for (iRow=0;iRow<4;iRow++) {
00243         rowArray_[iRow]->clear();
00244       }    
00245       
00246       for (iColumn=0;iColumn<2;iColumn++) {
00247         columnArray_[iColumn]->clear();
00248       }    
00249       
00250       // give matrix (and model costs and bounds a chance to be
00251       // refreshed (normally null)
00252       matrix_->refresh(this);
00253       // If getting nowhere - why not give it a kick
00254 #if 1
00255       if (perturbation_<101&&numberIterations_>2*(numberRows_+numberColumns_)
00256           &&initialStatus!=10) 
00257         perturb(1);
00258 #endif
00259       // If we have done no iterations - special
00260       if (lastGoodIteration_==numberIterations_&&factorType)
00261         factorType=3;
00262       if (saveModel) {
00263         // Doing sprint
00264         if (sequenceIn_<0||numberIterations_>=stopSprint) {
00265           problemStatus_=-1;
00266           originalModel(saveModel);
00267           saveModel=NULL;
00268           if (sequenceIn_<0&&numberIterations_<reasonableSprintIteration&&
00269               sprintPass>100)
00270             primalColumnPivot_->switchOffSprint();
00271           //lastSprintIteration=numberIterations_;
00272           printf("End small model\n");
00273         }
00274       }
00275           
00276       // may factorize, checks if problem finished
00277       statusOfProblemInPrimal(lastCleaned,factorType,progress_,true,saveModel);
00278       // See if sprint says redo beacuse of problems
00279       if (numberDualInfeasibilities_==-776) {
00280         // Need new set of variables
00281         problemStatus_=-1;
00282         originalModel(saveModel);
00283         saveModel=NULL;
00284         //lastSprintIteration=numberIterations_;
00285         printf("End small model after\n");
00286         statusOfProblemInPrimal(lastCleaned,factorType,progress_,true,saveModel);
00287       } 
00288       int numberSprintIterations=0;
00289       int numberSprintColumns = primalColumnPivot_->numberSprintColumns(numberSprintIterations);
00290       if (problemStatus_==777) {
00291         // problems so do one pass with normal
00292         problemStatus_=-1;
00293         originalModel(saveModel);
00294         saveModel=NULL;
00295         // Skip factorization
00296         //statusOfProblemInPrimal(lastCleaned,factorType,progress_,false,saveModel);
00297         statusOfProblemInPrimal(lastCleaned,factorType,progress_,true,saveModel);
00298       } else if (problemStatus_<0&&!saveModel&&numberSprintColumns&&firstFree_<0) {
00299         int numberSort=0;
00300         int numberFixed=0;
00301         int numberBasic=0;
00302         reasonableSprintIteration = numberIterations_ + 100;
00303         int * whichColumns = new int[numberColumns_];
00304         double * weight = new double[numberColumns_];
00305         int numberNegative=0;
00306         double sumNegative = 0.0;
00307         // now massage weight so all basic in plus good djs
00308         for (iColumn=0;iColumn<numberColumns_;iColumn++) {
00309           double dj = dj_[iColumn];
00310           switch(getColumnStatus(iColumn)) {
00311             
00312           case basic:
00313             dj = -1.0e50;
00314             numberBasic++;
00315             break;
00316           case atUpperBound:
00317             dj = -dj;
00318             break;
00319           case isFixed:
00320             dj=1.0e50;
00321             numberFixed++;
00322             break;
00323           case atLowerBound:
00324             dj = dj;
00325             break;
00326           case isFree:
00327             dj = -100.0*fabs(dj);
00328               break;
00329           case superBasic:
00330             dj = -100.0*fabs(dj);
00331             break;
00332           }
00333           if (dj<-dualTolerance_&&dj>-1.0e50) {
00334             numberNegative++;
00335             sumNegative -= dj;
00336           }
00337           weight[iColumn]=dj;
00338           whichColumns[iColumn] = iColumn;
00339         }
00340         handler_->message(CLP_SPRINT,messages_)
00341           <<sprintPass<<numberIterations_-lastSprintIteration<<objectiveValue()<<sumNegative
00342           <<numberNegative
00343           <<CoinMessageEol;
00344         sprintPass++;
00345         lastSprintIteration=numberIterations_;
00346         if (objectiveValue()*optimizationDirection_>lastObjectiveValue-1.0e-7&&sprintPass>5) {
00347           // switch off
00348           printf("Switching off sprint\n");
00349           primalColumnPivot_->switchOffSprint();
00350         } else {
00351           lastObjectiveValue = objectiveValue()*optimizationDirection_;
00352           // sort
00353           CoinSort_2(weight,weight+numberColumns_,whichColumns);
00354           numberSort = min(numberColumns_-numberFixed,numberBasic+numberSprintColumns);
00355           // Sort to make consistent ?
00356           std::sort(whichColumns,whichColumns+numberSort);
00357           saveModel = new ClpSimplex(this,numberSort,whichColumns);
00358           delete [] whichColumns;
00359           delete [] weight;
00360           // Skip factorization
00361           //statusOfProblemInPrimal(lastCleaned,factorType,progress_,false,saveModel);
00362           //statusOfProblemInPrimal(lastCleaned,factorType,progress_,true,saveModel);
00363           stopSprint = numberIterations_+numberSprintIterations;
00364           printf("Sprint with %d columns for %d iterations\n",
00365                  numberSprintColumns,numberSprintIterations);
00366         }
00367       }
00368       
00369       // Say good factorization
00370       factorType=1;
00371       
00372       // Say no pivot has occurred (for steepest edge and updates)
00373       pivotRow_=-2;
00374 
00375       // exit if victory declared
00376       if (problemStatus_>=0)
00377         break;
00378       
00379       // Iterate
00380       whileIterating(ifValuesPass);
00381     }
00382   }
00383   // if infeasible get real values
00384   if (problemStatus_==1) {
00385     infeasibilityCost_=0.0;
00386     createRim(7);
00387     nonLinearCost_->checkInfeasibilities(0.0);
00388     sumPrimalInfeasibilities_=nonLinearCost_->sumInfeasibilities();
00389     numberPrimalInfeasibilities_= nonLinearCost_->numberInfeasibilities();
00390     // and get good feasible duals
00391     computeDuals(NULL);
00392   }
00393   // clean up
00394   unflag();
00395   finish();
00396   restoreData(data);
00397   return problemStatus_;
00398 }

void ClpSimplexPrimal::primalColumn CoinIndexedVector updateArray,
CoinIndexedVector spareRow1,
CoinIndexedVector spareRow2,
CoinIndexedVector spareColumn1,
CoinIndexedVector spareColumn2
 

Chooses primal pivot column updateArray has cost updates (also use pivotRow_ from last iteration) Would be faster with separate region to scan and will have this (with square of infeasibility) when steepest For easy problems we can just choose one of the first columns we look at

Definition at line 1324 of file ClpSimplexPrimal.cpp.

References ClpNonLinearCost::changeDownInCost(), ClpNonLinearCost::changeUpInCost(), ClpSimplex::currentPrimalTolerance(), ClpNonLinearCost::lookBothWays(), ClpPrimalColumnPivot::pivotColumn(), and ClpNonLinearCost::setOne().

Referenced by ClpSimplexPrimalQuadratic::whileIterating(), and whileIterating().

01329 {
01330   sequenceIn_ = primalColumnPivot_->pivotColumn(updates,spareRow1,
01331                                                spareRow2,spareColumn1,
01332                                                spareColumn2);
01333   if (sequenceIn_>=0) {
01334     valueIn_=solution_[sequenceIn_];
01335     dualIn_=dj_[sequenceIn_];
01336     if (nonLinearCost_->lookBothWays()) {
01337       // double check 
01338       ClpSimplex::Status status = getStatus(sequenceIn_);
01339       
01340       switch(status) {
01341       case ClpSimplex::atUpperBound:
01342         if (dualIn_<0.0) {
01343           // move to other side
01344           printf("For %d U (%g, %g, %g) dj changed from %g",
01345                  sequenceIn_,lower_[sequenceIn_],solution_[sequenceIn_],
01346                  upper_[sequenceIn_],dualIn_);
01347           dualIn_ -= nonLinearCost_->changeUpInCost(sequenceIn_);
01348           printf(" to %g\n",dualIn_);
01349           nonLinearCost_->setOne(sequenceIn_,upper_[sequenceIn_]+2.0*currentPrimalTolerance());
01350           setStatus(sequenceIn_,ClpSimplex::atLowerBound);
01351         }
01352         break;
01353       case ClpSimplex::atLowerBound:
01354         if (dualIn_>0.0) {
01355           // move to other side
01356           printf("For %d L (%g, %g, %g) dj changed from %g",
01357                  sequenceIn_,lower_[sequenceIn_],solution_[sequenceIn_],
01358                  upper_[sequenceIn_],dualIn_);
01359           dualIn_ -= nonLinearCost_->changeDownInCost(sequenceIn_);
01360           printf(" to %g\n",dualIn_);
01361           nonLinearCost_->setOne(sequenceIn_,lower_[sequenceIn_]-2.0*currentPrimalTolerance());
01362           setStatus(sequenceIn_,ClpSimplex::atUpperBound);
01363         }
01364         break;
01365       default:
01366         break;
01367       }
01368     }
01369     lowerIn_=lower_[sequenceIn_];
01370     upperIn_=upper_[sequenceIn_];
01371     if (dualIn_>0.0)
01372       directionIn_ = -1;
01373     else 
01374       directionIn_ = 1;
01375   } else {
01376     sequenceIn_ = -1;
01377   }
01378 }

void ClpSimplexPrimal::primalRow CoinIndexedVector rowArray,
CoinIndexedVector rhsArray,
CoinIndexedVector spareArray,
CoinIndexedVector spareArray2,
int  valuesPass
 

Row array has pivot column This chooses pivot row. Rhs array is used for distance to next bound (for speed) For speed, we may need to go to a bucket approach when many variables go through bounds If valuesPass non-zero then compute dj for direction

Definition at line 949 of file ClpSimplexPrimal.cpp.

References ClpNonLinearCost::averageTheta(), ClpNonLinearCost::changeInCost(), CoinIndexedVector::clear(), CoinIndexedVector::denseVector(), CoinIndexedVector::getIndices(), CoinIndexedVector::getNumElements(), ClpNonLinearCost::goBackAll(), CoinMessageHandler::logLevel(), ClpNonLinearCost::nearest(), ClpSimplex::setActive(), ClpNonLinearCost::setAverageTheta(), CoinIndexedVector::setNumElements(), CoinIndexedVector::setPacked(), and ClpSimplex::solution().

Referenced by pivotResult().

00954 {
00955   //rowArray->scanAndPack();
00956   if (valuesPass) {
00957     dualIn_ = cost_[sequenceIn_];
00958 
00959     double * work=rowArray->denseVector();
00960     int number=rowArray->getNumElements();
00961     int * which=rowArray->getIndices();
00962 
00963     int iIndex;
00964     for (iIndex=0;iIndex<number;iIndex++) {
00965       
00966       int iRow = which[iIndex];
00967       double alpha = work[iIndex];
00968       int iPivot=pivotVariable_[iRow];
00969       dualIn_ -= alpha*cost_[iPivot];
00970     }
00971     // determine direction here
00972     if (dualIn_<-dualTolerance_) {
00973       directionIn_=1;
00974     } else if (dualIn_>dualTolerance_) {
00975       directionIn_=-1;
00976     } else {
00977       // towards nearest bound
00978       if (valueIn_-lowerIn_<upperIn_-valueIn_) {
00979         directionIn_=-1;
00980         dualIn_=dualTolerance_;
00981       } else {
00982         directionIn_=1;
00983         dualIn_=-dualTolerance_;
00984       }
00985     }
00986   }
00987 
00988   // sequence stays as row number until end
00989   pivotRow_=-1;
00990   int numberRemaining=0;
00991 
00992   double totalThru=0.0; // for when variables flip
00993   double acceptablePivot=1.0e-7;
00994   if (factorization_->pivots())
00995     acceptablePivot=1.0e-5; // if we have iterated be more strict
00996   double bestEverPivot=acceptablePivot;
00997   int lastPivotRow = -1;
00998   double lastPivot=0.0;
00999   double lastTheta=1.0e50;
01000 
01001   // use spareArrays to put ones looked at in
01002   // First one is list of candidates
01003   // We could compress if we really know we won't need any more
01004   // Second array has current set of pivot candidates
01005   // with a backup list saved in double * part of indexed vector
01006 
01007   // pivot elements
01008   double * spare;
01009   // indices
01010   int * index;
01011   spareArray->clear();
01012   spare = spareArray->denseVector();
01013   index = spareArray->getIndices();
01014 
01015   // we also need somewhere for effective rhs
01016   double * rhs=rhsArray->denseVector();
01017   //int * indexRhs = rhsArray->getIndices();
01018   //int numberFlip=0; // Those which may change if flips
01019 
01020   /*
01021     First we get a list of possible pivots.  We can also see if the
01022     problem looks unbounded.
01023 
01024     At first we increase theta and see what happens.  We start
01025     theta at a reasonable guess.  If in right area then we do bit by bit.
01026     We save possible pivot candidates
01027 
01028    */
01029 
01030   // do first pass to get possibles 
01031   // We can also see if unbounded
01032 
01033   double * work=rowArray->denseVector();
01034   int number=rowArray->getNumElements();
01035   int * which=rowArray->getIndices();
01036 
01037   // we need to swap sign if coming in from ub
01038   double way = directionIn_;
01039   double maximumMovement;
01040   if (way>0.0) 
01041     maximumMovement = min(1.0e30,upperIn_-valueIn_);
01042   else
01043     maximumMovement = min(1.0e30,valueIn_-lowerIn_);
01044 
01045   double averageTheta = nonLinearCost_->averageTheta();
01046   double tentativeTheta = min(10.0*averageTheta,maximumMovement);
01047   double upperTheta = maximumMovement;
01048   if (tentativeTheta>0.5*maximumMovement)
01049     tentativeTheta=maximumMovement;
01050 
01051   double dualCheck = fabs(dualIn_);
01052   // but make a bit more pessimistic
01053   dualCheck=max(dualCheck-100.0*dualTolerance_,0.99*dualCheck);
01054 
01055   int iIndex;
01056   bool gotList=false;
01057   int pivotOne=-1;
01058   while (!gotList) {
01059     pivotOne=-1;
01060     totalThru=0.0;
01061     // We also re-compute reduced cost
01062     numberRemaining=0;
01063     dualIn_ = cost_[sequenceIn_];
01064     double tolerance = primalTolerance_*1.002;
01065     for (iIndex=0;iIndex<number;iIndex++) {
01066 
01067       int iRow = which[iIndex];
01068       double alpha = work[iIndex];
01069       int iPivot=pivotVariable_[iRow];
01070       dualIn_ -= alpha*cost_[iPivot];
01071       alpha *= way;
01072       double oldValue = solution_[iPivot];
01073       // get where in bound sequence
01074       if (alpha>0.0) {
01075         // basic variable going towards lower bound
01076         double bound = lower_[iPivot];
01077         oldValue -= bound;
01078       } else {
01079         // basic variable going towards upper bound
01080         double bound = upper_[iPivot];
01081         oldValue = bound-oldValue;
01082       }
01083       
01084       double value = oldValue-tentativeTheta*fabs(alpha);
01085       assert (oldValue>=-tolerance);
01086       if (value<=tolerance) {
01087         value=oldValue-upperTheta*fabs(alpha);
01088         if (value<-primalTolerance_&&fabs(alpha)>=acceptablePivot) {
01089           upperTheta = (oldValue+primalTolerance_)/fabs(alpha);
01090           pivotOne=numberRemaining;
01091         }
01092         // add to list
01093         spare[numberRemaining]=alpha;
01094         rhs[numberRemaining]=oldValue;
01095         index[numberRemaining++]=iRow;
01096         totalThru += fabs(alpha);
01097         setActive(iRow);
01098         //} else if (value<primalTolerance_*1.002) {
01099         // May change if is a flip
01100         //indexRhs[numberFlip++]=iRow;
01101       }
01102     }
01103     if (upperTheta<maximumMovement&&totalThru*infeasibilityCost_>=1.0001*dualCheck) {
01104       // Can pivot here
01105       gotList=true;
01106     } else if (tentativeTheta<maximumMovement) {
01107       //printf("Going round with average theta of %g\n",averageTheta);
01108       tentativeTheta=maximumMovement;
01109     } else {
01110       gotList=true;
01111     }
01112   }
01113   totalThru=0.0;
01114   // we need to keep where rhs non-zeros are
01115   int numberInRhs=numberRemaining;
01116   memcpy(rhsArray->getIndices(),index,numberInRhs*sizeof(int));
01117   rhsArray->setNumElements(numberInRhs);
01118   rhsArray->setPacked();
01119 
01120   theta_=maximumMovement;
01121 
01122   bool goBackOne = false;
01123 
01124   //printf("%d remain out of %d\n",numberRemaining,number);
01125   int iTry=0;
01126 #define MAXTRY 1000
01127   if (numberRemaining&&upperTheta<maximumMovement) {
01128     // First check if previously chosen one will work
01129     if (pivotOne>=0&&0) {
01130       double thruCost = infeasibilityCost_*fabs(spare[pivotOne]);
01131       if (thruCost>=0.99*fabs(dualIn_))
01132         printf("Could pivot on %d as change %g dj %g\n",
01133                index[pivotOne],thruCost,dualIn_);
01134       double alpha = spare[pivotOne];
01135       double oldValue = rhs[pivotOne];
01136       theta_ = oldValue/fabs(alpha);
01137       pivotRow_=pivotOne;
01138       // Stop loop
01139       iTry=MAXTRY;
01140     }
01141 
01142     // first get ratio with tolerance
01143     for ( ;iTry<MAXTRY;iTry++) {
01144       
01145       upperTheta=maximumMovement;
01146       int iBest=-1;
01147       for (iIndex=0;iIndex<numberRemaining;iIndex++) {
01148         
01149         double alpha = fabs(spare[iIndex]);
01150         double oldValue = rhs[iIndex];
01151         double value = oldValue-upperTheta*alpha;
01152         
01153         if (value<-primalTolerance_ && alpha>=acceptablePivot) {
01154           upperTheta = (oldValue+primalTolerance_)/alpha;
01155           iBest=iIndex; // just in case weird numbers
01156         }
01157       }
01158       
01159       // now look at best in this lot
01160       double bestPivot=acceptablePivot;
01161       pivotRow_=-1;
01162       for (iIndex=0;iIndex<numberRemaining;iIndex++) {
01163         
01164         int iRow = index[iIndex];
01165         double alpha = spare[iIndex];
01166         double oldValue = rhs[iIndex];
01167         double value = oldValue-upperTheta*fabs(alpha);
01168         
01169         if (value<=0||iBest==iIndex) {
01170           // how much would it cost to go thru and modify bound
01171           totalThru += nonLinearCost_->changeInCost(pivotVariable_[iRow],alpha,rhs[iIndex]);
01172           setActive(iRow);
01173           if (fabs(alpha)>bestPivot) {
01174             bestPivot=fabs(alpha);
01175             theta_ = oldValue/bestPivot;
01176             pivotRow_=iIndex;
01177           }
01178         }
01179       }
01180       if (bestPivot<0.1*bestEverPivot&&
01181           bestEverPivot>1.0e-6&& bestPivot<1.0e-3) {
01182         // back to previous one
01183         goBackOne = true;
01184         break;
01185       } else if (pivotRow_==-1&&upperTheta>largeValue_) {
01186         if (lastPivot>acceptablePivot) {
01187           // back to previous one
01188           goBackOne = true;
01189         } else {
01190           // can only get here if all pivots so far too small
01191         }
01192         break;
01193       } else if (totalThru>=dualCheck) {
01194         break; // no point trying another loop
01195       } else {
01196         lastPivotRow=pivotRow_;
01197         lastTheta = theta_;
01198         if (bestPivot>bestEverPivot)
01199           bestEverPivot=bestPivot;
01200       }
01201     }
01202     // can get here without pivotRow_ set but with lastPivotRow
01203     if (goBackOne||(pivotRow_<0&&lastPivotRow>=0)) {
01204       // back to previous one
01205       pivotRow_=lastPivotRow;
01206       theta_ = lastTheta;
01207     }
01208   } else {
01209     // mark ones which may move
01210     //for (int i=0;i<numberFlip;i++) {
01211     //int iRow= indexRhs[i];
01212     //setActive(iRow);
01213     //}
01214   }
01215   //if (iTry>50)
01216   //printf("** %d tries\n",iTry);
01217   if (pivotRow_>=0) {
01218     int position=pivotRow_; // position in list
01219     pivotRow_=index[position];
01220     //alpha_ = work[pivotRow_];
01221     alpha_ = way*spare[position];
01222     // translate to sequence
01223     sequenceOut_ = pivotVariable_[pivotRow_];
01224     valueOut_ = solution(sequenceOut_);
01225     lowerOut_=lower_[sequenceOut_];
01226     upperOut_=upper_[sequenceOut_];
01227 #define MINIMUMTHETA 1.0e-12
01228     // Movement should be minimum for anti-degeneracy - unless
01229     // fixed variable out
01230     double minimumTheta;
01231     if (upperOut_>lowerOut_)
01232       minimumTheta=MINIMUMTHETA;
01233     else
01234       minimumTheta=0.0;
01235     // will we need to increase tolerance
01236     //#define CLP_DEBUG
01237 #ifdef CLP_DEBUG
01238     bool found=false;
01239 #endif
01240     double largestInfeasibility = primalTolerance_;
01241     if (theta_<minimumTheta&&(specialOptions_&4)==0&&!valuesPass) {
01242       theta_=minimumTheta;
01243       for (iIndex=0;iIndex<numberRemaining-numberRemaining;iIndex++) {
01244         largestInfeasibility = max (largestInfeasibility,
01245                                     -(rhs[iIndex]-fabs(spare[iIndex])*theta_));
01246       }
01247 #define CLP_DEBUG
01248 #ifdef CLP_DEBUG
01249       if (largestInfeasibility>primalTolerance_&&(handler_->logLevel()&32)>-1)
01250         printf("Primal tolerance increased from %g to %g\n",
01251                primalTolerance_,largestInfeasibility);
01252 #endif
01253 #undef CLP_DEBUG
01254       primalTolerance_ = max(primalTolerance_,largestInfeasibility);
01255     }
01256     // Need to look at all in some cases
01257     if (theta_>tentativeTheta) {
01258       for (iIndex=0;iIndex<number;iIndex++) 
01259         setActive(which[iIndex]);
01260     }
01261     if (way<0.0) 
01262       theta_ = - theta_;
01263     double newValue = valueOut_ - theta_*alpha_;
01264     // If  4 bit set - Force outgoing variables to exact bound (primal)
01265     if (alpha_*way<0.0) {
01266       directionOut_=-1;      // to upper bound
01267       if (fabs(theta_)>1.0e-6||(specialOptions_&4)!=0) {
01268         upperOut_ = nonLinearCost_->nearest(sequenceOut_,newValue);
01269       } else {
01270           upperOut_ = newValue;
01271       }
01272     } else {
01273       directionOut_=1;      // to lower bound
01274       if (fabs(theta_)>1.0e-6||(specialOptions_&4)!=0) {
01275         lowerOut_ = nonLinearCost_->nearest(sequenceOut_,newValue);
01276       } else {
01277         lowerOut_ = newValue;
01278       }
01279     }
01280     dualOut_ = reducedCost(sequenceOut_);
01281   } else if (maximumMovement<1.0e20) {
01282     // flip
01283     pivotRow_ = -2; // so we can tell its a flip
01284     sequenceOut_ = sequenceIn_;
01285     valueOut_ = valueIn_;
01286     dualOut_ = dualIn_;
01287     lowerOut_ = lowerIn_;
01288     upperOut_ = upperIn_;
01289     alpha_ = 0.0;
01290     if (way<0.0) {
01291       directionOut_=1;      // to lower bound
01292       theta_ = lowerOut_ - valueOut_;
01293     } else {
01294       directionOut_=-1;      // to upper bound
01295       theta_ = upperOut_ - valueOut_;
01296     }
01297   }
01298 
01299   double theta1 = max(theta_,1.0e-12);
01300   double theta2 = numberIterations_*nonLinearCost_->averageTheta();
01301   // Set average theta
01302   nonLinearCost_->setAverageTheta((theta1+theta2)/((double) (numberIterations_+1)));
01303   //if (numberIterations_%1000==0)
01304   //printf("average theta is %g\n",nonLinearCost_->averageTheta());
01305 
01306   // clear arrays
01307 
01308   memset(spare,0,numberRemaining*sizeof(double));
01309 
01310   // put back original bounds etc
01311   nonLinearCost_->goBackAll(rhsArray);
01312 
01313   rhsArray->clear();
01314 
01315 }

void ClpSimplexPrimal::statusOfProblemInPrimal int &  lastCleaned,
int  type,
ClpSimplexProgress progress,
bool  doFactorization,
ClpSimplex saveModel = NULL
 

Refactorizes if necessary Checks if finished. Updates status. lastCleaned refers to iteration at which some objective/feasibility cleaning too place.

type - 0 initial so set up save arrays etc

  • 1 normal -if good update save
  • 2 restoring from saved saveModel is normally NULL but may not be if doing Sprint

Definition at line 548 of file ClpSimplexPrimal.cpp.

References alwaysOptimal(), ClpSimplexProgress::badTimes(), ClpNonLinearCost::checkInfeasibilities(), ClpSimplex::createRim(), ClpSimplex::dualFeasible(), ClpSimplexProgress::endOddState(), ClpNonLinearCost::feasibleReportCost(), ClpSimplex::gutsOfSolution(), ClpSimplexProgress::lastIterationNumber(), ClpSimplexProgress::lastObjective(), ClpPrimalColumnPivot::looksOptimal(), ClpSimplexProgress::looping(), CoinMessageHandler::message(), ClpSimplexProgress::newOddState(), ClpNonLinearCost::numberInfeasibilities(), ClpSimplexProgress::oddState(), ClpSimplex::primalFeasible(), CoinMessageHandler::printing(), ClpPrimalColumnPivot::saveWeights(), ClpNonLinearCost::sumInfeasibilities(), unflag(), unPerturb(), and ClpNonLinearCost::zapCosts().

Referenced by pivotResult(), and primal().

00552 {
00553   if (type==2) {
00554     // trouble - restore solution
00555     memcpy(status_ ,saveStatus_,(numberColumns_+numberRows_)*sizeof(char));
00556     memcpy(rowActivityWork_,savedSolution_+numberColumns_ ,
00557            numberRows_*sizeof(double));
00558     memcpy(columnActivityWork_,savedSolution_ ,
00559            numberColumns_*sizeof(double));
00560     forceFactorization_=1; // a bit drastic but ..
00561     pivotRow_=-1; // say no weights update
00562     changeMade_++; // say change made
00563   }
00564   int saveThreshold = factorization_->sparseThreshold();
00565   int tentativeStatus = problemStatus_;
00566   if (problemStatus_>-3||problemStatus_==-4) {
00567     // factorize
00568     // later on we will need to recover from singularities
00569     // also we could skip if first time
00570     // do weights
00571     // This may save pivotRow_ for use 
00572     if (doFactorization)
00573     primalColumnPivot_->saveWeights(this,1);
00574 
00575     if (type&&doFactorization) {
00576       // is factorization okay?
00577       if (internalFactorize(1)) {
00578         if (solveType_==2) {
00579           // say odd
00580           problemStatus_=5;
00581           return;
00582         }
00583 #if 1
00584         // switch off dense
00585         int saveDense = factorization_->denseThreshold();
00586         factorization_->setDenseThreshold(0);
00587         internalFactorize(2);
00588         factorization_->setDenseThreshold(saveDense);
00589 #else
00590 
00591         // no - restore previous basis
00592         assert (type==1);
00593         memcpy(status_ ,saveStatus_,(numberColumns_+numberRows_)*sizeof(char));
00594         memcpy(rowActivityWork_,savedSolution_+numberColumns_ ,
00595                numberRows_*sizeof(double));
00596         memcpy(columnActivityWork_,savedSolution_ ,
00597                numberColumns_*sizeof(double));
00598         forceFactorization_=1; // a bit drastic but ..
00599         type = 2;
00600         assert (internalFactorize(1)==0);
00601 #endif
00602         changeMade_++; // say change made
00603       }
00604     }
00605     if (problemStatus_!=-4)
00606       problemStatus_=-3;
00607   }
00608   // at this stage status is -3 or -5 if looks unbounded
00609   // get primal and dual solutions
00610   // put back original costs and then check
00611   createRim(4);
00612   gutsOfSolution(NULL,NULL,(firstFree_>=0));
00613   // Double check reduced costs if no action
00614   if (progress->lastIterationNumber(0)==numberIterations_) {
00615     if (primalColumnPivot_->looksOptimal()) {
00616       numberDualInfeasibilities_ = 0;
00617       sumDualInfeasibilities_ = 0.0;
00618     }
00619   }
00620   // Check if looping
00621   int loop;
00622   if (type!=2) 
00623     loop = progress->looping();
00624   else
00625     loop=-1;
00626   if (loop>=0) {
00627     if (!problemStatus_) {
00628       // declaring victory
00629       numberPrimalInfeasibilities_ = 0;
00630       sumPrimalInfeasibilities_ = 0.0;
00631     } else {
00632       problemStatus_ = loop; //exit if in loop 
00633       problemStatus_ = 10; // instead - try other algorithm
00634     }
00635     problemStatus_ = 10; // instead - try other algorithm
00636     return ;
00637   } else if (loop<-1) {
00638     // Is it time for drastic measures
00639     if (nonLinearCost_->numberInfeasibilities()&&progress->badTimes()>5&&
00640         progress->oddState()<10&&progress->oddState()>=0) {
00641       progress->newOddState();
00642       nonLinearCost_->zapCosts();
00643     }
00644     // something may have changed
00645     gutsOfSolution(NULL,NULL);
00646   }
00647   // If progress then reset costs
00648   if (loop==-1&&!nonLinearCost_->numberInfeasibilities()&&progress->oddState()<0) {
00649     createRim(4,false); // costs back
00650     delete nonLinearCost_;
00651     nonLinearCost_ = new ClpNonLinearCost(this);
00652     progress->endOddState();
00653     gutsOfSolution(NULL,NULL);
00654   }
00655   // Flag to say whether to go to dual to clean up
00656   bool goToDual=false;
00657   // really for free variables in
00658   //if((progressFlag_&2)!=0)
00659   //problemStatus_=-1;;
00660   progressFlag_ = 0; //reset progress flag
00661 
00662   handler_->message(CLP_SIMPLEX_STATUS,messages_)
00663     <<numberIterations_<<nonLinearCost_->feasibleReportCost();
00664   handler_->printing(nonLinearCost_->numberInfeasibilities()>0)
00665     <<nonLinearCost_->sumInfeasibilities()<<nonLinearCost_->numberInfeasibilities();
00666   handler_->printing(sumDualInfeasibilities_>0.0)
00667     <<sumDualInfeasibilities_<<numberDualInfeasibilities_;
00668   handler_->printing(numberDualInfeasibilitiesWithoutFree_
00669                      <numberDualInfeasibilities_)
00670                        <<numberDualInfeasibilitiesWithoutFree_;
00671   handler_->message()<<CoinMessageEol;
00672   if (!primalFeasible()) {
00673     nonLinearCost_->checkInfeasibilities(primalTolerance_);
00674     gutsOfSolution(NULL,NULL);
00675   }
00676   // we may wish to say it is optimal even if infeasible
00677   bool alwaysOptimal = (specialOptions_&1)!=0;
00678   // give code benefit of doubt
00679   if (sumOfRelaxedDualInfeasibilities_ == 0.0&&
00680       sumOfRelaxedPrimalInfeasibilities_ == 0.0) {
00681     // say optimal (with these bounds etc)
00682     numberDualInfeasibilities_ = 0;
00683     sumDualInfeasibilities_ = 0.0;
00684     numberPrimalInfeasibilities_ = 0;
00685     sumPrimalInfeasibilities_ = 0.0;
00686     // But check if in sprint
00687     if (originalModel) {
00688       // Carry on and re-do
00689       numberDualInfeasibilities_ = -776;
00690     }
00691   }
00692   // had ||(type==3&&problemStatus_!=-5) -- ??? why ????
00693   if (dualFeasible()||problemStatus_==-4) {
00694     if (nonLinearCost_->numberInfeasibilities()&&!alwaysOptimal) {
00695       //may need infeasiblity cost changed
00696       // we can see if we can construct a ray
00697       // make up a new objective
00698       double saveWeight = infeasibilityCost_;
00699       // save nonlinear cost as we are going to switch off costs
00700       ClpNonLinearCost * nonLinear = nonLinearCost_;
00701       // do twice to make sure Primal solution has settled
00702       // put non-basics to bounds in case tolerance moved
00703       // put back original costs
00704       createRim(4);
00705       nonLinearCost_->checkInfeasibilities(0.0);
00706       gutsOfSolution(NULL,NULL);
00707 
00708       infeasibilityCost_=1.0e100;
00709       // put back original costs
00710       createRim(4);
00711       nonLinearCost_->checkInfeasibilities(primalTolerance_);
00712       // may have fixed infeasibilities - double check
00713       if (nonLinearCost_->numberInfeasibilities()==0) {
00714         // carry on
00715         problemStatus_ = -1;
00716         infeasibilityCost_=saveWeight;
00717         nonLinearCost_->checkInfeasibilities(primalTolerance_);
00718       } else {
00719         nonLinearCost_=NULL;
00720         // scale
00721         int i;
00722         for (i=0;i<numberRows_+numberColumns_;i++) 
00723           cost_[i] *= 1.0e-95;
00724         gutsOfSolution(NULL,NULL);
00725         nonLinearCost_=nonLinear;
00726         infeasibilityCost_=saveWeight;
00727         if ((infeasibilityCost_>=1.0e18||
00728              numberDualInfeasibilities_==0)&&perturbation_==101) {
00729           goToDual=unPerturb(); // stop any further perturbation
00730           if (nonLinearCost_->sumInfeasibilities()>1.0e-1)
00731             goToDual=false;
00732           nonLinearCost_->checkInfeasibilities(primalTolerance_);
00733           numberDualInfeasibilities_=1; // carry on
00734           problemStatus_=-1;
00735         }
00736         if (infeasibilityCost_>=1.0e20||
00737             numberDualInfeasibilities_==0) {
00738           // we are infeasible - use as ray
00739           delete [] ray_;
00740           ray_ = new double [numberRows_];
00741           memcpy(ray_,dual_,numberRows_*sizeof(double));
00742           // and get feasible duals
00743           infeasibilityCost_=0.0;
00744           createRim(4);
00745           nonLinearCost_->checkInfeasibilities(primalTolerance_);
00746           gutsOfSolution(NULL,NULL);
00747           // so will exit
00748           infeasibilityCost_=1.0e30;
00749           // reset infeasibilities
00750           sumPrimalInfeasibilities_=nonLinearCost_->sumInfeasibilities();;
00751           numberPrimalInfeasibilities_=
00752             nonLinearCost_->numberInfeasibilities();
00753         }
00754         if (infeasibilityCost_<1.0e20) {
00755           infeasibilityCost_ *= 5.0;
00756           changeMade_++; // say change made
00757           handler_->message(CLP_PRIMAL_WEIGHT,messages_)
00758             <<infeasibilityCost_
00759             <<CoinMessageEol;
00760           // put back original costs and then check
00761           createRim(4);
00762           nonLinearCost_->checkInfeasibilities(0.0);
00763           gutsOfSolution(NULL,NULL);
00764           problemStatus_=-1; //continue
00765           goToDual=false;
00766         } else {
00767           // say infeasible
00768           problemStatus_ = 1;
00769         }
00770       }
00771     } else {
00772       // may be optimal
00773       if (perturbation_==101) {
00774         goToDual=unPerturb(); // stop any further perturbation
00775         lastCleaned=-1; // carry on
00776       }
00777       bool unflagged = unflag();
00778       if ( lastCleaned!=numberIterations_||unflagged) {
00779         handler_->message(CLP_PRIMAL_OPTIMAL,messages_)
00780           <<primalTolerance_
00781           <<CoinMessageEol;
00782         if (numberTimesOptimal_<4) {
00783           numberTimesOptimal_++;
00784           changeMade_++; // say change made
00785           if (numberTimesOptimal_==1) {
00786             // better to have small tolerance even if slower
00787             factorization_->zeroTolerance(1.0e-15);
00788           }
00789           lastCleaned=numberIterations_;
00790           if (primalTolerance_!=dblParam_[ClpPrimalTolerance])
00791             handler_->message(CLP_PRIMAL_ORIGINAL,messages_)
00792               <<CoinMessageEol;
00793           double oldTolerance = primalTolerance_;
00794           primalTolerance_=dblParam_[ClpPrimalTolerance];
00795 #if 0
00796           double * xcost = new double[numberRows_+numberColumns_];
00797           double * xlower = new double[numberRows_+numberColumns_];
00798           double * xupper = new double[numberRows_+numberColumns_];
00799           double * xdj = new double[numberRows_+numberColumns_];
00800           double * xsolution = new double[numberRows_+numberColumns_];
00801           memcpy(xcost,cost_,(numberRows_+numberColumns_)*sizeof(double));
00802           memcpy(xlower,lower_,(numberRows_+numberColumns_)*sizeof(double));
00803           memcpy(xupper,upper_,(numberRows_+numberColumns_)*sizeof(double));
00804           memcpy(xdj,dj_,(numberRows_+numberColumns_)*sizeof(double));
00805           memcpy(xsolution,solution_,(numberRows_+numberColumns_)*sizeof(double));
00806 #endif
00807           // put back original costs and then check
00808           createRim(4);
00809           nonLinearCost_->checkInfeasibilities(oldTolerance);
00810 #if 0
00811           int i;
00812           for (i=0;i<numberRows_+numberColumns_;i++) {
00813             if (cost_[i]!=xcost[i])
00814               printf("** %d old cost %g new %g sol %g\n",
00815                      i,xcost[i],cost_[i],solution_[i]);
00816             if (lower_[i]!=xlower[i])
00817               printf("** %d old lower %g new %g sol %g\n",
00818                      i,xlower[i],lower_[i],solution_[i]);
00819             if (upper_[i]!=xupper[i])
00820               printf("** %d old upper %g new %g sol %g\n",
00821                      i,xupper[i],upper_[i],solution_[i]);
00822             if (dj_[i]!=xdj[i])
00823               printf("** %d old dj %g new %g sol %g\n",
00824                      i,xdj[i],dj_[i],solution_[i]);
00825             if (solution_[i]!=xsolution[i])
00826               printf("** %d old solution %g new %g sol %g\n",
00827                      i,xsolution[i],solution_[i],solution_[i]);
00828           }
00829           delete [] xcost;
00830           delete [] xupper;
00831           delete [] xlower;
00832           delete [] xdj;
00833           delete [] xsolution;
00834 #endif
00835           gutsOfSolution(NULL,NULL);
00836           if (sumOfRelaxedDualInfeasibilities_ == 0.0&&
00837               sumOfRelaxedPrimalInfeasibilities_ == 0.0) {
00838             // say optimal (with these bounds etc)
00839             numberDualInfeasibilities_ = 0;
00840             sumDualInfeasibilities_ = 0.0;
00841             numberPrimalInfeasibilities_ = 0;
00842             sumPrimalInfeasibilities_ = 0.0;
00843           }
00844           if (dualFeasible()&&!nonLinearCost_->numberInfeasibilities()&&lastCleaned>=0)
00845             problemStatus_=0;
00846           else
00847             problemStatus_ = -1;
00848         } else {
00849           problemStatus_=0; // optimal
00850           if (lastCleaned<numberIterations_) {
00851             handler_->message(CLP_SIMPLEX_GIVINGUP,messages_)
00852               <<CoinMessageEol;
00853           }
00854         }
00855       } else {
00856         problemStatus_=0; // optimal
00857       }
00858     }
00859   } else {
00860     // see if looks unbounded
00861     if (problemStatus_==-5) {
00862       if (nonLinearCost_->numberInfeasibilities()) {
00863         if (infeasibilityCost_>1.0e18&&perturbation_==101) {
00864           // back off weight
00865           infeasibilityCost_ = 1.0e13;
00866           goToDual=unPerturb(); // stop any further perturbation
00867         }
00868         //we need infeasiblity cost changed
00869         if (infeasibilityCost_<1.0e20) {
00870           infeasibilityCost_ *= 5.0;
00871           changeMade_++; // say change made
00872           handler_->message(CLP_PRIMAL_WEIGHT,messages_)
00873             <<infeasibilityCost_
00874             <<CoinMessageEol;
00875           // put back original costs and then check
00876           createRim(4);
00877           gutsOfSolution(NULL,NULL);
00878           problemStatus_=-1; //continue
00879         } else {
00880           // say unbounded
00881           problemStatus_ = 2;
00882         }
00883       } else {
00884         // say unbounded
00885         problemStatus_ = 2;
00886       } 
00887     } else {
00888       if(type==3&&problemStatus_!=-5)
00889         unflag(); // odd
00890       // carry on
00891       problemStatus_ = -1;
00892     }
00893   }
00894   if (type==0||type==1) {
00895     if (type!=1||!saveStatus_) {
00896       // create save arrays
00897       delete [] saveStatus_;
00898       delete [] savedSolution_;
00899       saveStatus_ = new unsigned char [numberRows_+numberColumns_];
00900       savedSolution_ = new double [numberRows_+numberColumns_];
00901     }
00902     // save arrays
00903     memcpy(saveStatus_,status_,(numberColumns_+numberRows_)*sizeof(char));
00904     memcpy(savedSolution_+numberColumns_ ,rowActivityWork_,
00905            numberRows_*sizeof(double));
00906     memcpy(savedSolution_ ,columnActivityWork_,numberColumns_*sizeof(double));
00907   }
00908   if (doFactorization) {
00909     // restore weights (if saved) - also recompute infeasibility list
00910     if (tentativeStatus>-3) 
00911       primalColumnPivot_->saveWeights(this,(type <2) ? 2 : 4);
00912     else
00913       primalColumnPivot_->saveWeights(this,3);
00914     if (saveThreshold) {
00915       // use default at present
00916       factorization_->sparseThreshold(0);
00917       factorization_->goSparse();
00918     }
00919   }
00920   if (problemStatus_<0&&!changeMade_) {
00921     problemStatus_=4; // unknown
00922   }
00923   lastGoodIteration_ = numberIterations_;
00924   if (goToDual) 
00925     problemStatus_=10; // try dual
00926 #if 0
00927   double thisObj = progress->lastObjective(0);
00928   double lastObj = progress->lastObjective(1);
00929   if (lastObj<thisObj-1.0e-7*max(fabs(thisObj),fabs(lastObj))-1.0e-8
00930       &&firstFree_<0) {
00931     int maxFactor = factorization_->maximumPivots();
00932     if (maxFactor>10) {
00933       if (forceFactorization_<0)
00934         forceFactorization_= maxFactor;
00935       forceFactorization_ = max (1,(forceFactorization_>>1));
00936       printf("Reducing factorization frequency\n");
00937     } 
00938   }
00939 #endif
00940 }

int ClpSimplexPrimal::updatePrimalsInPrimal CoinIndexedVector rowArray,
double  theta,
double &  objectiveChange,
int  valuesPass
 

The primals are updated by the given array. Returns number of infeasibilities. After rowArray will have cost changes for use next iteration

Definition at line 1384 of file ClpSimplexPrimal.cpp.

References CoinIndexedVector::add(), ClpNonLinearCost::changeInCost(), CoinIndexedVector::denseVector(), CoinIndexedVector::expand(), CoinIndexedVector::getIndices(), CoinIndexedVector::getNumElements(), CoinIndexedVector::scanAndPack(), ClpNonLinearCost::setChangeInCost(), CoinIndexedVector::setNumElements(), ClpNonLinearCost::setOne(), and CoinIndexedVector::setPacked().

Referenced by pivotResult(), and ClpSimplexPrimalQuadratic::whileIterating().

01388 {
01389   // Cost on pivot row may change - may need to change dualIn
01390   double oldCost=0.0;
01391   if (pivotRow_>=0)
01392     oldCost = cost_[sequenceOut_];
01393   //rowArray->scanAndPack();
01394   double * work=rowArray->denseVector();
01395   int number=rowArray->getNumElements();
01396   int * which=rowArray->getIndices();
01397 
01398   int newNumber = 0;
01399   int pivotPosition = -1;
01400   nonLinearCost_->setChangeInCost(0.0);
01401   int iIndex;
01402   if (!valuesPass) {
01403     for (iIndex=0;iIndex<number;iIndex++) {
01404       
01405       int iRow = which[iIndex];
01406       double alpha = work[iIndex];
01407       work[iIndex]=0.0;
01408       int iPivot=pivotVariable_[iRow];
01409       double change = theta*alpha;
01410       double value = solution_[iPivot] - change;
01411       solution_[iPivot]=value;
01412 #ifndef NDEBUG
01413       // check if not active then okay
01414       if (!active(iRow)) {
01415         // But make sure one going out is feasible
01416         if (change>0.0) {
01417           // going down
01418           if (value<lower_[iPivot]+primalTolerance_) {
01419             if (iPivot==sequenceOut_&&value>lower_[iPivot]-1.001*primalTolerance_)
01420               value=lower_[iPivot];
01421             double difference = nonLinearCost_->setOne(iPivot,value);
01422             assert (!difference);
01423           }
01424         } else {
01425           // going up
01426           if (value>upper_[iPivot]-primalTolerance_) {
01427             if (iPivot==sequenceOut_&&value<upper_[iPivot]+1.001*primalTolerance_)
01428               value=upper_[iPivot];
01429             double difference = nonLinearCost_->setOne(iPivot,value);
01430             assert (!difference);
01431           }
01432         }
01433       }
01434 #endif    
01435       if (active(iRow)) {
01436         clearActive(iRow);
01437         // But make sure one going out is feasible
01438         if (change>0.0) {
01439           // going down
01440           if (value<lower_[iPivot]+primalTolerance_) {
01441             if (iPivot==sequenceOut_&&value>lower_[iPivot]-1.001*primalTolerance_)
01442               value=lower_[iPivot];
01443             double difference = nonLinearCost_->setOne(iPivot,value);
01444             if (difference) {
01445               if (iRow==pivotRow_)
01446                 pivotPosition=newNumber;
01447               work[newNumber] = difference;
01448               //change reduced cost on this
01449               dj_[iPivot] = -difference;
01450               which[newNumber++]=iRow;
01451             }
01452           }
01453         } else {
01454           // going up
01455           if (value>upper_[iPivot]-primalTolerance_) {
01456             if (iPivot==sequenceOut_&&value<upper_[iPivot]+1.001*primalTolerance_)
01457               value=upper_[iPivot];
01458             double difference = nonLinearCost_->setOne(iPivot,value);
01459             if (difference) {
01460               if (iRow==pivotRow_)
01461                 pivotPosition=newNumber;
01462               work[newNumber] = difference;
01463               //change reduced cost on this
01464               dj_[iPivot] = -difference;
01465               which[newNumber++]=iRow;
01466             }
01467           }
01468         }
01469       }
01470     }
01471   } else {
01472     // values pass so look at all
01473     for (iIndex=0;iIndex<number;iIndex++) {
01474       
01475       int iRow = which[iIndex];
01476       double alpha = work[iIndex];
01477       work[iIndex]=0.0;
01478       int iPivot=pivotVariable_[iRow];
01479       double change = theta*alpha;
01480       double value = solution_[iPivot] - change;
01481       solution_[iPivot]=value;
01482       clearActive(iRow);
01483       // But make sure one going out is feasible
01484       if (change>0.0) {
01485         // going down
01486         if (value<lower_[iPivot]+primalTolerance_) {
01487           if (iPivot==sequenceOut_&&value>lower_[iPivot]-1.001*primalTolerance_)
01488             value=lower_[iPivot];
01489           double difference = nonLinearCost_->setOne(iPivot,value);
01490           if (difference) {
01491             if (iRow==pivotRow_)
01492               pivotPosition=newNumber;
01493             work[newNumber] = difference;
01494             //change reduced cost on this
01495             dj_[iPivot] = -difference;
01496             which[newNumber++]=iRow;
01497           }
01498         }
01499       } else {
01500         // going up
01501         if (value>upper_[iPivot]-primalTolerance_) {
01502           if (iPivot==sequenceOut_&&value<upper_[iPivot]+1.001*primalTolerance_)
01503             value=upper_[iPivot];
01504           double difference = nonLinearCost_->setOne(iPivot,value);
01505           if (difference) {
01506             if (iRow==pivotRow_)
01507               pivotPosition=newNumber;
01508             work[newNumber] = difference;
01509             //change reduced cost on this
01510             dj_[iPivot] = -difference;
01511             which[newNumber++]=iRow;
01512           }
01513         }
01514       }
01515     }
01516   }
01517   objectiveChange += nonLinearCost_->changeInCost();
01518   rowArray->setPacked();
01519 #if 0
01520   rowArray->setNumElements(newNumber);
01521   rowArray->expand();
01522   if (pivotRow_>=0) {
01523     dualIn_ += (oldCost-cost_[sequenceOut_]);
01524     // update change vector to include pivot
01525     rowArray->add(pivotRow_,-dualIn_);
01526     // and convert to packed
01527     rowArray->scanAndPack();
01528   } else {
01529     // and convert to packed
01530     rowArray->scanAndPack();
01531   }
01532 #else
01533   if (pivotRow_>=0) {
01534     dualIn_ += (oldCost-cost_[sequenceOut_]);
01535     // update change vector to include pivot
01536     if (pivotPosition>=0) {
01537       work[pivotPosition] -= dualIn_;
01538     } else {
01539       work[newNumber]=-dualIn_;
01540       which[newNumber++]=pivotRow_;
01541     }
01542   }
01543   rowArray->setNumElements(newNumber);
01544 #endif
01545   return 0;
01546 }

int ClpSimplexPrimal::whileIterating int  valuesOption  ) 
 

This has the flow between re-factorizations

Returns a code to say where decision to exit was made Problem status set to:

-2 re-factorize -4 Looks optimal/infeasible -5 Looks unbounded +3 max iterations

valuesOption has original value of valuesPass

Definition at line 410 of file ClpSimplexPrimal.cpp.

References CoinIndexedVector::checkClear(), CoinIndexedVector::clear(), ClpSimplex::createRim(), ClpSimplex::gutsOfSolution(), ClpSimplex::isColumn(), CoinMessageHandler::logLevel(), CoinMessageHandler::message(), nextSuperBasic(), ClpNonLinearCost::numberInfeasibilities(), pivotResult(), primalColumn(), ClpPrimalColumnPivot::saveWeights(), ClpSimplex::sequenceWithin(), CoinMessageHandler::setLogLevel(), and CoinIndexedVector::setNumElements().

Referenced by primal().

00411 {
00412   // Say if values pass
00413   int ifValuesPass=(firstFree_>=0) ? 1 : 0;
00414   int returnCode=-1;
00415   int superBasicType=1;
00416   if (valuesOption>1)
00417     superBasicType=3;
00418   // status stays at -1 while iterating, >=0 finished, -2 to invert
00419   // status -3 to go to top without an invert
00420   while (problemStatus_==-1) {
00421     //#define CLP_DEBUG 1
00422 #ifdef CLP_DEBUG
00423     {
00424       int i;
00425       // not [1] as has information
00426       for (i=0;i<4;i++) {
00427         if (i!=1)
00428           rowArray_[i]->checkClear();
00429       }    
00430       for (i=0;i<2;i++) {
00431         columnArray_[i]->checkClear();
00432       }    
00433     }      
00434 #endif
00435 #if CLP_DEBUG>2
00436     // very expensive
00437     if (numberIterations_>0&&numberIterations_<-2534) {
00438       handler_->setLogLevel(63);
00439       double saveValue = objectiveValue_;
00440       double * saveRow1 = new double[numberRows_];
00441       double * saveRow2 = new double[numberRows_];
00442       memcpy(saveRow1,rowReducedCost_,numberRows_*sizeof(double));
00443       memcpy(saveRow2,rowActivityWork_,numberRows_*sizeof(double));
00444       double * saveColumn1 = new double[numberColumns_];
00445       double * saveColumn2 = new double[numberColumns_];
00446       memcpy(saveColumn1,reducedCostWork_,numberColumns_*sizeof(double));
00447       memcpy(saveColumn2,columnActivityWork_,numberColumns_*sizeof(double));
00448       createRim(7);
00449       gutsOfSolution(NULL,NULL);
00450       printf("xxx %d old obj %g, recomputed %g, sum primal inf %g\n",
00451              numberIterations_,
00452              saveValue,objectiveValue_,sumPrimalInfeasibilities_);
00453       memcpy(rowReducedCost_,saveRow1,numberRows_*sizeof(double));
00454       memcpy(rowActivityWork_,saveRow2,numberRows_*sizeof(double));
00455       memcpy(reducedCostWork_,saveColumn1,numberColumns_*sizeof(double));
00456       memcpy(columnActivityWork_,saveColumn2,numberColumns_*sizeof(double));
00457       delete [] saveRow1;
00458       delete [] saveRow2;
00459       delete [] saveColumn1;
00460       delete [] saveColumn2;
00461       objectiveValue_=saveValue;
00462     }
00463 #endif
00464     if (!ifValuesPass) {
00465       // choose column to come in
00466       // can use pivotRow_ to update weights
00467       // pass in list of cost changes so can do row updates (rowArray_[1])
00468       // NOTE rowArray_[0] is used by computeDuals which is a 
00469       // slow way of getting duals but might be used 
00470       primalColumn(rowArray_[1],rowArray_[2],rowArray_[3],
00471                    columnArray_[0],columnArray_[1]);
00472     } else {
00473       // in values pass
00474       int sequenceIn=nextSuperBasic(superBasicType,columnArray_[0]);
00475       if (valuesOption>1)
00476         superBasicType=2;
00477       if (sequenceIn<0) {
00478         // end of values pass - initialize weights etc
00479         handler_->message(CLP_END_VALUES_PASS,messages_)
00480           <<numberIterations_;
00481         primalColumnPivot_->saveWeights(this,5);
00482         problemStatus_=-2; // factorize now
00483         pivotRow_=-1; // say no weights update
00484         returnCode=-4;
00485         // Clean up
00486         int i;
00487         for (i=0;i<numberRows_+numberColumns_;i++) {
00488           if (getColumnStatus(i)==atLowerBound||getColumnStatus(i)==isFixed)
00489             solution_[i]=lower_[i];
00490           else if (getColumnStatus(i)==atUpperBound)
00491             solution_[i]=upper_[i];
00492         }
00493         break;
00494       } else {
00495         // normal
00496         sequenceIn_ = sequenceIn;
00497         valueIn_=solution_[sequenceIn_];
00498         lowerIn_=lower_[sequenceIn_];
00499         upperIn_=upper_[sequenceIn_];
00500         dualIn_=dj_[sequenceIn_];
00501       }
00502     }
00503     pivotRow_=-1;
00504     sequenceOut_=-1;
00505     rowArray_[1]->clear();
00506     if (sequenceIn_>=0) {
00507       // we found a pivot column
00508       assert (!flagged(sequenceIn_));
00509 #ifdef CLP_DEBUG
00510       if ((handler_->logLevel()&32)) {
00511         char x = isColumn(sequenceIn_) ? 'C' :'R';
00512         std::cout<<"pivot column "<<
00513           x<<sequenceWithin(sequenceIn_)<<std::endl;
00514       }
00515 #endif
00516       // do second half of iteration
00517       returnCode = pivotResult(ifValuesPass);
00518       if (returnCode<-1&&returnCode>-5) {
00519         problemStatus_=-2; // 
00520       } else if (returnCode==-5) {
00521         // something flagged - continue;
00522       } else if (returnCode==2) {
00523         problemStatus_=-5; // looks unbounded
00524       } else if (returnCode==4) {
00525         problemStatus_=-2; // looks unbounded but has iterated
00526       } else if (returnCode!=-1) {
00527         assert(returnCode==3);
00528         problemStatus_=3;
00529       }
00530     } else {
00531       // no pivot column
00532 #ifdef CLP_DEBUG
00533       if (handler_->logLevel()&32)
00534         printf("** no column pivot\n");
00535 #endif
00536       if (nonLinearCost_->numberInfeasibilities())
00537         problemStatus_=-4; // might be infeasible 
00538       returnCode=0;
00539       break;
00540     }
00541   }
00542   if (valuesOption>1) 
00543     columnArray_[0]->setNumElements(0);
00544   return returnCode;
00545 }


The documentation for this class was generated from the following files:
Generated on Wed Dec 3 14:37:48 2003 for CLP by doxygen 1.3.5