os/ossrv/ossrv_pub/boost_apis/boost/graph/graphviz.hpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
//=======================================================================
sl@0
     2
// Copyright 2001 University of Notre Dame.
sl@0
     3
// Copyright 2003 Jeremy Siek
sl@0
     4
// Authors: Lie-Quan Lee and Jeremy Siek
sl@0
     5
//
sl@0
     6
// Distributed under the Boost Software License, Version 1.0. (See
sl@0
     7
// accompanying file LICENSE_1_0.txt or copy at
sl@0
     8
// http://www.boost.org/LICENSE_1_0.txt)
sl@0
     9
//=======================================================================
sl@0
    10
#ifndef BOOST_GRAPHVIZ_HPP
sl@0
    11
#define BOOST_GRAPHVIZ_HPP
sl@0
    12
sl@0
    13
#include <boost/config.hpp>
sl@0
    14
#include <string>
sl@0
    15
#include <map>
sl@0
    16
#include <iostream>
sl@0
    17
#include <fstream>
sl@0
    18
#include <stdio.h> // for FILE
sl@0
    19
#include <boost/property_map.hpp>
sl@0
    20
#include <boost/tuple/tuple.hpp>
sl@0
    21
#include <boost/graph/graph_traits.hpp>
sl@0
    22
#include <boost/graph/properties.hpp>
sl@0
    23
#include <boost/graph/subgraph.hpp>
sl@0
    24
#include <boost/graph/adjacency_list.hpp>
sl@0
    25
#include <boost/dynamic_property_map.hpp>
sl@0
    26
sl@0
    27
#ifdef BOOST_HAS_DECLSPEC
sl@0
    28
#  if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_GRAPH_DYN_LINK)
sl@0
    29
#    ifdef BOOST_GRAPH_SOURCE
sl@0
    30
#      define BOOST_GRAPH_DECL __declspec(dllexport)
sl@0
    31
#    else
sl@0
    32
#      define BOOST_GRAPH_DECL __declspec(dllimport)
sl@0
    33
#    endif  // BOOST_GRAPH_SOURCE
sl@0
    34
#  endif  // DYN_LINK
sl@0
    35
#endif  // BOOST_HAS_DECLSPEC
sl@0
    36
sl@0
    37
#ifndef BOOST_GRAPH_DECL
sl@0
    38
#  define BOOST_GRAPH_DECL
sl@0
    39
#endif
sl@0
    40
sl@0
    41
