Commit aaaa4bb7 authored by Tiago Peixoto's avatar Tiago Peixoto

* generalized GetCombinedDegreeHistogram() into GetCombinedVertexHistogram()

* removed GetVectorScalarCorrelation(), since it is substituted by the above
* changed range filter policy: if property is non-double, use generic python filtering instead


git-svn-id: https://svn.forked.de/graph-tool/trunk@18 d4600afd-f417-0410-95de-beed9576f240
parent 53c936d8
......@@ -91,7 +91,7 @@ statistics.add_option("--number-of-vertices", action="callback", callback=push_o
statistics.add_option("--number-of-edges", action="callback", callback=push_option, type="string", metavar="FILE", help="get the number of edges")
statistics.add_option("--vertex-histogram", action="callback", callback=push_option, type="string", metavar="DEGREE|FILE", help="get the vertex degree/property histogram")
statistics.add_option("--edge-histogram", action="callback", callback=push_option, type="string", metavar="PROPERTY|FILE", help="get the edge property histogram")
statistics.add_option("--combined-degree-histogram", action="callback", callback=push_option, type="string", metavar="FILE", help="get the combined (in,out)-degree histogram")
statistics.add_option("--combined-vertex-histogram", action="callback", callback=push_option, type="string", metavar="DEGREE1|DEGREE2|FILE", help="get the combined (DEGREE1,DEGREE2) histogram. Scalar properties are also accepted as DEGREE1 or DEGREE2")
statistics.add_option("--average-distance", action="callback", callback=push_option, type="string", metavar="[WEIGHT|]FILE", help="get the averarge distance")
statistics.add_option("--average-harmonic-distance", action="callback", callback=push_option, type="string", metavar="[WEIGHT|]FILE", help="get the averarge harmonic distance")
statistics.add_option("--component-size-histogram", action="callback", callback=push_option, type="string", metavar="FILE", help="get the component size histogram")
......@@ -103,7 +103,6 @@ correlations = parser.add_option_group("Correlations")
correlations.add_option("--vertex-correlation-histogram", action="callback", callback=push_option, type="string", metavar="DEGREE1|DEGREE2|FILE", help="get the degree correlation histogram. Scalar properties are also accepted in place of DEGREE")
correlations.add_option("--average-nearest-neighbours-correlation", action="callback", callback=push_option, type="string", metavar="ORIGIN-DEGREE|DEGREE|FILE", help="get the average nearest neighbours correlation")
correlations.add_option("--edge-vertex-correlation-histogram", action="callback", callback=push_option, type="string", metavar="DEGREE1|EDGE-PROP|DEGREE2|FILE", help="get the source degree vs. edge scalar vs. target degree correlation histogram. Scalar properties are also accepted in place of DEGREE-TYPE")
correlations.add_option("--vertex-scalar-correlation-histogram", action="callback", callback=push_option, type="string", metavar="DEGREE|VERTEX-PROP|FILE", help="get the degree vs. vertex scalar correlation histogram. Scalar properties are also accepted in place of DEGREE")
correlations.add_option("--assortativity-coefficient", action="callback", callback=push_option, type="string", metavar="DEGREE|FILE", help="get the assortativity coefficient. Scalar properties are also accepted in place of DEGREE")
correlations.add_option("--scalar-assortativity-coefficient", action="callback", callback=push_option, type="string", metavar="DEGREE|FILE", help="get the scalar assortativity coefficient. Scalar properties are also accepted in place of DEGREE")
......@@ -241,10 +240,13 @@ def parse_option(opt, just_file=False):
if just_file:
return opt.value
return (graph.GetNumberOfEdges(), opt.value)
elif opt.name == "combined-degree-histogram":
elif opt.name == "combined-vertex-histogram":
values = parse_values(opt.value)
if len(values) != 3:
raise OptionError(opt.name, "invalid value '%s'" % opt.value)
if just_file:
return opt.value
return (graph.GetCombinedDegreeHistogram(), opt.value)
return values[2]
return (graph.GetCombinedVertexHistogram(degree(values[0]),degree(values[1])), values[2])
elif opt.name == "average-distance":
values = parse_values(opt.value)
if len(values) > 2 or len(values) < 1:
......@@ -304,14 +306,6 @@ def parse_option(opt, just_file=False):
if just_file:
return values[3]
return (graph.GetEdgeVertexCorrelationHistogram(deg1,values[1],deg2), values[3])
elif opt.name == "vertex-scalar-correlation-histogram":
values = parse_values(opt.value)
if len(values) != 3:
raise OptionError(opt.name, "invalid value '%s'" % opt.value)
deg = degree(values[0])
if just_file:
return values[2]
return (graph.GetVertexDegreeScalarCorrelationHistogram(deg,values[1]),values[2])
elif opt.name == "average-nearest-neighbours-correlation":
values = parse_values(opt.value)
if len(values) != 3:
......
......@@ -28,6 +28,7 @@
#include <boost/graph/fruchterman_reingold.hpp>
#include <boost/graph/random_layout.hpp>
#include <boost/random.hpp>
#include <boost/python/make_function.hpp>
#include <unistd.h> /* standard unix functions, like getpid() */
#include <sys/types.h> /* various type definitions, like pid_t */
......@@ -71,9 +72,7 @@ GraphInterface::GraphInterface()
_directed(true),
_vertex_index(get(vertex_index,_mg)),
_edge_index(get(edge_index_t(),_mg)),
_vertex_filter_map(_vertex_index),
_vertex_range(make_pair(numeric_limits<double>::min(), numeric_limits<double>::max())),
_edge_filter_map(_edge_index),
_edge_range(make_pair(numeric_limits<double>::min(), numeric_limits<double>::max()))
{
......@@ -90,109 +89,62 @@ GraphInterface::~GraphInterface()
// SetVertexFilter()
//==============================================================================
void GraphInterface::SetVertexFilterProperty(string property)
python::object python_range_filter(python::object properties, string filter_property, pair<double,double> range)
{
if (property == "")
{
_vertex_filter_property = property;
return;
}
try
{
_vertex_filter_map = get_static_property_map<vertex_filter_map_t>
(find_property_map(_properties, property, typeid(double)));
_vertex_filter_property = property;
return;
}
catch (bad_cast) {}
catch (property_not_found) {}
typedef graph_traits<multigraph_t>::vertex_descriptor vertex_t;
bool found = false;
for(typeof(_properties.begin()) iter = _properties.begin(); iter != _properties.end(); ++iter)
if (iter->first == property && iter->second->key() == typeid(vertex_t))
found = true;
bool accept = true;
if (python::extract<double>(properties[filter_property]) < range.first || python::extract<double>(properties[filter_property]) > range.second)
accept = false;
return python::object(accept);
}
if (!found)
throw GraphException("property " + property + " not found");
void GraphInterface::SetVertexFilterProperty(string property)
{
_vertex_filter_property = property;
// copy from (possibly) existent non-double property map
try
if (property != "")
{
graph_traits<multigraph_t>::vertex_iterator v, v_end;
for(tie(v, v_end) = vertices(_mg); v != v_end; ++v)
_vertex_filter_map[*v] = lexical_cast<double> (get(property, _properties, *v));
}
catch (dynamic_get_failure)
{
throw GraphException("property " + property + " not found"); // not convertible to double
}
// substitute filter property in property list
for(typeof(_properties.begin()) iter = _properties.begin(); iter != _properties.end(); ++iter)
if (iter->first == property && iter->second->key() == typeid(vertex_t))
try
{
delete iter->second;
iter->second = new boost::detail::dynamic_property_map_adaptor<vertex_filter_map_t>(_vertex_filter_map);
break;
_vertex_filter_map = get_static_property_map<vertex_filter_map_t>(find_property_map(_properties, property,
typeid(graph_traits<multigraph_t>::vertex_descriptor)));
}
_vertex_filter_property = property;
catch (bad_cast)
{
// set generic vertex filter instead
function<python::object(python::object)> filter = bind<python::object>(python_range_filter, _1, property, _vertex_range);
SetGenericVertexFilter(python::make_function(filter, python::default_call_policies(), mpl::vector<python::object,python::object>::type()));
}
catch (property_not_found)
{
throw GraphException("property " + property + " not found");
}
}
}
bool GraphInterface::IsVertexFilterActive() const { return _vertex_filter_property != "" || _vertex_python_filter != python::object(); }
void GraphInterface::SetEdgeFilterProperty(string property)
{
if (property == "")
{
_edge_filter_property = property;
return;
}
try
{
_edge_filter_map = get_static_property_map<edge_filter_map_t>
(find_property_map(_properties, property, typeid(double)));
_edge_filter_property = property;
return;
}
catch (bad_cast) {}
catch (property_not_found) {}
typedef graph_traits<multigraph_t>::edge_descriptor edge_t;
bool found = false;
for(typeof(_properties.begin()) iter = _properties.begin(); iter != _properties.end(); ++iter)
if (iter->first == property && iter->second->key() == typeid(edge_t))
found = true;
if (!found)
throw GraphException("property " + property + " not found");
_edge_filter_property = property;
// copy from (possibly) existent non-double property map
try
{
graph_traits<multigraph_t>::edge_iterator e, e_end;
for(tie(e, e_end) = edges(_mg); e != e_end; ++e)
_edge_filter_map[*e] = lexical_cast<double>(get(property, _properties, *e));
}
catch (dynamic_get_failure)
if (property != "")
{
throw GraphException("property " + property + " not found"); // not conversible to double
}
// substitute filter property in property list
for(typeof(_properties.begin()) iter = _properties.begin(); iter != _properties.end(); ++iter)
if (iter->first == property && iter->second->key() == typeid(edge_t))
try
{
delete iter->second;
iter->second = new boost::detail::dynamic_property_map_adaptor<edge_filter_map_t>(_edge_filter_map);
break;
_edge_filter_map = get_static_property_map<edge_filter_map_t>(find_property_map(_properties, property,
typeid(graph_traits<multigraph_t>::edge_descriptor)));
}
_edge_filter_property = property;
catch (bad_cast)
{
// set generic edge filter instead
function<python::object(python::object)> filter = bind<python::object>(python_range_filter, _1, property, _edge_range);
SetGenericEdgeFilter(python::make_function(filter, python::default_call_policies(), mpl::vector<python::object,python::object>::type()));
}
catch (property_not_found)
{
throw GraphException("property " + property + " not found");
}
}
}
bool GraphInterface::IsEdgeFilterActive() const {return _edge_filter_property != "" || _edge_python_filter != python::object();}
......
......@@ -73,10 +73,9 @@ public:
hist_t GetEdgeHistogram(std::string property) const;
//correlations
hist2d_t GetCombinedDegreeHistogram() const;
hist2d_t GetCombinedVertexHistogram(deg_t degree1, deg_t degree2) const;
hist2d_t GetVertexCorrelationHistogram(deg_t degree1, deg_t degree2) const;
hist3d_t GetEdgeVertexCorrelationHistogram(deg_t deg1, std::string scalar, deg_t deg2) const;
hist2d_t GetVertexScalarCorrelationHistogram(deg_t deg, std::string scalar) const;
avg_corr_t GetAverageNearestNeighboursCorrelation(deg_t origin_degree, deg_t neighbour_degree) const;
// mixing
......
......@@ -216,10 +216,9 @@ BOOST_PYTHON_MODULE(libgraph_tool)
.def("GetVertexHistogram", &GraphInterfaceWrap::GetVertexHistogram)
.def("GetEdgeHistogram", &GraphInterfaceWrap::GetEdgeHistogram)
.def("GetComponentSizeHistogram", &GraphInterfaceWrap::GetComponentSizeHistogram)
.def("GetCombinedDegreeHistogram", &GraphInterfaceWrap::GetCombinedDegreeHistogram)
.def("GetCombinedVertexHistogram", &GraphInterfaceWrap::GetCombinedVertexHistogram)
.def("GetVertexCorrelationHistogram", &GraphInterfaceWrap::GetVertexCorrelationHistogram)
.def("GetEdgeVertexCorrelationHistogram", &GraphInterfaceWrap::GetEdgeVertexCorrelationHistogram)
.def("GetVertexScalarCorrelationHistogram", &GraphInterfaceWrap::GetVertexScalarCorrelationHistogram)
.def("GetAverageNearestNeighboursCorrelation", &GraphInterfaceWrap::GetAverageNearestNeighboursCorrelation)
.def("GetAssortativityCoefficient", &GraphInterfaceWrap::GetAssortativityCoefficient)
.def("GetScalarAssortativityCoefficient", &GraphInterfaceWrap::GetScalarAssortativityCoefficient)
......
......@@ -34,11 +34,15 @@ using namespace boost::lambda;
using namespace graph_tool;
//==============================================================================
// GetCombinedDegreeHistogram()
// retrieves the distribution of combined (in,out) degrees
// GetCombinedVertexHistogram()
// retrieves the distribution of combined (deg1,deg2) degrees
//==============================================================================
template <class DegreeSelector1, class DegreeSelector2>
struct get_combined_degree_histogram
{
get_combined_degree_histogram(DegreeSelector1& deg1, DegreeSelector2& deg2): _deg1(deg1), _deg2(deg2) {}
template <class Graph, class Hist>
void operator()(Graph &g, Hist &hist) const
{
......@@ -48,17 +52,69 @@ struct get_combined_degree_histogram
typename graph_traits<Graph>::vertex_iterator v, v_begin, v_end;
tie(v_begin, v_end) = vertices(g);
for(v = v_begin; v != v_end; ++v)
hist[make_pair(first_type(in_degree(*v,g)),second_type(out_degree(*v,g)))]++;
hist[make_pair(first_type(_deg1(*v,g)), second_type(_deg2(*v,g)))]++;
}
DegreeSelector1& _deg1;
DegreeSelector2& _deg2;
};
template <class SecondDegreeSelectors>
struct choose_combined_degree_histogram
{
choose_combined_degree_histogram(const GraphInterface &g, GraphInterface::deg_t deg1,
GraphInterface::deg_t deg2, GraphInterface::hist2d_t &hist)
: _g(g), _hist(hist)
{
tie(_deg1, _deg_name1) = get_degree_type(deg1);
tie(_deg2, _deg_name2) = get_degree_type(deg2);
}
template <class DegreeSelector1>
struct check_second_degree
{
check_second_degree(choose_combined_degree_histogram<SecondDegreeSelectors> &parent):_parent(parent) {}
template <class DegreeSelector2>
void operator()(DegreeSelector2)
{
if (mpl::at<degree_selector_index,DegreeSelector2>::type::value == _parent._deg2)
{
DegreeSelector1 deg1(_parent._deg_name1, _parent._g);
DegreeSelector2 deg2(_parent._deg_name2, _parent._g);
check_filter(_parent._g, bind<void>(get_combined_degree_histogram<DegreeSelector1,DegreeSelector2>(deg1,deg2), _1, var(_parent._hist)),
reverse_check(),directed_check());
}
}
choose_combined_degree_histogram<SecondDegreeSelectors> _parent;
};
template <class DegreeSelector>
void operator()(DegreeSelector)
{
if (mpl::at<degree_selector_index,DegreeSelector>::type::value == _deg1)
mpl::for_each<SecondDegreeSelectors>(check_second_degree<DegreeSelector>(*this));
}
const GraphInterface &_g;
GraphInterface::hist2d_t &_hist;
GraphInterface::degree_t _deg1;
string _deg_name1;
GraphInterface::degree_t _deg2;
string _deg_name2;
};
GraphInterface::hist2d_t
GraphInterface::GetCombinedDegreeHistogram() const
GraphInterface::GetCombinedVertexHistogram(deg_t deg1, deg_t deg2) const
{
if (!_directed)
throw GraphException("can't get combined degree histogram for undirected graph!");
hist2d_t hist;
check_filter(*this, bind<void>(get_combined_degree_histogram(), _1, var(hist)),reverse_check(),always_directed());
typedef mpl::vector<in_degreeS, out_degreeS, total_degreeS, scalarS> degree_selectors;
try
{
mpl::for_each<degree_selectors>(choose_combined_degree_histogram<degree_selectors>(*this, deg1, deg2, hist));
}
catch (dynamic_get_failure &e)
{
throw GraphException("error getting scalar property: " + string(e.what()));
}
return hist;
}
......@@ -262,80 +318,5 @@ GraphInterface::GetEdgeVertexCorrelationHistogram(GraphInterface::deg_t deg1, st
return hist;
}
//==============================================================================
// get_vertex_scalar_correlation_histogram
// retrieves the generalized vertex-scalar correlation histogram
//==============================================================================
template <class DegreeSelector>
struct get_vertex_scalar_correlation_histogram
{
get_vertex_scalar_correlation_histogram(DegreeSelector& deg, scalarS& scalar): _deg(deg), _scalar(scalar){}
template <class Graph, class Hist>
void operator()(Graph &g, Hist &hist) const
{
typename graph_traits<Graph>::vertex_iterator v, v_end;
for (tie(v,v_end) = vertices(g); v != v_end; ++v)
{
typename Hist::key_type key;
key.first = _deg(*v,g);
key.second = _scalar(*v,g);
hist[key]++;
}
}
DegreeSelector& _deg;
scalarS& _scalar;
};
//==============================================================================
// GetVertexScalarCorrelationHistogram(deg, scalar)
// retrieves the vertex-scalar correlation histogram
//==============================================================================
struct choose_vertex_scalar_correlation_histogram
{
choose_vertex_scalar_correlation_histogram(const GraphInterface& g, GraphInterface::deg_t deg, scalarS& scalar,
GraphInterface::hist2d_t& hist)
: _g(g), _scalar(scalar), _hist(hist)
{
tie(_deg, _deg_name) = get_degree_type(deg);
}
template <class DegreeSelector>
void operator()(DegreeSelector)
{
if (mpl::at<degree_selector_index,DegreeSelector>::type::value == _deg)
{
DegreeSelector deg(_deg_name, _g);
check_filter(_g, bind<void>(get_vertex_scalar_correlation_histogram<DegreeSelector>(deg, _scalar),_1, var(_hist)),
reverse_check(),directed_check());
}
}
const GraphInterface &_g;
scalarS& _scalar;
GraphInterface::hist2d_t &_hist;
GraphInterface::degree_t _deg;
string _deg_name;
};
GraphInterface::hist2d_t GraphInterface::GetVertexScalarCorrelationHistogram(deg_t deg, string scalar) const
{
hist2d_t hist;
scalarS scalar_sel(scalar, *this);
try
{
typedef mpl::vector<in_degreeS, out_degreeS, total_degreeS, scalarS> degree_selectors;
mpl::for_each<degree_selectors>(choose_vertex_scalar_correlation_histogram(*this, deg, scalar_sel, hist));
}
catch (dynamic_get_failure &e)
{
throw GraphException("error getting scalar property: " + string(e.what()));
}
return hist;
}
......@@ -143,20 +143,21 @@ public:
typedef Key key_type;
typedef boost::read_write_property_map_tag category;
DynamicPropertyMapWrap(boost::dynamic_property_map& dmap):_dmap(dmap) {}
// DynamicPropertyMapWrap(DynamicPropertyMapWrap& c):_dmap(c._dmap) {}
DynamicPropertyMapWrap(boost::dynamic_property_map& dmap):_dmap(&dmap) {}
DynamicPropertyMapWrap() {}
Value get(const Key& k) const
{
return get_converted_scalar_value<Value>(_dmap, k);
return get_converted_scalar_value<Value>(*_dmap, k);
}
void put(const Key& k, const Value& val)
{
_dmap.put(k, val);
_dmap->put(k, val);
}
private:
boost::dynamic_property_map& _dmap;
boost::dynamic_property_map* _dmap;
};
......@@ -168,7 +169,7 @@ namespace boost {
using namespace graph_tool;
template <class Value, class Key>
Value get(DynamicPropertyMapWrap<Value,Key> pmap, typename property_traits<DynamicPropertyMapWrap<Value,Key> >::key_type k)
Value get(const DynamicPropertyMapWrap<Value,Key>& pmap, typename property_traits<DynamicPropertyMapWrap<Value,Key> >::key_type k)
{
return pmap.get(k);
}
......
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