Sailanarmo
Sailanarmo

Reputation: 1181

How to properly use bundled properties in boost?

I am trying to modify a specific vertex in my undirected graph. Essentially, I want to be able to start at index 1 of 18, and run an algorithm to change the string of each node from that vertex. I read in a graph from a dot file. I was looking at Bundled Properties at boost's website and it seem straight forward. However, when I try to implement this I get Attempt to put a value into a const property map: Aborted (core dumped) error. So I find this solution and it looks the exact same as mine.

Here is a minimal example of what is throwing the error:

The File I am reading from test.dot:

graph G {
0 [isLeaf=1];
1 [isLeaf=0];
2 [isLeaf=1];
3 [isLeaf=1];
4 [isLeaf=0];
5 [isLeaf=1];
6 [isLeaf=0];
7 [isLeaf=1];
8 [isLeaf=0];
9 [isLeaf=1];
1--3  [time=3.41843];
1--4  [time=1.01826];
4--5  [time=4.2496];
2--6  [time=5.59155];
1--6  [time=9.48199];
6--7  [time=7.72868];
0--8  [time=7.38977];
4--8  [time=6.55225];
8--9  [time=0.0406912];
}

The code that I am running:

#include <iostream>
#include <string>

#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/graphviz.hpp>
#include <boost/property_map/dynamic_property_map.hpp>
#include <boost/graph/graph_utility.hpp>

struct Vertex
{
    bool isLeaf;
    std::string taxon;
};


typedef boost::property<boost::edge_weight_t, double> Edge;
typedef boost::adjacency_list<boost::vecS,boost::vecS, boost::undirectedS, Vertex, Edge> Graph;

int main()
{
    Graph g;

    boost::property_map<Graph, boost::edge_weight_t>::type weight = get(boost::edge_weight,g);  

    boost::dynamic_properties dp;
    dp.property("node_id", get(boost::vertex_index, g));
    dp.property("isLeaf", get(&Vertex::isLeaf, g));
    dp.property("time", weight);

    std::string blah = "Hello";

    std::ifstream dot("test.dot");

    boost::read_graphviz(dot,g,dp);

    g[1].taxon = blah;  
}

What is the reason for this error?

Upvotes: 2

Views: 619

Answers (1)

sehe
sehe

Reputation: 392893

Using vecS for VertexContainerSelector means you have an implicit vertex index descriptors. They are implicitly the integral index vertex descriptor¹, which happens to be the integral index into the container of vertices.

As such, the standard vertex_index property is read-only

Thought Experiment: what would writing to it mean?

If you changed the vertex_index property of a vertex, should it move around, physically, in memory? What if it overwrites an existing Vertex? What about the old location? Should the container be compacted? But that means that assigning a vertex index to a single vertex potentially changes all other vertex indices etc.)

You can get around that in various ways. Easiest would seem to add a field to the Vertex bundle to contain the node-id property as read from the input:

#include <iostream>
#include <string>

#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/graphviz.hpp>
#include <boost/property_map/dynamic_property_map.hpp>
#include <boost/graph/graph_utility.hpp>

struct Vertex {
    int id;
    bool isLeaf;
    std::string taxon;
};


typedef boost::property<boost::edge_weight_t, double> Edge;
typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS, Vertex, Edge> Graph;

int main()
{
    Graph g;
    boost::property_map<Graph, boost::edge_weight_t>::type weight = get(boost::edge_weight,g);  

    boost::dynamic_properties dp;
    dp.property("node_id", get(&Vertex::id, g));
    dp.property("isLeaf", get(&Vertex::isLeaf, g));
    dp.property("time", weight);

    std::string blah = "Hello";

    std::ifstream dot("test.dot");

    boost::read_graphviz(dot,g,dp);

    g[1].taxon = blah;  
}

Upvotes: 1

Related Questions