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

tour.cc

00001 #ifndef SCIL_TOUR_CC
00002 #define SCIL_TOUR_CC
00003 
00004 using namespace SCIL;
00005 using namespace std;
00006 
00007 #define VALONE 1000000
00008 
00009 template <typename Graph>
00010 class TOUR<Graph>::degree_equality : public cons_obj
00011 {
00012    private:
00013       const Graph& G;
00014       vertex_descriptor v;
00015       double deg;
00016       var_map<edge_descriptor>& VM;
00017 
00018    public:
00019 
00020    // The constructor saves the references to the graph and to the var_map<edge>
00021    // Furthermore we save the right hand side and the given node of the constraint.
00022    // We initialize the sense and the right hand side with equal and the given
00023    // right hand side.
00024    degree_equality(const Graph& G_, vertex_descriptor v_, var_map<edge_descriptor>& VM_,
00025                   double d)
00026       : cons_obj(Equal, d), G(G_), VM(VM_) { 
00027       v=v_; deg=d; 
00028    };
00029   
00030    virtual
00031    ~degree_equality()
00032    {};
00033   
00034    vertex_descriptor gnode() { return v; };
00035 
00036    // To generate the row, we can simply iterate over all edges adjacent to
00037    // the node of the degree constraint and add the appropriate variables.
00038    virtual void non_zero_entries(row& r) {
00039       edge_descriptor e;
00040       BGL_FORALL_OUTEDGES_T(v, e, G, Graph) {
00041          r+=VM[e];
00042       }
00043    };
00044 }; // END_OF_CLASS_DEGREE_EQUALITY
00045 
00046 template <typename Graph>
00047 class TOUR<Graph>::cutset_inequality : public cons_obj {
00048    private:
00049       Graph& G;
00050       var_map<edge_descriptor>& VM;
00051       map<vertex_descriptor, bool> cut;
00052       double rhs;
00053   
00054    public:
00055   
00056       cutset_inequality(Graph& Gt, var_map<edge_descriptor>& VM_, list<vertex_descriptor>& L) 
00057          : cons_obj(Greater, 2), G(Gt), VM(VM_)
00058       {
00059          vertex_descriptor v;
00060          BGL_FORALL_VERTICES_T(v, G, Graph)
00061             cut[v] = false;
00062          BOOST_FOREACH(v, L)
00063             cut[v] = true;
00064       };
00065 
00066       void non_zero_entries(row& r) { 
00067          edge_descriptor e;
00068          BGL_FORALL_EDGES_T(e, G, Graph) {
00069             if(coeff(e)==1) r+=VM[e];
00070          }
00071       }
00072 
00073    virtual
00074       ~cutset_inequality() {};
00075 
00076    double coeff(edge_descriptor e) { 
00077       if(cut[source(e, G)] != cut[target(e, G)]) return 1;
00078       return 0;
00079    };
00080 };
00081 
00082 template <typename Graph>
00083 TOUR<Graph>::TOUR(Graph& G_, var_map<edge_descriptor>& VM_)
00084    : G(G_), VM(VM_) { 
00085    edge_descriptor e;
00086    feps = 1.0e-4;
00087    BGL_FORALL_EDGES_T(e, G, Graph)
00088       if(VM[e].type() != Vartype_Binary) {
00089          cerr << "tour.cc: All variables in VM need to be Vartype_Binary" << endl;
00090          exit(1);
00091       }
00092 };
00093 
00094 template <typename Graph>
00095 void TOUR<Graph>::init(subproblem& S) {
00096    if(S.configuration("TOUR_Debug_Out")=="true")
00097       cerr << "TOUR::init\n";
00098    vertex_descriptor v;
00099    BGL_FORALL_VERTICES_T(v, G, Graph) {
00100       S.add_basic_constraint(new degree_equality(G,v,VM,2));
00101    }
00102 };
00103   
00104 
00105 template <typename Graph>
00106 typename TOUR<Graph>::status TOUR<Graph>::standard_separation(subproblem& S) {
00107    if(S.configuration("TOUR_Debug_Out")=="true")
00108       cerr << "TOUR::standard_separation\n";
00109    return separation(S, false);
00110 }
00111 
00112 template <typename Graph>
00113 typename TOUR<Graph>::status TOUR<Graph>::fast_separation(subproblem& S) {
00114    if(S.configuration("TOUR_Debug_Out")=="true")
00115       cerr << "TOUR::fast_separation\n";
00116    return separation(S, true);
00117 }
00118 
00119 
00120 
00121 template <typename Graph>
00122 typename TOUR<Graph>::status TOUR<Graph>::separation(subproblem& S, bool fast_separation) {
00123    // Preparation : Read the current LP-values of all edges
00124    //               We multiply the values with VALONE and round to the next integer
00125    int i=0;
00126    map<edge_descriptor, int> val;
00127    edge_descriptor e;
00128    BGL_FORALL_EDGES_T(e, G, Graph) {
00129       val[e]=(int) (VALONE*S.value(VM[e]));
00130    }
00131 
00132    // Heuristic : We create a copy H of G, where all edges with LP-value less than
00133    //             1 are deleted from the graph. We compute the connected components
00134    //             of this graph and check the subtour elemination constraints
00135    //             corresponding to the components for violation
00136    Graph H;
00137    vertex_descriptor u;
00138    map<vertex_descriptor, vertex_descriptor> HtoG;
00139    map<vertex_descriptor, vertex_descriptor> GtoH;
00140   
00141    // Copy all nodes of G
00142    int index = 0;
00143    map<vertex_descriptor, int> vertex_index;
00144    BGL_FORALL_VERTICES_T(u, G, Graph) { 
00145       GtoH[u]=add_vertex(H);
00146       HtoG[GtoH[u]]=u;
00147       vertex_index[GtoH[u]] = index;
00148       index++;
00149    }
00150   
00151       // Copy the edges with value close to 1
00152       BGL_FORALL_EDGES_T(e, G, Graph) if(val[e]>=VALONE-5)
00153          add_edge(GtoH[source(e, G)], GtoH[target(e, G)], H);
00154   
00155       // Compute the connected components
00156       vector<int> CC(num_vertices(H));
00157       int k = connected_components(H, &CC[0]);
00158       list<vertex_descriptor> CCL[k];
00159       BGL_FORALL_VERTICES_T(u,H, Graph) CCL[CC[vertex_index[u]]].push_back(HtoG[u]);
00160 
00161       // Create the corresponding subtour elemination constraints and check for
00162       // violation
00163       if(k>1) {
00164          for(int j=0;j<k;j++) {
00165             cons_obj* c=new cutset_inequality(G,VM,CCL[j]);
00166             if (c->violation(S) > feps) { 
00167                i++;
00168                S.add_basic_constraint(c, Dynamic); 
00169             } else delete c;
00170          }
00171       }
00172 
00173       // If the heuristic found a violated constraint, we stop the separation
00174       if(i>0) { 
00175          cout<<i<<" Heuristic\n"; 
00176          return constraint_found; 
00177       }
00178 
00179    // If only the fast heuristic should be applied, we stop the separation  
00180    if(fast_separation) 
00181       return no_constraint_found;
00182 
00183    // exact separation : We compute the minimal cut in G and check the
00184    //                    corresponding subtour elimination constraint for
00185    //                    violation
00186 
00187    MC<Graph> mc;
00188    MIN_CUT<Graph> *min_cut = new MIN_CUT<Graph>(G, val);        // calc min-cut of uG
00189    min_cut->run();
00190    mc = min_cut->minCut;
00191    delete min_cut;
00192    list<vertex_descriptor> cut; // min-cut of G
00193    BOOST_FOREACH( vertex_descriptor v, mc.nodes )
00194      cut.push_back(v);
00195 
00196 
00197    cons_obj* c=new cutset_inequality(G,VM,cut);
00198    if (c->violation(S) > feps) {
00199       i++; S.add_basic_constraint(c, Dynamic);
00200    } else delete c;
00201 
00202    // return the correct value
00203    if(i>0) {
00204       return constraint_found;
00205    }
00206 
00207    BGL_FORALL_VERTICES_T(u, H, Graph)
00208       clear_vertex(u, H);
00209 
00210    // Copy the edges with fractional value
00211    BGL_FORALL_EDGES_T(e, G, Graph) 
00212       if((val[e]>=5) && (val[e]<=VALONE-5))
00213          add_edge(GtoH[source(e, G)], GtoH[target(e, G)], H);
00214   
00215    // Compute the connected components
00216    {
00217       vector<int> CC(num_vertices(H));
00218       int k=connected_components(H,&CC[0]);
00219       list<vertex_descriptor> CCL[k];
00220       BGL_FORALL_VERTICES_T(u,H, Graph) CCL[CC[vertex_index[u]]].push_back(HtoG[u]);
00221 
00222       // Create the corresponding comb constraints and check for
00223       // violation
00224       vertex_descriptor v;
00225       map<vertex_descriptor, bool> R;
00226       if(k>1) {
00227          BGL_FORALL_VERTICES_T(v, G, Graph)
00228             R[v] = false;
00229          for(int j=0;j<k;j++) {
00230             row r;
00231             BOOST_FOREACH(v, CCL[j]) R[v]=true;
00232             double d=0;
00233             int t=0;
00234             BGL_FORALL_EDGES_T(e,G, Graph) {
00235                if((R[source(e, G)]) && (R[target(e, G)])) { 
00236                   d+=S.value(VM[e]);
00237                   r+=VM[e];
00238                }
00239                if((R[source(e, G)]!=R[target(e, G)]) && (val[e]>VALONE-10)) {
00240                   d+=S.value(VM[e]);
00241                   r+=VM[e];
00242                   t++;
00243                };
00244             };
00245             if((t % 2==1) && (d>CCL[j].size()+(t-1)/2+0.01)) {
00246                i++;
00247                S.add_basic_constraint(r<=CCL[j].size()+(t-1)/2);
00248                cout<<"comb\n";
00249             };
00250             BOOST_FOREACH(v, CCL[j]) R[v]=false;
00251          }
00252       }
00253    }
00254    if(i>0) {
00255       return constraint_found;
00256    }
00257 
00258    return no_constraint_found;
00259 }; // END_OF_SEPARATE
00260 
00261 
00262 template <typename Graph>
00263 typename TOUR<Graph>::status TOUR<Graph>::feasible(solution& S) {
00264    if(S.originating_subproblem()->configuration("TOUR_Debug_Out")=="true")
00265       cerr << "TOUR::feasible\n";
00266    // We construct a copy H of G, where we delete all edges with value different
00267    // from one. We check all degree equalities. If all degree equalities are
00268    // satisfied, we know that H is a Hamiltonian cycle if H is connected
00269 
00270    // Create H
00271    map<vertex_descriptor, vertex_descriptor> GtoH;
00272    Graph H;
00273    vertex_descriptor u;
00274    BGL_FORALL_VERTICES_T(u, G, Graph)
00275       GtoH[u]=add_vertex(H);
00276    edge_descriptor e;
00277    BGL_FORALL_EDGES_T(e,G, Graph) {
00278       if(S.value(VM[e])>0.5) add_edge(GtoH[source(e, G)], GtoH[target(e, G)], H);
00279    }
00280 
00281    // check degree equalities
00282    BGL_FORALL_VERTICES_T(u,H, Graph) if (out_degree(u, H)!=2) return infeasible_solution;
00283 
00284    // check connectedness
00285    vector<int> comp(num_vertices(H));
00286    int cc = connected_components(H,&comp[0]);
00287    if (cc == 1) return feasible_solution;
00288    return infeasible_solution;
00289 }; // END_OF_FEASIBLE
00290 
00291 template<typename Graph>
00292 void TOUR<Graph>::info() {
00293    cout<<"Method: Cutting Planes\n\n";
00294 
00295    cout<<"Configurations:\n";
00296    cout<<"TOUR_heuristic_only [true|false]\n";
00297    cout<<"TOUR_Debug_Out [true|false]\n";
00298 };
00299 
00300 #undef VALONE
00301 
00342 #endif
Generated on Mon Mar 28 22:03:51 2011 for SCIL by  doxygen 1.6.3