00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #ifdef COIN_USE_CPX
00013 #include "OsiCpxSolverInterface.hpp"
00014 #include "cplex.h"
00015 typedef OsiCpxSolverInterface OsiXxxSolverInterface;
00016 #endif
00017 #ifdef COIN_USE_CLP
00018 #include "OsiClpSolverInterface.hpp"
00019 typedef OsiClpSolverInterface OsiXxxSolverInterface;
00020 #endif
00021 #ifdef COIN_USE_OSL
00022 #include "OsiOslSolverInterface.hpp"
00023 typedef OsiOslSolverInterface OsiXxxSolverInterface;
00024 #endif
00025
00026 #include "BCP_lp.hpp"
00027 #include "BCP_lp_node.hpp"
00028 #include "AAP_lp.hpp"
00029 #include "AAP_var.hpp"
00030 #include "AAP_user_data.hpp"
00031
00032
00033 void AAP_lp::unpack_module_data(BCP_buffer& buf) {
00034
00035 lp_par.unpack(buf);
00036 aap = new AAP(buf);
00037 }
00038
00039
00040 void AAP_lp::pack_var_algo(const BCP_var_algo* var, BCP_buffer& buf){
00041
00042 {
00043 const AAP_var * mvar = dynamic_cast<const AAP_var*>(var);
00044 if(mvar){
00045 mvar->pack(buf);
00046 return;
00047 }
00048 }
00049 throw BCP_fatal_error("AAP_lp::pack_var_algo() : unknown cut type!\n");
00050 }
00051
00052
00053 BCP_var_algo* AAP_lp::unpack_var_algo(BCP_buffer& buf){
00054
00055 return new AAP_var(buf);
00056 }
00057
00058
00059 void AAP_lp::pack_user_data(const BCP_user_data* ud, BCP_buffer& buf){
00060
00061 {
00062 const AAP_user_data * data = dynamic_cast<const AAP_user_data*>(ud);
00063 if(data){
00064 data->pack(buf);
00065 return;
00066 }
00067 }
00068 throw BCP_fatal_error("AAP_tm::pack_user_data() : cast failed!\n");
00069 }
00070
00071
00072 BCP_user_data* AAP_lp::unpack_user_data(BCP_buffer& buf){
00073 return new AAP_user_data(buf);
00074 }
00075
00076
00077 OsiSolverInterface* AAP_lp::initialize_solver_interface(){
00078
00079 OsiXxxSolverInterface * si = new OsiXxxSolverInterface();
00080
00081 #ifdef COIN_USE_CPX
00082
00083
00084 CPXsetintparam(si->getEnvironmentPtr(),CPX_PARAM_PREIND, 0);
00085 #endif
00086
00087 return si;
00088 }
00089
00090
00091 void AAP_lp::display_lp_solution(const BCP_lp_result& lpres,
00092 const BCP_vec<BCP_var*>& vars,
00093 const BCP_vec<BCP_cut*>& cuts,
00094 const bool final_lp_solution){
00095
00096 #ifdef DBG_PRINT
00097
00098 cout << "UB: " << upper_bound() << " LB: "
00099 << getLpProblemPointer()->node->true_lower_bound << endl;
00100
00101 const int varnum = vars.size();
00102 for (int c = 0; c < varnum; ++c) {
00103 if(lpres.x()[c] > tolerance){
00104 const AAP_var* mvar = dynamic_cast<const AAP_var*>(vars[c]);
00105 if(mvar){
00106 cout << "Column " << c << " : " << lpres.x()[c] << endl;
00107 mvar->print(aap->getDimension());
00108 }
00109 }
00110 }
00111 #endif
00112
00113 }
00114
00115
00116 double AAP_lp::compute_lower_bound(const double old_lower_bound,
00117 const BCP_lp_result& lpres,
00118 const BCP_vec<BCP_var*>& vars,
00119 const BCP_vec<BCP_cut*>& cuts){
00120
00121
00122
00123
00124
00125
00126 if(lpres.termcode() & BCP_ProvenPrimalInf)
00127 return -DBL_MAX;
00128
00129 bool new_var = generate_vars(lpres.pi(), false);
00130
00131 if(new_var){
00132 return old_lower_bound;
00133
00134 }
00135 else{
00136 const int tc = lpres.termcode();
00137 if (tc & BCP_ProvenOptimal)
00138 return lpres.objval();
00139 else return old_lower_bound;
00140 }
00141 }
00142
00143
00144 void AAP_lp::generate_vars_in_lp(const BCP_lp_result& lpres,
00145 const BCP_vec<BCP_var*>& vars,
00146 const BCP_vec<BCP_cut*>& cuts,
00147 const bool before_fathom,
00148 BCP_vec<BCP_var*>& new_vars,
00149 BCP_vec<BCP_col*>& new_cols){
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163 new_vars.reserve(new_vars.size() + generated_vars.size());
00164 for (unsigned int i = 0; i < generated_vars.size(); ++i)
00165 new_vars.push_back(generated_vars[i]);
00166 generated_vars.clear();
00167 }
00168
00169
00170 void AAP_lp::restore_feasibility(const BCP_lp_result& lpres,
00171 const std::vector<double*> dual_rays,
00172 const BCP_vec<BCP_var*>& vars,
00173 const BCP_vec<BCP_cut*>& cuts,
00174 BCP_vec<BCP_var*>& vars_to_add,
00175 BCP_vec<BCP_col*>& cols_to_add){
00176
00177
00178
00179
00180 for(unsigned int r = 0; r < dual_rays.size(); r++){
00181 generate_vars(dual_rays[r], true);
00182 vars_to_add.reserve(vars_to_add.size() + generated_vars.size());
00183 for (unsigned int i = 0; i < generated_vars.size(); ++i)
00184 vars_to_add.push_back(generated_vars[i]);
00185
00186 generated_vars.clear();
00187 }
00188 }
00189
00190
00191 void AAP_lp::construct_cost(const double * pi, const bool from_restore,
00192 double * ap_costv, map<int,int> & jk_mini){
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202 #ifdef DBG_PRINT
00203 const AAP_user_data * datatmp
00204 = dynamic_cast<const AAP_user_data*>(get_user_data());
00205 cout << "ONES: ";
00206 for(unsigned int i = 0; i < datatmp->ones.size(); i++)
00207 cout << datatmp->ones[i] << " ";
00208 cout << endl;
00209 cout << "ZEROS: ";
00210 for(unsigned int i = 0; i < datatmp->zeros.size(); i++)
00211 cout << datatmp->zeros[i] << " ";
00212 cout << endl;
00213 #endif
00214
00215 const int dimension = aap->getDimension();
00216
00217 int index, index0, i, j, k, mult;
00218
00219
00220 double * rc = new double[aap->n_cols()];
00221 if(from_restore){
00222 CoinFillN(rc, aap->n_cols(), 0.0);
00223 mult = 1;
00224 }
00225 else{
00226 CoinDisjointCopyN(aap->getAssignCost(), aap->n_cols(), rc);
00227 mult = -1;
00228 }
00229
00230 int c = 0;
00231 for(i = 0; i < dimension; i++){
00232 for(j = 0; j < dimension; j++){
00233 for(k = 0; k < dimension; k++){
00234 rc[c] += (mult * pi[i]);
00235 c++;
00236 }
00237 }
00238 }
00239
00240
00241 const AAP_user_data * data
00242 = dynamic_cast<const AAP_user_data*>(get_user_data());
00243
00244
00245 for(index = 0; index < (int)data->ones.size(); index++)
00246 rc[data->ones[index]] += -bigM;
00247
00248
00249 for(index = 0; index < (int)data->zeros.size(); index++)
00250 rc[data->zeros[index]] += bigM;
00251
00252
00253
00254
00255 c = 0;
00256 for(j = 0; j < dimension; j++){
00257 for(k = 0; k < dimension; k++){
00258 index0 = index3(0,j,k,dimension);
00259 pair<int,double> mini = make_pair(index0,rc[index0]);
00260 for(i = 1; i < dimension; i++){
00261 index = index3(i,j,k,dimension);
00262 if(rc[index] < mini.second)
00263 mini = make_pair(index, rc[index]);
00264 }
00265 jk_mini.insert(make_pair(c, mini.first));
00266 ap_costv[c] = mini.second;
00267 c++;
00268 }
00269 }
00270
00271 delete [] rc;
00272 }
00273
00274
00275 bool AAP_lp::generate_vars(const double * pi, const bool from_restore){
00276
00277 const int dimension = aap->getDimension();
00278
00279 double objective_value;
00280 double * solution = new double[dimension * dimension];
00281 double * ap_costv = new double[dimension * dimension];
00282 map<int,int> jk_mini;
00283
00284 construct_cost(pi, from_restore, ap_costv, jk_mini);
00285
00286 int return_code = solve_assignment_problem(ap_costv, solution,
00287 objective_value);
00288
00289 if(return_code){
00290 delete [] solution;
00291 return false;
00292 }
00293
00294 double most_reduced_cost;
00295 const AAP_user_data * data
00296 = dynamic_cast<const AAP_user_data*>(get_user_data());
00297 const int n_ones = data->ones.size();
00298
00299 if(from_restore)
00300 most_reduced_cost = objective_value + pi[dimension] + (n_ones * bigM);
00301 else
00302 most_reduced_cost = objective_value - pi[dimension] + (n_ones * bigM);
00303
00304 if(most_reduced_cost >= -tolerance){
00305 delete [] solution;
00306 return false;
00307 }
00308
00309
00310
00311 double ap_cost = 0.0;
00312 vector<int> ap; ap.reserve(dimension);
00313 int index_aap, j, k, c = 0;
00314 for(j = 0; j < dimension; j++){
00315 for(k = 0; k < dimension; k++){
00316 if(solution[c] > tolerance){
00317 index_aap = jk_mini[c];
00318 ap.push_back(index_aap);
00319 ap_cost += aap->getAssignCost()[index_aap];
00320 }
00321 c++;
00322 }
00323 }
00324 AAP_var * new_var = new AAP_var(ap, ap_cost);
00325 generated_vars.push_back(new_var);
00326 delete [] solution;
00327 return true;
00328 }
00329
00330
00331 int AAP_lp::solve_assignment_problem(double * ap_costv,
00332 double * solution,
00333 double & objective_value){
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347 OsiXxxSolverInterface * siAP = new OsiXxxSolverInterface();
00348
00349 const int dimension = aap->getDimension();
00350 const int n_cols = dimension * dimension;
00351 const int n_rows = 2 * dimension;
00352
00353 int i, j, k, index;
00354 double * col_lb = new double[n_cols];
00355 double * col_ub = new double[n_cols];
00356 double * row_lb_ub = new double[n_rows];
00357 CoinFillN(col_lb, n_cols, 0.0);
00358 CoinFillN(col_ub, n_cols, 1.0);
00359 CoinFillN(row_lb_ub, n_rows, 1.0);
00360
00361
00362
00363 const AAP_user_data * data
00364 = dynamic_cast<const AAP_user_data*>(get_user_data());
00365
00366
00367
00368
00369
00370 for(index = 0; index < (int)data->ones.size(); index++){
00371 ijk(data->ones[index], dimension, i, j, k);
00372 col_lb[index2(j,k,dimension)] = 1.0;
00373 }
00374
00375
00376 CoinPackedMatrix * M = new CoinPackedMatrix(false,0,0);
00377 M->setDimensions(0, n_cols);
00378
00379
00380 for(j = 0; j < dimension; j++){
00381 CoinPackedVector row;
00382 for(k = 0; k < dimension; k++){
00383 index = index2(j,k,dimension);
00384 row.insert(index, 1.0);
00385 }
00386 M->appendRow(row);
00387 }
00388
00389
00390 for(k = 0; k < dimension; k++){
00391 CoinPackedVector row;
00392 for(j = 0; j < dimension; j++){
00393 index = index2(j,k,dimension);
00394 row.insert(index, 1.0);
00395 }
00396 M->appendRow(row);
00397 }
00398
00399
00400
00401
00402 siAP->assignProblem(M, col_lb, col_ub, ap_costv, row_lb_ub, row_lb_ub);
00403
00404
00405 siAP->initialSolve();
00406
00407 int return_code = 0;
00408 if(siAP->isProvenOptimal()){
00409 objective_value = siAP->getObjValue();
00410 CoinDisjointCopyN(siAP->getColSolution(), n_cols, solution);
00411 }
00412 else
00413 return_code = 1;
00414
00415 delete siAP;
00416
00417 return return_code;
00418 }
00419
00420
00421 void AAP_lp::vars_to_cols(const BCP_vec<BCP_cut*>& cuts,
00422 BCP_vec<BCP_var*>& vars,
00423 BCP_vec<BCP_col*>& cols,
00424 const BCP_lp_result& lpres,
00425 BCP_object_origin origin, bool allow_multiple){
00426
00427
00428
00429
00430
00431
00432
00433 const int varnum = vars.size();
00434 if (varnum == 0)
00435 return;
00436
00437 cols.reserve(varnum);
00438 for (int c = 0; c < varnum; ++c) {
00439 const AAP_var* mvar = dynamic_cast<const AAP_var*>(vars[c]);
00440 if(mvar){
00441
00442 CoinPackedVector col;
00443
00444
00445 vector<int> coeff(aap->getDimension(), 0);
00446 for(unsigned int p = 0; p < mvar->ap.size(); p++)
00447 coeff[ijk_i(mvar->ap[p], aap->getDimension())]++;
00448
00449 for(int i = 0; i < aap->getDimension(); i++)
00450 if(coeff[i] > 0)
00451 col.insert(i, static_cast<double>(coeff[i]));
00452 col.insert(aap->getDimension(), 1.0);
00453
00454 cols.unchecked_push_back(new BCP_col(col, mvar->cost,
00455 vars[c]->lb(), vars[c]->ub()));
00456 }
00457 }
00458 }