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

ClpSimplexDual Class Reference

#include <ClpSimplexDual.hpp>

Inheritance diagram for ClpSimplexDual:

ClpSimplex ClpModel List of all members.

Public Member Functions

Description of algorithm
int dual (int ifValuesPass)
int strongBranching (int numberVariables, const int *variables, double *newLower, double *newUpper, double **outputSolution, int *outputStatus, int *outputIterations, bool stopOnFirstInfeasible=true, bool alwaysFinish=false)
Functions used in dual
int whileIterating (double *&givenPi)
int updateDualsInDual (CoinIndexedVector *rowArray, CoinIndexedVector *columnArray, CoinIndexedVector *outputArray, double theta, double &objectiveChange, bool fullRecompute)
void updateDualsInValuesPass (CoinIndexedVector *rowArray, CoinIndexedVector *columnArray, double theta)
void flipBounds (CoinIndexedVector *rowArray, CoinIndexedVector *columnArray, double change)
void dualColumn (CoinIndexedVector *rowArray, CoinIndexedVector *columnArray, CoinIndexedVector *spareArray, CoinIndexedVector *spareArray2, double accpetablePivot, CoinBigIndex *dubiousWeights)
int checkPossibleValuesMove (CoinIndexedVector *rowArray, CoinIndexedVector *columnArray, double acceptablePivot, CoinBigIndex *dubiousWeights)
void doEasyOnesInValuesPass (double *givenReducedCosts)
void dualRow (int alreadyChosen)
int changeBounds (bool initialize, CoinIndexedVector *outputArray, double &changeCost)
bool changeBound (int iSequence)
void originalBound (int iSequence)
 Restores bound to original bound.

int checkUnbounded (CoinIndexedVector *ray, CoinIndexedVector *spare, double changeCost)
void statusOfProblemInDual (int &lastCleaned, int type, ClpSimplexProgress *progress, double *givenDjs)
void perturb ()
 Perturbs problem (method depends on perturbation()).

int fastDual (bool alwaysFinish=false)
int numberAtFakeBound ()
int pivotResult ()
int nextSuperBasic ()

Detailed Description

This solves LPs using the dual 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 ClpSimplexDual.hpp.


Member Function Documentation

bool ClpSimplexDual::changeBound int  iSequence  ) 
 

As changeBounds but just changes new bounds for a single variable. Returns true if change

Definition at line 2939 of file ClpSimplexDual.cpp.

References originalBound().

Referenced by whileIterating().

02940 {
02941   // old values 
02942   double oldLower=lower_[iSequence];
02943   double oldUpper=upper_[iSequence];
02944   double value=solution_[iSequence];
02945   bool modified=false;
02946   originalBound(iSequence);
02947   // original values
02948   double lowerValue=lower_[iSequence];
02949   double upperValue=upper_[iSequence];
02950   // back to altered values
02951   lower_[iSequence] = oldLower;
02952   upper_[iSequence] = oldUpper;
02953   if (getFakeBound(iSequence)!=noFake)
02954     numberFake_--;;
02955   if (value==oldLower) {
02956     if (upperValue > oldLower + dualBound_) {
02957       upper_[iSequence]=oldLower+dualBound_;
02958       setFakeBound(iSequence,upperFake);
02959       modified=true;
02960       numberFake_++;
02961     }
02962   } else if (value==oldUpper) {
02963     if (lowerValue < oldUpper - dualBound_) {
02964       lower_[iSequence]=oldUpper-dualBound_;
02965       setFakeBound(iSequence,lowerFake);
02966       modified=true;
02967       numberFake_++;
02968     }
02969   } else {
02970     assert(value==oldLower||value==oldUpper);
02971   }
02972   return modified;
02973 }

int ClpSimplexDual::changeBounds bool  initialize,
CoinIndexedVector outputArray,
double &  changeCost
 

Checks if any fake bounds active - if so returns number and modifies updatedDualBound_ and everything. Free variables will be left as free Returns number of bounds changed if >=0 Returns -1 if not initialize and no effect Fills in changeVector which can be used to see if unbounded and cost of change vector

Definition at line 1496 of file ClpSimplexDual.cpp.

References ClpMatrixBase::add(), ClpSimplex::createRim(), CoinMessageHandler::message(), and CoinIndexedVector::quickAdd().

Referenced by dual(), fastDual(), and statusOfProblemInDual().

01499 { 
01500   numberFake_ = 0;
01501   if (!initialize) {
01502     int numberInfeasibilities;
01503     double newBound;
01504     newBound = 5.0*dualBound_;
01505     numberInfeasibilities=0;
01506     changeCost=0.0;
01507     // put back original bounds and then check
01508     createRim(3);
01509     int iSequence;
01510     // bounds will get bigger - just look at ones at bounds
01511     for (iSequence=0;iSequence<numberRows_+numberColumns_;iSequence++) {
01512       double lowerValue=lower_[iSequence];
01513       double upperValue=upper_[iSequence];
01514       double value=solution_[iSequence];
01515       setFakeBound(iSequence,ClpSimplexDual::noFake);
01516       switch(getStatus(iSequence)) {
01517 
01518       case basic:
01519       case ClpSimplex::isFixed:
01520         break;
01521       case isFree:
01522       case superBasic:
01523         break;
01524       case atUpperBound:
01525         if (fabs(value-upperValue)>primalTolerance_) 
01526           numberInfeasibilities++;
01527         break;
01528       case atLowerBound:
01529         if (fabs(value-lowerValue)>primalTolerance_) 
01530           numberInfeasibilities++;
01531         break;
01532       }
01533     }
01534     // If dual infeasible then carry on
01535     if (numberInfeasibilities) {
01536       handler_->message(CLP_DUAL_CHECKB,messages_)
01537         <<newBound
01538         <<CoinMessageEol;
01539       int iSequence;
01540       for (iSequence=0;iSequence<numberRows_+numberColumns_;iSequence++) {
01541         double lowerValue=lower_[iSequence];
01542         double upperValue=upper_[iSequence];
01543         double newLowerValue;
01544         double newUpperValue;
01545         Status status = getStatus(iSequence);
01546         if (status==atUpperBound||
01547             status==atLowerBound) {
01548           double value = solution_[iSequence];
01549           if (value-lowerValue<=upperValue-value) {
01550             newLowerValue = max(lowerValue,value-0.666667*newBound);
01551             newUpperValue = min(upperValue,newLowerValue+newBound);
01552           } else {
01553             newUpperValue = min(upperValue,value+0.666667*newBound);
01554             newLowerValue = max(lowerValue,newUpperValue-newBound);
01555           }
01556           lower_[iSequence]=newLowerValue;
01557           upper_[iSequence]=newUpperValue;
01558           if (newLowerValue > lowerValue) {
01559             if (newUpperValue < upperValue) {
01560               setFakeBound(iSequence,ClpSimplexDual::bothFake);
01561               numberFake_++;
01562             } else {
01563               setFakeBound(iSequence,ClpSimplexDual::lowerFake);
01564               numberFake_++;
01565             }
01566           } else {
01567             if (newUpperValue < upperValue) {
01568               setFakeBound(iSequence,ClpSimplexDual::upperFake);
01569               numberFake_++;
01570             }
01571           }
01572           if (status==atUpperBound)
01573             solution_[iSequence] = newUpperValue;
01574           else
01575             solution_[iSequence] = newLowerValue;
01576           double movement = solution_[iSequence] - value;
01577           if (movement&&outputArray) {
01578             if (iSequence>=numberColumns_) {
01579               outputArray->quickAdd(iSequence,-movement);
01580               changeCost += movement*cost_[iSequence];
01581             } else {
01582               matrix_->add(this,outputArray,iSequence,movement);
01583               changeCost += movement*cost_[iSequence];
01584             }
01585           }
01586         }
01587       }
01588       dualBound_ = newBound;
01589     } else {
01590       numberInfeasibilities=-1;
01591     }
01592     return numberInfeasibilities;
01593   } else {
01594     int iSequence;
01595       
01596     for (iSequence=0;iSequence<numberRows_+numberColumns_;iSequence++) {
01597       Status status = getStatus(iSequence);
01598       if (status==atUpperBound||
01599           status==atLowerBound) {
01600         double lowerValue=lower_[iSequence];
01601         double upperValue=upper_[iSequence];
01602         double value = solution_[iSequence];
01603         if (lowerValue>-largeValue_||upperValue<largeValue_) {
01604           if (lowerValue-value>-0.5*dualBound_||
01605               upperValue-value<0.5*dualBound_) {
01606             if (fabs(lowerValue-value)<=fabs(upperValue-value)) {
01607               if (upperValue > lowerValue + dualBound_) {
01608                 upper_[iSequence]=lowerValue+dualBound_;
01609                 setFakeBound(iSequence,ClpSimplexDual::upperFake);
01610                 numberFake_++;
01611               }
01612             } else {
01613               if (lowerValue < upperValue - dualBound_) {
01614                 lower_[iSequence]=upperValue-dualBound_;
01615                 setFakeBound(iSequence,ClpSimplexDual::lowerFake);
01616                 numberFake_++;
01617               }
01618             }
01619           } else {
01620             lower_[iSequence]=-0.5*dualBound_;
01621             upper_[iSequence]= 0.5*dualBound_;
01622             setFakeBound(iSequence,ClpSimplexDual::bothFake);
01623             numberFake_++;
01624           }
01625         } else {
01626           // set non basic free variables to fake bounds
01627           // I don't think we should ever get here
01628           assert(!("should not be here"));
01629           lower_[iSequence]=-0.5*dualBound_;
01630           upper_[iSequence]= 0.5*dualBound_;
01631           setFakeBound(iSequence,ClpSimplexDual::bothFake);
01632           numberFake_++;
01633           setStatus(iSequence,atUpperBound);
01634           solution_[iSequence]=0.5*dualBound_;
01635         }
01636       }
01637     }
01638 
01639     return 1;
01640   }
01641 }

int ClpSimplexDual::checkPossibleValuesMove CoinIndexedVector rowArray,
CoinIndexedVector columnArray,
double  acceptablePivot,
CoinBigIndex *  dubiousWeights
 

Row array has row part of pivot row Column array has column part. This sees what is best thing to do in dual values pass Returns 0 if theta_ move will put basic variable out to bound, 1 if can change dual on chosen row and leave variable in basis

Definition at line 3798 of file ClpSimplexDual.cpp.

References CoinIndexedVector::denseVector(), CoinIndexedVector::getIndices(), CoinIndexedVector::getNumElements(), and CoinMessageHandler::logLevel().

Referenced by whileIterating().

03802 {
03803   double * work;
03804   int number;
03805   int * which;
03806   int iSection;
03807 
03808   double tolerance = dualTolerance_*1.001;
03809 
03810   double thetaDown = 1.0e31;
03811   double changeDown ;
03812   double thetaUp = 1.0e31;
03813   double bestAlphaDown = acceptablePivot*0.99999;
03814   double bestAlphaUp = acceptablePivot*0.99999;
03815   int sequenceDown =-1;
03816   int sequenceUp = sequenceOut_;
03817 
03818   double djBasic = dj_[sequenceOut_];
03819   if (djBasic>0.0) {
03820     // basic at lower bound so directionOut_ 1 and -1 in pivot row
03821     // dj will go to zero on other way
03822     thetaUp = djBasic;
03823     changeDown = -lower_[sequenceOut_];
03824   } else {
03825     // basic at upper bound so directionOut_ -1 and 1 in pivot row
03826     // dj will go to zero on other way
03827     thetaUp = -djBasic;
03828     changeDown = upper_[sequenceOut_];
03829   }
03830   bestAlphaUp = 1.0;
03831   int addSequence;
03832 
03833   double alphaUp=0.0;
03834   double alphaDown=0.0;
03835 
03836   for (iSection=0;iSection<2;iSection++) {
03837 
03838     int i;
03839     if (!iSection) {
03840       work = rowArray->denseVector();
03841       number = rowArray->getNumElements();
03842       which = rowArray->getIndices();
03843       addSequence = numberColumns_;
03844     } else {
03845       work = columnArray->denseVector();
03846       number = columnArray->getNumElements();
03847       which = columnArray->getIndices();
03848       addSequence = 0;
03849     }
03850     
03851     for (i=0;i<number;i++) {
03852       int iSequence = which[i];
03853       int iSequence2 = iSequence + addSequence;
03854       double alpha;
03855       double oldValue;
03856       double value;
03857 
03858       switch(getStatus(iSequence2)) {
03859           
03860       case basic:
03861         break;
03862       case ClpSimplex::isFixed:
03863         alpha = work[i];
03864         changeDown += alpha*upper_[iSequence2];
03865         break;
03866       case isFree:
03867       case superBasic:
03868         alpha = work[i];
03869         // dj must be effectively zero as dual feasible
03870         if (fabs(alpha)>bestAlphaUp) {
03871           thetaDown = 0.0;
03872           thetaUp = 0.0;
03873           bestAlphaDown = fabs(alpha);
03874           bestAlphaUp = bestAlphaUp;
03875           sequenceDown =iSequence2;
03876           sequenceUp = sequenceDown;
03877           alphaUp = alpha;
03878           alphaDown = alpha;
03879         }
03880         break;
03881       case atUpperBound:
03882         alpha = work[i];
03883         oldValue = dj_[iSequence2];
03884         changeDown += alpha*upper_[iSequence2];
03885         if (alpha>=acceptablePivot) {
03886           // might do other way
03887           value = oldValue+thetaUp*alpha;
03888           if (value>-tolerance) {
03889             if (value>tolerance||fabs(alpha)>bestAlphaUp) {
03890               thetaUp = -oldValue/alpha;
03891               bestAlphaUp = fabs(alpha);
03892               sequenceUp = iSequence2;
03893               alphaUp = alpha;
03894             }
03895           }
03896         } else if (alpha<=-acceptablePivot) {
03897           // might do this way
03898           value = oldValue-thetaDown*alpha;
03899           if (value>-tolerance) {
03900             if (value>tolerance||fabs(alpha)>bestAlphaDown) {
03901               thetaDown = oldValue/alpha;
03902               bestAlphaDown = fabs(alpha);
03903               sequenceDown = iSequence2;
03904               alphaDown = alpha;
03905             }
03906           }
03907         }
03908         break;
03909       case atLowerBound:
03910         alpha = work[i];
03911         oldValue = dj_[iSequence2];
03912         changeDown += alpha*lower_[iSequence2];
03913         if (alpha<=-acceptablePivot) {
03914           // might do other way
03915           value = oldValue+thetaUp*alpha;
03916           if (value<tolerance) {
03917             if (value<-tolerance||fabs(alpha)>bestAlphaUp) {
03918               thetaUp = -oldValue/alpha;
03919               bestAlphaUp = fabs(alpha);
03920               sequenceUp = iSequence2;
03921               alphaUp = alpha;
03922             }
03923           }
03924         } else if (alpha>=acceptablePivot) {
03925           // might do this way
03926           value = oldValue-thetaDown*alpha;
03927           if (value<tolerance) {
03928             if (value<-tolerance||fabs(alpha)>bestAlphaDown) {
03929               thetaDown = oldValue/alpha;
03930               bestAlphaDown = fabs(alpha);
03931               sequenceDown = iSequence2;
03932               alphaDown = alpha;
03933             }
03934           }
03935         }
03936         break;
03937       }
03938     }
03939   }
03940   int returnCode;
03941   thetaUp *= -1.0;
03942   double changeUp = -thetaUp * changeDown;
03943   changeDown = -thetaDown*changeDown;
03944   if (max(fabs(thetaDown),fabs(thetaUp))<1.0e-8) {
03945     // largest
03946     if (fabs(alphaDown)<fabs(alphaUp)) {
03947       sequenceDown =-1;
03948     }
03949   }
03950   // choose
03951   if (changeDown>changeUp&&sequenceDown>=0) {
03952     theta_ = thetaDown;
03953     sequenceIn_ = sequenceDown;
03954     alpha_ = alphaDown;
03955 #ifdef CLP_DEBUG
03956     if ((handler_->logLevel()&32))
03957       printf("predicted way - dirout %d, change %g,%g theta %g\n",
03958              directionOut_,changeDown,changeUp,theta_);
03959 #endif
03960     returnCode = 0;
03961   } else {
03962     theta_ = thetaUp;
03963     sequenceIn_ = sequenceUp;
03964     alpha_ = alphaUp;
03965     if (sequenceIn_!=sequenceOut_) {
03966 #ifdef CLP_DEBUG
03967       if ((handler_->logLevel()&32))
03968         printf("opposite way - dirout %d, change %g,%g theta %g\n",
03969                directionOut_,changeDown,changeUp,theta_);
03970 #endif
03971       returnCode = 0;
03972     } else {
03973 #ifdef CLP_DEBUG
03974       if ((handler_->logLevel()&32))
03975         printf("opposite way to zero dj - dirout %d, change %g,%g theta %g\n",
03976                directionOut_,changeDown,changeUp,theta_);
03977 #endif
03978       returnCode = 1;
03979     }
03980   }
03981   return returnCode;
03982 }

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

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

Definition at line 2290 of file ClpSimplexDual.cpp.

References CoinIndexedVector::clear(), CoinIndexedVector::denseVector(), CoinIndexedVector::getIndices(), CoinIndexedVector::getNumElements(), and ClpSimplex::solution().

Referenced by statusOfProblemInDual().

02293 {
02294   int status=2; // say unbounded
02295   factorization_->updateColumn(spare,ray);
02296   // get reduced cost
02297   int i;
02298   int number=ray->getNumElements();
02299   int * index = ray->getIndices();
02300   double * array = ray->denseVector();
02301   for (i=0;i<number;i++) {
02302     int iRow=index[i];
02303     int iPivot=pivotVariable_[iRow];
02304     changeCost -= cost(iPivot)*array[iRow];
02305   }
02306   double way;
02307   if (changeCost>0.0) {
02308     //try going down
02309     way=1.0;
02310   } else if (changeCost<0.0) {
02311     //try going up
02312     way=-1.0;
02313   } else {
02314 #ifdef CLP_DEBUG
02315     printf("can't decide on up or down\n");
02316 #endif
02317     way=0.0;
02318     status=-3;
02319   }
02320   double movement=1.0e10*way; // some largish number
02321   double zeroTolerance = 1.0e-14*dualBound_;
02322   for (i=0;i<number;i++) {
02323     int iRow=index[i];
02324     int iPivot=pivotVariable_[iRow];
02325     double arrayValue = array[iRow];
02326     if (fabs(arrayValue)<zeroTolerance)
02327       arrayValue=0.0;
02328     double newValue=solution(iPivot)+movement*arrayValue;
02329     if (newValue>upper(iPivot)+primalTolerance_||
02330         newValue<lower(iPivot)-primalTolerance_)
02331       status=-3; // not unbounded
02332   }
02333   if (status==2) {
02334     // create ray
02335     delete [] ray_;
02336     ray_ = new double [numberColumns_];
02337     ClpFillN(ray_,numberColumns_,0.0);
02338     for (i=0;i<number;i++) {
02339       int iRow=index[i];
02340       int iPivot=pivotVariable_[iRow];
02341       double arrayValue = array[iRow];
02342       if (iPivot<numberColumns_&&fabs(arrayValue)>=zeroTolerance)
02343         ray_[iPivot] = way* array[iRow];
02344     }
02345   }
02346   ray->clear();
02347   return status;
02348 }

