C++ graph with removable nodes, accessible properties and reliable IDs

。_饼干妹妹 提交于 2019-12-11 03:29:56

问题


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.


回答1:


Then, instead of using vertex pointers, I would use integer vertex indices.

In fact, I think you would use vertex descriptors. Which in the case of vecS container selections would be integral, yes

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.

Strictly speaking this is not always the case. It is the case with vecS, but not with e.g. listS (lists have stable iterators).

  • Iterator invalidation rules

All in all, I suggest looking at listS as the container selection and drop the assumption that vertex_descriptor be an integral type (it will become opaque).

In return for iterator stability, you will need to provide vertex index maps to certain algorithms.



来源:https://stackoverflow.com/questions/29109054/c-graph-with-removable-nodes-accessible-properties-and-reliable-ids

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!