lemon/lgf_writer.h
author Peter Kovacs <kpeter@inf.elte.hu>
Sat, 16 Mar 2013 14:11:32 +0100
changeset 1052 eb2f9d453070
parent 1026 699c7eac2c6d
child 1074 97d978243703
permissions -rw-r--r--
Adjust the formatting of bib2dox.py to Doxygen 1.8.x (#459)
alpar@209
     1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
deba@127
     2
 *
alpar@209
     3
 * This file is a part of LEMON, a generic C++ optimization library.
deba@127
     4
 *
alpar@877
     5
 * Copyright (C) 2003-2010
deba@127
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
deba@127
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
deba@127
     8
 *
deba@127
     9
 * Permission to use, modify and distribute this software is granted
deba@127
    10
 * provided that this copyright notice appears in all copies. For
deba@127
    11
 * precise terms see the accompanying LICENSE file.
deba@127
    12
 *
deba@127
    13
 * This software is provided "AS IS" with no warranty of any kind,
deba@127
    14
 * express or implied, and with no claim as to its suitability for any
deba@127
    15
 * purpose.
deba@127
    16
 *
deba@127
    17
 */
deba@127
    18
deba@127
    19
///\ingroup lemon_io
deba@127
    20
///\file
ladanyi@236
    21
///\brief \ref lgf-format "LEMON Graph Format" writer.
deba@127
    22
deba@127
    23
deba@127
    24
#ifndef LEMON_LGF_WRITER_H
deba@127
    25
#define LEMON_LGF_WRITER_H
deba@127
    26
deba@127
    27
#include <iostream>
deba@127
    28
#include <fstream>
deba@127
    29
#include <sstream>
deba@127
    30
deba@127
    31
#include <algorithm>
deba@127
    32
deba@127
    33
#include <vector>
deba@127
    34
#include <functional>
deba@127
    35
deba@220
    36
#include <lemon/core.h>
deba@220
    37
#include <lemon/maps.h>
deba@127
    38
deba@248
    39
#include <lemon/concept_check.h>
deba@248
    40
#include <lemon/concepts/maps.h>
deba@248
    41
deba@127
    42
namespace lemon {
deba@127
    43
deba@127
    44
  namespace _writer_bits {
deba@127
    45
deba@127
    46
    template <typename Value>
deba@127
    47
    struct DefaultConverter {
deba@127
    48
      std::string operator()(const Value& value) {
alpar@209
    49
        std::ostringstream os;
alpar@209
    50
        os << value;
alpar@209
    51
        return os.str();
deba@127
    52
      }
deba@127
    53
    };
deba@127
    54
deba@127
    55
    template <typename T>
deba@127
    56
    bool operator<(const T&, const T&) {
deba@290
    57
      throw FormatError("Label map is not comparable");
deba@127
    58
    }
deba@127
    59
deba@127
    60
    template <typename _Map>
deba@127
    61
    class MapLess {
deba@127
    62
    public:
deba@127
    63
      typedef _Map Map;
deba@127
    64
      typedef typename Map::Key Item;
deba@127
    65
deba@127
    66
    private:
deba@127
    67
      const Map& _map;
alpar@209
    68
deba@127
    69
    public:
deba@127
    70
      MapLess(const Map& map) : _map(map) {}
deba@127
    71
deba@127
    72
      bool operator()(const Item& left, const Item& right) {
alpar@209
    73
        return _map[left] < _map[right];
deba@127
    74
      }
deba@127
    75
    };
deba@127
    76
deba@165
    77
    template <typename _Graph, bool _dir, typename _Map>
deba@165
    78
    class GraphArcMapLess {
deba@165
    79
    public:
deba@165
    80
      typedef _Map Map;
deba@165
    81
      typedef _Graph Graph;
deba@165
    82
      typedef typename Graph::Edge Item;
deba@165
    83
deba@165
    84
    private:
deba@165
    85
      const Graph& _graph;
deba@165
    86
      const Map& _map;
alpar@209
    87
deba@165
    88
    public:
alpar@209
    89
      GraphArcMapLess(const Graph& graph, const Map& map)
alpar@209
    90
        : _graph(graph), _map(map) {}
deba@165
    91
deba@165
    92
      bool operator()(const Item& left, const Item& right) {
alpar@209
    93
        return _map[_graph.direct(left, _dir)] <
alpar@209
    94
          _map[_graph.direct(right, _dir)];
deba@165
    95
      }
deba@165
    96
    };
deba@165
    97
alpar@209
    98
    template <typename _Item>
deba@127
    99
    class MapStorageBase {
deba@127
   100
    public:
deba@127
   101
      typedef _Item Item;
deba@127
   102
deba@127
   103
    public:
deba@127
   104
      MapStorageBase() {}
deba@127
   105
      virtual ~MapStorageBase() {}
deba@127
   106
deba@127
   107
      virtual std::string get(const Item& item) = 0;
deba@127
   108
      virtual void sort(std::vector<Item>&) = 0;
deba@127
   109
    };
deba@127
   110
alpar@209
   111
    template <typename _Item, typename _Map,
alpar@209
   112
              typename _Converter = DefaultConverter<typename _Map::Value> >
deba@127
   113
    class MapStorage : public MapStorageBase<_Item> {
deba@127
   114
    public:
deba@127
   115
      typedef _Map Map;
deba@127
   116
      typedef _Converter Converter;
deba@127
   117
      typedef _Item Item;
alpar@209
   118
deba@127
   119
    private:
deba@127
   120
      const Map& _map;
deba@127
   121
      Converter _converter;
deba@127
   122
deba@127
   123
    public:
alpar@209
   124
      MapStorage(const Map& map, const Converter& converter = Converter())
alpar@209
   125
        : _map(map), _converter(converter) {}
deba@127
   126
      virtual ~MapStorage() {}
deba@127
   127
deba@127
   128
      virtual std::string get(const Item& item) {
alpar@209
   129
        return _converter(_map[item]);
deba@127
   130
      }
deba@127
   131
      virtual void sort(std::vector<Item>& items) {
alpar@209
   132
        MapLess<Map> less(_map);
alpar@209
   133
        std::sort(items.begin(), items.end(), less);
deba@127
   134
      }
deba@127
   135
    };
deba@127
   136
alpar@209
   137
    template <typename _Graph, bool _dir, typename _Map,
alpar@209
   138
              typename _Converter = DefaultConverter<typename _Map::Value> >
deba@165
   139
    class GraphArcMapStorage : public MapStorageBase<typename _Graph::Edge> {
deba@165
   140
    public:
deba@165
   141
      typedef _Map Map;
deba@165
   142
      typedef _Converter Converter;
deba@165
   143
      typedef _Graph Graph;
deba@165
   144
      typedef typename Graph::Edge Item;
deba@165
   145
      static const bool dir = _dir;
alpar@209
   146
deba@165
   147
    private:
deba@165
   148
      const Graph& _graph;
deba@165
   149
      const Map& _map;
deba@165
   150
      Converter _converter;
deba@165
   151
deba@165
   152
    public:
alpar@209
   153
      GraphArcMapStorage(const Graph& graph, const Map& map,
alpar@209
   154
                         const Converter& converter = Converter())
alpar@209
   155
        : _graph(graph), _map(map), _converter(converter) {}
deba@165
   156
      virtual ~GraphArcMapStorage() {}
deba@165
   157
deba@165
   158
      virtual std::string get(const Item& item) {
alpar@209
   159
        return _converter(_map[_graph.direct(item, dir)]);
deba@165
   160
      }
deba@165
   161
      virtual void sort(std::vector<Item>& items) {
alpar@209
   162
        GraphArcMapLess<Graph, dir, Map> less(_graph, _map);
alpar@209
   163
        std::sort(items.begin(), items.end(), less);
deba@165
   164
      }
deba@165
   165
    };
deba@165
   166
deba@127
   167
    class ValueStorageBase {
deba@127
   168
    public:
deba@127
   169
      ValueStorageBase() {}
deba@127
   170
      virtual ~ValueStorageBase() {}
deba@127
   171
alpar@209
   172
      virtual std::string get() = 0;
deba@127
   173
    };
deba@127
   174
deba@127
   175
    template <typename _Value, typename _Converter = DefaultConverter<_Value> >
deba@127
   176
    class ValueStorage : public ValueStorageBase {
deba@127
   177
    public:
deba@127
   178
      typedef _Value Value;
deba@127
   179
      typedef _Converter Converter;
deba@127
   180
deba@127
   181
    private:
deba@127
   182
      const Value& _value;
deba@127
   183
      Converter _converter;
deba@127
   184
deba@127
   185
    public:
deba@127
   186
      ValueStorage(const Value& value, const Converter& converter = Converter())
kpeter@212
   187
        : _value(value), _converter(converter) {}
deba@1030
   188
      
deba@127
   189
      virtual std::string get() {
alpar@209
   190
        return _converter(_value);
deba@127
   191
      }
deba@127
   192
    };
deba@127
   193
deba@1030
   194
    template <typename Value,
deba@1030
   195
              typename Map = std::map<Value, std::string> >
deba@127
   196
    struct MapLookUpConverter {
deba@1030
   197
      const Map& _map;
alpar@209
   198
deba@1030
   199
      MapLookUpConverter(const Map& map)
alpar@209
   200
        : _map(map) {}
alpar@209
   201
deba@1030
   202
      std::string operator()(const Value& value) {
deba@1030
   203
        typename Map::const_iterator it = _map.find(value);
alpar@209
   204
        if (it == _map.end()) {
deba@290
   205
          throw FormatError("Item not found");
alpar@209
   206
        }
alpar@209
   207
        return it->second;
deba@127
   208
      }
deba@127
   209
    };
deba@127
   210
deba@1030
   211
    template <typename Value,
deba@1030
   212
              typename Map1 = std::map<Value, std::string>,
deba@1030
   213
              typename Map2 = std::map<Value, std::string> >
deba@1030
   214
    struct DoubleMapLookUpConverter {
deba@1030
   215
      const Map1& _map1;
deba@1030
   216
      const Map2& _map2;
deba@1030
   217
deba@1030
   218
      DoubleMapLookUpConverter(const Map1& map1, const Map2& map2)
deba@1030
   219
        : _map1(map1), _map2(map2) {}
deba@1030
   220
deba@1030
   221
      std::string operator()(const Value& value) {
deba@1030
   222
        typename Map1::const_iterator it1 = _map1.find(value);
deba@1030
   223
        typename Map1::const_iterator it2 = _map2.find(value);
deba@1030
   224
        if (it1 == _map1.end()) {
deba@1030
   225
          if (it2 == _map2.end()) {
deba@1030
   226
            throw FormatError("Item not found");
deba@1030
   227
          } else {
deba@1030
   228
            return it2->second;
deba@1030
   229
          }
deba@1030
   230
        } else {
deba@1030
   231
          if (it2 == _map2.end()) {
deba@1030
   232
            return it1->second;
deba@1030
   233
          } else {
deba@1030
   234
            throw FormatError("Item is ambigous");
deba@1030
   235
          }
deba@1030
   236
        }
deba@1030
   237
      }
deba@1030
   238
    };
deba@1030
   239
deba@165
   240
    template <typename Graph>
deba@165
   241
    struct GraphArcLookUpConverter {
deba@165
   242
      const Graph& _graph;
deba@165
   243
      const std::map<typename Graph::Edge, std::string>& _map;
alpar@209
   244
alpar@209
   245
      GraphArcLookUpConverter(const Graph& graph,
alpar@209
   246
                              const std::map<typename Graph::Edge,
alpar@209
   247
                                             std::string>& map)
alpar@209
   248
        : _graph(graph), _map(map) {}
alpar@209
   249
deba@165
   250
      std::string operator()(const typename Graph::Arc& val) {
alpar@209
   251
        typename std::map<typename Graph::Edge, std::string>
alpar@209
   252
          ::const_iterator it = _map.find(val);
alpar@209
   253
        if (it == _map.end()) {
deba@290
   254
          throw FormatError("Item not found");
alpar@209
   255
        }
alpar@209
   256
        return (_graph.direction(val) ? '+' : '-') + it->second;
deba@165
   257
      }
deba@165
   258
    };
deba@165
   259
deba@197
   260
    inline bool isWhiteSpace(char c) {
alpar@209
   261
      return c == ' ' || c == '\t' || c == '\v' ||
alpar@209
   262
        c == '\n' || c == '\r' || c == '\f';
deba@127
   263
    }
deba@127
   264
deba@197
   265
    inline bool isEscaped(char c) {
alpar@209
   266
      return c == '\\' || c == '\"' || c == '\'' ||
alpar@209
   267
        c == '\a' || c == '\b';
deba@127
   268
    }
deba@127
   269
deba@197
   270
    inline static void writeEscape(std::ostream& os, char c) {
deba@127
   271
      switch (c) {
deba@127
   272
      case '\\':
alpar@209
   273
        os << "\\\\";
alpar@209
   274
        return;
deba@127
   275
      case '\"':
alpar@209
   276
        os << "\\\"";
alpar@209
   277
        return;
deba@127
   278
      case '\a':
alpar@209
   279
        os << "\\a";
alpar@209
   280
        return;
deba@127
   281
      case '\b':
alpar@209
   282
        os << "\\b";
alpar@209
   283
        return;
deba@127
   284
      case '\f':
alpar@209
   285
        os << "\\f";
alpar@209
   286
        return;
deba@127
   287
      case '\r':
alpar@209
   288
        os << "\\r";
alpar@209
   289
        return;
deba@127
   290
      case '\n':
alpar@209
   291
        os << "\\n";
alpar@209
   292
        return;
deba@127
   293
      case '\t':
alpar@209
   294
        os << "\\t";
alpar@209
   295
        return;
deba@127
   296
      case '\v':
alpar@209
   297
        os << "\\v";
alpar@209
   298
        return;
deba@127
   299
      default:
alpar@209
   300
        if (c < 0x20) {
alpar@209
   301
          std::ios::fmtflags flags = os.flags();
alpar@209
   302
          os << '\\' << std::oct << static_cast<int>(c);
alpar@209
   303
          os.flags(flags);
alpar@209
   304
        } else {
alpar@209
   305
          os << c;
alpar@209
   306
        }
alpar@209
   307
        return;
alpar@209
   308
      }
deba@127
   309
    }
deba@127
   310
deba@197
   311
    inline bool requireEscape(const std::string& str) {
alpar@156
   312
      if (str.empty() || str[0] == '@') return true;
deba@127
   313
      std::istringstream is(str);
deba@127
   314
      char c;
deba@127
   315
      while (is.get(c)) {
alpar@209
   316
        if (isWhiteSpace(c) || isEscaped(c)) {
alpar@209
   317
          return true;
alpar@209
   318
        }
deba@127
   319
      }
deba@127
   320
      return false;
deba@127
   321
    }
alpar@209
   322
deba@197
   323
    inline std::ostream& writeToken(std::ostream& os, const std::string& str) {
deba@127
   324
deba@127
   325
      if (requireEscape(str)) {
alpar@209
   326
        os << '\"';
alpar@209
   327
        for (std::string::const_iterator it = str.begin();
alpar@209
   328
             it != str.end(); ++it) {
alpar@209
   329
          writeEscape(os, *it);
alpar@209
   330
        }
alpar@209
   331
        os << '\"';
deba@127
   332
      } else {
alpar@209
   333
        os << str;
deba@127
   334
      }
deba@127
   335
      return os;
deba@127
   336
    }
deba@127
   337
deba@248
   338
    class Section {
deba@248
   339
    public:
deba@248
   340
      virtual ~Section() {}
deba@248
   341
      virtual void process(std::ostream& os) = 0;
deba@248
   342
    };
deba@248
   343
deba@248
   344
    template <typename Functor>
deba@248
   345
    class LineSection : public Section {
deba@248
   346
    private:
deba@248
   347
deba@248
   348
      Functor _functor;
deba@248
   349
deba@248
   350
    public:
deba@248
   351
deba@248
   352
      LineSection(const Functor& functor) : _functor(functor) {}
deba@248
   353
      virtual ~LineSection() {}
deba@248
   354
deba@248
   355
      virtual void process(std::ostream& os) {
deba@248
   356
        std::string line;
deba@248
   357
        while (!(line = _functor()).empty()) os << line << std::endl;
deba@248
   358
      }
deba@248
   359
    };
deba@248
   360
deba@248
   361
    template <typename Functor>
deba@248
   362
    class StreamSection : public Section {
deba@248
   363
    private:
deba@248
   364
deba@248
   365
      Functor _functor;
deba@248
   366
deba@248
   367
    public:
deba@248
   368
deba@248
   369
      StreamSection(const Functor& functor) : _functor(functor) {}
deba@248
   370
      virtual ~StreamSection() {}
deba@248
   371
deba@248
   372
      virtual void process(std::ostream& os) {
deba@248
   373
        _functor(os);
deba@248
   374
      }
deba@248
   375
    };
deba@248
   376
deba@127
   377
  }
deba@190
   378
deba@598
   379
  template <typename DGR>
deba@190
   380
  class DigraphWriter;
deba@190
   381
deba@598
   382
  template <typename TDGR>
alpar@877
   383
  DigraphWriter<TDGR> digraphWriter(const TDGR& digraph,
deba@598
   384
                                   std::ostream& os = std::cout);
deba@598
   385
  template <typename TDGR>
deba@598
   386
  DigraphWriter<TDGR> digraphWriter(const TDGR& digraph, const std::string& fn);
deba@190
   387
deba@598
   388
  template <typename TDGR>
deba@598
   389
  DigraphWriter<TDGR> digraphWriter(const TDGR& digraph, const char* fn);
kpeter@498
   390
alpar@209
   391
alpar@156
   392
  /// \ingroup lemon_io
alpar@209
   393
  ///
kpeter@192
   394
  /// \brief \ref lgf-format "LGF" writer for directed graphs
alpar@156
   395
  ///
alpar@156
   396
  /// This utility writes an \ref lgf-format "LGF" file.
alpar@156
   397
  ///
alpar@156
   398
  /// The writing method does a batch processing. The user creates a
alpar@156
   399
  /// writer object, then various writing rules can be added to the
alpar@156
   400
  /// writer, and eventually the writing is executed with the \c run()
alpar@156
   401
  /// member function. A map writing rule can be added to the writer
alpar@156
   402
  /// with the \c nodeMap() or \c arcMap() members. An optional
deba@163
   403
  /// converter parameter can also be added as a standard functor
kpeter@192
   404
  /// converting from the value type of the map to \c std::string. If it
kpeter@192
   405
  /// is set, it will determine how the value type of the map is written to
deba@163
   406
  /// the output stream. If the functor is not set, then a default
deba@163
   407
  /// conversion will be used. The \c attribute(), \c node() and \c
deba@163
   408
  /// arc() functions are used to add attribute writing rules.
alpar@156
   409
  ///
alpar@156
   410
  ///\code
deba@598
   411
  /// DigraphWriter<DGR>(digraph, std::cout).
kpeter@192
   412
  ///   nodeMap("coordinates", coord_map).
kpeter@192
   413
  ///   nodeMap("size", size).
kpeter@192
   414
  ///   nodeMap("title", title).
kpeter@192
   415
  ///   arcMap("capacity", cap_map).
kpeter@192
   416
  ///   node("source", src).
kpeter@192
   417
  ///   node("target", trg).
kpeter@192
   418
  ///   attribute("caption", caption).
kpeter@192
   419
  ///   run();
alpar@156
   420
  ///\endcode
alpar@156
   421
  ///
alpar@156
   422
  ///
alpar@156
   423
  /// By default, the writer does not write additional captions to the
alpar@156
   424
  /// sections, but they can be give as an optional parameter of
alpar@156
   425
  /// the \c nodes(), \c arcs() or \c
alpar@156
   426
  /// attributes() functions.
alpar@156
   427
  ///
alpar@156
   428
  /// The \c skipNodes() and \c skipArcs() functions forbid the
deba@163
   429
  /// writing of the sections. If two arc sections should be written
deba@163
   430
  /// to the output, it can be done in two passes, the first pass
deba@163
   431
  /// writes the node section and the first arc section, then the
deba@163
   432
  /// second pass skips the node section and writes just the arc
deba@163
   433
  /// section to the stream. The output stream can be retrieved with
deba@163
   434
  /// the \c ostream() function, hence the second pass can append its
deba@163
   435
  /// output to the output of the first pass.
deba@598
   436
  template <typename DGR>
deba@127
   437
  class DigraphWriter {
deba@127
   438
  public:
deba@127
   439
deba@598
   440
    typedef DGR Digraph;
deba@598
   441
    TEMPLATE_DIGRAPH_TYPEDEFS(DGR);
alpar@209
   442
deba@127
   443
  private:
deba@127
   444
deba@127
   445
deba@127
   446
    std::ostream* _os;
deba@127
   447
    bool local_os;
deba@127
   448
deba@598
   449
    const DGR& _digraph;
deba@127
   450
deba@127
   451
    std::string _nodes_caption;
deba@127
   452
    std::string _arcs_caption;
deba@127
   453
    std::string _attributes_caption;
alpar@209
   454
deba@127
   455
    typedef std::map<Node, std::string> NodeIndex;
deba@127
   456
    NodeIndex _node_index;
deba@127
   457
    typedef std::map<Arc, std::string> ArcIndex;
deba@127
   458
    ArcIndex _arc_index;
deba@127
   459
alpar@209
   460
    typedef std::vector<std::pair<std::string,
alpar@209
   461
      _writer_bits::MapStorageBase<Node>* > > NodeMaps;
alpar@209
   462
    NodeMaps _node_maps;
deba@127
   463
alpar@209
   464
    typedef std::vector<std::pair<std::string,
deba@127
   465
      _writer_bits::MapStorageBase<Arc>* > >ArcMaps;
deba@127
   466
    ArcMaps _arc_maps;
deba@127
   467
alpar@209
   468
    typedef std::vector<std::pair<std::string,
deba@127
   469
      _writer_bits::ValueStorageBase*> > Attributes;
deba@127
   470
    Attributes _attributes;
deba@127
   471
deba@127
   472
    bool _skip_nodes;
deba@127
   473
    bool _skip_arcs;
deba@127
   474
deba@127
   475
  public:
deba@127
   476
alpar@156
   477
    /// \brief Constructor
alpar@156
   478
    ///
alpar@156
   479
    /// Construct a directed graph writer, which writes to the given
alpar@156
   480
    /// output stream.
deba@598
   481
    DigraphWriter(const DGR& digraph, std::ostream& os = std::cout)
kpeter@293
   482
      : _os(&os), local_os(false), _digraph(digraph),
alpar@209
   483
        _skip_nodes(false), _skip_arcs(false) {}
deba@127
   484
alpar@156
   485
    /// \brief Constructor
alpar@156
   486
    ///
alpar@156
   487
    /// Construct a directed graph writer, which writes to the given
alpar@156
   488
    /// output file.
deba@598
   489
    DigraphWriter(const DGR& digraph, const std::string& fn)
deba@127
   490
      : _os(new std::ofstream(fn.c_str())), local_os(true), _digraph(digraph),
deba@290
   491
        _skip_nodes(false), _skip_arcs(false) {
deba@295
   492
      if (!(*_os)) {
deba@295
   493
        delete _os;
deba@295
   494
        throw IoError("Cannot write file", fn);
deba@295
   495
      }
deba@290
   496
    }
deba@127
   497
alpar@156
   498
    /// \brief Constructor
alpar@156
   499
    ///
alpar@156
   500
    /// Construct a directed graph writer, which writes to the given
alpar@156
   501
    /// output file.
deba@598
   502
    DigraphWriter(const DGR& digraph, const char* fn)
deba@127
   503
      : _os(new std::ofstream(fn)), local_os(true), _digraph(digraph),
deba@290
   504
        _skip_nodes(false), _skip_arcs(false) {
deba@295
   505
      if (!(*_os)) {
deba@295
   506
        delete _os;
deba@295
   507
        throw IoError("Cannot write file", fn);
deba@295
   508
      }
deba@290
   509
    }
deba@127
   510
alpar@156
   511
    /// \brief Destructor
deba@127
   512
    ~DigraphWriter() {
alpar@209
   513
      for (typename NodeMaps::iterator it = _node_maps.begin();
alpar@209
   514
           it != _node_maps.end(); ++it) {
alpar@209
   515
        delete it->second;
deba@127
   516
      }
deba@127
   517
alpar@209
   518
      for (typename ArcMaps::iterator it = _arc_maps.begin();
alpar@209
   519
           it != _arc_maps.end(); ++it) {
alpar@209
   520
        delete it->second;
deba@127
   521
      }
deba@127
   522
alpar@209
   523
      for (typename Attributes::iterator it = _attributes.begin();
alpar@209
   524
           it != _attributes.end(); ++it) {
alpar@209
   525
        delete it->second;
deba@127
   526
      }
deba@127
   527
deba@127
   528
      if (local_os) {
alpar@209
   529
        delete _os;
deba@127
   530
      }
deba@127
   531
    }
deba@127
   532
deba@127
   533
  private:
deba@190
   534
deba@598
   535
    template <typename TDGR>
alpar@877
   536
    friend DigraphWriter<TDGR> digraphWriter(const TDGR& digraph,
deba@598
   537
                                             std::ostream& os);
deba@598
   538
    template <typename TDGR>
deba@598
   539
    friend DigraphWriter<TDGR> digraphWriter(const TDGR& digraph,
deba@598
   540
                                             const std::string& fn);
deba@598
   541
    template <typename TDGR>
deba@598
   542
    friend DigraphWriter<TDGR> digraphWriter(const TDGR& digraph,
deba@598
   543
                                             const char *fn);
deba@190
   544
alpar@209
   545
    DigraphWriter(DigraphWriter& other)
deba@190
   546
      : _os(other._os), local_os(other.local_os), _digraph(other._digraph),
alpar@209
   547
        _skip_nodes(other._skip_nodes), _skip_arcs(other._skip_arcs) {
deba@190
   548
deba@190
   549
      other._os = 0;
deba@190
   550
      other.local_os = false;
deba@190
   551
deba@190
   552
      _node_index.swap(other._node_index);
deba@190
   553
      _arc_index.swap(other._arc_index);
deba@190
   554
deba@190
   555
      _node_maps.swap(other._node_maps);
deba@190
   556
      _arc_maps.swap(other._arc_maps);
deba@190
   557
      _attributes.swap(other._attributes);
deba@190
   558
deba@190
   559
      _nodes_caption = other._nodes_caption;
deba@190
   560
      _arcs_caption = other._arcs_caption;
deba@190
   561
      _attributes_caption = other._attributes_caption;
deba@190
   562
    }
alpar@209
   563
deba@127
   564
    DigraphWriter& operator=(const DigraphWriter&);
deba@127
   565
deba@127
   566
  public:
deba@127
   567
kpeter@584
   568
    /// \name Writing Rules
alpar@156
   569
    /// @{
alpar@209
   570
kpeter@192
   571
    /// \brief Node map writing rule
alpar@156
   572
    ///
kpeter@192
   573
    /// Add a node map writing rule to the writer.
deba@127
   574
    template <typename Map>
deba@127
   575
    DigraphWriter& nodeMap(const std::string& caption, const Map& map) {
deba@127
   576
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
alpar@209
   577
      _writer_bits::MapStorageBase<Node>* storage =
alpar@209
   578
        new _writer_bits::MapStorage<Node, Map>(map);
deba@127
   579
      _node_maps.push_back(std::make_pair(caption, storage));
deba@127
   580
      return *this;
deba@127
   581
    }
deba@127
   582
alpar@156
   583
    /// \brief Node map writing rule
alpar@156
   584
    ///
alpar@156
   585
    /// Add a node map writing rule with specialized converter to the
alpar@156
   586
    /// writer.
deba@127
   587
    template <typename Map, typename Converter>
alpar@209
   588
    DigraphWriter& nodeMap(const std::string& caption, const Map& map,
alpar@209
   589
                           const Converter& converter = Converter()) {
deba@127
   590
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
alpar@209
   591
      _writer_bits::MapStorageBase<Node>* storage =
alpar@209
   592
        new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
deba@127
   593
      _node_maps.push_back(std::make_pair(caption, storage));
deba@127
   594
      return *this;
deba@127
   595
    }
deba@127
   596
alpar@156
   597
    /// \brief Arc map writing rule
alpar@156
   598
    ///
alpar@156
   599
    /// Add an arc map writing rule to the writer.
deba@127
   600
    template <typename Map>
deba@127
   601
    DigraphWriter& arcMap(const std::string& caption, const Map& map) {
deba@127
   602
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
alpar@209
   603
      _writer_bits::MapStorageBase<Arc>* storage =
alpar@209
   604
        new _writer_bits::MapStorage<Arc, Map>(map);
deba@127
   605
      _arc_maps.push_back(std::make_pair(caption, storage));
deba@127
   606
      return *this;
deba@127
   607
    }
deba@127
   608
alpar@156
   609
    /// \brief Arc map writing rule
alpar@156
   610
    ///
alpar@156
   611
    /// Add an arc map writing rule with specialized converter to the
alpar@156
   612
    /// writer.
deba@127
   613
    template <typename Map, typename Converter>
alpar@209
   614
    DigraphWriter& arcMap(const std::string& caption, const Map& map,
alpar@209
   615
                          const Converter& converter = Converter()) {
deba@127
   616
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
alpar@209
   617
      _writer_bits::MapStorageBase<Arc>* storage =
alpar@209
   618
        new _writer_bits::MapStorage<Arc, Map, Converter>(map, converter);
deba@127
   619
      _arc_maps.push_back(std::make_pair(caption, storage));
deba@127
   620
      return *this;
deba@127
   621
    }
deba@127
   622
alpar@156
   623
    /// \brief Attribute writing rule
alpar@156
   624
    ///
alpar@156
   625
    /// Add an attribute writing rule to the writer.
deba@127
   626
    template <typename Value>
deba@127
   627
    DigraphWriter& attribute(const std::string& caption, const Value& value) {
alpar@209
   628
      _writer_bits::ValueStorageBase* storage =
alpar@209
   629
        new _writer_bits::ValueStorage<Value>(value);
deba@127
   630
      _attributes.push_back(std::make_pair(caption, storage));
deba@127
   631
      return *this;
deba@127
   632
    }
deba@127
   633
alpar@156
   634
    /// \brief Attribute writing rule
alpar@156
   635
    ///
alpar@156
   636
    /// Add an attribute writing rule with specialized converter to the
alpar@156
   637
    /// writer.
deba@127
   638
    template <typename Value, typename Converter>
alpar@209
   639
    DigraphWriter& attribute(const std::string& caption, const Value& value,
alpar@209
   640
                             const Converter& converter = Converter()) {
alpar@209
   641
      _writer_bits::ValueStorageBase* storage =
alpar@209
   642
        new _writer_bits::ValueStorage<Value, Converter>(value, converter);
deba@127
   643
      _attributes.push_back(std::make_pair(caption, storage));
deba@127
   644
      return *this;
deba@127
   645
    }
deba@127
   646
alpar@156
   647
    /// \brief Node writing rule
alpar@156
   648
    ///
alpar@156
   649
    /// Add a node writing rule to the writer.
deba@127
   650
    DigraphWriter& node(const std::string& caption, const Node& node) {
deba@127
   651
      typedef _writer_bits::MapLookUpConverter<Node> Converter;
deba@127
   652
      Converter converter(_node_index);
alpar@209
   653
      _writer_bits::ValueStorageBase* storage =
alpar@209
   654
        new _writer_bits::ValueStorage<Node, Converter>(node, converter);
deba@127
   655
      _attributes.push_back(std::make_pair(caption, storage));
deba@127
   656
      return *this;
deba@127
   657
    }
deba@127
   658
alpar@156
   659
    /// \brief Arc writing rule
alpar@156
   660
    ///
alpar@156
   661
    /// Add an arc writing rule to writer.
deba@127
   662
    DigraphWriter& arc(const std::string& caption, const Arc& arc) {
deba@127
   663
      typedef _writer_bits::MapLookUpConverter<Arc> Converter;
deba@127
   664
      Converter converter(_arc_index);
alpar@209
   665
      _writer_bits::ValueStorageBase* storage =
alpar@209
   666
        new _writer_bits::ValueStorage<Arc, Converter>(arc, converter);
deba@127
   667
      _attributes.push_back(std::make_pair(caption, storage));
deba@127
   668
      return *this;
deba@127
   669
    }
deba@127
   670
kpeter@584
   671
    /// \name Section Captions
alpar@156
   672
    /// @{
alpar@156
   673
kpeter@192
   674
    /// \brief Add an additional caption to the \c \@nodes section
alpar@156
   675
    ///
kpeter@192
   676
    /// Add an additional caption to the \c \@nodes section.
deba@127
   677
    DigraphWriter& nodes(const std::string& caption) {
deba@127
   678
      _nodes_caption = caption;
deba@127
   679
      return *this;
deba@127
   680
    }
deba@127
   681
kpeter@192
   682
    /// \brief Add an additional caption to the \c \@arcs section
alpar@156
   683
    ///
kpeter@192
   684
    /// Add an additional caption to the \c \@arcs section.
deba@127
   685
    DigraphWriter& arcs(const std::string& caption) {
deba@127
   686
      _arcs_caption = caption;
deba@127
   687
      return *this;
deba@127
   688
    }
deba@127
   689
kpeter@192
   690
    /// \brief Add an additional caption to the \c \@attributes section
alpar@156
   691
    ///
kpeter@192
   692
    /// Add an additional caption to the \c \@attributes section.
deba@127
   693
    DigraphWriter& attributes(const std::string& caption) {
deba@127
   694
      _attributes_caption = caption;
deba@127
   695
      return *this;
deba@127
   696
    }
deba@127
   697
kpeter@584
   698
    /// \name Skipping Section
alpar@156
   699
    /// @{
alpar@156
   700
alpar@156
   701
    /// \brief Skip writing the node set
alpar@156
   702
    ///
kpeter@192
   703
    /// The \c \@nodes section will not be written to the stream.
deba@127
   704
    DigraphWriter& skipNodes() {
deba@127
   705
      LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member");
deba@185
   706
      _skip_nodes = true;
deba@127
   707
      return *this;
deba@127
   708
    }
deba@127
   709
alpar@156
   710
    /// \brief Skip writing arc set
alpar@156
   711
    ///
kpeter@192
   712
    /// The \c \@arcs section will not be written to the stream.
deba@127
   713
    DigraphWriter& skipArcs() {
deba@127
   714
      LEMON_ASSERT(!_skip_arcs, "Multiple usage of skipArcs() member");
deba@185
   715
      _skip_arcs = true;
deba@127
   716
      return *this;
deba@127
   717
    }
deba@127
   718
alpar@156
   719
    /// @}
alpar@156
   720
deba@127
   721
  private:
deba@127
   722
deba@127
   723
    void writeNodes() {
deba@127
   724
      _writer_bits::MapStorageBase<Node>* label = 0;
deba@127
   725
      for (typename NodeMaps::iterator it = _node_maps.begin();
alpar@209
   726
           it != _node_maps.end(); ++it) {
deba@127
   727
        if (it->first == "label") {
alpar@209
   728
          label = it->second;
alpar@209
   729
          break;
alpar@209
   730
        }
deba@127
   731
      }
deba@127
   732
deba@127
   733
      *_os << "@nodes";
deba@127
   734
      if (!_nodes_caption.empty()) {
alpar@209
   735
        _writer_bits::writeToken(*_os << ' ', _nodes_caption);
deba@127
   736
      }
deba@127
   737
      *_os << std::endl;
deba@127
   738
deba@127
   739
      if (label == 0) {
alpar@209
   740
        *_os << "label" << '\t';
deba@127
   741
      }
deba@127
   742
      for (typename NodeMaps::iterator it = _node_maps.begin();
alpar@209
   743
           it != _node_maps.end(); ++it) {
alpar@209
   744
        _writer_bits::writeToken(*_os, it->first) << '\t';
deba@127
   745
      }
deba@127
   746
      *_os << std::endl;
deba@127
   747
deba@127
   748
      std::vector<Node> nodes;
deba@127
   749
      for (NodeIt n(_digraph); n != INVALID; ++n) {
alpar@209
   750
        nodes.push_back(n);
deba@127
   751
      }
alpar@209
   752
deba@127
   753
      if (label == 0) {
deba@598
   754
        IdMap<DGR, Node> id_map(_digraph);
deba@598
   755
        _writer_bits::MapLess<IdMap<DGR, Node> > id_less(id_map);
alpar@209
   756
        std::sort(nodes.begin(), nodes.end(), id_less);
deba@127
   757
      } else {
alpar@209
   758
        label->sort(nodes);
deba@127
   759
      }
deba@127
   760
deba@127
   761
      for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
alpar@209
   762
        Node n = nodes[i];
alpar@209
   763
        if (label == 0) {
alpar@209
   764
          std::ostringstream os;
alpar@209
   765
          os << _digraph.id(n);
alpar@209
   766
          _writer_bits::writeToken(*_os, os.str());
alpar@209
   767
          *_os << '\t';
alpar@209
   768
          _node_index.insert(std::make_pair(n, os.str()));
alpar@209
   769
        }
alpar@209
   770
        for (typename NodeMaps::iterator it = _node_maps.begin();
alpar@209
   771
             it != _node_maps.end(); ++it) {
alpar@209
   772
          std::string value = it->second->get(n);
alpar@209
   773
          _writer_bits::writeToken(*_os, value);
alpar@209
   774
          if (it->first == "label") {
alpar@209
   775
            _node_index.insert(std::make_pair(n, value));
alpar@209
   776
          }
alpar@209
   777
          *_os << '\t';
alpar@209
   778
        }
alpar@209
   779
        *_os << std::endl;
deba@127
   780
      }
deba@127
   781
    }
deba@127
   782
deba@185
   783
    void createNodeIndex() {
deba@185
   784
      _writer_bits::MapStorageBase<Node>* label = 0;
deba@185
   785
      for (typename NodeMaps::iterator it = _node_maps.begin();
alpar@209
   786
           it != _node_maps.end(); ++it) {
deba@185
   787
        if (it->first == "label") {
alpar@209
   788
          label = it->second;
alpar@209
   789
          break;
alpar@209
   790
        }
deba@185
   791
      }
deba@185
   792
deba@185
   793
      if (label == 0) {
alpar@209
   794
        for (NodeIt n(_digraph); n != INVALID; ++n) {
alpar@209
   795
          std::ostringstream os;
alpar@209
   796
          os << _digraph.id(n);
alpar@209
   797
          _node_index.insert(std::make_pair(n, os.str()));
alpar@209
   798
        }
deba@185
   799
      } else {
alpar@209
   800
        for (NodeIt n(_digraph); n != INVALID; ++n) {
alpar@209
   801
          std::string value = label->get(n);
alpar@209
   802
          _node_index.insert(std::make_pair(n, value));
alpar@209
   803
        }
deba@185
   804
      }
deba@185
   805
    }
deba@185
   806
deba@127
   807
    void writeArcs() {
deba@127
   808
      _writer_bits::MapStorageBase<Arc>* label = 0;
deba@127
   809
      for (typename ArcMaps::iterator it = _arc_maps.begin();
alpar@209
   810
           it != _arc_maps.end(); ++it) {
deba@127
   811
        if (it->first == "label") {
alpar@209
   812
          label = it->second;
alpar@209
   813
          break;
alpar@209
   814
        }
deba@127
   815
      }
deba@127
   816
deba@127
   817
      *_os << "@arcs";
deba@127
   818
      if (!_arcs_caption.empty()) {
alpar@209
   819
        _writer_bits::writeToken(*_os << ' ', _arcs_caption);
deba@127
   820
      }
deba@127
   821
      *_os << std::endl;
deba@127
   822
deba@127
   823
      *_os << '\t' << '\t';
deba@127
   824
      if (label == 0) {
alpar@209
   825
        *_os << "label" << '\t';
deba@127
   826
      }
deba@127
   827
      for (typename ArcMaps::iterator it = _arc_maps.begin();
alpar@209
   828
           it != _arc_maps.end(); ++it) {
alpar@209
   829
        _writer_bits::writeToken(*_os, it->first) << '\t';
deba@127
   830
      }
deba@127
   831
      *_os << std::endl;
deba@127
   832
deba@127
   833
      std::vector<Arc> arcs;
deba@127
   834
      for (ArcIt n(_digraph); n != INVALID; ++n) {
alpar@209
   835
        arcs.push_back(n);
deba@127
   836
      }
alpar@209
   837
deba@127
   838
      if (label == 0) {
deba@598
   839
        IdMap<DGR, Arc> id_map(_digraph);
deba@598
   840
        _writer_bits::MapLess<IdMap<DGR, Arc> > id_less(id_map);
alpar@209
   841
        std::sort(arcs.begin(), arcs.end(), id_less);
deba@127
   842
      } else {
alpar@209
   843
        label->sort(arcs);
deba@127
   844
      }
deba@127
   845
deba@127
   846
      for (int i = 0; i < static_cast<int>(arcs.size()); ++i) {
alpar@209
   847
        Arc a = arcs[i];
alpar@209
   848
        _writer_bits::writeToken(*_os, _node_index.
alpar@209
   849
                                 find(_digraph.source(a))->second);
alpar@209
   850
        *_os << '\t';
alpar@209
   851
        _writer_bits::writeToken(*_os, _node_index.
alpar@209
   852
                                 find(_digraph.target(a))->second);
alpar@209
   853
        *_os << '\t';
alpar@209
   854
        if (label == 0) {
alpar@209
   855
          std::ostringstream os;
alpar@209
   856
          os << _digraph.id(a);
alpar@209
   857
          _writer_bits::writeToken(*_os, os.str());
alpar@209
   858
          *_os << '\t';
alpar@209
   859
          _arc_index.insert(std::make_pair(a, os.str()));
alpar@209
   860
        }
alpar@209
   861
        for (typename ArcMaps::iterator it = _arc_maps.begin();
alpar@209
   862
             it != _arc_maps.end(); ++it) {
alpar@209
   863
          std::string value = it->second->get(a);
alpar@209
   864
          _writer_bits::writeToken(*_os, value);
alpar@209
   865
          if (it->first == "label") {
alpar@209
   866
            _arc_index.insert(std::make_pair(a, value));
alpar@209
   867
          }
alpar@209
   868
          *_os << '\t';
alpar@209
   869
        }
alpar@209
   870
        *_os << std::endl;
deba@127
   871
      }
deba@127
   872
    }
deba@127
   873
deba@185
   874
    void createArcIndex() {
deba@185
   875
      _writer_bits::MapStorageBase<Arc>* label = 0;
deba@185
   876
      for (typename ArcMaps::iterator it = _arc_maps.begin();
alpar@209
   877
           it != _arc_maps.end(); ++it) {
deba@185
   878
        if (it->first == "label") {
alpar@209
   879
          label = it->second;
alpar@209
   880
          break;
alpar@209
   881
        }
deba@185
   882
      }
deba@185
   883
deba@185
   884
      if (label == 0) {
alpar@209
   885
        for (ArcIt a(_digraph); a != INVALID; ++a) {
alpar@209
   886
          std::ostringstream os;
alpar@209
   887
          os << _digraph.id(a);
alpar@209
   888
          _arc_index.insert(std::make_pair(a, os.str()));
alpar@209
   889
        }
deba@185
   890
      } else {
alpar@209
   891
        for (ArcIt a(_digraph); a != INVALID; ++a) {
alpar@209
   892
          std::string value = label->get(a);
alpar@209
   893
          _arc_index.insert(std::make_pair(a, value));
alpar@209
   894
        }
deba@185
   895
      }
deba@185
   896
    }
deba@185
   897
deba@127
   898
    void writeAttributes() {
deba@127
   899
      if (_attributes.empty()) return;
deba@127
   900
      *_os << "@attributes";
deba@127
   901
      if (!_attributes_caption.empty()) {
alpar@209
   902
        _writer_bits::writeToken(*_os << ' ', _attributes_caption);
deba@127
   903
      }
deba@127
   904
      *_os << std::endl;
deba@127
   905
      for (typename Attributes::iterator it = _attributes.begin();
alpar@209
   906
           it != _attributes.end(); ++it) {
alpar@209
   907
        _writer_bits::writeToken(*_os, it->first) << ' ';
alpar@209
   908
        _writer_bits::writeToken(*_os, it->second->get());
alpar@209
   909
        *_os << std::endl;
deba@127
   910
      }
deba@127
   911
    }
alpar@209
   912
deba@127
   913
  public:
alpar@209
   914
kpeter@584
   915
    /// \name Execution of the Writer
alpar@156
   916
    /// @{
alpar@156
   917
alpar@156
   918
    /// \brief Start the batch processing
alpar@156
   919
    ///
kpeter@192
   920
    /// This function starts the batch processing.
deba@127
   921
    void run() {
deba@127
   922
      if (!_skip_nodes) {
alpar@209
   923
        writeNodes();
deba@185
   924
      } else {
alpar@209
   925
        createNodeIndex();
deba@127
   926
      }
alpar@209
   927
      if (!_skip_arcs) {
alpar@209
   928
        writeArcs();
deba@185
   929
      } else {
alpar@209
   930
        createArcIndex();
deba@127
   931
      }
deba@127
   932
      writeAttributes();
deba@127
   933
    }
deba@127
   934
kpeter@192
   935
    /// \brief Give back the stream of the writer
alpar@156
   936
    ///
kpeter@192
   937
    /// Give back the stream of the writer.
alpar@156
   938
    std::ostream& ostream() {
deba@127
   939
      return *_os;
deba@127
   940
    }
alpar@156
   941
alpar@156
   942
    /// @}
deba@127
   943
  };
deba@127
   944
deba@598
   945
  /// \ingroup lemon_io
deba@598
   946
  ///
kpeter@498
   947
  /// \brief Return a \ref DigraphWriter class
kpeter@498
   948
  ///
alpar@877
   949
  /// This function just returns a \ref DigraphWriter class.
deba@598
   950
  ///
deba@598
   951
  /// With this function a digraph can be write to a file or output
deba@598
   952
  /// stream in \ref lgf-format "LGF" format with several maps and
deba@598
   953
  /// attributes. For example, with the following code a network flow
deba@598
   954
  /// problem can be written to the standard output, i.e. a digraph
deba@598
   955
  /// with a \e capacity map on the arcs and \e source and \e target
deba@598
   956
  /// nodes:
deba@598
   957
  ///
deba@598
   958
  ///\code
deba@598
   959
  ///ListDigraph digraph;
deba@598
   960
  ///ListDigraph::ArcMap<int> cap(digraph);
deba@598
   961
  ///ListDigraph::Node src, trg;
deba@598
   962
  ///  // Setting the capacity map and source and target nodes
deba@598
   963
  ///digraphWriter(digraph, std::cout).
deba@598
   964
  ///  arcMap("capacity", cap).
deba@598
   965
  ///  node("source", src).
deba@598
   966
  ///  node("target", trg).
deba@598
   967
  ///  run();
deba@598
   968
  ///\endcode
deba@598
   969
  ///
deba@598
   970
  /// For a complete documentation, please see the \ref DigraphWriter
deba@598
   971
  /// class documentation.
deba@598
   972
  /// \warning Don't forget to put the \ref DigraphWriter::run() "run()"
deba@598
   973
  /// to the end of the parameter list.
kpeter@498
   974
  /// \relates DigraphWriter
deba@598
   975
  /// \sa digraphWriter(const TDGR& digraph, const std::string& fn)
deba@598
   976
  /// \sa digraphWriter(const TDGR& digraph, const char* fn)
deba@598
   977
  template <typename TDGR>
deba@598
   978
  DigraphWriter<TDGR> digraphWriter(const TDGR& digraph, std::ostream& os) {
deba@598
   979
    DigraphWriter<TDGR> tmp(digraph, os);
kpeter@498
   980
    return tmp;
kpeter@498
   981
  }
kpeter@498
   982
kpeter@498
   983
  /// \brief Return a \ref DigraphWriter class
kpeter@498
   984
  ///
kpeter@498
   985
  /// This function just returns a \ref DigraphWriter class.
kpeter@498
   986
  /// \relates DigraphWriter
deba@598
   987
  /// \sa digraphWriter(const TDGR& digraph, std::ostream& os)
deba@598
   988
  template <typename TDGR>
alpar@877
   989
  DigraphWriter<TDGR> digraphWriter(const TDGR& digraph,
deba@598
   990
                                    const std::string& fn) {
deba@598
   991
    DigraphWriter<TDGR> tmp(digraph, fn);
kpeter@498
   992
    return tmp;
kpeter@498
   993
  }
kpeter@498
   994
kpeter@498
   995
  /// \brief Return a \ref DigraphWriter class
kpeter@498
   996
  ///
kpeter@498
   997
  /// This function just returns a \ref DigraphWriter class.
kpeter@498
   998
  /// \relates DigraphWriter
deba@598
   999
  /// \sa digraphWriter(const TDGR& digraph, std::ostream& os)
deba@598
  1000
  template <typename TDGR>
deba@598
  1001
  DigraphWriter<TDGR> digraphWriter(const TDGR& digraph, const char* fn) {
deba@598
  1002
    DigraphWriter<TDGR> tmp(digraph, fn);
kpeter@498
  1003
    return tmp;
kpeter@498
  1004
  }
kpeter@498
  1005
deba@598
  1006
  template <typename GR>
ladanyi@303
  1007
  class GraphWriter;
ladanyi@303
  1008
deba@598
  1009
  template <typename TGR>
deba@598
  1010
  GraphWriter<TGR> graphWriter(const TGR& graph, std::ostream& os = std::cout);
deba@598
  1011
  template <typename TGR>
deba@598
  1012
  GraphWriter<TGR> graphWriter(const TGR& graph, const std::string& fn);
deba@598
  1013
  template <typename TGR>
deba@598
  1014
  GraphWriter<TGR> graphWriter(const TGR& graph, const char* fn);
deba@165
  1015
deba@165
  1016
  /// \ingroup lemon_io
alpar@209
  1017
  ///
deba@1024
  1018
  /// \brief \ref lgf-format "LGF" writer for undirected graphs
deba@165
  1019
  ///
deba@165
  1020
  /// This utility writes an \ref lgf-format "LGF" file.
kpeter@192
  1021
  ///
kpeter@192
  1022
  /// It can be used almost the same way as \c DigraphWriter.
kpeter@192
  1023
  /// The only difference is that this class can handle edges and
kpeter@192
  1024
  /// edge maps as well as arcs and arc maps.
deba@201
  1025
  ///
deba@201
  1026
  /// The arc maps are written into the file as two columns, the
deba@201
  1027
  /// caption of the columns are the name of the map prefixed with \c
deba@201
  1028
  /// '+' and \c '-'. The arcs are written into the \c \@attributes
deba@201
  1029
  /// section as a \c '+' or a \c '-' prefix (depends on the direction
deba@201
  1030
  /// of the arc) and the label of corresponding edge.
kpeter@559
  1031
  template <typename GR>
deba@165
  1032
  class GraphWriter {
deba@165
  1033
  public:
deba@165
  1034
kpeter@559
  1035
    typedef GR Graph;
deba@598
  1036
    TEMPLATE_GRAPH_TYPEDEFS(GR);
alpar@209
  1037
deba@165
  1038
  private:
deba@165
  1039
deba@165
  1040
deba@165
  1041
    std::ostream* _os;
deba@165
  1042
    bool local_os;
deba@165
  1043
deba@598
  1044
    const GR& _graph;
deba@165
  1045
deba@165
  1046
    std::string _nodes_caption;
deba@165
  1047
    std::string _edges_caption;
deba@165
  1048
    std::string _attributes_caption;
alpar@209
  1049
deba@165
  1050
    typedef std::map<Node, std::string> NodeIndex;
deba@165
  1051
    NodeIndex _node_index;
deba@165
  1052
    typedef std::map<Edge, std::string> EdgeIndex;
deba@165
  1053
    EdgeIndex _edge_index;
deba@165
  1054
alpar@209
  1055
    typedef std::vector<std::pair<std::string,
alpar@209
  1056
      _writer_bits::MapStorageBase<Node>* > > NodeMaps;
alpar@209
  1057
    NodeMaps _node_maps;
deba@165
  1058
alpar@209
  1059
    typedef std::vector<std::pair<std::string,
deba@165
  1060
      _writer_bits::MapStorageBase<Edge>* > >EdgeMaps;
deba@165
  1061
    EdgeMaps _edge_maps;
deba@165
  1062
alpar@209
  1063
    typedef std::vector<std::pair<std::string,
deba@165
  1064
      _writer_bits::ValueStorageBase*> > Attributes;
deba@165
  1065
    Attributes _attributes;
deba@165
  1066
deba@165
  1067
    bool _skip_nodes;
deba@165
  1068
    bool _skip_edges;
deba@165
  1069
deba@165
  1070
  public:
deba@165
  1071
deba@165
  1072
    /// \brief Constructor
deba@165
  1073
    ///
deba@1024
  1074
    /// Construct an undirected graph writer, which writes to the
deba@1024
  1075
    /// given output stream.
deba@598
  1076
    GraphWriter(const GR& graph, std::ostream& os = std::cout)
kpeter@293
  1077
      : _os(&os), local_os(false), _graph(graph),
alpar@209
  1078
        _skip_nodes(false), _skip_edges(false) {}
deba@165
  1079
deba@165
  1080
    /// \brief Constructor
deba@165
  1081
    ///
deba@1024
  1082
    /// Construct a undirected graph writer, which writes to the given
deba@165
  1083
    /// output file.
deba@598
  1084
    GraphWriter(const GR& graph, const std::string& fn)
deba@165
  1085
      : _os(new std::ofstream(fn.c_str())), local_os(true), _graph(graph),
deba@290
  1086
        _skip_nodes(false), _skip_edges(false) {
deba@295
  1087
      if (!(*_os)) {
deba@295
  1088
        delete _os;
deba@295
  1089
        throw IoError("Cannot write file", fn);
deba@295
  1090
      }
deba@290
  1091
    }
deba@165
  1092
deba@165
  1093
    /// \brief Constructor
deba@165
  1094
    ///
deba@1024
  1095
    /// Construct a undirected graph writer, which writes to the given
deba@165
  1096
    /// output file.
deba@598
  1097
    GraphWriter(const GR& graph, const char* fn)
deba@165
  1098
      : _os(new std::ofstream(fn)), local_os(true), _graph(graph),
deba@290
  1099
        _skip_nodes(false), _skip_edges(false) {
deba@295
  1100
      if (!(*_os)) {
deba@295
  1101
        delete _os;
deba@295
  1102
        throw IoError("Cannot write file", fn);
deba@295
  1103
      }
deba@290
  1104
    }
deba@165
  1105
deba@165
  1106
    /// \brief Destructor
deba@165
  1107
    ~GraphWriter() {
alpar@209
  1108
      for (typename NodeMaps::iterator it = _node_maps.begin();
alpar@209
  1109
           it != _node_maps.end(); ++it) {
alpar@209
  1110
        delete it->second;
deba@165
  1111
      }
deba@165
  1112
alpar@209
  1113
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
alpar@209
  1114
           it != _edge_maps.end(); ++it) {
alpar@209
  1115
        delete it->second;
deba@165
  1116
      }
deba@165
  1117
alpar@209
  1118
      for (typename Attributes::iterator it = _attributes.begin();
alpar@209
  1119
           it != _attributes.end(); ++it) {
alpar@209
  1120
        delete it->second;
deba@165
  1121
      }
deba@165
  1122
deba@165
  1123
      if (local_os) {
alpar@209
  1124
        delete _os;
deba@165
  1125
      }
deba@165
  1126
    }
alpar@209
  1127
deba@190
  1128
  private:
deba@165
  1129
deba@598
  1130
    template <typename TGR>
deba@598
  1131
    friend GraphWriter<TGR> graphWriter(const TGR& graph, std::ostream& os);
deba@598
  1132
    template <typename TGR>
alpar@877
  1133
    friend GraphWriter<TGR> graphWriter(const TGR& graph,
deba@598
  1134
                                        const std::string& fn);
deba@598
  1135
    template <typename TGR>
deba@598
  1136
    friend GraphWriter<TGR> graphWriter(const TGR& graph, const char *fn);
alpar@877
  1137
alpar@209
  1138
    GraphWriter(GraphWriter& other)
deba@190
  1139
      : _os(other._os), local_os(other.local_os), _graph(other._graph),
alpar@209
  1140
        _skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
deba@190
  1141
deba@190
  1142
      other._os = 0;
deba@190
  1143
      other.local_os = false;
deba@190
  1144
deba@190
  1145
      _node_index.swap(other._node_index);
deba@190
  1146
      _edge_index.swap(other._edge_index);
deba@190
  1147
deba@190
  1148
      _node_maps.swap(other._node_maps);
deba@190
  1149
      _edge_maps.swap(other._edge_maps);
deba@190
  1150
      _attributes.swap(other._attributes);
deba@190
  1151
deba@190
  1152
      _nodes_caption = other._nodes_caption;
deba@190
  1153
      _edges_caption = other._edges_caption;
deba@190
  1154
      _attributes_caption = other._attributes_caption;
deba@190
  1155
    }
