Search code examples
c++boostgraphml

Difficulty with read_graphml function from the Boost Graph library


I am trying to use the read_graphml function from the Boost library to read some .graphml files in a C++ application that I am developing. However, I am running into unexpected difficulties in reading properties. Here is a MWE of my code:

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

using namespace boost;

int main(int, char**){

    typedef adjacency_list<vecS, setS, undirectedS> Graph;


    std::ifstream graph_file;
    graph_file.open("more_exampleHoles_8.graphml", std::ifstream::in);

    Graph g;
    boost::dynamic_properties dp;
    boost::read_graphml(graph_file, g, dp);
}

Here is the contents of more_exampleHoles_8.graphml:

<?xml version='1.0' encoding='UTF-8'?>
<!-- created by IGraph/M, http://szhorvat.net/mathematica/IGraphM -->
<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="v_betti"
     for="node"
     attr.name="betti"
     attr.type="long" />
 <key for='node'
     id='v_dimk'
     attr.name='dimk'
     attr.type='long' />
 <key for='node'
     id='v_gap'
     attr.name='gap'
     attr.type='double' />
 <graph id='Graph'
     edgedefault='undirected'>
  <node id="1">
   <data key="v_betti">5</data>
   <data key='v_dimk'>1</data>
   <data key='v_gap'>0.12405641442417092</data>
  </node>
  <node id='2' />
  <node id='3' />
  <node id='4' />
  <node id='5' />
  <node id='6' />
  <node id='7' />
  <node id='8' />
  <node id='9' />
  <node id='10' />
  <node id='11' />
  <node id='12' />
  <edge source='1'
      target='2' />
  <edge source='1'
      target='3' />
  <edge source='1'
      target='4' />
  <edge source='1'
      target='8' />
  <edge source='2'
      target='7' />
  <edge source='2'
      target='9' />
  <edge source='2'
      target='11' />
  <edge source='3'
      target='5' />
  <edge source='3'
      target='10' />
  <edge source='4'
      target='5' />
  <edge source='4'
      target='6' />
  <edge source='4'
      target='7' />
  <edge source='4'
      target='8' />
  <edge source='4'
      target='9' />
  <edge source='4'
      target='11' />
  <edge source='5'
      target='9' />
  <edge source='5'
      target='10' />
  <edge source='6'
      target='8' />
  <edge source='7'
      target='10' />
  <edge source='8'
      target='10' />
  <edge source='9'
      target='11' />
 </graph>
</graphml>

When running the code, I receive the following output:

terminate called after throwing an instance of 'boost::wrapexcept<boost::property_not_found>'
  what():  Property not found: betti.
Aborted (core dumped)

I am pretty confident that the graphml is well formed, so this seems to me to be a bug with the read_graphml function. If I remove the following lines from the .graphml file, everything works fine, but of course I don't want to remove these lines.

   <data key="v_betti">5</data>
   <data key='v_dimk'>1</data>
   <data key='v_gap'>0.12405641442417092</data>

Solution

  • Boost expects you to define property maps for all properties present. If you want to ignore unknown properties, add the filter to the dynamic properties constructor:

    boost::dynamic_properties dp(boost::ignore_other_properties);
    

    Alternatively, add the property maps:

    Live On Coliru

    #include <boost/graph/graphml.hpp>
    #include <boost/property_map/dynamic_property_map.hpp>
    #include <fstream>
    #include <iostream>
    
    struct VertexProps {
        long   betti, dimk;
        double gap;
    };
    using Graph = boost::adjacency_list<boost::vecS, boost::setS, boost::undirectedS, VertexProps>;
    
    int main() {
        std::ifstream graph_file("more_exampleHoles_8.graphml");
        Graph         g;
    
        boost::dynamic_properties dp;
        dp.property("betti", get(&VertexProps::betti,   g));
        dp.property("dimk",  get(&VertexProps::dimk,    g));
        dp.property("gap",   get(&VertexProps::gap,     g));
        read_graphml(graph_file, g, dp);
    }