#include <SbbHeuristicUser.hpp>
Inheritance diagram for SbbLocalSearch:
Public Member Functions | |
SbbLocalSearch (SbbModel &model) | |
SbbLocalSearch (const SbbLocalSearch &) | |
virtual SbbHeuristic * | clone () 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 | |
SbbLocalSearch & | operator= (const SbbLocalSearch &rhs) |
Illegal Assignment operator. |
Definition at line 10 of file SbbHeuristicUser.hpp.
|
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 } |