#include <ClpSimplexDual.hpp>
Inheritance diagram for ClpSimplexDual:
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 () |
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.
|
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 } |
|
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 } |
|
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 } |
|
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 } |
|
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 } |
|
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 } |
|
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 } |
|
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 } |
|
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 } |
|
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 } |
|
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 } |
|
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 } |
|
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 }
|
|
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
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 } |
|
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 } |
|
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 } |
|
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 } |
|
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 } |