Commit 15f1ba1b authored by Tiago Peixoto's avatar Tiago Peixoto
Browse files

graphml: load vertex and edge ids as string properties, if not canonical

parent cf3440f4
...@@ -244,14 +244,14 @@ const char* mutate_graph_impl<MutableGraph>::m_type_names[] = ...@@ -244,14 +244,14 @@ const char* mutate_graph_impl<MutableGraph>::m_type_names[] =
"python_object"}; "python_object"};
void void
read_graphml(std::istream& in, mutate_graph& g); read_graphml(std::istream& in, mutate_graph& g, bool store_ids);
template<typename MutableGraph> template<typename MutableGraph>
void void
read_graphml(std::istream& in, MutableGraph& g, dynamic_properties& dp) read_graphml(std::istream& in, MutableGraph& g, dynamic_properties& dp, bool store_ids)
{ {
mutate_graph_impl<MutableGraph> mg(g,dp); mutate_graph_impl<MutableGraph> mg(g,dp);
read_graphml(in, mg); read_graphml(in, mg, store_ids);
} }
template <typename Types> template <typename Types>
...@@ -339,9 +339,24 @@ write_graphml(std::ostream& out, const Graph& g, VertexIndexMap vertex_index, ...@@ -339,9 +339,24 @@ write_graphml(std::ostream& out, const Graph& g, VertexIndexMap vertex_index,
out << " <!-- property keys -->\n"; out << " <!-- property keys -->\n";
bool has_vertex_ids = false;
bool has_edge_ids = false;
// Output keys // Output keys
for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end(); ++i) for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end(); ++i)
{ {
if (i->first == "_graphml_vertex_id")
{
has_vertex_ids = true;
continue;
}
if (i->first == "_graphml_edge_id")
{
has_edge_ids = true;
continue;
}
std::string key_id = "key" + lexical_cast<std::string>(key_count++); std::string key_id = "key" + lexical_cast<std::string>(key_count++);
if (i->second->key() == typeid(graph_property_tag)) if (i->second->key() == typeid(graph_property_tag))
graph_key_ids[i->first] = key_id; graph_key_ids[i->first] = key_id;
...@@ -364,11 +379,15 @@ write_graphml(std::ostream& out, const Graph& g, VertexIndexMap vertex_index, ...@@ -364,11 +379,15 @@ write_graphml(std::ostream& out, const Graph& g, VertexIndexMap vertex_index,
<< " />\n"; << " />\n";
} }
bool canonical_vertices = ordered_vertices && !has_vertex_ids;
bool canonical_edges = !has_edge_ids;
out << "\n <graph id=\"G\" edgedefault=\"" out << "\n <graph id=\"G\" edgedefault=\""
<< (graph_is_directed ? "directed" : "undirected") << "\"" << (graph_is_directed ? "directed" : "undirected") << "\""
<< " parse.nodeids=\"" << (ordered_vertices ? "canonical" : "free") << " parse.nodeids=\"" << (canonical_vertices ? "canonical" : "free")
<< "\"" << "\""
<< " parse.edgeids=\"canonical\" parse.order=\"nodesfirst\">\n\n"; << " parse.edgeids=\"" << (canonical_edges ? "canonical" : "free")
<< "\" parse.order=\"nodesfirst\">\n\n";
out << " <!-- graph properties -->\n"; out << " <!-- graph properties -->\n";
// Output graph data // Output graph data
...@@ -392,11 +411,20 @@ write_graphml(std::ostream& out, const Graph& g, VertexIndexMap vertex_index, ...@@ -392,11 +411,20 @@ write_graphml(std::ostream& out, const Graph& g, VertexIndexMap vertex_index,
vertex_iterator v, v_end; vertex_iterator v, v_end;
for (tie(v, v_end) = vertices(g); v != v_end; ++v) for (tie(v, v_end) = vertices(g); v != v_end; ++v)
{ {
out << " <node id=\"n" << get(vertex_index, *v) << "\">\n"; out << " <node id=\"";
if (has_vertex_ids)
out << protect_xml_string(get("_graphml_vertex_id", dp, *v));
else
out << "n" << get(vertex_index, *v);
out << "\">\n";
// Output data // Output data
for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end(); for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end();
++i) ++i)
{ {
if (i->first == "_graphml_vertex_id")
continue;
if (i->second->key() == typeid(vertex_descriptor)) if (i->second->key() == typeid(vertex_descriptor))
{ {
std::string val = protect_xml_string std::string val = protect_xml_string
...@@ -417,14 +445,34 @@ write_graphml(std::ostream& out, const Graph& g, VertexIndexMap vertex_index, ...@@ -417,14 +445,34 @@ write_graphml(std::ostream& out, const Graph& g, VertexIndexMap vertex_index,
typename graph_traits<Graph>::edges_size_type edge_count = 0; typename graph_traits<Graph>::edges_size_type edge_count = 0;
for (tie(e, e_end) = edges(g); e != e_end; ++e) for (tie(e, e_end) = edges(g); e != e_end; ++e)
{ {
out << " <edge id=\"e" << edge_count++ << "\" source=\"n" out << " <edge id=\"";
<< get(vertex_index, source(*e, g)) << "\" target=\"n" if (has_edge_ids)
<< get(vertex_index, target(*e, g)) << "\">\n"; out << protect_xml_string(get("_graphml_edge_id", dp, *e));
else
out << "e" << edge_count;
edge_count++;
out << "\" source=\"";
if (has_vertex_ids)
out << protect_xml_string(get("_graphml_vertex_id", dp,
source(*e, g)));
else
out << "n" << get(vertex_index, source(*e, g));
out << "\" target=\"";
if (has_vertex_ids)
out << protect_xml_string(get("_graphml_vertex_id", dp,
target(*e, g)));
else
out << "n" << get(vertex_index, target(*e, g));
out<< "\">\n";
// Output data // Output data
for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end(); for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end();
++i) ++i)
{ {
if (i->first == "_graphml_edge_id")
continue;
if (i->second->key() == typeid(edge_descriptor)) if (i->second->key() == typeid(edge_descriptor))
{ {
std::string val = protect_xml_string std::string val = protect_xml_string
......
...@@ -367,10 +367,7 @@ void build_stream ...@@ -367,10 +367,7 @@ void build_stream
python::tuple GraphInterface::ReadFromFile(string file, python::object pfile, python::tuple GraphInterface::ReadFromFile(string file, python::object pfile,
string format) string format)
{ {
bool graphviz = false; if (format != "dot" && format != "xml" && format != "auto")
if (format == "dot")
graphviz = true;
else if (format != "xml")
throw ValueException("error reading from file '" + file + throw ValueException("error reading from file '" + file +
"': requested invalid format '" + format + "'"); "': requested invalid format '" + format + "'");
try try
...@@ -390,10 +387,10 @@ python::tuple GraphInterface::ReadFromFile(string file, python::object pfile, ...@@ -390,10 +387,10 @@ python::tuple GraphInterface::ReadFromFile(string file, python::object pfile,
_directed = true; _directed = true;
try try
{ {
if (graphviz) if (format == "dot")
read_graphviz(stream, wg, dp, "vertex_name"); read_graphviz(stream, wg, dp, "vertex_name");
else else
read_graphml(stream, wg, dp); read_graphml(stream, wg, dp, true);
} }
catch (const undirected_graph_error&) catch (const undirected_graph_error&)
{ {
...@@ -407,10 +404,10 @@ python::tuple GraphInterface::ReadFromFile(string file, python::object pfile, ...@@ -407,10 +404,10 @@ python::tuple GraphInterface::ReadFromFile(string file, python::object pfile,
build_stream(stream, file, pfile, file_stream); build_stream(stream, file, pfile, file_stream);
FakeUndirGraph<GraphEdgeIndexWrap<multigraph_t,edge_index_map_t> > FakeUndirGraph<GraphEdgeIndexWrap<multigraph_t,edge_index_map_t> >
ug(wg); ug(wg);
if (graphviz) if (format == "dot")
read_graphviz(stream, ug, dp, "vertex_name"); read_graphviz(stream, ug, dp, "vertex_name");
else else
read_graphml(stream, ug, dp); read_graphml(stream, ug, dp, true);
} }
_state->_nedges = num_edges(_state->_mg); _state->_nedges = num_edges(_state->_mg);
_state->_max_edge_index = (_state->_nedges > 0) ? _state->_max_edge_index = (_state->_nedges > 0) ?
......
...@@ -33,8 +33,8 @@ std::string protect_xml_string(const std::string& os) ...@@ -33,8 +33,8 @@ std::string protect_xml_string(const std::string& os)
class graphml_reader class graphml_reader
{ {
public: public:
graphml_reader(mutate_graph& g) graphml_reader(mutate_graph& g, bool store_ids)
: m_g(g), m_canonical_vertices(false) { } : m_g(g), m_canonical_vertices(false), m_store_ids(store_ids) { }
void run(std::istream& in) void run(std::istream& in)
{ {
...@@ -111,7 +111,7 @@ private: ...@@ -111,7 +111,7 @@ private:
} }
self->m_active_descriptor = self->m_edge.size(); self->m_active_descriptor = self->m_edge.size();
self->handle_edge(source, target); self->handle_edge(id, source, target);
} }
else if (name == "node") else if (name == "node")
{ {
...@@ -202,6 +202,10 @@ private: ...@@ -202,6 +202,10 @@ private:
{ {
self->m_canonical_vertices = (value == "canonical"); self->m_canonical_vertices = (value == "canonical");
} }
else if (name == "parse.edgeids")
{
self->m_canonical_edges = (value == "canonical");
}
} }
self->m_active_descriptor = ""; self->m_active_descriptor = "";
} }
...@@ -282,6 +286,10 @@ private: ...@@ -282,6 +286,10 @@ private:
if (m_keys[iter->first] == node_key) if (m_keys[iter->first] == node_key)
handle_property(iter->first, v, iter->second); handle_property(iter->first, v, iter->second);
} }
if (m_store_ids && !m_canonical_vertices)
m_g.set_vertex_property("_graphml_vertex_id",
get_vertex_descriptor(v),
v, "string");
} }
} }
...@@ -301,7 +309,8 @@ private: ...@@ -301,7 +309,8 @@ private:
} }
void void
handle_edge(const std::string& u, const std::string& v) handle_edge(const std::string& id, const std::string& u,
const std::string& v)
{ {
handle_vertex(u); handle_vertex(u);
handle_vertex(v); handle_vertex(v);
...@@ -325,6 +334,11 @@ private: ...@@ -325,6 +334,11 @@ private:
if (m_keys[iter->first] == edge_key) if (m_keys[iter->first] == edge_key)
handle_property(iter->first, e, iter->second); handle_property(iter->first, e, iter->second);
} }
if (m_store_ids && !m_canonical_edges)
m_g.set_edge_property("_graphml_edge_id", get_edge_descriptor(e),
id, "string");
} }
void handle_property(const std::string& key_id, void handle_property(const std::string& key_id,
...@@ -381,15 +395,16 @@ private: ...@@ -381,15 +395,16 @@ private:
std::string m_character_data; std::string m_character_data;
bool m_canonical_vertices; bool m_canonical_vertices;
bool m_canonical_edges; bool m_canonical_edges;
bool m_store_ids;
XML_Parser m_parser; XML_Parser m_parser;
}; };
namespace boost namespace boost
{ {
void void
read_graphml(std::istream& in, mutate_graph& g) read_graphml(std::istream& in, mutate_graph& g, bool store_ids)
{ {
graphml_reader reader(g); graphml_reader reader(g, store_ids);
reader.run(in); reader.run(in);
} }
} }
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