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

ClpDualRowSteepest.cpp

00001 // Copyright (C) 2002, International Business Machines
00002 // Corporation and others.  All Rights Reserved.
00003 
00004 #include "CoinPragma.hpp"
00005 #include "ClpSimplex.hpp"
00006 #include "ClpDualRowSteepest.hpp"
00007 #include "CoinIndexedVector.hpp"
00008 #include "ClpFactorization.hpp"
00009 #include "CoinHelperFunctions.hpp"
00010 #include <cstdio>
00011 
00012 //#############################################################################
00013 // Constructors / Destructor / Assignment
00014 //#############################################################################
00015 
00016 //-------------------------------------------------------------------
00017 // Default Constructor 
00018 //-------------------------------------------------------------------
00019 ClpDualRowSteepest::ClpDualRowSteepest (int mode) 
00020   : ClpDualRowPivot(),
00021     state_(-1),
00022     mode_(mode),
00023     weights_(NULL),
00024     infeasible_(NULL),
00025     alternateWeights_(NULL),
00026     savedWeights_(NULL),
00027     dubiousWeights_(NULL)
00028 {
00029   type_=2+64*mode;
00030 }
00031 
00032 //-------------------------------------------------------------------
00033 // Copy constructor 
00034 //-------------------------------------------------------------------
00035 ClpDualRowSteepest::ClpDualRowSteepest (const ClpDualRowSteepest & rhs) 
00036 : ClpDualRowPivot(rhs)
00037 {  
00038   state_=rhs.state_;
00039   mode_ = rhs.mode_;
00040   model_ = rhs.model_;
00041   if (rhs.infeasible_) {
00042     infeasible_= new CoinIndexedVector(rhs.infeasible_);
00043   } else {
00044     infeasible_=NULL;
00045   }
00046   if (rhs.weights_) {
00047     assert(model_);
00048     int number = model_->numberRows();
00049     weights_= new double[number];
00050     ClpDisjointCopyN(rhs.weights_,number,weights_);
00051   } else {
00052     weights_=NULL;
00053   }
00054   if (rhs.alternateWeights_) {
00055     alternateWeights_= new CoinIndexedVector(rhs.alternateWeights_);
00056   } else {
00057     alternateWeights_=NULL;
00058   }
00059   if (rhs.savedWeights_) {
00060     savedWeights_= new CoinIndexedVector(rhs.savedWeights_);
00061   } else {
00062     savedWeights_=NULL;
00063   }
00064   if (rhs.dubiousWeights_) {
00065     assert(model_);
00066     int number = model_->numberRows();
00067     dubiousWeights_= new int[number];
00068     ClpDisjointCopyN(rhs.dubiousWeights_,number,dubiousWeights_);
00069   } else {
00070     dubiousWeights_=NULL;
00071   }
00072 }
00073 
00074 //-------------------------------------------------------------------
00075 // Destructor 
00076 //-------------------------------------------------------------------
00077 ClpDualRowSteepest::~ClpDualRowSteepest ()
00078 {
00079   delete [] weights_;
00080   delete [] dubiousWeights_;
00081   delete infeasible_;
00082   delete alternateWeights_;
00083   delete savedWeights_;
00084 }
00085 
00086 //----------------------------------------------------------------
00087 // Assignment operator 
00088 //-------------------------------------------------------------------
00089 ClpDualRowSteepest &
00090 ClpDualRowSteepest::operator=(const ClpDualRowSteepest& rhs)
00091 {
00092   if (this != &rhs) {
00093     ClpDualRowPivot::operator=(rhs);
00094     state_=rhs.state_;
00095     mode_ = rhs.mode_;
00096     model_ = rhs.model_;
00097     delete [] weights_;
00098     delete [] dubiousWeights_;
00099     delete infeasible_;
00100     delete alternateWeights_;
00101     delete savedWeights_;
00102     if (rhs.infeasible_!=NULL) {
00103       infeasible_= new CoinIndexedVector(rhs.infeasible_);
00104     } else {
00105       infeasible_=NULL;
00106     }
00107     if (rhs.weights_!=NULL) {
00108       assert(model_);
00109       int number = model_->numberRows();
00110       weights_= new double[number];
00111       ClpDisjointCopyN(rhs.weights_,number,weights_);
00112     } else {
00113       weights_=NULL;
00114     }
00115     if (rhs.alternateWeights_!=NULL) {
00116       alternateWeights_= new CoinIndexedVector(rhs.alternateWeights_);
00117     } else {
00118       alternateWeights_=NULL;
00119     }
00120     if (rhs.savedWeights_!=NULL) {
00121       savedWeights_= new CoinIndexedVector(rhs.savedWeights_);
00122     } else {
00123       savedWeights_=NULL;
00124     }
00125     if (rhs.dubiousWeights_) {
00126       assert(model_);
00127       int number = model_->numberRows();
00128       dubiousWeights_= new int[number];
00129       ClpDisjointCopyN(rhs.dubiousWeights_,number,dubiousWeights_);
00130     } else {
00131       dubiousWeights_=NULL;
00132     }
00133   }
00134   return *this;
00135 }
00136 
00137 // Returns pivot row, -1 if none
00138 int 
00139 ClpDualRowSteepest::pivotRow()
00140 {
00141   assert(model_);
00142   int i,iRow;
00143   double * infeas = infeasible_->denseVector();
00144   double largest=1.0e-50;
00145   int * index = infeasible_->getIndices();
00146   int number = infeasible_->getNumElements();
00147   const int * pivotVariable =model_->pivotVariable();
00148   int chosenRow=-1;
00149   int lastPivotRow = model_->pivotRow();
00150   double tolerance=model_->currentPrimalTolerance();
00151   // we can't really trust infeasibilities if there is primal error
00152   // this coding has to mimic coding in checkPrimalSolution
00153   double error = min(1.0e-3,model_->largestPrimalError());
00154   // allow tolerance at least slightly bigger than standard
00155   tolerance = tolerance +  error;
00156   // But cap
00157   tolerance = min(1000.0,tolerance);
00158   tolerance *= tolerance; // as we are using squares
00159   double * solution = model_->solutionRegion();
00160   double * lower = model_->lowerRegion();
00161   double * upper = model_->upperRegion();
00162   // do last pivot row one here
00163   //#define COLUMN_BIAS 4.0
00164   //#define FIXED_BIAS 10.0
00165   if (lastPivotRow>=0) {
00166 #ifdef COLUMN_BIAS 
00167     int numberColumns = model_->numberColumns();
00168 #endif
00169     int iPivot=pivotVariable[lastPivotRow];
00170     double value = solution[iPivot];
00171     double lower = model_->lower(iPivot);
00172     double upper = model_->upper(iPivot);
00173     if (value>upper+tolerance) {
00174       value -= upper;
00175       value *= value;
00176 #ifdef COLUMN_BIAS 
00177       if (iPivot<numberColumns)
00178         value *= COLUMN_BIAS; // bias towards columns
00179 k
00180 #endif
00181       // store square in list
00182       if (infeas[lastPivotRow])
00183         infeas[lastPivotRow] = value; // already there
00184       else
00185         infeasible_->quickAdd(lastPivotRow,value);
00186     } else if (value<lower-tolerance) {
00187       value -= lower;
00188       value *= value;
00189 #ifdef COLUMN_BIAS 
00190       if (iPivot<numberColumns)
00191         value *= COLUMN_BIAS; // bias towards columns
00192 #endif
00193       // store square in list
00194       if (infeas[lastPivotRow])
00195         infeas[lastPivotRow] = value; // already there
00196       else
00197         infeasible_->add(lastPivotRow,value);
00198     } else {
00199       // feasible - was it infeasible - if so set tiny
00200       if (infeas[lastPivotRow])
00201         infeas[lastPivotRow] = 1.0e-100;
00202     }
00203     number = infeasible_->getNumElements();
00204   }
00205   if(model_->numberIterations()<model_->lastBadIteration()+200) {
00206     // we can't really trust infeasibilities if there is dual error
00207     double checkTolerance = 1.0e-8;
00208     if (!model_->factorization()->pivots())
00209       checkTolerance = 1.0e-6;
00210     if (model_->largestPrimalError()>checkTolerance)
00211       tolerance *= model_->largestPrimalError()/checkTolerance;
00212   }
00213   int numberWanted;
00214   if (mode_<2 ) {
00215     numberWanted = number+1;
00216   } else if (mode_==2) {
00217     numberWanted = max(2000,number/8);
00218   } else {
00219     int numberElements = model_->factorization()->numberElements();
00220     double ratio = (double) numberElements/(double) model_->numberRows();
00221     numberWanted = max(2000,number/8);
00222     if (ratio<1.0) {
00223       numberWanted = max(2000,number/20);
00224     } else if (ratio>10.0) {
00225       ratio = number * (ratio/80.0);
00226       if (ratio>number)
00227         numberWanted=number+1;
00228       else
00229         numberWanted = max(2000,(int) ratio);
00230     }
00231   }
00232   int iPass;
00233   // Setup two passes
00234   int start[4];
00235   start[1]=number;
00236   start[2]=0;
00237   double dstart = ((double) number) * CoinDrand48();
00238   start[0]=(int) dstart;
00239   start[3]=start[0];
00240   //double largestWeight=0.0;
00241   //double smallestWeight=1.0e100;
00242   for (iPass=0;iPass<2;iPass++) {
00243     int end = start[2*iPass+1];
00244     for (i=start[2*iPass];i<end;i++) {
00245       iRow = index[i];
00246       double value = infeas[iRow];
00247       if (value>tolerance) {
00248         //#define OUT_EQ
00249 #ifdef OUT_EQ
00250         {
00251           int iSequence = pivotVariable[iRow];
00252           if (upper[iSequence]==lower[iSequence])
00253             value *= 2.0;
00254         }
00255 #endif
00256         double weight = weights_[iRow];
00257         //largestWeight = max(largestWeight,weight);
00258         //smallestWeight = min(smallestWeight,weight);
00259         //double dubious = dubiousWeights_[iRow];
00260         //weight *= dubious;
00261         //if (value>2.0*largest*weight||(value>0.5*largest*weight&&value*largestWeight>dubious*largest*weight)) {
00262         if (value>largest*weight) {
00263           // make last pivot row last resort choice
00264           if (iRow==lastPivotRow) {
00265             if (value*1.0e-10<largest*weight) 
00266               continue;
00267             else 
00268               value *= 1.0e-10;
00269           }
00270           int iSequence = pivotVariable[iRow];
00271           if (!model_->flagged(iSequence)) {
00272             //#define CLP_DEBUG 1
00273 #ifdef CLP_DEBUG
00274             double value2=0.0;
00275             if (solution[iSequence]>upper[iSequence]+tolerance) 
00276               value2=solution[iSequence]-upper[iSequence];
00277             else if (solution[iSequence]<lower[iSequence]-tolerance) 
00278               value2=solution[iSequence]-lower[iSequence];
00279             assert(fabs(value2*value2-infeas[iRow])<1.0e-8*min(value2*value2,infeas[iRow]));
00280 #endif
00281             if (solution[iSequence]>upper[iSequence]+tolerance||
00282                 solution[iSequence]<lower[iSequence]-tolerance) {
00283               chosenRow=iRow;
00284               largest=value/weight;
00285               //largestWeight = dubious;
00286             }
00287           } else {
00288             // just to make sure we don't exit before got something
00289             numberWanted++;
00290           }
00291         }
00292         numberWanted--;
00293         if (!numberWanted)
00294           break;
00295       }
00296     }
00297     if (!numberWanted)
00298       break;
00299   }
00300   //printf("smallest %g largest %g\n",smallestWeight,largestWeight);
00301   return chosenRow;
00302 }
00303 #define TRY_NORM 1.0e-4
00304 // Updates weights and returns pivot alpha
00305 double
00306 ClpDualRowSteepest::updateWeights(CoinIndexedVector * input,
00307                                   CoinIndexedVector * spare,
00308                                   CoinIndexedVector * updatedColumn)
00309 {
00310 #if CLP_DEBUG>2
00311   // Very expensive debug
00312   {
00313     int numberRows = model_->numberRows();
00314     CoinIndexedVector * temp = new CoinIndexedVector();
00315     temp->reserve(numberRows+
00316                   model_->factorization()->maximumPivots());
00317     double * array = alternateWeights_->denseVector();
00318     int * which = alternateWeights_->getIndices();
00319     int i;
00320     for (i=0;i<numberRows;i++) {
00321       double value=0.0;
00322       array[i] = 1.0;
00323       which[0] = i;
00324       alternateWeights_->setNumElements(1);
00325       model_->factorization()->updateColumnTranspose(temp,
00326                                                      alternateWeights_);
00327       int number = alternateWeights_->getNumElements();
00328       int j;
00329       for (j=0;j<number;j++) {
00330         int iRow=which[j];
00331         value+=array[iRow]*array[iRow];
00332         array[iRow]=0.0;
00333       }
00334       alternateWeights_->setNumElements(0);
00335       if (fabs(weights_[i]-value)>1.0e-4)
00336         printf("%d old %g, true %g\n",i,weights_[i],value);
00337       //else 
00338       //printf("%d matches %g\n",i,value);
00339     }
00340     delete temp;
00341   }
00342 #endif
00343   assert (input->packedMode());
00344   assert (updatedColumn->packedMode());
00345   double alpha=0.0;
00346   if (!model_->factorization()->networkBasis()) {
00347     // clear other region
00348     alternateWeights_->clear();
00349     double norm = 0.0;
00350     int i;
00351     double * work = input->denseVector();
00352     int numberNonZero = input->getNumElements();
00353     int * which = input->getIndices();
00354     double * work2 = spare->denseVector();
00355     int * which2 = spare->getIndices();
00356     // ftran
00357     //permute and move indices into index array
00358     //also compute norm
00359     //int *regionIndex = alternateWeights_->getIndices (  );
00360     const int *permute = model_->factorization()->permute();
00361     //double * region = alternateWeights_->denseVector();
00362     for ( i = 0; i < numberNonZero; i ++ ) {
00363       int iRow = which[i];
00364       double value = work[i];
00365       norm += value*value;
00366       iRow = permute[iRow];
00367       work2[iRow] = value;
00368       which2[i] = iRow;
00369     }
00370     spare->setNumElements ( numberNonZero );
00371     // Only one array active as already permuted
00372     model_->factorization()->updateColumn(spare,spare,true);
00373     // permute back
00374     numberNonZero = spare->getNumElements();
00375     // alternateWeights_ should still be empty
00376     int pivotRow = model_->pivotRow();
00377 #ifdef CLP_DEBUG
00378     if ( model_->logLevel (  ) >4  && 
00379          fabs(norm-weights_[pivotRow])>1.0e-3*(1.0+norm)) 
00380       printf("on row %d, true weight %g, old %g\n",
00381              pivotRow,sqrt(norm),sqrt(weights_[pivotRow]));
00382 #endif
00383     // could re-initialize here (could be expensive)
00384     norm /= model_->alpha() * model_->alpha();
00385     
00386     assert(norm);
00387     // pivot element
00388     alpha=0.0;
00389     double multiplier = 2.0 / model_->alpha();
00390     // look at updated column
00391     work = updatedColumn->denseVector();
00392     numberNonZero = updatedColumn->getNumElements();
00393     which = updatedColumn->getIndices();
00394     
00395     int nSave=0;
00396     double * work3 = alternateWeights_->denseVector();
00397     int * which3 = alternateWeights_->getIndices();
00398     const int * pivotColumn = model_->factorization()->pivotColumn();
00399     for (i =0; i < numberNonZero; i++) {
00400       int iRow = which[i];
00401       double theta = work[i];
00402       if (iRow==pivotRow)
00403         alpha = theta;
00404       double devex = weights_[iRow];
00405       work3[nSave]=devex; // save old
00406       which3[nSave++]=iRow;
00407       // transform to match spare
00408       int jRow = pivotColumn[iRow];
00409       double value = work2[jRow];
00410       devex +=  theta * (theta*norm+value * multiplier);
00411       if (devex < TRY_NORM) 
00412         devex = TRY_NORM;
00413       weights_[iRow]=devex;
00414     }
00415     alternateWeights_->setPackedMode(true);
00416     alternateWeights_->setNumElements(nSave);
00417     if (norm < TRY_NORM) 
00418       norm = TRY_NORM;
00419     weights_[pivotRow] = norm;
00420     spare->clear();
00421 #ifdef CLP_DEBUG
00422     spare->checkClear();
00423 #endif
00424   } else {
00425     // clear other region
00426     alternateWeights_->clear();
00427     double norm = 0.0;
00428     int i;
00429     double * work = input->denseVector();
00430     int number = input->getNumElements();
00431     int * which = input->getIndices();
00432     double * work2 = spare->denseVector();
00433     int * which2 = spare->getIndices();
00434     for (i=0;i<number;i++) {
00435       int iRow = which[i];
00436       double value = work[i];
00437       norm += value*value;
00438       work2[iRow]=value;
00439       which2[i]=iRow;
00440     }
00441     spare->setNumElements(number);
00442     // ftran
00443     model_->factorization()->updateColumn(alternateWeights_,spare);
00444     // alternateWeights_ should still be empty
00445     int pivotRow = model_->pivotRow();
00446 #ifdef CLP_DEBUG
00447     if ( model_->logLevel (  ) >4  && 
00448          fabs(norm-weights_[pivotRow])>1.0e-3*(1.0+norm)) 
00449       printf("on row %d, true weight %g, old %g\n",
00450              pivotRow,sqrt(norm),sqrt(weights_[pivotRow]));
00451 #endif
00452     // could re-initialize here (could be expensive)
00453     norm /= model_->alpha() * model_->alpha();
00454     
00455     assert(norm);
00456     //if (norm < TRY_NORM) 
00457     //norm = TRY_NORM;
00458     // pivot element
00459     alpha=0.0;
00460     double multiplier = 2.0 / model_->alpha();
00461     // look at updated column
00462     work = updatedColumn->denseVector();
00463     number = updatedColumn->getNumElements();
00464     which = updatedColumn->getIndices();
00465     
00466     int nSave=0;
00467     double * work3 = alternateWeights_->denseVector();
00468     int * which3 = alternateWeights_->getIndices();
00469     for (i =0; i < number; i++) {
00470       int iRow = which[i];
00471       double theta = work[i];
00472       if (iRow==pivotRow)
00473         alpha = theta;
00474       double devex = weights_[iRow];
00475       work3[nSave]=devex; // save old
00476       which3[nSave++]=iRow;
00477       double value = work2[iRow];
00478       devex +=  theta * (theta*norm+value * multiplier);
00479       if (devex < TRY_NORM) 
00480         devex = TRY_NORM;
00481       weights_[iRow]=devex;
00482     }
00483     assert (alpha);
00484     alternateWeights_->setPackedMode(true);
00485     alternateWeights_->setNumElements(nSave);
00486     if (norm < TRY_NORM) 
00487       norm = TRY_NORM;
00488     weights_[pivotRow] = norm;
00489     spare->clear();
00490   }
00491 #ifdef CLP_DEBUG
00492   spare->checkClear();
00493 #endif
00494   return alpha;
00495 }
00496   
00497 /* Updates primal solution (and maybe list of candidates)
00498    Uses input vector which it deletes
00499    Computes change in objective function
00500 */
00501 void 
00502 ClpDualRowSteepest::updatePrimalSolution(
00503                                         CoinIndexedVector * primalUpdate,
00504                                         double primalRatio,
00505                                         double & objectiveChange)
00506 {
00507   double * work = primalUpdate->denseVector();
00508   int number = primalUpdate->getNumElements();
00509   int * which = primalUpdate->getIndices();
00510   int i;
00511   double changeObj=0.0;
00512   double tolerance=model_->currentPrimalTolerance();
00513   const int * pivotVariable = model_->pivotVariable();
00514   double * infeas = infeasible_->denseVector();
00515   int pivotRow = model_->pivotRow();
00516   double * solution = model_->solutionRegion();
00517 #ifdef COLUMN_BIAS 
00518   int numberColumns = model_->numberColumns();
00519 #endif
00520   if (primalUpdate->packedMode()) {
00521     for (i=0;i<number;i++) {
00522       int iRow=which[i];
00523       int iPivot=pivotVariable[iRow];
00524       double value = solution[iPivot];
00525       double cost = model_->cost(iPivot);
00526       double change = primalRatio*work[i];
00527       work[i]=0.0;
00528       value -= change;
00529       changeObj -= change*cost;
00530       solution[iPivot] = value;
00531       double lower = model_->lower(iPivot);
00532       double upper = model_->upper(iPivot);
00533       // But if pivot row then use value of incoming
00534       // Although it is safer to recompute before next selection
00535       // in case something odd happens
00536       if (iRow==pivotRow) {
00537         iPivot = model_->sequenceIn();
00538         lower = model_->lower(iPivot);
00539         upper = model_->upper(iPivot);
00540         value = model_->valueIncomingDual();
00541       }
00542       if (value<lower-tolerance) {
00543         value -= lower;
00544         value *= value;
00545 #ifdef COLUMN_BIAS 
00546         if (iPivot<numberColumns)
00547           value *= COLUMN_BIAS; // bias towards columns
00548 #endif
00549 #ifdef FIXED_BIAS 
00550         if (lower==upper)
00551           value *= FIXED_BIAS; // bias towards taking out fixed variables
00552 #endif
00553         // store square in list
00554         if (infeas[iRow])
00555           infeas[iRow] = value; // already there
00556         else
00557           infeasible_->quickAdd(iRow,value);
00558       } else if (value>upper+tolerance) {
00559         value -= upper;
00560         value *= value;
00561 #ifdef COLUMN_BIAS 
00562         if (iPivot<numberColumns)
00563           value *= COLUMN_BIAS; // bias towards columns
00564 #endif
00565 #ifdef FIXED_BIAS 
00566         if (lower==upper)
00567           value *= FIXED_BIAS; // bias towards taking out fixed variables
00568 #endif
00569         // store square in list
00570         if (infeas[iRow])
00571           infeas[iRow] = value; // already there
00572         else
00573           infeasible_->quickAdd(iRow,value);
00574       } else {
00575         // feasible - was it infeasible - if so set tiny
00576         if (infeas[iRow])
00577           infeas[iRow] = 1.0e-100;
00578       }
00579     }
00580   } else {
00581     for (i=0;i<number;i++) {
00582       int iRow=which[i];
00583       int iPivot=pivotVariable[iRow];
00584       double value = solution[iPivot];
00585       double cost = model_->cost(iPivot);
00586       double change = primalRatio*work[iRow];
00587       value -= change;
00588       changeObj -= change*cost;
00589       solution[iPivot] = value;
00590       double lower = model_->lower(iPivot);
00591       double upper = model_->upper(iPivot);
00592       // But if pivot row then use value of incoming
00593       // Although it is safer to recompute before next selection
00594       // in case something odd happens
00595       if (iRow==pivotRow) {
00596         iPivot = model_->sequenceIn();
00597         lower = model_->lower(iPivot);
00598         upper = model_->upper(iPivot);
00599         value = model_->valueIncomingDual();
00600       }
00601       if (value<lower-tolerance) {
00602         value -= lower;
00603         value *= value;
00604 #ifdef COLUMN_BIAS 
00605         if (iPivot<numberColumns)
00606           value *= COLUMN_BIAS; // bias towards columns
00607 #endif
00608 #ifdef FIXED_BIAS 
00609         if (lower==upper)
00610           value *= FIXED_BIAS; // bias towards taking out fixed variables
00611 #endif
00612         // store square in list
00613         if (infeas[iRow])
00614           infeas[iRow] = value; // already there
00615         else
00616           infeasible_->quickAdd(iRow,value);
00617       } else if (value>upper+tolerance) {
00618         value -= upper;
00619         value *= value;
00620 #ifdef COLUMN_BIAS 
00621         if (iPivot<numberColumns)
00622           value *= COLUMN_BIAS; // bias towards columns
00623 #endif
00624 #ifdef FIXED_BIAS 
00625         if (lower==upper)
00626           value *= FIXED_BIAS; // bias towards taking out fixed variables
00627 #endif
00628         // store square in list
00629         if (infeas[iRow])
00630           infeas[iRow] = value; // already there
00631         else
00632           infeasible_->quickAdd(iRow,value);
00633       } else {
00634         // feasible - was it infeasible - if so set tiny
00635         if (infeas[iRow])
00636           infeas[iRow] = 1.0e-100;
00637       }
00638       work[iRow]=0.0;
00639     }
00640   }
00641   primalUpdate->setNumElements(0);
00642   objectiveChange += changeObj;
00643 }
00644 /* Saves any weights round factorization as pivot rows may change
00645    1) before factorization
00646    2) after factorization
00647    3) just redo infeasibilities
00648    4) restore weights
00649 */
00650 void 
00651 ClpDualRowSteepest::saveWeights(ClpSimplex * model,int mode)
00652 {
00653   // alternateWeights_ is defined as indexed but is treated oddly
00654   model_ = model;
00655   int numberRows = model_->numberRows();
00656   int numberColumns = model_->numberColumns();
00657   const int * pivotVariable = model_->pivotVariable();
00658   int i;
00659   if (mode==1&&weights_) {
00660     alternateWeights_->clear();
00661     // change from row numbers to sequence numbers
00662     int * which = alternateWeights_->getIndices();
00663     for (i=0;i<numberRows;i++) {
00664       int iPivot=pivotVariable[i];
00665       which[i]=iPivot;
00666     }
00667     state_=1;
00668   } else if (mode==2||mode==4||mode==5) {
00669     // restore
00670     if (!weights_||state_==-1||mode==5) {
00671       // initialize weights
00672       delete [] weights_;
00673       delete alternateWeights_;
00674       weights_ = new double[numberRows];
00675       alternateWeights_ = new CoinIndexedVector();
00676       // enough space so can use it for factorization
00677       alternateWeights_->reserve(numberRows+
00678                                  model_->factorization()->maximumPivots());
00679       if (!mode_||mode_==2||mode==5) {
00680         // initialize to 1.0 (can we do better?)
00681         for (i=0;i<numberRows;i++) {
00682           weights_[i]=1.0;
00683         }
00684       } else {
00685         CoinIndexedVector * temp = new CoinIndexedVector();
00686         temp->reserve(numberRows+
00687                       model_->factorization()->maximumPivots());
00688         double * array = alternateWeights_->denseVector();
00689         int * which = alternateWeights_->getIndices();
00690         for (i=0;i<numberRows;i++) {
00691           double value=0.0;
00692           array[0] = 1.0;
00693           which[0] = i;
00694           alternateWeights_->setNumElements(1);
00695           alternateWeights_->setPackedMode(true);
00696           model_->factorization()->updateColumnTranspose(temp,
00697                                                          alternateWeights_);
00698           int number = alternateWeights_->getNumElements();
00699           int j;
00700           for (j=0;j<number;j++) {
00701             value+=array[j]*array[j];
00702             array[j]=0.0;
00703           }
00704           alternateWeights_->setNumElements(0);
00705           weights_[i] = value;
00706         }
00707         delete temp;
00708       }
00709       // create saved weights (not really indexedvector)
00710       savedWeights_ = new CoinIndexedVector();
00711       savedWeights_->reserve(numberRows);
00712       
00713       double * array = savedWeights_->denseVector();
00714       int * which = savedWeights_->getIndices();
00715       for (i=0;i<numberRows;i++) {
00716         array[i]=weights_[i];
00717         which[i]=pivotVariable[i];
00718       }
00719     } else {
00720       int * which = alternateWeights_->getIndices();
00721       if (mode!=4) {
00722         // save
00723         memcpy(savedWeights_->getIndices(),which,
00724                numberRows*sizeof(int));
00725         memcpy(savedWeights_->denseVector(),weights_,
00726                numberRows*sizeof(double));
00727       } else {
00728         // restore
00729         memcpy(which,savedWeights_->getIndices(),
00730                numberRows*sizeof(int));
00731         memcpy(weights_,savedWeights_->denseVector(),
00732                numberRows*sizeof(double));
00733       }
00734       // restore (a bit slow - but only every re-factorization)
00735       double * array = new double[numberRows+numberColumns];
00736       for (i=0;i<numberRows;i++) {
00737         int iSeq=which[i];
00738         array[iSeq]=weights_[i];
00739       }
00740       for (i=0;i<numberRows;i++) {
00741         int iPivot=pivotVariable[i];
00742         weights_[i]=array[iPivot];
00743         if (weights_[i]<TRY_NORM)
00744           weights_[i] = TRY_NORM; // may need to check more
00745       }
00746       delete [] array;
00747     }
00748     state_=0;
00749     // set up infeasibilities
00750     if (!infeasible_) {
00751       infeasible_ = new CoinIndexedVector();
00752       infeasible_->reserve(numberRows);
00753     }
00754   }
00755   if (mode>=2) {
00756     // Get dubious weights
00757     //if (!dubiousWeights_)
00758     //dubiousWeights_=new int[numberRows];
00759     //model_->factorization()->getWeights(dubiousWeights_);
00760     infeasible_->clear();
00761     int iRow;
00762     const int * pivotVariable = model_->pivotVariable();
00763     double tolerance=model_->currentPrimalTolerance();
00764     for (iRow=0;iRow<numberRows;iRow++) {
00765       int iPivot=pivotVariable[iRow];
00766       double value = model_->solution(iPivot);
00767       double lower = model_->lower(iPivot);
00768       double upper = model_->upper(iPivot);
00769       if (value<lower-tolerance) {
00770         value -= lower;
00771         value *= value;
00772 #ifdef COLUMN_BIAS 
00773         if (iPivot<numberColumns)
00774           value *= COLUMN_BIAS; // bias towards columns
00775 #endif
00776 #ifdef FIXED_BIAS 
00777         if (lower==upper)
00778           value *= FIXED_BIAS; // bias towards taking out fixed variables
00779 #endif
00780         // store square in list
00781         infeasible_->quickAdd(iRow,value);
00782       } else if (value>upper+tolerance) {
00783         value -= upper;
00784         value *= value;
00785 #ifdef COLUMN_BIAS 
00786         if (iPivot<numberColumns)
00787           value *= COLUMN_BIAS; // bias towards columns
00788 #endif
00789 #ifdef FIXED_BIAS 
00790         if (lower==upper)
00791           value *= FIXED_BIAS; // bias towards taking out fixed variables
00792 #endif
00793         // store square in list
00794         infeasible_->quickAdd(iRow,value);
00795       }
00796     }
00797   }
00798 }
00799 // Gets rid of last update
00800 void 
00801 ClpDualRowSteepest::unrollWeights()
00802 {
00803   double * saved = alternateWeights_->denseVector();
00804   int number = alternateWeights_->getNumElements();
00805   int * which = alternateWeights_->getIndices();
00806   int i;
00807   if (alternateWeights_->packedMode()) {
00808     for (i=0;i<number;i++) {
00809       int iRow = which[i];
00810       weights_[iRow]=saved[i];
00811       saved[i]=0.0;
00812     }
00813   } else {
00814     for (i=0;i<number;i++) {
00815       int iRow = which[i];
00816       weights_[iRow]=saved[iRow];
00817       saved[iRow]=0.0;
00818     }
00819   }
00820   alternateWeights_->setNumElements(0);
00821 }
00822 //-------------------------------------------------------------------
00823 // Clone
00824 //-------------------------------------------------------------------
00825 ClpDualRowPivot * ClpDualRowSteepest::clone(bool CopyData) const
00826 {
00827   if (CopyData) {
00828     return new ClpDualRowSteepest(*this);
00829   } else {
00830     return new ClpDualRowSteepest();
00831   }
00832 }
00833 // Gets rid of all arrays
00834 void 
00835 ClpDualRowSteepest::clearArrays()
00836 {
00837   delete [] weights_;
00838   weights_=NULL;
00839   delete [] dubiousWeights_;
00840   dubiousWeights_=NULL;
00841   delete infeasible_;
00842   infeasible_ = NULL;
00843   delete alternateWeights_;
00844   alternateWeights_ = NULL;
00845   delete savedWeights_;
00846   savedWeights_ = NULL;
00847   state_ =-1;
00848 }
00849 // Returns true if would not find any row
00850 bool 
00851 ClpDualRowSteepest::looksOptimal() const
00852 {
00853   int iRow;
00854   const int * pivotVariable = model_->pivotVariable();
00855   double tolerance=model_->currentPrimalTolerance();
00856   // we can't really trust infeasibilities if there is primal error
00857   // this coding has to mimic coding in checkPrimalSolution
00858   double error = min(1.0e-3,model_->largestPrimalError());
00859   // allow tolerance at least slightly bigger than standard
00860   tolerance = tolerance +  error;
00861   // But cap
00862   tolerance = min(1000.0,tolerance);
00863   int numberRows = model_->numberRows();
00864   int numberInfeasible=0;
00865   for (iRow=0;iRow<numberRows;iRow++) {
00866     int iPivot=pivotVariable[iRow];
00867     double value = model_->solution(iPivot);
00868     double lower = model_->lower(iPivot);
00869     double upper = model_->upper(iPivot);
00870     if (value<lower-tolerance) {
00871       numberInfeasible++;
00872     } else if (value>upper+tolerance) {
00873       numberInfeasible++;
00874     }
00875   }
00876   return (numberInfeasible==0);
00877 }
00878 

Generated on Wed Dec 3 14:37:25 2003 for CLP by doxygen 1.3.5