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
00026
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
00095 BOOST_CONCEPT_ASSERT((BidirectionalGraphConcept<Graph>));
00096
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
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
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
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
00179
00180
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
00213 MC<uGraph> mc;
00214 MIN_CUT<uGraph> *min_cut = new MIN_CUT<uGraph>(uG, valUG);
00215 min_cut->run();
00216 mc = min_cut->minCut;
00217 delete min_cut;
00218 std::list<vertex_descriptor> cut;
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
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
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