00001
00002
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
00024
00025
00026
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
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
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
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
00091
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
00104
00105
00106
00107
00108
00109
00110
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
00130
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
00146 if (! p.msg_env->alive(p.get_parent() ))
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
00162
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
00171 if (p.no_more_cuts_cnt == 0)
00172 break;
00173
00174
00175 tout = cp.size() == 0 ? first_cut_time_out : all_cuts_time_out;
00176 if (tout >= 0){
00177
00178
00179 tout = std::max<double>(0.0, tout - (CoinCpuTime() - tin));
00180 }
00181 }
00182 }
00183
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 }