How to use Boost MST Algorithm on a complete Graph [closed] - c++

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
I am very new to the BGL. I have the following problem: I've got a very large complete Graph and weights for every edge and need to evaluate a Minimum Spanning Tree.
I would like to use the Boost Graph Libraries implementation. What structures should I use to represent my complete graph and how would I call the Algorithm? Also I'd like to store the resulting subgraph in some graph structure so that I can perform different operations on the MST afterwards.
Thank you very much.

Here's a simple example. I'd suggest an adjacency matrix since the graph is going to be complete, so the matrix is very dense.
using Graph =
boost::adjacency_matrix<boost::undirectedS, boost::no_property,
boost::property<boost::edge_weight_t, double>>;
using Vertex = Graph::vertex_descriptor;
using Edge = Graph::edge_descriptor;
Now let's create a graph
int main() {
Graph g(23);
Picking an arbitrary number (23) of vertices for this example. Let's use randomly generated weights:
auto weight_distribution = std::bind(
std::lognormal_distribution<>{0, 0.25},
std::mt19937{std::random_device{}()});
Creating all the edges to make the graph complete:
for (Vertex v = 0; v < num_vertices(g); ++v)
for (Vertex u = v + 1; u < num_vertices(g); ++u)
add_edge(v, u, 100*weight_distribution(), g);
Now, let's use Prim's algorithm (since all the weights are non-negative):
std::vector<Vertex> parent(num_vertices(g));
prim_minimum_spanning_tree(g, parent.data());
This writes the predecessor for each vertex in the parent vector (which is called the predecessor map).
Adding Some Output
For more interesting results, let's add some checks and output:
assert(std::ranges::all_of(
make_iterator_range(edges(g)),
[ew = get(boost::edge_weight, g)](auto e) { return ew[e] > 0; }));
Making sure the data satisfies the weight pre-condition. You might also do a completeness check depending on how you get your input data.
std::vector<Vertex> parent(num_vertices(g));
std::map<Vertex, double> distance;
auto root = vertex(0, g); // or just 0
Let's pass the optional arguments distance_map and root_vertex:
prim_minimum_spanning_tree(g, parent.data(),
boost::root_vertex(root)
.distance_map(boost::make_assoc_property_map(distance)));
That uses named parameters (starting with boost::root_vertex and chaining with .other_parameter(...).even_more(...). You can of course start with any named parameter).
Now we can use the recorded data:
double total_path_weight = 9;
for (Vertex v = 0; v < num_vertices(g); ++v) {
auto p = parent[v];
auto weight = distance[v];
std::cout << p << " -> " << v << " weight " << weight
<< (p == v ? " ROOT" : "") << "\n";
total_path_weight += weight;
}
std::cout << "Total path weight " << total_path_weight << "\n";
DEMO
Live On Coliru
#include <boost/graph/adjacency_matrix.hpp>
#include <boost/graph/prim_minimum_spanning_tree.hpp>
#include <random>
#include <iostream>
using Graph =
boost::adjacency_matrix<boost::undirectedS, boost::no_property,
boost::property<boost::edge_weight_t, double>>;
using Vertex = Graph::vertex_descriptor;
using Edge = Graph::edge_descriptor;
using boost::make_iterator_range;
int main() {
Graph g(23);
auto weight_distribution = std::bind(std::lognormal_distribution<>{0, 0.25},
std::mt19937{std::random_device{}()});
for (Vertex v = 0; v < num_vertices(g); ++v)
for (Vertex u = v + 1; u < num_vertices(g); ++u)
add_edge(v, u, 100*weight_distribution(), g);
assert(std::ranges::all_of(
make_iterator_range(edges(g)),
[ew = get(boost::edge_weight, g)](auto e) { return ew[e] > 0; }));
std::vector<Vertex> parent(num_vertices(g));
std::map<Vertex, double> distance;
auto root = vertex(0, g); // or just 0
prim_minimum_spanning_tree(g, parent.data(),
boost::root_vertex(root)
.distance_map(boost::make_assoc_property_map(distance)));
double total_path_weight = 9;
for (Vertex v = 0; v < num_vertices(g); ++v) {
auto p = parent[v];
auto weight = distance[v];
std::cout << p << " -> " << v << " weight " << weight
<< (p == v ? " ROOT" : "") << "\n";
total_path_weight += weight;
}
std::cout << "Total path weight " << total_path_weight << "\n";
}
Printing e.g.
0 -> 0 weight 0 ROOT
15 -> 1 weight 64.6241
21 -> 2 weight 62.1609
1 -> 3 weight 69.207
5 -> 4 weight 71.9255
2 -> 5 weight 68.3983
14 -> 6 weight 66.6639
17 -> 7 weight 69.5045
20 -> 8 weight 78.9941
6 -> 9 weight 69.3287
4 -> 10 weight 62.7512
0 -> 11 weight 65.9305
15 -> 12 weight 70.2627
4 -> 13 weight 67.9708
22 -> 14 weight 73.3816
14 -> 15 weight 61.069
6 -> 16 weight 63.5795
5 -> 17 weight 66.0981
6 -> 18 weight 54.6061
14 -> 19 weight 73.9725
5 -> 20 weight 74.7002
0 -> 21 weight 71.8757
17 -> 22 weight 68.6378
Total path weight 1504.64

Related

How does this creation of graph using stl library work?

I have a doubt in a line given below of this code:
cout<<"("<<c<<","<<(*i).get_vertex()<<") value of this pair : "<<(*i).get_weight()<<", ";
How this get_vertex and get_weight work without the help of class edge object. The code compiled successfully and it's working too but I can't figure out how the above line is working.
Output of the code is:
Pairs for 0 are -> (0,1) value of this pair : 2, (0,2) value of this pair : 3, (0,3) value of this pair : 4,
Pairs for 1 are -> (1,2) value of this pair : 5, (1,0) value of this pair : 2,
Pairs for 2 are -> (2,3) value of this pair : 8, (2,1) value of this pair : 5,
Pairs for 3 are -> (3,0) value of this pair : 4, (3,2) value of this pair : 8,
Code is given below:
#include<bits/stdc++.h>
using namespace std;
class edge{
int weight,vertex;
public:
edge(int w , int v){
weight = w;
vertex = v;
}
int get_weight()const{
return weight;
}
int get_vertex()const{
return vertex;
}
};
int main(){
int n = 4;
int c = 0;
vector<list<edge>>adj(n) ;
adj[0].push_back(edge(2,1));
adj[0].push_back(edge(3,2));
adj[0].push_back(edge(4,3));
adj[1].push_back(edge(5,2));
adj[1].push_back(edge(2,0));
adj[2].push_back(edge(8,3));
adj[2].push_back(edge(5,1));
adj[3].push_back(edge(4,0));
adj[3].push_back(edge(8,2));
vector<list<edge>>:: iterator it ;
for(it=adj.begin();it!=adj.end();it++){
cout<<" Pairs for "<<c<<" are -> ";
list<edge>li = *it;
list<edge>::iterator i;
for(i=li.begin();i!=li.end();i++){
cout<<"("<<c<<","<<(*i).get_vertex()<<") value of this pair : "<<(*i).get_weight()<<", ";
}
cout<<endl;
c++;
}
}
Break it into chunks.
Add whitespace:
cout << "("
<< c
<< ","
<< (*i).get_vertex()
<< ") value of this pair : "
<< (*i).get_weight()
<< ", ";
Does that make more sense?

Boost graph: Iterating through all vertices and printing adjacent vertices

I want to print all vertices with their adjacent vertices. I found some examples online on how to do that, yet it won't work for me. I am getting the error, that the ++ operator cannot be used on ai. Also I think it needs to be vertex_idMap[*ai] and not vertex_idMap[ai] but this prompts an error. Does anyone know why this is wrong?
typedef adjacency_list<vecS, listS, directedS, VertexIDPorperty, EdgeWeight> Graph; //the type of g
graph_traits <Graph>::vertex_iterator i, end;
graph_traits <Graph>::adjacency_iterator ai, a_end;
for (boost::tie(i, end) = vertices(g); i != end; ++i) {
std::cout << vertex_idMap[*i];
for (; ai != a_end; ++ai) { //the ++ai seems to be wrong?
std::cout << vertex_idMap[ai];
if (boost::next(ai) != a_end)
std::cout << ", ";
}
std::cout << std::endl;
Observations:
Where's the rest of the code? It obviously depends on the types used.
ai and a_end aren't initialized (perhaps you didn't actually mean the code doesn't compile, and this was your whole problem)
vertex_idMap[ai] will not compile, as a vertex_iterator is not a valid vertex_descriptor
Here's a fixed example with the missing bits imagined:
Live On Coliru
#include <boost/graph/adjacency_list.hpp>
#include <iostream>
using VertexIDPorperty = boost::property<boost::vertex_index_t, int>;
using EdgeWeight = boost::property<boost::edge_weight_t, double>;
typedef boost::adjacency_list<boost::vecS, boost::listS, boost::directedS, VertexIDPorperty, EdgeWeight> Graph;
Graph sample();
int main() {
Graph g = sample();
auto vertex_idMap = get(boost::vertex_index, g);
boost::graph_traits <Graph>::vertex_iterator i, end;
boost::graph_traits <Graph>::adjacency_iterator ai, a_end;
for (boost::tie(i, end) = vertices(g); i != end; ++i) {
std::cout << vertex_idMap[*i] << ": ";
for (boost::tie(ai, a_end) = adjacent_vertices(*i, g); ai != a_end; ++ai) {
std::cout << vertex_idMap[*ai];
if (boost::next(ai) != a_end)
std::cout << ", ";
}
std::cout << std::endl;
}
}
Implementing sample() to create a random graph:
#include <boost/graph/random.hpp>
#include <random>
Graph sample() {
Graph g;
std::mt19937 prng { std::random_device{}() };
generate_random_graph(g, 10, 20, prng);
int id = 0;
for (auto vd : boost::make_iterator_range(vertices(g))) {
put(boost::vertex_index, g, vd, ++id);
}
return g;
}
It prints something like:
1: 9, 9, 4
2: 6
3:
4:
5: 9, 9, 8, 9
6: 9, 3, 1
7: 2, 10
8: 6
9: 8
10: 7, 3, 8, 1, 4
Out Of The Box
Printing a graph can be done simpler:
#include <boost/graph/graph_utility.hpp>
// ...
int main() {
print_graph(sample());
}
Live On Coliru
1 -->
2 --> 3 10 9 6 6 10
3 --> 8
4 -->
5 --> 4
6 --> 1 5 8
7 --> 4 9 2 2 1
8 --> 6
9 --> 5 7
10 --> 7

Parallelizing Boruvka with openMP

I have implemented Boruvka's algorithm sequentially in C++ and I know one of the advantages of the algorithm is that it can easily be paralleled. I am trying to do this using openMP, but I can't figure out how to get it to work. I read in an adjacency list from graph.txt and print my output of the minimum spanning tree into mst.txt. Here is my sequential code for boruvka:
#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;
// initialize data structure for edges (given in adjacency list)
struct Edge {
int v1, v2, weight; // 2 connecting verticies and a weight
};
// initialize structure for the graph
struct Graph {
int vertex, edge;
Edge* e; // undirected graph so edge from v1 to v2 is same as v2 to v1
};
// Creates a graph for #verticies and #edges using arrays
struct Graph* formGraph(int vertex, int edge)
{
Graph* graph = new Graph;
graph->vertex = vertex;
graph->edge = edge;
graph->e = new Edge[edge]; // again, v1-v2 = v2-v1
return graph;
}
// initialize structure for subsets within the graph
struct Subset {
int parent, rank; // rank will act as counter
};
// will help to find lightest edge of sets recursively
int find(struct Subset subset[], int i)
{
if (subset[i].parent != i) {
subset[i].parent = find(subset, subset[i].parent);
}
// once it is =1
return subset[i].parent;
}
// A function that does union of two sets
void Union(struct Subset subs[], int set1, int set2)
{
int root1 = find(subs, set1);
int root2 = find(subs, set2);
//union by ranking
if (subs[root1].rank < subs[root2].rank) { // if rank2 is higher thats parent
subs[root1].parent = root2;
}
else if (subs[root1].rank > subs[root2].rank) { // if rank1 is higher thats parent
subs[root2].parent = root1;
}
else // ranks are the equal so increment rank by 1
{
subs[root2].parent = root1;
subs[root1].rank++;
}
}
// the boruvka algorithm implementation
void boruvka(struct Graph* graph) {
// set data of initial graph
int vertex = graph->vertex;
int edge = graph->edge;
Edge* e = graph->e;
//initially there will always be as many subsets as there are vertices
struct Subset *subs = new Subset[vertex];
int *lightest = new int[vertex]; // array storing least weight edge
// subset for each vertex
for (int v = 0; v < vertex; v++)
{
subs[v].parent = v; // initial parent (none)
subs[v].rank = 0; // initial rank (no parent so always 0)
lightest[v] = -1; // start from -1
}
int components = vertex; // iniitial trees = number of verticies
int minWeight = 0;
// must keep going until there is only one tree
while (components > 1)
{
// lightest weight for all edges
for (int i=0; i<edge; i++)
{
// gets subsets for edges that could connect
int set1 = find(subs, e[i].v1);
int set2 = find(subs, e[i].v2);
// waste of time if they're already in same set so don't check
if (set1 == set2)
continue;
// if different then check which one is lightest
else
{
if (lightest[set1] == -1 || e[lightest[set1]].weight > e[i].weight) {
lightest[set1] = i;
}
if (lightest[set2] == -1 || e[lightest[set2]].weight > e[i].weight) {
lightest[set2] = i;
}
}
}
// making sure the wieghts are added
for (int i=0; i<vertex; i++)
{
// make sure all lightest edges are included
if (lightest[i] != -1)
{
int s1 = find(subs, e[lightest[i]].v1);
int s2 = find(subs, e[lightest[i]].v2);
if (s1 == s2)
continue;
minWeight += e[lightest[i]].weight;
// Need to sort output lexicographically!?!?!?!?!!
printf("Edge %d-%d included in MST with weight %d\n", // prints verices and weight of edge
e[lightest[i]].v1, e[lightest[i]].v2,
e[lightest[i]].weight);
// union subsets together, decrease component number
Union(subs, s1, s2);
components--;
}
lightest[i] = -1; // in case after first iteration lightest edges fall in same subset
}
}
printf("Weight of MST is %d\n", minWeight);
return;
}
// main function for calling boruvka
int main() {
ifstream infile;
char inputFileName[] = "graph.txt"; // input filename here
infile.open(inputFileName, ios::in);
string line;
getline(infile, line);
int V = atoi(line.c_str()); // set num of vertices to first line of txt
getline(infile, line);
int E = atoi(line.c_str()); // set num of edges to second line of txt
// create graph for boruvka
struct Graph* graph = formGraph(V, E);
if (infile.is_open()) {
string data[3]; // initialize data array
int count = 0; // initialize counter
while (infile.good()) { // same as while not end of file
getline(infile, line);
stringstream ssin(line);
int i = 0;
while (ssin.good() && i < 3) {
ssin >> data[i];
i++;
}
graph->e[count].v1 = atoi(data[0].c_str());
graph->e[count].v2 = atoi(data[1].c_str());
graph->e[count].weight = atoi(data[2].c_str());
count++;
}
}
freopen("mst.txt","w",stdout); // writes output into mst.txt
// call boruvka function
boruvka(graph);
infile.close(); // close the input file
return 0;
}
An example of my graph.txt is this:
9
14
0 1 4
7 8 7
1 2 8
1 7 11
2 3 7
2 5 4
2 8 2
3 4 9
3 5 14
4 5 10
5 6 2
6 7 1
6 8 6
0 7 8
The output for this example which is correct that is placed in my mst.txt is this:
Edge 0-1 included in MST with weight 4
Edge 2-8 included in MST with weight 2
Edge 2-3 included in MST with weight 7
Edge 3-4 included in MST with weight 9
Edge 5-6 included in MST with weight 2
Edge 6-7 included in MST with weight 1
Edge 1-2 included in MST with weight 8
Edge 2-5 included in MST with weight 4
Weight of MST is 37
According to the algorithm, in each iteration, each tree in the forest will have one and only one edge added to the forest independently (edges from different trees could be the same), until the added edges connect the whole forest into a single tree.
Here you can see finding the only edge for each tree can be done in parallel. As long as you have more than one tree, you could use multiple threads to speed up the searching.
if you're interested, I've written an implementation of the parallel Boruvka's algorithm using OpenMP.
We store the graph as an edge list (edges) where each edge (u, v) appears twice: as an edge from u and from v. At each step of the algorithm, edges is sorted in O(E log E) = O(E log V) time.
Then edges are split between P processors. Each one of them calculates the array of shortest edges from its local nodes. Because allocating raw memory for all nodes is done in constant time, we can simply store this as an array and avoid using hashmaps. Then we merge the results between processors into a global shortest edge array using compare and swap. Note that because we sorted the edge list previously, all edges from u make up a continuous segment in edges. Because of this, the total number of extra iterations in the cas loop does not exceed O(P) which gives us O(E / P + P) = O(E / P) time for this step.
After that, we can merge components along the added edges in O(V * alpha(V) / P) time using a parallel DSU algorithm.
The next step is updating the list of vertices and edges, this can be done using parallel cumulative sum in O(V / P) and O(E / P) respectively.
Since the total number of iterations is O(log V), the overall time complexity is O(E log^2 V / P).

Dijkstra's Algorithm - Infinite Loop

As a homework assignment, I am to implement an adjacency list using an array of pointers to linked lists for each vertex. Each linked list has an element <destination> that states the vertex neighbor of adjacency list vertex.
The adjacency list is undirected and unweighted, so I am treating all weights as 1.
/* Adjacency List Node data structure (edge)
* Linked List data structure for storing linked vertices
*/
struct adjacencyListNode
{
int destination;
struct adjacencyListNode *next;
};
/* Adjacency List Vertex data structure (vertex)
* <AdjacencyList> consists of pointers to <n> adjacencyListVertex
*/
struct adjacencyListVertex
{
struct adjacencyListNode *head;
};
I am trying to perform Dijkstra's Algorithm on the adjacency list to find the minimum path from s to t.
Right now I am implementing the following algorithm:
/* Prints the length and path taken of the shortest path in adjacency list between s and t.
* Uses Dijkstra’s algorithm to compute shortest path.
* S: source vertex
* V: destination vertex
*/
void shortestPath(int s, int t) {
int known[size]; // shortest distance to vertex is know
int cost[size]; // distance from source <s> to each vertex
int path[size]; //path
// Initialization: Set all distances to infinity (represented by -1), since arrays have not been visited and graph is positively weighted
for (int index = 0; index<size; index++) {
cost[index] = INFINITY;
known[index] = 0;
}
// Set distance from source->source to 0
cost[s-1] = 0;
// Starting at s, traverse towards all reachable unvisited verticies, visit it and repeat
while (isFinished(known, size) == false) {
// Select a vertex from list of unvisited nodes which has the smallest cost
int cheapestVertex, cheapestValue = INFINITY+1;
for (int costCheck = 0; costCheck<size; costCheck++) {
if ((known[costCheck] == 0) && (cost[costCheck] < cheapestValue)) {
// We found a cheaper unvisited vertex
// cout << "Cheapest vertex: " << costCheck << endl;
cheapestVertex = costCheck;
cheapestValue = cost[cheapestVertex];
}
// cout << "found? " << cheapestVertex << " " << cheapestValue << endl;
}
// cout << "Cheapest vertex: " << cheapestVertex << endl;
// For each unvisited neighbor of our cheapest (unvisited) vertex
adjacencyListNode* iterator = A[cheapestVertex].head; // iterator is our first neighbor
while (iterator)
{
// Calculate the new cost from the current vertex <cheapestVertex>
if (cost[cheapestVertex]+1 < cost[iterator->destination] && known[iterator->destination] == 0) {
cost[iterator->destination] = cost[cheapestVertex]+1;
}
iterator = iterator->next; // move to next neighbor, repeat
}
// cout << "Cheapest vertex: " << cheapestVertex << " known." << endl;
// Mark the current vertex <cheapestVertex> as visited
known[cheapestVertex] = 1;
// DEBUG: (REMOVE BEFORE SUBMISSION)
for (int i = 0; i<size; i++) {
cout << "Vertex " << i << " : known? " << known[i] << ", cost? " << cost[i] << endl;
}
cout << endl;
if (cost[t-1] != INFINITY) break; // We already know shortest path, end.
}
// We know the shortest path cost to t
cout << "Cost to t: " << cost[t] << endl;
}
bool isFinished(int array[], int arraySize) {
bool finished = true;
for (int iterator=0; iterator < arraySize; iterator++) {
if (array[iterator] == 0) {
// vertex not known, we're not done.
finished = false;
}
}
return finished;
}
I am passing the following input, which just adds the stated related vertices and calls my shortest-path algorithm.
0 1
1 2
1 3
2 4
3 5
5 38
6 7
6 10
8 9
11 12
12 13
12 15
12 21
13 14
14 15
16 17
17 18
18 19
19 20
20 39
21 22
22 23
22 31
23 24
23 32
24 25
24 33
25 26
26 27
27 28
28 29
29 30
31 40
34 35
34 37
35 36
36 37
1
shortest-path
My code traverses from 0->1->2->3->4->5->38 and then repeats 38 infinitely.
Does anyone see where my issue is?
You have a few issues. As this is homework, I won't give you the full answers.
Issue 1: What happens if there are nodes that are unreachable from s? This is what is happening in your example.
Hint: You need to work out when to stop the loop (other than the one you have already). Look at your cheapest selection - how would you determine that there isn't a valid one?
Hint #2 - You current loop won't set a value for cheapestVertex if all remaining vertices have a cost of INFINITE, so you will be using an uninitialized value. Maybe check what the cheapest cost you found was before proceeding.
Issue 2: cost[iterator->destination] = cost[cheapestVertex]+1;
Hint: are you sure this is correct to do on every occasion? What if the node already has a cheaper cost, or has already been visited?
Issue 3: You can stop looking once you have t known. No need to check the whole graph. Note: This is an change that you don't necessarily need as your code will work without it.

graph levelization using BGL

Can you please post example code to levelize a directed graph using BGL?
Definition of levelization: Vertex has a property "int level". During BFS traversal of the graph, when a vertex is being "examined", look at its predecessor vertices' levels, take max of these, increment, and assign this to the "level" of this vertex.
If you mean the BFS depth then this is already built in to boost BFS and can be gotten easily.
Just use a vector to store the depths and a depth BFS visitor like this example I made:
#include <iostream>
#include <vector>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/breadth_first_search.hpp>
using namespace std;
using namespace boost;
typedef adjacency_list < vecS, vecS, directedS,
property< vertex_index_t, size_t> ,
property< edge_index_t, size_t > > Graph;
typedef graph_traits<Graph>::vertex_descriptor Vertex;
typedef graph_traits<Graph>::edge_descriptor Edge;
int main(int argc, char* argv[]){
Graph G;
vector<Vertex> verts;
for(size_t i = 0; i < 9; ++i){
Vertex v = add_vertex(G);
verts.push_back(v);
}
/*
0 0
/ \
1 1 4
/ \
2 2 5
/ \
3 3 6
\
4 7
\
5 8
*/
add_edge(verts.at(0),verts.at(1),G);
add_edge(verts.at(1),verts.at(2),G);
add_edge(verts.at(2),verts.at(3),G);
add_edge(verts.at(0),verts.at(4),G);
add_edge(verts.at(4),verts.at(5),G);
add_edge(verts.at(5),verts.at(6),G);
add_edge(verts.at(6),verts.at(7),G);
add_edge(verts.at(7),verts.at(8),G);
cout << "vertices " << num_vertices(G) << endl;
cout << "edges " << num_edges(G) << endl;
//store depths
vector<size_t> d(num_vertices(G));
//get an index map, from Graph definition property< vertex_index_t, size_t>
typedef boost::property_map< Graph, boost::vertex_index_t>::type VertexIndexMap;
VertexIndexMap v_index = get(boost::vertex_index, G);
// Create the external property map, this map wraps the storage vector d
boost::iterator_property_map< std::vector< size_t >::iterator, VertexIndexMap >
d_map(d.begin(), v_index);
//Start at 0
boost::breadth_first_search(G, verts.at(0),
boost::visitor(boost::make_bfs_visitor(
boost::record_distances(d_map, boost::on_tree_edge())
)));
cout << "Starting at 0" << endl;
for(size_t i = 0; i < 9; ++i){
//depth (level) of BFS
cout << "vertex " << i << "\t" << d.at(i) << endl;
}
vector<size_t> d2(num_vertices(G));
cout << "Starting at 4" << endl;
// Create the external property map, this map wraps the storage vector d
boost::iterator_property_map< std::vector< size_t >::iterator, VertexIndexMap >
d2_map(d2.begin(), v_index);
//start at 4
boost::breadth_first_search(G, verts.at(4),
boost::visitor(boost::make_bfs_visitor(
boost::record_distances(d2_map, boost::on_tree_edge())
)));
for(size_t i = 0; i < 9; ++i){
//depth (level) of BFS
cout << "vertex " << i << "\t" << d2.at(i) << endl;
}
}
Output should look like this:
vertices 9
edges 8
Starting at 0
vertex 0 0
vertex 1 1
vertex 2 2
vertex 3 3
vertex 4 1
vertex 5 2
vertex 6 3
vertex 7 4
vertex 8 5
Starting at 4
vertex 0 0
vertex 1 0
vertex 2 0
vertex 3 0
vertex 4 0
vertex 5 1
vertex 6 2
vertex 7 3
vertex 8 4
When you start at 4 the other vertices are not reachable (directed) so the vector contains default values (0 in this case). This should work for undirected too.