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

SbbLocalSearch Class Reference

#include <SbbHeuristicUser.hpp>

Inheritance diagram for SbbLocalSearch:

SbbHeuristic List of all members.

Public Member Functions

 SbbLocalSearch (SbbModel &model)
 SbbLocalSearch (const SbbLocalSearch &)
virtual SbbHeuristicclone () const
 Clone.

virtual void setModel (SbbModel *model)
 update model (This is needed if cliques update matrix etc)

virtual int solution (double &objectiveValue, double *newSolution)

Protected Attributes

CoinPackedMatrix matrix_
int numberSolutions_
int swap_

Private Member Functions

SbbLocalSearchoperator= (const SbbLocalSearch &rhs)
 Illegal Assignment operator.


Detailed Description

LocalSearch class

Definition at line 10 of file SbbHeuristicUser.hpp.


Member Function Documentation

int SbbLocalSearch::solution double &  objectiveValue,
double *  newSolution
[virtual]
 

returns 0 if no solution, 1 if valid solution. Sets solution values if good, sets objective value (only if good) This is called after cuts have been added - so can not add cuts First tries setting a variable to better value. If feasible then tries setting others. If not feasible then tries swaps

This first version does not do LP's and does swaps of two integer variables. Later versions could do Lps.

Implements SbbHeuristic.

Definition at line 62 of file SbbHeuristicUser.cpp.

References SbbModel::bestSolution(), OsiSolverInterface::getDblParam(), OsiSolverInterface::getNumCols(), OsiSolverInterface::getObjCoefficients(), OsiSolverInterface::getObjSense(), SbbModel::getObjValue(), OsiSolverInterface::getRowLower(), OsiSolverInterface::getRowUpper(), SbbModel::getSolutionCount(), SbbModel::integerVariable(), SbbModel::numberIntegers(), SbbModel::object(), SbbSimpleInteger::originalLowerBound(), SbbSimpleInteger::originalUpperBound(), solution(), and SbbModel::solver().

Referenced by solution().

