Main Page   Class Hierarchy   Compound List   File List   Compound Members  

dinic.cpp

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     // Variante 1
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     // Variante 2
00104 /*    unsigned int cap = 0;
00105     residual_edgelist_type::in_iterator eit2;
00106     eit2 = eit;
00107     for(; eit != eend ; eit++ )
00108     {
00109       cap += get( residual_capacity, eit );
00110     }
00111     if( cap <= pot )
00112     {
00113       pot -= cap;
00114       for(; eit2 != eend ; eit2++ )
00115       {
00116         cap = get( residual_capacity, eit2 );
00117         put( residual_flow, eit2, cap );
00118         put( edgeflag, eit2, true );
00119       }
00120     }
00121     else
00122     {
00123       double f = ( ((double) pot) / ((double) cap) );
00124       for(; eit2 != eend && pot != 0 ; eit2++ )
00125       {
00126         cap = get( residual_capacity, eit2 );
00127         unsigned int m = (unsigned int)( ((double) cap) * f );
00128         if( m == 0 ) m = 1;
00129         put( residual_flow, eit2, m );
00130         put( edgeflag, eit2, true );
00131         pot -= m;
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    Hauptroutine
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 }

Generated on Sun Feb 29 05:14:24 2004 for ParGraph by doxygen1.3-rc3