Commit a89e069c authored by Tiago Peixoto's avatar Tiago Peixoto
Browse files

Implement flow algorithms

This includes the edmonds karp, push relabel and kolmogorov maximum flow
algorithms from the BGL.
parent 4a1b3817
...@@ -293,6 +293,7 @@ src/graph/clustering/Makefile ...@@ -293,6 +293,7 @@ src/graph/clustering/Makefile
src/graph/community/Makefile src/graph/community/Makefile
src/graph/util/Makefile src/graph/util/Makefile
src/graph/topology/Makefile src/graph/topology/Makefile
src/graph/flow/Makefile
src/graph_tool/Makefile src/graph_tool/Makefile
]) ])
......
## Process this file with automake to produce Makefile.in ## Process this file with automake to produce Makefile.in
SUBDIRS = generation stats clustering community util topology centrality correlations SUBDIRS = generation stats clustering community util topology centrality correlations flow
AM_CPPFLAGS =\ AM_CPPFLAGS =\
-I$(srcdir)/.. \ -I$(srcdir)/.. \
......
## Process this file with automake to produce Makefile.in
AM_CPPFLAGS = $(MOD_CPPFLAGS)
AM_CFLAGS = $(AM_CXXFLAGS)
libgraph_tool_flowdir = $(pythondir)/graph_tool/flow
libgraph_tool_flow_LTLIBRARIES = libgraph_tool_flow.la
libgraph_tool_flow_la_includedir = $(pythondir)/graph_tool/include
libgraph_tool_flow_la_LIBADD = $(MOD_LIBADD)
libgraph_tool_flow_la_LDFLAGS = $(MOD_LDFLAGS)
libgraph_tool_flow_la_SOURCES = \
graph_edmonds_karp.cc \
graph_push_relabel.cc \
graph_kolmogorov.cc \
graph_flow_bind.cc
libgraph_tool_flow_la_include_HEADERS = \
graph_augment.hh
// Copyright (C) 2008 Tiago de Paula Peixoto <tiago@forked.de>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef GRAPH_AUGMENT_HH
#define GRAPH_AUGMENT_HH
namespace graph_tool
{
using namespace std;
using namespace boost;
template <class Graph, class AugmentedMap, class CapacityMap,
class ReversedMap, class ResidualMap>
void augment_graph(Graph& g, AugmentedMap augmented, CapacityMap capacity,
ReversedMap rmap, ResidualMap res)
{
typename graph_traits<Graph>::edge_iterator e, e_end;
for (tie(e,e_end) = edges(g); e != e_end; ++e)
augmented[*e] = false;
typename graph_traits<Graph>::vertex_iterator v, v_end;
vector<typename graph_traits<Graph>::edge_descriptor> e_list;
for (tie(v,v_end) = vertices(g); v != v_end; ++v)
{
e_list.clear();
typename graph_traits<Graph>::out_edge_iterator e, e_end;
for (tie(e, e_end) = out_edges(*v, g); e != e_end; ++e)
{
if (!augmented[*e])
e_list.push_back(*e);
}
for (size_t i = 0; i < e_list.size(); ++i)
{
typename graph_traits<Graph>::edge_descriptor ae;
ae = add_edge(target(e_list[i],g), source(e_list[i],g), g).first;
augmented[ae] = true;
capacity[ae] = 0;
rmap[e_list[i]] = ae;
rmap[ae] = e_list[i];
res[ae] = 0;
}
}
}
template <class Graph, class AugmentedMap>
void deaugment_graph(Graph& g, AugmentedMap augmented)
{
vector<typename graph_traits<Graph>::edge_descriptor> e_list;
typename graph_traits<Graph>::vertex_iterator v, v_end;
for (tie(v,v_end) = vertices(g); v != v_end; ++v)
{
e_list.clear();
typename graph_traits<Graph>::out_edge_iterator e, e_end;
for (tie(e, e_end) = out_edges(*v, g); e != e_end; ++e)
{
if (augmented[*e])
e_list.push_back(*e);
}
for (size_t i = 0; i < e_list.size(); ++i)
remove_edge(e_list[i],g);
}
}
template <class Type, class Index>
checked_vector_property_map<Type, Index>
get_checked(unchecked_vector_property_map<Type, Index> prop)
{
return prop.get_checked();
}
template <class Prop>
Prop
get_checked(Prop prop)
{
return prop;
}
} // graph_tool namespace
#endif // GRAPH_AUGMENT_HH
// graph-tool -- a general graph modification and manipulation thingy
//
// Copyright (C) 2007 Tiago de Paula Peixoto <tiago@forked.de>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "graph_filtering.hh"
#include "graph_selectors.hh"
#include "graph_properties.hh"
#include "graph.hh"
#include "graph_augment.hh"
#include <boost/graph/edmonds_karp_max_flow.hpp>
#include <boost/bind.hpp>
using namespace graph_tool;
using namespace boost;
struct get_edmonds_karp_max_flow
{
template <class Graph, class EdgeIndex, class CapacityMap,
class ResidualMap>
void operator()(Graph& g, EdgeIndex edge_index, size_t max_e, size_t src,
size_t sink, CapacityMap cm, ResidualMap res) const
{
typedef typename graph_traits<Graph>::edge_descriptor edge_t;
unchecked_vector_property_map<bool,EdgeIndex>
augmented(edge_index, max_e);
unchecked_vector_property_map<edge_t,EdgeIndex>
reverse_map(edge_index, max_e);
augment_graph(g, augmented.get_checked(), get_checked(cm),
reverse_map.get_checked(), res.get_checked());
boost::edmonds_karp_max_flow(g._g, vertex(src, g), vertex(sink, g),
capacity_map(cm).
reverse_edge_map(reverse_map).
residual_capacity_map(res));
deaugment_graph(g, augmented.get_checked());
}
};
void edmonds_karp_max_flow(GraphInterface& gi, size_t src, size_t sink,
boost::any capacity, boost::any res)
{
run_action<graph_tool::detail::always_directed, mpl::true_>()
(gi, bind<void>(get_edmonds_karp_max_flow(),
_1, gi.GetEdgeIndex(), gi.GetMaxEdgeIndex(),
src, sink, _2, _3),
edge_scalar_properties(), writable_edge_scalar_properties())
(capacity,res);
}
// Copyright (C) 2008 Tiago de Paula Peixoto <tiago@forked.de>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "graph.hh"
using namespace graph_tool;
using namespace boost;
void edmonds_karp_max_flow(GraphInterface& gi, size_t src, size_t sink,
boost::any capacity, boost::any res);
void push_relabel_max_flow(GraphInterface& gi, size_t src, size_t sink,
boost::any capacity, boost::any res);
void kolmogorov_max_flow(GraphInterface& gi, size_t src, size_t sink,
boost::any capacity, boost::any res);
#include <boost/python.hpp>
using namespace boost::python;
BOOST_PYTHON_MODULE(libgraph_tool_flow)
{
def("edmonds_karp_max_flow", &edmonds_karp_max_flow);
def("push_relabel_max_flow", &push_relabel_max_flow);
def("kolmogorov_max_flow", &kolmogorov_max_flow);
}
// graph-tool -- a general graph modification and manipulation thingy
//
// Copyright (C) 2007 Tiago de Paula Peixoto <tiago@forked.de>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "graph_filtering.hh"
#include "graph_selectors.hh"
#include "graph_properties.hh"
#include "graph.hh"
#include "graph_augment.hh"
#include <boost/mpl/if.hpp>
#include <boost/mpl/or.hpp>
namespace std
{
using namespace boost;
// we need a min() function with arguments of different types
template <class T1, class T2>
typename mpl::if_<
typename mpl::or_<typename is_floating_point<T1>::type,
typename is_floating_point<T2>::type>::type,
double, int>::type
min(const T1& v1, const T2& v2)
{
if (v1 <= v2)
return v1;
else
return v2;
}
}
#include <boost/graph/kolmogorov_max_flow.hpp>
#include <boost/bind.hpp>
using namespace graph_tool;
using namespace boost;
struct get_kolmogorov_max_flow
{
template <class Graph, class EdgeIndex, class VertexIndex,
class CapacityMap, class ResidualMap>
void operator()(Graph& g, EdgeIndex edge_index, size_t max_e,
VertexIndex vertex_index, size_t src, size_t sink,
CapacityMap cm, ResidualMap res) const
{
typedef typename graph_traits<Graph>::edge_descriptor edge_t;
unchecked_vector_property_map<bool,EdgeIndex>
augmented(edge_index, max_e);
unchecked_vector_property_map<edge_t,EdgeIndex>
reverse_map(edge_index, max_e);
unchecked_vector_property_map<edge_t,VertexIndex>
pred_map(vertex_index, num_vertices(g));
unchecked_vector_property_map<size_t,VertexIndex>
color_map(vertex_index, num_vertices(g));
unchecked_vector_property_map<size_t,VertexIndex>
dist_map(vertex_index, num_vertices(g));
augment_graph(g, augmented.get_checked(), get_checked(cm),
reverse_map.get_checked(), res.get_checked());
boost::kolmogorov_max_flow(g._g, cm, res, reverse_map, pred_map,
color_map, dist_map, vertex_index,
vertex(src, g), vertex(sink, g));
deaugment_graph(g, augmented.get_checked());
}
};
void kolmogorov_max_flow(GraphInterface& gi, size_t src, size_t sink,
boost::any capacity, boost::any res)
{
run_action<graph_tool::detail::always_directed, mpl::true_>()
(gi, bind<void>(get_kolmogorov_max_flow(),
_1, gi.GetEdgeIndex(), gi.GetMaxEdgeIndex(),
gi.GetVertexIndex(), src, sink, _2, _3),
edge_scalar_properties(), writable_edge_scalar_properties())
(capacity,res);
}
// graph-tool -- a general graph modification and manipulation thingy
//
// Copyright (C) 2007 Tiago de Paula Peixoto <tiago@forked.de>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "graph_filtering.hh"
#include "graph_selectors.hh"
#include "graph_properties.hh"
#include "graph.hh"
#include "graph_augment.hh"
#include <boost/mpl/if.hpp>
#include <boost/mpl/or.hpp>
namespace std
{
using namespace boost;
// we need a min() function with arguments of different types
template <class T1, class T2>
typename mpl::if_<
typename mpl::or_<typename is_floating_point<T1>::type,
typename is_floating_point<T2>::type>::type,
double, int>::type
min(const T1& v1, const T2& v2)
{
if (v1 <= v2)
return v1;
else
return v2;
}
}
#include <boost/graph/push_relabel_max_flow.hpp>
#include <boost/bind.hpp>
using namespace graph_tool;
using namespace boost;
struct get_push_relabel_max_flow
{
template <class Graph, class EdgeIndex, class CapacityMap,
class ResidualMap>
void operator()(Graph& g, EdgeIndex edge_index, size_t max_e, size_t src,
size_t sink, CapacityMap cm, ResidualMap res) const
{
typedef typename graph_traits<Graph>::edge_descriptor edge_t;
unchecked_vector_property_map<bool,EdgeIndex>
augmented(edge_index, max_e);
unchecked_vector_property_map<edge_t,EdgeIndex>
reverse_map(edge_index, max_e);
augment_graph(g, augmented.get_checked(), get_checked(cm),
reverse_map.get_checked(), res.get_checked());
boost::push_relabel_max_flow(g._g, vertex(src, g), vertex(sink, g),
capacity_map(cm).
reverse_edge_map(reverse_map).
residual_capacity_map(res));
deaugment_graph(g, augmented.get_checked());
}
};
void push_relabel_max_flow(GraphInterface& gi, size_t src, size_t sink,
boost::any capacity, boost::any res)
{
run_action<graph_tool::detail::always_directed, mpl::true_>()
(gi, bind<void>(get_push_relabel_max_flow(),
_1, gi.GetEdgeIndex(), gi.GetMaxEdgeIndex(),
src, sink, _2, _3),
edge_scalar_properties(), writable_edge_scalar_properties())
(capacity,res);
}
...@@ -53,3 +53,7 @@ graph_tool_utildir = $(MOD_DIR)/util ...@@ -53,3 +53,7 @@ graph_tool_utildir = $(MOD_DIR)/util
graph_tool_topology_PYTHON = \ graph_tool_topology_PYTHON = \
topology/__init__.py topology/__init__.py
graph_tool_topologydir = $(MOD_DIR)/topology graph_tool_topologydir = $(MOD_DIR)/topology
graph_tool_flow_PYTHON = \
flow/__init__.py
graph_tool_flowdir = $(MOD_DIR)/flow
...@@ -47,5 +47,7 @@ from graph_tool.run_action import * ...@@ -47,5 +47,7 @@ from graph_tool.run_action import *
graph_tool.run_action graph_tool.run_action
from graph_tool.topology import * from graph_tool.topology import *
import graph_tool.topology import graph_tool.topology
from graph_tool.flow import *
import graph_tool.flow
from graph_tool.util import * from graph_tool.util import *
import graph_tool.util import graph_tool.util
#! /usr/bin/env python
# graph_tool.py -- a general graph manipulation python module
#
# Copyright (C) 2007 Tiago de Paula Peixoto <tiago@forked.de>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
``graph_tool.flow`` - Maximum flow algorithms
---------------------------------------------
"""
from .. dl_import import dl_import
dl_import("import libgraph_tool_flow")
from .. core import _prop, _check_prop_scalar, _check_prop_writable
__all__ = ["edmonds_karp_max_flow", "push_relabel_max_flow",
"kolmogorov_max_flow"]
def edmonds_karp_max_flow(g, source, target, capacity, residual=None):
_check_prop_scalar(capacity, "capacity")
if residual == None:
residual = g.new_edge_property(capacity.value_type())
_check_prop_scalar(residual, "residual")
_check_prop_writable(residual, "residual")
libgraph_tool_flow.\
edmonds_karp_max_flow(g._Graph__graph, int(source), int(target),
_prop("e", g, capacity),
_prop("e", g, residual))
return residual
def push_relabel_max_flow(g, source, target, capacity, residual=None):
_check_prop_scalar(capacity, "capacity")
if residual == None:
residual = g.new_edge_property(capacity.value_type())
_check_prop_scalar(residual, "residual")
_check_prop_writable(residual, "residual")
libgraph_tool_flow.\
push_relabel_max_flow(g._Graph__graph, int(source), int(target),
_prop("e", g, capacity),
_prop("e", g, residual))
return residual
def kolmogorov_max_flow(g, source, target, capacity, residual=None):
_check_prop_scalar(capacity, "capacity")
if residual == None:
residual = g.new_edge_property(capacity.value_type())
_check_prop_scalar(residual, "residual")
_check_prop_writable(residual, "residual")
libgraph_tool_flow.\
kolmogorov_max_flow(g._Graph__graph, int(source), int(target),
_prop("e", g, capacity),
_prop("e", g, residual))
return residual
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment