Main Page   Class Hierarchy   Compound List   File List   Contact   Download   Symbolic Constraints   Examples  

atour.cc

00001 #ifndef ATOUR_CONSTRAINT_CC
00002 #define ATOUR_CONSTRAINT_CC
00003 
00004 
00005 using namespace SCIL;
00006 using namespace std;
00007 using namespace boost;
00008 
00009 #define VALONE 1000000
00010 
00011 template <typename Graph>
00012 class ATOUR<Graph>::dir_degree_equality : public cons_obj {
00013 private:
00014   const Graph& G;
00015   vertex_descriptor v;
00016   double deg;
00017   var_map<edge_descriptor>& VM;
00018   bool in;
00019   
00020 public:
00021 
00022    dir_degree_equality(subproblem& S_,
00023                   const Graph& G_, vertex_descriptor v_, var_map<edge_descriptor>& VM_,
00024                    double d, bool i_)
00025        /*{create The constraint $\sum_{e \in \delta(v)} x_e = d$, where $\delta(v)$ are the 
00026           edges which are adjacent to v and for which a variable was defined.}*/
00027      : cons_obj(Equal, d), G(G_), VM(VM_) { 
00028      v=v_; deg=d, in=i_; 
00029    };
00030 
00031    virtual
00032       ~dir_degree_equality()
00033       {};
00034   
00035    vertex_descriptor gnode() { return v; };
00036   
00037    virtual void non_zero_entries(row& r) {
00038       if(in) {
00039          typename GraphTraits::out_edge_iterator it, it_end;
00040          for (tie(it, it_end) = out_edges(v,G); it != it_end; it++) {
00041                   r+=VM[*it];
00042          }
00043       } else {
00044          typename GraphTraits::in_edge_iterator it, it_end;
00045          for (tie(it, it_end) = in_edges(v,G); it != it_end; it++) {
00046             r+=VM[*it];
00047          }
00048       };
00049    };
00050 };
00051 
00052 template <typename Graph>
00053 class ATOUR<Graph>::dir_cutset_inequality : public cons_obj {
00054 private:
00055    Graph& G;
00056    var_map<edge_descriptor>& VM;
00057    map<vertex_descriptor, bool> cut;
00058    double rhs;
00059   
00060 public:
00061   
00062    dir_cutset_inequality(Graph& Gt, 
00063       var_map<edge_descriptor>& VM_, 
00064       list<vertex_descriptor>& L) 
00065       : cons_obj(Less, L.size()-1), G(Gt), VM(VM_) {
00066       typename GraphTraits::vertex_iterator v_it, v_it_end;
00067       for(tie(v_it, v_it_end) = vertices(G); v_it != v_it_end; v_it++)
00068          cut[*v_it] = false;
00069       typename list<vertex_descriptor>::iterator it;
00070       for (it=L.begin(); it != L.end(); it++)
00071          cut[*it]=true;
00072    }
00073 
00074    void non_zero_entries(row& r) { 
00075       typename GraphTraits::edge_iterator it, it_end;
00076       for(tie(it, it_end) = edges(G); it != it_end; it++) {
00077          if(coeff(*it)==1) r+=VM[*it];
00078       }
00079    }
00080 
00081    virtual
00082    ~dir_cutset_inequality() {};
00083 
00084    double coeff(edge_descriptor e) { 
00085       if((cut[source(e, G)]) && (cut[target(e, G)])) return 1;
00086       return(0);
00087    };
00088 };
00089 
00090 template <typename Graph>
00091 ATOUR<Graph>::ATOUR(Graph& G_, var_map<edge_descriptor>& VM_)
00092    : G(G_), VM(VM_) {
00093    feps = 1.0e-4;
00094    //Graph has to provide in_edges() and out_edges()
00095    BOOST_CONCEPT_ASSERT((BidirectionalGraphConcept<Graph>));
00096    //Graph has to provide vertices() and edges()
00097    BOOST_CONCEPT_ASSERT((VertexAndEdgeListGraphConcept<Graph>));
00098    typename GraphTraits::edge_iterator it, it_end;
00099    for (tie(it, it_end) = edges(G); it != it_end; it++)
00100       if(VM[*it].type() != Vartype_Binary) {
00101          cerr << "atour.cc: All variables in VM need to be Vartype_Binary" << endl;
00102          exit(1);
00103       }
00104 };
00105 
00106 template <typename Graph>
00107 void ATOUR<Graph>::init(subproblem& S) {
00108    if (S.configuration("ATOUR_Debug_Out")=="true")
00109       cerr << "ATOUR::init\n";
00110    typename GraphTraits::vertex_iterator it, it_end;
00111    for (tie(it, it_end) = vertices(G); it != it_end; it++) {
00112       S.add_basic_constraint(new dir_degree_equality(S,G,*it,VM,1, true));
00113       S.add_basic_constraint(new dir_degree_equality(S,G,*it,VM,1, false));
00114    }
00115 }
00116 
00117 
00118 template <typename Graph>
00119 typename ATOUR<Graph>::status ATOUR<Graph>::heuristic_separation(subproblem& S) {
00120    typedef adjacency_list< vecS, vecS, undirectedS > uGraph;
00121    typedef graph_traits<uGraph>::edge_descriptor uEdge;
00122    typedef graph_traits<uGraph>::vertex_descriptor uVertex_descriptor;
00123    
00124    // Preparation
00125    int i=0;
00126    map<edge_descriptor, int> val;
00127    typename GraphTraits::edge_iterator e_it, e_it_end;
00128    for(tie(e_it, e_it_end) = edges(G); e_it != e_it_end; e_it++){
00129       val[*e_it] = max ((int) (VALONE*S.value(VM[*e_it])), 0);
00130    }
00131   
00132    // Heuristic
00133    uGraph H;
00134    map<uVertex_descriptor, vertex_descriptor> HtoG;
00135    map<vertex_descriptor, uVertex_descriptor> GtoH;
00136   
00137    typename GraphTraits::vertex_iterator v_it, v_it_end;
00138    for(tie(v_it, v_it_end) = vertices(G); v_it != v_it_end; v_it++) {
00139       GtoH[*v_it] = add_vertex(H);  
00140       HtoG[GtoH[*v_it]] = *v_it;
00141    }
00142 
00143    for(tie(e_it, e_it_end) = edges(G); e_it != e_it_end; e_it++) {
00144       if(val[*e_it]>=VALONE-5) add_edge( GtoH[source(*e_it, G)], GtoH[target(*e_it, G)], H);
00145    }
00146 
00147    typedef map<uVertex_descriptor, int> CC_t;
00148    CC_t CC;
00149    associative_property_map<CC_t> pm_CC(CC);
00150 
00151    int k = connected_components(H, pm_CC);
00152 
00153    typename graph_traits<uGraph>::vertex_iterator uv_it, uv_it_end;
00154    if(k>1) {
00155       for(int j=0;j<k;j++) {
00156          list<vertex_descriptor> CCL_one_element;
00157          for(tie(uv_it, uv_it_end) = vertices(H); uv_it != uv_it_end; uv_it++)
00158             if( pm_CC[*uv_it] == j )
00159                CCL_one_element.push_back(HtoG[*uv_it]);
00160          cons_obj* c=new dir_cutset_inequality(G,VM,CCL_one_element);
00161          if (c->violation(S) > feps) { 
00162                   i++;
00163                   S.add_basic_constraint(new dir_cutset_inequality(G,VM,CCL_one_element), Dynamic); 
00164          }
00165          delete c;
00166       }
00167    }
00168 
00169    // Heuristic succeeded?
00170    if(i>0) { 
00171       return constraint_found; 
00172    }
00173    return no_constraint_found;
00174 }
00175 
00176 template <typename Graph>
00177 typename ATOUR<Graph>::status ATOUR<Graph>::exact_separation(subproblem& S){
00178    // Create undirected copy of Graph G 
00179    // This is needed to perform min-cut
00180    // I think this workaround should soon be removed 
00181 
00182    typedef adjacency_list< vecS, vecS, undirectedS > uGraph;
00183    typedef graph_traits<uGraph>::edge_descriptor uEdge;
00184    typedef graph_traits<uGraph>::vertex_descriptor uVertex_descriptor;
00185 
00186    uGraph uG(num_vertices(G));
00187 
00188    std::map<vertex_descriptor, unsigned int> GtoUG;
00189    vector <vertex_descriptor> UGtoG(num_vertices(G));  
00190    int n=0;
00191    vertex_descriptor v;
00192    map<uVertex_descriptor, int> vertex_index;
00193    BGL_FORALL_VERTICES_T( v,G,Graph ){
00194       UGtoG[n] = v;
00195       GtoUG[v] = n;
00196       vertex_index[GtoUG[v]] = n;
00197       n++;
00198    }
00199 
00200    edge_descriptor e;
00201    uEdge ue;
00202    map<uEdge, int> valUG;
00203    BGL_FORALL_EDGES_T( e,G,Graph ){
00204       if(!edge(GtoUG[source(e,G)], GtoUG[target(e,G)],uG).second){
00205       ue = add_edge( GtoUG[source(e,G)], GtoUG[target(e,G)], uG ).first;      
00206       valUG[ue] = max ((int) (VALONE*S.value(VM[e])), 0);
00207       }else
00208          valUG[edge(GtoUG[source(e,G)], GtoUG[target(e,G)],uG).first] += max ((int) (VALONE*S.value(VM[e])), 0);
00209    }
00210  
00211  
00212    // exact separation   
00213    MC<uGraph> mc;
00214    MIN_CUT<uGraph> *min_cut = new MIN_CUT<uGraph>(uG, valUG);   // calc min-cut of uG
00215    min_cut->run();
00216    mc = min_cut->minCut;
00217    delete min_cut;
00218    std::list<vertex_descriptor> cut; // min-cut of G
00219    BOOST_FOREACH( long unsigned int ui, mc.nodes )
00220      cut.push_back(UGtoG[ui]);
00221 
00222    int i = 0;
00223    cons_obj* c = new dir_cutset_inequality(G, VM, cut);
00224    if (c->violation(S) > feps) {
00225        S.add_basic_constraint(new dir_cutset_inequality(G, VM, cut), Dynamic);
00226        i++;
00227    }
00228    delete c;
00229    if(i>0) {
00230       //cout<<"Exact CUT found inequality\n";
00231       return constraint_found;
00232    }
00233    else
00234       return no_constraint_found;
00235 }
00236 
00237 template <typename Graph>
00238 typename ATOUR<Graph>::status ATOUR<Graph>::fast_separation(subproblem& S) {
00239    if (S.configuration("ATOUR_Debug_Out")=="true")
00240       cerr << "ATOUR::fast_separation\n";
00241 
00242    return heuristic_separation(S);
00243 }
00244 
00245 template <typename Graph>
00246 typename ATOUR<Graph>::status ATOUR<Graph>::standard_separation(subproblem& S) {   
00247    
00248    if (S.configuration("ATOUR_Debug_Out")=="true")
00249       cerr << "ATOUR::standard_separation\n";
00250 
00251    if(heuristic_separation(S) == no_constraint_found)
00252       return exact_separation(S);
00253    else
00254       return constraint_found;
00255 
00256 }
00257 
00258 template <typename Graph>
00259 typename ATOUR<Graph>::status ATOUR<Graph>::feasible(solution& S) {
00260    if (S.originating_subproblem()->configuration("ATOUR_Debug_Out")=="true")
00261       cerr << "ATOUR::feasible\n";
00262    map<vertex_descriptor, vertex_descriptor> GtoH;
00263    Graph H;
00264    typename GraphTraits::vertex_iterator it, it_end;
00265    for (tie(it, it_end) = vertices(G); it != it_end; it++)
00266       GtoH[*it]=add_vertex(H);
00267    typename GraphTraits::edge_iterator e_it, e_it_end;
00268    for (tie(e_it, e_it_end) = edges(G); e_it != e_it_end; e_it++)
00269       if(S.value(VM[*e_it])>0.5)
00270          add_edge(GtoH[source(*e_it, G)], GtoH[target(*e_it,G)], H);
00271    vector<int> component(num_vertices(H));
00272    //Test if graph H is connected. If H has just 1 connected component, it is.
00273    if (connected_components(H, &component[0]) == 1) 
00274       return feasible_solution;
00275    else return infeasible_solution;
00276 }
00277 
00278 template <typename Graph>
00279 void ATOUR<Graph>::info() {
00280    cout<<"Configurations:\n";
00281    cout<<"ATOUR_Debug_Out [true|false]\n";
00282 };
00283 
00284 #undef VALONE
00285 
00286 #endif
Generated on Mon Mar 28 22:03:47 2011 for SCIL by  doxygen 1.6.3