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

SbbBranchActual.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 "SbbBranchActual.hpp"
00015 #include "CoinSort.hpp"
00016 
00017 // Default Constructor 
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 // Useful constructor (which are integer indices)
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   // Find out how many non sos
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 // Copy constructor 
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 // Clone
00075 SbbObject *
00076 SbbClique::clone() const
00077 {
00078   return new SbbClique(*this);
00079 }
00080 
00081 // Assignment operator 
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 // Destructor 
00107 SbbClique::~SbbClique ()
00108 {
00109   delete [] members_;
00110   delete [] type_;
00111 }
00112 
00113 // Infeasibility - large is 0.5
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; // non SOS
00141       // if slack then choose that
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     // sort
00154     std::sort(sort,sort+numberUnsatis);
00155     for (j=0;j<numberUnsatis;j++) {
00156       if ((j&1)!=0)
00157         otherWay += -sort[j];
00158     }
00159     // Need to think more
00160     double value = 0.2*numberUnsatis+0.01*(numberMembers_-numberFree);
00161     if (fabs(largestValue-0.5)<0.1) {
00162       // close to half
00163       value +=0.1;
00164     }
00165     if (slackValue) {
00166       // branching on slack
00167       value += slackValue;
00168     }
00169     // scale other way
00170     otherWay *= value/(1.0-otherWay);
00171     delete [] sort;
00172     return value;
00173   } else {
00174     delete [] sort;
00175     return 0.0; // satisfied
00176   }
00177 }
00178 
00179 // This looks at solution and sets bounds to contain solution
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 // Creates a branching object
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; // non SOS
00239       // if slack then choose that
00240       if (j==slack_&&value>0.05)
00241         slackValue = value;
00242       value = -value; // for sort
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     // sort
00252     CoinSort_2(sort,sort+numberUnsatis,upList);
00253     // put first in up etc
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     // put slack to 0 in first way
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   // create object
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 // Copy constructor 
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 // Clone
00335 SbbObject *
00336 SbbSimpleInteger::clone() const
00337 {
00338   return new SbbSimpleInteger(*this);
00339 }
00340 
00341 // Assignment operator 
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 // Destructor 
00353 SbbSimpleInteger::~SbbSimpleInteger ()
00354 {
00355 }
00356 
00357 // Infeasibility - large is 0.5
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   /*printf("%d %g %g %g %g\n",columnNumber_,value,lower[columnNumber_],
00369     solution[columnNumber_],upper[columnNumber_]);*/
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 // This looks at solution and sets bounds to contain solution
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   // Scaling may have moved it a bit
00404   assert (fabs(value-nearest)<=100.0*integerTolerance);
00405   solver->setColLower(columnNumber_,nearest);
00406   solver->setColUpper(columnNumber_,nearest);
00407 }
00408 
00409 // Creates a branching object
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 /* Given valid solution (i.e. satisfied) and reduced costs etc
00430    returns a branching object which would give a new feasible
00431    point in direction reduced cost says would be cheaper.
00432    If no feasible point returns null
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     // can we go down
00448     if (nearest>originalLower_+0.5) {
00449       // yes
00450       object = new SbbIntegerBranchingObject(model_,sequence_,-1,
00451                                              nearest-1.0,nearest-1.0);
00452     }
00453   } else {
00454     // can we go up
00455     if (nearest<originalUpper_-0.5) {
00456       // yes
00457       object = new SbbIntegerBranchingObject(model_,sequence_,-1,
00458                                              nearest+1.0,nearest+1.0);
00459     }
00460   }
00461   return object;
00462 }
00463   
00464 /* Given valid solution (i.e. satisfied) and reduced costs etc
00465    returns a branching object which would give a new feasible
00466    point in direction opposite to one reduced cost says would be cheaper.
00467    If no feasible point returns null
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     // can we go down
00483     if (nearest>originalLower_+0.5) {
00484       // yes
00485       object = new SbbIntegerBranchingObject(model_,sequence_,-1,
00486                                              nearest-1.0,nearest-1.0);
00487     }
00488   } else {
00489     // can we go up
00490     if (nearest<originalUpper_-0.5) {
00491       // yes
00492       object = new SbbIntegerBranchingObject(model_,sequence_,-1,
00493                                              nearest+1.0,nearest+1.0);
00494     }
00495   }
00496   return object;
00497 }
00498   
00499 /*
00500   Bounds may be tightened, so it may be good to be able to refresh the local
00501   copy of the original bounds.
00502  */
00503 void 
00504 SbbSimpleInteger::resetBounds()
00505 {
00506   originalLower_ = model_->solver()->getColLower()[columnNumber_];
00507   originalUpper_ = model_->solver()->getColUpper()[columnNumber_];
00508 }
00509 
00510 
00511 // Default Constructor 
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 // Useful constructor
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 // Useful constructor for fixing
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 // Copy constructor 
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 // Assignment operator 
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 // Destructor 
00577 SbbIntegerBranchingObject::~SbbIntegerBranchingObject ()
00578 {
00579 }
00580 
00581 /*
00582   Perform a branch by adjusting the bounds of the specified variable. Note
00583   that each arm of the branch advances the object to the next arm by
00584   advancing the value of way_.
00585 
00586   Providing new values for the variable's lower and upper bounds for each
00587   branching direction gives a little bit of additional flexibility and will
00588   be easily extensible to multi-way branching.
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;      // Swap direction
00617   }
00618 }
00619   
00620 // Default Constructor 
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 // Useful constructor
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 // Copy constructor 
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 // Assignment operator 
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 // Destructor 
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   // *** for way - up means fix all those in down section
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           // fix weak way
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;       // Swap direction
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           // fix weak way
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;      // Swap direction
00750   }
00751 #ifdef FULL_PRINT
00752   printf("\n");
00753 #endif
00754 }
00755   
00756 // Default Constructor 
00757 SbbLongCliqueBranchingObject::SbbLongCliqueBranchingObject()
00758   :SbbBranchingObject()
00759 {
00760   clique_=NULL;
00761   downMask_=NULL;
00762   upMask_=NULL;
00763 }
00764 
00765 // Useful constructor
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 // Copy constructor 
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 // Assignment operator 
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 // Destructor 
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   // *** for way - up means fix all those in down section
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           // fix weak way
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;       // Swap direction
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           // fix weak way
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;      // Swap direction
00904   }
00905 #ifdef FULL_PRINT
00906   printf("\n");
00907 #endif
00908 }
00909 // Default Constructor 
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 // Copy constructor 
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 // Clone
00939 SbbBranchDecision * 
00940 SbbBranchDefaultDecision::clone() const
00941 {
00942   return new SbbBranchDefaultDecision(*this);
00943 }
00944 
00945 // Initialize i.e. before start of choosing at a node
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   Simple default decision algorithm. Compare based on infeasibility (numInfUp,
00960   numInfDn) until a solution is found by search, then switch to change in
00961   objective (changeUp, changeDn). Note that bestSoFar is remembered in
00962   bestObject_, so the parameter bestSoFar is unused.
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     // before solution - choose smallest number 
00980     // could add in depth as well
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       // up and down have same number
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         // see which way
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     // got a solution
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 }

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