void ClpSimplexDual::doEasyOnesInValuesPass double *  givenReducedCosts  ) 
 

This sees if we can move duals in dual values pass. This is done before any pivoting

Definition at line 3987 of file ClpSimplexDual.cpp.

References ClpModel::matrix().

Referenced by dual().

03988 {
03989   // Get column copy
03990   CoinPackedMatrix * columnCopy = matrix();
03991   // Get a row copy in standard format
03992   CoinPackedMatrix copy;
03993   copy.reverseOrderedCopyOf(*columnCopy);
03994   // get matrix data pointers
03995   const int * column = copy.getIndices();
03996   const CoinBigIndex * rowStart = copy.getVectorStarts();
03997   const int * rowLength = copy.getVectorLengths(); 
03998   const double * elementByRow = copy.getElements();
03999   double tolerance = dualTolerance_*1.001;
04000 
04001   int iRow;
04002 #ifdef CLP_DEBUG
04003   {
04004     double value5=0.0;
04005     int i;
04006     for (i=0;i<numberRows_+numberColumns_;i++) {
04007       if (dj[i]<-1.0e-6)
04008         value5 += dj[i]*upper_[i];
04009       else if (dj[i] >1.0e-6)
04010         value5 += dj[i]*lower_[i];
04011     }
04012     printf("Values objective Value before %g\n",value5);
04013   }
04014 #endif
04015   // for scaled row
04016   double * scaled=NULL;
04017   if (rowScale_)
04018     scaled = new double[numberColumns_];
04019   for (iRow=0;iRow<numberRows_;iRow++) {
04020 
04021     int iSequence = iRow + numberColumns_;
04022     double djBasic = dj[iSequence];
04023     if (getRowStatus(iRow)==basic&&fabs(djBasic)>tolerance) {
04024 
04025       double changeUp ;
04026       // always -1 in pivot row
04027       if (djBasic>0.0) {
04028         // basic at lower bound
04029         changeUp = -lower_[iSequence];
04030       } else {
04031         // basic at upper bound
04032         changeUp = upper_[iSequence];
04033       }
04034       bool canMove=true;
04035       int i;
04036       const double * thisElements = elementByRow + rowStart[iRow]; 
04037       const int * thisIndices = column+rowStart[iRow];
04038       if (rowScale_) {
04039         // scale row
04040         double scale = rowScale_[iRow];
04041         for (i = 0;i<rowLength[iRow];i++) {
04042           int iColumn = thisIndices[i];
04043           double alpha = thisElements[i];
04044           scaled[i] = scale*alpha*columnScale_[iColumn];
04045         }
04046         thisElements = scaled;
04047       }
04048       for (i = 0;i<rowLength[iRow];i++) {
04049         int iColumn = thisIndices[i];
04050         double alpha = thisElements[i];
04051         double oldValue = dj[iColumn];;
04052         double value;
04053 
04054         switch(getStatus(iColumn)) {
04055           
04056         case basic:
04057           if (dj[iColumn]<-tolerance&&
04058               fabs(solution_[iColumn]-upper_[iColumn])<1.0e-8) {
04059             // at ub
04060             changeUp += alpha*upper_[iColumn];
04061             // might do other way
04062             value = oldValue+djBasic*alpha;
04063             if (value>tolerance) 
04064               canMove=false;
04065           } else if (dj[iColumn]>tolerance&&
04066               fabs(solution_[iColumn]-lower_[iColumn])<1.0e-8) {
04067             changeUp += alpha*lower_[iColumn];
04068             // might do other way
04069             value = oldValue+djBasic*alpha;
04070             if (value<-tolerance)
04071               canMove=false;
04072           } else {
04073             canMove=false;
04074           }
04075           break;
04076         case ClpSimplex::isFixed:
04077           changeUp += alpha*upper_[iColumn];
04078           break;
04079         case isFree:
04080         case superBasic:
04081           canMove=false;
04082         break;
04083       case atUpperBound:
04084         changeUp += alpha*upper_[iColumn];
04085         // might do other way
04086         value = oldValue+djBasic*alpha;
04087         if (value>tolerance) 
04088           canMove=false;
04089         break;
04090       case atLowerBound:
04091         changeUp += alpha*lower_[iColumn];
04092         // might do other way
04093         value = oldValue+djBasic*alpha;
04094         if (value<-tolerance)
04095           canMove=false;
04096         break;
04097         }
04098       }
04099       if (canMove) {
04100         if (changeUp*djBasic>1.0e-12||fabs(changeUp)<1.0e-8) {
04101           // move 
04102           for (i = 0;i<rowLength[iRow];i++) {
04103             int iColumn = thisIndices[i];
04104             double alpha = thisElements[i];
04105             dj[iColumn] += djBasic * alpha;
04106           }
04107           dj[iSequence]=0.0;
04108 #ifdef CLP_DEBUG
04109           {
04110             double value5=0.0;
04111             int i;
04112             for (i=0;i<numberRows_+numberColumns_;i++) {
04113               if (dj[i]<-1.0e-6)
04114                 value5 += dj[i]*upper_[i];
04115               else if (dj[i] >1.0e-6)
04116                 value5 += dj[i]*lower_[i];
04117             }
04118             printf("Values objective Value after row %d old dj %g %g\n",
04119                    iRow,djBasic,value5);
04120           }
04121 #endif
04122         }
04123       }
04124     }      
04125   }
04126   delete [] scaled;
04127 }

int ClpSimplexDual::dual int  ifValuesPass  ) 
 

Dual 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 updatedDualBound_ being given to getting dual feasible. In this version I have used the idea that this weight can be thought of as a fake bound. If the distance between the lower and upper bounds on a variable is less than the feasibility weight then we are always better off flipping to other bound to make dual feasible. If the distance is greater then we make up a fake bound updatedDualBound_ away from one bound. If we end up optimal or primal infeasible, we check to see if bounds okay. If so we have finished, if not we increase updatedDualBound_ and continue (after checking if unbounded). I am undecided about free variables - there is coding but I am not sure about it. At present I put them in basis anyway.

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 outgoing variable for Dantzig row choice. For steepest edge we keep an updated list of infeasibilities (actually squares). On easy problems we don't need full scan - just pick first reasonable.

One problem is how to tackle degeneracy and accuracy. At present I am using the modification of costs which I put in OSL and some of what I think is the dual analog of Gill et al. I am still not sure of the exact details.

The flow of dual is three while loops as follows:

