Boost logo

Boost Users :

Subject: Re: [Boost-users] boost::graph subgraph + write_graphviz()
From: Jeremiah Willcock (jewillco_at_[hidden])
Date: 2012-08-02 21:37:54


On Fri, 3 Aug 2012, Chris Cooper wrote:

> Ok thanks Jeremiah. This compiles and produces subgraph clauses, but
> it seems from browsing the subgraph implementation in
> boost/graph/graphviz.hpp that I'm currently unable to...
>
> - use custom label writers with subgraphs

That doesn't look to be supported, but *_attribute_t maps should be able
to do almost everything that you could do with custom label writers.

> - insert appropriate per-subgraph formatting detail required to get
> subgraphs rendering correctly via dot (eg as is shown in
> libs/graph/example/graphviz_test.dot).

For subgraph names (and "cluster*" names that trigger special behavior in
Dot), you can use the graph_name property of each subgraph. I don't know
about getting edges between subgraphs.

> I think I'd better leave this for now unless the above is
> straightforward. Thanks for your time. I may look into it again at
> some stage, maybe even get around to submitting a patch if I find the
> time...

I think subgraph rendering is probably easy, depending on what you want,
but it does look like edges between subgraphs and custom writers are not
possible without a lot of work.

Given that subgraph writing is not documented at all, you might want to
just write your own application-specific output code, probably using the
helper functions (such as for string escaping) that are used in
write_graphviz. The ideal would probably be something that can write out
everything that's in the parser_result struct in
boost/graph/detail/read_graphviz_new.hpp, but that would likely be a lot
of work.

-- Jeremiah Willcock