deba@190
  1156
deba@165
  1157
    GraphWriter& operator=(const GraphWriter&);
deba@165
  1158
deba@165
  1159
  public:
deba@165
  1160
kpeter@584
  1161
    /// \name Writing Rules
deba@165
  1162
    /// @{
alpar@209
  1163
kpeter@192
  1164
    /// \brief Node map writing rule
deba@165
  1165
    ///
kpeter@192
  1166
    /// Add a node map writing rule to the writer.
deba@165
  1167
    template <typename Map>
deba@165
  1168
    GraphWriter& nodeMap(const std::string& caption, const Map& map) {
deba@165
  1169
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
alpar@209
  1170
      _writer_bits::MapStorageBase<Node>* storage =
alpar@209
  1171
        new _writer_bits::MapStorage<Node, Map>(map);
deba@165
  1172
      _node_maps.push_back(std::make_pair(caption, storage));
deba@165
  1173
      return *this;
deba@165
  1174
    }
deba@165
  1175
deba@165
  1176
    /// \brief Node map writing rule
deba@165
  1177
    ///
deba@165
  1178
    /// Add a node map writing rule with specialized converter to the
deba@165
  1179
    /// writer.
deba@165
  1180
    template <typename Map, typename Converter>
alpar@209
  1181
    GraphWriter& nodeMap(const std::string& caption, const Map& map,
alpar@209
  1182
                           const Converter& converter = Converter()) {
deba@165
  1183
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
alpar@209
  1184
      _writer_bits::MapStorageBase<Node>* storage =
alpar@209
  1185
        new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
deba@165
  1186
      _node_maps.push_back(std::make_pair(caption, storage));
deba@165
  1187
      return *this;
deba@165
  1188
    }