while (not finished) {

while (not clean solution) {

Factorize and/or clean up solution by flipping variables so dual feasible. If looks finished check fake dual 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 row (outgoing variable). if none then we are primal feasible so looks as if done but we need to break and check bounds etc.

Get pivot row in tableau

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

If we do find incoming column, 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 flipping variables to stay dual 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 out 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 111 of file ClpSimplexDual.cpp.

References changeBounds(), CoinIndexedVector::clear(), doEasyOnesInValuesPass(), ClpSimplex::gutsOfSolution(), ClpSimplexProgress::lastIterationNumber(), CoinMessageHandler::logLevel(), CoinMessageHandler::message(), ClpModel::objectiveValue(), perturb(), CoinMessageHandler::printing(), ClpMatrixBase::refresh(), ClpSimplex::restoreData(), ClpSimplex::saveData(), ClpDataSave::sparseThreshold_, ClpSimplexProgress::startCheck(), ClpSimplex::startup(), statusOfProblemInDual(), ClpSimplex::transposeTimes(), and whileIterating().

Referenced by strongBranching().

00112 {
00113 
00114   /* *** Method
00115      This is a vanilla version of dual simplex.
00116 
00117      It tries to be a single phase approach with a weight of 1.0 being
00118      given to getting optimal and a weight of dualBound_ being
00119      given to getting dual feasible.  In this version I have used the
00120      idea that this weight can be thought of as a fake bound.  If the
00121      distance between the lower and upper bounds on a variable is less
00122      than the feasibility weight then we are always better off flipping
00123      to other bound to make dual feasible.  If the distance is greater
00124      then we make up a fake bound dualBound_ away from one bound.
00125      If we end up optimal or primal infeasible, we check to see if
00126      bounds okay.  If so we have finished, if not we increase dualBound_
00127      and continue (after checking if unbounded). I am undecided about
00128      free variables - there is coding but I am not sure about it.  At
00129      present I put them in basis anyway.
00130 
00131      The code is designed to take advantage of sparsity so arrays are
00132      seldom zeroed out from scratch or gone over in their entirety.
00133      The only exception is a full scan to find outgoing variable.  This
00134      will be changed to keep an updated list of infeasibilities (or squares
00135      if steepest edge).  Also on easy problems we don't need full scan - just
00136      pick first reasonable.
00137 
00138      One problem is how to tackle degeneracy and accuracy.  At present
00139      I am using the modification of costs which I put in OSL and which was
00140      extended by Gill et al.  I am still not sure of the exact details.
00141 
00142      The flow of dual is three while loops as follows:
00143 
00144      while (not finished) {
00145 
00146        while (not clean solution) {
00147 
00148           Factorize and/or clean up solution by flipping variables so
00149           dual feasible.  If looks finished check fake dual bounds.
00150           Repeat until status is iterating (-1) or finished (0,1,2)
00151 
00152        }
00153 
00154        while (status==-1) {
00155 
00156          Iterate until no pivot in or out or time to re-factorize.
00157 
00158          Flow is:
00159 
00160          choose pivot row (outgoing variable).  if none then
00161          we are primal feasible so looks as if done but we need to
00162          break and check bounds etc.
00163 
00164          Get pivot row in tableau
00165 
00166          Choose incoming column.  If we don't find one then we look
00167          primal infeasible so break and check bounds etc.  (Also the
00168          pivot tolerance is larger after any iterations so that may be
00169          reason)
00170 
00171          If we do find incoming column, we may have to adjust costs to
00172          keep going forwards (anti-degeneracy).  Check pivot will be stable
00173          and if unstable throw away iteration (we will need to implement
00174          flagging of basic variables sometime) and break to re-factorize.
00175          If minor error re-factorize after iteration.
00176 
00177          Update everything (this may involve flipping variables to stay
00178          dual feasible.
00179 
00180        }
00181 
00182      }
00183 
00184      At present we never check we are going forwards.  I overdid that in
00185      OSL so will try and make a last resort.
00186 
00187      Needs partial scan pivot out option.
00188      Needs dantzig, uninitialized and full steepest edge options (can still
00189      use partial scan)
00190 
00191      May need other anti-degeneracy measures, especially if we try and use
00192      loose tolerances as a way to solve in fewer iterations.
00193 
00194      I like idea of dynamic scaling.  This gives opportunity to decouple
00195      different implications of scaling for accuracy, iteration count and
00196      feasibility tolerance.
00197 
00198   */
00199   algorithm_ = -1;
00200 
00201   // save data
00202   ClpDataSave data = saveData();
00203 
00204   // Save so can see if doing after primal
00205   int initialStatus=problemStatus_;
00206 
00207   // If values pass then save given duals round check solution
00208   double * saveDuals = NULL;
00209   if (ifValuesPass) {
00210     saveDuals = new double [numberRows_+numberColumns_];
00211     memcpy(saveDuals,dual_,numberRows_*sizeof(double));
00212   }
00213   
00214   // sanity check
00215   // initialize - no values pass and algorithm_ is -1
00216   // put in standard form (and make row copy)
00217   // create modifiable copies of model rim and do optional scaling
00218   // If problem looks okay
00219   // Do initial factorization
00220   // If user asked for perturbation - do it
00221   if (!startup(0)) {
00222     // looks okay
00223     // Superbasic variables not allowed
00224     // If values pass then scale pi 
00225     if (ifValuesPass) {
00226       if (problemStatus_&&perturbation_<100) 
00227         perturb();
00228       int i;
00229       if (scalingFlag_>0) {
00230         for (i=0;i<numberRows_;i++) {
00231           dual_[i] = saveDuals[i]/rowScale_[i];
00232         }
00233       } else {
00234         memcpy(dual_,saveDuals,numberRows_*sizeof(double));
00235       }
00236       // now create my duals
00237       for (i=0;i<numberRows_;i++) {
00238         // slack
00239         double value = dual_[i];
00240         value += rowObjectiveWork_[i];
00241         saveDuals[i+numberColumns_]=value;
00242       }
00243       ClpDisjointCopyN(objectiveWork_,numberColumns_,saveDuals);
00244       transposeTimes(-1.0,dual_,saveDuals);
00245       memcpy(dj_,saveDuals,(numberColumns_+numberRows_)*sizeof(double));
00246       // set up possible ones
00247       for (i=0;i<numberRows_+numberColumns_;i++)
00248         clearPivoted(i);
00249       int iRow;
00250       for (iRow=0;iRow<numberRows_;iRow++) {
00251         int iPivot=pivotVariable_[iRow];
00252         if (fabs(saveDuals[iPivot])>dualTolerance_) {
00253           if (getStatus(iPivot)!=isFree) 
00254             setPivoted(iPivot);
00255         }
00256       }
00257     } 
00258 
00259     double objectiveChange;
00260     numberFake_ =0; // Number of variables at fake bounds
00261     changeBounds(true,NULL,objectiveChange);
00262     
00263     int lastCleaned=0; // last time objective or bounds cleaned up
00264 
00265     if (!ifValuesPass) {
00266       // Check optimal
00267       if (!numberDualInfeasibilities_&&!numberPrimalInfeasibilities_)
00268         problemStatus_=0;
00269     }
00270     if (problemStatus_<0&&perturbation_<100) {
00271       perturb();
00272       // Can't get here if values pass
00273       gutsOfSolution(NULL,NULL);
00274       if (handler_->logLevel()>2) {
00275         handler_->message(CLP_SIMPLEX_STATUS,messages_)
00276           <<numberIterations_<<objectiveValue();
00277         handler_->printing(sumPrimalInfeasibilities_>0.0)
00278           <<sumPrimalInfeasibilities_<<numberPrimalInfeasibilities_;
00279         handler_->printing(sumDualInfeasibilities_>0.0)
00280           <<sumDualInfeasibilities_<<numberDualInfeasibilities_;
00281         handler_->printing(numberDualInfeasibilitiesWithoutFree_
00282                            <numberDualInfeasibilities_)
00283                              <<numberDualInfeasibilitiesWithoutFree_;
00284         handler_->message()<<CoinMessageEol;
00285       }
00286     }
00287         
00288     // This says whether to restore things etc
00289     int factorType=0;
00290     // Start check for cycles
00291     progress_->startCheck();
00292     /*
00293       Status of problem:
00294       0 - optimal
00295       1 - infeasible
00296       2 - unbounded
00297       -1 - iterating
00298       -2 - factorization wanted
00299       -3 - redo checking without factorization
00300       -4 - looks infeasible
00301     */
00302     while (problemStatus_<0) {
00303       int iRow, iColumn;
00304       // clear
00305       for (iRow=0;iRow<4;iRow++) {
00306         rowArray_[iRow]->clear();
00307       }    
00308       
00309       for (iColumn=0;iColumn<2;iColumn++) {
00310         columnArray_[iColumn]->clear();
00311       }    
00312       
00313       // give matrix (and model costs and bounds a chance to be
00314       // refreshed (normally null)
00315       matrix_->refresh(this);
00316       // If getting nowhere - why not give it a kick
00317       // does not seem to work too well - do some more work
00318       if (perturbation_<101&&numberIterations_>2*(numberRows_+numberColumns_)
00319           &&initialStatus!=10) {
00320         perturb();
00321         // Can't get here if values pass
00322         gutsOfSolution(NULL,NULL);
00323         if (handler_->logLevel()>2) {
00324           handler_->message(CLP_SIMPLEX_STATUS,messages_)
00325             <<numberIterations_<<objectiveValue();
00326           handler_->printing(sumPrimalInfeasibilities_>0.0)
00327             <<sumPrimalInfeasibilities_<<numberPrimalInfeasibilities_;
00328           handler_->printing(sumDualInfeasibilities_>0.0)
00329             <<sumDualInfeasibilities_<<numberDualInfeasibilities_;
00330           handler_->printing(numberDualInfeasibilitiesWithoutFree_
00331                              <numberDualInfeasibilities_)
00332                                <<numberDualInfeasibilitiesWithoutFree_;
00333           handler_->message()<<CoinMessageEol;
00334         }
00335       }
00336       // may factorize, checks if problem finished
00337       statusOfProblemInDual(lastCleaned,factorType,progress_,saveDuals);
00338       // If values pass then do easy ones on first time
00339       if (ifValuesPass&&
00340           progress_->lastIterationNumber(0)<0) {
00341         doEasyOnesInValuesPass(saveDuals);
00342       }
00343       
00344       // Say good factorization
00345       factorType=1;
00346       if (data.sparseThreshold_) {
00347         // use default at present
00348         factorization_->sparseThreshold(0);
00349         factorization_->goSparse();
00350       }
00351 
00352       // exit if victory declared
00353       if (problemStatus_>=0)
00354         break;
00355       
00356       // Do iterations
00357       whileIterating(saveDuals);
00358     }
00359   }
00360 
00361   assert (problemStatus_||!sumPrimalInfeasibilities_);
00362 
00363   // clean up
00364   finish();
00365   delete [] saveDuals;
00366 
00367   // Restore any saved stuff
00368   restoreData(data);
00369   return problemStatus_;
00370 }

void ClpSimplexDual::dualColumn CoinIndexedVector rowArray,
CoinIndexedVector columnArray,
CoinIndexedVector spareArray,
CoinIndexedVector spareArray2,
double  accpetablePivot,
CoinBigIndex *  dubiousWeights
 

Row array has row part of pivot row Column array has column part. This chooses pivot column. Spare arrays are used to save pivots which will go infeasible We will check for basic so spare array will never overflow. If necessary will modify costs For speed, we may need to go to a bucket approach when many variables are being flipped

Definition at line 1651 of file ClpSimplexDual.cpp.

References CoinIndexedVector::clear(), CoinIndexedVector::denseVector(), CoinIndexedVector::getIndices(), CoinIndexedVector::getNumElements(), and CoinMessageHandler::logLevel().

Referenced by whileIterating().

01657 {
01658   double * work;
01659   int number;
01660   int * which;
01661   double * reducedCost;
01662   int iSection;
01663 
01664   sequenceIn_=-1;
01665   int numberPossiblySwapped=0;
01666   int numberRemaining=0;
01667   
01668   double totalThru=0.0; // for when variables flip
01669 
01670   double bestEverPivot=acceptablePivot;
01671   int lastSequence = -1;
01672   double lastPivot=0.0;
01673   double upperTheta;
01674   double newTolerance = dualTolerance_;
01675   //newTolerance = dualTolerance_+1.0e-6*dblParam_[ClpDualTolerance];
01676   // will we need to increase tolerance
01677   bool thisIncrease=false;
01678   // If we think we need to modify costs (not if something from broad sweep)
01679   bool modifyCosts=false;
01680   // Increase in objective due to swapping bounds (may be negative)
01681   double increaseInObjective=0.0;
01682 
01683   // use spareArrays to put ones looked at in
01684   // we are going to flip flop between
01685   int iFlip = 0;
01686   // Possible list of pivots
01687   int interesting[2];
01688   // where possible swapped ones are
01689   int swapped[2];
01690   // for zeroing out arrays after
01691   int marker[2][2];
01692   // pivot elements
01693   double * array[2], * spare, * spare2;
01694   // indices
01695   int * indices[2], * index, * index2;
01696   spareArray->clear();
01697   spareArray2->clear();
01698   array[0] = spareArray->denseVector();
01699   indices[0] = spareArray->getIndices();
01700   spare = array[0];
01701   index = indices[0];
01702   array[1] = spareArray2->denseVector();
01703   indices[1] = spareArray2->getIndices();
01704   int i;
01705   const double * lower;
01706   const double * upper;
01707 
01708   // initialize lists
01709   for (i=0;i<2;i++) {
01710     interesting[i]=0;
01711     swapped[i]=numberColumns_;
01712     marker[i][0]=0;
01713     marker[i][1]=numberColumns_;
01714   }
01715 
01716   /*
01717     First we get a list of possible pivots.  We can also see if the
01718     problem looks infeasible or whether we want to pivot in free variable.
01719     This may make objective go backwards but can only happen a finite
01720     number of times and I do want free variables basic.
01721 
01722     Then we flip back and forth.  At the start of each iteration
01723     interesting[iFlip] should have possible candidates and swapped[iFlip]
01724     will have pivots if we decide to take a previous pivot.
01725     At end of each iteration interesting[1-iFlip] should have
01726     candidates if we go through this theta and swapped[1-iFlip]
01727     pivots if we don't go through.
01728 
01729     At first we increase theta and see what happens.  We start
01730     theta at a reasonable guess.  If in right area then we do bit by bit.
01731 
01732    */
01733 
01734   // do first pass to get possibles 
01735   // We can also see if infeasible or pivoting on free
01736   double tentativeTheta = 1.0e22;
01737   upperTheta = 1.0e31;
01738   double freePivot = acceptablePivot;
01739 
01740   for (iSection=0;iSection<2;iSection++) {
01741 
01742     int addSequence;
01743 
01744     if (!iSection) {
01745       lower = rowLowerWork_;
01746       upper = rowUpperWork_;
01747       work = rowArray->denseVector();
01748       number = rowArray->getNumElements();
01749       which = rowArray->getIndices();
01750       reducedCost = rowReducedCost_;
01751       addSequence = numberColumns_;
01752     } else {
01753       lower = columnLowerWork_;
01754       upper = columnUpperWork_;
01755       work = columnArray->denseVector();
01756       number = columnArray->getNumElements();
01757       which = columnArray->getIndices();
01758       reducedCost = reducedCostWork_;
01759       addSequence = 0;
01760     }
01761     
01762     for (i=0;i<number;i++) {
01763       int iSequence = which[i];
01764       double alpha;
01765       double oldValue;
01766       double value;
01767       bool keep;
01768 
01769       switch(getStatus(iSequence+addSequence)) {
01770           
01771       case basic:
01772       case ClpSimplex::isFixed:
01773         break;
01774       case isFree:
01775       case superBasic:
01776         alpha = work[i];
01777         oldValue = reducedCost[iSequence];
01778         if (oldValue>dualTolerance_) {
01779           keep = true;
01780         } else if (oldValue<-dualTolerance_) {
01781           keep = true;
01782         } else {
01783           if (fabs(alpha)>10.0*acceptablePivot) 
01784             keep = true;
01785           else
01786             keep=false;
01787         }
01788         if (keep) {
01789           // free - choose largest
01790           if (fabs(alpha)>freePivot) {
01791             freePivot=fabs(alpha);
01792             sequenceIn_ = iSequence + addSequence;
01793             theta_=oldValue/alpha;
01794             alpha_=alpha;
01795           }
01796         }
01797         break;
01798       case atUpperBound:
01799         alpha = work[i];
01800         oldValue = reducedCost[iSequence];
01801         value = oldValue-tentativeTheta*alpha;
01802         assert (oldValue<=dualTolerance_*1.0001);
01803         if (value>newTolerance) {
01804           value = oldValue-upperTheta*alpha;
01805           if (value>newTolerance && -alpha>=acceptablePivot) 
01806             upperTheta = (oldValue-newTolerance)/alpha;
01807           // add to list
01808           spare[numberRemaining]=alpha;
01809           index[numberRemaining++]=iSequence+addSequence;
01810         }
01811         break;
01812       case atLowerBound:
01813         alpha = work[i];
01814         oldValue = reducedCost[iSequence];
01815         value = oldValue-tentativeTheta*alpha;
01816         assert (oldValue>=-dualTolerance_*1.0001);
01817         if (value<-newTolerance) {
01818           value = oldValue-upperTheta*alpha;
01819           if (value<-newTolerance && alpha>=acceptablePivot) 
01820             upperTheta = (oldValue+newTolerance)/alpha;
01821           // add to list
01822           spare[numberRemaining]=alpha;
01823           index[numberRemaining++]=iSequence+addSequence;
01824         }
01825         break;
01826       }
01827     }
01828   }
01829   interesting[0]=numberRemaining;
01830   marker[0][0] = numberRemaining;
01831 
01832   if (!numberRemaining&&sequenceIn_<0)
01833     return ; // Looks infeasible
01834 
01835   if (sequenceIn_>=0) {
01836     // free variable - always choose
01837   } else {
01838 
01839     theta_=1.0e50;
01840     // now flip flop between spare arrays until reasonable theta
01841     tentativeTheta = max(10.0*upperTheta,1.0e-7);
01842     
01843     // loops increasing tentative theta until can't go through
01844     
01845     while (tentativeTheta < 1.0e22) {
01846       double thruThis = 0.0;
01847       
01848       double bestPivot=acceptablePivot;
01849       int bestSequence=-1;
01850       
01851       numberPossiblySwapped = numberColumns_;
01852       numberRemaining = 0;
01853 
01854       upperTheta = 1.0e50;
01855 
01856       spare = array[iFlip];
01857       index = indices[iFlip];
01858       spare2 = array[1-iFlip];
01859       index2 = indices[1-iFlip];
01860 
01861       // try 3 different ways
01862       // 1 bias increase by ones with slightly wrong djs
01863       // 2 bias by all
01864       // 3 bias by all - tolerance (doesn't seem very good)
01865 #define TRYBIAS 1
01866 
01867 
01868       double increaseInThis=0.0; //objective increase in this loop
01869       
01870       for (i=0;i<interesting[iFlip];i++) {
01871         int iSequence = index[i];
01872         double alpha = spare[i];
01873         double oldValue = dj_[iSequence];
01874         double value = oldValue-tentativeTheta*alpha;
01875 
01876         if (alpha < 0.0) {
01877           //at upper bound
01878           if (value>newTolerance) {
01879             double range = upper_[iSequence] - lower_[iSequence];
01880             thruThis -= range*alpha;
01881 #if TRYBIAS==1
01882             if (oldValue>0.0)
01883               increaseInThis -= oldValue*range;
01884 #elif TRYBIAS==2
01885             increaseInThis -= oldValue*range;
01886 #else
01887             increaseInThis -= (oldValue+dualTolerance_)*range;
01888 #endif
01889             // goes on swapped list (also means candidates if too many)
01890             spare2[--numberPossiblySwapped]=alpha;
01891             index2[numberPossiblySwapped]=iSequence;
01892             if (fabs(alpha)>bestPivot) {
01893               bestPivot=fabs(alpha);
01894               bestSequence=numberPossiblySwapped;
01895             }
01896           } else {
01897             value = oldValue-upperTheta*alpha;
01898             if (value>newTolerance && -alpha>=acceptablePivot) 
01899               upperTheta = (oldValue-newTolerance)/alpha;
01900             spare2[numberRemaining]=alpha;
01901             index2[numberRemaining++]=iSequence;
01902           }
01903         } else {
01904           // at lower bound
01905           if (value<-newTolerance) {
01906             double range = upper_[iSequence] - lower_[iSequence];
01907             thruThis += range*alpha;
01908             //?? is this correct - and should we look at good ones
01909 #if TRYBIAS==1
01910             if (oldValue<0.0)
01911               increaseInThis += oldValue*range;
01912 #elif TRYBIAS==2
01913             increaseInThis += oldValue*range;
01914 #else
01915             increaseInThis += (oldValue-dualTolerance_)*range;
01916 #endif
01917             // goes on swapped list (also means candidates if too many)
01918             spare2[--numberPossiblySwapped]=alpha;
01919             index2[numberPossiblySwapped]=iSequence;
01920             if (fabs(alpha)>bestPivot) {
01921               bestPivot=fabs(alpha);
01922               bestSequence=numberPossiblySwapped;
01923             }
01924           } else {
01925             value = oldValue-upperTheta*alpha;
01926             if (value<-newTolerance && alpha>=acceptablePivot) 
01927               upperTheta = (oldValue+newTolerance)/alpha;
01928             spare2[numberRemaining]=alpha;
01929             index2[numberRemaining++]=iSequence;
01930           }
01931         }
01932       }
01933       swapped[1-iFlip]=numberPossiblySwapped;
01934       interesting[1-iFlip]=numberRemaining;
01935       marker[1-iFlip][0]= max(marker[1-iFlip][0],numberRemaining);
01936       marker[1-iFlip][1]= min(marker[1-iFlip][1],numberPossiblySwapped);
01937       
01938       if (totalThru+thruThis>=fabs(dualOut_)||
01939           increaseInObjective+increaseInThis<0.0) {
01940         // We should be pivoting in this batch
01941         // so compress down to this lot
01942         numberRemaining=0;
01943         for (i=numberColumns_-1;i>=swapped[1-iFlip];i--) {
01944           spare[numberRemaining]=spare2[i];
01945           index[numberRemaining++]=index2[i];
01946         }
01947         interesting[iFlip]=numberRemaining;
01948         int iTry;
01949 #define MAXTRY 100
01950         // first get ratio with tolerance
01951         for (iTry=0;iTry<MAXTRY;iTry++) {
01952           
01953           upperTheta=1.0e50;
01954           numberPossiblySwapped = numberColumns_;
01955           numberRemaining = 0;
01956 
01957           increaseInThis=0.0; //objective increase in this loop
01958 
01959           thruThis=0.0;
01960 
01961           spare = array[iFlip];
01962           index = indices[iFlip];
01963           spare2 = array[1-iFlip];
01964           index2 = indices[1-iFlip];
01965       
01966           for (i=0;i<interesting[iFlip];i++) {
01967             int iSequence=index[i];
01968             double alpha=spare[i];
01969             double oldValue = dj_[iSequence];
01970             double value = oldValue-upperTheta*alpha;
01971             
01972             if (alpha < 0.0) {
01973               //at upper bound
01974               if (value>newTolerance) {
01975                 if (-alpha>=acceptablePivot) {
01976                   upperTheta = (oldValue-newTolerance)/alpha;
01977                   // recompute value and make sure works
01978                   value = oldValue-upperTheta*alpha;
01979                   if (value<0)
01980                     upperTheta *= 1.0 +1.0e-11; // must be large
01981                 }
01982               }
01983             } else {
01984               // at lower bound
01985               if (value<-newTolerance) {
01986                 if (alpha>=acceptablePivot) {
01987                   upperTheta = (oldValue+newTolerance)/alpha;
01988                   // recompute value and make sure works
01989                   value = oldValue-upperTheta*alpha;
01990                   if (value>0)
01991                     upperTheta *= 1.0 +1.0e-11; // must be large
01992                 }
01993               }
01994             }
01995           }
01996           bestPivot=acceptablePivot;
01997           sequenceIn_=-1;
01998           double bestWeight=COIN_DBL_MAX;
01999           double largestPivot=acceptablePivot;
02000           // now choose largest and sum all ones which will go through
02001           //printf("XX it %d number %d\n",numberIterations_,interesting[iFlip]);
02002           for (i=0;i<interesting[iFlip];i++) {
02003             int iSequence=index[i];
02004             double alpha=spare[i];
02005             double value = dj_[iSequence]-upperTheta*alpha;
02006             double badDj=0.0;
02007             
02008             bool addToSwapped=false;
02009             
02010             if (alpha < 0.0) {
02011               //at upper bound
02012               if (value>=0.0) { 
02013                 addToSwapped=true;
02014 #if TRYBIAS==1
02015                 badDj = -max(dj_[iSequence],0.0);
02016 #elif TRYBIAS==2
02017                 badDj = -dj_[iSequence];
02018 #else
02019                 badDj = -dj_[iSequence]-dualTolerance_;
02020 #endif
02021               }
02022             } else {
02023               // at lower bound
02024               if (value<=0.0) {
02025                 addToSwapped=true;
02026 #if TRYBIAS==1
02027                 badDj = min(dj_[iSequence],0.0);
02028 #elif TRYBIAS==2
02029                 badDj = dj_[iSequence];
02030 #else
02031                 badDj = dj_[iSequence]-dualTolerance_;
02032 #endif
02033               }
02034             }
02035             if (!addToSwapped) {
02036               // add to list of remaining
02037               spare2[numberRemaining]=alpha;
02038               index2[numberRemaining++]=iSequence;
02039             } else {
02040               // add to list of swapped
02041               spare2[--numberPossiblySwapped]=alpha;
02042               index2[numberPossiblySwapped]=iSequence;
02043               // select if largest pivot
02044               bool take=false;
02045               double absAlpha = fabs(alpha);
02046               // User could do anything to break ties here
02047               double weight;
02048               if (dubiousWeights)
02049                 weight=dubiousWeights[iSequence];
02050               else
02051                 weight=1.0;
02052               weight += CoinDrand48()*1.0e-2;
02053               if (absAlpha>2.0*bestPivot) {
02054                 take=true;
02055               } else if (absAlpha>0.5*largestPivot) {
02056                 // could multiply absAlpha and weight
02057                 if (weight*bestPivot<bestWeight*absAlpha)
02058                   take=true;
02059               }
02060               if (take) {
02061                 sequenceIn_ = numberPossiblySwapped;
02062                 bestPivot =  absAlpha;
02063                 theta_ = dj_[iSequence]/alpha;
02064                 largestPivot = max(largestPivot,bestPivot);
02065                 bestWeight = weight;
02066                 //printf(" taken seq %d alpha %g weight %d\n",
02067                 //   iSequence,absAlpha,dubiousWeights[iSequence]);
02068               } else {
02069                 //printf(" not taken seq %d alpha %g weight %d\n",
02070                 //   iSequence,absAlpha,dubiousWeights[iSequence]);
02071               }
02072               double range = upper[iSequence] - lower[iSequence];
02073               thruThis += range*fabs(alpha);
02074               increaseInThis += badDj*range;
02075             }
02076           }
02077           swapped[1-iFlip]=numberPossiblySwapped;
02078           interesting[1-iFlip]=numberRemaining;
02079           marker[1-iFlip][0]= max(marker[1-iFlip][0],numberRemaining);
02080           marker[1-iFlip][1]= min(marker[1-iFlip][1],numberPossiblySwapped);
02081           // If we stop now this will be increase in objective (I think)
02082           double increase = (fabs(dualOut_)-totalThru)*theta_;
02083           increase += increaseInObjective;
02084           if (theta_<0.0)
02085             thruThis += fabs(dualOut_); // force using this one
02086           if (increaseInObjective<0.0&&increase<0.0&&lastSequence>=0) {
02087             // back
02088             // We may need to be more careful - we could do by
02089             // switch so we always do fine grained?
02090             bestPivot=0.0;
02091           } else {
02092             // add in
02093             totalThru += thruThis;
02094             increaseInObjective += increaseInThis;
02095           }
02096           if (bestPivot<0.1*bestEverPivot&&
02097               bestEverPivot>1.0e-6&&
02098               (bestPivot<1.0e-3||totalThru*2.0>fabs(dualOut_))) {
02099             // back to previous one
02100             sequenceIn_=lastSequence;
02101             // swap regions
02102             iFlip = 1-iFlip;
02103             break;
02104           } else if (sequenceIn_==-1&&upperTheta>largeValue_) {
02105             if (lastPivot>acceptablePivot) {
02106               // back to previous one
02107               sequenceIn_=lastSequence;
02108               // swap regions
02109               iFlip = 1-iFlip;
02110             } else {
02111               // can only get here if all pivots too small
02112             }
02113             break;
02114           } else if (totalThru>=fabs(dualOut_)) {
02115             modifyCosts=true; // fine grain - we can modify costs
02116             break; // no point trying another loop
02117           } else {
02118             lastSequence=sequenceIn_;
02119             if (bestPivot>bestEverPivot)
02120               bestEverPivot=bestPivot;
02121             iFlip = 1 -iFlip;
02122             modifyCosts=true; // fine grain - we can modify costs
02123           }
02124         }
02125         if (iTry==MAXTRY)
02126           iFlip = 1-iFlip; // flip back
02127         break;
02128       } else {
02129         // skip this lot
02130         if (bestPivot>1.0e-3||bestPivot>bestEverPivot) {
02131           bestEverPivot=bestPivot;
02132           lastSequence=bestSequence;
02133         } else {
02134           // keep old swapped
02135           memcpy(array[1-iFlip]+swapped[iFlip],
02136                  array[iFlip]+swapped[iFlip],
02137                  (numberColumns_-swapped[iFlip])*sizeof(double));
02138           memcpy(indices[1-iFlip]+swapped[iFlip],
02139                  indices[iFlip]+swapped[iFlip],
02140                  (numberColumns_-swapped[iFlip])*sizeof(int));
02141           marker[1-iFlip][1] = min(marker[1-iFlip][1],swapped[iFlip]);
02142           swapped[1-iFlip]=swapped[iFlip];
02143         }
02144         increaseInObjective += increaseInThis;
02145         iFlip = 1 - iFlip; // swap regions
02146         tentativeTheta = 2.0*upperTheta;
02147         totalThru += thruThis;
02148       }
02149     }
02150     
02151     // can get here without sequenceIn_ set but with lastSequence
02152     if (sequenceIn_<0&&lastSequence>=0) {
02153       // back to previous one
02154       sequenceIn_=lastSequence;
02155       // swap regions
02156       iFlip = 1-iFlip;
02157     }
02158     
02159 #define MINIMUMTHETA 1.0e-12
02160     // Movement should be minimum for anti-degeneracy - unless
02161     // fixed variable out
02162     double minimumTheta;
02163     if (upperOut_>lowerOut_)
02164       minimumTheta=MINIMUMTHETA;
02165     else
02166       minimumTheta=0.0;
02167     if (sequenceIn_>=0) {
02168       // at this stage sequenceIn_ is just pointer into index array
02169       // flip just so we can use iFlip
02170       iFlip = 1 -iFlip;
02171       spare = array[iFlip];
02172       index = indices[iFlip];
02173       double oldValue;
02174       alpha_ = spare[sequenceIn_];
02175       sequenceIn_ = indices[iFlip][sequenceIn_];
02176       oldValue = dj_[sequenceIn_];
02177       theta_ = oldValue/alpha_;
02178       if (theta_<minimumTheta) {
02179         // can't pivot to zero
02180         if (oldValue-minimumTheta*alpha_>=-dualTolerance_) {
02181           theta_=minimumTheta;
02182         } else if (oldValue-minimumTheta*alpha_>=-newTolerance) {
02183           theta_=minimumTheta;
02184           thisIncrease=true;
02185         } else {
02186           theta_=(oldValue+newTolerance)/alpha_;
02187           assert(theta_>=0.0);
02188           thisIncrease=true;
02189         } 
02190       }
02191       // may need to adjust costs so all dual feasible AND pivoted is exactly 0
02192       //int costOffset = numberRows_+numberColumns_;
02193       if (modifyCosts) {
02194         int i;
02195         for (i=numberColumns_-1;i>=swapped[iFlip];i--) {
02196           int iSequence=index[i];
02197           double alpha=spare[i];
02198           double value = dj_[iSequence]-theta_*alpha;
02199             
02200           // can't be free here
02201           
02202           if (alpha < 0.0) {
02203             //at upper bound
02204             if (value>dualTolerance_) {
02205               thisIncrease=true;
02206 #define MODIFYCOST 2
02207 #if MODIFYCOST
02208               // modify cost to hit new tolerance
02209               double modification = alpha*theta_-dj_[iSequence]
02210                 +newTolerance;
02211               //modification = min(modification,dualTolerance_);
02212               //assert (fabs(modification)<1.0e-7);
02213               dj_[iSequence] += modification;
02214               cost_[iSequence] +=  modification;
02215               //cost_[iSequence+costOffset] += modification; // save change
02216 #endif
02217             }
02218           } else {
02219             // at lower bound
02220             if (-value>dualTolerance_) {
02221               thisIncrease=true;
02222 #if MODIFYCOST
02223               // modify cost to hit new tolerance
02224               double modification = alpha*theta_-dj_[iSequence]
02225                 -newTolerance;
02226               //modification = max(modification,-dualTolerance_);
02227               //assert (fabs(modification)<1.0e-7);
02228               dj_[iSequence] += modification;
02229               cost_[iSequence] +=  modification;
02230               //cost_[iSequence+costOffset] += modification; // save change
02231 #endif
02232             }
02233           }
02234         }
02235       }
02236     }
02237   }
02238 
02239   if (sequenceIn_>=0) {
02240     lowerIn_ = lower_[sequenceIn_];
02241     upperIn_ = upper_[sequenceIn_];
02242     valueIn_ = solution_[sequenceIn_];
02243     dualIn_ = dj_[sequenceIn_];
02244 
02245     if (numberTimesOptimal_) {
02246       // can we adjust cost back closer to original
02247       //*** add coding
02248     }
02249 #if MODIFYCOST>1    
02250     // modify cost to hit zero exactly
02251     // so (dualIn_+modification)==theta_*alpha_
02252     double modification = theta_*alpha_-dualIn_;
02253     dualIn_ += modification;
02254     dj_[sequenceIn_]=dualIn_;
02255     cost_[sequenceIn_] += modification;
02256     //int costOffset = numberRows_+numberColumns_;
02257     //cost_[sequenceIn_+costOffset] += modification; // save change
02258     //assert (fabs(modification)<1.0e-6);
02259 #ifdef CLP_DEBUG
02260     if ((handler_->logLevel()&32)&&fabs(modification)>1.0e-15)
02261       printf("exact %d new cost %g, change %g\n",sequenceIn_,
02262              cost_[sequenceIn_],modification);
02263 #endif
02264 #endif
02265     
02266     if (alpha_<0.0) {
02267       // as if from upper bound
02268       directionIn_=-1;
02269       upperIn_=valueIn_;
02270     } else {
02271       // as if from lower bound
02272       directionIn_=1;
02273       lowerIn_=valueIn_;
02274     }
02275   }
02276   //if (thisIncrease) 
02277   //dualTolerance_+= 1.0e-6*dblParam_[ClpDualTolerance];
02278 
02279   // clear arrays
02280 
02281   for (i=0;i<2;i++) {
02282     memset(array[i],0,marker[i][0]*sizeof(double));
02283     memset(array[i]+marker[i][1],0,
02284            (numberColumns_-marker[i][1])*sizeof(double));
02285   }
02286 }

void ClpSimplexDual::dualRow int  alreadyChosen  ) 
 

Chooses dual pivot row 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 rows we look at

If alreadyChosen >=0 then in values pass and that row has been selected

Definition at line 1383 of file ClpSimplexDual.cpp.

References CoinIndexedVector::denseVector(), nextSuperBasic(), ClpDualRowPivot::pivotRow(), and ClpSimplex::unpack().

Referenced by whileIterating().

01384 {
01385   // get pivot row using whichever method it is
01386   int chosenRow=-1;
01387   if (alreadyChosen<0) {
01388     // first see if any free variables and put them in basis
01389     int nextFree = nextSuperBasic();
01390     //nextFree=-1; //off
01391     if (nextFree>=0) {
01392       // unpack vector and find a good pivot
01393       unpack(rowArray_[1],nextFree);
01394       factorization_->updateColumn(rowArray_[2],rowArray_[1]);
01395       
01396       double * work=rowArray_[1]->denseVector();
01397       int number=rowArray_[1]->getNumElements();
01398       int * which=rowArray_[1]->getIndices();
01399       double bestFeasibleAlpha=0.0;
01400       int bestFeasibleRow=-1;
01401       double bestInfeasibleAlpha=0.0;
01402       int bestInfeasibleRow=-1;
01403       int i;
01404       
01405       for (i=0;i<number;i++) {
01406         int iRow = which[i];
01407         double alpha = fabs(work[iRow]);
01408         if (alpha>1.0e-3) {
01409           int iSequence=pivotVariable_[iRow];
01410           double value = solution_[iSequence];
01411           double lower = lower_[iSequence];
01412           double upper = upper_[iSequence];
01413           double infeasibility=0.0;
01414           if (value>upper)
01415             infeasibility = value-upper;
01416           else if (value<lower)
01417             infeasibility = lower-value;
01418           if (infeasibility*alpha>bestInfeasibleAlpha&&alpha>1.0e-1) {
01419             if (!flagged(iSequence)) {
01420               bestInfeasibleAlpha = infeasibility*alpha;
01421               bestInfeasibleRow=iRow;
01422             }
01423           }
01424           if (alpha>bestFeasibleAlpha&&(lower>-1.0e20||upper<1.0e20)) {
01425             bestFeasibleAlpha = alpha;
01426             bestFeasibleRow=iRow;
01427           }
01428         }
01429       }
01430       if (bestInfeasibleRow>=0) 
01431         chosenRow = bestInfeasibleRow;
01432       else if (bestFeasibleAlpha>1.0e-2)
01433         chosenRow = bestFeasibleRow;
01434       if (chosenRow>=0)
01435         pivotRow_=chosenRow;
01436       rowArray_[1]->clear();
01437     } 
01438   } else {
01439     // in values pass
01440     chosenRow=alreadyChosen;
01441     pivotRow_=chosenRow;
01442   }
01443   if (chosenRow<0) 
01444     pivotRow_=dualRowPivot_->pivotRow();
01445 
01446   if (pivotRow_>=0) {
01447     sequenceOut_ = pivotVariable_[pivotRow_];
01448     valueOut_ = solution_[sequenceOut_];
01449     lowerOut_ = lower_[sequenceOut_];
01450     upperOut_ = upper_[sequenceOut_];
01451     if (alreadyChosen<0) {
01452       // if we have problems we could try other way and hope we get a 
01453       // zero pivot?
01454       if (valueOut_>upperOut_) {
01455         directionOut_ = -1;
01456         dualOut_ = valueOut_ - upperOut_;
01457       } else if (valueOut_<lowerOut_) {
01458         directionOut_ = 1;
01459         dualOut_ = lowerOut_ - valueOut_;
01460       } else {
01461         // odd (could be free) - it's feasible - go to nearest
01462         if (valueOut_-lowerOut_<upperOut_-valueOut_) {
01463           directionOut_ = 1;
01464           dualOut_ = lowerOut_ - valueOut_;
01465         } else {
01466           directionOut_ = -1;
01467           dualOut_ = valueOut_ - upperOut_;
01468         }
01469       }
01470 #ifdef CLP_DEBUG
01471       assert(dualOut_>=0.0);
01472 #endif
01473     } else {
01474       // in values pass so just use sign of dj
01475       // We don't want to go through any barriers so set dualOut low
01476       // free variables will never be here
01477       dualOut_ = 1.0e-6;
01478       if (dj_[sequenceOut_]>0.0) {
01479         // this will give a -1 in pivot row (as slacks are -1.0)
01480         directionOut_ = 1;
01481       } else {
01482         directionOut_ = -1;
01483       }
01484     }
01485   }
01486   return ;
01487 }

int ClpSimplexDual::fastDual bool  alwaysFinish = false  ) 
 