>
> On 3 August 2012 01:38, Jeremiah Willcock <jewillco_at_[hidden]> wrote:
>> On Thu, 2 Aug 2012, Chris Cooper wrote:
>>
>>> With the dynamic property code I posted previously you should be able
>>> to just change that write_graphviz_dp call to write_graphviz(ofs, G0).
>>> Here's some code as per my original post. With boost trunk it's
>>> currently failing with...
>>>
>>> include/boost/pending/property.hpp:126:5: error: no type named ¡type¢
>>> in ¡struct boost::lookup_one_property_internal<boost::no_property,
>>> boost::graph_graph_attribute_t>¢
>>
>>
>> It looks like some of the property map defaults in write_graphviz got lost
>> when I changed how property lookup works, and write_graphviz on subgraphs
>> isn't using the default property writers like the normal version of
>> write_graphviz does. The workaround is to change your property declarations
>> to:
>>
>> typedef std::map<std::string, std::string> smap;
>> typedef property<vertex_color_t, int,
>> property<vertex_attribute_t, smap> > vertex_p;
>> typedef property<edge_index_t, int,
>> property<edge_attribute_t, smap> > edge_p;
>> typedef property<graph_name_t, std::string,
>> property<graph_graph_attribute_t, smap,
>> property<graph_vertex_attribute_t, smap,
>> property<graph_edge_attribute_t, smap> > > >
>> graph_p;
>>
>> You don't need to initialize the new properties added here; the
>> default-constructed empty versions are fine. If you want to save storage,
>> you can create a dummy class that acts like an empty std::map<string,
>> string> and use that instead of smap in the code.
>>
>> -- Jeremiah Willcock
>>
>>
>>>
>>>
>>>
>>> #include <boost/config.hpp>
>>> #include <iostream>
>>> #include <fstream>
>>> #include <boost/graph/subgraph.hpp>
>>> #include <boost/graph/adjacency_list.hpp>
>>> #include <boost/graph/graph_utility.hpp>
>>> #include <boost/graph/graphviz.hpp>
>>>
>>> int main(int,char*[])
>>> {
>>> using namespace boost;
>>> typedef adjacency_list_traits<vecS, vecS, directedS> Traits;
>>> typedef property<vertex_color_t, int> vertex_p;
>>> typedef property<edge_index_t, int> edge_p;
>>> typedef property<graph_name_t, std::string> graph_p;
>>> typedef subgraph< adjacency_list<vecS, vecS, directedS, vertex_p,
>>> edge_p, graph_p > > Graph;
>>>
>>> const int N = 6;
>>> Graph G0(N);
>>> enum { A, B, C, D, E, F}; // for conveniently refering to vertices in
>>> G0
>>>
>>> Graph& G1 = G0.create_subgraph();
>>> Graph& G2 = G0.create_subgraph();
>>> enum { A1, B1, C1 }; // for conveniently refering to vertices in
>>> G1
>>> enum { A2, B2 }; // for conveniently refering to vertices in
>>> G2
>>>
>>> add_vertex(C, G1); // global vertex C becomes local A1 for G1
>>> add_vertex(E, G1); // global vertex E becomes local B1 for G1
>>> add_vertex(F, G1); // global vertex F becomes local C1 for G1
>>>
>>> add_vertex(A, G2); // global vertex A becomes local A1 for G2
>>> add_vertex(B, G2); // global vertex B becomes local B1 for G2
>>>
>>> add_edge(A, B, G0);
>>> add_edge(B, C, G0);
>>> add_edge(B, D, G0);
>>> add_edge(E, B, G0);
>>> add_edge(E, F, G0);
>>> add_edge(F, D, G0);
>>>
>>> add_edge(A1, C1, G1); // (A1,C1) is subgraph G1 local indices for (C,F).
>>>
>>> const char* names[] = { "A", "B", "C", "D", "E", "F" };
>>> const char* enames[] = { "0", "1", "2", "3", "4", "5" };
>>> const char* gnames[] = { "G0", "G1", "G2" };
>>>
>>> std::ofstream ofs("out.dot");
>>>
>>> #if 0
>>> // works
>>> write_graphviz(ofs, G0.m_graph, make_label_writer(names));
>>> #else
>>> write_graphviz(ofs, G0);
>>> //write_graphviz(ofs, G0, make_label_writer(names),
>>> make_label_writer(enames), make_label_writer(gnames));
>>> #endif
>>>
>>> return 0;
>>> }
>>>
>>>
>>>
>>> On 2 August 2012 11:58, Jeremiah Willcock <jewillco_at_[hidden]> wrote:
>>>>
>>>> On Thu, 2 Aug 2012, Chris Cooper wrote:
>>>>
>>>>> Thanks Jeremiah,
>>>>>
>>>>> I've now got something that compiles and runs, but still doesn't
>>>>> include 'subgraph' clauses in the dot output and corresponding
>>>>> rectangles when rendered. Interestingly if I now change back to
>>>>> write_graphviz(ofs, G0) I do get some subgraph clauses, but the names
>>>>> are messed up presumably since they're now being set up using dynamic
>>>>> properties. Also the subgraphs still don't render in this case.
>>>>
>>>>
>>>>
>>>> It looks like you do need to use write_graphviz (without _dp) to get
>>>> subgraphs in the output. Could you please try your original code with
>>>> the
>>>> Boost trunk and see what happens? That will allow your line numbers to
>>>> match up with mine. Also, a full code example using write_graphviz would
>>>> be
>>>> helpful. Thank you.
>>>>
>>>>
>>>> -- Jeremiah Willcock
>>>> _______________________________________________
>>>> Boost-users mailing list
>>>> Boost-users_at_[hidden]
>>>> http://lists.boost.org/mailman/listinfo.cgi/boost-users
>>>
>>> _______________________________________________
>>> Boost-users mailing list
>>> Boost-users_at_[hidden]
>>> http://lists.boost.org/mailman/listinfo.cgi/boost-users
>>
>>
>> _______________________________________________
>> Boost-users mailing list
>> Boost-users_at_[hidden]
>> http://lists.boost.org/mailman/listinfo.cgi/boost-users
> _______________________________________________
> Boost-users mailing list
> Boost-users_at_[hidden]
> http://lists.boost.org/mailman/listinfo.cgi/boost-users
>


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net