deba@165
  1189
deba@165
  1190
    /// \brief Edge map writing rule
deba@165
  1191
    ///
deba@165
  1192
    /// Add an edge map writing rule to the writer.
deba@165
  1193
    template <typename Map>
deba@165
  1194
    GraphWriter& edgeMap(const std::string& caption, const Map& map) {
deba@165
  1195
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
alpar@209
  1196
      _writer_bits::MapStorageBase<Edge>* storage =
alpar@209
  1197
        new _writer_bits::MapStorage<Edge, Map>(map);
deba@165
  1198
      _edge_maps.push_back(std::make_pair(caption, storage));
deba@165
  1199
      return *this;
deba@165
  1200
    }
deba@165
  1201
deba@165
  1202
    /// \brief Edge map writing rule
deba@165
  1203
    ///
deba@165
  1204
    /// Add an edge map writing rule with specialized converter to the
deba@165
  1205
    /// writer.
deba@165
  1206
    template <typename Map, typename Converter>
alpar@209
  1207
    GraphWriter& edgeMap(const std::string& caption, const Map& map,
alpar@209
  1208
                          const Converter& converter = Converter()) {
deba@165
  1209
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
alpar@209
  1210
      _writer_bits::MapStorageBase<Edge>* storage =
alpar@209
  1211
        new _writer_bits::MapStorage<Edge, Map, Converter>(map, converter);
deba@165
  1212
      _edge_maps.push_back(std::make_pair(caption, storage));
deba@165
  1213
      return *this;
deba@165
  1214
    }