Fast iterations. Misses out a lot of initialization. Normally stops on maximum iterations, first re-factorization or tentative optimum. If looks interesting then continues as normal. Returns 0 if finished properly, 1 otherwise.

Definition at line 3636 of file ClpSimplexDual.cpp.

References changeBounds(), CoinIndexedVector::clear(), ClpSimplex::gutsOfSolution(), numberAtFakeBound(), ClpModel::objectiveValue(), ClpMatrixBase::refresh(), ClpSimplex::restoreData(), ClpSimplex::saveData(), statusOfProblemInDual(), and whileIterating().

Referenced by strongBranching().

03637 {
03638   algorithm_ = -1;
03639   // save data
03640   ClpDataSave data = saveData();
03641   dualTolerance_=dblParam_[ClpDualTolerance];
03642   primalTolerance_=dblParam_[ClpPrimalTolerance];
03643 
03644   // save dual bound
03645   double saveDualBound = dualBound_;
03646 
03647   double objectiveChange;
03648   // for dual we will change bounds using dualBound_
03649   // for this we need clean basis so it is after factorize
03650   gutsOfSolution(NULL,NULL);
03651   numberFake_ =0; // Number of variables at fake bounds
03652   changeBounds(true,NULL,objectiveChange);
03653 
03654   problemStatus_ = -1;
03655   numberIterations_=0;
03656   factorization_->sparseThreshold(0);
03657   factorization_->goSparse();
03658 
03659   int lastCleaned=0; // last time objective or bounds cleaned up
03660 
03661   // number of times we have declared optimality
03662   numberTimesOptimal_=0;
03663 
03664   // This says whether to restore things etc
03665   int factorType=0;
03666   /*
03667     Status of problem:
03668     0 - optimal
03669     1 - infeasible
03670     2 - unbounded
03671     -1 - iterating
03672     -2 - factorization wanted
03673     -3 - redo checking without factorization
03674     -4 - looks infeasible
03675 
03676     BUT also from whileIterating return code is:
03677 
03678    -1 iterations etc
03679    -2 inaccuracy 
03680    -3 slight inaccuracy (and done iterations)
03681    +0 looks optimal (might be unbounded - but we will investigate)
03682    +1 looks infeasible
03683    +3 max iterations 
03684 
03685   */
03686 
03687   int returnCode = 0;
03688 
03689   int iRow,iColumn;
03690   while (problemStatus_<0) {
03691     // clear
03692     for (iRow=0;iRow<4;iRow++) {
03693       rowArray_[iRow]->clear();
03694     }    
03695     
03696     for (iColumn=0;iColumn<2;iColumn++) {
03697       columnArray_[iColumn]->clear();
03698     }    
03699 
03700     // give matrix (and model costs and bounds a chance to be
03701     // refreshed (normally null)
03702     matrix_->refresh(this);
03703     // may factorize, checks if problem finished
03704     // should be able to speed this up on first time
03705     statusOfProblemInDual(lastCleaned,factorType,progress_,NULL);
03706 
03707     // Say good factorization
03708     factorType=1;
03709 
03710     // Do iterations
03711     if (problemStatus_<0) {
03712       double * givenPi=NULL;
03713       returnCode = whileIterating(givenPi);
03714       if (!alwaysFinish&&(returnCode<1||returnCode==3)) {
03715         double limit = 0.0;
03716         getDblParam(ClpDualObjectiveLimit, limit);
03717         if(fabs(limit)>1.0e30||objectiveValue()*optimizationDirection_<
03718            limit|| 
03719            numberAtFakeBound()) {
03720           returnCode=1;
03721           secondaryStatus_ = 1; // and say was on cutoff
03722           // can't say anything interesting - might as well return
03723 #ifdef CLP_DEBUG
03724           printf("returning from fastDual after %d iterations with code %d\n",
03725                  numberIterations_,returnCode);
03726 #endif
03727           break;
03728         }
03729       }
03730       returnCode=0;
03731     }
03732   }
03733 
03734   // clear
03735   for (iRow=0;iRow<4;iRow++) {
03736     rowArray_[iRow]->clear();
03737   }    
03738   
03739   for (iColumn=0;iColumn<2;iColumn++) {
03740     columnArray_[iColumn]->clear();
03741   }    
03742   assert(!numberFake_||returnCode||problemStatus_); // all bounds should be okay
03743   // Restore any saved stuff
03744   restoreData(data);
03745   dualBound_ = saveDualBound;
03746   return returnCode;
03747 }

void ClpSimplexDual::flipBounds CoinIndexedVector rowArray,
CoinIndexedVector columnArray,
double  change
 

While updateDualsInDual sees what effect is of flip this does actuall flipping. If change >0.0 then value in array >0.0 => from lower to upper

Definition at line 2853 of file ClpSimplexDual.cpp.

References CoinIndexedVector::getIndices(), CoinIndexedVector::getNumElements(), CoinIndexedVector::setNumElements(), and ClpSimplex::solutionRegion().

Referenced by updateDualsInDual(), and whileIterating().

02856 {
02857   int number;
02858   int * which;
02859   
02860   int iSection;
02861 
02862   for (iSection=0;iSection<2;iSection++) {
02863     int i;
02864     double * solution = solutionRegion(iSection);
02865     double * lower = lowerRegion(iSection);
02866     double * upper = upperRegion(iSection);
02867     int addSequence;
02868     if (!iSection) {
02869       number = rowArray->getNumElements();
02870       which = rowArray->getIndices();
02871       addSequence = numberColumns_;
02872     } else {
02873       number = columnArray->getNumElements();
02874       which = columnArray->getIndices();
02875       addSequence = 0;
02876     }
02877     
02878     for (i=0;i<number;i++) {
02879       int iSequence = which[i];
02880       Status status = getStatus(iSequence+addSequence);
02881 
02882       switch(status) {
02883 
02884       case basic:
02885       case isFree:
02886       case superBasic:
02887       case ClpSimplex::isFixed:
02888         break;
02889       case atUpperBound:
02890         // to lower bound
02891         setStatus(iSequence+addSequence,atLowerBound);
02892         solution[iSequence] = lower[iSequence];
02893         break;
02894       case atLowerBound:
02895         // to upper bound 
02896         setStatus(iSequence+addSequence,atUpperBound);
02897         solution[iSequence] = upper[iSequence];
02898         break;
02899       }
02900     }
02901   }
02902   rowArray->setNumElements(0);
02903   columnArray->setNumElements(0);
02904 }

int ClpSimplexDual::nextSuperBasic  ) 
 

Get next free , -1 if none

Definition at line 4129 of file ClpSimplexDual.cpp.

Referenced by dualRow().

04130 {
04131   if (firstFree_>=0) {
04132     int returnValue=firstFree_;
04133     int iColumn=firstFree_+1;
04134     for (;iColumn<numberRows_+numberColumns_;iColumn++) {
04135       if (getStatus(iColumn)==isFree) 
04136         if (fabs(dj_[iColumn])>1.0e2*dualTolerance_) 
04137           break;
04138     }
04139     firstFree_ = iColumn;
04140     if (firstFree_==numberRows_+numberColumns_)
04141       firstFree_=-1;
04142     return returnValue;
04143   } else {
04144     return -1;
04145   }
04146 }

int ClpSimplexDual::numberAtFakeBound  ) 
 

Checks number of variables at fake bounds. This is used by fastDual so can exit gracefully before end

Definition at line 3751 of file ClpSimplexDual.cpp.

Referenced by fastDual(), and statusOfProblemInDual().

03752 {
03753   int iSequence;
03754   int numberFake=0;
03755   
03756   for (iSequence=0;iSequence<numberRows_+numberColumns_;iSequence++) {
03757     FakeBound bound = getFakeBound(iSequence);
03758     switch(getStatus(iSequence)) {
03759 
03760     case basic:
03761       break;
03762     case isFree:
03763     case superBasic:
03764     case ClpSimplex::isFixed:
03765       assert (bound==noFake);
03766       break;
03767     case atUpperBound:
03768       if (bound==upperFake||bound==bothFake)
03769         numberFake++;
03770       break;
03771     case atLowerBound:
03772       if (bound==lowerFake||bound==bothFake)
03773         numberFake++;
03774       break;
03775     }
03776   }
03777   numberFake_ = numberFake;
03778   return numberFake;
03779 }

int ClpSimplexDual::pivotResult  ) 
 

Pivot in a variable and choose an outgoing one. Assumes dual feasible - will not go through a reduced cost. Returns step length in theta Returns ray in ray_ (or NULL if no pivot) Return codes as before but -1 means no acceptable pivot

Definition at line 3787 of file ClpSimplexDual.cpp.

03788 {
03789   abort();
03790   return 0;
03791 }

void ClpSimplexDual::statusOfProblemInDual int &  lastCleaned,
int  type,
ClpSimplexProgress progress,
double *  givenDjs
 

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

Definition at line 2351 of file ClpSimplexDual.cpp.

References changeBounds(), ClpSimplex::checkDualSolution(), checkUnbounded(), CoinIndexedVector::clear(), ClpSimplexProgress::clearBadTimes(), ClpSimplex::computeDuals(), ClpSimplex::createRim(), CoinIndexedVector::denseVector(), ClpSimplex::dualFeasible(), ClpSimplex::gutsOfSolution(), ClpSimplex::isColumn(), ClpSimplexProgress::lastIterationNumber(), ClpSimplexProgress::lastObjective(), ClpDualRowPivot::looksOptimal(), ClpSimplexProgress::looping(), CoinMessageHandler::message(), ClpSimplexProgress::modifyObjective(), numberAtFakeBound(), ClpModel::objectiveValue(), ClpSimplex::originalLower(), ClpSimplex::originalUpper(), ClpSimplex::primalFeasible(), CoinMessageHandler::printing(), ClpDualRowPivot::saveWeights(), ClpSimplex::sequenceWithin(), ClpSimplex::setFlagged(), ClpSimplex::unpack(), and updateDualsInDual().

Referenced by dual(), and fastDual().

