Re: newbie: Graph library - bundled properties
Date: Mon, 22 Nov 2004 20:36:07 -0500 From: Doug Gregor
Subject: Re: [Boost-users] newbie: Graph library - bundled properties To: boost-users@lists.boost.org Message-ID: <0BEF9B5F-3CF0-11D9-84DF-000D932B7224@cs.indiana.edu> Content-Type: text/plain; charset=US-ASCII;
After modifying it, still had some compile problems.
using std::string;
struct edgeStruct {
int weight;
};
struct graphStruct {
string name;
};
int
main()
{
using namespace boost;
typedef adjacency_list
On Nov 22, 2004, at 8:25 PM, TC MA wrote:
int main() { using namespace boost; using std::string;
Move this struct...
struct edgeStruct { int weight; };
outside of main, because of this error message:
/home/tcma/cpp/boosttcma/libs/graph/graph_property.cpp:21:
error: `main()::edgeStruct' uses local type `main()::edgeStruct'
Doug
______________________________________________________________________ Post your free ad now! http://personals.yahoo.ca
You are not properly introducing your custom properties to boost.graph.
As an example of doing this correctly:
using std::string;
struct edgeStruct {
int weight;
};
struct graphStruct {
string name;
};
// create a tag for custom graph/edge properties
enum graph_Datum_t { graph_Datum };
enum edge_Datum_t { edge_Datum };
namespace boost {
BOOST_INSTALL_PROPERTY(graph,Datum);
BOOST_INSTALL_PROPERTY(edge,Datum);
}
typedef boost::property
After modifying it, still had some compile problems. using std::string; struct edgeStruct { int weight; }; struct graphStruct { string name; };
int main() { using namespace boost;
typedef adjacency_list
graph_t; graph_t g; graph_t::vertex_descriptor v = *vertices(g).first; graph_t::edge_descriptor e = *out_edges(v, g).first; g[e].weight = 1; g[e].name = "graphname";
std::cout << "name: " << g[e].name << std::endl;
typedef subgraph
subgraph_t; subgraph_t sg; get_property(sg, graph_name) = "subgraph";
std::cout << "name: " << get_property(sg, graph_name) << std::endl;
return exit_success; }
# compile output is: gcc-C++-action /home/tcma/cpp/boosttcma/libs/graph/graph_property.test/gcc/debug/inlining-on/graph_property.o /home/tcma/cpp/boosttcma/libs/graph/graph_property.cpp: In function `int main()': /home/tcma/cpp/boosttcma/libs/graph/graph_property.cpp:32: error: 'struct edgeStruct' has no member named 'name' /home/tcma/cpp/boosttcma/libs/graph/graph_property.cpp:34: error: 'struct edgeStruct' has no member named 'name' /home/tcma/cpp/boost_1_32_0/boost/graph/subgraph.hpp: At global scope: /home/tcma/cpp/boost_1_32_0/boost/graph/subgraph.hpp: In instantiation of `boost::subgraph
': /home/tcma/cpp/boosttcma/libs/graph/graph_property.cpp:39: instantiated from here /home/tcma/cpp/boost_1_32_0/boost/graph/subgraph.hpp:249: error: incomplete type `boost::STATIC_ASSERTION_FAILURE<0u>' used in nested name specifier /home/tcma/cpp/boost_1_32_0/boost/graph/subgraph.hpp:249: error: size of array has non-integral type `<type error>' /home/tcma/cpp/boost_1_32_0/boost/pending/detail/property.hpp: In instantiation of `boost::detail::build_property_tag_value_alist<graphStruct>': /home/tcma/cpp/boost_1_32_0/boost/pending/property.hpp:63: instantiated from `boost::property_value ' /home/tcma/cpp/boost_1_32_0/boost/graph/properties.hpp:235: instantiated from `boost::graph_property ' /home/tcma/cpp/boosttcma/libs/graph/graph_property.cpp:40: instantiated from here /home/tcma/cpp/boost_1_32_0/boost/pending/detail/property.hpp:94: error: no type named `next_type' in `struct graphStruct' /home/tcma/cpp/boost_1_32_0/boost/pending/detail/property.hpp:95: error: no type named `value_type' in `struct graphStruct' /home/tcma/cpp/boost_1_32_0/boost/pending/detail/property.hpp:96: error: no type named `tag_type' in `struct graphStruct' /home/tcma/cpp/boost_1_32_0/boost/pending/detail/property.hpp:97: error: no type named `next_type' in `struct graphStruct' /home/tcma/cpp/boost_1_32_0/boost/pending/detail/property.hpp:98: error: no type named `tag_type' in `struct graphStruct' /home/tcma/cpp/boost_1_32_0/boost/pending/property.hpp: In instantiation of `boost::property_value ': /home/tcma/cpp/boost_1_32_0/boost/graph/properties.hpp:235: instantiated from `boost::graph_property ' /home/tcma/cpp/boosttcma/libs/graph/graph_property.cpp:40: instantiated from here /home/tcma/cpp/boost_1_32_0/boost/pending/property.hpp:63: error: no type named `type' in `struct boost::detail::build_property_tag_value_alist<graphStruct>' /home/tcma/cpp/boost_1_32_0/boost/pending/property.hpp:64: error: no type named `type' in `struct boost::detail::build_property_tag_value_alist<graphStruct>' /home/tcma/cpp/boost_1_32_0/boost/graph/properties.hpp: In instantiation of `boost::graph_property ': /home/tcma/cpp/boosttcma/libs/graph/graph_property.cpp:40: instantiated from here /home/tcma/cpp/boost_1_32_0/boost/graph/properties.hpp:235: error: no type named `type' in `struct boost::property_value ' /home/tcma/cpp/boosttcma/libs/graph/graph_property.cpp: In function `int main()': /home/tcma/cpp/boosttcma/libs/graph/graph_property.cpp:40: error: no matching function for call to `get_property(main()::subgraph_t&, boost::graph_name_t)' /home/tcma/cpp/boosttcma/libs/graph/graph_property.cpp:42: error: no matching function for call to `get_property(main()::subgraph_t&, boost::graph_name_t)' /home/tcma/cpp/boost_1_32_0/boost/graph/subgraph.hpp: In constructor `boost::subgraph<Graph>::subgraph() [with Graph = main()::graph_t]': /home/tcma/cpp/boosttcma/libs/graph/graph_property.cpp:39: instantiated from here /home/tcma/cpp/boost_1_32_0/boost/graph/subgraph.hpp:106: error: no matching function for call to `boost::detail::error_property_not_found::error_property_not_found(int)' /home/tcma/cpp/boost_1_32_0/boost/pending/detail/property.hpp:21: note: candidates are: boost::detail::error_property_not_found::error_property_not_found() /home/tcma/cpp/boost_1_32_0/boost/pending/detail/property.hpp:21: note: boost::detail::error_property_not_found::error_property_not_found(const boost::detail::error_property_not_found&) set -e "g++" -c -Wall -ftemplate-depth-255 -g -O0 -Wno-inline -I"../../../bin/boost/libs/graph/example" -I "/home/tcma/cpp/boost_1_32_0" -o "/home/tcma/cpp/boosttcma/libs/graph/graph_property.test/gcc/debug/inlining-on/graph_property.o"
"/home/tcma/cpp/boosttcma/libs/graph/graph_property.cpp" "/usr/bin/objcopy" --set-section-flags .debug_str=contents,debug "/home/tcma/cpp/boosttcma/libs/graph/graph_property.test/gcc/debug/inlining-on/graph_property.o"
...failed gcc-C++-action /home/tcma/cpp/boosttcma/libs/graph/graph_property.test/gcc/debug/inlining-on/graph_property.o... ...skipped /home/tcma/cpp/boosttcma/libs/graph/graph_property for lack of graph_property.o... ...skipped /home/tcma/cpp/boosttcma/libs/graph/graph_property.run for lack of /home/tcma/cpp/boosttcma/libs/graph/graph_property... ...failed updating 1 target... ...skipped 3 targets...
Date: Mon, 22 Nov 2004 20:36:07 -0500 From: Doug Gregor
Subject: Re: [Boost-users] newbie: Graph library - bundled properties
To: boost-users@lists.boost.org Message-ID:
<0BEF9B5F-3CF0-11D9-84DF-000D932B7224@cs.indiana.edu>
Content-Type: text/plain; charset=US-ASCII;
format=flowed
On Nov 22, 2004, at 8:25 PM, TC MA wrote:
int main() { using namespace boost; using std::string;
Move this struct...
struct edgeStruct { int weight; };
outside of main, because of this error message:
/home/tcma/cpp/boosttcma/libs/graph/graph_property.cpp:21:
error: `main()::edgeStruct' uses local type `main()::edgeStruct'
Doug
______________________________________________________________________ Post your free ad now! http://personals.yahoo.ca
On Nov 23, 2004, at 3:51 PM, Jeffrey Holle wrote:
You are not properly introducing your custom properties to boost.graph. [snip] Your code example sugguests you expect things like operator[] methods where they aren't. I too like to code in this fashion.
Actually, we've improved this in the BGL, so that the operator[] methods do work for adjacency lists and adjacency matrices when using bundled properties. Check out the new stuff in 1.32.0 :) As for the other poster's question... I'll try to answer that later, but I think the problem is that bundled properties aren't support for the graph properties (e.g., the graph name), whereas they are supported for edges and vertices. This will probably change in a future revision.
Note that this class holds a boost subgraph by reference and accesses properties only through the root subgraph. I found this necessary in boost 1.31_0 because the properties of "derived" subgraphs had only default contructed property classes. If this has been fixed in boost 1.32_0, I'd like to know about it.
This is a subgraph issue? We'll try to tackle this for 1.33.0; is the bug in the Sourceforge bug tracker? Doug
Interesting. I will have to check out the new 1.32.0 stuff. The subgraph issue that I mentioned may need more of an explaination. I create derived subgraphs with create_subgraph(VertexIterator first, VertexIterator last) method of subgraph. This causes the edges that are "local" to the included vertex descriptors to be added to this derived subgraph. I find that internal properties of such a graph are not those of the base(root) graph. I know this because my property classes hold an interface pointer which is NULL when constructed with the default constructor. In my application, this is an invalid object which causes segment faults to occur. I've another issue that I'd really like to see changed. It has to do with the connected_components.hpp algorithm. There is a concept check, at line 99, which insists that the type of graph be undirected. I have to comment this line out every time I update my boost library. In my application, my graph is bidirectional. I am writting a diagram layout procedure and need to split the problem into multiple graphs if there are isolated components in the original graph because my layout algorithm only works on connected graphs. I've tried the other connected algorithms and they do not provide the proper answer for this application. I'd like to add both these issues to a bug system. Can you provide a link? Doug Gregor wrote:
On Nov 23, 2004, at 3:51 PM, Jeffrey Holle wrote:
You are not properly introducing your custom properties to boost.graph.
[snip]
Your code example sugguests you expect things like operator[] methods where they aren't. I too like to code in this fashion.
Actually, we've improved this in the BGL, so that the operator[] methods do work for adjacency lists and adjacency matrices when using bundled properties. Check out the new stuff in 1.32.0 :)
As for the other poster's question... I'll try to answer that later, but I think the problem is that bundled properties aren't support for the graph properties (e.g., the graph name), whereas they are supported for edges and vertices. This will probably change in a future revision.
Note that this class holds a boost subgraph by reference and accesses properties only through the root subgraph. I found this necessary in boost 1.31_0 because the properties of "derived" subgraphs had only default contructed property classes. If this has been fixed in boost 1.32_0, I'd like to know about it.
This is a subgraph issue? We'll try to tackle this for 1.33.0; is the bug in the Sourceforge bug tracker?
Doug
On Nov 23, 2004, at 6:24 PM, Jeffrey Holle wrote:
Interesting. I will have to check out the new 1.32.0 stuff.
The subgraph issue that I mentioned may need more of an explaination. I create derived subgraphs with create_subgraph(VertexIterator first, VertexIterator last) method of subgraph. This causes the edges that are "local" to the included vertex descriptors to be added to this derived subgraph.
I find that internal properties of such a graph are not those of the base(root) graph. I know this because my property classes hold an interface pointer which is NULL when constructed with the default constructor. In my application, this is an invalid object which causes segment faults to occur.
That's actually a surprisingly tough problem to solve given the way subgraph is implemented... I'll have to think about it a bit, but it would help me remember if it's in the bug tracker.
I've another issue that I'd really like to see changed. It has to do with the connected_components.hpp algorithm. There is a concept check, at line 99, which insists that the type of graph be undirected. I have to comment this line out every time I update my boost library.
In my application, my graph is bidirectional.
I don't see how that algorithm will work properly with directed graphs, because the DFS could miss part of the component when it chooses the wrong starting vertex in the group. Incremental connected components could work, or we could build a graph adaptor that turns a bidirectional graph into an undirected graph (which might be generally useful).
I am writting a diagram layout procedure and need to split the problem into multiple graphs if there are isolated components in the original graph because my layout algorithm only works on connected graphs.
I've tried the other connected algorithms and they do not provide the proper answer for this application.
You mean strongly connected components? Or the incremental connected components implementation?
I'd like to add both these issues to a bug system.
Thanks!
Can you provide a link?
With a bidirectional graph, I consider the answer to "Is it a connected graph?" or "Is it a strongly connected graph?" equal. Be aware that my graph is necessarly bidirectional because I need both the in and out edges of a graph in two areas of my algorithm. I consider this artifical because there is a default "direction" of each edge, which is the basis of my layout algorithm. I've attached an example graph that has 3 issolated components as I consider them. Its understandable that the subgraph properties issue is a challenge. I hope you understand that a "copy" isn't what's needed in derived subgraphs. Instead the equivalent to a "reference" is what's needed. Doug Gregor wrote:
On Nov 23, 2004, at 6:24 PM, Jeffrey Holle wrote:
Interesting. I will have to check out the new 1.32.0 stuff.
The subgraph issue that I mentioned may need more of an explaination. I create derived subgraphs with create_subgraph(VertexIterator first, VertexIterator last) method of subgraph. This causes the edges that are "local" to the included vertex descriptors to be added to this derived subgraph.
I find that internal properties of such a graph are not those of the base(root) graph. I know this because my property classes hold an interface pointer which is NULL when constructed with the default constructor. In my application, this is an invalid object which causes segment faults to occur.
That's actually a surprisingly tough problem to solve given the way subgraph is implemented... I'll have to think about it a bit, but it would help me remember if it's in the bug tracker.
I've another issue that I'd really like to see changed. It has to do with the connected_components.hpp algorithm. There is a concept check, at line 99, which insists that the type of graph be undirected. I have to comment this line out every time I update my boost library.
In my application, my graph is bidirectional.
I don't see how that algorithm will work properly with directed graphs, because the DFS could miss part of the component when it chooses the wrong starting vertex in the group. Incremental connected components could work, or we could build a graph adaptor that turns a bidirectional graph into an undirected graph (which might be generally useful).
I am writting a diagram layout procedure and need to split the problem into multiple graphs if there are isolated components in the original graph because my layout algorithm only works on connected graphs.
I've tried the other connected algorithms and they do not provide the proper answer for this application.
You mean strongly connected components? Or the incremental connected components implementation?
I'd like to add both these issues to a bug system.
Thanks!
Can you provide a link?
http://sourceforge.net/tracker/?group_id=7586
Doug
digraph Components { node [ shape = record ]; size="6,6"; 0[label="0",type="Component"]; 1[label="1",type="Component"]; 2[label="2",type="Component"]; 3[label="3",type="Component"]; 4[label="4",type="Component"]; 5[label="5",type="Component"]; 0 -> 1[type="Association"]; 1 -> 4[type="Association"]; 4 -> 0[type="Association"]; 2 -> 5[type="Association"]; }
On Nov 23, 2004, at 9:41 PM, Jeffrey Holle wrote:
With a bidirectional graph, I consider the answer to "Is it a connected graph?" or "Is it a strongly connected graph?" equal.
So we're talking about strongly connected components, then? I'm a bit confused because one could potential think of a bidirectional connected graph as a graph that would be connected if the edge directions were removed, whereas a strongly connected graph is a different beast.
Be aware that my graph is necessarly bidirectional because I need both the in and out edges of a graph in two areas of my algorithm. I consider this artifical because there is a default "direction" of each edge, which is the basis of my layout algorithm.
Okay. A bidirectional graph is just a directed graph with access to the in-edges.
I've attached an example graph that has 3 issolated components as I consider them.
digraph Components { node [ shape = record ]; size="6,6"; 0[label="0",type="Component"]; 1[label="1",type="Component"]; 2[label="2",type="Component"]; 3[label="3",type="Component"]; 4[label="4",type="Component"]; 5[label="5",type="Component"]; 0 -> 1[type="Association"]; 1 -> 4[type="Association"]; 4 -> 0[type="Association"]; 2 -> 5[type="Association"]; }
I see four strongly connected components: {0, 1, 4}, {2}, {3}, {5} If I were to remove edge directions and use standard connected components, I would get three components {0, 1, 4}, {2, 5}, {3}. Which result did you intend?
Its understandable that the subgraph properties issue is a challenge. I hope you understand that a "copy" isn't what's needed in derived subgraphs. Instead the equivalent to a "reference" is what's needed.
Yep, I see the problem. It's "hard" mainly because the subgraph contains copies of the underlying graph edges, but it's nontrivial to rewrite that underlying graph appropriately to turn copies into references. Anyway, we'll just have to dig into the subgraph code to see what we can do. I definitely agree that the "reference" semantics are the desired semantics. Doug
On Nov 23, 2004, at 11:23 AM, TC MA wrote:
struct graphStruct { string name; };
Unfortunately, bundled graph properties aren't supported (yet). You
can, however, add a graph name property using property
typedef adjacency_list
graph_t;
Change this to:
typedef adjacency_list
g[e].name = "graphname";
std::cout << "name: " << g[e].name << std::endl;
These two won't compile because we can't get at the graph properties that way. "e" is an edge descriptor, so "g[e]" is going to give you an edgeStruct& back (that's how we were able to set the edge weight ). To get to the graph_name property we just added above, use: get_property(g, graph_name); If we can come up with a better syntax for the future, we'll definitely do it. For now, we're stuck with that mess.
typedef subgraph
subgraph_t;
You're actually going to run into a minor problem here, because the
subgraph adaptor requires an edge_index property that we haven't
provided. The easiest way to introduce such a property is to actually
mix bundled and non-bundled parameters, like so:
typedef adjacency_list
subgraph_t sg; get_property(sg, graph_name) = "subgraph";
std::cout << "name: " << get_property(sg, graph_name) << std::endl;
return exit_success; }
All of this is fine; it's actually what we changed the above code to. As you can probably tell, we're still working out some of the kinks in the bundled properties setup. It's better than what we had before, but we still have a bit of work to do to make it really slick. Doug
participants (3)
-
Doug Gregor
-
Jeffrey Holle
-
TC MA