deba@165
  1215
deba@165
  1216
    /// \brief Arc map writing rule
deba@165
  1217
    ///
deba@165
  1218
    /// Add an arc map writing rule to the writer.
deba@165
  1219
    template <typename Map>
deba@165
  1220
    GraphWriter& arcMap(const std::string& caption, const Map& map) {
deba@165
  1221
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
alpar@209
  1222
      _writer_bits::MapStorageBase<Edge>* forward_storage =
deba@598
  1223
        new _writer_bits::GraphArcMapStorage<GR, true, Map>(_graph, map);
deba@165
  1224
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
alpar@209
  1225
      _writer_bits::MapStorageBase<Edge>* backward_storage =
deba@598
  1226
        new _writer_bits::GraphArcMapStorage<GR, false, Map>(_graph, map);
deba@165
  1227
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
deba@165
  1228
      return *this;
deba@165
  1229
    }
deba@165
  1230
deba@165
  1231
    /// \brief Arc map writing rule
deba@165
  1232
    ///
deba@165
  1233
    /// Add an arc map writing rule with specialized converter to the
deba@165
  1234
    /// writer.
deba@165
  1235
    template <typename Map, typename Converter>
alpar@209
  1236
    GraphWriter& arcMap(const std::string& caption, const Map& map,
alpar@209
  1237
                          const Converter& converter = Converter()) {
deba@165
  1238
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
alpar@209
  1239
      _writer_bits::MapStorageBase<Edge>* forward_storage =
deba@598
  1240
        new _writer_bits::GraphArcMapStorage<GR, true, Map, Converter>
alpar@209
  1241
        (_graph, map, converter);
deba@165
  1242
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
alpar@209
  1243
      _writer_bits::MapStorageBase<Edge>* backward_storage =
deba@598
  1244
        new _writer_bits::GraphArcMapStorage<GR, false, Map, Converter>
alpar@209
  1245
        (_graph, map, converter);
deba@165
  1246
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
deba@165
  1247
      return *this;
deba@165
  1248
    }
deba@165
  1249
deba@165
  1250
    /// \brief Attribute writing rule
deba@165
  1251
    ///
deba@165
  1252
    /// Add an attribute writing rule to the writer.
deba@165
  1253
    template <typename Value>
deba@165
  1254
    GraphWriter& attribute(const std::string& caption, const Value& value) {
alpar@209
  1255
      _writer_bits::ValueStorageBase* storage =
alpar@209
  1256
        new _writer_bits::ValueStorage<Value>(value);
deba@165
  1257
      _attributes.push_back(std::make_pair(caption, storage));
deba@165
  1258
      return *this;
deba@165
  1259
    }
deba@165
  1260
deba@165
  1261
    /// \brief Attribute writing rule
deba@165
  1262
    ///
deba@165
  1263
    /// Add an attribute writing rule with specialized converter to the
deba@165
  1264
    /// writer.
deba@165
  1265
    template <typename Value, typename Converter>
alpar@209
  1266
    GraphWriter& attribute(const std::string& caption, const Value& value,
alpar@209
  1267
                             const Converter& converter = Converter()) {
alpar@209
  1268
      _writer_bits::ValueStorageBase* storage =
alpar@209
  1269
        new _writer_bits::ValueStorage<Value, Converter>(value, converter);
deba@165
  1270
      _attributes.push_back(std::make_pair(caption, storage));
deba@165
  1271
      return *this;
deba@165
  1272
    }
deba@165
  1273
deba@165
  1274
    /// \brief Node writing rule
deba@165
  1275
    ///
deba@165
  1276
    /// Add a node writing rule to the writer.
deba@165
  1277
    GraphWriter& node(const std::string& caption, const Node& node) {
deba@165
  1278
      typedef _writer_bits::MapLookUpConverter<Node> Converter;
deba@165
  1279
      Converter converter(_node_index);
alpar@209
  1280
      _writer_bits::ValueStorageBase* storage =
alpar@209
  1281
        new _writer_bits::ValueStorage<Node, Converter>(node, converter);
deba@165
  1282
      _attributes.push_back(std::make_pair(caption, storage));
deba@165
  1283
      return *this;
deba@165
  1284
    }
deba@165
  1285
deba@165
  1286
    /// \brief Edge writing rule
deba@165
  1287
    ///
deba@165
  1288
    /// Add an edge writing rule to writer.
deba@165
  1289
    GraphWriter& edge(const std::string& caption, const Edge& edge) {
deba@165
  1290
      typedef _writer_bits::MapLookUpConverter<Edge> Converter;
deba@165
  1291
      Converter converter(_edge_index);
alpar@209
  1292
      _writer_bits::ValueStorageBase* storage =
alpar@209
  1293
        new _writer_bits::ValueStorage<Edge, Converter>(edge, converter);
deba@165
  1294
      _attributes.push_back(std::make_pair(caption, storage));
deba@165
  1295
      return *this;
deba@165
  1296
    }
deba@165
  1297
deba@165
  1298
    /// \brief Arc writing rule
deba@165
  1299
    ///
deba@165
  1300
    /// Add an arc writing rule to writer.
deba@165
  1301
    GraphWriter& arc(const std::string& caption, const Arc& arc) {
deba@598
  1302
      typedef _writer_bits::GraphArcLookUpConverter<GR> Converter;
deba@165
  1303
      Converter converter(_graph, _edge_index);
alpar@209
  1304
      _writer_bits::ValueStorageBase* storage =
alpar@209
  1305
        new _writer_bits::ValueStorage<Arc, Converter>(arc, converter);
deba@165
  1306
      _attributes.push_back(std::make_pair(caption, storage));
deba@165
  1307
      return *this;
deba@165
  1308
    }
deba@165
  1309
kpeter@584
  1310
    /// \name Section Captions
deba@165
  1311
    /// @{
deba@165
  1312
kpeter@192
  1313
    /// \brief Add an additional caption to the \c \@nodes section
deba@165
  1314
    ///
kpeter@192
  1315
    /// Add an additional caption to the \c \@nodes section.
deba@165
  1316
    GraphWriter& nodes(const std::string& caption) {
deba@165
  1317
      _nodes_caption = caption;
deba@165
  1318
      return *this;
deba@165
  1319
    }
deba@165
  1320
deba@1024
  1321
    /// \brief Add an additional caption to the \c \@edges section
deba@165
  1322
    ///
deba@1024
  1323
    /// Add an additional caption to the \c \@edges section.
deba@165
  1324
    GraphWriter& edges(const std::string& caption) {
deba@165
  1325
      _edges_caption = caption;
deba@165
  1326
      return *this;
deba@165
  1327
    }
deba@165
  1328
kpeter@192
  1329
    /// \brief Add an additional caption to the \c \@attributes section
deba@165
  1330
    ///
kpeter@192
  1331
    /// Add an additional caption to the \c \@attributes section.
deba@165
  1332
    GraphWriter& attributes(const std::string& caption) {
deba@165
  1333
      _attributes_caption = caption;
deba@165
  1334
      return *this;
deba@165
  1335
    }
deba@165
  1336
kpeter@584
  1337
    /// \name Skipping Section
deba@165
  1338
    /// @{
deba@165
  1339
deba@165
  1340
    /// \brief Skip writing the node set
deba@165
  1341
    ///
kpeter@192
  1342
    /// The \c \@nodes section will not be written to the stream.
deba@165
  1343
    GraphWriter& skipNodes() {
deba@165
  1344
      LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member");
deba@185
  1345
      _skip_nodes = true;
deba@165
  1346
      return *this;
deba@165
  1347
    }
deba@165
  1348
deba@165
  1349
    /// \brief Skip writing edge set
deba@165
  1350
    ///
kpeter@192
  1351
    /// The \c \@edges section will not be written to the stream.
deba@165
  1352
    GraphWriter& skipEdges() {
deba@165
  1353
      LEMON_ASSERT(!_skip_edges, "Multiple usage of skipEdges() member");
deba@185
  1354
      _skip_edges = true;
deba@165
  1355
      return *this;
deba@165
  1356
    }
deba@165
  1357
deba@165
  1358
    /// @}
deba@165
  1359
deba@165
  1360
  private:
deba@165
  1361
deba@165
  1362
    void writeNodes() {
deba@165
  1363
      _writer_bits::MapStorageBase<Node>* label = 0;
deba@165
  1364
      for (typename NodeMaps::iterator it = _node_maps.begin();
alpar@209
  1365
           it != _node_maps.end(); ++it) {
deba@165
  1366
        if (it->first == "label") {
alpar@209
  1367
          label = it->second;
alpar@209
  1368
          break;
alpar@209
  1369
        }
deba@165
  1370
      }
deba@165
  1371
deba@165
  1372
      *_os << "@nodes";
deba@165
  1373
      if (!_nodes_caption.empty()) {
alpar@209
  1374
        _writer_bits::writeToken(*_os << ' ', _nodes_caption);
deba@165
  1375
      }
deba@165
  1376
      *_os << std::endl;
deba@165
  1377
deba@165
  1378
      if (label == 0) {
alpar@209
  1379
        *_os << "label" << '\t';
deba@165
  1380
      }
deba@165
  1381
      for (typename NodeMaps::iterator it = _node_maps.begin();
alpar@209
  1382
           it != _node_maps.end(); ++it) {
alpar@209
  1383
        _writer_bits::writeToken(*_os, it->first) << '\t';
deba@165
  1384
      }
deba@165
  1385
      *_os << std::endl;
deba@165
  1386
deba@165
  1387
      std::vector<Node> nodes;
deba@165
  1388
      for (NodeIt n(_graph); n != INVALID; ++n) {
alpar@209
  1389
        nodes.push_back(n);
deba@165
  1390
      }
alpar@209
  1391
deba@165
  1392
      if (label == 0) {
deba@598
  1393
        IdMap<GR, Node> id_map(_graph);
deba@598
  1394
        _writer_bits::MapLess<IdMap<GR, Node> > id_less(id_map);
alpar@209
  1395
        std::sort(nodes.begin(), nodes.end(), id_less);
deba@165
  1396
      } else {
alpar@209
  1397
        label->sort(nodes);
deba@165
  1398
      }
deba@165
  1399
deba@165
  1400
      for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
alpar@209
  1401
        Node n = nodes[i];
alpar@209
  1402
        if (label == 0) {
alpar@209
  1403
          std::ostringstream os;
alpar@209
  1404
          os << _graph.id(n);
alpar@209
  1405
          _writer_bits::writeToken(*_os, os.str());
alpar@209
  1406
          *_os << '\t';
alpar@209
  1407
          _node_index.insert(std::make_pair(n, os.str()));
alpar@209
  1408
        }
alpar@209
  1409
        for (typename NodeMaps::iterator it = _node_maps.begin();
alpar@209
  1410
             it != _node_maps.end(); ++it) {
alpar@209
  1411
          std::string value = it->second->get(n);
alpar@209
  1412
          _writer_bits::writeToken(*_os, value);
alpar@209
  1413
          if (it->first == "label") {
alpar@209
  1414
            _node_index.insert(std::make_pair(n, value));
alpar@209
  1415
          }
alpar@209
  1416
          *_os << '\t';
alpar@209
  1417
        }
alpar@209
  1418
        *_os << std::endl;
deba@165
  1419
      }