02354 {
02355   bool normalType=true;
02356   if (type==2) {
02357     // trouble - restore solution
02358     memcpy(status_ ,saveStatus_,(numberColumns_+numberRows_)*sizeof(char));
02359     memcpy(rowActivityWork_,savedSolution_+numberColumns_ ,
02360            numberRows_*sizeof(double));
02361     memcpy(columnActivityWork_,savedSolution_ ,
02362            numberColumns_*sizeof(double));
02363     forceFactorization_=1; // a bit drastic but ..
02364     changeMade_++; // say something changed
02365   }
02366   int tentativeStatus = problemStatus_;
02367   double changeCost;
02368   bool unflagVariables = true;
02369   if (problemStatus_>-3||factorization_->pivots()) {
02370     // factorize
02371     // later on we will need to recover from singularities
02372     // also we could skip if first time
02373     // save dual weights
02374     dualRowPivot_->saveWeights(this,1);
02375     if (type) {
02376       // is factorization okay?
02377       if (internalFactorize(1)) {
02378         // no - restore previous basis
02379         unflagVariables = false;
02380         assert (type==1);
02381         changeMade_++; // say something changed
02382         memcpy(status_ ,saveStatus_,(numberColumns_+numberRows_)*sizeof(char));
02383         memcpy(rowActivityWork_,savedSolution_+numberColumns_ ,
02384                numberRows_*sizeof(double));
02385         memcpy(columnActivityWork_,savedSolution_ ,
02386                numberColumns_*sizeof(double));
02387         // get correct bounds on all variables
02388         double dummyChangeCost=0.0;
02389         changeBounds(true,rowArray_[2],dummyChangeCost);
02390         // throw away change
02391         int i;
02392         for (i=0;i<4;i++) 
02393           rowArray_[i]->clear();
02394         // need to reject something
02395         char x = isColumn(sequenceOut_) ? 'C' :'R';
02396         handler_->message(CLP_SIMPLEX_FLAG,messages_)
02397           <<x<<sequenceWithin(sequenceOut_)
02398           <<CoinMessageEol;
02399         setFlagged(sequenceOut_);
02400         progress_->clearBadTimes();
02401         
02402         forceFactorization_=1; // a bit drastic but ..
02403         type = 2;
02404         //assert (internalFactorize(1)==0);
02405         if (internalFactorize(1)) {
02406           memcpy(status_ ,saveStatus_,(numberColumns_+numberRows_)*sizeof(char));
02407           memcpy(rowActivityWork_,savedSolution_+numberColumns_ ,
02408                  numberRows_*sizeof(double));
02409           memcpy(columnActivityWork_,savedSolution_ ,
02410                  numberColumns_*sizeof(double));
02411           // debug
02412 #ifndef NDEBUG
02413           int returnCode = internalFactorize(1);
02414           assert (returnCode==0);
02415 #else
02416           internalFactorize(1);
02417 #endif
02418         }
02419       }
02420     }
02421     if (problemStatus_!=-4||factorization_->pivots()>10)
02422       problemStatus_=-3;
02423   }
02424   // at this stage status is -3 or -4 if looks infeasible
02425   // get primal and dual solutions
02426   gutsOfSolution(givenDuals,NULL);
02427   // Double check infeasibility if no action
02428   if (progress->lastIterationNumber(0)==numberIterations_) {
02429     if (dualRowPivot_->looksOptimal()) {
02430       numberPrimalInfeasibilities_ = 0;
02431       sumPrimalInfeasibilities_ = 0.0;
02432     }
02433   }
02434   // Check if looping
02435   int loop;
02436   if (!givenDuals&&type!=2) 
02437     loop = progress->looping();
02438   else
02439     loop=-1;
02440   int situationChanged=0;
02441   if (loop>=0) {
02442     problemStatus_ = loop; //exit if in loop
02443     if (!problemStatus_) {
02444       // declaring victory
02445       numberPrimalInfeasibilities_ = 0;
02446       sumPrimalInfeasibilities_ = 0.0;
02447     } else {
02448       problemStatus_ = 10; // instead - try other algorithm
02449     }
02450     return;
02451   } else if (loop<-1) {
02452     // something may have changed
02453     gutsOfSolution(NULL,NULL);
02454     situationChanged=1;
02455   }
02456   // really for free variables in
02457   if((progressFlag_&2)!=0) {
02458     situationChanged=2;
02459   }
02460   progressFlag_ = 0; //reset progress flag
02461   handler_->message(CLP_SIMPLEX_STATUS,messages_)
02462     <<numberIterations_<<objectiveValue();
02463   handler_->printing(sumPrimalInfeasibilities_>0.0)
02464     <<sumPrimalInfeasibilities_<<numberPrimalInfeasibilities_;
02465   handler_->printing(sumDualInfeasibilities_>0.0)
02466     <<sumDualInfeasibilities_<<numberDualInfeasibilities_;
02467   handler_->printing(numberDualInfeasibilitiesWithoutFree_
02468                      <numberDualInfeasibilities_)
02469                        <<numberDualInfeasibilitiesWithoutFree_;
02470   handler_->message()<<CoinMessageEol;
02471 
02472   // dual bound coming in
02473   //double saveDualBound = dualBound_;
02474   while (problemStatus_<=-3) {
02475     int cleanDuals=0;
02476     if (situationChanged!=0)
02477       cleanDuals=1;
02478     int numberChangedBounds=0;
02479     int doOriginalTolerance=0;
02480     if ( lastCleaned==numberIterations_)
02481       doOriginalTolerance=1;
02482     // check optimal
02483     // give code benefit of doubt
02484     if (sumOfRelaxedDualInfeasibilities_ == 0.0&&
02485         sumOfRelaxedPrimalInfeasibilities_ == 0.0) {
02486       // say optimal (with these bounds etc)
02487       numberDualInfeasibilities_ = 0;
02488       sumDualInfeasibilities_ = 0.0;
02489       numberPrimalInfeasibilities_ = 0;
02490       sumPrimalInfeasibilities_ = 0.0;
02491     }
02492     //if (dualFeasible()||problemStatus_==-4||(primalFeasible()&&!numberDualInfeasibilitiesWithoutFree_)) {
02493     if (dualFeasible()||problemStatus_==-4) {
02494       progress->modifyObjective(objectiveValue_
02495                                -sumDualInfeasibilities_*dualBound_);
02496       if (primalFeasible()) {
02497         normalType=false;
02498         // may be optimal - or may be bounds are wrong
02499         handler_->message(CLP_DUAL_BOUNDS,messages_)
02500           <<dualBound_
02501           <<CoinMessageEol;
02502         // save solution in case unbounded
02503         ClpDisjointCopyN(columnActivityWork_,numberColumns_,
02504                           columnArray_[0]->denseVector());
02505         ClpDisjointCopyN(rowActivityWork_,numberRows_,
02506                           rowArray_[2]->denseVector());
02507         numberChangedBounds=changeBounds(false,rowArray_[3],changeCost);
02508         if (numberChangedBounds<=0&&!numberDualInfeasibilities_) {
02509           //looks optimal - do we need to reset tolerance
02510           if (perturbation_==101) {
02511             perturbation_=102; // stop any perturbations
02512             cleanDuals=1;
02513             createRim(4);
02514             // make sure fake bounds are back
02515             changeBounds(true,NULL,changeCost);
02516           }
02517           if (lastCleaned<numberIterations_&&numberTimesOptimal_<4) {
02518             doOriginalTolerance=2;
02519             numberTimesOptimal_++;
02520             changeMade_++; // say something changed
02521             if (numberTimesOptimal_==1) {
02522               dualTolerance_ = dblParam_[ClpDualTolerance];
02523               // better to have small tolerance even if slower
02524               factorization_->zeroTolerance(1.0e-15);
02525             } else {
02526               dualTolerance_ = dblParam_[ClpDualTolerance];
02527               dualTolerance_ *= pow(2.0,numberTimesOptimal_-1);
02528             }
02529             cleanDuals=2; // If nothing changed optimal else primal
02530           } else {
02531             problemStatus_=0; // optimal
02532             if (lastCleaned<numberIterations_) {
02533               handler_->message(CLP_SIMPLEX_GIVINGUP,messages_)
02534                 <<CoinMessageEol;
02535             }
02536           }
02537         } else {
02538           cleanDuals=1;
02539           if (doOriginalTolerance==1) {
02540             // check unbounded
02541             // find a variable with bad dj
02542             int iSequence;
02543             int iChosen=-1;
02544             double largest = 100.0*primalTolerance_;
02545             for (iSequence=0;iSequence<numberRows_+numberColumns_;
02546                  iSequence++) {
02547               double djValue = dj_[iSequence];
02548               double originalLo = originalLower(iSequence);
02549               double originalUp = originalUpper(iSequence);
02550               if (fabs(djValue)>fabs(largest)) {
02551                 if (getStatus(iSequence)!=basic) {
02552                   if (djValue>0&&originalLo<-1.0e20) {
02553                     if (djValue>fabs(largest)) {
02554                       largest=djValue;
02555                       iChosen=iSequence;
02556                     }
02557                   } else if (djValue<0&&originalUp>1.0e20) {
02558                     if (-djValue>fabs(largest)) {
02559                       largest=djValue;
02560                       iChosen=iSequence;
02561                     }
02562                   } 
02563                 }
02564               }
02565             }
02566             if (iChosen>=0) {
02567               int iSave=sequenceIn_;
02568               sequenceIn_=iChosen;
02569               unpack(rowArray_[1]);
02570               sequenceIn_ = iSave;
02571               // if dual infeasibilities then must be free vector so add in dual
02572               if (numberDualInfeasibilities_) {
02573                 if (fabs(changeCost)>1.0e-5)
02574                   printf("Odd free/unbounded combo\n");
02575                 changeCost += cost_[iChosen];
02576               }
02577               problemStatus_ = checkUnbounded(rowArray_[1],rowArray_[0],
02578                                               changeCost);
02579               rowArray_[1]->clear();
02580             } else {
02581               problemStatus_=-3;
02582             }
02583             if (problemStatus_==2&&perturbation_==101) {
02584               perturbation_=102; // stop any perturbations
02585               cleanDuals=1;
02586               createRim(4);
02587               problemStatus_=-1;
02588             }
02589             if (problemStatus_==2) {
02590               // it is unbounded - restore solution
02591               // but first add in changes to non-basic
02592               int iColumn;
02593               double * original = columnArray_[0]->denseVector();
02594               for (iColumn=0;iColumn<numberColumns_;iColumn++) {
02595                 if(getColumnStatus(iColumn)!= basic)
02596                   ray_[iColumn] += 
02597                     columnActivityWork_[iColumn]-original[iColumn];
02598                 columnActivityWork_[iColumn] = original[iColumn];
02599               }
02600               ClpDisjointCopyN(rowArray_[2]->denseVector(),numberRows_,
02601                                 rowActivityWork_);
02602             }
02603           } else {
02604             doOriginalTolerance=2;
02605             rowArray_[0]->clear();
02606           }
02607         }
02608         ClpFillN(columnArray_[0]->denseVector(),numberColumns_,0.0);
02609         ClpFillN(rowArray_[2]->denseVector(),numberRows_,0.0);
02610       } 
02611       if (problemStatus_==-4||problemStatus_==5) {
02612         // may be infeasible - or may be bounds are wrong
02613         numberChangedBounds=changeBounds(false,NULL,changeCost);
02614         /* Should this be here as makes no difference to being feasible.
02615            But seems to make a difference to run times. */
02616         if (perturbation_==101&&0) {
02617           perturbation_=102; // stop any perturbations
02618           cleanDuals=1;
02619           numberChangedBounds=1;
02620           // make sure fake bounds are back
02621           changeBounds(true,NULL,changeCost);
02622           createRim(4);
02623         }
02624         if (numberChangedBounds<=0||dualBound_>1.0e20||
02625             (largestPrimalError_>1.0&&dualBound_>1.0e17)) {
02626           problemStatus_=1; // infeasible
02627           if (perturbation_==101) {
02628             perturbation_=102; // stop any perturbations
02629             //cleanDuals=1;
02630             //numberChangedBounds=1;
02631             //createRim(4);
02632           }
02633         } else {
02634           normalType=false;
02635           problemStatus_=-1; //iterate
02636           cleanDuals=1;
02637           if (numberChangedBounds<=0)
02638             doOriginalTolerance=2;
02639           // and delete ray which has been created
02640           delete [] ray_;
02641           ray_ = NULL;
02642         }
02643 
02644       }
02645     } else {
02646       cleanDuals=1;
02647     }
02648     if (problemStatus_<0) {
02649       if (doOriginalTolerance==2) {
02650         // put back original tolerance
02651         lastCleaned=numberIterations_;
02652         handler_->message(CLP_DUAL_ORIGINAL,messages_)
02653           <<CoinMessageEol;
02654         perturbation_=102; // stop any perturbations
02655 #if 0
02656         double * xcost = new double[numberRows_+numberColumns_];
02657         double * xlower = new double[numberRows_+numberColumns_];
02658         double * xupper = new double[numberRows_+numberColumns_];
02659         double * xdj = new double[numberRows_+numberColumns_];
02660         double * xsolution = new double[numberRows_+numberColumns_];
02661         memcpy(xcost,cost_,(numberRows_+numberColumns_)*sizeof(double));
02662         memcpy(xlower,lower_,(numberRows_+numberColumns_)*sizeof(double));
02663         memcpy(xupper,upper_,(numberRows_+numberColumns_)*sizeof(double));
02664         memcpy(xdj,dj_,(numberRows_+numberColumns_)*sizeof(double));
02665         memcpy(xsolution,solution_,(numberRows_+numberColumns_)*sizeof(double));
02666 #endif
02667         createRim(4);
02668         // make sure duals are current
02669         computeDuals(givenDuals);
02670         checkDualSolution();
02671 #if 0
02672         int i;
02673         for (i=0;i<numberRows_+numberColumns_;i++) {
02674           if (cost_[i]!=xcost[i])
02675             printf("** %d old cost %g new %g sol %g\n",
02676                    i,xcost[i],cost_[i],solution_[i]);
02677           if (lower_[i]!=xlower[i])
02678             printf("** %d old lower %g new %g sol %g\n",
02679                    i,xlower[i],lower_[i],solution_[i]);
02680           if (upper_[i]!=xupper[i])
02681             printf("** %d old upper %g new %g sol %g\n",
02682                    i,xupper[i],upper_[i],solution_[i]);
02683           if (dj_[i]!=xdj[i])
02684             printf("** %d old dj %g new %g sol %g\n",
02685                    i,xdj[i],dj_[i],solution_[i]);
02686           if (solution_[i]!=xsolution[i])
02687             printf("** %d old solution %g new %g sol %g\n",
02688                    i,xsolution[i],solution_[i],solution_[i]);
02689         }
02690         //delete [] xcost;
02691         //delete [] xupper;
02692         //delete [] xlower;
02693         //delete [] xdj;
02694         //delete [] xsolution;
02695 #endif
02696         // put back bounds as they were if was optimal
02697         if (doOriginalTolerance==2) {
02698           changeMade_++; // say something changed
02699           changeBounds(true,NULL,changeCost);
02700           cleanDuals=2;
02701           //cleanDuals=1;
02702         }
02703 #if 0
02704         //int i;
02705         for (i=0;i<numberRows_+numberColumns_;i++) {
02706           if (cost_[i]!=xcost[i])
02707             printf("** %d old cost %g new %g sol %g\n",
02708                    i,xcost[i],cost_[i],solution_[i]);
02709           if (lower_[i]!=xlower[i])
02710             printf("** %d old lower %g new %g sol %g\n",
02711                    i,xlower[i],lower_[i],solution_[i]);
02712           if (upper_[i]!=xupper[i])
02713             printf("** %d old upper %g new %g sol %g\n",
02714                    i,xupper[i],upper_[i],solution_[i]);
02715           if (dj_[i]!=xdj[i])
02716             printf("** %d old dj %g new %g sol %g\n",
02717                    i,xdj[i],dj_[i],solution_[i]);
02718           if (solution_[i]!=xsolution[i])
02719             printf("** %d old solution %g new %g sol %g\n",
02720                    i,xsolution[i],solution_[i],solution_[i]);
02721         }
02722         delete [] xcost;
02723         delete [] xupper;
02724         delete [] xlower;
02725         delete [] xdj;
02726         delete [] xsolution;
02727 #endif
02728       }
02729       if (cleanDuals==1||(cleanDuals==2&&!numberDualInfeasibilities_)) {
02730         // make sure dual feasible
02731         // look at all rows and columns
02732         rowArray_[0]->clear();
02733         columnArray_[0]->clear();
02734         double objectiveChange=0.0;
02735 #if 0
02736         double * xcost = new double[numberRows_+numberColumns_];
02737         double * xlower = new double[numberRows_+numberColumns_];
02738         double * xupper = new double[numberRows_+numberColumns_];
02739         double * xdj = new double[numberRows_+numberColumns_];
02740         double * xsolution = new double[numberRows_+numberColumns_];
02741         memcpy(xcost,cost_,(numberRows_+numberColumns_)*sizeof(double));
02742         memcpy(xlower,lower_,(numberRows_+numberColumns_)*sizeof(double));
02743         memcpy(xupper,upper_,(numberRows_+numberColumns_)*sizeof(double));
02744         memcpy(xdj,dj_,(numberRows_+numberColumns_)*sizeof(double));
02745         memcpy(xsolution,solution_,(numberRows_+numberColumns_)*sizeof(double));
02746 #endif
02747         updateDualsInDual(rowArray_[0],columnArray_[0],rowArray_[1],
02748           0.0,objectiveChange,true);
02749 #if 0
02750         int i;
02751         for (i=0;i<numberRows_+numberColumns_;i++) {
02752           if (cost_[i]!=xcost[i])
02753             printf("** %d old cost %g new %g sol %g\n",
02754                    i,xcost[i],cost_[i],solution_[i]);
02755           if (lower_[i]!=xlower[i])
02756             printf("** %d old lower %g new %g sol %g\n",
02757                    i,xlower[i],lower_[i],solution_[i]);
02758           if (upper_[i]!=xupper[i])
02759             printf("** %d old upper %g new %g sol %g\n",
02760                    i,xupper[i],upper_[i],solution_[i]);
02761           if (dj_[i]!=xdj[i])
02762             printf("** %d old dj %g new %g sol %g\n",
02763                    i,xdj[i],dj_[i],solution_[i]);
02764           if (solution_[i]!=xsolution[i])
02765             printf("** %d old solution %g new %g sol %g\n",
02766                    i,xsolution[i],solution_[i],solution_[i]);
02767         }
02768         delete [] xcost;
02769         delete [] xupper;
02770         delete [] xlower;
02771         delete [] xdj;
02772         delete [] xsolution;
02773 #endif
02774         // for now - recompute all
02775         gutsOfSolution(NULL,NULL);
02776         updateDualsInDual(rowArray_[0],columnArray_[0],rowArray_[1],
02777                   0.0,objectiveChange,true);
02778         //assert(numberDualInfeasibilitiesWithoutFree_==0);
02779 
02780         if (numberDualInfeasibilities_||situationChanged==2) 
02781           problemStatus_=-1; // carry on as normal
02782         situationChanged=0;
02783       } else {
02784         // iterate
02785         if (cleanDuals!=2) 
02786           problemStatus_=-1;
02787         else
02788           problemStatus_ = 10; // try primal
02789       }
02790     }
02791   }
02792   if (type==0||type==1) {
02793     if (!type) {
02794       // create save arrays
02795       delete [] saveStatus_;
02796       delete [] savedSolution_;
02797       saveStatus_ = new unsigned char [numberRows_+numberColumns_];
02798       savedSolution_ = new double [numberRows_+numberColumns_];
02799     }
02800     // save arrays
02801     memcpy(saveStatus_,status_,(numberColumns_+numberRows_)*sizeof(char));
02802     memcpy(savedSolution_+numberColumns_ ,rowActivityWork_,
02803            numberRows_*sizeof(double));
02804     memcpy(savedSolution_ ,columnActivityWork_,numberColumns_*sizeof(double));
02805   }
02806 
02807   // restore weights (if saved) - also recompute infeasibility list
02808   if (tentativeStatus>-3) 
02809     dualRowPivot_->saveWeights(this,(type <2) ? 2 : 4);
02810   else
02811     dualRowPivot_->saveWeights(this,3);
02812   // unflag all variables (we may want to wait a bit?)
02813   if (tentativeStatus!=-2&&unflagVariables) {
02814     int iRow;
02815     for (iRow=0;iRow<numberRows_;iRow++) {
02816       int iPivot=pivotVariable_[iRow];
02817       clearFlagged(iPivot);
02818     }
02819   }
02820   // see if cutoff reached
02821   double limit = 0.0;
02822   getDblParam(ClpDualObjectiveLimit, limit);
02823   if(fabs(limit)<1.0e30&&objectiveValue()*optimizationDirection_>
02824            limit&&
02825            !numberAtFakeBound()&&!numberDualInfeasibilities_) {
02826     problemStatus_=1;
02827     secondaryStatus_ = 1; // and say was on cutoff
02828   }
02829   if (problemStatus_<0&&!changeMade_) {
02830     problemStatus_=4; // unknown
02831   }
02832   lastGoodIteration_ = numberIterations_;
02833 #if 0
02834   double thisObj = progress->lastObjective(0);
02835   double lastObj = progress->lastObjective(1);
02836   if (lastObj>thisObj+1.0e-6*max(fabs(thisObj),fabs(lastObj))+1.0e-8
02837       &&givenDuals==NULL) {
02838     int maxFactor = factorization_->maximumPivots();
02839     if (maxFactor>10) {
02840       if (forceFactorization_<0)
02841         forceFactorization_= maxFactor;
02842       forceFactorization_ = max (1,(forceFactorization_>>1));
02843       printf("Reducing factorization frequency\n");
02844     } 
02845   }
02846 #endif
02847 }

