00001
00002
00003
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
00047 CoinSort_2(positions.begin(), positions.end(), perm.begin());
00048
00049
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
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
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
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
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
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
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
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
00282
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 }