Commit 0db15a14 authored by Tiago Peixoto's avatar Tiago Peixoto
Browse files

Implement group_vector_property() and ungroup_vector_property()

These functions group several scalar properties into one vector
properties, and ungroup a vector property into several scalar
properties.
parent 8dd99577
......@@ -301,6 +301,11 @@ bool openmp_enabled()
#endif
}
void ungroup_vector_property(GraphInterface& g, boost::any vector_prop,
boost::any prop, size_t pos, bool edge);
void group_vector_property(GraphInterface& g, boost::any vector_prop,
boost::any prop, size_t pos, bool edge);
BOOST_PYTHON_MODULE(libgraph_tool_core)
{
// numpy
......@@ -389,6 +394,9 @@ BOOST_PYTHON_MODULE(libgraph_tool_core)
def("set_pickler", &set_pickler);
def("set_unpickler", &set_unpickler);
def("group_vector_property", &group_vector_property);
def("ungroup_vector_property", &ungroup_vector_property);
class_<LibInfo>("mod_info")
.add_property("name", &LibInfo::GetName)
.add_property("author", &LibInfo::GetAuthor)
......
......@@ -17,11 +17,14 @@
#include "graph.hh"
#include "graph_properties.hh"
#include "graph_filtering.hh"
#include "graph_selectors.hh"
#include "graph_util.hh"
#include <boost/mpl/for_each.hpp>
#include <boost/python/extract.hpp>
using namespace std;
using namespace boost;
using namespace graph_tool;
......@@ -65,5 +68,4 @@ void GraphInterface::ShiftVertexProperty(boost::any prop, size_t index) const
throw GraphException("invalid writable property map");
}
} // graph_tool namespace
// 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.hh"
#include "graph_properties.hh"
#include "graph_filtering.hh"
#include "graph_selectors.hh"
#include "graph_properties_group.hh"
#include <boost/python/extract.hpp>
using namespace std;
using namespace boost;
using namespace graph_tool;
typedef mpl::transform<value_types,make_vector>::type vector_types;
typedef property_map_types::apply<vector_types,
GraphInterface::vertex_index_map_t,
mpl::bool_<false> >::type
vertex_vector_properties;
typedef property_map_types::apply<vector_types,
GraphInterface::edge_index_map_t,
mpl::bool_<false> >::type
edge_vector_properties;
void group_vector_property(GraphInterface& g, boost::any vector_prop,
boost::any prop, size_t pos, bool edge)
{
if (edge)
run_action<graph_tool::detail::always_directed_never_reversed>()
(g, bind<void>(do_group_vector_property<mpl::true_,mpl::true_>(),
_1, _2, _3, pos),
edge_vector_properties(), edge_properties())
(vector_prop, prop);
else
run_action<graph_tool::detail::always_directed_never_reversed>()
(g, bind<void>(do_group_vector_property<mpl::true_,mpl::false_>(),
_1, _2, _3, pos),
vertex_vector_properties(), vertex_properties())
(vector_prop, prop);
}
// 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/>.
#ifndef GRAPH_PROPERTIES_GROUP_HH
#define GRAPH_PROPERTIES_GROUP_HH
namespace graph_tool
{
template <class Group = mpl::true_, class Edge = mpl::false_>
struct do_group_vector_property
{
template <class Graph, class VectorPropertyMap, class PropertyMap>
void operator()(Graph& g, VectorPropertyMap vector_map, PropertyMap map,
size_t pos) const
{
int i, N = num_vertices(g);
#pragma omp parallel for default(shared) private(i)
for (i = 0; i < N; ++i)
{
typename graph_traits<Graph>::vertex_descriptor v = vertex(i, g);
if (v == graph_traits<Graph>::null_vertex())
continue;
dispatch_descriptor(g, vector_map, map, v, pos, Edge());
}
}
template <class Graph, class VectorPropertyMap, class PropertyMap,
class Descriptor>
inline void dispatch_descriptor(Graph& g, VectorPropertyMap& vector_map,
PropertyMap& map, const Descriptor& v,
size_t pos, mpl::true_) const
{
typename graph_traits<Graph>::out_edge_iterator e, e_end;
for (tie(e,e_end) = out_edges(v, g); e != e_end; ++e)
{
typename property_traits<VectorPropertyMap>::value_type& vec =
vector_map[*e];
if (vec.size() <= pos)
vec.resize(pos+1);
group_or_ungroup(vector_map, map, *e, pos, Group());
}
}
template <class Graph, class VectorPropertyMap, class PropertyMap,
class Descriptor>
inline void dispatch_descriptor(Graph& g, VectorPropertyMap& vector_map,
PropertyMap& map, const Descriptor& v,
size_t pos, mpl::false_) const
{
if (vector_map[v].size() <= pos)
vector_map[v].resize(pos+1);
group_or_ungroup(vector_map, map, v, pos, Group());
}
template <class VectorPropertyMap, class PropertyMap, class Descriptor>
inline void group_or_ungroup(VectorPropertyMap& vector_map,
PropertyMap& map, const Descriptor& v,
size_t pos, mpl::true_) const
{
convert(get(map,v), vector_map[v][pos]);
}
template <class VectorPropertyMap, class PropertyMap, class Descriptor>
inline void group_or_ungroup(VectorPropertyMap& vector_map,
PropertyMap& map, const Descriptor& v,
size_t pos, mpl::false_) const
{
convert(vector_map[v][pos], map[v]);
}
template <class RetVal, class Value>
inline void convert(const Value& v, RetVal& r) const
{
r = lexical_cast<RetVal>(v);
}
template <class RetVal>
inline void convert(const python::object& v, RetVal& r) const
{
#pragma omp critical
r = python::extract<RetVal>(v);
}
template <class Value>
inline void convert(const Value& v, python::object& r) const
{
#pragma omp critical
r = python::object(v);
}
template <class Value>
inline void convert(const Value& v, Value& r) const
{
r = v;
}
inline void convert(const python::object& v, python::object& r) const
{
#pragma omp critical
r = v;
}
};
} // namespace graph_tool
#endif // GRAPH_PROPERTIES_GROUP_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.hh"
#include "graph_properties.hh"
#include "graph_filtering.hh"
#include "graph_selectors.hh"
#include "graph_properties_group.hh"
#include <boost/python/extract.hpp>
using namespace std;
using namespace boost;
using namespace graph_tool;
typedef mpl::transform<value_types,make_vector>::type vector_types;
typedef property_map_types::apply<vector_types,
GraphInterface::vertex_index_map_t,
mpl::bool_<false> >::type
vertex_vector_properties;
typedef property_map_types::apply<vector_types,
GraphInterface::edge_index_map_t,
mpl::bool_<false> >::type
edge_vector_properties;
void ungroup_vector_property(GraphInterface& g, boost::any vector_prop,
boost::any prop, size_t pos, bool edge)
{
if (edge)
run_action<graph_tool::detail::always_directed_never_reversed>()
(g, bind<void>(do_group_vector_property<mpl::false_,mpl::true_>(),
_1, _2, _3, pos),
edge_vector_properties(), writable_edge_properties())
(vector_prop, prop);
else
run_action<graph_tool::detail::always_directed_never_reversed>()
(g, bind<void>(do_group_vector_property<mpl::false_,mpl::false_>(),
_1, _2, _3, pos),
vertex_vector_properties(), writable_vertex_properties())
(vector_prop, prop);
}
......@@ -94,9 +94,11 @@ import scipy.stats
from . core import __version__, Graph, Vector_bool, Vector_int32_t, \
Vector_int64_t, Vector_double, Vector_long_double, Vector_string, \
value_types, load_graph, PropertyMap, Vertex, Edge, show_config
value_types, load_graph, PropertyMap, Vertex, Edge, \
group_vector_property, ungroup_vector_property, show_config
__all__ = ["Graph", "Vertex", "Edge", "Vector_bool", "Vector_int32_t",
"Vector_int64_t", "Vector_double", "Vector_long_double",
"Vector_string", "value_types", "load_graph", "PropertyMap",
"group_vector_property", "ungroup_vector_property",
"show_config"]
......@@ -210,11 +210,103 @@ def _check_prop_writable(prop, name=None):
raise ValueError("property map%s is not writable." %\
((" '%s'" % name) if name != None else ""))
def _check_prop_scalar(prop, name=None):
if prop.value_type() not in ["bool", "int32_t", "int64_t", "unsigned long",
"double", "long double"]:
raise ValueError("property map%s is not of scalar type." %\
((" '%s'" % name) if name != None else ""))
def _check_prop_scalar(prop, name=None, floating=False):
scalars = ["bool", "int32_t", "int64_t", "unsigned long",
"double", "long double"]
if floating:
scalars = ["double", "long double"]
if prop.value_type() not in scalars:
raise ValueError("property map%s is not of scalar%s type." %\
(((" '%s'" % name) if name != None else ""),
(" floating" if floating else "")))
def _check_prop_vector(prop, name=None, floating=False):
scalars = ["bool", "int32_t", "int64_t", "unsigned long",
"double", "long double"]
if floating:
scalars = ["double", "long double"]
vals = ["vector<%s>" % v for v in scalars]
if prop.value_type() not in vals:
raise ValueError("property map%s is not of vector%s type." %\
(((" '%s'" % name) if name != None else ""),
(" floating" if floating else "")))
def group_vector_property(g, props, value_type=None, vprop=None, pos=None):
types = set()
keys = set()
for i,p in enumerate(props):
if "vector" in p.value_type():
raise ValueError("property map 'props[%d]' is a vector property." %
i)
types.add(p.value_type())
keys.add(p.key_type())
if len(keys) > 1:
raise ValueError("'props' must be of the same key type." )
k = keys.pop()
if vprop == None:
if value_type == None and len(types) == 1:
value_type = types.pop()
if value_type != None:
value_type = "vector<%s>" % value_type
if k == 'v':
vprop = g.new_vertex_property(value_type)
elif k == 'e':
vprop = g.new_edge_property(value_type)
else:
vprop = g.new_graph_property(value_type)
else:
ValueError("Can't automatically determine property map value" +
" type. Please provide the 'value_type' parameter.")
_check_prop_vector(vprop, name="vprop")
for i,p in enumerate(props):
if k != "g":
g.stash_filter(directed=True, reversed=True)
g.set_directed(True)
g.set_reversed(False)
libcore.group_vector_property(g._Graph__graph,
_prop(k, g, vprop),
_prop(k, g, p),
i if pos == None else pos[i],
k == 'e')
g.pop_filter(directed=True, reversed=True)
else:
vprop[g][i if pos == None else pos[i]] = p[g]
return vprop
def ungroup_vector_property(g, vprop, pos, props=None):
_check_prop_vector(vprop, name="vprop")
k = vprop.key_type()
value_type = vprop.value_type().split("<")[1].split(">")[0]
if props == None:
if k == 'v':
props = [g.new_vertex_property(value_type) for i in pos]
elif k == 'e':
props = [g.new_edge_property(value_type) for i in pos]
else:
props = [g.new_graph_property(value_type) for i in pos]
for i,p in enumerate(pos):
if props[i].key_type() != k:
raise ValueError("'props' must be of the same key type as 'vprop'.")
if k != 'g':
g.stash_filter(directed=True, reversed=True)
g.set_directed(True)
g.set_reversed(False)
libcore.ungroup_vector_property(g._Graph__graph,
_prop(k, g, vprop),
_prop(k, g, props[i]),
pos[i], k == 'e')
g.pop_filter(directed=True, reversed=True)
else:
if len(vprop[g]) <= pos[i]:
vprop[g].resize(pos[i]+1)
props[i][g] = vprop[g][pos[i]]
return props
class PropertyDict(dict):
"""Wrapper for the dict of vertex, graph or edge properties, which sets the
......
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