00001
00002
00003 #if defined(_MSC_VER)
00004
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
00017 SbbLocalSearch::SbbLocalSearch()
00018 :SbbHeuristic()
00019 {
00020 numberSolutions_=0;
00021 swap_=0;
00022 }
00023
00024
00025
00026 SbbLocalSearch::SbbLocalSearch(SbbModel & model)
00027 :SbbHeuristic(model)
00028 {
00029 numberSolutions_=0;
00030 swap_=0;
00031
00032 assert(model.solver());
00033 matrix_ = *model.solver()->getMatrixByCol();
00034 }
00035
00036
00037 SbbLocalSearch::~SbbLocalSearch ()
00038 {
00039 }
00040
00041
00042 SbbHeuristic *
00043 SbbLocalSearch::clone() const
00044 {
00045 return new SbbLocalSearch(*this);
00046 }
00047
00048
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
00059
00060
00061 int
00062 SbbLocalSearch::solution(double & solutionValue,
00063 double * betterSolution)
00064 {
00065
00066 if (numberSolutions_==model_->getSolutionCount())
00067 return 0;
00068
00069
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
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
00097 int numberColumns = solver->getNumCols();
00098 double * newSolution = new double [numberColumns];
00099 memcpy(newSolution,solution,numberColumns*sizeof(double));
00100
00101
00102 char * way = new char[numberIntegers];
00103
00104 double * cost = new double[numberIntegers];
00105
00106 char * mark = new char[numberRows];
00107 memset(mark,0,numberRows);
00108
00109 double * save = new double[numberRows];
00110
00111
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
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
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
00153
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
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
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
00190 mark[iRow]=1;
00191 numberInfeasible++;
00192 }
00193 }
00194
00195 for (k=i+1;k<numberIntegers;k++) {
00196 if ((way[k]&1)!=0) {
00197
00198 if (-objectiveCoefficient-cost[k]<bestChange) {
00199
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
00213 numberMarked++;
00214 }
00215 }
00216 if (good&&numberMarked==numberInfeasible) {
00217
00218 goodK=k;
00219 wayK=-1;
00220 wayI=-1;
00221 bestChange = -objectiveCoefficient-cost[k];
00222 }
00223 }
00224 }
00225 if ((way[k]&2)!=0) {
00226
00227 if (-objectiveCoefficient+cost[k]<bestChange) {
00228
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
00242 numberMarked++;
00243 }
00244 }
00245 if (good&&numberMarked==numberInfeasible) {
00246
00247 goodK=k;
00248 wayK=1;
00249 wayI=-1;
00250 bestChange = -objectiveCoefficient+cost[k];
00251 }
00252 }
00253 }
00254 }
00255
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
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
00274 mark[iRow]=1;
00275 numberInfeasible++;
00276 }
00277 }
00278
00279 for (k=i+1;k<numberIntegers;k++) {
00280 if ((way[k]&1)!=0) {
00281
00282 if (objectiveCoefficient-cost[k]<bestChange) {
00283
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
00297 numberMarked++;
00298 }
00299 }
00300 if (good&&numberMarked==numberInfeasible) {
00301
00302 goodK=k;
00303 wayK=-1;
00304 wayI=1;
00305 bestChange = objectiveCoefficient-cost[k];
00306 }
00307 }
00308 }
00309 if ((way[k]&2)!=0) {
00310
00311 if (objectiveCoefficient+cost[k]<bestChange) {
00312
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
00326 numberMarked++;
00327 }
00328 }
00329 if (good&&numberMarked==numberInfeasible) {
00330
00331 goodK=k;
00332 wayK=1;
00333 wayI=1;
00334 bestChange = objectiveCoefficient+cost[k];
00335 }
00336 }
00337 }
00338 }
00339
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
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
00363 const SbbObject * object = model_->object(goodK);
00364 const SbbSimpleInteger * integerObject =
00365 dynamic_cast<const SbbSimpleInteger *> (object);
00366
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
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
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
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
00421 void SbbLocalSearch::setModel(SbbModel * model)
00422 {
00423 model_ = model;
00424
00425 assert(model_->solver());
00426 matrix_ = *model_->solver()->getMatrixByCol();
00427 }
00428
00429