I want to have all edges have to properties, weight and capacity. I found that BGL has these both already defined. So I define Edge and Vertex properties for the Graph
typedef property<vertex_name_t, string> VertexProperty;
typedef property<edge_weight_t, int, property<edge_capacity_t, int> > EdgeProperty;
typedef adjacency_list<listS,vecS, undirectedS, VertexProperty, EdgeProperty > Graph;
Here is where I am trying to add the edges to the graph:
172: EdgeProperty prop = (weight, capacity);
173: add_edge(vertex1,vertex2, prop, g);
If I had just 1 property I know it would be prop = 5; However, with two I am confused about the formatting.
Here is the error I am receiving:
graph.cc: In function ‘void con_graph()’:
graph.cc:172: warning: left-hand operand of comma has no effect
If you look at the implementation of boost::property you'll see that a property value cannot be initialized this way. And even then, the syntax you have (weight, capacity) is not valid anyways, so, if it was possible to initialize the property like that, it would be written EdgeProperty prop = EdgeProperty(weight, capacity); or just EdgeProperty prop(weight, capacity);. But, again, that won't work. Technically, this is the way you would need to initialize the property value:
EdgeProperty prop = EdgeProperty(weight, property<edge_capacity_t, int>(capacity));
But this is kind of ugly as the number of properties increase. So, it would be cleaner to default-construct the edge-property and then manually set each individual property:
EdgeProperty prop;
get_property_value(prop, edge_weight_t) = weight;
get_property_value(prop, edge_capacity_t) = capacity;
Of course, the better alternative is to use bundled properties instead of the older boost::property chains.
The correct form is:
EdgeProperty prop;
get_property_value(prop, edge_weight) = weight;
get_property_value(prop, edge_capacity) = capacity;
Related
My actual intention is to use mcgregor_common_subgraphs to find some induced partial subgraphs. But it takes too long to compare small graphs. So instead of comparing the entire graphs I want to filter out a subset of comparable vertices and edges. Then find subgraphs between them.
So I use filtered_graph with vertex and edge predicates for both of these graphs. And pass the filtered graph to mcgregor_common_subgraphs. But it complains
error: use of deleted function ‘boost::iterators::filter_iterator<bya::util::isomorphism::directed_graph::vertex_filter_predicate, boost::range_detail::integer_iterator<long unsigned int> >& boost::iterators::filter_iterator<bya::util::isomorphism::directed_graph::vertex_filter_predicate, boost::range_detail::integer_iterator<long unsigned int> >::operator=(const boost::iterators::filter_iterator<bya::util::isomorphism::directed_graph::vertex_filter_predicate, boost::range_detail::integer_iterator<long unsigned int> >&)’
So I planned to copy the filtered graph into a new graph with copy_graph. But it complains that there is no default constructor for the vertex predicate vertex_filter_predicate.
error: no matching function for call to ‘bya::util::isomorphism::directed_graph::vertex_filter_predicate::vertex_filter_predicate()’
However my vertex and edge predicate takes a const reference to the original graph. So I cannot add an empty default constructor. I have searched in boost documentation, but didn't find any example of copying a filtered_graph. What is the solution ? Also why would copy_graph require the predicates to copy ?
struct directed_graph{
typedef boost::adjacency_list<boost::setS, boost::vecS, boost::bidirectionalS, vertex_data, edge_data> graph_type;
graph_type _graph;
// ...
};
I have a directed graph struct inside which I have the predicates and equivalance comparators. Both small and large are instances of directed_graph.
directed_graph::edge_filter_predicate edge_filter_small (small._graph, allowed_vertex_ids), edge_filter_large (large._graph, allowed_vertex_ids);
directed_graph::vertex_filter_predicate vertex_filter_small(small._graph, allowed_vertex_ids), vertex_filter_large(large._graph, allowed_vertex_ids);
boost::filtered_graph<directed_graph::graph_type, directed_graph::edge_filter_predicate, directed_graph::vertex_filter_predicate> filtered_small_view(small._graph, edge_filter_small, vertex_filter_small);
boost::filtered_graph<directed_graph::graph_type, directed_graph::edge_filter_predicate, directed_graph::vertex_filter_predicate> filtered_large_view(large._graph, edge_filter_large, vertex_filter_large);
directed_graph::graph_type filtered_small;
boost::copy_graph(filtered_small_view, filtered_small);
I'm a BGL newbie with a (possibly) easy question: I have a directed graph and use bundled properties for edges, one of them being an index of type int. Knowing a unique index, I would like to get the corresponding edge_descriptor of that edge in order to perform operations on it. The following example summarizes my problem:
#include <boost/graph/adjacency_list.hpp>
struct EdgeProperties {
EdgeProperties(): distance(10), time_limit(5) {};
int index;
int distance;
int time_limit;
};
typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, boost::no_property, EdgeProperties> Graph;
int main() {
Graph graph;
EdgeProperties edge_prop1, edge_prop2, edge_prop3, edge_prop4;
// Define edge properties
edge_prop1.index = 0;
edge_prop2.index = 1;
edge_prop3.index = 2;
edge_prop4.index = 3;
// Add edges to graph
boost::add_edge(0, 1, edge_prop1, graph);
boost::add_edge(0, 2, edge_prop2, graph);
boost::add_edge(1, 3, edge_prop3, graph);
boost::add_edge(2, 3, edge_prop4, graph);
// Get vertex_descriptor from an (int) index:
int vertex_index = 2;
boost::graph_traits<Graph>::vertex_descriptor v = boost::vertex(vertex_index, graph);
// I would like to get an edge_descriptor from an (int) index property:
// The following DOES NOT work:
boost::graph_traits<Graph>::edge_descriptor e = boost::edge(edge_prop1.index, graph);
}
I read about property maps as well, but could not find a solution my problem. I would prefer bundled properties over internal properties.
Is there a way of assigning unique int type indices via a bundle property to edges and access edges through these int type values?
Sadly, I don't think boost::graph is of immediate help here.
First, there is no mechanism to find an edge (or vertex, for that matter), based on a field of an edge property - BGL keeps any such mapping, and the 'index' field you have is entirely for your purposes.
Second, there is the boost::edges function that returns an iterator range for all edges of the graph. I though that you could pass vecS as edge container type to adjacency_list template, and then look inside this range, but per http://www.boost.org/doc/libs/1_61_0/libs/graph/doc/EdgeListGraph.html the iterators are only required to be multi-pass input iterators, and the implementation does exactly that -- even with vecS as edge type, you can't do random access.
Therefore, it seems that the only way to accomplish what you want is to keep your own unodered_map from index to edge descriptor.
I have an adjacency list defined as shown below. At this point I need to access vertex_descriptor as an int type. How can I do that tvertex source = ...; int source_as_int = ???source??? I remember bumping into this same question before and solved it but don't remember how and the BGL documentation is useless using it as reference, they should try to take a look at and learn from Javadocs.
Another possibility is to use a possible member function of the vertex_descriptor type or otherwise some of the global BGL functions for this purpose ... one never knows where to look for this and they seem to randomly choose between making global functions or member functions, a total fail of an intuitive design if you ask me.
typedef adjacency_list_traits<setS, setS, bidirectionalS> ttraits;
typedef adjacency_list<setS, setS, bidirectionalS,
// vertex properties
property<vertex_color_t, default_color_type>,
// edge properties
property<edge_capacity_t, int,
property<edge_residual_capacity_t, int,
property<edge_reverse_t, ttraits::edge_descriptor> > >, no_property, vecS> tbgl_adjlist_bidir;
typedef graph_traits<tbgl_adjlist_bidir>::vertex_descriptor tvertex;
typedef graph_traits<tbgl_adjlist_bidir>::edge_descriptor tedge;
typedef property_map<tbgl_adjlist_bidir, edge_capacity_t>::type tedge_capacity_map;
typedef property_map<tbgl_adjlist_bidir, edge_reverse_t>::type treverse_edge_map;
typedef property_map<tbgl_adjlist_bidir, vertex_color_t>::type tvertex_color_map;
typedef graph_traits<tbgl_adjlist_bidir>::out_edge_iterator tout_edge_iterator;
typedef graph_traits<tbgl_adjlist_bidir>::in_edge_iterator tin_edge_iterator;
OK I figured it out. Adding the vertex property vertex_index_t solves the problem. I can then access the int index of the vertex like this:
typedef adjacency_list_traits<setS, vecS, bidirectionalS> ttraits;
typedef adjacency_list<setS, vecS, bidirectionalS,
// vertex properties
property<vertex_index_t, int,
property<vertex_color_t, default_color_type> >,
// edge properties
property<edge_capacity_t, int,
property<edge_residual_capacity_t, int,
property<edge_reverse_t, ttraits::edge_descriptor> > >, no_property, vecS> tbgl_adjlist_bidir;
typedef graph_traits<tbgl_adjlist_bidir>::vertex_descriptor tvertex;
typedef graph_traits<tbgl_adjlist_bidir>::edge_descriptor tedge;
typedef property_map<tbgl_adjlist_bidir, edge_capacity_t>::type tedge_capacity_map;
typedef property_map<tbgl_adjlist_bidir, edge_reverse_t>::type treverse_edge_map;
typedef property_map<tbgl_adjlist_bidir, vertex_color_t>::type tvertex_color_map;
typedef property_map<tbgl_adjlist_bidir, vertex_index_t>::type tvertex_index_map;
typedef graph_traits<tbgl_adjlist_bidir>::vertex_iterator tvertex_iterator;
typedef graph_traits<tbgl_adjlist_bidir>::edge_iterator tedge_iterator;
typedef graph_traits<tbgl_adjlist_bidir>::out_edge_iterator tout_edge_iterator;
typedef graph_traits<tbgl_adjlist_bidir>::in_edge_iterator tin_edge_iterator;
then I use it like this:
tbgl_adjlist_bidir bgl_adjlist_bidir;
// ...
tvertex_index_map indices = get(vertex_index, bgl_adjlist_bidir);
// ...
tvertex source;
// ...
int source_as_int = indices[source];
The type of a vertex_descriptor depends on the underlying structure of the VertexListS-template parameter of adjacency_list. The only case i know of, where the descriptor is an int is, when the VertexList-Type is vecS. But keep in mind: If you choose vecS as your VertexList-Type all (stored) descriptors can become invalid, when you change the structure of your graph(as described in Iterator and Descriptor Stability/Invalidation).
Could I interest you in using custom vertex and edge types instead? They're much, much easier to work with in your own code. And as for calling on BGL algorithms, you can use Bundled Properties.
Since my graph use setS for vertex, I have to either provide a vertex_index property map for my graph, or give an explicit vertex_id argument to write_graphviz, to be able to use write_graphviz.
My graph is defined as: typedef adjacency_list<setS, setS, undirectedS, NodeData, EdgeData> Graph;
Where NodeData and EdgeData are structures.
Can you please give me a very simple example of how to provide a vertex_index property map for my graph ? or how to give an explicit vertex_id argument to write_graphviz ?
Thanks
The solution is just to:
1) Say the vertex descriptor is defined as typedef Graph::vertex_descriptor NodeID; then you need to define an associative property map as following:
typedef map<NodeID, size_t> IndexMap;
IndexMap mapIndex;
associative_property_map<IndexMap> propmapIndex(mapIndex);
2) In the code, index all vertices as following:
int i=0;
BGL_FORALL_VERTICES(v, g, Graph)
{
put(propmapIndex, v, i++);
}
3) You can now use graphvize to drow/visualize your graph as following:
ofstream myfile;
myfile.open ("example.txt");
write_graphviz(myfile, g, default_writer(), default_writer(), default_writer(), propmapIndex);
myfile.close();
The graph will be described in example.txt, you can visualize it using graphviz.
I am investigating the use of the boost graph libraries in order to apply them to various network problems I have in mind.
In the examples I have been looking at the graph edge values ("weights") are always initialized as integers, such as in these Bellman-Ford and Kruskal algorithms eg:
int weights[] = { 1, 1, 2, 7, 3, 1, 1, 1 };
My problem is if I try and change the weights to double, I get a heap of warning messages about conversions etc, which so far I have not been able to figure out how to overcome.
Does anyone see a way around this?
It's caused by a mismatch between the weights[] array and the type used for edge weights by your boost graph/algorithm.
In the first linked sample, eg, you should also change
struct EdgeProperties {
int weight;
};
[...]
property_map<Graph, int EdgeProperties::*>::type
to
struct EdgeProperties {
double weight;
};
[...]
property_map<Graph, double EdgeProperties::*>::type
In the second
typedef adjacency_list < vecS, vecS, undirectedS,
no_property, property < edge_weight_t, int > > Graph;
to
typedef adjacency_list < vecS, vecS, undirectedS,
no_property, property < edge_weight_t, double > > Graph;