deba@165
  1420
    }
deba@165
  1421
deba@185
  1422
    void createNodeIndex() {
deba@185
  1423
      _writer_bits::MapStorageBase<Node>* label = 0;
deba@185
  1424
      for (typename NodeMaps::iterator it = _node_maps.begin();
alpar@209
  1425
           it != _node_maps.end(); ++it) {
deba@185
  1426
        if (it->first == "label") {
alpar@209
  1427
          label = it->second;
alpar@209
  1428
          break;
alpar@209
  1429
        }
deba@185
  1430
      }
deba@185
  1431
deba@185
  1432
      if (label == 0) {
alpar@209
  1433
        for (NodeIt n(_graph); n != INVALID; ++n) {
alpar@209
  1434
          std::ostringstream os;
alpar@209
  1435
          os << _graph.id(n);
alpar@209
  1436
          _node_index.insert(std::make_pair(n, os.str()));
alpar@209
  1437
        }
deba@185
  1438
      } else {
alpar@209
  1439
        for (NodeIt n(_graph); n != INVALID; ++n) {
alpar@209
  1440
          std::string value = label->get(n);
alpar@209
  1441
          _node_index.insert(std::make_pair(n, value));
alpar@209
  1442
        }
deba@185
  1443
      }
deba@185
  1444
    }
deba@185
  1445
deba@165
  1446
    void writeEdges() {
deba@165
  1447
      _writer_bits::MapStorageBase<Edge>* label = 0;
deba@165
  1448
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
alpar@209
  1449
           it != _edge_maps.end(); ++it) {
deba@165
  1450
        if (it->first == "label") {
alpar@209
  1451
          label = it->second;
alpar@209
  1452
          break;
alpar@209
  1453
        }
deba@165
  1454
      }
deba@165
  1455
deba@165
  1456
      *_os << "@edges";
deba@165
  1457
      if (!_edges_caption.empty()) {
alpar@209
  1458
        _writer_bits::writeToken(*_os << ' ', _edges_caption);
deba@165
  1459
      }
deba@165
  1460
      *_os << std::endl;
deba@165
  1461
deba@165
  1462
      *_os << '\t' << '\t';
deba@165
  1463
      if (label == 0) {
alpar@209
  1464
        *_os << "label" << '\t';
deba@165
  1465
      }
deba@165
  1466
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
alpar@209
  1467
           it != _edge_maps.end(); ++it) {
alpar@209
  1468
        _writer_bits::writeToken(*_os, it->first) << '\t';
deba@165
  1469
      }
deba@165
  1470
      *_os << std::endl;
deba@165
  1471
deba@165
  1472
      std::vector<Edge> edges;
deba@165
  1473
      for (EdgeIt n(_graph); n != INVALID; ++n) {
alpar@209
  1474
        edges.push_back(n);
deba@165
  1475
      }
alpar@209
  1476
deba@165
  1477
      if (label == 0) {
deba@598
  1478
        IdMap<GR, Edge> id_map(_graph);
deba@598
  1479
        _writer_bits::MapLess<IdMap<GR, Edge> > id_less(id_map);
alpar@209
  1480
        std::sort(edges.begin(), edges.end(), id_less);
deba@165
  1481
      } else {
alpar@209
  1482
        label->sort(edges);
deba@165
  1483
      }
deba@165
  1484
deba@165
  1485
      for (int i = 0; i < static_cast<int>(edges.size()); ++i) {
alpar@209
  1486
        Edge e = edges[i];
alpar@209
  1487
        _writer_bits::writeToken(*_os, _node_index.
alpar@209
  1488
                                 find(_graph.u(e))->second);
alpar@209
  1489
        *_os << '\t';
alpar@209
  1490
        _writer_bits::writeToken(*_os, _node_index.
alpar@209
  1491
                                 find(_graph.v(e))->second);
alpar@209
  1492
        *_os << '\t';
alpar@209
  1493
        if (label == 0) {
alpar@209
  1494
          std::ostringstream os;
alpar@209
  1495
          os << _graph.id(e);
alpar@209
  1496
          _writer_bits::writeToken(*_os, os.str());
alpar@209
  1497
          *_os << '\t';
alpar@209
  1498
          _edge_index.insert(std::make_pair(e, os.str()));
alpar@209
  1499
        }
alpar@209
  1500
        for (typename EdgeMaps::iterator it = _edge_maps.begin();
alpar@209
  1501
             it != _edge_maps.end(); ++it) {
alpar@209
  1502
          std::string value = it->second->get(e);
alpar@209
  1503
          _writer_bits::writeToken(*_os, value);
alpar@209
  1504
          if (it->first == "label") {
alpar@209
  1505
            _edge_index.insert(std::make_pair(e, value));
alpar@209
  1506
          }
alpar@209
  1507
          *_os << '\t';
alpar@209
  1508
        }
alpar@209
  1509
        *_os << std::endl;
deba@165
  1510
      }
deba@165
  1511
    }
deba@165
  1512
deba@185
  1513
    void createEdgeIndex() {
deba@185
  1514
      _writer_bits::MapStorageBase<Edge>* label = 0;
deba@185
  1515
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
alpar@209
  1516
           it != _edge_maps.end(); ++it) {
deba@185
  1517
        if (it->first == "label") {
alpar@209
  1518
          label = it->second;
alpar@209
  1519
          break;
alpar@209
  1520
        }
deba@185
  1521
      }
deba@185
  1522
deba@185
  1523
      if (label == 0) {
alpar@209
  1524
        for (EdgeIt e(_graph); e != INVALID; ++e) {
alpar@209
  1525
          std::ostringstream os;
alpar@209
  1526
          os << _graph.id(e);
alpar@209
  1527
          _edge_index.insert(std::make_pair(e, os.str()));
alpar@209
  1528
        }
deba@185
  1529
      } else {
alpar@209
  1530
        for (EdgeIt e(_graph); e != INVALID; ++e) {
alpar@209
  1531
          std::string value = label->get(e);
alpar@209
  1532
          _edge_index.insert(std::make_pair(e, value));
alpar@209
  1533
        }
deba@185
  1534
      }
deba@185
  1535
    }
deba@185
  1536
deba@165
  1537
    void writeAttributes() {
deba@165
  1538
      if (_attributes.empty()) return;
deba@165
  1539
      *_os << "@attributes";
deba@165
  1540
      if (!_attributes_caption.empty()) {
alpar@209
  1541
        _writer_bits::writeToken(*_os << ' ', _attributes_caption);
deba@165
  1542
      }
deba@165
  1543
      *_os << std::endl;
deba@165
  1544
      for (typename Attributes::iterator it = _attributes.begin();
alpar@209
  1545
           it != _attributes.end(); ++it) {
alpar@209
  1546
        _writer_bits::writeToken(*_os, it->first) << ' ';
alpar@209
  1547
        _writer_bits::writeToken(*_os, it->second->get());
alpar@209
  1548
        *_os << std::endl;
deba@165
  1549
      }
deba@165
  1550
    }
alpar@209
  1551
deba@165
  1552
  public:
alpar@209
  1553
kpeter@584
  1554
    /// \name Execution of the Writer
deba@165
  1555
    /// @{
deba@165
  1556
deba@165
  1557
    /// \brief Start the batch processing
deba@165
  1558
    ///
kpeter@192
  1559
    /// This function starts the batch processing.
deba@165
  1560
    void run() {
deba@165
  1561
      if (!_skip_nodes) {
alpar@209
  1562
        writeNodes();
deba@185
  1563
      } else {
alpar@209
  1564
        createNodeIndex();
deba@165
  1565
      }
alpar@209
  1566
      if (!_skip_edges) {
alpar@209
  1567
        writeEdges();
deba@185
  1568
      } else {
alpar@209
  1569
        createEdgeIndex();
deba@165
  1570
      }
deba@165
  1571
      writeAttributes();
deba@165
  1572
    }
deba@165
  1573
kpeter@192
  1574
    /// \brief Give back the stream of the writer
deba@165
  1575
    ///
kpeter@192
  1576
    /// Give back the stream of the writer
deba@165
  1577
    std::ostream& ostream() {
deba@165
  1578
      return *_os;
deba@165
  1579
    }
deba@165
  1580
deba@165
  1581
    /// @}
deba@165
  1582
  };
deba@165
  1583
deba@598
  1584
  /// \ingroup lemon_io
deba@598
  1585
  ///
kpeter@498
  1586
  /// \brief Return a \ref GraphWriter class
kpeter@498
  1587
  ///
alpar@877
  1588
  /// This function just returns a \ref GraphWriter class.
deba@598
  1589
  ///
deba@598
  1590
  /// With this function a graph can be write to a file or output
deba@598
  1591
  /// stream in \ref lgf-format "LGF" format with several maps and
deba@598
  1592
  /// attributes. For example, with the following code a weighted
deba@598
  1593
  /// matching problem can be written to the standard output, i.e. a
deba@598
  1594
  /// graph with a \e weight map on the edges:
deba@598
  1595
  ///
deba@598
  1596
  ///\code
deba@598
  1597
  ///ListGraph graph;
deba@598
  1598
  ///ListGraph::EdgeMap<int> weight(graph);
deba@598
  1599
  ///  // Setting the weight map
deba@598
  1600
  ///graphWriter(graph, std::cout).
deba@598
  1601
  ///  edgeMap("weight", weight).
deba@598
  1602
  ///  run();
deba@598
  1603
  ///\endcode
deba@598
  1604
  ///
deba@598
  1605
  /// For a complete documentation, please see the \ref GraphWriter
deba@598
  1606
  /// class documentation.
deba@598
  1607
  /// \warning Don't forget to put the \ref GraphWriter::run() "run()"
deba@598
  1608
  /// to the end of the parameter list.
kpeter@498
  1609
  /// \relates GraphWriter
deba@598
  1610
  /// \sa graphWriter(const TGR& graph, const std::string& fn)
deba@598
  1611
  /// \sa graphWriter(const TGR& graph, const char* fn)
deba@598
  1612
  template <typename TGR>
deba@598
  1613
  GraphWriter<TGR> graphWriter(const TGR& graph, std::ostream& os) {
deba@598
  1614
    GraphWriter<TGR> tmp(graph, os);
kpeter@498
  1615
    return tmp;
kpeter@498
  1616
  }
kpeter@498
  1617
kpeter@498
  1618
  /// \brief Return a \ref GraphWriter class
kpeter@498
  1619
  ///
kpeter@498
  1620
  /// This function just returns a \ref GraphWriter class.
kpeter@498
  1621
  /// \relates GraphWriter
deba@598
  1622
  /// \sa graphWriter(const TGR& graph, std::ostream& os)
deba@598
  1623
  template <typename TGR>
deba@598
  1624
  GraphWriter<TGR> graphWriter(const TGR& graph, const std::string& fn) {
deba@598
  1625
    GraphWriter<TGR> tmp(graph, fn);
kpeter@498
  1626
    return tmp;
kpeter@498
  1627
  }
kpeter@498
  1628
kpeter@498
  1629
  /// \brief Return a \ref GraphWriter class
kpeter@498
  1630
  ///
kpeter@498
  1631
  /// This function just returns a \ref GraphWriter class.
kpeter@498
  1632
  /// \relates GraphWriter
deba@598
  1633
  /// \sa graphWriter(const TGR& graph, std::ostream& os)
deba@598
  1634
  template <typename TGR>
deba@598
  1635
  GraphWriter<TGR> graphWriter(const TGR& graph, const char* fn) {
deba@598
  1636
    GraphWriter<TGR> tmp(graph, fn);
kpeter@498
  1637
    return tmp;
kpeter@498
  1638
  }
kpeter@498
  1639
deba@1024
  1640
  template <typename BGR>
deba@1024
  1641
  class BpGraphWriter;
deba@1024
  1642
deba@1024
  1643
  template <typename TBGR>
deba@1024
  1644
  BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph,
deba@1024
  1645
                                    std::ostream& os = std::cout);
deba@1024
  1646
  template <typename TBGR>
deba@1024
  1647
  BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph, const std::string& fn);
deba@1024
  1648
  template <typename TBGR>
deba@1024
  1649
  BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph, const char* fn);
deba@1024
  1650
deba@1024
  1651
  /// \ingroup lemon_io
deba@1024
  1652
  ///
deba@1024
  1653
  /// \brief \ref lgf-format "LGF" writer for undirected bipartite graphs
deba@1024
  1654
  ///
deba@1024
  1655
  /// This utility writes an \ref lgf-format "LGF" file.
deba@1024
  1656
  ///
deba@1024
  1657
  /// It can be used almost the same way as \c GraphWriter, but it
deba@1024
  1658
  /// reads the red and blue nodes from separate sections, and these
deba@1024
  1659
  /// sections can contain different set of maps.
deba@1024
  1660
  ///
deba@1026
  1661
  /// The red and blue node maps are written to the corresponding
deba@1024
  1662
  /// sections. The node maps are written to both of these sections
deba@1024
  1663
  /// with the same map name.
deba@1024
  1664
  template <typename BGR>
deba@1024
  1665
  class BpGraphWriter {
deba@1024
  1666
  public:
deba@1024
  1667
deba@1024
  1668
    typedef BGR BpGraph;
deba@1024
  1669
    TEMPLATE_BPGRAPH_TYPEDEFS(BGR);
deba@1024
  1670
deba@1024
  1671
  private:
deba@1024
  1672
deba@1024
  1673
deba@1024
  1674
    std::ostream* _os;
deba@1024
  1675
    bool local_os;
deba@1024
  1676
deba@1024
  1677
    const BGR& _graph;
deba@1024
  1678
deba@1024
  1679
    std::string _nodes_caption;
deba@1024
  1680
    std::string _edges_caption;
deba@1024
  1681
    std::string _attributes_caption;
deba@1024
  1682
deba@1030
  1683
    typedef std::map<Node, std::string> RedNodeIndex;
deba@1030
  1684
    RedNodeIndex _red_node_index;
deba@1030
  1685
    typedef std::map<Node, std::string> BlueNodeIndex;
deba@1030
  1686
    BlueNodeIndex _blue_node_index;
deba@1024
  1687
    typedef std::map<Edge, std::string> EdgeIndex;
deba@1024
  1688
    EdgeIndex _edge_index;
deba@1024
  1689
deba@1024
  1690
    typedef std::vector<std::pair<std::string,
deba@1030
  1691
      _writer_bits::MapStorageBase<RedNode>* > > RedNodeMaps;
deba@1030
  1692
    RedNodeMaps _red_node_maps;
deba@1030
  1693
    typedef std::vector<std::pair<std::string,
deba@1030
  1694
      _writer_bits::MapStorageBase<BlueNode>* > > BlueNodeMaps;
deba@1030
  1695
    BlueNodeMaps _blue_node_maps;
deba@1024
  1696
deba@1024
  1697
    typedef std::vector<std::pair<std::string,
deba@1024
  1698
      _writer_bits::MapStorageBase<Edge>* > >EdgeMaps;
deba@1024
  1699
    EdgeMaps _edge_maps;
deba@1024
  1700
deba@1024
  1701
    typedef std::vector<std::pair<std::string,
deba@1024
  1702
      _writer_bits::ValueStorageBase*> > Attributes;
deba@1024
  1703
    Attributes _attributes;
deba@1024
  1704
deba@1024
  1705
    bool _skip_nodes;
deba@1024
  1706
    bool _skip_edges;
deba@1024
  1707
deba@1024
  1708
  public:
deba@1024
  1709
deba@1024
  1710
    /// \brief Constructor
deba@1024
  1711
    ///
deba@1024
  1712
    /// Construct a bipartite graph writer, which writes to the given
deba@1024
  1713
    /// output stream.
deba@1024
  1714
    BpGraphWriter(const BGR& graph, std::ostream& os = std::cout)
deba@1024
  1715
      : _os(&os), local_os(false), _graph(graph),
deba@1024
  1716
        _skip_nodes(false), _skip_edges(false) {}
deba@1024
  1717
deba@1024
  1718
    /// \brief Constructor
deba@1024
  1719
    ///
deba@1024
  1720
    /// Construct a bipartite graph writer, which writes to the given
deba@1024
  1721
    /// output file.
deba@1024
  1722
    BpGraphWriter(const BGR& graph, const std::string& fn)
deba@1024
  1723
      : _os(new std::ofstream(fn.c_str())), local_os(true), _graph(graph),
deba@1024
  1724
        _skip_nodes(false), _skip_edges(false) {
deba@1024
  1725
      if (!(*_os)) {
deba@1024
  1726
        delete _os;
deba@1024
  1727
        throw IoError("Cannot write file", fn);
deba@1024
  1728
      }
deba@1024
  1729
    }
deba@1024
  1730
deba@1024
  1731
    /// \brief Constructor
deba@1024
  1732
    ///
deba@1024
  1733
    /// Construct a bipartite graph writer, which writes to the given
deba@1024
  1734
    /// output file.
deba@1024
  1735
    BpGraphWriter(const BGR& graph, const char* fn)
deba@1024
  1736
      : _os(new std::ofstream(fn)), local_os(true), _graph(graph),
deba@1024
  1737
        _skip_nodes(false), _skip_edges(false) {
deba@1024
  1738
      if (!(*_os)) {
deba@1024
  1739
        delete _os;
deba@1024
  1740
        throw IoError("Cannot write file", fn);
deba@1024
  1741
      }
deba@1024
  1742
    }
deba@1024
  1743
deba@1024
  1744
    /// \brief Destructor
deba@1024
  1745
    ~BpGraphWriter() {
deba@1030
  1746
      for (typename RedNodeMaps::iterator it = _red_node_maps.begin();
deba@1030
  1747
           it != _red_node_maps.end(); ++it) {
deba@1024
  1748
        delete it->second;
deba@1024
  1749
      }
deba@1024
  1750
deba@1030
  1751
      for (typename BlueNodeMaps::iterator it = _blue_node_maps.begin();
deba@1030
  1752
           it != _blue_node_maps.end(); ++it) {
deba@1024
  1753
        delete it->second;
deba@1024
  1754
      }
deba@1024
  1755
deba@1024
  1756
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
deba@1024
  1757
           it != _edge_maps.end(); ++it) {
deba@1024
  1758
        delete it->second;
deba@1024
  1759
      }
deba@1024
  1760
deba@1024
  1761
      for (typename Attributes::iterator it = _attributes.begin();
deba@1024
  1762
           it != _attributes.end(); ++it) {
deba@1024
  1763
        delete it->second;
deba@1024
  1764
      }
deba@1024
  1765
deba@1024
  1766
      if (local_os) {
deba@1024
  1767
        delete _os;
deba@1024
  1768
      }
deba@1024
  1769
    }
