Main Page | Class Hierarchy | File List

AAP_lp_branch.cpp

00001 // $Id: AAP_lp_branch.cpp,v 1.2 2003/12/03 01:52:30 magh Exp $
00002 
00003 /* ------------------------------------------------------------------------
00004  Author: Matthew Galati (magh@lehigh.edu)
00005 
00006  (c) Copyright 2003 Lehigh University. All Rights Reserved.
00007 
00008  This software is licensed under the Common Public License. Please see 
00009  accompanying file for terms.    
00010 ---------------------------------------------------------------------------*/
00011 
00012 #include "AAP_lp.hpp"
00013 #include "AAP_user_data.hpp"
00014 
00015 /*--------------------------------------------------------------------------*/
00016 BCP_branching_decision AAP_lp ::
00017 select_branching_candidates(const BCP_lp_result& lpres,
00018                             const BCP_vec<BCP_var*>& vars,
00019                             const BCP_vec<BCP_cut*>& cuts,
00020                             const BCP_lp_var_pool& local_var_pool,
00021                             const BCP_lp_cut_pool& local_cut_pool,
00022                             BCP_vec<BCP_lp_branching_object*>& cans){
00023   /*
00024     Create candidate branching objects using a disjunction on:
00025     x_ijk = sum{s in F'} s_ijk lambda_s
00026 
00027     For x_ijk = 0, for all s in F' such that s_ijk  = 1, set lambda_s = 0
00028     For x_ijk = 1, for all s in F' such that s_ijk != 1, set lambda_s = 0
00029     
00030     Possible return values are:
00031     BCP_DoNotBranch_Fathomed : The node should be fathomed without branching
00032     BCP_DoNotBranch          : BCP should continue to work on this node
00033     BCP_DoBranch :           : Branching must be done. In this case the 
00034     method returns the branching object candidates 
00035   */
00036 
00037   // Do not branch if new variables have been generated
00038   if(local_var_pool.size() > 0)
00039     return BCP_DoNotBranch;
00040 
00041   //As candidates select those closest to 0.5
00042   branch_close_to_half(lpres, vars, cans);
00043 
00044   if (cans.size() == 0) {
00045     throw BCP_fatal_error("\
00046  LP : No var/cut in pool but couldn't select branching object.\n");
00047   }
00048   return BCP_DoBranch;
00049 }
00050 
00051 /*--------------------------------------------------------------------------*/
00052 void AAP_lp::set_user_data_for_children(BCP_presolved_lp_brobj* best,
00053                                         const int selected){
00054 
00055   // Store the information about which variable was branched on and
00056   // what it was set to in user_data for use in restricting the column 
00057   // generation routine in generate_vars.
00058   
00059   const AAP_user_data * data 
00060     = dynamic_cast<const AAP_user_data*>(get_user_data());
00061   
00062   AAP_user_data * data0 = new AAP_user_data(*data);
00063   AAP_user_data * data1 = new AAP_user_data(*data);
00064   
00065   data0->zeros.push_back(cand_to_variable[selected]);
00066   data1->ones.push_back(cand_to_variable[selected]);
00067   
00068   best->user_data()[0] = data0;
00069   best->user_data()[1] = data1;
00070 }
00071 
00072 /*--------------------------------------------------------------------------*/
00073 void AAP_lp:: branch_close_to_half(const BCP_lp_result& lpres,
00074                                    const BCP_vec<BCP_var*>& vars,
00075                                    BCP_vec<BCP_lp_branching_object*>& cans){
00076 
00077   //Order first by closeness to 0.5, then by cost 
00078   //increasing order on | x* - 0.5 |, decreasing on cost
00079   //x*_ijk = sum{s in F'} s_ijk lambda*_s
00080   
00081   //var_candidates: ijk -> (x*_ijk, c_ijk)
00082   vector< pair<int, pair<double, double> > > var_candidates;
00083   var_candidates.reserve(aap->n_cols());
00084 
00085   for(int i = 0; i < aap->n_cols(); i++)
00086     var_candidates.push_back(make_pair(i, make_pair(0.0, 
00087                                                     aap->getAssignCost()[i])));
00088   
00089   const int varnum = vars.size();
00090   for(int c = 0; c < varnum; ++c) {
00091     if(lpres.x()[c] <= tolerance) continue;
00092     const AAP_var* mvar = dynamic_cast<const AAP_var*>(vars[c]);
00093     if(mvar){
00094       for(unsigned int p = 0; p < mvar->ap.size(); p++)
00095         var_candidates[mvar->ap[p]].second.first += lpres.x()[c]; 
00096     }
00097   }
00098 
00099   for(int i = 0; i < aap->n_cols(); i++){
00100     var_candidates[i].second.first = 
00101       fabs(var_candidates[i].second.first - 0.5);
00102   }
00103 
00104   const int strong_branch_cands 
00105     = lp_par.entry(AAP_lp_par::AAP_StrongBranch_Can);
00106   
00107   partial_sort(var_candidates.begin(), 
00108                var_candidates.begin() + strong_branch_cands,
00109                var_candidates.end(), is_less_than());
00110 
00111   cand_to_variable.clear();
00112   append_branching_vars(lpres, vars, var_candidates, cans);
00113 
00114 }
00115 
00116 /*--------------------------------------------------------------------------*/
00117 void AAP_lp::append_branching_vars(const BCP_lp_result& lpres,
00118                                    const BCP_vec<BCP_var*>& vars,
00119                                    const vector< pair<int, pair<double, 
00120                                    double> > > & var_candidates,
00121                                    BCP_vec<BCP_lp_branching_object*>& cans){
00122 
00123   const int strong_branch_cands 
00124     = lp_par.entry(AAP_lp_par::AAP_StrongBranch_Can);
00125   const int varnum = vars.size();
00126   
00127   int count = 0;
00128   vector< pair<int, pair<double, double> > >::const_iterator vi;
00129   for(vi = var_candidates.begin(); vi != var_candidates.end(); vi++){
00130     if(count >= strong_branch_cands) break;
00131 
00132     cand_to_variable.insert(make_pair(count, (*vi).first));
00133 
00134     /*
00135       Branching candidates are constructed as a BCP_lp_branching_object 
00136       with the arguments:
00137 
00138       const int children                 - number of children for this object
00139       BCP_vec<BCP_var*>* const new_vars  - vars to add
00140       BCP_vec<BCP_cut*>* const new_cuts  - cuts to add
00141       const BCP_vec<int>* const fvp      - forced variable position
00142       const BCP_vec<int>* const fcp      - forced constraint position
00143       const BCP_vec<double>* const fvb   - forced variable bound
00144       const BCP_vec<double>* const fcb   - forced constraint bound
00145       const BCP_vec<int>* const ivp      - implied variable position
00146       const BCP_vec<int>* const icp      - implied constraint position
00147       const BCP_vec<double>* const ivb   - implied variable bound
00148       const BCP_vec<double>* const icb   - implied constraint bound   
00149     
00150       length of fvb = number of children * 2 * length of fvp
00151       
00152       For 2 children, for each position fvb holds the new bound
00153       for child 1 (x_ijk = 0) lb and ub and child 2 (x_ijk = 1) lb and ub
00154     */
00155 
00156     BCP_vec<int> fvp;    
00157     BCP_vec<double> fvb;
00158     vector<bool> contains_ijk;
00159 
00160     /*
00161       For x_ijk = 0, for all s in F' such that s_ijk  = 1, set lambda_s = 0
00162       For x_ijk = 1, for all s in F' such that s_ijk != 1, set lambda_s = 0
00163       
00164       So, essentially, *every* column will have its bounds adjusted in one
00165       of the  children. If ijk is in this s then we want to reset its bounds 
00166       in child 1, if not, then we want to reset its bounds in child 2.
00167     */
00168 
00169     for(int s = 0; s < varnum; ++s) {//loop over lambda
00170 
00171       //if this variable has already been branched on, skip it
00172       if(vars[s]->is_fixed()) continue;
00173 
00174       vector<int>::iterator pos;
00175       AAP_var* mvar = dynamic_cast<AAP_var*>(vars[s]);
00176       if(mvar){
00177         int ijk_index = (*vi).first;
00178         pos = find(mvar->ap.begin(), mvar->ap.end(), ijk_index);
00179         if(pos != mvar->ap.end()) 
00180           contains_ijk.push_back(true);
00181         else 
00182           contains_ijk.push_back(false);
00183         fvp.push_back(s);        
00184       }
00185     }
00186 
00187     //x_ijk = 0 (child 1)
00188     for(unsigned int i = 0; i < fvp.size(); i++){
00189       if(contains_ijk[i]){//set to 0
00190         fvb.push_back(vars[fvp[i]]->lb());   
00191         fvb.push_back(0.0);
00192       }
00193       else{              //do nothing
00194         fvb.push_back(vars[fvp[i]]->lb());   
00195         fvb.push_back(vars[fvp[i]]->ub());
00196       }
00197     }
00198 
00199     //x_ijk = 1 (child 2)
00200     for(unsigned int i = 0; i < fvp.size(); i++){
00201       if(!contains_ijk[i]){//set to 0
00202         fvb.push_back(vars[fvp[i]]->lb());   
00203         fvb.push_back(0.0);
00204       }
00205       else{                //do nothing
00206         fvb.push_back(vars[fvp[i]]->lb());   
00207         fvb.push_back(vars[fvp[i]]->ub());
00208       }
00209     }
00210 
00211     cans.push_back(new BCP_lp_branching_object(2, 0, 0, &fvp, 0, &fvb, 0,
00212                                                0, 0, 0, 0));
00213 
00214 #ifdef DBG_PRINT
00215     cout << "Candidate: " << count << " branch on var " << (*vi).first;
00216     ijk_print((*vi).first, aap->getDimension());
00217     cout << endl;
00218     for(unsigned int i = 0; i < fvp.size(); i++){
00219       cout << "pos : " << fvp[i];
00220       cout << " (lb, ub) : (" << fvb[2*i] << ", " << fvb[2*i+1] << ")" 
00221            << " (lb, ub) : (" << fvb[(2*fvp.size()) + (2*i)] 
00222            << ", " << fvb[(2*fvp.size()) + (2*i)+1] << ")" << endl;
00223     }
00224     for(unsigned int i = 0; i < fvb.size(); i++)
00225       cout << fvb[i] << " ";
00226     cout << endl;
00227 #endif
00228 
00229     count++;
00230   }
00231 }

Generated on Wed Dec 3 01:30:51 2003 for AAP_BP by doxygen 1.3.5