int ClpSimplexDual::strongBranching int  numberVariables,
const int *  variables,
double *  newLower,
double *  newUpper,
double **  outputSolution,
int *  outputStatus,
int *  outputIterations,
bool  stopOnFirstInfeasible = true,
bool  alwaysFinish = false
 

For strong branching. On input lower and upper are new bounds while on output they are change in objective function values (>1.0e50 infeasible). Return code is 0 if nothing interesting, -1 if infeasible both ways and +1 if infeasible one way (check values to see which one(s)) Solutions are filled in as well - even down, odd up - also status and number of iterations

Reimplemented from ClpSimplex.

Definition at line 3306 of file ClpSimplexDual.cpp.

References ClpSimplex::checkPrimalSolution(), ClpSimplex::createRim(), ClpSimplex::deleteRim(), dual(), fastDual(), ClpModel::isDualObjectiveLimitReached(), CoinMessageHandler::message(), and ClpModel::objectiveValue().

03312 {
03313   int i;
03314   int returnCode=0;
03315   double saveObjectiveValue = objectiveValue_;
03316 #if 1
03317   algorithm_ = -1;
03318 
03319   //scaling(false);
03320 
03321   // put in standard form (and make row copy)
03322   // create modifiable copies of model rim and do optional scaling
03323   createRim(7+8+16,true);
03324 
03325   // change newLower and newUpper if scaled
03326 
03327   // Do initial factorization
03328   // and set certain stuff
03329   // We can either set increasing rows so ...IsBasic gives pivot row
03330   // or we can just increment iBasic one by one
03331   // for now let ...iBasic give pivot row
03332   factorization_->increasingRows(2);
03333   // row activities have negative sign
03334   factorization_->slackValue(-1.0);
03335   factorization_->zeroTolerance(1.0e-13);
03336 
03337   int factorizationStatus = internalFactorize(0);
03338   if (factorizationStatus<0)
03339     return 1; // some error
03340   else if (factorizationStatus)
03341     handler_->message(CLP_SINGULARITIES,messages_)
03342       <<factorizationStatus
03343       <<CoinMessageEol;
03344   
03345   // save stuff
03346   ClpFactorization saveFactorization(*factorization_);
03347   // save basis and solution 
03348   double * saveSolution = new double[numberRows_+numberColumns_];
03349   memcpy(saveSolution,solution_,
03350          (numberRows_+numberColumns_)*sizeof(double));
03351   unsigned char * saveStatus = 
03352     new unsigned char [numberRows_+numberColumns_];
03353   memcpy(saveStatus,status_,(numberColumns_+numberRows_)*sizeof(char));
03354   // save bounds as createRim makes clean copies
03355   double * saveLower = new double[numberRows_+numberColumns_];
03356   memcpy(saveLower,lower_,
03357          (numberRows_+numberColumns_)*sizeof(double));
03358   double * saveUpper = new double[numberRows_+numberColumns_];
03359   memcpy(saveUpper,upper_,
03360          (numberRows_+numberColumns_)*sizeof(double));
03361   double * saveObjective = new double[numberRows_+numberColumns_];
03362   memcpy(saveObjective,cost_,
03363          (numberRows_+numberColumns_)*sizeof(double));
03364   int * savePivot = new int [numberRows_];
03365   memcpy(savePivot, pivotVariable_, numberRows_*sizeof(int));
03366   // need to save/restore weights.
03367 
03368   int iSolution = 0;
03369   for (i=0;i<numberVariables;i++) {
03370     int iColumn = variables[i];
03371     double objectiveChange;
03372     double saveBound;
03373     
03374     // try down
03375     
03376     saveBound = columnUpper_[iColumn];
03377     // external view - in case really getting optimal 
03378     columnUpper_[iColumn] = newUpper[i];
03379     if (scalingFlag_<=0) 
03380       upper_[iColumn] = newUpper[i];
03381     else 
03382       upper_[iColumn] = newUpper[i]/columnScale_[iColumn]; // scale
03383     // Start of fast iterations
03384     int status = fastDual(alwaysFinish);
03385     if (status) {
03386       // not finished - might be optimal
03387       checkPrimalSolution(rowActivityWork_,columnActivityWork_);
03388       double limit = 0.0;
03389       getDblParam(ClpDualObjectiveLimit, limit);
03390       if (!numberPrimalInfeasibilities_&&objectiveValue()*optimizationDirection_<
03391           limit) { 
03392         problemStatus_=0;
03393       } 
03394       status=problemStatus_;
03395     }
03396     if (status||(problemStatus_==0&&!isDualObjectiveLimitReached())) {
03397       objectiveChange = objectiveValue_-saveObjectiveValue;
03398     } else {
03399       objectiveChange = 1.0e100;
03400       status=1;
03401     }
03402 
03403     if (scalingFlag_<=0) {
03404       memcpy(outputSolution[iSolution],solution_,numberColumns_*sizeof(double));
03405     } else {
03406       int j;
03407       double * sol = outputSolution[iSolution];
03408       for (j=0;j<numberColumns_;j++) 
03409         sol[j] = solution_[j]*columnScale_[j];
03410     }
03411     outputStatus[iSolution]=status;
03412     outputIterations[iSolution]=numberIterations_;
03413     iSolution++;
03414     // restore
03415     memcpy(solution_,saveSolution,
03416            (numberRows_+numberColumns_)*sizeof(double));
03417     memcpy(status_,saveStatus,(numberColumns_+numberRows_)*sizeof(char));
03418     memcpy(lower_,saveLower,
03419            (numberRows_+numberColumns_)*sizeof(double));
03420     memcpy(upper_,saveUpper,
03421            (numberRows_+numberColumns_)*sizeof(double));
03422     memcpy(cost_,saveObjective,
03423          (numberRows_+numberColumns_)*sizeof(double));
03424     columnUpper_[iColumn] = saveBound;
03425     memcpy(pivotVariable_, savePivot, numberRows_*sizeof(int));
03426     delete factorization_;
03427     factorization_ = new ClpFactorization(saveFactorization);
03428 
03429     newUpper[i]=objectiveChange;
03430 #ifdef CLP_DEBUG
03431     printf("down on %d costs %g\n",iColumn,objectiveChange);
03432 #endif
03433           
03434     // try up
03435     
03436     saveBound = columnLower_[iColumn];
03437     // external view - in case really getting optimal 
03438     columnLower_[iColumn] = newLower[i];
03439     if (scalingFlag_<=0) 
03440       lower_[iColumn] = newLower[i];
03441     else 
03442       lower_[iColumn] = newLower[i]/columnScale_[iColumn]; // scale
03443     // Start of fast iterations
03444     status = fastDual(alwaysFinish);
03445     if (status) {
03446       // not finished - might be optimal
03447       checkPrimalSolution(rowActivityWork_,columnActivityWork_);
03448       double limit = 0.0;
03449       getDblParam(ClpDualObjectiveLimit, limit);
03450       if (!numberPrimalInfeasibilities_&&objectiveValue()*optimizationDirection_<
03451           limit) { 
03452         problemStatus_=0;
03453       } 
03454       status=problemStatus_;
03455     }
03456     if (status||(problemStatus_==0&&!isDualObjectiveLimitReached())) {
03457       objectiveChange = objectiveValue_-saveObjectiveValue;
03458     } else {
03459       objectiveChange = 1.0e100;
03460       status=1;
03461     }
03462     if (scalingFlag_<=0) {
03463       memcpy(outputSolution[iSolution],solution_,numberColumns_*sizeof(double));
03464     } else {
03465       int j;
03466       double * sol = outputSolution[iSolution];
03467       for (j=0;j<numberColumns_;j++) 
03468         sol[j] = solution_[j]*columnScale_[j];
03469     }
03470     outputStatus[iSolution]=status;
03471     outputIterations[iSolution]=numberIterations_;
03472     iSolution++;
03473 
03474     // restore
03475     memcpy(solution_,saveSolution,
03476            (numberRows_+numberColumns_)*sizeof(double));
03477     memcpy(status_,saveStatus,(numberColumns_+numberRows_)*sizeof(char));
03478     memcpy(lower_,saveLower,
03479            (numberRows_+numberColumns_)*sizeof(double));
03480     memcpy(upper_,saveUpper,
03481            (numberRows_+numberColumns_)*sizeof(double));
03482     memcpy(cost_,saveObjective,
03483          (numberRows_+numberColumns_)*sizeof(double));
03484     columnLower_[iColumn] = saveBound;
03485     memcpy(pivotVariable_, savePivot, numberRows_*sizeof(int));
03486     delete factorization_;
03487     factorization_ = new ClpFactorization(saveFactorization);
03488 
03489     newLower[i]=objectiveChange;
03490 #ifdef CLP_DEBUG
03491     printf("up on %d costs %g\n",iColumn,objectiveChange);
03492 #endif
03493           
03494     /* Possibilities are:
03495        Both sides feasible - store
03496        Neither side feasible - set objective high and exit if desired
03497        One side feasible - change bounds and resolve
03498     */
03499     if (newUpper[i]<1.0e100) {
03500       if(newLower[i]<1.0e100) {
03501         // feasible - no action
03502       } else {
03503         // up feasible, down infeasible
03504         returnCode=1;
03505         if (stopOnFirstInfeasible)
03506           break;
03507       }
03508     } else {
03509       if(newLower[i]<1.0e100) {
03510         // down feasible, up infeasible
03511         returnCode=1;
03512         if (stopOnFirstInfeasible)
03513           break;
03514       } else {
03515         // neither side feasible
03516         returnCode=-1;
03517         break;
03518       }
03519     }
03520   }
03521   delete [] saveSolution;
03522   delete [] saveLower;
03523   delete [] saveUpper;
03524   delete [] saveObjective;
03525   delete [] saveStatus;
03526   delete [] savePivot;
03527 
03528   // Get rid of some arrays and empty factorization
03529   deleteRim();
03530 #else
03531   // save basis and solution 
03532   double * rowSolution = new double[numberRows_];
03533   memcpy(rowSolution,rowActivity_,numberRows_*sizeof(double));
03534   double * columnSolution = new double[numberColumns_];
03535   memcpy(columnSolution,columnActivity_,numberColumns_*sizeof(double));
03536   unsigned char * saveStatus = 
03537     new unsigned char [numberRows_+numberColumns_];
03538   if (!status_) {
03539     // odd but anyway setup all slack basis
03540     status_ = new unsigned char [numberColumns_+numberRows_];
03541     memset(status_,0,(numberColumns_+numberRows_)*sizeof(char));
03542   }
03543   memcpy(saveStatus,status_,(numberColumns_+numberRows_)*sizeof(char));
03544   int iSolution =0;
03545   for (i=0;i<numberVariables;i++) {
03546     int iColumn = variables[i];
03547     double objectiveChange;
03548     
03549     // try down
03550     
03551     double saveUpper = columnUpper_[iColumn];
03552     columnUpper_[iColumn] = newUpper[i];
03553     int status=dual(0);
03554     memcpy(outputSolution[iSolution],columnActivity_,numberColumns_*sizeof(double));
03555     outputStatus[iSolution]=status;
03556     outputIterations[iSolution]=numberIterations_;
03557     iSolution++;
03558 
03559     // restore
03560     columnUpper_[iColumn] = saveUpper;
03561     memcpy(rowActivity_,rowSolution,numberRows_*sizeof(double));
03562     memcpy(columnActivity_,columnSolution,numberColumns_*sizeof(double));
03563     memcpy(status_,saveStatus,(numberColumns_+numberRows_)*sizeof(char));
03564 
03565     if (problemStatus_==0&&!isDualObjectiveLimitReached()) {
03566       objectiveChange = objectiveValue_-saveObjectiveValue;
03567     } else {
03568       objectiveChange = 1.0e100;
03569     }
03570     newUpper[i]=objectiveChange;
03571 #ifdef CLP_DEBUG
03572     printf("down on %d costs %g\n",iColumn,objectiveChange);
03573 #endif
03574           
03575     // try up
03576     
03577     double saveLower = columnLower_[iColumn];
03578     columnLower_[iColumn] = newLower[i];
03579     status=dual(0);
03580     memcpy(outputSolution[iSolution],columnActivity_,numberColumns_*sizeof(double));
03581     outputStatus[iSolution]=status;
03582     outputIterations[iSolution]=numberIterations_;
03583     iSolution++;
03584 
03585     // restore
03586     columnLower_[iColumn] = saveLower;
03587     memcpy(rowActivity_,rowSolution,numberRows_*sizeof(double));
03588     memcpy(columnActivity_,columnSolution,numberColumns_*sizeof(double));
03589     memcpy(status_,saveStatus,(numberColumns_+numberRows_)*sizeof(char));
03590 
03591     if (problemStatus_==0&&!isDualObjectiveLimitReached()) {
03592       objectiveChange = objectiveValue_-saveObjectiveValue;
03593     } else {
03594       objectiveChange = 1.0e100;
03595     }
03596     newLower[i]=objectiveChange;
03597 #ifdef CLP_DEBUG
03598     printf("up on %d costs %g\n",iColumn,objectiveChange);
03599 #endif
03600           
03601     /* Possibilities are:
03602        Both sides feasible - store
03603        Neither side feasible - set objective high and exit
03604        One side feasible - change bounds and resolve
03605     */
03606     if (newUpper[i]<1.0e100) {
03607       if(newLower[i]<1.0e100) {
03608         // feasible - no action
03609       } else {
03610         // up feasible, down infeasible
03611         returnCode=1;
03612         if (stopOnFirstInfeasible)
03613           break;
03614       }
03615     } else {
03616       if(newLower[i]<1.0e100) {
03617         // down feasible, up infeasible
03618         returnCode=1;
03619         if (stopOnFirstInfeasible)
03620           break;
03621       } else {
03622         // neither side feasible
03623         returnCode=-1;
03624         break;
03625       }
03626     }
03627   }
03628   delete [] rowSolution;
03629   delete [] columnSolution;
03630   delete [] saveStatus;
03631 #endif
03632   objectiveValue_ = saveObjectiveValue;
03633   return returnCode;
03634 }

int ClpSimplexDual::updateDualsInDual CoinIndexedVector rowArray,
CoinIndexedVector columnArray,
CoinIndexedVector outputArray,
double  theta,
double &  objectiveChange,
bool  fullRecompute
 

The duals are updated by the given arrays. Returns number of infeasibilities. After rowArray and columnArray will just have those which have been flipped. Variables may be flipped between bounds to stay dual feasible. The output vector has movement of primal solution (row length array)

Definition at line 1011 of file ClpSimplexDual.cpp.

References ClpMatrixBase::add(), CoinIndexedVector::clear(), CoinIndexedVector::denseVector(), flipBounds(), CoinIndexedVector::getIndices(), CoinIndexedVector::getNumElements(), CoinMessageHandler::logLevel(), CoinIndexedVector::packedMode(), CoinIndexedVector::quickAdd(), CoinIndexedVector::setNumElements(), and ClpSimplex::solutionRegion().

Referenced by statusOfProblemInDual(), and whileIterating().

