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 "SbbBranchActual.hpp"
00015 #include "CoinSort.hpp"
00016
00017
00018 SbbClique::SbbClique ()
00019 : SbbObject(),
00020 numberMembers_(0),
00021 numberNonSOSMembers_(0),
00022 members_(NULL),
00023 type_(NULL),
00024 cliqueType_(-1),
00025 slack_(-1)
00026 {
00027 }
00028
00029
00030 SbbClique::SbbClique (SbbModel * model, int cliqueType, int numberMembers,
00031 const int * which, const char * type, int identifier,int slack)
00032 : SbbObject(model)
00033 {
00034 id_=identifier;
00035 numberMembers_=numberMembers;
00036 if (numberMembers_) {
00037 members_ = new int[numberMembers_];
00038 memcpy(members_,which,numberMembers_*sizeof(int));
00039 type_ = new char[numberMembers_];
00040 memcpy(type_,type,numberMembers_*sizeof(char));
00041 } else {
00042 members_ = NULL;
00043 type_ = NULL;
00044 }
00045
00046 int i;
00047 numberNonSOSMembers_=0;
00048 for (i=0;i<numberMembers_;i++)
00049 if (!type_[i])
00050 numberNonSOSMembers_++;
00051 cliqueType_ = cliqueType;
00052 slack_ = slack;
00053 }
00054
00055
00056 SbbClique::SbbClique ( const SbbClique & rhs)
00057 :SbbObject(rhs)
00058 {
00059 numberMembers_ = rhs.numberMembers_;
00060 numberNonSOSMembers_ = rhs.numberNonSOSMembers_;
00061 if (numberMembers_) {
00062 members_ = new int[numberMembers_];
00063 memcpy(members_,rhs.members_,numberMembers_*sizeof(int));
00064 type_ = new char[numberMembers_];
00065 memcpy(type_,rhs.type_,numberMembers_*sizeof(char));
00066 } else {
00067 members_ = NULL;
00068 type_ = NULL;
00069 }
00070 cliqueType_ = rhs.cliqueType_;
00071 slack_ = rhs.slack_;
00072 }
00073
00074
00075 SbbObject *
00076 SbbClique::clone() const
00077 {
00078 return new SbbClique(*this);
00079 }
00080
00081
00082 SbbClique &
00083 SbbClique::operator=( const SbbClique& rhs)
00084 {
00085 if (this!=&rhs) {
00086 SbbObject::operator=(rhs);
00087 delete [] members_;
00088 delete [] type_;
00089 numberMembers_ = rhs.numberMembers_;
00090 numberNonSOSMembers_ = rhs.numberNonSOSMembers_;
00091 if (numberMembers_) {
00092 members_ = new int[numberMembers_];
00093 memcpy(members_,rhs.members_,numberMembers_*sizeof(int));
00094 type_ = new char[numberMembers_];
00095 memcpy(type_,rhs.type_,numberMembers_*sizeof(char));
00096 } else {
00097 members_ = NULL;
00098 type_ = NULL;
00099 }
00100 cliqueType_ = rhs.cliqueType_;
00101 slack_ = rhs.slack_;
00102 }
00103 return *this;
00104 }
00105
00106
00107 SbbClique::~SbbClique ()
00108 {
00109 delete [] members_;
00110 delete [] type_;
00111 }
00112
00113
00114 double
00115 SbbClique::infeasibility(int & preferredWay, double & otherWay) const
00116 {
00117 int numberUnsatis=0, numberFree=0;
00118 int j;
00119 const int * integer = model_->integerVariable();
00120 OsiSolverInterface * solver = model_->solver();
00121 const double * solution = model_->currentSolution();
00122 const double * lower = solver->getColLower();
00123 const double * upper = solver->getColUpper();
00124 double largestValue=0.0;
00125 double integerTolerance =
00126 model_->getDblParam(SbbModel::SbbIntegerTolerance);
00127 double * sort = new double[numberMembers_];
00128
00129 double slackValue=0.0;
00130 for (j=0;j<numberMembers_;j++) {
00131 int sequence = members_[j];
00132 int iColumn = integer[sequence];
00133 double value = solution[iColumn];
00134 value = max(value, lower[iColumn]);
00135 value = min(value, upper[iColumn]);
00136 double nearest = floor(value+0.5);
00137 double distance = fabs(value-nearest);
00138 if (distance>integerTolerance) {
00139 if (!type_[j])
00140 value = 1.0-value;
00141
00142 if (j==slack_&&value>0.05)
00143 slackValue = value;
00144 largestValue = max(value,largestValue);
00145 sort[numberUnsatis++]=-value;
00146 } else if (upper[iColumn]>lower[iColumn]) {
00147 numberFree++;
00148 }
00149 }
00150 preferredWay=1;
00151 otherWay = 0.0;
00152 if (numberUnsatis) {
00153
00154 std::sort(sort,sort+numberUnsatis);
00155 for (j=0;j<numberUnsatis;j++) {
00156 if ((j&1)!=0)
00157 otherWay += -sort[j];
00158 }
00159
00160 double value = 0.2*numberUnsatis+0.01*(numberMembers_-numberFree);
00161 if (fabs(largestValue-0.5)<0.1) {
00162
00163 value +=0.1;
00164 }
00165 if (slackValue) {
00166
00167 value += slackValue;
00168 }
00169
00170 otherWay *= value/(1.0-otherWay);
00171 delete [] sort;
00172 return value;
00173 } else {
00174 delete [] sort;
00175 return 0.0;
00176 }
00177 }
00178
00179
00180 void
00181 SbbClique::feasibleRegion()
00182 {
00183 int j;
00184 const int * integer = model_->integerVariable();
00185 OsiSolverInterface * solver = model_->solver();
00186 const double * solution = model_->currentSolution();
00187 const double * lower = solver->getColLower();
00188 const double * upper = solver->getColUpper();
00189 double integerTolerance =
00190 model_->getDblParam(SbbModel::SbbIntegerTolerance);
00191
00192 for (j=0;j<numberMembers_;j++) {
00193 int sequence = members_[j];
00194 int iColumn = integer[sequence];
00195 double value = solution[iColumn];
00196 value = max(value, lower[iColumn]);
00197 value = min(value, upper[iColumn]);
00198 double nearest = floor(value+0.5);
00199 double distance = fabs(value-nearest);
00200 assert(distance<=integerTolerance);
00201 solver->setColLower(iColumn,nearest);
00202 solver->setColUpper(iColumn,nearest);
00203 }
00204 }
00205
00206
00207
00208 SbbBranchingObject *
00209 SbbClique::createBranch(int way) const
00210 {
00211 int numberUnsatis=0;
00212 int j;
00213 int nUp=0;
00214 int nDown=0;
00215 int numberFree=numberMembers_;
00216 const int * integer = model_->integerVariable();
00217 OsiSolverInterface * solver = model_->solver();
00218 const double * solution = model_->currentSolution();
00219 const double * lower = solver->getColLower();
00220 const double * upper = solver->getColUpper();
00221 int * upList = new int[numberMembers_];
00222 int * downList = new int[numberMembers_];
00223 double * sort = new double[numberMembers_];
00224 double integerTolerance =
00225 model_->getDblParam(SbbModel::SbbIntegerTolerance);
00226
00227 double slackValue=0.0;
00228 for (j=0;j<numberMembers_;j++) {
00229 int sequence = members_[j];
00230 int iColumn = integer[sequence];
00231 double value = solution[iColumn];
00232 value = max(value, lower[iColumn]);
00233 value = min(value, upper[iColumn]);
00234 double nearest = floor(value+0.5);
00235 double distance = fabs(value-nearest);
00236 if (distance>integerTolerance) {
00237 if (!type_[j])
00238 value = 1.0-value;
00239
00240 if (j==slack_&&value>0.05)
00241 slackValue = value;
00242 value = -value;
00243 upList[numberUnsatis]=j;
00244 sort[numberUnsatis++]=value;
00245 } else if (upper[iColumn]>lower[iColumn]) {
00246 upList[--numberFree]=j;
00247 }
00248 }
00249 assert (numberUnsatis);
00250 if (!slackValue) {
00251
00252 CoinSort_2(sort,sort+numberUnsatis,upList);
00253
00254 int kWay=1;
00255 for (j=0;j<numberUnsatis;j++) {
00256 if (kWay>0)
00257 upList[nUp++]=upList[j];
00258 else
00259 downList[nDown++]=upList[j];
00260 kWay = -kWay;
00261 }
00262 for (j=numberFree;j<numberMembers_;j++) {
00263 if (kWay>0)
00264 upList[nUp++]=upList[j];
00265 else
00266 downList[nDown++]=upList[j];
00267 kWay = -kWay;
00268 }
00269 } else {
00270
00271 nUp = 1;
00272 upList[0]=slack_;
00273 for (j=0;j<numberUnsatis;j++) {
00274 downList[nDown++]=upList[j];
00275 }
00276 for (j=numberFree;j<numberMembers_;j++) {
00277 downList[nDown++]=upList[j];
00278 }
00279 }
00280
00281 SbbBranchingObject * branch;
00282 if (numberMembers_ <=64)
00283 branch = new SbbCliqueBranchingObject(model_,this,way,
00284 nDown,downList,nUp,upList);
00285 else
00286 branch = new SbbLongCliqueBranchingObject(model_,this,way,
00287 nDown,downList,nUp,upList);
00288 delete [] upList;
00289 delete [] downList;
00290 delete [] sort;
00291 return branch;
00292 }
00293
00294
00295
00300 SbbSimpleInteger::SbbSimpleInteger ()
00301 : SbbObject(),
00302 sequence_(-1),
00303 columnNumber_(-1),
00304 originalLower_(0.0),
00305 originalUpper_(1.0)
00306 {
00307 }
00308
00313 SbbSimpleInteger::SbbSimpleInteger (SbbModel * model, int sequence,
00314 int iColumn)
00315 : SbbObject(model)
00316 {
00317 sequence_ = sequence ;
00318 columnNumber_ = iColumn ;
00319 originalLower_ = model_->solver()->getColLower()[columnNumber_] ;
00320 originalUpper_ = model_->solver()->getColUpper()[columnNumber_] ;
00321 }
00322
00323
00324 SbbSimpleInteger::SbbSimpleInteger ( const SbbSimpleInteger & rhs)
00325 :SbbObject(rhs)
00326
00327 {
00328 sequence_ = rhs.sequence_;
00329 columnNumber_ = model_->integerVariable()[sequence_];
00330 originalLower_ = rhs.originalLower_;
00331 originalUpper_ = rhs.originalUpper_;
00332 }
00333
00334
00335 SbbObject *
00336 SbbSimpleInteger::clone() const
00337 {
00338 return new SbbSimpleInteger(*this);
00339 }
00340
00341
00342 SbbSimpleInteger &
00343 SbbSimpleInteger::operator=( const SbbSimpleInteger& rhs)
00344 {
00345 if (this!=&rhs) {
00346 SbbObject::operator=(rhs);
00347 columnNumber_ = model_->integerVariable()[sequence_];
00348 }
00349 return *this;
00350 }
00351
00352
00353 SbbSimpleInteger::~SbbSimpleInteger ()
00354 {
00355 }
00356
00357
00358 double
00359 SbbSimpleInteger::infeasibility(int & preferredWay, double & otherWay) const
00360 {
00361 OsiSolverInterface * solver = model_->solver();
00362 const double * solution = model_->currentSolution();
00363 const double * lower = solver->getColLower();
00364 const double * upper = solver->getColUpper();
00365 double value = solution[columnNumber_];
00366 value = max(value, lower[columnNumber_]);
00367 value = min(value, upper[columnNumber_]);
00368
00369
00370 double nearest = floor(value+0.5);
00371 double integerTolerance =
00372 model_->getDblParam(SbbModel::SbbIntegerTolerance);
00373 if (nearest>value)
00374 preferredWay=1;
00375 else
00376 preferredWay=-1;
00377 otherWay = 1.0-fabs(value-nearest);
00378 if (fabs(value-nearest)<=integerTolerance)
00379 return 0.0;
00380 else
00381 return fabs(value-nearest);
00382 }
00383
00384
00389 void
00390 SbbSimpleInteger::feasibleRegion()
00391 {
00392 OsiSolverInterface * solver = model_->solver();
00393 const double * lower = solver->getColLower();
00394 const double * upper = solver->getColUpper();
00395 const double * solution = model_->currentSolution();
00396 double value = solution[columnNumber_];
00397 value = max(value, lower[columnNumber_]);
00398 value = min(value, upper[columnNumber_]);
00399
00400 double nearest = floor(value+0.5);
00401 double integerTolerance =
00402 model_->getDblParam(SbbModel::SbbIntegerTolerance);
00403
00404 assert (fabs(value-nearest)<=100.0*integerTolerance);
00405 solver->setColLower(columnNumber_,nearest);
00406 solver->setColUpper(columnNumber_,nearest);
00407 }
00408
00409
00410 SbbBranchingObject *
00411 SbbSimpleInteger::createBranch(int way) const
00412 {
00413 OsiSolverInterface * solver = model_->solver();
00414 const double * solution = model_->currentSolution();
00415 const double * lower = solver->getColLower();
00416 const double * upper = solver->getColUpper();
00417 double value = solution[columnNumber_];
00418 value = max(value, lower[columnNumber_]);
00419 value = min(value, upper[columnNumber_]);
00420 double nearest = floor(value+0.5);
00421 double integerTolerance =
00422 model_->getDblParam(SbbModel::SbbIntegerTolerance);
00423 assert (fabs(value-nearest)>integerTolerance);
00424 return new SbbIntegerBranchingObject(model_,sequence_,way,
00425 value);
00426 }
00427
00428
00429
00430
00431
00432
00433
00434 SbbBranchingObject *
00435 SbbSimpleInteger::preferredNewFeasible() const
00436 {
00437 OsiSolverInterface * solver = model_->solver();
00438 double value = model_->currentSolution()[columnNumber_];
00439
00440 double nearest = floor(value+0.5);
00441 double integerTolerance =
00442 model_->getDblParam(SbbModel::SbbIntegerTolerance);
00443 assert (fabs(value-nearest)<=integerTolerance);
00444 double dj = solver->getObjSense()*solver->getReducedCost()[columnNumber_];
00445 SbbIntegerBranchingObject * object = NULL;
00446 if (dj>=0.0) {
00447
00448 if (nearest>originalLower_+0.5) {
00449
00450 object = new SbbIntegerBranchingObject(model_,sequence_,-1,
00451 nearest-1.0,nearest-1.0);
00452 }
00453 } else {
00454
00455 if (nearest<originalUpper_-0.5) {
00456
00457 object = new SbbIntegerBranchingObject(model_,sequence_,-1,
00458 nearest+1.0,nearest+1.0);
00459 }
00460 }
00461 return object;
00462 }
00463
00464
00465
00466
00467
00468
00469 SbbBranchingObject *
00470 SbbSimpleInteger::notPreferredNewFeasible() const
00471 {
00472 OsiSolverInterface * solver = model_->solver();
00473 double value = model_->currentSolution()[columnNumber_];
00474
00475 double nearest = floor(value+0.5);
00476 double integerTolerance =
00477 model_->getDblParam(SbbModel::SbbIntegerTolerance);
00478 assert (fabs(value-nearest)<=integerTolerance);
00479 double dj = solver->getObjSense()*solver->getReducedCost()[columnNumber_];
00480 SbbIntegerBranchingObject * object = NULL;
00481 if (dj<=0.0) {
00482
00483 if (nearest>originalLower_+0.5) {
00484
00485 object = new SbbIntegerBranchingObject(model_,sequence_,-1,
00486 nearest-1.0,nearest-1.0);
00487 }
00488 } else {
00489
00490 if (nearest<originalUpper_-0.5) {
00491
00492 object = new SbbIntegerBranchingObject(model_,sequence_,-1,
00493 nearest+1.0,nearest+1.0);
00494 }
00495 }
00496 return object;
00497 }
00498
00499
00500
00501
00502
00503 void
00504 SbbSimpleInteger::resetBounds()
00505 {
00506 originalLower_ = model_->solver()->getColLower()[columnNumber_];
00507 originalUpper_ = model_->solver()->getColUpper()[columnNumber_];
00508 }
00509
00510
00511
00512 SbbIntegerBranchingObject::SbbIntegerBranchingObject()
00513 :SbbBranchingObject()
00514 {
00515 down_[0] = 0.0;
00516 down_[1] = 0.0;
00517 up_[0] = 0.0;
00518 up_[1] = 0.0;
00519 }
00520
00521
00522 SbbIntegerBranchingObject::SbbIntegerBranchingObject (SbbModel * model,
00523 int variable, int way , double value)
00524 :SbbBranchingObject(model,variable,way,value)
00525 {
00526 int iColumn = model_->integerVariable()[variable_];
00527 down_[0] = model_->solver()->getColLower()[iColumn];
00528 down_[1] = floor(value_);
00529 up_[0] = ceil(value_);
00530 up_[1] = model->getColUpper()[iColumn];
00531 }
00532
00533 SbbIntegerBranchingObject::SbbIntegerBranchingObject (SbbModel * model,
00534 int variable, int way,
00535 double lowerValue,
00536 double upperValue)
00537 :SbbBranchingObject(model,variable,way,lowerValue)
00538 {
00539 numberBranchesLeft_=1;
00540 down_[0] = lowerValue;
00541 down_[1] = upperValue;
00542 up_[0] = lowerValue;
00543 up_[1] = upperValue;
00544 }
00545
00546
00547
00548 SbbIntegerBranchingObject::SbbIntegerBranchingObject ( const SbbIntegerBranchingObject & rhs) :SbbBranchingObject(rhs)
00549 {
00550 down_[0] = rhs.down_[0];
00551 down_[1] = rhs.down_[1];
00552 up_[0] = rhs.up_[0];
00553 up_[1] = rhs.up_[1];
00554 }
00555
00556
00557 SbbIntegerBranchingObject &
00558 SbbIntegerBranchingObject::operator=( const SbbIntegerBranchingObject& rhs)
00559 {
00560 if (this != &rhs) {
00561 SbbBranchingObject::operator=(rhs);
00562 down_[0] = rhs.down_[0];
00563 down_[1] = rhs.down_[1];
00564 up_[0] = rhs.up_[0];
00565 up_[1] = rhs.up_[1];
00566 }
00567 return *this;
00568 }
00569 SbbBranchingObject *
00570 SbbIntegerBranchingObject::clone() const
00571 {
00572 return (new SbbIntegerBranchingObject(*this));
00573 }
00574
00575
00576
00577 SbbIntegerBranchingObject::~SbbIntegerBranchingObject ()
00578 {
00579 }
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590 void
00591 SbbIntegerBranchingObject::branch()
00592 {
00593 numberBranchesLeft_--;
00594 int iColumn = model_->integerVariable()[variable_];
00595 if (way_<0) {
00596 #ifdef SBB_DEBUG
00597 { double olb,oub ;
00598 olb = model_->solver()->getColLower()[iColumn] ;
00599 oub = model_->solver()->getColUpper()[iColumn] ;
00600 printf("branching down on var %d: [%g,%g] => [%g,%g]\n",
00601 iColumn,olb,oub,down_[0],down_[1]) ; }
00602 #endif
00603 model_->solver()->setColLower(iColumn,down_[0]);
00604 model_->solver()->setColUpper(iColumn,down_[1]);
00605 way_=1;
00606 } else {
00607 #ifdef SBB_DEBUG
00608 { double olb,oub ;
00609 olb = model_->solver()->getColLower()[iColumn] ;
00610 oub = model_->solver()->getColUpper()[iColumn] ;
00611 printf("branching up on var %d: [%g,%g] => [%g,%g]\n",
00612 iColumn,olb,oub,up_[0],up_[1]) ; }
00613 #endif
00614 model_->solver()->setColLower(iColumn,up_[0]);
00615 model_->solver()->setColUpper(iColumn,up_[1]);
00616 way_=-1;
00617 }
00618 }
00619
00620
00621 SbbCliqueBranchingObject::SbbCliqueBranchingObject()
00622 :SbbBranchingObject()
00623 {
00624 clique_ = NULL;
00625 downMask_[0]=0;
00626 downMask_[1]=0;
00627 upMask_[0]=0;
00628 upMask_[1]=0;
00629 }
00630
00631
00632 SbbCliqueBranchingObject::SbbCliqueBranchingObject (SbbModel * model,
00633 const SbbClique * clique,
00634 int way ,
00635 int numberOnDownSide, const int * down,
00636 int numberOnUpSide, const int * up)
00637 :SbbBranchingObject(model,clique->id(),way,0.5)
00638 {
00639 clique_ = clique;
00640 downMask_[0]=0;
00641 downMask_[1]=0;
00642 upMask_[0]=0;
00643 upMask_[1]=0;
00644 int i;
00645 for (i=0;i<numberOnDownSide;i++) {
00646 int sequence = down[i];
00647 int iWord = sequence>>5;
00648 int iBit = sequence - 32*iWord;
00649 unsigned int k = 1<<iBit;
00650 downMask_[iWord] |= k;
00651 }
00652 for (i=0;i<numberOnUpSide;i++) {
00653 int sequence = up[i];
00654 int iWord = sequence>>5;
00655 int iBit = sequence - 32*iWord;
00656 unsigned int k = 1<<iBit;
00657 upMask_[iWord] |= k;
00658 }
00659 }
00660
00661
00662 SbbCliqueBranchingObject::SbbCliqueBranchingObject ( const SbbCliqueBranchingObject & rhs) :SbbBranchingObject(rhs)
00663 {
00664 clique_=rhs.clique_;
00665 downMask_[0]=rhs.downMask_[0];
00666 downMask_[1]=rhs.downMask_[1];
00667 upMask_[0]=rhs.upMask_[0];
00668 upMask_[1]=rhs.upMask_[1];
00669 }
00670
00671
00672 SbbCliqueBranchingObject &
00673 SbbCliqueBranchingObject::operator=( const SbbCliqueBranchingObject& rhs)
00674 {
00675 if (this != &rhs) {
00676 SbbBranchingObject::operator=(rhs);
00677 clique_=rhs.clique_;
00678 downMask_[0]=rhs.downMask_[0];
00679 downMask_[1]=rhs.downMask_[1];
00680 upMask_[0]=rhs.upMask_[0];
00681 upMask_[1]=rhs.upMask_[1];
00682 }
00683 return *this;
00684 }
00685 SbbBranchingObject *
00686 SbbCliqueBranchingObject::clone() const
00687 {
00688 return (new SbbCliqueBranchingObject(*this));
00689 }
00690
00691
00692
00693 SbbCliqueBranchingObject::~SbbCliqueBranchingObject ()
00694 {
00695 }
00696 void
00697 SbbCliqueBranchingObject::branch()
00698 {
00699 numberBranchesLeft_--;
00700 int iWord;
00701 int numberMembers = clique_->numberMembers();
00702 const int * which = clique_->members();
00703 const int * integerVariables = model_->integerVariable();
00704 int numberWords=(numberMembers+31)>>5;
00705
00706 if (way_<0) {
00707 #ifdef FULL_PRINT
00708 printf("Down Fix ");
00709 #endif
00710 for (iWord=0;iWord<numberWords;iWord++) {
00711 int i;
00712 for (i=0;i<32;i++) {
00713 unsigned int k = 1<<i;
00714 if ((upMask_[iWord]&k)!=0) {
00715 int iColumn = which[i+32*iWord];
00716 #ifdef FULL_PRINT
00717 printf("%d ",i+32*iWord);
00718 #endif
00719
00720 if (clique_->type(i+32*iWord))
00721 model_->solver()->setColUpper(integerVariables[iColumn],0.0);
00722 else
00723 model_->solver()->setColLower(integerVariables[iColumn],1.0);
00724 }
00725 }
00726 }
00727 way_=1;
00728 } else {
00729 #ifdef FULL_PRINT
00730 printf("Up Fix ");
00731 #endif
00732 for (iWord=0;iWord<numberWords;iWord++) {
00733 int i;
00734 for (i=0;i<32;i++) {
00735 unsigned int k = 1<<i;
00736 if ((downMask_[iWord]&k)!=0) {
00737 int iColumn = which[i+32*iWord];
00738 #ifdef FULL_PRINT
00739 printf("%d ",i+32*iWord);
00740 #endif
00741
00742 if (clique_->type(i+32*iWord))
00743 model_->solver()->setColUpper(integerVariables[iColumn],0.0);
00744 else
00745 model_->solver()->setColLower(integerVariables[iColumn],1.0);
00746 }
00747 }
00748 }
00749 way_=-1;
00750 }
00751 #ifdef FULL_PRINT
00752 printf("\n");
00753 #endif
00754 }
00755
00756
00757 SbbLongCliqueBranchingObject::SbbLongCliqueBranchingObject()
00758 :SbbBranchingObject()
00759 {
00760 clique_=NULL;
00761 downMask_=NULL;
00762 upMask_=NULL;
00763 }
00764
00765
00766 SbbLongCliqueBranchingObject::SbbLongCliqueBranchingObject (SbbModel * model,
00767 const SbbClique * clique,
00768 int way ,
00769 int numberOnDownSide, const int * down,
00770 int numberOnUpSide, const int * up)
00771 :SbbBranchingObject(model,clique->id(),way,0.5)
00772 {
00773 clique_ = clique;
00774 int numberMembers = clique_->numberMembers();
00775 int numberWords=(numberMembers+31)>>5;
00776 downMask_ = new unsigned int [numberWords];
00777 upMask_ = new unsigned int [numberWords];
00778 memset(downMask_,0,numberWords*sizeof(unsigned int));
00779 memset(upMask_,0,numberWords*sizeof(unsigned int));
00780 int i;
00781 for (i=0;i<numberOnDownSide;i++) {
00782 int sequence = down[i];
00783 int iWord = sequence>>5;
00784 int iBit = sequence - 32*iWord;
00785 unsigned int k = 1<<iBit;
00786 downMask_[iWord] |= k;
00787 }
00788 for (i=0;i<numberOnUpSide;i++) {
00789 int sequence = up[i];
00790 int iWord = sequence>>5;
00791 int iBit = sequence - 32*iWord;
00792 unsigned int k = 1<<iBit;
00793 upMask_[iWord] |= k;
00794 }
00795 }
00796
00797
00798 SbbLongCliqueBranchingObject::SbbLongCliqueBranchingObject ( const SbbLongCliqueBranchingObject & rhs) :SbbBranchingObject(rhs)
00799 {
00800 clique_=rhs.clique_;
00801 if (rhs.downMask_) {
00802 int numberMembers = clique_->numberMembers();
00803 int numberWords=(numberMembers+31)>>5;
00804 downMask_ = new unsigned int [numberWords];
00805 memcpy(downMask_,rhs.downMask_,numberWords*sizeof(unsigned int));
00806 upMask_ = new unsigned int [numberWords];
00807 memcpy(upMask_,rhs.upMask_,numberWords*sizeof(unsigned int));
00808 } else {
00809 downMask_=NULL;
00810 upMask_=NULL;
00811 }
00812 }
00813
00814
00815 SbbLongCliqueBranchingObject &
00816 SbbLongCliqueBranchingObject::operator=( const SbbLongCliqueBranchingObject& rhs)
00817 {
00818 if (this != &rhs) {
00819 SbbBranchingObject::operator=(rhs);
00820 clique_=rhs.clique_;
00821 delete [] downMask_;
00822 delete [] upMask_;
00823 if (rhs.downMask_) {
00824 int numberMembers = clique_->numberMembers();
00825 int numberWords=(numberMembers+31)>>5;
00826 downMask_ = new unsigned int [numberWords];
00827 memcpy(downMask_,rhs.downMask_,numberWords*sizeof(unsigned int));
00828 upMask_ = new unsigned int [numberWords];
00829 memcpy(upMask_,rhs.upMask_,numberWords*sizeof(unsigned int));
00830 } else {
00831 downMask_=NULL;
00832 upMask_=NULL;
00833 }
00834 }
00835 return *this;
00836 }
00837 SbbBranchingObject *
00838 SbbLongCliqueBranchingObject::clone() const
00839 {
00840 return (new SbbLongCliqueBranchingObject(*this));
00841 }
00842
00843
00844
00845 SbbLongCliqueBranchingObject::~SbbLongCliqueBranchingObject ()
00846 {
00847 delete [] downMask_;
00848 delete [] upMask_;
00849 }
00850 void
00851 SbbLongCliqueBranchingObject::branch()
00852 {
00853 numberBranchesLeft_--;
00854 int iWord;
00855 int numberMembers = clique_->numberMembers();
00856 const int * which = clique_->members();
00857 const int * integerVariables = model_->integerVariable();
00858 int numberWords=(numberMembers+31)>>5;
00859
00860 if (way_<0) {
00861 #ifdef FULL_PRINT
00862 printf("Down Fix ");
00863 #endif
00864 for (iWord=0;iWord<numberWords;iWord++) {
00865 int i;
00866 for (i=0;i<32;i++) {
00867 unsigned int k = 1<<i;
00868 if ((upMask_[iWord]&k)!=0) {
00869 int iColumn = which[i+32*iWord];
00870 #ifdef FULL_PRINT
00871 printf("%d ",i+32*iWord);
00872 #endif
00873
00874 if (clique_->type(i+32*iWord))
00875 model_->solver()->setColUpper(integerVariables[iColumn],0.0);
00876 else
00877 model_->solver()->setColLower(integerVariables[iColumn],1.0);
00878 }
00879 }
00880 }
00881 way_=1;
00882 } else {
00883 #ifdef FULL_PRINT
00884 printf("Up Fix ");
00885 #endif
00886 for (iWord=0;iWord<numberWords;iWord++) {
00887 int i;
00888 for (i=0;i<32;i++) {
00889 unsigned int k = 1<<i;
00890 if ((downMask_[iWord]&k)!=0) {
00891 int iColumn = which[i+32*iWord];
00892 #ifdef FULL_PRINT
00893 printf("%d ",i+32*iWord);
00894 #endif
00895
00896 if (clique_->type(i+32*iWord))
00897 model_->solver()->setColUpper(integerVariables[iColumn],0.0);
00898 else
00899 model_->solver()->setColLower(integerVariables[iColumn],1.0);
00900 }
00901 }
00902 }
00903 way_=-1;
00904 }
00905 #ifdef FULL_PRINT
00906 printf("\n");
00907 #endif
00908 }
00909
00910 SbbBranchDefaultDecision::SbbBranchDefaultDecision()
00911 :SbbBranchDecision()
00912 {
00913 bestCriterion_ = 0.0;
00914 bestChangeUp_ = 0.0;
00915 bestNumberUp_ = 0;
00916 bestChangeDown_ = 0.0;
00917 bestNumberDown_ = 0;
00918 bestObject_ = NULL;
00919 }
00920
00921
00922 SbbBranchDefaultDecision::SbbBranchDefaultDecision (
00923 const SbbBranchDefaultDecision & rhs)
00924 :SbbBranchDecision()
00925 {
00926 bestCriterion_ = rhs.bestCriterion_;
00927 bestChangeUp_ = rhs.bestChangeUp_;
00928 bestNumberUp_ = rhs.bestNumberUp_;
00929 bestChangeDown_ = rhs.bestChangeDown_;
00930 bestNumberDown_ = rhs.bestNumberDown_;
00931 bestObject_ = rhs.bestObject_;
00932 }
00933
00934 SbbBranchDefaultDecision::~SbbBranchDefaultDecision()
00935 {
00936 }
00937
00938
00939 SbbBranchDecision *
00940 SbbBranchDefaultDecision::clone() const
00941 {
00942 return new SbbBranchDefaultDecision(*this);
00943 }
00944
00945
00946 void
00947 SbbBranchDefaultDecision::initialize(SbbModel * model)
00948 {
00949 bestCriterion_ = 0.0;
00950 bestChangeUp_ = 0.0;
00951 bestNumberUp_ = 0;
00952 bestChangeDown_ = 0.0;
00953 bestNumberDown_ = 0;
00954 bestObject_ = NULL;
00955 }
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965 int
00966 SbbBranchDefaultDecision::betterBranch(SbbBranchingObject * thisOne,
00967 SbbBranchingObject * bestSoFar,
00968 double changeUp, int numInfUp,
00969 double changeDn, int numInfDn)
00970 {
00971 bool beforeSolution = thisOne->model()->getSolutionCount()==
00972 thisOne->model()->getNumberHeuristicSolutions();;
00973 int betterWay=0;
00974 if (beforeSolution) {
00975 if (!bestObject_) {
00976 bestNumberUp_=INT_MAX;
00977 bestNumberDown_=INT_MAX;
00978 }
00979
00980
00981 int bestNumber = min(bestNumberUp_,bestNumberDown_);
00982 if (numInfUp<numInfDn) {
00983 if (numInfUp<bestNumber) {
00984 betterWay = 1;
00985 } else if (numInfUp==bestNumber) {
00986 if (changeUp<bestCriterion_)
00987 betterWay=1;
00988 }
00989 } else if (numInfUp>numInfDn) {
00990 if (numInfDn<bestNumber) {
00991 betterWay = -1;
00992 } else if (numInfDn==bestNumber) {
00993 if (changeDn<bestCriterion_)
00994 betterWay=-1;
00995 }
00996 } else {
00997
00998 bool better=false;
00999 if (numInfUp<bestNumber) {
01000 better=true;
01001 } else if (numInfUp==bestNumber) {
01002 if (min(changeUp,changeDn)<bestCriterion_)
01003 better=true;;
01004 }
01005 if (better) {
01006
01007 if (changeUp<=changeDn)
01008 betterWay=1;
01009 else
01010 betterWay=-1;
01011 }
01012 }
01013 } else {
01014 if (!bestObject_) {
01015 bestCriterion_=-1.0;
01016 }
01017
01018 if (changeUp<=changeDn) {
01019 if (changeUp>bestCriterion_)
01020 betterWay=1;
01021 } else {
01022 if (changeDn>bestCriterion_)
01023 betterWay=-1;
01024 }
01025 }
01026 if (betterWay) {
01027 bestCriterion_ = min(changeUp,changeDn);
01028 bestChangeUp_ = changeUp;
01029 bestNumberUp_ = numInfUp;
01030 bestChangeDown_ = changeDn;
01031 bestNumberDown_ = numInfDn;
01032 bestObject_=thisOne;
01033 }
01034 return betterWay;
01035 }