deba@1024
  1770
deba@1024
  1771
  private:
deba@1024
  1772
deba@1024
  1773
    template <typename TBGR>
deba@1024
  1774
    friend BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph,
deba@1024
  1775
                                             std::ostream& os);
deba@1024
  1776
    template <typename TBGR>
deba@1024
  1777
    friend BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph,
deba@1024
  1778
                                             const std::string& fn);
deba@1024
  1779
    template <typename TBGR>
deba@1024
  1780
    friend BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph, const char *fn);
deba@1024
  1781
deba@1024
  1782
    BpGraphWriter(BpGraphWriter& other)
deba@1024
  1783
      : _os(other._os), local_os(other.local_os), _graph(other._graph),
deba@1024
  1784
        _skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
deba@1024
  1785
deba@1024
  1786
      other._os = 0;
deba@1024
  1787
      other.local_os = false;
deba@1024
  1788
deba@1030
  1789
      _red_node_index.swap(other._red_node_index);
deba@1030
  1790
      _blue_node_index.swap(other._blue_node_index);
deba@1024
  1791
      _edge_index.swap(other._edge_index);
deba@1024
  1792
deba@1030
  1793
      _red_node_maps.swap(other._red_node_maps);
deba@1030
  1794
      _blue_node_maps.swap(other._blue_node_maps);
deba@1024
  1795
      _edge_maps.swap(other._edge_maps);
deba@1024
  1796
      _attributes.swap(other._attributes);
deba@1024
  1797
deba@1024
  1798
      _nodes_caption = other._nodes_caption;
deba@1024
  1799
      _edges_caption = other._edges_caption;
deba@1024
  1800
      _attributes_caption = other._attributes_caption;
deba@1024
  1801
    }
deba@1024
  1802
deba@1024
  1803
    BpGraphWriter& operator=(const BpGraphWriter&);
deba@1024
  1804
deba@1024
  1805
  public:
deba@1024
  1806
deba@1024
  1807
    /// \name Writing Rules
deba@1024
  1808
    /// @{
deba@1024
  1809
deba@1024
  1810
    /// \brief Node map writing rule
deba@1024
  1811
    ///
deba@1024
  1812
    /// Add a node map writing rule to the writer.
deba@1024
  1813
    template <typename Map>
deba@1024
  1814
    BpGraphWriter& nodeMap(const std::string& caption, const Map& map) {
deba@1024
  1815
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
deba@1030
  1816
      _writer_bits::MapStorageBase<RedNode>* red_storage =
deba@1030
  1817
        new _writer_bits::MapStorage<RedNode, Map>(map);
deba@1030
  1818
      _red_node_maps.push_back(std::make_pair(caption, red_storage));
deba@1030
  1819
      _writer_bits::MapStorageBase<BlueNode>* blue_storage =
deba@1030
  1820
        new _writer_bits::MapStorage<BlueNode, Map>(map);
deba@1030
  1821
      _blue_node_maps.push_back(std::make_pair(caption, blue_storage));
deba@1024
  1822
      return *this;
deba@1024
  1823
    }
deba@1024
  1824
deba@1024
  1825
    /// \brief Node map writing rule
deba@1024
  1826
    ///
deba@1024
  1827
    /// Add a node map writing rule with specialized converter to the
deba@1024
  1828
    /// writer.
deba@1024
  1829
    template <typename Map, typename Converter>
deba@1024
  1830
    BpGraphWriter& nodeMap(const std::string& caption, const Map& map,
deba@1024
  1831
                           const Converter& converter = Converter()) {
deba@1024
  1832
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
deba@1030
  1833
      _writer_bits::MapStorageBase<RedNode>* red_storage =
deba@1030
  1834
        new _writer_bits::MapStorage<RedNode, Map, Converter>(map, converter);
deba@1030
  1835
      _red_node_maps.push_back(std::make_pair(caption, red_storage));
deba@1030
  1836
      _writer_bits::MapStorageBase<BlueNode>* blue_storage =
deba@1030
  1837
        new _writer_bits::MapStorage<BlueNode, Map, Converter>(map, converter);
deba@1030
  1838
      _blue_node_maps.push_back(std::make_pair(caption, blue_storage));
deba@1024
  1839
      return *this;
deba@1024
  1840
    }
deba@1024
  1841
deba@1026
  1842
    /// \brief Red node map writing rule
deba@1024
  1843
    ///
deba@1026
  1844
    /// Add a red node map writing rule to the writer.
deba@1024
  1845
    template <typename Map>
deba@1026
  1846
    BpGraphWriter& redNodeMap(const std::string& caption, const Map& map) {
deba@1030
  1847
      checkConcept<concepts::ReadMap<RedNode, typename Map::Value>, Map>();
deba@1030
  1848
      _writer_bits::MapStorageBase<RedNode>* storage =
deba@1030
  1849
        new _writer_bits::MapStorage<RedNode, Map>(map);
deba@1030
  1850
      _red_node_maps.push_back(std::make_pair(caption, storage));
deba@1024
  1851
      return *this;
deba@1024
  1852
    }
deba@1024
  1853
deba@1026
  1854
    /// \brief Red node map writing rule
deba@1024
  1855
    ///
deba@1026
  1856
    /// Add a red node map writing rule with specialized converter to the
deba@1024
  1857
    /// writer.
deba@1024
  1858
    template <typename Map, typename Converter>
deba@1026
  1859
    BpGraphWriter& redNodeMap(const std::string& caption, const Map& map,
deba@1026
  1860
                              const Converter& converter = Converter()) {
deba@1030
  1861
      checkConcept<concepts::ReadMap<RedNode, typename Map::Value>, Map>();
deba@1030
  1862
      _writer_bits::MapStorageBase<RedNode>* storage =
deba@1030
  1863
        new _writer_bits::MapStorage<RedNode, Map, Converter>(map, converter);
deba@1030
  1864
      _red_node_maps.push_back(std::make_pair(caption, storage));
deba@1024
  1865
      return *this;
deba@1024
  1866
    }
deba@1024
  1867
deba@1026
  1868
    /// \brief Blue node map writing rule
deba@1024
  1869
    ///
deba@1026
  1870
    /// Add a blue node map writing rule to the writer.
deba@1024
  1871
    template <typename Map>
deba@1026
  1872
    BpGraphWriter& blueNodeMap(const std::string& caption, const Map& map) {
deba@1030
  1873
      checkConcept<concepts::ReadMap<BlueNode, typename Map::Value>, Map>();
deba@1030
  1874
      _writer_bits::MapStorageBase<BlueNode>* storage =
deba@1030
  1875
        new _writer_bits::MapStorage<BlueNode, Map>(map);
deba@1030
  1876
      _blue_node_maps.push_back(std::make_pair(caption, storage));
deba@1024
  1877
      return *this;
deba@1024
  1878
    }
deba@1024
  1879
deba@1026
  1880
    /// \brief Blue node map writing rule
deba@1024
  1881
    ///
deba@1026
  1882
    /// Add a blue node map writing rule with specialized converter to the
deba@1024
  1883
    /// writer.
deba@1024
  1884
    template <typename Map, typename Converter>
deba@1026
  1885
    BpGraphWriter& blueNodeMap(const std::string& caption, const Map& map,
deba@1026
  1886
                               const Converter& converter = Converter()) {
deba@1030
  1887
      checkConcept<concepts::ReadMap<BlueNode, typename Map::Value>, Map>();
deba@1030
  1888
      _writer_bits::MapStorageBase<BlueNode>* storage =
deba@1030
  1889
        new _writer_bits::MapStorage<BlueNode, Map, Converter>(map, converter);
deba@1030
  1890
      _blue_node_maps.push_back(std::make_pair(caption, storage));
deba@1024
  1891
      return *this;
deba@1024
  1892
    }
deba@1024
  1893
deba@1024
  1894
    /// \brief Edge map writing rule
deba@1024
  1895
    ///
deba@1024
  1896
    /// Add an edge map writing rule to the writer.
deba@1024
  1897
    template <typename Map>
deba@1024
  1898
    BpGraphWriter& edgeMap(const std::string& caption, const Map& map) {
deba@1024
  1899
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
deba@1024
  1900
      _writer_bits::MapStorageBase<Edge>* storage =
deba@1024
  1901
        new _writer_bits::MapStorage<Edge, Map>(map);
deba@1024
  1902
      _edge_maps.push_back(std::make_pair(caption, storage));
deba@1024
  1903
      return *this;
deba@1024
  1904
    }
deba@1024
  1905
deba@1024
  1906
    /// \brief Edge map writing rule
deba@1024
  1907
    ///
deba@1024
  1908
    /// Add an edge map writing rule with specialized converter to the
deba@1024
  1909
    /// writer.
deba@1024
  1910
    template <typename Map, typename Converter>
deba@1024
  1911
    BpGraphWriter& edgeMap(const std::string& caption, const Map& map,
deba@1024
  1912
                          const Converter& converter = Converter()) {
deba@1024
  1913
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
deba@1024
  1914
      _writer_bits::MapStorageBase<Edge>* storage =
deba@1024
  1915
        new _writer_bits::MapStorage<Edge, Map, Converter>(map, converter);
deba@1024
  1916
      _edge_maps.push_back(std::make_pair(caption, storage));
deba@1024
  1917
      return *this;
deba@1024
  1918
    }
deba@1024
  1919
deba@1024
  1920
    /// \brief Arc map writing rule
deba@1024
  1921
    ///
deba@1024
  1922
    /// Add an arc map writing rule to the writer.
deba@1024
  1923
    template <typename Map>
deba@1024
  1924
    BpGraphWriter& arcMap(const std::string& caption, const Map& map) {
deba@1024
  1925
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
deba@1024
  1926
      _writer_bits::MapStorageBase<Edge>* forward_storage =
deba@1024
  1927
        new _writer_bits::GraphArcMapStorage<BGR, true, Map>(_graph, map);
deba@1024
  1928
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
deba@1024
  1929
      _writer_bits::MapStorageBase<Edge>* backward_storage =
deba@1024
  1930
        new _writer_bits::GraphArcMapStorage<BGR, false, Map>(_graph, map);
deba@1024
  1931
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
deba@1024
  1932
      return *this;
deba@1024
  1933
    }
deba@1024
  1934
deba@1024
  1935
    /// \brief Arc map writing rule
deba@1024
  1936
    ///
deba@1024
  1937
    /// Add an arc map writing rule with specialized converter to the
deba@1024
  1938
    /// writer.
deba@1024
  1939
    template <typename Map, typename Converter>
deba@1024
  1940
    BpGraphWriter& arcMap(const std::string& caption, const Map& map,
deba@1024
  1941
                          const Converter& converter = Converter()) {
deba@1024
  1942
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
deba@1024
  1943
      _writer_bits::MapStorageBase<Edge>* forward_storage =
deba@1024
  1944
        new _writer_bits::GraphArcMapStorage<BGR, true, Map, Converter>
deba@1024
  1945
        (_graph, map, converter);
deba@1024
  1946
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
deba@1024
  1947
      _writer_bits::MapStorageBase<Edge>* backward_storage =
deba@1024
  1948
        new _writer_bits::GraphArcMapStorage<BGR, false, Map, Converter>
deba@1024
  1949
        (_graph, map, converter);
deba@1024
  1950
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
deba@1024
  1951
      return *this;
deba@1024
  1952
    }
deba@1024
  1953
deba@1024
  1954
    /// \brief Attribute writing rule
deba@1024
  1955
    ///
deba@1024
  1956
    /// Add an attribute writing rule to the writer.
deba@1024
  1957
    template <typename Value>
deba@1024
  1958
    BpGraphWriter& attribute(const std::string& caption, const Value& value) {
deba@1024
  1959
      _writer_bits::ValueStorageBase* storage =
deba@1024
  1960
        new _writer_bits::ValueStorage<Value>(value);
deba@1024
  1961
      _attributes.push_back(std::make_pair(caption, storage));
deba@1024
  1962
      return *this;
deba@1024
  1963
    }
deba@1024
  1964
deba@1024
  1965
    /// \brief Attribute writing rule
deba@1024
  1966
    ///
deba@1024
  1967
    /// Add an attribute writing rule with specialized converter to the
deba@1024
  1968
    /// writer.
deba@1024
  1969
    template <typename Value, typename Converter>
deba@1024
  1970
    BpGraphWriter& attribute(const std::string& caption, const Value& value,
deba@1024
  1971
                             const Converter& converter = Converter()) {
deba@1024
  1972
      _writer_bits::ValueStorageBase* storage =
deba@1024
  1973
        new _writer_bits::ValueStorage<Value, Converter>(value, converter);
deba@1024
  1974
      _attributes.push_back(std::make_pair(caption, storage));
deba@1024
  1975
      return *this;
deba@1024
  1976
    }
deba@1024
  1977
deba@1024
  1978
    /// \brief Node writing rule
deba@1024
  1979
    ///
deba@1024
  1980
    /// Add a node writing rule to the writer.
deba@1024
  1981
    BpGraphWriter& node(const std::string& caption, const Node& node) {
deba@1030
  1982
      typedef _writer_bits::DoubleMapLookUpConverter<
deba@1030
  1983
        Node, RedNodeIndex, BlueNodeIndex> Converter;
deba@1030
  1984
      Converter converter(_red_node_index, _blue_node_index);
deba@1030
  1985
      _writer_bits::ValueStorageBase* storage =
deba@1030
  1986
        new _writer_bits::ValueStorage<Node, Converter>(node, converter);
deba@1030
  1987
      _attributes.push_back(std::make_pair(caption, storage));
deba@1030
  1988
      return *this;
deba@1030
  1989
    }
deba@1030
  1990
deba@1030
  1991
    /// \brief Red node writing rule
deba@1030
  1992
    ///
deba@1030
  1993
    /// Add a red node writing rule to the writer.
deba@1030
  1994
    BpGraphWriter& redNode(const std::string& caption, const RedNode& node) {
deba@1024
  1995
      typedef _writer_bits::MapLookUpConverter<Node> Converter;
deba@1030
  1996
      Converter converter(_red_node_index);
deba@1030
  1997
      _writer_bits::ValueStorageBase* storage =
deba@1030
  1998
        new _writer_bits::ValueStorage<Node, Converter>(node, converter);
deba@1030
  1999
      _attributes.push_back(std::make_pair(caption, storage));
deba@1030
  2000
      return *this;
deba@1030
  2001
    }
deba@1030
  2002
deba@1030
  2003
    /// \brief Blue node writing rule
deba@1030
  2004
    ///
deba@1030
  2005
    /// Add a blue node writing rule to the writer.
deba@1030
  2006
    BpGraphWriter& blueNode(const std::string& caption, const BlueNode& node) {
deba@1030
  2007
      typedef _writer_bits::MapLookUpConverter<Node> Converter;
deba@1030
  2008
      Converter converter(_blue_node_index);
deba@1024
  2009
      _writer_bits::ValueStorageBase* storage =
deba@1024
  2010
        new _writer_bits::ValueStorage<Node, Converter>(node, converter);
deba@1024
  2011
      _attributes.push_back(std::make_pair(caption, storage));
deba@1024
  2012
      return *this;
deba@1024
  2013
    }
deba@1024
  2014
deba@1024
  2015
    /// \brief Edge writing rule
