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

ClpNonLinearCost.cpp

00001 // Copyright (C) 2002, International Business Machines
00002 // Corporation and others.  All Rights Reserved.
00003 
00004 #include "CoinPragma.hpp"
00005 #include <iostream>
00006 #include <cassert>
00007 
00008 #include "CoinIndexedVector.hpp"
00009 
00010 #include "ClpNonLinearCost.hpp"
00011 #include "ClpSimplex.hpp"
00012 
00013 //#############################################################################
00014 // Constructors / Destructor / Assignment
00015 //#############################################################################
00016 
00017 //-------------------------------------------------------------------
00018 // Default Constructor 
00019 //-------------------------------------------------------------------
00020 ClpNonLinearCost::ClpNonLinearCost () :
00021   changeCost_(0.0),
00022   feasibleCost_(0.0),
00023   largestInfeasibility_(0.0),
00024   sumInfeasibilities_(0.0),
00025   averageTheta_(0.0),
00026   numberRows_(0),
00027   numberColumns_(0),
00028   start_(NULL),
00029   whichRange_(NULL),
00030   offset_(NULL),
00031   lower_(NULL),
00032   cost_(NULL),
00033   model_(NULL),
00034   infeasible_(NULL),
00035   numberInfeasibilities_(-1),
00036   convex_(true),
00037   bothWays_(false)
00038 {
00039 
00040 }
00041 /* Constructor from simplex.
00042    This will just set up wasteful arrays for linear, but
00043    later may do dual analysis and even finding duplicate columns 
00044 */
00045 ClpNonLinearCost::ClpNonLinearCost ( ClpSimplex * model)
00046 {
00047   model_ = model;
00048   numberRows_ = model_->numberRows();
00049   numberColumns_ = model_->numberColumns();
00050   int numberTotal = numberRows_+numberColumns_;
00051   convex_ = true;
00052   bothWays_ = false;
00053   start_ = new int [numberTotal+1];
00054   whichRange_ = new int [numberTotal];
00055   offset_ = new int [numberTotal];
00056   memset(offset_,0,numberTotal*sizeof(int));
00057 
00058   numberInfeasibilities_=0;
00059   changeCost_=0.0;
00060   feasibleCost_=0.0;
00061   double infeasibilityCost = model_->infeasibilityCost();
00062   sumInfeasibilities_=0.0;
00063   averageTheta_=0.0;
00064   largestInfeasibility_=0.0;
00065 
00066   // First see how much space we need
00067   int put=0;
00068 
00069   int iSequence;
00070   double * upper = model_->upperRegion();
00071   double * lower = model_->lowerRegion();
00072   double * cost = model_->costRegion();
00073 
00074   // For quadratic we need -inf,0,0,+inf
00075   for (iSequence=0;iSequence<numberTotal;iSequence++) {
00076     if (lower[iSequence]>-1.0e20)
00077       put++;
00078     if (upper[iSequence]<1.0e20)
00079       put++;
00080     put += 2;
00081   }
00082 
00083   lower_ = new double [put];
00084   cost_ = new double [put];
00085   infeasible_ = new unsigned int[(put+31)>>5];
00086   memset(infeasible_,0,((put+31)>>5)*sizeof(unsigned int));
00087 
00088   put=0;
00089 
00090   start_[0]=0;
00091 
00092   for (iSequence=0;iSequence<numberTotal;iSequence++) {
00093 
00094     if (lower[iSequence]>-COIN_DBL_MAX) {
00095       lower_[put] = -COIN_DBL_MAX;
00096       setInfeasible(put,true);
00097       cost_[put++] = cost[iSequence]-infeasibilityCost;
00098     }
00099     whichRange_[iSequence]=put;
00100     lower_[put] = lower[iSequence];
00101     cost_[put++] = cost[iSequence];
00102     lower_[put] = upper[iSequence];
00103     cost_[put++] = cost[iSequence]+infeasibilityCost;
00104     if (upper[iSequence]<1.0e20) {
00105       lower_[put] = COIN_DBL_MAX;
00106       setInfeasible(put-1,true);
00107       cost_[put++] = 1.0e50;
00108     }
00109     start_[iSequence+1]=put;
00110   }
00111 }
00112 ClpNonLinearCost::ClpNonLinearCost(ClpSimplex * model,const int * starts,
00113                    const double * lowerNon, const double * costNon)
00114 {
00115 
00116   // what about scaling? - only try without it initially
00117   assert(!model->scalingFlag());
00118   model_ = model;
00119   numberRows_ = model_->numberRows();
00120   numberColumns_ = model_->numberColumns();
00121   int numberTotal = numberRows_+numberColumns_;
00122   convex_ = true;
00123   bothWays_ = true;
00124   start_ = new int [numberTotal+1];
00125   whichRange_ = new int [numberTotal];
00126   offset_ = new int [numberTotal];
00127   memset(offset_,0,numberTotal*sizeof(int));
00128   
00129   double whichWay = model_->optimizationDirection();
00130   printf("Direction %g\n",whichWay);
00131 
00132   numberInfeasibilities_=0;
00133   changeCost_=0.0;
00134   feasibleCost_=0.0;
00135   double infeasibilityCost = model_->infeasibilityCost();
00136   largestInfeasibility_=0.0;
00137   sumInfeasibilities_=0.0;
00138 
00139   int iSequence;
00140   assert (!model_->rowObjective());
00141   double * cost = model_->objective();
00142 
00143   // First see how much space we need 
00144   // Also set up feasible bounds
00145   int put=starts[numberColumns_];
00146 
00147   double * columnUpper = model_->columnUpper();
00148   double * columnLower = model_->columnLower();
00149   for (iSequence=0;iSequence<numberColumns_;iSequence++) {
00150     if (columnLower[iSequence]>-1.0e20)
00151       put++;
00152     if (columnUpper[iSequence]<1.0e20)
00153       put++;
00154   }
00155 
00156   double * rowUpper = model_->rowUpper();
00157   double * rowLower = model_->rowLower();
00158   for (iSequence=0;iSequence<numberRows_;iSequence++) {
00159     if (rowLower[iSequence]>-1.0e20)
00160       put++;
00161     if (rowUpper[iSequence]<1.0e20)
00162       put++;
00163     put +=2;
00164   }
00165   lower_ = new double [put];
00166   cost_ = new double [put];
00167   infeasible_ = new unsigned int[(put+31)>>5];
00168   memset(infeasible_,0,((put+31)>>5)*sizeof(unsigned int));
00169 
00170   // now fill in 
00171   put=0;
00172 
00173   start_[0]=0;
00174   for (iSequence=0;iSequence<numberTotal;iSequence++) {
00175     lower_[put] = -COIN_DBL_MAX;
00176     whichRange_[iSequence]=put+1;
00177     double thisCost;
00178     double lowerValue;
00179     double upperValue;
00180     if (iSequence>=numberColumns_) {
00181       // rows
00182       lowerValue = rowLower[iSequence-numberColumns_];
00183       upperValue = rowUpper[iSequence-numberColumns_];
00184       if (lowerValue>-1.0e30) {
00185         setInfeasible(put,true);
00186         cost_[put++] = -infeasibilityCost;
00187         lower_[put] = lowerValue;
00188       }
00189       cost_[put++] = 0.0;
00190       thisCost = 0.0;
00191     } else {
00192       // columns - move costs and see if convex
00193       lowerValue = columnLower[iSequence];
00194       upperValue = columnUpper[iSequence];
00195       if (lowerValue>-1.0e30) {
00196         setInfeasible(put,true);
00197         cost_[put++] = whichWay*cost[iSequence]-infeasibilityCost;
00198         lower_[put] = lowerValue;
00199       }
00200       int iIndex = starts[iSequence];
00201       int end = starts[iSequence+1];
00202       assert (fabs(columnLower[iSequence]-lowerNon[iIndex])<1.0e-8);
00203       thisCost = -COIN_DBL_MAX;
00204       for (;iIndex<end;iIndex++) {
00205         if (lowerNon[iIndex]<columnUpper[iSequence]-1.0e-8) {
00206           lower_[put] = lowerNon[iIndex];
00207           cost_[put++] = whichWay*costNon[iIndex];
00208           // check convexity
00209           if (whichWay*costNon[iIndex]<thisCost-1.0e-12)
00210             convex_ = false;
00211           thisCost = whichWay*costNon[iIndex];
00212         } else {
00213           break;
00214         }
00215       }
00216     }
00217     lower_[put] = upperValue;
00218     setInfeasible(put,true);
00219     cost_[put++] = thisCost+infeasibilityCost;
00220     if (upperValue<1.0e20) {
00221       lower_[put] = COIN_DBL_MAX;
00222       cost_[put++] = 1.0e50;
00223     }
00224     int iFirst = start_[iSequence];
00225     if (lower_[iFirst] != -COIN_DBL_MAX) {
00226       setInfeasible(iFirst,true);
00227       whichRange_[iSequence]=iFirst+1;
00228     } else {
00229       whichRange_[iSequence]=iFirst;
00230     }
00231     start_[iSequence+1]=put;
00232   }
00233   // can't handle non-convex at present
00234   assert(convex_);
00235 }
00236 
00237 //-------------------------------------------------------------------
00238 // Copy constructor 
00239 //-------------------------------------------------------------------
00240 ClpNonLinearCost::ClpNonLinearCost (const ClpNonLinearCost & rhs) :
00241   changeCost_(0.0),
00242   feasibleCost_(0.0),
00243   largestInfeasibility_(0.0),
00244   sumInfeasibilities_(0.0),
00245   averageTheta_(0.0),
00246   numberRows_(rhs.numberRows_),
00247   numberColumns_(rhs.numberColumns_),
00248   start_(NULL),
00249   whichRange_(NULL),
00250   offset_(NULL),
00251   lower_(NULL),
00252   cost_(NULL),
00253   model_(NULL),
00254   infeasible_(NULL),
00255   numberInfeasibilities_(-1),
00256   convex_(true),
00257   bothWays_(rhs.bothWays_)
00258 {  
00259   if (numberRows_) {
00260     int numberTotal = numberRows_+numberColumns_;
00261     start_ = new int [numberTotal+1];
00262     memcpy(start_,rhs.start_,(numberTotal+1)*sizeof(int));
00263     whichRange_ = new int [numberTotal];
00264     memcpy(whichRange_,rhs.whichRange_,numberTotal*sizeof(int));
00265     offset_ = new int [numberTotal];
00266     memcpy(offset_,rhs.offset_,numberTotal*sizeof(int));
00267     int numberEntries = start_[numberTotal];
00268     lower_ = new double [numberEntries];
00269     memcpy(lower_,rhs.lower_,numberEntries*sizeof(double));
00270     cost_ = new double [numberEntries];
00271     memcpy(cost_,rhs.cost_,numberEntries*sizeof(double));
00272     model_ = rhs.model_;
00273     numberInfeasibilities_=rhs.numberInfeasibilities_;
00274     changeCost_ = rhs.changeCost_;
00275     feasibleCost_ = rhs.feasibleCost_;
00276     largestInfeasibility_ = rhs.largestInfeasibility_;
00277     sumInfeasibilities_ = rhs.sumInfeasibilities_;
00278     averageTheta_ = rhs.averageTheta_;
00279     convex_ = rhs.convex_;
00280     infeasible_ = new unsigned int[(numberEntries+31)>>5];
00281     memcpy(infeasible_,rhs.infeasible_,
00282            ((numberEntries+31)>>5)*sizeof(unsigned int));
00283   }
00284 }
00285 
00286 //-------------------------------------------------------------------
00287 // Destructor 
00288 //-------------------------------------------------------------------
00289 ClpNonLinearCost::~ClpNonLinearCost ()
00290 {
00291   delete [] start_;
00292   delete [] whichRange_;
00293   delete [] offset_;
00294   delete [] lower_;
00295   delete [] cost_;
00296   delete [] infeasible_;
00297 }
00298 
00299 //----------------------------------------------------------------
00300 // Assignment operator 
00301 //-------------------------------------------------------------------
00302 ClpNonLinearCost &
00303 ClpNonLinearCost::operator=(const ClpNonLinearCost& rhs)
00304 {
00305   if (this != &rhs) {
00306     numberRows_ = rhs.numberRows_;
00307     numberColumns_ = rhs.numberColumns_;
00308     delete [] start_;
00309     delete [] whichRange_;
00310     delete [] offset_;
00311     delete [] lower_;
00312     delete []cost_;
00313     delete [] infeasible_;
00314     start_ = NULL;
00315     whichRange_ = NULL;
00316     lower_ = NULL;
00317     cost_= NULL;
00318     infeasible_=NULL;
00319     if (numberRows_) {
00320       int numberTotal = numberRows_+numberColumns_;
00321       start_ = new int [numberTotal+1];
00322       memcpy(start_,rhs.start_,(numberTotal+1)*sizeof(int));
00323       whichRange_ = new int [numberTotal];
00324       memcpy(whichRange_,rhs.whichRange_,numberTotal*sizeof(int));
00325       offset_ = new int [numberTotal];
00326       memcpy(offset_,rhs.offset_,numberTotal*sizeof(int));
00327       int numberEntries = start_[numberTotal];
00328       lower_ = new double [numberEntries];
00329       memcpy(lower_,rhs.lower_,numberEntries*sizeof(double));
00330       cost_ = new double [numberEntries];
00331       memcpy(cost_,rhs.cost_,numberEntries*sizeof(double));
00332       infeasible_ = new unsigned int[(numberEntries+31)>>5];
00333       memcpy(infeasible_,rhs.infeasible_,
00334              ((numberEntries+31)>>5)*sizeof(unsigned int));
00335     }
00336     model_ = rhs.model_;
00337     numberInfeasibilities_=rhs.numberInfeasibilities_;
00338     changeCost_ = rhs.changeCost_;
00339     feasibleCost_ = rhs.feasibleCost_;
00340     largestInfeasibility_ = rhs.largestInfeasibility_;
00341     sumInfeasibilities_ = rhs.sumInfeasibilities_;
00342     averageTheta_ = rhs.averageTheta_;
00343     convex_ = rhs.convex_;
00344     bothWays_ = rhs.bothWays_;
00345   }
00346   return *this;
00347 }
00348 // Changes infeasible costs and computes number and cost of infeas
00349 // We will need to re-think objective offsets later
00350 // We will also need a 2 bit per variable array for some
00351 // purpose which will come to me later
00352 void 
00353 ClpNonLinearCost::checkInfeasibilities(double oldTolerance)
00354 {
00355   numberInfeasibilities_=0;
00356   double infeasibilityCost = model_->infeasibilityCost();
00357   changeCost_=0.0;
00358   largestInfeasibility_ = 0.0;
00359   sumInfeasibilities_ = 0.0;
00360   double primalTolerance = model_->currentPrimalTolerance();
00361   int iSequence;
00362   double * solution = model_->solutionRegion();
00363   double * upper = model_->upperRegion();
00364   double * lower = model_->lowerRegion();
00365   double * cost = model_->costRegion();
00366   bool toNearest = oldTolerance<=0.0;
00367   feasibleCost_=0.0;
00368     
00369   // nonbasic should be at a valid bound
00370   for (iSequence=0;iSequence<numberColumns_+numberRows_;iSequence++) {
00371     double lowerValue;
00372     double upperValue;
00373     double value=solution[iSequence];
00374     int iRange;
00375     // get correct place
00376     int start = start_[iSequence];
00377     int end = start_[iSequence+1]-1;
00378     // correct costs for this infeasibility weight
00379     // If free then true cost will be first
00380     double thisFeasibleCost=cost_[start];
00381     if (infeasible(start)) {
00382       thisFeasibleCost = cost_[start+1];
00383       cost_[start] = thisFeasibleCost-infeasibilityCost;
00384     }
00385     if (infeasible(end-1)) {
00386       thisFeasibleCost = cost_[end-2];
00387       cost_[end-1] = thisFeasibleCost+infeasibilityCost;
00388     }
00389     for (iRange=start; iRange<end;iRange++) {
00390       if (value<lower_[iRange+1]+primalTolerance) {
00391         // put in better range if infeasible
00392         if (value>=lower_[iRange+1]-primalTolerance&&infeasible(iRange)&&iRange==start) 
00393           iRange++;
00394         whichRange_[iSequence]=iRange;
00395         break;
00396       }
00397     }
00398     assert(iRange<end);
00399     lowerValue = lower_[iRange];
00400     upperValue = lower_[iRange+1];
00401     ClpSimplex::Status status = model_->getStatus(iSequence);
00402     if (upperValue==lowerValue) {
00403       if (status != ClpSimplex::basic) 
00404         model_->setStatus(iSequence,ClpSimplex::isFixed);
00405     }
00406     switch(status) {
00407       
00408     case ClpSimplex::basic:
00409     case ClpSimplex::superBasic:
00410       // iRange is in correct place
00411       // slot in here
00412       if (infeasible(iRange)) {
00413         if (lower_[iRange]<-1.0e50) {
00414           //cost_[iRange] = cost_[iRange+1]-infeasibilityCost;
00415           // possibly below
00416           lowerValue = lower_[iRange+1];
00417           if (value<lowerValue-primalTolerance) {
00418             value = lowerValue-value;
00419             sumInfeasibilities_ += value;
00420             largestInfeasibility_ = max(largestInfeasibility_,value);
00421             changeCost_ -= lowerValue*
00422               (cost_[iRange]-cost[iSequence]);
00423             numberInfeasibilities_++;
00424           }
00425         } else {
00426           //cost_[iRange] = cost_[iRange-1]+infeasibilityCost;
00427           // possibly above
00428           upperValue = lower_[iRange];
00429           if (value>upperValue+primalTolerance) {
00430             value = value-upperValue;
00431             sumInfeasibilities_ += value;
00432             largestInfeasibility_ = max(largestInfeasibility_,value);
00433             changeCost_ -= upperValue*
00434               (cost_[iRange]-cost[iSequence]);
00435             numberInfeasibilities_++;
00436           }
00437         }
00438       }
00439       //lower[iSequence] = lower_[iRange];
00440       //upper[iSequence] = lower_[iRange+1];
00441       //cost[iSequence] = cost_[iRange];
00442       break;
00443     case ClpSimplex::isFree:
00444       if (toNearest)
00445         solution[iSequence] = 0.0;
00446       break;
00447     case ClpSimplex::atUpperBound:
00448       if (!toNearest) {
00449         // With increasing tolerances - we may be at wrong place
00450         if (fabs(value-upperValue)>oldTolerance*1.0001) {
00451           if (fabs(value-lowerValue)<=oldTolerance*1.0001) {
00452             if  (fabs(value-lowerValue)>primalTolerance)
00453               solution[iSequence]=lowerValue;
00454             model_->setStatus(iSequence,ClpSimplex::atLowerBound);
00455           } else {
00456             model_->setStatus(iSequence,ClpSimplex::superBasic);
00457           }
00458         } else if  (fabs(value-upperValue)>primalTolerance) {
00459           solution[iSequence]=upperValue;
00460         }
00461       } else {
00462         // Set to nearest and make at upper bound
00463         int kRange;
00464         iRange=-1;
00465         double nearest = COIN_DBL_MAX;
00466         for (kRange=start; kRange<end;kRange++) {
00467           if (fabs(lower_[kRange]-value)<nearest) {
00468             nearest = fabs(lower_[kRange]-value);
00469             iRange=kRange;
00470           }
00471         }
00472         assert (iRange>=0);
00473         iRange--;
00474         solution[iSequence]=lower_[iRange+1];
00475       }
00476       break;
00477     case ClpSimplex::atLowerBound:
00478       if (!toNearest) {
00479         // With increasing tolerances - we may be at wrong place
00480         if (fabs(value-lowerValue)>oldTolerance*1.0001) {
00481           if (fabs(value-upperValue)<=oldTolerance*1.0001) {
00482             if  (fabs(value-upperValue)>primalTolerance)
00483               solution[iSequence]=upperValue;
00484             model_->setStatus(iSequence,ClpSimplex::atLowerBound);
00485           } else {
00486             model_->setStatus(iSequence,ClpSimplex::superBasic);
00487           }
00488         } else if  (fabs(value-lowerValue)>primalTolerance) {
00489           solution[iSequence]=lowerValue;
00490         }
00491       } else {
00492         // Set to nearest and make at lower bound
00493         int kRange;
00494         iRange=-1;
00495         double nearest = COIN_DBL_MAX;
00496         for (kRange=start; kRange<end;kRange++) {
00497           if (fabs(lower_[kRange]-value)<nearest) {
00498             nearest = fabs(lower_[kRange]-value);
00499             iRange=kRange;
00500           }
00501         }
00502         assert (iRange>=0);
00503         solution[iSequence]=lower_[iRange];
00504       }
00505       break;
00506     case ClpSimplex::isFixed:
00507       if (toNearest) {
00508         // Set to true fixed
00509         for (iRange=start; iRange<end;iRange++) {
00510           if (lower_[iRange]==lower_[iRange+1])
00511             break;
00512         }
00513         if (iRange==end) {
00514           // Odd - but make sensible
00515           // Set to nearest and make at lower bound
00516           int kRange;
00517           iRange=-1;
00518           double nearest = COIN_DBL_MAX;
00519           for (kRange=start; kRange<end;kRange++) {
00520             if (fabs(lower_[kRange]-value)<nearest) {
00521               nearest = fabs(lower_[kRange]-value);
00522               iRange=kRange;
00523             }
00524           }
00525           assert (iRange>=0);
00526           model_->setStatus(iSequence,ClpSimplex::atLowerBound);
00527         }
00528         solution[iSequence]=lower_[iRange];
00529       }
00530       break;
00531     }
00532     lower[iSequence] = lower_[iRange];
00533     upper[iSequence] = lower_[iRange+1];
00534     cost[iSequence] = cost_[iRange];
00535     feasibleCost_ += thisFeasibleCost*solution[iSequence];
00536   }
00537 }
00538 /* Goes through one bound for each variable.
00539    If array[i]*multiplier>0 goes down, otherwise up.
00540    The indices are row indices and need converting to sequences
00541 */
00542 void 
00543 ClpNonLinearCost::goThru(int numberInArray, double multiplier,
00544               const int * index, const double * array,
00545                          double * rhs)
00546 {
00547   assert (model_!=NULL);
00548   const int * pivotVariable = model_->pivotVariable();
00549   int i;
00550   for (i=0;i<numberInArray;i++) {
00551     int iRow = index[i];
00552     int iPivot = pivotVariable[iRow];
00553     double alpha = multiplier*array[iRow];
00554     // get where in bound sequence
00555     int iRange = whichRange_[iPivot];
00556     iRange += offset_[iPivot]; //add temporary bias
00557     double value = model_->solution(iPivot);
00558     if (alpha>0.0) {
00559       // down one
00560       iRange--;
00561       assert(iRange>=start_[iPivot]);
00562       rhs[iRow] = value - lower_[iRange];
00563     } else {
00564       // up one
00565       iRange++;
00566       assert(iRange<start_[iPivot+1]-1);
00567       rhs[iRow] = lower_[iRange+1] - value;
00568     }
00569     offset_[iPivot] = iRange - whichRange_[iPivot];
00570   }
00571 }
00572 /* Takes off last iteration (i.e. offsets closer to 0)
00573  */
00574 void 
00575 ClpNonLinearCost::goBack(int numberInArray, const int * index, 
00576               double * rhs)
00577 {
00578   assert (model_!=NULL);
00579   const int * pivotVariable = model_->pivotVariable();
00580   int i;
00581   for (i=0;i<numberInArray;i++) {
00582     int iRow = index[i];
00583     int iPivot = pivotVariable[iRow];
00584     // get where in bound sequence
00585     int iRange = whichRange_[iPivot];
00586     bool down;
00587     // get closer to original
00588     if (offset_[iPivot]>0) {
00589       offset_[iPivot]--;
00590       assert (offset_[iPivot]>=0);
00591       down = false;
00592     } else {
00593       offset_[iPivot]++;
00594       assert (offset_[iPivot]<=0);
00595       down = true;
00596     }
00597     iRange += offset_[iPivot]; //add temporary bias
00598     double value = model_->solution(iPivot);
00599     if (down) {
00600       // down one
00601       assert(iRange>=start_[iPivot]);
00602       rhs[iRow] = value - lower_[iRange];
00603     } else {
00604       // up one
00605       assert(iRange<start_[iPivot+1]-1);
00606       rhs[iRow] = lower_[iRange+1] - value;
00607     }
00608   }
00609 }
00610 void 
00611 ClpNonLinearCost::goBackAll(const CoinIndexedVector * update)
00612 {
00613   assert (model_!=NULL);
00614   const int * pivotVariable = model_->pivotVariable();
00615   int i;
00616   int number = update->getNumElements();
00617   const int * index = update->getIndices();
00618   for (i=0;i<number;i++) {
00619     int iRow = index[i];
00620     int iPivot = pivotVariable[iRow];
00621     offset_[iPivot]=0;
00622   }
00623 #ifdef CLP_DEBUG
00624   for (i=0;i<numberRows_+numberColumns_;i++) 
00625     assert(!offset_[i]);
00626 #endif
00627 }
00628 void 
00629 ClpNonLinearCost::checkInfeasibilities(int numberInArray, const int * index)
00630 {
00631   assert (model_!=NULL);
00632   double primalTolerance = model_->currentPrimalTolerance();
00633   const int * pivotVariable = model_->pivotVariable();
00634   int i;
00635   for (i=0;i<numberInArray;i++) {
00636     int iRow = index[i];
00637     int iPivot = pivotVariable[iRow];
00638     // get where in bound sequence
00639     int iRange;
00640     int currentRange = whichRange_[iPivot];
00641     double value = model_->solution(iPivot);
00642     int start = start_[iPivot];
00643     int end = start_[iPivot+1]-1;
00644     for (iRange=start; iRange<end;iRange++) {
00645       if (value<lower_[iRange+1]+primalTolerance) {
00646         // put in better range
00647         if (value>=lower_[iRange+1]-primalTolerance&&infeasible(iRange)&&iRange==start) 
00648           iRange++;
00649         break;
00650       }
00651     }
00652     assert(iRange<end);
00653     assert(model_->getStatus(iPivot)==ClpSimplex::basic);
00654     double & lower = model_->lowerAddress(iPivot);
00655     double & upper = model_->upperAddress(iPivot);
00656     double & cost = model_->costAddress(iPivot);
00657     whichRange_[iPivot]=iRange;
00658     if (iRange!=currentRange) {
00659       if (infeasible(iRange))
00660         numberInfeasibilities_++;
00661       if (infeasible(currentRange))
00662         numberInfeasibilities_--;
00663     }
00664     lower = lower_[iRange];
00665     upper = lower_[iRange+1];
00666     cost = cost_[iRange];
00667   }
00668 }
00669 /* Puts back correct infeasible costs for each variable
00670    The input indices are row indices and need converting to sequences
00671    for costs.
00672    On input array is empty (but indices exist).  On exit just
00673    changed costs will be stored as normal CoinIndexedVector
00674 */
00675 void 
00676 ClpNonLinearCost::checkChanged(int numberInArray, CoinIndexedVector * update)
00677 {
00678   assert (model_!=NULL);
00679   double primalTolerance = model_->currentPrimalTolerance();
00680   const int * pivotVariable = model_->pivotVariable();
00681   int number=0;
00682   int * index = update->getIndices();
00683   double * work = update->denseVector();
00684   int i;
00685   for (i=0;i<numberInArray;i++) {
00686     int iRow = index[i];
00687     int iPivot = pivotVariable[iRow];
00688     // get where in bound sequence
00689     int iRange;
00690     double value = model_->solution(iPivot);
00691     int start = start_[iPivot];
00692     int end = start_[iPivot+1]-1;
00693     for (iRange=start; iRange<end;iRange++) {
00694       if (value<lower_[iRange+1]+primalTolerance) {
00695         // put in better range
00696         if (value>=lower_[iRange+1]-primalTolerance&&infeasible(iRange)&&iRange==start) 
00697           iRange++;
00698         break;
00699       }
00700     }
00701     assert(iRange<end);
00702     assert(model_->getStatus(iPivot)==ClpSimplex::basic);
00703     int jRange = whichRange_[iPivot];
00704     if (iRange!=jRange) {
00705       // changed
00706       work[iRow] = cost_[jRange]-cost_[iRange];
00707       index[number++]=iRow;
00708       double & lower = model_->lowerAddress(iPivot);
00709       double & upper = model_->upperAddress(iPivot);
00710       double & cost = model_->costAddress(iPivot);
00711       whichRange_[iPivot]=iRange;
00712       if (infeasible(iRange))
00713         numberInfeasibilities_++;
00714       if (infeasible(jRange))
00715         numberInfeasibilities_--;
00716       lower = lower_[iRange];
00717       upper = lower_[iRange+1];
00718       cost = cost_[iRange];
00719     }
00720   }
00721   update->setNumElements(number);
00722 }
00723 /* Sets bounds and cost for one variable - returns change in cost*/
00724 double 
00725 ClpNonLinearCost::setOne(int iPivot, double value)
00726 {
00727   assert (model_!=NULL);
00728   double primalTolerance = model_->currentPrimalTolerance();
00729   // get where in bound sequence
00730   int iRange;
00731   int currentRange = whichRange_[iPivot];
00732   int start = start_[iPivot];
00733   int end = start_[iPivot+1]-1;
00734   if (!bothWays_) {
00735     // If fixed try and get feasible
00736     if (lower_[start+1]==lower_[start+2]&&fabs(value-lower_[start+1])<1.001*primalTolerance) {
00737       iRange =start+1;
00738     } else {
00739       for (iRange=start; iRange<end;iRange++) {
00740         if (value<=lower_[iRange+1]+primalTolerance) {
00741           // put in better range
00742           if (value>=lower_[iRange+1]-primalTolerance&&infeasible(iRange)&&iRange==start) 
00743             iRange++;
00744           break;
00745         }
00746       }
00747     }
00748   } else {
00749     // leave in current if possible
00750     iRange = whichRange_[iPivot];
00751     if (value<lower_[iRange]-primalTolerance||value>lower_[iRange+1]+primalTolerance) {
00752       for (iRange=start; iRange<end;iRange++) {
00753         if (value<lower_[iRange+1]+primalTolerance) {
00754           // put in better range
00755           if (value>=lower_[iRange+1]-primalTolerance&&infeasible(iRange)&&iRange==start) 
00756             iRange++;
00757           break;
00758         }
00759       }
00760     }
00761   }
00762   assert(iRange<end);
00763   whichRange_[iPivot]=iRange;
00764   if (iRange!=currentRange) {
00765     if (infeasible(iRange))
00766       numberInfeasibilities_++;
00767     if (infeasible(currentRange))
00768       numberInfeasibilities_--;
00769   }
00770   double & lower = model_->lowerAddress(iPivot);
00771   double & upper = model_->upperAddress(iPivot);
00772   double & cost = model_->costAddress(iPivot);
00773   lower = lower_[iRange];
00774   upper = lower_[iRange+1];
00775   ClpSimplex::Status status = model_->getStatus(iPivot);
00776   if (upper==lower) {
00777     if (status != ClpSimplex::basic) {
00778       model_->setStatus(iPivot,ClpSimplex::isFixed);
00779       status = ClpSimplex::basic; // so will skip
00780     }
00781   }
00782   switch(status) {
00783       
00784   case ClpSimplex::basic:
00785   case ClpSimplex::superBasic:
00786   case ClpSimplex::isFree:
00787     break;
00788   case ClpSimplex::atUpperBound:
00789   case ClpSimplex::atLowerBound:
00790   case ClpSimplex::isFixed:
00791     // set correctly
00792     if (fabs(value-lower)<=primalTolerance*1.001){
00793       model_->setStatus(iPivot,ClpSimplex::atLowerBound);
00794     } else if (fabs(value-upper)<=primalTolerance*1.001){
00795       model_->setStatus(iPivot,ClpSimplex::atUpperBound);
00796     } else {
00797       // set superBasic
00798       model_->setStatus(iPivot,ClpSimplex::superBasic);
00799     }
00800     break;
00801   }
00802   double difference = cost-cost_[iRange]; 
00803   cost = cost_[iRange];
00804   changeCost_ += value*difference;
00805   return difference;
00806 }
00807 /* Sets bounds and cost for outgoing variable 
00808    may change value
00809    Returns direction */
00810 int 
00811 ClpNonLinearCost::setOneOutgoing(int iPivot, double & value)
00812 {
00813   assert (model_!=NULL);
00814   double primalTolerance = model_->currentPrimalTolerance();
00815   // get where in bound sequence
00816   int iRange;
00817   int currentRange = whichRange_[iPivot];
00818   int start = start_[iPivot];
00819   int end = start_[iPivot+1]-1;
00820   // Set perceived direction out
00821   int direction;
00822   if (value<=lower_[currentRange]+1.001*primalTolerance) {
00823     direction=1;
00824   } else if (value>=lower_[currentRange+1]-1.001*primalTolerance) {
00825     direction=-1;
00826   } else {
00827     // odd
00828     direction=0;
00829   }
00830   // If fixed try and get feasible
00831   if (lower_[start+1]==lower_[start+2]&&fabs(value-lower_[start+1])<1.001*primalTolerance) {
00832     iRange =start+1;
00833   } else {
00834     // See if exact
00835     for (iRange=start; iRange<end;iRange++) {
00836       if (value==lower_[iRange+1]) {
00837         // put in better range
00838         if (infeasible(iRange)&&iRange==start) 
00839           iRange++;
00840         break;
00841       }
00842     }
00843     if (iRange==end) {
00844       // not exact
00845       for (iRange=start; iRange<end;iRange++) {
00846         if (value<=lower_[iRange+1]+primalTolerance) {
00847           // put in better range
00848           if (value>=lower_[iRange+1]-primalTolerance&&infeasible(iRange)&&iRange==start) 
00849             iRange++;
00850           break;
00851         }
00852       }
00853     }
00854   }
00855   assert(iRange<end);
00856   whichRange_[iPivot]=iRange;
00857   if (iRange!=currentRange) {
00858     if (infeasible(iRange))
00859       numberInfeasibilities_++;
00860     if (infeasible(currentRange))
00861       numberInfeasibilities_--;
00862   }
00863   double & lower = model_->lowerAddress(iPivot);
00864   double & upper = model_->upperAddress(iPivot);
00865   double & cost = model_->costAddress(iPivot);
00866   lower = lower_[iRange];
00867   upper = lower_[iRange+1];
00868   if (upper==lower) {
00869     value=upper;
00870   } else {
00871     // set correctly
00872     if (fabs(value-lower)<=primalTolerance*1.001){
00873       value = min(value,lower+primalTolerance);
00874     } else if (fabs(value-upper)<=primalTolerance*1.001){
00875       value = max(value,upper-primalTolerance);
00876     } else {
00877       //printf("*** variable wandered off bound %g %g %g!\n",
00878       //     lower,value,upper);
00879       if (value-lower<=upper-value) 
00880         value = lower+primalTolerance;
00881       else 
00882         value = upper-primalTolerance;
00883     }
00884   }
00885   double difference = cost-cost_[iRange]; 
00886   cost = cost_[iRange];
00887   changeCost_ += value*difference;
00888   return direction;
00889 }
00890 // Returns nearest bound
00891 double 
00892 ClpNonLinearCost::nearest(int sequence, double solutionValue)
00893 {
00894   assert (model_!=NULL);
00895   // get where in bound sequence
00896   int iRange;
00897   int start = start_[sequence];
00898   int end = start_[sequence+1];
00899   int jRange=-1;
00900   double nearest=COIN_DBL_MAX;
00901   for (iRange=start; iRange<end;iRange++) {
00902     if (fabs(solutionValue-lower_[iRange])<nearest) {
00903       jRange=iRange;
00904       nearest=fabs(solutionValue-lower_[iRange]);
00905     }
00906   }
00907   assert(jRange<end);
00908   return lower_[jRange];
00909 }
00911 double 
00912 ClpNonLinearCost::feasibleReportCost() const
00913 { 
00914   double value;
00915   model_->getDblParam(ClpObjOffset,value);
00916   return feasibleCost_*model_->optimizationDirection()-value;
00917 }
00918 // Get rid of real costs (just for moment)
00919 void 
00920 ClpNonLinearCost::zapCosts()
00921 {
00922   int iSequence;
00923   double infeasibilityCost = model_->infeasibilityCost();
00924   // zero out all costs
00925   int n = start_[numberColumns_+numberRows_];
00926   memset(cost_,0,n*sizeof(double));
00927   for (iSequence=0;iSequence<numberColumns_+numberRows_;iSequence++) {
00928     int start = start_[iSequence];
00929     int end = start_[iSequence+1]-1;
00930     // correct costs for this infeasibility weight
00931     if (infeasible(start)) {
00932       cost_[start] = -infeasibilityCost;
00933     }
00934     if (infeasible(end-1)) {
00935       cost_[end-1] = infeasibilityCost;
00936     }
00937   }
00938 }

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