Boost C++ Libraries: Ticket #3259: write_graphviz requires more concepts than the documentation states https://svn.boost.org/trac10/ticket/3259 <p> I wanted to use write_graphviz with my custom graph adapter that implements <a class="missing wiki">VertexListGraph</a> as well as <a class="missing wiki">IncidenceGraph</a>. The documentation states, that write_graphviz only requires a <a class="missing wiki">VertexListGraph</a>. But inside, it uses an edge_iterator, and calls edges(g), both of which belong to the <a class="missing wiki">EdgeListGraph</a>. </p> <p> This discrepancy was confirmed at the boost mailing list. </p> <p> First, the documentation should be updated. </p> <p> But then I would also suggest to provide a second specialization for <a class="missing wiki">IncidenceGraph</a> that calls out_deges() for each vertex instead of edges(). </p> <p> When I find time, I will prepare some code for my proposal. </p> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/3259 Trac 1.4.3 richi@… Thu, 16 Jul 2009 10:01:24 GMT <link>https://svn.boost.org/trac10/ticket/3259#comment:1 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/3259#comment:1</guid> <description> <p> Here's the code that I had in mind : </p> <p> template &lt;typename <a class="missing wiki">EdgeListGraph</a>, typename <a class="missing wiki">VertexPropertiesWriter</a>, </p> <blockquote> <p> typename <a class="missing wiki">EdgePropertiesWriter</a>, typename <a class="missing wiki">GraphPropertiesWriter</a>, typename VertexID&gt; </p> </blockquote> <p> static inline void write_graphviz_dispatch(std::ostream&amp; out, const <a class="missing wiki">EdgeListGraph</a>&amp; g, </p> <blockquote> <p> <a class="missing wiki">VertexPropertiesWriter</a> vpw, <a class="missing wiki">EdgePropertiesWriter</a> epw, <a class="missing wiki">GraphPropertiesWriter</a> gpw, VertexID vertex_id, edge_list_graph_tag) </p> </blockquote> <p> { </p> <blockquote> <p> typedef typename graph_traits&lt;<a class="missing wiki">EdgeListGraph</a>&gt;::directed_category cat_type; typedef graphviz_io_traits&lt;cat_type&gt; Traits; std::string name = "G"; out &lt;&lt; Traits::name() &lt;&lt; " " &lt;&lt; name &lt;&lt; " {" &lt;&lt; std::endl; </p> </blockquote> <blockquote> <p> gpw(out); <em>print graph properties </em></p> </blockquote> <blockquote> <p> typename graph_traits&lt;<a class="missing wiki">EdgeListGraph</a>&gt;::vertex_iterator i, end; </p> </blockquote> <blockquote> <p> for(tie(i,end) = vertices(g); i != end; ++i) { </p> <blockquote> <p> out &lt;&lt; get(vertex_id, *i); vpw(out, *i); <em>print vertex attributes out &lt;&lt; ";" &lt;&lt; std::endl; </em></p> </blockquote> <p> } typename graph_traits&lt;<a class="missing wiki">EdgeListGraph</a>&gt;::edge_iterator ei, edge_end; for(tie(ei, edge_end) = edges(g); ei != edge_end; ++ei) { </p> <blockquote> <p> out &lt;&lt; get(vertex_id, source(*ei, g)) &lt;&lt; Traits::delimiter() &lt;&lt; get(vertex_id, target(*ei, g)) &lt;&lt; " "; epw(out, *ei); <em>print edge attributes out &lt;&lt; ";" &lt;&lt; std::endl; </em></p> </blockquote> <p> } out &lt;&lt; "}" &lt;&lt; std::endl; </p> </blockquote> <p> } </p> <p> template &lt;typename <a class="missing wiki">VertexListGraph</a>, typename <a class="missing wiki">VertexPropertiesWriter</a>, </p> <blockquote> <p> typename <a class="missing wiki">EdgePropertiesWriter</a>, typename <a class="missing wiki">GraphPropertiesWriter</a>, typename VertexID&gt; </p> </blockquote> <p> inline void write_graphviz_dispatch(std::ostream&amp; out, const <a class="missing wiki">VertexListGraph</a>&amp; g, </p> <blockquote> <p> <a class="missing wiki">VertexPropertiesWriter</a> vpw, <a class="missing wiki">EdgePropertiesWriter</a> epw, <a class="missing wiki">GraphPropertiesWriter</a> gpw, VertexID vertex_id, vertex_list_graph_tag) </p> </blockquote> <p> { </p> <blockquote> <p> typedef typename graph_traits&lt;<a class="missing wiki">VertexListGraph</a>&gt;::directed_category cat_type; typedef graphviz_io_traits&lt;cat_type&gt; Traits; std::string name = "G"; out &lt;&lt; Traits::name() &lt;&lt; " " &lt;&lt; name &lt;&lt; " {" &lt;&lt; std::endl; </p> </blockquote> <blockquote> <p> gpw(out); <em>print graph properties </em></p> </blockquote> <blockquote> <p> typename graph_traits&lt;<a class="missing wiki">VertexListGraph</a>&gt;::vertex_iterator i, end; </p> </blockquote> <blockquote> <p> for(tie(i,end) = vertices(g); i != end; ++i) { </p> <blockquote> <p> out &lt;&lt; get(vertex_id, *i); vpw(out, *i); <em>print vertex attributes out &lt;&lt; ";" &lt;&lt; std::endl; </em></p> </blockquote> <p> } </p> </blockquote> <blockquote> <p> for(tie(i,end) = vertices(g); i != end; ++i) { </p> <blockquote> <p> typename graph_traits&lt;<a class="missing wiki">VertexListGraph</a>&gt;::out_edge_iterator ei, edge_end; for(tie(ei, edge_end) = out_edges(*i, g); ei != edge_end; ++ei) { </p> <blockquote> <p> out &lt;&lt; get(vertex_id, source(*ei, g)) &lt;&lt; Traits::delimiter() &lt;&lt; get(vertex_id, target(*ei, g)) &lt;&lt; " "; epw(out, *ei); <em>print edge attributes out &lt;&lt; ";" &lt;&lt; std::endl; </em></p> </blockquote> <p> } </p> </blockquote> <p> } out &lt;&lt; "}" &lt;&lt; std::endl; </p> </blockquote> <p> } </p> <p> <em> dispatcher template &lt;typename Graph, typename <a class="missing wiki">VertexPropertiesWriter</a>, </em></p> <blockquote> <p> typename <a class="missing wiki">EdgePropertiesWriter</a>, typename <a class="missing wiki">GraphPropertiesWriter</a>, typename VertexID&gt; </p> </blockquote> <p> inline void write_graphviz(std::ostream&amp; out, const Graph&amp; g, </p> <blockquote> <p> <a class="missing wiki">VertexPropertiesWriter</a> vpw, <a class="missing wiki">EdgePropertiesWriter</a> epw, <a class="missing wiki">GraphPropertiesWriter</a> gpw, VertexID vertex_id) </p> </blockquote> <p> { </p> <blockquote> <p> typedef typename graph_traits&lt;Graph&gt;::traversal_category cat_type; function_requires&lt;<a class="missing wiki">IncidenceGraphConcept</a>&lt;Graph&gt; &gt;(); </p> </blockquote> <blockquote> <p> write_graphviz_dispatch(out, g, vpw, epw, gpw, vertex_id, cat_type()); </p> </blockquote> <p> } </p> <p> works for me, but it's not extensively tested... </p> <p> </p> </description> <category>Ticket</category> </item> <item> <author>Richard Ulrich <richi@…></author> <pubDate>Thu, 16 Jul 2009 11:38:51 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/3259#comment:2 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/3259#comment:2</guid> <description> <p> looks better with the code tag : </p> <pre class="wiki">template &lt;typename EdgeListGraph, typename VertexPropertiesWriter, typename EdgePropertiesWriter, typename GraphPropertiesWriter, typename VertexID&gt; static inline void write_graphviz_dispatch(std::ostream&amp; out, const EdgeListGraph&amp; g, VertexPropertiesWriter vpw, EdgePropertiesWriter epw, GraphPropertiesWriter gpw, VertexID vertex_id, edge_list_graph_tag) { typedef typename graph_traits&lt;EdgeListGraph&gt;::directed_category cat_type; typedef graphviz_io_traits&lt;cat_type&gt; Traits; std::string name = "G"; out &lt;&lt; Traits::name() &lt;&lt; " " &lt;&lt; name &lt;&lt; " {" &lt;&lt; std::endl; gpw(out); //print graph properties typename graph_traits&lt;EdgeListGraph&gt;::vertex_iterator i, end; for(tie(i,end) = vertices(g); i != end; ++i) { out &lt;&lt; get(vertex_id, *i); vpw(out, *i); //print vertex attributes out &lt;&lt; ";" &lt;&lt; std::endl; } typename graph_traits&lt;EdgeListGraph&gt;::edge_iterator ei, edge_end; for(tie(ei, edge_end) = edges(g); ei != edge_end; ++ei) { out &lt;&lt; get(vertex_id, source(*ei, g)) &lt;&lt; Traits::delimiter() &lt;&lt; get(vertex_id, target(*ei, g)) &lt;&lt; " "; epw(out, *ei); //print edge attributes out &lt;&lt; ";" &lt;&lt; std::endl; } out &lt;&lt; "}" &lt;&lt; std::endl; } template &lt;typename VertexListGraph, typename VertexPropertiesWriter, typename EdgePropertiesWriter, typename GraphPropertiesWriter, typename VertexID&gt; inline void write_graphviz_dispatch(std::ostream&amp; out, const VertexListGraph&amp; g, VertexPropertiesWriter vpw, EdgePropertiesWriter epw, GraphPropertiesWriter gpw, VertexID vertex_id, vertex_list_graph_tag) { typedef typename graph_traits&lt;VertexListGraph&gt;::directed_category cat_type; typedef graphviz_io_traits&lt;cat_type&gt; Traits; std::string name = "G"; out &lt;&lt; Traits::name() &lt;&lt; " " &lt;&lt; name &lt;&lt; " {" &lt;&lt; std::endl; gpw(out); //print graph properties typename graph_traits&lt;VertexListGraph&gt;::vertex_iterator i, end; for(tie(i,end) = vertices(g); i != end; ++i) { out &lt;&lt; get(vertex_id, *i); vpw(out, *i); //print vertex attributes out &lt;&lt; ";" &lt;&lt; std::endl; } for(tie(i,end) = vertices(g); i != end; ++i) { typename graph_traits&lt;VertexListGraph&gt;::out_edge_iterator ei, edge_end; for(tie(ei, edge_end) = out_edges(*i, g); ei != edge_end; ++ei) { out &lt;&lt; get(vertex_id, source(*ei, g)) &lt;&lt; Traits::delimiter() &lt;&lt; get(vertex_id, target(*ei, g)) &lt;&lt; " "; epw(out, *ei); //print edge attributes out &lt;&lt; ";" &lt;&lt; std::endl; } } out &lt;&lt; "}" &lt;&lt; std::endl; } // dispatcher template &lt;typename Graph, typename VertexPropertiesWriter, typename EdgePropertiesWriter, typename GraphPropertiesWriter, typename VertexID&gt; inline void write_graphviz(std::ostream&amp; out, const Graph&amp; g, VertexPropertiesWriter vpw, EdgePropertiesWriter epw, GraphPropertiesWriter gpw, VertexID vertex_id) { typedef typename graph_traits&lt;Graph&gt;::traversal_category cat_type; function_requires&lt;IncidenceGraphConcept&lt;Graph&gt; &gt;(); write_graphviz_dispatch(out, g, vpw, epw, gpw, vertex_id, cat_type()); } </pre> </description> <category>Ticket</category> </item> <item> <dc:creator>Andrew Sutton</dc:creator> <pubDate>Fri, 17 Jul 2009 12:44:32 GMT</pubDate> <title>status, severity, milestone changed https://svn.boost.org/trac10/ticket/3259#comment:3 https://svn.boost.org/trac10/ticket/3259#comment:3 <ul> <li><strong>status</strong> <span class="trac-field-old">new</span> → <span class="trac-field-new">assigned</span> </li> <li><strong>severity</strong> <span class="trac-field-old">Cosmetic</span> → <span class="trac-field-new">Problem</span> </li> <li><strong>milestone</strong> <span class="trac-field-old">Boost 1.40.0</span> → <span class="trac-field-new">Boost 1.41.0</span> </li> </ul> <p> The specialization proposed by the reporter is somewhat interesting since it only applies to directed graphs. Using the suggested specialization with an undirected graph will cause each edge to be given twice. It may be worth considering a DirectedGraph concept that embodies this property of the out_edges() function. Conversely, an UndirectedGraph concept may provide a different guarantee. </p> <p> However, the proposed solution - as given - won't work. </p> Ticket Andrew Sutton Fri, 17 Jul 2009 13:03:43 GMT status changed; resolution set https://svn.boost.org/trac10/ticket/3259#comment:4 https://svn.boost.org/trac10/ticket/3259#comment:4 <ul> <li><strong>status</strong> <span class="trac-field-old">assigned</span> → <span class="trac-field-new">closed</span> </li> <li><strong>resolution</strong> → <span class="trac-field-new">fixed</span> </li> </ul> <p> Added a concept assertion on <a class="missing wiki">EdgeListGraph</a> to the core write_graphviz function to ensure that it actually requires the concept. Updated documentation to reflect requirements on <a class="missing wiki">VertexAndEdgeListGraph</a> (<a class="changeset" href="https://svn.boost.org/trac10/changeset/54995" title="Adding edge-list requirements to write-grapviz function(s) and ...">r54995</a>). </p> Ticket