Change Target of Edge in BGL - boost-graph

If my BGL graph contain edge from node x to node y, and I want to change the target of this edge, so that now it's pointing from x to z, how it can be done?
Are there any functions in BGL for that?

You can remove an edge and add another one instead - see remove_edge and add_edge defined in the MutableGraph concept. I don't see any direct manipulation function. Alternatively, you can define your own one that would hide the removal and addition. Special care should be taken for the graphs with properties attached to edges (i.e. MutablePropertyGraph).

Related

C++ Boost graph library: Isomorphism with edge property

The boost graph library has an isomorphism function with a very minimal example:
https://www.boost.org/doc/libs/1_68_0/libs/graph/example/isomorphism.cpp
I need to find isomorphism between two graphs with a very minimal extension, that each line has two properties, that can be indicated with integer values. I guess this is equivalent to a weight.
I cannot for the life of me understand the role of property maps or how to incorporate those. Could someone point me to a relevant example so I can see how this works?
Boost.Graph uses "property maps" to associate data with different graph elements (i.e. vertices, edges, or the graph as a whole). A property map is simply a container that can associate the graph's internal descriptor types to some other data. A few examples can be found here and here.
I assume you've already seen the docs for the isomorphism function. So in your case each of your graphs will have one property map for edge weights, and then you have the option to provide more property maps when calling the isomorphism function to control the behavior and/or get extra data out. However, I don't see any way to provide a predicate for verifying that the edge weights match; you may have to handle that yourself (e.g. first run the function to check for "pure" isomorphism, then walk edges of one graph and use the output isomorphism_map to find corresponding edges in the second graph and check equality)
As far as I can tell that algorithm doesn't allow you to specify edge equivalence criteria. Perhaps you can apply vf2_sub_graph_iso, though, which takes an optional EdgeEquivalencePredicate

if add_vertex in BGL checks for the existence of the vertex

In BGL, add_edge checks if the edge already exists. Is there the same mechanism for add_vertex?
For example, if we have a vertex with some bundled_properties, and then we add it to the graph, and then connect an edge to it, would be this vertex duplicated if there was a similar vertex?
When two vertices have similar properties (internal, or bundled) they are the same vertex, and add_vertex instead of adding it with new index shouldn't just return the index to an existing one? – Bruce 11 mins ago
If you have two vertices with "similar properties", you decide whether you want to add another vertex with those properties or not.
if we have a vertex with some bundled_properties, and then we add it to the graph, and then connect an edge to it, would be this vertex duplicated if there was a similar vertex?
You add edges by referring to vertex_descriptors. There is no way to "connect an edge to vertex properties". So, add_edge cannot accidentally create a new vertex using some property.
Note: There might be confusion because using vectorS² for vertex container selector lets you add edges by referring to potentially non-existing vertex descriptors. Really, that doesn't "add vertices" as much as it "extends the valid domain for vertex ids/descriptors". E.g.:
adjacency_list<> g;
add_edge(10, 11, g);
doesn't really add 12 vertices. It extends the vertex id domain to encompass the value 11. Live On Coliru
Let's look at add_vertex:
The call is add_vertex and it adds a vertex. In fact, you don't usually insert properties for them, that's merely a convenience.
There is no fundamental difference between:
vertex_descriptor v = add_vertex(g);
g[v] = vertexProperties;
And
vertex_descriptor v = add_vertex(vertexProperties, g);
In both cases you will always get a new, unique, vertex descriptor, and have its properties set to a specific value.
Why the difference with add_edge then?
Is add_edge really different? Like with add_vertex there is no difference between:
vertex_descriptor from {/*...*/}, to {/*...*/};
edge_descriptor e = add_edge(from, to, g).first;
g[e] = edgeProperties;
And
edge_descriptor e = add_edge(from, to, edgeProperties, g).first;
You will note that both (possibly) add an edge, returning its descriptor, and both set the properties to specific values.
The important point here is that adjacency_list does not know or care about the properties. They add information for you, or useful for certain algorithms, but they are not relevant to the graph concept modeled by adjacency_list.
Why does add_edge conditionally add?
That's because the adjacency_list uses strategies that imply invariants that need to be checked:
if your edge-container selection happens to be e.g. setS, its insertion method may or may not insert a new edge; adjacency_lists<> just forwards the behaviour¹ to add_edge
if your adjacency_list uses undirected or bidirectional as well, this puts extra contraints on edges (e.g. preventing addition of (a->b) as well as (b->a) in a bidirectional graph that uses setS as the edge container selector).
Summarizing:
add_vertex does not take any identifying information, hence it doesn't need to check for constraints (in fact, it cannot).
add_edge does take identifying information (the endpoint vertices) and it can check these against the constraints that arise from the strategies that you chose when instantiating the adjacency_list.
¹ e.g. to elegantly avoid doubled edges
² or possibly other Random Access vertex container selectors, that have integral vertex descriptors that act as implicit vertex id

Modelling a graph with classes 'edge' and 'node'

