00001
00002
00003
00004 #include "BCP_warmstart.hpp"
00005 #include "BCP_lp_result.hpp"
00006 #include "BCP_lp_node.hpp"
00007 #include "BCP_lp.hpp"
00008 #include "BCP_lp_functions.hpp"
00009 #include "BCP_lp_user.hpp"
00010 #include "BCP_solution.hpp"
00011
00012
00013
00014 void BCP_lp_process_result(BCP_lp_prob& p, const BCP_lp_result& lpres)
00015 {
00016 p.user_has_lp_result_processing = true;
00017 p.user->process_lp_result(lpres, p.node->vars, p.node->cuts,
00018 p.node->true_lower_bound,
00019 p.new_true_lower_bound, p.sol,
00020 p.new_cuts, p.new_rows, p.new_vars, p.new_cols);
00021 }
00022
00023
00024
00025 void BCP_lp_purge_slack_pool(BCP_lp_prob& p)
00026 {
00027 BCP_vec<int> purge;
00028 p.user->purge_slack_pool(p.slack_pool, purge);
00029 if (purge.size() > 0)
00030 purge_ptr_vector_by_index(p.slack_pool, purge.begin(), purge.end());
00031 }
00032
00033
00034
00035 void BCP_lp_test_feasibility(BCP_lp_prob& p, const BCP_lp_result& lpres)
00036 {
00037 BCP_solution* sol = p.user_has_lp_result_processing ? p.sol :
00038 p.user->test_feasibility(lpres, p.node->vars, p.node->cuts);
00039 p.sol = NULL;
00040
00041 if (sol) {
00042
00043 p.user->send_feasible_solution(sol);
00044 delete sol;
00045 }
00046 }
00047
00048
00049
00050 double BCP_lp_compute_lower_bound(BCP_lp_prob& p, const BCP_lp_result& lpres)
00051 {
00052 return p.user_has_lp_result_processing ? p.new_true_lower_bound :
00053 p.user->compute_lower_bound(p.node->true_lower_bound,
00054 lpres, p.node->vars, p.node->cuts);
00055 }
00056
00057
00058
00059 void BCP_lp_clean_up_node(BCP_lp_prob& p)
00060 {
00061 p.node->clean();
00062 BCP_vec<BCP_var*>& vars = p.node->vars;
00063 purge_ptr_vector(vars, vars.entry(p.core->varnum()), vars.end());
00064 BCP_vec<BCP_cut*>& cuts = p.node->cuts;
00065 purge_ptr_vector(cuts, cuts.entry(p.core->cutnum()), cuts.end());
00066 p.parent->clean();
00067
00068
00069 purge_ptr_vector(*p.local_cut_pool);
00070 purge_ptr_vector(*p.local_var_pool);
00071 }
00072
00073
00074
00075 BCP_message_tag BCP_lp_pack_for_cg(BCP_lp_prob& p)
00076 {
00077 BCP_buffer& buf = p.msg_buf;
00078 buf.clear();
00079 buf.pack(p.node->level).pack(p.node->index).pack(p.node->iteration_count);
00080
00081 buf.set_msgtag(BCP_Msg_ForCG_User);
00082
00083 p.user->pack_primal_solution(buf, *p.lp_result,
00084 p.node->vars, p.node->cuts);
00085
00086 return buf.msgtag();
00087 }
00088
00089
00090
00091 BCP_message_tag BCP_lp_pack_for_vg(BCP_lp_prob& p)
00092 {
00093 BCP_buffer& buf = p.msg_buf;
00094 buf.clear();
00095 buf.pack(p.node->level).pack(p.node->index).pack(p.node->iteration_count);
00096
00097 buf.set_msgtag(BCP_Msg_ForVG_User);
00098
00099 p.user->pack_dual_solution(buf, *p.lp_result,
00100 p.node->vars, p.node->cuts);
00101
00102 return buf.msgtag();
00103 }
00104
00105
00106
00107 void
00108 BCP_lp_prepare_for_new_node(BCP_lp_prob& p)
00109 {
00110 int i;
00111
00112 BCP_var_set& vars = p.node->vars;
00113 BCP_cut_set& cuts = p.node->cuts;
00114
00115 BCP_vec<int> vcp;
00116 BCP_vec<double> vbd;
00117 BCP_vec<int> ccp;
00118 BCP_vec<double> cbd;
00119
00120 const int varnum = vars.size();
00121 BCP_vec<BCP_obj_status> vstat;
00122 vstat.reserve(varnum);
00123 for (i = 0; i < varnum; ++i) {
00124 vstat.unchecked_push_back(vars[i]->status());
00125 }
00126
00127 const int cutnum = cuts.size();
00128 BCP_vec<BCP_obj_status> cstat;
00129 cstat.reserve(cutnum);
00130 for (i = 0; i < cutnum; ++i) {
00131 cstat.unchecked_push_back(cuts[i]->status());
00132 }
00133
00134 p.user->initialize_new_search_tree_node(vars, cuts, vstat, cstat,
00135 vcp, vbd, ccp, cbd);
00136
00137 p.sol = NULL;
00138
00139 if (2 * vcp.size() != vbd.size()) {
00140 throw BCP_fatal_error("new node init returned uneven var vectors\n");
00141 }
00142 if (2 * ccp.size() != cbd.size()) {
00143 throw BCP_fatal_error("new node init returned uneven cut vectors\n");
00144 }
00145
00146 const double petol = p.lp_result->primalTolerance();
00147
00148 OsiSolverInterface& lp = *p.lp_solver;
00149
00150 const int var_change_num = vcp.size();
00151 if (var_change_num > 0) {
00152 BCP_vec<double>::const_iterator newbd = vbd.begin();
00153
00154
00155 for (i = 0; i < var_change_num; ++i) {
00156 const double new_lb = *newbd;
00157 ++newbd;
00158 const double new_ub = *newbd;
00159 ++newbd;
00160 const int pos = vcp[i];
00161 if (vars[pos]->lb() > new_lb+petol || vars[pos]->ub() < new_ub-petol)
00162 throw BCP_fatal_error("new node init enlarged var feas region!\n");
00163 }
00164 lp.setColSetBounds(vcp.begin(), vcp.end(), vbd.begin());
00165 vars.set_lb_ub(vcp, vbd.begin());
00166 }
00167
00168 const int cut_change_num = ccp.size();
00169 if (cut_change_num > 0) {
00170 BCP_vec<double>::const_iterator newbd = cbd.begin();
00171
00172
00173 for (i = 0; i < cut_change_num; ++i) {
00174 const double new_lb = *newbd;
00175 ++newbd;
00176 const double new_ub = *newbd;
00177 ++newbd;
00178 const int pos = ccp[i];
00179 if (cuts[pos]->lb() > new_lb+petol || cuts[pos]->ub() < new_ub-petol)
00180 throw BCP_fatal_error("new node init enlarged cut feas region!\n");
00181 }
00182 lp.setRowSetBounds(ccp.begin(), ccp.end(), cbd.begin());
00183 cuts.set_lb_ub(ccp, cbd.begin());
00184 }
00185
00186 if (lp.numberObjects() == 0) {
00187 if (!p.intAndSosObjects.empty()) {
00188 lp.addObjects(p.intAndSosObjects.size(), &p.intAndSosObjects[0]);
00189 const int numObj = lp.numberObjects();
00190 OsiObject** obj = lp.objects();
00191 for (int i = 0; i < numObj; ++i) {
00192 OsiSimpleInteger* io = dynamic_cast<OsiSimpleInteger*>(obj[i]);
00193 if (io) {
00194 io->resetBounds(&lp);
00195 } else {
00196
00197 break;
00198 }
00199 }
00200 } else {
00201 for (int i = 0; i < varnum; ++i) {
00202 if (vars[i]->var_type() != BCP_ContinuousVar) {
00203 lp.setInteger(i);
00204 }
00205 }
00206 lp.findIntegersAndSOS(false);
00207 }
00208 }
00209
00210
00211 if (p.param(BCP_lp_par::WarmstartInfo) == BCP_WarmstartRoot &&
00212 p.warmstartRoot != NULL) {
00213 lp.setWarmStart(p.warmstartRoot);
00214 }
00215 }
00216
00217
00218
00219 void
00220 BCP_lp_add_cols_to_lp(const BCP_vec<BCP_col*>& cols, OsiSolverInterface* lp)
00221 {
00222 const int colnum = cols.size();
00223 double * clb = new double[colnum];
00224 double * cub = new double[colnum];
00225 double * obj = new double[colnum];
00226 const CoinPackedVectorBase** vectors =
00227 new const CoinPackedVectorBase*[colnum];
00228 for (int i = 0; i < colnum; ++i) {
00229 const BCP_col * col = cols[i];
00230 vectors[i] = col;
00231 clb[i] = col->LowerBound();
00232 cub[i] = col->UpperBound();
00233 obj[i] = col->Objective();
00234 }
00235 lp->addCols(colnum, vectors, clb, cub, obj);
00236 delete[] vectors;
00237 delete[] obj;
00238 delete[] cub;
00239 delete[] clb;
00240 }
00241
00242
00243
00244 void
00245 BCP_lp_add_rows_to_lp(const BCP_vec<BCP_row*>& rows, OsiSolverInterface* lp)
00246 {
00247 const int rownum = rows.size();
00248 double * rlb = new double[rownum];
00249 double * rub = new double[rownum];
00250 const CoinPackedVectorBase** vectors =
00251 new const CoinPackedVectorBase*[rownum];
00252 for (int i = 0; i < rownum; ++i) {
00253 const BCP_row * row = rows[i];
00254 vectors[i] = row;
00255 rlb[i] = row->LowerBound();
00256 rub[i] = row->UpperBound();
00257 }
00258 lp->addRows(rownum, vectors, rlb, rub);
00259 delete[] vectors;
00260 delete[] rub;
00261 delete[] rlb;
00262 }