boost::adjacency_list<> and boost::listS - boost

the documentation says:
listS selects std::list
The same is being used in an example I'm trying to adapt.
I don't see anywhere in the example where the edge and the vertex type are being passed to boost::adjacency_list<>.
And unsurprisingly constructing the graph using a begin-end pair into a container of edges does not compile for me.
How can one tell the graph library about the type of edges and vertices one intends to use?

I created a copy of the graph with plain std::size_t for vertices and std::pair<std::size_t, std::size_t> for edges.
I'm unclear why I have to do this, as the graph library is a template library.

Q. I don't see anywhere in the example where the edge and the vertex type are being passed to boost::adjacency_list<>.
You choose all the properties of the graph with the template arguments.
The first two choose how edges and vertexes are to be stored. For adjacency-lists, the adjacency-list is a given, but you can choose the edge container selector (which stores the adjacencies (out-edges) per source vertex) and the actual vertex container selector (which stores the vertices themselves).
The other template arguments include the vertex/edge and graph properties. So, where the container selectors choose how to store graph entities, the properties describe what should be stored.
HOW everything is being stored is ultimately an implementation detail.
Q. And unsurprisingly constructing the graph using a begin-end pair into a container of edges does not compile for me.
We can't say anything about that, because we don't know what you mean by "a container of edges". Do you already have your graph in some other format?¹
The constructor arguments are not required to build a graph. E.g.:
#include <boost/graph/adjacency_list.hpp>
using G = boost::adjacency_list<>;
int main() {
G g(10);
}
Is the simplest possible program that creates a graph with 10, unconnected, vertices. To also print it: Live
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graph_utility.hpp>
using G = boost::adjacency_list<>;
int main() {
G g(10);
print_graph(g);
}
Output shows 10 vertices with no adjacencies:
0 -->
1 -->
2 -->
3 -->
4 -->
5 -->
6 -->
7 -->
8 -->
9 -->
How can one tell the graph library about the type of edges and vertices one intends to use?
Let me start with the "using", then modify the types a little:
Instead you can add edges/vertices after construction: Live
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graph_utility.hpp>
using G = boost::adjacency_list<>;
using V = G::vertex_descriptor;
using E = G::edge_descriptor;
int main() {
G g;
V v1 = add_vertex(g);
V v2 = add_vertex(g);
E e1 = add_edge(v1, v2, g).first;
// or:
auto [ed, inserted] = add_edge(v1, v2, g);
std::cout << "Second insertion happened: " << std::boolalpha << inserted << "\n";
print_graph(g);
}
Output:
Second insertion happened: true
0 --> 1 1
1 -->
Now, let's immediately show the effect of setS as edge storage:
using G = boost::adjacency_list<boost::setS>;
Output becomes - because the setS doesn't admit duplicate out-edges:
Second insertion happened: false
0 --> 1
1 -->
Now, let's also try a different vertex container selector?
using G = boost::adjacency_list<boost::setS, boost::listS>;
Uhoh, now there is trouble printing the graph, because, as you might have read already in the linked documentation:
If the VertexList of the graph is vecS, then the graph has a builtin vertex indices accessed via the property map for the vertex_index_t property. The indices fall in the range [0, num_vertices(g)) and are contiguous. When a vertex is removed the indices are adjusted so that they retain these properties. Some care must be taken when using these indices to access exterior property storage. The property map for vertex index is a model of Readable Property Map.
If you use listS then there is no implicit vertex index. Of course, we can add an index, but let's instead add a name property to our vertex.
There are many ways to add properties, but let me show you the more versatile/friendly version: bundled properties:
struct VertexProps {
std::string name;
};
using G = boost::adjacency_list<boost::setS, boost::listS, boost::undirectedS, VertexProps>;
Now, all we need to do is tell print_graph to use the name property from the bundle instead of the vertex index (which isn't usable for printing since listS):
print_graph(g, get(&VertexProps::name, g));
Of course, it becomes nicer when you actually give the vertices names:
V v1 = add_vertex(VertexProps{"v1"}, g);
V v2 = add_vertex(VertexProps{"v2"}, g);
But of course, names can be changed:
g[v2].name += "(changed)";
See it all together: Live
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graph_utility.hpp>
struct VertexProps {
std::string name;
};
using G = boost::adjacency_list<boost::setS, boost::listS, boost::undirectedS, VertexProps>;
using V = G::vertex_descriptor;
using E = G::edge_descriptor;
int main() {
G g;
V v1 = add_vertex(VertexProps{"v1"}, g);
V v2 = add_vertex(VertexProps{"v2"}, g);
E e1 = add_edge(v1, v2, g).first;
// or:
auto [ed, inserted] = add_edge(v1, v2, g);
g[v2].name += "(changed)";
std::cout << "Second insertion happened: " << std::boolalpha << inserted << "\n";
print_graph(g, get(&VertexProps::name, g));
}
Prints
Second insertion happened: false
v1 <--> v2(changed)
v2(changed) <--> v1
¹ You may not need to copy anything at all, just adapt/use the existing graph)

