Implementing Christofides algorithm with GCAL in C++ - c++

I want to implement a slightly altered Christofides algorithm for undirected graphs, whose vertices are 2D points. Seems like I need CGAL only for triangulation, everything else is provided in boost. Am I wrong?
Is there a better way to copy a graph from Point_set_2 class into boost's adjacency_list (other than iterating over adjacency lists and adding edge for every neighbour)?

Related

Efficient Transitive Reduction of Adjacency List DAG

I have a large directed acyclic graph, and I'd like to compute the transitive reduction of that graph.
I'm currently computing the transitive reduction using a naive depth-first search, but that algorithm is too slow for my use case. However, the efficient algorithms I've been able to find work on an adjacency matrix representation, whereas my representation is roughly equivalent to an adjacency list. (It's actually represented as a set of C++ objects, each with pointers to their children and parents).
I obviously could transform my DAG into an adjacency matrix, do the reduction, and transform it back; but that seems a bit wasteful, and I'd like a simpler algorithm if possible.
My graph contains ~100,000 nodes.

Sorting a C++ vector based on an adjacency matrix

I have a vector e whose elements are indices to edges in a 2D (surface) mesh. For whatever reason, I would like to reorder this vector, so that each edge is surrounded by edges that are closest to it (basically, similar to what the asker is trying to achieve in this question).
I don't need it to be an exact or perfect solution (there probably isn't one), but I'd like to get as close as possible.
Here are the steps I have taken:
Create an adjacency matrix B for the mesh edges,
Use an algorithm such as RCM to get a reordering of the adjacency matrix to reduce its bandwidth (I'm using Petsc's MatGetOrdering to do this),
Apply the new ordering to get a new, reshuffled adjacency matrix, B2.
At this point, I would like to reorder the original vector e of mesh edges, to get a new vector e2 whose adjacency matrix is now B2.
Is this possible? i.e. is there enough information above to achieve this?
Is this a good approach to do what I'm trying to achieve?
If not, what would be the most sensible and robust approach? (e.g. I was also playing around with trying to do this based on physical distances rather than edge connectivity, but I'm not sure which approach is more realistic / sensible / robust),
If yes, how do I accomplish the last step of reordering the edge vector based on the new adjacency matrix?
I'm fairly new to Stack Exchange so please let me know if I should be asking this on another sub-community. I am also fairly new to graph theory, so I may be missing something obvious.
Thanks!

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...

Fastest way to run prim's on a growing range of coordinates

I was hoping someone could give me a general method for computing the MST for a problem that works from input that is formatted as such:
<number of vertices>
<x> <y>
<x> <y>
...
I understand how to implement prim's algorithm, but I was looking for a method that (using prim's algorithm) will require the least amount of memory/time to execute. Should I store everything in an adjacency matrix? If the number of vertices grows to say, 10,000, what is the optimal way to solve this problem (assuming prim's is used)?
You really need to use Prim's?
A simple way is use Kruskal algorithm to recompute the spanning tree (using only previously selected edges) every time you add a node. Since Kruskal is O(E log E) and in every iteration you'll have exactly 2*V-1 edges to compute (V-1 from previous tree + V from newly added node). You'll need O(V log V) for each insertion.
Prim's algoritm is faster if you have a dense graph (a graph that has a lot of edges). If you use an adjacency matrix, the complexity of Prim's algoritm would be O(|V|^2).
This can be improved by using a binary heap data structure with the graph represented by an adjacency list. Using this method, the complexity would be O(|E|log|V|).
Using a fibonacci heap data structure with an adjacency list would be even faster with a complexity of O(|E| + |V|log|V|).
Note: E refers to the number of edges in the graph, while V refers to the number of vertexes in the graph.
The STL has already implemented a binary heap data structure, std::priority_queue. A std::priority_queue calls the heap algoritms in the algoritm library. You could also use a std::vector (or any other container that has random access iterators) and call make_heap, push_heap, pop_heap, etc. These are all in the algoritm library. More info here: http://www.cplusplus.com/reference/algorithm/.
You could also implement your own heap data structure, but that may be too complicated and not worth the performance benefits.

using Dijkstra algorithm to find shortest path in an adjacency matrix

I have a homework assignment where I'm supposed to find the cheapest airfares between two cities, taking into account layovers.
We are required to use an adjacency matrix along with Dijkstra's algorithm. I'm looking at the algorithm in my book, as well as wikipedia (among other sites). I'm confused because in the parameter for the algorithm it has:
DijkstraAlgorithm(weighted simple digraph, vertex first)
What I'm having a hard time understanding- especially when looking at the entire pseudocode- is why it only takes one vertex as an argument? I need to find the cheapest airfare(shortest path) between two vertices. Why does the algorithm only require one?
Dijkstra's will find the shortest path from the provided vertex (first in your example) to every vertex in your graph. That's why it only takes one vertex as input.