00001 #ifndef SCIL_STEINER_ARBORESCENCE_CC
00002 #define SCIL_STEINER_ARBORESCENCE_CC
00003
00004 #define LEPS 1e-4
00005
00006 using namespace SCIL;
00007 using std::cerr;
00008 using std::endl;
00009
00010 template <typename Graph>
00011 SteinerArborescence<Graph>::SteinerArborescence(Graph& G_,
00012 vertex_descriptor root_, std::list<vertex_descriptor>& terminals_,
00013 var_map<edge_descriptor>& VM_)
00014 : G(G_), root(root_), terminals(terminals_), VM(VM_) {
00015 feps = 1.0e-4;
00016 BGL_FORALL_EDGES_T(e, G, Graph)
00017 if(VM[e].type() != Vartype_Binary) {
00018 cerr << "SteinerArborescence.cc: All variables in VM";
00019 cerr << " need to be Vartype_Binary" << endl;
00020 exit(1);
00021 }
00022
00023 BOOST_CONCEPT_ASSERT((boost::BidirectionalGraphConcept<Graph>));
00024 BOOST_CONCEPT_ASSERT((boost::VertexAndEdgeListGraphConcept<Graph>));
00025 }
00026
00027 template <typename Graph>
00028 void SteinerArborescence<Graph>::init(subproblem& S) {
00029 if (S.configuration("SteinerArborescence_Debug_Out")=="true")
00030 cerr << "SteinerArborescence::init\n";
00031
00032 typename std::list<vertex_descriptor>::iterator it;
00033 it = search_n(terminals.begin(), terminals.end(), 1, root);
00034 if( it != terminals.end() ) {
00035 cerr << "SteinerArborescence: The root node must not be a terminal!" << endl;
00036 exit(1);
00037 }
00038
00039
00040
00041 BGL_FORALL_VERTICES_T(v, G, Graph) {
00042 row r;
00043 typename GraphTraits::in_edge_iterator ie_it, ie_it_end;
00044 for(tie(ie_it, ie_it_end) = in_edges(v,G); ie_it != ie_it_end; ie_it++)
00045 r += VM[*ie_it];
00046 it = search_n(terminals.begin(), terminals.end(), 1, v);
00047 if( it != terminals.end() )
00048 S.add_basic_constraint(r==1., Static);
00049 else if( v != root )
00050 S.add_basic_constraint(r<=1., Static);
00051 }
00052 row r;
00053 typename GraphTraits::out_edge_iterator oe_it, oe_it_end;
00054 for(tie(oe_it, oe_it_end) = out_edges(root, G); oe_it != oe_it_end; oe_it++)
00055 r += VM[*oe_it];
00056 S.add_basic_constraint(r>=1.,Static);
00057
00058 int i = 0;
00059 BGL_FORALL_VERTICES_T(v, G, Graph) {
00060 vertex_descriptor new_vertex_Gmf = add_vertex(Gmf);
00061 vertex_descriptor new_vertex_Fmf = add_vertex(Fmf);
00062 vertices_GtoGmf[v] = new_vertex_Gmf;
00063 vertices_GtoFmf[v] = new_vertex_Fmf;
00064 vertex_index_Gmf[new_vertex_Gmf] = i;
00065 vertex_index_Fmf[new_vertex_Fmf] = i;
00066 i++;
00067 }
00068
00069 BGL_FORALL_EDGES_T(e, G, Graph) {
00070 edge_descriptor original_edge_Gmf, original_edge_Fmf, reverse_edge_Gmf, reverse_edge_Fmf;
00071 vertex_descriptor s = vertices_GtoGmf[source(e, G)];
00072 vertex_descriptor t = vertices_GtoGmf[target(e, G)];
00073 vertex_descriptor u = vertices_GtoFmf[source(e, G)];
00074 vertex_descriptor v = vertices_GtoFmf[target(e, G)];
00075 original_edge_Gmf = add_edge(s, t, Gmf).first;
00076 original_edge_Fmf = add_edge(v, u, Fmf).first;
00077 is_original_edge_Gmf[original_edge_Gmf] = true;
00078 is_original_edge_Fmf[original_edge_Fmf] = true;
00079 if(!edge(target(e, G), source(e, G), G).second){
00080 reverse_edge_Gmf = (add_edge(t, s, Gmf)).first;
00081 is_original_edge_Gmf[reverse_edge_Gmf] = false;
00082 reverse_edge_Fmf = (add_edge(u, v, Fmf)).first;
00083 is_original_edge_Fmf[reverse_edge_Fmf] = false;
00084 }
00085 else if(edge(t, s, Gmf).second){
00086 reverse_edge_Gmf = edge(t, s, Gmf).first;
00087 rev_Gmf[original_edge_Gmf] = reverse_edge_Gmf;
00088 rev_Gmf[reverse_edge_Gmf] = original_edge_Gmf;
00089 reverse_edge_Fmf = edge(u, v, Fmf).first;
00090 rev_Fmf[original_edge_Fmf] = reverse_edge_Fmf;
00091 rev_Fmf[reverse_edge_Fmf] = original_edge_Fmf;
00092 }
00093 edges_GmfToG[original_edge_Gmf] = e;
00094 edges_FmfToG[original_edge_Fmf] = e;
00095 }
00096
00097 return;
00098 };
00099
00101
00102
00103
00104 template <typename Graph>
00105 class SteinerArborescence<Graph>::dfs_visitor : public default_dfs_visitor {
00106 public:
00107 dfs_visitor(map<vertex_descriptor, bool>* _reached) : reached(_reached) {}
00109 void discover_vertex(vertex_descriptor u, const Graph &G) const {
00110 (*reached)[u] = true;
00111 }
00113 map<vertex_descriptor, bool> *reached;
00114 };
00115
00116 template <typename Graph>
00117 typename SteinerArborescence<Graph>::status
00118 SteinerArborescence<Graph>::feasible(solution& S) {
00119 if (S.originating_subproblem()->configuration("SteinerArborescence_Debug_Out")=="true")
00120 cerr << "SteinerArborescence::feasible\n";
00121 map<vertex_descriptor, vertex_descriptor> GtoH;
00122 Graph H;
00123 BGL_FORALL_VERTICES_T(u1, G, Graph)
00124 GtoH[u1] = add_vertex(H);
00125 BGL_FORALL_EDGES_T(e, G, Graph)
00126 if(S.value(VM[e])>0.5)
00127 add_edge(GtoH[source(e, G)], GtoH[target(e, G)], H);
00128
00129
00130 map<vertex_descriptor, bool> reached;
00131 typedef map<vertex_descriptor, default_color_type> color_map_t;
00132 color_map_t color_map;
00133 BGL_FORALL_VERTICES_T(v, H, Graph) {
00134 reached[v] = false;
00135 color_map[v] = white_color;
00136 }
00137 associative_property_map<color_map_t> pm_color(color_map);
00138 dfs_visitor vis(&reached);
00139
00140 depth_first_visit(H, GtoH[root], vis, pm_color);
00141
00142 std::list<vertex_descriptor> reached_vertices;
00143 BGL_FORALL_VERTICES_T(v, H, Graph)
00144 if(reached[v]) reached_vertices.push_back(v);
00145
00146
00147 vertex_descriptor u1;
00148 BOOST_FOREACH(u1, terminals) {
00149
00150
00151 if ( !reached[GtoH[u1]] ) return infeasible_solution;
00152 }
00153 return feasible_solution;
00154 }
00155
00156 template <typename Graph>
00157 int SteinerArborescence<Graph>::separate_flipped(subproblem& S) {
00158 if (S.configuration("SteinerArborescence_Debug_Out")=="true")
00159 cerr << "SteinerArborescence::seperate_flipped\n";
00160 int numfound = 0;
00161 capacity_map_t c;
00162 capacity_map_t d;
00163 capacity_map_t residual_capacity;
00164 BGL_FORALL_EDGES_T(e, Fmf, Graph)
00165 residual_capacity[e] = 0;
00166 BGL_FORALL_EDGES_T(e, Fmf, Graph) {
00167 if(is_original_edge_Fmf[e]) {
00168
00169 c[e] = (int) (1000. * S.value(VM[edges_FmfToG[e]]));
00170 if( c[e] == 0 )
00171 c[e] = 1;
00172 } else {
00173
00174 c[e] = 0;
00175 }
00176 }
00177
00178 color_map_t color_map;
00179 BGL_FORALL_VERTICES_T(v, Fmf, Graph)
00180 color_map[v] = white_color;
00181
00182 predecessor_map_t pred_map;
00183
00184 vdistance_map_t vdist_map;
00185
00186
00187
00188 associative_property_map<capacity_map_t> pm_capacity(d);
00189 associative_property_map<capacity_map_t> pm_res_cap(residual_capacity);
00190 associative_property_map<rev_edge_map_t> pm_rev(rev_Fmf);
00191 associative_property_map<vertex_index_map_t> pm_vi(vertex_index_Fmf);
00192 associative_property_map<color_map_t> pm_color(color_map);
00193 associative_property_map<predecessor_map_t> pm_pred(pred_map);
00194 associative_property_map<vdistance_map_t> pm_vdist(vdist_map);
00195
00196 vertex_descriptor v;
00197 BOOST_FOREACH(v, terminals) {
00198 std::list<vertex_descriptor> cut;
00199 BGL_FORALL_EDGES_T(e, Fmf, Graph)
00200 d[e] = c[e];
00201 map<edge_descriptor, bool> fixed;
00202 BGL_FORALL_EDGES_T(e, Fmf, Graph)
00203 fixed[e] = false;
00204 int cv = 0;
00205 int go = 0;
00206 bool added = true;
00207 while( added ) {
00208 BGL_FORALL_VERTICES_T(u, Fmf, Graph)
00209 color_map[u] = white_color;
00210 cv = boykov_kolmogorov_max_flow(Fmf, pm_capacity, pm_res_cap, pm_rev,
00211 pm_pred, pm_color, pm_vdist, pm_vi, vertices_GtoFmf[v],
00212 vertices_GtoFmf[root]);
00213 go++;
00214 added = false;
00215 cut.clear();
00216 typename GraphTraits::vertex_iterator v_it, v_it_end;
00217
00218
00219
00220 for(tie(v_it,v_it_end) = vertices(Fmf); v_it != v_it_end; v_it++)
00221 if (color_map[*v_it] == black_color) cut.push_back(*v_it);
00222 if (S.configuration("SteinerArborescence_Debug_Out")=="true")
00223 cerr << "cv: " << cv << endl;
00224 if( cv < 1000 && cut.size() >= 1 && cut.size() < num_vertices(Fmf) - 1 ) {
00225 row r;
00226 vertex_descriptor w;
00227 BOOST_FOREACH(w, cut) {
00228 BGL_FORALL_OUTEDGES_T(w, e, Fmf, Graph) {
00229 if (search_n(cut.begin(),cut.end(),1,target(e,Fmf)) == cut.end()
00230 && is_original_edge_Fmf[e] ) {
00231 r += VM[edges_FmfToG[e]];
00232 d[e] = 1000;
00233 fixed[e] = true;
00234 }
00235 }
00236 }
00237 cons_obj* con = (r>=1.);
00238 if( con->violation(S) > feps ) {
00239 S.add_basic_constraint(r>=1., Dynamic);
00240 if (S.configuration("SteinerArborescence_Debug_Out")=="true")
00241 if( go > 1 )
00242 cerr << go << " added: " << r << " >= 1" << endl;
00243 numfound++;
00244 added = true;
00245 }
00246 delete con;
00247 }
00248 }
00249 }
00250
00251
00252
00253 }
00254
00255 template <typename Graph>
00256 typename SteinerArborescence<Graph>::status
00257 SteinerArborescence<Graph>::standard_separation(subproblem& S){
00258 return separation(S, false);
00259 }
00260
00261 template <typename Graph>
00262 typename SteinerArborescence<Graph>::status
00263 SteinerArborescence<Graph>::separation(subproblem& S,
00264 bool separate_fast) {
00265 if (S.configuration("SteinerArborescence_Debug_Out")=="true")
00266 cerr << "SteinerArborescence::standard_separation\n";
00267
00268 int numfound = 0;
00269 capacity_map_t c;
00270 capacity_map_t d;
00271 capacity_map_t residual_capacity;
00272 BGL_FORALL_EDGES_T(e, Gmf, Graph)
00273 residual_capacity[e] = 0;
00274 BGL_FORALL_EDGES_T(e, Gmf, Graph) {
00275 if(is_original_edge_Gmf[e]) {
00276
00277 c[e] = (int) (1000. * S.value(VM[edges_GmfToG[e]]));
00278 if( c[e] == 0 )
00279 c[e] = 1;
00280 } else {
00281
00282 c[e] = 0;
00283 }
00284 }
00285
00286 color_map_t color_map;
00287 BGL_FORALL_VERTICES_T(v, Gmf, Graph)
00288 color_map[v] = white_color;
00289
00290 predecessor_map_t pred_map;
00291
00292 vdistance_map_t vdist_map;
00293
00294
00295
00296 associative_property_map<capacity_map_t> pm_capacity(d);
00297 associative_property_map<capacity_map_t> pm_res_cap(residual_capacity);
00298 associative_property_map<rev_edge_map_t> pm_rev(rev_Gmf);
00299 associative_property_map<vertex_index_map_t> pm_vi(vertex_index_Gmf);
00300 associative_property_map<color_map_t> pm_color(color_map);
00301 associative_property_map<predecessor_map_t> pm_pred(pred_map);
00302 associative_property_map<vdistance_map_t> pm_vdist(vdist_map);
00303
00304 vertex_descriptor v;
00305 BOOST_FOREACH(v, terminals) {
00306 std::list<vertex_descriptor> cut;
00307 BGL_FORALL_EDGES_T(e, Gmf, Graph)
00308 d[e] = c[e];
00309 map<edge_descriptor, bool> fixed;
00310 BGL_FORALL_EDGES_T(e, Gmf, Graph)
00311 fixed[e] = false;
00312 int cv = 0;
00313 int go = 0;
00314 bool added = true;
00315 while( added ) {
00316 BGL_FORALL_VERTICES_T(u, Gmf, Graph)
00317 color_map[u] = white_color;
00318 cv = boykov_kolmogorov_max_flow(Gmf, pm_capacity, pm_res_cap, pm_rev,
00319 pm_pred, pm_color, pm_vdist, pm_vi, vertices_GtoGmf[root],
00320 vertices_GtoGmf[v]);
00321 go++;
00322 added = false;
00323 cut.clear();
00324 typename GraphTraits::vertex_iterator v_it, v_it_end;
00325
00326
00327
00328 for(tie(v_it,v_it_end) = vertices(Gmf); v_it != v_it_end; v_it++)
00329 if (color_map[*v_it] == black_color) cut.push_back(*v_it);
00330 if (S.configuration("SteinerArborescence_Debug_Out")=="true")
00331 cerr << "cv: " << cv << endl;
00332 if( cv < 1000 && cut.size() >= 1 && cut.size() < num_vertices(Gmf) - 1 ) {
00333 row r;
00334 vertex_descriptor w;
00335 BOOST_FOREACH(w, cut) {
00336 BGL_FORALL_OUTEDGES_T(w, e, Gmf, Graph) {
00337 if (search_n(cut.begin(),cut.end(),1,target(e,Gmf)) == cut.end()
00338 && is_original_edge_Gmf[e] ) {
00339 r += VM[edges_GmfToG[e]];
00340 d[e] = 1000;
00341 fixed[e] = true;
00342 }
00343 }
00344 }
00345 cons_obj* con = (r>=1.);
00346 if( con->violation(S) > feps ) {
00347 S.add_basic_constraint(r>=1., Dynamic);
00348 if (S.configuration("SteinerArborescence_Debug_Out")=="true")
00349 if( go > 1 )
00350 cerr << go << " added: " << r << " >= 1" << endl;
00351 numfound++;
00352 added = true;
00353 }
00354 delete con;
00355 }
00356 }
00357 }
00358
00359 if (separate_fast) {
00360 if ( numfound )
00361 return constraint_found;
00362 return no_constraint_found;
00363 }
00364 numfound += separate_flipped(S);
00365 if (S.configuration("SteinerArborescence_Debug_Out")=="true")
00366 cerr << "numfound: " << numfound << endl;
00367
00368
00369 std::map<vertex_descriptor, double> nodecut;
00370 std::map<vertex_descriptor, row> noderow;
00371 BGL_FORALL_VERTICES_T(v, Gmf, Graph) {
00372 if( search_n(terminals.begin(), terminals.end(), 1, vertices_GtoGmf[v])
00373 != terminals.end() || vertices_GtoGmf[root] == v )
00374 continue;
00375 double t = 0;
00376 row r;
00377 BGL_FORALL_INEDGES_T(v, e, Gmf, Graph){
00378 if(is_original_edge_Gmf[e]){
00379 t += c[e];
00380 r += VM[edges_GmfToG[e]];
00381 }
00382 }
00383 nodecut[v] = t;
00384 noderow[v] = r;
00385
00386 }
00387
00388
00389 BGL_FORALL_VERTICES_T(v, Gmf, Graph) {
00390 if(search_n(terminals.begin(), terminals.end(), 1, v) != terminals.end()
00391 || v == vertices_GtoGmf[root] )
00392 continue;
00393 std::list<vertex_descriptor> cut, cut2;
00394 bool stop = false;
00395
00396
00397 associative_property_map<capacity_map_t> pm_cap(c);
00398 BGL_FORALL_EDGES_T(e, Gmf, Graph)
00399 residual_capacity[e] = 0;
00400 BGL_FORALL_VERTICES_T(v, Gmf, Graph)
00401 color_map[v] = white_color;
00402
00403 int cv = 0;
00404 cv = boykov_kolmogorov_max_flow(Gmf, pm_cap, pm_res_cap, pm_rev, pm_pred,
00405 pm_color, pm_vdist, pm_vi, vertices_GtoGmf[root], v);
00406
00407 cut.clear();
00408 typename GraphTraits::vertex_iterator v_it, v_it_end;
00409
00410
00411
00412 for(tie(v_it,v_it_end) = vertices(Gmf); v_it != v_it_end; v_it++){
00413 if (color_map[*v_it] == black_color)
00414 cut.push_back(*v_it);
00415 else
00416 cut2.push_back(*v_it);
00417 }
00418
00419
00420 if( cut.size() >= 1 && cut.size() < num_vertices(Gmf) - 1 ) {
00421 vertex_descriptor w;
00422 BOOST_FOREACH(w, terminals) {
00423 if( search_n(cut.begin(),cut.end(),1,vertices_GtoGmf[w])==cut.end() ) {
00424 stop = true;
00425
00426 break;
00427 }
00428 }
00429 if( stop )
00430 break;
00431
00432 row r;
00433 BOOST_FOREACH(w, cut) {
00434 BGL_FORALL_OUTEDGES_T(w, e, Gmf, Graph) {
00435 if(search_n(cut.begin(),cut.end(),1,target(e, Gmf)) == cut.end()
00436 && is_original_edge_Gmf[e])
00437 r += VM[edges_GmfToG[e]];
00438 }
00439 }
00440 BOOST_FOREACH(w, cut2) {
00441 if( cv - nodecut[w] < 20. ) {
00442 cons_obj* con = (r-noderow[w]>=0.);
00443 if( con->violation(S) > feps ) {
00444 S.add_basic_constraint(r-noderow[w]>=0., Dynamic);
00445
00446 numfound++;
00447 }
00448 delete con;
00449 }
00450 }
00451 }
00452 }
00453
00454 if( numfound )
00455 return constraint_found;
00456
00457 return no_constraint_found;
00458 }
00459
00460 template <typename Graph>
00461 typename SteinerArborescence<Graph>::status
00462 SteinerArborescence<Graph>::fast_separation(subproblem& S) {
00463 return separation(S, true);
00464 }
00465
00466 template<typename Graph>
00467 void SteinerArborescence<Graph>::info() {
00468 cout<<"Configurations:\n";
00469 cout<<"SteinerArborescence_Debug_Out [true|false]\n";
00470 };
00471 #endif