/home/coin/SVN-release/OS-2.1.0/Bcp/src/LP/BCP_lp_generate_cuts.cpp

Go to the documentation of this file.
00001 // Copyright (C) 2000, International Business Machines
00002 // Corporation and others.  All Rights Reserved.
00003 #include "CoinTime.hpp"
00004 
00005 #include "BCP_lp_functions.hpp"
00006 #include "BCP_enum.hpp"
00007 #include "BCP_lp_result.hpp"
00008 #include "BCP_lp_pool.hpp"
00009 #include "BCP_lp_user.hpp"
00010 #include "BCP_lp.hpp"
00011 #include "BCP_lp_node.hpp"
00012 
00013 int BCP_lp_generate_cuts(BCP_lp_prob& p,
00014                          bool varset_changed, const bool from_repricing)
00015 {
00016     double time0 = CoinCpuTime();
00017 
00018     BCP_lp_result& lpres = *p.lp_result;
00019     BCP_lp_cut_pool& cp = *p.local_cut_pool;
00020     int prev_size = cp.size();
00021 
00022     if (prev_size > 0 && ! cp.rows_are_valid()){
00023         // we must regenerate the rows from the constraints
00024         // first delete the old rows then expand the cuts again
00025 
00026         // these will hold cuts and rows expanded from the cuts
00027         BCP_vec<BCP_cut*> cuts;
00028         BCP_vec<BCP_row*> rows;
00029 
00030         cuts.reserve(prev_size);
00031         int i;
00032         for (i = 0; i < prev_size; ++i) {
00033             cp[i]->delete_row();
00034             cuts.unchecked_push_back(cp[i]->cut());
00035         }
00036         // now expand
00037         rows.reserve(prev_size);
00038         p.user->cuts_to_rows(p.node->vars, cuts, rows,
00039                              lpres, BCP_Object_Leftover, false);
00040         for (i = 0; i < prev_size; ++i) {
00041             cp[i]->set_row(rows[i]);
00042         }
00043         rows.clear();
00044     }
00045     cp.rows_are_valid(true);
00046 
00047     if (p.param(BCP_lp_par::LpVerb_ReportLocalCutPoolSize))
00048         printf("LP:   Number of leftover cuts: %i\n", prev_size);
00049 
00050     // Generate cuts within the LP process
00051     BCP_vec<BCP_cut*> new_cuts;
00052     BCP_vec<BCP_row*> new_rows;
00053     if (p.user_has_lp_result_processing) {
00054         new_cuts = p.new_cuts;
00055         new_rows = p.new_rows;
00056         p.new_cuts.clear();
00057         p.new_rows.clear();
00058     } else {
00059         p.user->generate_cuts_in_lp(lpres, p.node->vars, p.node->cuts,
00060                                     new_cuts, new_rows);
00061     }
00062     if (new_cuts.size() > 0) {
00063         const int new_size = new_cuts.size();
00064         if (new_rows.size() != 0) {
00065             if (static_cast<int>(new_rows.size()) != new_size) {
00066                 throw BCP_fatal_error("\
00067 LP: uneven new_cuts/new_rows sizes in generate_cuts_in_lp().\n");
00068             }
00069         } else {
00070             // expand the generated cuts
00071             new_rows.reserve(new_size);
00072             p.user->cuts_to_rows(p.node->vars, new_cuts, new_rows,
00073                                  lpres, BCP_Object_FromGenerator, false);
00074         }
00075 
00076         cp.reserve(cp.size() + new_size);
00077         for (int i = 0; i < new_size; ++i) {
00078             new_cuts[i]->set_bcpind(-BCP_lp_next_cut_index(p));
00079             cp.unchecked_push_back(new BCP_lp_waiting_row(new_cuts[i],
00080                                                           new_rows[i]));
00081         }
00082         new_rows.clear();
00083         new_cuts.clear();
00084         if (p.param(BCP_lp_par::LpVerb_ReportLocalCutPoolSize))
00085             printf("LP:   Number of cuts generated in the LP process: %i\n",
00086                    new_size);
00087         prev_size = cp.size();
00088     }
00089 
00090     // Compute the violation for everything in the local cut pool and throw out
00091     // the ones not violated
00092     if (prev_size > 0) {
00093         cp.compute_violations(lpres, cp.begin(), cp.end());
00094         double petol = 0.0;
00095         p.lp_solver->getDblParam(OsiPrimalTolerance, petol);
00096         const int cnt = cp.remove_nonviolated(petol);
00097         if (p.param(BCP_lp_par::LpVerb_ReportLocalCutPoolSize))
00098             printf("LP:   Non-violated (hence removed): %i\n", cnt);
00099         prev_size = cp.size();
00100     }
00101 
00102     if (p.param(BCP_lp_par::MessagePassingIsSerial)) {
00103         // If the message passing environment is not really parallel (i.e.,
00104         // while the CG/CP are working the LP stops and also the LP must
00105         // immediately process any cuts sent back then this is the place to
00106         // send the lp solution to the CG/CP.
00107         // send the current solution to CG, and also to CP if we are either
00108         //  - at the beginning of a chain (but not in the root in the
00109         //    first phase)
00110         //  - or this is the cut_pool_check_freq-th iteration.
00111         if (p.node->cg != -1 || p.node->cp != -1) {
00112             const BCP_message_tag msgtag = BCP_lp_pack_for_cg(p);
00113             if (p.node->cg != -1) {
00114                 ++p.no_more_cuts_cnt;
00115                 p.msg_env->send(p.node->cg, msgtag, p.msg_buf);
00116             }
00117             if (p.node->cp != -1) {
00118                 if (! (p.node->iteration_count %
00119                        p.param(BCP_lp_par::CutPoolCheckFrequency))
00120                     || varset_changed) {
00121                     ++p.no_more_cuts_cnt;
00122                     p.msg_env->send(p.node->cp, msgtag, p.msg_buf);
00123                 }
00124             }
00125         }
00126     }
00127 
00128     if (p.no_more_cuts_cnt > 0){
00129         // Receive cuts if we have sent out the lp solution somewhere.
00130         // set the timeout (all the times are in microseconds).
00131         double first_cut_time_out = varset_changed ?
00132             p.param(BCP_lp_par::FirstLP_FirstCutTimeout) :
00133             p.param(BCP_lp_par::LaterLP_FirstCutTimeout);
00134         double all_cuts_time_out = varset_changed ?
00135             p.param(BCP_lp_par::FirstLP_AllCutsTimeout) :
00136             p.param(BCP_lp_par::LaterLP_AllCutsTimeout);
00137         double tout = cp.size() == 0 ? first_cut_time_out : all_cuts_time_out;
00138         double tin = CoinCpuTime();
00139 
00140         while(true){
00141             p.msg_buf.clear();
00142             p.msg_env->receive(BCP_AnyProcess, BCP_Msg_AnyMessage,
00143                                p.msg_buf, tout);
00144             if (p.msg_buf.msgtag() == BCP_Msg_NoMessage){
00145                 // check that everyone is still alive
00146                 if (! p.msg_env->alive(p.get_parent() /*tree_manager*/))
00147                     throw BCP_fatal_error("\
00148 LP:   The TM has died -- LP exiting\n");
00149                 if (p.node->cg != -1 && ! p.msg_env->alive(p.node->cg))
00150                     throw BCP_fatal_error("\
00151 LP:   The CG has died -- LP exiting\n");
00152                 if (p.node->cp != -1 && ! p.msg_env->alive(p.node->cp))
00153                     throw BCP_fatal_error("\
00154 LP:   The CP has died -- LP exiting\n");
00155                 if (p.node->vg != -1 && ! p.msg_env->alive(p.node->vg))
00156                     throw BCP_fatal_error("\
00157 LP:   The VG has died -- LP exiting\n");
00158                 if (p.node->vp != -1 && ! p.msg_env->alive(p.node->vp))
00159                     throw BCP_fatal_error("\
00160 LP:   The VP has died -- LP exiting\n");
00161                 // now the message queue is empty and received_message has
00162                 // returned, i.e., we have waited enough
00163                 if (p.param(BCP_lp_par::LpVerb_ReportCutGenTimeout))
00164                     printf("LP:   Receive cuts timed out after %f secs\n",
00165                            (prev_size != static_cast<int>(cp.size()) ?
00166                             all_cuts_time_out : first_cut_time_out));
00167                 break;
00168             }
00169             p.process_message();
00170             // break out if no more cuts can come
00171             if (p.no_more_cuts_cnt == 0)
00172                 break;
00173 
00174             // reset the timeout
00175             tout = cp.size() == 0 ? first_cut_time_out : all_cuts_time_out;
00176             if (tout >= 0){
00177                 // with this tout we'll read out the rest of the message queue
00178                 // even if cut generation times out.
00179                 tout = std::max<double>(0.0, tout - (CoinCpuTime() - tin));
00180             }
00181         }
00182     }
00183     // reset no_more_cuts_cnt to 0
00184     p.no_more_cuts_cnt = 0;
00185 
00186     if (p.param(BCP_lp_par::LpVerb_ReportLocalCutPoolSize)) {
00187         printf("LP:   Number of cuts received from CG: %i\n",
00188                static_cast<int>(cp.size() - prev_size));
00189         printf("LP:   Total number of cuts in local pool: %i\n",
00190                static_cast<int>(cp.size()));
00191     }
00192 
00193     if (cp.size() > 0) {
00194         const int oldsize = cp.size();
00195         double petol = 0.0;
00196         p.lp_solver->getDblParam(OsiPrimalTolerance, petol);
00197         const int cnt = cp.remove_nonviolated(petol);
00198         if (cnt > 0) {
00199             printf("\
00200 LP: *WARNING*: There are nonviolated cuts in the local CP\n\
00201                at the end of cut generation.\n\
00202                Discarding %i cuts out of %i.\n", cnt, oldsize);
00203         }
00204     }
00205 
00206     p.stat.time_cut_generation += CoinCpuTime() - time0;
00207 
00208     return cp.size();
00209 }

Generated on Tue Mar 30 03:04:32 2010 by  doxygen 1.4.7