deba@1024
  2016
    ///
deba@1024
  2017
    /// Add an edge writing rule to writer.
deba@1024
  2018
    BpGraphWriter& edge(const std::string& caption, const Edge& edge) {
deba@1024
  2019
      typedef _writer_bits::MapLookUpConverter<Edge> Converter;
deba@1024
  2020
      Converter converter(_edge_index);
deba@1024
  2021
      _writer_bits::ValueStorageBase* storage =
deba@1024
  2022
        new _writer_bits::ValueStorage<Edge, Converter>(edge, converter);
deba@1024
  2023
      _attributes.push_back(std::make_pair(caption, storage));
deba@1024
  2024
      return *this;
deba@1024
  2025
    }
deba@1024
  2026
deba@1024
  2027
    /// \brief Arc writing rule
deba@1024
  2028
    ///
deba@1024
  2029
    /// Add an arc writing rule to writer.
deba@1024
  2030
    BpGraphWriter& arc(const std::string& caption, const Arc& arc) {
deba@1024
  2031
      typedef _writer_bits::GraphArcLookUpConverter<BGR> Converter;
deba@1024
  2032
      Converter converter(_graph, _edge_index);
deba@1024
  2033
      _writer_bits::ValueStorageBase* storage =
deba@1024
  2034
        new _writer_bits::ValueStorage<Arc, Converter>(arc, converter);
deba@1024
  2035
      _attributes.push_back(std::make_pair(caption, storage));
deba@1024
  2036
      return *this;
deba@1024
  2037
    }
deba@1024
  2038
deba@1024
  2039
    /// \name Section Captions
deba@1024
  2040
    /// @{
deba@1024
  2041
deba@1024
  2042
    /// \brief Add an additional caption to the \c \@red_nodes and
deba@1024
  2043
    /// \c \@blue_nodes section
deba@1024
  2044
    ///
deba@1024
  2045
    /// Add an additional caption to the \c \@red_nodes and \c
deba@1024
  2046
    /// \@blue_nodes section.
deba@1024
  2047
    BpGraphWriter& nodes(const std::string& caption) {
deba@1024
  2048
      _nodes_caption = caption;
deba@1024
  2049
      return *this;
deba@1024
  2050
    }
deba@1024
  2051
deba@1024
  2052
    /// \brief Add an additional caption to the \c \@edges section
deba@1024
  2053
    ///
deba@1024
  2054
    /// Add an additional caption to the \c \@edges section.
deba@1024
  2055
    BpGraphWriter& edges(const std::string& caption) {
deba@1024
  2056
      _edges_caption = caption;
deba@1024
  2057
      return *this;
deba@1024
  2058
    }
deba@1024
  2059
deba@1024
  2060
    /// \brief Add an additional caption to the \c \@attributes section
deba@1024
  2061
    ///
deba@1024
  2062
    /// Add an additional caption to the \c \@attributes section.
deba@1024
  2063
    BpGraphWriter& attributes(const std::string& caption) {
deba@1024
  2064
      _attributes_caption = caption;
deba@1024
  2065
      return *this;
deba@1024
  2066
    }
deba@1024
  2067
deba@1024
  2068
    /// \name Skipping Section
deba@1024
  2069
    /// @{
deba@1024
  2070
deba@1024
  2071
    /// \brief Skip writing the node set
deba@1024
  2072
    ///
deba@1024
  2073
    /// The \c \@red_nodes and \c \@blue_nodes section will not be
deba@1024
  2074
    /// written to the stream.
deba@1024
  2075
    BpGraphWriter& skipNodes() {
deba@1024
  2076
      LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member");
deba@1024
  2077
      _skip_nodes = true;
deba@1024
  2078
      return *this;
deba@1024
  2079
    }
deba@1024
  2080
deba@1024
  2081
    /// \brief Skip writing edge set
deba@1024
  2082
    ///
deba@1024
  2083
    /// The \c \@edges section will not be written to the stream.
deba@1024
  2084
    BpGraphWriter& skipEdges() {
deba@1024
  2085
      LEMON_ASSERT(!_skip_edges, "Multiple usage of skipEdges() member");
deba@1024
  2086
      _skip_edges = true;
deba@1024
  2087
      return *this;
deba@1024
  2088
    }
deba@1024
  2089
deba@1024
  2090
    /// @}
deba@1024
  2091
deba@1024
  2092
  private:
deba@1024
  2093
deba@1024
  2094
    void writeRedNodes() {
deba@1030
  2095
      _writer_bits::MapStorageBase<RedNode>* label = 0;
deba@1030
  2096
      for (typename RedNodeMaps::iterator it = _red_node_maps.begin();
deba@1030
  2097
           it != _red_node_maps.end(); ++it) {
deba@1024
  2098
        if (it->first == "label") {
deba@1024
  2099
          label = it->second;
deba@1024
  2100
          break;
deba@1024
  2101
        }
deba@1024
  2102
      }
deba@1024
  2103
deba@1024
  2104
      *_os << "@red_nodes";
deba@1024
  2105
      if (!_nodes_caption.empty()) {
deba@1024
  2106
        _writer_bits::writeToken(*_os << ' ', _nodes_caption);
deba@1024
  2107
      }
deba@1024
  2108
      *_os << std::endl;
deba@1024
  2109
deba@1024
  2110
      if (label == 0) {
deba@1024
  2111
        *_os << "label" << '\t';
deba@1024
  2112
      }
deba@1030
  2113
      for (typename RedNodeMaps::iterator it = _red_node_maps.begin();
deba@1030
  2114
           it != _red_node_maps.end(); ++it) {
deba@1024
  2115
        _writer_bits::writeToken(*_os, it->first) << '\t';
deba@1024
  2116
      }
deba@1024
  2117
      *_os << std::endl;
deba@1024
  2118
deba@1030
  2119
      std::vector<RedNode> nodes;
deba@1026
  2120
      for (RedNodeIt n(_graph); n != INVALID; ++n) {
deba@1024
  2121
        nodes.push_back(n);
deba@1024
  2122
      }
deba@1024
  2123
deba@1024
  2124
      if (label == 0) {
deba@1024
  2125
        IdMap<BGR, Node> id_map(_graph);
deba@1024
  2126
        _writer_bits::MapLess<IdMap<BGR, Node> > id_less(id_map);
deba@1024
  2127
        std::sort(nodes.begin(), nodes.end(), id_less);
deba@1024
  2128
      } else {
deba@1024
  2129
        label->sort(nodes);
deba@1024
  2130
      }
deba@1024
  2131
deba@1024
  2132
      for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
deba@1030
  2133
        RedNode n = nodes[i];
deba@1024
  2134
        if (label == 0) {
deba@1024
  2135
          std::ostringstream os;
deba@1030
  2136
          os << _graph.id(static_cast<Node>(n));
deba@1024
  2137
          _writer_bits::writeToken(*_os, os.str());
deba@1024
  2138
          *_os << '\t';
deba@1030
  2139
          _red_node_index.insert(std::make_pair(n, os.str()));
deba@1024
  2140
        }
deba@1030
  2141
        for (typename RedNodeMaps::iterator it = _red_node_maps.begin();
deba@1030
  2142
             it != _red_node_maps.end(); ++it) {
deba@1024
  2143
          std::string value = it->second->get(n);
deba@1024
  2144
          _writer_bits::writeToken(*_os, value);
deba@1024
  2145
          if (it->first == "label") {
deba@1030
  2146
            _red_node_index.insert(std::make_pair(n, value));
deba@1024
  2147
          }
deba@1024
  2148
          *_os << '\t';
deba@1024
  2149
        }
deba@1024
  2150
        *_os << std::endl;
deba@1024
  2151
      }
deba@1024
  2152
    }
deba@1024
  2153
deba@1024
  2154
    void writeBlueNodes() {
deba@1030
  2155
      _writer_bits::MapStorageBase<BlueNode>* label = 0;
deba@1030
  2156
      for (typename BlueNodeMaps::iterator it = _blue_node_maps.begin();
deba@1030
  2157
           it != _blue_node_maps.end(); ++it) {
deba@1024
  2158
        if (it->first == "label") {
deba@1024
  2159
          label = it->second;
deba@1024
  2160
          break;
deba@1024
  2161
        }
deba@1024
  2162
      }
deba@1024
  2163
deba@1024
  2164
      *_os << "@blue_nodes";
deba@1024
  2165
      if (!_nodes_caption.empty()) {
deba@1024
  2166
        _writer_bits::writeToken(*_os << ' ', _nodes_caption);
deba@1024
  2167
      }
deba@1024
  2168
      *_os << std::endl;
deba@1024
  2169
deba@1024
  2170
      if (label == 0) {
deba@1024
  2171
        *_os << "label" << '\t';
deba@1024
  2172
      }
deba@1030
  2173
      for (typename BlueNodeMaps::iterator it = _blue_node_maps.begin();
deba@1030
  2174
           it != _blue_node_maps.end(); ++it) {
deba@1024
  2175
        _writer_bits::writeToken(*_os, it->first) << '\t';
deba@1024
  2176
      }
deba@1024
  2177
      *_os << std::endl;
deba@1024
  2178
deba@1030
  2179
      std::vector<BlueNode> nodes;
deba@1026
  2180
      for (BlueNodeIt n(_graph); n != INVALID; ++n) {
deba@1024
  2181
        nodes.push_back(n);
deba@1024
  2182
      }
deba@1024
  2183
deba@1024
  2184
      if (label == 0) {
deba@1024
  2185
        IdMap<BGR, Node> id_map(_graph);
deba@1024
  2186
        _writer_bits::MapLess<IdMap<BGR, Node> > id_less(id_map);
deba@1024
  2187
        std::sort(nodes.begin(), nodes.end(), id_less);
deba@1024
  2188
      } else {
deba@1024
  2189
        label->sort(nodes);
deba@1024
  2190
      }
deba@1024
  2191
deba@1024
  2192
      for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
deba@1030
  2193
        BlueNode n = nodes[i];
deba@1024
  2194
        if (label == 0) {
deba@1024
  2195
          std::ostringstream os;
deba@1030
  2196
          os << _graph.id(static_cast<Node>(n));
deba@1024
  2197
          _writer_bits::writeToken(*_os, os.str());
deba@1024
  2198
          *_os << '\t';
deba@1030
  2199
          _blue_node_index.insert(std::make_pair(n, os.str()));
deba@1024
  2200
        }
deba@1030
  2201
        for (typename BlueNodeMaps::iterator it = _blue_node_maps.begin();
deba@1030
  2202
             it != _blue_node_maps.end(); ++it) {
deba@1024
  2203
          std::string value = it->second->get(n);
deba@1024
  2204
          _writer_bits::writeToken(*_os, value);
deba@1024
  2205
          if (it->first == "label") {
deba@1030
  2206
            _blue_node_index.insert(std::make_pair(n, value));
deba@1024
  2207
          }
deba@1024
  2208
          *_os << '\t';
deba@1024
  2209
        }
deba@1024
  2210
        *_os << std::endl;
deba@1024
  2211
      }
deba@1024
  2212
    }
deba@1024
  2213
deba@1024
  2214
    void createRedNodeIndex() {
deba@1030
  2215
      _writer_bits::MapStorageBase<RedNode>* label = 0;
deba@1030
  2216
      for (typename RedNodeMaps::iterator it = _red_node_maps.begin();
deba@1030
  2217
           it != _red_node_maps.end(); ++it) {
deba@1024
  2218
        if (it->first == "label") {
deba@1024
  2219
          label = it->second;
deba@1024
  2220
          break;
deba@1024
  2221
        }
deba@1024
  2222
      }
deba@1024
  2223
deba@1024
  2224
      if (label == 0) {
deba@1030
  2225
        for (RedNodeIt n(_graph); n != INVALID; ++n) {
deba@1024
  2226
          std::ostringstream os;
deba@1024
  2227
          os << _graph.id(n);
deba@1030
  2228
          _red_node_index.insert(std::make_pair(n, os.str()));
deba@1024
  2229
        }
deba@1024
  2230
      } else {
deba@1030
  2231
        for (RedNodeIt n(_graph); n != INVALID; ++n) {
deba@1024
  2232
          std::string value = label->get(n);
deba@1030
  2233
          _red_node_index.insert(std::make_pair(n, value));
deba@1024
  2234
        }
deba@1024
  2235
      }
deba@1024
  2236
    }
deba@1024
  2237
deba@1024
  2238
    void createBlueNodeIndex() {
deba@1030
  2239
      _writer_bits::MapStorageBase<BlueNode>* label = 0;
deba@1030
  2240
      for (typename BlueNodeMaps::iterator it = _blue_node_maps.begin();
deba@1030
  2241
           it != _blue_node_maps.end(); ++it) {
deba@1024
  2242
        if (it->first == "label") {
deba@1024
  2243
          label = it->second;
deba@1024
  2244
          break;
deba@1024
  2245
        }
deba@1024
  2246
      }
deba@1024
  2247
deba@1024
  2248
      if (label == 0) {
deba@1030
  2249
        for (BlueNodeIt n(_graph); n != INVALID; ++n) {
deba@1024
  2250
          std::ostringstream os;
deba@1024
  2251
          os << _graph.id(n);
deba@1030
  2252
          _blue_node_index.insert(std::make_pair(n, os.str()));
deba@1024
  2253
        }
deba@1024
  2254
      } else {
deba@1030
  2255
        for (BlueNodeIt n(_graph); n != INVALID; ++n) {
deba@1024
  2256
          std::string value = label->get(n);
deba@1030
  2257
          _blue_node_index.insert(std::make_pair(n, value));
deba@1024
  2258
        }
deba@1024
  2259
      }
deba@1024
  2260
    }
deba@1024
  2261
deba@1024
  2262
    void writeEdges() {
deba@1024
  2263
      _writer_bits::MapStorageBase<Edge>* label = 0;
deba@1024
  2264
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
deba@1024
  2265
           it != _edge_maps.end(); ++it) {
deba@1024
  2266
        if (it->first == "label") {
deba@1024
  2267
          label = it->second;
deba@1024
  2268
          break;
deba@1024
  2269
        }
deba@1024
  2270
      }
deba@1024
  2271
deba@1024
  2272
      *_os << "@edges";
deba@1024
  2273
      if (!_edges_caption.empty()) {
deba@1024
  2274
        _writer_bits::writeToken(*_os << ' ', _edges_caption);
deba@1024
  2275
      }
deba@1024
  2276
      *_os << std::endl;
deba@1024
  2277
deba@1024
  2278
      *_os << '\t' << '\t';
deba@1024
  2279
      if (label == 0) {
deba@1024
  2280
        *_os << "label" << '\t';
deba@1024
  2281
      }
deba@1024
  2282
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
deba@1024
  2283
           it != _edge_maps.end(); ++it) {
deba@1024
  2284
        _writer_bits::writeToken(*_os, it->first) << '\t';
deba@1024
  2285
      }
deba@1024
  2286
      *_os << std::endl;
deba@1024
  2287
deba@1024
  2288
      std::vector<Edge> edges;
deba@1024
  2289
      for (EdgeIt n(_graph); n != INVALID; ++n) {
deba@1024
  2290
        edges.push_back(n);
deba@1024
  2291
      }
deba@1024
  2292
deba@1024
  2293
      if (label == 0) {
deba@1024
  2294
        IdMap<BGR, Edge> id_map(_graph);
deba@1024
  2295
        _writer_bits::MapLess<IdMap<BGR, Edge> > id_less(id_map);
deba@1024
  2296
        std::sort(edges.begin(), edges.end(), id_less);
deba@1024
  2297
      } else {
deba@1024
  2298
        label->sort(edges);
deba@1024
  2299
      }
deba@1024
  2300
deba@1024
  2301
      for (int i = 0; i < static_cast<int>(edges.size()); ++i) {
deba@1024
  2302
        Edge e = edges[i];
deba@1030
  2303
        _writer_bits::writeToken(*_os, _red_node_index.
deba@1024
  2304
                                 find(_graph.redNode(e))->second);
deba@1024
  2305
        *_os << '\t';
deba@1030
  2306
        _writer_bits::writeToken(*_os, _blue_node_index.
deba@1024
  2307
                                 find(_graph.blueNode(e))->second);
deba@1024
  2308
        *_os << '\t';
deba@1024
  2309
        if (label == 0) {
deba@1024
  2310
          std::ostringstream os;
deba@1024
  2311
          os << _graph.id(e);
deba@1024
  2312
          _writer_bits::writeToken(*_os, os.str());
deba@1024
  2313
          *_os << '\t';
deba@1024
  2314
          _edge_index.insert(std::make_pair(e, os.str()));
deba@1024
  2315
        }
deba@1024
  2316
        for (typename EdgeMaps::iterator it = _edge_maps.begin();
deba@1024
  2317
             it != _edge_maps.end(); ++it) {
deba@1024
  2318
          std::string value = it->second->get(e);
deba@1024
  2319
          _writer_bits::writeToken(*_os, value);
deba@1024
  2320
          if (it->first == "label") {
deba@1024
  2321
            _edge_index.insert(std::make_pair(e, value));
deba@1024
  2322
          }
deba@1024
  2323
          *_os << '\t';
deba@1024
  2324
        }
deba@1024
  2325
        *_os << std::endl;
deba@1024
  2326
      }
deba@1024
  2327
    }
deba@1024
  2328
deba@1024
  2329
    void createEdgeIndex() {
deba@1024
  2330
      _writer_bits::MapStorageBase<Edge>* label = 0;
deba@1024
  2331
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
deba@1024
  2332
           it != _edge_maps.end(); ++it) {
deba@1024
  2333
        if (it->first == "label") {
deba@1024
  2334
          label = it->second;
deba@1024
  2335
          break;
deba@1024
  2336
        }
deba@1024
  2337
      }
