Commit 224bd568 authored by Tiago Peixoto's avatar Tiago Peixoto
Browse files

* add EditVertexProperty() and EditEdgeProperty()

* cleanup src/graph/graph_python_filtering.hh


git-svn-id: https://svn.forked.de/graph-tool/trunk@39 d4600afd-f417-0410-95de-beed9576f240
parent 1152b5ed
......@@ -85,6 +85,8 @@ filtering.add_option("--edge-range-filter", action="callback", callback=push_opt
filtering.add_option("--reset-edge-filter", action="callback", callback=push_option, help="remove edge filter")
modification = parser.add_option_group("Graph Modification")
modification.add_option("--edit-vertex-property", action="callback", callback=push_option, type="string", metavar="PROPERTY|EXPRESSION", help="edit the selected vertex property")
modification.add_option("--edit-edge-property", action="callback", callback=push_option, type="string", metavar="PROPERTY|EXPRESSION", help="edit the selected edge property")
modification.add_option("--remove-vertex-property", action="callback", callback=push_option, type="string", metavar="PROPERTY", help="remove vertex property from graph")
modification.add_option("--remove-edge-property", action="callback", callback=push_option, type="string", metavar="PROPERTY|RANGE", help="remove edge property from graph")
modification.add_option("--insert-vertex-index-property", action="callback", callback=push_option, type="string", metavar="PROPERTY", help="insert vertex index as property")
......@@ -586,6 +588,35 @@ def filter_function():
if just_file:
return None
graph.RemoveParallelEdges()
elif opt.name == "edit-vertex-property" or opt.name == "edit-edge-property":
values = parse_values(opt.value)
if len(values) != 2:
raise OptionError(opt.name, "invalid value '%s'" % opt.value)
if just_file:
return None
edit_vars = dict()
try:
exec """
try:
from math import *
from scipy import *
from scipy.special import *
from scipy.optimize import *
from scipy.optimize.minpack import *
import psyco
psyco.full()
except ImportError:
pass
def edit_function():
return %s
""" % values[1] in edit_vars
except:
raise OptionError(opt.name, "invalid value '%s': %s" % (opt.value,sys.exc_info()[0]))
if opt.name == "edit-vertex-property":
graph.EditVertexProperty(values[0],(edit_vars["edit_function"],edit_vars))
else:
graph.EditEdgeProperty(values[0],(edit_vars["edit_function"],edit_vars))
elif opt.name == "remove-vertex-property":
if just_file:
return None
......
......@@ -330,50 +330,6 @@ GraphInterface::hist_t GraphInterface::GetComponentSizeHistogram() const
return hist;
}
//==============================================================================
// RemoveVertexProperty(property)
//==============================================================================
void GraphInterface::RemoveVertexProperty(string property)
{
dynamic_properties_copy dp;
try
{
dynamic_property_map& prop_map = find_property_map(_properties, property, typeid(graph_traits<multigraph_t>::vertex_descriptor));
for (typeof(_properties.begin()) iter = _properties.begin(); iter != _properties.end(); ++iter)
{
if (iter->second != &prop_map)
dp.insert(iter->first, auto_ptr<dynamic_property_map>(iter->second));
}
}
catch (property_not_found)
{
throw GraphException("property '" + property + "' not found");
}
_properties = dp;
}
//==============================================================================
// RemoveEdgeProperty(property)
//==============================================================================
void GraphInterface::RemoveEdgeProperty(string property)
{
dynamic_properties_copy dp;
try
{
dynamic_property_map& prop_map = find_property_map(_properties, property, typeid(graph_traits<multigraph_t>::edge_descriptor));
for (typeof(_properties.begin()) iter = _properties.begin(); iter != _properties.end(); ++iter)
{
if (iter->second != &prop_map)
dp.insert(iter->first, auto_ptr<dynamic_property_map>(iter->second));
}
}
catch (property_not_found)
{
throw GraphException("property '" + property + "' not found");
}
_properties = dp;
}
//==============================================================================
// InsertEdgeIndexProperty(property)
//==============================================================================
......
......@@ -120,6 +120,8 @@ public:
void RemoveVertexProperty(std::string property);
void InsertEdgeIndexProperty(std::string property);
void InsertVertexIndexProperty(std::string property);
void EditVertexProperty(std::string property, boost::python::object op);
void EditEdgeProperty(std::string property, boost::python::object op);
void RemoveParallelEdges();
// layout
......
......@@ -244,6 +244,8 @@ BOOST_PYTHON_MODULE(libgraph_tool)
.def("GetEdgeFilterRange", &GraphInterfaceWrap::GetEdgeFilterRange)
.def("IsEdgeFilterActive", &GraphInterfaceWrap::IsEdgeFilterActive)
.def("SetGenericEdgeFilter", &GraphInterfaceWrap::SetGenericEdgeFilter)
.def("EditEdgeProperty", &GraphInterfaceWrap::EditEdgeProperty)
.def("EditVertexProperty", &GraphInterfaceWrap::EditVertexProperty)
.def("RemoveEdgeProperty", &GraphInterfaceWrap::RemoveEdgeProperty)
.def("RemoveVertexProperty", &GraphInterfaceWrap::RemoveVertexProperty)
.def("InsertEdgeIndexProperty", &GraphInterfaceWrap::InsertEdgeIndexProperty)
......
......@@ -189,8 +189,8 @@ struct check_directed
template <class Graph, class Action, class ReverseCheck, class DirectedCheck>
void check_python_filter(const Graph& g, const GraphInterface &gi, Action a, bool& found, ReverseCheck, DirectedCheck)
{
typedef PythonFilter<Graph,mpl::bool_<true> > vertex_filter_t;
typedef PythonFilter<Graph,mpl::bool_<false> > edge_filter_t;
typedef PythonFilter<Graph,typename graph_traits<Graph>::vertex_descriptor> vertex_filter_t;
typedef PythonFilter<Graph,typename graph_traits<Graph>::edge_descriptor> edge_filter_t;
if (gi._edge_python_filter != python::object())
{
......@@ -199,7 +199,7 @@ void check_python_filter(const Graph& g, const GraphInterface &gi, Action a, boo
if (gi._vertex_python_filter != python::object())
{
typedef PythonFilter<efg_t, mpl::bool_<true>, mpl::bool_<true> > vertex_filter_t;
typedef PythonFilter<efg_t, typename graph_traits<efg_t>::vertex_descriptor, mpl::bool_<true> > vertex_filter_t;
typedef filtered_graph<efg_t,keep_all,vertex_filter_t> vefg_t;
vefg_t vefg(efg,keep_all(),vertex_filter_t(efg, gi._properties, gi._vertex_python_filter));
mpl::for_each<DirectedCheck>(check_directed<vefg_t,Action,ReverseCheck>(vefg, a, gi._reversed, gi._directed, found));
......
......@@ -16,17 +16,172 @@
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include <boost/lambda/bind.hpp>
#include "graph.hh"
#include "histogram.hh"
#include "graph_filtering.hh"
#include "graph_selectors.hh"
#include "graph_properties.hh"
using namespace std;
using namespace boost;
using namespace boost::lambda;
using namespace graph_tool;
//==============================================================================
// find_property_map(dp,name,key_type)
//==============================================================================
boost::dynamic_property_map&
graph_tool::find_property_map(const boost::dynamic_properties& dp, std::string name, const std::type_info& key_type)
dynamic_property_map&
graph_tool::find_property_map(const dynamic_properties& dp, string name, const type_info& key_type)
{
for(typeof(dp.begin()) iter = dp.begin(); iter != dp.end(); ++iter)
if (iter->first == name && iter->second->key() == key_type)
return *iter->second;
throw boost::property_not_found(name);
throw property_not_found(name);
}
//==============================================================================
// RemoveVertexProperty(property)
//==============================================================================
void GraphInterface::RemoveVertexProperty(string property)
{
dynamic_properties_copy dp;
try
{
dynamic_property_map& prop_map = find_property_map(_properties, property, typeid(graph_traits<multigraph_t>::vertex_descriptor));
for (typeof(_properties.begin()) iter = _properties.begin(); iter != _properties.end(); ++iter)
{
if (iter->second != &prop_map)
dp.insert(iter->first, auto_ptr<dynamic_property_map>(iter->second));
}
}
catch (property_not_found)
{
throw GraphException("property '" + property + "' not found");
}
_properties = dp;
}
//==============================================================================
// RemoveEdgeProperty(property)
//==============================================================================
void GraphInterface::RemoveEdgeProperty(string property)
{
dynamic_properties_copy dp;
try
{
dynamic_property_map& prop_map = find_property_map(_properties, property, typeid(graph_traits<multigraph_t>::edge_descriptor));
for (typeof(_properties.begin()) iter = _properties.begin(); iter != _properties.end(); ++iter)
{
if (iter->second != &prop_map)
dp.insert(iter->first, auto_ptr<dynamic_property_map>(iter->second));
}
}
catch (property_not_found)
{
throw GraphException("property '" + property + "' not found");
}
_properties = dp;
}
//==============================================================================
// edit_property
//==============================================================================
template <class Descriptor>
struct edit_property
{
template <class Graph, class PropertyMap>
void operator()(const Graph& g, const dynamic_properties& dp, PropertyMap prop_map, python::object& op) const
{
typedef mpl::vector<in_degreeS,out_degreeS,total_degreeS> degrees;
python::object operation = op[0], variables = op[1];
typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
typedef typename mpl::if_<is_same<Descriptor,vertex_descriptor>,vertex_descriptor,edge_descriptor>::type descriptor_t;
descriptor_t u;
populate_python_funcs<descriptor_t>()(g, u, dp, variables);
put_properties(g, u, prop_map, operation);
}
template<class Graph, class PropertyMap>
void put_properties(const Graph& g, typename graph_traits<Graph>::vertex_descriptor& v,
PropertyMap prop_map, python::object& operation) const
{
typename graph_traits<Graph>::vertex_iterator vi,v_end;
for (tie(vi, v_end) = vertices(g); vi != v_end; ++vi)
{
v = *vi;
typename property_traits<PropertyMap>::value_type val = python::extract<typename property_traits<PropertyMap>::value_type>(operation());
put(prop_map, v, val);
}
}
template<class Graph, class PropertyMap>
void put_properties(const Graph& g, typename graph_traits<Graph>::edge_descriptor& e,
PropertyMap prop_map, python::object& operation) const
{
typename graph_traits<Graph>::edge_iterator ei,e_end;
for (tie(ei, e_end) = edges(g); ei != e_end; ++ei)
{
e = *ei;
typename property_traits<PropertyMap>::value_type val = python::extract<typename property_traits<PropertyMap>::value_type>(operation());
put(prop_map, e, val);
}
}
};
//==============================================================================
// EditVertexProperty()
//==============================================================================
void GraphInterface::EditVertexProperty(string property, python::object op)
{
typedef graph_traits<multigraph_t>::vertex_descriptor vertex_descriptor;
try
{
dynamic_property_map& dpmap = find_property_map(_properties, property, typeid(graph_traits<multigraph_t>::vertex_descriptor));
typedef DynamicPropertyMapWrap<double,vertex_descriptor> prop_map_t;
prop_map_t prop_map(dpmap);
check_filter(*this, bind<void>(edit_property<vertex_descriptor>(), _1, var(_properties), prop_map, var(op)),
reverse_check(), directed_check());
}
catch (property_not_found)
{
typedef vector_property_map<double, vertex_index_map_t> prop_map_t;
prop_map_t prop_map(_vertex_index);
check_filter(*this, bind<void>(edit_property<vertex_descriptor>(), _1, var(_properties), prop_map, var(op)),
reverse_check(), directed_check());
_properties.property(property, prop_map);
}
}
void GraphInterface::EditEdgeProperty(string property, python::object op)
{
typedef graph_traits<multigraph_t>::edge_descriptor edge_descriptor;
try
{
dynamic_property_map& dpmap = find_property_map(_properties, property, typeid(graph_traits<multigraph_t>::edge_descriptor));
typedef DynamicPropertyMapWrap<double,edge_descriptor> prop_map_t;
prop_map_t prop_map(dpmap);
check_filter(*this, bind<void>(edit_property<edge_descriptor>(), _1, var(_properties), prop_map, var(op)),
reverse_check(), directed_check());
}
catch (property_not_found)
{
typedef vector_property_map<double, edge_index_map_t> prop_map_t;
prop_map_t prop_map(_edge_index);
check_filter(*this, bind<void>(edit_property<edge_descriptor>(), _1, var(_properties), prop_map, var(op)),
reverse_check(), directed_check());
_properties.property(property, prop_map);
}
}
......@@ -39,60 +39,57 @@ namespace graph_tool
using namespace boost;
//==============================================================================
// PythonFilter
// populate_python_funcs
//==============================================================================
template <class Graph, class VertexFilter, class HasBase = mpl::bool_<false> >
class PythonFilter
{
public:
typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
typedef mpl::vector<in_degreeS,out_degreeS,total_degreeS> degrees;
PythonFilter(){}
PythonFilter(const Graph& g, const dynamic_properties& dp, python::object filter)
: _g(&g), _filter(filter[0])
template <class Descriptor, class HasBase = mpl::bool_<false> >
struct populate_python_funcs
{
template<class Graph>
void operator()(const Graph& g, Descriptor& u, const dynamic_properties& dp, python::object& variables)
{
python::object variables = filter[1];
for(typeof(dp.begin()) iter = dp.begin(); iter != dp.end(); ++iter)
{
if (iter->second->key() == typeid(vertex_descriptor) && VertexFilter::value)
variables[iter->first] = python::make_function(get_value<vertex_descriptor>(*iter->second, _v),
python::default_call_policies(), mpl::vector<python::object>::type());
if (iter->second->key() == typeid(edge_descriptor) && !VertexFilter::value)
variables[iter->first] = python::make_function(get_value<edge_descriptor>(*iter->second, _e),
if (iter->second->key() == typeid(Descriptor))
variables[iter->first] = python::make_function(get_value<Descriptor>(*iter->second, u),
python::default_call_policies(), mpl::vector<python::object>::type());
}
populate_specific(g, u, dp, variables);
}
if (VertexFilter::value)
{
mpl::for_each<degrees>(put_degree_function(*_g, _v, variables));
typedef mpl::vector<in_degreeS, out_degreeS, total_degreeS> degrees;
typedef typename mpl::if_<HasBase, degrees, mpl::vector<> >::type base_degrees;
mpl::for_each<base_degrees>(put_base_degree_function(*_g, _v, variables, "orig_"));
}
else
{
variables["is_loop"] = python::make_function(is_loop(*_g, _e), python::default_call_policies(), mpl::vector<python::object>::type());
template <class Graph>
void populate_specific(const Graph& g, typename graph_traits<Graph>::vertex_descriptor& v, const dynamic_properties& dp, python::object& variables)
{
mpl::for_each<degrees>(put_degree_function<Graph>(g, v, variables));
typedef typename mpl::if_<HasBase, degrees, mpl::vector<> >::type base_degrees;
mpl::for_each<base_degrees>(put_base_degree_function<Graph>(g, v, variables, "orig_"));
}
template <class Graph>
void populate_specific(const Graph& g, typename graph_traits<Graph>::edge_descriptor& e, const dynamic_properties& dp, python::object& variables)
{
typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
variables["is_loop"] = python::make_function(is_loop<Graph>(g, e), python::default_call_policies(), mpl::vector<python::object>::type());
for(typeof(dp.begin()) iter = dp.begin(); iter != dp.end(); ++iter)
for(typeof(dp.begin()) iter = dp.begin(); iter != dp.end(); ++iter)
{
if (iter->second->key() == typeid(vertex_descriptor))
{
if (iter->second->key() == typeid(vertex_descriptor))
{
variables["source_"+iter->first] = python::make_function(get_source_or_target_value<true>(*_g, *iter->second, _e),
python::default_call_policies(), mpl::vector<python::object>::type());
variables["target_"+iter->first] = python::make_function(get_source_or_target_value<false>(*_g, *iter->second, _e),
python::default_call_policies(), mpl::vector<python::object>::type());
}
variables["source_"+iter->first] = python::make_function(get_source_or_target_value<Graph,true>(g, *iter->second, e),
python::default_call_policies(), mpl::vector<python::object>::type());
variables["target_"+iter->first] = python::make_function(get_source_or_target_value<Graph,false>(g, *iter->second, e),
python::default_call_policies(), mpl::vector<python::object>::type());
}
mpl::for_each<degrees>(put_source_or_target_degree_function<true>(*_g, _e, variables, "source_"));
mpl::for_each<degrees>(put_source_or_target_degree_function<false>(*_g, _e, variables, "target_"));
}
mpl::for_each<degrees>(put_source_or_target_degree_function<Graph,true>(g, e, variables, "source_"));
mpl::for_each<degrees>(put_source_or_target_degree_function<Graph,false>(g, e, variables, "target_"));
}
template <class VertexOrEdge>
struct get_value
{
......@@ -127,9 +124,12 @@ public:
python::object _retval;
};
template <bool Source>
template <class Graph, bool Source>
struct get_source_or_target_value
{
typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
get_source_or_target_value(const Graph& g, dynamic_property_map& dmap, const edge_descriptor& e)
: _g(g),_dmap(dmap),_e(e){}
......@@ -151,10 +151,12 @@ public:
const edge_descriptor& _e;
};
template <class G, class Degree>
template <class Graph, class Degree>
struct get_degree
{
get_degree(const G& g, const vertex_descriptor& v)
typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
get_degree(const Graph& g, const vertex_descriptor& v)
: _g(g), _v(v) {}
python::object operator()()
......@@ -162,13 +164,16 @@ public:
return python::object(_degree(_v, _g));
}
const G& _g;
const Graph& _g;
const vertex_descriptor& _v;
Degree _degree;
};
template <class Graph>
struct put_degree_function
{
typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
put_degree_function(const Graph& g, const vertex_descriptor& v, python::object variables, std::string prefix = "")
: _g(g), _v(v), _variables(variables), _prefix(prefix) {}
template <class Degree>
......@@ -182,11 +187,14 @@ public:
python::object& _variables;
std::string _prefix;
};
struct put_base_degree_function: public put_degree_function
template <class Graph>
struct put_base_degree_function: public put_degree_function<Graph>
{
typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
put_base_degree_function(const Graph& g, const vertex_descriptor& v, python::object& variables, std::string prefix = "")
: put_degree_function(g, v, variables, prefix) {}
: put_degree_function<Graph>(g, v, variables, prefix) {}
template <class Degree>
void operator()(Degree degree)
......@@ -196,9 +204,12 @@ public:
}
};
template <bool Source>
template <class Graph, bool Source>
struct put_source_or_target_degree_function
{
typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
put_source_or_target_degree_function(const Graph& g, const edge_descriptor& e, python::object& variables, std::string prefix = "")
: _g(g), _e(e), _variables(variables), _prefix(prefix) {}
template <class Degree>
......@@ -209,7 +220,7 @@ public:
v = source(_e, this->_g);
else
v = target(_e, this->_g);
put_degree_function(_g, v, _variables, _prefix)(d);
put_degree_function<Graph>(_g, v, _variables, _prefix)(d);
}
const Graph& _g;
......@@ -218,8 +229,11 @@ public:
std::string _prefix;
};
template<class Graph>
struct is_loop
{
typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
is_loop(const Graph& g, const edge_descriptor& e): _g(g), _e(e) {}
python::object operator()()
{
......@@ -229,30 +243,45 @@ public:
const edge_descriptor& _e;
};
inline bool operator() (edge_descriptor e) const
{
_e = e;
return python::extract<bool>(_filter());
}
inline bool operator() (vertex_descriptor v) const
};
//==============================================================================
// PythonFilter
//==============================================================================
template <class Graph, class Descriptor, class HasBase = mpl::bool_<false> >
class PythonFilter
{
public:
typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
typedef mpl::vector<in_degreeS,out_degreeS,total_degreeS> degrees;
PythonFilter(){}
PythonFilter(const Graph& g, const dynamic_properties& dp, python::object filter)
: _g(&g), _filter(filter[0])
{
python::object variables = filter[1];
populate_python_funcs<Descriptor, HasBase>()(*_g, _u, dp, variables);
}
inline bool operator() (Descriptor u) const
{
_v = v;
_u = u;
return python::extract<bool>(_filter());
}
private:
Graph const* _g;
python::object _filter;
static vertex_descriptor _v;
static edge_descriptor _e;
static Descriptor _u;
};
template <class Graph, class VertexFilter, class HasBase>
typename PythonFilter<Graph,VertexFilter,HasBase>::vertex_descriptor PythonFilter<Graph,VertexFilter,HasBase>::_v;
template <class Graph, class VertexFilter, class HasBase>
typename PythonFilter<Graph,VertexFilter,HasBase>::edge_descriptor PythonFilter<Graph,VertexFilter,HasBase>::_e;
template <class Graph, class Descriptor, class HasBase>
Descriptor PythonFilter<Graph,Descriptor,HasBase>::_u;
} //graph_tool namespace
......
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