00001
00002
00003
00004 #include <cstdio>
00005 #include <numeric>
00006 #include <utility>
00007
00008 #include "CoinWarmStart.hpp"
00009 #include "CoinTime.hpp"
00010
00011 #include "BCP_math.hpp"
00012 #include "BCP_enum.hpp"
00013 #include "BCP_matrix.hpp"
00014 #include "BCP_warmstart.hpp"
00015 #include "BCP_lp_result.hpp"
00016 #include "BCP_lp_node.hpp"
00017 #include "BCP_lp_user.hpp"
00018 #include "BCP_lp_functions.hpp"
00019 #include "BCP_lp_pool.hpp"
00020 #include "BCP_lp_branch.hpp"
00021 #include "BCP_lp.hpp"
00022
00023
00024
00025 static inline std::pair<int,int>
00026 BCP_add_branching_objects(BCP_lp_prob& p,
00027 BCP_vec<BCP_lp_branching_object*>& candidates);
00028 static inline void
00029 BCP_mark_result_of_strong_branching(BCP_lp_prob& p,
00030 const BCP_lp_branching_object* can,
00031 const int added_col_num,
00032 const int added_row_num);
00033 static inline BCP_branching_decision
00034 BCP_lp_select_branching_object(BCP_lp_prob& p,
00035 BCP_presolved_lp_brobj*& best_presolved);
00036 static inline void
00037 BCP_lp_make_parent_from_node(BCP_lp_prob& p);
00038
00039
00040
00041 static inline void
00042 BCP_print_brobj_stat(BCP_lp_prob& p,
00043 const int orig_varnum,
00044 const int candidate_num, const int selected,
00045 const BCP_presolved_lp_brobj* best_presolved)
00046 {
00047 const BCP_lp_branching_object* can = best_presolved->candidate();
00048
00049 if (p.param(BCP_lp_par::LpVerb_StrongBranchResult)) {
00050 p.user->print(true, "\nLP: SB selected candidate %i out of %i.\n\n",
00051 selected, candidate_num);
00052 p.user->print(true, "LP: The selected object is:");
00053 if (p.param(BCP_lp_par::LpVerb_StrongBranchPositions)) {
00054 can->print_branching_info(orig_varnum,
00055 p.lp_result->x(),
00056 p.lp_solver->getObjCoefficients());
00057 }
00058 for (int i = 0; i < can->child_num; ++i) {
00059 const BCP_lp_result& res = best_presolved->lpres(i);
00060 const double lb = res.objval();
00061 p.user->print(true,
00062 (lb>BCP_DBL_MAX/10 ? " [%e,%i,%i]":" [%.4f,%i,%i]"),
00063 lb, res.termcode(), res.iternum());
00064 }
00065 p.user->print(true, "\n");
00066 }
00067
00068 if (p.param(BCP_lp_par::LpVerb_ChildrenInfo)){
00069 const BCP_vec<BCP_child_action>& action = best_presolved->action();
00070 for (int i = can->child_num - 1; i >= 0; --i)
00071 switch (action[i]){
00072 case BCP_KeepChild:
00073 case BCP_ReturnChild:
00074 break;
00075 case BCP_FathomChild:
00076 p.user->print(true, "LP: Child %i is fathomed.\n", i);
00077 break;
00078 }
00079 }
00080 }
00081
00082
00083
00084 static inline std::pair<int,int>
00085 BCP_add_branching_objects(BCP_lp_prob& p,
00086 BCP_vec<BCP_lp_branching_object*>& candidates){
00087
00088 if (candidates.size() == 0)
00089 return std::pair<int,int>(0, 0);
00090
00091 BCP_lp_branching_object* can;
00092 BCP_vec<BCP_lp_branching_object*>::iterator cani;
00093 BCP_vec<BCP_lp_branching_object*>::iterator lastcani = candidates.end();
00094 BCP_var_set& vars = p.node->vars;
00095 BCP_cut_set& cuts = p.node->cuts;
00096
00097
00098 int newvar_num = 0;
00099 int newcut_num = 0;
00100 for (cani = candidates.begin(); cani != lastcani; ++cani){
00101 can = *cani;
00102 can->init_pos_for_added(vars.size() + newvar_num,
00103 cuts.size() + newcut_num);
00104 if (can->vars_to_add)
00105 newvar_num += can->vars_to_add->size();
00106 if (can->cuts_to_add)
00107 newcut_num += can->cuts_to_add->size();
00108 }
00109
00110 const int orig_col_num = vars.size();
00111 const int orig_row_num = cuts.size();
00112
00113 OsiSolverInterface* lp = p.lp_solver;
00114
00115
00116 if (newvar_num > 0){
00117 BCP_vec<BCP_var*> new_vars;
00118 new_vars.reserve(newvar_num);
00119 for (cani = candidates.begin(); cani != lastcani; ++cani){
00120 can = *cani;
00121 if (can->vars_to_add)
00122 new_vars.append(*can->vars_to_add);
00123 }
00124
00125 BCP_vec<BCP_col*> cols;
00126 cols.reserve(newvar_num);
00127 p.user->vars_to_cols(cuts, new_vars, cols,
00128 *p.lp_result, BCP_Object_Branching, false);
00129 BCP_lp_add_cols_to_lp(cols, lp);
00130 purge_ptr_vector(cols);
00131
00132 for (int i = 0; i < newvar_num; ++i) {
00133 new_vars[i]->set_bcpind(-BCP_lp_next_var_index(p));
00134 }
00135 vars.append(new_vars);
00136 }
00137
00138
00139 if (newcut_num > 0){
00140 BCP_vec<BCP_cut*> new_cuts;
00141 new_cuts.reserve(newcut_num);
00142 for (cani = candidates.begin(); cani != lastcani; ++cani){
00143 can = *cani;
00144 if (can->cuts_to_add)
00145 new_cuts.append(*can->cuts_to_add);
00146 }
00147
00148 BCP_vec<BCP_row*> rows;
00149 rows.reserve(newcut_num);
00150 BCP_fatal_error::abort_on_error = false;
00151 try {
00152 p.user->cuts_to_rows(vars, new_cuts, rows,
00153 *p.lp_result, BCP_Object_Branching, false);
00154 }
00155 catch (...) {
00156 }
00157 BCP_fatal_error::abort_on_error = true;
00158 BCP_lp_add_rows_to_lp(rows, lp);
00159 purge_ptr_vector(rows);
00160
00161 for (int i = 0; i < newcut_num; ++i) {
00162 new_cuts[i]->set_bcpind(-BCP_lp_next_cut_index(p));
00163 }
00164 cuts.append(new_cuts);
00165 p.node->lb_at_cutgen.insert(p.node->lb_at_cutgen.end(), newcut_num,
00166 p.lp_result->objval());
00167 }
00168
00169
00170
00171
00172
00173 if (newvar_num > 0) {
00174 for (int i = orig_col_num; i < orig_col_num + newvar_num; ++i)
00175 lp->setColBounds(i, 0.0, 0.0);
00176 }
00177 if (newcut_num > 0) {
00178 const double inf = lp->getInfinity();
00179 for (int i = orig_row_num; i < orig_row_num + newcut_num; ++i)
00180 lp->setRowBounds(i, -inf, inf);
00181 }
00182
00183 return std::pair<int,int>(newvar_num, newcut_num);
00184 }
00185
00186
00187
00188 static inline void
00189 BCP_mark_result_of_strong_branching(BCP_lp_prob& p,
00190 const BCP_lp_branching_object* can,
00191 const int added_col_num,
00192 const int added_row_num)
00193 {
00194 BCP_var_set& vars = p.node->vars;
00195 if (can->forced_var_pos) {
00196 BCP_vec<int>::const_iterator ii = can->forced_var_pos->begin();
00197 BCP_vec<int>::const_iterator lastii = can->forced_var_pos->end();
00198 for ( ; ii != lastii; ++ii)
00199 vars[*ii]->make_non_removable();
00200 }
00201 if (can->implied_var_pos) {
00202
00203
00204 BCP_vec<int>::const_iterator ii = can->implied_var_pos->begin();
00205 BCP_vec<int>::const_iterator lastii = can->implied_var_pos->end();
00206 for ( ; ii != lastii; ++ii)
00207 vars[*ii]->make_active();
00208 }
00209
00210 if (added_col_num) {
00211 BCP_var_set::iterator vari = vars.entry(vars.size() - added_col_num);
00212 BCP_var_set::const_iterator lastvari = vars.end();
00213 for ( ; vari != lastvari; ++vari) {
00214 if (! (*vari)->is_non_removable())
00215 (*vari)->make_to_be_removed();
00216 }
00217 }
00218
00219 BCP_cut_set& cuts = p.node->cuts;
00220 if (can->forced_cut_pos) {
00221 BCP_vec<int>::const_iterator ii = can->forced_cut_pos->begin();
00222 BCP_vec<int>::const_iterator lastii = can->forced_cut_pos->end();
00223 for ( ; ii != lastii; ++ii)
00224 cuts[*ii]->make_non_removable();
00225 }
00226 if (can->implied_cut_pos) {
00227
00228
00229 BCP_vec<int>::const_iterator ii = can->implied_cut_pos->begin();
00230 BCP_vec<int>::const_iterator lastii = can->implied_cut_pos->end();
00231 for ( ; ii != lastii; ++ii)
00232 cuts[*ii]->make_active();
00233 }
00234 if (added_row_num > 0){
00235 BCP_cut_set::iterator cuti = cuts.entry(cuts.size() - added_row_num);
00236 BCP_cut_set::const_iterator lastcuti = cuts.end();
00237 for ( ; cuti != lastcuti; ++cuti) {
00238 if (! (*cuti)->is_non_removable())
00239 (*cuti)->make_to_be_removed();
00240 }
00241 }
00242 }
00243
00244
00245
00246 static inline int
00247 BCP_lp_perform_strong_branching(BCP_lp_prob& p,
00248 BCP_vec<BCP_lp_branching_object*>& candidates,
00249 BCP_presolved_lp_brobj*& best_presolved)
00250 {
00251 OsiSolverInterface* lp = p.lp_solver;
00252 BCP_var_set& vars = p.node->vars;
00253 BCP_cut_set& cuts = p.node->cuts;
00254
00255 const int orig_colnum = vars.size();
00256
00257 const std::pair<int,int> added_object_num =
00258 BCP_add_branching_objects(p, candidates);
00259
00260 const int added_colnum = added_object_num.first;
00261 const int added_rownum = added_object_num.second;
00262
00263 const int colnum = vars.size();
00264 const int rownum = cuts.size();
00265
00266 int i, j;
00267
00268 const CoinWarmStart * ws = p.lp_solver->getWarmStart();
00269
00270
00271 lp->markHotStart();
00272
00273
00274 BCP_vec<double> rowbounds(2 * rownum, 0.0);
00275 BCP_vec<double> colbounds(2 * colnum, 0.0);
00276
00277 const int maxind = std::max<int>(rownum, colnum);
00278 BCP_vec<int> all_indices(maxind, 0);
00279 for (i = 0; i < maxind; ++i)
00280 all_indices[i] = i;
00281
00282 const double * rlb_orig = lp->getRowLower();
00283 const double * rub_orig = lp->getRowUpper();
00284 for (j = -1, i = 0; i < rownum; ++i) {
00285 rowbounds[++j] = rlb_orig[i];
00286 rowbounds[++j] = rub_orig[i];
00287 }
00288
00289 const double * clb_orig = lp->getColLower();
00290 const double * cub_orig = lp->getColUpper();
00291 for (j = -1, i = 0; i < colnum; ++i) {
00292 colbounds[++j] = clb_orig[i];
00293 colbounds[++j] = cub_orig[i];
00294 }
00295
00296 best_presolved = 0;
00297
00298
00299 BCP_vec<BCP_lp_branching_object*>::iterator cani;
00300
00301 if (p.param(BCP_lp_par::MaxPresolveIter) > 0) {
00302 lp->setIntParam(OsiMaxNumIterationHotStart,
00303 p.param(BCP_lp_par::MaxPresolveIter));
00304 }
00305
00306 p.user->print(p.param(BCP_lp_par::LpVerb_StrongBranchResult),
00307 "\nLP: Starting strong branching:\n\n");
00308
00309 const OsiBabSolver* babSolver = p.user->getOsiBabSolver();
00310
00311 int cand_ind = -1;
00312 for (cani = candidates.begin(); cani != candidates.end(); ++cani){
00313
00314 BCP_presolved_lp_brobj* tmp_presolved =
00315 new BCP_presolved_lp_brobj(*cani);
00316 const BCP_lp_branching_object* can = *cani;
00317 ++cand_ind;
00318 for (i = 0; i < can->child_num; ++i){
00319 can->apply_child_bd(lp, i);
00320
00321 p.user->modify_lp_parameters(p.lp_solver, 1, true);
00322 #if 0
00323 char fname[1000];
00324 sprintf(fname, "matrix-%i.%i.%i-child-%i.%i",
00325 p.node->level, p.node->index, p.node->iteration_count,
00326 cand_ind, i);
00327 lp->writeMps(fname, "mps");
00328 #endif
00329 lp->solveFromHotStart();
00330 tmp_presolved->get_results(*lp, i);
00331 BCP_lp_test_feasibility(p, tmp_presolved->lpres(i));
00332 if (babSolver) {
00333 p.user->generate_cuts_in_lp(tmp_presolved->lpres(i),
00334 p.node->vars, p.node->cuts,
00335 tmp_presolved->get_new_cuts()[i],
00336 tmp_presolved->get_new_rows()[i]);
00337 }
00338 }
00339
00340 if (can->cuts_affected() > 0)
00341 lp->setRowSetBounds(all_indices.begin(), all_indices.entry(rownum),
00342 rowbounds.begin());
00343 if (can->vars_affected() > 0)
00344 lp->setColSetBounds(all_indices.begin(), all_indices.entry(colnum),
00345 colbounds.begin());
00346
00347 if (p.param(BCP_lp_par::LpVerb_PresolveResult)) {
00348 p.user->print(true, "LP: Presolving:");
00349 if (p.param(BCP_lp_par::LpVerb_PresolvePositions)) {
00350 can->print_branching_info(orig_colnum,
00351 p.lp_result->x(),
00352 p.lp_solver->getObjCoefficients());
00353 }
00354 for (i = 0; i < can->child_num; ++i) {
00355 const BCP_lp_result& res = tmp_presolved->lpres(i);
00356 const double lb = res.objval();
00357 p.user->print(true,
00358 (lb>BCP_DBL_MAX/10 ? " [%e,%i,%i]":" [%.4f,%i,%i]"),
00359 lb, res.termcode(), res.iternum());
00360 }
00361 p.user->print(true, "\n");
00362 }
00363
00364 switch (p.user->compare_branching_candidates(tmp_presolved,
00365 best_presolved)) {
00366 case BCP_OldPresolvedIsBetter:
00367 break;
00368 case BCP_NewPresolvedIsBetter:
00369 std::swap(tmp_presolved, best_presolved);
00370 break;
00371 case BCP_NewPresolvedIsBetter_BranchOnIt:
00372
00373
00374 purge_ptr_vector(candidates, cani + 1, candidates.end());
00375 std::swap(tmp_presolved, best_presolved);
00376 break;
00377 }
00378 delete tmp_presolved;
00379 }
00380
00381
00382 lp->unmarkHotStart();
00383 p.lp_solver->setWarmStart(ws);
00384
00385
00386
00387
00388 BCP_lp_branching_object* can = best_presolved->candidate();
00389 int selected = 0;
00390 for (i=0, cani=candidates.begin(); cani != candidates.end(); ++cani, ++i) {
00391 if (*cani != can) {
00392 delete *cani;
00393 } else {
00394 selected = i;
00395 }
00396 }
00397
00398
00399 BCP_mark_result_of_strong_branching(p, can, added_colnum, added_rownum);
00400
00401
00402 BCP_lp_delete_cols_and_rows(p, can, added_colnum, added_rownum,
00403 false ,
00404 true );
00405
00406 delete ws;
00407
00408 return selected;
00409 }
00410
00411
00412
00413 static inline BCP_branching_decision
00414 BCP_lp_select_branching_object(BCP_lp_prob& p,
00415 BCP_presolved_lp_brobj*& best_presolved)
00416 {
00417 BCP_var_set& vars = p.node->vars;
00418 BCP_cut_set& cuts = p.node->cuts;
00419 BCP_vec<BCP_lp_branching_object*> candidates;
00420
00421 bool force_branch = (p.lp_result->termcode() & BCP_Abandoned) != 0;
00422
00423 BCP_branching_decision do_branch =
00424 p.user->select_branching_candidates(*p.lp_result,
00425 vars, cuts,
00426 *p.local_var_pool,
00427 *p.local_cut_pool,
00428 candidates,
00429 force_branch);
00430 switch (do_branch){
00431 case BCP_DoNotBranch_Fathomed:
00432 return BCP_DoNotBranch_Fathomed;
00433 case BCP_DoNotBranch:
00434 if (p.local_var_pool->size() == 0 && p.local_cut_pool->size() == 0) {
00435
00436
00437
00438
00439 const double petol = p.lp_result->primalTolerance();
00440 const double * x = p.lp_result->x();
00441 for (int i = vars.size() - 1; i >= 0; --i) {
00442 const BCP_var* v = vars[i];
00443 if (x[i] + petol < v->lb() || x[i] - petol > v->ub()) {
00444 return BCP_DoNotBranch;
00445 }
00446 }
00447 const double * lhs = p.lp_result->lhs();
00448 for (int i = cuts.size() - 1; i >= 0; --i) {
00449 const BCP_cut* c = cuts[i];
00450 if (lhs[i] + petol < c->lb() || lhs[i] - petol > c->ub()) {
00451 return BCP_DoNotBranch;
00452 }
00453 }
00454 p.user->print(true, "\
00455 LP: ***WARNING*** : BCP_DoNotBranch, but nothing can be added! ***WARNING***\n");
00456
00457 }
00458 return BCP_DoNotBranch;
00459 case BCP_DoBranch:
00460 break;
00461 }
00462
00463
00464 if (candidates.size() < 1) {
00465 throw BCP_fatal_error("\
00466 BCP_lp_select_branching_object: branching forced but no candidates selected\n");
00467 }
00468
00469
00470 double time0 = CoinCpuTime();
00471 const int orig_colnum = p.node->vars.size();
00472
00473
00474
00475 int selected = 0;
00476 if (p.param(BCP_lp_par::MaxPresolveIter) < 0) {
00477 if (candidates.size() > 1) {
00478 p.user->print(true, "\
00479 LP: Strong branching is disabled but more than one candidate is selected.\n\
00480 Deleting all candidates but the first.\n");
00481
00482 BCP_vec<BCP_lp_branching_object*>::iterator can =
00483 candidates.begin();
00484 for (++can; can != candidates.end(); ++can) {
00485 delete *can;
00486 }
00487 candidates.erase(candidates.begin()+1, candidates.end());
00488 }
00489 BCP_add_branching_objects(p, candidates);
00490 best_presolved = new BCP_presolved_lp_brobj(candidates[0]);
00491 if (candidates[0]->objval_) {
00492 best_presolved->set_objective_values(*candidates[0]->objval_,
00493 *candidates[0]->termcode_,
00494 p.node->true_lower_bound);
00495 } else {
00496 best_presolved->initialize_lower_bound(p.node->true_lower_bound);
00497 }
00498 } else {
00499 selected = BCP_lp_perform_strong_branching(p, candidates,
00500 best_presolved);
00501 }
00502
00503 const BCP_lp_branching_object* can = best_presolved->candidate();
00504
00505
00506 p.user->set_actions_for_children(best_presolved);
00507 BCP_vec<BCP_child_action>& action = best_presolved->action();
00508
00509 if (p.node->dive == BCP_DoNotDive){
00510 bool needed_overriding = false;
00511 for (int i = can->child_num - 1; i >= 0; --i) {
00512 if (action[i] == BCP_KeepChild) {
00513 action[i] = BCP_ReturnChild;
00514 needed_overriding = true;
00515 }
00516 }
00517 p.user->print(needed_overriding &&
00518 p.param(BCP_lp_par::LpVerb_StrongBranchResult),
00519 "LP: Every child is returned because of not diving.\n");
00520 }
00521
00522
00523
00524
00525
00526
00527
00528
00529 if (p.param(BCP_lp_par::MaxPresolveIter) >= 0) {
00530 BCP_print_brobj_stat(p, orig_colnum, candidates.size(), selected,
00531 best_presolved);
00532 }
00533
00534
00535 p.user->set_user_data_for_children(best_presolved, selected);
00536
00537
00538
00539
00540 p.user->modify_lp_parameters(p.lp_solver, 1, false);
00541 p.lp_solver->initialSolve();
00542 p.lp_result->get_results(*p.lp_solver);
00543 p.node->quality = p.lp_result->objval();
00544
00545 p.stat.time_branching += CoinCpuTime() - time0;
00546
00547 return BCP_DoBranch;
00548 }
00549
00550
00551
00552 static inline void
00553 BCP_lp_make_parent_from_node(BCP_lp_prob& p)
00554 {
00555 BCP_lp_parent& parent = *p.parent;
00556 BCP_lp_node& node = *p.node;
00557
00558 const int bvarnum = p.core->varnum();
00559 const int bcutnum = p.core->cutnum();
00560
00561
00562
00563
00564 node.tm_storage.core_change = (bvarnum + bcutnum > 0 ?
00565 BCP_Storage_WrtParent : BCP_Storage_NoData);
00566 int i;
00567
00568 const BCP_var_set& vars = node.vars;
00569 const int varnum = vars.size();
00570 BCP_obj_set_change& var_set = parent.var_set;
00571 BCP_vec<int>& var_ind = var_set._new_objs;
00572 BCP_vec<BCP_obj_change>& var_ch = var_set._change;
00573 var_ind.clear();
00574 var_ch.clear();
00575 var_ind.reserve(varnum - bvarnum);
00576 var_ch.reserve(varnum - bvarnum);
00577 for (i = bvarnum; i < varnum; ++i) {
00578 const BCP_var* var = vars[i];
00579 assert(var->bcpind() > 0);
00580 var_ind.unchecked_push_back(var->bcpind());
00581 var_ch.unchecked_push_back(BCP_obj_change(var->lb(), var->ub(),
00582 var->status()));
00583 }
00584 node.tm_storage.var_change = BCP_Storage_WrtParent;
00585
00586 const BCP_cut_set& cuts = node.cuts;
00587 const int cutnum = cuts.size();
00588 BCP_obj_set_change& cut_set = parent.cut_set;
00589 BCP_vec<int>& cut_ind = cut_set._new_objs;
00590 BCP_vec<BCP_obj_change>& cut_ch = cut_set._change;
00591 cut_ind.clear();
00592 cut_ch.clear();
00593 cut_ind.reserve(cutnum - bcutnum);
00594 cut_ch.reserve(cutnum - bcutnum);
00595 for (i = bcutnum; i < cutnum; ++i) {
00596 const BCP_cut* cut = cuts[i];
00597 assert(cut->bcpind() > 0);
00598 cut_ind.unchecked_push_back(cut->bcpind());
00599 cut_ch.unchecked_push_back(BCP_obj_change(cut->lb(), cut->ub(),
00600 cut->status()));
00601 }
00602 node.tm_storage.cut_change = BCP_Storage_WrtParent;
00603
00604 delete parent.warmstart;
00605 parent.warmstart = node.warmstart;
00606 node.warmstart = 0;
00607 node.tm_storage.warmstart = BCP_Storage_WrtParent;
00608
00609 parent.index = node.index;
00610
00611 delete node.user_data;
00612 node.user_data = 0;
00613 }
00614
00615
00616
00617 BCP_branching_result
00618 BCP_lp_branch(BCP_lp_prob& p)
00619 {
00620 BCP_presolved_lp_brobj* best_presolved = 0;
00621
00622
00623
00624 BCP_branching_decision do_branch = BCP_DoBranch;
00625 do_branch = BCP_lp_select_branching_object(p, best_presolved);
00626
00627 switch (do_branch){
00628 case BCP_DoNotBranch_Fathomed:
00629 BCP_lp_send_cuts_to_cp(p, -1);
00630 BCP_lp_perform_fathom(p,"LP: Forcibly fathoming node in branch().\n",
00631 BCP_Msg_NodeDescription_Discarded);
00632 return BCP_BranchingFathomedThisNode;
00633 case BCP_DoNotBranch:
00634 BCP_lp_send_cuts_to_cp(p,
00635 p.param(BCP_lp_par::CutEffectiveCountBeforePool));
00636
00637
00638 return BCP_BranchingContinueThisNode;
00639 break;
00640 case BCP_DoBranch:
00641 break;
00642 }
00643
00644
00645
00646
00647
00648
00649 int keep = BCP_lp_send_node_description(p, best_presolved,
00650 BCP_Msg_NoMessage);
00651
00652
00653 BCP_lp_send_cuts_to_cp(p, -1);
00654
00655 if (keep < 0){
00656 if (p.param(BCP_lp_par::LpVerb_FathomInfo)) {
00657 if (best_presolved->is_pruned())
00658 p.user->print(true, "LP: Forcibly Pruning node\n");
00659 else
00660 p.user->print(true, "LP: Returned children to TM. Waiting for new node.\n");
00661 }
00662 delete best_presolved->candidate();
00663 delete best_presolved;
00664 BCP_lp_clean_up_node(p);
00665 return BCP_BranchingFathomedThisNode;
00666 }
00667
00668
00669
00670 BCP_lp_make_parent_from_node(p);
00671
00672
00673 BCP_lp_branching_object* can = best_presolved->candidate();
00674 can->apply_child_bd(p.lp_solver, keep);
00675 if (can->vars_affected()) {
00676 BCP_var_set& vars = p.node->vars;
00677 if (can->forced_var_pos) {
00678 vars.set_lb_ub(*can->forced_var_pos, can->forced_var_bd_child(keep));
00679 const BCP_vec<int>& pos = *can->forced_var_pos;
00680 for (int p = pos.size() - 1; p >= 0; --p) {
00681 vars[pos[p]]->make_non_removable();
00682 }
00683 }
00684 if (can->implied_var_pos)
00685 vars.set_lb_ub(*can->implied_var_pos,can->implied_var_bd_child(keep));
00686 }
00687 if (can->cuts_affected()) {
00688 BCP_cut_set& cuts = p.node->cuts;
00689 if (can->forced_cut_pos) {
00690 cuts.set_lb_ub(*can->forced_cut_pos, can->forced_cut_bd_child(keep));
00691 const BCP_vec<int>& pos = *can->forced_cut_pos;
00692 for (int p = pos.size() - 1; p >= 0; --p) {
00693 cuts[pos[p]]->make_non_removable();
00694 }
00695 }
00696 if (can->implied_cut_pos)
00697 cuts.set_lb_ub(*can->implied_cut_pos,can->implied_cut_bd_child(keep));
00698 }
00699
00700 delete p.node->user_data;
00701 p.node->user_data = best_presolved->user_data()[keep];
00702 best_presolved->user_data()[keep] = 0;
00703
00704
00705 delete best_presolved->candidate();
00706 delete best_presolved;
00707
00708 return BCP_BranchingDivedIntoNewNode;
00709 }