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

SbbHeuristicUser.cpp

00001 // Copyright (C) 2002, International Business Machines
00002 // Corporation and others.  All Rights Reserved.
00003 #if defined(_MSC_VER)
00004 // Turn off compiler warning about long names
00005 #  pragma warning(disable:4786)
00006 #endif
00007 #include <cassert>
00008 #include <cmath>
00009 #include <cfloat>
00010 
00011 #include "OsiSolverInterface.hpp"
00012 #include "SbbModel.hpp"
00013 #include "SbbMessage.hpp"
00014 #include "SbbHeuristicUser.hpp"
00015 #include "SbbBranchActual.hpp"
00016 // Default Constructor
00017 SbbLocalSearch::SbbLocalSearch() 
00018   :SbbHeuristic()
00019 {
00020   numberSolutions_=0;
00021   swap_=0;
00022 }
00023 
00024 // Constructor with model - assumed before cuts
00025 
00026 SbbLocalSearch::SbbLocalSearch(SbbModel & model)
00027   :SbbHeuristic(model)
00028 {
00029   numberSolutions_=0;
00030   swap_=0;
00031   // Get a copy of original matrix
00032   assert(model.solver());
00033   matrix_ = *model.solver()->getMatrixByCol();
00034 }
00035 
00036 // Destructor 
00037 SbbLocalSearch::~SbbLocalSearch ()
00038 {
00039 }
00040 
00041 // Clone
00042 SbbHeuristic *
00043 SbbLocalSearch::clone() const
00044 {
00045   return new SbbLocalSearch(*this);
00046 }
00047 
00048 // Copy constructor 
00049 SbbLocalSearch::SbbLocalSearch(const SbbLocalSearch & rhs)
00050 :
00051   SbbHeuristic(rhs),
00052   matrix_(rhs.matrix_),
00053   numberSolutions_(rhs.numberSolutions_),
00054   swap_(rhs.swap_)
00055 {
00056 }
00057 /*
00058   First tries setting a variable to better value.  If feasible then
00059   tries setting others.  If not feasible then tries swaps
00060   Returns 1 if solution, 0 if not */
00061 int
00062 SbbLocalSearch::solution(double & solutionValue,
00063                          double * betterSolution)
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 }
00420 // update model
00421 void SbbLocalSearch::setModel(SbbModel * model)
00422 {
00423   model_ = model;
00424   // Get a copy of original matrix
00425   assert(model_->solver());
00426   matrix_ = *model_->solver()->getMatrixByCol();
00427 }
00428 
00429   

Generated on Wed Dec 3 14:36:19 2003 for Sbb by doxygen 1.3.5