BGL: filtered_graph and breadth_first_search.
Hello everybody,
Often, given a graph G and a subset of it's vertices, there is a need to perform
something on an induced graph containing those vertices. I thought about using
filtered_graph for that purpose, but for some reason I am unable to use
breadth_first_search with a filtered_graph - I get pages of errors from the
compiler complaining about something in filtered_graph.hpp, and I don't
understand what is the problem. Here is a minimal test program which
exemplifies the error. Note that if the line containing a call to a
breadth_first_search is commented out, everything compiles properly.
What is the problem here?
---------------------------------------------------------------------
#include
On 4/19/07, Dima F.
Hello everybody,
Often, given a graph G and a subset of it's vertices, there is a need to perform something on an induced graph containing those vertices. I thought about using filtered_graph for that purpose, but for some reason I am unable to use breadth_first_search with a filtered_graph - I get pages of errors from the compiler complaining about something in filtered_graph.hpp, and I don't understand what is the problem. Here is a minimal test program which exemplifies the error. Note that if the line containing a call to a breadth_first_search is commented out, everything compiles properly. What is the problem here?
<snip code> Hi Dima, Your predicate should have const member functions - replace bool operator()(const vertex_t &v) {} bool operator()(const edge_t &e) {} with bool operator()(const vertex_t &v) const {} bool operator()(const edge_t &e) const {} and it should compile. Regards, Aaron
Aaron Windsor wrote:
Your predicate should have const member functions - replace
bool operator()(const vertex_t &v) {}
bool operator()(const edge_t &e) {}
with bool operator()(const vertex_t &v) const {}
bool operator()(const edge_t &e) const {}
and it should compile.
Thanks, it indeed compiles fine.
Is there are other restrictions on using filtered_graph with
breadth_first_search? The problem is that predicates of a filtered_graph
should be Default Constructable, and it seems that even though in an
example in a documentation of filtered_graph predicate has instance
members, predicates of filtered_graphs which are used in breadth_first_search
couldn't have any non-static members, because at some stage during the
search predicates are default-constructed, and values of it's members
are lost - for example, in order to be able to implement my idea of an
induced subgraph, I would like each predicate instance to have a pointer
to a graph to which filtering is going to be applied (see an example below).
Is it somehow possible to let predicates to a filtered_graph have
instance variables? Of course it is possible to use globals or static
members, but this is a bad solution.
P.S.: it seems that an idea of an induced graph can be realized by using
'subgraph' adaptor, but in a general case having predicates with instance
members or some equivalent of instance members looks like a good thing -
if at least it have been possible to get a reference to a graph given
it's edge or vertex the problem would have been much easier to solve,
but unfortunately it seems that graph's edge/vertex doesn't know anything
about a graph it belongs to.
Predicate example:
----------------------------------------------------------------
template
On 4/20/07, Dima F.
Aaron Windsor wrote:
Your predicate should have const member functions - replace
bool operator()(const vertex_t &v) {}
bool operator()(const edge_t &e) {}
with bool operator()(const vertex_t &v) const {}
bool operator()(const edge_t &e) const {}
and it should compile.
Thanks, it indeed compiles fine.
Is there are other restrictions on using filtered_graph with breadth_first_search? The problem is that predicates of a filtered_graph should be Default Constructable, and it seems that even though in an example in a documentation of filtered_graph predicate has instance members, predicates of filtered_graphs which are used in breadth_first_search couldn't have any non-static members, because at some stage during the search predicates are default-constructed, and values of it's members are lost - for example, in order to be able to implement my idea of an induced subgraph, I would like each predicate instance to have a pointer to a graph to which filtering is going to be applied (see an example below).
Is it somehow possible to let predicates to a filtered_graph have instance variables? Of course it is possible to use globals or static members, but this is a bad solution.
Hi Dima, The predicates used in a filtered_graph can have non-static members. In particular, I don't see anything wrong with the example you included in your previous email. The predicate needs to be default constructable because in the implementation of filtered_graph, it's stored by value in an iterator and the iterator must be default constructable. But you can still create a non-default instance of your predicate and pass it in to filtered_graph and you should get the results you expect - just make sure it has the correct semantics when default constructed. Regards, Aaron
Aaron Windsor wrote:
The predicates used in a filtered_graph can have non-static members. In particular, I don't see anything wrong with the example you included in your previous email. The predicate needs to be default constructable because in the implementation of filtered_graph, it's stored by value in an iterator and the iterator must be default constructable. But you can still create a non-default instance of your predicate and pass it in to filtered_graph and you should get the results you expect - just make sure it has the correct semantics when default constructed.
Here is an example which (it seems to me) shows that non-static
members in predicate can cause a problem (see code below). The
program causes segmentation fault, and it happens when pointer to one
of non-static members is dereferenced. When I tried to find the
reason, it seems that a pointer, when used in operator() during
an execution of BFS, contains garbage, that is - it doesn't point
to an object it was pointing to after a predicate object was constructed.
When you run the program, it is possible to see according to a log
messages that sometimes predicate is constructed using a default
constructor, which means that it's members are not copied to a new object.
P.S.: Also, I see that copy-constructor is used, which is somewhat
strange - it is written (http://www.sgi.com/tech/stl/DefaultConstructible.html):
"[1] The form X x = X() is not guaranteed to be a valid expression, because it
uses a copy constructor. A type that is DefaultConstructible is not necessarily
Assignable"
and predicate is only supposed to be Default Constructible, not Assignable...
Test program:
------------------------------------------------------------
#include <set>
#include <iostream>
#include
On 4/20/07, Dima F.
Aaron Windsor wrote:
The predicates used in a filtered_graph can have non-static members. In particular, I don't see anything wrong with the example you included in your previous email. The predicate needs to be default constructable because in the implementation of filtered_graph, it's stored by value in an iterator and the iterator must be default constructable. But you can still create a non-default instance of your predicate and pass it in to filtered_graph and you should get the results you expect - just make sure it has the correct semantics when default constructed.
Here is an example which (it seems to me) shows that non-static members in predicate can cause a problem (see code below). The program causes segmentation fault, and it happens when pointer to one of non-static members is dereferenced. When I tried to find the reason, it seems that a pointer, when used in operator() during an execution of BFS, contains garbage, that is - it doesn't point to an object it was pointing to after a predicate object was constructed.
When you run the program, it is possible to see according to a log messages that sometimes predicate is constructed using a default constructor, which means that it's members are not copied to a new object.
P.S.: Also, I see that copy-constructor is used, which is somewhat strange - it is written (http://www.sgi.com/tech/stl/DefaultConstructible.html):
"[1] The form X x = X() is not guaranteed to be a valid expression, because it uses a copy constructor. A type that is DefaultConstructible is not necessarily Assignable"
<snip>
cout << "\nAnd in filtered graph:\n\n";
typedef induced_graph_filter
filter_t; filter_t filter(&g, &cont); filtered_graph
g2(g, filter);
Hi Dima,
Well, you do need a copy constructor - look a the line above, where
you pass filter by value in the filtered_graph constructor. The copy
constructor is called there (and anywhere else filter is passed by value).
But even though your filtered graph is declared as a
filtered_graph
Aaron Windsor wrote:
Well, you do need a copy constructor - look a the line above, where you pass filter by value in the filtered_graph constructor. The copy constructor is called there (and anywhere else filter is passed by value).
Thanks a lot for all your explanations!
participants (2)
-
Aaron Windsor
-
Dima F.