[BGL] Subgraphs: Name-to-Index Property Map.
Dear BGL users,
I am trying to produce a simple routine to extract the subgraph of a
graph, by using the vertex names of the subgraphs. That is, for two
graphs G and H, I want to define the following operator:
G -= H;
Here, the resulting subgraph of G should have all the vertices that H
doesn't have. During this process, the incident edges of the removed
vertices are also removed. I have checked the subgraph class in BGL, but
this refers to a substantially different concept. I have tried the
following code, which works, but is extremely slow for the type of
application that I had in mind:
//////////////////////////////////////////////////
class Graph
{
public:
typedef adjacency_list
On Wednesday, 25. May 2011 10:54:07 Cedric Ginestet wrote:
Dear BGL users,
I am trying to produce a simple routine to extract the subgraph of a graph, by using the vertex names of the subgraphs. That is, for two graphs G and H, I want to define the following operator: G -= H; Here, the resulting subgraph of G should have all the vertices that H doesn't have. During this process, the incident edges of the removed vertices are also removed. I have checked the subgraph class in BGL, but this refers to a substantially different concept. I have tried the following code, which works, but is extremely slow for the type of application that I had in mind:
////////////////////////////////////////////////// class Graph { public: typedef adjacency_list
> UndirectedGraph; Graph(); ~Graph(); int Nv(); // Return number of vertices Rcpp::IntegerVector V(); // Return vector of NAMES of vertices as integers. Graph& operator-= (Graph& H); private: UndirectedGraph G; }; ///////////////////////////////////////////////////////////////////////// // Overloaded Operators. Graph& Graph::operator-= (Graph& H){ typedef graph_traits<UndirectedGraph>::vertex_descriptor Vdescriptor; typedef property_map
::type VertexNameMap; typedef iterator_property_map name_to_vertex_map; Rcpp::IntegerVector vec = H.V(); VertexNameMap NameIndex; for(ivIter t=vec.begin(); t!=vec.end(); ++t){
// Create/Update Iterator map (LValuePropertyMap). int x[this->Nv()]; NameIndex = get(vertex_name,G); for(int i=0; i < this->Nv(); ++i) x[NameIndex[i]]=i; name_to_vertex_map NVmap(x);
// Remove vertex from name of *t in H. Vdescriptor u=NVmap[*t]; clear_vertex(u,G); remove_vertex(u,G); }//t return *this; }//-= //////////////////////////////////////////////////
The problem seems to be that I re-create an iterator map (from vertex NAMES to vertex INDICES) every time I remove a single vertex. This seems counter-efficient. I would need to be able to create a reference to a similar map that is automatically updated every time I remove a vertex. However, since vertices in BGL are indexed from 0 to Nv-1, I don't see a way to produce a LValuePropertyMap from vertex's names to vertex's indices.
Any help/opinion would be greatly appreciated,
Maybe a soution would be to use filtered_graph and as the predicate the vertices (or directly names) of H (in the form of a set?!). However, this would require to copy the filtered_graph again into an adjacency_list, which might be costly, depending on your situation. Besides this, I would suggest you to use vertex_descriptor instead of int, as vertex_descriptor is more general and your code will then most likely also work if you decide to change vecS into listS (in case this plays a role). Concerning your code, I am wondering if it is intended that vertex_name_t is of type int and not std::string? The more, when you want to compare each vertex from one graph with each vertex of the other (which you basically have to do for completeness), I would assume this takes quadratic running time and hence will be fairly costly. Unless you have maps that allow a faster lookup, but you will then need to create a map NAMES to INDICES(vertex_descriptor) for one graph and then do something like: name_to_vertex_map_H[getName(vertex_of_G)] and in case this key exists, you can remove vertex_of_G from G, as you have found a vertex with an equivalent name in H. It would then also be nonrelevant if your graph (for simplicity I take G) would have vertices with the same name, as they would all be "mapped" by the name_to_vertex_map_H and thus could be adequately handled. I actually don't see the need to update the map then, because the deleted vertices will not show up again (your iterator went to the next vertex) and if there are different nodes with the same name, they will be taken care of. One thing that comes into my mind when writing you this is that you also should have a look at iterator-invalidation due to the clear_vertex() and remove_vertex(). I am right now not sure if this is critical for vecS or not. Hope that these thoughts are handy in some way. If not, please let me know. Best, Cedric
participants (2)
-
Cedric Ginestet
-
Cedric Laczny