Commit a89e069c authored by Tiago Peixoto's avatar Tiago Peixoto

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
src/graph/community/Makefile
src/graph/util/Makefile
src/graph/topology/Makefile
src/graph/flow/Makefile
src/graph_tool/Makefile
])
......
## 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 =\
-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
graph_tool_topology_PYTHON = \
topology/__init__.py
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 *
graph_tool.run_action
from graph_tool.topology import *
import graph_tool.topology
from graph_tool.flow import *
import graph_tool.flow
from graph_tool.util import *
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