Boost Graph Library: Push-Relabel Maximum Flow

# `push_relabel_max_flow`

    // named parameter version
    template <class Graph, class P, class T, class R>
    typename property_traits<CapacityEdgeMap>::value_type
    push_relabel_max_flow(Graph& g,
       typename graph_traits<Graph>::vertex_descriptor src,
       typename graph_traits<Graph>::vertex_descriptor sink,
       const bgl_named_params<P, T, R>& params = all defaults)

    // non-named parameter version
    template <class Graph,
    	  class CapacityEdgeMap, class ResidualCapacityEdgeMap,
    	  class ReverseEdgeMap, class VertexIndexMap>
    typename property_traits<CapacityEdgeMap>::value_type
    push_relabel_max_flow(Graph& g,
       typename graph_traits<Graph>::vertex_descriptor src,
       typename graph_traits<Graph>::vertex_descriptor sink,
       CapacityEdgeMap cap, ResidualCapacityEdgeMap res,
       ReverseEdgeMap rev, VertexIndexMap index_map)

The `push_relabel_max_flow()` function calculates the maximum flow of a network. See Section Network Flow Algorithms for a description of maximum flow. The calculated maximum flow will be the return value of the function. The function also calculates the flow values f(u,v) for all (u,v) in E, which are returned in the form of the residual capacity r(u,v) = c(u,v) - f(u,v).

There are several special requirements on the input graph and property map parameters for this algorithm. First, the directed graph G=(V,E) that represents the network must be augmented to include the reverse edge for every edge in E. That is, the input graph should be Gin = (V,{E U ET}). The `ReverseEdgeMap` argument `rev` must map each edge in the original graph to its reverse edge, that is (u,v) -> (v,u) for all (u,v) in E. The `CapacityEdgeMap` argument `cap` must map each edge in E to a positive number, and each edge in ET to 0.

This algorithm was developed by Goldberg.

### Complexity

The time complexity is O(V3).

### Where Defined

`boost/graph/preflow_push_max_flow.hpp`

### Parameters

IN: `VertexListGraph& g`

> A directed graph. The graph's type must be a model of Vertex List Graph. For each edge (u,v) in the graph, the reverse edge (v,u) must also be in the graph.

IN: `vertex_descriptor src`

> The source vertex for the flow network graph.

IN: `vertex_descriptor sink`

> The sink vertex for the flow network graph.

### Named Parameters

IN: `capacity_map(EdgeCapacityMap cap)`

> The edge capacity property map. The type must be a model of a constant Lvalue Property Map. The key type of the map must be the graph's edge descriptor type.
> Default: `get(edge_capacity, g)`

OUT: `residual_capacity_map(ResidualCapacityEdgeMap res)`

> The edge residual capacity property map. The type must be a model of a mutable Lvalue Property Map. The key type of the map must be the graph's edge descriptor type.
> Default: `get(edge_residual_capacity, g)`

IN: `reverse_edge_map(ReverseEdgeMap rev)`

> An edge property map that maps every edge (u,v) in the graph to the reverse edge (v,u). The map must be a model of constant Lvalue Property Map. The key type of the map must be the graph's edge descriptor type.
> Default: `get(edge_reverse, g)`

IN: `vertex_index_map(VertexIndexMap index_map)`

> Maps each vertex of the graph to a unique integer in the range `[0, num_vertices(g))`. The map must be a model of constant LvaluePropertyMap. The key type of the map must be the graph's vertex descriptor type.
> Default: `get(vertex_index, g)` Note: if you use this default, make sure your graph has an internal `vertex_index` property. For example, `adjacenty_list` with `VertexList=listS` does not have an internal `vertex_index` property.

### Example

This reads in an example maximum flow problem (a graph with edge capacities) from a file in the DIMACS format. The source for this example can be found in `example/max_flow.cpp`.

    #include <boost/config.hpp>
    #include <iostream>
    #include <string>
    #include <boost/graph/push_relabel_max_flow.hpp>
    #include <boost/graph/adjacency_list.hpp>
    #include <boost/graph/read_dimacs.hpp>

    int
    main()
    {
      using namespace boost;

      typedef adjacency_list_traits<vecS, vecS, directedS> Traits;
      typedef adjacency_list<vecS, vecS, directedS,
        property<vertex_name_t, std::string>,
        property<edge_capacity_t, long,
          property<edge_residual_capacity_t, long,
    	property<edge_reverse_t, Traits::edge_descriptor> > >
      > Graph;

      Graph g;
      long flow;

      property_map<Graph, edge_capacity_t>::type
        capacity = get(edge_capacity, g);
      property_map<Graph, edge_reverse_t>::type
        rev = get(edge_reverse, g);
      property_map<Graph, edge_residual_capacity_t>::type
        residual_capacity = get(edge_residual_capacity, g);

      Traits::vertex_descriptor s, t;
      read_dimacs_max_flow(g, capacity, rev, s, t);

      flow = push_relabel_max_flow(g, s, t);

      std::cout << "c  The total flow:" << std::endl;
      std::cout << "s " << flow << std::endl << std::endl;

      std::cout << "c flow values:" << std::endl;
      graph_traits<Graph>::vertex_iterator u_iter, u_end;
      graph_traits<Graph>::out_edge_iterator ei, e_end;
      for (boost::tie(u_iter, u_end) = vertices(g); u_iter != u_end; ++u_iter)
        for (boost::tie(ei, e_end) = out_edges(*u_iter, g); ei != e_end; ++ei)
          if (capacity[*ei] > 0)
            std::cout << "f " << *u_iter << " " << target(*ei, g) << " "
                      << (capacity[*ei] - residual_capacity[*ei]) << std::endl;
      return 0;
    }

The output is:

    c  The total flow:
    s 4

    c flow values:
    f 0 1 4
    f 1 2 4
    f 2 3 2
    f 2 4 2
    f 3 1 0
    f 3 6 2
    f 4 5 3
    f 5 6 0
    f 5 7 3
    f 6 4 1
    f 6 7 1

### See Also

`edmonds_karp_max_flow()`
`boykov_kolmogorov_max_flow()`.

Copyright © 2000-2001 | Jeremy Siek, Indiana University (jsiek@osl.iu.edu)