I'm trying to migrate from a proprietary graph library to an Open Source one.
EDIT: since so few people seem to know how Boost Graph actually works, if you can provide a solution using the LEMON Graph Library, that's fine too.
Currently, my vertices have type Graph_Vertex*
and can have an associated void*
pointer to store related information. A similar logic is used with respect to edges, which are of type Graph_Edge*
. I use the void*
pointer to store my own structure Node_State
, which is something like this
struct Node_State {
std::string name;
int id;
// other stuff
};
From what I've seen of the BGL up to now, I could create a graph using an adjacency_list
structure and bundled properties to point to my Node_State
. Then, instead of using vertex pointers, I would use integer vertex indices.
I've been looking at the tutorial and some questions here, and this seems possible. I'm thinking about something like
typedef adjacency_list < listS, vecS, bidirectionalS, Node_State> gr;
I'll remove all the edges to and from a vertex from time to time. Very less frequently, I may remove a node too. That's why I would choose listS, vecS
.
I would like to make it easy to create a second version of this structure for undirected edges. I am not sure if bidirectionalS
is the best option for my case. Your input is appreciated in this regard.
There's another problem though. Right now, I can use an external map to find each vertex by its name or using a unique integer id.
std::map<int, Graph_Vertex*> nodes_by_id;
std::map<std::string, Graph_Vertex*> nodes_by_name();
If I delete a vertex, I just need to remove the corresponding entry(ies) in the map(s), and things keep working.
From what I understand, this is not so easy to achieve with BGL, because deleting a vertex triggers the renumbering of all the vertices with a higher ID, and might also cause a reallocation of the internal structures. So goodbye ids and goodbye pointers.
Main question. Is it possible to create a map<name, node>
or map<index, node>
that can survive node removals with minimal adjustments (e.g. just removing the invalid keys)? If not, what's the best way to map nodes to some unique identifier that survives modifications to the graph?
An option could be using the internal properties. Tutorial example here.
struct vertex_index_t { };
struct edge_index_t { };
struct vertex_name_t { };
struct edge_name_t { };
And keeping some external structures
std::map<vertex_index_t, Graph_Vertex*> nodes_by_id;
std::map<vertex_name_t, Graph_Vertex*> nodes_by_name;
std::map<edge_index_t, Graph_Edge*> edges_by_id;
std::map<edge_name_t, Graph_Edge*> edges_by_name;
This would be much more similar to what I have now, and require less changes to the current code.
I haven't really understood how vertex_index_t
is affected by vertex removal, and how vertex_name_t
can be assigned. If this can work, though, a similar logic could be applied to edges using edge_index_t
and edge_name_t
too.
Wrap up. I need a working piece of code showing how to:
- add vertices (with properties)
- add arcs (with properties)
- remove vertices
- remove arcs
With these important requisites:
- being able to index vertices by id (int or string) so that it's easy to retrieve them and access their properties
- ids must not change if a vertex is removed
- the addition of indices and properties should not make running algorithms like "find connected components" and "Dijkstra search" more difficult
I would be happy if I could achieve something like
Vertex* vertex0 = Graph.get_vertex_by_name("v0");
Vertex_Data* v0_data = vertex0.get_data();
Edge* edge4 = Graph.get_edge_by_id(4);
Edge_Data* e4_data = edge4.get_data();
This may seem like a lot of questions, but really just the basis of what I need to get this library up and running. Anything less and it's completely useless for what I need to do.
Please, hit all the bullet points.
Think of this as a tutorial, my hope is that giving a bounty will help other people as well.