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

Externalize property maps by default

This commit removes the internal property maps from the GraphInterface
class, and makes all property maps external by default. The internal
property maps were moved to the python layer.
parent 07dbd3b0
......@@ -33,7 +33,7 @@ assortativity_coefficient(const GraphInterface& gi,
double a, a_err;
run_action<>()(gi,bind<void>(get_assortativity_coefficient(), _1, _2,
var(a), var(a_err)), all_selectors())
(degree_selector(deg, gi));
(degree_selector(deg));
return make_pair(a, a_err);
}
......@@ -46,7 +46,7 @@ scalar_assortativity_coefficient(const GraphInterface& gi,
run_action<>()(gi, bind<void>(get_scalar_assortativity_coefficient(),
_1, _2, var(a), var(a_err)),
all_selectors())
(degree_selector(deg, gi));
(degree_selector(deg));
return make_pair(a, a_err);
}
......
......@@ -49,7 +49,7 @@ python::object
get_vertex_correlation_histogram(const GraphInterface& gi,
GraphInterface::deg_t deg1,
GraphInterface::deg_t deg2,
string weight,
boost::any weight,
const vector<long double>& xbin,
const vector<long double>& ybin)
{
......@@ -64,11 +64,9 @@ get_vertex_correlation_histogram(const GraphInterface& gi,
typedef DynamicPropertyMapWrap<long double, GraphInterface::edge_t>
wrapped_weight_t;
if (weight != "")
if (!weight.empty())
{
dynamic_property_map* map =
any_cast<dynamic_property_map*>(edge_prop(weight, gi, true));
weight_prop = wrapped_weight_t(*map);
weight_prop = wrapped_weight_t(weight, edge_scalar_properties());
}
else
weight_prop = cweight_map_t(1);
......@@ -79,12 +77,12 @@ get_vertex_correlation_histogram(const GraphInterface& gi,
(hist, bins, ret_bins),
all_selectors(), all_selectors(),
mpl::vector<cweight_map_t>())
(degree_selector(deg1, gi), degree_selector(deg2, gi), weight_prop);
(degree_selector(deg1), degree_selector(deg2), weight_prop);
}
catch (ActionNotFound&)
{
graph_correlations_imp1(gi, hist, ret_bins, degree_selector(deg1, gi),
degree_selector(deg2, gi), weight_prop, bins);
graph_correlations_imp1(gi, hist, ret_bins, degree_selector(deg1),
degree_selector(deg2), weight_prop, bins);
}
return python::make_tuple(hist, ret_bins);
......
......@@ -52,7 +52,7 @@ get_vertex_combined_correlation_histogram(const GraphInterface& gi,
ret_bins),
all_selectors(), all_selectors(),
mpl::vector<dummy_weight>())
(degree_selector(deg1, gi), degree_selector(deg2, gi),
(degree_selector(deg1), degree_selector(deg2),
boost::any(dummy_weight()));
return python::make_tuple(hist, ret_bins);
......
......@@ -40,6 +40,7 @@ GraphInterface::GraphInterface()
_directed(true),
_vertex_index(get(vertex_index,_mg)),
_edge_index(get(edge_index_t(),_mg)),
_graph_index(0),
_vertex_filter_map(_vertex_index),
_vertex_filter_invert(false),
_vertex_filter_active(false),
......@@ -80,67 +81,13 @@ size_t GraphInterface::GetNumberOfEdges() const
return n;
}
// signal handling
void catch_sig_stop(int sig_num)
void GraphInterface::Clear()
{
std::cerr << "graph-tool: received signal ";
switch (sig_num)
{
case SIGINT:
std::cerr << "SIGINT (Interrupt).";
break;
case SIGTERM:
std::cerr << "SIGTERM (Termination).";
break;
case SIGQUIT:
std::cerr << "SIGQUIT (Terminal quit).";
break;
case SIGHUP:
std::cerr << "SIGHUP (Hangup).";
break;
case SIGPWR:
std::cerr << "SIGPWR (Power failure restart).";
break;
case SIGSEGV:
std::cerr << "SIGSEGV (Segmentation fault). "
<< "There's a bug somewhere in the program. Go fix it.";
break;
case SIGBUS:
std::cerr << "SIGBUS (BUS error). The bus is broken, I guess...";
break;
case SIGFPE:
std::cerr << "SIGFPE (Floating-point exception). "
<< "INFs and NANs are wreaking havoc.";
break;
case SIGILL:
std::cerr << "SIGILL (Illegal instruction). Did you compile it right?";
break;
case SIGXCPU:
std::cerr << "SIGXCPU (CPU limit exceeded). Time's over.";
break;
case SIGXFSZ:
std::cerr << "SIGXFSZ (File size limit exceeded). "
<< "The fascist sysadmin doesn't let you write more.";
break;
}
std::cerr << " Bailing out cowardly and calling abort()." << std::endl;
abort();
_mg.clear();
}
// initialize signal handling
void GraphInterface::InitSignalHandling()
void GraphInterface::ClearEdges()
{
signal(SIGINT, catch_sig_stop);
signal(SIGTERM, catch_sig_stop);
signal(SIGQUIT, catch_sig_stop);
signal(SIGHUP, catch_sig_stop);
signal(SIGPWR, catch_sig_stop);
signal(SIGSEGV, catch_sig_stop);
signal(SIGBUS, catch_sig_stop);
signal(SIGFPE, catch_sig_stop);
signal(SIGILL, catch_sig_stop);
signal(SIGXCPU, catch_sig_stop);
signal(SIGXFSZ, catch_sig_stop);
//
}
......@@ -29,6 +29,7 @@
#include <boost/python/object.hpp>
#include <boost/python/dict.hpp>
#include <boost/mpl/vector.hpp>
#include "graph_properties.hh"
#include "config.h"
namespace graph_tool
......@@ -69,11 +70,9 @@ public:
TOTAL_DEGREE
} degree_t;
typedef boost::variant<degree_t, string> deg_t; // general "degree" type,
// i.e., either a degree_t
// above or a string
// representing a scalar
// vertex property
// general "degree" type, i.e., either a degree_t above or a string
// representing a scalar vertex property
typedef boost::variant<degree_t, boost::any> deg_t;
//
// Basic manipulation
......@@ -82,35 +81,28 @@ public:
size_t GetNumberOfVertices() const;
size_t GetNumberOfEdges() const;
void SetDirected(bool directed) {_directed = directed;}
bool GetDirected() const {return _directed;}
bool GetDirected() {return _directed;}
void SetReversed(bool reversed) {_reversed = reversed;}
bool GetReversed() const {return _reversed;}
bool GetReversed() {return _reversed;}
// graph filtering
void SetVertexFilterProperty(string property, bool invert);
pair<string, bool> GetVertexFilterProperty() const;
void SetVertexFilterProperty(boost::any prop, bool invert);
bool IsVertexFilterActive() const;
void SetEdgeFilterProperty(string property, bool invert);
pair<string, bool> GetEdgeFilterProperty() const;
void SetEdgeFilterProperty(boost::any prop, bool invert);
bool IsEdgeFilterActive() const;
// graph modification
void RemoveVertexProperty(string property);
void RemoveEdgeProperty(string property);
void RemoveGraphProperty(string property);
void InsertEdgeIndexProperty(string property);
void InsertVertexIndexProperty(string property);
void AddVertexProperty(string property, string type);
void AddEdgeProperty(string property, string type);
void AddGraphProperty(string property, string type);
void InsertPropertyMap(string name, boost::any map);
void ReIndexEdges();
void PurgeVertices(); // removes filtered vertices
void PurgeEdges(); // removes filtered edges
void Clear();
// i/o
void WriteToFile(string s, python::object pf, string format);
void ReadFromFile(string s, python::object pf, string format);
void ClearEdges();
void ShiftVertexProperty(boost::any map, size_t index) const;
void CopyVertexProperty(const GraphInterface& src, boost::any prop_src,
boost::any prop_tgt);
void CopyEdgeProperty(const GraphInterface& src, boost::any prop_src,
boost::any prop_tgt);
//
// python interface
......@@ -124,19 +116,16 @@ public:
python::object AddEdge(const python::object& s, const python::object& t);
void RemoveEdge(const python::object& e);
python::dict GetVertexProperties() const;
python::dict GetEdgeProperties() const;
python::dict GetGraphProperties() const;
void PutPropertyMap(string name, const python::object& map);
// used for graph properties
graph_property_tag GetDescriptor() const { return graph_property_tag(); }
bool CheckValid() const {return true;}
void ExportPythonInterface() const;
// signal handling
void InitSignalHandling();
// I/O
void WriteToFile(string s, python::object pf, string format,
python::list properties);
python::tuple ReadFromFile(string s, python::object pf, string format);
//
// Internal types
......@@ -156,9 +145,11 @@ public:
typedef property_map<multigraph_t,vertex_index_t>::type vertex_index_map_t;
typedef property_map<multigraph_t,edge_index_t>::type edge_index_map_t;
typedef ConstantPropertyMap<size_t,graph_property_tag> graph_index_map_t;
vertex_index_map_t GetVertexIndex() {return _vertex_index;}
edge_index_map_t GetEdgeIndex() {return _edge_index;}
boost::any GetVertexIndex() {return _vertex_index;}
boost::any GetEdgeIndex() {return _edge_index;}
boost::any GetGraphIndex() {return graph_index_map_t(0);}
private:
// Gets the encapsulated graph view. See graph_filtering.cc for details
......@@ -174,15 +165,6 @@ private:
template <class Action>
friend void RunAction(GraphInterface& g, const Action& a);
friend boost::any degree_selector(deg_t deg, const GraphInterface& gi);
friend boost::any vertex_prop(const string& name, const GraphInterface& gi,
bool dynamic);
friend boost::any edge_prop(const string& name, const GraphInterface& gi,
bool dynamic);
friend boost::any graph_prop(const string& name, const GraphInterface& gi,
bool dynamic);
// python interface
friend class PythonVertex;
template <class Graph>
......@@ -204,25 +186,26 @@ private:
// edge index map
edge_index_map_t _edge_index;
// graph properties
dynamic_properties _properties;
// graph index map
graph_index_map_t _graph_index;
// vertex filter
typedef vector_property_map<uint8_t,vertex_index_map_t> vertex_filter_t;
vertex_filter_t _vertex_filter_map;
string _vertex_filter_property;
bool _vertex_filter_invert;
bool _vertex_filter_active;
// edge filter
typedef vector_property_map<uint8_t,edge_index_map_t> edge_filter_t;
edge_filter_t _edge_filter_map;
string _edge_filter_property;
bool _edge_filter_invert;
bool _edge_filter_active;
};
#pragma GCC visibility pop
// Exceptions
// ==========
//
// This is the main exception which will be thrown the outside world, when
// things go wrong
......
......@@ -282,6 +282,7 @@ BOOST_PYTHON_MODULE(libgraph_tool_core)
def("raise_error", &raise_error);
def("get_property_types", &get_property_types);
class_<boost::any>("any", no_init);
mpl::for_each<mpl::push_back<scalar_types,string>::type>(export_vector_types());
......@@ -295,27 +296,13 @@ BOOST_PYTHON_MODULE(libgraph_tool_core)
.def("GetReversed", &GraphInterface::GetReversed)
.def("SetVertexFilterProperty",
&GraphInterface::SetVertexFilterProperty)
.def("GetVertexFilterProperty",
&GraphInterface::GetVertexFilterProperty)
.def("IsVertexFilterActive", &GraphInterface::IsVertexFilterActive)
.def("SetEdgeFilterProperty",
&GraphInterface::SetEdgeFilterProperty)
.def("GetEdgeFilterProperty",
&GraphInterface::GetEdgeFilterProperty)
.def("IsEdgeFilterActive", &GraphInterface::IsEdgeFilterActive)
.def("AddEdgeProperty", &GraphInterface::AddEdgeProperty)
.def("AddVertexProperty", &GraphInterface::AddVertexProperty)
.def("AddGraphProperty", &GraphInterface::AddGraphProperty)
.def("RemoveEdgeProperty", &GraphInterface::RemoveEdgeProperty)
.def("RemoveVertexProperty", &GraphInterface::RemoveVertexProperty)
.def("RemoveGraphProperty", &GraphInterface::RemoveGraphProperty)
.def("PurgeVertices", &GraphInterface::PurgeVertices)
.def("PurgeEdges", &GraphInterface::PurgeEdges)
.def("ReIndexEdges", &GraphInterface::ReIndexEdges)
.def("InsertEdgeIndexProperty",
&GraphInterface::InsertEdgeIndexProperty)
.def("InsertVertexIndexProperty",
&GraphInterface::InsertVertexIndexProperty)
.def("ShiftVertexProperty", &GraphInterface::ShiftVertexProperty)
.def("WriteToFile", &GraphInterface::WriteToFile)
.def("ReadFromFile",&GraphInterface::ReadFromFile)
.def("Vertices", &GraphInterface::Vertices)
......@@ -326,19 +313,19 @@ BOOST_PYTHON_MODULE(libgraph_tool_core)
.def("RemoveVertex", &GraphInterface::RemoveVertex)
.def("RemoveEdge", &GraphInterface::RemoveEdge)
.def("Clear", &GraphInterface::Clear)
.def("GetVertexProperties", &GraphInterface::GetVertexProperties)
.def("GetEdgeProperties", &GraphInterface::GetEdgeProperties)
.def("GetGraphProperties", &GraphInterface::GetGraphProperties)
.def("PutPropertyMap", &GraphInterface::PutPropertyMap)
.def("InitSignalHandling", &GraphInterface::InitSignalHandling);
.def("ClearEdges", &GraphInterface::ClearEdges)
.def("GetVertexIndex", &GraphInterface::GetVertexIndex)
.def("GetEdgeIndex", &GraphInterface::GetEdgeIndex)
.def("GetGraphIndex", &GraphInterface::GetGraphIndex)
.def("CopyVertexProperty", &GraphInterface::CopyVertexProperty)
.def("CopyEdgeProperty", &GraphInterface::CopyEdgeProperty);
enum_<GraphInterface::degree_t>("Degree")
.value("In", GraphInterface::IN_DEGREE)
.value("Out", GraphInterface::OUT_DEGREE)
.value("Total", GraphInterface::TOTAL_DEGREE);
variant_from_python<string>();
variant_from_python<boost::any>();
variant_from_python<GraphInterface::degree_t>();
to_python_converter<pair<string,bool>, pair_to_tuple<string,bool> >();
to_python_converter<pair<size_t,size_t>, pair_to_tuple<size_t,size_t> >();
......
......@@ -17,6 +17,8 @@
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
#include <boost/mpl/contains.hpp>
#include <boost/python/extract.hpp>
#include "graph.hh"
#include "graph_filtering.hh"
......@@ -64,43 +66,13 @@ struct graph_copy
}
};
struct copy_vertex_property
{
template <class GraphDst, class GraphSrc, class VertexProperty>
void operator()(GraphDst* dstp, GraphSrc* srcp,
VertexProperty dst_map,
boost::any src_property) const
{
GraphDst& dst = *dstp;
GraphSrc& src = *srcp;
VertexProperty src_map = any_cast<VertexProperty>(src_property);
typename graph_traits<GraphSrc>::vertex_iterator v, v_end;
size_t count = 0;
for (tie(v, v_end) = vertices(src); v != v_end; ++v)
{
dst_map[vertex(count,dst)] = src_map[*v];
++count;
}
}
};
struct copy_edge_property
{
template <class GraphSrc, class EdgeProperty>
void operator()(GraphSrc* srcp,
EdgeProperty dst_map,
boost::any src_property) const
{
GraphSrc& src = *srcp;
EdgeProperty src_map = any_cast<EdgeProperty>(src_property);
typename graph_traits<GraphSrc>::edge_iterator e, e_end;
for (tie(e, e_end) = edges(src); e != e_end; ++e)
{
put(dst_map, *e, get(src_map, *e));
}
}
};
typedef graph_tool::detail::get_all_graph_views
::apply<graph_tool::detail::scalar_pairs,
mpl::bool_<false>,
mpl::bool_<true>,
mpl::bool_<false>,
mpl::bool_<true>,
mpl::bool_<true> >::type graph_views;
// copy constructor
GraphInterface::GraphInterface(const GraphInterface& gi)
......@@ -117,52 +89,216 @@ GraphInterface::GraphInterface(const GraphInterface& gi)
_edge_filter_active(false)
{
typedef mpl::transform<detail::all_graph_views,
mpl::quote1<add_pointer> >::type graph_views;
mpl::quote1<add_pointer> >::type all_graph_views;
run_action<detail::never_filtered>()(*this, bind<void>(graph_copy(), _1, _2,
_vertex_index,
gi._vertex_index,
_edge_index,
gi._edge_index),
graph_views())(gi.GetGraphView());
run_action<graph_views>()(*this, bind<void>(graph_copy(), _1, _2,
_vertex_index,
gi._vertex_index,
_edge_index,
gi._edge_index),
all_graph_views())(gi.GetGraphView());
}
typedef property_map_types::apply<value_types, vertex_index_map_t,
mpl::bool_<false> >::type
vertex_properties;
//
// Property map copying
// ====================
typedef property_map_types::apply<value_types, edge_index_map_t,
mpl::bool_<false> >::type
edge_properties;
// handle type convertions
// generic types
template <class Type1, class Type2>
struct convert
{
Type1 operator()(const Type2& v) const
{
return do_convert(v, is_convertible<Type2,Type1>());
}
Type1 do_convert(const Type2& v, mpl::bool_<true>) const
{
return Type1(v);
}
for (typeof(gi._properties.begin()) iter = gi._properties.begin();
iter != gi._properties.end(); ++iter)
Type1 do_convert(const Type2& v, mpl::bool_<false>) const
{
string name = iter->first;
string type = get_type_name<>()(iter->second->value());
if (iter->second->key() == typeid(vertex_t))
return specific_convert<Type1,Type2>()(v);
}
template <class T1, class T2>
struct specific_convert
{
T1 operator()(const T2& v) const
{
AddVertexProperty(name, type);
run_action<detail::never_filtered>()
(*this, bind<void>(copy_vertex_property(), _1, _2, _3,
prop(name, gi._vertex_index,
gi._properties)),
graph_views(), vertex_properties())
(gi.GetGraphView(), prop(name, _vertex_index, _properties));
throw bad_lexical_cast(); // default action
}
else if (iter->second->key() == typeid(edge_t))
};
// specific specializations
// python::object
template <class T1>
struct specific_convert<T1,python::object>
{
T1 operator()(const python::object& v) const
{
AddEdgeProperty(name, type);
run_action<detail::never_filtered>()
(*this, bind<void>(copy_edge_property(), _1, _2,
prop(name, gi._edge_index, gi._properties)),
edge_properties())
(prop(name, _edge_index, _properties));
python::extract<Type1> x(v);
if (x.check())
return x();
else
throw bad_lexical_cast();
}
};
// string
template <class T1>
struct specific_convert<T1,string>
{
T1 operator()(const string& v) const
{
return lexical_cast<Type1>(v);
}
};
template <class T2>
struct specific_convert<string,T2>
{
string operator()(const T2& v) const
{
return lexical_cast<string>(v);
}
};
// vectors
template <class T1, class T2>
struct specific_convert<vector<T1>, vector<T2> >
{
vector<T1> operator()(const vector<T2>& v) const
{
vector<T1> v2(v.size());
convert<T1,T2> c;
for (size_t i = 0; i < v.size(); ++i)
v2[i] = c(v[i]);
return v2;
}
};
};
// python::object to string, to solve ambiguity
template<> template<>
struct convert<string,python::object>::specific_convert<string,python::object>
{
string operator()(const python::object& v) const
{
python::extract<string> x(v);
if (x.check())
return x();
else
throw bad_lexical_cast();
}
};
template <class IteratorSel>
struct copy_property
{
template <class Graph, class PropertySrc,
class PropertyTgt>
void operator()(Graph* tgtp, boost::any srcp, PropertySrc src_map,
PropertyTgt dst_map) const
{
typedef typename property_traits<PropertySrc>::value_type val_src;
typedef typename property_traits<PropertyTgt>::value_type val_tgt;
try
{
AddGraphProperty(name, type);
put(name, _properties, graph_property_tag(),
iter->second->get(graph_property_tag()));
Graph& tgt = *tgtp;
Graph& src = *any_cast<Graph*>(srcp);
convert<val_tgt,val_src> c;
typename IteratorSel::template apply<Graph>::type vs, vs_end;
typename IteratorSel::template apply<Graph>::type vt, vt_end;
tie(vt, vt_end) = IteratorSel::range(tgt);
for (tie(vs, vs_end) = IteratorSel::range(src); vs != vs_end; ++vs)
{