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

* added "--list-properties" option

* added support for specifying property type when creating/editing properties
* added initial support for graph properties (are loaded, listed, and saved)


git-svn-id: https://svn.forked.de/graph-tool/trunk@81 d4600afd-f417-0410-95de-beed9576f240
parent 74030f01
......@@ -94,8 +94,8 @@ class mutate_graph_impl : public mutate_graph
bool type_found = false;
try
{
mpl::for_each<value_types>(put_property<MutableGraph,value_types>
(name, m_dp, m_g, value, value_type, m_type_names, type_found));
mpl::for_each<value_types>(put_property<graph_property_tag,value_types>
(name, m_dp, graph_property_tag(), value, value_type, m_type_names, type_found));
}
catch (bad_lexical_cast)
{
......@@ -245,8 +245,8 @@ write_graphml(std::ostream& out, const Graph& g, VertexIndexMap vertex_index,
for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end(); ++i)
{
std::string key_id = "key" + lexical_cast<std::string>(key_count++);
if (i->second->key() == typeid(Graph))
vertex_key_ids[i->first] = key_id;
if (i->second->key() == typeid(graph_property_tag))
graph_key_ids[i->first] = key_id;
else if (i->second->key() == typeid(vertex_descriptor))
vertex_key_ids[i->first] = key_id;
else if (i->second->key() == typeid(edge_descriptor))
......@@ -256,7 +256,7 @@ write_graphml(std::ostream& out, const Graph& g, VertexIndexMap vertex_index,
std::string type_name = "string";
mpl::for_each<value_types>(get_type_name<value_types>(i->second->value(), type_names, type_name));
out << " <key id=\"" << key_id << "\" for=\""
<< (i->second->key() == typeid(Graph) ? "graph" : (i->second->key() == typeid(vertex_descriptor) ? "node" : "edge")) << "\""
<< (i->second->key() == typeid(graph_property_tag) ? "graph" : (i->second->key() == typeid(vertex_descriptor) ? "node" : "edge")) << "\""
<< " attr.name=\"" << i->first << "\""
<< " attr.type=\"" << type_name << "\""
<< " />\n";
......@@ -270,10 +270,10 @@ write_graphml(std::ostream& out, const Graph& g, VertexIndexMap vertex_index,
// Output graph data
for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end(); ++i)
{
if (i->second->key() == typeid(Graph))
if (i->second->key() == typeid(graph_property_tag))
{
out << " <data key=\"" << graph_key_ids[i->first] << "\">"
<< i->second->get_string(g) << "</data>\n";
<< i->second->get_string(graph_property_tag()) << "</data>\n";
}
}
......
......@@ -34,16 +34,7 @@ import string
import time
import signal
from time import *
from math import *
try:
from scipy import *
from scipy.special import *
from scipy.optimize import *
from scipy.optimize.minpack import *
except ImportError:
pass
#import gc # garbage collector
#gc.enable()
......@@ -91,12 +82,13 @@ 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("--edit-vertex-property", action="callback", callback=push_option, type="string", metavar="PROPERTY[|TYPE]|EXPRESSION", help="edit the selected vertex property")
modification.add_option("--edit-edge-property", action="callback", callback=push_option, type="string", metavar="PROPERTY[|TYPE]|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")
modification.add_option("--insert-edge-index-property", action="callback", callback=push_option, type="string", metavar="PROPERTY", help="insert edge index as property")
modification.add_option("--list-properties", action="callback", callback=push_option, help="list all properties")
statistics = parser.add_option_group("Basic Statistics")
statistics.add_option("--number-of-vertices", action="callback", callback=push_option, type="string", metavar="FILE", help="get the number of vertices")
......@@ -211,7 +203,7 @@ def generate_graph(parameters):
pjk = "1.0"
pjk_ceil = "pjk(j,k)"
m_pjk = "1.0"
inv_pjk_ceil = ""
inv_pjk_ceil = "(inv_poisson(p,2), inv_poisson(p,2))"
corr = "1.0"
corr_ceil = "corr(jl,kl,j,k)"
m_corr = "1.0"
......@@ -245,8 +237,14 @@ def generate_graph(parameters):
raise OptionError(opt.name, e)
# some predefined functions
variables = globals()
try:
from scipy.special import gammaincc
from scipy.optimize import fsolve
except ImportError:
pass
variables = globals()
def inv_poisson(p,m):
return round(fsolve(lambda k,l: gammaincc(k,l)-p, m, (m))-0.5+1e-15)
variables["inv_poisson"] = inv_poisson
......@@ -277,7 +275,7 @@ def generate_graph(parameters):
m_pjk = float(m_pjk)
variables["m_pjk"] = m_pjk
if "file:" in inv_pjk_ceil:
exec open(inv_pjk_ceil.replace("file:","").strip()).read() in variables
else:
......@@ -762,13 +760,19 @@ def parse_option(opt, just_file=False):
graph.SetReversed(not graph.GetReversed())
elif opt.name == "edit-vertex-property" or opt.name == "edit-edge-property":
values = parse_values(opt.value)
if len(values) != 2:
if len(values) < 2 or len(values) > 3:
raise OptionError(opt.name, "invalid value '%s'" % opt.value)
if just_file:
return None
if len(values) == 2:
val_type = "double"
expr = values[1]
else:
val_type = values[1].strip()
expr = values[2]
edit_vars = dict()
if "file:" in values[1]:
expressions = values[1].split("file:")
if "file:" in expr:
expressions = expr.split("file:")
if len(expressions) > 1:
exec expressions[0] in edit_vars
exec open(expressions[1].strip()).read() in edit_vars
......@@ -777,11 +781,11 @@ def parse_option(opt, just_file=False):
edit_function = edit_vars["edit_function"]
else:
def edit_function():
return (eval(values[1],edit_vars))
return (eval(expr,edit_vars))
if opt.name == "edit-vertex-property":
graph.EditVertexProperty(values[0],(edit_function,edit_vars))
graph.EditVertexProperty(values[0], val_type, (edit_function,edit_vars))
else:
graph.EditEdgeProperty(values[0],(edit_function,edit_vars))
graph.EditEdgeProperty(values[0], val_type, (edit_function,edit_vars))
elif opt.name == "remove-vertex-property":
if just_file:
return None
......@@ -798,6 +802,10 @@ def parse_option(opt, just_file=False):
if just_file:
return None
graph.InsertVertexIndexProperty(opt.value)
elif opt.name == "list-properties":
if just_file:
return None
graph.ListProperties()
def open_file(name, mode="w"):
if name == "-":
......
......@@ -137,8 +137,9 @@ 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 EditVertexProperty(std::string property, std::string type, boost::python::object op);
void EditEdgeProperty(std::string property, std::string type, boost::python::object op);
void ListProperties() const;
// layout
void ComputeGraphLayoutGursoy(size_t iter = 0, size_t seed = 4357);
......
......@@ -262,6 +262,7 @@ BOOST_PYTHON_MODULE(libgraph_tool)
.def("EditVertexProperty", &GraphInterfaceWrap::EditVertexProperty)
.def("RemoveEdgeProperty", &GraphInterfaceWrap::RemoveEdgeProperty)
.def("RemoveVertexProperty", &GraphInterfaceWrap::RemoveVertexProperty)
.def("ListProperties", &GraphInterfaceWrap::ListProperties)
.def("InsertEdgeIndexProperty", &GraphInterfaceWrap::InsertEdgeIndexProperty)
.def("InsertVertexIndexProperty", &GraphInterfaceWrap::InsertVertexIndexProperty)
.def("ComputeGraphLayoutGursoy", &GraphInterfaceWrap::ComputeGraphLayoutGursoy)
......
......@@ -84,7 +84,15 @@ struct create_dynamic_map
}
catch (bad_any_cast)
{
mpl::for_each<value_types>(check_value_type<EdgeIndexMap>(_edge_map, any_cast<edge_t>(key), value, map));
try
{
mpl::for_each<value_types>(check_value_type<EdgeIndexMap>(_edge_map, any_cast<edge_t>(key), value, map));
}
catch (bad_any_cast)
{
ConstantPropertyMap<size_t,graph_property_tag> graph_index(0);
mpl::for_each<value_types>(check_value_type<ConstantPropertyMap<size_t,graph_property_tag> >(graph_index, any_cast<graph_property_tag>(key), value, map));
}
}
return auto_ptr<dynamic_property_map>(map);
}
......@@ -236,6 +244,7 @@ void GraphInterface::ReadFromFile(string file, string format)
else
read_graphml(stream, ug, dp);
}
_properties = dp;
}
catch (ios_base::failure &e)
......
......@@ -25,6 +25,10 @@
#include "graph_selectors.hh"
#include "graph_properties.hh"
#include <boost/mpl/for_each.hpp>
#include <iostream>
#include <iomanip>
using namespace std;
using namespace boost;
using namespace boost::lambda;
......@@ -137,52 +141,134 @@ struct edit_property
put(prop_map, e, val);
}
}
};
//==============================================================================
// update_property_map()
//==============================================================================
template <class ValueTypes, class Descriptor, class IndexMap>
class update_property_map
{
public:
update_property_map(GraphInterface& gi, dynamic_properties& dp, IndexMap index_map, string property, string type, char* types[], python::object op)
: _gi(gi), _dp(dp), _index_map(index_map), _property(property), _type(type), _types(types), _op(op) {}
template <class ValueType>
void operator()(ValueType)
{
if (_type == _types[mpl::find<ValueTypes,ValueType>::type::pos::value])
{
try
{
dynamic_property_map& dpmap = find_property_map(_dp, _property, typeid(Descriptor));
typedef DynamicPropertyMapWrap<ValueType,Descriptor> prop_map_t;
prop_map_t prop_map(dpmap);
check_filter(_gi, bind<void>(edit_property<Descriptor>(), _1, var(_dp), prop_map, var(_op)),
reverse_check(), directed_check());
}
catch (property_not_found)
{
typedef vector_property_map<ValueType, IndexMap> prop_map_t;
prop_map_t prop_map(_index_map);
check_filter(_gi, bind<void>(edit_property<Descriptor>(), _1, var(_dp), prop_map, var(_op)),
reverse_check(), directed_check());
_dp.property(_property, prop_map);
}
}
}
private:
GraphInterface& _gi;
dynamic_properties& _dp;
IndexMap _index_map;
string _property;
string _type;
char** _types;
python::object _op;
};
//==============================================================================
// EditVertexProperty()
//==============================================================================
void GraphInterface::EditVertexProperty(string property, python::object op)
void GraphInterface::EditVertexProperty(string property, string type, python::object op)
{
typedef mpl::vector<bool, int, long, float, double, std::string> value_types;
char* type_names[] = {"boolean", "int", "long", "float", "double", "string"};
bool valid = false;
for(int i = 0; i < mpl::size<value_types>::type::value; ++i)
if (type == type_names[i])
valid = true;
if (!valid)
throw GraphException("invalid type: " + type);
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);
}
mpl::for_each<value_types>(update_property_map<value_types,vertex_descriptor,vertex_index_map_t>(*this, _properties, _vertex_index, property, type, type_names, op));
}
void GraphInterface::EditEdgeProperty(string property, python::object op)
//==============================================================================
// EditEdgeProperty()
//==============================================================================
void GraphInterface::EditEdgeProperty(string property, string type, python::object op)
{
typedef mpl::vector<bool, int, long, float, double, std::string> value_types;
char* type_names[] = {"boolean", "int", "long", "float", "double", "string"};
bool valid = false;
for(int i = 0; i < mpl::size<value_types>::type::value; ++i)
if (type == type_names[i])
valid = true;
if (!valid)
throw GraphException("invalid type: " + type);
typedef graph_traits<multigraph_t>::edge_descriptor edge_descriptor;
try
mpl::for_each<value_types>(update_property_map<value_types,edge_descriptor,edge_index_map_t>(*this, _properties, _edge_index, property, type, type_names, op));
}
//==============================================================================
// ListProperties()
//==============================================================================
template <class ValueTypes>
class print_name
{
public:
print_name(const type_info& type, char* types[]): _type(type), _types(types) {}
template <class ValueType>
void operator()(ValueType)
{
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());
if (_type == typeid(ValueType))
cout << _types[mpl::find<ValueTypes,ValueType>::type::pos::value];
}
catch (property_not_found)
private:
const type_info& _type;
char** _types;
};
void GraphInterface::ListProperties() const
{
typedef mpl::vector<bool, int, long, float, double, std::string> value_types;
char* type_names[] = {"boolean", "int", "long", "float", "double", "string"};
for (typeof(_properties.begin()) p = _properties.begin(); p != _properties.end(); ++p)
{
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);
cout << setw(15) << left << p->first << " " << setw(8) << left;
if (p->second->key() == typeid(graph_traits<multigraph_t>::vertex_descriptor))
cout << "(vertex)";
else
if (p->second->key() == typeid(graph_traits<multigraph_t>::edge_descriptor))
cout << "(edge)";
else
cout << "(graph)";
cout << " type: ";
mpl::for_each<value_types>(print_name<value_types>(p->second->value(), type_names));
cout << endl;
}
}
......@@ -298,7 +298,7 @@ public:
typedef Value value_type;
typedef value_type& reference;
typedef Key key_type;
typedef boost::read_write_property_map_tag category;
typedef boost::readable_property_map_tag category;
ConstantPropertyMap(value_type c): _c(c) {}
ConstantPropertyMap(){}
......
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