/home/coin/SVN-release/OS-2.1.1/Bcp/src/LP/BCP_lp_branch.cpp

Go to the documentation of this file.
00001 // Copyright (C) 2000, International Business Machines
00002 // Corporation and others.  All Rights Reserved.
00003 // #include <cfloat>
00004 #include <numeric>
00005 #include <algorithm>
00006 
00007 #include "CoinSort.hpp"
00008 
00009 #include "BCP_math.hpp"
00010 #include "BCP_vector.hpp"
00011 #include "BCP_lp_branch.hpp"
00012 
00013 #include "OsiSolverInterface.hpp"
00014 #include "OsiBranchingObject.hpp"
00015 
00016 #include "BCP_var.hpp"
00017 #include "BCP_cut.hpp"
00018 #include "BCP_lp_result.hpp"
00019 
00020 //#############################################################################
00021 
00022 static void
00023 BCP_reset_pos(BCP_vec<int>& pos, const int start)
00024 {
00025    int i = pos.size();
00026    while (--i >= 0) {
00027       if (pos[i] < 0) {
00028          pos[i] = (start - 1) - pos[i];
00029       }
00030    }
00031 }
00032 
00033 //#############################################################################
00034 
00035 static void BCP_reorder_pos(const int child_num,
00036                             BCP_vec<int>& positions, BCP_vec<double>& bounds)
00037 {
00038    const int size = positions.size();
00039    if (size <= 1)
00040       return;
00041 
00042    BCP_vec<int> perm;
00043    perm.reserve(size);
00044    for (int i = 0; i < size; ++i)
00045       perm.unchecked_push_back(i);
00046    // order the pair list based on the first entry (pos)
00047    CoinSort_2(positions.begin(), positions.end(), perm.begin());
00048 
00049    // apply the permutation to each block in bounds
00050    BCP_vec<double> new_bd;
00051    new_bd.reserve(bounds.size());
00052    const BCP_vec<int>::const_iterator lastpos = perm.end();
00053    for (int i = 0; i < child_num; ++i){
00054       BCP_vec<double>::const_iterator old_bd = bounds.entry(2 * size * i);
00055       BCP_vec<int>::const_iterator pos = perm.begin();
00056       for ( ; pos != lastpos; ++pos) {
00057          const int bd_pos = *pos << 1;
00058          new_bd.unchecked_push_back(*(old_bd + bd_pos));
00059          new_bd.unchecked_push_back(*(old_bd + (bd_pos+1)));
00060       }
00061    }
00062    bounds = new_bd;
00063 }
00064 
00065 //#############################################################################
00066 
00067 BCP_lp_branching_object::
00068 BCP_lp_branching_object(const BCP_lp_integer_branching_object& o,
00069                         const int* order) :
00070     child_num(2),
00071     vars_to_add(0), cuts_to_add(0),
00072     forced_var_pos(new BCP_vec<int>(1,-1)), forced_cut_pos(0),
00073     forced_var_bd(new BCP_vec<double>(4,0.0)), forced_cut_bd(0),
00074     implied_var_pos(0), implied_cut_pos(0),
00075     implied_var_bd(0), implied_cut_bd(0),
00076     objval_(0), termcode_(0)
00077 {
00078     BCP_vec<int>& fvp = *forced_var_pos;
00079     BCP_vec<double>& fvb = *forced_var_bd;
00080     fvp[0] = o.originalObject()->columnNumber();
00081     memcpy(&fvb[0], o.childBounds(order[0]), 2*sizeof(double));
00082     memcpy(&fvb[2], o.childBounds(order[1]), 2*sizeof(double));
00083 }
00084 
00085 //#############################################################################
00086 
00087 BCP_lp_branching_object::
00088 BCP_lp_branching_object(const OsiSolverInterface* osi,
00089                         const BCP_lp_sos_branching_object& o,
00090                         const int* order) :
00091     child_num(2),
00092     vars_to_add(0), cuts_to_add(0),
00093     forced_var_pos(0), forced_cut_pos(0),
00094     forced_var_bd(0), forced_cut_bd(0),
00095     implied_var_pos(0), implied_cut_pos(0),
00096     implied_var_bd(0), implied_cut_bd(0),
00097     objval_(0), termcode_(0)
00098 {
00099     const OsiSOS* sos = dynamic_cast<const OsiSOS*>(o.originalObject());
00100     const int * which = sos->members();
00101     const double * weights = sos->weights();
00102     const double value = o.value();
00103     int i;
00104 
00105     const double* clb = osi->getColLower();
00106     const double* cub = osi->getColUpper();
00107 
00108     const int len = sos->numberMembers();
00109     forced_var_pos = new BCP_vec<int>(sos->members(), sos->members()+len);
00110     forced_var_bd  = new BCP_vec<double>(4*len, 0.0);
00111     BCP_vec<double>& fvb = *forced_var_bd;
00112     double* downchildBounds = NULL;
00113     double* upchildBounds = NULL;
00114     if ( order[0] == 0) {
00115         downchildBounds = &fvb[0];
00116         upchildBounds = &fvb[2*len];
00117     } else {
00118         downchildBounds = &fvb[2*len];
00119         upchildBounds = &fvb[0];
00120     }
00121     for (i = 0; i < len; ++i) {
00122         const int pos = which[i];
00123         downchildBounds[2*i]   = upchildBounds[2*i]   = clb[pos];
00124         downchildBounds[2*i+1] = upchildBounds[2*i+1] = cub[pos];
00125     }
00126     // upper bounds in child 0
00127     for (i = 0; i < len; ++i) {
00128         if (weights[i] > value)
00129             break;
00130     }
00131     assert (i < len);
00132     for ( ; i < len; ++i) {
00133         downchildBounds[2*i+1] = 0.0;
00134     }
00135     // upper bounds in child 1
00136     for (i = 0 ; i < len; ++i) {
00137         if (weights[i] >= value)
00138             break;
00139         else
00140             upchildBounds[2*i+1] = 0.0;
00141     }
00142     assert ( i < len);
00143 }
00144 
00145 //#############################################################################
00146 
00147 void
00148 BCP_lp_branching_object::init_pos_for_added(const int added_vars_start,
00149                                             const int added_cuts_start)
00150 {
00151    if (vars_to_add){
00152       if (forced_var_pos)
00153          BCP_reset_pos(*forced_var_pos, added_vars_start);
00154       if (implied_var_pos)
00155          BCP_reset_pos(*implied_var_pos, added_vars_start);
00156    }
00157    if (cuts_to_add){
00158       if (forced_cut_pos)
00159          BCP_reset_pos(*forced_cut_pos, added_cuts_start);
00160       if (implied_cut_pos)
00161          BCP_reset_pos(*implied_cut_pos, added_cuts_start);
00162    }
00163 
00164    // reorder the positions so that it's increasing everywhere
00165    if (forced_var_pos)
00166       BCP_reorder_pos(child_num, *forced_var_pos, *forced_var_bd);
00167    if (implied_var_pos)
00168       BCP_reorder_pos(child_num, *implied_var_pos, *implied_var_bd);
00169    if (forced_cut_pos)
00170       BCP_reorder_pos(child_num, *forced_cut_pos, *forced_cut_bd);
00171    if (implied_cut_pos)
00172       BCP_reorder_pos(child_num, *implied_cut_pos, *implied_cut_bd);
00173 }
00174 
00175 //#############################################################################
00176 
00177 void
00178 BCP_lp_branching_object::apply_child_bd(OsiSolverInterface* lp,
00179                                         const int child_ind) const
00180 {
00181    if (forced_var_pos) {
00182       const int len = forced_var_pos->size();
00183       lp->setColSetBounds(forced_var_pos->begin(), forced_var_pos->end(),
00184                           forced_var_bd->entry(2 * len * child_ind));
00185    }
00186    if (implied_var_pos) {
00187       const int len = implied_var_pos->size();
00188       lp->setColSetBounds(implied_var_pos->begin(), implied_var_pos->end(),
00189                           implied_var_bd->entry(2 * len * child_ind));
00190    }
00191    if (forced_cut_pos) {
00192       const int len = forced_cut_pos->size();
00193       lp->setRowSetBounds(forced_cut_pos->begin(), forced_cut_pos->end(),
00194                           forced_cut_bd->entry(2 * len * child_ind));
00195    }
00196    if (implied_cut_pos) {
00197       const int len = implied_cut_pos->size();
00198       lp->setRowSetBounds(implied_cut_pos->begin(), implied_cut_pos->end(),
00199                           implied_cut_bd->entry(2 * len * child_ind));
00200    }
00201 }
00202 
00203 //#############################################################################
00204 
00205 void
00206 BCP_lp_branching_object::print_branching_info(const int orig_varnum,
00207                                               const double * x,
00208                                               const double * obj) const
00209 {
00210    printf(" (");
00211    if (forced_var_pos) {
00212       const int ind = (*forced_var_pos)[0];
00213       if (ind < orig_varnum) {
00214          printf("%i,%.4f,%.4f", ind, x[ind], obj[ind]);
00215       } else {
00216          // must be a var added in branching
00217          printf(";%i,-,-", ind);
00218       }
00219       const int size = forced_var_pos->size();
00220       for (int i = 1; i < size; ++i) {
00221          const int ind = (*forced_var_pos)[i];
00222          if (ind < orig_varnum) {
00223             printf(";%i,%.4f,%.4f", ind, x[ind], obj[ind]);
00224          } else {
00225             // must be a var added in branching
00226             printf(";%i,-,-", ind);
00227          }
00228       }
00229    }
00230    printf(" / ");
00231    if (forced_cut_pos) {
00232       printf("%i", (*forced_cut_pos)[0]);
00233       const int size = forced_cut_pos->size();
00234       for (int i = 1; i < size; ++i)
00235          printf(";%i", (*forced_cut_pos)[i]);
00236    }
00237    printf(" )");
00238 }
00239 
00240 //#############################################################################
00241 
00242 void BCP_presolved_lp_brobj::fake_objective_values(const double itlim_objval)
00243 {
00244    for (int i = _candidate->child_num - 1; i >= 0; --i){
00245       const int tc = _lpres[i]->termcode();
00246       if (tc & (BCP_ProvenPrimalInf | BCP_DualObjLimReached)) {
00247          _lpres[i]->fake_objective_value(BCP_DBL_MAX);
00248          continue;
00249       }
00250       // *THINK* : what to do in these cases?
00251       if (tc & (BCP_ProvenDualInf | BCP_PrimalObjLimReached |
00252                 BCP_IterationLimit | BCP_Abandoned | BCP_TimeLimit) ) {
00253          _lpres[i]->fake_objective_value(itlim_objval);
00254          continue;
00255       }
00256    }
00257 }
00258 
00259 void BCP_presolved_lp_brobj::set_objective_values(const BCP_vec<double>& obj,
00260                                                   const BCP_vec<int>& termcode,
00261                                                   const double itlim_objval)
00262 {
00263    for (int i = _candidate->child_num - 1; i >= 0; --i) {
00264       const int tc = termcode[i];
00265       if (tc & (BCP_ProvenPrimalInf | BCP_DualObjLimReached)) {
00266          _lpres[i]->fake_objective_value(BCP_DBL_MAX);
00267          continue;
00268       }
00269       // *THINK* : what to do in these cases?
00270       if (tc & (BCP_ProvenDualInf | BCP_PrimalObjLimReached |
00271                 BCP_IterationLimit | BCP_Abandoned | BCP_TimeLimit) ) {
00272          _lpres[i]->fake_objective_value(itlim_objval);
00273          continue;
00274       }
00275       _lpres[i]->fake_objective_value(obj[i]);
00276    }
00277 }
00278 
00279 bool BCP_presolved_lp_brobj::fathomable(const double objval_limit) const
00280 {
00281    // If ALL descendants in cand terminated with primal infeasibility
00282    // or high cost, that proves that the current node can be fathomed.
00283    for (int i = _candidate->child_num - 1; i >= 0; --i) {
00284       const int tc = _lpres[i]->termcode();
00285       if (! ((tc & BCP_ProvenPrimalInf) ||
00286              (tc & BCP_DualObjLimReached) ||
00287              ((tc & BCP_ProvenOptimal) && _lpres[i]->objval() > objval_limit)))
00288          return false;
00289    }
00290    return true;
00291 }
00292 
00293 bool BCP_presolved_lp_brobj::had_numerical_problems() const
00294 {
00295    for (int i = _candidate->child_num - 1; i >= 0; --i)
00296       if (_lpres[i]->termcode() == BCP_Abandoned)
00297          return true;
00298    return false;
00299 }

Generated on Mon May 3 03:05:11 2010 by  doxygen 1.4.7