namespace boost {
sl@0
    42
sl@0
    43
  template <typename directed_category>
sl@0
    44
  struct graphviz_io_traits {
sl@0
    45
    static std::string name() {
sl@0
    46
      return "digraph";
sl@0
    47
    }
sl@0
    48
    static std::string delimiter() {
sl@0
    49
      return "->";
sl@0
    50
    }  };
sl@0
    51
sl@0
    52
  template <>
sl@0
    53
  struct graphviz_io_traits <undirected_tag> {
sl@0
    54
    static std::string name() {
sl@0
    55
      return "graph";
sl@0
    56
    }
sl@0
    57
    static std::string delimiter() {
sl@0
    58
      return "--";
sl@0
    59
    }
sl@0
    60
  };
sl@0
    61
sl@0
    62
  struct default_writer {
sl@0
    63
    void operator()(std::ostream&) const {
sl@0
    64
    }
sl@0
    65
    template <class VorE>
sl@0
    66
    void operator()(std::ostream&, const VorE&) const {
sl@0
    67
    }
sl@0
    68
  };
sl@0
    69
sl@0
    70
  template <class Name>
sl@0
    71
  class label_writer {
sl@0
    72
  public:
sl@0
    73
    label_writer(Name _name) : name(_name) {}
sl@0
    74
    template <class VertexOrEdge>
sl@0
    75
    void operator()(std::ostream& out, const VertexOrEdge& v) const {
sl@0
    76
      out << "[label=\"" << get(name, v) << "\"]";
sl@0
    77
    }
sl@0
    78
  private:
sl@0
    79
    Name name;
sl@0
    80
  };
sl@0
    81
  template <class Name>
sl@0
    82
  inline label_writer<Name>
sl@0
    83
  make_label_writer(Name n) {
sl@0
    84
    return label_writer<Name>(n);
sl@0
    85
  }
sl@0
    86
sl@0
    87
  enum edge_attribute_t        { edge_attribute        = 1111 };
sl@0
    88
  enum vertex_attribute_t      { vertex_attribute      = 2222 };
sl@0
    89
  enum graph_graph_attribute_t { graph_graph_attribute = 3333 };
sl@0
    90
  enum graph_vertex_attribute_t  { graph_vertex_attribute  = 4444 };
sl@0
    91
  enum graph_edge_attribute_t  { graph_edge_attribute  = 5555 };
sl@0
    92
sl@0
    93
  BOOST_INSTALL_PROPERTY(edge, attribute);
sl@0
    94
  BOOST_INSTALL_PROPERTY(vertex, attribute);
sl@0
    95
  BOOST_INSTALL_PROPERTY(graph, graph_attribute);
sl@0
    96
  BOOST_INSTALL_PROPERTY(graph, vertex_attribute);
sl@0
    97
  BOOST_INSTALL_PROPERTY(graph, edge_attribute);
sl@0
    98
sl@0
    99
sl@0
   100
  template <class Attribute>
sl@0
   101
  inline void write_attributes(const Attribute& attr, std::ostream& out) {
sl@0
   102
    typename Attribute::const_iterator i, iend;
sl@0
   103
    i    = attr.begin();
sl@0
   104
    iend = attr.end();
sl@0
   105
sl@0
   106
    while ( i != iend ) {
sl@0
   107
      out << i->first << "=\"" << i->second << "\"";
sl@0
   108
      ++i;
sl@0
   109
      if ( i != iend )
sl@0
   110
        out << ", ";
sl@0
   111
    }
sl@0
   112
  }
sl@0
   113
sl@0
   114
  template<typename Attributes>
sl@0
   115
  inline void write_all_attributes(Attributes attributes,
sl@0
   116
                                   const std::string& name,
sl@0
   117
                                   std::ostream& out)
sl@0
   118
  {
sl@0
   119
    typename Attributes::const_iterator i = attributes.begin(),
sl@0
   120
                                        end = attributes.end();
sl@0
   121
    if (i != end) {
sl@0
   122
      out << name << " [\n";
sl@0
   123
      write_attributes(attributes, out);
sl@0
   124
      out << "];\n";
sl@0
   125
    }
sl@0
   126
  }
sl@0
   127
sl@0
   128
  inline void write_all_attributes(detail::error_property_not_found,
sl@0
   129
                                   const std::string&,
sl@0
   130
                                   std::ostream&)
sl@0
   131
  {
sl@0
   132
    // Do nothing - no attributes exist
sl@0
   133
  }
sl@0
   134
sl@0
   135
sl@0
   136
sl@0
   137
sl@0
   138
  template <typename GraphGraphAttributes,
sl@0
   139
            typename GraphNodeAttributes,
sl@0
   140
            typename GraphEdgeAttributes>
sl@0
   141
  struct graph_attributes_writer
sl@0
   142
  {
sl@0
   143
    graph_attributes_writer(GraphGraphAttributes gg,
sl@0
   144
                            GraphNodeAttributes gn,
sl@0
   145
                            GraphEdgeAttributes ge)
sl@0
   146
      : g_attributes(gg), n_attributes(gn), e_attributes(ge) { }
sl@0
   147
sl@0
   148
    void operator()(std::ostream& out) const {
sl@0
   149
      write_all_attributes(g_attributes, "graph", out);
sl@0
   150
      write_all_attributes(n_attributes, "node", out);
sl@0
   151
      write_all_attributes(e_attributes, "edge", out);
sl@0
   152
    }
sl@0
   153
    GraphGraphAttributes g_attributes;
sl@0
   154
    GraphNodeAttributes n_attributes;
sl@0
   155
    GraphEdgeAttributes e_attributes;
sl@0
   156
  };
sl@0
   157
sl@0
   158
  template <typename GAttrMap, typename NAttrMap, typename EAttrMap>
sl@0
   159
  graph_attributes_writer<GAttrMap, NAttrMap, EAttrMap>
sl@0
   160
  make_graph_attributes_writer(const GAttrMap& g_attr, const NAttrMap& n_attr,
sl@0
   161
                              const EAttrMap& e_attr) {
sl@0
   162
    return graph_attributes_writer<GAttrMap, NAttrMap, EAttrMap>
sl@0
   163
      (g_attr, n_attr, e_attr);
sl@0
   164
  }
sl@0
   165
sl@0
   166
sl@0
   167
  template <typename Graph>
sl@0
   168
  graph_attributes_writer
sl@0
   169
    <typename graph_property<Graph, graph_graph_attribute_t>::type,
sl@0
   170
     typename graph_property<Graph, graph_vertex_attribute_t>::type,
sl@0
   171
     typename graph_property<Graph, graph_edge_attribute_t>::type>
sl@0
   172
  make_graph_attributes_writer(const Graph& g)
sl@0
   173
  {
sl@0
   174
    typedef typename graph_property<Graph, graph_graph_attribute_t>::type
sl@0
   175
      GAttrMap;
sl@0
   176
    typedef typename graph_property<Graph, graph_vertex_attribute_t>::type
sl@0
   177
      NAttrMap;
sl@0
   178
    typedef typename graph_property<Graph, graph_edge_attribute_t>::type
sl@0
   179
      EAttrMap;
sl@0
   180
    GAttrMap gam = get_property(g, graph_graph_attribute);
sl@0
   181
    NAttrMap nam = get_property(g, graph_vertex_attribute);
sl@0
   182
    EAttrMap eam = get_property(g, graph_edge_attribute);
sl@0
   183
    graph_attributes_writer<GAttrMap, NAttrMap, EAttrMap> writer(gam, nam, eam);
sl@0
   184
    return writer;
sl@0
   185
  }
sl@0
   186
sl@0
   187
  template <typename AttributeMap>
sl@0
   188
  struct attributes_writer {
sl@0
   189
    attributes_writer(AttributeMap attr)
sl@0
   190
      : attributes(attr) { }
sl@0
   191
sl@0
   192
    template <class VorE>
sl@0
   193
    void operator()(std::ostream& out, const VorE& e) const {
sl@0
   194
      this->write_attribute(out, attributes[e]);
sl@0
   195
    }
sl@0
   196
sl@0
   197
    private:
sl@0
   198
      template<typename AttributeSequence>
sl@0
   199
      void write_attribute(std::ostream& out,
sl@0
   200
                           const AttributeSequence& seq) const
sl@0
   201
      {
sl@0
   202
        if (!seq.empty()) {
sl@0
   203
          out << "[";
sl@0
   204
          write_attributes(seq, out);
sl@0
   205
          out << "]";
sl@0
   206
        }
sl@0
   207
      }
sl@0
   208
sl@0
   209
      void write_attribute(std::ostream&,
sl@0
   210
                           detail::error_property_not_found) const
sl@0
   211
      {
sl@0
   212
      }
sl@0
   213
    AttributeMap attributes;
sl@0
   214
  };
sl@0
   215
sl@0
   216
  template <typename Graph>
sl@0
   217
  attributes_writer
sl@0
   218
    <typename property_map<Graph, edge_attribute_t>::const_type>
sl@0
   219
  make_edge_attributes_writer(const Graph& g)
sl@0
   220
  {
sl@0
   221
    typedef typename property_map<Graph, edge_attribute_t>::const_type
sl@0
   222
      EdgeAttributeMap;
sl@0
   223
    return attributes_writer<EdgeAttributeMap>(get(edge_attribute, g));
sl@0
   224
  }
sl@0
   225
sl@0
   226
  template <typename Graph>
sl@0
   227
  attributes_writer
sl@0
   228
    <typename property_map<Graph, vertex_attribute_t>::const_type>
sl@0
   229
  make_vertex_attributes_writer(const Graph& g)
sl@0
   230
  {
sl@0
   231
    typedef typename property_map<Graph, vertex_attribute_t>::const_type
sl@0
   232
      VertexAttributeMap;
sl@0
   233
    return attributes_writer<VertexAttributeMap>(get(vertex_attribute, g));
sl@0
   234
  }
sl@0
   235
sl@0
   236
  template <typename Graph, typename VertexPropertiesWriter,
sl@0
   237
            typename EdgePropertiesWriter, typename GraphPropertiesWriter,
sl@0
   238
            typename VertexID>
sl@0
   239
  inline void write_graphviz(std::ostream& out, const Graph& g,
sl@0
   240
                             VertexPropertiesWriter vpw,
sl@0
   241
                             EdgePropertiesWriter epw,
sl@0
   242
                             GraphPropertiesWriter gpw,
sl@0
   243
                             VertexID vertex_id)
sl@0
   244
  {
sl@0
   245
    typedef typename graph_traits<Graph>::directed_category cat_type;
sl@0
   246
    typedef graphviz_io_traits<cat_type> Traits;
sl@0
   247
    std::string name = "G";
sl@0
   248
    out << Traits::name() << " " << name << " {" << std::endl;
sl@0
   249
sl@0
   250
    gpw(out); //print graph properties
sl@0
   251
sl@0
   252
    typename graph_traits<Graph>::vertex_iterator i, end;
sl@0
   253
sl@0
   254
    for(tie(i,end) = vertices(g); i != end; ++i) {
sl@0
   255
      out << get(vertex_id, *i);
sl@0
   256
      vpw(out, *i); //print vertex attributes
sl@0
   257
      out << ";" << std::endl;
sl@0
   258
    }
sl@0
   259
    typename graph_traits<Graph>::edge_iterator ei, edge_end;
sl@0
   260
    for(tie(ei, edge_end) = edges(g); ei != edge_end; ++ei) {
sl@0
   261
      out << get(vertex_id, source(*ei, g)) << Traits::delimiter() << get(vertex_id, target(*ei, g)) << " ";
sl@0
   262
      epw(out, *ei); //print edge attributes
sl@0
   263
      out << ";" << std::endl;
sl@0
   264
    }
sl@0
   265
    out << "}" << std::endl;
sl@0
   266
  }
sl@0
   267
sl@0
   268
  template <typename Graph, typename VertexPropertiesWriter,
sl@0
   269
            typename EdgePropertiesWriter, typename GraphPropertiesWriter>
sl@0
   270
  inline void write_graphviz(std::ostream& out, const Graph& g,
sl@0
   271
                             VertexPropertiesWriter vpw,
sl@0
   272
                             EdgePropertiesWriter epw,
sl@0
   273
                             GraphPropertiesWriter gpw)
sl@0
   274
  { write_graphviz(out, g, vpw, epw, gpw, get(vertex_index, g)); }
sl@0
   275
sl@0
   276
#if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
sl@0
   277
  // ambiguous overload problem with VC++
sl@0
   278
  template <typename Graph>
sl@0
   279
  inline void
sl@0
   280
  write_graphviz(std::ostream& out, const Graph& g) {
sl@0
   281
    default_writer dw;
sl@0
   282
    default_writer gw;
sl@0
   283
    write_graphviz(out, g, dw, dw, gw);
sl@0
   284
  }
sl@0
   285
#endif
sl@0
   286
sl@0
   287
  template <typename Graph, typename VertexWriter>
sl@0
   288
  inline void
sl@0
   289
  write_graphviz(std::ostream& out, const Graph& g, VertexWriter vw) {
sl@0
   290
    default_writer dw;
sl@0
   291
    default_writer gw;
sl@0
   292
    write_graphviz(out, g, vw, dw, gw);
sl@0
   293
  }
sl@0
   294
sl@0
   295
  template <typename Graph, typename VertexWriter, typename EdgeWriter>
sl@0
   296
  inline void
sl@0
   297
  write_graphviz(std::ostream& out, const Graph& g,
sl@0
   298
                 VertexWriter vw, EdgeWriter ew) {
sl@0
   299
    default_writer gw;
sl@0
   300
    write_graphviz(out, g, vw, ew, gw);
sl@0
   301
  }
sl@0
   302
sl@0
   303
  namespace detail {
sl@0
   304
sl@0
   305
    template <class Graph_, class RandomAccessIterator, class VertexID>
sl@0
   306
    void write_graphviz_subgraph (std::ostream& out,
sl@0
   307
                                  const subgraph<Graph_>& g,
sl@0
   308
                                  RandomAccessIterator vertex_marker,
sl@0
   309
                                  RandomAccessIterator edge_marker,
sl@0
   310
                                  VertexID vertex_id)
sl@0
   311
    {
sl@0
   312
      typedef subgraph<Graph_> Graph;
sl@0
   313
      typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
sl@0
   314
      typedef typename graph_traits<Graph>::directed_category cat_type;
sl@0
   315
      typedef graphviz_io_traits<cat_type> Traits;
sl@0
   316
sl@0
   317
      typedef typename graph_property<Graph, graph_name_t>::type NameType;
sl@0
   318
      const NameType& g_name = get_property(g, graph_name);
sl@0
   319
sl@0
   320
      if ( g.is_root() )
sl@0
   321
        out << Traits::name() ;
sl@0
   322
      else
sl@0
   323
        out << "subgraph";
sl@0
   324
sl@0
   325
      out << " " << g_name << " {" << std::endl;
sl@0
   326
sl@0
   327
      typename Graph::const_children_iterator i_child, j_child;
sl@0
   328
sl@0
   329
      //print graph/node/edge attributes
sl@0
   330
#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300
sl@0
   331
      typedef typename graph_property<Graph, graph_graph_attribute_t>::type
sl@0
   332
        GAttrMap;
sl@0
   333
      typedef typename graph_property<Graph, graph_vertex_attribute_t>::type
sl@0
   334
        NAttrMap;
sl@0
   335
      typedef typename graph_property<Graph, graph_edge_attribute_t>::type
sl@0
   336
        EAttrMap;
sl@0
   337
      GAttrMap gam = get_property(g, graph_graph_attribute);
sl@0
   338
      NAttrMap nam = get_property(g, graph_vertex_attribute);
sl@0
   339
      EAttrMap eam = get_property(g, graph_edge_attribute);
sl@0
   340
      graph_attributes_writer<GAttrMap, NAttrMap, EAttrMap> writer(gam, nam, eam);
sl@0
   341
      writer(out);
sl@0
   342
#else
sl@0
   343
      make_graph_attributes_writer(g)(out);
sl@0
   344
#endif
sl@0
   345
sl@0
   346
      //print subgraph
sl@0
   347
      for ( tie(i_child,j_child) = g.children();
sl@0
   348
            i_child != j_child; ++i_child )
sl@0
   349
        write_graphviz_subgraph(out, *i_child, vertex_marker, edge_marker,
sl@0
   350
                                vertex_id);
sl@0
   351
sl@0
   352
      // Print out vertices and edges not in the subgraphs.
sl@0
   353
sl@0
   354
      typename graph_traits<Graph>::vertex_iterator i, end;
sl@0
   355
      typename graph_traits<Graph>::edge_iterator ei, edge_end;
sl@0
   356
sl@0
   357
      for(tie(i,end) = vertices(g); i != end; ++i) {
sl@0
   358
        Vertex v = g.local_to_global(*i);
sl@0
   359
        int pos = get(vertex_id, v);
sl@0
   360
        if ( vertex_marker[pos] ) {
sl@0
   361
          vertex_marker[pos] = false;
sl@0
   362
          out << pos;
sl@0
   363
#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300
sl@0
   364
          typedef typename property_map<Graph, vertex_attribute_t>::const_type
sl@0
   365
            VertexAttributeMap;
sl@0
   366
          attributes_writer<VertexAttributeMap> vawriter(get(vertex_attribute,
sl@0
   367
                                                             g.root()));
sl@0
   368
          vawriter(out, v);
sl@0
   369
#else
sl@0
   370
          make_vertex_attributes_writer(g.root())(out, v);
sl@0
   371
#endif
sl@0
   372
          out << ";" << std::endl;
sl@0
   373
        }
sl@0
   374
      }
sl@0
   375
sl@0
   376
      for (tie(ei, edge_end) = edges(g); ei != edge_end; ++ei) {
sl@0
   377
        Vertex u = g.local_to_global(source(*ei,g)),
sl@0
   378
          v = g.local_to_global(target(*ei, g));
sl@0
   379
        int pos = get(get(edge_index, g.root()), g.local_to_global(*ei));
sl@0
   380
        if ( edge_marker[pos] ) {
sl@0
   381
          edge_marker[pos] = false;
sl@0
   382
          out << get(vertex_id, u) << " " << Traits::delimiter()
sl@0
   383
              << " " << get(vertex_id, v);
sl@0
   384
#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300
sl@0
   385
          typedef typename property_map<Graph, edge_attribute_t>::const_type
sl@0
   386
            EdgeAttributeMap;
sl@0
   387
          attributes_writer<EdgeAttributeMap> eawriter(get(edge_attribute, g));
sl@0
   388
          eawriter(out, *ei);
sl@0
   389
#else
sl@0
   390
          make_edge_attributes_writer(g)(out, *ei); //print edge properties
sl@0
   391
#endif
sl@0
   392
          out << ";" << std::endl;
sl@0
   393
        }
sl@0
   394
      }
sl@0
   395
      out << "}" << std::endl;
sl@0
   396
    }
sl@0
   397
  } // namespace detail
sl@0
   398
sl@0
   399
  // requires graph_name graph property
sl@0
   400
  template <typename Graph>
sl@0
   401
  void write_graphviz(std::ostream& out, const subgraph<Graph>& g) {
sl@0
   402
    std::vector<bool> edge_marker(num_edges(g), true);
sl@0
   403
    std::vector<bool> vertex_marker(num_vertices(g), true);
sl@0
   404
sl@0
   405
    detail::write_graphviz_subgraph(out, g,
sl@0
   406
                                    vertex_marker.begin(),
sl@0
   407
                                    edge_marker.begin(), 
sl@0
   408
                                    get(vertex_index, g));
sl@0
   409
  }
sl@0
   410
sl@0
   411
  template <typename Graph>
sl@0
   412
  void write_graphviz(const std::string& filename, const subgraph<Graph>& g) {
sl@0
   413
    std::ofstream out(filename.c_str());
sl@0
   414
    std::vector<bool> edge_marker(num_edges(g), true);
sl@0
   415
    std::vector<bool> vertex_marker(num_vertices(g), true);
sl@0
   416
sl@0
   417
    detail::write_graphviz_subgraph(out, g,
sl@0
   418
                                    vertex_marker.begin(),
sl@0
   419
                                    edge_marker.begin(),
sl@0
   420
                                    get(vertex_index, g));
sl@0
   421
  }
sl@0
   422
sl@0
   423
  template <typename Graph, typename VertexID>
sl@0
   424
  void write_graphviz(std::ostream& out, const subgraph<Graph>& g,
sl@0
   425
                      VertexID vertex_id) 
sl@0
   426
  {
sl@0
   427
    std::vector<bool> edge_marker(num_edges(g), true);
sl@0
   428
    std::vector<bool> vertex_marker(num_vertices(g), true);
sl@0
   429
sl@0
   430
    detail::write_graphviz_subgraph(out, g,
sl@0
   431
                                    vertex_marker.begin(),
sl@0
   432
                                    edge_marker.begin(), 
sl@0
   433
                                    vertex_id);
sl@0
   434
  }
sl@0
   435
sl@0
   436
  template <typename Graph, typename VertexID>
sl@0
   437
  void write_graphviz(const std::string& filename, const subgraph<Graph>& g,
sl@0
   438
                      VertexID vertex_id) 
sl@0
   439
  {
sl@0
   440
    std::ofstream out(filename.c_str());
sl@0
   441
    std::vector<bool> edge_marker(num_edges(g), true);
sl@0
   442
    std::vector<bool> vertex_marker(num_vertices(g), true);
sl@0
   443
sl@0
   444
    detail::write_graphviz_subgraph(out, g,
sl@0
   445
                                    vertex_marker.begin(),
sl@0
   446
                                    edge_marker.begin(),
sl@0
   447
                                    vertex_id);
sl@0
   448
  }
sl@0
   449
sl@0
   450
  typedef std::map<std::string, std::string> GraphvizAttrList;
sl@0
   451
sl@0
   452
  typedef property<vertex_attribute_t, GraphvizAttrList>
sl@0
   453
          GraphvizVertexProperty;
sl@0
   454
sl@0
   455
  typedef property<edge_attribute_t, GraphvizAttrList,
sl@0
   456
                   property<edge_index_t, int> >
sl@0
   457
          GraphvizEdgeProperty;
sl@0
   458
sl@0
   459
  typedef property<graph_graph_attribute_t, GraphvizAttrList,
sl@0
   460
                   property<graph_vertex_attribute_t, GraphvizAttrList,
sl@0
   461
                   property<graph_edge_attribute_t, GraphvizAttrList,
sl@0
   462
                   property<graph_name_t, std::string> > > >
sl@0
   463
          GraphvizGraphProperty;
sl@0
   464
sl@0
   465
  typedef subgraph<adjacency_list<vecS,
sl@0
   466
                   vecS, directedS,
sl@0
   467
                   GraphvizVertexProperty,
sl@0
   468
                   GraphvizEdgeProperty,
sl@0
   469
                   GraphvizGraphProperty> >
sl@0
   470
          GraphvizDigraph;
sl@0
   471
sl@0
   472
  typedef subgraph<adjacency_list<vecS,
sl@0
   473
                   vecS, undirectedS,
sl@0
   474
                   GraphvizVertexProperty,
sl@0
   475
                   GraphvizEdgeProperty,
sl@0
   476
                   GraphvizGraphProperty> >
sl@0
   477
          GraphvizGraph;
sl@0
   478
sl@0
   479
sl@0
   480
  // These four require linking the BGL-Graphviz library: libbgl-viz.a
sl@0
   481
  // from the /src directory.
sl@0
   482
  extern void read_graphviz(const std::string& file, GraphvizDigraph& g);
sl@0
   483
  extern void read_graphviz(FILE* file, GraphvizDigraph& g);
sl@0
   484
sl@0
   485
  extern void read_graphviz(const std::string& file, GraphvizGraph& g);
sl@0
   486
  extern void read_graphviz(FILE* file, GraphvizGraph& g);
sl@0
   487
sl@0
   488
  class dynamic_properties_writer
sl@0
   489
  {
sl@0
   490
  public:
sl@0
   491
    dynamic_properties_writer(const dynamic_properties& dp) : dp(&dp) { }
sl@0
   492
sl@0
   493
    template<typename Descriptor>
sl@0
   494
    void operator()(std::ostream& out, Descriptor key) const
sl@0
   495
    {
sl@0
   496
      bool first = true;
sl@0
   497
      for (dynamic_properties::const_iterator i = dp->begin(); 
sl@0
   498
           i != dp->end(); ++i) {
sl@0
   499
        if (typeid(key) == i->second->key()) {
sl@0
   500
          if (first) out << " [";
sl@0
   501
          else out << ", ";
sl@0
   502
          first = false;
sl@0
   503
sl@0
   504
          out << i->first << "=\"" << i->second->get_string(key) << "\"";
sl@0
   505
        }
sl@0
   506
      }
sl@0
   507
sl@0
   508
      if (!first) out << "]";
sl@0
   509
    }
sl@0
   510
sl@0
   511
  private:
sl@0
   512
    const dynamic_properties* dp;
sl@0
   513
  };
sl@0
   514
sl@0
   515
  class dynamic_vertex_properties_writer
sl@0
   516
  {
sl@0
   517
  public:
sl@0
   518
    dynamic_vertex_properties_writer(const dynamic_properties& dp,
sl@0
   519
                                     const std::string& node_id) 
sl@0
   520
      : dp(&dp), node_id(&node_id) { }
sl@0
   521
sl@0
   522
    template<typename Descriptor>
sl@0
   523
    void operator()(std::ostream& out, Descriptor key) const
sl@0
   524
    {
sl@0
   525
      bool first = true;
sl@0
   526
      for (dynamic_properties::const_iterator i = dp->begin(); 
sl@0
   527
           i != dp->end(); ++i) {
sl@0
   528
        if (typeid(key) == i->second->key()
sl@0
   529
            && i->first != *node_id) {
sl@0
   530
          if (first) out << " [";
sl@0
   531
          else out << ", ";
sl@0
   532
          first = false;
sl@0
   533
sl@0
   534
          out << i->first << "=\"" << i->second->get_string(key) << "\"";
sl@0
   535
        }
sl@0
   536
      }
sl@0
   537
sl@0
   538
      if (!first) out << "]";
sl@0
   539
    }
sl@0
   540
sl@0
   541
  private:
sl@0
   542
    const dynamic_properties* dp;
sl@0
   543
    const std::string* node_id;
sl@0
   544
  };
sl@0
   545
sl@0
   546
  namespace graph { namespace detail {
sl@0
   547
sl@0
   548
    template<typename Vertex>
sl@0
   549
    struct node_id_property_map
sl@0
   550
    {
sl@0
   551
      typedef std::string value_type;
sl@0
   552
      typedef value_type reference;
sl@0
   553
      typedef Vertex key_type;
sl@0
   554
      typedef readable_property_map_tag category;
sl@0
   555
sl@0
   556
      node_id_property_map() {}
sl@0
   557
sl@0
   558
      node_id_property_map(const dynamic_properties& dp,
sl@0
   559
                           const std::string& node_id)
sl@0
   560
        : dp(&dp), node_id(&node_id) { }
sl@0
   561
sl@0
   562
      const dynamic_properties* dp;
sl@0
   563
      const std::string* node_id;
sl@0
   564
    };
sl@0
   565
sl@0
   566
    template<typename Vertex>
sl@0
   567
    inline std::string 
sl@0
   568
    get(node_id_property_map<Vertex> pm, 
sl@0
   569
        typename node_id_property_map<Vertex>::key_type v)
sl@0
   570
    { return get(*pm.node_id, *pm.dp, v); }
sl@0
   571
sl@0
   572
  } } // end namespace graph::detail
sl@0
   573
sl@0
   574
  template<typename Graph>
sl@0
   575
  inline void
sl@0
   576
  write_graphviz(std::ostream& out, const Graph& g,
sl@0
   577
                 const dynamic_properties& dp, 
sl@0
   578
                 const std::string& node_id = "node_id")
sl@0
   579
  {
sl@0
   580
    typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
sl@0
   581
    write_graphviz(out, g, dp, node_id,
sl@0
   582
                   graph::detail::node_id_property_map<Vertex>(dp, node_id));
sl@0
   583
  }
sl@0
   584
sl@0
   585
  template<typename Graph, typename VertexID>
sl@0
   586
  void
sl@0
   587
  write_graphviz(std::ostream& out, const Graph& g,
sl@0
   588
                 const dynamic_properties& dp, const std::string& node_id,
sl@0
   589
                 VertexID id)
sl@0
   590
  {
sl@0
   591
    write_graphviz
sl@0
   592
      (out, g,
sl@0
   593
       /*vertex_writer=*/dynamic_vertex_properties_writer(dp, node_id),
sl@0
   594
       /*edge_writer=*/dynamic_properties_writer(dp),
sl@0
   595
       /*graph_writer=*/default_writer(),
sl@0
   596
       id);
sl@0
   597
  }
sl@0
   598
sl@0
   599
/////////////////////////////////////////////////////////////////////////////
sl@0
   600
// Graph reader exceptions
sl@0
   601
/////////////////////////////////////////////////////////////////////////////
sl@0
   602
struct graph_exception : public std::exception {
sl@0
   603
  virtual ~graph_exception() throw() {}
sl@0
   604
  virtual const char* what() const throw() = 0;
sl@0
   605
};
sl@0
   606
sl@0
   607
struct bad_parallel_edge : public graph_exception {
sl@0
   608
  std::string from;
sl@0
   609
  std::string to;
sl@0
   610
  mutable std::string statement;
sl@0
   611
  bad_parallel_edge(const std::string& i, const std::string& j) :
sl@0
   612
    from(i), to(j) {}
sl@0
   613
sl@0
   614
  virtual ~bad_parallel_edge() throw() {}
sl@0
   615
  const char* what() const throw() {
sl@0
   616
    if(statement.empty())
sl@0
   617
      statement =
sl@0
   618
        std::string("Failed to add parallel edge: (")
sl@0
   619
        + from +  "," + to + ")\n";
sl@0
   620
sl@0
   621
    return statement.c_str();
sl@0
   622
  }
sl@0
   623
};
sl@0
   624
sl@0
   625
struct directed_graph_error : public graph_exception {
sl@0
   626
  virtual ~directed_graph_error() throw() {}
sl@0
   627
  virtual const char* what() const throw() {
sl@0
   628
    return
sl@0
   629
      "read_graphviz: "
sl@0
   630
      "Tried to read a directed graph into an undirected graph.";
sl@0
   631
  }
sl@0
   632
};
sl@0
   633
sl@0
   634
struct undirected_graph_error : public graph_exception {
sl@0
   635
  virtual ~undirected_graph_error() throw() {}
sl@0
   636
  virtual const char* what() const throw() {
sl@0
   637
    return
sl@0
   638
      "read_graphviz: "
sl@0
   639
      "Tried to read an undirected graph into a directed graph.";
sl@0
   640
  }
sl@0
   641
};
sl@0
   642
sl@0
   643
namespace detail { namespace graph {
sl@0
   644
sl@0
   645
typedef std::string id_t;
sl@0
   646
typedef id_t node_t;
sl@0
   647
sl@0
   648
// edges are not uniquely determined by adjacent nodes
sl@0
   649
class edge_t {
sl@0
   650
  int idx_;
sl@0
   651
  explicit edge_t(int i) : idx_(i) {}
sl@0
   652
public:
sl@0
   653
  static edge_t new_edge() {
sl@0
   654
    static int idx = 0;
sl@0
   655
    return edge_t(idx++);
sl@0
   656
  };
sl@0
   657
  
sl@0
   658
  bool operator==(const edge_t& rhs) const {
sl@0
   659
    return idx_ == rhs.idx_;
sl@0
   660
  }
sl@0
   661
  bool operator<(const edge_t& rhs) const {
sl@0
   662
    return idx_ < rhs.idx_;
sl@0
   663
  }
sl@0
   664
};
sl@0
   665
sl@0
   666
class mutate_graph
sl@0
   667
{
sl@0
   668
 public:
sl@0
   669
  virtual ~mutate_graph() {}
sl@0
   670
  virtual bool is_directed() const = 0;
sl@0
   671
  virtual void do_add_vertex(const node_t& node) = 0;
sl@0
   672
sl@0
   673
  virtual void 
sl@0
   674
  do_add_edge(const edge_t& edge, const node_t& source, const node_t& target)
sl@0
   675
    = 0;
sl@0
   676
sl@0
   677
  virtual void 
sl@0
   678
  set_node_property(const id_t& key, const node_t& node, const id_t& value) = 0;
sl@0
   679
sl@0
   680
  virtual void 
sl@0
   681
  set_edge_property(const id_t& key, const edge_t& edge, const id_t& value) = 0;
sl@0
   682
};
sl@0
   683
sl@0
   684
template<typename MutableGraph>
sl@0
   685
class mutate_graph_impl : public mutate_graph
sl@0
   686
{
sl@0
   687
  typedef typename graph_traits<MutableGraph>::vertex_descriptor bgl_vertex_t;
sl@0
   688
  typedef typename graph_traits<MutableGraph>::edge_descriptor   bgl_edge_t;
sl@0
   689
sl@0
   690
 public:
sl@0
   691
  mutate_graph_impl(MutableGraph& graph, dynamic_properties& dp,
sl@0
   692
                    std::string node_id_prop)
sl@0
   693
    : graph_(graph), dp_(dp), node_id_prop_(node_id_prop) { }
sl@0
   694
sl@0
   695
  ~mutate_graph_impl() {}
sl@0
   696
sl@0
   697
  bool is_directed() const
sl@0
   698
  {
sl@0
   699
    return 
sl@0
   700
      boost::is_convertible<
sl@0
   701
        typename boost::graph_traits<MutableGraph>::directed_category,
sl@0
   702
        boost::directed_tag>::value;
sl@0
   703
  }
sl@0
   704
sl@0
   705
  virtual void do_add_vertex(const node_t& node)
sl@0
   706
  {
sl@0
   707
    // Add the node to the graph.
sl@0
   708
    bgl_vertex_t v = add_vertex(graph_);
sl@0
   709
sl@0
   710
    // Set up a mapping from name to BGL vertex.
sl@0
   711
    bgl_nodes.insert(std::make_pair(node, v));
sl@0
   712
    
sl@0
   713
    // node_id_prop_ allows the caller to see the real id names for nodes.
sl@0
   714
    put(node_id_prop_, dp_, v, node);
sl@0
   715
  }
sl@0
   716
sl@0
   717
  void 
sl@0
   718
  do_add_edge(const edge_t& edge, const node_t& source, const node_t& target)
sl@0
   719
  {
sl@0
   720
    std::pair<bgl_edge_t, bool> result =
sl@0
   721
     add_edge(bgl_nodes[source], bgl_nodes[target], graph_);
sl@0
   722
    
sl@0
   723
    if(!result.second) {
sl@0
   724
      // In the case of no parallel edges allowed
sl@0
   725
      throw bad_parallel_edge(source, target);
sl@0
   726
    } else {
sl@0
   727
      bgl_edges.insert(std::make_pair(edge, result.first));
sl@0
   728
    }
sl@0
   729
  }
sl@0
   730
sl@0
   731
  void
sl@0
   732
  set_node_property(const id_t& key, const node_t& node, const id_t& value)
sl@0
   733
  {
sl@0
   734
    put(key, dp_, bgl_nodes[node], value);
sl@0
   735
  }
sl@0
   736
sl@0
   737
  void
sl@0
   738
  set_edge_property(const id_t& key, const edge_t& edge, const id_t& value)
sl@0
   739
  {
sl@0
   740
    put(key, dp_, bgl_edges[edge], value);
sl@0
   741
  }
sl@0
   742
sl@0
   743
 protected:
sl@0
   744
  MutableGraph& graph_;
sl@0
   745
  dynamic_properties& dp_;
sl@0
   746
  std::string node_id_prop_;
sl@0
   747
  std::map<node_t, bgl_vertex_t> bgl_nodes;
sl@0
   748
  std::map<edge_t, bgl_edge_t> bgl_edges;
sl@0
   749
};
sl@0
   750
sl@0
   751
BOOST_GRAPH_DECL
sl@0
   752
bool read_graphviz(std::istream& in, mutate_graph& graph);
sl@0
   753
sl@0
   754
} } // end namespace detail::graph
sl@0
   755
sl@0
   756
// Parse the passed stream as a GraphViz dot file.
sl@0
   757
template <typename MutableGraph>
sl@0
   758
bool read_graphviz(std::istream& in, MutableGraph& graph,
sl@0
   759
                   dynamic_properties& dp,
sl@0
   760
                   std::string const& node_id = "node_id") 
sl@0
   761
{
sl@0
   762
  detail::graph::mutate_graph_impl<MutableGraph> m_graph(graph, dp, node_id);
sl@0
   763
  return detail::graph::read_graphviz(in, m_graph);
sl@0
   764
}
sl@0
   765
sl@0
   766
} // namespace boost
sl@0
   767
sl@0
   768
#ifdef BOOST_GRAPH_READ_GRAPHVIZ_ITERATORS
sl@0
   769
#  include <boost/graph/detail/read_graphviz_spirit.hpp>
sl@0
   770
#endif // BOOST_GRAPH_READ_GRAPHVIZ_ITERATORS
sl@0
   771
sl@0
   772
#endif // BOOST_GRAPHVIZ_HPP