00064 {
00065 
00066   if (numberSolutions_==model_->getSolutionCount())
00067     return 0;
00068 
00069   // worth trying
00070   numberSolutions_=model_->getSolutionCount();
00071 
00072   OsiSolverInterface * solver = model_->solver();
00073   const double * rowLower = solver->getRowLower();
00074   const double * rowUpper = solver->getRowUpper();
00075   const double * solution = model_->bestSolution();
00076   const double * objective = solver->getObjCoefficients();
00077   double primalTolerance;
00078   assert(solver->getDblParam(OsiPrimalTolerance,primalTolerance));
00079 
00080   int numberRows = matrix_.getNumRows();
00081 
00082   int numberIntegers = model_->numberIntegers();
00083   const int * integerVariable = model_->integerVariable();
00084   
00085   int i;
00086   double direction = solver->getObjSense();
00087   double newSolutionValue = model_->getObjValue()*direction;
00088   int returnCode = 0;
00089 
00090   // Column copy
00091   const double * element = matrix_.getElements();
00092   const int * row = matrix_.getIndices();
00093   const int * columnStart = matrix_.getVectorStarts();
00094   const int * columnLength = matrix_.getVectorLengths();
00095 
00096   // Get solution array for heuristic solution
00097   int numberColumns = solver->getNumCols();
00098   double * newSolution = new double [numberColumns];
00099   memcpy(newSolution,solution,numberColumns*sizeof(double));
00100 
00101   // way is 1 if down possible, 2 if up possible, 3 if both possible
00102   char * way = new char[numberIntegers];
00103   // corrected costs
00104   double * cost = new double[numberIntegers];
00105   // for array to mark infeasible rows after iColumn branch
00106   char * mark = new char[numberRows];
00107   memset(mark,0,numberRows);
00108   // space to save values so we don't introduce rounding errors
00109   double * save = new double[numberRows];
00110 
00111   // clean solution
00112   for (i=0;i<numberIntegers;i++) {
00113     int iColumn = integerVariable[i];
00114     const SbbObject * object = model_->object(i);
00115     const SbbSimpleInteger * integerObject = 
00116       dynamic_cast<const  SbbSimpleInteger *> (object);
00117     assert(integerObject);
00118     // get original bounds
00119     double originalLower = integerObject->originalLowerBound();
00120     double originalUpper = integerObject->originalUpperBound();
00121 
00122     double value=newSolution[iColumn];
00123     double nearest=floor(value+0.5);
00124     assert(fabs(value-nearest)<10.0*primalTolerance);
00125     value=nearest;
00126     newSolution[iColumn]=nearest;
00127     cost[i] = direction*objective[iColumn];
00128     int iway=0;
00129     
00130     if (value>originalLower+0.5) 
00131       iway = 1;
00132     if (value<originalUpper-0.5) 
00133       iway |= 2;
00134     way[i]=iway;
00135   }
00136 
00137   // get row activities
00138   double * rowActivity = new double[numberRows];
00139   memset(rowActivity,0,numberRows*sizeof(double));
00140 
00141   for (i=0;i<numberColumns;i++) {
00142     int j;
00143     double value = newSolution[i];
00144     if (value) {
00145       for (j=columnStart[i];
00146            j<columnStart[i]+columnLength[i];j++) {
00147         int iRow=row[j];
00148         rowActivity[iRow] += value*element[j];
00149       }
00150     }
00151   }
00152   // check was feasible - if not adjust (cleaning may move)
00153   // if very infeasible then give up
00154   bool tryHeuristic=true;
00155   for (i=0;i<numberRows;i++) {
00156     if(rowActivity[i]<rowLower[i]) {
00157       if (rowActivity[i]<rowLower[i]-10.0*primalTolerance)
00158         tryHeuristic=false;
00159       rowActivity[i]=rowLower[i];
00160     } else if(rowActivity[i]>rowUpper[i]) {
00161       if (rowActivity[i]<rowUpper[i]+10.0*primalTolerance)
00162         tryHeuristic=false;
00163       rowActivity[i]=rowUpper[i];
00164     }
00165   }
00166   if (tryHeuristic) {
00167     
00168     // best change in objective
00169     double bestChange=0.0;
00170     
00171     for (i=0;i<numberIntegers;i++) {
00172       int iColumn = integerVariable[i];
00173       
00174       double objectiveCoefficient = cost[i];
00175       int k;
00176       int j;
00177       int goodK=-1;
00178       int wayK=-1,wayI=-1;
00179       if ((way[i]&1)!=0) {
00180         int numberInfeasible=0;
00181         // save row activities and adjust
00182         for (j=columnStart[iColumn];
00183              j<columnStart[iColumn]+columnLength[iColumn];j++) {
00184           int iRow = row[j];
00185           save[iRow]=rowActivity[iRow];
00186           rowActivity[iRow] -= element[j];
00187           if(rowActivity[iRow]<rowLower[iRow]-primalTolerance||
00188              rowActivity[iRow]>rowUpper[iRow]+primalTolerance) {
00189             // mark row
00190             mark[iRow]=1;
00191             numberInfeasible++;
00192           }
00193         }
00194         // try down
00195         for (k=i+1;k<numberIntegers;k++) {
00196           if ((way[k]&1)!=0) {
00197             // try down
00198             if (-objectiveCoefficient-cost[k]<bestChange) {
00199               // see if feasible down
00200               bool good=true;
00201               int numberMarked=0;
00202               int kColumn = integerVariable[k];
00203               for (j=columnStart[kColumn];
00204                    j<columnStart[kColumn]+columnLength[kColumn];j++) {
00205                 int iRow = row[j];
00206                 double newValue = rowActivity[iRow] - element[j];
00207                 if(newValue<rowLower[iRow]-primalTolerance||
00208                    newValue>rowUpper[iRow]+primalTolerance) {
00209                   good=false;
00210                   break;
00211                 } else if (mark[iRow]) {
00212                   // made feasible
00213                   numberMarked++;
00214                 }
00215               }
00216               if (good&&numberMarked==numberInfeasible) {
00217                 // better solution
00218                 goodK=k;
00219                 wayK=-1;
00220                 wayI=-1;
00221                 bestChange = -objectiveCoefficient-cost[k];
00222               }
00223             }
00224           }
00225           if ((way[k]&2)!=0) {
00226             // try up
00227             if (-objectiveCoefficient+cost[k]<bestChange) {
00228               // see if feasible up
00229               bool good=true;
00230               int numberMarked=0;
00231               int kColumn = integerVariable[k];
00232               for (j=columnStart[kColumn];
00233                    j<columnStart[kColumn]+columnLength[kColumn];j++) {
00234                 int iRow = row[j];
00235                 double newValue = rowActivity[iRow] + element[j];
00236                 if(newValue<rowLower[iRow]-primalTolerance||
00237                    newValue>rowUpper[iRow]+primalTolerance) {
00238                   good=false;
00239                   break;
00240                 } else if (mark[iRow]) {
00241                   // made feasible
00242                   numberMarked++;
00243                 }
00244               }
00245               if (good&&numberMarked==numberInfeasible) {
00246                 // better solution
00247                 goodK=k;
00248                 wayK=1;
00249                 wayI=-1;
00250                 bestChange = -objectiveCoefficient+cost[k];
00251               }
00252             }
00253           }
00254         }
00255         // restore row activities
00256         for (j=columnStart[iColumn];
00257              j<columnStart[iColumn]+columnLength[iColumn];j++) {
00258           int iRow = row[j];
00259           rowActivity[iRow] = save[iRow];
00260           mark[iRow]=0;
00261         }
00262       }
00263       if ((way[i]&2)!=0) {
00264         int numberInfeasible=0;
00265         // save row activities and adjust
00266         for (j=columnStart[iColumn];
00267              j<columnStart[iColumn]+columnLength[iColumn];j++) {
00268           int iRow = row[j];
00269           save[iRow]=rowActivity[iRow];
00270           rowActivity[iRow] += element[j];
00271           if(rowActivity[iRow]<rowLower[iRow]-primalTolerance||
00272              rowActivity[iRow]>rowUpper[iRow]+primalTolerance) {
00273             // mark row
00274             mark[iRow]=1;
00275             numberInfeasible++;
00276           }
00277         }
00278         // try up
00279         for (k=i+1;k<numberIntegers;k++) {
00280           if ((way[k]&1)!=0) {
00281             // try down
00282             if (objectiveCoefficient-cost[k]<bestChange) {
00283               // see if feasible down
00284               bool good=true;
00285               int numberMarked=0;
00286               int kColumn = integerVariable[k];
00287               for (j=columnStart[kColumn];
00288                    j<columnStart[kColumn]+columnLength[kColumn];j++) {
00289                 int iRow = row[j];
00290                 double newValue = rowActivity[iRow] - element[j];
00291                 if(newValue<rowLower[iRow]-primalTolerance||
00292                    newValue>rowUpper[iRow]+primalTolerance) {
00293                   good=false;
00294                   break;
00295                 } else if (mark[iRow]) {
00296                   // made feasible
00297                   numberMarked++;
00298                 }
00299               }
00300               if (good&&numberMarked==numberInfeasible) {
00301                 // better solution
00302                 goodK=k;
00303                 wayK=-1;
00304                 wayI=1;
00305                 bestChange = objectiveCoefficient-cost[k];
00306               }
00307             }
00308           }
00309           if ((way[k]&2)!=0) {
00310             // try up
00311             if (objectiveCoefficient+cost[k]<bestChange) {
00312               // see if feasible up
00313               bool good=true;
00314               int numberMarked=0;
00315               int kColumn = integerVariable[k];
00316               for (j=columnStart[kColumn];
00317                    j<columnStart[kColumn]+columnLength[kColumn];j++) {
00318                 int iRow = row[j];
00319                 double newValue = rowActivity[iRow] + element[j];
00320                 if(newValue<rowLower[iRow]-primalTolerance||
00321                    newValue>rowUpper[iRow]+primalTolerance) {
00322                   good=false;
00323                   break;
00324                 } else if (mark[iRow]) {
00325                   // made feasible
00326                   numberMarked++;
00327                 }
00328               }
00329               if (good&&numberMarked==numberInfeasible) {
00330                 // better solution
00331                 goodK=k;
00332                 wayK=1;
00333                 wayI=1;
00334                 bestChange = objectiveCoefficient+cost[k];
00335               }
00336             }
00337           }
00338         }
00339         // restore row activities
00340         for (j=columnStart[iColumn];
00341              j<columnStart[iColumn]+columnLength[iColumn];j++) {
00342           int iRow = row[j];
00343           rowActivity[iRow] = save[iRow];
00344           mark[iRow]=0;
00345         }
00346       }
00347       if (goodK>=0) {
00348         // we found something - update solution
00349         for (j=columnStart[iColumn];
00350              j<columnStart[iColumn]+columnLength[iColumn];j++) {
00351           int iRow = row[j];
00352           rowActivity[iRow]  += wayI * element[j];
00353         }
00354         newSolution[iColumn] += wayI;
00355         int kColumn = integerVariable[goodK];
00356         for (j=columnStart[kColumn];
00357              j<columnStart[kColumn]+columnLength[kColumn];j++) {
00358           int iRow = row[j];
00359           rowActivity[iRow]  += wayK * element[j];
00360         }
00361         newSolution[kColumn] += wayK;
00362         // See if k can go further ?
00363         const SbbObject * object = model_->object(goodK);
00364         const SbbSimpleInteger * integerObject = 
00365           dynamic_cast<const  SbbSimpleInteger *> (object);
00366         // get original bounds
00367         double originalLower = integerObject->originalLowerBound();
00368         double originalUpper = integerObject->originalUpperBound();
00369         
00370         double value=newSolution[kColumn];
00371         int iway=0;
00372         
00373         if (value>originalLower+0.5) 
00374           iway = 1;
00375         if (value<originalUpper-0.5) 
00376           iway |= 2;
00377         way[goodK]=iway;
00378       }
00379     }
00380     if (bestChange+newSolutionValue<solutionValue) {
00381       // new solution
00382       memcpy(betterSolution,newSolution,numberColumns*sizeof(double));
00383       returnCode=1;
00384       solutionValue = newSolutionValue + bestChange;
00385       if (bestChange>1.0e-12)
00386         printf("Local search heuristic improved solution by %g\n",
00387              -bestChange);
00388       // paranoid check
00389       memset(rowActivity,0,numberRows*sizeof(double));
00390       
00391       for (i=0;i<numberColumns;i++) {
00392         int j;
00393         double value = newSolution[i];
00394         if (value) {
00395           for (j=columnStart[i];
00396                j<columnStart[i]+columnLength[i];j++) {
00397             int iRow=row[j];
00398             rowActivity[iRow] += value*element[j];
00399           }
00400         }
00401       }
00402       // check was approximately feasible
00403       for (i=0;i<numberRows;i++) {
00404         if(rowActivity[i]<rowLower[i]) {
00405           assert (rowActivity[i]>rowLower[i]-10.0*primalTolerance);
00406         } else if(rowActivity[i]>rowUpper[i]) {
00407           assert (rowActivity[i]<rowUpper[i]+10.0*primalTolerance);
00408         }
00409       }
00410     }
00411   }
00412   delete [] newSolution;
00413   delete [] rowActivity;
00414   delete [] way;
00415   delete [] cost;
00416   delete [] save;
00417   delete [] mark;
00418   return returnCode;
00419 }


The documentation for this class was generated from the following files:
Generated on Wed Dec 3 14:36:23 2003 for Sbb by doxygen 1.3.5