00001 #include "dinic.hpp"
00002 #include "PG_algorithm.hpp"
00003
00004 Graph * g;
00005 Graph::VertexSetHandle grayset1, grayset2, set_s_vertex, set_t_vertex;
00006
00007 VertexPropertyMap< vertex_level_tag, Graph > level;
00008 VertexPropertyMap< vertex_potential_tag, Graph > potential;
00009 EdgeMap< edgelist1_tag, Graph > network_edges;
00010 EdgeMap< edgelist_residual_tag, Graph > residual_edges;
00011 EdgePropertyMap< edge_flow_tag, EdgeMap< edgelist1_tag, Graph > >
00012 network_flow;
00013 EdgePropertyMap< edge_flow_tag, EdgeMap< edgelist_residual_tag, Graph > >
00014 residual_flow;
00015 EdgePropertyMap< edge_capacity_tag, EdgeMap< edgelist1_tag, Graph > >
00016 network_capacity;
00017 EdgePropertyMap< edge_capacity_tag, EdgeMap< edgelist_residual_tag, Graph > >
00018 residual_capacity;
00019 EdgePropertyMap< edge_flag1_tag, EdgeMap< edgelist_residual_tag, Graph > >
00020 edgeflag;
00021 EdgePropertyMap< edge_reference_tag, EdgeMap< edgelist_residual_tag, Graph > >
00022 edgereference;
00023
00024 size_t iteration = 0;
00025
00026 #define LOCALTIME
00027 double crg_time = 0, clg_time = 0, pf_time = 0;
00028
00029 bool is_edge_marked( ResidualEdge e ) {
00030 return get( edgeflag, e );
00031 }
00032
00033 struct create_residual_edge
00034 {
00035 AllToAllBuffer buf;
00036
00037 void operator()( NetworkEdge e ) {
00038 unsigned int flow = get( network_flow, e );
00039 unsigned int cap = get( network_capacity, e );
00040 Vertex v1 = source(e, *g);
00041 Vertex v2 = target(e, *g);
00042
00043 if( flow < cap )
00044 {
00045 residual_edges_property_type prop( cap - flow,
00046 residual_edges_property_type::next_type( true,
00047 residual_edges_property_type::next_type::next_type( get_edge_id(e),
00048 residual_edges_property_type::next_type::next_type::next_type( 0 ))));
00049
00050 add_edge( residual_edges, v1, v2, prop, *g, buf );
00051 }
00052 if( flow > 0 )
00053 {
00054 residual_edges_property_type prop( flow,
00055 residual_edges_property_type::next_type( true,
00056 residual_edges_property_type::next_type::next_type( get_edge_id(e),
00057 residual_edges_property_type::next_type::next_type::next_type( 0 ))));
00058
00059 add_edge( residual_edges, v2, v1, prop, *g, buf );
00060 }
00061 }
00062 };
00063
00064 struct flow_tag {};
00065 typedef property< flow_tag, unsigned int > first_pull_type;
00066
00067 struct pull_discover_vertex
00068 {
00069 typedef on_discover_vertex Category;
00070
00071 void operator() ( Vertex v )
00072 {
00073 unsigned int pot = 0;
00074 if( is_inside( v, set_t_vertex ) )
00075 {
00076 residual_edgelist_type::in_iterator eit, eend;
00077 boost::tie( eit, eend ) = in_edges( *g, v, residual_edges );
00078 for(; eit != eend ; eit++ ) pot += get( residual_capacity, *eit );
00079 }
00080 put( potential, v, *g, pot );
00081 }
00082 };
00083
00084 struct pull_choose_edges
00085 {
00086 typedef on_examine_vertex Category;
00087
00088 void operator() ( Vertex v )
00089 {
00090 unsigned int pot = get( potential, v, *g );
00091 residual_edgelist_type::in_iterator eit, eend;
00092 boost::tie( eit, eend ) = in_edges( *g, v, residual_edges );
00093
00094 for(; eit != eend && pot != 0 ; eit++ )
00095 {
00096 unsigned int m, cap = get( residual_capacity, *eit );
00097 m = std::min( cap, pot );
00098 put( residual_flow, *eit, m );
00099 put( edgeflag, *eit, true );
00100 pot -= m;
00101 }
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134 }
00135 };
00136
00137 struct pull_on_edge_prepare
00138 {
00139 typedef on_examine_edge Category;
00140
00141 void operator() ( Vertex v1, ResidualEdge & e, Vertex v2, first_pull_type & prop )
00142 {
00143 get_property_value( prop, flow_tag() ) = get( residual_flow, e );
00144 }
00145 void operator() ( Vertex v1, ResidualEdge e, Vertex v2 ) {}
00146 };
00147
00148 template< class Cat >
00149 struct pull_on_edge
00150 {
00151 typedef Cat Category;
00152
00153 void operator() ( VertexID_t v1, EdgeID_t eid, VertexID_t v2id, first_pull_type & prop, no_property & )
00154 {
00155 Vertex v2 = g->get_known_vertex( v2id );
00156 ResidualEdge e = out_edge( *g, v2, eid, residual_edges );
00157 unsigned int m = get_property_value( prop, flow_tag() );
00158 put( potential, v2, *g, get( potential, v2, *g ) + m );
00159 put( residual_flow, e, m );
00160 put( edgeflag, e, true );
00161 }
00162 void operator() ( Vertex v1, ResidualEdge e, Vertex v2 )
00163 {
00164 unsigned int m = get( residual_flow, e );
00165 put( potential, v2, *g, get( potential, v2, *g ) + m );
00166 }
00167 };
00168
00169 struct base_edge_pos_tag {};
00170 struct remove_edge_tag {};
00171 typedef property< base_edge_pos_tag, bool,
00172 property< remove_edge_tag, bool,
00173 property< flow_tag, unsigned int > > > first_transfer_type;
00174
00175 struct tf_new_vertex {
00176 typedef on_discover_vertex Category;
00177 void operator() ( Vertex v1 )
00178 {
00179 if( !is_inside( v1, set_s_vertex ) )
00180 put( potential, v1, *g, 0 );
00181 }
00182 };
00183
00184 struct transfer_flow
00185 {
00186 typedef on_examine_edge Category;
00187
00188 void operator() ( Vertex v1, ResidualEdge & e, Vertex v2, first_transfer_type & prop )
00189 {
00190 unsigned int pot = get( potential, v1, *g ),
00191 flow = get( residual_flow, e ),
00192 cap = get( residual_capacity, e ), m;
00193 m = std::min( flow, pot );
00194 put( potential, v1, *g, pot - m );
00195 get_property_value( prop, flow_tag() ) = m;
00196
00197 pair< NetworkEdge, bool > base_edge =
00198 out_edge_test( *g, v1, get( edgereference, e), network_edges );
00199 if( base_edge.second )
00200 {
00201 put( network_flow, base_edge.first, get( network_flow, base_edge.first ) + m );
00202 get_property_value( prop, base_edge_pos_tag() ) = false;
00203 }
00204 else
00205 {
00206 get_property_value( prop, base_edge_pos_tag() ) = true;
00207 }
00208
00209 if( m == cap || (!is_inside( v1, set_s_vertex ) &&
00210 in_degree( *g, v1, residual_edges ) == 0 ) )
00211 {
00212 remove_edge( e, *g, residual_edges );
00213 get_property_value( prop, remove_edge_tag() ) = true;
00214 }
00215 else
00216 {
00217 put( residual_capacity, e, cap - m );
00218 put( edgeflag, e, false );
00219 get_property_value( prop, remove_edge_tag() ) = false;
00220 }
00221 }
00222 void operator() ( Vertex v1, ResidualEdge e, Vertex v2 ){}
00223 };
00224
00225 void if_remove_residual_edge( ResidualEdge e, Vertex v2,
00226 unsigned int cap_rest, bool b )
00227 {
00228 if( b )
00229 {
00230 remove_edge( e, *g, residual_edges );
00231 if( in_degree( *g, v2, residual_edges ) == 0 )
00232 {
00233 residual_edgelist_type::out_iterator outit, outend;
00234 boost::tie( outit, outend ) = out_edges( *g, v2, residual_edges );
00235 for(; outit != outend ; outit++ )
00236 {
00237 if( get( edgeflag, *outit ) == false )
00238 {
00239 put( edgeflag, *outit, true );
00240 put( residual_flow, *outit, 0 );
00241 }
00242 }
00243 }
00244 }
00245 else
00246 {
00247 put( residual_capacity, e, cap_rest );
00248 put( edgeflag, e, false );
00249 }
00250 }
00251
00252 template< class Cat >
00253 struct transfer_flow_other_side
00254 {
00255 typedef Cat Category;
00256
00257 void operator() ( VertexID_t v1, EdgeID_t eid, VertexID_t v2id, first_transfer_type & prop, no_property & )
00258 {
00259 Vertex v2 = g->get_known_vertex( v2id );
00260 ResidualEdge e = in_edge( *g, v2, eid, residual_edges );
00261 unsigned int m = get_property_value( prop, flow_tag() ),
00262 cap = get( residual_capacity, e ),
00263 pot = get( potential, v2, *g );
00264 put( potential, v2, *g, pot + m );
00265
00266 if( get_property_value( prop, base_edge_pos_tag() ) == true )
00267 {
00268 NetworkEdge base_edge = out_edge( *g, v2, get( edgereference, e ), network_edges );
00269 put( network_flow, base_edge, get( network_flow, base_edge ) - m );
00270 }
00271
00272 if_remove_residual_edge( e, v2, cap - m, get_property_value( prop, remove_edge_tag() ) );
00273 }
00274 void operator() ( Vertex v1, ResidualEdge e, Vertex v2 )
00275 {
00276 unsigned int pot1 = get( potential, v1, *g ), m,
00277 pot2 = get( potential, v2, *g ),
00278 flow = get( residual_flow, e ),
00279 cap = get( residual_capacity, e );
00280 m = std::min( flow, pot1 );
00281 put( potential, v1, *g, pot1 - m );
00282 put( potential, v2, *g, pot2 + m );
00283
00284 pair< NetworkEdge, bool > base_edge_test =
00285 out_edge_test( *g, v1, get( edgereference, e), network_edges );
00286 if( base_edge_test.second )
00287 {
00288 put( network_flow, base_edge_test.first, get( network_flow, base_edge_test.first ) + m );
00289 }
00290 else
00291 {
00292 NetworkEdge base_edge = out_edge( *g, v2, get( edgereference, e ), network_edges );
00293 put( network_flow, base_edge, get( network_flow, base_edge ) - m );
00294 }
00295
00296 if_remove_residual_edge( e, v2, cap - m, m == cap || (!is_inside( v1, set_s_vertex ) &&
00297 in_degree( *g, v1, residual_edges ) == 0 ) );
00298 }
00299 };
00300
00301 void create_residual_graph()
00302 {
00303 if( _libbase.rank() == 0 ) std::cout<<"Erzeuge Residualgraph..."<<std::endl;
00304 #ifdef LOCALTIME
00305 double local_time1, local_time2;
00306 local_time1 = MPI_Wtime();
00307 #endif
00308 create_residual_edge cre;
00309 for_each_out_edge( *g, network_edges, cre );
00310 add_delayed_edges( residual_edges, *g, cre.buf );
00311 #ifdef LOCALTIME
00312 local_time2 = MPI_Wtime();
00313 crg_time += (local_time2 - local_time1);
00314 #endif
00315 }
00316
00317 bool create_level_graph()
00318 {
00319 if( _libbase.rank() == 0 ) std::cout<<"Erzeuge Levelgraph..."<<std::endl;
00320 #ifdef LOCALTIME
00321 double local_time1, local_time2;
00322 local_time1 = MPI_Wtime();
00323 #endif
00324 bool found = false;
00325 copy( set_s_vertex, grayset1 );
00326
00327 bfs_is_vertex_inside_targetset< Graph::VertexSet >
00328 vis1( *set_t_vertex, &found );
00329 bfs_set_edgeproperty_both_sides< on_target_new_vertex, Graph,
00330 EdgeMap< edgelist_residual_tag, Graph >,
00331 EdgePropertyMap< edge_flag1_tag, EdgeMap< edgelist_residual_tag, Graph > > > vis2( *g, false );
00332 bfs_set_edgeproperty_both_sides< on_target_next_level, Graph,
00333 EdgeMap< edgelist_residual_tag, Graph >,
00334 EdgePropertyMap< edge_flag1_tag, EdgeMap< edgelist_residual_tag, Graph > > > vis3( *g, false );
00335
00336 breadth_first_search( *g, *grayset1, *grayset2, &found, level, residual_edges,
00337 make_bfs_visitor( bfs_distribution_types< no_property, no_property >(),
00338 make_pair( vis3.get_functors(), make_pair( vis2.get_functors(), vis1 ))) );
00339
00340 remove_edges_if( *g, residual_edges, is_edge_marked );
00341 #ifdef LOCALTIME
00342 local_time2 = MPI_Wtime();
00343 clg_time += (local_time2 - local_time1);
00344 #endif
00345
00346 return PG_ReduceAnd( !found );
00347 }
00348
00349
00350 bool pull_flow()
00351 {
00352 if( _libbase.rank() == 0 ) std::cout<<"Ermittle Fluss im Levelgraph..."<<std::endl;
00353 #ifdef LOCALTIME
00354 double local_time1, local_time2;
00355 local_time1 = MPI_Wtime();
00356 #endif
00357 bool found;
00358 FilteredEdgeMap< bool (*)(residual_edgelist_type::Edge),
00359 ReverseEdgeMap< edgelist_residual_tag, Graph > > emap(is_edge_marked);
00360 Graph::VertexSet::set_type gset1, gset2;
00361 copy( set_t_vertex, gset1 );
00362
00363 pull_discover_vertex vis1;
00364 pull_choose_edges vis2;
00365 pull_on_edge_prepare vis3;
00366 pull_on_edge< on_target_new_vertex > vis4;
00367 pull_on_edge< on_target_next_level > vis5;
00368
00369 breadth_first_search( *g, gset1, gset2, &found, level, emap,
00370 make_bfs_visitor( bfs_distribution_types< first_pull_type, no_property >(),
00371 make_pair( vis5, make_pair( vis4, make_pair( vis3, make_pair( vis1, vis2)))) ) );
00372
00373 copy( set_s_vertex, gset1 );
00374 FilteredEdgeMap< bool (*)(residual_edgelist_type::Edge),
00375 EdgeMap< edgelist_residual_tag, Graph > > emap2(is_edge_marked);
00376 transfer_flow tvis1;
00377 tf_new_vertex tvis2;
00378 transfer_flow_other_side< on_target_new_vertex > tvis3;
00379 transfer_flow_other_side< on_target_next_level > tvis4;
00380
00381 breadth_first_search( *g, gset1, gset2, &found, level, emap2,
00382 make_bfs_visitor( bfs_distribution_types< first_transfer_type, no_property >(),
00383 make_pair( tvis1, make_pair( tvis2, make_pair( tvis3, tvis4 ))) ) );
00384 #ifdef LOCALTIME
00385 local_time2 = MPI_Wtime();
00386 pf_time += (local_time2 - local_time1);
00387 #endif
00388
00389 bool has_blocking_flow = false;
00390 if( ! (*set_t_vertex).empty() )
00391 {
00392 if( in_degree( *g, *((*set_t_vertex).begin()), residual_edges ) == 0 )
00393 has_blocking_flow = true;
00394 }
00395 return PG_ReduceOr( has_blocking_flow );
00396 }
00397
00398 void dinic()
00399 {
00400 double starttime, endtime;
00401 starttime = MPI_Wtime();
00402 copy( set_s_vertex, grayset1 );
00403 bfs_do_distribution( *g, *grayset1, *grayset2, level, network_edges );
00404
00405 for(;;)
00406 {
00407 create_residual_graph();
00408 if( create_level_graph() ) break;
00409 while( !pull_flow() );
00410
00411 remove_edges( *g, residual_edges );
00412 iteration++;
00413 }
00414 endtime = MPI_Wtime();
00415
00416 if( ! (*set_s_vertex).empty() )
00417 {
00418 unsigned int flow = 0;
00419 network_edgelist_type::out_iterator eit, eend;
00420 boost::tie( eit, eend ) = out_edges( *g, *(*set_s_vertex).begin(), network_edges );
00421 for(; eit != eend ; eit++ )
00422 {
00423 flow += get( network_flow, *eit );
00424 }
00425 std::cout << "\nAusgehender Fluss von s: " << flow << std::endl;
00426 std::cout << "Laufzeit: " << (endtime-starttime) << "s" << std::endl;
00427 }
00428 #ifdef LOCALTIME
00429 for(size_t i = 0 ; i<_libbase.size() ; i++ )
00430 {
00431 MPI_Barrier( _libbase.comm() );
00432 if( i == _libbase.rank() )
00433 {
00434 std::cout << "Residualgraph: " << crg_time << "s" << std::endl;
00435 std::cout << "Levelgraph: " << clg_time << "s" << std::endl;
00436 std::cout << "Pull Flow: " << pf_time << "s" << std::endl;
00437 }
00438 }
00439 #endif
00440 }
00441
00442
00443
00444
00445 int main( int argc, char *argv[] )
00446 {
00447 ParGraph_init( argc, argv );
00448 g = new Graph();
00449 grayset1 = add_vertex_set( *g );
00450 grayset2 = add_vertex_set( *g );
00451 set_s_vertex = add_vertex_set( *g );
00452 set_t_vertex = add_vertex_set( *g );
00453
00454 dinic_read_graph( argc, argv );
00455 dinic();
00456
00457 delete g;
00458 ParGraph_finalize();
00459 return 0;
00460 }