Related

Implementing Graph Program

I was trying to implement graph via adjacency matrix using arrays.
But I stumbled upon an issue
My graph has vertices like 5,7,3,6 (they are not in order to map to array index).
I know to implement then is they are same as array indices.
I thought to make another lookup array, with vertices and array indices.
But that will make it have high time complexity.
I tried searching on Google too, but all I found was for array indices.
Any suggestion will be helpful adjacency list or matrix
I can think of two straight-forward options:
1. Vertex Tagging
For each vertex you read, identify it with a tag. In your case:
vertex | tag
-------|-----
5 | 0
7 | 1
3 | 2
6 | 3
In order to have a good performance doing this, you should map the vertices with a unordered_map (or hash map) in direct and inverse order, so that when you are given a vertex, you can get its tag in O(1) with forward[vertex] and when you are given a tag, you can find its vertex in O(1) with backwards[tag]:
int tag = 0;
unordered_map<int, int> forward, backwards;
for(int v : vertices){
forward[v] = tag;
backwards[tag] = v;
tag++;
}
Lastly, represent your graph as an adjacency list just as you know, using the tags, that are 0, 1, ..., n - 1.
2. Direct Mapping
This is easier. Instead of using an array for your vertices, use an unordered_map that maps a vertex value to its adjacency list:
unordered_map<int, vector<int>> G;
for(int v : vertices){
G[v] = vector<int>();
vector<int> &adj = G[v];
//add all nodes adjacent to v in adj
}
If you want to iterate through the adjacency list of 5, just do:
vector<int> &adjList = G[5];
for(int v : adjList){
//stuff
}

Related to Graph daa structure

