#include <SbbHeuristic.hpp>
Inheritance diagram for SbbRounding:
Public Member Functions | |
SbbRounding (SbbModel &model) | |
SbbRounding (const SbbRounding &) | |
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) |
void | setSeed (int value) |
Set seed. | |
Protected Attributes | |
CoinPackedMatrix | matrix_ |
CoinPackedMatrix | matrixByRow_ |
int | seed_ |
Private Member Functions | |
SbbRounding & | operator= (const SbbRounding &rhs) |
Illegal Assignment operator. |
Definition at line 67 of file SbbHeuristic.hpp.
|
returns 0 if no solution, 1 if valid solution with better objective value than one passed in Sets solution values if good, sets objective value (only if good) This is called after cuts have been added - so can not add cuts Implements SbbHeuristic. Definition at line 86 of file SbbHeuristic.cpp. References OsiSolverInterface::getColLower(), OsiSolverInterface::getColSolution(), OsiSolverInterface::getColUpper(), OsiSolverInterface::getDblParam(), SbbModel::getDblParam(), OsiSolverInterface::getNumCols(), OsiSolverInterface::getObjCoefficients(), OsiSolverInterface::getObjSense(), OsiSolverInterface::getObjValue(), OsiSolverInterface::getRowLower(), OsiSolverInterface::getRowUpper(), SbbModel::integerVariable(), OsiSolverInterface::isInteger(), SbbModel::numberIntegers(), solution(), and SbbModel::solver(). Referenced by solution().
00088 { 00089 00090 OsiSolverInterface * solver = model_->solver(); 00091 const double * lower = solver->getColLower(); 00092 const double * upper = solver->getColUpper(); 00093 const double * rowLower = solver->getRowLower(); 00094 const double * rowUpper = solver->getRowUpper(); 00095 const double * solution = solver->getColSolution(); 00096 const double * objective = solver->getObjCoefficients(); 00097 double integerTolerance = model_->getDblParam(SbbModel::SbbIntegerTolerance); 00098 double primalTolerance; 00099 solver->getDblParam(OsiPrimalTolerance,primalTolerance); 00100 00101 int numberRows = matrix_.getNumRows(); 00102 00103 int numberIntegers = model_->numberIntegers(); 00104 const int * integerVariable = model_->integerVariable(); 00105 int i; 00106 double direction = solver->getObjSense(); 00107 double newSolutionValue = direction*solver->getObjValue(); 00108 int returnCode = 0; 00109 00110 // Column copy 00111 const double * element = matrix_.getElements(); 00112 const int * row = matrix_.getIndices(); 00113 const int * columnStart = matrix_.getVectorStarts(); 00114 const int * columnLength = matrix_.getVectorLengths(); 00115 // Row copy 00116 const double * elementByRow = matrixByRow_.getElements(); 00117 const int * column = matrixByRow_.getIndices(); 00118 const int * rowStart = matrixByRow_.getVectorStarts(); 00119 const int * rowLength = matrixByRow_.getVectorLengths(); 00120 00121 // Get solution array for heuristic solution 00122 int numberColumns = solver->getNumCols(); 00123 double * newSolution = new double [numberColumns]; 00124 memcpy(newSolution,solution,numberColumns*sizeof(double)); 00125 00126 double * rowActivity = new double[numberRows]; 00127 memset(rowActivity,0,numberRows*sizeof(double)); 00128 for (i=0;i<numberColumns;i++) { 00129 int j; 00130 double value = newSolution[i]; 00131 if (value) { 00132 for (j=columnStart[i]; 00133 j<columnStart[i]+columnLength[i];j++) { 00134 int iRow=row[j]; 00135 rowActivity[iRow] += value*element[j]; 00136 } 00137 } 00138 } 00139 // check was feasible - if not adjust (cleaning may move) 00140 for (i=0;i<numberRows;i++) { 00141 if(rowActivity[i]<rowLower[i]) { 00142 //assert (rowActivity[i]>rowLower[i]-1000.0*primalTolerance); 00143 rowActivity[i]=rowLower[i]; 00144 } else if(rowActivity[i]>rowUpper[i]) { 00145 //assert (rowActivity[i]<rowUpper[i]+1000.0*primalTolerance); 00146 rowActivity[i]=rowUpper[i]; 00147 } 00148 } 00149 for (i=0;i<numberIntegers;i++) { 00150 int iColumn = integerVariable[i]; 00151 double value=newSolution[iColumn]; 00152 if (fabs(floor(value+0.5)-value)>integerTolerance) { 00153 double below = floor(value); 00154 double newValue=newSolution[iColumn]; 00155 double cost = direction * objective[iColumn]; 00156 double move; 00157 if (cost>0.0) { 00158 // try up 00159 move = 1.0 -(value-below); 00160 } else if (cost<0.0) { 00161 // try down 00162 move = below-value; 00163 } else { 00164 // won't be able to move unless we can grab another variable 00165 // just for now go down 00166 move = below-value; 00167 } 00168 newValue += move; 00169 newSolution[iColumn] = newValue; 00170 newSolutionValue += move*cost; 00171 int j; 00172 for (j=columnStart[iColumn]; 00173 j<columnStart[iColumn]+columnLength[iColumn];j++) { 00174 int iRow = row[j]; 00175 rowActivity[iRow] += move*element[j]; 00176 } 00177 } 00178 } 00179 00180 double penalty=0.0; 00181 00182 // see if feasible 00183 for (i=0;i<numberRows;i++) { 00184 double value = rowActivity[i]; 00185 double thisInfeasibility=0.0; 00186 if (value<rowLower[i]-primalTolerance) 00187 thisInfeasibility = value-rowLower[i]; 00188 else if (value>rowUpper[i]+primalTolerance) 00189 thisInfeasibility = value-rowUpper[i]; 00190 if (thisInfeasibility) { 00191 // See if there are any slacks I can use to fix up 00192 // maybe put in coding for multiple slacks? 00193 double bestCost = 1.0e50; 00194 int k; 00195 int iBest=-1; 00196 double addCost=0.0; 00197 double newValue=0.0; 00198 double changeRowActivity=0.0; 00199 double absInfeasibility = fabs(thisInfeasibility); 00200 for (k=rowStart[i];k<rowStart[i]+rowLength[i];k++) { 00201 int iColumn = column[k]; 00202 if (columnLength[iColumn]==1) { 00203 double currentValue = newSolution[iColumn]; 00204 double elementValue = elementByRow[k]; 00205 double lowerValue = lower[iColumn]; 00206 double upperValue = upper[iColumn]; 00207 double gap = rowUpper[i]-rowLower[i]; 00208 double absElement=fabs(elementValue); 00209 if (thisInfeasibility*elementValue>0.0) { 00210 // we want to reduce 00211 if ((currentValue-lowerValue)*absElement>=absInfeasibility) { 00212 // possible - check if integer 00213 double distance = absInfeasibility/absElement; 00214 double thisCost = -direction*objective[iColumn]*distance; 00215 if (solver->isInteger(iColumn)) { 00216 distance = ceil(distance-primalTolerance); 00217 assert (currentValue-distance>=lowerValue-primalTolerance); 00218 if (absInfeasibility-distance*absElement< -gap-primalTolerance) 00219 thisCost=1.0e100; // no good 00220 else 00221 thisCost = -direction*objective[iColumn]*distance; 00222 } 00223 if (thisCost<bestCost) { 00224 bestCost=thisCost; 00225 iBest=iColumn; 00226 addCost = thisCost; 00227 newValue = currentValue-distance; 00228 changeRowActivity = -distance*elementValue; 00229 } 00230 } 00231 } else { 00232 // we want to increase 00233 if ((upperValue-currentValue)*absElement>=absInfeasibility) { 00234 // possible - check if integer 00235 double distance = absInfeasibility/absElement; 00236 double thisCost = direction*objective[iColumn]*distance; 00237 if (solver->isInteger(iColumn)) { 00238 distance = ceil(distance-1.0e-7); 00239 assert (currentValue-distance<=upperValue+primalTolerance); 00240 if (absInfeasibility-distance*absElement< -gap-primalTolerance) 00241 thisCost=1.0e100; // no good 00242 else 00243 thisCost = direction*objective[iColumn]*distance; 00244 } 00245 if (thisCost<bestCost) { 00246 bestCost=thisCost; 00247 iBest=iColumn; 00248 addCost = thisCost; 00249 newValue = currentValue+distance; 00250 changeRowActivity = distance*elementValue; 00251 } 00252 } 00253 } 00254 } 00255 } 00256 if (iBest>=0) { 00257 /*printf("Infeasibility of %g on row %d cost %g\n", 00258 thisInfeasibility,i,addCost);*/ 00259 newSolution[iBest]=newValue; 00260 thisInfeasibility=0.0; 00261 newSolutionValue += addCost; 00262 rowActivity[i] += changeRowActivity; 00263 } 00264 penalty += fabs(thisInfeasibility); 00265 } 00266 } 00267 00268 // Could also set SOS (using random) and repeat 00269 if (!penalty) { 00270 // See if we can do better 00271 //seed_++; 00272 //CoinSeedRandom(seed_); 00273 // Random number between 0 and 1. 00274 double randomNumber = CoinDrand48(); 00275 int iPass; 00276 int start[2]; 00277 int end[2]; 00278 int iRandom = (int) (randomNumber*((double) numberIntegers)); 00279 start[0]=iRandom; 00280 end[0]=numberIntegers; 00281 start[1]=0; 00282 end[1]=iRandom; 00283 for (iPass=0;iPass<2;iPass++) { 00284 int i; 00285 for (i=start[iPass];i<end[iPass];i++) { 00286 int iColumn = integerVariable[i]; 00287 double value=newSolution[iColumn]; 00288 assert (fabs(floor(value+0.5)-value)<integerTolerance); 00289 double cost = direction * objective[iColumn]; 00290 double move=0.0; 00291 if (cost>0.0) 00292 move = -1.0; 00293 else if (cost<0.0) 00294 move=1.0; 00295 while (move) { 00296 bool good=true; 00297 double newValue=newSolution[iColumn]+move; 00298 if (newValue<lower[iColumn]-primalTolerance|| 00299 newValue>upper[iColumn]+primalTolerance) { 00300 move=0.0; 00301 } else { 00302 // see if we can move 00303 int j; 00304 for (j=columnStart[iColumn]; 00305 j<columnStart[iColumn]+columnLength[iColumn];j++) { 00306 int iRow = row[j]; 00307 double newActivity = rowActivity[iRow] + move*element[j]; 00308 if (newActivity<rowLower[iRow]-primalTolerance|| 00309 newActivity>rowUpper[iRow]+primalTolerance) { 00310 good=false; 00311 break; 00312 } 00313 } 00314 if (good) { 00315 newSolution[iColumn] = newValue; 00316 newSolutionValue += move*cost; 00317 int j; 00318 for (j=columnStart[iColumn]; 00319 j<columnStart[iColumn]+columnLength[iColumn];j++) { 00320 int iRow = row[j]; 00321 rowActivity[iRow] += move*element[j]; 00322 } 00323 } else { 00324 move=0.0; 00325 } 00326 } 00327 } 00328 } 00329 } 00330 if (newSolutionValue<solutionValue) { 00331 // paranoid check 00332 memset(rowActivity,0,numberRows*sizeof(double)); 00333 for (i=0;i<numberColumns;i++) { 00334 int j; 00335 double value = newSolution[i]; 00336 if (value) { 00337 for (j=columnStart[i]; 00338 j<columnStart[i]+columnLength[i];j++) { 00339 int iRow=row[j]; 00340 rowActivity[iRow] += value*element[j]; 00341 } 00342 } 00343 } 00344 // check was approximately feasible 00345 bool feasible=true; 00346 for (i=0;i<numberRows;i++) { 00347 if(rowActivity[i]<rowLower[i]) { 00348 if (rowActivity[i]<rowLower[i]-1000.0*primalTolerance) 00349 feasible = false; 00350 } else if(rowActivity[i]>rowUpper[i]) { 00351 if (rowActivity[i]>rowUpper[i]+1000.0*primalTolerance) 00352 feasible = false; 00353 } 00354 } 00355 if (feasible) { 00356 // new solution 00357 memcpy(betterSolution,newSolution,numberColumns*sizeof(double)); 00358 solutionValue = newSolutionValue; 00359 //printf("** Solution of %g found by rounding\n",newSolutionValue); 00360 returnCode=1; 00361 } else { 00362 // Can easily happen 00363 //printf("Debug SbbRounding giving bad solution\n"); 00364 } 00365 } 00366 } 00367 delete [] newSolution; 00368 delete [] rowActivity; 00369 return returnCode; 00370 } |