I have to model an unweighted graph in C++ and do BFS and DFS. But, I have to create two separate classes: node and edge which would contain the two extremities of type node. I do not understand how would I be able to do any search in the graph using the edge class. If it were me, I would only create the node class and have the neighbours of node X in a list/array inside the class. Is there something I am missing? How could I take advantege of the class edge? Is there any way to do the searches without using an adjacency matrix or list? Thank you!
You can still use adjacency lists. But they will contain not references to other nodes, but rather references to edge instances, which in turn contain both endpoints as node references, as you mention. Of course, that seems kind of redundant because if you have, say source and target nodes in each edge and then you access some edge of a given node using something like node.edges[i].source, then you instantly know that this source is the node itself, otherwise this edge wouldn't even be in this node's adjacency list. But source may still be useful if you pass a reference to edge alone somewhere, where you don't have the source node at hand.
That aside, for the simplest graph this kind of approach seems like an overkill, because edges only store source and destination edges, the former being mostly redundant. But you may need to extend your edge class later with something like weights, labels, auxiliary data like residual flow or something like that. So having such class is a nice idea after all.
Moreover, some algorithms work directly on edges. For example, you may need to search for an edge satisfying some criterion. Having a separate class gives you freedom to create lists of edges without ad-hoc approaches like pair<Node, Node> or something.
You miss the constant of space complexity in storing the edges.
When you store the edges in adjacency matrix/list, you have to store both (node1, node2) and (node2, node1) for each edge.
You double the space, although the big-O complexity stays the same.
However, there're times when such space constant has to be considered.
You can take advantage of the class edge when you would like to save as much space as possible, and you would like to prioritize space over time.
Linear search on all the edge instances is a way.
Linear search is slow but you prioritize space over time.
Maybe parallel search when you have a distributed system is another way, but you have to verify.
Your homework question may have an artificial constraint of the design of the edge class. Artificial constraint idea comes from https://meta.stackexchange.com/questions/10811/how-do-i-ask-and-answer-homework-questions

Boost Graph : Test if two vertices are adjacent

I'm new in using C++ boost library in particularly the boost graph library which a needed to try coding some algorithms where i commonly check the adjacency of two vertices and dealing with other graph concepts like computing graph invariants.
What i know is that we can iterate through adjacent vertices with the function : adjacent_vertices(u, g) but i'm searching for an efficient way to test if two vertices u, v are adjacent or not without doing linear search
The AdjacencyMatrix concept gives a complexity guarantee that the edge() function must return in constant time.
To check if two vertices v and w are adjacent in G, you write edge(v, w, G).second, since the function returns a pair where the second value indicates if the edge exists.
The edge() function is implemented for other graph representations as well. Here is a graph that shows how different representations compare with regard to performance of checking vertex adjacency:
Here is the code used to generate the data for this plot. Each data point is 100 random graphs of medium density, with 100 random edge checks per each graph. Note the logarithmic y axis.
What is the best choice will eventually depend on your particular application, because for other operations the ordering of structures by speed is different. In other words, avoid premature optimization.
BGL is a highly generic library. You can adapt most any datastructure for use with its algorithms.
You can vary the edge container. You don't mention it, but I'm assuming you've been looking at the interface/complexity guarantees for boost::adjacency_list.
Indeed the edge membership test will be O(n) even if you use setS for the edge container selector. This is mostly because adjacency lists store outgoing edges are per vertex. So in worst case, each vertex contains at most one outgoing edge and the search is practically O(n) [1]
In this case you simply want to select another graph implementation.
The documentation page on Graph Concepts is a good starting point to find out about which concepts are expected. As well as, which models supply those concepts.
In the worst case you can adapt your data structure for use with Boost Graph algorithms. E.g. you could store all edges in a simple std::[unordered_]set<std::pair<VID, VID> > and adapt it to model the EdgeListGraph concept.
That way you will have performant lookups.
[1] of course this also means, in best case the search is whatever your set implementation affords: O(log n) because all edges could originate from the same vertex...

Reconstruct all the edges in a triangle mesh

I have a triangle mesh which contains millions of triangles. Currently in my data structure only the triangles and the vertices are stored. I want to reconstruct all the edges and stored them in a data container. The idea may be like this: Traverse all the triangles, get each two of its vertices, and create an edge between them. The question is the shared edge maybe created twice. So to overcome this problem, I need a data container EdgeContainer to store the edges and it should have a function to check whether this edge has been already created. So it is like a map with multiple keys, but according to my question, this map should also have the following functions:
EdgeContainer(v1, v2) should return the same result as EdgeContainer(v2, v1), where v1 and v2 are the pointers to two vertices.
EdgeContainer should have a function like EdgeContainer::Remove(v1), which will remove all edges incident to vertex v1.
The implementation should be as efficient as possible.
Is there any existing library which can handle this?
First i suggest you have a look at the concept of
half-edge http://www.flipcode.com/archives/The_Half-Edge_Data_Structure.shtml meshes it is used in CGAL and also in OpenMesh and you should be aware of the concept of you are going to use any of them.
I my slef recommend OpenMesh http://openmesh.org/Documentation/OpenMesh-2.0-Documentation/tutorial_01.html it is free and open source, you can easily create mesh from set of vertices and indices, and after creating mesh you can easily iterate over all edges.
Your easiest bet would be to use the Cgal library, which is basically designed for doing this.
http://doc.cgal.org/latest/Triangulation_2/index.html
It provides natural iterators for iterating over faces, edges and vertices.
Notice that in Cgal, they do not actually store the edges explicitly, they are generated
each time the structure is iterated. This can be done efficiently using some clever rules
that stop you from counting things twice: looking at the code, it appears that each face
is iterated once, and an edge is added for each neighbouring face to the current face,
that comes earlier in the list of faces than the current face.
Note that visiting the edges in this fashion only requires constant time per edge (depending on how you store your faces) so that you are unlikely to benefit from storing them separately. Also note that the edge is defined by two adjacent faces, rather than two adjacent vertices. You can transform them in constant time.
Simple solution is to use sorted pair of indices:
struct _edge_desc : public std::pair<int,int> {
_edge_desc(int a, int b): std::pair<int,int>(a<b?a:b, a<b?b:a) {}
};
std::set<_edge_desc> Edges;
If additional info about edges is needed than it can be store in separate vector, and instead of using set for storing edges, use map that maps to index in vector.
std::vector<some_struct> EdgesInfo;
std::map<_edge_desc, int> EdgesMap;