Could anyone please differentiate between implicit graph and explicit graph.Actually i tried to read Wikipedia page related to this topic but got confused.
An explicit graph is an explicitly defined graph, where we know how many nodes and edges are present and which nodes have an edge between them.
An implicit graph is not explicitly defined, meaning we don't know about it's nodes and edges instead we are building the graph as we go in some process.
Which is very commonly in a backtrack search.
For example: A simple backtrack for generating all subsets of a set {A, B, C}
#include <iostream>
using namespace std;
char elements[4]= "ABC";
void powerSet(int n, string subset){
if(n < 0){
cout<< subset <<endl;
return;
}
powerSet(n-1, subset);
powerSet(n-1, subset+ elements[n]);
}
int main(){
powerSet(2, string(""));
}
We don't have any graph defined yet we're constructing and using the following tree: (the recursion tree isn't the exact for the code above but it is very similar )
/ \
/ \
a {}
/ \ / \
b {} b {}
/ \ / \ / \ /\
c {} c {} c {} c {}
abc ab ac a bc b c {empty} :We get these subsets

Boost minimum spanning tree with some edges included/excluded

I'm trying to implement the list of all possible spanning trees of a graph in order of increasing cost. I'm using the algorithm by Sorensen and Janssens (2005). The graph is initialized as follows:
typedef property<edge_weight_t, int> EdgeWeightProperty;
typedef adjacency_list<vecS, vecS, undirectedS, no_property, EdgeWeightProperty> Graph;
typedef Graph::edge_descriptor Edge;
typedef Graph::vertex_descriptor Vertex;
typedef boost::graph_traits<Graph>::edge_iterator EdgeIterator;
typedef std::pair<EdgeIterator, EdgeIterator> EdgePair;
Graph g;
add_edge(1, 2, 3, g);
add_edge(1, 3, 1, g);
add_edge(1, 4, 2, g);
add_edge(2, 3, 3, g);
add_edge(2, 4, 1, g);
After this it's necessary to find the minimum spanning tree of a graph with some limitations, for instance Edge(2)-(4) shouldn't be in MST and Edge(1)-(2) should be there.
For the edge exclusion it's possible to use remove_edge_if(..) to delete the edge from the graph.
template<typename WMap>
class Remover
{
public:
Remover(const WMap& weights, int threshold)
: m_weights(weights), m_threshold(threshold) {}
template<typename ED>
bool operator()(ED w) const { return m_weights[w] <= m_threshold; }
private:
const WMap& m_weights;
int m_threshold;
};
....
// remove edges of weight < 1
Remover< property_map<Graph, edge_weight_t>::type> r(get(edge_weight, g), 1);
remove_edge_if(r, g);
....
std::list < Edge > spanning_treeT;
kruskal_minimum_spanning_tree(g, std::back_inserter(spanning_treeT));
But how should I ensure that one of the edges is always in the spanning tree? I was trying just to add some Edge into output of the Kruskal function, but it didn't work apparently. It yields MST of the graph + added edge:
std::list < Edge > spanning_tree_g2;
Vertex u, v;
EdgePair ep = edges(g2);
u = source(*ep.first, g2);
v = target(*ep.first, g2);
Edge ed = edge(u, v, g2).first;
spanning_tree_g2.push_front(ed);
kruskal_minimum_spanning_tree(g2, std::back_inserter(spanning_tree_g2));
Is it possible to mark the edges in a way that Kruskal algorithm knows what to include and what not to?
I seems you could force the inclusion of a certain edge by splitting this edge and inserting two "artificial" vertices in the middle.
The MST algorithm is already required to produce a tree of edges that covers all vertices.
Because the artifical vertices have been purposely added by you, it's easy to make sure it's never reachable using any other edges.
Before:
------------------[e:w1+w2]------------------
After:
----[e1:w1]---(v1)---[em:0]---(v2)---[e2:w2]----
(where v1 and v2 are the vertices inserted).
After the fact you "collapse" any sequence of (e1,em,e2) or (e2,em,e1) into (e).
You might end up with a tree that reaches v1 and v2 but never traverses em. In that case you can simply drop one of e1 and e2 and replace it with e unconditionally.

What does boost::out_edges( v, g ) in Boost.Graph do?

I am not able to comprehend the documentation for this function, I have seen several times the following
tie (ei,ei_end) = out_edges(*(vi+a),g);
**g**<-graph
**vi**<-beginning vertex of graph
**a**<- a node
**ei and ei_end** <- edge iterators
What does the function return,and what does it do,when could I use?
Can I find all edges from a node for example?
Provides iterators to iterate over the out-going edges of node u from graph g, e.g.:
typename graph_traits < Graph >::out_edge_iterator ei, ei_end;
for (boost::tie(ei, ei_end) = out_edges(u, g); ei != ei_end; ++ei) {
auto source = boost::source ( *ei, g );
auto target = boost::target ( *ei, g );
std::cout << "There is an edge from " << source << " to " << target << std::endl;
}
where Graph is your type definition of the graph an g is an instance of that. However, out_edges is only applicable for graphs with directed edges. The opposite of out_edges is in_edges that provides you iterators to compute in-coming edges of a node.
In an undirected graph both out_edges and in_edges will return all the edges connecting to the node in question.
However, more information can be easily found on http://www.boost.org/doc/libs/1_55_0/libs/graph/doc/graph_concepts.html or just in the Boost.Graph examples/tests.
As explained above, for a directed graph, out_edges accepts a "vertex_descriptor and the graph(adjacency list) to be examined" and returns "all the edges that emanate (directed from) the given vertex_descriptor", by means of an iterator-range.
As described in https://www.boost.org/doc/libs/1_69_0/libs/graph/doc/adjacency_list.html
std::pair<out_edge_iterator, out_edge_iterator>
out_edges(vertex_descriptor u, const adjacency_list& g)
Returns an iterator-range providing access to the out-edges of vertex
u in graph g. If the graph is undirected, this iterator-range provides
access to all edges incident on vertex u. For both directed and
undirected graphs, for an out-edge e, source(e, g) == u and target(e,
g) == v where v is a vertex adjacent to u.
In short, to answer some of your questions,
Yes, you can use it to find all edges from a node.
For undirected graphs, the behavior is as explained in the link above, it returns all the edges incident on the vertex (all edges connected to it)

Correlation Network Implementation

I have been working on my graph/network problem, and I think I finally know what I want to do. Now that I am getting into the implementation, I am having issues deciding what libraries to use. The graph itself is pretty simple, each node is labeled by a string, and each each is a probability/correlation coefficient between the two nodes(variables), and is undirected. The operations that I want to perform on the graph are:
Inserting new nodes/edges (fast)
Finding the all pairs shortest (1/probability) path, and remembering the nodes in the path - probably Johnson's algorithm
Constructing the minimum weight Steiner tree for k specific vertices
Use Johnson's algorithm to build shortest paths
Iterating over the current nodes in the path p, find the shortest route to the remaining nodes in k
Looking at the mean degree of the graph
Evaluating the betweenness of the nodes
Getting the clustering coefficients
Finding the modularity of the graph
For many of these, I want to compare the result to the Erdos-Renyi model, testing against it as a null hypothesis. Also, being able to be able to use the statistical mechanics definitions via a Markov Field would be helpful, as then I could calculate correlations between two nodes that are not identical, and ask the graph questions about the entropy, etc. So a good mapping onto a Markov field library of some sort would be useful too.
The crux of the problem at the moment is that I am trying to find a C++ library to work in. I have taken a look at R, but I want something that is going to be more robust and faster. The three libraries that I am considering are:
LEMON
Easy to use and install
Straightforward documentation
Has some of the functions I want already
Dynamically creating a graph from reading in a text file, and making sure there are no duplicate nodes, is a nightmare that I have not been able to figure out
Boost Graph Library
Intractable, arcane definitions for objects, and how to use them
Documentation does not match what the code does, necessarily
Does have many of the algorithms that I want, as well as a very easy way to create a graph from a text file
MultiThreaded Graph Library
Parallelism already incorporated
Reads easier than the BGL
Not as many functions
Still arcane
Further down the road, I envision the graph living on a distributed network, with distributed storage (hadoop or something). I suspect that the whole graph will not fit into memory, and so I will have to come up with a caching scenario to look at parts of the graph.
What library would people suggest for the problem that I described? Would it be better to just use the BGL, and write my own functions? What about the multi-threaded version? Are there any libraries that lend themselves more readily to the type of work I want to do, especially the quantities I want to compute?
Original Post
Thanks!
Edit1
So I am seriously frustrated by the BGL. I have an adjacency list graph, and I want to run my own version of the Johnson's (or Floyd's, at this point, I am not picky) on the graph, and return the Distance Matrix for me to look at. Except that I can't get it to work. Here is my full code implementation thus far:
using namespace boost;
int main()
{
//Read in the file
std::ifstream datafile("stuff");
if (!datafile)
{
std::cerr << "No Stuff file" << std::endl;
return EXIT_FAILURE;
}
//Build the graph
typedef adjacency_list < vecS, vecS, undirectedS, property < vertex_name_t,
std::string >, property < edge_weight_t, double > > Graph;
Graph g;
//Build the two properties we want, string and double
//Note, you have to nest properties for more
typedef property_map< Graph, vertex_index_t >::type vertex_index_map_t;
vertex_index_map_t vertex_index_map = get(vertex_index, g);
typedef property_map < Graph, vertex_name_t >::type name_map_t;
name_map_t name_map = get(vertex_name, g);
typedef property_map < Graph, edge_weight_t >::type probability_map_t;
probability_map_t probability = get(edge_weight, g);
//Map of of the vertices by string
typedef graph_traits < Graph >::vertex_descriptor Vertex;
typedef std::map < std::string, Vertex > NameVertexMap;
NameVertexMap AllNodes;
//Load the file into the graph
for (std::string line; std::getline(datafile, line);)
{
char_delimiters_separator < char >sep(false, "", ";");
tokenizer <> line_toks(line, sep);
tokenizer <>::iterator i = line_toks.begin();
std::string conditionA = *i++;
NameVertexMap::iterator pos;
bool inserted;
Vertex u, v;
boost::tie(pos, inserted) = AllNodes.insert(std::make_pair(conditionA, Vertex()));
if (inserted)
{
u = add_vertex(g);
name_map[u] = conditionA;
pos->second = u;
}
else
{
u = pos->second;
}
std::string correlation = *i++;
std::istringstream incorrelation(correlation);
double correlate;
incorrelation >> correlate;
boost::tie(pos, inserted) = AllNodes.insert(std::make_pair(*i, Vertex()));
if (inserted) {
v = add_vertex(g);
name_map[v] = *i;
pos->second = v;
}
else
{
v = pos->second;
}
graph_traits < Graph >::edge_descriptor e;
boost::tie(e, inserted) = add_edge(u, v, g);
if (inserted)
probability[e] = 1.0/correlate;
}
typedef boost::graph_traits<Graph>::edge_iterator edge_iter;
std::pair<edge_iter, edge_iter> edgePair;
Vertex u, v;
for(edgePair = edges(g); edgePair.first != edgePair.second; ++edgePair.first)
{
u = source(*edgePair.first, g);
v = target(*edgePair.first, g);
std::cout << "( " << vertex_index_map[u] << ":" << name_map[u] << ", ";
std::cout << probability[*edgePair.first] << ", ";
std::cout << vertex_index_map[v] << ":" << name_map[v] << " )" << std::endl;
}
}
Where the input file is of the format NodeA;correlation;NodeB. The code that I pasted above works, but I get into serious trouble when I attempt to include the johnson_all_pairs_shortest_paths functionality. Really what I want is not only a DistanceMatrix D (which I cannot seem to construct correctly, I want it to be a square matrix of doubles double D[V][V], V = num_vertices(g), but it gives me back that I am not calling the function correctly), but also a list of the nodes that were taken along that path, similar to what the wiki article has for Floyd's Algorithm path reconstruction. Should I just make the attempt to roll my own algorithm(s) for this problem, since I can't figure out if the functionality is there or not (not to mention how to make the function calls)? The documentation for the BGL is as obtuse as the implementation, so I don't really have any modern examples to go on.

Resources