/home/coin/SVN-release/OS-2.0.0/Bcp/src/LP/BCP_lp_branching.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 <cstdio>
00005 #include <numeric>
00006 #include <utility> // for pair<>
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     // Print some statistics
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     // to make things short
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     // first count the number of cols/rows to add
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     // deal with the vars
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     // now add the rows
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     // mark the newly added vars as fixed to 0, and the newly added cuts as
00170     // free. (var_indices and cut_indices simply contain the indices of the
00171     // added vars/cuts.)
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         // just to make sure that these vars are not deleted before the implied
00203         // bound change takes place...
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         // just to make sure that these cuts are not deleted before the implied
00228         // bound change takes place...
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; // loop variable
00267 
00268     const CoinWarmStart * ws = p.lp_solver->getWarmStart();
00269 
00270     // prepare for strong branching
00271     lp->markHotStart();
00272 
00273     // save the lower/upper bounds of every var/cut
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     // Look at the candidates one-by-one and presolve them.
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         // Create a temporary branching object to hold the current results
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             // bound changes always imply that primal feasibility is lost.
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         // reset the bounds of the affected vars/cuts
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         // Compare the current one with the best so far
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             // Free the remaining candidates if there are any. This also resets
00373             // candidates.end(), thus 
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     // indicate to the lp solver that strong branching is done
00382     lp->unmarkHotStart();
00383     p.lp_solver->setWarmStart(ws);
00384 
00385     // delete all the candidates but the selected one (candidates will just
00386     // silently go out of scope and we'll be left with a pointer to the final
00387     // candidate in best_presolved).
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     // Mark the cols/rows of the OTHER candidates as removable
00399     BCP_mark_result_of_strong_branching(p, can, added_colnum, added_rownum);
00400     // Delete whatever cols/rows we want to delete. This function also updates
00401     // var/cut_positions !!!
00402     BCP_lp_delete_cols_and_rows(p, can, added_colnum, added_rownum,
00403                                 false /* not from fathom */,
00404                                 true /* to force deletion */);
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             /* Hmmm... check whether some magic was done and the former sol is
00436                now infeasible, so resolving is perfectly normal.
00437                NOTE: We only check whether the former primal sol and lhs
00438                values are within the bounds! */
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; // YES...
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; // YES...
00452                 }
00453             }
00454             p.user->print(true, "\
00455 LP: ***WARNING*** : BCP_DoNotBranch, but nothing can be added! ***WARNING***\n");
00456             //throw BCP_fatal_error("BCP_DoNotBranch, but nothing can be added!\n");
00457         }
00458         return BCP_DoNotBranch;
00459     case BCP_DoBranch:
00460         break;
00461     }
00462 
00463     // give error message if there are no branching candidates
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     // ** OK, now we have to branch. **
00470     double time0 = CoinCpuTime();
00471     const int orig_colnum = p.node->vars.size();
00472 
00473     // if branching candidates are not presolved then choose the first
00474     // branching candidate as the best candidate.
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             // delete all other candidates
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     // decide what to do with each child
00506     p.user->set_actions_for_children(best_presolved);
00507     BCP_vec<BCP_child_action>& action = best_presolved->action();
00508     // override the set values if we won't dive
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     // We don't know what is fathomable! strong branching may give an approx
00523     // sol for the children's subproblems, but it may not be a lower
00524     // bound. Let the tree manager decide what to do with them.
00525 
00526     // now throw out the fathomable ones. This can be done only if nothing
00527     // needs to be priced, there already is an upper bound and strong branching
00528     // was enabled (otherwise we don't have the LPs solved)
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     // finally get the user data for the children
00535     p.user->set_user_data_for_children(best_presolved, selected);
00536    
00537     // Now just resolve the LP to get what'll be sent to the TM.
00538     // 2nd arg is 1, since only only bd changes happened which can afffect
00539     // only primal feasibility 
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     // deal with parent's fields one-by-one
00562 
00563     // core_as_change has already been updated correctly in BCP_lp_pack_core()
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     // this is needed to stop gcc complaining about uninitialized use of
00623     // do_branch (this complaint might arise from inlining)
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         // the branching objects are already added and we will add from the
00637         // local pools as well.
00638         return BCP_BranchingContinueThisNode;
00639         break;
00640     case BCP_DoBranch:
00641         break;
00642     }
00643 
00644     // Now p.node has the final set of vars/cuts for this node, and this
00645     // routine will extract the final warmstart information. Send this all off
00646     // to the the TM. This function also sends off the branching info, and gets
00647     // diving info from TM. In case of diving it receives/updates the index of
00648     // the node and the internal indices of the not yet indexed vars/cuts.
00649     int keep = BCP_lp_send_node_description(p, best_presolved,
00650                                             BCP_Msg_NoMessage);
00651 
00652     // send out the cuts to be sent to the CP
00653     BCP_lp_send_cuts_to_cp(p, -1);
00654 
00655     if (keep < 0){ // if no diving then return quickly
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     // Otherwise we dive. start updating things.
00669     // first move the current node to be the parent
00670     BCP_lp_make_parent_from_node(p);
00671 
00672     // now apply the bounds of the kept child
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     // Delete the old user data before getting new
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     // Get rid of best_presolved
00705     delete best_presolved->candidate();
00706     delete best_presolved;
00707 
00708     return BCP_BranchingDivedIntoNewNode;
00709 }

Generated on Mon Aug 3 03:02:15 2009 by  doxygen 1.4.7