01017 {
01018   
01019   outputArray->clear();
01020   
01021   
01022   int numberInfeasibilities=0;
01023   int numberRowInfeasibilities=0;
01024   
01025   // use a tighter tolerance except for all being okay
01026   double tolerance = dualTolerance_;
01027   
01028   double changeObj=0.0;
01029 
01030   // Coding is very similar but we can save a bit by splitting
01031   // Do rows
01032   if (!fullRecompute) {
01033     int i;
01034     double * reducedCost = djRegion(0);
01035     const double * lower = lowerRegion(0);
01036     const double * upper = upperRegion(0);
01037     const double * cost = costRegion(0);
01038     double * work;
01039     int number;
01040     int * which;
01041     assert(rowArray->packedMode());
01042     work = rowArray->denseVector();
01043     number = rowArray->getNumElements();
01044     which = rowArray->getIndices();
01045     for (i=0;i<number;i++) {
01046       int iSequence = which[i];
01047       double alphaI = work[i];
01048       work[i]=0.0;
01049       
01050       Status status = getStatus(iSequence+numberColumns_);
01051       // more likely to be at upper bound ?
01052       if (status==atUpperBound) {
01053 
01054         double value = reducedCost[iSequence]-theta*alphaI;
01055         reducedCost[iSequence]=value;
01056 
01057         if (value>tolerance) {
01058           // to lower bound (if swap)
01059           which[numberInfeasibilities++]=iSequence;
01060           double movement = lower[iSequence]-upper[iSequence];
01061           assert (fabs(movement)<1.0e30);
01062 #ifdef CLP_DEBUG
01063           if ((handler_->logLevel()&32))
01064             printf("%d %d, new dj %g, alpha %g, movement %g\n",
01065                    0,iSequence,value,alphaI,movement);
01066 #endif
01067           changeObj += movement*cost[iSequence];
01068           outputArray->quickAdd(iSequence,-movement);
01069         }
01070       } else if (status==atLowerBound) {
01071 
01072         double value = reducedCost[iSequence]-theta*alphaI;
01073         reducedCost[iSequence]=value;
01074 
01075         if (value<-tolerance) {
01076           // to upper bound 
01077           which[numberInfeasibilities++]=iSequence;
01078           double movement = upper[iSequence] - lower[iSequence];
01079           assert (fabs(movement)<1.0e30);
01080 #ifdef CLP_DEBUG
01081           if ((handler_->logLevel()&32))
01082             printf("%d %d, new dj %g, alpha %g, movement %g\n",
01083                    0,iSequence,value,alphaI,movement);
01084 #endif
01085           changeObj += movement*cost[iSequence];
01086           outputArray->quickAdd(iSequence,-movement);
01087         }
01088       }
01089     }
01090   } else  {
01091     double * solution = solutionRegion(0);
01092     double * reducedCost = djRegion(0);
01093     const double * lower = lowerRegion(0);
01094     const double * upper = upperRegion(0);
01095     const double * cost = costRegion(0);
01096     int * which;
01097     which = rowArray->getIndices();
01098     int iSequence;
01099     for (iSequence=0;iSequence<numberRows_;iSequence++) {
01100       double value = reducedCost[iSequence];
01101       
01102       Status status = getStatus(iSequence+numberColumns_);
01103       // more likely to be at upper bound ?
01104       if (status==atUpperBound) {
01105         double movement=0.0;
01106 
01107         if (value>tolerance) {
01108           // to lower bound (if swap)
01109           // put back alpha
01110           which[numberInfeasibilities++]=iSequence;
01111           movement = lower[iSequence]-upper[iSequence];
01112           changeObj += movement*cost[iSequence];
01113           outputArray->quickAdd(iSequence,-movement);
01114           assert (fabs(movement)<1.0e30);
01115         } else if (value>-tolerance) {
01116           // at correct bound but may swap
01117           FakeBound bound = getFakeBound(iSequence+numberColumns_);
01118           if (bound==ClpSimplexDual::upperFake) {
01119             movement = lower[iSequence]-upper[iSequence];
01120             assert (fabs(movement)<1.0e30);
01121             setStatus(iSequence+numberColumns_,atLowerBound);
01122             solution[iSequence] = lower[iSequence];
01123             changeObj += movement*cost[iSequence];
01124             numberFake_--;
01125             setFakeBound(iSequence+numberColumns_,noFake);
01126           }
01127         }
01128       } else if (status==atLowerBound) {
01129         double movement=0.0;
01130 
01131         if (value<-tolerance) {
01132           // to upper bound 
01133           // put back alpha
01134           which[numberInfeasibilities++]=iSequence;
01135           movement = upper[iSequence] - lower[iSequence];
01136           assert (fabs(movement)<1.0e30);
01137           changeObj += movement*cost[iSequence];
01138           outputArray->quickAdd(iSequence,-movement);
01139         } else if (value<tolerance) {
01140           // at correct bound but may swap
01141           FakeBound bound = getFakeBound(iSequence+numberColumns_);
01142           if (bound==ClpSimplexDual::lowerFake) {
01143             movement = upper[iSequence]-lower[iSequence];
01144             assert (fabs(movement)<1.0e30);
01145             setStatus(iSequence+numberColumns_,atUpperBound);
01146             solution[iSequence] = upper[iSequence];
01147             changeObj += movement*cost[iSequence];
01148             numberFake_--;
01149             setFakeBound(iSequence+numberColumns_,noFake);
01150           }
01151         }
01152       }
01153     }
01154   }
01155 
01156   // Do columns
01157   if (!fullRecompute) {
01158     int i;
01159     double * reducedCost = djRegion(1);
01160     const double * lower = lowerRegion(1);
01161     const double * upper = upperRegion(1);
01162     const double * cost = costRegion(1);
01163     double * work;
01164     int number;
01165     int * which;
01166     // set number of infeasibilities in row array
01167     numberRowInfeasibilities=numberInfeasibilities;
01168     rowArray->setNumElements(numberInfeasibilities);
01169     numberInfeasibilities=0;
01170     work = columnArray->denseVector();
01171     number = columnArray->getNumElements();
01172     which = columnArray->getIndices();
01173     
01174     for (i=0;i<number;i++) {
01175       int iSequence = which[i];
01176       double alphaI = work[i];
01177       work[i]=0.0;
01178       
01179       Status status = getStatus(iSequence);
01180       if (status==atLowerBound) {
01181         double value = reducedCost[iSequence]-theta*alphaI;
01182         reducedCost[iSequence]=value;
01183         double movement=0.0;
01184 
01185         if (value<-tolerance) {
01186           // to upper bound 
01187           which[numberInfeasibilities++]=iSequence;
01188           movement = upper[iSequence] - lower[iSequence];
01189           assert (fabs(movement)<1.0e30);
01190 #ifdef CLP_DEBUG
01191           if ((handler_->logLevel()&32))
01192             printf("%d %d, new dj %g, alpha %g, movement %g\n",
01193                    1,iSequence,value,alphaI,movement);
01194 #endif
01195           changeObj += movement*cost[iSequence];
01196           matrix_->add(this,outputArray,iSequence,movement);
01197         }
01198       } else if (status==atUpperBound) {
01199         double value = reducedCost[iSequence]-theta*alphaI;
01200         reducedCost[iSequence]=value;
01201         double movement=0.0;
01202 
01203         if (value>tolerance) {
01204           // to lower bound (if swap)
01205           which[numberInfeasibilities++]=iSequence;
01206           movement = lower[iSequence]-upper[iSequence];
01207           assert (fabs(movement)<1.0e30);
01208 #ifdef CLP_DEBUG
01209           if ((handler_->logLevel()&32))
01210             printf("%d %d, new dj %g, alpha %g, movement %g\n",
01211                    1,iSequence,value,alphaI,movement);
01212 #endif
01213           changeObj += movement*cost[iSequence];
01214           matrix_->add(this,outputArray,iSequence,movement);
01215         }
01216       } else if (status==isFree) {
01217         double value = reducedCost[iSequence]-theta*alphaI;
01218         reducedCost[iSequence]=value;
01219       }
01220     }
01221   } else {
01222     double * solution = solutionRegion(1);
01223     double * reducedCost = djRegion(1);
01224     const double * lower = lowerRegion(1);
01225     const double * upper = upperRegion(1);
01226     const double * cost = costRegion(1);
01227     int * which;
01228     // set number of infeasibilities in row array
01229     numberRowInfeasibilities=numberInfeasibilities;
01230     rowArray->setNumElements(numberInfeasibilities);
01231     numberInfeasibilities=0;
01232     which = columnArray->getIndices();
01233     int iSequence;
01234     for (iSequence=0;iSequence<numberColumns_;iSequence++) {
01235       double value = reducedCost[iSequence];
01236       
01237       Status status = getStatus(iSequence);
01238       if (status==atLowerBound) {
01239         double movement=0.0;
01240 
01241         if (value<-tolerance) {
01242           // to upper bound 
01243           // put back alpha
01244           which[numberInfeasibilities++]=iSequence;
01245           movement = upper[iSequence] - lower[iSequence];
01246           assert (fabs(movement)<1.0e30);
01247           changeObj += movement*cost[iSequence];
01248           matrix_->add(this,outputArray,iSequence,movement);
01249         } else if (value<tolerance) {
01250           // at correct bound but may swap
01251           FakeBound bound = getFakeBound(iSequence);
01252           if (bound==ClpSimplexDual::lowerFake) {
01253             movement = upper[iSequence]-lower[iSequence];
01254             assert (fabs(movement)<1.0e30);
01255             setStatus(iSequence,atUpperBound);
01256             solution[iSequence] = upper[iSequence];
01257             changeObj += movement*cost[iSequence];
01258             numberFake_--;
01259             setFakeBound(iSequence,noFake);
01260           }
01261         }
01262       } else if (status==atUpperBound) {
01263         double movement=0.0;
01264 
01265         if (value>tolerance) {
01266           // to lower bound (if swap)
01267           // put back alpha
01268           which[numberInfeasibilities++]=iSequence;
01269           movement = lower[iSequence]-upper[iSequence];
01270           assert (fabs(movement)<1.0e30);
01271           changeObj += movement*cost[iSequence];
01272           matrix_->add(this,outputArray,iSequence,movement);
01273         } else if (value>-tolerance) {
01274           // at correct bound but may swap
01275           FakeBound bound = getFakeBound(iSequence);
01276           if (bound==ClpSimplexDual::upperFake) {
01277             movement = lower[iSequence]-upper[iSequence];
01278             assert (fabs(movement)<1.0e30);
01279             setStatus(iSequence,atLowerBound);
01280             solution[iSequence] = lower[iSequence];
01281             changeObj += movement*cost[iSequence];
01282             numberFake_--;
01283             setFakeBound(iSequence,noFake);
01284           }
01285         }
01286       }
01287     }
01288   }
01289 #ifdef CLP_DEBUG
01290   if (fullRecompute&&numberFake_&&(handler_->logLevel()&16)!=0) 
01291     printf("%d fake after full update\n",numberFake_);
01292 #endif
01293   // set number of infeasibilities
01294   columnArray->setNumElements(numberInfeasibilities);
01295   numberInfeasibilities += numberRowInfeasibilities;
01296   if (fullRecompute) {
01297     // do actual flips
01298     flipBounds(rowArray,columnArray,0.0);
01299   }
01300   objectiveChange += changeObj;
01301   return numberInfeasibilities;
01302 }

void ClpSimplexDual::updateDualsInValuesPass CoinIndexedVector rowArray,
CoinIndexedVector columnArray,
double  theta
 

The duals are updated by the given arrays. This is in values pass - so no changes to primal is made

Definition at line 1304 of file ClpSimplexDual.cpp.

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

Referenced by whileIterating().

01307 {
01308   
01309   // use a tighter tolerance except for all being okay
01310   double tolerance = dualTolerance_;
01311   
01312   // Coding is very similar but we can save a bit by splitting
01313   // Do rows
01314   {
01315     int i;
01316     double * reducedCost = djRegion(0);
01317     double * work;
01318     int number;
01319     int * which;
01320     work = rowArray->denseVector();
01321     number = rowArray->getNumElements();
01322     which = rowArray->getIndices();
01323     for (i=0;i<number;i++) {
01324       int iSequence = which[i];
01325       double alphaI = work[i];
01326       double value = reducedCost[iSequence]-theta*alphaI;
01327       work[i]=0.0;
01328       reducedCost[iSequence]=value;
01329       
01330       Status status = getStatus(iSequence+numberColumns_);
01331       // more likely to be at upper bound ?
01332       if (status==atUpperBound) {
01333 
01334         if (value>tolerance) 
01335           reducedCost[iSequence]=0.0;
01336       } else if (status==atLowerBound) {
01337 
01338         if (value<-tolerance) {
01339           reducedCost[iSequence]=0.0;
01340         }
01341       }
01342     }
01343   }
01344   rowArray->setNumElements(0);
01345 
01346   // Do columns
01347   {
01348     int i;
01349     double * reducedCost = djRegion(1);
01350     double * work;
01351     int number;
01352     int * which;
01353     work = columnArray->denseVector();
01354     number = columnArray->getNumElements();
01355     which = columnArray->getIndices();
01356     
01357     for (i=0;i<number;i++) {
01358       int iSequence = which[i];
01359       double alphaI = work[i];
01360       double value = reducedCost[iSequence]-theta*alphaI;
01361       work[i]=0.0;
01362       reducedCost[iSequence]=value;
01363       
01364       Status status = getStatus(iSequence);
01365       if (status==atLowerBound) {
01366         if (value<-tolerance) 
01367           reducedCost[iSequence]=0.0;
01368       } else if (status==atUpperBound) {
01369         if (value>tolerance) 
01370           reducedCost[iSequence]=0.0;
01371       }
01372     }
01373   }
01374   columnArray->setNumElements(0);
01375 }

int ClpSimplexDual::whileIterating double *&  givenPi  ) 
 

This has the flow between re-factorizations Broken out for clarity and will be used by strong branching

Reasons to come out: -1 iterations etc -2 inaccuracy -3 slight inaccuracy (and done iterations) +0 looks optimal (might be unbounded - but we will investigate) +1 looks infeasible +3 max iterations

If givenPi not NULL then in values pass

Definition at line 380 of file ClpSimplexDual.cpp.

References changeBound(), ClpDualRowPivot::checkAccuracy(), CoinIndexedVector::checkClear(), checkPossibleValuesMove(), CoinIndexedVector::clear(), ClpSimplexProgress::clearBadTimes(), CoinIndexedVector::createPacked(), CoinIndexedVector::denseVector(), dualColumn(), dualRow(), ClpMatrixBase::dubiousWeights(), CoinIndexedVector::expand(), flipBounds(), ClpSimplex::gutsOfSolution(), ClpSimplex::housekeeping(), ClpSimplex::isColumn(), CoinMessageHandler::logLevel(), CoinMessageHandler::message(), originalBound(), ClpSimplex::sequenceWithin(), ClpSimplex::setFlagged(), CoinMessageHandler::setLogLevel(), ClpMatrixBase::transposeTimes(), ClpSimplex::unpack(), ClpSimplex::unpackPacked(), ClpDualRowPivot::unrollWeights(), updateDualsInDual(), updateDualsInValuesPass(), ClpDualRowPivot::updatePrimalSolution(), and ClpDualRowPivot::updateWeights().

Referenced by dual(), and fastDual().

