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

Resuscitate the line_graph() code

parent 1d16a08d
......@@ -17,7 +17,9 @@ libgraph_tool_generation_la_LDFLAGS = $(MOD_LDFLAGS)
libgraph_tool_generation_la_SOURCES = \
graph_generation.cc \
graph_rewiring.cc \
graph_predecessor.cc
graph_predecessor.cc \
graph_line_graph.cc
libgraph_tool_generation_la_include_HEADERS = \
graph_generation.hh \
......
......@@ -95,6 +95,8 @@ void random_rewire(GraphInterface& gi, string strat, bool self_loops,
bool parallel_edges, size_t seed);
void predecessor_graph(GraphInterface& gi, GraphInterface& gpi,
boost::any pred_map);
void line_graph(GraphInterface& gi, GraphInterface& lgi,
boost::any edge_index);
using namespace boost::python;
......@@ -103,4 +105,5 @@ BOOST_PYTHON_MODULE(libgraph_tool_generation)
def("gen_random_graph", &generate_random_graph);
def("random_rewire", &random_rewire);
def("predecessor_graph", &predecessor_graph);
def("line_graph", &line_graph);
}
// 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.hh"
#include "graph_properties.hh"
#include <tr1/unordered_set>
#include <iostream>
#include <iomanip>
#include <boost/graph/graphviz.hpp>
#include <boost/graph/graphml.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/filter/gzip.hpp>
#include <boost/iostreams/filter/bzip2.hpp>
#include <boost/iostreams/device/file.hpp>
using namespace std;
using namespace boost;
using namespace graph_tool;
// retrieves the line graph
struct get_line_graph
{
template <class Graph, class VertexIndex, class LineGraph,
class EdgeIndexMap, class LGVertexIndex>
void operator()(const Graph& g, VertexIndex vertex_index,
LineGraph& line_graph, EdgeIndexMap edge_index,
LGVertexIndex vmap) const
{
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
typedef boost::property<edge_index_t, size_t> EdgeProperty;
typedef typename property_map<LineGraph, vertex_index_t>::type
line_vertex_index_map_t;
line_vertex_index_map_t line_vertex_index(get(boost::vertex_index,
line_graph));
typedef typename graph_traits<LineGraph>::vertex_descriptor lg_vertex_t;
typedef HashedDescriptorMap<EdgeIndexMap,lg_vertex_t>
edge_to_vertex_map_t;
edge_to_vertex_map_t edge_to_vertex_map(edge_index);
typename LGVertexIndex::checked_t vertex_map = vmap.get_checked();
typename graph_traits<Graph>::edge_iterator e, e_end;
for (tie(e, e_end) = edges(g); e != e_end; ++e)
{
typename graph_traits<LineGraph>::vertex_descriptor v;
v = add_vertex(line_graph);
edge_to_vertex_map[*e] = v;
vertex_map[v] = edge_index[*e];
}
typedef typename property_map<LineGraph,edge_index_t>::type
line_edge_index_map_t;
line_edge_index_map_t line_edge_index(get(edge_index_t(), line_graph));
size_t e_index = 0;
if (boost::is_directed(g))
{
typename graph_traits<Graph>::vertex_iterator v, v_end;
for (tie(v, v_end) = vertices(g); v != v_end; ++v)
{
typename graph_traits<Graph>::out_edge_iterator e1, e2, e1_end,
e2_end;;
for (tie(e1, e1_end) = out_edges(*v, g); e1 != e1_end; ++e1)
{
for (tie(e2, e2_end) = out_edges(target(*e1, g), g);
e2 != e2_end; ++e2)
{
typename graph_traits<LineGraph>::edge_descriptor
new_edge;
new_edge = add_edge(edge_to_vertex_map[*e1],
edge_to_vertex_map[*e2],
line_graph).first;
line_edge_index[new_edge] = e_index++;
}
}
}
}
else
{
typename graph_traits<Graph>::vertex_iterator v, v_end;
for (tie(v, v_end) = vertices(g); v != v_end; ++v)
{
typename graph_traits<Graph>::out_edge_iterator e1, e2, e_end;
for (tie(e1, e_end) = out_edges(*v, g); e1 != e_end; ++e1)
for (e2 = e1; e2 != e_end; ++e2)
if (*e1 != *e2)
{
typename graph_traits<LineGraph>::edge_descriptor
new_edge;
new_edge = add_edge(edge_to_vertex_map[*e1],
edge_to_vertex_map[*e2],
line_graph).first;
line_edge_index[new_edge] = e_index++;
}
}
}
}
};
void line_graph(GraphInterface& gi, GraphInterface& lgi,
boost::any edge_index)
{
typedef property_map_types::apply<mpl::vector<int64_t>,
GraphInterface::vertex_index_map_t,
mpl::false_>::type
vertex_properties;
run_action<>()(gi, bind<void>(get_line_graph(), _1,
gi.GetVertexIndex(),
ref(lgi.GetGraph()), lgi.GetEdgeIndex(),
_2),
vertex_properties())(edge_index);
lgi.ReIndexEdges();
}
// 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.hh"
#include "graph_properties.hh"
#include <tr1/unordered_set>
#include <iostream>
#include <iomanip>
#include <boost/graph/graphviz.hpp>
#include <boost/graph/graphml.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/filter/gzip.hpp>
#include <boost/iostreams/filter/bzip2.hpp>
#include <boost/iostreams/device/file.hpp>
using namespace std;
using namespace boost;
using namespace graph_tool;
// retrieves the line graph
struct get_line_graph
{
template <class Graph, class EdgeIndexMap>
void operator()(const Graph* pg, EdgeIndexMap edge_index,
dynamic_properties& properties, string file,
string format) const
{
const Graph& g = *pg;
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
typedef boost::property<edge_index_t, size_t> EdgeProperty;
typedef adjacency_list <vecS, // edges
vecS, // vertices
undirectedS,
no_property,
EdgeProperty > line_graph_t;
line_graph_t line_graph;
typedef typename property_map<line_graph_t, vertex_index_t>::type
line_vertex_index_map_t;
line_vertex_index_map_t line_vertex_index(get(vertex_index,
line_graph));
typedef HashedDescriptorMap
<line_vertex_index_map_t,
typename graph_traits
<typename Graph::original_graph_t>::edge_descriptor> edge_map_t;
edge_map_t edge_map(line_vertex_index);
typedef HashedDescriptorMap
<EdgeIndexMap,
typename graph_traits<line_graph_t>::vertex_descriptor>
edge_to_vertex_map_t;
edge_to_vertex_map_t edge_to_vertex_map(edge_index);
typename graph_traits<Graph>::edge_iterator e, e_end;
for (tie(e, e_end) = edges(g); e != e_end; ++e)
{
typename graph_traits<line_graph_t>::vertex_descriptor v;
v = add_vertex(line_graph);
edge_to_vertex_map[*e] = v;
edge_map[v] = *e;
}
typedef typename property_map<line_graph_t,edge_index_t>::type
line_edge_index_map_t;
line_edge_index_map_t line_edge_index(get(edge_index_t(), line_graph));
typedef HashedDescriptorMap<line_edge_index_map_t,vertex_t>
vertex_map_t;
vertex_map_t vertex_map(line_edge_index);
size_t e_index = 0;
typename graph_traits<Graph>::vertex_iterator v, v_end;
for (tie(v, v_end) = vertices(g); v != v_end; ++v)
{
typename graph_traits<Graph>::out_edge_iterator e1, e2, e_end;
for (tie(e1, e_end) = out_edges(*v, g); e1 != e_end; ++e1)
for (e2 = e1; e2 != e_end; ++e2)
if (*e1 != *e2)
{
typename graph_traits<line_graph_t>::edge_descriptor
new_edge;
new_edge = add_edge(edge_to_vertex_map[*e1],
edge_to_vertex_map[*e2],
line_graph).first;
line_edge_index[new_edge] = e_index++;
vertex_map[new_edge] = *v;
}
}
dynamic_properties dp;
for (typeof(properties.begin()) iter = properties.begin();
iter != properties.end(); ++iter)
{
if (iter->second->key() != typeid(graph_property_tag))
{
if (iter->second->key() == typeid(vertex_t))
dp.insert(iter->first,
auto_ptr<dynamic_property_map>
(new dynamic_property_map_wrap<vertex_map_t>
(vertex_map, *iter->second)));
else
dp.insert(iter->first,
auto_ptr<dynamic_property_map>
(new dynamic_property_map_wrap<edge_map_t>
(edge_map, *iter->second)));
}
else
{
dp.insert(iter->first,
auto_ptr<dynamic_property_map>(iter->second));
}
}
bool graphviz = false;
if (format == "")
graphviz = ends_with(file,".dot") || ends_with(file,".dot.gz")
|| ends_with(file,".dot.bz2");
else if (format == "dot")
graphviz = true;
else if (format != "xml")
throw GraphException("error writing to file '" + file +
"': requested invalid format '" +
format + "'");
try
{
iostreams::filtering_stream<iostreams::output> stream;
ofstream file_stream;
if (file == "-")
stream.push(cout);
else
{
file_stream.open(file.c_str(), ios_base::out |
ios_base::binary);
file_stream.exceptions(ios_base::badbit | ios_base::failbit);
if (ends_with(file,".gz"))
stream.push(iostreams::gzip_compressor());
if (ends_with(file,".bz2"))
stream.push(iostreams::bzip2_compressor());
stream.push(file_stream);
}
stream.exceptions(ios_base::badbit | ios_base::failbit);
if (graphviz)
{
dp.property("vertex_id", line_vertex_index);
write_graphviz(stream, line_graph, dp, string("vertex_id"));
}
else
{
write_graphml(stream, line_graph, line_vertex_index, dp, true);
}
stream.reset();
}
catch (ios_base::failure &e)
{
throw GraphException("error writing to file '" + file + "':" +
e.what());
}
for (typeof(dp.begin()) iter = dp.begin(); iter != dp.end(); ++iter)
if (iter->second->key() == typeid(graph_property_tag))
iter->second = 0;
}
template <class DescriptorMap>
class dynamic_property_map_wrap: public dynamic_property_map
{
public:
dynamic_property_map_wrap(DescriptorMap& edge_map,
dynamic_property_map& dm)
: _descriptor_map(edge_map), _dm(dm) {}
any get(const any& key)
{
key_t k = any_cast<key_t>(key);
return _dm.get(_descriptor_map[k]);
}
string get_string(const any& key)
{
key_t k = any_cast<key_t>(key);
return _dm.get_string(_descriptor_map[k]);
}
void put(const any& key, const any& value)
{
return _dm.put(_descriptor_map[any_cast<key_t>(key)], value);
}
const type_info& key() const
{
return typeid(key_t);
}
const type_info& value() const
{
return _dm.value();
}
private:
DescriptorMap& _descriptor_map;
typedef typename property_traits<DescriptorMap>::key_type key_t;
dynamic_property_map& _dm;
};
};
void GraphInterface::GetLineGraph(string out_file, string format)
{
bool directed = _directed;
_directed = false;
run_action<detail::never_directed>()
(*this, bind<void>(get_line_graph(), _1, var(_edge_index),
var(_properties), out_file, format))();
_directed = directed;
}
......@@ -27,7 +27,7 @@ dl_import("import libgraph_tool_generation")
from .. core import Graph, _check_prop_scalar, _prop
import sys, numpy
__all__ = ["random_graph", "random_rewire", "predecessor_tree"]
__all__ = ["random_graph", "random_rewire", "predecessor_tree", "line_graph"]
def _corr_wrap(i, j, corr):
return corr(i[1], j[1])
......@@ -387,3 +387,13 @@ def predecessor_tree(g, pred_map):
pg._Graph__graph,
_prop("v", g, pred_map))
return pg
def line_graph(g):
lg = Graph(directed=g.is_directed())
vertex_map = lg.new_vertex_property("int64_t")
libgraph_tool_generation.line_graph(g._Graph__graph,
lg._Graph__graph,
_prop("v", lg, vertex_map))
return lg, vertex_map
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