deba@1024
  2338
deba@1024
  2339
      if (label == 0) {
deba@1024
  2340
        for (EdgeIt e(_graph); e != INVALID; ++e) {
deba@1024
  2341
          std::ostringstream os;
deba@1024
  2342
          os << _graph.id(e);
deba@1024
  2343
          _edge_index.insert(std::make_pair(e, os.str()));
deba@1024
  2344
        }
deba@1024
  2345
      } else {
deba@1024
  2346
        for (EdgeIt e(_graph); e != INVALID; ++e) {
deba@1024
  2347
          std::string value = label->get(e);
deba@1024
  2348
          _edge_index.insert(std::make_pair(e, value));
deba@1024
  2349
        }
deba@1024
  2350
      }
deba@1024
  2351
    }
deba@1024
  2352
deba@1024
  2353
    void writeAttributes() {
deba@1024
  2354
      if (_attributes.empty()) return;
deba@1024
  2355
      *_os << "@attributes";
deba@1024
  2356
      if (!_attributes_caption.empty()) {
deba@1024
  2357
        _writer_bits::writeToken(*_os << ' ', _attributes_caption);
deba@1024
  2358
      }
deba@1024
  2359
      *_os << std::endl;
deba@1024
  2360
      for (typename Attributes::iterator it = _attributes.begin();
deba@1024
  2361
           it != _attributes.end(); ++it) {
deba@1024
  2362
        _writer_bits::writeToken(*_os, it->first) << ' ';
deba@1024
  2363
        _writer_bits::writeToken(*_os, it->second->get());
deba@1024
  2364
        *_os << std::endl;
deba@1024
  2365
      }
deba@1024
  2366
    }
deba@1024
  2367
deba@1024
  2368
  public:
deba@1024
  2369
deba@1024
  2370
    /// \name Execution of the Writer
deba@1024
  2371
    /// @{
deba@1024
  2372
deba@1024
  2373
    /// \brief Start the batch processing
deba@1024
  2374
    ///
deba@1024
  2375
    /// This function starts the batch processing.
deba@1024
  2376
    void run() {
deba@1024
  2377
      if (!_skip_nodes) {
deba@1024
  2378
        writeRedNodes();
deba@1024
  2379
        writeBlueNodes();
deba@1024
  2380
      } else {
deba@1024
  2381
        createRedNodeIndex();
deba@1024
  2382
        createBlueNodeIndex();
deba@1024
  2383
      }
deba@1024
  2384
      if (!_skip_edges) {
deba@1024
  2385
        writeEdges();
deba@1024
  2386
      } else {
deba@1024
  2387
        createEdgeIndex();
deba@1024
  2388
      }
deba@1024
  2389
      writeAttributes();
deba@1024
  2390
    }
deba@1024
  2391
deba@1024
  2392
    /// \brief Give back the stream of the writer
deba@1024
  2393
    ///
deba@1024
  2394
    /// Give back the stream of the writer
deba@1024
  2395
    std::ostream& ostream() {
deba@1024
  2396
      return *_os;
deba@1024
  2397
    }
deba@1024
  2398
deba@1024
  2399
    /// @}
deba@1024
  2400
  };
deba@1024
  2401
deba@1024
  2402
  /// \ingroup lemon_io
deba@1024
  2403
  ///
deba@1024
  2404
  /// \brief Return a \ref BpGraphWriter class
deba@1024
  2405
  ///
deba@1024
  2406
  /// This function just returns a \ref BpGraphWriter class.
deba@1024
  2407
  ///
deba@1024
  2408
  /// With this function a bipartite graph can be write to a file or output
deba@1024
  2409
  /// stream in \ref lgf-format "LGF" format with several maps and
deba@1024
  2410
  /// attributes. For example, with the following code a bipartite
deba@1024
  2411
  /// weighted matching problem can be written to the standard output,
deba@1024
  2412
  /// i.e. a graph with a \e weight map on the edges:
deba@1024
  2413
  ///
deba@1024
  2414
  ///\code
deba@1024
  2415
  ///ListBpGraph graph;
deba@1024
  2416
  ///ListBpGraph::EdgeMap<int> weight(graph);
deba@1024
  2417
  ///  // Setting the weight map
deba@1024
  2418
  ///bpGraphWriter(graph, std::cout).
deba@1024
  2419
  ///  edgeMap("weight", weight).
deba@1024
  2420
  ///  run();
deba@1024
  2421
  ///\endcode
deba@1024
  2422
  ///
deba@1024
  2423
  /// For a complete documentation, please see the \ref BpGraphWriter
deba@1024
  2424
  /// class documentation.
deba@1024
  2425
  /// \warning Don't forget to put the \ref BpGraphWriter::run() "run()"
deba@1024
  2426
  /// to the end of the parameter list.
deba@1024
  2427
  /// \relates BpGraphWriter
deba@1024
  2428
  /// \sa bpGraphWriter(const TBGR& graph, const std::string& fn)
deba@1024
  2429
  /// \sa bpGraphWriter(const TBGR& graph, const char* fn)
deba@1024
  2430
  template <typename TBGR>
deba@1024
  2431
  BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph, std::ostream& os) {
deba@1024
  2432
    BpGraphWriter<TBGR> tmp(graph, os);
deba@1024
  2433
    return tmp;
deba@1024
  2434
  }
deba@1024
  2435
deba@1024
  2436
  /// \brief Return a \ref BpGraphWriter class
deba@1024
  2437
  ///
deba@1024
  2438
  /// This function just returns a \ref BpGraphWriter class.
deba@1024
  2439
  /// \relates BpGraphWriter
deba@1024
  2440
  /// \sa graphWriter(const TBGR& graph, std::ostream& os)
deba@1024
  2441
  template <typename TBGR>
deba@1024
  2442
  BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph, const std::string& fn) {
deba@1024
  2443
    BpGraphWriter<TBGR> tmp(graph, fn);
deba@1024
  2444
    return tmp;
deba@1024
  2445
  }
deba@1024
  2446
deba@1024
  2447
  /// \brief Return a \ref BpGraphWriter class
deba@1024
  2448
  ///
deba@1024
  2449
  /// This function just returns a \ref BpGraphWriter class.
deba@1024
  2450
  /// \relates BpGraphWriter
deba@1024
  2451
  /// \sa graphWriter(const TBGR& graph, std::ostream& os)
deba@1024
  2452
  template <typename TBGR>
deba@1024
  2453
  BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph, const char* fn) {
deba@1024
  2454
    BpGraphWriter<TBGR> tmp(graph, fn);
deba@1024
  2455
    return tmp;
deba@1024
  2456
  }
deba@1024
  2457
deba@248
  2458
  class SectionWriter;
deba@248
  2459
deba@248
  2460
  SectionWriter sectionWriter(std::istream& is);
deba@248
  2461
  SectionWriter sectionWriter(const std::string& fn);
deba@248
  2462
  SectionWriter sectionWriter(const char* fn);
deba@248
  2463
deba@248
  2464
  /// \ingroup lemon_io
deba@248
  2465
  ///
deba@248
  2466
  /// \brief Section writer class
deba@248
  2467
  ///
deba@248
  2468
  /// In the \ref lgf-format "LGF" file extra sections can be placed,
deba@248
  2469
  /// which contain any data in arbitrary format. Such sections can be
deba@248
  2470
  /// written with this class. A writing rule can be added to the
deba@248
  2471
  /// class with two different functions. With the \c sectionLines()
deba@248
  2472
  /// function a generator can write the section line-by-line, while
deba@248
  2473
  /// with the \c sectionStream() member the section can be written to
deba@248
  2474
  /// an output stream.
deba@248
  2475
  class SectionWriter {
deba@248
  2476
  private:
deba@248
  2477
deba@248
  2478
    std::ostream* _os;
deba@248
  2479
    bool local_os;
deba@248
  2480
deba@248
  2481
    typedef std::vector<std::pair<std::string, _writer_bits::Section*> >
deba@248
  2482
    Sections;
deba@248
  2483
deba@248
  2484
    Sections _sections;
deba@248
  2485
deba@248
  2486
  public:
deba@248
  2487
deba@248
  2488
    /// \brief Constructor
deba@248
  2489
    ///
deba@248
  2490
    /// Construct a section writer, which writes to the given output
deba@248
  2491
    /// stream.
deba@248
  2492
    SectionWriter(std::ostream& os)
deba@248
  2493
      : _os(&os), local_os(false) {}
deba@248
  2494
deba@248
  2495
    /// \brief Constructor
deba@248
  2496
    ///
deba@248
  2497
    /// Construct a section writer, which writes into the given file.
deba@248
  2498
    SectionWriter(const std::string& fn)
deba@290
  2499
      : _os(new std::ofstream(fn.c_str())), local_os(true) {
deba@295
  2500
      if (!(*_os)) {
deba@295
  2501
        delete _os;
deba@295
  2502
        throw IoError("Cannot write file", fn);
deba@295
  2503
      }
deba@290
  2504
    }
deba@248
  2505
deba@248
  2506
    /// \brief Constructor
deba@248
  2507
    ///
deba@248
  2508
    /// Construct a section writer, which writes into the given file.
deba@248
  2509
    SectionWriter(const char* fn)
deba@290
  2510
      : _os(new std::ofstream(fn)), local_os(true) {
deba@295
  2511
      if (!(*_os)) {
deba@295
  2512
        delete _os;
deba@295
  2513
        throw IoError("Cannot write file", fn);
deba@295
  2514
      }
deba@290
  2515
    }
deba@248
  2516
deba@248
  2517
    /// \brief Destructor
deba@248
  2518
    ~SectionWriter() {
deba@248
  2519
      for (Sections::iterator it = _sections.begin();
deba@248
  2520
           it != _sections.end(); ++it) {
deba@248
  2521
        delete it->second;
deba@248
  2522
      }
deba@248
  2523
deba@248
  2524
      if (local_os) {
deba@248
  2525
        delete _os;
deba@248
  2526
      }
deba@248
  2527
deba@248
  2528
    }
deba@248
  2529
deba@248
  2530
  private:
deba@248
  2531
deba@248
  2532
    friend SectionWriter sectionWriter(std::ostream& os);
deba@248
  2533
    friend SectionWriter sectionWriter(const std::string& fn);
deba@248
  2534
    friend SectionWriter sectionWriter(const char* fn);
deba@248
  2535
deba@248
  2536
    SectionWriter(SectionWriter& other)
deba@248
  2537
      : _os(other._os), local_os(other.local_os) {
deba@248
  2538
deba@248
  2539
      other._os = 0;
deba@248
  2540
      other.local_os = false;
deba@248
  2541
deba@248
  2542
      _sections.swap(other._sections);
deba@248
  2543
    }
deba@248
  2544
deba@248
  2545
    SectionWriter& operator=(const SectionWriter&);
deba@248
  2546
deba@248
  2547
  public:
deba@248
  2548
kpeter@584
  2549
    /// \name Section Writers
deba@248
  2550
    /// @{
deba@248
  2551
deba@248
  2552
    /// \brief Add a section writer with line oriented writing
deba@248
  2553
    ///
deba@248
  2554
    /// The first parameter is the type descriptor of the section, the
deba@248
  2555
    /// second is a generator with std::string values. At the writing
deba@248
  2556
    /// process, the returned \c std::string will be written into the
deba@248
  2557
    /// output file until it is an empty string.
deba@248
  2558
    ///
deba@248
  2559
    /// For example, an integer vector is written into a section.
deba@248
  2560
    ///\code
deba@248
  2561
    ///  @numbers
deba@248
  2562
    ///  12 45 23 78
deba@248
  2563
    ///  4 28 38 28
deba@248
  2564
    ///  23 6 16
deba@248
  2565
    ///\endcode
deba@248
  2566
    ///
deba@248
  2567
    /// The generator is implemented as a struct.
deba@248
  2568
    ///\code
deba@248
  2569
    ///  struct NumberSection {
deba@248
  2570
    ///    std::vector<int>::const_iterator _it, _end;
deba@248
  2571
    ///    NumberSection(const std::vector<int>& data)
deba@248
  2572
    ///      : _it(data.begin()), _end(data.end()) {}
deba@248
  2573
    ///    std::string operator()() {
deba@248
  2574
    ///      int rem_in_line = 4;
deba@248
  2575
    ///      std::ostringstream ls;
deba@248
  2576
    ///      while (rem_in_line > 0 && _it != _end) {
deba@248
  2577
    ///        ls << *(_it++) << ' ';
deba@248
  2578
    ///        --rem_in_line;
deba@248
  2579
    ///      }
deba@248
  2580
    ///      return ls.str();
deba@248
  2581
    ///    }
deba@248
  2582
    ///  };
deba@248
  2583
    ///
deba@248
  2584
    ///  // ...
deba@248
  2585
    ///
deba@248
  2586
    ///  writer.sectionLines("numbers", NumberSection(vec));
deba@248
  2587
    ///\endcode
deba@248
  2588
    template <typename Functor>
deba@248
  2589
    SectionWriter& sectionLines(const std::string& type, Functor functor) {
deba@248
  2590
      LEMON_ASSERT(!type.empty(), "Type is empty.");
deba@248
  2591
      _sections.push_back(std::make_pair(type,
deba@248
  2592
        new _writer_bits::LineSection<Functor>(functor)));
deba@248
  2593
      return *this;
deba@248
  2594
    }
deba@248
  2595
deba@248
  2596
deba@248
  2597
    /// \brief Add a section writer with stream oriented writing
deba@248
  2598
    ///
deba@248
  2599
    /// The first parameter is the type of the section, the second is
deba@248
  2600
    /// a functor, which takes a \c std::ostream& parameter. The
deba@248
  2601
    /// functor writes the section to the output stream.
deba@248
  2602
    /// \warning The last line must be closed with end-line character.
deba@248
  2603
    template <typename Functor>
deba@248
  2604
    SectionWriter& sectionStream(const std::string& type, Functor functor) {
deba@248
  2605
      LEMON_ASSERT(!type.empty(), "Type is empty.");
deba@248
  2606
      _sections.push_back(std::make_pair(type,
deba@248
  2607
         new _writer_bits::StreamSection<Functor>(functor)));
deba@248
  2608
      return *this;
deba@248
  2609
    }
deba@248
  2610
deba@248
  2611
    /// @}
deba@248
  2612
deba@248
  2613
  public:
deba@248
  2614
deba@248
  2615
kpeter@584
  2616
    /// \name Execution of the Writer
deba@248
  2617
    /// @{
deba@248
  2618
deba@248
  2619
    /// \brief Start the batch processing
deba@248
  2620
    ///
deba@248
  2621
    /// This function starts the batch processing.
deba@248
  2622
    void run() {
deba@248
  2623
deba@248
  2624
      LEMON_ASSERT(_os != 0, "This writer is assigned to an other writer");
deba@248
  2625
deba@248
  2626
      for (Sections::iterator it = _sections.begin();
deba@248
  2627
           it != _sections.end(); ++it) {
deba@248
  2628
        (*_os) << '@' << it->first << std::endl;
deba@248
  2629
        it->second->process(*_os);
deba@248
  2630
      }
deba@248
  2631
    }
deba@248
  2632
deba@248
  2633
    /// \brief Give back the stream of the writer
deba@248
  2634
    ///
deba@248
  2635
    /// Returns the stream of the writer
deba@248
  2636
    std::ostream& ostream() {
deba@248
  2637
      return *_os;
deba@248
  2638
    }
deba@248
  2639
deba@248
  2640
    /// @}
deba@248
  2641
deba@248
  2642
  };
deba@248
  2643
deba@598
  2644
  /// \ingroup lemon_io
deba@598
  2645
  ///
deba@248
  2646
  /// \brief Return a \ref SectionWriter class
deba@248
  2647
  ///
deba@248
  2648
  /// This function just returns a \ref SectionWriter class.
deba@598
  2649
  ///
deba@598
  2650
  /// Please see SectionWriter documentation about the custom section
deba@598
  2651
  /// output.
deba@598
  2652
  ///
deba@248
  2653
  /// \relates SectionWriter
deba@598
  2654
  /// \sa sectionWriter(const std::string& fn)
deba@598
  2655
  /// \sa sectionWriter(const char *fn)
deba@248
  2656
  inline SectionWriter sectionWriter(std::ostream& os) {
deba@248
  2657
    SectionWriter tmp(os);
deba@248
  2658
    return tmp;
deba@248
  2659
  }
deba@248
  2660
deba@248
  2661
  /// \brief Return a \ref SectionWriter class
deba@248
  2662
  ///
deba@248
  2663
  /// This function just returns a \ref SectionWriter class.
deba@248
  2664
  /// \relates SectionWriter
deba@598
  2665
  /// \sa sectionWriter(std::ostream& os)
deba@248
  2666
  inline SectionWriter sectionWriter(const std::string& fn) {
deba@248
  2667
    SectionWriter tmp(fn);
deba@248
  2668
    return tmp;
deba@248
  2669
  }
deba@248
  2670
deba@248
  2671
  /// \brief Return a \ref SectionWriter class
deba@248
  2672
  ///
deba@248
  2673
  /// This function just returns a \ref SectionWriter class.
deba@248
  2674
  /// \relates SectionWriter
deba@598
  2675
  /// \sa sectionWriter(std::ostream& os)
deba@248
  2676
  inline SectionWriter sectionWriter(const char* fn) {
deba@248
  2677
    SectionWriter tmp(fn);
deba@248
  2678
    return tmp;
deba@248
  2679
  }
deba@127
  2680
}
deba@127
  2681
deba@127
  2682
#endif