Boost logo

Boost :

Subject: [boost] Graph properties and GraphML
From: Arthur Castonguay (thearthurc_at_[hidden])
Date: 2012-03-21 08:24:43


I'm using 1.49.0 and am attempting to read a GraphML file that has graph
attributes on it (example file below). My test program is below too. I've
run into two issues.
1. The GraphML reader didn't quite handle them. There was some facilities
put in place but it was never glued together. I added some code (patch
below) and now it appears that that will do what I want... I'm getting
"property not found" exception now. Great... onto item 2.
2. I cannot seem to wire the graph property into the dynamic properties.
 I've used the same syntax used for node and edge
properties: props.property("gattr", get(&GraphProperty::gattr, g));

I've search examples and cannot find an instance of this to see if graph
properties are handled differently. It's possible I've just written bad
code for #2. I'm still working through the adjacency_list code to see if I
can grok what's going on. Figured maybe someone more familiar with this
could find the issue quickly.

Once functionaly, I'll report a bug regarding item #1 but I want to ensure
the writing of the GraphML works as well before doing that (the code
appears to write graph attributes.. can't test yet due to item #2).

For those that don't want to bother, this is the compile error I'm getting:

boost/graph/adjacency_list.hpp: In function ‘typename
boost::property_map<boost::adjacency_list<OutEdgeListS, VertexListS,
DirectedS, VertexProperty, EdgeProperty, GraphProperty, EdgeListS>, T
Bundle::*>::type boost::get(T Bundle::*,
boost::adjacency_list<OutEdgeListS, VertexListS, DirectedS, VertexProperty,
EdgeProperty, GraphProperty, EdgeListS>&) [with OutEdgeListS = boost::vecS,
VertexListS = boost::vecS, DirectedS = boost::bidirectionalS,
VertexProperty = NodeProperty, EdgeProperty = EdgeProperty, GraphProperty =
GraphProperty, EdgeListS = boost::listS, T = std::string, Bundle =
GraphProperty]’:
ex.cpp:37: instantiated from here
boost/boost/graph/adjacency_list.hpp:561: error: no matching function for
call to ‘boost::bundle_property_map<boost::adjacency_list<boost::vecS,
boost::vecS, boost::bidirectionalS, NodeProperty, EdgeProperty,
GraphProperty, boost::listS>,
boost::detail::edge_desc_impl<boost::bidirectional_tag, long unsigned int>,
EdgeProperty, std::basic_string<char, std::char_traits<char>,
std::allocator<char> >
>::bundle_property_map(boost::adjacency_list<boost::vecS, boost::vecS,
boost::bidirectionalS, NodeProperty, EdgeProperty, GraphProperty,
boost::listS>*, std::string GraphProperty::*&)’
boost/boost/graph/properties.hpp:397: note: candidates are:
boost::bundle_property_map<Graph, Descriptor, Bundle,
T>::bundle_property_map(Graph*, T Bundle::*) [with Graph =
boost::adjacency_list<boost::vecS, boost::vecS, boost::bidirectionalS,
NodeProperty, EdgeProperty, GraphProperty, boost::listS>, Descriptor =
boost::detail::edge_desc_impl<boost::bidirectional_tag, long unsigned int>,
Bundle = EdgeProperty, T = std::basic_string<char, std::char_traits<char>,
std::allocator<char> >]
boost/boost/graph/properties.hpp:396: note:
boost::bundle_property_map<Graph, Descriptor, Bundle,
T>::bundle_property_map() [with Graph = boost::adjacency_list<boost::vecS,
boost::vecS, boost::bidirectionalS, NodeProperty, EdgeProperty,
GraphProperty, boost::listS>, Descriptor =
boost::detail::edge_desc_impl<boost::bidirectional_tag, long unsigned int>,
Bundle = EdgeProperty, T = std::basic_string<char, std::char_traits<char>,
std::allocator<char> >]
boost/boost/graph/properties.hpp:390: note:
boost::bundle_property_map<boost::adjacency_list<boost::vecS, boost::vecS,
boost::bidirectionalS, NodeProperty, EdgeProperty, GraphProperty,
boost::listS>, boost::detail::edge_desc_impl<boost::bidirectional_tag, long
unsigned int>, EdgeProperty, std::basic_string<char,
std::char_traits<char>, std::allocator<char> > >::bundle_property_map(const
boost::bundle_property_map<boost::adjacency_list<boost::vecS, boost::vecS,
boost::bidirectionalS, NodeProperty, EdgeProperty, GraphProperty,
boost::listS>, boost::detail::edge_desc_impl<boost::bidirectional_tag, long
unsigned int>, EdgeProperty, std::basic_string<char,
std::char_traits<char>, std::allocator<char> > >&)

Here's my compiler version:

$ cc --version
i686-apple-darwin11-llvm-gcc-4.2 (GCC) 4.2.1 (Based on Apple Inc. build
5658) (LLVM build 2336.1.00)
Copyright (C) 2007 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Any ideas? Is item #2 a bug or dumbass programmer (aka me)?

Regards,
Arthur

--- 8< Start ex.graphml 8< ---
<?xml version="1.0" encoding="UTF-8"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns
     http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
  <key id="key0" for="graph" attr.name="gattr" attr.type="string"/>
  <key id="key1" for="node" attr.name="nattr" attr.type="string"/>
  <key id="key2" for="edge" attr.name="eattr" attr.type="string"/>
  <graph id="G" edgedefault="directed">
    <data key="key0">graphval</data>
    <node id="n0">
      <data key="key1">nodeval0</data>
    </node>
    <node id="n1">
      <data key="key1">nodeval1</data>
    </node>
    <edge source="n0" target="n1">
      <data key="key2">edgeval</data>
    </edge>
  </graph>
</graphml>
--- 8< End ex.graphml 8< ---

--- 8< Start ex.cpp 8< ---
#include <iostream>
#include <string>

#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graphml.hpp>
#include <boost/property_map/dynamic_property_map.hpp>

struct GraphProperty {
    std::string gattr;
};

struct NodeProperty {
    std::string nattr;
};

struct EdgeProperty {
    std::string eattr;
};

typedef boost::adjacency_list<boost::vecS,
                              boost::vecS,
                              boost::bidirectionalS,
                              NodeProperty,
                              EdgeProperty,
                              GraphProperty> Graph;

using namespace std;
using namespace boost;

int main()
{
    Graph g;

    dynamic_properties props;
    props.property("nattr", get(&NodeProperty::nattr, g));
    props.property("eattr", get(&EdgeProperty::eattr, g));
    props.property("gattr", get(&GraphProperty::gattr, g)); // Fails to
compile

    try {
        read_graphml(cin, g, props);
        write_graphml(cout, g, props);
    } catch (parse_error e) {
        cerr << e.what() << endl;
    } catch (bad_parallel_edge e) {
        cerr << e.what() << endl;
    } catch (directed_graph_error e) {
        cerr << e.what() << endl;
    } catch (property_not_found e) {
        cerr << e.what() << endl;
    } catch (...) {
        cerr << "Caught unhandled excption" << endl;
    }

    return EXIT_SUCCESS;
}
--- 8< Start ex.cpp 8< ---

Patch to enable graph properties on GraphML files. Using 1.49.0.

Index: libs/graph/src/graphml.cpp
===================================================================
--- libs/graph/src/graphml.cpp (revision 1)
+++ libs/graph/src/graphml.cpp (working copy)
@@ -74,6 +74,15 @@
       std::vector<const ptree*> graphs;
       get_graphs(gml, graphs);
       BOOST_FOREACH(const ptree* gr, graphs) {
+ // Search for graph attributes
+ BOOST_FOREACH(const ptree::value_type& attr, *gr) {
+ if (attr.first != "data") continue;
+ std::string key =
attr.second.get<std::string>(path("<xmlattr>/key"));
+ std::string value = attr.second.get_value("");
+ handle_graph_property(key, value);
+ }
+ }
+ BOOST_FOREACH(const ptree* gr, graphs) {
         // Search for nodes
         BOOST_FOREACH(const ptree::value_type& node, *gr) {
           if (node.first != "node") continue;
@@ -183,6 +192,11 @@
         }
     }

+ void handle_graph_property(const std::string& key_id, const
std::string& value)
+ {
+ m_g.set_graph_property(m_key_name[key_id], value,
m_key_type[key_id]);
+ }
+
     void handle_node_property(const std::string& key_id, const
std::string& descriptor, const std::string& value)
     {
       m_g.set_vertex_property(m_key_name[key_id], m_vertex[descriptor],
value, m_key_type[key_id]);


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk