/home/coin/SVN-release/OS-2.4.2/examples/branchCutPrice/LP/OS_lp.cpp

Go to the documentation of this file.
00001 /* $Id: OS_lp.cpp 2907 2009-09-06 07:26:05Z kmartin $ */
00002 // Last edit: 6/23/06
00003 //
00004 // Name:     OS_lp.cpp
00005 // Author:   Francois Margot
00006 //           Tepper School of Business
00007 //           Carnegie Mellon University, Pittsburgh, PA 15213
00008 //           email: fmargot@andrew.cmu.edu
00009 // Date:     12/28/03
00010 //-----------------------------------------------------------------------------
00011 // Copyright (C) 2003, Francois Margot, International Business Machines
00012 // Corporation and others.  All Rights Reserved.
00013 
00014 #undef HEUR_SOL
00015 
00016 #include <vector>
00017 
00018 #include "OS_lp.hpp"
00019 #include "OS_cut.hpp"
00020 #include "OS_var.hpp"
00021 #include "OsiClpSolverInterface.hpp"
00022 #include "CglSimpleRounding.hpp"
00023 #include "CglKnapsackCover.hpp"
00024 
00025 #include "BCP_math.hpp"
00026 #include "BCP_lp.hpp"
00027 #include "BCP_problem_core.hpp"
00028 #include "BCP_lp_param.hpp"
00029 
00030 using namespace std;
00031 
00032 /************************************************************************/ 
00033 void
00034 OS_lp::unpack_module_data(BCP_buffer& buf)
00035 {
00036   buf.unpack( os_prob);
00037   EPS = os_prob->EPSILON; 
00044   // just a simple test
00045   
00046   std::cout << "number of variables " << os_prob->osinstance->getVariableNumber() << std::endl;
00047 
00048 
00049   
00050 }
00051 
00052 
00053 
00054 /************************************************************************/
00055 OsiSolverInterface * OS_lp::initialize_solver_interface(){
00056 
00057         OsiClpSolverInterface * clp = new OsiClpSolverInterface;
00058         clp->messageHandler()->setLogLevel(0);
00059         return clp;
00060 }
00061 
00062 /************************************************************************/
00063 void OS_lp::initialize_new_search_tree_node(const BCP_vec<BCP_var*>& vars,
00064                                        const BCP_vec<BCP_cut*>& cuts,
00065                                        const BCP_vec<BCP_obj_status>& vstatus,
00066                                        const BCP_vec<BCP_obj_status>& cstatus,
00067                                        BCP_vec<int>& var_changed_pos,
00068                                        BCP_vec<double>& var_new_bd,
00069                                        BCP_vec<int>& cut_changed_pos,
00070                                        BCP_vec<double>& cut_new_bd)
00071 
00072   // Called at the beginning of the optimization of a node. 
00073   // The node LP is not yet solved.
00074 
00075 {
00076   in_strong = 0;
00077   
00078         //BCP_lp_param.hpp for a list of parameters
00079         //lets get a parameter -- should be true by default
00080         bool relSol = BCP_lp_user::get_param(BCP_lp_par::LpVerb_RelaxedSolution) ;
00081         std::cout  << relSol << std::endl;
00082         
00083         // now reset the value
00084         if(relSol == true){
00085                 BCP_lp_user::set_param( BCP_lp_par::LpVerb_RelaxedSolution, false);
00086         }else{
00087                 BCP_lp_user::set_param( BCP_lp_par::LpVerb_RelaxedSolution, true);
00088         }
00089         
00090         // see if it got reset
00091         relSol = BCP_lp_user::get_param(BCP_lp_par::LpVerb_RelaxedSolution) ;
00092         std::cout  <<  relSol << std::endl;
00093         
00094 
00095         //set another way
00096         // number of cuts to keep in the pool
00097         //this->getLpProblemPointer()->par.set_entry(BCP_lp_par::IneffectiveBeforeDelete, 10000); 
00098         
00099         // turn off strong branching
00100         //this->getLpProblemPointer()->par.set_entry(BCP_lp_par::MaxPresolveIter, -1);
00101         
00102 
00103 #ifdef USER_DATA
00104   MY_user_data *curr_ud = dynamic_cast<MY_user_data*> (get_user_data());
00105   curr_ud->is_processed = 1;
00106 #endif
00107 
00108 }
00109 
00110 /************************************************************************/
00111 void OS_lp::modify_lp_parameters(OsiSolverInterface* lp, bool in_strong_branching){
00112 
00113   // Called each time the node LP is solved
00114         
00115         
00116         /****
00117          * 
00118          *  BCP_lp_param.hpp for param doc. 
00119          *  BCP_lp_param.cpp for default values.
00120          *  to change a param in your user class: getLpProblemPointer()->par.set_entry(LpVerb_RelaxedSolution, false);
00121          *  to change a param in bb.par:  BCP_LpVerb_RelaxedSolution 0
00122          * 
00123          */
00124         
00125         
00126 
00127   // if (in_strong_branching) {
00128   //   in_strong = 1;
00129   //   lp->setIntParam(OsiMaxNumIterationHotStart, 50);
00130   // }
00131 
00132    // write the current LP in file lpnode.lp
00133    //lp->writeLp("lpnode", "lp");
00134    //cout << "LP node written in file lpnode.lp" << endl;
00135 
00136    // to write the current LP file in file lpnode.mps use the following:
00137    // lp->writeMps("lpnode", "mps", 0.0);
00138    // cout << "LP node written in file lpnode.mps" << endl;
00139 
00140 }
00141 
00142 
00143 
00144 /************************************************************************/
00145 BCP_solution* OS_lp::generate_heuristic_solution(const BCP_lp_result& lpres,
00146                             const BCP_vec<BCP_var*>& vars,
00147                             const BCP_vec<BCP_cut*>& cuts)  {
00148         //not implemented
00149         return NULL;
00150 }
00151 
00152 
00153 /********************************************************************/
00154 BCP_branching_decision OS_lp::select_branching_candidates(const BCP_lp_result& lpres,
00155                                  const BCP_vec<BCP_var*>& vars,
00156                                    const BCP_vec<BCP_cut*>& cuts,
00157                                    const BCP_lp_var_pool& local_var_pool,
00158                                    const BCP_lp_cut_pool& local_cut_pool,
00159                                    BCP_vec<BCP_lp_branching_object*>& cands,
00160                                    bool force_branch) {
00161         
00162         
00163           // Called at the end of each iteration. Possible return values are:
00164           // BCP_DoNotBranch_Fathomed : The node should be fathomed without branching
00165           // BCP_DoNotBranch :          BCP should continue to work on this node
00166           // BCP_DoBranch :             Branching must be done. In this case the 
00167           //                            method returns the branching object candidates 
00168           //                            in one of the arguments 
00169 
00170         std::cout << "INSIDE BRANCHING DECISION: TESTING VARIABLE TYPES " << std::endl;
00171         std::cout << "SIZE OF VARS  =  " <<  vars.size()  << std::endl;
00172         std::cout << "SIZE OF LOCAL VAR POOL  =  " << local_var_pool.size()   << std::endl;
00173         std::cout << "CANDS SIZE  =  " << cands.size()   << std::endl;
00174 
00175         
00176         const double intTol = BCP_lp_user::get_param(BCP_lp_par::IntegerTolerance) ;
00177         //const double intTol = 1e-5;
00178         int num_vars = vars.size();
00179         
00180         //for(int i = 0; i < num_vars; i++){
00181         //      std::cout << "lower = " << vars[ i]->lb() << std::endl;
00182         //      std::cout << "upper = " << vars[ i]->ub() << std::endl;
00183                 
00184         //}
00185 
00186         // if no colums were generated use default branching 
00187         //if(local_var_pool.size() == 0) return BCP_lp_user::select_branching_candidates( lpres,
00188         //      vars, cuts, local_var_pool, local_cut_pool, cands, force_branch);
00189         
00190 
00191         // Don't branch if cutting planes have been generated
00192 
00193         if( local_cut_pool.size() > 0 ) {
00194     
00195                 cout << "select_branching_candidates() returns BCP_DoNotBranch"  << endl;
00196     
00197                 return(BCP_DoNotBranch);
00198   }
00199   else {
00200     // Branch on the first fractional non-continous variable
00201     int i;
00202     const double *x = lpres.x();
00203     BCP_vec<int> select_pos;
00204 
00205     for(i = 0; i < num_vars; i++) {  
00206         
00207         //std::cout << "TESTING VARIABLE  " << i  << "  FOR BRANCHING" << std::endl;
00208         //std::cout << "VALUE =   " << x[i]  << std::endl;
00209         //std::cout << "x[i] -floor( x[i])  =   " << x[i] -floor( x[i])  << std::endl;
00210         //std::cout << "x[i] -floor( x[i])  =   " << ceil( x[i]) - x[i]  << std::endl;
00211     
00212         if( vars[ i]->var_type() < 2)   {
00213                 if((x[i] -floor( x[i])  > intTol) && (ceil( x[i]) - x[i] > intTol)) {
00214                         select_pos.push_back(i);
00215 
00216                         // put in cands all variables whose index are in select_pos
00217 
00218                         append_branching_vars( lpres.x(), vars, select_pos, cands);
00219 
00220                         cout << "Branching on variable: " << i << " (" << x[i] << ")   depth: " << current_level() << endl;
00221                         break;
00222                 }
00223         }
00224     }
00225   
00226     if (cands.size() == 0 && local_var_pool.size() == 0) {
00227         throw BCP_fatal_error("select_banching_candidate() : No cut in pool but couldn't select branching variable.\n");
00228         //return BCP_DoNotBranch_Fathomed;
00229     }
00230     
00231     if (cands.size() == 0 && local_var_pool.size() > 0) {// none of the current variables are fractional so don't branch
00232         
00233         return BCP_DoNotBranch;
00234     }
00235 
00236     cout << "select_branching_candidates() returns BCP_DoBranch" << endl;
00237 
00238     return BCP_DoBranch;
00239   }
00240 
00241 }
00242 
00243 
00244 /**************************************************************************/
00245 void OS_lp::set_user_data_for_children(BCP_presolved_lp_brobj* best, 
00246                                   const int selected)
00247 
00248   // Given the branching decision (parameter "best"; "selected" is the
00249   // index of the chosen branching decision in the candidate list), 
00250   // set the user data for the children.
00251 
00252 {
00253 #ifdef USER_DATA
00254   BCP_lp_branching_object *cand = best->candidate();
00255   MY_user_data *curr_ud = dynamic_cast<MY_user_data*> (get_user_data());
00256   real_user_data *curr_rud = curr_ud->p_rud;
00257 
00258   for(int i=0; i<cand->child_num; i++) {
00259     MY_user_data *ud = new MY_user_data(curr_rud->max_card_set_zero);
00260     real_user_data *rud = ud->p_rud;
00261 
00262     rud->card_set_zero = curr_rud->card_set_zero;
00263 
00264     for(int j=0; j<curr_rud->card_set_zero; j++) {
00265       rud->set_zero[j] = curr_rud->set_zero[j];
00266     }
00267 
00268     int ind_br = (*(cand->forced_var_pos))[0];
00269 
00270     if((*(cand->forced_var_bd))[2*i + 1] < EPS) {
00271       rud->set_zero[curr_rud->card_set_zero] = ind_br;
00272       (rud->card_set_zero)++;
00273     }
00274     best->user_data()[i] = ud;
00275   }
00276 #endif /* USER_DATA */
00277 } /* set_user_data_for_children */
00278 
00279 
00280 
00281 
00282 
00283 /************************************************************************/
00284 
00285 
00286 void  OS_lp::cuts_to_rows(const BCP_vec<BCP_var*>& vars, // on what to expand
00287                     BCP_vec<BCP_cut*>& cuts,       // what to expand
00288                     BCP_vec<BCP_row*>& rows,       // the expanded rows
00289                     // things that the user can use for lifting cuts if allowed
00290                     const BCP_lp_result& lpres,
00291                     BCP_object_origin origin, bool allow_multiple) {
00292 
00293   // Required function when indexed or algorithmic cuts are used.
00294   // Describes how to get a row of the matrix from the representation of the
00295   // cut.
00296         std::cout << "Execute cuts_to_rows" << std::endl;
00297         const int cutnum = cuts.size();
00298         for (int i=0; i<cutnum; ++i) {
00299                 const OsiRowCut* bcut = dynamic_cast<const OS_cut*>(cuts[i]);
00300                 if (bcut) {
00301     
00302                         rows.push_back(new BCP_row(bcut->row(), bcut->lb(), bcut->ub()));
00303                         continue;
00304                 }
00305                 throw BCP_fatal_error("Unknown cut type in cuts_to_rows.\n");
00306         }
00307 }
00308 
00309 /************************************************************************/
00310 
00311 void OS_lp::vars_to_cols(const BCP_vec<BCP_cut*>& cuts,
00312                      BCP_vec<BCP_var*>& vars,
00313                      BCP_vec<BCP_col*>& cols,
00314                      const BCP_lp_result& lpres,
00315                      BCP_object_origin origin, bool allow_multiple)
00316 {
00317 
00318         std::cout << "EXECUTE vars_to_cols  **************" << std::endl;
00319     static const CoinPackedVector emptyVector(false);
00320     const int numvars = vars.size();
00321     int i;
00322     for (i = 0; i < numvars; ++i) {
00323         const OS_var* v = dynamic_cast<const OS_var*>(vars[i]);
00324             // Since we do not generate cuts, we can just disregard the "cuts"
00325             // argument, since the column corresponding to the var is exactly
00326             // the flow (plus the entry in the appropriate convexity
00327             // constraint)
00328             BCP_col* col = new BCP_col(v->coinPackedVec, v->weight, 0.0, 1.0);
00329             //col->insert(data.numarcs + v->commodity, 1.0);
00330             
00331             cols.push_back( col);
00332             // Excercise: if we had generated cuts, then the coefficients for
00333             // those rows would be appended to the end of each column
00334     }
00335 }
00336 
00337 
00338 /************************************************************************/
00339 void OS_lp::process_lp_result(const BCP_lp_result& lpres,
00340                       const BCP_vec<BCP_var*>& vars,
00341                       const BCP_vec<BCP_cut*>& cuts,
00342                       const double old_lower_bound,
00343                       double& true_lower_bound,
00344                       BCP_solution*& sol,
00345                       BCP_vec<BCP_cut*>& new_cuts,
00346                       BCP_vec<BCP_row*>& new_rows,
00347                       BCP_vec<BCP_var*>& new_vars,
00348                       BCP_vec<BCP_col*>& new_cols){
00349         
00350         
00351         generated_cuts = false;
00352         generated_vars = false;
00353         
00354 
00355 #if 1
00356         
00357         {
00358 
00359                 OsiClpSolverInterface* my_lp_solver;
00360                 
00361                 my_lp_solver =  dynamic_cast<OsiClpSolverInterface *>(getLpProblemPointer()->lp_solver);
00362                 
00363         
00364             //try a simple knapsack cut
00365             //CglSimpleRounding rounding;
00366                 CglKnapsackCover  knapCover;
00367         
00368             //CoinRelFltEq eq(0.0001);
00369             OsiSolverInterface::ApplyCutsReturnCode acRc;
00370             OsiCuts my_cuts;
00371         
00372                 //my_lp_solver =  (getLpProblemPointer()->lp_solver);
00373             double epsilon = .1;
00374             int i, k;
00375 
00376                 
00377                 // generate the knapsack constraints
00378             knapCover.generateCuts(*my_lp_solver, my_cuts);  
00379             const double *x = lpres.x();
00380             
00381                 CoinPackedVector pv;
00382                 int *pvIndexes = NULL;
00383                 double *pvElements = NULL;
00384                 int numElem;
00385                 double lhs = 0;
00386         OS_cut* cut;
00387             int ncuts = my_cuts.sizeRowCuts();
00388             const OsiRowCut **newRowCuts = new const OsiRowCut * [ncuts];
00389             std::cout <<  "sizeRowCuts() =    " << ncuts  << std::endl;
00390             for(i = 0; i < ncuts; i++) {
00391               newRowCuts[i] = &my_cuts.rowCut(i); 
00392               cut = new OS_cut( *newRowCuts[i]);
00393               // do not add cut if not violated  -- kipp add a test
00394               //cout   <<" rhs = " <<  newRowCuts[i]->rhs()  << endl;
00395               cout   <<" sense = " <<  newRowCuts[i]->sense()  << endl;
00396               pv = newRowCuts[i]->row();
00397               pvIndexes = pv.getIndices();
00398               pvElements =  pv.getElements();
00399               numElem = pv.getNumElements();
00400 
00401               lhs = 0;
00402               for(k = 0; k < numElem; k++){
00403                   lhs += pvElements[ k]*x[ pvIndexes[k] ];
00404                   //std::cout << pvElements[ k] << std::endl;
00405               }
00406              
00407               if( (newRowCuts[i]->sense() == 'L')  && (lhs > newRowCuts[i]->rhs() +epsilon )  ){
00408                   cout   <<" lhs - rhs = " <<  lhs -  newRowCuts[i]->rhs() << endl;
00409                   std::cout <<  "PUSHING BACK KNAPSACK COVER ROUNDING CUT"    << std::endl;
00410                   algo_cuts.push_back( cut);  
00411               }
00412             }   
00413                     
00414                 generated_cuts = (algo_cuts.size() > 0);
00415                 for(i = 0; i < ncuts; i++){
00416                         //delete newRowCuts[ i];
00417                 }
00418                 delete[] newRowCuts;
00419         }// end Cgl cut generation scope
00420         
00421 #endif
00422         
00423 #if 0
00424         
00425         {
00426                 int i;
00427                 int num_vars = vars.size();
00428                 const double *x = lpres.x();
00429                 OsiRowCut* rcut = new OsiRowCut();
00430                 // the cut column indexes
00431                 int *cutind = new int[ num_vars];
00432                 //  number of nonzeros in the cut
00433                 int cut_nz;
00434         
00435                 //we are just playing around here -- say the sum of the rhs cannot exceed 503.77
00436                 double  cutrhs = 503.77;
00437                 //cutrhs = 7000;
00438                 // the cut coefficients
00439                 double *cutcoef = new double[ num_vars];
00440                 double lhs = 0;
00441                 for(i=0; i < num_vars; i++) {
00442                         cutcoef[ i] = 1;
00443                         cutind[ i] = i;
00444                         cut_nz = num_vars;
00445                         lhs += x[ i];
00446                 }
00447                 std::cout  <<  "The LHS IS EQUAL TO ===   " << lhs << std::endl;
00448                 
00449         
00450             if(lhs > cutrhs + EPS) {
00451         
00452             // cut is violated -- add it
00453                 rcut->setLb(-BCP_DBL_MAX);
00454                 rcut->setUb( cutrhs);
00455                 rcut->setRow( cut_nz, cutind, cutcoef);
00456                 OS_cut* cut = new OS_cut( *rcut);
00457                 algo_cuts.push_back( cut);
00458                 std::cout  <<  "WE ARE ADDING A CUT!!!!!!!!   "   << std::endl;
00459             }  
00460                 delete rcut;
00461                 delete[] cutind;
00462                 delete[] cutcoef;
00463                 generated_cuts = (algo_cuts.size() > 0);
00464         }// end user cut generation scope
00465         
00466 #endif  
00467         
00468 #if 0
00469         { // variable generation scope
00470                 const double* pi = lpres.pi();
00471                 int numNonz = 4;
00472                 int varIdx = vars.size();
00473             int* ind = new int[ numNonz];
00474             double* val = new double[ numNonz];
00475                 double objVal = -13.0;
00476                 double reducedCost  = 0.0;
00477                 int i;
00478                 
00479                 ind[ 0] = 0;
00480                 ind[ 1] = 1;
00481                 ind[ 2] = 2;
00482                 ind[ 3] = 3;
00483                         
00484                 val[ 0] = 1.0;
00485                 val[ 1] = 1.0;
00486                 val[ 2] = 1.0;
00487                 val[ 3] = 1.0;
00488                 
00489                 for(i = 0 ; i < numNonz; i++){
00490                         reducedCost += -pi[ i]*val[ i];
00491                 }
00492                 reducedCost += objVal;
00493                 std::cout << "REDUCED COST =   **************   "  << reducedCost << std::endl;
00494                 
00495                 if(reducedCost < -.01  && vars.size() < 3) {
00496                         std::cout << "CALL OS_var CONSTRUCTOR   "    << std::endl;
00497                         algo_vars.push_back(new OS_var(varIdx, CoinPackedVector(numNonz, ind, val, true), objVal));     
00498                         std::cout << "DONE WITH CALL OS_var CONSTRUCTOR   "    << std::endl;
00499                 }
00500                 
00501                 delete[] val;
00502             delete[] ind;
00503         
00504                 
00505             generated_vars = (algo_vars.size() > 0);
00506         }// end variable generation scope
00507 
00508 #endif
00509     
00510     
00511     //end of generated variables
00512   
00513     
00514         // if no cuts or vars were found  call the old method   
00515     if( (generated_vars == false) && (generated_cuts == false) ){
00516         BCP_lp_user::process_lp_result(lpres, vars, cuts, 
00517                         old_lower_bound, true_lower_bound, sol, new_cuts,
00518                         new_rows, new_vars, new_cols);          
00519         return;
00520     }
00521     
00522     int i;
00523     // add the cuts
00524     
00525         if (generated_cuts) {
00526             new_cuts.append( algo_cuts);
00527             
00528             // now convert the generated cuts into rows
00529             
00530             int cutnum = algo_cuts.size();
00531           
00532             for (i = 0; i < cutnum; ++i) {
00533                 
00534                 
00535                 const OsiRowCut* bcut = dynamic_cast<const OS_cut*>(algo_cuts[i]);
00536                
00537                 if (bcut) {
00538                         new_rows.push_back(new BCP_row(bcut->row(), bcut->lb(), bcut->ub()));
00539                         //delete algo_cuts[ i];
00540                 }
00541                 else{
00542                         throw BCP_fatal_error("Unknown cut type in cuts_to_rows.\n");
00543                 }
00544             }
00545             
00546             
00547             //delete algo_cuts[0];
00548             algo_cuts.clear();  
00549         }
00550     
00551     // add the vars
00552     
00553     
00554         if (generated_vars) {
00555             new_vars.append( algo_vars);
00556             
00557             
00558             
00559             //convert the generated variables to columns
00560             
00561             static const CoinPackedVector emptyVector(false);
00562             const int numvars = algo_vars.size();
00563             for (i = 0; i < numvars; ++i) {
00564                 const OS_var* v = dynamic_cast<const OS_var*>(algo_vars[i]);
00565                     // Since we do not generate cuts, we can just disregard the "cuts"
00566                     // argument, since the column corresponding to the var is exactly
00567                     // the flow (plus the entry in the appropriate convexity
00568                     // constraint)
00569                     BCP_col* col = new BCP_col(v->coinPackedVec, v->weight, 0.0, 1.0);
00570                     //col->insert(data.numarcs + v->commodity, 1.0);
00571                     
00572                     new_cols.push_back( col);
00573                     // Excercise: if we had generated cuts, then the coefficients for
00574                     // those rows would be appended to the end of each column
00575             }
00576             
00577              
00578             algo_vars.clear();
00579         
00580                 std::cout << "GENERATED VARS IS TRUE **************   "  << std::endl;
00581                 true_lower_bound = old_lower_bound;
00582     } else {
00583         std::cout << "GENERATED VARS IS FALSE **************   "  << std::endl;
00584         true_lower_bound = lpres.objval();
00585     }
00586         std::cout << "TRUE LOWER BOUND **************   "  << true_lower_bound << std::endl;
00587 }
00588 
00589 
00590 
00591 /************************************************************************/
00592 
00593 
00594         void  OS_lp::display_lp_solution(const BCP_lp_result& lpres,
00595                                  const BCP_vec<BCP_var*>& vars,
00596                                  const BCP_vec<BCP_cut*>& cuts,
00597                                  const bool final_lp_solution){
00598                 
00599         
00600                 BCP_lp_user::display_lp_solution( lpres, vars, cuts,
00601                                                   final_lp_solution);
00602                 return;
00603         
00604                 bool relSol = false;
00605                 unsigned int i;
00606                 double ietol;
00607                 ietol = BCP_lp_user::get_param(BCP_lp_par::IntegerTolerance) ;
00608                 relSol = BCP_lp_user::get_param(BCP_lp_par::LpVerb_RelaxedSolution) ;
00609         
00610                 const double *x = lpres.x();
00611                 if( relSol == true){
00612                         for (i = 0; i < vars.size(); ++i) {
00613                                 if(x[ i] > ietol) std::cout << x[ i] << std::endl;
00614                         }
00615                 }       
00616 
00617 // kipp write OSrL here?
00618 // if final_lp_solution is true print out some osrl.
00619 }
00620 
00621 
00622 

Generated on Wed Nov 30 03:04:10 2011 by  doxygen 1.4.7