00381 {
00382 #ifdef CLP_DEBUG
00383   int debugIteration=-1;
00384 #endif
00385   {
00386     int i;
00387     for (i=0;i<4;i++) {
00388       rowArray_[i]->clear();
00389     }    
00390     for (i=0;i<2;i++) {
00391       columnArray_[i]->clear();
00392     }    
00393   }      
00394   // if can't trust much and long way from optimal then relax
00395   if (largestPrimalError_>10.0)
00396     factorization_->relaxAccuracyCheck(min(1.0e2,largestPrimalError_/10.0));
00397   else
00398     factorization_->relaxAccuracyCheck(1.0);
00399   // status stays at -1 while iterating, >=0 finished, -2 to invert
00400   // status -3 to go to top without an invert
00401   int returnCode = -1;
00402 
00403 #if 0
00404   // compute average infeasibility for backward test
00405   double averagePrimalInfeasibility = sumPrimalInfeasibilities_/
00406     ((double ) (numberPrimalInfeasibilities_+1));
00407 #endif
00408 
00409   // Get dubious weights
00410   factorization_->getWeights(rowArray_[0]->getIndices());
00411   CoinBigIndex * dubiousWeights = matrix_->dubiousWeights(this,rowArray_[0]->getIndices());
00412   // If values pass then get list of candidates
00413   int * candidateList = NULL;
00414   int numberCandidates = 0;
00415 #ifdef CLP_DEBUG
00416   bool wasInValuesPass= (givenDuals!=NULL);
00417 #endif
00418   int candidate=-1;
00419   if (givenDuals) {
00420     candidateList = new int[numberRows_];
00421     // move reduced costs across
00422     memcpy(dj_,givenDuals,(numberRows_+numberColumns_)*sizeof(double));
00423     int iRow;
00424     for (iRow=0;iRow<numberRows_;iRow++) {
00425       int iPivot=pivotVariable_[iRow];
00426       if (flagged(iPivot))
00427         continue;
00428       if (fabs(dj_[iPivot])>dualTolerance_) {
00429         if (pivoted(iPivot)) 
00430           candidateList[numberCandidates++]=iRow;
00431       } else {
00432         clearPivoted(iPivot);
00433       }
00434     }
00435     // and set first candidate
00436     if (!numberCandidates) {
00437       delete [] candidateList;
00438       delete [] givenDuals;
00439       givenDuals=NULL;
00440       candidateList=NULL;
00441       int iRow;
00442       for (iRow=0;iRow<numberRows_;iRow++) {
00443         int iPivot=pivotVariable_[iRow];
00444         clearPivoted(iPivot);
00445       }
00446     }
00447   }
00448   while (problemStatus_==-1) {
00449 #ifdef CLP_DEBUG
00450     if (givenDuals) {
00451       double value5=0.0;
00452       int i;
00453       for (i=0;i<numberRows_+numberColumns_;i++) {
00454         if (dj_[i]<-1.0e-6)
00455           if (upper_[i]<1.0e20)
00456             value5 += dj_[i]*upper_[i];
00457           else
00458             printf("bad dj %g on %d with large upper status %d\n",
00459                    dj_[i],i,status_[i]&7);
00460         else if (dj_[i] >1.0e-6)
00461           if (lower_[i]>-1.0e20)
00462             value5 += dj_[i]*lower_[i];
00463           else
00464             printf("bad dj %g on %d with large lower status %d\n",
00465                    dj_[i],i,status_[i]&7);
00466       }
00467       printf("Values objective Value %g\n",value5);
00468     }
00469     if ((handler_->logLevel()&32)&&wasInValuesPass) {
00470       double value5=0.0;
00471       int i;
00472       for (i=0;i<numberRows_+numberColumns_;i++) {
00473         if (dj_[i]<-1.0e-6)
00474           if (upper_[i]<1.0e20)
00475             value5 += dj_[i]*upper_[i];
00476         else if (dj_[i] >1.0e-6)
00477           if (lower_[i]>-1.0e20)
00478             value5 += dj_[i]*lower_[i];
00479       }
00480       printf("Values objective Value %g\n",value5);
00481       {
00482         int i;
00483         for (i=0;i<numberRows_+numberColumns_;i++) {
00484           int iSequence = i;
00485           double oldValue;
00486           
00487           switch(getStatus(iSequence)) {
00488             
00489           case basic:
00490           case ClpSimplex::isFixed:
00491             break;
00492           case isFree:
00493           case superBasic:
00494             abort();
00495             break;
00496           case atUpperBound:
00497             oldValue = dj_[iSequence];
00498             //assert (oldValue<=tolerance);
00499             assert (fabs(solution_[iSequence]-upper_[iSequence])<1.0e-7);
00500             break;
00501           case atLowerBound:
00502             oldValue = dj_[iSequence];
00503             //assert (oldValue>=-tolerance);
00504             assert (fabs(solution_[iSequence]-lower_[iSequence])<1.0e-7);
00505             break;
00506           }
00507         }
00508       }
00509     }
00510 #endif
00511 #ifdef CLP_DEBUG
00512     {
00513       int i;
00514       for (i=0;i<4;i++) {
00515         rowArray_[i]->checkClear();
00516       }    
00517       for (i=0;i<2;i++) {
00518         columnArray_[i]->checkClear();
00519       }    
00520     }      
00521 #endif
00522 #if CLP_DEBUG>2
00523     // very expensive
00524     if (numberIterations_>0&&numberIterations_<-801) {
00525       handler_->setLogLevel(63);
00526       double saveValue = objectiveValue_;
00527       double * saveRow1 = new double[numberRows_];
00528       double * saveRow2 = new double[numberRows_];
00529       memcpy(saveRow1,rowReducedCost_,numberRows_*sizeof(double));
00530       memcpy(saveRow2,rowActivityWork_,numberRows_*sizeof(double));
00531       double * saveColumn1 = new double[numberColumns_];
00532       double * saveColumn2 = new double[numberColumns_];
00533       memcpy(saveColumn1,reducedCostWork_,numberColumns_*sizeof(double));
00534       memcpy(saveColumn2,columnActivityWork_,numberColumns_*sizeof(double));
00535       gutsOfSolution(NULL,NULL);
00536       printf("xxx %d old obj %g, recomputed %g, sum dual inf %g\n",
00537              numberIterations_,
00538              saveValue,objectiveValue_,sumDualInfeasibilities_);
00539       if (saveValue>objectiveValue_+1.0e-2)
00540         printf("**bad**\n");
00541       memcpy(rowReducedCost_,saveRow1,numberRows_*sizeof(double));
00542       memcpy(rowActivityWork_,saveRow2,numberRows_*sizeof(double));
00543       memcpy(reducedCostWork_,saveColumn1,numberColumns_*sizeof(double));
00544       memcpy(columnActivityWork_,saveColumn2,numberColumns_*sizeof(double));
00545       delete [] saveRow1;
00546       delete [] saveRow2;
00547       delete [] saveColumn1;
00548       delete [] saveColumn2;
00549       objectiveValue_=saveValue;
00550     }
00551 #endif
00552 #if 0
00553     if (!factorization_->pivots()){
00554       int iPivot;
00555       double * array = rowArray_[3]->denseVector();
00556       int i;
00557       for (iPivot=0;iPivot<numberRows_;iPivot++) {
00558         int iSequence = pivotVariable_[iPivot];
00559         unpack(rowArray_[3],iSequence);
00560         factorization_->updateColumn(rowArray_[2],rowArray_[3]);
00561         assert (fabs(array[iPivot]-1.0)<1.0e-4);
00562         array[iPivot]=0.0;
00563         for (i=0;i<numberRows_;i++)
00564           assert (fabs(array[i])<1.0e-4);
00565         rowArray_[3]->clear();
00566       }
00567     }
00568 #endif
00569 #ifdef CLP_DEBUG
00570     {
00571       int iSequence, number=numberRows_+numberColumns_;
00572       for (iSequence=0;iSequence<number;iSequence++) {
00573         double lowerValue=lower_[iSequence];
00574         double upperValue=upper_[iSequence];
00575         double value=solution_[iSequence];
00576         if(getStatus(iSequence)!=basic) {
00577           assert(lowerValue>-1.0e20);
00578           assert(upperValue<1.0e20);
00579         }
00580         switch(getStatus(iSequence)) {
00581           
00582         case basic:
00583           break;
00584         case isFree:
00585         case superBasic:
00586           break;
00587         case atUpperBound:
00588           assert (fabs(value-upperValue)<=primalTolerance_) ;
00589           break;
00590         case atLowerBound:
00591         case ClpSimplex::isFixed:
00592           assert (fabs(value-lowerValue)<=primalTolerance_) ;
00593           break;
00594         }
00595       }
00596     }
00597     if(numberIterations_==debugIteration) {
00598       printf("dodgy iteration coming up\n");
00599     }
00600 #endif
00601     // choose row to go out
00602     // dualRow will go to virtual row pivot choice algorithm
00603     // make sure values pass off if it should be
00604     if (numberCandidates) 
00605       candidate = candidateList[--numberCandidates];
00606     else
00607       candidate=-1;
00608     dualRow(candidate);
00609     if (pivotRow_>=0) {
00610       // we found a pivot row
00611       handler_->message(CLP_SIMPLEX_PIVOTROW,messages_)
00612         <<pivotRow_
00613         <<CoinMessageEol;
00614       // check accuracy of weights
00615       dualRowPivot_->checkAccuracy();
00616       // Get good size for pivot
00617       double acceptablePivot=1.0e-7;
00618       if (factorization_->pivots()>10)
00619         acceptablePivot=1.0e-5; // if we have iterated be more strict
00620       else if (factorization_->pivots()>5)
00621         acceptablePivot=1.0e-6; // if we have iterated be slightly more strict
00622       // get sign for finding row of tableau
00623       if (candidate<0) {
00624         // normal iteration
00625         // create as packed
00626         double direction=directionOut_;
00627         rowArray_[0]->createPacked(1,&pivotRow_,&direction);
00628         factorization_->updateColumnTranspose(rowArray_[1],rowArray_[0]);
00629         // put row of tableau in rowArray[0] and columnArray[0]
00630         matrix_->transposeTimes(this,-1.0,
00631                               rowArray_[0],rowArray_[3],columnArray_[0]);
00632         // do ratio test for normal iteration
00633         dualColumn(rowArray_[0],columnArray_[0],columnArray_[1],
00634                  rowArray_[3],acceptablePivot,dubiousWeights);
00635       } else {
00636         // Make sure direction plausible
00637         assert (upperOut_<1.0e50||lowerOut_>-1.0e50);
00638         if (directionOut_<0&&fabs(valueOut_-upperOut_)>dualBound_+primalTolerance_) {
00639           if (fabs(valueOut_-upperOut_)>fabs(valueOut_-lowerOut_))
00640             directionOut_=1;
00641         } else if (directionOut_>0&&fabs(valueOut_-upperOut_)<dualBound_+primalTolerance_) {
00642           if (fabs(valueOut_-upperOut_)>fabs(valueOut_-lowerOut_))
00643             directionOut_=-1;
00644         }
00645         double direction=directionOut_;
00646         rowArray_[0]->createPacked(1,&pivotRow_,&direction);
00647         factorization_->updateColumnTranspose(rowArray_[1],rowArray_[0]);
00648         // put row of tableau in rowArray[0] and columnArray[0]
00649         matrix_->transposeTimes(this,-1.0,
00650                               rowArray_[0],rowArray_[3],columnArray_[0]);
00651         acceptablePivot *= 10.0;
00652         // do ratio test
00653         checkPossibleValuesMove(rowArray_[0],columnArray_[0],
00654                                             acceptablePivot,NULL);
00655 
00656         // recompute true dualOut_
00657         if (directionOut_<0) {
00658           dualOut_ = valueOut_ - upperOut_;
00659         } else {
00660           dualOut_ = lowerOut_ - valueOut_;
00661         }
00662         // check what happened if was values pass
00663         // may want to move part way i.e. movement
00664         bool normalIteration = (sequenceIn_!=sequenceOut_);
00665 
00666         clearPivoted(sequenceOut_);  // make sure won't be done again
00667         // see if end of values pass
00668         if (!numberCandidates) {
00669           int iRow;
00670           delete [] candidateList;
00671           delete [] givenDuals;
00672           candidate=-2; // -2 signals end 
00673           givenDuals=NULL;
00674           handler_->message(CLP_END_VALUES_PASS,messages_)
00675             <<numberIterations_;
00676           candidateList=NULL;
00677           for (iRow=0;iRow<numberRows_;iRow++) {
00678             int iPivot=pivotVariable_[iRow];
00679             //assert (fabs(dj_[iPivot]),1.0e-5);
00680             clearPivoted(iPivot);
00681           }
00682         }
00683         if (!normalIteration) {
00684           //rowArray_[0]->cleanAndPackSafe(1.0e-60);
00685           //columnArray_[0]->cleanAndPackSafe(1.0e-60);
00686           updateDualsInValuesPass(rowArray_[0],columnArray_[0],theta_);
00687           if (candidate==-2)
00688             problemStatus_=-2;
00689           continue; // skip rest of iteration
00690         } else {
00691           // recompute dualOut_
00692           if (directionOut_<0) {
00693             dualOut_ = valueOut_ - upperOut_;
00694           } else {
00695             dualOut_ = lowerOut_ - valueOut_;
00696           }
00697         }
00698       }
00699       if (sequenceIn_>=0) {
00700         // normal iteration
00701         // update the incoming column
00702         double btranAlpha = -alpha_*directionOut_; // for check
00703         unpackPacked(rowArray_[1]);
00704         factorization_->updateColumnFT(rowArray_[2],rowArray_[1]);
00705         // and update dual weights (can do in parallel - with extra array)
00706         alpha_ = dualRowPivot_->updateWeights(rowArray_[0],
00707                                               rowArray_[2],
00708                                               rowArray_[1]);
00709         // see if update stable
00710 #ifdef CLP_DEBUG
00711         if ((handler_->logLevel()&32))
00712           printf("btran alpha %g, ftran alpha %g\n",btranAlpha,alpha_);
00713 #endif
00714         double checkValue=1.0e-7;
00715         // if can't trust much and long way from optimal then relax
00716         if (largestPrimalError_>10.0)
00717           checkValue = min(1.0e-4,1.0e-8*largestPrimalError_);
00718         if (fabs(btranAlpha)<1.0e-12||fabs(alpha_)<1.0e-12||
00719             fabs(btranAlpha-alpha_)>checkValue*(1.0+fabs(alpha_))) {
00720           handler_->message(CLP_DUAL_CHECK,messages_)
00721             <<btranAlpha
00722             <<alpha_
00723             <<CoinMessageEol;
00724           if (factorization_->pivots()) {
00725             dualRowPivot_->unrollWeights();
00726             problemStatus_=-2; // factorize now
00727             rowArray_[0]->clear();
00728             rowArray_[1]->clear();
00729             columnArray_[0]->clear();
00730             returnCode=-2;
00731             break;
00732           } else {
00733             // take on more relaxed criterion
00734             if (fabs(btranAlpha)<1.0e-12||fabs(alpha_)<1.0e-12||
00735                 fabs(btranAlpha-alpha_)>1.0e-4*(1.0+fabs(alpha_))) {
00736               dualRowPivot_->unrollWeights();
00737               // need to reject something
00738               char x = isColumn(sequenceOut_) ? 'C' :'R';
00739               handler_->message(CLP_SIMPLEX_FLAG,messages_)
00740                 <<x<<sequenceWithin(sequenceOut_)
00741                 <<CoinMessageEol;
00742               setFlagged(sequenceOut_);
00743               progress_->clearBadTimes();
00744               lastBadIteration_ = numberIterations_; // say be more cautious
00745               rowArray_[0]->clear();
00746               rowArray_[1]->clear();
00747               columnArray_[0]->clear();
00748               continue;
00749             }
00750           }
00751         }
00752         // update duals BEFORE replaceColumn so can do updateColumn
00753         double objectiveChange=0.0;
00754         // do duals first as variables may flip bounds
00755         // rowArray_[0] and columnArray_[0] may have flips
00756         // so use rowArray_[3] for work array from here on
00757         int nswapped = 0;
00758         //rowArray_[0]->cleanAndPackSafe(1.0e-60);
00759         //columnArray_[0]->cleanAndPackSafe(1.0e-60);
00760         if (candidate==-1) 
00761           nswapped = updateDualsInDual(rowArray_[0],columnArray_[0],
00762                                        rowArray_[2],theta_,
00763                                        objectiveChange,false);
00764         else 
00765           updateDualsInValuesPass(rowArray_[0],columnArray_[0],theta_);
00766 
00767         // which will change basic solution
00768         if (nswapped) {
00769           factorization_->updateColumn(rowArray_[3],rowArray_[2]);
00770           dualRowPivot_->updatePrimalSolution(rowArray_[2],
00771                                               1.0,objectiveChange);
00772 #ifdef CLP_DEBUG
00773           double saveDualOut = dualOut_;
00774 #endif
00775           // recompute dualOut_
00776           valueOut_ = solution_[sequenceOut_];
00777           if (directionOut_<0) {
00778             dualOut_ = valueOut_ - upperOut_;
00779           } else {
00780             dualOut_ = lowerOut_ - valueOut_;
00781           }
00782 #if 0
00783           if (dualOut_<0.0) {
00784 #ifdef CLP_DEBUG
00785             if (handler_->logLevel()&32) {
00786               printf(" dualOut_ %g %g save %g\n",dualOut_,averagePrimalInfeasibility,saveDualOut);
00787               printf("values %g %g %g %g %g %g %g\n",lowerOut_,valueOut_,upperOut_,
00788                      objectiveChange,);
00789             }
00790 #endif
00791             if (upperOut_==lowerOut_)
00792               dualOut_=0.0;
00793           }
00794           if(dualOut_<-max(1.0e-12*averagePrimalInfeasibility,1.0e-8)
00795              &&factorization_->pivots()>100&&
00796              getStatus(sequenceIn_)!=isFree) {
00797             // going backwards - factorize
00798             dualRowPivot_->unrollWeights();
00799             problemStatus_=-2; // factorize now
00800             returnCode=-2;
00801             break;
00802           }
00803 #endif
00804         }
00805         // amount primal will move
00806         double movement = -dualOut_*directionOut_/alpha_;
00807         // so objective should increase by fabs(dj)*movement
00808         // but we already have objective change - so check will be good
00809         if (objectiveChange+fabs(movement*dualIn_)<-1.0e-5) {
00810 #ifdef CLP_DEBUG
00811           if (handler_->logLevel()&32)
00812             printf("movement %g, swap change %g, rest %g  * %g\n",
00813                    objectiveChange+fabs(movement*dualIn_),
00814                    objectiveChange,movement,dualIn_);
00815 #endif
00816           if(factorization_->pivots()) {
00817             // going backwards - factorize
00818             dualRowPivot_->unrollWeights();
00819             problemStatus_=-2; // factorize now
00820             returnCode=-2;
00821             break;
00822           }
00823         }
00824         assert(fabs(dualOut_)<1.0e50);
00825         // if stable replace in basis
00826         int updateStatus = factorization_->replaceColumn(rowArray_[2],
00827                                                          pivotRow_,
00828                                                          alpha_);
00829         // if no pivots, bad update but reasonable alpha - take and invert
00830         if (updateStatus==2&&
00831                    !factorization_->pivots()&&fabs(alpha_)>1.0e-5)
00832           updateStatus=4;
00833         if (updateStatus==1||updateStatus==4) {
00834           // slight error
00835           if (factorization_->pivots()>5||updateStatus==4) {
00836             problemStatus_=-2; // factorize now
00837             returnCode=-3;
00838           }
00839         } else if (updateStatus==2) {
00840           // major error
00841           dualRowPivot_->unrollWeights();
00842           // later we may need to unwind more e.g. fake bounds
00843           if (factorization_->pivots()) {
00844             problemStatus_=-2; // factorize now
00845             returnCode=-2;
00846             break;
00847           } else {
00848             // need to reject something
00849             char x = isColumn(sequenceOut_) ? 'C' :'R';
00850             handler_->message(CLP_SIMPLEX_FLAG,messages_)
00851               <<x<<sequenceWithin(sequenceOut_)
00852               <<CoinMessageEol;
00853             setFlagged(sequenceOut_);
00854             progress_->clearBadTimes();
00855             lastBadIteration_ = numberIterations_; // say be more cautious
00856             rowArray_[0]->clear();
00857             rowArray_[1]->clear();
00858             columnArray_[0]->clear();
00859             // make sure dual feasible
00860             // look at all rows and columns
00861             double objectiveChange=0.0;
00862             updateDualsInDual(rowArray_[0],columnArray_[0],rowArray_[1],
00863                               0.0,objectiveChange,true);
00864             continue;
00865           }
00866         } else if (updateStatus==3) {
00867           // out of memory
00868           // increase space if not many iterations
00869           if (factorization_->pivots()<
00870               0.5*factorization_->maximumPivots()&&
00871               factorization_->pivots()<200)
00872             factorization_->areaFactor(
00873                                        factorization_->areaFactor() * 1.1);
00874           problemStatus_=-2; // factorize now
00875         } else if (updateStatus==5) {
00876           problemStatus_=-2; // factorize now
00877         }
00878         // update primal solution
00879         if (theta_<0.0&&candidate==-1) {
00880 #ifdef CLP_DEBUG
00881           if (handler_->logLevel()&32)
00882             printf("negative theta %g\n",theta_);
00883 #endif
00884           theta_=0.0;
00885         }
00886         // do actual flips
00887         flipBounds(rowArray_[0],columnArray_[0],theta_);
00888         //rowArray_[1]->expand();
00889         dualRowPivot_->updatePrimalSolution(rowArray_[1],
00890                                             movement,
00891                                             objectiveChange);
00892 #ifdef CLP_DEBUG
00893         double oldobj=objectiveValue_;
00894 #endif
00895         // modify dualout
00896         dualOut_ /= alpha_;
00897         dualOut_ *= -directionOut_;
00898         //setStatus(sequenceIn_,basic);
00899         dj_[sequenceIn_]=0.0;
00900         double oldValue=valueIn_;
00901         if (directionIn_==-1) {
00902           // as if from upper bound
00903           valueIn_ = upperIn_+dualOut_;
00904         } else {
00905           // as if from lower bound
00906           valueIn_ = lowerIn_+dualOut_;
00907         }
00908         objectiveChange += cost_[sequenceIn_]*(valueIn_-oldValue);
00909         // outgoing
00910         // set dj to zero unless values pass
00911         if (directionOut_>0) {
00912           valueOut_ = lowerOut_;
00913           if (candidate==-1)
00914             dj_[sequenceOut_] = theta_;
00915         } else {
00916           valueOut_ = upperOut_;
00917           if (candidate==-1)
00918             dj_[sequenceOut_] = -theta_;
00919         }
00920         solution_[sequenceOut_]=valueOut_;
00921         int whatNext=housekeeping(objectiveChange);
00922         // and set bounds correctly
00923         originalBound(sequenceIn_); 
00924         changeBound(sequenceOut_);
00925 #ifdef CLP_DEBUG
00926         if (objectiveValue_<oldobj-1.0e-5&&(handler_->logLevel()&16))
00927           printf("obj backwards %g %g\n",objectiveValue_,oldobj);
00928 #endif
00929         if (whatNext==1||candidate==-2) {
00930           problemStatus_ =-2; // refactorize
00931         } else if (whatNext==2) {
00932           // maximum iterations or equivalent
00933           problemStatus_= 3;
00934           returnCode=3;
00935           break;
00936         }
00937       } else {
00938         // no incoming column is valid
00939 #ifdef CLP_DEBUG
00940         if (handler_->logLevel()&32)
00941           printf("** no column pivot\n");
00942 #endif
00943         if (factorization_->pivots()<5) {
00944           problemStatus_=-4; //say looks infeasible
00945           // create ray anyway
00946           delete [] ray_;
00947           ray_ = new double [ numberRows_];
00948           rowArray_[0]->expand(); // in case packed
00949           ClpDisjointCopyN(rowArray_[0]->denseVector(),numberRows_,ray_);
00950         }
00951         rowArray_[0]->clear();
00952         columnArray_[0]->clear();
00953         returnCode=1;
00954         break;
00955       }
00956     } else {
00957       // no pivot row
00958 #ifdef CLP_DEBUG
00959       if (handler_->logLevel()&32)
00960         printf("** no row pivot\n");
00961 #endif
00962       if (!factorization_->pivots()) {
00963         // may have crept through - so may be optimal
00964         // check any flagged variables
00965         int iRow;
00966         for (iRow=0;iRow<numberRows_;iRow++) {
00967           int iPivot=pivotVariable_[iRow];
00968           if (flagged(iPivot))
00969             break;
00970         }
00971         if (numberFake_||numberDualInfeasibilities_) {
00972           // may be dual infeasible
00973           problemStatus_=-5;
00974         } else {
00975           if (iRow<numberRows_) {
00976 #ifdef CLP_DEBUG
00977             std::cerr<<"Flagged variables at end - infeasible?"<<std::endl;
00978             printf("Probably infeasible - pivot was %g\n",alpha_);
00979 #endif
00980             if (fabs(alpha_)<1.0e-4) {
00981               problemStatus_=1;
00982             } else {
00983 #ifdef CLP_DEBUG
00984               abort();
00985 #endif
00986             }
00987           } else {
00988             problemStatus_=0;
00989           }
00990         }
00991       } else {
00992         problemStatus_=-3;
00993       }
00994       returnCode=0;
00995       break;
00996     }
00997   }
00998   if (givenDuals) {
00999     memcpy(givenDuals,dj_,(numberRows_+numberColumns_)*sizeof(double));
01000     // get rid of any values pass array
01001     delete [] candidateList;
01002   }
01003   delete [] dubiousWeights;
01004   return returnCode;
01005 }


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